# 属性模版 — 前端技术方案

> **依据：** 《属性模版功能需求.md》v1.2、《属性模版技术方案.md》v1.3  
> **前端规范：** `doc/前端设计/前端设计.md`  
> **范围：** 仅 **ruoyi-ui 商家端** 当前店铺属性模版列表、添加/编辑弹窗、删除；商品列表 **选用** 模版见商品模块。  
> **实现状态：** 页面与 API 封装已落地，待菜单配置及 `/agri/seller/attrTemplate` 联调。

---

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

| 项 | 说明 |
|----|------|
| 框架 | Vue 2 + Element UI |
| 请求 | `@/utils/request` + `sellerShopHeaders()` |
| 参考页面 | `ruoyi-ui/src/views/agri/seller/shopCategory/index.vue`（列表 CRUD） |
| 原型 | `doc/店铺后台/商品管理/属性模版/Snipaste_*.jpg` |
| 布局 | 检索 `el-card` + `<br/>` + 列表 `el-card` + `border` 表格 |
| 店铺切换 | **仅 Navbar**；业务页不展示店铺选择器 |

---

## 2. 文件清单

| 类型 | 路径 | 说明 |
|------|------|------|
| 列表页 | `ruoyi-ui/src/views/agri/seller/attrTemplate/index.vue` | 检索、列表、添加/编辑弹窗 |
| 模版 API | `ruoyi-ui/src/api/agri/seller/attrTemplate.js` | CRUD、options |
| 店铺上下文 | `api/agri/seller/context.js` + `utils/sellerShop.js` | X-Shop-Id |

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

---

## 3. 菜单与路由

| 菜单名称 | 组件路径 | 路由 path（建议） | 权限标识 |
|----------|----------|-------------------|----------|
| 属性模版 | `agri/seller/attrTemplate/index` | `seller/attrTemplate` | `agri:seller:attrTemplate:list` |

**上级菜单：** 店铺经营管理端 → **商品管理**

| 按钮权限 | 标识 |
|----------|------|
| 详情回显 | `agri:seller:attrTemplate:query` |
| 添加 | `agri:seller:attrTemplate:add` |
| 编辑 | `agri:seller:attrTemplate:edit` |
| 删除 / 批量删除 | `agri:seller:attrTemplate:remove` |

---

## 4. 页面结构

```text
属性模版
├── 检索区（el-card）
│   └── 属性模版名称 keyword（模糊）
├── 列表区（el-card + border 表格）
│   ├── 工具栏：添加属性模版、批量删除
│   ├── 列：选择框、属性模版名称、名称列表、操作（编辑/删除）
│   └── 分页（默认 15 条/页，对齐原型）
└── 添加/编辑弹窗（720px，可滚动）
    ├── * 属性模版名称 templateName
    ├── 【属性】段
    │   ├── 属性项：属性名 + 多个属性值（+增加属性值）
    │   └── + 添加属性项
    └── 【规格】段
        ├── 规格项：规格名 + 多个规格值（+增加规格值）
        └── + 添加规格项
```

**名称列表列：** 后端聚合 `nameList`（先属性项名、后规格项名，逗号分隔）。

---

## 5. 店铺上下文

| 步骤 | 说明 |
|------|------|
| `created` | `getSellerContext` → `setSellerShopContext` |
| API | 全部请求带 `X-Shop-Id` |
| 切换店铺 | Navbar `location.reload()` |

---

## 6. 接口封装

**Base URL：** `/agri/seller/attrTemplate`

| 前端方法 | HTTP | 路径 | 用途 |
|----------|------|------|------|
| `listAttrTemplate` | GET | `/list` | 分页；query：`keyword` |
| `getAttrTemplate` | GET | `/{templateId}` | 编辑回显 |
| `addAttrTemplate` | POST | `/` | 新增 |
| `updateAttrTemplate` | PUT | `/` | 编辑（全量替换项与值） |
| `delAttrTemplate` | DELETE | `/{templateIds}` | 删除；批量逗号分隔 |
| `attrTemplateOptions` | GET | `/options` | 发品下拉（商品列表复用） |

### 6.1 保存体（AttrTemplateSaveDTO）

```json
{
  "templateId": 2,
  "templateName": "手机",
  "attributes": [
    { "itemName": "品牌", "values": ["小米", "华为"] }
  ],
  "specs": [
    { "itemName": "颜色", "values": ["红色", "白色"] }
  ]
}
```

| 校验 | 前端预检 | 后端 |
|------|----------|------|
| 模版名称必填 | form rules | ✓ |
| 至少一项属性或规格 | `buildSubmitPayload` | ✓ |
| 项名称非空、段内不重名 | ✓ | ✓ |
| 属性与规格项名不重名 | ✓ | ✓ |
| 每项至少一个非空值 | ✓ | ✓ |
| 同项下值不重复 | ✓ | ✓ |

### 6.2 详情回显

| 字段 | 说明 |
|------|------|
| templateId, templateName | |
| attributes[] | `{ itemName, values[] }` |
| specs[] | 同上 |

编辑时将 `values` 映射为可编辑输入框数组；空详情段展示「添加属性项/规格项」按钮。

### 6.3 删除

| 场景 | 行为 |
|------|------|
| 单删 | 二次确认 |
| 批删 | 勾选后批量；含被商品引用 → 整批失败，`data.reasons` |

---

## 7. 与商品列表协作（非本页实现）

| 能力 | 接口 |
|------|------|
| 发品下拉 | `GET /agri/seller/goods/attrTemplateOptions` 或本模块 `/options` |
| 选用预填 | `GET /agri/seller/goods/attrTemplate/{id}` |
| 保存商品 | `GoodsSaveDTO.attrTemplateId` + `attributes` / `specs` |

编辑模版 **不追溯** 已保存商品；删除有引用时阻断。

---

## 8. 联调检查清单

- [ ] 菜单 `agri/seller/attrTemplate/index` 可访问
- [ ] 列表名称列表与原型一致
- [ ] 添加/编辑动态增删属性项、规格项及值
- [ ] 名称/值重复、跨段重名前端提示与后端一致
- [ ] 批量删除含被引用模版时整批失败
- [ ] 商品列表可选用 `/options` 数据

---

## 9. 修订记录

| 版本 | 说明 |
|------|------|
| v1.0 | 首版：列表 + 属性/规格动态表单弹窗 |

---

*文档版本：v1.0 · 关联《属性模版功能需求.md》v1.2*
