| | |
| | | /** |
| | | * 报销单附件文件名规范校验(2026-10-15) |
| | | * 报销单附件文件名规范校验(2026-11-03 调整) |
| | | * |
| | | * 业务口径(业务方确认): |
| | | * 1. 必须包含中文(至少 1 个汉字)——"为方便查验附件,请用中文规范命名附件!" |
| | | * 2. 去掉扩展名后的主干,按字符数计算不能超过 20 个字——"为方便查验附件,附件名字长度不能超过20个字!" |
| | | * 业务口径: |
| | | * 1. 允许文件名不含中文;含中文/纯英文/数字均可 |
| | | * 2. 去掉扩展名后的主干,按字符数计算不能超过 20 个字 |
| | | * 3. 不能包含空格及 / \ : * ? " < > | # % 等特殊字符 |
| | | * 4. 同一明细行内不能重名(比较时忽略扩展名大小写与首尾空格) |
| | | * 5. 只校验新上传/新保存的附件;历史附件由后端按 existingNames 放行 |
| | | * |
| | | * 使用场景: |
| | | * - 上传成功回调:不合格 → 弹提示且不加入列表; |
| | |
| | | /** 主干(去扩展名)最大字符数 */ |
| | | export const MAX_MAIN_LENGTH = 20; |
| | | |
| | | /** 汉字 */ |
| | | const RE_CHINESE = /[\u4e00-\u9fa5]/; |
| | | |
| | | /** 非法字符:空格(含各类空白)+ / \ : * ? " < > | # % */ |
| | | const RE_ILLEGAL = /[\s/\\:*?"<>|#%]/; |
| | | |
| | | export const MSG_NO_CHINESE = "为方便查验附件,请用中文规范命名附件!"; |
| | | export const MSG_EMPTY_NAME = "为方便查验附件,附件名不能为空!"; |
| | | export const MSG_TOO_LONG = "为方便查验附件,附件名字长度不能超过20个字!"; |
| | | export const MSG_ILLEGAL = '为方便查验附件,附件名不能包含空格及 / \\ : * ? " < > | # % 等特殊字符!'; |
| | | export const MSG_DUPLICATE = "为方便查验附件,同一行内不能有重名的附件!"; |
| | |
| | | export function checkFileName(fileName) { |
| | | const name = (fileName || "").trim(); |
| | | if (!name) { |
| | | return { ok: false, msg: MSG_NO_CHINESE, main: "" }; |
| | | return { ok: false, msg: MSG_EMPTY_NAME, main: "" }; |
| | | } |
| | | if (RE_ILLEGAL.test(name)) { |
| | | return { ok: false, msg: MSG_ILLEGAL, main: mainName(name) }; |
| | | } |
| | | const main = mainName(name); |
| | | if (!RE_CHINESE.test(main)) { |
| | | return { ok: false, msg: MSG_NO_CHINESE, main }; |
| | | } |
| | | // 不再强制要求中文;含中文、纯英文、数字均可 |
| | | // 按字符数计(用扩展运算符按码点计数,中文/字母/数字/全角各计 1) |
| | | if ([...main].length > MAX_MAIN_LENGTH) { |
| | | return { ok: false, msg: MSG_TOO_LONG, main }; |