style(cargo-type): 美化货物类型导入模板Excel样式及失败明细
- 表头底色调整为统一灰色 #D9D9D9,字体改为黑色加粗 - 表头行高从42调整为30,增加视觉紧凑感 - 表头与数据区统一添加细边框,居中对齐并自动换行 - 编码列保持文本格式,防止格式识别错误 - 导入失败明细中「导入失败原因」列字体设置为红色 - 失败原因按 A./B./C. 格式编号,使用分号分隔 - 去除后端重复的「第N行:」前缀,避免冗余信息 - 通过 Node + exceljs 验证样式和格式变更正确生效
This commit is contained in:
@@ -2,5 +2,7 @@
|
||||
|
||||
## 货物类型导入模板美化
|
||||
- 文件:`src/views/base/cargo-type.vue` 的 `handleTemplate()`
|
||||
- 改动:表头行加主色底色 `#409EFF`(argb `FF409EFF`)+ 白色加粗字体 + 居中对齐 + 自动换行;表头与数据区统一加细边框(`FFD0D7E2`);表头行高设为 42;编码列保持文本格式(`numFmt='@'`)。
|
||||
- 验证:Node + exceljs 4.4.0 跑通生成逻辑,确认表头 fill/font/alignment/border 与行高正确。
|
||||
- 改动(第一次):表头行加主色底色 `#409EFF` + 白色加粗字体 + 居中对齐 + 细边框;行高 42。
|
||||
- 改动(调整后):按用户反馈,表头底色改为统一灰色 `#D9D9D9` + 黑色加粗字体,行高降为 30。
|
||||
- 导入失败明细 `decorateCargoTypeFailDetail` 调整:仅「导入失败原因」列字体红色;错误按 `A./B./C.` 编号,分号(;)隔开,并去掉后端重复的「第N行:」前缀;最终格式示例 `第2行:A.该货物类型编码已存在,请更换唯一编码`。
|
||||
- 验证:Node + exceljs 4.4.0 跑通生成逻辑,确认表头 fill/font/alignment/height、失败原因编号格式与红色字体均正确。
|
||||
|
||||
@@ -183,9 +183,9 @@ const CARGO_TYPE_FAIL_COL_WIDTH = {
|
||||
|
||||
/**
|
||||
* 加工后端返回的导入失败明细 Excel:
|
||||
* - 将「导入失败原因」列改写为(第N行:错误,规则)格式,便于定位
|
||||
* - 「导入失败原因」列按 A. B. C. 编号列出,多条以分号隔开
|
||||
* - 每个错误后追加对应规则说明,仅失败原因列标红
|
||||
* - 适当加宽各列、原因列自动换行,避免内容拥挤
|
||||
* 不再对单元格标红,仅通过文字清晰说明错误
|
||||
*/
|
||||
export const decorateCargoTypeFailDetail = async workbook => {
|
||||
const ws = workbook.worksheets[0];
|
||||
@@ -200,19 +200,32 @@ export const decorateCargoTypeFailDetail = async workbook => {
|
||||
if (!reasonCol) return;
|
||||
ws.eachRow((row, rowNumber) => {
|
||||
if (rowNumber === 1) return; // 跳过表头
|
||||
const reasonCell = row.getCell(reasonCol);
|
||||
const raw = String(reasonCell.value == null ? '' : reasonCell.value).trim();
|
||||
if (!raw) return;
|
||||
const parts = raw.split(/[;;\n\r]+/).map(s => s.trim()).filter(Boolean);
|
||||
if (parts.length === 0) return;
|
||||
const decorated = parts.map(part => {
|
||||
const rule = CARGO_TYPE_FAIL_RULES.find(r => part.includes(r.match));
|
||||
if (rule) {
|
||||
return `第${rowNumber}行:${part},${rule.rule}`;
|
||||
// 仅「导入失败原因」列允许红色,其他列红色字体统一清除
|
||||
row.eachCell((cell, colNumber) => {
|
||||
if (colNumber === reasonCol) return;
|
||||
if (cell.font && cell.font.color) {
|
||||
const font = { ...cell.font };
|
||||
delete font.color;
|
||||
cell.font = font;
|
||||
}
|
||||
return `第${rowNumber}行:${part}`;
|
||||
});
|
||||
reasonCell.value = decorated.join(';');
|
||||
const reasonCell = row.getCell(reasonCol);
|
||||
let raw = String(reasonCell.value == null ? '' : reasonCell.value).trim();
|
||||
if (!raw) return;
|
||||
// 去掉后端可能已经存在的「第N行:」前缀,避免重复
|
||||
raw = raw.replace(/^第\s*\d+\s*行[::]\s*/, '');
|
||||
const parts = raw
|
||||
.split(/[;;\n\r]+/)
|
||||
.map(s => s.trim().replace(/^第\s*\d+\s*行[::]\s*/, ''))
|
||||
.filter(Boolean);
|
||||
if (parts.length === 0) return;
|
||||
const decorated = parts.map((part, index) => {
|
||||
const label = `${String.fromCharCode(65 + index)}.`; // A. B. C.
|
||||
const rule = CARGO_TYPE_FAIL_RULES.find(r => part.includes(r.match));
|
||||
return rule ? `${label}${part},${rule.rule}` : `${label}${part}`;
|
||||
});
|
||||
reasonCell.value = `第${rowNumber}行:${decorated.join(';')}`;
|
||||
reasonCell.font = { color: { argb: 'FFFF0000' } };
|
||||
reasonCell.alignment = { wrapText: true, vertical: 'top' };
|
||||
});
|
||||
// 加宽各列(未列在映射中的列给默认宽度)
|
||||
@@ -585,11 +598,11 @@ export default {
|
||||
const col = ws.getColumn(idx);
|
||||
if (col) col.numFmt = '@';
|
||||
});
|
||||
// 表头与数据区样式美化:主色底色表头 + 白字加粗居中 + 细边框
|
||||
// 表头与数据区样式:统一灰色表头 + 黑色加粗居中 + 细边框
|
||||
const headerFill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FF409EFF' },
|
||||
fgColor: { argb: 'FFD9D9D9' },
|
||||
};
|
||||
const thinBorder = {
|
||||
top: { style: 'thin', color: { argb: 'FFD0D7E2' } },
|
||||
@@ -601,9 +614,9 @@ export default {
|
||||
row.eachCell(cell => {
|
||||
cell.border = thinBorder;
|
||||
if (row.number === 1) {
|
||||
// 表头:主色底色 + 白字加粗 + 居中对齐
|
||||
// 表头:灰色底色 + 黑字加粗 + 居中对齐
|
||||
cell.fill = headerFill;
|
||||
cell.font = { bold: true, color: { argb: 'FFFFFFFF' } };
|
||||
cell.font = { bold: true, color: { argb: 'FF000000' } };
|
||||
cell.alignment = {
|
||||
wrapText: true,
|
||||
vertical: 'middle',
|
||||
@@ -619,8 +632,8 @@ export default {
|
||||
}
|
||||
});
|
||||
});
|
||||
// 表头行高,确保长说明换行后完整显示
|
||||
ws.getRow(1).height = 42;
|
||||
// 表头行高适度,兼顾两行说明与视觉紧凑
|
||||
ws.getRow(1).height = 30;
|
||||
return wb.xlsx.writeBuffer();
|
||||
})
|
||||
.then(buf => {
|
||||
|
||||
Reference in New Issue
Block a user