forked from ChaiHao/BPOS-MVP
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
71 lines
3.5 KiB
TypeScript
71 lines
3.5 KiB
TypeScript
/**
|
|
* 网页标签的名与章 —— 三面各有一套,多标签并开时一眼可辨「我在定义、在监控、还是在干活」。
|
|
*
|
|
* 章随台面的**皮肤基调**走,不另造视觉:
|
|
* 工作台 = 品牌蓝渐变圆角方 + 白色机器人(与左轨品牌章、登录页方章同源);
|
|
* 设计中心 = 深靛底 + 路网(定义企业的流转 —— 与流程包区的靛色同源);
|
|
* 运营中心 = 深色底 + 仪表(看企业今天跑得怎样 —— 驾驶舱的那支指针)。
|
|
* SVG 以 data: URI 内联 —— 不添静态资产,构建零配置。
|
|
*/
|
|
|
|
const DESK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
|
<stop offset="0" stop-color="#3d7bff"/><stop offset="1" stop-color="#2454d6"/>
|
|
</linearGradient></defs>
|
|
<rect width="32" height="32" rx="8" fill="url(#g)"/>
|
|
<g transform="translate(4,5)">
|
|
<circle cx="12" cy="1.5" r="1.3" fill="#fff"/>
|
|
<rect x="11.4" y="2.3" width="1.2" height="2.2" rx="0.6" fill="#fff"/>
|
|
<rect x="3.6" y="4.6" width="16.8" height="13" rx="4.6" fill="#fff"/>
|
|
<rect x="1.2" y="8.8" width="2.2" height="4.8" rx="1.1" fill="#fff"/>
|
|
<rect x="20.6" y="8.8" width="2.2" height="4.8" rx="1.1" fill="#fff"/>
|
|
<circle cx="9.2" cy="10.4" r="1.9" fill="#2454d6"/>
|
|
<circle cx="14.8" cy="10.4" r="1.9" fill="#2454d6"/>
|
|
<path d="M9.3 13.8c.7.9 1.7 1.35 2.7 1.35s2-.45 2.7-1.35" stroke="#2454d6" stroke-width="1.3" fill="none" stroke-linecap="round" opacity="0.55"/>
|
|
</g>
|
|
</svg>`;
|
|
|
|
/** 设计中心:深靛底 + 路网 —— 线接着点,正是「连线即映射」 */
|
|
const DESIGN_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
<rect width="32" height="32" rx="8" fill="#232b6e"/>
|
|
<g transform="translate(4,4)" fill="none" stroke="#9db1ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15" stroke="#fff"/>
|
|
<circle cx="6" cy="19" r="2.6" fill="#232b6e"/>
|
|
<circle cx="18" cy="5" r="2.6" fill="#232b6e"/>
|
|
</g>
|
|
</svg>`;
|
|
|
|
/** 运营中心:深色底 + 仪表 —— 指针指着「今天跑得怎样」 */
|
|
const OPS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
<rect width="32" height="32" rx="8" fill="#141b2e"/>
|
|
<g transform="translate(4,5)" fill="none" stroke="#5fdcb4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M3.34 18a10 10 0 1 1 17.32 0"/>
|
|
<path d="m12 13 4.2-4.2" stroke="#fff"/>
|
|
<circle cx="12" cy="18" r="1.6" fill="#fff" stroke="none"/>
|
|
</g>
|
|
</svg>`;
|
|
|
|
/** 三面各一套章名 —— `desk` 是工作台,另两个是治理的两个台面 */
|
|
export type TabSurface = 'desk' | 'design' | 'ops';
|
|
|
|
const IDENTITY: Readonly<Record<TabSurface, { title: string; icon: string }>> = {
|
|
desk: { title: 'JCAI 工作台', icon: DESK_ICON },
|
|
design: { title: 'JCAI 设计中心', icon: DESIGN_ICON },
|
|
ops: { title: 'JCAI 运营中心', icon: OPS_ICON },
|
|
};
|
|
|
|
/** 进哪面就挂哪套 —— 登录页也按 URL 归面,标签在登录前就叫对名字 */
|
|
export function applyTabIdentity(surface: TabSurface): void {
|
|
const { title, icon } = IDENTITY[surface];
|
|
document.title = title;
|
|
|
|
let link = document.querySelector<HTMLLinkElement>('link[rel="icon"]');
|
|
if (link === null) {
|
|
link = document.createElement('link');
|
|
link.rel = 'icon';
|
|
document.head.appendChild(link);
|
|
}
|
|
link.type = 'image/svg+xml';
|
|
link.href = 'data:image/svg+xml;utf8,' + encodeURIComponent(icon);
|
|
}
|