mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-27 15:41:32 +08:00
fix(upload): repair file upload and delete invalidation
This commit is contained in:
@@ -4,6 +4,7 @@ import Icon from '/@/components/Icon/index';
|
||||
import { DownOutlined } from '@ant-design/icons-vue';
|
||||
import { ActionItem } from '/@/components/Table';
|
||||
import { Button } from '/@/components/Button';
|
||||
import { snowUuid } from '/@/utils/uuid';
|
||||
const prefixCls = 'basic-table-action';
|
||||
export default defineComponent({
|
||||
name: 'TableAction',
|
||||
@@ -23,7 +24,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
function renderButton(action: ActionItem, index: number) {
|
||||
function renderButton(action: ActionItem) {
|
||||
const { disabled = false, label, icon, color = '', type = 'link', ...actionProps } = action;
|
||||
const button = (
|
||||
<Button
|
||||
@@ -32,7 +33,7 @@ export default defineComponent({
|
||||
disabled={disabled}
|
||||
color={color}
|
||||
{...actionProps}
|
||||
key={`${index}-${label}`}
|
||||
key={`${snowUuid()}`}
|
||||
>
|
||||
{() => (
|
||||
<>
|
||||
@@ -45,10 +46,10 @@ export default defineComponent({
|
||||
return button;
|
||||
}
|
||||
|
||||
function renderPopConfirm(action: ActionItem, index: number) {
|
||||
function renderPopConfirm(action: ActionItem) {
|
||||
const { popConfirm = null } = action;
|
||||
if (!popConfirm) {
|
||||
return renderButton(action, index);
|
||||
return renderButton(action);
|
||||
}
|
||||
const {
|
||||
title,
|
||||
@@ -60,7 +61,7 @@ export default defineComponent({
|
||||
} = popConfirm;
|
||||
return (
|
||||
<Popconfirm
|
||||
key={`p-${index}-${title}`}
|
||||
key={`${snowUuid()}`}
|
||||
title={title}
|
||||
onConfirm={confirm}
|
||||
onCancel={cancel}
|
||||
@@ -68,7 +69,7 @@ export default defineComponent({
|
||||
cancelText={cancelText}
|
||||
icon={icon}
|
||||
>
|
||||
{() => renderButton(action, index)}
|
||||
{() => renderButton(action)}
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
@@ -92,8 +93,8 @@ export default defineComponent({
|
||||
return (
|
||||
<div class={prefixCls}>
|
||||
{actions &&
|
||||
actions.map((action, index) => {
|
||||
return renderPopConfirm(action, index);
|
||||
actions.map((action) => {
|
||||
return renderPopConfirm(action);
|
||||
})}
|
||||
{dropDownActions && dropDownActions.length && (
|
||||
<Dropdown overlayClassName="basic-tale-action-dropdown">
|
||||
@@ -104,13 +105,13 @@ export default defineComponent({
|
||||
<Menu>
|
||||
{{
|
||||
default: () => {
|
||||
return dropDownActions.map((action, index) => {
|
||||
return dropDownActions.map((action) => {
|
||||
const { disabled = false } = action;
|
||||
action.ghost = true;
|
||||
return (
|
||||
<Menu.Item key={`${index}`} disabled={disabled}>
|
||||
<Menu.Item key={`${snowUuid()}`} disabled={disabled}>
|
||||
{() => {
|
||||
return renderPopConfirm(action, index);
|
||||
return renderPopConfirm(action);
|
||||
}}
|
||||
</Menu.Item>
|
||||
);
|
||||
|
@@ -10,13 +10,14 @@ export default defineComponent({
|
||||
return () => {
|
||||
const { columns, actionColumn, dataSource } = props;
|
||||
|
||||
const columnList = [...columns, actionColumn];
|
||||
return (
|
||||
<table class="file-table">
|
||||
<colgroup>
|
||||
{[...columns, actionColumn].map((item) => {
|
||||
const { width = 0 } = item;
|
||||
{columnList.map((item) => {
|
||||
const { width = 0, dataIndex } = item;
|
||||
return width ? (
|
||||
<col style={'width:' + width + 'px;min-width:' + width + 'px;'} />
|
||||
<col style={'width:' + width + 'px;min-width:' + width + 'px;'} key={dataIndex} />
|
||||
) : (
|
||||
<col />
|
||||
);
|
||||
@@ -24,9 +25,13 @@ export default defineComponent({
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="file-table-tr">
|
||||
{[...columns, actionColumn].map((item) => {
|
||||
const { title = '', align = 'center' } = item;
|
||||
return <th class={['file-table-th', align]}>{title}</th>;
|
||||
{columnList.map((item) => {
|
||||
const { title = '', align = 'center', dataIndex } = item;
|
||||
return (
|
||||
<th class={['file-table-th', align]} key={dataIndex}>
|
||||
{title}
|
||||
</th>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -34,16 +39,20 @@ export default defineComponent({
|
||||
{dataSource.map((record = {}) => {
|
||||
return (
|
||||
<tr class="file-table-tr">
|
||||
{[...columns, actionColumn].map((item) => {
|
||||
{columnList.map((item) => {
|
||||
const { dataIndex = '', customRender, align = 'center' } = item;
|
||||
if (customRender && isFunction(customRender)) {
|
||||
return (
|
||||
<td class={['file-table-td', align]}>
|
||||
<td class={['file-table-td', align]} key={dataIndex}>
|
||||
{customRender({ text: record[dataIndex], record })}
|
||||
</td>
|
||||
);
|
||||
} else {
|
||||
return <td class={['file-table-td', align]}>{record[dataIndex]}</td>;
|
||||
return (
|
||||
<td class={['file-table-td', align]} key={dataIndex}>
|
||||
{record[dataIndex]}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</tr>
|
||||
|
27
src/components/Upload/src/ThumbUrl.vue
Normal file
27
src/components/Upload/src/ThumbUrl.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<span class="thumb">
|
||||
<img v-if="fileUrl" :src="fileUrl" />
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
fileUrl: propTypes.string.def(''),
|
||||
fileName: propTypes.string.def(''),
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.thumb {
|
||||
img {
|
||||
position: static;
|
||||
display: block;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,26 +0,0 @@
|
||||
<template>
|
||||
<span>
|
||||
<img v-if="fileUrl" :src="fileUrl" />
|
||||
<span v-else>{{ fileType }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
fileUrl: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
fileType: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
fileName: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
@@ -23,8 +23,10 @@
|
||||
{{ getUploadBtnText }}
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div class="upload-modal-toolbar">
|
||||
<Alert :message="getHelpText" type="info" banner class="upload-modal-toolbar__text"></Alert>
|
||||
<Alert :message="getHelpText" type="info" banner class="upload-modal-toolbar__text" />
|
||||
|
||||
<Upload
|
||||
:accept="getStringAccept"
|
||||
:multiple="multiple"
|
||||
@@ -50,7 +52,7 @@
|
||||
import { basicProps } from './props';
|
||||
import { createTableColumns, createActionColumn } from './data';
|
||||
// utils
|
||||
import { checkFileType, checkImgType, getBase64WithFile } from './utils';
|
||||
import { checkFileType, checkImgType, getBase64WithFile } from './helper';
|
||||
import { buildUUID } from '/@/utils/uuid';
|
||||
import { createImgPreview } from '/@/components/Preview/index';
|
||||
import { uploadApi } from '/@/api/sys/upload';
|
||||
@@ -63,9 +65,9 @@
|
||||
components: { BasicModal, Upload, Alert, FileList },
|
||||
props: basicProps,
|
||||
setup(props, { emit }) {
|
||||
// 是否正在上传
|
||||
const { t } = useI18n();
|
||||
|
||||
// 是否正在上传
|
||||
const isUploadingRef = ref(false);
|
||||
const fileListRef = ref<FileItem[]>([]);
|
||||
const state = reactive<{ fileList: FileItem[] }>({
|
||||
@@ -116,7 +118,6 @@
|
||||
const { size, name } = file;
|
||||
const { maxSize } = props;
|
||||
const accept = unref(getAccept);
|
||||
|
||||
// 设置最大值,则判断
|
||||
if (maxSize && file.size / 1024 / 1024 >= maxSize) {
|
||||
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
|
||||
@@ -175,7 +176,6 @@
|
||||
}
|
||||
try {
|
||||
item.status = UploadResultStatus.UPLOADING;
|
||||
|
||||
const { data } = await uploadApi(
|
||||
{
|
||||
...(props.uploadParams || {}),
|
||||
@@ -266,15 +266,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// const [registerTable] = useTable({
|
||||
// columns: createTableColumns(),
|
||||
// actionColumn: createActionColumn(handleRemove, handlePreview),
|
||||
// pagination: false,
|
||||
// inset: true,
|
||||
// scroll: {
|
||||
// y: 3000,
|
||||
// },
|
||||
// });
|
||||
return {
|
||||
columns: createTableColumns(),
|
||||
actionColumn: createActionColumn(handleRemove, handlePreview),
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import type { BasicColumn, ActionItem } from '/@/components/Table';
|
||||
|
||||
import { FileItem, PreviewFileItem, UploadResultStatus } from './types';
|
||||
import { checkImgType, isImgTypeByName } from './utils';
|
||||
import { checkImgType, isImgTypeByName } from './helper';
|
||||
import { Progress, Tag } from 'ant-design-vue';
|
||||
|
||||
import TableAction from '/@/components/Table/src/components/TableAction';
|
||||
|
||||
import ThumbUrl from './ThumbUrl.vue';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -17,8 +17,8 @@ export function createTableColumns(): BasicColumn[] {
|
||||
title: t('component.upload.legend'),
|
||||
width: 100,
|
||||
customRender: ({ record }) => {
|
||||
const { thumbUrl, type } = (record as FileItem) || {};
|
||||
return <span>{thumbUrl ? <img style={{ maxWidth: '100%' }} src={thumbUrl} /> : type}</span>;
|
||||
const { thumbUrl } = (record as FileItem) || {};
|
||||
return thumbUrl && <ThumbUrl fileUrl={thumbUrl} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -108,10 +108,8 @@ export function createPreviewColumns(): BasicColumn[] {
|
||||
title: t('component.upload.legend'),
|
||||
width: 100,
|
||||
customRender: ({ record }) => {
|
||||
const { url, type } = (record as PreviewFileItem) || {};
|
||||
return (
|
||||
<span>{isImgTypeByName(url) ? <img src={url} style={{ width: '50px' }} /> : type}</span>
|
||||
);
|
||||
const { url } = (record as PreviewFileItem) || {};
|
||||
return isImgTypeByName(url) && <ThumbUrl fileUrl={url} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@@ -18,7 +18,7 @@ export default {
|
||||
maxSizeMultiple: '只能上传不超过{0}MB的文件!',
|
||||
maxNumber: '最多只能上传{0}个文件',
|
||||
|
||||
legend: '图例',
|
||||
legend: '略缩图',
|
||||
fileName: '文件名',
|
||||
fileSize: '文件大小',
|
||||
fileStatue: '状态',
|
||||
|
@@ -19,7 +19,7 @@ export function buildUUID(): string {
|
||||
}
|
||||
|
||||
let unique = 0;
|
||||
export function snowUuid(prefix: string): string {
|
||||
export function snowUuid(prefix = ''): string {
|
||||
const time = Date.now();
|
||||
const random = Math.floor(Math.random() * 1000000000);
|
||||
unique++;
|
||||
|
Reference in New Issue
Block a user