harry před 1 rokem
rodič
revize
f221923300
4 změnil soubory, kde provedl 340 přidání a 103 odebrání
  1. 95 91
      package.json
  2. 112 0
      plugins/PostPreViewQr/index.ts
  3. 116 0
      script/index.mjs
  4. 17 12
      src/components/VideoSwiper/index.tsx

+ 95 - 91
package.json

@@ -1,93 +1,97 @@
 {
-	"name": " pqVideoMiniprogram",
-	"version": "1.0.0",
-	"private": true,
-	"description": " 票圈视频新小程序,票圈好看视频",
-	"templateInfo": {
-		"name": "default",
-		"typescript": true,
-		"css": "Less",
-		"framework": "React"
-	},
-	"scripts": {
-		"build:weapp": "taro build --type weapp",
-		"build:swan": "taro build --type swan",
-		"build:alipay": "taro build --type alipay",
-		"build:tt": "taro build --type tt",
-		"build:h5": "taro build --type h5",
-		"build:rn": "taro build --type rn",
-		"build:qq": "taro build --type qq",
-		"build:jd": "taro build --type jd",
-		"build:quickapp": "taro build --type quickapp",
-		"build:harmony-hybrid": "taro build --type harmony-hybrid",
-		"dev:weapp": "npm run build:weapp -- --watch",
-		"dev:swan": "npm run build:swan -- --watch",
-		"dev:alipay": "npm run build:alipay -- --watch",
-		"dev:tt": "npm run build:tt -- --watch",
-		"dev:h5": "npm run build:h5 -- --watch",
-		"dev:rn": "npm run build:rn -- --watch",
-		"dev:qq": "npm run build:qq -- --watch",
-		"dev:jd": "npm run build:jd -- --watch",
-		"dev:quickapp": "npm run build:quickapp -- --watch",
-		"dev:harmony-hybrid": "npm run build:harmony-hybrid -- --watch",
-		"test": "jest"
-	},
-	"browserslist": [
-		"last 3 versions",
-		"Android >= 4.1",
-		"ios >= 8"
-	],
-	"author": "",
-	"dependencies": {
-		"@babel/runtime": "^7.21.5",
-        "@reduxjs/toolkit": "^1.9.7",
-		"@tarojs/components": "3.6.23",
-		"@tarojs/helper": "3.6.23",
-		"@tarojs/plugin-platform-weapp": "3.6.23",
-		"@tarojs/plugin-platform-alipay": "3.6.23",
-		"@tarojs/plugin-platform-tt": "3.6.23",
-		"@tarojs/plugin-platform-swan": "3.6.23",
-		"@tarojs/plugin-platform-jd": "3.6.23",
-		"@tarojs/plugin-platform-qq": "3.6.23",
-		"@tarojs/plugin-platform-h5": "3.6.23",
-		"@tarojs/plugin-platform-harmony-hybrid": "3.6.23",
-		"@tarojs/runtime": "3.6.23",
-		"@tarojs/shared": "3.6.23",
-		"@tarojs/taro": "3.6.23",
-		"@tarojs/plugin-framework-react": "3.6.23",
-		"@tarojs/react": "3.6.23",
-		"@types/react-redux": "^7.1.30",
-		"react-dom": "^18.0.0",
-		"react": "^18.0.0",
-		"react-redux": "^8.1.3"
-	},
-	"devDependencies": {
-		"@babel/core": "^7.8.0",
-		"@tarojs/cli": "3.6.23",
-		"@types/webpack-env": "^1.13.6",
-		"@tarojs/test-utils-react": "^0.1.1",
-		"@types/react": "^18.0.0",
-		"webpack": "5.78.0",
-		"@tarojs/taro-loader": "3.6.23",
-		"@tarojs/webpack5-runner": "3.6.23",
-		"babel-preset-taro": "3.6.23",
-		"eslint-config-taro": "3.6.23",
-		"eslint": "^8.12.0",
-		"@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
-		"react-refresh": "^0.11.0",
-		"eslint-plugin-react": "^7.8.2",
-		"eslint-plugin-import": "^2.12.0",
-		"eslint-plugin-react-hooks": "^4.2.0",
-		"stylelint": "^14.4.0",
-		"@typescript-eslint/parser": "^6.2.0",
-		"@typescript-eslint/eslint-plugin": "^6.2.0",
-		"typescript": "^5.1.0",
-		"tsconfig-paths-webpack-plugin": "^4.1.0",
-		"postcss": "^8.4.18",
-		"ts-node": "^10.9.1",
-		"@types/node": "^18.15.11",
-		"@types/jest": "^29.3.1",
-		"jest": "^29.3.1",
-		"jest-environment-jsdom": "^29.5.0"
-	}
+  "name": " pqVideoMiniprogram",
+  "version": "1.0.0",
+  "private": true,
+  "description": " 票圈视频新小程序,票圈好看视频",
+  "templateInfo": {
+    "name": "default",
+    "typescript": true,
+    "css": "Less",
+    "framework": "React"
+  },
+  "scripts": {
+    "build:weapp": "taro build --type weapp",
+    "build:swan": "taro build --type swan",
+    "build:alipay": "taro build --type alipay",
+    "build:tt": "taro build --type tt",
+    "build:h5": "taro build --type h5",
+    "build:rn": "taro build --type rn",
+    "build:qq": "taro build --type qq",
+    "build:jd": "taro build --type jd",
+    "build:quickapp": "taro build --type quickapp",
+    "build:harmony-hybrid": "taro build --type harmony-hybrid",
+    "dev:weapp": "npm run build:weapp -- --watch",
+    "dev:swan": "npm run build:swan -- --watch",
+    "dev:alipay": "npm run build:alipay -- --watch",
+    "dev:tt": "npm run build:tt -- --watch",
+    "dev:h5": "npm run build:h5 -- --watch",
+    "dev:rn": "npm run build:rn -- --watch",
+    "dev:qq": "npm run build:qq -- --watch",
+    "dev:jd": "npm run build:jd -- --watch",
+    "dev:quickapp": "npm run build:quickapp -- --watch",
+    "dev:harmony-hybrid": "npm run build:harmony-hybrid -- --watch",
+    "test": "jest",
+    "script": "node ./script/index.mjs"
+  },
+  "browserslist": [
+    "last 3 versions",
+    "Android >= 4.1",
+    "ios >= 8"
+  ],
+  "author": "",
+  "dependencies": {
+    "@babel/runtime": "^7.21.5",
+    "@reduxjs/toolkit": "^1.9.7",
+    "@tarojs/components": "3.6.23",
+    "@tarojs/helper": "3.6.23",
+    "@tarojs/plugin-platform-weapp": "3.6.23",
+    "@tarojs/plugin-platform-alipay": "3.6.23",
+    "@tarojs/plugin-platform-tt": "3.6.23",
+    "@tarojs/plugin-platform-swan": "3.6.23",
+    "@tarojs/plugin-platform-jd": "3.6.23",
+    "@tarojs/plugin-platform-qq": "3.6.23",
+    "@tarojs/plugin-platform-h5": "3.6.23",
+    "@tarojs/plugin-platform-harmony-hybrid": "3.6.23",
+    "@tarojs/runtime": "3.6.23",
+    "@tarojs/shared": "3.6.23",
+    "@tarojs/taro": "3.6.23",
+    "@tarojs/plugin-framework-react": "3.6.23",
+    "@tarojs/react": "3.6.23",
+    "@types/react-redux": "^7.1.30",
+    "react-dom": "^18.0.0",
+    "react": "^18.0.0",
+    "react-redux": "^8.1.3"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.8.0",
+    "@tarojs/cli": "3.6.23",
+    "@types/webpack-env": "^1.13.6",
+    "@tarojs/test-utils-react": "^0.1.1",
+    "@types/react": "^18.0.0",
+    "webpack": "5.78.0",
+    "@tarojs/taro-loader": "3.6.23",
+    "@tarojs/webpack5-runner": "3.6.23",
+    "babel-preset-taro": "3.6.23",
+    "eslint-config-taro": "3.6.23",
+    "eslint": "^8.12.0",
+    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
+    "react-refresh": "^0.11.0",
+    "eslint-plugin-react": "^7.8.2",
+    "eslint-plugin-import": "^2.12.0",
+    "eslint-plugin-react-hooks": "^4.2.0",
+    "stylelint": "^14.4.0",
+    "@typescript-eslint/parser": "^6.2.0",
+    "@typescript-eslint/eslint-plugin": "^6.2.0",
+    "typescript": "^5.1.0",
+    "tsconfig-paths-webpack-plugin": "^4.1.0",
+    "postcss": "^8.4.18",
+    "ts-node": "^10.9.1",
+    "@types/node": "^18.15.11",
+    "@types/jest": "^29.3.1",
+    "jest": "^29.3.1",
+    "jest-environment-jsdom": "^29.5.0",
+    "@inquirer/prompts": "^3.3.0",
+    "chalk": "^5.3.0",
+    "commander": "^11.1.0"
+  }
 }

