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
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>
63 lines
2.9 KiB
TypeScript
63 lines
2.9 KiB
TypeScript
import { Link } from "react-router-dom";
|
||
import { Users, Building2, Coins, ArrowUpRight, Download } from "lucide-react";
|
||
import { useTenant } from "../shell/AppShell";
|
||
import { fmtCredits, ROLE_LABEL } from "../api";
|
||
import { Badge } from "../ui";
|
||
|
||
// 概览:当前组织 + 我的角色 + 余额,和去往各功能的入口。桌面端下载指引放这
|
||
// (薄 Web 面的定位就是「装桌面端之前能用的那些事」)。
|
||
export function Overview() {
|
||
const { ctx, tenants } = useTenant();
|
||
|
||
const cards = [
|
||
{ to: "/team", icon: Users, title: "团队", desc: "邀请成员、分配角色" },
|
||
{ to: "/orgs", icon: Building2, title: "组织", desc: `我所属的 ${tenants.length} 个组织` },
|
||
{ to: "/usage", icon: Coins, title: "用量与账单", desc: "余额、消耗趋势与明细" },
|
||
];
|
||
|
||
return (
|
||
<div className="mx-auto max-w-3xl p-8">
|
||
<h1 className="text-xl font-semibold tracking-tight text-slate-100">
|
||
{ctx?.tenant?.name ?? "…"}
|
||
</h1>
|
||
<div className="mt-2 flex items-center gap-2 text-xs text-slate-500">
|
||
{ctx?.role && <Badge tone="accent">{ROLE_LABEL[ctx.role] ?? ctx.role}</Badge>}
|
||
<span>套餐 {ctx?.tenant?.plan ?? "-"}</span>
|
||
<span>·</span>
|
||
<span>
|
||
余额 <span className="tabular-nums text-slate-300">{fmtCredits(ctx?.credit_balance_micro ?? 0)}</span> 积分
|
||
</span>
|
||
</div>
|
||
|
||
<div className="mt-8 grid grid-cols-1 gap-3 md:grid-cols-3">
|
||
{cards.map((c) => {
|
||
const Icon = c.icon;
|
||
return (
|
||
<Link key={c.to} to={c.to}
|
||
className="group flex flex-col rounded-xl border border-line bg-ink-900 p-4 shadow-card transition-colors hover:border-brand/40">
|
||
<div className="flex items-center justify-between">
|
||
<Icon className="h-5 w-5 text-slate-300 transition-colors group-hover:text-brand-400" strokeWidth={1.8} />
|
||
<ArrowUpRight className="h-4 w-4 text-slate-700 transition-colors group-hover:text-slate-400" />
|
||
</div>
|
||
<div className="mt-3 text-sm font-medium text-slate-100">{c.title}</div>
|
||
<div className="mt-1 text-xs text-slate-500">{c.desc}</div>
|
||
</Link>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
<div className="mt-8 flex items-start gap-3 rounded-xl border border-line bg-ink-900 p-4">
|
||
<Download className="mt-0.5 h-4 w-4 shrink-0 text-slate-500" />
|
||
<div className="text-xs leading-relaxed text-slate-500">
|
||
<span className="text-slate-300">日常工作在桌面端进行。</span>
|
||
编排智能体、知识库问答、报告生成都在 sundynix 桌面应用里——
|
||
<a className="text-brand-400 hover:underline" href="https://github.com/blizzardzhang/sundynix-agentix/releases/latest" target="_blank" rel="noreferrer">
|
||
下载最新版
|
||
</a>
|
||
,用当前账号登录即可。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|