docs: 计划 Task 7 片段的 BOM 改成转义写法
内联的零宽字符在编辑器里看不见也改不动,写文件时极易悄悄落成真字符——实现这个 Task 的过程中在源码、提交信息、记忆文件里各踩了一次。改成 JS 转义写法后源码可见。 片段同步为已提交的实现与测试版本:测试引入 BOM 常量,实现片段注释也对齐。 把文档里的两个片段抽出来覆盖真实文件实跑,2 个用例通过。
This commit is contained in:
parent
444c2ed1af
commit
8a61186cfd
|
|
@ -2006,18 +2006,22 @@ git commit -m "feat: 物料导入与模板下载接口"
|
||||||
import { describe, expect, test } from 'vitest'
|
import { describe, expect, test } from 'vitest'
|
||||||
import { buildCsv } from './exportCsv'
|
import { buildCsv } from './exportCsv'
|
||||||
|
|
||||||
|
// BOM 用转义写,不内联那个零宽字符:内联的话看不见也改不动,
|
||||||
|
// 一旦被编辑器或编码转换吃掉,测试就会以一个极难看懂的方式失败。
|
||||||
|
const BOM = '\uFEFF'
|
||||||
|
|
||||||
describe('buildCsv', () => {
|
describe('buildCsv', () => {
|
||||||
test('用逗号分隔并在行尾换行', () => {
|
test('用逗号分隔并在行尾换行', () => {
|
||||||
const csv = buildCsv([
|
const csv = buildCsv([
|
||||||
['行号', '失败原因'],
|
['行号', '失败原因'],
|
||||||
[3, '物料名称不能为空']
|
[3, '物料名称不能为空']
|
||||||
])
|
])
|
||||||
expect(csv).toBe('行号,失败原因\r\n3,物料名称不能为空\r\n')
|
expect(csv).toBe(BOM + '行号,失败原因\r\n3,物料名称不能为空\r\n')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('包含逗号、引号、换行的字段用双引号包裹并转义', () => {
|
test('包含逗号、引号、换行的字段用双引号包裹并转义', () => {
|
||||||
const csv = buildCsv([['规格', '备注'], ['M8,30', '含"引号"'], ['两\n行', '']])
|
const csv = buildCsv([['规格', '备注'], ['M8,30', '含"引号"'], ['两\n行', '']])
|
||||||
expect(csv).toBe('规格,备注\r\n"M8,30","含""引号"""\r\n"两\n行",\r\n')
|
expect(csv).toBe(BOM + '规格,备注\r\n"M8,30","含""引号"""\r\n"两\n行",\r\n')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
@ -2032,11 +2036,11 @@ Expected: FAIL(模块不存在)
|
||||||
创建 `frontend/src/utils/exportCsv.js`:
|
创建 `frontend/src/utils/exportCsv.js`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// 生成 CSV 文本。带 UTF-8 BOM,Excel 打开中文才不会乱码;字段里的
|
// 生成 CSV 文本。带 UTF-8 BOM(写成转义而不是内联零宽字符,源码里才看得见),
|
||||||
// 逗号、引号、换行按 RFC 4180 用双引号包裹并转义。
|
// Excel 打开中文才不会乱码;字段里的逗号、引号、换行按 RFC 4180 用双引号包裹并转义。
|
||||||
export function buildCsv(rows) {
|
export function buildCsv(rows) {
|
||||||
const lines = rows.map(row => row.map(escapeCsvCell).join(','))
|
const lines = rows.map(row => row.map(escapeCsvCell).join(','))
|
||||||
return '' + lines.map(line => line + '\r\n').join('')
|
return '\uFEFF' + lines.map(line => line + '\r\n').join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeCsvCell(value) {
|
function escapeCsvCell(value) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user