优化报表导出功能
This commit is contained in:
parent
f4c768df29
commit
398fca9265
Binary file not shown.
270
src/sql.ts
270
src/sql.ts
@ -2,6 +2,7 @@
|
|||||||
import { addNumbers, roundTo, toDecimal } from '@/lib/decimal'
|
import { addNumbers, roundTo, toDecimal } from '@/lib/decimal'
|
||||||
import { formatThousands } from '@/lib/numberFormat'
|
import { formatThousands } from '@/lib/numberFormat'
|
||||||
import ExcelJS from "ExcelJS";
|
import ExcelJS from "ExcelJS";
|
||||||
|
import { number } from 'motion-v/es';
|
||||||
// 统一数字千分位格式化,默认保留 2 位小数。
|
// 统一数字千分位格式化,默认保留 2 位小数。
|
||||||
const numberFormatter = (value: unknown, fractionDigits = 2) =>
|
const numberFormatter = (value: unknown, fractionDigits = 2) =>
|
||||||
formatThousands(value, fractionDigits)
|
formatThousands(value, fractionDigits)
|
||||||
@ -151,8 +152,7 @@ export const expertList = {
|
|||||||
7: { code: 'C9-3-2', name: '一级造价工程师且具备高级工程师资格', maxPrice: 2000, minPrice: 1800, defPrice: 1900, manageCoe: 2.05 },
|
7: { code: 'C9-3-2', name: '一级造价工程师且具备高级工程师资格', maxPrice: 2000, minPrice: 1800, defPrice: 1900, manageCoe: 2.05 },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const additionalWorkList
|
export const additionalWorkList = ['人员驻场服务及其他附加工作', '咨询服务协调工作'];
|
||||||
=['人员驻场服务及其他附加工作','咨询服务协调工作']
|
|
||||||
|
|
||||||
let costScaleCal = [
|
let costScaleCal = [
|
||||||
{ code: 'C1-1', staLine: 0, endLine: 100, basic: { staPrice: 0, rate: 0.01 }, optional: { staPrice: 0, rate: 0.002 } },
|
{ code: 'C1-1', staLine: 0, endLine: 100, basic: { staPrice: 0, rate: 0.01 }, optional: { staPrice: 0, rate: 0.002 } },
|
||||||
@ -552,182 +552,7 @@ export async function exportFile(fileName: string, data: any): Promise<void> {
|
|||||||
// 按模板生成最终工作簿:填充封面、目录、各分表及汇总数据。
|
// 按模板生成最终工作簿:填充封面、目录、各分表及汇总数据。
|
||||||
async function generateTemplate(data) {
|
async function generateTemplate(data) {
|
||||||
// const downTextTmp = { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: '常规' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: '下标' }] };
|
// const downTextTmp = { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: '常规' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: '下标' }] };
|
||||||
|
console.log(data)
|
||||||
data.contracts[0].addtional = {// 附加工作费
|
|
||||||
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'C' }] },
|
|
||||||
name: '附加工作',
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'F' }] },
|
|
||||||
name: '人员驻场服务及其他附加工作',
|
|
||||||
fee: 10000,
|
|
||||||
m4: {
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
expert: 0,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expert: 1,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
m5: {//数量单价
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'X' }] },
|
|
||||||
name: '咨询服务协调工作',
|
|
||||||
fee: 10000,
|
|
||||||
m0: { //费率计取
|
|
||||||
|
|
||||||
coe: 0.03,//费率
|
|
||||||
fee: 10000,
|
|
||||||
},
|
|
||||||
m4: { //工时法
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
expert: 0,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expert: 1,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
m5: {
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
};
|
|
||||||
data.contracts[0].reserve = {// 预备费
|
|
||||||
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'Y' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'B' }] },
|
|
||||||
name: '预备费',
|
|
||||||
fee: 10000,
|
|
||||||
m0: {
|
|
||||||
coe: 0.03,
|
|
||||||
fee: 10000,
|
|
||||||
},
|
|
||||||
m4: {
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
expert: 0,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expert: 1,
|
|
||||||
price: 100000,
|
|
||||||
person_num: 10,
|
|
||||||
work_day: 3,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
m5: {
|
|
||||||
fee: 10000,
|
|
||||||
det: [
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '×××项',
|
|
||||||
unit: '项',
|
|
||||||
amount: 10,
|
|
||||||
price: 100000,
|
|
||||||
fee: 100000,
|
|
||||||
remark: '',// 用户输入的说明
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
};
|
|
||||||
data.contracts[1].addtional = null;
|
|
||||||
data.contracts[1].reserve = null;
|
|
||||||
data.contracts[2].addtional = null;
|
|
||||||
data.contracts[2].reserve = null;
|
|
||||||
data.contracts[3].addtional = null;
|
|
||||||
data.contracts[3].reserve = null;
|
|
||||||
data.contracts[4].addtional = null;
|
|
||||||
data.contracts[4].reserve = null;
|
|
||||||
// data.contracts[5].addtional = null;
|
|
||||||
// data.contracts[5].reserve = null;
|
|
||||||
try {
|
try {
|
||||||
// 获取模板
|
// 获取模板
|
||||||
let templateExcel = 'template20260226001test010';
|
let templateExcel = 'template20260226001test010';
|
||||||
@ -1780,7 +1605,7 @@ async function generateTemplate(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let num_f01 = 1;
|
let num_f01 = 1;
|
||||||
Object.keys(allMajors).sort((a, b) => majorList[a].order - majorList[b].order).forEach(majorid => {
|
Object.keys(allMajors).sort((a, b) => (a < 0 ? a : majorList[a].order) - (b < 0 ? b : majorList[b].order)).forEach(majorid => {
|
||||||
let scaleX = allMajors[majorid];
|
let scaleX = allMajors[majorid];
|
||||||
let code;
|
let code;
|
||||||
let name;
|
let name;
|
||||||
@ -1843,7 +1668,7 @@ async function generateTemplate(data) {
|
|||||||
});
|
});
|
||||||
f01_sheet.spliceRows(3, 1);
|
f01_sheet.spliceRows(3, 1);
|
||||||
// f01_sheet.getRow(2).height = 27;
|
// f01_sheet.getRow(2).height = 27;
|
||||||
f01_sheet.orderNo = ml_number + 2 + 11;
|
f01_sheet.orderNo = ml_number + 2 + 12;
|
||||||
} else {
|
} else {
|
||||||
workbook.removeWorksheet('辅01表');
|
workbook.removeWorksheet('辅01表');
|
||||||
}
|
}
|
||||||
@ -1864,14 +1689,14 @@ async function generateTemplate(data) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
f02_sheet.spliceRows(2, 1);
|
f02_sheet.spliceRows(2, 1);
|
||||||
f02_sheet.orderNo = ml_number + 3 + 11;
|
f02_sheet.orderNo = ml_number + 3 + 12;
|
||||||
} else {
|
} else {
|
||||||
workbook.removeWorksheet('辅02表');
|
workbook.removeWorksheet('辅02表');
|
||||||
}
|
}
|
||||||
if (data.majorCoes?.length) {
|
if (data.majorCoes?.length) {
|
||||||
let f03_sheet = workbook.getWorksheet('辅03表');
|
let f03_sheet = workbook.getWorksheet('辅03表');
|
||||||
let num_f03 = 1;
|
let num_f03 = 1;
|
||||||
data.majorCoes.sort((a, b) => majorList[a.majorid].order - majorList[b.majorid].order).forEach(mcoei => {
|
data.majorCoes.sort((a, b) => (a < 0 ? a : majorList[a.majorid].order) - (b < 0 ? b : majorList[b.majorid].order)).forEach(mcoei => {
|
||||||
let majorCoeX = majorList[mcoei.majorid];
|
let majorCoeX = majorList[mcoei.majorid];
|
||||||
cusInsertRowFunc(2 + num_f03, [f03_sheet.getRow(2)], f03_sheet, (targetRow) => {
|
cusInsertRowFunc(2 + num_f03, [f03_sheet.getRow(2)], f03_sheet, (targetRow) => {
|
||||||
targetRow.getCell(1).value = num_f03++;
|
targetRow.getCell(1).value = num_f03++;
|
||||||
@ -1883,7 +1708,7 @@ async function generateTemplate(data) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
f03_sheet.spliceRows(2, 1);
|
f03_sheet.spliceRows(2, 1);
|
||||||
f03_sheet.orderNo = ml_number + 4 + 11;
|
f03_sheet.orderNo = ml_number + 4 + 12;
|
||||||
} else {
|
} else {
|
||||||
workbook.removeWorksheet('辅03表');
|
workbook.removeWorksheet('辅03表');
|
||||||
}
|
}
|
||||||
@ -1898,6 +1723,85 @@ async function generateTemplate(data) {
|
|||||||
|
|
||||||
window.workbook = workbook;
|
window.workbook = workbook;
|
||||||
|
|
||||||
|
// 更新编制说明
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
// ctx.font = "12pt 宋体";
|
||||||
|
// const maxTitleWidth = 336;
|
||||||
|
// const maxTextWidth = 720;
|
||||||
|
const pageMaxHei = 733;
|
||||||
|
// 20.25 25.5 33.75
|
||||||
|
const titleHeiDet = { fir: 11.25, els: 22.5 };
|
||||||
|
const textHeiDet = { fir: 6.75, els: 13.5 };
|
||||||
|
|
||||||
|
const descSheet = workbook.getWorksheet('编制说明');
|
||||||
|
descSheet.getRow(1).getCell(1).value = data.name;
|
||||||
|
let descRowNum = 5;
|
||||||
|
if (data.scale?.length) {
|
||||||
|
let engCosts = data.scale.filter(f => f.major > 6 && majorList[f.major].hasCost);
|
||||||
|
if (engCosts.length) {
|
||||||
|
descRowNum++;
|
||||||
|
let copyRowNum = descRowNum;
|
||||||
|
engCosts.forEach((sci, scindex) => {
|
||||||
|
descRowNum++;
|
||||||
|
cusInsertRowFunc(descRowNum, [descSheet.getRow(copyRowNum)], descSheet, (targetRow) => {
|
||||||
|
targetRow.getCell(1).value = ` ${scindex + 1}.${majorList[sci.major].name}${Number(sci.cost).toLocaleString()}万元${scindex == engCosts.length - 1 ? '。' : ';'}`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
descSheet.spliceRows(copyRowNum, 1);
|
||||||
|
} else {
|
||||||
|
descSheet.spliceRows(descRowNum, 2);
|
||||||
|
descSheet.getRow(descRowNum).getCell(1).value = ' (二)本项目征地拆迁费包括:';
|
||||||
|
descSheet.getRow(descRowNum + 2).getCell(1).value = ' (三)其他费用包括:';
|
||||||
|
}
|
||||||
|
let zcScales = data.scale.filter(f => [1, 2, 3].includes(f.major));
|
||||||
|
if (zcScales.length) {
|
||||||
|
descRowNum++;
|
||||||
|
let copyRowNum = descRowNum;
|
||||||
|
zcScales.forEach((sci, scindex) => {
|
||||||
|
descRowNum++;
|
||||||
|
cusInsertRowFunc(descRowNum, [descSheet.getRow(copyRowNum)], descSheet, (targetRow) => {
|
||||||
|
switch (sci.major) {
|
||||||
|
case 1:
|
||||||
|
let desc1 = [];
|
||||||
|
if (sci.area) desc1.push(`征地总面积约${Number(sci.area).toLocaleString()}亩`);
|
||||||
|
if (sci.cost) desc1.push(`征地补偿费用${Number(sci.cost).toLocaleString()}万元`);
|
||||||
|
targetRow.getCell(1).value = ` ${scindex + 1}.征地情况:${desc1.join(',')}。`;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
let desc2 = [];
|
||||||
|
if (sci.area) desc2.push(`拆迁总面积约${Number(sci.area).toLocaleString()}亩`);
|
||||||
|
if (sci.cost) desc2.push(`拆迁补偿费用${Number(sci.cost).toLocaleString()}万元`);
|
||||||
|
targetRow.getCell(1).value = ` ${scindex + 1}.拆迁补偿情况:${desc2.join(',')}。`;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
targetRow.getCell(1).value = ` ${scindex + 1}.迁改工程情况:费用${Number(sci.cost).toLocaleString()}万元。`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
descSheet.spliceRows(copyRowNum, 1);
|
||||||
|
} else {
|
||||||
|
descSheet.spliceRows(descRowNum, 2);
|
||||||
|
descSheet.getRow(descRowNum).getCell(1).value = engCosts.length ? ' (三)其他费用包括:' : ' (二)其他费用包括:';
|
||||||
|
}
|
||||||
|
let otherCosts = data.scale.filter(f => [4, 5, 6].includes(f.major));
|
||||||
|
if (otherCosts.length) {
|
||||||
|
let desc = [];
|
||||||
|
otherCosts.forEach(sci => {
|
||||||
|
desc.push(`${majorList[sci.major].name}${Number(sci.cost).toLocaleString()}万元`);
|
||||||
|
});
|
||||||
|
descSheet.getRow(descRowNum).getCell(1).value = descSheet.getRow(descRowNum).getCell(1).value + `${desc.join(',')}。`;
|
||||||
|
descRowNum++;
|
||||||
|
} else {
|
||||||
|
descSheet.spliceRows(descRowNum, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
descSheet.spliceRows(descRowNum, 5);
|
||||||
|
descRowNum++;
|
||||||
|
}
|
||||||
|
console.log(descRowNum);
|
||||||
|
|
||||||
return workbook;
|
return workbook;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user