diff --git a/src/api/backend/api/contract.ts b/src/api/backend/api/contract.ts index d66d493..73e8743 100644 --- a/src/api/backend/api/contract.ts +++ b/src/api/backend/api/contract.ts @@ -51,6 +51,25 @@ export async function contractInfo( }); } +/** 解除合同和附件关联 PUT /api/contract/unlink-attachments/${param0} */ +export async function unlinkAttachments( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.ContractUpdateParams, + body: API.ContractUpdateDto, + options?: RequestOptions, +) { + const { id: param0, ...queryParams } = params; + return request(`/api/contract/unlink-attachments/${param0}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...options, + }); +} + /** 更新合同 PUT /api/contract/${param0} */ export async function contractUpdate( // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) diff --git a/src/api/backend/api/typings.d.ts b/src/api/backend/api/typings.d.ts index 6e71ea2..7665655 100644 --- a/src/api/backend/api/typings.d.ts +++ b/src/api/backend/api/typings.d.ts @@ -930,19 +930,20 @@ declare namespace API { page?: number; pageSize?: number; field?: string; + ids?: string; order?: 'ASC' | 'DESC'; /** 文件名 */ - name: string; + name?: string; /** 文件后缀 */ - extName: string; + extName?: string; /** 文件类型 */ - type: string; + type?: string; /** 大小 */ - size: string; + size?: string; /** 上传时间 */ - time: string[]; + time?: string[]; /** 上传者 */ - username: string; + username?: string; _t?: number; }; @@ -1293,6 +1294,9 @@ declare namespace API { deliveryDeadline: Date; /** 审核状态(字典) */ status: number; + + /** 附件 */ + files?: any[]; id: number; createdAt: string; updatedAt: string; @@ -1315,28 +1319,30 @@ declare namespace API { /** 审核状态(字典) */ status: number; }; - + type ContractUpdateParams = { id: number; }; type ContractUpdateDto = { /** 合同编号 */ - contractNumber: string; + contractNumber?: string; /** 合同标题 */ - title: string; + title?: string; /** 合同类型(字典) */ - type: number; + type?: number; /** 甲方 */ - partyA: string; + partyA?: string; /** 乙方 */ - partyB: string; + partyB?: string; /** 签订日期 */ - signingDate: string; + signingDate?: string; /** 交付期限 */ - deliveryDeadline: string; + deliveryDeadline?: string; /** 审核状态(字典) */ - status: number; + status?: number; + /** 附件 */ + fileIds?: number[]; }; type ContractDeleteParams = { diff --git a/src/components/business/README.md b/src/components/business/README.md index 403b3c2..f224398 100644 --- a/src/components/business/README.md +++ b/src/components/business/README.md @@ -1,3 +1,5 @@ ### 业务组件(目录说明) +1.AttachmentManage不同的业务调用该组件需要传入该业务数据link的文件ids,需要传入unlink文件的方法,只是解除关联,文件实际还在服务器上没有删除,如果想要物理删除文件,需要到存储管理中去删除。 + #### 与业务强耦合的组件可以放这里 diff --git a/src/components/business/attachment-manage/columns.tsx b/src/components/business/attachment-manage/columns.tsx new file mode 100644 index 0000000..bdb2eef --- /dev/null +++ b/src/components/business/attachment-manage/columns.tsx @@ -0,0 +1,153 @@ +import { Tag, Tooltip, Image, Progress } from 'ant-design-vue'; +import type { TableColumn } from '@/components/core/dynamic-table'; +import type { FormSchema } from '@/components/core/schema-form'; +import { formatToDateTime } from '@/utils/dateUtil'; +import { baseApiUrl } from '@/utils/request'; + +export type TableListItem = API.StorageInfo; +export type TableColumnItem = TableColumn; + +export type FileItem = { + file: File; + uid: string; + name: string; + size: number; + status: string; + thumbUrl: string; + percent: number; +}; + +export enum UploadResultStatus { + SUCCESS = 'success', + ERROR = 'error', + UPLOADING = 'uploading', +} + +export const baseColumns: TableColumnItem[] = [ + { + title: '文件名', + dataIndex: 'name', + width: 150, + ellipsis: true, + customRender({ record }) { + return ( + + {{ + title: () => record.path, + default: () => ( + + {record.name} + + ), + }} + + ); + }, + }, + { + title: '预览图', + dataIndex: 'path', + width: 150, + customRender({ record }) { + return ; + }, + }, + { + title: '文件后缀', + dataIndex: 'extName', + width: 80, + }, + { + title: '类别', + dataIndex: 'type', + width: 80, + }, + { + title: '大小', + dataIndex: 'size', + width: 80, + customRender: ({ record }) => { + return {record.size}; + }, + }, + { + title: '上传者', + dataIndex: 'username', + width: 120, + }, + { + title: '创建时间', + dataIndex: 'createdAt', + width: 160, + customRender: ({ record }) => formatToDateTime(record.createdAt), + }, +]; + +export const fileListColumns: TableColumn[] = [ + { + dataIndex: 'thumbUrl', + title: '缩略图', + width: 100, + customRender: ({ record }) => { + const { thumbUrl } = record; + return thumbUrl && ; + }, + }, + { + dataIndex: 'name', + title: '文件名', + align: 'left', + customRender: ({ text, record }) => { + const { percent, status: uploadStatus } = record || {}; + let status: 'normal' | 'exception' | 'active' | 'success' = 'normal'; + if (uploadStatus === UploadResultStatus.ERROR) { + status = 'exception'; + } else if (uploadStatus === UploadResultStatus.UPLOADING) { + status = 'active'; + } else if (uploadStatus === UploadResultStatus.SUCCESS) { + status = 'success'; + } + return ( +
+

+ {text} +

+ +
+ ); + }, + }, + { + dataIndex: 'size', + title: '文件大小', + width: 100, + customRender: ({ text = 0 }) => { + return text && `${(text / 1024).toFixed(2)}KB`; + }, + }, + { + dataIndex: 'status', + title: '状态', + width: 100, + customRender: ({ text }) => { + if (text === UploadResultStatus.SUCCESS) { + return 上传成功; + } else if (text === UploadResultStatus.ERROR) { + return 上传失败; + } else if (text === UploadResultStatus.UPLOADING) { + return 上传中; + } + + return text || '待上传'; + }, + }, +]; + +export const searchFormSchema: FormSchema[] = [ + { + field: 'name', + label: '名称', + component: 'Input', + colProps: { span: 8 }, + }, +]; diff --git a/src/components/business/attachment-manage/index.vue b/src/components/business/attachment-manage/index.vue new file mode 100644 index 0000000..87c1ded --- /dev/null +++ b/src/components/business/attachment-manage/index.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/components/business/file-manage/index.vue b/src/components/business/file-manage/index.vue deleted file mode 100644 index 0e7b47b..0000000 --- a/src/components/business/file-manage/index.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/src/views/contract/columns.tsx b/src/views/contract/columns.tsx index 65e30c7..b1113d3 100644 --- a/src/views/contract/columns.tsx +++ b/src/views/contract/columns.tsx @@ -1,22 +1,27 @@ import type { TableColumn } from '@/components/core/dynamic-table'; import { ContractStatusEnum } from '@/enums/contractEnum'; import { formatToDate } from '@/utils/dateUtil'; -import { Tag } from 'ant-design-vue'; +import { Tag, Button } from 'ant-design-vue'; export type TableListItem = API.ContractEntity; export type TableColumnItem = TableColumn; -export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): TableColumnItem[] => { +export const baseColumns = (ctx: { + contractTypes: API.DictItemEntity[]; + dynamicTableInstance; +}): TableColumnItem[] => { const { contractTypes } = ctx; return [ { title: '编号', - width: 120, + width: 100, + maxWidth: 100, + fixed: 'left', dataIndex: 'contractNumber', }, { title: '标题', - width: 200, + width: 180, dataIndex: 'title', }, { @@ -37,17 +42,18 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table }, { title: '甲方', - width: 150, + width: 120, dataIndex: 'partyA', }, { title: '乙方', - width: 150, + width: 120, dataIndex: 'partyB', }, { title: '签订时间', - width: 100, + width: 60, + maxWidth: 60, hideInSearch: true, dataIndex: 'signingDate', customRender: ({ record }) => { @@ -56,7 +62,8 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table }, { title: '交付期限', - width: 100, + width: 60, + maxWidth: 60, hideInSearch: true, dataIndex: 'deliveryDeadline', customRender: ({ record }) => { @@ -68,12 +75,13 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table dataIndex: 'status', maxWidth: 60, width: 60, + fixed:'right', formItemProps: { component: 'Select', componentProps: { options: Object.values(ContractStatusEnum) - .filter((value) => typeof value === 'number') - .map((item) => formatStatus(item as ContractStatusEnum)), + .filter((value) => typeof value === 'number') + .map((item) => formatStatus(item as ContractStatusEnum)), }, }, customRender: ({ record }) => { @@ -81,6 +89,7 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table return {label}; }, }, + ]; }; diff --git a/src/views/contract/index.vue b/src/views/contract/index.vue index c4a1ece..97c8a9d 100644 --- a/src/views/contract/index.vue +++ b/src/views/contract/index.vue @@ -7,6 +7,7 @@ :data-request="Api.contract.contractList" :columns="columns" bordered + :scroll="{ x: 1920 }" size="small" > - diff --git a/src/views/contract/upload-contract.vue b/src/views/contract/upload-contract.vue index 3f9d449..2d34ca9 100644 --- a/src/views/contract/upload-contract.vue +++ b/src/views/contract/upload-contract.vue @@ -23,7 +23,12 @@ import Api from '@/api/'; const emit = defineEmits(['close']); - + const { afterUploadCallback } = defineProps({ + afterUploadCallback: { + type: Function, + default: () => ({}), + }, + }); const [DynamicTable] = useTable(); const fileList = ref([]); @@ -56,10 +61,10 @@ const onOk = async () => { const uploadFileList = fileList.value.filter((n) => n.status !== UploadResultStatus.SUCCESS); - await Promise.all( + const res = await Promise.all( uploadFileList.map(async (item) => { try { - await Api.toolsUpload.uploadUpload({ file: item.file }, undefined, { + const itemRes = await Api.toolsUpload.uploadUpload({ file: item.file }, undefined, { onUploadProgress(progressEvent) { const complete = ((progressEvent.loaded / progressEvent.total!) * 100) | 0; item.percent = complete; @@ -67,12 +72,16 @@ }, }); item.status = UploadResultStatus.SUCCESS; + return itemRes; } catch (error) { console.log(error); item.status = UploadResultStatus.ERROR; } }), ); + message.success({ content: '上传完成', key: '上传完成' }); + afterUploadCallback && afterUploadCallback(res.filter((item) => !!item)); + console.log(fileList.value.filter((n) => n.status === UploadResultStatus.SUCCESS)); }; const beforeUpload: UploadProps['beforeUpload'] = async (file) => {