/** * 运营后台数据权限 / 员工负责线路 单一目录。 * * 来源:《询价智能体运营后台数据权限下拉选项.xlsx》(2026-09)。 * key = 写入 sys_role.description / inq_staff_role.routes 的稳定码; * title = 界面展示文案。 */ export type DataPermNode = { key: string; title: string; children?: DataPermNode[]; }; /** 空运具体线路(不含全线) */ export const AIR_ROUTE_ITEMS: { key: string; title: string }[] = [ { key: "CGO-KUL", title: "郑州-吉隆坡(CGO-KUL)" }, { key: "SZX-KUL", title: "深圳-吉隆坡(SZX-KUL)" }, { key: "HKG-KUL", title: "香港-吉隆坡(HKG-KUL)" }, { key: "NKG-KUL", title: "南京-吉隆坡(NKG-KUL)" }, { key: "HKG-DEL", title: "香港-新德里(HKG-DEL)" }, { key: "CGO-DEL", title: "郑州-新德里(CGO-DEL)" }, { key: "CGO-BLR", title: "郑州-班加罗尔(CGO-BLR)" }, { key: "CGO-MAA", title: "郑州-金奈(CGO-MAA)" }, { key: "CTU-MAA", title: "成都-金奈(CTU-MAA)" }, { key: "CKG-BOM", title: "重庆-孟买(CKG-BOM)" }, { key: "ZUH-CRK", title: "珠海-克拉克(ZUH-CRK)" }, { key: "SZX-CRK", title: "深圳-克拉克(SZX-CRK)" }, { key: "EHU-ORD", title: "鄂州-芝加哥(EHU-ORD)" }, { key: "WNZ-CGK", title: "温州-雅加达(WNZ-CGK)" }, { key: "国内-曼谷(BKK 外采)", title: "国内-曼谷(BKK 外采)" }, { key: "国外-国外(外采-空运)", title: "国外-国外(外采-空运)" }, { key: "其他线路和快递双清包税(外采-空运)", title: "其他线路和快递双清包税(外采-空运)" }, ]; export const LAND_ROUTE_ITEMS: { key: string; title: string }[] = [ { key: "中港/中亚/中欧", title: "中港/中亚/中欧" }, { key: "国内长途/零担", title: "国内长途/零担" }, { key: "国内城配/拖车/打包", title: "国内城配/拖车/打包" }, { key: "东南亚", title: "东南亚" }, ]; /** 角色弹窗数据权限树(父节点仅作分组,不写入 description;文案对齐旧后台「空运数据」) */ export const DATA_PERM_TREE: DataPermNode[] = [ { key: "group:air", title: "空运数据", children: [{ key: "空运全线", title: "空运全线" }, ...AIR_ROUTE_ITEMS], }, { key: "group:sea", title: "海运数据", children: [{ key: "海运全线", title: "海运全线" }], }, { key: "group:land", title: "陆运数据", children: [{ key: "陆运全线", title: "陆运全线" }, ...LAND_ROUTE_ITEMS], }, ]; /** 旧后台独立勾选项:系统异常消息通知(企微) */ export const SYSTEM_EXCEPTION_NOTIFY_KEY = "系统异常·消息通知"; export const SYSTEM_EXCEPTION_NOTIFY_TITLE = "系统异常消息通知(企微)"; /** 员工岗位 → 可选负责线路 key(与角色数据权限同源) */ export const ROUTES_BY_ROLE: Record<"air" | "sea" | "land", string[]> = { air: ["空运全线", ...AIR_ROUTE_ITEMS.map((x) => x.key)], sea: ["海运全线"], land: ["陆运全线", ...LAND_ROUTE_ITEMS.map((x) => x.key)], }; const TITLE_BY_KEY: Record = (() => { const m: Record = { 空运全线: "空运全线", 海运全线: "海运全线", 陆运全线: "陆运全线", [SYSTEM_EXCEPTION_NOTIFY_KEY]: SYSTEM_EXCEPTION_NOTIFY_TITLE, }; for (const x of AIR_ROUTE_ITEMS) m[x.key] = x.title; for (const x of LAND_ROUTE_ITEMS) m[x.key] = x.title; return m; })(); /** 已知稳定码集合(不含分组父节点) */ export const KNOWN_DATA_PERM_KEYS = new Set(Object.keys(TITLE_BY_KEY)); /** * 旧写法 → 新稳定码。 * 无法识别时返回 trim 后原文(可能仍展示,但不进勾选树)。 */ const ALIAS_TO_KEY: Record = { 空运全线: "空运全线", 空运全部线路: "空运全线", "空运·全部线路": "空运全线", "空运·全线": "空运全线", 全线: "空运全线", 海运全线: "海运全线", "海运·全部线路": "海运全线", "海运·海运全线": "海运全线", 陆运全线: "陆运全线", "陆运·全部线路": "陆运全线", "陆运·中港/中亚/中欧": "中港/中亚/中欧", "陆运·国内长途/零担": "国内长途/零担", "陆运·国内城配/拖车/打包": "国内城配/拖车/打包", "陆运·东南亚": "东南亚", BKK: "国内-曼谷(BKK 外采)", "外采-空运": "国外-国外(外采-空运)", [SYSTEM_EXCEPTION_NOTIFY_KEY]: SYSTEM_EXCEPTION_NOTIFY_KEY, 系统异常消息通知: SYSTEM_EXCEPTION_NOTIFY_KEY, "系统异常消息通知(企微)": SYSTEM_EXCEPTION_NOTIFY_KEY, }; for (const item of AIR_ROUTE_ITEMS) { ALIAS_TO_KEY[item.key] = item.key; ALIAS_TO_KEY[item.title] = item.key; ALIAS_TO_KEY[`空运·${item.key}`] = item.key; } for (const item of LAND_ROUTE_ITEMS) { ALIAS_TO_KEY[item.key] = item.key; ALIAS_TO_KEY[`陆运·${item.key}`] = item.key; } export function normalizeDataPermKey(raw: string): string { const s = String(raw || "").trim(); if (!s) return ""; if (ALIAS_TO_KEY[s]) return ALIAS_TO_KEY[s]; // 空运·XXX / 陆运·XXX 兜底剥前缀 const m = s.match(/^(?:空运|海运|陆运)[·•](.+)$/); if (m) { const inner = m[1].trim(); if (ALIAS_TO_KEY[inner]) return ALIAS_TO_KEY[inner]; if (inner === "全部线路" || inner === "全线") { if (s.startsWith("空运")) return "空运全线"; if (s.startsWith("海运")) return "海运全线"; if (s.startsWith("陆运")) return "陆运全线"; } if (KNOWN_DATA_PERM_KEYS.has(inner)) return inner; } return s; } /** 批量归一;去重保序;只保留已知码(角色勾选回显用) */ export function normalizeDataPermKeys(rawList: string[]): string[] { const out: string[] = []; const seen = new Set(); for (const raw of rawList || []) { const k = normalizeDataPermKey(raw); if (!k || !KNOWN_DATA_PERM_KEYS.has(k) || seen.has(k)) continue; seen.add(k); out.push(k); } return out; } /** 员工 routes:归一后保留已知码;未知旧值也保留以免丢数据 */ export function normalizeStaffRouteKeys(rawList: string[]): string[] { const out: string[] = []; const seen = new Set(); for (const raw of rawList || []) { const k = normalizeDataPermKey(raw); if (!k || seen.has(k)) continue; seen.add(k); out.push(k); } return out; } export function dataPermTitle(key: string): string { const k = normalizeDataPermKey(key); return TITLE_BY_KEY[k] || key; } /** Ant Design Tree 用:过滤掉分组父 key,只交叶子 */ export function leafDataPermKeys(checked: string[]): string[] { return (checked || []).filter((k) => KNOWN_DATA_PERM_KEYS.has(k)); }