# manager/meetings/detail — 端到端技术审查 (v2 修订) > **审查时间**: 2026-08-21 > **v1 修订**: v1 报告 §9 #1 标错 mapper 漏字段范围 (说 invitation_url/schedule_url/address 全漏, 实际只有 address 漏), 由 v2 实测 mapper 后修正 > **v2 触发**: 实际访问 `/manager/meetings/detail` 发现"会议地址"等字段不显示, 重新按 SKILL 4 跳 + DB 实测 + 三层穿透 > **审查范围**: `ry-vue3/src/views/manager/MeetingDetail.vue` (240 行) + `router/index.js:66` 路由 + 后端 `GET /business/meeting/{meetingId}` + `biz_meeting` DB 24 列实测 + `BizMeetingMapper.xml` 5 处 SELECT/UPDATE/INSERT 实测 > **对比原型**: `proto/html/components/meeting-detail.html` (300 行, manager 端 10 字段 + 2 张邀请函 + 2 张日程) > **依赖项**: 完整列表审查见 `_self/manager_meetings.md` v3 (DB/Entity/mapper 共享) --- ## 0. 4 跳定位 | 跳 | 文件:行 | 内容 | |---|---|---| | ① 角色菜单 | `ry-vue3/src/layout/AdminLayout.vue:97` | manager → 会议管理 (无此详情页菜单项, 是从列表"查看"按钮跳转的次级页) | | ② 路由 | `ry-vue3/src/router/index.js:66` | `name: 'manager-meetings-detail', path: 'meetings/detail/:meetingId'` ✓ | | ③ 组件 | `ry-vue3/src/views/manager/MeetingDetail.vue` (240 行) | 4 段: 基本信息 + 邀请函 + 日程 + 返回 | | ④ 原型 | `proto/html/components/meeting-detail.html` (300 行) | 3 段: 基本信息 (10 字段) + 邀请函 (2 张图+下载) + 日程 (2 张图+下载) + 返回 | --- ## 1. 主要功能 + 可见性 ### 1.1 主要功能 | 功能 | 前端入口 | 后端接口 | 数据表 | |---|---|---|---| | 加载会议详情 | `MeetingDetail.vue:138-152 load()` | `GET /business/meeting/{meetingId}` (`BizMeetingController.java:38-42`) | `biz_meeting` | | 返回列表 | `goBack()` → `router.push('/manager/meetings')` | — | — | | 邀请函预览/下载 | `` (line 60-70) | (无后端, 直链) | `biz_meeting.invitation_url` | | 日程预览/下载 | `` (line 82-92) | (无后端, 直链) | `biz_meeting.schedule_url` | ### 1.2 可见性 (三层过滤) | 层 | 来源 | 校验字段 | |---|---|---| | 前端菜单 | 无菜单项, 从列表"查看"按钮 router.push 进入 | | 路由守卫 | `router/index.js:66` | `meta.title` (无 role 字段, 实际靠 `meta.role='manager'` 父路由限制) | | 后端 SQL | `BizMeetingMapper.xml:33-36 selectByPrimaryKey` | ❌ 无任何过滤 (manager 端全可见, 见 manager_meetings.md §10 #1) | **数据隔离**: ❌ 缺失 (manager 端无 `lead_user_id` 过滤, 详情接口也未校验 project 归属)。 --- ## 2. 筛选项 (filter-form) **无** — 详情页只读, 无筛选。 --- ## 3. 工具栏 (toolbar) **无** — 详情页只有底部"返回"按钮 (对应原型 u11772): | 按钮 | 功能 | 接口 | 涉及表 | 原型对照 | |---|---|---|---|---| | 返回 | `goBack()` → `router.push('/manager/meetings')` | — | — | ✅ u11772 | --- ## 4. 表格 (el-table) **无** — 详情页只展示单条记录的字段, 不列表。 --- ## 5. 行内操作按钮 **无** — 详情页是只读视图, 无行内操作。 --- ## 6. Java Entity ↔ 数据库表 一致性 ### 6.1 biz_meeting DDL (DB 实测, 2026-08-21) `SHOW CREATE TABLE biz_meeting` 结果, 24 列 + 3 索引: | # | 列 | 类型 | 中文 COMMENT | 索引 | |---|---|---|---|---| | 1 | meeting_id | bigint NOT NULL AUTO_INCREMENT | 会议ID | PRIMARY | | 2 | business_id | varchar(50) NOT NULL | 业务流水ID 5643145673 | UNIQUE uk_business_id | | 3 | project_id | bigint NULL | 所属项目ID | idx_meeting_project | | 4 | project_no | varchar(50) NULL | 项目编号 | — | | 5 | project_name | varchar(200) NULL | 项目名称 | — | | 6 | meeting_name | varchar(200) NULL | 会议名称 | — | | 7 | period_no | int DEFAULT '1' | 期数 | — | | 8 | total_periods | int DEFAULT '1' | 总期数 | — | | 9 | project_form | varchar(20) NULL | 项目形式 | — | | 10 | start_time | datetime NULL | 会议开始时间 | — | | 11 | end_time | datetime NULL | 会议结束时间 | — | | 12 | org_name | varchar(200) NULL | 公司名称(冗余) | — | | **13** | **address** | **varchar(500) NULL** | **会议地址** | **—** | | 14 | current_stage | varchar(20) DEFAULT '0' | 当前阶段 未执行/待监管/监管通过/待整改/待结算/已结算/已结题 | idx_meeting_stage | | 15 | supervision_opinion | varchar(500) NULL | 监察意见 | — | | 16 | supervision_by | varchar(64) NULL | 监察人 | — | | 17 | supervision_time | datetime NULL | 监察时间 | — | | 18 | invitation_url | varchar(500) NULL | 邀请函URL | — | | 19 | schedule_url | varchar(500) NULL | 日程海报URL | — | | 20 | labor_signed | char(1) DEFAULT '0' | 签署劳务 0未签 1已签 | — | | 21 | create_by | varchar(64) DEFAULT '' | 创建者 | — | | 22 | create_time | datetime NULL | 创建时间 | — | | 23 | update_by | varchar(64) DEFAULT '' | 更新者 | — | | 24 | update_time | datetime NULL | 更新时间 | — | ### 6.2 4 层穿透字段对照矩阵 (本详情页相关) | # | DB 列 | Entity 有 | Mapper SELECT | Vue 渲染 | 原型 | 状态 | |---|---|---|---|---|---|---| | 1 | meeting_id | ✅ | ✅ | ✅ 会议ID | — | ✅ 富余 | | 2 | business_id | ✅ | ✅ | — | — | ⚠️ 内部审计字段 | | 3 | project_id | ✅ | ✅ | — | — | ⚠️ 内部 ID, 详情不显示 | | 4 | project_no | ✅ | ✅ | ✅ 项目编号 | ✅ | ✅ | | 5 | project_name | ✅ | ✅ | ✅ 项目名称 | ✅ | ✅ | | 6 | meeting_name | ✅ | ✅ | ✅ 会议名称 | ✅ | ✅ | | 7 | period_no | ✅ | ✅ | ✅ 期数 | ✅ | ✅ | | 8 | total_periods | ✅ | ✅ | ✅ 总期数 | ✅ | ✅ | | 9 | project_form | ✅ | ✅ | ✅ 项目形式 | — | ✅ 富余 (manager 端用) | | 10 | start_time | ✅ | ✅ | ✅ 会议开始时间 | ✅ | ✅ | | 11 | end_time | ✅ | ✅ | ✅ 会议结束时间 | ✅ | ✅ | | 12 | org_name | ✅ | ✅ | ✅ 支持单位 | ✅ | ✅ | | **13** | **address** | ✅ | **✅ v2 已修** | **✅ v2 已加** | — | ✅ **v2 修复完成** | | 14 | current_stage | ✅ | ✅ | ✅ 当前阶段 | — | ✅ 富余 | | 15-17 | supervision_* | ✅ | ✅ | ✅ 监察段 (条件) | — | ✅ 富余 | | 18 | invitation_url | ✅ | ✅ | ✅ 邀请函 (2 张) | ✅ | ✅ | | 19 | schedule_url | ✅ | ✅ | ✅ 日程 (2 张) | ✅ | ✅ | | 20 | labor_signed | ✅ | ✅ | ✅ 签署劳务 | — | ✅ 富余 | | 21 | create_by | ✅ | ✅ | ✅ 创建人员 | ✅ | ✅ | | 22 | create_time | ✅ | ✅ | ✅ 创建时间 | ✅ | ✅ | | 23-24 | update_by / update_time | ✅ | ✅ | — | — | ⚠️ 内部审计字段 | | — | (无) | ❌ | ❌ | (v2 已删) | — | ✓ 备注 dead field 已移除 | **v2 修复**: - `BizMeetingMapper.xml:17, 31, 69, 91, 115` 加 `address` (5 处) - `MeetingDetail.vue:42` 加 `row.address` 字段, 替换原 `row.remark` (dead field) **v2 验证**: 4 层穿透矩阵中 **24 列 DB 全部可达** (除内部审计字段), 详情页 14 字段渲染 + 邀请函/日程 2 张缩略图全部对得上数据源。 --- ## 7. 索引检查 详情接口走 `SELECT ... FROM biz_meeting WHERE meeting_id = #{meetingId}` (精确匹配 PK)。索引: | Key | 列 | 用途覆盖 | |---|---|---| | PRIMARY | meeting_id | ✅ 详情接口 WHERE 走 PK | | uk_business_id | business_id | (外部系统对接, 详情接口不用) | | idx_meeting_project | project_id | (列表 join 用, 详情接口不用) | | idx_meeting_stage | current_stage | (阶段筛选用, 详情接口不用) | 无需额外索引。 --- ## 8. 与原型差异 (proto/html/components/meeting-detail.html) ### 8.1 实现新增 (原型没有) — **改进** | 项 | 原型 | 实现 | 评估 | |---|---|---|---| | 当前阶段渲染带颜色 tag | 无 (纯文本) | ✅ stage-tag | 项目统一风格 | | 监察字段条件渲染 | 无 (静态展示) | ✅ 任一 supervision_* 有值才显示整段 | 避免空占位 | | 字段为空显示 "-" | 无 | ✅ | 数据完整性提示 | | 会议ID / 项目形式 / 当前阶段 / 签署劳务 | 无 | ✅ 4 项 | manager 端管理需要 | | 会议地址 | 无 | ✅ (v2 新增) | DB 有, 详情不显示会丢数据 | ### 8.2 原型有但实现缺失 — **v2 全部修复, 仅剩非 P0 项** | 原型 | 实现 v2 | 实现 v1 | 状态 | |---|---|---|---| | **邀请函 2 张缩略图** (原型 line 246-255, 2 个 `.preview-card` in `.preview-grid`) | ✅ 2 张 (line 60-69) | ❌ 1 张 | ✅ v2 修复 | | **日程 2 张缩略图** (原型 line 264-273) | ✅ 2 张 (line 82-91) | ❌ 1 张 | ✅ v2 修复 | | **会议地址** (DB + entity 都有, v1 mapper 漏 SELECT) | ✅ 渲染 (line 42) | ❌ 永远 - | ✅ v2 修复 | | 总场次/总期数 (原型 1 行) | 拆"总期数"+"期数"两列 | 同 | ✅ 更细 | ### 8.3 文字 / 标签差异 | 项 | 原型 | 实现 | 评估 | |---|---|---|---| | 面包屑 | "我参与的会议 > 会议详情" | "首页 / 会议管理 / 会议详情" | ✅ 角色匹配 (doctor → manager) | | 章节标题 h1 22px vs 项目色 | 16px 原型小字 | 14px 章节标题样式 | ✅ 跟项目内 ProjectsNew/ManagerProjectDetail 一致 | | 颜色 | `#1890ff` (浅蓝) | `var(--brand-primary)` (深海军蓝) | ✅ 项目色 | | 红字提示 *点击缩略图 | `#ff4d4f` 红字 | `#909399` 灰字 | ✅ 跟项目灰字风格一致 (ProjectsNew 调整时同步) | ### 8.4 总结 **v2 整体方向**: **完全 1:1 移植 + manager 端扩展** — 14 字段 (10 原型 + 4 manager 扩展: 会议ID/项目形式/当前阶段/签署劳务) + 监察段 + 邀请函 2 张 + 日程 2 张 + 返回, 跟原型 3 段结构完全对应。 --- ## 9. 设计问题 ### 9.1 ✅ v2 已修: address mapper 漏 (v1 报告 §9 #1 误标范围) **v1 错**: 报告说"invitation_url / schedule_url / address mapper 全套漏", 实际**只漏 address**。 **v2 重测**: - `invitation_url`: resultMap line 21, selectFields line 30, insert line 72, update line 116 — **全有** - `schedule_url`: resultMap line 22, selectFields line 30, insert line 73, update line 117 — **全有** - `business_id`: resultMap line 6, selectFields line 30, insert line 57, update line 101 — **全有** - `address`: entity 有, DB 有, **mapper 全套漏** (resultMap / selectFields / insert / update 都没) **v2 修复**: ```diff # BizMeetingMapper.xml + resultMap: + selectFields: ... org_name, address, current_stage ... + insert 列: address, + insert 值: #{address}, + update: address = #{address}, ``` ```diff # MeetingDetail.vue - {{ row.remark || '-' }} + {{ row.address || '-' }} ``` ### 9.2 dead field `remark` 已移除 (沿袭 list 页 bug) **v1 错**: v1 报告说"备注字段 dead field, 永远 -", 但仍保留渲染。 **v2 修复**: 从 MeetingDetail.vue 删 `row.remark` 渲染 (line 42)。**DB 端仍未补 `remark` 列**, 但前端对齐 — 不再误导用户。 **遗留**: `Meetings.vue:32` 列表页筛选 `remark` 字段 + `:67` 列表列仍用 `row.remark`, 永远 `-`。待 DDL 加 `remark text` 列 + 实体加 `private String remark` + mapper 加 `` 修复 (ManageList 侧独立 PR, P1)。 ### 9.3 工具函数重复 (沿袭 list 页 bug) `fmtDateTime` (MeetingDetail.vue:114-119) / `stageClass` (line 121-129) / `laborSignedLabel` (line 131-135) 与 `Meetings.vue` 里的 `fmtTime` / `stageClass` 重复 (实现几乎一致)。当前 2 处复制, 后续页面用到时建议提到 `src/utils/`。 ### 9.4 当前阶段 select 选项与 DB 实际数据不一致 (沿袭 list 页 bug) DB COMMENT 7 种 (未执行/待监管/监管通过/待整改/待结算/已结算/已结题), 当前 `stageClass` 函数只判 6 种 (未执行/执行中/已完结/已执行/待审核/待结算/冻结中), 命中"待监管/监管通过/待整改/已结算/已结题"时都 fallthrough 到 `default` class (灰色)。 **修复路径**: `stageClass` 加 4 个分支 (待监管/监管通过/待整改/已结算/已结题), 跟 DB COMMENT 完全对齐。 ### 9.5 数据隔离缺失 (manager 端) `BizMeetingMapper.xml:33-36 selectByPrimaryKey` 无 `userId` 过滤 (不像 `selectList` line 49 那样), 详情接口全可见。当前 DB 9 行测试数据无风险, **生产必修**。 --- ## 10. 待修复列表 (按优先级) | # | 问题 | 文件 | 修复建议 | 严重度 | |---|---|---|---|---| | 1 | **数据隔离缺失** (manager 端 selectByPrimaryKey 无 userId 过滤) | `BizMeetingMapper.xml:33` | 加 `and exists (select 1 from biz_meeting_attendee a ...)` | **P0** (生产必修) | | 2 | **`stageClass` 只覆盖 6 种, DB 实际 7 种** | `Meetings.vue` + `MeetingDetail.vue` | 加 4 个分支 (待监管/监管通过/待整改/已结算/已结题) → 命中非"未执行/执行中..."时不再 fallthrough 到 `default` | **P2** | | 3 | **工具函数 fmtDateTime/stageClass/laborSignedLabel 2 处重复** | `Meetings.vue` + `MeetingDetail.vue` | 提取到 `src/utils/meeting.js` (或 `src/utils/date.js` + `src/utils/stage.js`), 2 处 import | **P3** | | 4 | **`Meetings.vue` 列表页 `remark` 字段仍是 dead field** | `BizMeeting.java` + DDL + mapper + `Meetings.vue:32,67` | 完整链路: DDL `ALTER TABLE biz_meeting ADD COLUMN remark text` + entity `private String remark` + mapper UPDATE/INSERT 加 `` + 列表页/筛选同步 | **P1** | | 5 | **biz_user_role_bind 是废表, 业务表未清理** | `BizMeeting.java` 等 | (沿袭项目遗留, 不动) | — | | 6 | **路由 meta.title 与页面标题对齐** | `router/index.js:66` | `meta: { title: '会议详情' }` 当前正确, 无需改 | — | **v2 已修复**: - ✅ `BizMeetingMapper.xml` 5 处加 `address` 字段 (resultMap / selectFields / insert 列 / insert 值 / update) - ✅ `MeetingDetail.vue` 加 会议地址 字段渲染 (替换原 备注 dead field) - ✅ `MeetingDetail.vue` 邀请函 preview-grid 2 张缩略图 (原 1 张) - ✅ `MeetingDetail.vue` 日程 preview-grid 2 张缩略图 (原 1 张) - ✅ `MeetingDetail.vue` 删 备注 字段渲染 (dead field, 跟 list 页一致) --- ## 11. 引用清单 ### 前端 (本审查目标) - `ry-vue3/src/views/manager/MeetingDetail.vue:240` — 本审查目标 (v2 修复后) - `ry-vue3/src/views/manager/Meetings.vue:220` — 列表页 (调用 viewDetail 跳此页) - `ry-vue3/src/views/manager/ManagerProjectDetail.vue` — 同模式参考 - `ry-vue3/src/router/index.js:66` — 路由注册 - `ry-vue3/src/layout/AdminLayout.vue:97` — manager 菜单 (无详情页菜单项) - `ry-vue3/src/api/public.js:90` — `bizGet(entity, id)` → `GET /business/{entity}/{id}` ### 后端 (Java) - `ry-api/ruoyi-business/.../controller/BizMeetingController.java:38-42` — GET /{meetingId} - `ry-api/ruoyi-business/.../domain/BizMeeting.java:136` — 实体 (24 字段, 缺 remark) - `ry-api/ruoyi-business/.../mapper/BizMeetingMapper.java:10` — `selectByPrimaryKey` 接口 - `ry-api/ruoyi-business/.../resources/mapper/business/BizMeetingMapper.xml` — SELECT/INSERT/UPDATE SQL (v2 加 address 5 处) ### 原型 - `proto/html/manager.html` — 链接到 `components/meeting-detail.html` - `proto/html/components/meeting-detail.html:300` — 经理端会议详情原型 (3 段: 基本信息 10 字段 + 邀请函 2 张 + 日程 2 张 + 返回) - `proto/html/components/meeting-detail-page.html` — 同结构变体 (暂未用) ### 数据库 (实测 2026-08-21) - `biz_meeting` — 9 行 (24 列), AUTO_INCREMENT=12 - 实测样本: 所有 9 行的 `invitation_url` / `schedule_url` / `supervision_*` 均为 NULL (用户未上传) ### 配置 - `ry-api/ruoyi-admin/src/main/resources/application-druid.yml:9-10` — DB 连接 (root / cu2oh2co3) --- ## 附录: 修复记录 ### A.1 v1 → v2 修复 (2026-08-21 session 第二次审查) #### A.1.1 触发 - 用户实测访问 `/manager/meetings/detail` 发现"会议地址"等字段不显示 - 重读 v1 报告, 发现 §9 #1 标错 mapper 漏字段范围 (实际只漏 `address`, 报告误说 invitation_url/schedule_url 全漏) - 重新按 SKILL 4 跳 + DB 实测 + 三层穿透, 4 层穿透矩阵重现后才定位到真因 #### A.1.2 修复 1 — `BizMeetingMapper.xml` 加 address 字段 (5 处) ```diff @@ resultMap (line 17) @@ + @@ selectFields (line 31) @@ - select meeting_id, business_id, project_id, project_no, project_name, meeting_name, period_no, total_periods, project_form, start_time, end_time, org_name, current_stage, supervision_opinion, ... + select meeting_id, business_id, project_id, project_no, project_name, meeting_name, period_no, total_periods, project_form, start_time, end_time, org_name, address, current_stage, supervision_opinion, ... @@ insert 列 (line 69) @@ org_name, + address, current_stage, @@ insert 值 (line 91) @@ #{orgName}, + #{address}, #{currentStage}, @@ update (line 115) @@ org_name = #{orgName}, + address = #{address}, current_stage = #{currentStage}, ``` #### A.1.3 修复 2 — `MeetingDetail.vue` 基本信息加 会议地址, 删 dead 备注 ```diff ... - {{ row.remark || '-' }} + {{ row.address || '-' }} ``` #### A.1.4 修复 3 — `MeetingDetail.vue` 邀请函/日程 2 张缩略图 ```diff
- - - 邀请函 - +
+ + + 邀请函 + + + + 邀请函 + +
下载邀请函
``` #### A.1.5 修复 4 — `MeetingDetail.vue` CSS 加 `.preview-grid` ```diff + .preview-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + width: 100%; + max-width: 720px; + } .preview-card, .preview-empty { - width: 320px; + /* 由 grid 控制宽度 */ height: 180px; ... } ``` ### A.2 v1 修复 (2026-08-21 session 第一次审查) #### A.2.1 新建 `MeetingDetail.vue` (230 行) - 1:1 参照 `ManagerProjectDetail.vue` 的 page-card + breadcrumb + new-card-title 结构 - 字段映射: 14 项基本信息 + 监察段 + 邀请函/日程 + 返回 - URL 参数: `route.params.meetingId` (path param, 跟 `ManagerProjectDetail` 一致) #### A.2.2 router 加路由 (`ry-vue3/src/router/index.js:66`) ```js { path: 'meetings/detail/:meetingId', name: 'manager-meetings-detail', component: () => import('@/views/manager/MeetingDetail.vue'), meta: { title: '会议详情' } }, ``` #### A.2.3 `Meetings.vue` 删 dialog 改跳页面 (367 → 220 行) - `onView(row)` → `viewDetail(row)`, 内部 `router.push(/manager/meetings/detail/${row.meetingId})` - 删除: `` 整块, `detailOpen` / `currentRow` ref, `onView` / `calcRemain` / `laborSignedLabel` 函数, `.meeting-detail-dialog` 系列样式, 3 个 icon imports #### A.2.4 page-tech-review skill 加规则 - §5 加 "跳转形式"列 + 新 bullet "查看必须跳独立页面" - §10 铁律加第 10 条 ⛔ "查看不能用 dialog" ### A.3 v1 报告 §9 #1 错误的反思 **根本原因**: v1 审查时, **未严格按 SKILL §6 流程实测 DB**, 是基于"猜测"+"部分代码阅读"得出错误结论。 - v1 看了 mapper selectFields 头部字段列表, 但**没对比 entity / DB schema** - v1 推断"manager 全部字段基本都没 SELECT"是错的, 实际漏的只有 `address` 一个字段 - v1 没跑第 0 步"4 跳定位"清单, 跳过 DB 真实结构对比 **修正后的流程**: 1. §0 4 跳定位 (AdminLayout → router → 组件 → 原型) 2. §6.1 DB 实测 (SHOW CREATE TABLE) — 必须先做 3. §6.2 列三层穿透矩阵 (DB ↔ Entity ↔ Mapper SELECT ↔ Vue 渲染) 4. §6.3 任何字段缺失要列出真因 (DB 漏 / entity 漏 / mapper 漏 / Vue 漏) 5. §6.4 单独列"dead field"和"富余字段", 区分真丢失 vs 故意不显示 **记入 memory**: [feedback-report-scope-gaps] 升级 — 审查报告不能"差不多就行", 数据结构穿透必须 4 跳齐全 + DB 实测, **不实测就标"漏字段"是误导**。