# 嘉宾排序系统 **Repository Path**: mehuli/guest-sorting-system ## Basic Information - **Project Name**: 嘉宾排序系统 - **Description**: (含前后端) - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-25 - **Last Updated**: 2026-04-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # paizuo-vue 基于 Vue 3 + Vite 对原始排座系统进行重构的前端项目,目标是将 html 目录中的原型页面逐步迁移为可维护、可扩展、可回归验证的工程化实现。 当前重构重点放在会议排座页面,已具备本地保存、导入导出、上下文工具栏、分区树、亮暗主题、打印预览与视觉回归测试能力。 ## 项目目标 - 将原始静态页面重构为 Vue 3 单页应用 - 保持与原始页面尽量一致的 UI、交互与数据结构 - 通过亮色/暗色视觉回归测试持续约束重构偏差 - 为后续功能演进提供更清晰的组件、状态与脚本结构 ## 技术栈 - Vue 3 - Vite - Vue Router - Pinia - xlsx - Playwright - pixelmatch - pngjs ## 目录结构 - src/main.js:应用入口 - src/router/index.js:路由配置 - src/views/MeetingFull.vue:会议排座重构主页面 - src/views/BanquetFull.vue:宴会排座重构页面 - src/views/PreviewFull.vue:预览页 - src/views/Setup.vue:场次初始化页 - src/stores:状态管理 - src/utils:存储、统计等工具函数 - scripts/meeting-visual-regression.mjs:会议页视觉回归脚本 - artifacts/meeting-visual:会议页亮色回归产物 - artifacts/meeting-visual-dark:会议页暗色回归产物 ## 开发命令 安装依赖: ```bash npm install ``` 启动开发环境: ```bash npm run dev ``` 构建生产包: ```bash npm run build ``` 本地预览构建结果: ```bash npm run preview ``` ## 回归测试 会议页亮色视觉回归: ```bash npm run regression:meeting-visual ``` 会议页暗色视觉回归: ```bash npm run regression:meeting-visual:dark ``` 其他脚本: ```bash npm run regression:meeting npm run regression:banquet ``` 说明: - 视觉回归会先对原始 html 页面和 Vue 重构页面注入相同测试场次数据,再输出原图、重建图和 diff 图 - 亮色回归产物位于 artifacts/meeting-visual - 暗色回归产物位于 artifacts/meeting-visual-dark ## 当前能力概览 - 会议页本地保存、最近编辑、打印与打印预览 - 工具栏上下文操作、排序、分区、过道和舞台管理 - 左侧分区树与画布选中联动 - 亮色/暗色主题切换与本地记忆 - 会议页亮色与暗色视觉回归链路 - 画布快捷操作:保存、撤销、重做、重置视图、全选、搜索、打印、删除清空嘉宾信息、空格平移 ## 画布配置 JSON 说明 会议页“导出 JSON”导出的内容就是当前画布布局对象;本地保存到 localStorage 时,只保留 scenes 和 recent 这一层容器,单场次 value 直接保存布局对象。 ### 会议页布局对象 示例: ```json { "sceneId": "scene_xxxxx", "eventName": "会议排座", "sceneType": "meeting", "gridRows": 12, "gridCols": 18, "activeCards": [0, 1], "deletedCards": [8], "lockedCards": [3], "cardPartitions": [[0, "A区"]], "partitionCustomColors": [["A区", "#3b82f6"]], "cardOrderNumbers": [[0, 1]], "cardGuestNames": [[0, "张三"]], "cardGuestUnits": [[0, "示例单位"]], "cardGuestTitles": [[0, "示例职务"]], "aisleBlocks": [{ "cardIndices": [20, 21] }], "stageBlocks": [{ "cardIndices": [40, 41, 42] }], "zoomLevel": 100, "panX": 0, "panY": 0, "savedAt": 1713000000000 } ``` 字段说明: | 字段 | 类型 | 说明 | | --- | --- | --- | | sceneId | `string` | 场次唯一标识,用于本地保存和预览页读取。 | | eventName | `string` | 当前场次名称。 | | sceneType | `string` | 场次类型,会议页固定为 meeting。 | | gridRows | `number` | 网格总行数。 | | gridCols | `number` | 网格总列数。 | | activeCards | `number[]` | 已启用卡片索引列表。通常表示已有有效座位内容或启用状态。 | | deletedCards | `number[]` | 被删除但仍保留占位格的卡片索引列表。 | | lockedCards | `number[]` | 锁定卡片索引列表。 | | cardPartitions | `Array<[number, string]>` | 卡片索引到分区名称的映射数组。 | | partitionCustomColors | `Array<[string, string]>` | 分区名称到自定义颜色值的映射数组,颜色格式通常为十六进制。 | | cardOrderNumbers | `Array<[number, number]>` | 卡片索引到编号的映射数组。 | | cardGuestNames | `Array<[number, string]>` | 卡片索引到嘉宾姓名的映射数组。 | | cardGuestUnits | `Array<[number, string]>` | 卡片索引到单位名称的映射数组。 | | cardGuestTitles | `Array<[number, string]>` | 卡片索引到职务名称的映射数组。 | | aisleBlocks | `object[]` | 过道块列表。每项至少包含 cardIndices,合并过道时还可能包含 originalAisles。 | | stageBlocks | `object[]` | 舞台块列表。每项包含 cardIndices。 | | zoomLevel | `number` | 当前画布缩放百分比,范围通常为 10 到 300。 | | panX | `number` | 当前画布水平平移量。 | | panY | `number` | 当前画布垂直平移量。 | | savedAt | `number` | 当前布局对象生成时间戳。 | 补充说明: - 卡片索引使用从 0 开始的一维索引,计算方式为 row * gridCols + col。 - cardPartitions、cardOrderNumbers、cardGuestNames 等字段采用“键值对数组”而不是对象,便于序列化和兼容旧数据。 - aisleBlocks 示例:`{ "cardIndices": [20, 21, 22] }` - 合并过道的 aisleBlocks 还可能包含 `originalAisles`,例如:`{ "cardIndices": [20, 21, 22, 38], "originalAisles": [[20, 21, 22], [21, 38]] }` - stageBlocks 示例:`{ "cardIndices": [40, 41, 42, 43] }` ### 本地场次存储外层结构 localStorage 中的 `paizuo_layout_scenes_v1` 使用的是“外层场次字典 + 最近列表”结构,scenes[sceneId] 直接就是布局对象。 示例: ```json { "scenes": { "scene_xxxxx": { "sceneId": "scene_xxxxx", "eventName": "会议排座", "sceneType": "meeting", "savedAt": 1713000000000, "gridRows": 12, "gridCols": 18 } }, "recent": ["scene_xxxxx"] } ``` 外层字段说明: | 字段 | 类型 | 说明 | | --- | --- | --- | | scenes | `object` | 以 sceneId 为 key 的场次字典,value 直接为具体布局对象。 | | recent | `string[]` | 最近编辑场次列表,按最近访问顺序排列。 | | scenes[sceneId] | `object` | 具体画布布局对象,字段见上文。 | | scenes[sceneId].sceneId | `string` | 场次 id。 | | scenes[sceneId].eventName | `string` | 场次显示名称。 | | scenes[sceneId].sceneType | `string` | 场次类型。 | | scenes[sceneId].savedAt | `number` | 场次最近保存时间。 | 兼容说明:读取时仍兼容旧版 `scenes[sceneId] = { sceneName, sceneType, savedAt, layout }` 结构;保存新数据时会统一写成上面的直接布局对象格式。 如果要手动构造导入文件,会议页“导入场次布局”读取的是上面的“会议页布局对象”,不需要再额外包 scenes 外层。 ## 版本说明 详细变更记录见 [VERSION.md](./VERSION.md)。 ## 说明 - dist、artifacts 为构建与回归产物目录 - node_modules 不参与版本说明维护 - 如果需要继续压缩视觉差异,建议优先结合 diff 图微调会议页的暗色主题细节