Files
violin-home/AGENT.md
T
simple321vip 4da6832b44 feat: R1 重构对称迁移 + 升级依赖 + 配置文件分离
- 命名重构:tenant → customer(对齐后端 R1 重构)
  - Tenant → Customer / tenant_id → customerId
  - tenantStore → customerStore / getTenant/setTenant → getCustomer/setCustomer
  - cookie key tenant → customer, HTTP header tenantId → customerId
- 后端契约更新:AuthResponse 加 sub 字段
- 接口 URL 修复:/auth/oidc/callback → /api/v1/auth/oidc/callback
- 依赖升级:vue 3.5 / element-plus 2.8 / vite 5 / typescript 5.6 / sass 1.79
- 删 node-sass / scss / sass-loader / moment / mock/index.ts
- 配置文件拆分:.env.development / .env.production / .env.example
- 删除冗余 view/auth/auth/callback.vue 副本
- .gitignore 增加 dist / .opencode / tmp
- 新增 AGENT.md 与后端风格对齐
2026-06-22 08:02:21 +08:00

7.7 KiB
Raw Blame History

AGENT.md — violin-home

面向 AI agent 的工程导览:模块关系、路由约定、与后端的契约、扩展点。 代码即事实,本文件是索引;如代码与本文档冲突,以代码为准


项目定位

violin-home 是 violin 微服务套件的统一前端门户,部署在 https://www.violin-home.cn/

  • 认证:Authentik OIDC,回调路径 /auth/callback,前端把 code POST 到 violin-auth 服务换 token
  • 后端:依赖 violin-auth(认证)/ violin-bookmark(书签)/ violin-calendar(日历)/ violin-onenote / violin-cloud / 等子服务
  • 域名:生产 https://www.violin-home.cn/;本地 dev 走 .env.developmentVITE_APP_URL

技术栈

维度 选型
框架 Vue 3.5 + Composition API (<script setup>)
构建 Vite 5
语言 TypeScript 5.6
UI Element Plus 2.8 + Icons
状态 Pinia 2.2
路由 vue-router 4.4memory history,不是 hash / web
HTTP axios 1.7
图表 ECharts 5
Markdown md-editor-v3 4
日期 dayjs已废弃 moment
Mock vite-plugin-mock 3仅 dev 启用
拖拽 vuedraggable 4
样式 SCSSDart Sass 1.79已删除 node-sass

目录结构

