docs: 补充支付设计文档、store 字段设计文档及实施计划
This commit is contained in:
@@ -0,0 +1,644 @@
|
||||
# 门店管理新增字段 Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers-subagent-driven-development (recommended) or superpowers-executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 在 admin-ui 门店管理模块中适配后端新增的 9 个字段,修改表单弹窗和列表页,所有变更在现有 `useApiForm` + `ApiFormDialog` + `RuiTable` 框架内完成。
|
||||
|
||||
**Architecture:** 修改 2 个现有文件。`StoreFormDialog.vue` 新增 7 个可编辑字段(useApiForm fields 数组)、2 个只读字段(custom-fields 插槽)、数据双向转换逻辑(amenities JSON 序列化、serviceFeeRate 百分比转换)。`Index.vue` 新增 3 列(门店类型 Tag、包间信息、设施标签)、1 个筛选条件(门店类型下拉)、`parseAmenities` 工具函数。
|
||||
|
||||
**Tech Stack:** Vue 3 (Composition API / `<script setup>`) + TypeScript + Element Plus + Vite + pnpm
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
| # | 文件 | 操作 | 变更说明 |
|
||||
|---|------|------|---------|
|
||||
| 1 | `admin-ui/src/views/cashier/store/StoreFormDialog.vue` | 修改 | 扩展 `useApiForm` 的 `initial` 和 `fields`(+7 字段);修改 `onSubmit` 添加 amenities/serviceFeeRate 数据转换;修改 `watch` 添加编辑回填数据转换;模板添加 `width="720px"` 和 `#custom-fields` 插槽 |
|
||||
| 2 | `admin-ui/src/views/cashier/store/Index.vue` | 修改 | `queryParams` 增加 `storeType`;`handleReset` 补充 `storeType` 重置;新增 `parseAmenities` 工具函数;`columns` 增加 3 列;模板增加门店类型筛选和 3 个列 slot |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: StoreFormDialog — 扩展 initial 默认值
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/StoreFormDialog.vue` (lines 32–40)
|
||||
|
||||
- [ ] **Step 1: 在 `useApiForm` 的 `initial` 对象中追加新字段默认值**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
initial: {
|
||||
storeName: '',
|
||||
storeCode: '',
|
||||
address: '',
|
||||
contactPhone: '',
|
||||
contactName: '',
|
||||
businessHours: '',
|
||||
status: 1,
|
||||
},
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
initial: {
|
||||
storeName: '',
|
||||
storeCode: '',
|
||||
address: '',
|
||||
contactPhone: '',
|
||||
contactName: '',
|
||||
businessHours: '',
|
||||
status: 1,
|
||||
storeType: 'STANDARD',
|
||||
amenities: [],
|
||||
longitude: undefined,
|
||||
latitude: undefined,
|
||||
serviceFeeRate: undefined,
|
||||
openingDate: '',
|
||||
legalPerson: '',
|
||||
},
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/StoreFormDialog.vue
|
||||
git commit -m "feat(store): 扩展 useApiForm initial 默认值,新增 7 个字段默认值"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: StoreFormDialog — 在 fields 数组中追加 7 个新字段
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/StoreFormDialog.vue` (lines 76–86, status 字段之后、fields 数组结束之前)
|
||||
|
||||
- [ ] **Step 1: 在 status 字段配置之后、`],` 之前,插入 7 个新字段配置**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
{
|
||||
key: 'status',
|
||||
label: '状态',
|
||||
type: 'radio',
|
||||
required: true,
|
||||
options: [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 0 },
|
||||
],
|
||||
},
|
||||
],
|
||||
onSubmit: async (data) => {
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
{
|
||||
key: 'status',
|
||||
label: '状态',
|
||||
type: 'radio',
|
||||
required: true,
|
||||
options: [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'storeType',
|
||||
label: '门店类型',
|
||||
type: 'select',
|
||||
required: true,
|
||||
options: [
|
||||
{ label: '旗舰店', value: 'FLAGSHIP' },
|
||||
{ label: '标准店', value: 'STANDARD' },
|
||||
{ label: '社区店', value: 'COMMUNITY' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'amenities',
|
||||
label: '设施标签',
|
||||
type: 'checkbox',
|
||||
options: [
|
||||
{ label: '免费停车', value: '免费停车' },
|
||||
{ label: '免费WiFi', value: '免费WiFi' },
|
||||
{ label: '充电桩', value: '充电桩' },
|
||||
{ label: '24小时营业', value: '24小时营业' },
|
||||
{ label: '包厢', value: '包厢' },
|
||||
{ label: '吸烟区', value: '吸烟区' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'longitude',
|
||||
label: '经度',
|
||||
type: 'number',
|
||||
props: { min: -180, max: 180, precision: 6, step: 0.000001 },
|
||||
},
|
||||
{
|
||||
key: 'latitude',
|
||||
label: '纬度',
|
||||
type: 'number',
|
||||
props: { min: -90, max: 90, precision: 6, step: 0.000001 },
|
||||
},
|
||||
{
|
||||
key: 'serviceFeeRate',
|
||||
label: '平台服务费率(%)',
|
||||
type: 'number',
|
||||
props: { min: 0, max: 100, precision: 2, step: 0.01 },
|
||||
},
|
||||
{
|
||||
key: 'openingDate',
|
||||
label: '开业日期',
|
||||
type: 'date',
|
||||
props: { valueFormat: 'YYYY-MM-DD' },
|
||||
},
|
||||
{
|
||||
key: 'legalPerson',
|
||||
label: '法人姓名',
|
||||
type: 'input',
|
||||
},
|
||||
],
|
||||
onSubmit: async (data) => {
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/StoreFormDialog.vue
|
||||
git commit -m "feat(store): 在 useApiForm fields 中新增 7 个可编辑字段配置"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: StoreFormDialog — 修改 onSubmit 添加数据转换
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/StoreFormDialog.vue` (lines 86–100, onSubmit 回调)
|
||||
|
||||
- [ ] **Step 1: 替换 onSubmit 回调,添加 amenities JSON 序列化和 serviceFeeRate 百分比转小数**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
onSubmit: async (data) => {
|
||||
const isEdit = !!(data as any).id
|
||||
|
||||
if (isEdit) {
|
||||
await storeService.update(data)
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
else {
|
||||
await storeService.add(data)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
emit('success')
|
||||
emit('update:visible', false)
|
||||
},
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
onSubmit: async (rawData) => {
|
||||
const data = { ...rawData } as any
|
||||
|
||||
// amenities: string[] → JSON 字符串
|
||||
if (Array.isArray(data.amenities)) {
|
||||
data.amenities = JSON.stringify(data.amenities)
|
||||
}
|
||||
|
||||
// serviceFeeRate: 百分比 → 小数
|
||||
if (data.serviceFeeRate != null && data.serviceFeeRate !== '') {
|
||||
data.serviceFeeRate = Number(data.serviceFeeRate) / 100
|
||||
}
|
||||
|
||||
const isEdit = !!data.id
|
||||
|
||||
if (isEdit) {
|
||||
await storeService.update(data)
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
else {
|
||||
await storeService.add(data)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
|
||||
emit('success')
|
||||
emit('update:visible', false)
|
||||
},
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/StoreFormDialog.vue
|
||||
git commit -m "feat(store): onSubmit 中添加 amenities JSON 序列化和 serviceFeeRate 百分比转小数"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: StoreFormDialog — 修改 watch 添加编辑回填数据转换
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/StoreFormDialog.vue` (lines 104–116, watch 回调)
|
||||
|
||||
- [ ] **Step 1: 替换 watch 回调,添加 amenities JSON 解析和 serviceFeeRate 小数转百分比**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
// 监听编辑数据
|
||||
watch(() => props.visible, (val) => {
|
||||
if (val) {
|
||||
if (props.row) {
|
||||
// 编辑时设置表单数据
|
||||
form.value = {
|
||||
...props.row,
|
||||
}
|
||||
}
|
||||
else {
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
// 监听编辑数据
|
||||
watch(() => props.visible, (val) => {
|
||||
if (val) {
|
||||
if (props.row) {
|
||||
const rowData = { ...props.row }
|
||||
|
||||
// amenities: JSON 字符串 → string[]
|
||||
if (typeof rowData.amenities === 'string' && rowData.amenities) {
|
||||
try {
|
||||
rowData.amenities = JSON.parse(rowData.amenities)
|
||||
}
|
||||
catch {
|
||||
rowData.amenities = []
|
||||
}
|
||||
}
|
||||
else if (!Array.isArray(rowData.amenities)) {
|
||||
rowData.amenities = []
|
||||
}
|
||||
|
||||
// serviceFeeRate: 小数 → 百分比
|
||||
if (rowData.serviceFeeRate != null) {
|
||||
rowData.serviceFeeRate = Number(rowData.serviceFeeRate) * 100
|
||||
}
|
||||
|
||||
// 编辑时设置表单数据
|
||||
form.value = rowData
|
||||
}
|
||||
else {
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/StoreFormDialog.vue
|
||||
git commit -m "feat(store): watch 中添加 amenities JSON 解析和 serviceFeeRate 小数转百分比回填"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: StoreFormDialog — 模板添加 width 属性和 custom-fields 插槽
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/StoreFormDialog.vue` (lines 120–128, template 中的 ApiFormDialog 标签)
|
||||
|
||||
- [ ] **Step 1: 替换 ApiFormDialog 自闭合标签为开闭标签,添加 width 和 custom-fields 插槽**
|
||||
|
||||
**Old string:**
|
||||
```vue
|
||||
<ApiFormDialog
|
||||
v-model:visible="localVisible"
|
||||
v-model:form="form"
|
||||
:title="(form as any).id ? '编辑门店' : '新增门店'"
|
||||
:fields="fields"
|
||||
:rules="rules"
|
||||
:loading="loading"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```vue
|
||||
<ApiFormDialog
|
||||
v-model:visible="localVisible"
|
||||
v-model:form="form"
|
||||
:title="(form as any).id ? '编辑门店' : '新增门店'"
|
||||
:width="'720px'"
|
||||
:fields="fields"
|
||||
:rules="rules"
|
||||
:loading="loading"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
<template #custom-fields="{ form: formData }">
|
||||
<template v-if="formData.id">
|
||||
<el-form-item label="包间总数">
|
||||
<span>{{ formData.roomCount ?? '-' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="空闲包间数">
|
||||
<span>{{ formData.freeRoomCount ?? '-' }}</span>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</ApiFormDialog>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/StoreFormDialog.vue
|
||||
git commit -m "feat(store): ApiFormDialog 增加 width=720px 和 custom-fields 插槽展示只读包间字段"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Index.vue — 扩展 queryParams、handleReset、新增 parseAmenities 工具函数
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/Index.vue`
|
||||
|
||||
- [ ] **Step 1: 在 queryParams 中增加 storeType 字段**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
const queryParams = ref({
|
||||
storeName: '',
|
||||
status: undefined as number | undefined,
|
||||
})
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
const queryParams = ref({
|
||||
storeName: '',
|
||||
status: undefined as number | undefined,
|
||||
storeType: undefined as string | undefined,
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 在 handleReset 中补充 storeType 重置**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
function handleReset() {
|
||||
queryParams.value = {
|
||||
storeName: '',
|
||||
status: undefined,
|
||||
}
|
||||
tableRef.value?.reset()
|
||||
}
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
function handleReset() {
|
||||
queryParams.value = {
|
||||
storeName: '',
|
||||
status: undefined,
|
||||
storeType: undefined,
|
||||
}
|
||||
tableRef.value?.reset()
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 在 `handleStatusChange` 函数之后(`</script>` 标签之前),添加 `parseAmenities` 工具函数**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
async function handleStatusChange(row: any, status: number) {
|
||||
if (!row?.id) return
|
||||
try {
|
||||
await storeService.changeStatus(row.id, status)
|
||||
ElMessage.success(status === 1 ? '启用成功' : '禁用成功')
|
||||
} catch {
|
||||
row.status = status === 1 ? 0 : 1
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
async function handleStatusChange(row: any, status: number) {
|
||||
if (!row?.id) return
|
||||
try {
|
||||
await storeService.changeStatus(row.id, status)
|
||||
ElMessage.success(status === 1 ? '启用成功' : '禁用成功')
|
||||
} catch {
|
||||
row.status = status === 1 ? 0 : 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析设施标签(兼容 JSON 字符串和数组)
|
||||
*/
|
||||
function parseAmenities(val: any): string[] {
|
||||
if (Array.isArray(val)) return val
|
||||
if (typeof val === 'string' && val) {
|
||||
try { return JSON.parse(val) } catch { return [] }
|
||||
}
|
||||
return []
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/Index.vue
|
||||
git commit -m "feat(store): queryParams 增加 storeType 筛选、handleReset 补充重置、新增 parseAmenities 工具函数"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Index.vue — 在 columns 数组中追加 3 列配置
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/Index.vue` (lines 12–28, columns 数组)
|
||||
|
||||
- [ ] **Step 1: 在 address 列之后追加 storeType、roomInfo、amenities 3 列**
|
||||
|
||||
**Old string:**
|
||||
```ts
|
||||
{ prop: 'address', label: '地址', minWidth: 200, tooltip: true },
|
||||
{ prop: 'businessHours', label: '营业时间', width: 120 },
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```ts
|
||||
{ prop: 'address', label: '地址', minWidth: 200, tooltip: true },
|
||||
{ prop: 'storeType', label: '门店类型', width: 100, align: 'center', slot: true },
|
||||
{ prop: 'roomInfo', label: '包间', width: 120, align: 'center', slot: true },
|
||||
{ prop: 'amenities', label: '设施标签', minWidth: 200, slot: true },
|
||||
{ prop: 'businessHours', label: '营业时间', width: 120 },
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/Index.vue
|
||||
git commit -m "feat(store): columns 增加 storeType/roomInfo/amenities 3 列配置"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 8: Index.vue — 模板添加门店类型筛选和 3 个列 slot
|
||||
|
||||
**Files:**
|
||||
- Modify: `admin-ui/src/views/cashier/store/Index.vue` (template 部分)
|
||||
|
||||
- [ ] **Step 1: 在状态筛选的 `</el-form-item>` 之后、查询按钮的 `<el-form-item>` 之前,插入门店类型筛选**
|
||||
|
||||
**Old string:**
|
||||
```vue
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option label="启用" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```vue
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option label="启用" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="门店类型">
|
||||
<el-select v-model="queryParams.storeType" placeholder="请选择门店类型" clearable>
|
||||
<el-option label="旗舰店" value="FLAGSHIP" />
|
||||
<el-option label="标准店" value="STANDARD" />
|
||||
<el-option label="社区店" value="COMMUNITY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 在状态列 slot(`#column-status`)的 `</template>` 之后、操作列 slot 之前,插入 3 个列 slot 模板**
|
||||
|
||||
**Old string:**
|
||||
```vue
|
||||
<!-- 状态列 -->
|
||||
<template #column-status="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="(val: any) => handleStatusChange(row, val as number)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
```
|
||||
|
||||
**New string:**
|
||||
```vue
|
||||
<!-- 状态列 -->
|
||||
<template #column-status="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="(val: any) => handleStatusChange(row, val as number)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 门店类型列 -->
|
||||
<template #column-storeType="{ row }">
|
||||
<el-tag
|
||||
:type="row.storeType === 'FLAGSHIP' ? 'danger' : row.storeType === 'STANDARD' ? '' : 'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ { FLAGSHIP: '旗舰店', STANDARD: '标准店', COMMUNITY: '社区店' }[row.storeType] || '-' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<!-- 包间信息列 -->
|
||||
<template #column-roomInfo="{ row }">
|
||||
<span>{{ row.freeRoomCount ?? '-' }}/{{ row.roomCount ?? '-' }}</span>
|
||||
</template>
|
||||
|
||||
<!-- 设施标签列 -->
|
||||
<template #column-amenities="{ row }">
|
||||
<template v-if="parseAmenities(row.amenities).length">
|
||||
<el-tag
|
||||
v-for="tag in parseAmenities(row.amenities)"
|
||||
:key="tag"
|
||||
size="small"
|
||||
type="info"
|
||||
class="mr-1 mb-1"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add admin-ui/src/views/cashier/store/Index.vue
|
||||
git commit -m "feat(store): 模板新增门店类型筛选条件和 storeType/roomInfo/amenities 列 slot"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 9: 构建验证 + 最终提交
|
||||
|
||||
- [ ] **Step 1: 运行 TypeScript 类型检查**
|
||||
|
||||
Run: `pnpm --filter admin-ui type-check`
|
||||
Expected: 0 errors, 命令退出码 0
|
||||
|
||||
- [ ] **Step 2: 运行 ESLint 检查**
|
||||
|
||||
Run: `pnpm --filter admin-ui lint`
|
||||
Expected: 0 errors, 0 warnings(或仅有与本次修改无关的已存在 warnings)
|
||||
|
||||
- [ ] **Step 3: 运行 Vite 构建**
|
||||
|
||||
Run: `pnpm --filter admin-ui build`
|
||||
Expected: 构建成功,无编译错误,输出 dist 目录
|
||||
|
||||
- [ ] **Step 4: 启动开发服务器进行手动验证**
|
||||
|
||||
Run: `pnpm --filter admin-ui dev`
|
||||
Expected: 开发服务器正常启动,浏览器打开后:
|
||||
1. 门店管理列表页正确展示新增 3 列
|
||||
2. 门店类型下拉筛选功能正常
|
||||
3. 点击新增门店,弹窗宽度 720px,7 个新字段正确渲染
|
||||
4. 新增模式下不显示包间总数/空闲包间数
|
||||
5. 点击编辑门店,所有新字段正确回填,包间字段只读展示
|
||||
6. 提交表单无报错
|
||||
|
||||
验证完毕后按 `Ctrl+C` 停止开发服务器。
|
||||
|
||||
---
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [ ] `pnpm --filter admin-ui type-check` 通过
|
||||
- [ ] `pnpm --filter admin-ui lint` 通过
|
||||
- [ ] `pnpm --filter admin-ui build` 成功
|
||||
- [ ] 列表新增 3 列正确展示(门店类型 Tag、包间 X/Y、设施多 Tag)
|
||||
- [ ] 门店类型筛选功能正常(筛选 + 重置)
|
||||
- [ ] 新增门店:7 个新字段可正常填写和提交
|
||||
- [ ] 编辑门店:所有新字段正确回填,只读字段不可编辑
|
||||
- [ ] amenities 数据双向转换正确(JSON 字符串 ↔ 数组)
|
||||
- [ ] serviceFeeRate 数据双向转换正确(小数 ↔ 百分比)
|
||||
- [ ] 新增模式下 roomCount/freeRoomCount 区域不显示
|
||||
- [ ] 无数据时各列正确降级显示 `-`
|
||||
Reference in New Issue
Block a user