diff --git a/src/assets/styles/global.css b/src/assets/styles/global.css index 6c18a1f..3e1f2e9 100644 --- a/src/assets/styles/global.css +++ b/src/assets/styles/global.css @@ -12,6 +12,14 @@ body, overflow: hidden; } +/* +.ant-input-affix-wrapper-readonly, +.ant-input[readonly], +.ant-input-affix-wrapper-readonly .ant-input { + background-color: #fafafa; + cursor: default; +} +*/ @keyframes rotate { 0% { transform: rotate(0deg) diff --git a/src/components/content/dialog/uploadForm.vue b/src/components/content/dialog/uploadForm.vue index 8ad08f1..2c836b6 100644 --- a/src/components/content/dialog/uploadForm.vue +++ b/src/components/content/dialog/uploadForm.vue @@ -2,13 +2,20 @@ import { watch, ref, onMounted } from 'vue'; import { Button } from '../../common'; import { Modal, Space } from 'ant-design-vue'; -import { AsyncUploader, EditorData, PageData } from '@skyfox2000/webbase'; -import { AnyData, IUrlInfo } from '@skyfox2000/fapi'; +import { AsyncUploader, EditorData, gridRowUpdate, PageData } from '@skyfox2000/webbase'; +import { AnyData, ApiResponse, IUrlInfo, ResStatus } from '@skyfox2000/fapi'; import UploadFileList from './uploadList.vue'; import { UploadFile } from '@skyfox2000/webbase'; import message from 'vue-m-message'; +import { UploadStatus } from '@skyfox2000/webbase'; const props = defineProps<{ + /** + * #### 使用模式 + * - Row 数据行 + * - Page 页面 + */ + mode: 'Row' | 'Page'; /** * 文件后缀限制 */ @@ -44,6 +51,20 @@ const maxCount = props.maxCount ?? 1; const maxConcurrent = props.maxConcurrent ?? 3; const fileList = ref([]); +const emit = defineEmits<{ + /** + * 显示预处理 + */ + 'before:file-list': [EditorData, UploadFile[]]; + /** + * 上传前预处理 + */ + 'before:upload': [UploadFile[]]; + /** + * 上传结束,处理上传后的文件 + */ + 'after:upload': [UploadFile[]]; +}>(); watch( () => uploaderForm.value.visible, @@ -62,36 +83,64 @@ const dialogUpload = async () => { if (!url.api) url.api = props.pageData.api; if (url.authorize === undefined) url.authorize = props.pageData.authorize; + emit('before:upload', fileList.value); const uploader = new AsyncUploader(url, maxConcurrent); uploaderForm.value.isFormLoading = true; try { if (fileList.value.length === 0) { message.warning('请选择上传的文件!'); - setTimeout(() => { - uploaderForm.value.isFormLoading = false; - }, 10000); return; } // 开始上传文件 await uploader.upload( fileList.value, - (file) => { - console.log(`${file.name} 上传进度:${file.percent}% (${file.status})`); - }, + (_) => {}, (files) => { uploaderForm.value.isFormLoading = false; - console.log('所有文件上传结束:', files); + let err_count = 0; + for (const file of files) { + if (file.status === UploadStatus.Error) { + err_count++; + } + } + if (!err_count) message.success('全部文件上传成功!'); + else if (err_count < files.length) message.error('上传结束,部分文件上传失败!'); + else message.error('上传结束,所有文件上传失败!'); + // 由外部控制存储字段处理或新建formData对象 + emit('after:upload', files); + dialogSave(); }, ); } catch (error) { uploaderForm.value.isFormLoading = false; console.error('上传错误:', error); + message.error('上传错误,请稍后再试!'); + emit('after:upload', fileList.value); + } +}; + +const dialogSave = async () => { + switch (props.mode) { + case 'Row': + if (uploaderForm.value.formData) { + // 仅修改上传相关字段 + const result: ApiResponse = await gridRowUpdate(props.pageData, uploaderForm.value.formData); + if (result.status === ResStatus.SUCCESS) { + uploaderForm.value.visible = false; + } + } + break; + case 'Page': + break; } }; onMounted(() => { + const list: UploadFile[] = []; + emit('before:file-list', uploaderForm.value, list); + fileList.value.push(...list); open.value = uploaderForm.value.visible; }); @@ -106,11 +155,11 @@ const dialogClose = () => { :wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[430px]')" @close="dialogClose" > - + diff --git a/src/components/content/dialog/uploadList.vue b/src/components/content/dialog/uploadList.vue index 46236d1..00a86fe 100644 --- a/src/components/content/dialog/uploadList.vue +++ b/src/components/content/dialog/uploadList.vue @@ -1,30 +1,53 @@