Files
zMainPage/docs/architecture.md
zikai 4334dec00d docs: 精简 README,细节拆分到 docs/
README 仅保留概览/结构/基础设施/安装/开发命令;
架构、新增页签、子模块管理细节移至 docs/ 下三个 md:
- docs/architecture.md:模块注册/PageShell/KeepAlive/存活校验
- docs/add-module.md:新增页签步骤 + 元数据字段速查 + 常见变体
- docs/submodule-timeTableFix.md:submodule 升级/clone/移除/独立访问
2026-07-23 04:09:42 +00:00

80 lines
4.7 KiB
Markdown
Raw 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.

# 架构
mainPage 是一个 Vue 3 模块化多项目展示站。核心设计目标:**高内聚低耦合** -- 每个项目页签是一个独立「模块」,由注册表自动生成页签与路由,新增/删除页签只增删一个文件夹,互不影响。
## 模块注册表(扩展点核心)
`src/modules/index.js``import.meta.glob('./*/index.js', { eager: true })` 约定式收集每个子模块的 `index.js`。每个模块默认导出元数据:
```js
export default {
id: 'whiteboard', // 必填:唯一标识,同时作路由 path / KeepAlive 匹配名
tabKey: 'tabs.whiteboard', // 必填i18n 键,页签标题与 PageShell 标题均用此
component: () => import('./Whiteboard.vue'), // 必填:懒加载组件(函数形式,独立 chunk
order: 2, // 可选:页签排序,缺省 999排在显式页签之后
hidden: true, // 可选:不在导航显示,但 URL 访问后保持可见(如 cqy
requiresAlive: 'https://f.zikai.wang/health', // 可选:存活探针 URL服务失活则隐藏页签并卸载组件
param: 'boardId', // 可选:路由参数名,生成 /<id>/:<param>? 子路径
}
```
### 元数据字段 -> 消费方矩阵
| 字段 | 注册表 | router | useProjects | App.vue | TabNav |
|------|--------|--------|-------------|---------|--------|
| `id` | 必填校验 | path+name+meta.moduleId | visited 集合 / 路由关联 | keepInclude 名单 | `:to` + `:key` |
| `tabKey` | 必填校验 | - | - | - | 标题文案 |
| `component` | 必填校验 | 路由 component | - | RouterView 渲染 | - |
| `order` | 排序 | 决定 `/` 重定向目标 | 继承顺序 | - | 继承顺序 |
| `hidden` | 透传 | - | 可见性门控 | - | - |
| `requiresAlive` | 透传 | - | 可见性门控 | keepInclude + startPolling | - |
| `param` | 透传 | `/:<param>?` 后缀 | - | - | - |
### 容错
注册表对每个模块做字段完整性校验(缺 `id`/`tabKey`/`component` 的模块跳过),单个模块异常不影响其余页签加载。
## PageShell统一页面外壳
`src/components/ui/PageShell.vue` 是可复用的页面外壳组件,统一所有页面的:
- **容器宽度**:默认复用全局 `.container``max-width: 1080px`,居中,左右 `padding``fluid` 变体突破限制全宽(如日历页)
- **垂直节奏**`padding: var(--space-xl) 0 var(--space-2xl)``padded: false` 可关
- **标题**`titleKey` prop -> i18n 文案,渲染为 `<h1>`
- **操作区**`#actions` 具名插槽,放在标题旁(如白板的切换白板表单)
各模块根组件用 `<PageShell>` 包裹内容,不再各写一套 `.container`/标题/间距。新增页签照此复用。
## KeepAlive 缓存与卸载
`App.vue``<KeepAlive :include="keepInclude">` 包裹路由组件,切换页签不卸载(状态保留)。
- `keepInclude` 是模块 id 列表,默认包含所有模块。
- 声明了 `requiresAlive` 的模块,当存活探测为 `down` 时移出名单 -> 组件卸载;恢复 `up` 后重新纳入。
- **匹配约定**KeepAlive 按组件 `name` 匹配,因此每个模块组件需 `defineOptions({ name: <模块 id> })`
- 内置模块mobile-game/whiteboard/calendar直接在组件内声明。
- 子模块集成timetable由 mainPage 侧包装器 `Timetable.vue` 持有 name子项目自身不持 name保持纯净
## 存活校验requiresAlive
`src/composables/useLiveness.js` 提供跨域存活探测:
- 探测方式:`fetch(url, { mode: 'no-cors', cache: 'no-store' })`resolve 即存活4s 超时。
- 时机:应用加载即探测一次,之后每 30s 周期重探(`startPolling`)。
- 结果在全应用共享(模块级 `cache` Map`useProjects`(页签可见性)与 `App.vue`KeepAlive 卸载)共用同一 ref。
- **乐观显示**探测中pending/存活up都显示页签仅明确不可达down才隐藏并卸载恢复后自动重新加载。
目前仅白板页签使用(`requiresAlive: 'https://f.zikai.wang/health'`)。
## 路由
`src/router/index.js` 遍历注册表生成路由每个模块一条路由path = `/<id>` + 可选 `/:<param>?`。history 模式,需站点根 `.htaccess` 做 SPA 回退(见 README 安装步骤)。
## 国际化
`src/i18n/` -- 中文同步注入主 chunk默认语言英文通过动态 `import()` 懒加载成独立 chunk只看中文的访客不会下载英文资源。各模块 `tabKey` 指向 `tabs.*` 下的文案。
## 集中配置
`src/config/app.config.js` -- 外部服务 URL白板地址、存活探针路径等集中管理模块按需 import。改 URL 只改这里(需重新 build