Files
agt-web/apps/web-antd/src/views/report/progress/modules/project.vue
2025-09-19 17:18:14 +08:00

165 lines
4.7 KiB
Vue

<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { downloadFileFromBlobPart } from '@vben/utils';
import dayjs from 'dayjs';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { exportProject, getProgressByProjectPage } from '#/api/report/progress';
import { ShadowContainer } from '#/components/shadow-container';
import { useProjectGridColumns, useProjectGridFormSchema } from '../data';
/** 导出表格 */
async function onExport(body: any) {
const formValues = await gridApi.formApi.getValues();
const data = await exportProject({ ...body, ...formValues });
downloadFileFromBlobPart({
fileName: `${body.filename}.xlsx`,
source: data,
});
}
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: useProjectGridFormSchema(),
submitOnEnter: true,
fieldMappingTime: [['updateTime', ['updateTimeStart', 'updateTimeEnd']]],
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',
},
gridOptions: {
columns: useProjectGridColumns(),
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getProgressByProjectPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
pagerConfig: {
enabled: true,
},
toolbarConfig: {
refresh: { code: 'query' },
search: true,
export: true,
},
height: 'auto',
rowConfig: {
keyField: 'id',
isHover: false,
useKey: true,
},
columnConfig: {
useKey: true,
},
border: true,
virtualXConfig: {
enabled: false,
},
virtualYConfig: {
enabled: false,
},
exportConfig: {
remote: true,
type: 'xlsx',
types: ['xlsx'],
mode: 'all',
modes: [
{ label: '导出全部数据', value: 'all' },
{ label: '导出当前页数据', value: 'current' },
],
filename() {
return `项目进展数据${dayjs().format('YYYYMMDDHHmmss')}`;
},
sheetName() {
return `项目进展列表`;
},
slots: {
parameter: 'exportParameter',
},
async exportMethod({ options, $grid }) {
const proxyInfo = $grid?.getProxyInfo();
// 处理条件参数
const body = {
filename: options.filename,
sheetName: options.sheetName,
isHeader: options.isHeader,
original: options.original,
mode: options.mode,
pageNo: proxyInfo ? proxyInfo.pager.currentPage : null,
pageSize: proxyInfo ? proxyInfo.pager.pageSize : null,
ids:
options.mode === 'selected'
? options.data.map((item) => item.id)
: [],
includeFields: options.columns.map((column) => {
return column.field;
}),
};
await onExport(body);
},
},
headerCellStyle: { backgroundColor: '#fafafa' },
spanMethod({ row, rowIndex, column, visibleData }) {
const spanFields = ['projectName', 'customerName'];
let columnField = column.field as string;
const mergeFields = [
'serialNo',
'status',
'businessStatus',
'businessOwnerName',
'technicalOwnerAName',
'technicalOwnerBName',
'startTime',
];
if (mergeFields.includes(columnField)) {
// 字段与前面的合并方式相同
columnField = 'projectName';
}
const cellValue = (row as Record<string, any>)[columnField];
if (cellValue && spanFields.includes(columnField)) {
const prevRow = visibleData[rowIndex - 1];
let nextRow = visibleData[rowIndex + 1];
if (
prevRow &&
(prevRow as Record<string, any>)[columnField] === cellValue
) {
return { rowspan: 0, colspan: 0 };
} else {
let countRowspan = 1;
while (
nextRow &&
(nextRow as Record<string, any>)[columnField] === cellValue
) {
nextRow = visibleData[++countRowspan + rowIndex];
}
if (countRowspan > 1) {
return { rowspan: countRowspan, colspan: 1 };
}
}
}
},
} as VxeTableGridOptions<any>,
});
</script>
<template>
<Grid table-title="项目进展">
<template #contentDefault="{ row }">
<!-- <div v-html="row.content" style="white-space: pre-wrap"></div> -->
<ShadowContainer
:content="row.content"
styles="font-family: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, 'Helvetica Neue',
arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';"
/>
</template>
</Grid>
</template>