Zikai 15af291da0 feat: init mainPage portfolio site
Vue 3 模块化作品集主页,浅色极简风格,中英双语懒加载 i18n。

- 模块注册表(import.meta.glob)约定式收集项目模块,新增页签无需改导航/路由
- i18n: 中文同步注入主 chunk,英文动态 import() 拆独立 chunk,仅切换时下载
- 第一个页签 mobile-game: 展示 448/449 移动游戏毕设(概览/截图轮播/版本时间线/团队/排行榜/ML视频)
- 排行榜复用 /449/449rest.php,失败优雅降级
- 构建: vite outDir=/root/html,emptyOutDir=false,产物用 mainPage/ 命名空间
- 样式: CSS 变量令牌,无 UI 框架运行时依赖
2026-07-12 14:18:35 +00:00
2026-07-12 14:18:35 +00:00
2026-07-12 14:18:35 +00:00
2026-07-12 14:18:35 +00:00
2026-07-12 14:18:35 +00:00
2026-07-12 14:18:35 +00:00

mainPage · 作品集主页

Zikai 的作品集主页 -- 一个 Vue 3 模块化的多项目展示站点。 采用浅色极简美术风格,中英双语并支持懒加载(默认中文,只看中文的访客不会下载英文资源)。 设计目标:高内聚低耦合、可扩展 -- 后续每个新项目都是一个独立「模块」,自动生成页签与路由。

这是「主页」项目本身。它展示的第一个项目页签是 448/449 移动游戏毕设, 详见同级目录下的 /root/html/448/README.md/root/html/449/README.md


技术栈

选型
框架 Vue 3<script setup> Composition API
构建 Vite 5
路由 vue-router 4history 模式,路由表由模块注册表动态生成)
国际化 vue-i18n 9中文同步注入英文动态 import() 懒加载)
样式 原生 CSS + CSS 变量令牌(无 UI 框架,零运行时样式依赖)

Node 版本要求:≥ 18本项目在 Node 18.19 + npm 9.2 下开发与构建)。


目录结构

mainPage/
├── index.html                      # Vite 入口模板
├── package.json
├── vite.config.js                  # ★ 构建输出配置(见下「构建与部署」)
├── .gitignore
├── README.md                       # 本文件
├── public/
│   └── favicon.svg                 # 站点图标
└── src/
    ├── main.js                     # 应用入口(挂载 i18n、router、全局样式
    ├── App.vue                     # 根布局:顶栏 + 标签导航 + <router-view> + 页脚
    │
    ├── i18n/                       # 国际化(懒加载核心)
    │   ├── index.js                #   i18n 实例仅同步注入中文loadLocaleAsync() 动态切语言
    │   └── locales/
    │       ├── zh-CN.js            #   中文(默认,打进主 chunk
    │       └── en.js               #   英文(动态 import() -> 独立 chunk切换时才下载
    │
    ├── router/
    │   └── index.js                # 路由表遍历模块注册表自动生成
    │
    ├── modules/                    # ★★★ 扩展点:每个项目一个模块文件夹
    │   ├── index.js                #   模块注册表import.meta.glob 约定式收集)
    │   └── mobile-game/            #   第一个页签448/449 移动游戏项目
    │       ├── index.js            #     模块元数据id / tabKey / order / 懒加载组件)
    │       ├── MobileGame.vue      #     项目展示主页
    │       ├── components/
    │       │   ├── HeroSection.vue       # 顶部项目概览横幅
    │       │   ├── ScreenshotCarousel.vue# 截图轮播(复用 /448/1..3.jpg
    │       │   ├── VersionTimeline.vue   # 版本演进时间线
    │       │   ├── TeamCard.vue          # 团队成员卡片
    │       │   └── Leaderboard.vue       # 排行榜AJAX 调 /449/449rest.php失败降级
    │       └── data/
    │           ├── versions.js     #     版本数据448 各版本信息)
    │           └── team.js         #     团队成员数据
    │
    ├── components/                 # 全局共享组件
    │   ├── TabNav.vue              #   标签页导航(由模块注册表驱动,自动生成页签)
    │   ├── LanguageSwitcher.vue    #   中/英切换按钮
    │   └── ui/                     #   基础 UI 基元
    │       ├── Card.vue
    │       └── Tag.vue
    │
    ├── composables/                # 组合式逻辑
    │   ├── useProjects.js          #   读取已注册模块列表
    │   └── useI18nLazy.js          #   语言懒加载切换逻辑
    │
    └── styles/
        ├── variables.css           #   主题令牌(浅色极简:色板/圆角/阴影/间距)
        └── base.css                #   重置 + 排版基础

架构要点

1. 模块化扩展(高内聚低耦合)

