优化 upload 模块

This commit is contained in:
icssoa 2022-08-17 00:59:03 +08:00
parent e2470a31bf
commit 07ca7ddadd
5 changed files with 139 additions and 94 deletions

View File

@ -24,10 +24,12 @@
<div class="item"> <div class="item">
<p>自定义内容</p> <p>自定义内容</p>
<cl-upload text="选择图片" multiple> <cl-upload text="选择图片" multiple drag>
<el-button>上传</el-button> <div style="width: 100%">
<template #item="{ item, index }"> <el-button>上传</el-button>
<p>{{ item.url }}</p> </div>
<template #item="{ item }">
<div class="cs-item">{{ item.url }}</div>
</template> </template>
</cl-upload> </cl-upload>
</div> </div>
@ -63,5 +65,10 @@ const list = computed(() => urls.value.split(",").filter(Boolean));
font-size: 14px; font-size: 14px;
} }
} }
.cs-item {
border: 1px solid var(--el-border-color);
padding: 5px 10px;
}
} }
</style> </style>

View File

@ -6,10 +6,40 @@
`cl-upload--${type}`, `cl-upload--${type}`,
{ {
'is-slot': $slots.default, 'is-slot': $slots.default,
'is-custom': $slots.item,
'is-disabled': disabled 'is-disabled': disabled
} }
]" ]"
> >
<div class="cl-upload__header">
<el-upload
ref="Upload"
action=""
:accept="accept"
:show-file-list="false"
:before-upload="beforeUpload"
:http-request="httpRequest"
:headers="headers"
:multiple="multiple"
:disabled="disabled"
>
<slot>
<template v-if="type == 'image' && isAdd">
<div class="cl-upload__item">
<el-icon :size="24"><picture-filled /></el-icon>
<span class="cl-upload__text">{{ text }}</span>
</div>
</template>
<template v-if="type == 'file'">
<div class="cl-upload__btn">
<el-button type="success">{{ text }}</el-button>
</div>
</template>
</slot>
</el-upload>
</div>
<!-- 列表 --> <!-- 列表 -->
<draggable <draggable
v-model="list" v-model="list"
@ -93,36 +123,6 @@
</slot> </slot>
</el-upload> </el-upload>
</template> </template>
<template #header>
<el-upload
ref="Upload"
action=""
class="un-drag"
:accept="accept"
:show-file-list="false"
:before-upload="beforeUpload"
:http-request="httpRequest"
:headers="headers"
:multiple="multiple"
:disabled="disabled"
>
<slot>
<template v-if="type == 'image' && isAdd">
<div class="cl-upload__item">
<el-icon :size="24"><picture-filled /></el-icon>
<span class="cl-upload__text">{{ text }}</span>
</div>
</template>
<template v-else-if="type == 'file'">
<div class="cl-upload__btn">
<el-button type="success">{{ text }}</el-button>
</div>
</template>
</slot>
</el-upload>
</template>
</draggable> </draggable>
</div> </div>
</div> </div>
@ -142,7 +142,7 @@ import { PictureFilled, ZoomIn, Delete } from "@element-plus/icons-vue";
import { useCool, module } from "/@/cool"; import { useCool, module } from "/@/cool";
import { extname, uuid } from "/@/cool/utils"; import { extname, uuid } from "/@/cool/utils";
import { useBase } from "/$/base"; import { useBase } from "/$/base";
import { fileSize, fileName } from "../utils"; import { fileSize, fileName, fileType } from "../utils";
interface Item { interface Item {
url: string; url: string;
@ -257,7 +257,7 @@ function beforeUpload(file: any, item?: Item) {
} }
const d = { const d = {
type: file.type?.includes("image") ? "image" : "file", type: fileType(file.name).value,
preload: "", preload: "",
progress: 0, progress: 0,
url: "", url: "",
@ -423,23 +423,6 @@ function check() {
return list.value.find((e) => e.progress != 100); return list.value.find((e) => e.progress != 100);
} }
//
function fileType(path: string) {
if (props.type == "image") {
return "image";
} else {
if (
["bmp", "jpg", "jpeg", "png", "tif", "gif", "svg", "webp"].includes(
extname(path).toLocaleLowerCase()
)
) {
return "image";
} else {
return "file";
}
}
}
// //
function update() { function update() {
const check = list.value.find((e) => !e.url); const check = list.value.find((e) => !e.url);
@ -463,7 +446,7 @@ watch(
return item; return item;
} else { } else {
return { return {
type: fileType(url), type: fileType(url).value,
progress: 0, progress: 0,
uid: uuid(), uid: uuid(),
url, url,
@ -519,34 +502,26 @@ defineExpose({
box-sizing: border-box; box-sizing: border-box;
} }
.is-drag {
margin: 0 5px 5px 0;
}
.un-drag {
.cl-upload__item {
margin-right: 5px;
}
.cl-upload__btn {
margin-bottom: 5px;
}
}
&--file { &--file {
.cl-upload__list { .cl-upload__list {
width: 100%; width: 100%;
margin-top: 10px;
}
}
.un-drag { &__header {
width: 100%; .cl-upload__item {
} margin-right: 5px;
} }
} }
&__list { &__list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin: 0 5px 0 0;
.cl-upload__item {
margin-right: 5px;
}
} }
&__text { &__text {
@ -606,7 +581,7 @@ defineExpose({
} }
} }
&.is-file { &:not(.is-image) {
padding: 10px; padding: 10px;
.cl-upload { .cl-upload {

View File

@ -25,7 +25,7 @@
@drop="onDrop" @drop="onDrop"
> >
<!-- 类目 --> <!-- 类目 -->
<Category /> <category />
<!-- 内容 --> <!-- 内容 -->
<div class="cl-upload-space__content"> <div class="cl-upload-space__content">
@ -40,6 +40,7 @@
:show-file-list="false" :show-file-list="false"
:disabled="disabled" :disabled="disabled"
:limit="9999" :limit="9999"
:accept="accept"
multiple multiple
@success="onSuccess" @success="onSuccess"
@upload="onUpload" @upload="onUpload"
@ -119,6 +120,8 @@ const props = defineProps({
limit: Number, limit: Number,
// //
disabled: Boolean, disabled: Boolean,
//
accept: String,
// //
showBtn: { showBtn: {
type: Boolean, type: Boolean,
@ -137,7 +140,7 @@ const { app } = useBase();
const { options } = module.get("upload"); const { options } = module.get("upload");
// cl-upload // cl-upload
const Upload = ref<any>(); const Upload = ref();
// //
const limit = props.limit || options.limit?.select; const limit = props.limit || options.limit?.select;
@ -181,14 +184,6 @@ watch(
// //
const isSelected = computed(() => !isEmpty(selection.value)); const isSelected = computed(() => !isEmpty(selection.value));
//
provide("space", {
category,
selection,
refresh,
loading
});
// //
function open() { function open() {
visible.value = true; visible.value = true;
@ -225,27 +220,33 @@ function onUpload(data: any) {
list.value.unshift(data); list.value.unshift(data);
} }
const reqParams = {
page: 1
};
// //
async function refresh(params: any = {}) { async function refresh(params: any = {}) {
// //
clear(); clear();
const d = { //
Object.assign(reqParams, {
type: props.accept?.split("/")[0],
...pagination, ...pagination,
...params, ...params,
classifyId: category.id classifyId: category.id
}; });
// //
if (d.page == 1) { if (reqParams.page == 1) {
loading.value = true; loading.value = true;
} }
await service.space.info.page(d).then((res) => { await service.space.info.page(reqParams).then((res) => {
// //
Object.assign(pagination, res.pagination); Object.assign(pagination, res.pagination);
if (d.page == 1) { if (reqParams.page == 1) {
list.value = []; list.value = [];
} }
@ -331,6 +332,14 @@ function loadmore() {
} }
} }
//
provide("space", {
category,
selection,
refresh,
loading
});
onMounted(() => { onMounted(() => {
refresh(); refresh();
}); });

View File

@ -30,11 +30,17 @@
<span class="cl-upload-space-file__name" <span class="cl-upload-space-file__name"
>{{ fileName(url) }}.{{ extname(url) }}</span >{{ fileName(url) }}.{{ extname(url) }}</span
> >
<!-- 大小 -->
<span class="cl-upload-space-file__size">{{ fileSize(info.size) }}</span>
</template> </template>
<!-- 文件类型 -->
<span
class="cl-upload-space-file__type"
:style="{
backgroundColor: type.color
}"
>{{ type.label }}</span
>
<!-- 进度条 --> <!-- 进度条 -->
<div <div
class="cl-upload-space-file__progress" class="cl-upload-space-file__progress"
@ -56,7 +62,7 @@
import { computed, inject } from "vue"; import { computed, inject } from "vue";
import { ContextMenu } from "@cool-vue/crud"; import { ContextMenu } from "@cool-vue/crud";
import { extname } from "/@/cool/utils"; import { extname } from "/@/cool/utils";
import { fileSize, fileName } from "../../utils"; import { fileName, fileType } from "../../utils";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
@ -83,6 +89,9 @@ const isSelected = computed(() => index.value >= 0);
// //
const url = computed(() => info.value.preload || info.value.url); const url = computed(() => info.value.preload || info.value.url);
//
const type = computed(() => fileType(info.value.url));
// //
function select() { function select() {
emit("select", info.value); emit("select", info.value);
@ -178,7 +187,7 @@ function onContextMenu(e: any) {
} }
} }
&.is-file { &:not(.is-image) {
padding: 10px; padding: 10px;
.cl-upload-space-file { .cl-upload-space-file {
@ -220,6 +229,17 @@ function onContextMenu(e: any) {
width: calc(100% - 20px); width: calc(100% - 20px);
} }
&__type {
position: absolute;
top: 5px;
left: 5px;
color: #fff;
background-color: var(--color-primary);
font-size: 12px;
padding: 2px 5px;
border-radius: 3px;
}
&__error { &__error {
padding: 10px; padding: 10px;
color: red; color: red;

View File

@ -1,4 +1,4 @@
import { filename } from "/@/cool/utils"; import { filename, extname } from "/@/cool/utils";
// 文件大小 // 文件大小
export function fileSize(size: number): string { export function fileSize(size: number): string {
@ -17,3 +17,37 @@ export function fileSize(size: number): string {
export function fileName(url: string) { export function fileName(url: string) {
return filename(url.substring(url.indexOf("_") + 1)); return filename(url.substring(url.indexOf("_") + 1));
} }
// 文件类型
export function fileType(path: string) {
const fs = [
{
label: "图片",
value: "image",
format: ["bmp", "jpg", "jpeg", "png", "tif", "gif", "svg", "webp"],
color: "#67C23A"
},
{
label: "视频",
value: "video",
format: ["avi", "wmv", "mpg", "mpeg", "mov", "rm", "ram", "swf", "flv", "mp4"],
color: "#409EFF"
},
{
label: "音频",
value: "audio",
format: ["mp3", "wav", "wma", "mp2", "flac", "midi", "ra", "ape", "aac", "cda"],
color: "#E6A23C"
}
];
return (
fs.find((e) => {
return e.format.find((a) => a == extname(path).toLocaleLowerCase());
}) || {
label: "文件",
value: "file",
color: "#909399"
}
);
}