Skip to content

Commit de0ff08

Browse files
committed
docs: 新增前端 AGENTS.md 并修订 commit 规则
1 parent e3bf36a commit de0ff08

2 files changed

Lines changed: 119 additions & 5 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ ChuChartManager/ # CCM 主仓库(monorepo)
4343
### Git
4444

4545
- **不要自动 push** — 只在用户明确说 push 时才推
46-
- **不要未经确认 commit**改完等用户确认
47-
- commit 带签名`git -c gpg.format=ssh commit -S -m "..."`如果失败就不带签名
48-
- commit message 用中文,conventional commits 格式,统一 commit 风格
46+
- **不要未经确认 commit**改完等用户 review
47+
- commit 签名`git -c gpg.format=ssh commit -S -m "..."`如果失败就不签名
48+
- commit message 用中文,conventional commits **不加 scope**`type: description`
4949

5050
### AppleChu
5151

@@ -69,8 +69,7 @@ ChuChartManager/ # CCM 主仓库(monorepo)
6969

7070
| 功能 | 原因 |
7171
|------|------|
72-
| 自定义分辨率 | Segatools 先于 mod 创建 D3D9 设备 |
73-
| FPS 显示 OSD | 同上,Present hook 不生效 |
72+
| 自定义分辨率 | 未知 可能是写死的 |
7473

7574
## 构建
7675

