mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 14:10:27 +08:00
更新 upload 插件
This commit is contained in:
parent
52e345712e
commit
d9b2405184
@ -111,7 +111,7 @@ import { ZoomIn, Delete, VideoPause, VideoPlay } from "@element-plus/icons-vue";
|
|||||||
import { ContextMenu } from "@cool-vue/crud";
|
import { ContextMenu } from "@cool-vue/crud";
|
||||||
import { useCool } from "/@/cool";
|
import { useCool } from "/@/cool";
|
||||||
import { extname } from "/@/cool/utils";
|
import { extname } from "/@/cool/utils";
|
||||||
import { download, fileName, getRule } from "../../utils";
|
import { fileName, getRule } from "../../utils";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import Viewer from "./viewer.vue";
|
import Viewer from "./viewer.vue";
|
||||||
@ -172,16 +172,6 @@ function onContextMenu(e: any) {
|
|||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "下载",
|
|
||||||
callback(done) {
|
|
||||||
if (props.item.url) {
|
|
||||||
download(props.item.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: "复制链接",
|
label: "复制链接",
|
||||||
callback(done) {
|
callback(done) {
|
||||||
|
@ -11,34 +11,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 文档 -->
|
<!-- 文档 -->
|
||||||
<cl-dialog
|
<cl-dialog v-model="doc.visible" title="文档预览" height="70vh" width="80%" :scrollbar="false">
|
||||||
v-model="doc.visible"
|
|
||||||
title="文档预览"
|
|
||||||
height="70vh"
|
|
||||||
width="80%"
|
|
||||||
:scrollbar="false"
|
|
||||||
:controls="['slot-download', 'fullscreen', 'close']"
|
|
||||||
>
|
|
||||||
<template #slot-download>
|
|
||||||
<button type="button" class="cl-dialog__controls-icon" @click="download(doc.url)">
|
|
||||||
<el-icon>
|
|
||||||
<icon-download />
|
|
||||||
</el-icon>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div class="viewer-doc" v-loading="doc.loading">
|
<div class="viewer-doc" v-loading="doc.loading">
|
||||||
<iframe :src="doc.previewUrl" :ref="setRefs('docIframe')" />
|
<iframe :src="doc.url" :ref="setRefs('docIframe')" />
|
||||||
</div>
|
</div>
|
||||||
</cl-dialog>
|
</cl-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="file-viewer">
|
<script lang="ts" setup name="file-viewer">
|
||||||
import { reactive, nextTick } from "vue";
|
import { reactive, nextTick } from "vue";
|
||||||
import { getType, download } from "../../utils";
|
import { getType } from "../../utils";
|
||||||
import type { Upload } from "../../types";
|
import type { Upload } from "../../types";
|
||||||
import { useCool } from "/@/cool";
|
import { useCool } from "/@/cool";
|
||||||
import { Download as IconDownload } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
const { refs, setRefs } = useCool();
|
const { refs, setRefs } = useCool();
|
||||||
|
|
||||||
@ -52,8 +36,7 @@ const img = reactive({
|
|||||||
const doc = reactive({
|
const doc = reactive({
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
url: "",
|
url: ""
|
||||||
previewUrl: ""
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
@ -77,8 +60,7 @@ function open(item: Upload.Item) {
|
|||||||
if (["word", "excel", "ppt", "pdf"].includes(type)) {
|
if (["word", "excel", "ppt", "pdf"].includes(type)) {
|
||||||
doc.visible = true;
|
doc.visible = true;
|
||||||
doc.loading = true;
|
doc.loading = true;
|
||||||
doc.previewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${decodeURIComponent(url)}`;
|
doc.url = `https://view.officeapps.live.com/op/view.aspx?src=${decodeURIComponent(url)}`;
|
||||||
doc.url = url;
|
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
refs.docIframe.onload = () => {
|
refs.docIframe.onload = () => {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
:http-request="httpRequest"
|
:http-request="httpRequest"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:multiple="multiple"
|
:multiple="multiple"
|
||||||
:disabled="uploadDisabled"
|
:disabled="disabled"
|
||||||
>
|
>
|
||||||
<slot>
|
<slot>
|
||||||
<el-button type="success">{{ text }}</el-button>
|
<el-button type="success">{{ text }}</el-button>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
:http-request="httpRequest"
|
:http-request="httpRequest"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:multiple="multiple"
|
:multiple="multiple"
|
||||||
:disabled="uploadDisabled"
|
:disabled="disabled"
|
||||||
>
|
>
|
||||||
<slot>
|
<slot>
|
||||||
<div class="cl-upload__demo is-dragger" v-if="drag">
|
<div class="cl-upload__demo is-dragger" v-if="drag">
|
||||||
@ -103,7 +103,7 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:disabled="uploadDisabled"
|
:disabled="disabled"
|
||||||
v-if="showFileList"
|
v-if="showFileList"
|
||||||
>
|
>
|
||||||
<slot name="item" :item="item" :index="index">
|
<slot name="item" :item="item" :index="index">
|
||||||
@ -127,15 +127,15 @@
|
|||||||
<script lang="ts" setup name="cl-upload">
|
<script lang="ts" setup name="cl-upload">
|
||||||
import { computed, ref, watch, type PropType, nextTick } from "vue";
|
import { computed, ref, watch, type PropType, nextTick } from "vue";
|
||||||
import { isArray, isNumber } from "lodash-es";
|
import { isArray, isNumber } from "lodash-es";
|
||||||
import { type AxiosProgressEvent } from "axios";
|
|
||||||
import Draggable from "vuedraggable";
|
import Draggable from "vuedraggable";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { PictureFilled, UploadFilled } from "@element-plus/icons-vue";
|
import { PictureFilled, UploadFilled } from "@element-plus/icons-vue";
|
||||||
import { useForm } from "@cool-vue/crud";
|
import { useForm } from "@cool-vue/crud";
|
||||||
import { useCool, module } from "/@/cool";
|
import { useCool } from "/@/cool";
|
||||||
import { useBase } from "/$/base";
|
import { useBase } from "/$/base";
|
||||||
import { uuid, isPromise } from "/@/cool/utils";
|
import { uuid, isPromise } from "/@/cool/utils";
|
||||||
import { getUrls, getType, pathJoin } from "../utils";
|
import { getUrls, getType } from "../utils";
|
||||||
|
import { useUpload } from "../hooks";
|
||||||
import UploadItem from "./upload-item/index.vue";
|
import UploadItem from "./upload-item/index.vue";
|
||||||
import type { Upload } from "../types";
|
import type { Upload } from "../types";
|
||||||
|
|
||||||
@ -187,15 +187,7 @@ const props = defineProps({
|
|||||||
// 上传前钩子
|
// 上传前钩子
|
||||||
beforeUpload: Function,
|
beforeUpload: Function,
|
||||||
// 云端上传路径前缀
|
// 云端上传路径前缀
|
||||||
prefixPath: {
|
prefixPath: String,
|
||||||
type: String,
|
|
||||||
default: "app"
|
|
||||||
},
|
|
||||||
// 云端上传路径
|
|
||||||
menu: {
|
|
||||||
type: String,
|
|
||||||
default: "base"
|
|
||||||
},
|
|
||||||
|
|
||||||
// CRUD穿透值
|
// CRUD穿透值
|
||||||
isEdit: Boolean,
|
isEdit: Boolean,
|
||||||
@ -206,12 +198,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(["update:modelValue", "upload", "success", "error", "progress"]);
|
const emit = defineEmits(["update:modelValue", "upload", "success", "error", "progress"]);
|
||||||
|
|
||||||
const { service, refs, setRefs } = useCool();
|
const { refs, setRefs } = useCool();
|
||||||
const { user } = useBase();
|
const { user } = useBase();
|
||||||
const Form = useForm();
|
const Form = useForm();
|
||||||
|
const { options, toUpload } = useUpload();
|
||||||
// 模块配置
|
|
||||||
const { options } = module.get("upload");
|
|
||||||
|
|
||||||
// 元素尺寸
|
// 元素尺寸
|
||||||
const size = computed(() => {
|
const size = computed(() => {
|
||||||
@ -224,11 +214,6 @@ const disabled = computed(() => {
|
|||||||
return props.isDisabled || props.disabled;
|
return props.isDisabled || props.disabled;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 上传禁用
|
|
||||||
const uploadDisabled = computed(() => {
|
|
||||||
return disabled.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 最大上传数量
|
// 最大上传数量
|
||||||
const limit = props.limit || options.limit.upload;
|
const limit = props.limit || options.limit.upload;
|
||||||
|
|
||||||
@ -357,7 +342,7 @@ function clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 文件上传请求
|
// 文件上传请求
|
||||||
async function httpRequest(req: any, item?: any) {
|
async function httpRequest(req: any, item?: Upload.Item) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
item = list.value.find((e) => e.uid == req.file.uid);
|
item = list.value.find((e) => e.uid == req.file.uid);
|
||||||
}
|
}
|
||||||
@ -366,149 +351,23 @@ async function httpRequest(req: any, item?: any) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件id
|
// 上传请求
|
||||||
const fileId = uuid("");
|
toUpload(req.file, {
|
||||||
|
prefixPath: props.prefixPath,
|
||||||
try {
|
onProgress(progress) {
|
||||||
// 上传模式、类型
|
item.progress = progress;
|
||||||
const { mode, type } = await service.base.comm.uploadMode();
|
emit("progress", item);
|
||||||
|
}
|
||||||
// 本地上传
|
})
|
||||||
const isLocal = mode == "local";
|
.then((res) => {
|
||||||
|
Object.assign(item, res);
|
||||||
// 文件名
|
emit("success", item);
|
||||||
const fileName = fileId + "_" + req.file.name;
|
update();
|
||||||
|
})
|
||||||
// Key
|
.catch((err) => {
|
||||||
const key = isLocal ? fileName : pathJoin(props.prefixPath, props.menu, fileName);
|
item.error = err.message;
|
||||||
|
emit("error", item);
|
||||||
// 多种上传请求
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// 上传到云端
|
|
||||||
async function next({
|
|
||||||
host,
|
|
||||||
preview,
|
|
||||||
data
|
|
||||||
}: {
|
|
||||||
host: string;
|
|
||||||
preview?: string;
|
|
||||||
data?: any;
|
|
||||||
}) {
|
|
||||||
const fd = new FormData();
|
|
||||||
|
|
||||||
// key
|
|
||||||
fd.append("key", key);
|
|
||||||
|
|
||||||
// 签名数据
|
|
||||||
for (const i in data) {
|
|
||||||
if (!fd.has(i)) {
|
|
||||||
fd.append(i, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件
|
|
||||||
fd.append("file", req.file);
|
|
||||||
|
|
||||||
// 上传
|
|
||||||
await service
|
|
||||||
.request({
|
|
||||||
url: host,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data",
|
|
||||||
Authorization: isLocal ? user.token : null
|
|
||||||
},
|
|
||||||
timeout: 600000,
|
|
||||||
data: fd,
|
|
||||||
onUploadProgress(e: AxiosProgressEvent) {
|
|
||||||
item.progress = e.total ? Math.floor((e.loaded / e.total) * 100) : 0;
|
|
||||||
emit("progress", item);
|
|
||||||
},
|
|
||||||
proxy: isLocal,
|
|
||||||
NProgress: false
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
item.key = encodeURIComponent(key);
|
|
||||||
|
|
||||||
if (isLocal) {
|
|
||||||
item.url = res;
|
|
||||||
} else {
|
|
||||||
item.url = pathJoin(preview || host, item.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
item.fileId = fileId;
|
|
||||||
|
|
||||||
emit("success", item);
|
|
||||||
resolve(item.url);
|
|
||||||
update();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
ElMessage.error(err.message);
|
|
||||||
item.error = err.message;
|
|
||||||
emit("error", item);
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLocal) {
|
|
||||||
next({
|
|
||||||
host: "/admin/base/comm/upload"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
service.base.comm
|
|
||||||
.upload(
|
|
||||||
type == "aws"
|
|
||||||
? {
|
|
||||||
key
|
|
||||||
}
|
|
||||||
: {}
|
|
||||||
)
|
|
||||||
.then((res) => {
|
|
||||||
switch (type) {
|
|
||||||
// 腾讯
|
|
||||||
case "cos":
|
|
||||||
next({
|
|
||||||
host: res.url,
|
|
||||||
data: res.credentials
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
// 阿里
|
|
||||||
case "oss":
|
|
||||||
next({
|
|
||||||
host: res.host,
|
|
||||||
preview: res.publicDomain,
|
|
||||||
data: {
|
|
||||||
OSSAccessKeyId: res.OSSAccessKeyId,
|
|
||||||
policy: res.policy,
|
|
||||||
signature: res.signature
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
// 七牛
|
|
||||||
case "qiniu":
|
|
||||||
next({
|
|
||||||
host: res.uploadUrl,
|
|
||||||
preview: res.publicDomain,
|
|
||||||
data: {
|
|
||||||
token: res.token
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
// aws
|
|
||||||
case "aws":
|
|
||||||
next({
|
|
||||||
host: res.url,
|
|
||||||
data: res.fields
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
ElMessage.error("上传配置错误");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检测是否还有未上传的文件
|
// 检测是否还有未上传的文件
|
||||||
|
@ -3,8 +3,8 @@ export default () => {
|
|||||||
label: "文件上传",
|
label: "文件上传",
|
||||||
description: "基于 el-upload 封装的文件上传组件",
|
description: "基于 el-upload 封装的文件上传组件",
|
||||||
author: "COOL",
|
author: "COOL",
|
||||||
version: "1.0.0",
|
version: "1.1.0",
|
||||||
updateTime: "2024-02-01",
|
updateTime: "2024-02-05",
|
||||||
demo: [
|
demo: [
|
||||||
{
|
{
|
||||||
name: "基础用法",
|
name: "基础用法",
|
||||||
@ -47,6 +47,11 @@ export default () => {
|
|||||||
// 上传大小限制
|
// 上传大小限制
|
||||||
size: 100
|
size: 100
|
||||||
},
|
},
|
||||||
|
// 云端上传路径前缀
|
||||||
|
prefixPath: {
|
||||||
|
type: String,
|
||||||
|
default: "app/base"
|
||||||
|
},
|
||||||
// 规则
|
// 规则
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
180
src/plugins/upload/hooks/index.ts
Normal file
180
src/plugins/upload/hooks/index.ts
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { module, service } from "/@/cool";
|
||||||
|
import { uuid } from "/@/cool/utils";
|
||||||
|
import { pathJoin } from "../utils";
|
||||||
|
import { useBase } from "/$/base";
|
||||||
|
import { type AxiosProgressEvent } from "axios";
|
||||||
|
import type { Upload } from "../types";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
|
||||||
|
export function useUpload() {
|
||||||
|
const { options } = module.get("upload");
|
||||||
|
const { user } = useBase();
|
||||||
|
|
||||||
|
// 上传
|
||||||
|
async function toUpload(
|
||||||
|
file: File,
|
||||||
|
opts: Upload.Options = {}
|
||||||
|
): Promise<{
|
||||||
|
key: string;
|
||||||
|
url: string;
|
||||||
|
fileId: string;
|
||||||
|
}> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
// 合并配置
|
||||||
|
const { prefixPath, onProgress } = merge(opts, options);
|
||||||
|
|
||||||
|
// 文件id
|
||||||
|
const fileId = uuid("");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 上传模式、类型
|
||||||
|
const { mode, type } = await service.base.comm.uploadMode();
|
||||||
|
|
||||||
|
// 本地上传
|
||||||
|
const isLocal = mode == "local";
|
||||||
|
|
||||||
|
// 文件名
|
||||||
|
const fileName = fileId + "_" + file.name;
|
||||||
|
|
||||||
|
// Key
|
||||||
|
let key = isLocal ? fileName : pathJoin(prefixPath!, fileName);
|
||||||
|
|
||||||
|
// 多种上传请求
|
||||||
|
// 上传到云端
|
||||||
|
async function next({
|
||||||
|
host,
|
||||||
|
preview,
|
||||||
|
data
|
||||||
|
}: {
|
||||||
|
host: string;
|
||||||
|
preview?: string;
|
||||||
|
data?: any;
|
||||||
|
}) {
|
||||||
|
const fd = new FormData();
|
||||||
|
|
||||||
|
// key
|
||||||
|
fd.append("key", key);
|
||||||
|
|
||||||
|
// 签名数据
|
||||||
|
for (const i in data) {
|
||||||
|
if (!fd.has(i)) {
|
||||||
|
fd.append(i, data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件
|
||||||
|
fd.append("file", file);
|
||||||
|
|
||||||
|
// 上传
|
||||||
|
await service
|
||||||
|
.request({
|
||||||
|
url: host,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
Authorization: isLocal ? user.token : null
|
||||||
|
},
|
||||||
|
timeout: 600000,
|
||||||
|
data: fd,
|
||||||
|
onUploadProgress(e: AxiosProgressEvent) {
|
||||||
|
const progress = e.total
|
||||||
|
? Math.floor((e.loaded / e.total) * 100)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
onProgress?.(progress);
|
||||||
|
},
|
||||||
|
proxy: isLocal,
|
||||||
|
NProgress: false
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
key = encodeURIComponent(key);
|
||||||
|
|
||||||
|
let url = "";
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
url = res;
|
||||||
|
} else {
|
||||||
|
url = pathJoin(preview || host, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
key,
|
||||||
|
url,
|
||||||
|
fileId
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
ElMessage.error(err.message);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
next({
|
||||||
|
host: "/admin/base/comm/upload"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
service.base.comm
|
||||||
|
.upload(
|
||||||
|
type == "aws"
|
||||||
|
? {
|
||||||
|
key
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
switch (type) {
|
||||||
|
// 腾讯
|
||||||
|
case "cos":
|
||||||
|
next({
|
||||||
|
host: res.url,
|
||||||
|
data: res.credentials
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// 阿里
|
||||||
|
case "oss":
|
||||||
|
next({
|
||||||
|
host: res.host,
|
||||||
|
preview: res.publicDomain,
|
||||||
|
data: {
|
||||||
|
OSSAccessKeyId: res.OSSAccessKeyId,
|
||||||
|
policy: res.policy,
|
||||||
|
signature: res.signature
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// 七牛
|
||||||
|
case "qiniu":
|
||||||
|
next({
|
||||||
|
host: res.uploadUrl,
|
||||||
|
preview: res.publicDomain,
|
||||||
|
data: {
|
||||||
|
token: res.token
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// aws
|
||||||
|
case "aws":
|
||||||
|
next({
|
||||||
|
host: res.url,
|
||||||
|
data: res.fields
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error("文件上传失败");
|
||||||
|
console.error("[upload]", err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
options,
|
||||||
|
toUpload
|
||||||
|
};
|
||||||
|
}
|
6
src/plugins/upload/types/index.d.ts
vendored
6
src/plugins/upload/types/index.d.ts
vendored
@ -15,4 +15,10 @@ export declare namespace Upload {
|
|||||||
isPlay?: boolean;
|
isPlay?: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
prefixPath?: string;
|
||||||
|
onProgress?(progress: number): void;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { last } from "lodash-es";
|
import { last } from "lodash-es";
|
||||||
import { filename, extname } from "/@/cool/utils";
|
import { filename, extname } from "/@/cool/utils";
|
||||||
import { module } from "/@/cool";
|
import { module } from "/@/cool";
|
||||||
import type { Upload } from "../types";
|
import { Upload } from "../types";
|
||||||
|
|
||||||
// 模块参数
|
// 模块参数
|
||||||
const { options } = module.get("upload");
|
const { options } = module.get("upload");
|
||||||
@ -74,14 +74,3 @@ export function pathJoin(...parts: string[]): string {
|
|||||||
return normalizedParts.join("/");
|
return normalizedParts.join("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载
|
|
||||||
export function download(url: string) {
|
|
||||||
const a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = url;
|
|
||||||
a.target = "_blank";
|
|
||||||
a.style.display = "none";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user