hookehuyr

feat(上传): 实现视频文件上传功能并添加文件校验

添加 `browser-md5-file` 依赖,实现视频文件上传功能,包括文件校验、上传进度跟踪及七牛云上传逻辑。移除不再使用的 `@uppy` 相关依赖。
...@@ -9,13 +9,10 @@ ...@@ -9,13 +9,10 @@
9 "version": "0.0.0", 9 "version": "0.0.0",
10 "dependencies": { 10 "dependencies": {
11 "@heroicons/vue": "^2.2.0", 11 "@heroicons/vue": "^2.2.0",
12 - "@uppy/core": "^4.4.3",
13 - "@uppy/dashboard": "^4.3.2",
14 - "@uppy/vue": "^2.1.1",
15 - "@uppy/xhr-upload": "^4.3.3",
16 "@vant/touch-emulator": "^1.4.0", 12 "@vant/touch-emulator": "^1.4.0",
17 "@vant/use": "^1.6.0", 13 "@vant/use": "^1.6.0",
18 "@videojs-player/vue": "^1.0.0", 14 "@videojs-player/vue": "^1.0.0",
15 + "browser-md5-file": "^1.1.1",
19 "dayjs": "^1.11.13", 16 "dayjs": "^1.11.13",
20 "swiper": "^11.2.6", 17 "swiper": "^11.2.6",
21 "vant": "^4.9.18", 18 "vant": "^4.9.18",
...@@ -1196,22 +1193,12 @@ ...@@ -1196,22 +1193,12 @@
1196 "win32" 1193 "win32"
1197 ] 1194 ]
1198 }, 1195 },
1199 - "node_modules/@transloadit/prettier-bytes": {
1200 - "version": "0.3.5",
1201 - "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.5.tgz",
1202 - "integrity": "sha512-xF4A3d/ZyX2LJWeQZREZQw+qFX4TGQ8bGVP97OLRt6sPO6T0TNHBFTuRHOJh7RNmYOBmQ9MHxpolD9bXihpuVA=="
1203 - },
1204 "node_modules/@types/estree": { 1196 "node_modules/@types/estree": {
1205 "version": "1.0.6", 1197 "version": "1.0.6",
1206 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 1198 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
1207 "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 1199 "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
1208 "dev": true 1200 "dev": true
1209 }, 1201 },
1210 - "node_modules/@types/retry": {
1211 - "version": "0.12.2",
1212 - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
1213 - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="
1214 - },
1215 "node_modules/@types/video.js": { 1202 "node_modules/@types/video.js": {
1216 "version": "7.3.58", 1203 "version": "7.3.58",
1217 "resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.58.tgz", 1204 "resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.58.tgz",
...@@ -1224,220 +1211,6 @@ ...@@ -1224,220 +1211,6 @@
1224 "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", 1211 "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
1225 "dev": true 1212 "dev": true
1226 }, 1213 },
1227 - "node_modules/@uppy/companion-client": {
1228 - "version": "4.4.1",
1229 - "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-4.4.1.tgz",
1230 - "integrity": "sha512-ardMacShsfzaIbqHEH48YlpzWZkBj1qhAj0Dvn3r31p9d0HA5xFUvAdLYrZ6ezKvZ0RcDbf0SB5qCrQMkjscXQ==",
1231 - "dependencies": {
1232 - "@uppy/utils": "^6.1.1",
1233 - "namespace-emitter": "^2.0.1",
1234 - "p-retry": "^6.1.0"
1235 - },
1236 - "peerDependencies": {
1237 - "@uppy/core": "^4.4.1"
1238 - }
1239 - },
1240 - "node_modules/@uppy/core": {
1241 - "version": "4.4.3",
1242 - "resolved": "https://registry.npmjs.org/@uppy/core/-/core-4.4.3.tgz",
1243 - "integrity": "sha512-Ma/v9+u0xYoxFcTajBpe0TUHI0Vjw2IKgB0AUNevhgFsBRgA03nL5n8Fac8TrC0QjPkYu7h0n2xf2EgzvyxAQA==",
1244 - "dependencies": {
1245 - "@transloadit/prettier-bytes": "^0.3.4",
1246 - "@uppy/store-default": "^4.2.0",
1247 - "@uppy/utils": "^6.1.2",
1248 - "lodash": "^4.17.21",
1249 - "mime-match": "^1.0.2",
1250 - "namespace-emitter": "^2.0.1",
1251 - "nanoid": "^5.0.9",
1252 - "preact": "^10.5.13"
1253 - }
1254 - },
1255 - "node_modules/@uppy/core/node_modules/nanoid": {
1256 - "version": "5.1.5",
1257 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
1258 - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
1259 - "funding": [
1260 - {
1261 - "type": "github",
1262 - "url": "https://github.com/sponsors/ai"
1263 - }
1264 - ],
1265 - "bin": {
1266 - "nanoid": "bin/nanoid.js"
1267 - },
1268 - "engines": {
1269 - "node": "^18 || >=20"
1270 - }
1271 - },
1272 - "node_modules/@uppy/dashboard": {
1273 - "version": "4.3.2",
1274 - "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-4.3.2.tgz",
1275 - "integrity": "sha512-6cikgcY/TMy+Fq/v03QI1BNocfm1kOxii3kuUaxnz1SFGeuZ/55+C7KKL7SP/IdeoVwH7KV+550HThT0uwIQEw==",
1276 - "dependencies": {
1277 - "@transloadit/prettier-bytes": "^0.3.4",
1278 - "@uppy/informer": "^4.2.1",
1279 - "@uppy/provider-views": "^4.4.2",
1280 - "@uppy/status-bar": "^4.1.2",
1281 - "@uppy/thumbnail-generator": "^4.1.1",
1282 - "@uppy/utils": "^6.1.2",
1283 - "classnames": "^2.2.6",
1284 - "lodash": "^4.17.21",
1285 - "memoize-one": "^6.0.0",
1286 - "nanoid": "^5.0.9",
1287 - "preact": "^10.5.13",
1288 - "shallow-equal": "^3.0.0"
1289 - },
1290 - "peerDependencies": {
1291 - "@uppy/core": "^4.4.2"
1292 - }
1293 - },
1294 - "node_modules/@uppy/dashboard/node_modules/nanoid": {
1295 - "version": "5.1.5",
1296 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
1297 - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
1298 - "funding": [
1299 - {
1300 - "type": "github",
1301 - "url": "https://github.com/sponsors/ai"
1302 - }
1303 - ],
1304 - "bin": {
1305 - "nanoid": "bin/nanoid.js"
1306 - },
1307 - "engines": {
1308 - "node": "^18 || >=20"
1309 - }
1310 - },
1311 - "node_modules/@uppy/informer": {
1312 - "version": "4.2.1",
1313 - "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-4.2.1.tgz",
1314 - "integrity": "sha512-0en8Py47pl6RMDrgUfqFoF807W5kK5AKVJNT1SkTsLiGg5anmTIMuvmNG3k6LN4cn9P/rKyEHSdGcoBBUj9u7Q==",
1315 - "dependencies": {
1316 - "@uppy/utils": "^6.1.1",
1317 - "preact": "^10.5.13"
1318 - },
1319 - "peerDependencies": {
1320 - "@uppy/core": "^4.4.1"
1321 - }
1322 - },
1323 - "node_modules/@uppy/provider-views": {
1324 - "version": "4.4.2",
1325 - "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-4.4.2.tgz",
1326 - "integrity": "sha512-YGrPJuydrksmMCjvo7Ty7/lDLNo/Y8zsOgWgWmVbXB0V5aRvqY49LeKY8HDlOXclKmn6dl5CeQFf7p46txRNGQ==",
1327 - "dependencies": {
1328 - "@uppy/utils": "^6.1.2",
1329 - "classnames": "^2.2.6",
1330 - "nanoid": "^5.0.9",
1331 - "p-queue": "^8.0.0",
1332 - "preact": "^10.5.13"
1333 - },
1334 - "peerDependencies": {
1335 - "@uppy/core": "^4.4.2"
1336 - }
1337 - },
1338 - "node_modules/@uppy/provider-views/node_modules/nanoid": {
1339 - "version": "5.1.5",
1340 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
1341 - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
1342 - "funding": [
1343 - {
1344 - "type": "github",
1345 - "url": "https://github.com/sponsors/ai"
1346 - }
1347 - ],
1348 - "bin": {
1349 - "nanoid": "bin/nanoid.js"
1350 - },
1351 - "engines": {
1352 - "node": "^18 || >=20"
1353 - }
1354 - },
1355 - "node_modules/@uppy/status-bar": {
1356 - "version": "4.1.2",
1357 - "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-4.1.2.tgz",
1358 - "integrity": "sha512-Z2fDXItoE940uMo3kwdDo4ZFPjTk5GY6y/C/G5+tSl6nL/IaDtWo5iVbAKHIH4s9SIRwCBgllEhxbmEPhuK7eA==",
1359 - "dependencies": {
1360 - "@transloadit/prettier-bytes": "^0.3.4",
1361 - "@uppy/utils": "^6.1.2",
1362 - "classnames": "^2.2.6",
1363 - "preact": "^10.5.13"
1364 - },
1365 - "peerDependencies": {
1366 - "@uppy/core": "^4.4.2"
1367 - }
1368 - },
1369 - "node_modules/@uppy/store-default": {
1370 - "version": "4.2.0",
1371 - "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-4.2.0.tgz",
1372 - "integrity": "sha512-PieFVa8yTvRHIqsNKfpO/yaJw5Ae/hT7uT58ryw7gvCBY5bHrNWxH5N0XFe8PFHMpLpLn8v3UXGx9ib9QkB6+Q=="
1373 - },
1374 - "node_modules/@uppy/thumbnail-generator": {
1375 - "version": "4.1.1",
1376 - "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-4.1.1.tgz",
1377 - "integrity": "sha512-65znkGNgVTbVte51IKOhgxOpHGSwYj9Qik2jF2ZBocMbhBY4gPkWFwqMrKQBfddA9KbUa4jVe1psxhAQTzYgiA==",
1378 - "dependencies": {
1379 - "@uppy/utils": "^6.1.1",
1380 - "exifr": "^7.0.0"
1381 - },
1382 - "peerDependencies": {
1383 - "@uppy/core": "^4.4.1"
1384 - }
1385 - },
1386 - "node_modules/@uppy/utils": {
1387 - "version": "6.1.2",
1388 - "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-6.1.2.tgz",
1389 - "integrity": "sha512-PCrw6v51M6p3hlrlB2INmcocen4Dyjun1SobjVZRBkg4wutQE8ihZfSrH5ZE8UXFelufhtO16wlaZMi0EHk84w==",
1390 - "dependencies": {
1391 - "lodash": "^4.17.21",
1392 - "preact": "^10.5.13"
1393 - }
1394 - },
1395 - "node_modules/@uppy/vue": {
1396 - "version": "2.1.1",
1397 - "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-2.1.1.tgz",
1398 - "integrity": "sha512-svmkqO3QObuPOyVE0ttTFcwjrjzsxiDGgqau0tuV27FNO0/50GGzrJcBOy+P7kkZhQ23qEBltScQzOc75s7uUQ==",
1399 - "dependencies": {
1400 - "shallow-equal": "^3.0.0"
1401 - },
1402 - "peerDependencies": {
1403 - "@uppy/core": "^4.4.1",
1404 - "@uppy/dashboard": "^4.3.1",
1405 - "@uppy/drag-drop": "^4.1.1",
1406 - "@uppy/file-input": "^4.1.1",
1407 - "@uppy/progress-bar": "^4.2.1",
1408 - "@uppy/status-bar": "^4.1.1",
1409 - "vue": ">=3.0.0"
1410 - },
1411 - "peerDependenciesMeta": {
1412 - "@uppy/dashboard": {
1413 - "optional": true
1414 - },
1415 - "@uppy/drag-drop": {
1416 - "optional": true
1417 - },
1418 - "@uppy/file-input": {
1419 - "optional": true
1420 - },
1421 - "@uppy/progress-bar": {
1422 - "optional": true
1423 - },
1424 - "@uppy/status-bar": {
1425 - "optional": true
1426 - }
1427 - }
1428 - },
1429 - "node_modules/@uppy/xhr-upload": {
1430 - "version": "4.3.3",
1431 - "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-4.3.3.tgz",
1432 - "integrity": "sha512-I7RVppwTvLRlVfoW5piMxcZKzWF42E6CwYFQ42d2LzizrkG4tVLQkQrTZlw85za3nhcSrX3o/d1eNx3pzLmsdw==",
1433 - "dependencies": {
1434 - "@uppy/companion-client": "^4.4.1",
1435 - "@uppy/utils": "^6.1.2"
1436 - },
1437 - "peerDependencies": {
1438 - "@uppy/core": "^4.4.2"
1439 - }
1440 - },
1441 "node_modules/@vant/popperjs": { 1214 "node_modules/@vant/popperjs": {
1442 "version": "1.3.0", 1215 "version": "1.3.0",
1443 "resolved": "https://registry.npmjs.org/@vant/popperjs/-/popperjs-1.3.0.tgz", 1216 "resolved": "https://registry.npmjs.org/@vant/popperjs/-/popperjs-1.3.0.tgz",
...@@ -1900,6 +1673,14 @@ ...@@ -1900,6 +1673,14 @@
1900 "node": ">=8" 1673 "node": ">=8"
1901 } 1674 }
1902 }, 1675 },
1676 + "node_modules/browser-md5-file": {
1677 + "version": "1.1.1",
1678 + "resolved": "https://registry.npmjs.org/browser-md5-file/-/browser-md5-file-1.1.1.tgz",
1679 + "integrity": "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw==",
1680 + "dependencies": {
1681 + "spark-md5": "^2.0.2"
1682 + }
1683 + },
1903 "node_modules/browserslist": { 1684 "node_modules/browserslist": {
1904 "version": "4.24.4", 1685 "version": "4.24.4",
1905 "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", 1686 "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
...@@ -2026,11 +1807,6 @@ ...@@ -2026,11 +1807,6 @@
2026 "node": ">= 6" 1807 "node": ">= 6"
2027 } 1808 }
2028 }, 1809 },
2029 - "node_modules/classnames": {
2030 - "version": "2.5.1",
2031 - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
2032 - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
2033 - },
2034 "node_modules/color-convert": { 1810 "node_modules/color-convert": {
2035 "version": "2.0.1", 1811 "version": "2.0.1",
2036 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1812 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
...@@ -2336,16 +2112,6 @@ ...@@ -2336,16 +2112,6 @@
2336 "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 2112 "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
2337 "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" 2113 "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
2338 }, 2114 },
2339 - "node_modules/eventemitter3": {
2340 - "version": "5.0.1",
2341 - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
2342 - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
2343 - },
2344 - "node_modules/exifr": {
2345 - "version": "7.1.3",
2346 - "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz",
2347 - "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw=="
2348 - },
2349 "node_modules/exsolve": { 2115 "node_modules/exsolve": {
2350 "version": "1.0.4", 2116 "version": "1.0.4",
2351 "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", 2117 "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz",
...@@ -2702,17 +2468,6 @@ ...@@ -2702,17 +2468,6 @@
2702 "node": ">=0.10.0" 2468 "node": ">=0.10.0"
2703 } 2469 }
2704 }, 2470 },
2705 - "node_modules/is-network-error": {
2706 - "version": "1.1.0",
2707 - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz",
2708 - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==",
2709 - "engines": {
2710 - "node": ">=16"
2711 - },
2712 - "funding": {
2713 - "url": "https://github.com/sponsors/sindresorhus"
2714 - }
2715 - },
2716 "node_modules/is-number": { 2471 "node_modules/is-number": {
2717 "version": "7.0.0", 2472 "version": "7.0.0",
2718 "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2473 "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
...@@ -2822,11 +2577,6 @@ ...@@ -2822,11 +2577,6 @@
2822 "url": "https://github.com/sponsors/antfu" 2577 "url": "https://github.com/sponsors/antfu"
2823 } 2578 }
2824 }, 2579 },
2825 - "node_modules/lodash": {
2826 - "version": "4.17.21",
2827 - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
2828 - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
2829 - },
2830 "node_modules/lru-cache": { 2580 "node_modules/lru-cache": {
2831 "version": "5.1.1", 2581 "version": "5.1.1",
2832 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 2582 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
...@@ -2863,11 +2613,6 @@ ...@@ -2863,11 +2613,6 @@
2863 "node": ">= 0.4" 2613 "node": ">= 0.4"
2864 } 2614 }
2865 }, 2615 },
2866 - "node_modules/memoize-one": {
2867 - "version": "6.0.0",
2868 - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
2869 - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
2870 - },
2871 "node_modules/merge2": { 2616 "node_modules/merge2": {
2872 "version": "1.4.1", 2617 "version": "1.4.1",
2873 "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2618 "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
...@@ -2899,14 +2644,6 @@ ...@@ -2899,14 +2644,6 @@
2899 "node": ">= 0.6" 2644 "node": ">= 0.6"
2900 } 2645 }
2901 }, 2646 },
2902 - "node_modules/mime-match": {
2903 - "version": "1.0.2",
2904 - "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz",
2905 - "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
2906 - "dependencies": {
2907 - "wildcard": "^1.1.0"
2908 - }
2909 - },
2910 "node_modules/mime-types": { 2647 "node_modules/mime-types": {
2911 "version": "2.1.35", 2648 "version": "2.1.35",
2912 "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2649 "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
...@@ -3032,11 +2769,6 @@ ...@@ -3032,11 +2769,6 @@
3032 "thenify-all": "^1.0.0" 2769 "thenify-all": "^1.0.0"
3033 } 2770 }
3034 }, 2771 },
3035 - "node_modules/namespace-emitter": {
3036 - "version": "2.0.1",
3037 - "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
3038 - "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g=="
3039 - },
3040 "node_modules/nanoid": { 2772 "node_modules/nanoid": {
3041 "version": "3.3.11", 2773 "version": "3.3.11",
3042 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 2774 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
...@@ -3108,48 +2840,6 @@ ...@@ -3108,48 +2840,6 @@
3108 "url": "https://github.com/sponsors/ljharb" 2840 "url": "https://github.com/sponsors/ljharb"
3109 } 2841 }
3110 }, 2842 },
3111 - "node_modules/p-queue": {
3112 - "version": "8.1.0",
3113 - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz",
3114 - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==",
3115 - "dependencies": {
3116 - "eventemitter3": "^5.0.1",
3117 - "p-timeout": "^6.1.2"
3118 - },
3119 - "engines": {
3120 - "node": ">=18"
3121 - },
3122 - "funding": {
3123 - "url": "https://github.com/sponsors/sindresorhus"
3124 - }
3125 - },
3126 - "node_modules/p-retry": {
3127 - "version": "6.2.1",
3128 - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz",
3129 - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==",
3130 - "dependencies": {
3131 - "@types/retry": "0.12.2",
3132 - "is-network-error": "^1.0.0",
3133 - "retry": "^0.13.1"
3134 - },
3135 - "engines": {
3136 - "node": ">=16.17"
3137 - },
3138 - "funding": {
3139 - "url": "https://github.com/sponsors/sindresorhus"
3140 - }
3141 - },
3142 - "node_modules/p-timeout": {
3143 - "version": "6.1.4",
3144 - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz",
3145 - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==",
3146 - "engines": {
3147 - "node": ">=14.16"
3148 - },
3149 - "funding": {
3150 - "url": "https://github.com/sponsors/sindresorhus"
3151 - }
3152 - },
3153 "node_modules/package-json-from-dist": { 2843 "node_modules/package-json-from-dist": {
3154 "version": "1.0.1", 2844 "version": "1.0.1",
3155 "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", 2845 "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
...@@ -3398,15 +3088,6 @@ ...@@ -3398,15 +3088,6 @@
3398 "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 3088 "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
3399 "dev": true 3089 "dev": true
3400 }, 3090 },
3401 - "node_modules/preact": {
3402 - "version": "10.26.4",
3403 - "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.4.tgz",
3404 - "integrity": "sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==",
3405 - "funding": {
3406 - "type": "opencollective",
3407 - "url": "https://opencollective.com/preact"
3408 - }
3409 - },
3410 "node_modules/process": { 3091 "node_modules/process": {
3411 "version": "0.11.10", 3092 "version": "0.11.10",
3412 "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 3093 "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
...@@ -3518,14 +3199,6 @@ ...@@ -3518,14 +3199,6 @@
3518 "url": "https://github.com/sponsors/ljharb" 3199 "url": "https://github.com/sponsors/ljharb"
3519 } 3200 }
3520 }, 3201 },
3521 - "node_modules/retry": {
3522 - "version": "0.13.1",
3523 - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
3524 - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
3525 - "engines": {
3526 - "node": ">= 4"
3527 - }
3528 - },
3529 "node_modules/reusify": { 3202 "node_modules/reusify": {
3530 "version": "1.1.0", 3203 "version": "1.1.0",
3531 "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", 3204 "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
...@@ -3628,11 +3301,6 @@ ...@@ -3628,11 +3301,6 @@
3628 "semver": "bin/semver.js" 3301 "semver": "bin/semver.js"
3629 } 3302 }
3630 }, 3303 },
3631 - "node_modules/shallow-equal": {
3632 - "version": "3.1.0",
3633 - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz",
3634 - "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg=="
3635 - },
3636 "node_modules/shebang-command": { 3304 "node_modules/shebang-command": {
3637 "version": "2.0.0", 3305 "version": "2.0.0",
3638 "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 3306 "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
...@@ -3746,6 +3414,11 @@ ...@@ -3746,6 +3414,11 @@
3746 "node": ">=0.10.0" 3414 "node": ">=0.10.0"
3747 } 3415 }
3748 }, 3416 },
3417 + "node_modules/spark-md5": {
3418 + "version": "2.0.2",
3419 + "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-2.0.2.tgz",
3420 + "integrity": "sha512-9WfT+FYBEvlrOOBEs484/zmbtSX4BlGjzXih1qIEWA1yhHbcqgcMHkiwXoWk2Sq1aJjLpcs6ZKV7JxrDNjIlNg=="
3421 + },
3749 "node_modules/string-width": { 3422 "node_modules/string-width": {
3750 "version": "5.1.2", 3423 "version": "5.1.2",
3751 "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 3424 "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
...@@ -4448,11 +4121,6 @@ ...@@ -4448,11 +4121,6 @@
4448 "node": ">= 8" 4121 "node": ">= 8"
4449 } 4122 }
4450 }, 4123 },
4451 - "node_modules/wildcard": {
4452 - "version": "1.1.2",
4453 - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
4454 - "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
4455 - },
4456 "node_modules/wrap-ansi": { 4124 "node_modules/wrap-ansi": {
4457 "version": "8.1.0", 4125 "version": "8.1.0",
4458 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 4126 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
19 "@vant/touch-emulator": "^1.4.0", 19 "@vant/touch-emulator": "^1.4.0",
20 "@vant/use": "^1.6.0", 20 "@vant/use": "^1.6.0",
21 "@videojs-player/vue": "^1.0.0", 21 "@videojs-player/vue": "^1.0.0",
22 + "browser-md5-file": "^1.1.1",
22 "dayjs": "^1.11.13", 23 "dayjs": "^1.11.13",
23 "swiper": "^11.2.6", 24 "swiper": "^11.2.6",
24 "vant": "^4.9.18", 25 "vant": "^4.9.18",
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
41 import { ref, defineProps, defineEmits, watch } from 'vue'; 41 import { ref, defineProps, defineEmits, watch } from 'vue';
42 import { showToast } from 'vant'; 42 import { showToast } from 'vant';
43 import VideoPlayer from '@/components/ui/VideoPlayer.vue'; 43 import VideoPlayer from '@/components/ui/VideoPlayer.vue';
44 -import { v4 as uuidv4 } from 'uuid'; 44 +import { uploadFile, validateFile } from '@/utils/upload';
45 45
46 const props = defineProps({ 46 const props = defineProps({
47 modelValue: { 47 modelValue: {
...@@ -76,8 +76,9 @@ const uploadProgress = ref(0); ...@@ -76,8 +76,9 @@ const uploadProgress = ref(0);
76 const maxSize = 100 * 1024 * 1024; // 100MB 76 const maxSize = 100 * 1024 * 1024; // 100MB
77 77
78 const beforeRead = (file) => { 78 const beforeRead = (file) => {
79 - if (!file.type.includes('video/')) { 79 + const validation = validateFile(file);
80 - showToast('请上传视频文件'); 80 + if (!validation.valid) {
81 + showToast(validation.message);
81 return false; 82 return false;
82 } 83 }
83 return true; 84 return true;
...@@ -90,28 +91,22 @@ const afterRead = async (file) => { ...@@ -90,28 +91,22 @@ const afterRead = async (file) => {
90 videoName.value = ''; 91 videoName.value = '';
91 uploadProgress.value = 0; 92 uploadProgress.value = 0;
92 93
93 - const formData = new FormData();
94 - formData.append('file', file.file);
95 -
96 try { 94 try {
97 - // 模拟上传进度 95 + // 实际上传逻辑
98 - const timer = setInterval(() => { 96 + const fileCode = 'video'; // 视频上传的fileCode
99 - uploadProgress.value += 10; 97 + const result = await uploadFile(file.file, fileCode, (progress) => {
100 - if (uploadProgress.value >= 100) { 98 + uploadProgress.value = progress;
101 - clearInterval(timer); 99 + });
102 - // 模拟上传成功后的视频URL 100 +
103 - videoUrl.value = URL.createObjectURL(file.file); 101 + if (result && result.src) {
104 - videoId.value = uuidv4(); 102 + videoUrl.value = result.src;
105 - videoName.value = file.file.name; 103 + videoId.value = result.meta_id || result.hash;
106 - } 104 + videoName.value = file.file.name;
107 - }, 300); 105 + } else {
108 - 106 + throw new Error('上传失败');
109 - // TODO: 实际的上传逻辑 107 + }
110 - // const response = await uploadVideo(formData);
111 - // videoUrl.value = response.data.url;
112 - // videoId.value = uuidv4();
113 - // videoName.value = file.file.name;
114 } catch (error) { 108 } catch (error) {
109 + uploadProgress.value = 0;
115 showToast('上传失败'); 110 showToast('上传失败');
116 console.error('Upload error:', error); 111 console.error('Upload error:', error);
117 } 112 }
......
1 +import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common';
2 +import BMF from 'browser-md5-file';
3 +// import { v4 as uuidv4 } from 'uuid';
4 +
5 +// 获取文件后缀
6 +const getFileSuffix = (fileName) => {
7 + return /.[^.]+$/.exec(fileName) || '';
8 +};
9 +
10 +// 获取文件MD5
11 +const getFileMD5 = (file) => {
12 + return new Promise((resolve, reject) => {
13 + const bmf = new BMF();
14 + bmf.md5(file, (err, md5) => {
15 + if (err) {
16 + reject(err);
17 + return;
18 + }
19 + resolve(md5);
20 + });
21 + });
22 +};
23 +
24 +// 上传文件到七牛云
25 +const uploadToQiniu = async (file, token, fileName, onProgress) => {
26 + const formData = new FormData();
27 + formData.append('file', file);
28 + formData.append('token', token);
29 + formData.append('key', fileName);
30 +
31 + const config = {
32 + headers: { 'Content-Type': 'multipart/form-data' },
33 + onUploadProgress: (progressEvent) => {
34 + if (progressEvent.total > 0) {
35 + const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
36 + // 使用requestAnimationFrame确保进度更新的平滑性
37 + requestAnimationFrame(() => {
38 + onProgress?.(percent);
39 + });
40 + }
41 + }
42 + };
43 +
44 + // 根据协议选择上传地址
45 + const qiniuUploadUrl = window.location.protocol === 'https:'
46 + ? 'https://up.qbox.me'
47 + : 'http://upload.qiniu.com';
48 +
49 + return await qiniuUploadAPI(qiniuUploadUrl, formData, config);
50 +};
51 +
52 +// 校验文件
53 +export const validateFile = (file, options = {}) => {
54 + const {
55 + maxSize = 100, // 默认100MB
56 + allowedTypes = ['video/mp4', 'video/quicktime'],
57 + } = options;
58 +
59 + if (!allowedTypes.includes(file.type)) {
60 + return {
61 + valid: false,
62 + message: '请上传正确格式的视频文件'
63 + };
64 + }
65 +
66 + const fileSize = (file.size / 1024 / 1024).toFixed(2);
67 + if (fileSize > maxSize) {
68 + return {
69 + valid: false,
70 + message: `文件大小不能超过${maxSize}MB`
71 + };
72 + }
73 +
74 + return { valid: true };
75 +};
76 +
77 +// 上传文件
78 +export const uploadFile = async (file, fileCode, onProgress) => {
79 + try {
80 + // 获取文件MD5
81 + const md5 = await getFileMD5(file);
82 +
83 + // 获取七牛token
84 + const tokenResult = await qiniuTokenAPI({
85 + name: file.name,
86 + hash: md5
87 + });
88 +
89 + // 如果文件已存在,直接返回
90 + if (tokenResult.data) {
91 + onProgress?.(100);
92 + return tokenResult.data;
93 + }
94 +
95 + // 新文件上传
96 + if (tokenResult.token) {
97 + const suffix = getFileSuffix(file.name);
98 + const fileName = `uploadForm/${fileCode}/${md5}${suffix}`;
99 +
100 + // TODO: image_info 为七牛返回的图片信息,现在是上传视频看后期适配
101 + const { filekey, image_info } = await uploadToQiniu(
102 + file,
103 + tokenResult.token,
104 + fileName,
105 + onProgress
106 + );
107 +
108 + if (filekey) {
109 + // 保存文件信息
110 + const { data } = await saveFileAPI({
111 + name: file.name,
112 + filekey,
113 + hash: md5,
114 + height: image_info?.height,
115 + width: image_info?.width,
116 + });
117 +
118 + return data;
119 + }
120 + }
121 +
122 + throw new Error('上传失败');
123 + } catch (error) {
124 + console.error('Upload error:', error);
125 + throw error;
126 + }
127 +};