# 我的预约（专家）— 技术方案

> 依据：`我的预约(专家)功能需求.md`（同目录）；关联 `我的预约(兽医)技术方案.md`、`我的预约(机构)技术方案.md`

---

## 1. 技术架构

| 项 | 说明 |
| --- | --- |
| **整体** | RuoYi **v3.9.2**（**springboot2** 分支）单体后端 + 若依 **Vue2** 管理端 |
| **运行时** | JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
| **数据库** | MySQL **5.7.39**，InnoDB，`utf8mb4` |
| **专家资源** | `biz_tech_resource`（专家 `resource_type=004005`，`sys_user_id` 绑定登录用户，角色 **`exp`**） |
| **预约数据** | 与兽医/机构共用 **`biz_service_appointment`**；评价 **`biz_service_appointment_review`**（专家独有） |
| **移动端** | 预约 `INSERT`、取消、写评价由「预约服务」完成；本模块为**专家后台查询、接单、查评价** |

**后端分层（专家模块）**

| 层 | 职责 |
| --- | --- |
| `Controller` | 列表/详情/确认/拒绝/评价列表；`@PreAuthorize`；`AjaxResult` / `TableDataInfo` |
| `Service` | 解析当前专家 `provider_id`、状态机、越权、拒绝理由校验、评价只读查询 |
| `Mapper` + XML | 预约表 `provider_type=3`；评价表按 `appointment_id` |
| `support` | `ExpertProviderResolver`、`ExpertAppointmentValidation`、`ExpertAppointmentStatusResolver`；复用 `ServiceAppointmentRules`（`diagnosis` 包） |

**代码包（建议）**：`com.ruoyi.web.modules.farming`（与畜牧科技资源同域）  
**共用（兽医已建，跨包引用）**：`BizServiceAppointment`、`BizServiceAppointmentMapper`、`ServiceAppointmentRules`（`com.ruoyi.web.modules.diagnosis`）  
**初始化脚本**：`sql/biz_service_appointment.sql`（须已执行）；`sql/biz_service_appointment_review.sql`（本期新增）

---

## 2. 关联方案设计（三端共用）

### 2.1 统一预约主表 `biz_service_appointment`

| `provider_type` | 服务对象 | `provider_id` 指向 | 后台模块 | 移动端提交后 `status` |
| --- | --- | --- | --- | --- |
| `1` | 兽医 | `biz_medical_resource.id`（`resource_type=1`） | 我的预约（兽医） | `0` 待确认 |
| `2` | 诊疗机构 | `biz_medical_resource.id`（`resource_type=3`） | 我的预约（机构） | `5` 已预约 |
| **`3`** | **科技专家** | **`biz_tech_resource.id`（`resource_type=1`）** | **我的预约（专家）** | **`0` 待确认** |

专家与兽医**接单制、五态**一致；与机构**登记制、三态**隔离。

### 2.2 状态枚举（库表 `status`）

| 值 | 常量 | 专家/兽医展示 | 专家列表可筛 | 机构 |
| --- | --- | --- | --- | --- |
| `0` | `PENDING` | 待确认 | ✓ | — |
| `1` | `CONFIRMED` | 已确认 | ✓ | — |
| `2` | `REJECTED` | 已拒绝 | ✓ | — |
| `3` | `CANCELLED` | 已取消 | ✓ | ✓ |
| `4` | `COMPLETED` | 已完成 | ✓ | ✓ |
| `5` | `BOOKED` | — | — | ✓（已预约） |

应用层：`provider_type=3` 时，`status` 仅允许 **`0～4`**；筛选 `5` 视为非法；列表**不得出现** `5`。

### 2.3 三端接口对照

| 模块 | Base Path | 写操作 | 评价 |
| --- | --- | --- | --- |
| 兽医 | `/diseaseTreatment/myAppointment/vet` | 确认、拒绝 | 无 |
| 机构 | `/diseaseTreatment/myAppointment/org` | 无 | 无 |
| **专家（本文档）** | **`/techService/myAppointment/expert`** | **确认、拒绝** | **`GET .../reviewList/{id}`** |

### 2.4 当前登录人解析（专家）

```text
loginUser.userId
  → biz_tech_resource
      WHERE sys_user_id = ? AND resource_type = 1
        AND account_assigned = 1 AND del_flag = '0'
  → provider_id = id

列表/操作 WHERE provider_type = 3 AND provider_id = ?
```

