# 店铺管理 — 前端技术方案

> **依据：** 《店铺管理功能需求.md》v1.3.6、《店铺管理技术方案.md》v1.3  
> **实现状态：** 列表/添加/编辑/账号管理/删除已对齐 v1.3.6；待后端 `/agri/shop` 联调。

---

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

| 项 | 说明 |
|----|------|
| 框架 | Vue 2 + Element UI |
| 请求 | `@/utils/request` |
| 参考页面 | `ruoyi-ui/src/views/agri/content/banner/index.vue` |
| 选商户 | 复用 `selectMerchantList`、`openShopCheck`（`@/api/agri/merchant`） |
| 店铺状态 | `0` 开业 / `1` 停业 |

---

## 2. 文件清单

| 类型 | 路径 | 说明 |
|------|------|------|
| 页面 | `ruoyi-ui/src/views/agri/org/shop/index.vue` | 列表、开店/编辑弹窗、账号管理弹窗 |
| API | `ruoyi-ui/src/api/agri/shop.js` | 店铺 CRUD、删店预检、账号查询/修改 |
| API | `ruoyi-ui/src/api/agri/merchant.js` | `selectMerchantList`、`openShopCheck` |

**组件 name：** `AgriShop`

---

## 3. 菜单与路由

| 菜单名称 | 组件路径 | 路由 path（建议） | 权限标识 |
|----------|----------|-------------------|----------|
| 店铺管理 | `agri/org/shop/index` | `shop` | `agri:shop:list` |

**上级菜单：** 农资管理 → **组织管理**

| 按钮权限 | 标识 |
|----------|------|
| 添加店铺 | `agri:shop:add` |
| 编辑店铺 | `agri:shop:edit` |
| 删除店铺 | `agri:shop:remove` |
| 账号管理 | `agri:shop:account` |

> **店铺设置** 已独立菜单，见《店铺设置前端技术方案.md》；本页 **无** 逐店设置入口。

---

## 4. 页面结构

```text
店铺管理
├── 检索区（el-card）
│   ├── 关键词 keyword（店铺名/商户名/经营账号）
│   ├── 店铺状态 shopStatus
│   └── 商户名称 merchantName（支持路由 query 带入）
├── 列表区（el-card + border 表格）
│   ├── 列：名称、头像、商户名、状态、经营账号
│   └── 操作：编辑、账号管理、删除
├── 添加/编辑弹窗（640px）
│   ├── 公共：名称、头像、电话、描述
│   ├── 添加：选商户、经营账号只读展示、店铺状态（选填，默认开业）
│   └── 编辑：所属商户/经营账号只读、店铺状态（开业/停业）
└── 账号管理弹窗（560px）
    ├── 提示：修改同步至该商户下全部店铺
    ├── 下属店铺标签列表
    └── 登录名、管理员姓名、重置密码
```

---

## 5. v1.3 / v1.3.6 对齐要点

| 变更项 | 前端处理 |
|--------|----------|
| 添加店铺 **不再** 采集 loginName/adminName/password | 添加弹窗无账号输入项 |
| 经营账号由 **商户入驻** 绑定 | 选商户后 `getShopAccount` 只读展示；无账号阻断 |
| `shop_phone` 添加/编辑 **均选填** | 有值时校验 `^[0-9\-+()\s]{5,20}$`；**编辑不再必填** |
| `shop_status` 添加时 **选填** | 未选默认后端 0（开业） |
| 账号登录名 | 对应 `sys_user.user_name`，**11 位手机号**；`validateLoginName`；脱敏回显时 placeholder 提示 |
| 编辑 PUT | `buildUpdatePayload` 仅含 shopId/名称/头像/描述/状态/电话；不含 merchantId |
| 停业 S12 | 仅 `0→1` 时传 `confirm:false` → needConfirm → `confirm:true` |
| 改登录名 | 登录名变更时 `confirm:false/true` 两步；未改登录名不传 confirm |
| 开店/删店 | `openShopCheck` + 账号校验；`deleteShopCheck` 展示 reasons |

---

## 6. 复用组件

| 组件 | 用途 |
|------|------|
| `ImageUpload` | 店铺头像，limit=1，5MB，png/jpg/jpeg |
| `ImagePreview` | 列表头像缩略图 |
| `Pagination` / `RightToolbar` | 分页与检索显隐 |

---

## 7. API 对接

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

| 前端方法 | HTTP | 路径 | 调用场景 |
|----------|------|------|----------|
| `listShop` | GET | `/list` | 列表 |
| `getShop` | GET | `/{shopId}` | 编辑回显（含经营账号摘要） |
| `addShop` | POST | `/` | 添加店铺（**不含**账号字段） |
| `updateShop` | PUT | `/` | 编辑店铺 |
| `deleteShopCheck` | GET | `/{shopId}/deleteCheck` | 删除预检 |
| `delShop` | DELETE | `/{shopIds}` | 删除 |
| `getShopAccount` | GET | `/merchant/{merchantId}/account` | 添加时展示账号、账号管理回显 |
| `updateShopAccount` | PUT | `/merchant/{merchantId}/account` | 保存账号 |

**协作接口（merchant.js）：**

