Files
zMainPage/docs/add-module.md
zikai 25dbceee2d refactor: 清理死代码/提前失败/高内聚低耦合,重写文档
死代码清理:
- 删除未使用的 UI 组件 Card.vue / Tag.vue
- 移除 app.config.js 死字段 healthTimeoutMs(×2)与 isDev()
- 移除 PageShell.vue 死 prop padded(恒为默认值)
- 移除 useLocale.js 死导出 isZh/pick/locale
- 移除 router/index.js 不可达 try/catch,简化为直接 .map()
- 移除 package.json 重复依赖 ical.js(子模块自带)
- 移除 i18n 死键 common.notAvailable / common.serviceUnavailable
- 移除 vite.config.js 陈旧的 /448 /449 dev proxy(z449 为构建期组件,不走该 URL)

提前失败/日志:
- useI18nLazy.js switchLocale 加载语言包失败时 console.error 记录(原静默吞错)
- modules/index.js 字段不全的模块跳过时 console.warn 告警(原与文档承诺不符、静默跳过)
- deploy.sh 补齐 zWhiteBoard / zPDF_package 的 npm install 与子模块初始化
  (均为构建期组件 import,全新检出时缺少依赖会构建失败)

文档对齐现状(无 iframe、无外部域名):
- README 改写为简洁版,修正 iframe/ical.js/子模块数量过时描述
- architecture.md 修正 requiresAlive 示例(同源 /api/health,非外部域名)
  与「仅白板使用」断言(PDF 也用);移除已删 padded prop
- add-module.md 同步移除 padded、修正 requiresAlive 示例
- submodule-timeTableFix.md 修正 ical.js 归属(子模块自带,非父项目共享)
- submodule-zPDF_package.md 子项目数量 3 -> 4
- 新增 submodule-zWhiteBoard.md
- readme-fixes.md 记录本次勘误
2026-07-28 11:57:32 +08:00

115 lines
3.9 KiB
Markdown
Raw Permalink 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.

# 新增一个项目页签
新增页签 = 新建 `src/modules/<新项目>/` 文件夹,无需改动导航或路由代码。注册表自动收集并生成页签与路由。
## 步骤
### 1. 建模块文件夹与元数据
复制 `src/modules/timetable/`(最简范式)或 `whiteboard/`(带存活校验)为 `src/modules/<新项目>/`
`index.js` 默认导出元数据(字段含义见 [architecture.md](./architecture.md#模块注册表扩展点核心)
```js
export default {
id: 'my-project', // 必填:唯一标识,同时作路由 path / KeepAlive 匹配名
tabKey: 'tabs.myProject', // 必填i18n 键
order: 4, // 可选:页签排序,缺省 999
component: () => import('./MyProject.vue') // 必填:懒加载组件
}
```
### 2. 实现组件,用 PageShell 包裹
组件内 `defineOptions({ name: <id> })`KeepAlive 匹配用),并用 `<PageShell>` 统一容器宽度与标题:
```vue
<script setup>
defineOptions({ name: 'my-project' })
import PageShell from '../../components/ui/PageShell.vue'
import { useLocale } from '../../composables/useLocale.js'
const { t } = useLocale()
</script>
<template>
<PageShell title-key="tabs.myProject">
<!-- 页面内容 -->
</PageShell>
</template>
```
PageShell props
- `titleKey`i18n 键,渲染页面标题;不传则无标题
- `fluid`true 突破 1080px 全宽(如日历页)
- `#actions` 具名插槽:标题旁的操作区(如白板切换表单)
### 3. 加 i18n 文案
`src/i18n/locales/zh-CN.js``en.js``tabs` 下加对应文案:
```js
tabs: {
// ...
myProject: '我的项目', // zh-CN
myProject: 'My Project', // en
}
```
### 4. 构建
```bash
npm run build
```
页签与路由自动出现。
## 常见变体
### 隐藏页签(仅 URL 访问)
```js
export default { id: 'secret', tabKey: 'tabs.secret', order: 99, hidden: true, component: () => import('./Secret.vue') }
```
`hidden: true` 的页签不在导航显示,但 URL 访问后保持可见(访问过的隐藏页签不会因切走而消失)。
### 依赖外部服务存活(挂掉则隐藏并卸载)
```js
import { healthUrl } from '../../config/app.config.js'
export default {
id: 'my-service', tabKey: 'tabs.myService', order: 5,
requiresAlive: healthUrl('myService'), // 同源探针 URL/api/health
component: () => import('./MyService.vue')
}
```
服务失活时页签隐藏、组件卸载;恢复后自动重新加载。详见 [architecture.md](./architecture.md#存活校验requiresalive)。
### 路由参数(如 /my-project/:id
```js
export default { id: 'my-project', tabKey: 'tabs.myProject', order: 4, param: 'itemId', component: () => import('./MyProject.vue') }
```
生成路由 `/<id>/:<param>?`,组件内用 `useRoute().params.<param>` 读取。
### 集成独立子项目git submodule
参照 `timetable` 模块(无 i18n 子项目)或 `mobile-game` 模块(带独立 i18n 的子项目):建 mainPage 侧包装器组件 import 子项目 `App.vue`,包装器持有 `defineOptions({ name })`。子项目保持纯净。
- **无 i18n 的子项目**(如 timeTableFix包装器直接 import App.vue 即可。
- **带独立 i18n 的子项目**(如 z449子项目 App.vue 接 `:locale` prop包装器把 mainPage 当前语言透传(`<Z449App :locale="locale" />`),子项目 `watch` 同步到自己的 i18n 实例。详见 [submodule-z449.md](./submodule-z449.md)。
## 元数据字段速查
| 字段 | 必填 | 说明 |
|------|------|------|
| `id` | 是 | 唯一标识,路由 path / KeepAlive 匹配名 |
| `tabKey` | 是 | i18n 键,页签与页面标题 |
| `component` | 是 | 懒加载组件函数 |
| `order` | 否 | 排序,缺省 999 |
| `hidden` | 否 | 隐藏页签URL 访问后保持可见 |
| `requiresAlive` | 否 | 存活探针 URL失活则隐藏并卸载 |
| `param` | 否 | 路由参数名,生成 `/:<param>?` |