# mainPage · 作品集主页 Zikai 的作品集主页 -- Vue 3 模块化多项目展示站。浅色极简、中英双语(英文按需懒加载)。 每个项目页签是一个独立「模块」,由注册表自动生成页签与路由 -- 新增/删除页签只增删一个文件夹,互不影响。 --- ## 项目结构 ``` mainPage/ ├── index.html ├── package.json # 含 ical.js(timeTableFix 依赖) ├── vite.config.js # 构建输出到 /root/html(emptyOutDir=false,不清空既有文件) ├── .gitmodules # git submodule:third_party/timeTableFix ├── README.md ├── public/favicon.svg ├── third_party/ │ └── timeTableFix/ # ★ git submodule:ICS 日程整理器,独立仓库 │ # src/App.vue 被 timetable 模块直接 import 为路由组件 └── src/ ├── main.js # 应用入口(挂载 i18n / router / 全局样式) ├── App.vue # 根布局:顶栏 + 标签导航 + + 页脚 ├── config/ │ └── app.config.js # ★ 集中配置:外部服务 URL(白板地址 / 存活探针等) ├── i18n/ # 国际化(中文同步注入;英文动态 import() 懒加载) │ ├── index.js │ └── locales/{zh-CN,en}.js ├── router/index.js # 路由表由模块注册表自动生成 ├── modules/ # ★ 扩展点:每个页签一个文件夹 │ ├── index.js # 注册表(import.meta.glob 约定式收集,带容错) │ ├── mobile-game/ # 移动游戏项目页签 │ ├── whiteboard/ # 共享记事本页签(iframe 嵌入 + 存活校验) │ ├── timetable/ # 日程整理页签(构建期 import 子模块 App.vue) │ └── calendar/ # 隐藏页(仅手动访问 /cqy) ├── components/ # 共享组件(TabNav / LanguageSwitcher / ui 基元) ├── composables/ # useProjects(页签+存活联动)/ useLiveness / useI18nLazy / useLocale └── styles/ # variables.css(主题令牌)+ base.css ``` ## 模块机制(高内聚低耦合) - `src/modules/index.js` 用 `import.meta.glob('./*/index.js', { eager: true })` 收集所有模块,单个模块导出异常会跳过并告警,不影响其余页签。 - 每个模块 `index.js` 默认导出元数据: ```js export default { id: 'whiteboard', // 唯一标识 + 路由 path tabKey: 'tabs.whiteboard', // i18n 键 order: 2, // 页签排序 component: () => import('./Whiteboard.vue'), // 懒加载组件(独立 chunk) requiresAlive: 'https://f.zikai.wang/health' // 可选:存活探针 URL,挂掉则隐藏页签 } ``` - `TabNav` 遍历注册表渲染页签;`router` 遍历注册表生成路由。 - 删除一个页签 = 删 `src/modules//` 文件夹并重新 build,其余页签不受影响。 ### 存活校验 声明了 `requiresAlive` 的模块,应用加载即探测探针 URL(`no-cors` fetch,4s 超时),之后每 30s 周期重探。 乐观显示:探测中/存活都显示页签,仅明确不可达时才隐藏并从 KeepAlive 移出(卸载组件);恢复后自动重新加载。目前仅白板页签使用。 ## 依赖的基础设施 | 项 | 要求 | |---|---| | Node.js | ≥ 18(开发于 18.19 + npm 9.2) | | Web 服务器 | Apache 2.4(启用 `mod_rewrite`),对外静态服务 `/root/html` | | SPA 回退 | history 模式需站点根 `.htaccess` 回退到 `index.html`(见下) | > 共享记事本页签通过 iframe 嵌入外部服务(默认 `https://f.zikai.wang/wb/share`),URL 在 `src/config/app.config.js` 集中配置。该服务需公开且允许被 iframe 嵌入。 > > 日程整理页签(timeTableFix)通过 **git submodule** 作为子项目,构建期直接 import 其 `App.vue` 为路由组件(非 iframe);同时其独立 app 可经 Apache `/ttf/` 反代单独访问。 ## Ubuntu 从 0 安装 ```bash # 1. 安装 Node.js 18 curl -fsSL https://deb.nodesource.com/setup_18.x | sudo bash - sudo apt-get install -y nodejs # 2. 取代码(含子模块 timeTableFix) git clone --recursive https://git.zikai.wang/zikai/zMainPage.git mainPage cd mainPage # 若已 clone 但未带子模块:git submodule update --init --recursive npm install # 3. 构建(产物输出到 /root/html,不清空既有文件) npm run build # 4. 安装并启用 Apache sudo apt-get install -y apache2 sudo a2enmod rewrite ``` 站点根放 `.htaccess`(Apache 需 `AllowOverride All`)做 SPA 回退: ```apache RewriteEngine On RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] RewriteRule ^ index.html [L] ``` 把 `/root/html`(或 `/var/www/html`)设为 `DocumentRoot`,访问站点即可。开发预览用 `npm run dev`(http://localhost:5173)。 ## 如何新增一个项目页签 1. 复制 `src/modules/whiteboard/`(或 `mobile-game/`)为 `src/modules/<新项目>/`。 2. 改 `<新项目>/index.js` 的 `id` / `tabKey` / `order` / `component`。 3. 在 `src/i18n/locales/zh-CN.js` 与 `en.js` 的 `tabs` 下加对应文案。 4. `npm run build` -- 页签与路由自动出现,无需改导航或路由代码。 ## 子项目 timeTableFix 的升级 timeTableFix 作为 git submodule 独立维护,升级流程: ```bash cd mainPage git submodule update --remote third_party/timeTableFix # 拉取最新 cd third_party/timeTableFix && git checkout master # 固定到目标分支/commit cd ../.. git add third_party/timeTableFix # 更新 gitlink 指针 git commit -m "chore: 升级 timeTableFix 子模块" npm run build # 重新构建 mainPage ``` timeTableFix 本身完全独立,可单独 `npm run build` / `npm test`,也可经 Apache `/ttf/` 反代单独访问。 --- ## 开发命令 ```bash npm install # 首次安装依赖 npm run dev # 开发服务器 http://localhost:5173 npm run build # 构建到 /root/html npm run preview # 本地预览构建产物 ```