feat: 导出word
parent
b4bca91fea
commit
63a6604b0b
@ -0,0 +1,61 @@
|
|||||||
|
import { Button } from 'antd';
|
||||||
|
// import { useProductsAuditStatesMapVal, useProductsTypesMapVal } from '@/hooks/useProductsSets';
|
||||||
|
// import { useTranslation } from 'react-i18next';
|
||||||
|
// import useProductsStore, { getAgencyAllExtrasAction } from '@/stores/Products/Index';
|
||||||
|
// import RequireAuth from '@/components/RequireAuth';
|
||||||
|
// import { PERM_PRODUCTS_OFFER_AUDIT } from '@/config';
|
||||||
|
// import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
// import AgencyContract from '../Print/AgencyContract';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
|
import { Packer } from 'docx';
|
||||||
|
// import { isEmpty } from '@/utils/commons';
|
||||||
|
|
||||||
|
const ExportDocxBtn = ({ ...props }) => {
|
||||||
|
// const { t } = useTranslation();
|
||||||
|
// const [agencyProducts] = useProductsStore((state) => [state.agencyProducts]);
|
||||||
|
// const [activeAgency] = useProductsStore((state) => [state.activeAgency]);
|
||||||
|
// const { travel_agency_id, use_year, audit_state } = params;
|
||||||
|
|
||||||
|
// const auditStatesMap = useProductsAuditStatesMapVal();
|
||||||
|
// const productsTypesMapVal = useProductsTypesMapVal();
|
||||||
|
|
||||||
|
// const { getRemarkList } = useProductsStore((selector) => ({
|
||||||
|
// getRemarkList: selector.getRemarkList,
|
||||||
|
// }));
|
||||||
|
// const handleDownload = async () => {
|
||||||
|
// // await refresh();
|
||||||
|
// const _agencyExtras = await getAgencyAllExtrasAction(params);
|
||||||
|
// const agencyExtras = Object.keys(_agencyExtras).reduce((acc, pid) => {
|
||||||
|
// const pitemExtras = _agencyExtras[pid];
|
||||||
|
// const _pitem = (pitemExtras || []).map(eitem => ({ ...eitem, info: { ...eitem.info, product_type_name_txt: productsTypesMapVal[eitem.info.product_type_id]?.label || eitem.info.product_type_name } } ));
|
||||||
|
// return { ...acc, [pid]: _pitem };
|
||||||
|
// }, {});
|
||||||
|
// const remarks = await getRemarkList();
|
||||||
|
// const remarksMappedByType = remarks.reduce((r, v) => ({ ...r, [v.product_type_id]: v }), {});
|
||||||
|
// const documentCreator = new AgencyContract();
|
||||||
|
// const doc = documentCreator.create([
|
||||||
|
// params,
|
||||||
|
// activeAgency,
|
||||||
|
// agencyProducts,
|
||||||
|
// agencyExtras,
|
||||||
|
// // remarks,
|
||||||
|
// remarksMappedByType,
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// const _d = dayjs().format('YYYYMMDD_HH.mm.ss.SSS'); // Date.now().toString(32)
|
||||||
|
// // console.log(params);
|
||||||
|
// const _state = isEmpty(audit_state) ? '' : auditStatesMap[audit_state].label;
|
||||||
|
// Packer.toBlob(doc).then((blob) => {
|
||||||
|
// saveAs(blob, `${activeAgency.travel_agency_name}${use_year}年地接合同-${_state}-${_d}.docx`);
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button size='small' onClick={() => {}}>
|
||||||
|
导出 .docx
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ExportDocxBtn;
|
||||||
@ -0,0 +1,507 @@
|
|||||||
|
import {
|
||||||
|
Packer,
|
||||||
|
Paragraph,
|
||||||
|
Table,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
WidthType,
|
||||||
|
TextRun,
|
||||||
|
AlignmentType,
|
||||||
|
FrameAnchorType,
|
||||||
|
HorizontalPositionAlign,
|
||||||
|
VerticalPositionAlign,
|
||||||
|
HeadingLevel,
|
||||||
|
LevelFormat,
|
||||||
|
NumberFormat,
|
||||||
|
PageNumber,
|
||||||
|
BorderStyle,
|
||||||
|
LineRuleType,
|
||||||
|
HorizontalPositionRelativeFrom,
|
||||||
|
VerticalPositionRelativeFrom,
|
||||||
|
} from 'docx';
|
||||||
|
import * as docx from 'docx';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
|
import logoPath from './cht letter header logo.png';
|
||||||
|
|
||||||
|
const pageMargins = {
|
||||||
|
top: `10mm`,
|
||||||
|
bottom: `10mm`,
|
||||||
|
left: `20mm`,
|
||||||
|
right: `20mm`,
|
||||||
|
};
|
||||||
|
// Helper function (e.g., in a separate file or within your component logic)
|
||||||
|
async function getLogoArrayBuffer(logoUrl) {
|
||||||
|
const response = await fetch(logoUrl);
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
return arrayBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只支持两级的嵌套表头
|
||||||
|
*/
|
||||||
|
function buildTable(cols, data) {
|
||||||
|
const spanCols = cols.some((col) => col?.children?.length)
|
||||||
|
? [null].reduce((a, c, ri) => {
|
||||||
|
const r0col = cols.map((col) => ({ ...col, rowSpan: col?.children?.length ? 1 : 2, columnSpan: col?.children?.length ? col.children.length : 1 }));
|
||||||
|
a.push(r0col);
|
||||||
|
const r1col = cols
|
||||||
|
.filter((cc) => cc?.children?.length)
|
||||||
|
.reduce((ac, cc) => {
|
||||||
|
const allChild = cc.children.map((ccc) => ({ ...ccc }));
|
||||||
|
ac.push(...allChild);
|
||||||
|
return ac;
|
||||||
|
}, []);
|
||||||
|
a.push(r1col);
|
||||||
|
return a;
|
||||||
|
}, [])
|
||||||
|
: [cols];
|
||||||
|
const flatCols = cols.some((col) => col?.children?.length)
|
||||||
|
? cols.reduce((a, col) => {
|
||||||
|
col?.children?.length === undefined && a.push({ ...col, rowSpan: col?.children?.length ? 1 : 2, colSpan: col?.children?.length ? col.children.length : 1 });
|
||||||
|
const r1col = (col?.children || []).map((ccc) => ({ ...ccc, rowSpan: 1, colSpan: 1 }));
|
||||||
|
return a.concat(r1col);
|
||||||
|
}, [])
|
||||||
|
: cols;
|
||||||
|
const thead = spanCols.map(
|
||||||
|
(th) =>
|
||||||
|
new TableRow({
|
||||||
|
children: th.map(
|
||||||
|
(td) =>
|
||||||
|
new TableCell({
|
||||||
|
rowSpan: td.rowSpan,
|
||||||
|
columnSpan: td.columnSpan,
|
||||||
|
children: [new Paragraph({ text: td.title, alignment: AlignmentType.CENTER, style: 'TableHeader' })],
|
||||||
|
verticalAlign: AlignmentType.CENTER,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const rows = data.map(
|
||||||
|
(row, ci) =>
|
||||||
|
new TableRow({
|
||||||
|
children: flatCols.map(
|
||||||
|
(cell) =>
|
||||||
|
new TableCell({
|
||||||
|
// width: { size: 100 / flatCols.length, type: WidthType.PERCENTAGE },
|
||||||
|
margins: {
|
||||||
|
top: 100,
|
||||||
|
bottom: 100,
|
||||||
|
left: 100,
|
||||||
|
right: 100,
|
||||||
|
},
|
||||||
|
alignment: typeof row[cell.dataIndex] === 'number' ? AlignmentType.RIGHT : AlignmentType.START,
|
||||||
|
verticalAlign: AlignmentType.CENTER,
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
text: String(row[cell.dataIndex]),
|
||||||
|
verticalAlign: AlignmentType.CENTER,
|
||||||
|
alignment: typeof row[cell.dataIndex] === 'number' ? AlignmentType.RIGHT : AlignmentType.START,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return new Table({
|
||||||
|
rows: [...thead, ...rows],
|
||||||
|
width: { size: 100, type: WidthType.PERCENTAGE },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTitle(text) {
|
||||||
|
return new Paragraph({
|
||||||
|
text,
|
||||||
|
heading: HeadingLevel.TITLE,
|
||||||
|
alignment: AlignmentType.CENTER,
|
||||||
|
pageBreakBefore: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const createHeaderText = () =>
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun('Hello World'), // ✅ Required before Textbox
|
||||||
|
// new docx.Textbox({
|
||||||
|
// // anchor: {
|
||||||
|
// // horizontal: FrameAnchorType.MARGIN,
|
||||||
|
// // vertical: FrameAnchorType.MARGIN,
|
||||||
|
// // },
|
||||||
|
// // alignment: {
|
||||||
|
// // x: HorizontalPositionAlign.RIGHT,
|
||||||
|
// // y: VerticalPositionAlign.TOP,
|
||||||
|
// // },
|
||||||
|
// alignment: 'right',
|
||||||
|
// verticalAlign: AlignmentType.END,
|
||||||
|
// children: [
|
||||||
|
// new TextRun({
|
||||||
|
// text: '111Tel: 86-773-2885311',
|
||||||
|
// break: 1,
|
||||||
|
// }),
|
||||||
|
// new TextRun({
|
||||||
|
// text: 'Fax: 86-773-2827424',
|
||||||
|
// break: 1,
|
||||||
|
// }),
|
||||||
|
// new TextRun({
|
||||||
|
// text: 'E-mail: products@chinahighlights.com',
|
||||||
|
// break: 1,
|
||||||
|
// }),
|
||||||
|
// new TextRun({
|
||||||
|
// text: 'Web site: https://www.chinahighlights.com',
|
||||||
|
// break: 1,
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// positioning: 'Floating',
|
||||||
|
// floating: {
|
||||||
|
// horizontalPosition: {
|
||||||
|
// relative: HorizontalPositionAlign.LEFT,
|
||||||
|
// offset: 0,
|
||||||
|
// },
|
||||||
|
// verticalPosition: {
|
||||||
|
// relative: VerticalPositionAlign.TOP,
|
||||||
|
// offset: 0,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// // style: { width: "200pt", height: "auto" }
|
||||||
|
// }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const createHeaderRight = () =>
|
||||||
|
new Paragraph({
|
||||||
|
frame: {
|
||||||
|
// position: 0,
|
||||||
|
width: 4000,
|
||||||
|
height: 800,
|
||||||
|
anchor: {
|
||||||
|
horizontal: FrameAnchorType.MARGIN,
|
||||||
|
vertical: FrameAnchorType.MARGIN,
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
x: HorizontalPositionAlign.RIGHT,
|
||||||
|
y: VerticalPositionAlign.TOP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
alignment: AlignmentType.RIGHT,
|
||||||
|
verticalAlign: AlignmentType.END,
|
||||||
|
style: 'Header',
|
||||||
|
// thematicBreak: true,
|
||||||
|
// border: {
|
||||||
|
// top: { color: 'auto', space: 10, value: BorderStyle.DOUBLE, size: 20 },
|
||||||
|
// bottom: { color: 'bf192a', space: 10, value: BorderStyle.DOUBLE, size: 20 },
|
||||||
|
// left: { color: 'auto', space: 10, value: BorderStyle.DOUBLE, size: 20 },
|
||||||
|
// right: { color: 'auto', space: 10, value: BorderStyle.DOUBLE, size: 20 },
|
||||||
|
// },
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
relative: HorizontalPositionAlign.LEFT,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
relative: VerticalPositionAlign.TOP,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: 'Tel: 86-773-2885311',
|
||||||
|
break: 1,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: 'Fax: 86-773-2827424',
|
||||||
|
break: 1,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: 'E-mail: products@chinahighlights.com',
|
||||||
|
break: 1,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: 'Web site: https://www.chinahighlights.com',
|
||||||
|
break: 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
// Template function
|
||||||
|
const createDoc = async (agencyName, title, sectionsData) => {
|
||||||
|
const logoArrayBuffer = await getLogoArrayBuffer(logoPath);
|
||||||
|
|
||||||
|
const image = new docx.ImageRun({
|
||||||
|
// type: 'png',
|
||||||
|
data: logoArrayBuffer,
|
||||||
|
// Set dimensions in **EMUs** (English Metric Units) or **pixels**.
|
||||||
|
// If using pixels, docx converts them, but EMUs (914400 EMUs = 1 inch) are standard.
|
||||||
|
// E.g., for a 75x75 pixel image, you might use:
|
||||||
|
// width: 75,
|
||||||
|
// height: 75,
|
||||||
|
transformation: {
|
||||||
|
width: 100,
|
||||||
|
height: 66,
|
||||||
|
},
|
||||||
|
// positioning: 'Floating',
|
||||||
|
// floating: {
|
||||||
|
// horizontalPosition: {
|
||||||
|
// relative: HorizontalPositionAlign.LEFT,
|
||||||
|
// offset: 0,
|
||||||
|
// },
|
||||||
|
// verticalPosition: {
|
||||||
|
// relative: VerticalPositionAlign.TOP,
|
||||||
|
// offset: 0,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
|
||||||
|
const doc = new docx.Document({
|
||||||
|
creator: 'China Highlights',
|
||||||
|
subject: 'CH信笺2025',
|
||||||
|
styles: {
|
||||||
|
paragraphStyles: [
|
||||||
|
{
|
||||||
|
id: 'Header',
|
||||||
|
name: 'Header',
|
||||||
|
quickFormat: true,
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
run: {
|
||||||
|
size: 16,
|
||||||
|
font: { name: 'Verdana' },
|
||||||
|
color: '000000',
|
||||||
|
// underline: { type: 'single', width: 1, color: 'bf192a' },
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
// after: 200,
|
||||||
|
// line: 240,
|
||||||
|
// lineRule: LineRuleType.AT_LEAST,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Footer',
|
||||||
|
name: 'Footer',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 16,
|
||||||
|
font: { name: 'Verdana' },
|
||||||
|
color: '000000',
|
||||||
|
// underline: { type: 'single', width: 1, color: 'bf192a' },
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
after: 100,
|
||||||
|
line: 240,
|
||||||
|
// lineRule:
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Normal',
|
||||||
|
name: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 22,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
after: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Title',
|
||||||
|
name: 'Title',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 44,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 200,
|
||||||
|
after: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Heading1',
|
||||||
|
name: 'Heading 1',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 32,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 200,
|
||||||
|
after: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Heading2',
|
||||||
|
name: 'Heading 2',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 28,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 120,
|
||||||
|
after: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'TableHeader',
|
||||||
|
name: 'Table Header',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 22,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
bold: true,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 80,
|
||||||
|
after: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
numbering: {
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
reference: 'header1',
|
||||||
|
levels: [{ level: 0, text: '%1、', format: LevelFormat.CHINESE_COUNTING }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// 目录
|
||||||
|
features: {
|
||||||
|
updateFields: true,
|
||||||
|
},
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
page: {
|
||||||
|
pageNumbers: {
|
||||||
|
start: 1,
|
||||||
|
formatType: NumberFormat.DECIMAL,
|
||||||
|
},
|
||||||
|
margin: pageMargins,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
default: new docx.Header({
|
||||||
|
children: [
|
||||||
|
new docx.Paragraph({
|
||||||
|
children: [image],
|
||||||
|
alignment: docx.AlignmentType.LEFT, // Align the image in the header
|
||||||
|
style: 'Header',
|
||||||
|
// todo: 边框位置被图文框占用
|
||||||
|
// thematicBreak: true,
|
||||||
|
border: {
|
||||||
|
top: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
bottom: { style: 'inset', size: 20, space: 0, color: 'bf192a' },
|
||||||
|
left: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
right: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
createHeaderRight(),
|
||||||
|
// createHeaderText(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: new docx.Footer({
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
alignment: AlignmentType.END,
|
||||||
|
style: 'Footer',
|
||||||
|
// thematicBreak: true,
|
||||||
|
border: {
|
||||||
|
top: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
bottom: { style: 'inset', size: 20, space: 0, color: 'bf192a' },
|
||||||
|
left: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
right: { style: 'none', size: 10, space: 0, color: 'bf192a' },
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
children: ['- ', PageNumber.CURRENT, ' -'],
|
||||||
|
size: 18,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
alignment: AlignmentType.CENTER,
|
||||||
|
style: 'Footer',
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: '中国 桂林市七里店路70号创意产业园6号楼4层 桂林海纳国际旅行社有限公司 邮编541004',
|
||||||
|
// break: 1,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: 'China Highlights, Discovery Your Way (Since 1959)!',
|
||||||
|
break: 1,
|
||||||
|
font: 'Arial',
|
||||||
|
bold: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
// new Paragraph({
|
||||||
|
// alignment: AlignmentType.RIGHT,
|
||||||
|
// children: [
|
||||||
|
// new TextRun({
|
||||||
|
// text: `${new Date().toLocaleString()}系统生成`,
|
||||||
|
// italics: true,
|
||||||
|
// size: 20,
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// }),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
createTitle(agencyName),
|
||||||
|
new docx.TableOfContents('toc', {
|
||||||
|
hyperlink: true,
|
||||||
|
headingStyleRange: '1-5',
|
||||||
|
}),
|
||||||
|
|
||||||
|
createTitle(title),
|
||||||
|
...sectionsData.reduce((arr, { tableTitle, tableColumns, tableData }) => {
|
||||||
|
const _tableTitle = new Paragraph({
|
||||||
|
text: tableTitle,
|
||||||
|
heading: HeadingLevel.HEADING_1,
|
||||||
|
alignment: AlignmentType.START,
|
||||||
|
numbering: { reference: 'header1', level: 0 },
|
||||||
|
});
|
||||||
|
const table = buildTable(tableColumns, tableData);
|
||||||
|
return [...arr, _tableTitle, table];
|
||||||
|
}, []),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return doc;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export function
|
||||||
|
export async function exportDoc(agencyName, title, sectionsData) {
|
||||||
|
const doc = await createDoc(agencyName, title, sectionsData);
|
||||||
|
const blob = await Packer.toBlob(doc);
|
||||||
|
saveAs(blob, `${title}.${agencyName}.docx`);
|
||||||
|
}
|
||||||
@ -0,0 +1,308 @@
|
|||||||
|
import { isEmpty } from '@/utils/commons';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
AlignmentType,
|
||||||
|
BorderStyle,
|
||||||
|
Document,
|
||||||
|
Footer,
|
||||||
|
Header,
|
||||||
|
HeadingLevel,
|
||||||
|
LevelFormat,
|
||||||
|
NumberFormat,
|
||||||
|
PageNumber,
|
||||||
|
Paragraph,
|
||||||
|
Tab,
|
||||||
|
Table,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
TabStopType,
|
||||||
|
TextRun,
|
||||||
|
WidthType,
|
||||||
|
Media,
|
||||||
|
} from 'docx';
|
||||||
|
// import { splitTable_6, splitTable_7, splitTable_B, splitTable_D, splitTable_J, splitTable_Q, splitTable_R, splitTable_8 } from '@/hooks/useProductsQuotationFormat';
|
||||||
|
// import { formatGroupSize } from '@/hooks/useProductsSets';
|
||||||
|
import logo from './cht letter header logo.png';
|
||||||
|
|
||||||
|
const unitMap = {
|
||||||
|
'0': '人',
|
||||||
|
'1': '团',
|
||||||
|
};
|
||||||
|
|
||||||
|
const DOC_TITLE = '地接合同';
|
||||||
|
const pageMargins = {
|
||||||
|
top: `15mm`,
|
||||||
|
bottom: `15mm`,
|
||||||
|
left: `10mm`,
|
||||||
|
right: `10mm`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableBorderNone = {
|
||||||
|
top: { style: BorderStyle.NONE, size: 0, color: 'FFFFFF' },
|
||||||
|
bottom: { style: BorderStyle.NONE, size: 0, color: 'FFFFFF' },
|
||||||
|
left: { style: BorderStyle.NONE, size: 0, color: 'FFFFFF' },
|
||||||
|
right: { style: BorderStyle.NONE, size: 0, color: 'FFFFFF' },
|
||||||
|
};
|
||||||
|
const tableBorderOne = {
|
||||||
|
top: { style: BorderStyle.SINGLE, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.SINGLE, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.SINGLE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.SINGLE, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
const tableBorderInner = {
|
||||||
|
top: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.INSET, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.INSET, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
const tableBorderInnerB = {
|
||||||
|
top: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.INSET, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
const tableBorderInnerDashB = {
|
||||||
|
top: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.DASHED, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
const tableBorderInnerT = {
|
||||||
|
top: { style: BorderStyle.INSET, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
const tableBorderInnerR = {
|
||||||
|
top: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
bottom: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
left: { style: BorderStyle.NONE, space: 0, size: 6, color: 'auto' },
|
||||||
|
right: { style: BorderStyle.INSET, space: 0, size: 6, color: 'auto' },
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @version
|
||||||
|
* @date 2025-08-20
|
||||||
|
*/
|
||||||
|
export default class TemplateLetter2025 {
|
||||||
|
#remarkList = {};
|
||||||
|
create([headerParams, activeAgency, agencyProducts, agencyExtras, remarks]) {
|
||||||
|
this.#remarkList = remarks;
|
||||||
|
const { use_year } = headerParams;
|
||||||
|
const h1 = `${activeAgency.travel_agency_name}${use_year}年${DOC_TITLE}`;
|
||||||
|
const yearStart = dayjs(`${use_year}-01-01`).format('YYYY.MM.DD');
|
||||||
|
const yearEnd = dayjs(`${use_year}-12-31`).format('YYYY.MM.DD');
|
||||||
|
|
||||||
|
const document = new Document({
|
||||||
|
creator: 'China Highlights',
|
||||||
|
title: h1,
|
||||||
|
subject: 'CH信笺2025',
|
||||||
|
styles: {
|
||||||
|
paragraphStyles: [
|
||||||
|
{
|
||||||
|
id: 'Normal',
|
||||||
|
name: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 22,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
after: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Title',
|
||||||
|
name: 'Title',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 44,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 200,
|
||||||
|
after: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Heading1',
|
||||||
|
name: 'Heading 1',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 32,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 200,
|
||||||
|
after: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Heading2',
|
||||||
|
name: 'Heading 2',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 28,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 120,
|
||||||
|
after: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'TableHeader',
|
||||||
|
name: 'Table Header',
|
||||||
|
basedOn: 'Normal',
|
||||||
|
next: 'Normal',
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
size: 22,
|
||||||
|
font: { name: '宋体' },
|
||||||
|
color: '000000',
|
||||||
|
bold: true,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: {
|
||||||
|
before: 80,
|
||||||
|
after: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
numbering: {
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
reference: 'products-type',
|
||||||
|
levels: [{ level: 0, text: '%1、', format: LevelFormat.CHINESE_COUNTING }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'terms',
|
||||||
|
levels: [{ level: 0, text: '%1.', format: LevelFormat.DECIMAL }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
page: {
|
||||||
|
pageNumbers: {
|
||||||
|
start: 1,
|
||||||
|
formatType: NumberFormat.DECIMAL,
|
||||||
|
},
|
||||||
|
margin: pageMargins,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
default: new Header({
|
||||||
|
children: [
|
||||||
|
this.createPageHeaderRightText(`Tel: 86-773-2885311`, { italics: false }),
|
||||||
|
this.createPageHeaderRightText(`Fax: 86-773-2827424`, { italics: false }),
|
||||||
|
this.createPageHeaderRightText(`E-mail: products@chinahighlights.com`, { italics: false }),
|
||||||
|
this.createPageHeaderRightText(`Web site: https://www.chinahighlights.com`, { italics: false }),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: new Footer({
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
alignment: AlignmentType.CENTER,
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
children: ['第', PageNumber.CURRENT, '页'],
|
||||||
|
size: 20,
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
children: [', 共 ', PageNumber.TOTAL_PAGES, '页'],
|
||||||
|
size: 20,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
alignment: AlignmentType.RIGHT,
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: `${new Date().toLocaleString()}系统生成`,
|
||||||
|
italics: true,
|
||||||
|
size: 20,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
createHeading(text) {
|
||||||
|
return new Paragraph({
|
||||||
|
text: text,
|
||||||
|
heading: HeadingLevel.HEADING_1,
|
||||||
|
alignment: AlignmentType.CENTER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createTitle(text) {
|
||||||
|
return new Paragraph({
|
||||||
|
text: text,
|
||||||
|
heading: HeadingLevel.TITLE,
|
||||||
|
alignment: AlignmentType.CENTER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createSubHeading(text, style = {}) {
|
||||||
|
return new Paragraph({
|
||||||
|
text: text,
|
||||||
|
heading: HeadingLevel.HEADING_1,
|
||||||
|
...style,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPageHeaderLeftLogo(doc) {
|
||||||
|
const response = await fetch(logo);
|
||||||
|
const imageBuffer = await response.arrayBuffer();
|
||||||
|
return new Paragraph({
|
||||||
|
children: [
|
||||||
|
Media.addImage(doc, imageBuffer, 120, 60), // width, height
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createPageHeaderRightText(text, style = {}) {
|
||||||
|
return new Paragraph({
|
||||||
|
alignment: AlignmentType.RIGHT,
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: text,
|
||||||
|
italics: true,
|
||||||
|
size: 20,
|
||||||
|
...style,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,102 @@
|
|||||||
|
import { useContext } from 'react';
|
||||||
|
import { Row, Col, Typography, Space, Table, Divider, Button } from 'antd';
|
||||||
|
import { stores_Context } from '../config';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
import { toJS } from 'mobx';
|
||||||
|
import SearchForm from '../components/search/SearchForm';
|
||||||
|
import useHostCaseStore from '../zustand/HostCase';
|
||||||
|
import { useShallow } from 'zustand/shallow';
|
||||||
|
import { exportDoc } from '../components/TemplateLetter2025/Index';
|
||||||
|
|
||||||
|
const HostCaseReport = ({ ...props }) => {
|
||||||
|
const { date_picker_store } = useContext(stores_Context);
|
||||||
|
// const host_case_data = customer_store.host_case_data;
|
||||||
|
|
||||||
|
const [loading, reset, searchValues, setSearchValues, forExport] = useHostCaseStore(
|
||||||
|
useShallow((state) => [state.loading, state.reset, state.searchValues, state.setSearchValues, state.forExport])
|
||||||
|
);
|
||||||
|
const [caseSummary, caseSummaryByGuide, caseFeatured, getCaseReport] = useHostCaseStore(
|
||||||
|
useShallow((state) => [state.caseSummary, state.caseSummaryByGuide, state.caseFeatured, state.getCaseReport])
|
||||||
|
);
|
||||||
|
|
||||||
|
const getData = async (formVal) => {
|
||||||
|
reset();
|
||||||
|
await getCaseReport(formVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
const summaryCols = [
|
||||||
|
{ title: '接团数', dataIndex: 'group_count', width: '6rem' },
|
||||||
|
{ title: '东道主团数', dataIndex: 'group_count_dongdaozhu', width1: '8rem' },
|
||||||
|
{ title: '东道主个数', dataIndex: 'case_count_dongdaozhu', width1: '8rem' },
|
||||||
|
{ title: '东道主实施比例', dataIndex: 'dongdaozhu_rate' },
|
||||||
|
{
|
||||||
|
title: '各类型个数',
|
||||||
|
children: [
|
||||||
|
{ title: 'Live There', dataIndex: 'live_there_count' },
|
||||||
|
{ title: '动机圆梦', dataIndex: 'dream_fulfillment_count' },
|
||||||
|
{ title: '仪式感创造', dataIndex: 'ceremony_creation_count' },
|
||||||
|
{ title: '遗憾弥补', dataIndex: 'regret_compensation_count' },
|
||||||
|
{ title: '力挽狂澜', dataIndex: 'rescue_mission_count' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const guideSummaryCols = [{ title: '姓名', dataIndex: 'TGI_Name', width: '6rem' }, ...summaryCols];
|
||||||
|
const featuredCaseCols = [
|
||||||
|
{ title: '团号', dataIndex: 'GRI_No', width: '16rem' },
|
||||||
|
{ title: '导游', dataIndex: 'chinese_name', width: '8rem' },
|
||||||
|
{ title: '案例类型', dataIndex: 'case_name', width: '8rem' },
|
||||||
|
{ title: '案例', dataIndex: 'case_text' },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Space direction="vertical" style={{ width: '100%' }}>
|
||||||
|
<Row gutter={16} className={toJS(date_picker_store.siderBroken) ? '' : 'sticky-top'}>
|
||||||
|
<Col className="gutter-row" span={24}>
|
||||||
|
<SearchForm
|
||||||
|
defaultValue={{
|
||||||
|
initialValue: {
|
||||||
|
...toJS(date_picker_store.formValues),
|
||||||
|
...searchValues,
|
||||||
|
},
|
||||||
|
shows: ['dates', 'agency'],
|
||||||
|
fieldProps: {
|
||||||
|
DepartmentList: { show_all: false, mode: 'multiple' },
|
||||||
|
dates: { hide_vs: true },
|
||||||
|
agency: { rules: [{ required: true, message: '请选择地接社' }] },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onSubmit={(_err, obj, form) => {
|
||||||
|
setSearchValues(obj, form);
|
||||||
|
getData(obj);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<div className="max-w-screen-xl " style={{}}>
|
||||||
|
<Divider orientation="right">
|
||||||
|
<Button size='small'
|
||||||
|
onClick={() => {
|
||||||
|
exportDoc(forExport.agencyName, forExport.title, [
|
||||||
|
{ tableTitle: '2025年东道主总体情况', tableColumns: summaryCols, tableData: caseSummary },
|
||||||
|
{ tableTitle: '2025年导游实施东道主情况', tableColumns: guideSummaryCols, tableData: caseSummaryByGuide },
|
||||||
|
{ tableTitle: '2025年精品案例', tableColumns: featuredCaseCols, tableData: caseFeatured },
|
||||||
|
]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
导出 .docx
|
||||||
|
</Button>
|
||||||
|
</Divider>
|
||||||
|
<Typography.Title level={3}>2025年东道主总体情况</Typography.Title>
|
||||||
|
<Table dataSource={caseSummary} columns={summaryCols} loading={loading} pagination={false} bordered />
|
||||||
|
<Typography.Title level={3}>2025年导游实施东道主情况</Typography.Title>
|
||||||
|
<Table dataSource={caseSummaryByGuide} columns={guideSummaryCols} loading={loading} pagination={false} bordered rowKey={'TGI_SN'} />
|
||||||
|
<Typography.Title level={3}>2025年精品案例</Typography.Title>
|
||||||
|
<Table dataSource={caseFeatured} columns={featuredCaseCols} loading={loading} pagination={false} bordered rowKey={'case_id'} />
|
||||||
|
</div>
|
||||||
|
</Space>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default observer(HostCaseReport);
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { devtools } from 'zustand/middleware';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
import { fetchJSON } from '../utils/request';
|
||||||
|
import { HT_HOST } from '../config';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms an array of row data into an array of objects,
|
||||||
|
* using a separate array of column names as keys.
|
||||||
|
*
|
||||||
|
* @param {string[]} cols - The array of column names (keys).
|
||||||
|
* @param {any[][]} rows - The array of row data (values).
|
||||||
|
* @returns {Object[]} The transformed array of objects.
|
||||||
|
*/
|
||||||
|
export const transformRows = (cols, rows) => {
|
||||||
|
return rows.map((row) => {
|
||||||
|
return row.reduce((acc, val, i) => {
|
||||||
|
acc[cols[i].display_name] = val;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchCaseSummary = async (params) => {
|
||||||
|
const searchParams = {
|
||||||
|
...params,
|
||||||
|
vei_sn: params.agency,
|
||||||
|
};
|
||||||
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/service-Analyse2/dong_dao_zhu_total`, searchParams);
|
||||||
|
return errcode !== 0 ? [] : (result || []);
|
||||||
|
};
|
||||||
|
export const fetchCaseSummaryByGuide = async (params) => {
|
||||||
|
const searchParams = {
|
||||||
|
...params,
|
||||||
|
vei_sn: params.agency,
|
||||||
|
};
|
||||||
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/service-Analyse2/dong_dao_zhu_tour_guide`, searchParams);
|
||||||
|
return errcode !== 0 ? [] : (result || []); // .sort(sortDescBy('case_count_dongdaozhu'));
|
||||||
|
};
|
||||||
|
export const fetchCaseFeatured = async (params) => {
|
||||||
|
const searchParams = {
|
||||||
|
...params,
|
||||||
|
vei_sn: params.agency,
|
||||||
|
};
|
||||||
|
const { errcode, result } = await fetchJSON(`${HT_HOST}/service-Analyse2/dong_dao_zhu_case`, searchParams);
|
||||||
|
return errcode !== 0 ? [] : (result || []);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 东道主报告----------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
const initialState = {
|
||||||
|
loading: false,
|
||||||
|
loadingCase: false,
|
||||||
|
caseSummary: [],
|
||||||
|
caseSummaryByGuide: [],
|
||||||
|
caseFeatured: [],
|
||||||
|
|
||||||
|
forExport: {
|
||||||
|
agencyName: '',
|
||||||
|
title: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const useHostCaseStore = create(
|
||||||
|
devtools(
|
||||||
|
immer((set, get) => ({
|
||||||
|
...initialState,
|
||||||
|
searchValues: {},
|
||||||
|
searchValuesToSub: {},
|
||||||
|
reset: () => set(initialState),
|
||||||
|
|
||||||
|
setLoading: (loading) => set({ loading }),
|
||||||
|
setSearchValues: (obj, values) => set((state) => ({ searchValues: values, searchValuesToSub: obj })),
|
||||||
|
|
||||||
|
setLoadingCase: (loadingCase) => set({ loadingCase }),
|
||||||
|
setCaseFeatured: (caseFeatured) => set({ caseFeatured }),
|
||||||
|
setCaseSummary: (caseSummary) => set({ caseSummary }),
|
||||||
|
setCaseSummaryByGuide: (caseSummaryByGuide) => set({ caseSummaryByGuide }),
|
||||||
|
|
||||||
|
async getCaseReport(params) {
|
||||||
|
const { setLoading, searchValues } = get();
|
||||||
|
setLoading(true);
|
||||||
|
const [summary, guideSummary, featured] = await Promise.all([
|
||||||
|
fetchCaseSummary(params),
|
||||||
|
fetchCaseSummaryByGuide(params),
|
||||||
|
fetchCaseFeatured(params)
|
||||||
|
]);
|
||||||
|
set({
|
||||||
|
caseSummary: summary,
|
||||||
|
caseSummaryByGuide: guideSummary,
|
||||||
|
caseFeatured: featured,
|
||||||
|
forExport: { title: `${moment(params.Date1).format('YYYY年MM月')}-${moment(params.Date2).format('YYYY年MM月')}总结`, agencyName: searchValues.agency.label },
|
||||||
|
});
|
||||||
|
setLoading(false);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
{ name: 'hostCaseReportStore' }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
export default useHostCaseStore;
|
||||||
Loading…
Reference in New Issue