新增一个项目页签 = 新建 src/modules/<新项目>/ 文件夹,无需改动导航或路由代码。

  • src/modules/index.jsimport.meta.glob('./*/index.js', { eager: true }) 约定式收集所有模块。
  • 每个模块 index.js 默认导出元数据:
    export default {
      id: 'mobile-game',              // 唯一标识,同时作路由 path
      tabKey: 'tabs.mobileGame',      // i18n 键,页签标题
      order: 1,                       // 页签排序
      component: () => import('./MobileGame.vue')  // 懒加载组件
    }
    
  • TabNav.vue 遍历注册表渲染页签;router/index.js 遍历注册表生成路由。
  • 模块自包含组件、数据,模块间无直接引用 -> 高内聚低耦合。

2. i18n 懒加载(中文页不加载英文资源)

  • 创建 i18n 实例时只同步注入中文 zh-CN(随主 chunk 下发)。
  • en.js 通过 () => import('./locales/en.js') 注册Vite/Rollup 自动拆成独立 chunk en.[hash].js
  • 切换英文时 useI18nLazyawait import() 拉取英文 chunkmergeLocaleMessage 后再切 locale
  • 结果:只看中文的访客永不请求英文 chunk;首次切英文才下载,之后切换无网络请求。
  • 构建产物可见 js/mainPage/en.[hash].js(约 0.27 KB独立存在。

3. 浅色极简美术

主题令牌集中在 src/styles/variables.css:白底 #fff / 浅灰面 #f7f8fa、单一靛蓝强调色 #4f46e5、圆角 12px、柔和阴影、细线边框、充足留白。无深色、无渐变铺底、无霓虹悬浮微交互克制轻微上移 + 阴影加深)。


开发

cd /root/zikai/mainPage
npm install        # 首次安装依赖
npm run dev        # 启动开发服务器 (http://localhost:5173)

开发服务器配置了代理:/448/449 请求转发到 http://localhost:8080 (假设该端口有静态服务器在跑,否则截图/排行榜/视频会 404但页面其余部分正常。 开发时可临时用 python3 -m http.server 8080 --directory /root/html 提供这些静态资源。

构建与打包

npm run build      # 产物输出到 /root/html

输出路径与安全策略(vite.config.js

  • build.outDir = '/root/html'emptyOutDir = false(★ 不清空 outDir/root/html 已含 448/449/旧 js/css 等既有内容,绝不能被构建清空。
  • mainPage/ 命名空间子目录避免与 /root/html/js/root/html/css 旧文件冲突:
    • JS -> js/mainPage/[name].[hash].js
    • CSS -> css/mainPage/[name].[hash].css
    • 其他资源 -> assets/mainPage/[name].[hash][extname]
  • base = '/',引用既有 448/449 资源用站点根绝对路径(/448/.../449/...)。

构建产物示例

/root/html/
├── index.html                       # 入口Vite 注入 <script>/<link>
├── favicon.svg
├── js/mainPage/
│   ├── index.[hash].js              # 主 chunk含 Vue/router/中文 i18n
│   ├── MobileGame.[hash].js         # 移动游戏页(懒加载)
│   └── en.[hash].js                 # 英文语言包(懒加载,仅切英文时下载)
└── css/mainPage/
    ├── index.[hash].css             # 全局样式
    └── MobileGame.[hash].css        # 移动游戏页样式

预览构建产物

npm run preview     # 本地预览构建后的产物

部署

构建产物直接落在站点根 /root/html,由 Web 服务器(如 nginx/root/html 为根提供静态服务即可。 注意:当前主机上 nginx 默认 root 为 /var/www/html(与 /root/html 内容同步); 若需以 /root/html 为根对外服务,请调整 nginx 的 root 指令并启用 nginx。 主页引用的 /448/.../449/... 资源必须能从站点根访问到448/449 目录本就在 /root/html 下)。


如何新增一个项目页签

  1. 复制 src/modules/mobile-game/src/modules/<新项目>/
  2. 编辑 <新项目>/index.js,改 idtabKeyordercomponent 指向。
  3. src/i18n/locales/zh-CN.jsen.jstabs 下新增对应的 tabKey 文案。
  4. 实现模块主组件与子组件(可复用 components/ui/ 基元)。
  5. npm run build -- 页签与路由自动出现,无需改动 TabNavrouter

已知限制

  • 排行榜依赖 /449/449rest.phpPHP + MySQL在线后端不可用时组件优雅降级显示「服务暂不可用」。
  • 演示视频 /448/ml/449ml.mp4(约 34 MBpreload="none",点播才加载。
  • 448/449 的 README 总结了既有项目(构建产物,无源码),见各自目录。
Description
No description provided
Readme 328 KiB
Languages
Vue 42.1%
JavaScript 41.5%
Shell 8.9%
CSS 6.7%
HTML 0.8%