无绑定：列表返回空；写操作/详情越权返回「未绑定专家资源，无法查询预约」/「无法操作」。

**Mapper 扩展（与兽医 `selectVetResourceBySysUserId` 对称）**

```sql
SELECT ... FROM biz_tech_resource
WHERE sys_user_id = #{sysUserId}
  AND resource_type = 1
  AND account_assigned = 1
  AND del_flag = '0'
LIMIT 1
```

### 2.5 专家与兽医/机构差异（实现约束）

| 项 | 专家 | 兽医 | 机构 |
| --- | --- | --- | --- |
| 资源表 | `biz_tech_resource` | `biz_medical_resource` | `biz_medical_resource` |
| 包路径 | `farming` | `diagnosis` | `diagnosis` |
| 列表列 | 完整（含拒绝理由） | 完整 | 精简 |
| 确认/拒绝 | ✓（`status=0`） | ✓ | — |
| 评价子表 | ✓ | — | — |
| 详情已完成 | 联查评价星级+综合评价 | 无评价区 | 无评价区 |

处置逻辑（确认/拒绝/状态机）**复用兽医实现模式**；评价为专家增量。

---

## 3. 数据库设计

### 3.1 复用表 `biz_service_appointment`

专家模块**不重复建预约主表**；字段与兽医方案一致。专家侧关心字段：

| 字段 | 专家用途 |
| --- | --- |
| `provider_type` | 固定 `3` |
| `provider_id` | `biz_tech_resource.id` |
| `appointee_name`～`service_requirement` | 列表 + 详情 |
| `status` | `0～4` |
| `reject_reason` / `confirm_time` / `reject_time` | 拒绝/确认流程 |

**DDL**：见 `sql/biz_service_appointment.sql`（已存在则无需重复执行）。

### 3.2 新增表 `biz_service_appointment_review`（专家评价）

| 字段 | 类型 | 非空 | 说明 |
| --- | --- | --- | --- |
| `id` | `bigint(20)` | Y | 主键 |
| `appointment_id` | `bigint(20)` | Y | 关联 `biz_service_appointment.id` |
| `reviewer_name` | `varchar(64)` | Y | 评价人姓名 |
| `review_time` | `datetime` | Y | 评价时间 |
| `punctuality_score` | `tinyint(4)` | Y | 到场准时（1～5 星） |
| `attitude_score` | `tinyint(4)` | Y | 服务态度（1～5 星） |
| `guidance_score` | `tinyint(4)` | Y | 指导效果（1～5 星） |
| `summary` | `varchar(200)` | N | 综合评价（移动端 ≤100 字） |
| `create_time` | `datetime` | N | 创建时间 |

**索引**：`PRIMARY KEY (id)`；`KEY idx_appointment_id (appointment_id)`。

**DDL（MySQL 5.7）**

