diff --git a/package.json b/package.json
index 23b0953..9f5e8e8 100644
--- a/package.json
+++ b/package.json
@@ -21,11 +21,13 @@
"dingtalk-jsapi": "^3.0.20",
"echarts": "5.2.2",
"element-ui": "2.15.6",
+ "js-sha3": "^0.9.3",
"jsonwebtoken": "^9.0.2",
"nprogress": "0.2.0",
"screenfull": "5.2.0",
"serve": "^14.2.0",
"sign-canvas": "1.1.4",
+ "spark-md5": "^3.0.2",
"vue": "^2.6.14",
"vue-cropper": "^0.6.2",
"vue-cropperjs": "^2.2.2",
diff --git a/src/com/cutUpload.js b/src/com/cutUpload.js
new file mode 100644
index 0000000..c37e223
--- /dev/null
+++ b/src/com/cutUpload.js
@@ -0,0 +1,179 @@
+import { getProgress, postTask, getPartUrl, getMerge } from "/src/com/uploadApi";
+// import createOverallHase from '@/com/createOverallHase'
+import SparkMD5 from 'spark-md5'
+import axios from "axios";
+
+const DEFAULT_SIZE = 20 * 1024 * 1024
+export function cutUpload (file, isFace = false, backUploadProgress){
+ return new Promise((resolve, reject) => {
+ const PART_SIZE = 1024 * 1024 * 20; // 20M
+ // 计算上传进度
+ const calculateProgress = (progressArr, total) => {
+ let count = 0;
+ progressArr.forEach((item) => {
+ count += item;
+ });
+ if (count == total) {
+ count = Math.floor(total * 0.9999);//如果上传进度为100%,伪造上传进度,为合并文件做准备
+ }
+ return count;
+ };
+ // 分片上传函数
+ const requestUploadFun = async (url, fileData, uploadProgress) => {
+ try {
+ await axios.put(url, fileData, {
+ headers: {
+ "Content-Type": "application/octet-stream",
+ },
+ onUploadProgress: function (progressEvent) {
+ uploadProgress(progressEvent.loaded);
+ }
+ });
+ } catch (error) {
+ console.error(error);
+ reject(error);
+ throw error;
+ }
+ };
+
+ const uploadChunks = async (file, identifier, progressData, uploadProgressFun) => {
+ const progressEvent = { total: file.size, loaded: 0 };
+ const progressArr = [];
+ const partNumberSet = new Set(progressData.parts.map((item) => item.partNumber));
+ const partCount = Math.ceil(file.size / PART_SIZE);
+ let totalSize = 0;
+ const partArr = [];
+ for (let i = 0; i < partCount; i++) {
+ let partNumber = i + 1;
+ const start = PART_SIZE * (partNumber - 1);
+ const end = Math.min(start + PART_SIZE, file.size);
+ if (!partNumberSet.has(partNumber)) {
+ const blob = file.slice(start, end);
+ totalSize += blob.size;
+ progressArr[partNumber] = 0;
+ partArr.push({ partNumber, blob });
+ } else {
+ progressArr[partNumber] = end - start;
+ progressEvent.loaded = calculateProgress(progressArr, progressEvent.total);
+ uploadProgressFun(progressEvent);
+ }
+ }
+
+ const uploadUrlDataArr = await Promise.all(partArr.map(async item => {
+ const urlData = await getPartUrl(identifier, item.partNumber);
+ return {
+ uploadUrl: urlData.uploadUrl,
+ fileData: item.blob,
+ partNumber: item.partNumber
+ }
+ }));
+
+ const uploadPromises = uploadUrlDataArr.map(async (uploadUrlData, i) => {
+ return requestUploadFun(uploadUrlData.uploadUrl, uploadUrlData.fileData, function (loaded) {
+ progressArr[uploadUrlData.partNumber] = loaded;
+ progressEvent.loaded = calculateProgress(progressArr, progressEvent.total);
+ uploadProgressFun(progressEvent);
+ });
+ });
+
+ await Promise.all(uploadPromises);
+ };
+
+ // 获取hash
+ const uploadFile = async (file, onUploadProgress = () => {}, checkFace, onCheckFace = () => {}) => {
+ if (file) {
+ const hashStr = await createOverallHase(file);
+ const fileForm = {
+ identifier: hashStr,
+ fileName: file.name,
+ fileSize: file.size.toString(),
+ checkFace: checkFace,
+ };
+ uploadProgress(file, fileForm, onCheckFace, onUploadProgress)
+ } else {
+ console.log("文件为空");
+ }
+ };
+
+ let obj = {}
+ uploadFile(file, function(Progress) {
+ backUploadProgress(Progress)
+ }, isFace, function(faceData){
+ resolve({...obj, ...faceData})
+ })
+
+ // 判断任务 是否存在
+ const uploadProgress = async (file, fileForm, onCheckFace, onUploadProgressFun) => {
+ try {
+ const progressData = await getProgress(fileForm.identifier, fileForm.checkFace);
+ if (progressData.errMessage === "文件上传任务不存在") {
+ await postTask(fileForm);
+ await uploadProgress(file, fileForm, onCheckFace, onUploadProgressFun);
+ } else {
+ if (!progressData.finished) {
+ if (progressData.parts.length == progressData.totalPartNum) {
+ await getMerge(fileForm.identifier);
+ } else {
+ //const chunksArr = await uploadFile(file);
+ await uploadChunks(file, fileForm.identifier, progressData, onUploadProgressFun);
+ }
+ await uploadProgress(file, fileForm, onCheckFace, onUploadProgressFun);
+ } else {
+ let checkFaceMsg = progressData.checkFaceMsg
+
+ // onUploadProgressFun({ total: Number(file.size), loaded: Number(file.size) });
+ onUploadProgressFun({ total: Number(file.size), loaded: Number(file.size), path: progressData.path })
+ if (fileForm.checkFace) {
+ // onCheckFace({ isFace: progressData.face, checkFaceMsg: progressData.checkFaceMsg });
+ onCheckFace({ total: Number(file.size), loaded: Number(file.size), isFace: progressData.face, checkFaceMsg, path: progressData.path })
+ }
+ // let checkFaceMsg = progressData.checkFaceMsg
+ // resolve({ total: Number(file.size), loaded: Number(file.size), isFace: progressData.face, checkFaceMsg, path: progressData.path });
+ // console.log(progressData.path);
+ }
+ }
+ } catch (err) {
+ reject(err);
+ }
+ };
+
+ })
+}
+
+// md5
+const createOverallHase = (file, chunkSize = DEFAULT_SIZE) => {
+ return new Promise((resolve, reject) => {
+ const startMs = new Date().getTime();
+ let blobSlice =
+ File.prototype.slice ||
+ File.prototype.mozSlice ||
+ File.prototype.webkitSlice;
+ let chunks = Math.ceil(file.size / chunkSize);
+ let currentChunk = 0;
+ let spark = new SparkMD5.ArrayBuffer(); //追加数组缓冲区。
+ let fileReader = new FileReader(); //读取文件
+ fileReader.onload = function (e) {
+ spark.append(e.target.result);
+ currentChunk++;
+ if (currentChunk < chunks) {
+ loadNext();
+ } else {
+ const md5 = spark.end(); //完成md5的计算,返回十六进制结果。
+ console.log('文件md5计算结束,总耗时:', (new Date().getTime() - startMs) / 1000, 's')
+ resolve(md5);
+ }
+ };
+ fileReader.onerror = function (e) {
+ reject(e);
+ };
+
+ function loadNext() {
+ console.log('当前part number:', currentChunk, '总块数:', chunks);
+ let start = currentChunk * chunkSize;
+ let end = start + chunkSize;
+ (end > file.size) && (end = file.size);
+ fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
+ }
+ loadNext();
+ });
+}
\ No newline at end of file
diff --git a/src/com/uploadApi.js b/src/com/uploadApi.js
new file mode 100644
index 0000000..a43d0cf
--- /dev/null
+++ b/src/com/uploadApi.js
@@ -0,0 +1,35 @@
+import request from "/src/utils/request";
+
+
+// 查询分片上传进度
+export function getProgress(identifier,checkFace){
+ return request({
+ url: `/manager/file/task/${identifier}?checkFace=${checkFace}`,
+ method: 'GET',
+ })
+}
+
+// 初始化分片上传
+export function postTask(data){
+ return request({
+ url: '/manager/file/task',
+ method: 'POST',
+ data
+ })
+}
+// 获取指定分片的上传地址
+export function getPartUrl(identifier, partNumber){
+ return request({
+ url: `/manager/file/task/part/${identifier}/${partNumber}`,
+ method: 'GET',
+ })
+}
+
+// 完成上传时调用
+export function getMerge(identifier){
+ return request({
+ url: `/manager/file/task/merge/${identifier}`,
+ method: 'GET',
+ })
+}
+
diff --git a/src/views/classList/classList/index.vue b/src/views/classList/classList/index.vue
index fed75e3..7e568fd 100644
--- a/src/views/classList/classList/index.vue
+++ b/src/views/classList/classList/index.vue
@@ -35,7 +35,7 @@
修改名称
删除
- 设置规则
+ 设置规则
@@ -155,9 +155,14 @@
-
+
+
+
@@ -165,14 +170,18 @@
import columns from "./columns";
import { getClass, getClassStudent, postManager, putManager, deleteManager, getGuardian } from "./api";
import { getRuleGroup } from "../../regulation/api";
-
+import { Loading } from 'element-ui';
import { formatDate } from "@/com/index";
import CommonHead from './components/CommonHead.vue'
+import { cutUpload } from "@/com/cutUpload";
+// import workerUrl from '@/com/worker.js';
+// import { cutFile } from '@/com/cutFile'
const FlagEnum = {
INTO: 0,// 进
OUT: 1,// 出
MORNING: 2, // 早上到校时间
};
+let loading
export default {
name: "deviceManagement",
data() {
@@ -217,8 +226,9 @@ export default {
/* 设置规则组 */
isRuleDialog: false, // 进出校规则模态框
activeName: '', // 展开的规则组
- radio: '',
+ radio: '', // 校区选中的规则组
ruleGroupArr: [], // 规则组数据
+ loadingText: '打包中'
};
},
components: {
@@ -235,8 +245,62 @@ export default {
}
},
mounted () {
+ // console.log(workerUrl)
+ // let worker = new Worker(workerUrl);
},
methods: {
+
+ async onClickFile(e) {
+ loading = Loading.service({
+ lock: true,
+ text: '打包上传中...',
+ spinner: 'el-icon-loading',
+ background: 'rgba(0, 0, 0, 0.7)'
+ });
+ const file = e.target.files[0]
+
+ cutUpload(file, true, (progressEvent) =>{
+ let progressNum = (progressEvent.loaded / progressEvent.total) * 100
+ loading.text = '上传进度' + progressNum.toFixed(2) + '%'
+ if(progressNum == 100){
+ console.log('完成')
+ loading.text = '上传完成!'
+ console.log(loading.text)
+ setTimeout(() => {
+ loading.close();
+ }, 1000);
+ }
+ console.log(progressEvent.loaded + '/' + progressEvent.total);
+ }).then(res =>{
+ console.log(res)
+ })
+
+ },
+ // 点击确定修改小区规则
+ onClickAffirmRule() {
+ console.log(this.radio)
+ if(!this.radio){
+ this.$message.error('请选择需要设置的规则组')
+ return
+ }
+ this.ruleGroupForm.ruleGroupId = this.radio
+ putManager(this.ruleGroupForm).then(res =>{
+ this.$message.success('修改成功')
+ this.classList();
+ this.nodeData = this.ruleGroupForm.ruleGroupId
+ this.isRuleDialog = false
+
+ })
+
+ },
+ // 点击设置规则组
+ onClickUpdateRule () {
+ this.isRuleDialog = true
+ console.log(this.nodeData)
+ this.ruleGroupForm = JSON.parse(JSON.stringify(this.nodeData))
+ this.radio = this.ruleGroupForm.ruleGroupId
+
+ },
// 规则组列表
ruleList(){
getRuleGroup().then( res =>{
diff --git a/yarn.lock b/yarn.lock
index 6c5fa0c..89f3255 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5665,6 +5665,11 @@ js-message@1.0.7:
resolved "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz"
integrity sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==
+js-sha3@^0.9.3:
+ version "0.9.3"
+ resolved "https://registry.npmmirror.com/js-sha3/-/js-sha3-0.9.3.tgz#f0209432b23a66a0f6c7af592c26802291a75c2a"
+ integrity sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==
+
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz"
@@ -8336,6 +8341,11 @@ source-map@^0.7.3:
resolved "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz"
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+spark-md5@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmmirror.com/spark-md5/-/spark-md5-3.0.2.tgz#7952c4a30784347abcee73268e473b9c0167e3fc"
+ integrity sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==
+
spdx-correct@^3.0.0:
version "3.2.0"
resolved "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz"