# 商城服务协议 — 前端技术方案

> **依据：** 《商城服务协议功能需求.md》v1.0、《商城服务协议技术方案.md》v1.0  
> **前端规范：** `doc/前端设计/前端设计.md`  
> **原型参考：** 同目录 `Snipaste_2026-05-28_15-59-09.jpg`（启用 + 富文本 + 提交）  
> **范围：** 仅 **ruoyi-ui 平台管理端** 单页配置；C 端注册/登录勾选 **不在 ruoyi-ui 实现**。  
> **实现状态：** 页面与 API 封装已落地，待后端 `/agri/mallServiceAgreement` 联调。

---

## 1. 技术栈与写法约定

| 项 | 说明 |
|----|------|
| 框架 | Vue 2 + Element UI |
| 请求 | `@/utils/request` |
| 参考页面 | `merchantEntryAgreement/index.vue`（同构单页协议配置） |
| 与入驻协议关系 | **UI 与交互同构**，API 路径与权限标识不同 |
| 启用字段 | `"0"` / `"1"` |

---

## 2. 文件清单

| 类型 | 路径 | 说明 |
|------|------|------|
| 页面 | `ruoyi-ui/src/views/agri/content/mallServiceAgreement/index.vue` | 服务协议配置 + 预览 |
| API | `ruoyi-ui/src/api/agri/mallServiceAgreement.js` | GET / PUT |

**组件 name：** `MallServiceAgreement`

---

## 3. 菜单与路由

| 菜单名称 | 组件路径 | 路由 path（建议） | 权限标识 |
|----------|----------|-------------------|----------|
| 商城服务协议 | `agri/content/mallServiceAgreement/index` | `mallServiceAgreement` | `agri:mallServiceAgreement:query` |

**上级菜单：** 农资管理 → **内容管理**

| 按钮权限 | 标识 |
|----------|------|
| 保存 | `agri:mallServiceAgreement:edit` |

---

## 4. 页面结构

```text
商城服务协议（单页 · el-card）
├── 卡片标题 + 说明文案
│   └── 「关闭启用后 C 端无法新注册；已注册会员登录不再要求勾选本协议」（SP4）
├── 表单
│   ├── 协议标题 agreementTitle
│   ├── 协议版本号 versionLabel
│   ├── 是否启用 enableFlag
│   ├── 最后更新 updateBy / updateTime（只读）
│   ├── 协议内容 content（Editor）
│   └── 预览 + 保存
└── 预览弹窗
```

### 4.1 与原型对照

| 原型（Snipaste） | 本实现 |
|------------------|--------|
| 标题「服务协议」 | 卡片 header「商城服务协议」 |
| 「启用协议」开关 | 「是否启用」单选（是/否），值 `1`/`0` |
| 顶部说明段落 | 卡片 header 右侧灰色说明（SP4 文案） |
| 「内容」富文本 + 工具栏 | 全局 `Editor` 组件 |
| 「提交」按钮 | 「保存」按钮 + `agri:mallServiceAgreement:edit` |

额外字段（功能需求 §4～§5）：协议标题、版本号、最后更新人/时间、预览按钮。

---

## 5. 复用组件

| 组件 | 用途 |
|------|------|
| `Editor` | 富文本，`min-height="280"` |

校验工具 `isBlankHtml` 与入驻协议页 **相同实现**（可后续抽公共 util，本期不抽以保持简单）。

---

## 6. API 对接

**基路径：** `/agri/mallServiceAgreement`

| 前端方法 | HTTP | 路径 | 说明 |
|----------|------|------|------|
| `getMallServiceAgreement` | GET | `/` | 加载配置 |
| `saveMallServiceAgreement` | PUT | `/` | 保存配置 |

### 6.1 字段映射

与入驻协议一致，表字段对应：

| 前端 | 后端 |
|------|------|
| agreementTitle | agreement_title |
| versionLabel | version_label |
| content | content |
| enableFlag | enable_flag |

### 6.2 保存请求体

```json
{
  "agreementTitle": "农资商城用户服务协议",
  "versionLabel": "v1.0",
  "content": "<p>...</p>",
  "enableFlag": "1",
  "remark": ""
}
```

---

## 7. 校验规则

| 规则 | 说明 |
|------|------|
| 标题必填 | AP 对齐：请输入协议标题 |
| 启用=是 时正文必填 | 启用状态下请填写协议内容 |
| 空白 HTML | 协议内容不能为空 |

`enableFlag` 切换时触发 `content` 字段重新校验。

---

## 8. 权限指令

```html
v-hasPermi="['agri:mallServiceAgreement:edit']"
```

---

## 9. 与 C 端、会员模块边界

| 端 | 接口 | ruoyi-ui 本期 |
|----|------|---------------|
| 平台 | `/agri/mallServiceAgreement` | ✅ |
| C 端 | `GET /api/member/serviceAgreement` | ❌ 另端 |
| 会员注册 | `POST /api/member/register` + `agreementAccepted` | ❌ 会员模块 |
| 会员登录 | `POST /api/member/login` + `agreementAccepted`（协议启用时） | ❌ 会员模块 |

**SP4 前端说明（配置页文案）：** 协议 `enableFlag=0` 时，C 端不可新注册；已注册且会员启用的用户登录 **不要求** 勾选——该逻辑在 C 端/会员 Facade 实现，平台页仅展示提示。

---

## 10. 与商城入驻协议前端差异

| 项 | 入驻协议 | 服务协议（本模块） |
|----|----------|-------------------|
| 页面路径 | `.../merchantEntryAgreement/` | `.../mallServiceAgreement/` |
| API | `/agri/merchantEntryAgreement` | `/agri/mallServiceAgreement` |
| 权限前缀 | `agri:merchantEntryAgreement:*` | `agri:mallServiceAgreement:*` |
| 卡片说明文案 | 拦新 **商家入驻** | 拦新 **会员注册** + 老用户登录不勾选 |
| 默认标题（SQL 种子） | 农资商城商家入驻协议 | 农资商城用户服务协议 |

页面 `.vue` 结构 intentionally 同构，便于维护。

---

## 11. 联调检查清单

- [ ] GET/PUT 基路径正确  
- [ ] 启用且无正文时保存失败  
- [ ] 禁用时可保存空正文  
- [ ] 富文本超长时后端返回明确 msg（512KB 上限）  
- [ ] 保存后 updateBy/updateTime 更新  

---

## 12. 非本期（前端）

协议历史、勾选存证、C 端注册/登录页、下单页二次协议、多语言。

---

## 13. 修订记录

| 版本 | 日期 | 说明 |
|------|------|------|
| v1.0 | 2026-05 | 首版：单页配置；对齐原型与功能需求 v1.0 |

---

*文档版本：v1.0 · ruoyi-ui · 关联《商城服务协议功能需求.md》v1.0*