| 方法 | 路径 | 用途 |
|------|------|------|
| `selectMerchantList` | GET `/agri/merchant/selectList` | 添加店铺选商户 |
| `openShopCheck` | GET `/agri/merchant/{id}/openShopCheck` | 选商户后可开店校验 |

### 7.1 列表请求参数

| 字段 | 说明 |
|------|------|
| keyword | 模糊店铺名、商户名、账号 |
| shopStatus | `0` / `1` |
| merchantName | 模糊；路由 `?merchantName=` 自动填入 |

### 7.2 添加店铺请求体（v1.2.5）

```json
{
  "shopName": "张三农资店",
  "shopAvatar": "/profile/upload/xx.jpg",
  "shopPhone": "010-88886666",
  "shopDesc": "",
  "merchantId": 1,
  "shopStatus": "0"
}
```

- `shopPhone`、`shopDesc`、`shopStatus` 均可省略；`shopStatus` 省略时后端默认 **开业(0)**。
- **不传** `loginName` / `adminName` / `password`；商户须已在入驻时绑定 `biz_merchant_account`。

### 7.3 编辑店铺 · 停业二次确认（S12）

1. 首次 `PUT` 带 `shopStatus: "1"`（开业→停业），不传 `confirm` 或 `confirm: false`
2. 若 `response.data.needConfirm === true`，弹窗 `confirmMessage`
3. 用户确认后再次 `PUT`，带 `confirm: true`

### 7.4 账号管理 · 改登录名 confirm

与停业流程相同：`needConfirm` + `confirm: true` 两步协议；文案含「同步至该商户下全部店铺」。

### 7.5 删除预检

`GET /{shopId}/deleteCheck` 返回 `canDelete`、`reasons[]`；`canDelete=false` 时前端直接 `msgWarning`，不弹二次确认。

---

## 8. 交互与校验

| 场景 | 前端行为 |
|------|----------|
| 选商户变更 | `openShopCheck` → 不通过则清空并提示 reason |
| 选商户变更 | `getShopAccount` → 无账号则提示「尚未配置经营账号…」并清空 |
| 选商户成功 | 只读展示「管理员 / 脱敏登录名」 |
| 添加提交 | `buildAddPayload()` 仅含店名字段；校验 `merchantAccountOk` |
| 编辑 | `merchantId`、经营账号 **不可改**（走账号管理） |
| 商家电话 | 添加/编辑 **均选填**；有值时 `validateShopPhone`（5～20 位电话字符） |
| 账号登录名 | 11 位手机号 `/^1[3-9]\d{9}$/`；GET 仅脱敏时用 placeholder 提示补全 |
| 编辑提交 | `buildUpdatePayload` 白名单字段；停业/改登录名 confirm 两步 |
| 删除 | 先 `deleteShopCheck`，通过后二次确认再 `DELETE` |
| 经营账号展示 | 列表 `accountAdminName / accountLoginName`（后端脱敏） |

---

## 9. 权限指令

```html
v-hasPermi="['agri:shop:add']"
v-hasPermi="['agri:shop:edit']"
v-hasPermi="['agri:shop:remove']"
v-hasPermi="['agri:shop:account']"
```

---

## 10. 与关联模块边界

| 模块 | 关系 |
|------|------|
| 商户管理 | 经营账号在 **新增入驻/审核通过** 时绑定；选商户须经营完整且已有账号 |
| 店铺设置 | 全局免审开关 **不在** 本页配置 |
| 商品管理 | 删店前置无出售中/待审核商品（后端 deleteCheck） |

---

## 11. 联调检查清单

- [ ] 编辑店铺可不填商家电话保存成功  
- [ ] 账号登录名非 11 位手机号前端拦截  
- [ ] 编辑 PUT body 不含 merchantId / 账号字段  
- [ ] 路由 query `merchantName` 筛选生效  
- [ ] 添加店铺 **无** 账号输入项，POST body 无 loginName/adminName/password  
- [ ] 商户无经营账号时添加被阻断  
- [ ] 同商户第二家店添加成功，列表账号展示一致  
- [ ] 开业→停业 needConfirm 两步  
- [ ] 改登录名 needConfirm 两步  
- [ ] deleteCheck 阻断并展示 reasons  
- [ ] 列表 accountLoginName 脱敏展示  

---

## 12. 非本期（前端）

商家端店铺资料页（`/agri/seller/shop`）、子管理员 CRUD、导出。

---

## 13. 修订记录

| 版本 | 日期 | 说明 |
|------|------|------|
| v1.3 | 2026-06 | v1.3.6：编辑电话选填、登录名 11 位、buildUpdatePayload、confirm 精细化 |
| v1.2 | 2026-05 | v1.3 文档：编辑电话亦选填；登录名 11 位手机号 |
| v1.1 | 2026-05 | 对齐 v1.2.5：移除添加账号字段、openShopCheck、deleteCheck |
| v1.0 | 2026-05 | 首版：列表 CRUD、账号管理、停业/改登录名 confirm |

---

*文档版本：v1.3 · ruoyi-ui · 关联《店铺管理功能需求.md》v1.3.6、《店铺管理技术方案.md》v1.3*
