# 配送设置 — 前端技术方案

> **依据：** 《配送设置功能需求.md》v1.1、《配送设置技术方案.md》v1.3  
> **前端规范：** `doc/前端设计/前端设计.md`  
> **范围：** 仅 **ruoyi-ui 商家端** 当前店铺 **发货信息** 查询与保存（Upsert）；**不含** 运费模版、订单发货、平台维护。  
> **实现状态：** 页面与 API 封装已落地，待菜单配置及 `/agri/seller/delivery` 联调。

---

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

| 项 | 说明 |
|----|------|
| 框架 | Vue 2 + Element UI |
| 请求 | `@/utils/request` + `sellerShopHeaders()` 携带 **`X-Shop-Id`** |
| 参考页面 | `agri/seller/shop/index.vue`（单店设置、上下文加载） |
| 省市区 | 复用 `mixins/regionCascader.js` + `GET /agri/region/tree`（经 `getRegionCascaderTree` 规范化） |
| 布局 | 单页 **`el-card` + 表单**（无检索区、无列表） |
| 店铺切换 | **仅 Navbar**；业务页禁止展示店铺选择器 |

---

## 2. 文件清单

| 类型 | 路径 | 说明 |
|------|------|------|
| 设置页 | `ruoyi-ui/src/views/agri/seller/delivery/index.vue` | 发货信息表单、保存 |
| 配送 API | `ruoyi-ui/src/api/agri/seller/delivery.js` | GET / PUT |
| 省市区 | `api/agri/region.js` + `utils/region.js` + `mixins/regionCascader.js` | 级联选择与落库 |
| 店铺上下文 | `api/agri/seller/context.js` + `utils/sellerShop.js` | X-Shop-Id |

**组件 name（keep-alive）：** `AgriSellerDelivery`

---

## 3. 菜单与路由

| 菜单名称 | 组件路径 | 路由 path（建议） | 权限标识 |
|----------|----------|-------------------|----------|
| 配送设置 | `agri/seller/delivery/index` | `seller/delivery` | `agri:seller:delivery:query` |

**上级菜单：** 店铺经营管理端 → **物流相关**（与 **运费模版** 并列）

| 按钮权限 | 标识 | 说明 |
|----------|------|------|
| 查询 | `agri:seller:delivery:query` | 进入页面、GET 回显 |
| 保存 | `agri:seller:delivery:edit` | 「保存」按钮与 PUT |

---

## 4. 页面结构

```text
配送设置（每店一份 · 单页表单）
└── 发货信息设置（el-card）
    ├── 引导提示（未配置时 el-alert）
    ├── 发货人 shipperName *
    ├── 发货人联系方式 shipperMobile *（11 位手机）
    ├── 发货地区 shipRegionCascader *（省/市/区县级联 → region.regionCode）
    ├── 发货详细地址 detailAddress *
    ├── 最近更新 updateTime（只读，有数据时展示）
    └── 保存（Upsert，无删除）
```

**不提供：** 列表、删除、多仓库、页内店铺选择、运费规则表单。

---

## 5. 店铺上下文（X-Shop-Id）

| 步骤 | 说明 |
|------|------|
| `created` | `GET /agri/seller/context` → `setSellerShopContext` |
| GET / PUT | `sellerShopHeaders()` |
| Navbar 切店 | `location.reload()` 整页刷新 |

---

## 6. API 封装

**模块：** `ruoyi-ui/src/api/agri/seller/delivery.js`  
**Base URL：** `/agri/seller/delivery`

| 前端方法 | HTTP | 路径 | 用途 |
|----------|------|------|------|
| `getSellerDeliverySetting()` | GET | `/` | 查询当前店设置；无数据时 `data` 为 `null` |
| `saveSellerDeliverySetting(data)` | PUT | `/` | 新增或覆盖保存 |

### 6.1 查询响应（ShopDeliverySettingVO）

| 字段 | 说明 |
|------|------|
| settingId | 有值表示已配置 |
| shipperName / shipperMobile | 发货人信息 |
| region.regionCode | 区县级 `biz_region.code`；用于级联回显 |
| region.provinceName / cityName / districtName | 名称快照（展示用） |
| detailAddress | 详细地址 |
| updateTime | 最近更新时间 |

### 6.2 保存 Body（ShopDeliverySaveDTO）

```json
{
  "shipperName": "张三",
  "shipperMobile": "13800138000",
  "region": { "regionCode": "540102" },
  "detailAddress": "某某街道 1 号"
}
```

| 字段 | 前端校验 |
|------|----------|
| shipperName | 必填；≤64 |
| shipperMobile | 必填；`/^1[3-9]\d{9}$/` |
| region.regionCode | 级联须选至 **区县**（`parseRegionSelection`） |
| detailAddress | 必填；≤256 |

> 名称快照（`region_name` / `city_name`）由 **后端** 据 `regionCode` 写入；前端 **仅传 regionCode**。

---

## 7. 省市区级联

| 项 | 说明 |
|----|------|
| 组件 | `el-cascader` + `REGION_CASCADER_PROPS`（`value: code`） |
| 表单字段 | `shipRegionCascader`（路径）、`shipRegionCode`（落库）、`shipRegionName`（本地展示，不传后端） |
| 变更 | `@change` → `applyRegionSelection(codes, 'ship')` |
| 回显 | GET 后 `region.regionCode` → `syncRegionCascaderFromForm` |
| 约束 | 仅 **type=3 区县** 可选；与商户注册地址同一套 normalize 逻辑 |

---

## 8. 交互要点

| 场景 | 行为 |
|------|------|
| 首次进入 | `data=null` → 空表单 + 蓝色引导文案 |
| 已有配置 | 全字段回显 + 展示 `updateTime` |
| 保存成功 | Toast「保存成功」→ 重新 GET 刷新 |
| 校验失败 | 字段级提示；不提交 |
| 无编辑权限 | 隐藏「保存」按钮（`v-hasPermi`） |
| 与运费模版 | **独立菜单/页面**；本页不含运费字段 |

---

## 9. 联调检查清单

- [ ] 菜单组件路径 `agri/seller/delivery/index` 及按钮权限
- [ ] Navbar 切换店铺后表单加载对应店数据
- [ ] 首次 PUT 创建；再次 PUT 覆盖
- [ ] 省市区未选全时前端拦截
- [ ] 保存后 C 端商品详情 `logistics.shipCity` 有值（后端 Facade）
- [ ] 未选店铺时后端返回「请先选择当前店铺」

---

## 10. 修订记录

| 版本 | 说明 |
|------|------|
| v1.0 | 首版：单页发货信息表单 + 省市区级联 + Upsert API |

---

*文档版本：v1.0 · 关联《配送设置功能需求.md》v1.1、《配送设置技术方案.md》v1.3*
