Skip to content

前端 Monorepo 架构

包结构与依赖关系

@shice/composables  →  @shice/stores  →  @shice/api  →  @shice/shared
       ↓                     ↓                ↓               ↓
   业务逻辑Hook         Pinia状态管理      HTTP客户端      类型+工具

依赖方向:单向自上而下,禁止反向依赖。


@shice/shared — 类型定义层

文件frontend/packages/shared/src/

  • 纯 TypeScript,零运行时依赖,零 DOM API
  • 类型按领域拆分:user.ts, person.ts, strategy.ts, chat.ts, subscription.ts, api.ts, selfProfile.ts
  • ApiResponse<T>PaginatedResponse<T> 作为所有 API 响应的泛型容器
  • ChatRequest.locale?: string — 后端回复语言
  • SelfProfileFields — 用户自我画像(summary / goals / communicationStyle / boundaries / context)
  • 常量集中管理:RELATIONSHIP_TYPE_LABELS, SCENARIO_TYPE_LABELS, IMPORTANCE_LABELS
  • 工具函数:formatDate, truncate, generateId, debounce

跨端注意:绝不引入浏览器/Node.js 特有 API,UniApp 可直接 workspace 引用。


@shice/api — HTTP 客户端层

文件frontend/packages/api/src/

  • 与后端契约:REST 路径与请求/响应形状以 api_routes.md(对照 internal/handler/router.go)为准;流式对话见 sse.md
  • 基于 axios 封装,按模块拆分:auth.ts(含 getSelfProfile/updateSelfProfile)、person.ts, chat.ts, strategy.ts, subscription.ts
  • Base URL 通过 configureApiClient({ baseUrl }) 动态注入
  • Token 自动刷新:401 拦截器 → /auth/refresh → 重试
  • streamChat(data: ChatRequest, ...) — POST + fetch ReadableStream 方式实现 SSE
  • 策略 API 类型已带 locale 字段,前端页面接入时需传入

@shice/stores — 状态管理层

文件frontend/packages/stores/src/

  • useUserStore:登录/注册 + token 持久化 + restoreSession() + isPremium
  • usePersonStore:CRUD + 分页 + personMap O(1) 查找
  • useChatStore:乐观更新 + 流式对话 + streaming / streamingContent / selectedModel + currentRequestLocale()localStorage('shice_locale') 读取

跨端注意localStorage 需在 UniApp 中替换为 uni.setStorageSync(抽取 StorageAdapter)。


@shice/composables — 业务逻辑层

  • useAuth:认证流程
  • usePersonManager:人物 CRUD + 搜索 + 分页
  • 不含 UI 操作;后续扩展 useChat, useStrategy

Web 应用 (apps/web)

技术选型

依赖用途
Vue 3 ^3.5核心框架
Naive UI ^2.40组件库
vue-i18n 9中英界面国际化
vue-router 4SPA 路由
UnoCSS原子 CSS
Vite 6构建工具

路由设计

/login, /register       → guest only
/                        → MainLayout (requiresAuth)
  ├── /                  → DashboardView
  ├── /persons           → PersonListView
  ├── /persons/:id       → PersonDetailView
  ├── /chat              → ChatView
  ├── /chat/:sessionId   → ChatView
  └── /settings          → SettingsView

布局

  • 桌面端:左侧 NLayoutSider(220px,可折叠)+ 顶栏(暗色切换 + 语言切换 NSelect + 用户下拉)
  • 移动端:汉堡菜单 + Teleport 侧栏遮罩

国际化

  • i18n.tscreateI18n({ legacy: false });locale 初始值来自 localStorage('shice_locale')
  • App.vue watch locale → 同步 localStorage + Naive UI locale (zhCN/enUS)
  • MainLayout 顶栏 NSelect 切换语言
  • locales/zh.json / en.json:nav / chat / settings / common

核心页面

  • DashboardView:统计卡片 + 快速操作 + 最近动态 Timeline
  • PersonListView:搜索 + 过滤 + 卡片列表 + 新建 Modal
  • PersonDetailView:头部信息 + 详情卡片 + 操作区
  • ChatView:左右分栏(会话列表 + 聊天区);流式打字机 + 停止生成 + 自动滚动
  • 画像与档案更新提案:SSE 结束帧若含 profileProposal,由 useChatStore 暂存为 pendingProfileProposal
    • incomplete_self / incomplete_person(系统判断「我的画像」或关联人脉档案偏空):先弹出居中引导(文案见 i18n chat.profileCenterNudge*),用户点「去更新」后打开 ProfileProposalModal;弹窗内会 请求 GET /auth/self-profile 或人脉详情,把 该侧全部可编辑字段 展开为一列表格(宽屏约 min(720px, 96vw)),并与 LLM 返回的 patch 按 key 合并;缺失路径下每一行默认勾选,可「全不选」或单项取消后再「应用所选」;写入仍走既有 PUT self-profile / PUT persons/:id
    • refinement:不经过居中引导,在输入区上方显示 底部提示条 + 约 30 秒倒计时,可直接打开同一确认弹窗;弹窗内容为后端给出的 patch 列表(默认全选)。
  • 组件:views/chat/ChatView.vuecomponents/chat/ProfileProposalModal.vue;文案键 chat.profileProposal*chat.profileCenterNudge*chat.profileProposalFullFormHintchat.profileProposalLoading
  • SettingsView:账号 Tab(订阅状态 / 外观 / 关于)+ 我的画像 Tab(SelfProfile 表单)

Vite 配置

  • /api 代理到 http://127.0.0.1:8080(与 vite.config.ts 一致)
  • @/ 路径别名指向 src/
  • 生产构建在 ELECTRON=1 时使用 base: './',供桌面包加载本地 index.html
  • server.strictPort: true 且端口 3000,与 apps/desktop 开发态固定打开 http://127.0.0.1:3000 对齐(勿同时开两个占 3000 的 dev)

Electron 桌面壳 (apps/desktop)

  • 开发:仓库根下 cd frontend && pnpm dev:desktopconcurrently 启动 dev:web + Electron;等待3000 就绪)
  • 构建安装包pnpm build:desktopcd apps/desktop && pnpm pack(解包目录在 release/
  • 路由file:// 打开本地文件时自动使用 hash historyrouter/index.ts);开发态走 http 仍为 history 模式
  • 预加载preload.cjs 暴露 window.shiceElectron.platform;OAuth / 自动更新等仍可按 ui_design_notes.md 扩展