violin-home/
├── public/                       静态资源(不打包)
│   ├── blog/*.ts                 博客元数据(按业务模块拆分)
│   └── reset/                    Authentik reset 入口(reset.html 等)
├── src/
│   ├── api/                      axios 接口封装(每个业务一个文件)
│   ├── components/               公共组件
│   │   ├── common/               通用组件
│   │   ├── layout/               顶层布局
│   │   ├── login/                登录 / 注册 / sorryPage
│   │   ├── cloud/                云盘 + aplayer 音乐
│   │   ├── illustration/         插画
│   │   ├── customPic/            自定义图片
│   │   └── operate/              操作组件
│   ├── const/                    全局常量
│   ├── entity/                   实体类型(TypeScript interface
│   ├── router/                   路由表(**统一指向 @/view/**
│   ├── service/                  服务层(独立于 axios 的工具服务)
│   ├── store/                    Pinia stores
│   ├── style/                    全局样式(mixin.scss 在 vite.config.ts 里自动注入)
│   ├── types/                    类型声明(*.d.ts
│   ├── utils/                    工具函数(auth 令牌管理、request axios 封装、date、number
│   ├── view/                     **页面视图(业务页)** — 单数 view
│   ├── App.vue
│   ├── env.d.ts
│   ├── main.ts
│   └── permission.ts             路由守卫
├── mock/                         vite-plugin-mock 的 mock 数据
├── authentik-deploy/             Authentik 部署相关(helm values、reset 脚本)
├── .env.development              本地开发
├── .env.test                     测试环境
├── .env.production               生产环境
├── Dockerfile
├── Jenkinsfile
├── nginx.conf
├── vite.config.ts
└── tsconfig.json

路由约定

全部路由指向 @/view/(单数),包括 /auth/callback

  • router/index.ts唯一的路由表
  • 路由 meta.name 是侧边栏展示的中文名
  • /auth/callbackview/auth/callback.vue 处理 OIDC 回调(拿 code → POST /auth/oidc/callback 到 violin-auth → 存 token

禁止新建 views/(复数)目录。


认证流程(OIDC

浏览器 → Authentik 登录页(不在本工程)
       ↓ 回调到 https://www.violin-home.cn/auth/callback?code=...&state=...
       ↓
view/auth/callback.vue
       ↓ POST { code, redirect_uri } → VITE_APP_URL + '/auth/oidc/callback'
       ↓
violin-auth 服务(cn.violin.auth.service.OAuthService.oidcAuthorize
       ↓ 返回 { token, user_id, name }
       ↓
utils/auth.setToken / setTenant 存到 cookie + localStorage
       ↓ 跳到 /

关键约定

  • redirect_uri 必须和 Authentik 应用的配置完全一致(VITE_OIDC_REDIRECT_URI
  • state 必须校验(防 CSRF),前后端都用 sessionStorage.oidc_state 缓存
  • token 由 setToken() 存到 cookiejs-cookie),后续 axios 请求拦截器自动加 Authorization: Bearer <token>

HTTP 封装(utils/request.ts

  • baseURL = import.meta.env.VITE_APP_URL
  • 请求拦截器:从 js-cookie 读 token,加到 header
  • 响应拦截器:401 → 跳 /login5xx → ElMessage 报错

每个业务模块在 src/api/ 下有自己的文件(如 api/bookmark.ts),导出按业务分组的函数:

import { service } from '@/utils/request'
export const getBookmarks = (params: PageQuery) =>
  service({ url: '/api/v1/bookmark', method: 'get', params })

状态管理(Pinia

src/store/ 下每个业务一个 storesettings、strategy、table、tenant)。禁止把所有状态塞进一个 store。

  • tenant store 管当前 customer(对应后端的 customerId
  • settings store 管用户偏好
  • strategy store 管 CTA 策略模板
  • table store 管通用表格筛选/分页状态

与后端子服务的对应

路径前缀 后端服务 端口(K8s 内)
/auth/** violin-auth 8080
/api/v1/bookmark/** violin-bookmark 8081
/api/v1/calendar/** violin-calendar 8082
/api/v1/onenote/** violin-onenote 8083
/api/v1/cloud/** violin-cloud 8084
/api/v1/trader/** violin-trader 8085
/api/v1/user/** violin-authuser 模块) 8080

路由由 K8s ingress 统一反向代理;前端只关心 VITE_APP_URL 单一域名。


构建与运行

# 安装依赖(推荐 pnpm,yarn 也行)
npm install

# 本地 dev(启动 mock
npm run dev

# 生产构建(先类型检查,再打包)
npm run build

# 测试环境构建
npm run build:test

# 预览构建产物
npm run preview

Nodev18+不要用 v14/16,老的 sass-loader/node-sass 不兼容)。


已知坑(不要"清理"它们)

1. view/ 单数 vs views/ 复数

永远只创建 view/ 单数目录views/ 是历史遗物,已删除过又留下空目录。

2. node-sass 已废弃

package.json没有 node-sass。如果你看到 npm installnode-sass 相关错误,是因为旧依赖被缓存,不要手动加回 node-sass,用 Dart Sasssass: ^1.79)即可。

3. axios 0.x → 1.x

升级到 axios 1.7 后,axios.create() 配置有少量变化(如 paramsSerializer)。如果你看到 interceptor is not a function 之类的报错,看下拦截器是否还兼容旧签名。

4. Vue Router 4 用 memory history

createMemoryHistory() 而非 createWebHistory() / createWebHashHistory()。刷新页面会丢路由——如果要做刷新保留路由,需要切到 createWebHistory() 并配合 K8s ingress 重写。

5. vite-plugin-mock 仅 dev 启用

生产构建不会带 mocklocalEnabled: command === 'serve')。如果发现生产缺数据,看下是不是依赖了 mock。


相关项目

  • violin-auth — 认证服务(OIDC + JWT 签发)
  • violin-bookmark / violin-calendar / violin-onenote / violin-cloud / violin-trader — 业务子服务
  • violin-common / violin-core — 后端共享框架
  • violin-parent — 后端父 POM