```sql
CREATE TABLE IF NOT EXISTS `biz_service_appointment_review` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `appointment_id` bigint(20) NOT NULL COMMENT '预约ID',
  `reviewer_name` varchar(64) NOT NULL COMMENT '评价人姓名',
  `review_time` datetime NOT NULL COMMENT '评价时间',
  `punctuality_score` tinyint(4) NOT NULL COMMENT '到场准时1-5',
  `attitude_score` tinyint(4) NOT NULL COMMENT '服务态度1-5',
  `guidance_score` tinyint(4) NOT NULL COMMENT '指导效果1-5',
  `summary` varchar(200) DEFAULT NULL COMMENT '综合评价',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_appointment_id` (`appointment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务预约评价(专家)';
```

**约定**：评价由移动端写入；后台**只读**；通常一条预约对应一条评价，表结构支持多条以便扩展。

### 3.3 专家列表查询（Mapper XML 语义）

```sql
WHERE provider_type = 3 AND provider_id = #{providerId}
  <if test="appointeeName != null and appointeeName != ''">
    AND appointee_name LIKE concat('%', #{appointeeName}, '%')
  </if>
  <if test="startDate != null and startDate != ''">
    AND appoint_date &gt;= #{startDate}
  </if>
  <if test="endDate != null and endDate != ''">
    AND appoint_date &lt;= #{endDate}
  </if>
  <if test="status != null">
    AND status = #{status}
  </if>
ORDER BY appoint_date DESC, create_time DESC, id DESC
```

**详情/越权**：`id` + `provider_type=3` + `provider_id=当前专家`。

**确认/拒绝更新**（与兽医对称，`provider_type=3`）：

```sql
-- 确认：status 0 → 1，写 confirm_time
-- 拒绝：status 0 → 2，写 reject_reason、reject_time
WHERE id = #{id} AND provider_type = 3 AND provider_id = #{providerId} AND status = 0
```

**评价列表**：

```sql
SELECT reviewer_name, review_time, summary, punctuality_score, attitude_score, guidance_score
FROM biz_service_appointment_review
WHERE appointment_id = #{appointmentId}
ORDER BY review_time DESC, id DESC
```

详情接口在 `status=4` 时可联查**最新一条**评价填充星级与 `summary`（或 Service 二次查询）。

---

## 4. 接口设计（专家）

统一响应：RuoYi `AjaxResult` / `TableDataInfo`（`code`、`msg`、`data` / `rows`、`total`）。

**权限标识（示例）**：`techService:expertMyAppointment:list|query|confirm|reject|complete|reviewList`

**Base Path（示例）**：`/techService/myAppointment/expert`

| # | 说明 | Method | URI | 权限 | 要点 |
| --- | --- | --- | --- | --- | --- |
| 4.1 | 分页列表 | GET | `/list` | `...:list` | Query：`pageNum`（默认 1）、`pageSize`（默认 **20**）、`appointeeName`、`startDate`、`endDate`（`yyyy-MM-dd`）、`status`（**`0～4`**）；**禁止**传 `providerId` |
| 4.2 | 详情 | GET | `/{id}` | `...:query` | 校验归属；返回预约全字段 + `statusLabel`；**已完成**且存在评价时附带 `punctualityScore`、`attitudeScore`、`guidanceScore`、`summary`（及展示用星标文案可选） |
| 4.3 | 确认接诊 | POST | `/confirm/{id}` | `...:confirm` | 前置 `status=0`；更新 `status=1`，`confirm_time` |
| 4.4 | 拒绝接诊 | POST | `/reject/{id}` | `...:reject` | Body：`rejectReason`（必填 1～100 字）；前置 `status=0`；更新 `status=2` |
| 4.5 | 完成接诊 | POST | `/complete/{id}` | `...:complete` | 前置 `status=1`；更新 `status=4` |
| 4.6 | 评价列表 | GET | `/reviewList/{id}` | `...:reviewList` | 前置预约 `status=4` 且归属当前专家；返回评价行列表 |

### 4.1 列表响应字段（建议）

`id`、`appointeeName`、`appointDate`、`timeStart`、`timeEnd`、`contactPhone`、`serviceAddress`、`serviceRequirement`、`status`、`statusLabel`、`rejectReason`、`createTime`。

### 4.2 详情 `data` 补充（已完成 + 有评价）

| 字段 | 说明 |
| --- | --- |
| `punctualityScore` | 到场准时 1～5 |
| `attitudeScore` | 服务态度 1～5 |
| `guidanceScore` | 指导效果 1～5 |
| `summary` | 综合评价全文 |

无评价：上述字段为空或不返回；前端展示「暂无评价」。

### 4.3 评价列表 `rows[]` 字段

| 字段 | 说明 |
| --- | --- |
| `reviewerName` | 评价人姓名 |
| `reviewTime` | 评价时间 |
| `summary` | 综合评价 |
| `punctualityScore` / `attitudeScore` / `guidanceScore` | 可选下发，供列表扩展列 |

### 4.4 拒绝 Body

```json
{ "rejectReason": "时段冲突无法接诊" }
```

校验规则与兽医一致：trim 后 1～100 字。

### 4.5 业务错误（`msg` 示例）

| 场景 | 文案 |
| --- | --- |
| 日期筛选 | 结束日期不能早于开始日期 |
| 状态筛选非法 | 状态筛选无效 |
| 无专家绑定 | 未绑定专家资源，无法查询预约 / 无法操作 |
| 越权 | 无权操作该预约记录 / 无权查看该预约记录 |
| 非待确认 | 当前状态不允许确认接诊 / 当前状态不允许拒绝接诊 |
| 已取消 | 该预约已取消，无法操作 |
| 拒绝理由 | 请填写拒绝理由 / 拒绝理由不能超过 100 字 |
| 评价 | 仅已完成预约可查看评价；暂无评价 |

### 4.6 三端接口差异（实现对照）

| 能力 | 专家 | 兽医 | 机构 |
| --- | --- | --- | --- |
| 列表 | `GET .../expert/list` | `GET .../vet/list` | `GET .../org/list` |
| 详情 | `GET .../expert/{id}` | `GET .../vet/{id}` | `GET .../org/{id}` |
| 确认 | `POST .../expert/confirm/{id}` | `POST .../vet/confirm/{id}` | — |
| 拒绝 | `POST .../expert/reject/{id}` | `POST .../vet/reject/{id}` | — |
| 评价 | `GET .../expert/reviewList/{id}` | — | — |

---

## 5. 实现要点

| 项 | 说明 |
| --- | --- |
| 越权 | 所有 `id` 操作校验 `provider_type=3` 且 `provider_id=当前专家` |
| 状态机 | 确认/拒绝仅 `status=0`；与兽医相同并发策略 |
| 评价只读 | 无 POST/PUT 评价接口；`reviewList` 前校验预约已完成且归属 |
| 串单防护 | `provider_type=3` 且 `status=5` 记日志并过滤或报错 |
| 复用 | `ServiceAppointmentRules`、`VetAppointmentRejectBody` 可迁至公共包或 farming 内复制 `ExpertAppointmentRejectBody` |
| 日志 | `@Log` 记录确认、拒绝；查看评价按平台惯例 |
| 组件路径 | `techService/myAppointment/expert/index`（「牧业养殖科技服务」目录下） |

**建议新增类（专家）**

| 类 | 职责 |
| --- | --- |
| `BizTechResourceMapper.selectExpertResourceBySysUserId` | 解析 `provider_id` |
| `BizServiceAppointmentMapper` 扩展 | `selectExpertAppointmentList`、`selectExpertAppointmentByIdAndProvider`、`updateConfirmExpertAppointment`、`updateRejectExpertAppointment` |
| `BizServiceAppointmentReview` + Mapper | 评价实体与查询 |
| `ExpertMyAppointmentServiceImpl` + `BizExpertMyAppointmentController` | 业务与 HTTP |
| `ExpertAppointmentValidation` / `ExpertAppointmentStatusResolver` | 校验与标签（五态，同兽医） |

---

## 6. 与上下游衔接

| 系统 | 说明 |
| --- | --- |
| 移动端预约服务 | `INSERT`：`provider_type=3`，`status=0` |
| 移动端取消 | `status=3` |
| 移动端写评价 | `INSERT` `biz_service_appointment_review`（预约须 `status=4`） |
| 已完成 | 业务闭环置 `status=4` 后用户方可评价 |
| 畜牧科技资源管理 | 专家已发布且分配账号（`role_key=exp`） |
| 我的预约（兽医/机构） | 同表不同 `provider_type`；列表互不可见 |

---

## 7. 菜单与权限（示例）

| 类型 | 名称 | 权限标识 |
| --- | --- | --- |
| 菜单 | 我的预约（专家） | `techService:expertMyAppointment:list` |
| 按钮 | 查询 | `techService:expertMyAppointment:query` |
| 按钮 | 确认接诊 | `techService:expertMyAppointment:confirm` |
| 按钮 | 拒绝接诊 | `techService:expertMyAppointment:reject` |
| 按钮 | 完成接诊 | `techService:expertMyAppointment:complete` |
| 按钮 | 查看评价 | `techService:expertMyAppointment:reviewList` |

---

## 8. 交付清单

- [ ] `sql/biz_service_appointment_review.sql`  
- [ ] `BizTechResourceMapper.selectExpertResourceBySysUserId`  
- [ ] `BizServiceAppointmentMapper` 专家查询/更新 + XML（`provider_type=3`）  
- [ ] `BizServiceAppointmentReview` + Mapper + XML  
- [ ] `ExpertMyAppointmentController` + Service + 校验/状态解析  
- [ ] 菜单权限 SQL（专家）  
- [ ] 单元测试 + MockMvc（列表 scope、确认、拒绝、评价、越权）  

---

## 9. 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初稿：共用预约主表；新增评价表；专家接口与兽医对齐并扩展 reviewList；三端关联与 farming 包定位 |
