feat: 合同删除附件,附件管理模块封装
This commit is contained in:
parent
3ff2e732b2
commit
1392cf5441
|
@ -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<any>(`/api/contract/unlink-attachments/${param0}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
params: { ...queryParams },
|
||||||
|
data: body,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 更新合同 PUT /api/contract/${param0} */
|
/** 更新合同 PUT /api/contract/${param0} */
|
||||||
export async function contractUpdate(
|
export async function contractUpdate(
|
||||||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||||
|
|
|
@ -930,19 +930,20 @@ declare namespace API {
|
||||||
page?: number;
|
page?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
field?: string;
|
field?: string;
|
||||||
|
ids?: string;
|
||||||
order?: 'ASC' | 'DESC';
|
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;
|
_t?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1293,6 +1294,9 @@ declare namespace API {
|
||||||
deliveryDeadline: Date;
|
deliveryDeadline: Date;
|
||||||
/** 审核状态(字典) */
|
/** 审核状态(字典) */
|
||||||
status: number;
|
status: number;
|
||||||
|
|
||||||
|
/** 附件 */
|
||||||
|
files?: any[];
|
||||||
id: number;
|
id: number;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
@ -1322,21 +1326,23 @@ declare namespace API {
|
||||||
|
|
||||||
type ContractUpdateDto = {
|
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 = {
|
type ContractDeleteParams = {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
### 业务组件(目录说明)
|
### 业务组件(目录说明)
|
||||||
|
|
||||||
|
1.AttachmentManage不同的业务调用该组件需要传入该业务数据link的文件ids,需要传入unlink文件的方法,只是解除关联,文件实际还在服务器上没有删除,如果想要物理删除文件,需要到存储管理中去删除。
|
||||||
|
|
||||||
#### 与业务强耦合的组件可以放这里
|
#### 与业务强耦合的组件可以放这里
|
||||||
|
|
|
@ -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<TableListItem>;
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Tooltip>
|
||||||
|
{{
|
||||||
|
title: () => record.path,
|
||||||
|
default: () => (
|
||||||
|
<a href={baseApiUrl + record.path} target="_blank">
|
||||||
|
{record.name}
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '预览图',
|
||||||
|
dataIndex: 'path',
|
||||||
|
width: 150,
|
||||||
|
customRender({ record }) {
|
||||||
|
return <Image src={baseApiUrl + record.path}></Image>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '文件后缀',
|
||||||
|
dataIndex: 'extName',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类别',
|
||||||
|
dataIndex: 'type',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '大小',
|
||||||
|
dataIndex: 'size',
|
||||||
|
width: 80,
|
||||||
|
customRender: ({ record }) => {
|
||||||
|
return <Tag color="blue">{record.size}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '上传者',
|
||||||
|
dataIndex: 'username',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createdAt',
|
||||||
|
width: 160,
|
||||||
|
customRender: ({ record }) => formatToDateTime(record.createdAt),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const fileListColumns: TableColumn<FileItem>[] = [
|
||||||
|
{
|
||||||
|
dataIndex: 'thumbUrl',
|
||||||
|
title: '缩略图',
|
||||||
|
width: 100,
|
||||||
|
customRender: ({ record }) => {
|
||||||
|
const { thumbUrl } = record;
|
||||||
|
return thumbUrl && <Image src={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 (
|
||||||
|
<div>
|
||||||
|
<p class="truncate mb-1 max-w-[280px]" title={text}>
|
||||||
|
{text}
|
||||||
|
</p>
|
||||||
|
<Progress percent={percent} size="small" status={status} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 <Tag color="green">上传成功</Tag>;
|
||||||
|
} else if (text === UploadResultStatus.ERROR) {
|
||||||
|
return <Tag color="red">上传失败</Tag>;
|
||||||
|
} else if (text === UploadResultStatus.UPLOADING) {
|
||||||
|
return <Tag color="blue">上传中</Tag>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text || '待上传';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const searchFormSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
label: '名称',
|
||||||
|
component: 'Input',
|
||||||
|
colProps: { span: 8 },
|
||||||
|
},
|
||||||
|
];
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<DynamicTable
|
||||||
|
row-key="id"
|
||||||
|
header-title="附件管理"
|
||||||
|
:data-request="loadTableData"
|
||||||
|
:columns="baseColumns"
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<a-popconfirm
|
||||||
|
title="你确定要删除这些附件吗?"
|
||||||
|
ok-text="确定"
|
||||||
|
cancel-text="取消"
|
||||||
|
@confirm="handleDelete"
|
||||||
|
>
|
||||||
|
<a-button :disabled="!$auth('tool:storage:delete') || !checkedKeys.length" type="error">
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</DynamicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { baseColumns, searchFormSchema } from './columns';
|
||||||
|
import { useTable, type LoadDataParams } from '@/components/core/dynamic-table';
|
||||||
|
import Api from '@/api/';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AttachmentManage',
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
fileIds: {
|
||||||
|
type: Array as PropType<number[]>,
|
||||||
|
},
|
||||||
|
onDelete: { type: Function as PropType<(ids: number[]) => Promise<void>>, default: () => {} },
|
||||||
|
});
|
||||||
|
const checkedKeys = ref<Array<number>>([]);
|
||||||
|
const loadTableData = async (params: LoadDataParams) => {
|
||||||
|
const data = await Api.toolsStorage.storageList({
|
||||||
|
...params,
|
||||||
|
ids: (props.fileIds || []).join(','),
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
const [DynamicTable, dynamicTableInstance] = useTable({
|
||||||
|
formProps: {
|
||||||
|
schemas: searchFormSchema,
|
||||||
|
},
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
selectedRowKeys: checkedKeys as unknown as Key[],
|
||||||
|
onSelect: (record, selected) => {
|
||||||
|
if (selected) {
|
||||||
|
checkedKeys.value = [...checkedKeys.value, record.id];
|
||||||
|
} else {
|
||||||
|
checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||||
|
const changeIds = changeRows.map((item) => item.id);
|
||||||
|
if (selected) {
|
||||||
|
checkedKeys.value = [...checkedKeys.value, ...changeIds];
|
||||||
|
} else {
|
||||||
|
checkedKeys.value = checkedKeys.value.filter((id) => {
|
||||||
|
return !changeIds.includes(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
await props.onDelete?.(checkedKeys.value); // 通常是unlink
|
||||||
|
await Api.toolsStorage.storageDelete({ ids: checkedKeys.value });
|
||||||
|
checkedKeys.value = [];
|
||||||
|
dynamicTableInstance?.reload();
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,11 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>test</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineOptions({
|
|
||||||
name: 'FileManage',
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
|
@ -1,22 +1,27 @@
|
||||||
import type { TableColumn } from '@/components/core/dynamic-table';
|
import type { TableColumn } from '@/components/core/dynamic-table';
|
||||||
import { ContractStatusEnum } from '@/enums/contractEnum';
|
import { ContractStatusEnum } from '@/enums/contractEnum';
|
||||||
import { formatToDate } from '@/utils/dateUtil';
|
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 TableListItem = API.ContractEntity;
|
||||||
export type TableColumnItem = TableColumn<TableListItem>;
|
export type TableColumnItem = TableColumn<TableListItem>;
|
||||||
|
|
||||||
export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): TableColumnItem[] => {
|
export const baseColumns = (ctx: {
|
||||||
|
contractTypes: API.DictItemEntity[];
|
||||||
|
dynamicTableInstance;
|
||||||
|
}): TableColumnItem[] => {
|
||||||
const { contractTypes } = ctx;
|
const { contractTypes } = ctx;
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: '编号',
|
title: '编号',
|
||||||
width: 120,
|
width: 100,
|
||||||
|
maxWidth: 100,
|
||||||
|
fixed: 'left',
|
||||||
dataIndex: 'contractNumber',
|
dataIndex: 'contractNumber',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '标题',
|
title: '标题',
|
||||||
width: 200,
|
width: 180,
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -37,17 +42,18 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '甲方',
|
title: '甲方',
|
||||||
width: 150,
|
width: 120,
|
||||||
dataIndex: 'partyA',
|
dataIndex: 'partyA',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '乙方',
|
title: '乙方',
|
||||||
width: 150,
|
width: 120,
|
||||||
dataIndex: 'partyB',
|
dataIndex: 'partyB',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '签订时间',
|
title: '签订时间',
|
||||||
width: 100,
|
width: 60,
|
||||||
|
maxWidth: 60,
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
dataIndex: 'signingDate',
|
dataIndex: 'signingDate',
|
||||||
customRender: ({ record }) => {
|
customRender: ({ record }) => {
|
||||||
|
@ -56,7 +62,8 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '交付期限',
|
title: '交付期限',
|
||||||
width: 100,
|
width: 60,
|
||||||
|
maxWidth: 60,
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
dataIndex: 'deliveryDeadline',
|
dataIndex: 'deliveryDeadline',
|
||||||
customRender: ({ record }) => {
|
customRender: ({ record }) => {
|
||||||
|
@ -68,12 +75,13 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
maxWidth: 60,
|
maxWidth: 60,
|
||||||
width: 60,
|
width: 60,
|
||||||
|
fixed:'right',
|
||||||
formItemProps: {
|
formItemProps: {
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: Object.values(ContractStatusEnum)
|
options: Object.values(ContractStatusEnum)
|
||||||
.filter((value) => typeof value === 'number')
|
.filter((value) => typeof value === 'number')
|
||||||
.map((item) => formatStatus(item as ContractStatusEnum)),
|
.map((item) => formatStatus(item as ContractStatusEnum)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customRender: ({ record }) => {
|
customRender: ({ record }) => {
|
||||||
|
@ -81,6 +89,7 @@ export const baseColumns = (ctx: { contractTypes: API.DictItemEntity[] }): Table
|
||||||
return <Tag color={color}>{label}</Tag>;
|
return <Tag color={color}>{label}</Tag>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
:data-request="Api.contract.contractList"
|
:data-request="Api.contract.contractList"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
bordered
|
bordered
|
||||||
|
:scroll="{ x: 1920 }"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
|
@ -20,7 +21,6 @@
|
||||||
</template>
|
</template>
|
||||||
</DynamicTable>
|
</DynamicTable>
|
||||||
</div>
|
</div>
|
||||||
<!-- <UploadModal v-if="isUploadPopupVisiable" :visiable="isUploadPopupVisiable"></UploadModal> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
|
@ -28,12 +28,14 @@
|
||||||
import { baseColumns, type TableColumnItem, type TableListItem } from './columns';
|
import { baseColumns, type TableColumnItem, type TableListItem } from './columns';
|
||||||
import Api from '@/api/';
|
import Api from '@/api/';
|
||||||
import { useDictStore } from '@/store/modules/dict';
|
import { useDictStore } from '@/store/modules/dict';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref, type FunctionalComponent } from 'vue';
|
||||||
import { DictEnum } from '@/enums/dictEnum';
|
import { DictEnum } from '@/enums/dictEnum';
|
||||||
import { useFormModal, useModal } from '@/hooks/useModal';
|
import { useFormModal, useModal } from '@/hooks/useModal';
|
||||||
import { contractSchemas } from './formSchemas';
|
import { contractSchemas } from './formSchemas';
|
||||||
import { formatToDate } from '@/utils/dateUtil';
|
import { formatToDate } from '@/utils/dateUtil';
|
||||||
import UploadContract from './upload-contract.vue';
|
import UploadContract from './upload-contract.vue';
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
import AttachmentManage from '@/components/business/attachment-manage/index.vue';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'Contract',
|
name: 'Contract',
|
||||||
});
|
});
|
||||||
|
@ -54,13 +56,23 @@
|
||||||
getContractTypes().then((res) => {
|
getContractTypes().then((res) => {
|
||||||
columns.value = [
|
columns.value = [
|
||||||
...baseColumns({
|
...baseColumns({
|
||||||
|
dynamicTableInstance,
|
||||||
contractTypes: contractTypes.value,
|
contractTypes: contractTypes.value,
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
width: 50,
|
||||||
|
maxWidth: 50,
|
||||||
|
hideInSearch: true,
|
||||||
|
fixed:'right',
|
||||||
|
dataIndex: 'files',
|
||||||
|
customRender: ({ record }) => <FilesRender {...record} />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
maxWidth: 100,
|
maxWidth: 80,
|
||||||
width: 100,
|
width: 80,
|
||||||
minWidth: 100,
|
minWidth: 80,
|
||||||
dataIndex: 'ACTION',
|
dataIndex: 'ACTION',
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
|
@ -86,8 +98,8 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:cloud-server-outlined',
|
icon: 'ant-design:cloud-upload-outlined',
|
||||||
tooltip: '上传下载附件',
|
tooltip: '上传附件',
|
||||||
onClick: () => openFileManageModal(record),
|
onClick: () => openFileManageModal(record),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -97,25 +109,37 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const openFileManageModal = async (record: API.ContractEntity) => {
|
const openFileManageModal = async (record: API.ContractEntity) => {
|
||||||
// UseModalComp.show({
|
|
||||||
// title: '文件管理',
|
|
||||||
// content: FileManage,
|
|
||||||
// });
|
|
||||||
isUploadPopupVisiable.value = true;
|
isUploadPopupVisiable.value = true;
|
||||||
fnModal.show({
|
fnModal.show({
|
||||||
width: 800,
|
width: 800,
|
||||||
title: `合同编号: ${record.contractNumber}`,
|
title: `合同编号: ${record.contractNumber}`,
|
||||||
content: () => {
|
content: () => {
|
||||||
return <UploadContract onClose={handleUploadClose}></UploadContract>;
|
return (
|
||||||
|
<UploadContract
|
||||||
|
onClose={handleUploadClose}
|
||||||
|
afterUploadCallback={(files) => {
|
||||||
|
afterUploadCallback(files, record.id);
|
||||||
|
}}
|
||||||
|
></UploadContract>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
destroyOnClose: true,
|
||||||
|
open: isUploadPopupVisiable.value,
|
||||||
footer: null,
|
footer: null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const handleUploadClose = (hasSuccess: boolean) => {
|
const handleUploadClose = (hasSuccess: boolean) => {
|
||||||
fnModal.hide();
|
fnModal.hide();
|
||||||
// 在这里你可以关闭模态框
|
isUploadPopupVisiable.value = false;
|
||||||
// fnModal.hide();
|
|
||||||
};
|
};
|
||||||
|
const afterUploadCallback = async (
|
||||||
|
files: { filename: { path: string; id: number } }[],
|
||||||
|
id: number,
|
||||||
|
) => {
|
||||||
|
await Api.contract.contractUpdate({ id }, { fileIds: files.map((item) => item.filename.id) });
|
||||||
|
dynamicTableInstance?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 打开新增/编辑弹窗
|
* @description 打开新增/编辑弹窗
|
||||||
*/
|
*/
|
||||||
|
@ -153,6 +177,42 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function delRowConfirm(record) {}
|
function delRowConfirm(record) {}
|
||||||
|
|
||||||
|
const FilesRender: FunctionalComponent<TableListItem> = (contract: API.ContractEntity) => {
|
||||||
|
const [fnModal] = useModal();
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => {
|
||||||
|
openFilesManageModal(fnModal, contract);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{contract.files?.length || 0}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openFilesManageModal = (fnModal, contract: API.ContractEntity) => {
|
||||||
|
const fileIds = contract.files?.map((item) => item.id) || [];
|
||||||
|
fnModal.show({
|
||||||
|
width: 1200,
|
||||||
|
title: `附件管理`,
|
||||||
|
content: () => {
|
||||||
|
return (
|
||||||
|
<AttachmentManage
|
||||||
|
fileIds={fileIds}
|
||||||
|
onDelete={(unlinkIds) => unlinkAttachments(contract.id, unlinkIds)}
|
||||||
|
></AttachmentManage>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
destroyOnClose: true,
|
||||||
|
footer: null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const unlinkAttachments = async (id: number, unlinkIds: number[]) => {
|
||||||
|
await Api.contract.unlinkAttachments({ id }, { fileIds: unlinkIds });
|
||||||
|
dynamicTableInstance?.reload();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -23,7 +23,12 @@
|
||||||
import Api from '@/api/';
|
import Api from '@/api/';
|
||||||
|
|
||||||
const emit = defineEmits(['close']);
|
const emit = defineEmits(['close']);
|
||||||
|
const { afterUploadCallback } = defineProps({
|
||||||
|
afterUploadCallback: {
|
||||||
|
type: Function,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
const [DynamicTable] = useTable();
|
const [DynamicTable] = useTable();
|
||||||
|
|
||||||
const fileList = ref<FileItem[]>([]);
|
const fileList = ref<FileItem[]>([]);
|
||||||
|
@ -56,10 +61,10 @@
|
||||||
|
|
||||||
const onOk = async () => {
|
const onOk = async () => {
|
||||||
const uploadFileList = fileList.value.filter((n) => n.status !== UploadResultStatus.SUCCESS);
|
const uploadFileList = fileList.value.filter((n) => n.status !== UploadResultStatus.SUCCESS);
|
||||||
await Promise.all(
|
const res = await Promise.all(
|
||||||
uploadFileList.map(async (item) => {
|
uploadFileList.map(async (item) => {
|
||||||
try {
|
try {
|
||||||
await Api.toolsUpload.uploadUpload({ file: item.file }, undefined, {
|
const itemRes = await Api.toolsUpload.uploadUpload({ file: item.file }, undefined, {
|
||||||
onUploadProgress(progressEvent) {
|
onUploadProgress(progressEvent) {
|
||||||
const complete = ((progressEvent.loaded / progressEvent.total!) * 100) | 0;
|
const complete = ((progressEvent.loaded / progressEvent.total!) * 100) | 0;
|
||||||
item.percent = complete;
|
item.percent = complete;
|
||||||
|
@ -67,12 +72,16 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
item.status = UploadResultStatus.SUCCESS;
|
item.status = UploadResultStatus.SUCCESS;
|
||||||
|
return itemRes;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
item.status = UploadResultStatus.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) => {
|
const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
|
||||||
|
|
Loading…
Reference in New Issue