Files
Blizzard 7c67256f87
CI / Go · build + vet + test (pull_request) Failing after 30m3s
CI / Frontend · tsc (sundynix-admin) (pull_request) Failing after 9m42s
CI / Frontend · tsc (sundynix-desktop/frontend) (pull_request) Failing after 16m53s
CI / Frontend · tsc (sundynix-web) (pull_request) Has been cancelled
CI / mcp-py · sandbox guard (pull_request) Has been cancelled
feat(web): 薄 Web 面 sundynix-web —— 注册/组织/团队/账单自助入口
SaaS P3 收口第二刀(设计见 SAAS_DESIGN.md §8)。第三个产品面:desktop=用户
工作产品、admin=平台超管控制塔、web=租户客户的自助柜台——做「装桌面端之前
就要能用」的那些事,三者不合并。

- 骨架抄 admin(HashRouter+路由注册表+me()/sdx:logout 鉴权门+vite/vitest
  单文件配置);UI 整目录搬 desktop 的 ui/ 组件+ink/brand 主题 token(亮暗
  双主题),品牌观感与桌面端一致;api.ts 抄 desktop 的 auth/tenant/usage 段
  (纯 fetch 零 Wails 依赖),成员管理/建组织打新的租户自助接口。
- 页面:登录注册(一页两态)/概览(组织+角色+余额+桌面端下载指引)/团队(名册+
  邀请+改角色+移除,写控件按角色显隐、真闸在后端)/组织(列表+自助新建+切换)/
  用量与账单(余额 hero+趋势+合计+最近消耗,数据全来自现成 /me/usage;充值
  只放说明占位,支付 P5 再接,不做假入口)。
- 工程:vite :5175、launch.json 配置、make webface、ci.yml web 矩阵纳入。
- 测试:tsc 干净;vitest 3 例(fmtCredits 去尾零——测试先行抓出 1.50 毛刺;
  ASSIGNABLE_ROLES 不含 owner)。浏览器 live 全流程:甲(owner)登录→概览→
  团队邀请乙→乙(member)登录写控件全隐藏、名册只读,组织/用量页真数据渲染。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:47:23 +08:00

123 lines
3.2 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 主题令牌::root=亮色,.dark=暗色。值为 RGB 三元组,供 tailwind 的 rgb(var() / α) 取用。
亮色走 shadcn 中性灰(zinc),暗色为精炼中性暗(zinc 系,替代原偏蓝的 ink)。 */
:root {
--ink-950: 249 249 250; /* 页面底 */
--ink-900: 255 255 255; /* 顶栏/面板 */
--ink-850: 255 255 255; /* 卡片 */
--ink-800: 244 244 245; /* hover/抬升 */
--ink-700: 228 228 231;
--ink-600: 212 212 216;
--line: 228 228 231; /* 边框 zinc-200 */
--slate-100: 24 24 27; /* 最强文字 */
--slate-200: 24 24 27; /* 主文字 */
--slate-300: 63 63 70;
--slate-400: 82 82 91;
--slate-500: 113 113 122; /* 次要 */
--slate-600: 161 161 170; /* 弱 */
--slate-700: 212 212 216;
--sb-thumb: 212 212 216;
--sb-thumb-hover: 161 161 170;
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.06);
color-scheme: light;
}
.dark {
--ink-950: 10 10 12;
--ink-900: 20 20 24;
--ink-850: 24 24 27;
--ink-800: 31 31 35;
--ink-700: 38 38 43;
--ink-600: 50 50 56;
--line: 39 39 42; /* zinc-800 */
--slate-100: 244 244 245;
--slate-200: 228 228 231;
--slate-300: 212 212 216;
--slate-400: 161 161 170;
--slate-500: 138 138 147;
--slate-600: 113 113 122;
--slate-700: 82 82 91;
--sb-thumb: 39 39 42;
--sb-thumb-hover: 63 63 70;
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.25);
color-scheme: dark;
}
html,
body,
#root {
height: 100%;
margin: 0;
}
body {
background: rgb(var(--ink-950));
color: rgb(var(--slate-300));
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* 滚动条随主题 */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-thumb {
background: rgb(var(--sb-thumb));
border-radius: 8px;
border: 2px solid transparent;
background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
background: rgb(var(--sb-thumb-hover));
background-clip: padding-box;
}
::-webkit-scrollbar-track {
background: transparent;
}
/* 紫→青品牌渐变文字 */
.brand-gradient {
background: linear-gradient(90deg, #a78bfa, #22d3ee);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
/* 输入控件随主题(color-scheme 由 :root/.dark 设定,控件自动继承) */
/* react-flow 画布主题化:控件/连线/迷你图与设计系统对齐(colorMode 已处理大半,此处精修) */
.react-flow__controls {
box-shadow: none;
border: 1px solid rgb(var(--line));
border-radius: 8px;
overflow: hidden;
}
.react-flow__controls-button {
background: rgb(var(--ink-900));
border-bottom: 1px solid rgb(var(--line));
color: rgb(var(--slate-400));
}
.react-flow__controls-button:hover {
background: rgb(var(--ink-800));
}
.react-flow__controls-button svg {
fill: currentColor;
}
.react-flow__edge-path {
stroke: rgb(var(--slate-600));
stroke-width: 1.5;
}
.react-flow__edge.selected .react-flow__edge-path,
.react-flow__edge:focus .react-flow__edge-path {
stroke: #8b5cf6;
}
.react-flow__minimap {
border: 1px solid rgb(var(--line));
border-radius: 8px;
}