# Taro 抖音小程序发布视频解决方案

## 概述

抖音小程序提供了官方的视频发布能力，允许用户通过小程序直接拍摄并发布视频到抖音。在 Taro 框架中，我们需要通过特定的方式来调用这个官方 API。

## 核心原理

抖音小程序的视频发布功能基于两个核心要素：
1. **Button 组件**：设置 `open-type="uploadDouyinVideo"`
2. **Page 钩子**：在页面中配置 `onUploadDouyinVideo` 钩子函数

## 实现方案

### 方案一：函数组件 + useReady Hook（推荐）

```typescript
import React, { useState } from 'react';
import { View, Button, Text } from '@tarojs/components';
import Taro, { useReady } from '@tarojs/taro';

const VideoPublishPage: React.FC = () => {
  const [uploadStatus, setUploadStatus] = useState<string>('');

  useReady(() => {
    // 获取当前页面实例
    const pages = Taro.getCurrentPages();
    const currentPage = pages[pages.length - 1];
    
    // 配置抖音视频上传钩子
    currentPage.onUploadDouyinVideo = function(uploadOptions) {
      console.log('抖音视频上传参数:', uploadOptions);
      
      setUploadStatus('正在处理视频...');
      
      // 处理上传结果
      if (uploadOptions.errMsg) {
        if (uploadOptions.errMsg.includes('ok')) {
          setUploadStatus('视频发布成功！');
          Taro.showToast({
            title: '发布成功',
            icon: 'success'
          });
        } else {
          setUploadStatus('视频发布失败');
          Taro.showToast({
            title: '发布失败',
            icon: 'error'
          });
        }
      }
    };
  });

  return (
    <View className="video-publish-container">
      <View className="header">
        <Text className="title">发布抖音视频</Text>
      </View>
      
      <View className="content">
        {/* 关键：Button 组件设置 openType */}
        <Button 
          openType="uploadDouyinVideo"
          className="upload-button"
          type="primary"
        >
          拍摄并发布视频
        </Button>
        
        {uploadStatus && (
          <View className="status">
            <Text>{uploadStatus}</Text>
          </View>
        )}
      </View>
    </View>
  );
};

export default VideoPublishPage;
```

### 方案二：类组件实现

```typescript
import { Component } from 'react';
import { View, Button } from '@tarojs/components';
import Taro from '@tarojs/taro';

class VideoPublishPage extends Component {
  
  onReady() {
    // 在页面 onReady 生命周期中配置钩子
    this.$instance.page.onUploadDouyinVideo = (uploadOptions) => {
      console.log('抖音视频上传参数:', uploadOptions);
      this.handleVideoUpload(uploadOptions);
    };
  }

  handleVideoUpload = (uploadOptions: any) => {
    console.log('处理视频上传:', uploadOptions);
    
    Taro.showToast({
      title: '视频发布中...',
      icon: 'loading'
    });
  };

  render() {
    return (
      <View className="video-publish-page">
        <Button openType="uploadDouyinVideo">
          发布抖音视频
        </Button>
      </View>
    );
  }
}

export default VideoPublishPage;
```

### 方案三：自定义 Hook 封装

```typescript
// hooks/useUploadDouyinVideo.ts
import { useReady } from '@tarojs/taro';
import Taro from '@tarojs/taro';

interface UploadOptions {
  errMsg?: string;
  [key: string]: any;
}

export const useUploadDouyinVideo = (
  onUpload: (options: UploadOptions) => void
) => {
  useReady(() => {
    const pages = Taro.getCurrentPages();
    const currentPage = pages[pages.length - 1];
    
    if (currentPage) {
      currentPage.onUploadDouyinVideo = onUpload;
    }
  });
};

// 使用示例
import React from 'react';
import { View, Button } from '@tarojs/components';
import { useUploadDouyinVideo } from '../hooks/useUploadDouyinVideo';

const VideoPublishPage: React.FC = () => {
  
  useUploadDouyinVideo((uploadOptions) => {
    console.log('视频上传参数:', uploadOptions);
    // 处理上传逻辑
  });

  return (
    <View>
      <Button openType="uploadDouyinVideo">
        发布抖音视频
      </Button>
    </View>
  );
};
```

## 配置要求

### 1. app.config.ts 配置

```typescript
export default {
  pages: [
    'pages/video-publish/index'
  ],
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#fff',
    navigationBarTitleText: '抖音视频发布',
    navigationBarTextStyle: 'black'
  },
  // 抖音小程序权限配置
  permission: {
    'scope.camera': {
      desc: '需要使用摄像头拍摄视频'
    },
    'scope.writePhotosAlbum': {
      desc: '需要保存视频到相册'
    }
  }
}
```

### 2. 样式配置

```scss
// video-publish/index.scss
.video-publish-container {
  padding: 40px 32px;
  
  .header {
    text-align: center;
    margin-bottom: 60px;
    
    .title {
      font-size: 36px;
      font-weight: bold;
      color: #333;
    }
  }
  
  .content {
    .upload-button {
      width: 100%;
      height: 88px;
      font-size: 32px;
      border-radius: 12px;
      margin-bottom: 40px;
    }
    
    .status {
      text-align: center;
      padding: 20px;
      background-color: #f5f5f5;
      border-radius: 8px;
      
      text {
        color: #666;
        font-size: 28px;
      }
    }
  }
}
```

## 关键要点

### 1. 必须配置的两个要素
- **Button 组件**：`openType="uploadDouyinVideo"`
- **钩子函数**：`onUploadDouyinVideo`

### 2. 钩子函数配置时机
- 必须在页面的 `onReady` 生命周期或之后配置
- 函数组件使用 `useReady` Hook
- 类组件在 `onReady` 方法中配置

### 3. 参数说明
```typescript
// uploadOptions 参数结构
interface UploadOptions {
  errMsg: string;  // 上传结果信息
  // 其他抖音官方返回的参数
}
```

## 故障排除

### 问题1：钩子函数不触发

**解决方案**：确保在正确的时机配置钩子

```typescript
useReady(() => {
  // 延迟配置，确保页面完全加载
  setTimeout(() => {
    const pages = Taro.getCurrentPages();
    const currentPage = pages[pages.length - 1];
    
    if (currentPage) {
      currentPage.onUploadDouyinVideo = function(uploadOptions) {
        console.log('视频上传回调:', uploadOptions);
      };
    }
  }, 100);
});
```

### 问题2：Button 点击无反应

**检查清单**：
- [ ] `openType` 属性是否正确设置为 `"uploadDouyinVideo"`
- [ ] 是否在真实的抖音小程序环境中测试
- [ ] 权限配置是否正确

### 问题3：Taro 版本兼容性

**建议**：
- 使用 Taro 3.x 以上版本
- 确保抖音小程序基础库版本支持该功能

## 注意事项

1. **测试环境**：该功能需要在真实的抖音小程序环境中测试，开发工具可能无法完全模拟
2. **权限申请**：需要在小程序后台申请相应的视频发布权限
3. **用户体验**：建议添加加载状态和错误处理
4. **版本兼容**：确保 Taro 版本和抖音小程序基础库版本的兼容性

## 参考资料

- [抖音小程序官方文档 - 发布抖音视频](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/api/open-interface/video-capacity/upload-douyin-video)
- [Taro GitHub Issue #13882](https://github.com/NervJS/taro/issues/13882)