ChuChartManager/Front/AGENTS.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# FRONTEND KNOWLEDGE BASE
2+
3+
## OVERVIEW
4+
5+
Vue 3 + TypeScript 前端 SPA,通过 axios 调用本地 ASP.NET Core 后端 API,内嵌于 WinForms WebView2 窗口。
6+
7+
## STRUCTURE
8+
9+
```
10+
Front/
11+
├── src/
12+
│ ├── api/ # axios API 客户端(手写,按域分文件)
13+
│ │ ├── index.ts # apiClient 实例 + Music 相关 API + WebView2 baseUrl 适配
14+
│ │ ├── convert.ts # 谱面格式转换(c2s/ugc/sus)
15+
│ │ ├── course.ts # 课题模式
16+
│ │ ├── customResource.ts # 自制资源(删除曲目等)
17+
│ │ ├── ddsExtractor.ts # DDS 纹理提取
18+
│ │ ├── emote.ts # FreeMote E-mote
19+
│ │ ├── event.ts # 活动管理
20+
│ │ ├── loginBonus.ts # 登录奖励
21+
│ │ ├── option.ts # Option 目录管理(A000/A001/...)
22+
│ │ └── stage.ts # 舞台管理
23+
│ ├── client/
24+
│ │ └── mod.ts # Mod 相关 API(AppleChu / ChuModLoader)
25+
│ ├── components/ # 可复用组件:Sidebar.vue, StatusBar.vue, PlayerBar.vue, BottomOverlay.vue, FileTypeIcon.vue, DirSelect.tsx
26+
│ ├── locales/ # i18n YAML:zh.yaml / en.yaml / ja.yaml + index.ts
27+
│ ├── store/ # 全局状态:refs.ts(侧栏、option 目录)、player.ts(音频播放器)、status.ts(状态栏文本)
28+
│ ├── utils/ # 工具:getSubDirFile.ts(File System Access)、sanitizeFsName.ts
29+
│ ├── views/ # 页面(按域子目录):BatchAction/, Charts (MusicList.vue), Course/, Emote/, Event/, LoginBonus/, ModManager/, MusicList/OptionDirsManager/, ResourceManager/, Tools/, Oobe/, ImportMusicModal.vue, Settings.vue
30+
│ ├── App.vue # 根组件,按 sidebarActive 切换视图
31+
│ ├── main.ts # 入口:初始化主题 + i18n + WebView2 message 监听
32+
│ ├── fs-access.d.ts # File System Access API 类型补丁
33+
│ └── yaml.d.ts # yaml import 类型
34+
├── vite.config.ts # Vite 配置(输出 ../wwwroot,dev 代理 5000,FreeMote driver 复制插件)
35+
├── uno.config.ts # UnoCSS 配置
36+
├── package.json # pnpm workspace 成员(ccm-frontend)
37+
└── tsconfig.json # TypeScript strict,@ → ./src,jsxImportSource: vue
38+
```
39+
40+
## WHERE TO LOOK
41+
42+
| 任务 | 位置 |
43+
|------|------|
44+
| 调用后端 API | `src/api/*.ts`(按域分文件),统一 `apiClient` axios 实例 |
45+
| 添加新页面 | `src/views/` 对应子目录,挂到 `src/components/Sidebar.vue``SidebarKey` 并在 `App.vue``v-if` |
46+
| 全局状态 | `src/store/refs.ts`(侧栏 + option dirs)、`player.ts`(音频)、`status.ts`(状态文本) |
47+
| 复用组件 | `src/components/` |
48+
| 国际化文本 | `src/locales/{zh,en,ja}.yaml`,三语必须同步 |
49+
| 切换语言 | `setLocale()`,同时写入后端 `Config/SetLocale` 持久化 |
50+
| 前端入口 | `src/main.ts``App.vue`(按 `sidebarActive` 切视图) |
51+
| 文件保存到本地 | `utils/getSubDirFile.ts` + `showDirectoryPicker`(File System Access API) |
52+
| 文件名清理 | `utils/sanitizeFsName.ts``sanitizeFsSegment` |
53+
| Emote 播放器 | `views/Emote/EmotePlayerCanvas.tsx` 通过 `/emote-driver/` 加载 FreeMote-SDK WebGL driver |
54+
55+
## DATA FLOW
56+
57+
1. 页面/store 调用 `src/api/*.ts` 中的函数
58+
2. 函数用 `apiClient`(axios 实例)请求后端 `/api/*` 端点
59+
3. WebView2 启动时后端通过 `chrome.webview.postMessage` 推送 backendUrl,`main.ts` 监听并设置 `apiClient.defaults.baseURL`
60+
4. 状态变更通过 `store/refs.ts` 中的 `updateOptionDirs()` 等触发 UI 刷新
61+
5. 错误处理:组件内部 try/catch + `addToast` 提示(来自 `@munet/ui`
62+
63+
WebView2 集成:
64+
- `main.ts` 监听 `chrome.webview` message 事件 → 写入 `globalThis.backendUrl` + 动态 import `./api` 更新 baseURL
65+
- `api/index.ts``isWebView = !!(window as any).chrome?.webview`
66+
- `ensureBackendUrl()``App.vue onMounted` 等待 backendUrl 就绪
67+
68+
## CONVENTIONS
69+
70+
- 包管理器:**pnpm**(workspace 成员,根仓库 `pnpm-workspace.yaml`),不用 npm / yarn
71+
- UI 组件库:**@munet/ui**(workspace:* 引用 MuNET-UI 子模块),核心组件 Button/Radio/Select/Popover/CheckBox/Modal/Progress/addToast
72+
- Naive UI 仅用于 `BatchAction/MusicSelector.tsx``NDataTable`(虚拟滚动+过滤)
73+
- 样式方案:**UnoCSS** 原子化 + **SASS 缩进语法**(不是 SCSS)
74+
- 主题:`@munet/ui``selectedThemeName = UIThemes.DynamicLight`,hue 默认 353
75+
- 路径别名:`@``./src`
76+
- TypeScript strict,JSX 用 `defineComponent(...)`(兼容 Vue + JSX,`jsxImportSource: vue`
77+
- 视图混用 `.vue`(template)和 `.tsx`(JSX setup),优先 `.tsx`(参考 MCM Front 写法)
78+
- 状态管理极简,全局 `ref` 散在 `store/*.ts`(不使用 Pinia)
79+
- API 客户端 **全手写**(无 swagger 生成),按业务域分文件
80+
- 代码注释使用中文
81+
- 三语 i18n 必须同步:新增 key 时 `zh.yaml` / `en.yaml` / `ja.yaml` 都加
82+
83+
## ANTI-PATTERNS
84+
85+
- 不要手写 UI 图标 emoji,统一用 iconify class(`i-mdi-*` / `i-tabler:*` / `i-ri:*`)或 `components/FileTypeIcon.vue`
86+
- 不要引入新 npm 依赖除非确实必要
87+
- 不要在视图组件里直接 fetch,统一走 `src/api/*.ts`
88+
- 不要在 `Models/` 风格的地方写业务逻辑(前端无强 Model 层,但 store 只放纯 ref)
89+
- 不要破坏三语 i18n 同步
90+
- 不要为深色主题写适配(当前仅支持浅色,相关选项已在设置页移除)
91+
92+
## BUILD
93+
94+
```bash
95+
# 安装依赖(在 Front 目录)
96+
pnpm install
97+
98+
# 开发(端口 5173,代理后端 5000)
99+
pnpm dev
100+
101+
# 构建(输出到 ../wwwroot)
102+
pnpm build
103+
104+
# 预览构建产物
105+
pnpm preview
106+
```
107+
108+
## NOTES
109+
110+
- 后端 dev 端口 **5000**(不是 MCM 的 5181),dev 代理 `/api` 到 localhost:5000
111+
- 入口 hash `#oobe` / `#mode-select` 切换到引导页 (`views/Oobe/`)
112+
- Player 是单例 `Audio` 元素,存于 `store/player.ts`,状态 ref 化
113+
- `views/Emote/` 嵌入 FreeMote-SDK WebGL driver,vite 启动时通过 `copyEmoteDriver` 插件从 `../../FreeMote-SDK/WebGL/driver` 复制 / 反代
114+
- File System Access API 类型由 `fs-access.d.ts` 补齐,仅 Chromium 浏览器支持(WebView2 OK)
115+
- 批量导出走流式 ZipReader + `showDirectoryPicker` 边解压边写盘(参考 `views/BatchAction/remoteExport.tsx`

0 commit comments

Comments
 (0)