+ 112 - 0
plugins/PostPreViewQr/index.ts

@@ -0,0 +1,112 @@
+const fetch = require('node-fetch')
+const FormData = require('form-data')
+const { createReadStream } = require('fs')
+
+const ROBOT_ID = 'cli_a13ad2afa438d00b'
+const ROBOT_ST = '4tK9LY9VbiQlY5umhE42dclBFo6t4p5O'
+const ROBOT_URL = 'https://open.feishu.cn/open-apis/bot/v2/hook/4a877590-334e-4212-9198-25e7768c64f9'
+const IMG_UPLOAD_URL = 'https://open.feishu.cn/open-apis/im/v1/images'
+const GET_ACCESS_TOKEN_URL = 'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal'
+
+async function getAccessToken() {
+  const body = {
+    app_id: ROBOT_ID,
+    app_secret: ROBOT_ST
+  }
+
+  const response = await fetch(GET_ACCESS_TOKEN_URL, {
+    method: 'post',
+    body: JSON.stringify(body),
+    headers: {'Content-Type': 'application/json'}
+  })
+
+  return await response.json()
+}
+
+async function uploadQr(access_token, imgPath) {
+  const formData = new FormData()
+  const file = createReadStream(imgPath)
+  formData.append('image', file)
+  formData.append('image_type', 'message')
+
+  const response = await fetch(IMG_UPLOAD_URL, {
+    method: 'post',
+    headers: {
+      authorization: `Bearer ${access_token}`
+    },
+    body: formData
+  })
+
+  return await response.json()
+}
+
+async function sendQrToFeishu(image_key, desc) {
+  const schema = {
+    msg_type: 'post',
+    content: {
+        post: {
+            zh_cn: {
+                title: '小程序预览二维码',
+                content: [
+                    [
+                        {
+                            tag: 'img',
+                            image_key: image_key
+                        }
+                    ],
+                    [
+                        {
+                            tag: 'text',
+                            text: desc
+                        }
+                    ]
+                ]
+            }
+        }
+    }
+  }
+
+  const response = await fetch(ROBOT_URL, {
+    method: 'post',
+    headers: {'Content-Type': 'application/json'},
+    body: JSON.stringify(schema),
+  })
+
+  return await response.json()
+}
+
+function PostPreViewQr(ctx) {
+  ctx.register({
+    name: 'onPreviewComplete',
+    fn: ({ success, data, error }) => {
+      console.log('接收预览后数据', success, data, error)
+      if (success) {
+        const { qrCodeLocalPath } = data
+        getAccessToken().then((res: any) => {
+          const { code, tenant_access_token, msg } = res
+        
+          if (code !== 0)
+            return Promise.reject({ code, msg })
+        
+          return tenant_access_token
+        }).then(res => uploadQr(res, qrCodeLocalPath))
+        .then((res: any) => {
+          const { code , data, msg } = res
+        
+          if (code !== 0)
+            return Promise.reject({ code , msg })
+        
+          const { image_key } = data
+        
+          return sendQrToFeishu(image_key, '票圈好视界')
+        
+        }).catch(err => {
+          console.error(err)
+        })
+      }
+
+    }
+  })
+}
+
+export default PostPreViewQr

