hookehuyr

联调图片上传功能

......@@ -13,15 +13,18 @@
"@vitejs/plugin-legacy": "^1.8.2",
"@vueuse/core": "^8.5.0",
"animate.css": "^4.1.1",
"browser-md5-file": "^1.1.1",
"dayjs": "^1.11.3",
"default-passive-events": "^2.0.0",
"global": "^4.4.0",
"html2canvas": "^1.4.1",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"js-sha1": "^0.6.0",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"mui-player": "^1.7.0",
"sha1": "^1.1.1",
"typescript": "^4.7.3",
"uuid": "^8.3.2",
"vant": "^4.0.0-rc.8",
......@@ -1204,6 +1207,15 @@
"node": ">=8"
}
},
"node_modules/browser-md5-file": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz",
"integrity": "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw==",
"license": "MIT",
"dependencies": {
"spark-md5": "^2.0.2"
}
},
"node_modules/browser-stdout": {
"version": "1.3.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz",
......@@ -1389,6 +1401,15 @@
"tslib": "^2.0.3"
}
},
"node_modules/charenc": {
"version": "0.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
"license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
"node_modules/check-error": {
"version": "1.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz",
......@@ -1656,6 +1677,15 @@
"node": ">= 8"
}
},
"node_modules/crypt": {
"version": "0.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
"license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
......@@ -3431,6 +3461,12 @@
"node": ">=12"
}
},
"node_modules/js-sha1": {
"version": "0.6.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz",
"integrity": "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==",
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
......@@ -5052,6 +5088,19 @@
"randombytes": "^2.1.0"
}
},
"node_modules/sha1": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz",
"integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=",
"license": "BSD-3-Clause",
"dependencies": {
"charenc": ">= 0.0.1",
"crypt": ">= 0.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz",
......@@ -5193,6 +5242,12 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"license": "MIT"
},
"node_modules/spark-md5": {
"version": "2.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz",
"integrity": "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc=",
"license": "WTFPL"
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
......@@ -7042,6 +7097,14 @@
"fill-range": "^7.0.1"
}
},
"browser-md5-file": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz",
"integrity": "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw==",
"requires": {
"spark-md5": "^2.0.2"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz",
......@@ -7172,6 +7235,11 @@
"tslib": "^2.0.3"
}
},
"charenc": {
"version": "0.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
},
"check-error": {
"version": "1.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz",
......@@ -7358,6 +7426,11 @@
"which": "^2.0.1"
}
},
"crypt": {
"version": "0.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
},
"css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
......@@ -8569,6 +8642,11 @@
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
},
"js-sha1": {
"version": "0.6.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz",
"integrity": "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
......@@ -9668,6 +9746,15 @@
"randombytes": "^2.1.0"
}
},
"sha1": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz",
"integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=",
"requires": {
"charenc": ">= 0.0.1",
"crypt": ">= 0.0.1"
}
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz",
......@@ -9768,6 +9855,11 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"spark-md5": {
"version": "2.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz",
"integrity": "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc="
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
......
......@@ -17,15 +17,18 @@
"@vitejs/plugin-legacy": "^1.8.2",
"@vueuse/core": "^8.5.0",
"animate.css": "^4.1.1",
"browser-md5-file": "^1.1.1",
"dayjs": "^1.11.3",
"default-passive-events": "^2.0.0",
"global": "^4.4.0",
"html2canvas": "^1.4.1",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"js-sha1": "^0.6.0",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"mui-player": "^1.7.0",
"sha1": "^1.1.1",
"typescript": "^4.7.3",
"uuid": "^8.3.2",
"vant": "^4.0.0-rc.8",
......
/*
* @Date: 2022-06-17 14:54:29
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-09-06 17:03:55
* @LastEditTime: 2022-12-01 16:26:27
* @FilePath: /data-table/src/api/common.js
* @Description: 通用接口
*/
......@@ -22,8 +22,6 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
/**
* @description: 获取七牛token
* @param {*} filename 文件名
* @param {*} file 图片base64
* @returns
*/
export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));
......
......@@ -7,18 +7,28 @@
-->
<template>
<div class="image-uploader-field">
<div class="label">{{ item.label }}<span v-if="item.required">&nbsp;*</span></div>
<div class="label">
{{ item.component_props.label
}}<span v-if="item.component_props.required">&nbsp;*</span>
</div>
<div style="padding: 1rem">
<van-uploader
upload-icon="add"
:before-read="beforeRead"
:after-read="afterRead"
:before-delete="beforeDelete"
v-model="fileList"
:multiple="item.component_props.multiple"
/>
</div>
<div class="type-text">上传格式:{{ type_text }}</div>
</div>
<van-overlay :show="loading">
<div class="wrapper" @click.stop>
<van-loading vertical color="#FFFFFF">上传中...</van-loading>
</div>
</van-overlay>
</template>
<script setup>
......@@ -28,62 +38,82 @@
* @param image_type[Array] 图片上传类型
* @param multiple[Boolean] 图片多选
*/
import { Toast } from "vant";
import { showSuccessToast, showFailToast } from "vant";
import _ from "lodash";
import { v4 as uuidv4 } from "uuid";
import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from "@/api/common";
import BMF from "browser-md5-file";
import { useRoute } from "vue-router";
import axios from "axios";
import { getEtag } from "@/utils/qetag.js"; // 生成hash值
const $route = useRoute();
const props = defineProps({
item: Object,
});
const emit = defineEmits(["active"]);
const show_empty = ref(false);
// 文件类型中文页面显示
const type_text = computed(() => {
return props.item.component_props.image_type.join("/");
return props.item.component_props.image_type;
});
// 上传前置处理
const beforeRead = (file) => {
// 类型限制
const image_types = _.map(
props.item.component_props.image_type,
props.item.component_props.image_type.split("/"),
(item) => `image/${item}`
);
let flag = true;
if (_.isArray(file)) {
// 多张图片
const types = _.difference(_.uniq(_.map(file, (item) => item.type)), image_types); // 数组返回不能上传的类型
if (types.length) {
flag = false;
Toast("请上传指定格式图片");
showFailToast("请上传指定格式图片");
}
} else {
if (!_.includes(image_types, file.type)) {
Toast("请上传指定格式图片");
showFailToast("请上传指定格式图片");
flag = false;
}
}
return flag;
};
const afterRead = async (file) => {
// 此时可以自行将文件上传至服务器
let affix = uuidv4();
let base64url = file.content.slice(file.content.indexOf(",") + 1); // 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA.......
// 获取七牛token
const { token, key, code } = await qiniuTokenAPI({
filename: `${affix}_image_upload`,
file: base64url,
});
if (code) {
const config = {
headers: {
"Content-Type": "application/octet-stream",
Authorization: "UpToken " + token, // UpToken后必须有一个 ' '(空格)
},
/********** 上传七牛云获取图片地址 ***********/
const loading = ref(false);
const formCode = $route.query.code; // 表单code
const uuid = () => {
let s = [];
let hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
};
const uploadQiniu = async (file, token, filename) => {
let formData = new FormData();
formData.append("file", file); // 通过append向form对象添加数据
formData.append("token", token);
formData.append("key", formCode + "/" + uuid() + "." + file.name.split(".")[1]);
let config = {
headers: { "Content-Type": "multipart/form-data" },
};
// 上传七牛服务器
// 自拍图片上传七牛服务器
const { filekey, hash, image_info } = await qiniuUploadAPI(
"http://upload.qiniup.com/putb64/-1/key/" + key,
base64url,
"http://upload.qiniu.com/",
formData,
config
);
if (filekey) {
......@@ -95,17 +125,79 @@ const afterRead = async (file) => {
height: image_info.height,
width: image_info.width,
});
console.warn(data.src);
return data;
}
};
/****************** END *******************/
const afterRead = async (files) => {
loading.value = true;
// 获取HASH值
const hash = getEtag(files.content);
// 获取七牛token
const filename = formCode + "/" + uuid() + "." + files.file.name.split(".")[1];
const { token, key, code } = await qiniuTokenAPI({
name: filename,
hash,
});
// 文件上传七牛云
files.status = "uploading";
files.message = "上传中...";
const imgUrl = await uploadQiniu(files.file, token, filename);
// 上传失败提示
if (!imgUrl.src) {
files.status = "failed";
files.message = "上传失败";
loading.value = false;
} else {
files.status = "";
files.message = "";
fileList.value.pop();
fileList.value.push({
url: imgUrl.src,
isImage: true,
});
props.item.value = {
key: "image_uploader",
filed_name: props.item.key,
value: fileList.value,
};
emit("active", props.item.value);
loading.value = false;
}
};
const beforeDelete = (files) => {
fileList.value = fileList.value.filter((item) => {
if (item.url !== files.url) return item;
});
props.item.value = {
key: "image_uploader",
filed_name: props.item.key,
value: fileList.value,
};
emit("active", props.item.value);
};
const fileList = ref([
{ url: "https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg" },
// { url: "https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg" },
// Uploader 根据文件后缀来判断是否为图片文件
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
// { url: 'https://cloud-image', isImage: true },
]);
const validImageUploader = () => {
// 必填项 未上传图片
if (props.item.component_props.required && !fileList.value.length) {
show_empty.value = true;
} else {
show_empty.value = false;
}
return !show_empty.value;
};
defineExpose({ validImageUploader });
</script>
<style lang="less" scoped>
......@@ -127,4 +219,17 @@ const fileList = ref([
color: gray;
}
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block {
width: 120px;
height: 120px;
background-color: #fff;
}
</style>
......
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-28 10:17:40
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-11-17 10:17:01
* @LastEditTime: 2022-12-01 16:33:51
* @FilePath: /data-table/src/utils/axios.js
* @Description:
*/
......@@ -28,7 +28,7 @@ axios.interceptors.request.use(
* POST PHP需要修改数据格式
* 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错
*/
config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data;
// config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data;
// 绑定默认请求头
config.params = { ...config.params, timestamp }
return config;
......
import sha1 from "js-sha1";
function getEtag(buffer, callback) {
// sha1算法
var shA1 = sha1.digest;
// 以4M为单位分割
var blockSize = 4 * 1024 * 1024;
var sha1String = [];
var prefix = 0x16;
var blockCount = 0;
var bufferSize = buffer.size || buffer.length || buffer.byteLength;
blockCount = Math.ceil(bufferSize / blockSize);
for (var i = 0; i < blockCount; i++) {
sha1String.push(shA1(buffer.slice(i * blockSize, (i + 1) * blockSize)));
}
function concatArr2Uint8(s) {//Array 2 Uint8Array
var tmp = [];
for (var i of s) tmp = tmp.concat(i);
return new Uint8Array(tmp);
}
function Uint8ToBase64(u8Arr, urisafe) {//Uint8Array 2 Base64
var CHUNK_SIZE = 0x8000; //arbitrary number
var index = 0;
var length = u8Arr.length;
var result = '';
var slice;
while (index < length) {
slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
result += String.fromCharCode.apply(null, slice);
index += CHUNK_SIZE;
}
return urisafe ? btoa(result).replace(/\//g, '_').replace(/\+/g, '-') : btoa(result);
}
function calcEtag() {
if (!sha1String.length) return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ';
var sha1Buffer = concatArr2Uint8(sha1String);
// 如果大于4M,则对各个块的sha1结果再次sha1
if (blockCount > 1) {
prefix = 0x96;
sha1Buffer = shA1(sha1Buffer.buffer);
} else {
sha1Buffer = Array.apply([], sha1Buffer);
}
sha1Buffer = concatArr2Uint8([[prefix], sha1Buffer]);
return Uint8ToBase64(sha1Buffer, true);
}
return (calcEtag());
}
export { getEtag }
This diff is collapsed. Click to expand it.
......@@ -184,10 +184,11 @@ onMounted(async () => {
// },
// ];
// 生成自定义组件
createComponentType(mockData.value);
// createComponentType(mockData.value);
createComponentType(formData.value);
});
const image_uploader = ref(null);
const sign = ref(null);
const rate_picker = ref(null);
const video = ref(null);
......@@ -196,15 +197,17 @@ const onSubmit = async (values) => {
// 合并自定义字段到提交表单字段
postData.value = _.assign(postData.value, values);
// 格式化value值为json格式, 提交格式有问题
// for (const key in postData.value) {
// postData.value[key] = JSON.stringify(postData.value[key]);
// }
for (let key in postData.value) {
key = JSON.stringify(key);
// postData.value[key] = postData.value[key];
}
// 检查非表单输入项
if (validOther()) {
if (validOther().status) {
// 通过验证
const result = await addFormDataAPI({
form_code: $route.query.code,
data: JSON.stringify(postData.value),
// data: JSON.stringify(postData.value),
data: postData.value,
});
if (result.code) {
showSuccessToast("提交成功");
......@@ -212,12 +215,19 @@ const onSubmit = async (values) => {
// console.warn(postData.value);
// console.warn("通过验证");
} else {
console.warn("不通过验证");
console.warn(validOther().key + "不通过验证");
// 图片上传控件报错提示
if (validOther().key === "image_uploader") {
showFailToast("图片上传为空");
}
}
};
const onActive = (item) => {
// 返回自定义字段
if (item.key === "image_uploader") {
postData.value[item.filed_name] = item.value;
}
if (item.key === "sign") {
postData.value["sign"] = item.value;
}
......@@ -228,16 +238,32 @@ const onActive = (item) => {
const validOther = () => {
// 检验没有绑定name的输入项
let flag = true;
let valid = {
status: true,
key: "",
};
if (image_uploader.value) {
// 检验图片上传
valid = {
status: image_uploader.value[0].validImageUploader(),
key: "image_uploader",
};
}
if (sign.value) {
// 检验电子签名
flag = sign.value[0].validSign();
valid = {
status: sign.value[0].validSign(),
key: "sign",
};
}
if (rate_picker.value) {
// 检验评分
flag = rate_picker.value[0].validRate();
valid = {
status: rate_picker.value[0].validRate(),
key: "rate_picker",
};
}
return flag;
return valid;
};
</script>
......
......@@ -632,6 +632,13 @@
dependencies:
"fill-range" "^7.0.1"
"browser-md5-file@^1.1.1":
"integrity" "sha512-9h2UViTtZPhBa7oHvp5mb7MvJaX5OKEPUsplDwJ800OIV+In7BOR3RXOMB78obn2iQVIiS3WkVLhG7Zu1EMwbw=="
"resolved" "https://mirrors.cloud.tencent.com/npm/browser-md5-file/-/browser-md5-file-1.1.1.tgz"
"version" "1.1.1"
dependencies:
"spark-md5" "^2.0.2"
"browser-stdout@1.3.1":
"integrity" "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
"resolved" "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz"
......@@ -756,6 +763,11 @@
"snake-case" "^3.0.4"
"tslib" "^2.0.3"
"charenc@>= 0.0.1":
"integrity" "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
"resolved" "https://mirrors.cloud.tencent.com/npm/charenc/-/charenc-0.0.2.tgz"
"version" "0.0.2"
"check-error@^1.0.2":
"integrity" "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
"resolved" "https://mirrors.cloud.tencent.com/npm/check-error/-/check-error-1.0.2.tgz"
......@@ -920,6 +932,11 @@
"shebang-command" "^2.0.0"
"which" "^2.0.1"
"crypt@>= 0.0.1":
"integrity" "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
"resolved" "https://mirrors.cloud.tencent.com/npm/crypt/-/crypt-0.0.2.tgz"
"version" "0.0.2"
"css-line-break@^2.1.0":
"integrity" "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w=="
"resolved" "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz"
......@@ -1854,6 +1871,11 @@
"resolved" "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz"
"version" "3.0.1"
"js-sha1@^0.6.0":
"integrity" "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w=="
"resolved" "https://mirrors.cloud.tencent.com/npm/js-sha1/-/js-sha1-0.6.0.tgz"
"version" "0.6.0"
"js-tokens@^4.0.0":
"integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
"resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
......@@ -2693,6 +2715,14 @@
dependencies:
"randombytes" "^2.1.0"
"sha1@^1.1.1":
"integrity" "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg="
"resolved" "https://mirrors.cloud.tencent.com/npm/sha1/-/sha1-1.1.1.tgz"
"version" "1.1.1"
dependencies:
"charenc" ">= 0.0.1"
"crypt" ">= 0.0.1"
"shebang-command@^2.0.0":
"integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
"resolved" "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz"
......@@ -2765,6 +2795,11 @@
"resolved" "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz"
"version" "1.4.8"
"spark-md5@^2.0.2":
"integrity" "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc="
"resolved" "https://mirrors.cloud.tencent.com/npm/spark-md5/-/spark-md5-2.0.2.tgz"
"version" "2.0.2"
"sprintf-js@~1.0.2":
"integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
"resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
......