hookehuyr

联调图片上传功能

...@@ -13,15 +13,18 @@ ...@@ -13,15 +13,18 @@
13 "@vitejs/plugin-legacy": "^1.8.2", 13 "@vitejs/plugin-legacy": "^1.8.2",
14 "@vueuse/core": "^8.5.0", 14 "@vueuse/core": "^8.5.0",
15 "animate.css": "^4.1.1", 15 "animate.css": "^4.1.1",
16 + "browser-md5-file": "^1.1.1",
16 "dayjs": "^1.11.3", 17 "dayjs": "^1.11.3",
17 "default-passive-events": "^2.0.0", 18 "default-passive-events": "^2.0.0",
18 "global": "^4.4.0", 19 "global": "^4.4.0",
19 "html2canvas": "^1.4.1", 20 "html2canvas": "^1.4.1",
20 "jquery": "^3.6.0", 21 "jquery": "^3.6.0",
21 "js-cookie": "^3.0.1", 22 "js-cookie": "^3.0.1",
23 + "js-sha1": "^0.6.0",
22 "lodash": "^4.17.21", 24 "lodash": "^4.17.21",
23 "moment": "^2.29.3", 25 "moment": "^2.29.3",
24 "mui-player": "^1.7.0", 26 "mui-player": "^1.7.0",
27 + "sha1": "^1.1.1",
25 "typescript": "^4.7.3", 28 "typescript": "^4.7.3",
26 "uuid": "^8.3.2", 29 "uuid": "^8.3.2",
27 "vant": "^4.0.0-rc.8", 30 "vant": "^4.0.0-rc.8",
...@@ -1204,6 +1207,15 @@ ...@@ -1204,6 +1207,15 @@
1204 "node": ">=8" 1207 "node": ">=8"
1205 } 1208 }
1206 }, 1209 },
1210 + "node_modules/browser-md5-file": {
1211 + "version": "1.1.1",
1212 + "resolved": "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz",
1213 + "integrity": "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw==",
1214 + "license": "MIT",
1215 + "dependencies": {
1216 + "spark-md5": "^2.0.2"
1217 + }
1218 + },
1207 "node_modules/browser-stdout": { 1219 "node_modules/browser-stdout": {
1208 "version": "1.3.1", 1220 "version": "1.3.1",
1209 "resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz", 1221 "resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz",
...@@ -1389,6 +1401,15 @@ ...@@ -1389,6 +1401,15 @@
1389 "tslib": "^2.0.3" 1401 "tslib": "^2.0.3"
1390 } 1402 }
1391 }, 1403 },
1404 + "node_modules/charenc": {
1405 + "version": "0.0.2",
1406 + "resolved": "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz",
1407 + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
1408 + "license": "BSD-3-Clause",
1409 + "engines": {
1410 + "node": "*"
1411 + }
1412 + },
1392 "node_modules/check-error": { 1413 "node_modules/check-error": {
1393 "version": "1.0.2", 1414 "version": "1.0.2",
1394 "resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz", 1415 "resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz",
...@@ -1656,6 +1677,15 @@ ...@@ -1656,6 +1677,15 @@
1656 "node": ">= 8" 1677 "node": ">= 8"
1657 } 1678 }
1658 }, 1679 },
1680 + "node_modules/crypt": {
1681 + "version": "0.0.2",
1682 + "resolved": "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz",
1683 + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
1684 + "license": "BSD-3-Clause",
1685 + "engines": {
1686 + "node": "*"
1687 + }
1688 + },
1659 "node_modules/css-line-break": { 1689 "node_modules/css-line-break": {
1660 "version": "2.1.0", 1690 "version": "2.1.0",
1661 "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", 1691 "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
...@@ -3431,6 +3461,12 @@ ...@@ -3431,6 +3461,12 @@
3431 "node": ">=12" 3461 "node": ">=12"
3432 } 3462 }
3433 }, 3463 },
3464 + "node_modules/js-sha1": {
3465 + "version": "0.6.0",
3466 + "resolved": "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz",
3467 + "integrity": "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==",
3468 + "license": "MIT"
3469 + },
3434 "node_modules/js-tokens": { 3470 "node_modules/js-tokens": {
3435 "version": "4.0.0", 3471 "version": "4.0.0",
3436 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 3472 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
...@@ -5052,6 +5088,19 @@ ...@@ -5052,6 +5088,19 @@
5052 "randombytes": "^2.1.0" 5088 "randombytes": "^2.1.0"
5053 } 5089 }
5054 }, 5090 },
5091 + "node_modules/sha1": {
5092 + "version": "1.1.1",
5093 + "resolved": "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz",
5094 + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=",
5095 + "license": "BSD-3-Clause",
5096 + "dependencies": {
5097 + "charenc": ">= 0.0.1",
5098 + "crypt": ">= 0.0.1"
5099 + },
5100 + "engines": {
5101 + "node": "*"
5102 + }
5103 + },
5055 "node_modules/shebang-command": { 5104 "node_modules/shebang-command": {
5056 "version": "2.0.0", 5105 "version": "2.0.0",
5057 "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz", 5106 "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz",
...@@ -5193,6 +5242,12 @@ ...@@ -5193,6 +5242,12 @@
5193 "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 5242 "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
5194 "license": "MIT" 5243 "license": "MIT"
5195 }, 5244 },
5245 + "node_modules/spark-md5": {
5246 + "version": "2.0.2",
5247 + "resolved": "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz",
5248 + "integrity": "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc=",
5249 + "license": "WTFPL"
5250 + },
5196 "node_modules/sprintf-js": { 5251 "node_modules/sprintf-js": {
5197 "version": "1.0.3", 5252 "version": "1.0.3",
5198 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 5253 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
...@@ -7042,6 +7097,14 @@ ...@@ -7042,6 +7097,14 @@
7042 "fill-range": "^7.0.1" 7097 "fill-range": "^7.0.1"
7043 } 7098 }
7044 }, 7099 },
7100 + "browser-md5-file": {
7101 + "version": "1.1.1",
7102 + "resolved": "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz",
7103 + "integrity": "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw==",
7104 + "requires": {
7105 + "spark-md5": "^2.0.2"
7106 + }
7107 + },
7045 "browser-stdout": { 7108 "browser-stdout": {
7046 "version": "1.3.1", 7109 "version": "1.3.1",
7047 "resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz", 7110 "resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz",
...@@ -7172,6 +7235,11 @@ ...@@ -7172,6 +7235,11 @@
7172 "tslib": "^2.0.3" 7235 "tslib": "^2.0.3"
7173 } 7236 }
7174 }, 7237 },
7238 + "charenc": {
7239 + "version": "0.0.2",
7240 + "resolved": "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz",
7241 + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
7242 + },
7175 "check-error": { 7243 "check-error": {
7176 "version": "1.0.2", 7244 "version": "1.0.2",
7177 "resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz", 7245 "resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz",
...@@ -7358,6 +7426,11 @@ ...@@ -7358,6 +7426,11 @@
7358 "which": "^2.0.1" 7426 "which": "^2.0.1"
7359 } 7427 }
7360 }, 7428 },
7429 + "crypt": {
7430 + "version": "0.0.2",
7431 + "resolved": "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz",
7432 + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
7433 + },
7361 "css-line-break": { 7434 "css-line-break": {
7362 "version": "2.1.0", 7435 "version": "2.1.0",
7363 "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", 7436 "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
...@@ -8569,6 +8642,11 @@ ...@@ -8569,6 +8642,11 @@
8569 "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", 8642 "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
8570 "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" 8643 "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
8571 }, 8644 },
8645 + "js-sha1": {
8646 + "version": "0.6.0",
8647 + "resolved": "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz",
8648 + "integrity": "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w=="
8649 + },
8572 "js-tokens": { 8650 "js-tokens": {
8573 "version": "4.0.0", 8651 "version": "4.0.0",
8574 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 8652 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
...@@ -9668,6 +9746,15 @@ ...@@ -9668,6 +9746,15 @@
9668 "randombytes": "^2.1.0" 9746 "randombytes": "^2.1.0"
9669 } 9747 }
9670 }, 9748 },
9749 + "sha1": {
9750 + "version": "1.1.1",
9751 + "resolved": "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz",
9752 + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=",
9753 + "requires": {
9754 + "charenc": ">= 0.0.1",
9755 + "crypt": ">= 0.0.1"
9756 + }
9757 + },
9671 "shebang-command": { 9758 "shebang-command": {
9672 "version": "2.0.0", 9759 "version": "2.0.0",
9673 "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz", 9760 "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz",
...@@ -9768,6 +9855,11 @@ ...@@ -9768,6 +9855,11 @@
9768 "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 9855 "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
9769 "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" 9856 "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
9770 }, 9857 },
9858 + "spark-md5": {
9859 + "version": "2.0.2",
9860 + "resolved": "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz",
9861 + "integrity": "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc="
9862 + },
9771 "sprintf-js": { 9863 "sprintf-js": {
9772 "version": "1.0.3", 9864 "version": "1.0.3",
9773 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 9865 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
......
...@@ -17,15 +17,18 @@ ...@@ -17,15 +17,18 @@
17 "@vitejs/plugin-legacy": "^1.8.2", 17 "@vitejs/plugin-legacy": "^1.8.2",
18 "@vueuse/core": "^8.5.0", 18 "@vueuse/core": "^8.5.0",
19 "animate.css": "^4.1.1", 19 "animate.css": "^4.1.1",
20 + "browser-md5-file": "^1.1.1",
20 "dayjs": "^1.11.3", 21 "dayjs": "^1.11.3",
21 "default-passive-events": "^2.0.0", 22 "default-passive-events": "^2.0.0",
22 "global": "^4.4.0", 23 "global": "^4.4.0",
23 "html2canvas": "^1.4.1", 24 "html2canvas": "^1.4.1",
24 "jquery": "^3.6.0", 25 "jquery": "^3.6.0",
25 "js-cookie": "^3.0.1", 26 "js-cookie": "^3.0.1",
27 + "js-sha1": "^0.6.0",
26 "lodash": "^4.17.21", 28 "lodash": "^4.17.21",
27 "moment": "^2.29.3", 29 "moment": "^2.29.3",
28 "mui-player": "^1.7.0", 30 "mui-player": "^1.7.0",
31 + "sha1": "^1.1.1",
29 "typescript": "^4.7.3", 32 "typescript": "^4.7.3",
30 "uuid": "^8.3.2", 33 "uuid": "^8.3.2",
31 "vant": "^4.0.0-rc.8", 34 "vant": "^4.0.0-rc.8",
......
1 /* 1 /*
2 * @Date: 2022-06-17 14:54:29 2 * @Date: 2022-06-17 14:54:29
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2022-09-06 17:03:55 4 + * @LastEditTime: 2022-12-01 16:26:27
5 * @FilePath: /data-table/src/api/common.js 5 * @FilePath: /data-table/src/api/common.js
6 * @Description: 通用接口 6 * @Description: 通用接口
7 */ 7 */
...@@ -22,8 +22,6 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params)); ...@@ -22,8 +22,6 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
22 22
23 /** 23 /**
24 * @description: 获取七牛token 24 * @description: 获取七牛token
25 - * @param {*} filename 文件名
26 - * @param {*} file 图片base64
27 * @returns 25 * @returns
28 */ 26 */
29 export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params)); 27 export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));
......
...@@ -7,18 +7,28 @@ ...@@ -7,18 +7,28 @@
7 --> 7 -->
8 <template> 8 <template>
9 <div class="image-uploader-field"> 9 <div class="image-uploader-field">
10 - <div class="label">{{ item.label }}<span v-if="item.required">&nbsp;*</span></div> 10 + <div class="label">
11 + {{ item.component_props.label
12 + }}<span v-if="item.component_props.required">&nbsp;*</span>
13 + </div>
11 <div style="padding: 1rem"> 14 <div style="padding: 1rem">
12 <van-uploader 15 <van-uploader
13 upload-icon="add" 16 upload-icon="add"
14 :before-read="beforeRead" 17 :before-read="beforeRead"
15 :after-read="afterRead" 18 :after-read="afterRead"
19 + :before-delete="beforeDelete"
16 v-model="fileList" 20 v-model="fileList"
17 :multiple="item.component_props.multiple" 21 :multiple="item.component_props.multiple"
18 /> 22 />
19 </div> 23 </div>
20 <div class="type-text">上传格式:{{ type_text }}</div> 24 <div class="type-text">上传格式:{{ type_text }}</div>
21 </div> 25 </div>
26 +
27 + <van-overlay :show="loading">
28 + <div class="wrapper" @click.stop>
29 + <van-loading vertical color="#FFFFFF">上传中...</van-loading>
30 + </div>
31 + </van-overlay>
22 </template> 32 </template>
23 33
24 <script setup> 34 <script setup>
...@@ -28,84 +38,166 @@ ...@@ -28,84 +38,166 @@
28 * @param image_type[Array] 图片上传类型 38 * @param image_type[Array] 图片上传类型
29 * @param multiple[Boolean] 图片多选 39 * @param multiple[Boolean] 图片多选
30 */ 40 */
31 -import { Toast } from "vant"; 41 +import { showSuccessToast, showFailToast } from "vant";
32 import _ from "lodash"; 42 import _ from "lodash";
33 import { v4 as uuidv4 } from "uuid"; 43 import { v4 as uuidv4 } from "uuid";
34 import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from "@/api/common"; 44 import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from "@/api/common";
45 +import BMF from "browser-md5-file";
46 +import { useRoute } from "vue-router";
47 +import axios from "axios";
48 +import { getEtag } from "@/utils/qetag.js"; // 生成hash值
35 49
50 +const $route = useRoute();
36 const props = defineProps({ 51 const props = defineProps({
37 item: Object, 52 item: Object,
38 }); 53 });
54 +const emit = defineEmits(["active"]);
55 +
56 +const show_empty = ref(false);
39 57
58 +// 文件类型中文页面显示
40 const type_text = computed(() => { 59 const type_text = computed(() => {
41 - return props.item.component_props.image_type.join("/"); 60 + return props.item.component_props.image_type;
42 }); 61 });
43 62
44 // 上传前置处理 63 // 上传前置处理
45 const beforeRead = (file) => { 64 const beforeRead = (file) => {
65 + // 类型限制
46 const image_types = _.map( 66 const image_types = _.map(
47 - props.item.component_props.image_type, 67 + props.item.component_props.image_type.split("/"),
48 (item) => `image/${item}` 68 (item) => `image/${item}`
49 ); 69 );
70 +
50 let flag = true; 71 let flag = true;
51 if (_.isArray(file)) { 72 if (_.isArray(file)) {
52 // 多张图片 73 // 多张图片
53 const types = _.difference(_.uniq(_.map(file, (item) => item.type)), image_types); // 数组返回不能上传的类型 74 const types = _.difference(_.uniq(_.map(file, (item) => item.type)), image_types); // 数组返回不能上传的类型
54 if (types.length) { 75 if (types.length) {
55 flag = false; 76 flag = false;
56 - Toast("请上传指定格式图片"); 77 + showFailToast("请上传指定格式图片");
57 } 78 }
58 } else { 79 } else {
59 if (!_.includes(image_types, file.type)) { 80 if (!_.includes(image_types, file.type)) {
60 - Toast("请上传指定格式图片"); 81 + showFailToast("请上传指定格式图片");
61 flag = false; 82 flag = false;
62 } 83 }
63 } 84 }
64 return flag; 85 return flag;
65 }; 86 };
66 87
67 -const afterRead = async (file) => { 88 +/********** 上传七牛云获取图片地址 ***********/
68 - // 此时可以自行将文件上传至服务器 89 +const loading = ref(false);
69 - let affix = uuidv4(); 90 +const formCode = $route.query.code; // 表单code
70 - let base64url = file.content.slice(file.content.indexOf(",") + 1); // 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA....... 91 +const uuid = () => {
92 + let s = [];
93 + let hexDigits = "0123456789abcdef";
94 + for (var i = 0; i < 36; i++) {
95 + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
96 + }
97 + s[14] = "4";
98 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
99 + s[8] = s[13] = s[18] = s[23] = "-";
100 +
101 + var uuid = s.join("");
102 + return uuid;
103 +};
104 +
105 +const uploadQiniu = async (file, token, filename) => {
106 + let formData = new FormData();
107 + formData.append("file", file); // 通过append向form对象添加数据
108 + formData.append("token", token);
109 + formData.append("key", formCode + "/" + uuid() + "." + file.name.split(".")[1]);
110 + let config = {
111 + headers: { "Content-Type": "multipart/form-data" },
112 + };
113 + // 自拍图片上传七牛服务器
114 + const { filekey, hash, image_info } = await qiniuUploadAPI(
115 + "http://upload.qiniu.com/",
116 + formData,
117 + config
118 + );
119 + if (filekey) {
120 + // 保存图片
121 + const { data } = await saveFileAPI({
122 + filekey,
123 + hash,
124 + format: image_info.format,
125 + height: image_info.height,
126 + width: image_info.width,
127 + });
128 + return data;
129 + }
130 +};
131 +/****************** END *******************/
132 +
133 +const afterRead = async (files) => {
134 + loading.value = true;
135 + // 获取HASH值
136 + const hash = getEtag(files.content);
71 // 获取七牛token 137 // 获取七牛token
138 + const filename = formCode + "/" + uuid() + "." + files.file.name.split(".")[1];
72 const { token, key, code } = await qiniuTokenAPI({ 139 const { token, key, code } = await qiniuTokenAPI({
73 - filename: `${affix}_image_upload`, 140 + name: filename,
74 - file: base64url, 141 + hash,
75 }); 142 });
76 - if (code) { 143 + // 文件上传七牛云
77 - const config = { 144 + files.status = "uploading";
78 - headers: { 145 + files.message = "上传中...";
79 - "Content-Type": "application/octet-stream", 146 + const imgUrl = await uploadQiniu(files.file, token, filename);
80 - Authorization: "UpToken " + token, // UpToken后必须有一个 ' '(空格) 147 + // 上传失败提示
81 - }, 148 + if (!imgUrl.src) {
149 + files.status = "failed";
150 + files.message = "上传失败";
151 + loading.value = false;
152 + } else {
153 + files.status = "";
154 + files.message = "";
155 + fileList.value.pop();
156 + fileList.value.push({
157 + url: imgUrl.src,
158 + isImage: true,
159 + });
160 +
161 + props.item.value = {
162 + key: "image_uploader",
163 + filed_name: props.item.key,
164 + value: fileList.value,
82 }; 165 };
83 - // 上传七牛服务器 166 + emit("active", props.item.value);
84 - const { filekey, hash, image_info } = await qiniuUploadAPI( 167 + loading.value = false;
85 - "http://upload.qiniup.com/putb64/-1/key/" + key,
86 - base64url,
87 - config
88 - );
89 - if (filekey) {
90 - // 保存图片
91 - const { data } = await saveFileAPI({
92 - filekey,
93 - hash,
94 - format: image_info.format,
95 - height: image_info.height,
96 - width: image_info.width,
97 - });
98 - console.warn(data.src);
99 - }
100 } 168 }
101 }; 169 };
102 170
171 +const beforeDelete = (files) => {
172 + fileList.value = fileList.value.filter((item) => {
173 + if (item.url !== files.url) return item;
174 + });
175 + props.item.value = {
176 + key: "image_uploader",
177 + filed_name: props.item.key,
178 + value: fileList.value,
179 + };
180 + emit("active", props.item.value);
181 +};
182 +
103 const fileList = ref([ 183 const fileList = ref([
104 - { url: "https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg" }, 184 + // { url: "https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg" },
105 // Uploader 根据文件后缀来判断是否为图片文件 185 // Uploader 根据文件后缀来判断是否为图片文件
106 // 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明 186 // 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
107 // { url: 'https://cloud-image', isImage: true }, 187 // { url: 'https://cloud-image', isImage: true },
108 ]); 188 ]);
189 +
190 +const validImageUploader = () => {
191 + // 必填项 未上传图片
192 + if (props.item.component_props.required && !fileList.value.length) {
193 + show_empty.value = true;
194 + } else {
195 + show_empty.value = false;
196 + }
197 + return !show_empty.value;
198 +};
199 +
200 +defineExpose({ validImageUploader });
109 </script> 201 </script>
110 202
111 <style lang="less" scoped> 203 <style lang="less" scoped>
...@@ -127,4 +219,17 @@ const fileList = ref([ ...@@ -127,4 +219,17 @@ const fileList = ref([
127 color: gray; 219 color: gray;
128 } 220 }
129 } 221 }
222 +
223 +.wrapper {
224 + display: flex;
225 + align-items: center;
226 + justify-content: center;
227 + height: 100%;
228 +}
229 +
230 +.block {
231 + width: 120px;
232 + height: 120px;
233 + background-color: #fff;
234 +}
130 </style> 235 </style>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 * @Author: hookehuyr hookehuyr@gmail.com 2 * @Author: hookehuyr hookehuyr@gmail.com
3 * @Date: 2022-05-28 10:17:40 3 * @Date: 2022-05-28 10:17:40
4 * @LastEditors: hookehuyr hookehuyr@gmail.com 4 * @LastEditors: hookehuyr hookehuyr@gmail.com
5 - * @LastEditTime: 2022-11-17 10:17:01 5 + * @LastEditTime: 2022-12-01 16:33:51
6 * @FilePath: /data-table/src/utils/axios.js 6 * @FilePath: /data-table/src/utils/axios.js
7 * @Description: 7 * @Description:
8 */ 8 */
...@@ -28,7 +28,7 @@ axios.interceptors.request.use( ...@@ -28,7 +28,7 @@ axios.interceptors.request.use(
28 * POST PHP需要修改数据格式 28 * POST PHP需要修改数据格式
29 * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错 29 * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错
30 */ 30 */
31 - config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data; 31 + // config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data;
32 // 绑定默认请求头 32 // 绑定默认请求头
33 config.params = { ...config.params, timestamp } 33 config.params = { ...config.params, timestamp }
34 return config; 34 return config;
......
1 +import sha1 from "js-sha1";
2 +
3 +function getEtag(buffer, callback) {
4 + // sha1算法
5 + var shA1 = sha1.digest;
6 +
7 + // 以4M为单位分割
8 + var blockSize = 4 * 1024 * 1024;
9 + var sha1String = [];
10 + var prefix = 0x16;
11 + var blockCount = 0;
12 +
13 + var bufferSize = buffer.size || buffer.length || buffer.byteLength;
14 + blockCount = Math.ceil(bufferSize / blockSize);
15 +
16 + for (var i = 0; i < blockCount; i++) {
17 + sha1String.push(shA1(buffer.slice(i * blockSize, (i + 1) * blockSize)));
18 + }
19 + function concatArr2Uint8(s) {//Array 2 Uint8Array
20 + var tmp = [];
21 + for (var i of s) tmp = tmp.concat(i);
22 + return new Uint8Array(tmp);
23 + }
24 + function Uint8ToBase64(u8Arr, urisafe) {//Uint8Array 2 Base64
25 + var CHUNK_SIZE = 0x8000; //arbitrary number
26 + var index = 0;
27 + var length = u8Arr.length;
28 + var result = '';
29 + var slice;
30 + while (index < length) {
31 + slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
32 + result += String.fromCharCode.apply(null, slice);
33 + index += CHUNK_SIZE;
34 + }
35 + return urisafe ? btoa(result).replace(/\//g, '_').replace(/\+/g, '-') : btoa(result);
36 + }
37 + function calcEtag() {
38 + if (!sha1String.length) return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ';
39 + var sha1Buffer = concatArr2Uint8(sha1String);
40 + // 如果大于4M,则对各个块的sha1结果再次sha1
41 + if (blockCount > 1) {
42 + prefix = 0x96;
43 + sha1Buffer = shA1(sha1Buffer.buffer);
44 + } else {
45 + sha1Buffer = Array.apply([], sha1Buffer);
46 + }
47 + sha1Buffer = concatArr2Uint8([[prefix], sha1Buffer]);
48 + return Uint8ToBase64(sha1Buffer, true);
49 + }
50 + return (calcEtag());
51 +}
52 +
53 +export { getEtag }
This diff is collapsed. Click to expand it.
...@@ -184,10 +184,11 @@ onMounted(async () => { ...@@ -184,10 +184,11 @@ onMounted(async () => {
184 // }, 184 // },
185 // ]; 185 // ];
186 // 生成自定义组件 186 // 生成自定义组件
187 - createComponentType(mockData.value); 187 + // createComponentType(mockData.value);
188 createComponentType(formData.value); 188 createComponentType(formData.value);
189 }); 189 });
190 190
191 +const image_uploader = ref(null);
191 const sign = ref(null); 192 const sign = ref(null);
192 const rate_picker = ref(null); 193 const rate_picker = ref(null);
193 const video = ref(null); 194 const video = ref(null);
...@@ -196,15 +197,17 @@ const onSubmit = async (values) => { ...@@ -196,15 +197,17 @@ const onSubmit = async (values) => {
196 // 合并自定义字段到提交表单字段 197 // 合并自定义字段到提交表单字段
197 postData.value = _.assign(postData.value, values); 198 postData.value = _.assign(postData.value, values);
198 // 格式化value值为json格式, 提交格式有问题 199 // 格式化value值为json格式, 提交格式有问题
199 - // for (const key in postData.value) { 200 + for (let key in postData.value) {
200 - // postData.value[key] = JSON.stringify(postData.value[key]); 201 + key = JSON.stringify(key);
201 - // } 202 + // postData.value[key] = postData.value[key];
203 + }
202 // 检查非表单输入项 204 // 检查非表单输入项
203 - if (validOther()) { 205 + if (validOther().status) {
204 // 通过验证 206 // 通过验证
205 const result = await addFormDataAPI({ 207 const result = await addFormDataAPI({
206 form_code: $route.query.code, 208 form_code: $route.query.code,
207 - data: JSON.stringify(postData.value), 209 + // data: JSON.stringify(postData.value),
210 + data: postData.value,
208 }); 211 });
209 if (result.code) { 212 if (result.code) {
210 showSuccessToast("提交成功"); 213 showSuccessToast("提交成功");
...@@ -212,12 +215,19 @@ const onSubmit = async (values) => { ...@@ -212,12 +215,19 @@ const onSubmit = async (values) => {
212 // console.warn(postData.value); 215 // console.warn(postData.value);
213 // console.warn("通过验证"); 216 // console.warn("通过验证");
214 } else { 217 } else {
215 - console.warn("不通过验证"); 218 + console.warn(validOther().key + "不通过验证");
219 + // 图片上传控件报错提示
220 + if (validOther().key === "image_uploader") {
221 + showFailToast("图片上传为空");
222 + }
216 } 223 }
217 }; 224 };
218 225
219 const onActive = (item) => { 226 const onActive = (item) => {
220 // 返回自定义字段 227 // 返回自定义字段
228 + if (item.key === "image_uploader") {
229 + postData.value[item.filed_name] = item.value;
230 + }
221 if (item.key === "sign") { 231 if (item.key === "sign") {
222 postData.value["sign"] = item.value; 232 postData.value["sign"] = item.value;
223 } 233 }
...@@ -228,16 +238,32 @@ const onActive = (item) => { ...@@ -228,16 +238,32 @@ const onActive = (item) => {
228 238
229 const validOther = () => { 239 const validOther = () => {
230 // 检验没有绑定name的输入项 240 // 检验没有绑定name的输入项
231 - let flag = true; 241 + let valid = {
242 + status: true,
243 + key: "",
244 + };
245 + if (image_uploader.value) {
246 + // 检验图片上传
247 + valid = {
248 + status: image_uploader.value[0].validImageUploader(),
249 + key: "image_uploader",
250 + };
251 + }
232 if (sign.value) { 252 if (sign.value) {
233 // 检验电子签名 253 // 检验电子签名
234 - flag = sign.value[0].validSign(); 254 + valid = {
255 + status: sign.value[0].validSign(),
256 + key: "sign",
257 + };
235 } 258 }
236 if (rate_picker.value) { 259 if (rate_picker.value) {
237 // 检验评分 260 // 检验评分
238 - flag = rate_picker.value[0].validRate(); 261 + valid = {
262 + status: rate_picker.value[0].validRate(),
263 + key: "rate_picker",
264 + };
239 } 265 }
240 - return flag; 266 + return valid;
241 }; 267 };
242 </script> 268 </script>
243 269
......
...@@ -632,6 +632,13 @@ ...@@ -632,6 +632,13 @@
632 dependencies: 632 dependencies:
633 "fill-range" "^7.0.1" 633 "fill-range" "^7.0.1"
634 634
635 +"browser-md5-file@^1.1.1":
636 + "integrity" "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw=="
637 + "resolved" "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz"
638 + "version" "1.1.1"
639 + dependencies:
640 + "spark-md5" "^2.0.2"
641 +
635 "browser-stdout@1.3.1": 642 "browser-stdout@1.3.1":
636 "integrity" "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" 643 "integrity" "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
637 "resolved" "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz" 644 "resolved" "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz"
...@@ -756,6 +763,11 @@ ...@@ -756,6 +763,11 @@
756 "snake-case" "^3.0.4" 763 "snake-case" "^3.0.4"
757 "tslib" "^2.0.3" 764 "tslib" "^2.0.3"
758 765
766 +"charenc@>= 0.0.1":
767 + "integrity" "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
768 + "resolved" "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz"
769 + "version" "0.0.2"
770 +
759 "check-error@^1.0.2": 771 "check-error@^1.0.2":
760 "integrity" "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" 772 "integrity" "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
761 "resolved" "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz" 773 "resolved" "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz"
...@@ -920,6 +932,11 @@ ...@@ -920,6 +932,11 @@
920 "shebang-command" "^2.0.0" 932 "shebang-command" "^2.0.0"
921 "which" "^2.0.1" 933 "which" "^2.0.1"
922 934
935 +"crypt@>= 0.0.1":
936 + "integrity" "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
937 + "resolved" "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz"
938 + "version" "0.0.2"
939 +
923 "css-line-break@^2.1.0": 940 "css-line-break@^2.1.0":
924 "integrity" "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==" 941 "integrity" "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w=="
925 "resolved" "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz" 942 "resolved" "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz"
...@@ -1854,6 +1871,11 @@ ...@@ -1854,6 +1871,11 @@
1854 "resolved" "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz" 1871 "resolved" "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz"
1855 "version" "3.0.1" 1872 "version" "3.0.1"
1856 1873
1874 +"js-sha1@^0.6.0":
1875 + "integrity" "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w=="
1876 + "resolved" "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz"
1877 + "version" "0.6.0"
1878 +
1857 "js-tokens@^4.0.0": 1879 "js-tokens@^4.0.0":
1858 "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 1880 "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
1859 "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 1881 "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
...@@ -2693,6 +2715,14 @@ ...@@ -2693,6 +2715,14 @@
2693 dependencies: 2715 dependencies:
2694 "randombytes" "^2.1.0" 2716 "randombytes" "^2.1.0"
2695 2717
2718 +"sha1@^1.1.1":
2719 + "integrity" "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg="
2720 + "resolved" "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz"
2721 + "version" "1.1.1"
2722 + dependencies:
2723 + "charenc" ">= 0.0.1"
2724 + "crypt" ">= 0.0.1"
2725 +
2696 "shebang-command@^2.0.0": 2726 "shebang-command@^2.0.0":
2697 "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" 2727 "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
2698 "resolved" "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz" 2728 "resolved" "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz"
...@@ -2765,6 +2795,11 @@ ...@@ -2765,6 +2795,11 @@
2765 "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" 2795 "resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz"
2766 "version" "1.4.8" 2796 "version" "1.4.8"
2767 2797
2798 +"spark-md5@^2.0.2":
2799 + "integrity" "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc="
2800 + "resolved" "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz"
2801 + "version" "2.0.2"
2802 +
2768 "sprintf-js@~1.0.2": 2803 "sprintf-js@~1.0.2":
2769 "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 2804 "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
2770 "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" 2805 "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
......