+ 116 - 0
script/index.mjs

@@ -0,0 +1,116 @@
+import fs from 'fs'
+import path from 'path'
+import { fileURLToPath } from 'url'
+import { exec } from 'child_process'
+import { Command } from 'commander'
+import { input, select, confirm } from '@inquirer/prompts'
+import chalk from 'chalk'
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = path.dirname(__filename)
+
+function processArgv() {
+  const program = new Command()
+  // 解析参数
+  program
+    .option('-t, --type <type>', 'Building type')
+    .option('-d, --desc <char>', 'version description')
+    .option('-v, --version <char>', 'version code')
+    .action(async (options) => {
+      let { type, desc, version } = options
+      if (!type)
+        type = await selectBuildingType()
+
+      console.log(chalk.hex('#76a9d8').bold(type))
+
+      if (type === 'preview') {
+        build(type)
+        return
+      }
+
+      if (!version)
+        version = await confirmVersion()
+
+      console.log(chalk.hex('#76a9d8').bold(version))
+
+      if (!desc)
+        desc = await input({ message: '请输入描述信息' })
+
+      if (!desc)
+        desc = `版本 - ${version}`
+
+      console.log(chalk.hex('#76a9d8').bold(desc))
+
+      fs.writeFileSync(
+        path.join(__dirname, '../config/version.json'),
+        JSON.stringify({ version, desc }),
+        { encoding: 'utf-8' }
+      )
+
+      build(type)
+    })
+
+    program.parse()
+}
+
+async function selectBuildingType() {
+  return await select({
+    message: 'Select a building type',
+    choices: [
+      {
+        name: 'publish',
+        value: 'publish',
+        description: 'build and upload',
+      },
+      {
+        name: 'preview',
+        value: 'preview',
+        description: 'build and preview',
+      }
+    ],
+  })
+}
+
+async function confirmVersion() {
+  let curV = fs.readFileSync(path.join(__dirname, '../config/version.json'), { encoding: 'utf-8'})
+  curV = JSON.parse(curV)
+
+  const message = `当前参数为${curV.version},是采用否自增版本号?`
+  const res = await confirm({ message })
+
+  if (!res)
+    return await input({ message: '请输入版本号' })
+
+  let [main, mid ,min] = curV.version.split('.')
+  
+  min++
+  
+  if (min === 50) {
+    min = 0
+    mid++
+  }
+  
+  if (mid === 50) {
+    mid === 0
+    main++
+  }
+  
+  return `${main}.${mid}.${min}`
+}
+
+function build(type) {
+  let command = 'rm -rf dist && yarn upload'
+
+  if (type === 'preview')
+    command = 'rm -rf dist && yarn preview'
+
+
+  const script = exec(command)
+ 
+  // 将打包信息,打印到控制台
+  script.stdout.on('data', (chunk) => {
+    console.log(chalk.hex('#f9d472').bold(chunk))
+  })
+}
+
+processArgv()

