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

View File

@ -6,10 +6,40 @@
`cl-upload--${type}`,
{
'is-slot': $slots.default,
'is-custom': $slots.item,
'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
v-model="list"
@ -93,36 +123,6 @@
</slot>
</el-upload>
</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>
</div>
</div>
@ -142,7 +142,7 @@ import { PictureFilled, ZoomIn, Delete } from "@element-plus/icons-vue";
import { useCool, module } from "/@/cool";
import { extname, uuid } from "/@/cool/utils";
import { useBase } from "/$/base";
import { fileSize, fileName } from "../utils";
import { fileSize, fileName, fileType } from "../utils";
interface Item {
url: string;
@ -257,7 +257,7 @@ function beforeUpload(file: any, item?: Item) {
}
const d = {
type: file.type?.includes("image") ? "image" : "file",
type: fileType(file.name).value,
preload: "",
progress: 0,
url: "",
@ -423,23 +423,6 @@ function check() {
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() {
const check = list.value.find((e) => !e.url);
@ -463,7 +446,7 @@ watch(
return item;
} else {
return {
type: fileType(url),
type: fileType(url).value,
progress: 0,
uid: uuid(),
url,
@ -519,34 +502,26 @@ defineExpose({
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 {
.cl-upload__list {
width: 100%;
margin-top: 10px;
}
}
.un-drag {
width: 100%;
}
&__header {
.cl-upload__item {
margin-right: 5px;
}
}
&__list {
display: flex;
flex-wrap: wrap;
margin: 0 5px 0 0;
.cl-upload__item {
margin-right: 5px;
}
}
&__text {
@ -606,7 +581,7 @@ defineExpose({
}
}
&.is-file {
&:not(.is-image) {
padding: 10px;
.cl-upload {

View File

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

View File

@ -30,11 +30,17 @@
<span class="cl-upload-space-file__name"
>{{ fileName(url) }}.{{ extname(url) }}</span
>
<!-- 大小 -->
<span class="cl-upload-space-file__size">{{ fileSize(info.size) }}</span>
</template>
<!-- 文件类型 -->
<span
class="cl-upload-space-file__type"
:style="{
backgroundColor: type.color
}"
>{{ type.label }}</span
>
<!-- 进度条 -->
<div
class="cl-upload-space-file__progress"
@ -56,7 +62,7 @@
import { computed, inject } from "vue";
import { ContextMenu } from "@cool-vue/crud";
import { extname } from "/@/cool/utils";
import { fileSize, fileName } from "../../utils";
import { fileName, fileType } from "../../utils";
import { useClipboard } from "@vueuse/core";
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 type = computed(() => fileType(info.value.url));
//
function select() {
emit("select", info.value);
@ -178,7 +187,7 @@ function onContextMenu(e: any) {
}
}
&.is-file {
&:not(.is-image) {
padding: 10px;
.cl-upload-space-file {
@ -220,6 +229,17 @@ function onContextMenu(e: any) {
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 {
padding: 10px;
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 {
@ -17,3 +17,37 @@ export function fileSize(size: number): string {
export function fileName(url: string) {
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"
}
);
}