# 服务费与律师收款接口文档

版本：`v1`  
更新时间：`2026-03-26`

---

## 统一响应结构

所有接口统一返回 `R<T>`：

- `code`：状态码（`200` 成功，非 `200` 失败）
- `msg`：提示信息
- `data`：业务数据

---

## 一、律师收款账号接口

BasePath：`/lawyer/user`

### 1. 保存微信收款账号

- **URL**：`POST /lawyer/user/saveWechatAccount`
- **Content-Type**：`application/json`

请求体（统一对象 `LawyerPaymentAccountDto`）：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lawyerId | Integer | 是 | 律师ID |
| wechatId | String | 是 | 微信ID |
| wechatName | String | 是 | 微信名称 |
| aliId | String | 否 | 统一DTO字段，可不传 |
| aliName | String | 否 | 统一DTO字段，可不传 |
| bankCardNo | String | 否 | 统一DTO字段，可不传 |
| bankName | String | 否 | 统一DTO字段，可不传 |

请求示例：

```json
{
  "lawyerId": 1001,
  "wechatId": "wx_appid_xxx",
  "wechatName": "张三微信"
}
```

成功返回示例：

```json
{
  "code": 200,
  "msg": "保存成功",
  "data": true
}
```

---

### 2. 保存支付宝收款账号

- **URL**：`POST /lawyer/user/saveAlipayAccount`
- **Content-Type**：`application/json`

请求体：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lawyerId | Integer | 是 | 律师ID |
| aliId | String | 是 | 支付宝ID |
| aliName | String | 是 | 支付宝名称 |
| wechatId | String | 否 | 统一DTO字段，可不传 |
| wechatName | String | 否 | 统一DTO字段，可不传 |
| bankCardNo | String | 否 | 统一DTO字段，可不传 |
| bankName | String | 否 | 统一DTO字段，可不传 |

请求示例：

```json
{
  "lawyerId": 1001,
  "aliId": "ali_appid_xxx",
  "aliName": "张三支付宝"
}
```

---

### 3. 保存银行卡收款账号

- **URL**：`POST /lawyer/user/saveBankAccount`
- **Content-Type**：`application/json`

请求体：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lawyerId | Integer | 是 | 律师ID |
| bankCardNo | String | 是 | 银行卡号 |
| bankName | String | 是 | 开户行名称 |
| wechatId | String | 否 | 统一DTO字段，可不传 |
| wechatName | String | 否 | 统一DTO字段，可不传 |
| aliId | String | 否 | 统一DTO字段，可不传 |
| aliName | String | 否 | 统一DTO字段，可不传 |

请求示例：

```json
{
  "lawyerId": 1001,
  "bankCardNo": "622202xxxxxx",
  "bankName": "中国建设银行"
}
```

---

### 4. 查询律师收款账号

- **URL**：`GET /lawyer/user/getPaymentAccounts?lawyerId=1001`

Query 参数：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lawyerId | Integer | 是 | 律师ID |

`data` 返回字段：

| 字段 | 类型 | 说明 |
|---|---|---|
| lawyerWechatId | String | 微信ID |
| lawyerWechatName | String | 微信名称 |
| lawyerAliId | String | 支付宝ID |
| lawyerAliName | String | 支付宝名称 |
| bankCardNo | String | 银行卡号 |
| bankName | String | 开户行名称 |

---

## 二、服务费规则接口

BasePath：`/store/serviceFee`

### 1. 服务费列表

- **URL**：`GET /store/serviceFee/list`

Query 参数：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| storeId | Integer | 是 | 门店ID |
| name | String | 否 | 名称模糊查询 |
| status | Integer | 否 | 0关闭/1开启 |
| pageNum | Integer | 否 | 默认1 |
| pageSize | Integer | 否 | 默认10 |

返回：`IPage<StoreServiceFeeRuleListVo>`

主要字段：

| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 规则ID |
| feeName | String | 服务费名称 |
| feeType | Integer | 1按人数/2按桌台/3按消费金额 |
| feeValue | BigDecimal | 金额/比例 |
| status | Integer | 状态 |
| effectiveMode | String | PERMANENT/CUSTOM |
| tableCount | Integer | 适用桌台数量 |
| updatedTime | DateTime | 更新时间 |

---

### 2. 服务费详情（编辑回显）

- **URL**：`GET /store/serviceFee/detail?id=10`

Query 参数：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | Integer | 是 | 规则ID |

返回：`StoreServiceFeeRuleDetailVo`

| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 规则ID |
| storeId | Integer | 门店ID |
| feeName | String | 名称 |
| feeType | Integer | 类型 |
| feeValue | BigDecimal | 金额/比例 |
| status | Integer | 状态 |
| effectiveMode | String | PERMANENT/CUSTOM |
| startDate | String | yyyy-MM-dd |
| endDate | String | yyyy-MM-dd |
| tableIds | Integer[] | 适用桌台 |
| slots | Slot[] | 生效时段 |

`Slot` 字段：
- `weekdayMask`：Integer（周一到周日按位标记）
- `startTime`：String（`HH:mm:ss`）
- `endTime`：String（`HH:mm:ss`）

---

### 3. 新建服务费

- **URL**：`POST /store/serviceFee/create`
- **Content-Type**：`application/json`

请求体（`StoreServiceFeeRuleSaveDto`）：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| storeId | Integer | 是 | 门店ID |
| feeName | String | 是 | 名称（同店唯一） |
| feeType | Integer | 是 | 1按人数/2按桌台/3按消费金额 |
| feeValue | BigDecimal | 是 | 金额或比例 |
| status | Integer | 是 | 0关闭/1开启 |
| effectiveMode | String | 是 | PERMANENT/CUSTOM |
| startDate | String | CUSTOM时必填 | yyyy-MM-dd |
| endDate | String | CUSTOM时必填 | yyyy-MM-dd |
| tableIds | Integer[] | 是 | 适用桌台ID |
| slots | Slot[] | 是 | 生效星期+时段 |

请求示例：

```json
{
  "storeId": 1,
  "feeName": "晚市服务费",
  "feeType": 1,
  "feeValue": 5.00,
  "status": 1,
  "effectiveMode": "CUSTOM",
  "startDate": "2026-01-01",
  "endDate": "2026-12-31",
  "tableIds": [101, 102],
  "slots": [
    {
      "weekdayMask": 62,
      "startTime": "15:00:00",
      "endTime": "18:00:00"
    }
  ]
}
```

成功返回：`data` 为新建规则ID（Integer）

---

### 4. 编辑服务费

- **URL**：`POST /store/serviceFee/update`
- **Content-Type**：`application/json`

请求体：同“新建服务费”，另需 `id`（必填）

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | Integer | 是 | 规则ID |

---

### 5. 删除服务费

- **URL**：`POST /store/serviceFee/delete?id=123`

Query 参数：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | Integer | 是 | 规则ID |

---

### 6. 桌台列表

- **URL**：`GET /store/serviceFee/tableList?storeId=1&categoryId=2`

Query 参数：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| storeId | Integer | 是 | 门店ID |
| categoryId | Integer | 否 | 分类ID |

返回：`List<StoreBookingTableVo>`

主要字段：

| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 桌台ID |
| storeId | Integer | 门店ID |
| categoryId | Integer | 分类ID |
| categoryName | String | 分类名称 |
| tableNumber | String | 桌号 |
| seatingCapacity | Integer | 座位数 |

---

## 三、业务校验规则（前后端联调重点）

### 1. 名称唯一校验
- 同一 `storeId` 下，`feeName` 不允许重复。
- 返回提示：`服务费名称已存在`

### 2. 生效日期校验
- `effectiveMode = CUSTOM` 时，`startDate/endDate` 必填，且 `startDate <= endDate`。
- 返回提示：`开始日期不能大于结束日期`

### 3. 生效时间校验
- 每个时段 `startTime < endTime`。
- 返回提示：`生效开始时间必须早于结束时间`

### 4. 桌台+时间重叠校验
- 同店同桌台下，若“日期有交集 + 星期有交集 + 时段有交集”，则判定重叠。
- 返回提示：`桌台[xxx]服务费时间重叠，请调整生效日期/星期/时间`

### 5. 同桌台同时间段类型限制
- 同店同桌台同时间段下，只能存在一种 `feeType`。
- 返回提示：`桌台[xxx]在该时间段已配置其他类型服务费`

---

## 四、常见错误提示（可直接前端toast）

- `门店ID不能为空`
- `服务费名称不能为空`
- `服务费类型不能为空`
- `服务费金额不能为空`
- `服务费状态不能为空`
- `生效模式不能为空`
- `适用桌台不能为空`
- `生效时段不能为空`
- `服务费名称已存在`
- `开始日期不能大于结束日期`
- `生效开始时间必须早于结束时间`
- `桌台[xxx]服务费时间重叠，请调整生效日期/星期/时间`
- `桌台[xxx]在该时间段已配置其他类型服务费`