+ 17 - 12
src/components/VideoSwiper/index.tsx

@@ -23,7 +23,6 @@ export default function VideoSwiper({ list, onFinish, needResumePlay, flushList
     const [currentIndex, setCurrentIndex] = useState(0)
     const [circular, setCircular] = useState(false)
     const [videoList, setVideoList] = useState<VideoInfo[]>(list.slice(0, 3))
-    const [showRedShareBtn, setShowRedShareBtn] = useState(false)
     const [seekProgress, setSeekProgress] = useState(false)
     const [needPlayerResume, setNeedPlayerResume] = useState(false)
 
@@ -41,10 +40,6 @@ export default function VideoSwiper({ list, onFinish, needResumePlay, flushList
      * @return {*}
      */
     function didTimeUpdate(e) {
-        let { currentTime = 0, duration = 1000000 } = e
-        if (!showRedShareBtn && currentTime / duration >= 0.1) {
-            setShowRedShareBtn(true)
-        }
     }
     function onProgressMove(e) {
         setSeekProgress(e || false)
@@ -158,7 +153,6 @@ export default function VideoSwiper({ list, onFinish, needResumePlay, flushList
                             needResumePlay={needPlayerResume}
                             onTimeUpdate={didTimeUpdate}
                             onProgressMove={onProgressMove} />
-                        {!seekProgress && <VideoIntroduce detail={video} showRedShareBtn={showRedShareBtn} />}
                         {!seekProgress && <VideoBar video={video} />}
                     </SwiperItem>
                 )
@@ -180,8 +174,7 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
     const [startMoveX, setStartMoveX] = useState(0)
     const [hasReportPlaySuccess, setHasReportPlaySuccess] = useState(false)
     const [hasReportRealplay, setHasReportRealplay] = useState(false)
-    const [updatePlayerVideoIdx, setUpdatePlayerVideoIdx] = useState(-1)
-    const [detail, setDetail] = useState({})
+    const [showRedShareBtn, setShowRedShareBtn] = useState(false)
 
     let videoContext = Taro.createVideoContext(`${video.id}`)
     const logReportVideoPlaySuccessOnce = once(logReportVideoPlaySuccess)
@@ -202,6 +195,10 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
         setShowEndCover(false)
     }, [current])
 
+    useEffect(() => {
+        setShowRedShareBtn(false)
+    }, [video])
+
     useEffect(() => {
         if (needResumePlay && current == index) {
             playerPlay()
@@ -235,11 +232,17 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
             return
 
         const { detail } = evt || {}
-        const { currentTime, duration } = detail || {}
+        const { currentTime = 0, duration = 1000000 } = detail || {}
         setCurrentPlayTime(currentTime)
 
         onTimeUpdate(detail)
-        setDurPersec(currentTime / duration)
+
+        let per = currentTime / duration
+        setDurPersec(per)
+
+        if (!showRedShareBtn && per >= 0.1) {
+            setShowRedShareBtn(true)
+        }
 
         if (!hasReportPlaySuccess) {
             setHasReportPlaySuccess(true)
@@ -275,6 +278,7 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
 
     function onRePlay() {
         setShowEndCover(false)
+        setShowRedShareBtn(false)
         videoContext.seek(0)
         playerPlay()
     }
@@ -351,8 +355,9 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
 
                     </View>
                 </View>
-
             </View>
+
+            {!showProgressIndicator && <VideoIntroduce detail={video} showRedShareBtn={showRedShareBtn} index={index}/>}
             {showProgressIndicator && <View className='progress-indicator'>
                 <View className='showInfo'>
                     <View className='showInfo-a'>{formatSecondsAsTime(seekTime)}</View>
@@ -371,7 +376,7 @@ function CustomVideo({ video, current, index, onTimeUpdate, onProgressMove, need
     )
 }
 
-function VideoIntroduce({ detail, showRedShareBtn }) {
+function VideoIntroduce({ detail, showRedShareBtn, index}) {
     return (
         <View className='video-introduce'>
             <View className='video-user-info'>