| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /**
- * 工作台菜单图标解析:取菜单名称关键字 + 自动配色。
- *
- * 规则:
- * 1. 先按 KEYWORD_RULES 的关键字匹配(specific 在前、generic 在后,顺序不能乱);
- * 2. 没命中时去掉通用后缀(申请/工单/管理等)取首字,保证后续新增菜单无需改前端就能有图标;
- * 3. 颜色:命中规则用规则色;兜底按名称哈希从色板取色,同一个菜单名永远同一个颜色。
- */
- // 已知菜单的关键字与颜色(顺序敏感:如「离职交接单」要先于「离职」、「补卡」要先于「打卡」)
- const KEYWORD_RULES = [
- { keywords: ["工资", "薪资", "薪酬"], char: "薪", color: "#f59a23" },
- { keywords: ["档案"], char: "档", color: "#9270ca" },
- { keywords: ["交接"], char: "交", color: "#4b7902" },
- { keywords: ["离职"], char: "离", color: "#ee7a6e" },
- { keywords: ["调岗", "异动"], char: "岗", color: "#7262fd" },
- { keywords: ["转正"], char: "正", color: "#269a99" },
- { keywords: ["入职"], char: "入", color: "#07a44d" },
- { keywords: ["请假"], char: "假", color: "#6e7bf2" },
- { keywords: ["补卡"], char: "卡", color: "#4fa8ee" },
- { keywords: ["打卡"], char: "打", color: "#157a2c" },
- { keywords: ["排班"], char: "调", color: "#8f7bf0" },
- { keywords: ["加班"], char: "班", color: "#4fc08d" },
- { keywords: ["外勤", "外出"], char: "外", color: "#93a0b4" },
- { keywords: ["出差"], char: "差", color: "#f2b63c" },
- { keywords: ["考勤"], char: "勤", color: "#157a2c" },
- { keywords: ["质检"], char: "质", color: "#269a99" },
- { keywords: ["不合格"], char: "不", color: "#ee7a6e" },
- { keywords: ["申请"], char: "申", color: "#157a2c" },
- { keywords: ["审批", "待办"], char: "批", color: "#f59a23" },
- ];
- // 兜底取字时依次去掉的通用后缀(循环去,直到不再变化)
- const STRIP_SUFFIXES = ["申请", "办理", "管理", "记录", "审批", "工单", "清单", "列表", "单"];
- // 兜底配色板:新菜单哈希取色,视觉上与主题绿协调
- const PALETTE = [
- "#157a2c", "#2699a9", "#9270ca", "#61cdbb",
- "#f2b63c", "#6e7bf2", "#ee7a6e", "#4b7902",
- ];
- export function hexToRgba(hex, alpha) {
- const value = String(hex || "").replace("#", "");
- if (value.length !== 6) return hex;
- const r = parseInt(value.slice(0, 2), 16);
- const g = parseInt(value.slice(2, 4), 16);
- const b = parseInt(value.slice(4, 6), 16);
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
- }
- export function stripMenuSuffixes(name) {
- let result = String(name || "").trim();
- let changed = true;
- while (changed && result.length > 1) {
- changed = false;
- for (const suffix of STRIP_SUFFIXES) {
- if (result.length > suffix.length && result.endsWith(suffix)) {
- result = result.slice(0, -suffix.length);
- changed = true;
- }
- }
- }
- return result;
- }
- function hashName(name) {
- const text = String(name || "");
- let hash = 0;
- for (let i = 0; i < text.length; i += 1) {
- hash = (hash * 31 + text.charCodeAt(i)) >>> 0;
- }
- return hash;
- }
- /**
- * @param {string} name 菜单名称(如「离职交接单」「保养工单」)
- * @returns {{ char: string, color: string, bg: string }}
- */
- export function resolveMenuIcon(name) {
- const text = String(name || "").trim();
- if (!text) return { char: "·", color: "#93a0b4", bg: hexToRgba("#93a0b4", 0.14) };
- for (const rule of KEYWORD_RULES) {
- if (rule.keywords.some((k) => text.indexOf(k) >= 0)) {
- return { char: rule.char, color: rule.color, bg: hexToRgba(rule.color, 0.14) };
- }
- }
- // 兜底:去通用后缀取首字(维修工单→维、保养工单→保、备品备件申请单→备)
- const stem = stripMenuSuffixes(text);
- const char = (stem || text).charAt(0);
- const color = PALETTE[hashName(text) % PALETTE.length];
- return { char, color, bg: hexToRgba(color, 0.14) };
- }
|