Files
guoju0808/_self/manager_meetings.md
T

388 lines
24 KiB
Markdown
Raw 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.
# manager/meetings — 端到端技术审查
> **审查时间**: 2026-08-18
> **触发场景**: 用户访问 `/manager/meetings` (manager 角色)
> **审查范围**: `ry-vue3/src/views/manager/Meetings.vue` (会议管理列表页) + 后端 BizMeeting 全链路 + DB 实测
> **对比原型**: `proto/html/components/meetings.html` ("我参与的会议" doctor 端原型; 实装 manager 端复用 UI, 是合理的设计选择)
---
## 0. 4 跳定位 (铁律: 不按名字猜)
| 跳 | 文件:行 | 内容 |
|---|---|---|
| ① 角色菜单 | `ry-vue3/src/layout/AdminLayout.vue:99` | `path: '/manager/meetings', title: '会议管理'` ✓ |
| ② 路由 | `ry-vue3/src/router/index.js:69-70` | `name: 'manager-meetings', component: () => import('@/views/manager/Meetings.vue')` ✓ |
| ③ 组件 | `ry-vue3/src/views/manager/Meetings.vue` (343 行) | 列表 + 筛选 + 批量提交 + 查看/修改/提交/复制 |
| ④ 原型 | `proto/html/components/meetings.html` | 7 列表格 + 4 项筛选 (项目编号/会议名称/当前阶段/签署状态) |
---
## 1. 主要功能 + 可见性
### 1.1 主要功能
| 功能 | 前端入口 | 后端接口 | 数据表 |
|---|---|---|---|
| 筛选 + 分页列表 | `Meetings.vue` `<el-table>` + `<el-pagination>` | `GET /business/meeting/list` (BizMeetingController:24-29) | `biz_meeting` |
| 查看详情 (弹窗) | `onView(row)``el-dialog` + `el-descriptions` 只读 | 复用列表 row, 无额外请求 | `biz_meeting` |
| 修改会议 (弹窗) | `onEdit(row)``submitEdit()` | `PUT /business/meeting` (BizMeetingController:42-46) | `biz_meeting` |
| 提交 (单条) | `onSubmit(row)` → confirm → bizUpdate | `PUT /business/meeting` | `biz_meeting.current_stage` |
| 复制 (单条) | `onCopy(row)``editMode='copy'``submitEdit` 走 bizAdd | `POST /business/meeting` | `biz_meeting` 新行 |
| 批量提交 | `onBatchSubmit()` → for 循环逐条 bizUpdate | `PUT /business/meeting` × N | `biz_meeting.current_stage` |
### 1.2 可见性 (三层过滤)
| 层 | 来源 | 校验字段 |
|---|---|---|
| 前端菜单 | `AdminLayout.vue:99` | 角色 = manager |
| 路由守卫 | `router/index.js:69-70` | `meta.title` (无 role 字段, 由 menu 拦截) |
| 后端 SQL | `BizMeetingMapper.xml:37 selectList` | **❌ 无任何过滤** — 后端全量返回, 不按 unit_type / lead_user_id 隔离 |
**数据隔离**: ❌ **缺失** — manager 端没有 `@DataScope``lead_user_id` 过滤。当前 DB 7 行测试数据无风险, 生产环境会暴露全部会议 (见 §10 #1)。
**看不到本页面的人群**: admin / leader / doctor / executor / sponsor 各有独立 `/<role>/meetings` 路由 + 独立菜单项, 路由层就分开了。
---
## 2. 筛选项 (filter-form)
| UI label | 控件 | 绑定字段 | 后端 `<if>` | 命中表.字段 | 选项来源 | 原型对照 |
|---|---|---|---|---|---|---|
| 项目编号 | el-input (模糊) | `q.projectNo` | ✅ `project_no LIKE concat('%',...)` | `biz_meeting.project_no` | — | ✅ 项目编号 |
| 会议ID | el-input (精确) | `q.meetingId` | ✅ `meeting_id = #{meetingId}` | `biz_meeting.meeting_id` | — | ✅ 会议ID (原型有) |
| 会议名称 | el-input (模糊) | `q.meetingName` | ✅ `meeting_name LIKE concat('%',...)` | `biz_meeting.meeting_name` | — | ✅ 会议名称 |
| 第?期 | el-input-number | `q.periodNo` | ✅ `period_no = #{periodNo}` | `biz_meeting.period_no` | — | ✅ 第?期 (原型有) |
| 会议时间 (start~end) | el-date-picker × 2 | `q.startTime`, `q.endTime` | ✅ `start_time >=` + `end_time <=` | `biz_meeting.start_time/end_time` | — | ❌ 原型无 (实现增) |
| 项目形式 | el-select | `q.projectForm` | ✅ `project_form =` | `biz_meeting.project_form` | **写死** 4 项 (线上/线下/线上+线下/其他) | ❌ 原型无 (实现增) |
| 当前阶段 | el-select | `q.currentStage` | ✅ `current_stage =` | `biz_meeting.current_stage` | **写死** 4 项 (未执行/执行中/已执行/已完结) ⚠️ | ✅ 原型有 (但原型是 未开始/已结束) |
| 备注 | el-input (模糊) | `q.remark` | ❌ **缺失**`biz_meeting``remark` 列 | (无字段) | — | ❌ 原型无 |
**完整 SQL 块** (`BizMeetingMapper.xml:37-50`):
```sql
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, supervision_by, supervision_time,
invitation_url, schedule_url, labor_signed,
create_by, create_time, update_by, update_time
from biz_meeting
where [project_no LIKE] [AND meeting_id =] [AND meeting_name LIKE]
[AND period_no =] [AND project_form =] [AND current_stage =]
[AND start_time >=] [AND end_time <=]
order by meeting_id desc
```
8 项 filter 中 7 项生效; **remark filter 是死路** — 实体/表/INSERT 都没有此字段 (见 §6.3, §9 #3)。
---
## 3. 工具栏 (filter-form / batch-bar)
| 按钮 | 功能 | 接口 | 涉及表 | 原型对照 |
|---|---|---|---|---|
| 查找 | 触发 `load()` → bizList | `GET /business/meeting/list?...` | `biz_meeting` | ✅ 查找 |
| 重置 | 清空 q → load | 同上 | — | ❌ 原型无 |
| 批量提交 | `onBatchSubmit()` 逐条 update currentStage='执行中' | `PUT /business/meeting` × N | `biz_meeting.current_stage` | ❌ 原型无 (manager 专属) |
**提示行**: `<span v-if="selectedIds.length" class="filter-tip">已选 N 条</span>` — 推到 batch-bar 最右 (`.filter-tip { margin-left: auto }`)。
---
## 4. 表格 (el-table)
### 4.1 数据来源
见 §2 完整 SQL 块 (从 `BizMeetingMapper.xml:37-50` selectList + `BizMeetingMapper.xml:29-32` selectFields)。
### 4.2 列映射
| 列名 | row.* | DB 表.字段 | 原型对照 |
|---|---|---|---|
| 多选框 | (selection) | — | ❌ 原型无 (manager 专属) |
| 项目编号 | `row.projectNo` | `biz_meeting.project_no` | ✅ 项目编号 |
| 会议ID | `row.meetingId` | `biz_meeting.meeting_id` | ✅ 会议ID (原型有) |
| 项目形式 | `row.projectForm` | `biz_meeting.project_form` | ❌ 原型无 (实现增) |
| 会议名称 | `row.meetingName` | `biz_meeting.meeting_name` | ✅ 会议名称 |
| 会议开始时间 | `row.startTime` (fmtTime) | `biz_meeting.start_time` | ❌ 原型无 |
| 会议结束时间 | `row.endTime` (fmtTime) | `biz_meeting.end_time` | ❌ 原型无 |
| 总期数 | `row.totalPeriods` | `biz_meeting.total_periods` | ❌ 原型无 |
| 期数 | `row.periodNo` ("第 X 期") | `biz_meeting.period_no` | ❌ 原型无 |
| 当前阶段 | `row.currentStage` (stage-tag) | `biz_meeting.current_stage` | ✅ 当前阶段 |
| 备注 | `row.remark` (永远空, 见 §9 #3) | (无) | ❌ 原型无 |
| 操作 | 查看/修改/提交/复制 | — | ❌ 原型 1 个按钮 (签署劳务), manager 端 4 按钮 |
**新增列 (原型无, 实现增) ✅ 改进**: 项目形式, 开始/结束时间, 总期数, 期数, 多选框, 4 个操作按钮。
**遗漏列 (DB 有, 列表未显示)**:
- `org_name` (公司名称) — 列表可加
- `create_time` / `update_time` — 审计可用
- `labor_signed` (0/1) — 原型有 "签署状态" 列
- `invitation_url` / `schedule_url` — 原型有, 当前只在详情 dialog
---
## 5. 行内操作按钮
| 按钮 | 触发函数 | 接口 | 后端动作 | 涉及表.字段 | 原型对照 |
|---|---|---|---|---|---|
| 查看 | `onView(row)` | (无) | 弹 detailOpen dialog | — | ❌ 原型跳转 detail 页 |
| 修改 | `onEdit(row)``submitEdit()` | `PUT /business/meeting` | UPDATE biz_meeting SET meeting_name?, project_form?, start_time?, end_time?, total_periods?, remark? WHERE meeting_id=? | `biz_meeting` (6 字段) | ❌ 原型无 |
| 提交 | `onSubmit(row)` | `PUT /business/meeting` | UPDATE biz_meeting SET current_stage='执行中' WHERE meeting_id=? | `biz_meeting.current_stage` | ❌ 原型无 |
| 复制 | `onCopy(row)``submitEdit()` (走 `bizAdd`) | `POST /business/meeting` | INSERT biz_meeting (...); meetingId AUTO_INCREMENT, businessId 兜底雪花 ID | `biz_meeting` (新行) | ❌ 原型无 |
**真实落点**:
- **"提交"**: 直接 `UPDATE current_stage = '执行中'`, 无业务校验 (任何状态都能转, 包括"已完结"→"执行中" 状态回滚)。不写日志 (`biz_meeting_log` 表不存在)。
- **"修改"**: 改 6 字段 (无 `remark`, 详见 §9 #3); start_time > end_time 不校验; meetingName 空不校验。
---
## 6. Java Entity ↔ 数据库表 一致性
### 6.1 biz_meeting DDL (实测 2026-08-18)
```sql
CREATE TABLE `biz_meeting` (
`meeting_id` bigint NOT NULL AUTO_INCREMENT COMMENT '会议ID',
`business_id` varchar(50) NOT NULL COMMENT '业务编号ID',
`project_id` bigint DEFAULT NULL COMMENT '关联项目ID',
`project_no` varchar(50) DEFAULT NULL COMMENT '项目编号',
`project_name` varchar(200) DEFAULT NULL COMMENT '项目名称',
`meeting_name` varchar(200) DEFAULT NULL COMMENT '会议名称',
`period_no` int DEFAULT '1' COMMENT '期数',
`total_periods` int DEFAULT '1' COMMENT '总期数',
`project_form` varchar(20) DEFAULT NULL COMMENT '项目形式',
`start_time` datetime DEFAULT NULL COMMENT '会议开始时间',
`end_time` datetime DEFAULT NULL COMMENT '会议结束时间',
`org_name` varchar(200) DEFAULT NULL COMMENT '公司名称(冗余)',
`current_stage` varchar(20) DEFAULT '0' COMMENT '当前阶段 未执行/执行中/监管通过/待整改/待结算/已结算/已结题',
`supervision_opinion` varchar(500) DEFAULT NULL COMMENT '监察意见',
`supervision_by` varchar(64) DEFAULT NULL COMMENT '监察人',
`supervision_time` datetime DEFAULT NULL COMMENT '监察时间',
`invitation_url` varchar(500) DEFAULT NULL COMMENT '邀请函URL',
`schedule_url` varchar(500) DEFAULT NULL COMMENT '日程海报URL',
`labor_signed` char(1) DEFAULT '0' COMMENT '签署劳务 0未签 1已签',
`create_by` varchar(64) DEFAULT '' COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT '' COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`meeting_id`),
UNIQUE KEY `uk_business_id` (`business_id`),
KEY `idx_meeting_project` (`project_id`),
KEY `idx_meeting_stage` (`current_stage`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci COMMENT='会议表';
```
### 6.2 关联表
- `biz_project` — 见 `manager_projects.md` §6, 最近 `ALTER TABLE ADD COLUMN create_user_id bigint`
- `biz_person` — PK `person_id`, UNIQUE `uk_person_user_id (user_id)`, 用于 JOIN 取 create_user_name
### 6.3 Entity ↔ 表字段对照表
| 实体字段 | 中文列名 (DB COMMENT) | 实体类型 | 表字段 | 表类型 | 一致? |
|---|---|---|---|---|---|
| meetingId | 会议ID | Long | meeting_id | bigint | ✅ |
| businessId | 业务编号ID | String | business_id | varchar(50) | ✅ |
| projectId | 关联项目ID | Long | project_id | bigint | ✅ |
| projectNo | 项目编号 | String | project_no | varchar(50) | ✅ |
| projectName | 项目名称 | String | project_name | varchar(200) | ✅ |
| meetingName | 会议名称 | String | meeting_name | varchar(200) | ✅ |
| periodNo | 期数 | **Long** | period_no | **int** | ⚠️ 类型不一致 (MyBatis 自动转 OK) |
| totalPeriods | 总期数 | **Long** | total_periods | **int** | ⚠️ 类型不一致 (同上) |
| projectForm | 项目形式 | String | project_form | varchar(20) | ✅ |
| startTime | 会议开始时间 | Date | start_time | datetime | ✅ (有 @JsonFormat + @DateTimeFormat) |
| endTime | 会议结束时间 | Date | end_time | datetime | ✅ |
| orgName | 公司名称(冗余) | String | org_name | varchar(200) | ✅ |
| currentStage | 当前阶段 | String | current_stage | varchar(20) | ✅ |
| supervisionOpinion | 监察意见 | String | supervision_opinion | varchar(500) | ✅ |
| supervisionBy | 监察人 | String | supervision_by | varchar(64) | ✅ |
| supervisionTime | 监察时间 | Date | supervision_time | datetime | ✅ (有 @JsonFormat) |
| invitationUrl | 邀请函URL | String | invitation_url | varchar(500) | ✅ |
| scheduleUrl | 日程海报URL | String | schedule_url | varchar(500) | ✅ |
| laborSigned | 签署劳务 | String | labor_signed | char(1) | ✅ |
| createBy | 创建人 | String | create_by | varchar(64) | ✅ (BaseEntity, MetaObjectHandler 自动填) |
| createTime | 创建时间 | Date | create_time | datetime | ✅ |
| updateBy | 修改人 | String | update_by | varchar(64) | ✅ |
| updateTime | 修改时间 | Date | update_time | datetime | ✅ |
| — | (无 `remark` 字段) | — | (无 `remark` 列) | — | ❌ **实体缺 remark 字段** (见 §9 #3) |
**修订记录** (本节实体版本演进):
- 第一轮: meetingId String→Long, supervisionTime String→Date, INSERT/UPDATE/selectFields 补漏, businessId 雪花 ID 兜底 (commit 66a928a, 共享 manager_meeting_new.md)
- 第四轮: startTime/endTime 加 `@DateTimeFormat` (commit 14757f3) — 让前端 `"2026-08-18 10:00:00"` 字符串能 Spring 绑定到 Date
---
## 7. 索引检查
| 表 | Key | 列 | 用途覆盖 |
|---|---|---|---|
| biz_meeting | PRIMARY | meeting_id | ✅ ORDER BY + WHERE meeting_id = |
| biz_meeting | uk_business_id | business_id (UNIQUE) | ✅ 雪花 ID 防冲突 |
| biz_meeting | idx_meeting_project | project_id | ✅ `WHERE project_id =` (项目侧查会议) |
| biz_meeting | idx_meeting_stage | current_stage | ✅ `WHERE current_stage =` (filter 启用后生效) |
**缺失但暂可接受** (按 §2 筛选启用后):
- `idx_project_no``LIKE '%xxx%'` 模糊匹配无法走索引, 但当前 7 行可接受 (见 §10 #6)
- `idx_meeting_name` — 同上
- 复合 `(project_id, meeting_id)` — JOIN 用, 当前单 `project_id` 索引够
---
## 8. 与原型差异
### 8.1 实现新增 (原型没有) — **改进**
| 项 | 原型 | 实现 | 评估 |
|---|---|---|---|
| 筛选 会议ID / 第?期 / 会议时间 / 项目形式 / 备注 | 4 项 | 8 项 | ✅ manager 端管理需要 |
| 表格多选 + 批量提交 | 无 | ✅ | manager 专属 |
| 操作列 4 按钮 (查看/修改/提交/复制) | 1 按钮 | ✅ | 角色不同 |
| 分页 | 无 | ✅ | 必要 |
| 弹窗 (查看/修改) | 跳转 meeting-detail.html | ✅ 弹窗紧凑 |
### 8.2 原型有但实现缺失 — **回退**
| 原型 | 实现 | 差距 |
|---|---|---|
| "签署状态" 列 (`labor_signed`) | 仅 filter 8 项无此 (见 §10 #4) | ❌ 缺 filter + 列 |
| 弹框 邀请函 + 日程 (原型动态面板) | 无 | ❌ 原型专门有 |
| 顶部红字提示 | 无 | ❌ |
### 8.3 文字 / 标签差异
| 项 | 原型 | 实现 | 评估 |
|---|---|---|---|
| 面包屑 | 首页 > 我参与的会议 | 首页 / 会议管理 | ✅ 角色匹配 |
| 当前阶段 select | 未开始 / 已结束 | 未执行 / 执行中 / 已执行 / 已完结 | ⚠️ 实装更细, 但跟 DB 实际数据不一致 (见 §9 #1) |
| 颜色 | `#1890ff` (浅蓝) | `var(--brand-primary)` (深海军蓝) | ✅ 项目色 |
### 8.4 总结
**整体方向**: **扩展** — 实现远超原型 (manager 端多 5 列 + 批量提交 + 修改 dialog); 原型"邀请函/日程弹框"和"签署状态"未移植; "红字提示"未加。
---
## 9. 设计问题
> 集中列设计层面问题, 不重复 §10 (待修复)。已修的归附录 "修复记录"。
### 9.1 当前阶段 select 与 DB 实际数据不一致
DDL 注释列了 7 种 (未执行/执行中/监管通过/待整改/待结算/已结算/已结题), 但 DB 实际 6 种 (0/已结算/已结题/待整改/待监管/监管通过), 前端 select 又是另一套 4 种 (未执行/执行中/已执行/已完结)。**三者全不一致**, filter 启用后用户选"未执行"也筛不到任何数据。
### 9.2 calcRemain 读不存在的字段
`Meetings.vue:186``row.submitDeadlineDays`, 但 `BizMeeting` 实体无此字段 (BizProject 才有)。当前永远 fallback 到 30 天, 是个静默 bug (见 §10 #2)。
### 9.3 实体无 remark 字段
前端 3 处使用 (`Meetings.vue:32 q.remark`, `:67 row.remark`, `:125 editForm.remark`), 但 `BizMeeting` 实体无 `remark`, 表也无 `remark` 列。后果:
- filter "备注" 永远无效 (Spring `@ModelAttribute` 绑定到不存在的 setter 报 IllegalArgumentException? 实测 silent fail)
- 列表"备注"列永远空
- 详情 dialog"备注"行永远 `-`
- 修改 dialog "备注"输入框写入 → mapper UPDATE 无对应 `<if>` → 静默丢
修复路径有 2 条 (见 §10 #3)。
### 9.4 数据隔离缺失 (manager 端)
`BizMeetingMapper.xml:37 selectList``@DataScope``lead_user_id` 过滤。当前测试数据无风险, 生产必修 (见 §10 #1)。
### 9.5 状态回滚无校验
"提交" 操作任何 stage 都能转 "执行中", 包括 "已完结" → "执行中" (状态回滚)。应加前置校验 (见 §10 #5)。
---
## 10. 待修复列表 (严格只列未修)
| # | 问题 | 文件 | 修复建议 | 严重度 |
|---|---|---|---|---|
| 1 | **数据隔离缺失** (selectList 无 lead_user_id 过滤) | `BizMeetingMapper.xml:37` | 加 `<if test="params.leadUserId != null">and project_id in (select project_id from biz_project where lead_user_id = #{params.leadUserId})</if>`; Controller 注入当前 user_id | **P0** (生产必修) |
| 2 | **`calcRemain``row.submitDeadlineDays`** (BizMeeting 无此字段) | `Meetings.vue:186` | 改成读 `row.project?.submitDeadlineDays` (后端 JOIN biz_project); 或去此字段 (manager 不需要) | **P1** |
| 3 | **实体无 `remark` 字段** (前端 3 处 silent fail) | `BizMeeting.java` + `BizMeetingMapper.xml` | 路径 A: 加 `private String remark` + getter/setter + mapper UPDATE/INSERT 加 `<if>`; 路径 B: 前端 3 处全删 (业务可能不需要) | **P1** |
| 4 | **filter 缺"签署状态"** (原型有, 实体有 `labor_signed`) | `Meetings.vue` filter + table column | 加 `<el-select v-model="q.laborSigned">` 2 option + table 加列 | **P2** |
| 5 | **状态回滚无校验** (任何 stage → "执行中") | `Meetings.vue:271-273 onSubmit` + `:302-309 onBatchSubmit` | 加 `if (currentStage === '未执行')` 才能提交, 否则 ElMessageBox 提示 | **P2** |
| 6 | **筛选后端需补索引** (`idx_project_no` + `idx_meeting_name`) | `biz_meeting` table | `ALTER TABLE biz_meeting ADD KEY idx_project_no (project_no), ADD KEY idx_meeting_name (meeting_name);` (⚠️ `LIKE '%xxx%'` 模糊匹配无法走索引, 实际效果有限) | **P3** |
| 7 | **实体 periodNo/totalPeriods Long vs int** | `BizMeeting.java` | 改 int, MyBatis INSERT 不需 Long 转换 | **P3** |
| 8 | **当前阶段 select 选项跟 DB 实际数据不一致** (见 §9 #1) | `Meetings.vue:25-31` | 改成跟 DB 一致 (已结算/已结题/待整改/待监管/监管通过 等), 或加 DB 不存在的值 (DB 加 ENUM 同步) | **P1** |
| 9 | **filter 8 项挤一行** (屏幕窄乱) | `Meetings.vue:6-37` | 拆 2 行, 或 grid-template-columns: repeat(4, 1fr) | **P2** |
| 10 | **批量提交无事务/无批量 endpoint** | `Meetings.vue:302-309` | 后端加 `PUT /business/meeting/batch?ids=...` + `@Transactional`; 前端 for 循环改单次调用 | **P2** |
| 11 | **详情 dialog 缺字段** (create_time / org_name / supervision_* / labor_signed / invitation_url / schedule_url) | `Meetings.vue:91-103` | el-descriptions 加 5-8 行; URL 字段加 `<a :href>` 链接 | **P1** |
| 12 | **`totalPeriods` 永远 1** (MeetingNew.vue 没让填) | `MeetingNew.vue` | 加"总期数"字段 (用户填, INSERT 时一起写) | **P1** |
---
## 11. 引用清单
### 前端
- `ry-vue3/src/views/manager/Meetings.vue:343` — 本审查目标
- `ry-vue3/src/views/manager/MeetingNew.vue` — 新建会议独立页 (共享 BizMeeting)
- `ry-vue3/src/layout/AdminLayout.vue:99` — manager 菜单项
- `ry-vue3/src/router/index.js:69-70` — 路由
- `ry-vue3/src/utils/request.js:15-30` — axios 拦截器 (`__silentError` 跳过 toast)
- `ry-vue3/src/api/public.js:32, 92-93``bizList` / `bizUpdate` / `bizAdd`
### 后端 (Java)
- `ry-api/ruoyi-business/.../controller/BizMeetingController.java:54` — 5 endpoints
- `ry-api/ruoyi-business/.../domain/BizMeeting.java:107` — 24 字段, **缺 remark**
- `ry-api/ruoyi-business/.../service/impl/BizMeetingServiceImpl.java:34` — insert 调 SnowflakeId 兜底 businessId
- `ry-api/ruoyi-business/.../mapper/BizMeetingMapper.java` — mapper 接口
### Mapper XML
- `ry-api/ruoyi-business/src/main/resources/mapper/business/BizMeetingMapper.xml:128` — selectList 7 个 `<if>` 已生效
### 配置 / 工具
- `ry-api/ruoyi-admin/src/main/resources/application-druid.yml:9-10` — DB 连接 (root / cu2oh2co3)
- `ry-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/id/SnowflakeId.java` — 雪花 ID 生成器
- `ry-api/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java:27` — getUserId()
### 原型
- `proto/html/components/meetings.html:546` — "我参与的会议" 原型 (doctor 端, 实装 manager 重用)
- `proto/html/components/meeting-detail.html` — 会议详情原型 (现用 el-dialog 替代)
### 数据库 (实测 2026-08-18)
- `biz_meeting` — 7 行, 4 索引 (PK + UNIQUE + 2 普通), 23 列 (见 §6.1)
- `biz_project` — 12 行, 含 `create_user_id bigint` (commit ffda9c6)
- `biz_person` — JOIN `user_id → name`
---
## 附录: 修复记录 (按 commit 时间倒序)
> 已修的问题不进入 §10。本节按 commit 顺序列出, 每条标明 issue → fix → 验证。
### A.5 commit `bae9fa6` (2026-08-18) — 恢复会议ID + 第?期 filter (第五轮续)
- **背景**: 第四轮前后曾误删 `会议ID` / `第?期` filter, 用户澄清两个字段原型中都有.
- **修改**: `Meetings.vue:8` 加回 `<el-form-item label="会议ID">` (el-input); `Meetings.vue:10` 第?期从 el-input 改 el-input-number (`:min="0" :precision="0"`); `q` reactive + `reset()` 加回 `meetingId:''`; mapper `<if>` 块本就有, 无需动.
- **验证**: `q.meetingId=14` → 1 行; `q.periodNo=1` → 1 行; 留空 → 不影响其他筛选.
### A.4 commit `14757f3` (2026-08-18) — mapper selectList 加 7 个筛选 if + @DateTimeFormat (第四轮)
- **解决**: P0#1 全部筛选不生效 (`<where>` 空).
- **修改**: `BizMeetingMapper.xml:37-50` 加 7 个 `<if>` (project_no LIKE, meeting_id =, meeting_name LIKE, period_no =, project_form =, current_stage =, start_time >=, end_time <=); `BizMeeting.java:30-33` startTime/endTime 加 `@DateTimeFormat` 让 Spring 能绑字符串.
- **验证**: `LIKE %ZH-2026-6%` → 5 行; `current_stage=已结算` → 1 行; `start_time>=2026-03-01` → 4 行; `period_no=1` → 1 行; 组合 AND 正常.
### A.3 commits `6d4f1e6` + `6774c44` (2026-08-18) — style-alignment + 批量按钮去 plain (第三轮)
- **解决**: 批量按钮 disabled 顺色; "已选 X 条" 紧贴按钮左边; inline style 残留; batch-bar 属性顺序.
- **修改**: `Meetings.vue:41` 批量按钮去 `plain`; `Meetings.vue:324 .filter-tip { margin-left: auto }`; `<span class="date-sep">至</span>` 替代 inline style; `.batch-bar` 属性顺序对齐 People.vue.
### A.2 commit `08d81e9` (2026-08-18) — onCopy 改 bizAdd + 三处双 toast (第二轮)
- **解决**: P0#3 onCopy bug (meetingId='' 走 bizUpdate → 0 行 + 误报成功); P0#4 双 toast.
- **修改**: `Meetings.vue:222-228 editMode` ref + `Meetings.vue:246-267 submitEdit()` 按 editMode 分支 (copy → bizAdd, edit → bizUpdate); 三处 bizUpdate 加 `{ __silentError: true }`.
### A.1 commit `66a928a` (跨 session, manager_meeting_new.md 第一轮) — 数据库正确性
- 共享 `BizMeeting` 修复: meetingId String→Long, supervisionTime String→Date, INSERT/UPDATE/selectFields 补漏, businessId 雪花 ID 兜底 (13 项).
- 详细见 `manager_meeting_new.md` §修复记录 第一轮.
### 跨页相关 commit (影响本页但不直接修改)
- `ffda9c6` — biz_project 加 `create_user_id` (影响 §6.2)
- `a081da8` — MeetingNew.vue "期数" 文案改 "请填写第几期" (独立页)
- `4fbfcbf` + `8f62f65` + `518da05` + `29a4b02` + `379cf22` + `ac31387` — MeetingNew.vue 原型 1:1 重写 + 双 toast 修复