shop-wx/doc/暂存柜功能文档.md

374 lines
12 KiB
Markdown
Raw Normal View History

# 暂存柜功能文档
## 概述
`storage-cells-summary` 组件是智能柜管理系统中用于暂存柜(临时存储)功能的核心组件。该组件提供以下核心功能:
1. **可用格口展示** - 显示当前店铺/区域的可用暂存柜格口,按格口类型(小格、中格、大格、超大格)分类统计
2. **格口选择** - 允许用户选择特定类型的格口进行物品存入
3. **物品存入流程** - 完整的存入物品流程:分配格口 → 生成密码 → 验证密码 → 打开格口
4. **物品取出流程** - 通过密码验证取出已暂存的物品
5. **状态管理** - 使用状态机模式管理弹窗流程,确保业务流程完整性
## 功能特性
### 1. 数据展示
- 实时获取并显示可用格口数量
- 按四种格口类型分类统计:小格(1)、中格(2)、大格(3)、超大格(4)
- 显示每种类型的剩余可用数量
- 支持刷新数据
### 2. 格口选择
- 可视化格口类型卡片展示
- 显示每种类型的SVG图标
- 智能禁用无可用格口的类型
- 选中状态视觉反馈
### 3. 存入流程
```
用户点击"物品暂存" → 分配选定类型格口 → 生成4位数字密码 →
显示密码给用户 → 用户确认已记住 → 输入密码验证 →
验证通过打开格口 → 刷新格口状态
```
### 4. 取出流程
```
用户点击"物品取出" → 输入4位密码 → 验证密码 →
验证通过打开格口 → 刷新格口状态
```
### 5. 用户交互
- 加载状态提示
- 错误状态处理与重试
- 空状态提示
- 弹窗式密码输入与验证
- 数字键盘集成
## 组件结构
### 文件位置
```
src/components/storage-cells-summary/
├── index.vue # 主组件文件
└── usePopupState.ts # 弹窗状态管理hook
```
### 组件Props
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `shopId` | `number` | 必填 | 店铺ID用于获取可用格口列表 |
| `autoLoad` | `boolean` | `true` | 是否自动加载数据 |
| `showButtons` | `boolean` | `true` | 是否显示操作按钮(存入/取出) |
### 组件Emits
| 事件名 | 参数 | 说明 |
|--------|------|------|
| `deposit` | 无 | 点击存入按钮时触发(向后兼容) |
| `retrieve` | 无 | 点击取出按钮时触发(向后兼容) |
| `refresh` | 无 | 数据刷新完成时触发 |
| `error` | `Error` | 数据加载失败时触发 |
| `backToAddressSelect` | 无 | 点击"重选地址"按钮时触发 |
### 核心状态变量
| 变量名 | 类型 | 说明 |
|--------|------|------|
| `loading` | `Ref<boolean>` | 数据加载状态 |
| `error` | `Ref<Error \| null>` | 错误信息 |
| `cellsData` | `Ref<AvailableStorageCellDTO[]>` | 格口数据列表 |
| `selectedCellType` | `Ref<number>` | 当前选中的格口类型 |
| `depositLoading` | `Ref<boolean>` | 存入操作加载状态 |
| `retrieveLoading` | `Ref<boolean>` | 取出操作加载状态 |
| `generatedPassword` | `Ref<string>` | 生成的密码(向后兼容) |
### 计算属性
| 属性名 | 说明 |
|--------|------|
| `availableCells` | 过滤出无密码的可用格口 |
| `cellTypeStats` | 按类型统计可用格口数量 |
| `hasAvailableCells` | 是否存在可用格口 |
## 业务流程
### 1. 数据初始化流程
```mermaid
graph TD
A[组件挂载] --> B{autoLoad为true?};
B -->|是| C[调用refresh函数];
B -->|否| D[等待手动刷新];
C --> E[调用availableStorageCells API];
E --> F[更新cellsData];
F --> G[触发refresh事件];
```
### 2. 物品存入流程
```mermaid
graph TD
A[用户点击"物品暂存"] --> B[触发deposit事件];
B --> C[调用handleDepositFlow];
C --> D[调用storeItemApi分配格口];
D --> E{是否获取到密码?};
E -->|是| F[显示密码弹窗];
E -->|否| G[显示错误提示];
F --> H[用户点击"已记住"];
H --> I[进入密码验证状态];
I --> J[用户输入密码];
J --> K[密码验证];
K --> L{密码正确?};
L -->|是| M[调用openByPassword打开格口];
L -->|否| N[显示密码错误提示];
M --> O[显示成功提示];
O --> P[刷新格口数据];
```
### 3. 物品取出流程
```mermaid
graph TD
A[用户点击"物品取出"] --> B[触发retrieve事件];
B --> C[显示密码输入弹窗];
C --> D[用户输入密码];
D --> E[调用openByPassword打开格口];
E --> F[显示成功提示];
F --> G[刷新格口数据];
```
## API接口
### 依赖的API模块
```typescript
import {
availableStorageCells, // 获取可用格口列表
storeItemApi, // 存入物品分配格口
openByPassword, // 根据密码打开格口
resetByPassword // 重置格口状态(当前未使用)
} from '@/api/cabinet/index'
```
### 1. availableStorageCells
**功能**:获取指定店铺的可用暂存柜格口列表
**请求参数**
```typescript
{
shopId: number // 店铺ID
}
```
**响应数据结构**`AvailableStorageCellDTO[]`
```typescript
interface AvailableStorageCellDTO {
cellId: number; // 格口ID
cabinetId: number; // 柜机ID
cabinetName: string; // 柜子名称
mainboardId: number; // 主板ID
cellNo: number; // 格口号
pinNo: number; // 针脚序号
stock: number; // 库存数量
cellPrice: number; // 格口租用价格
isRented: number; // 是否已租用0-未租用1-已租用)
cellType: number; // 格口类型1-小格2-中格3-大格4-超大格)
usageStatus: number; // 使用状态1-空闲2-已占用)
availableStatus: number;// 可用状态1-正常2-故障)
hasPassword: boolean; // 是否有密码true-有密码/已占用false-无密码/可用)
goodsId: number; // 商品ID
goodsName: string; // 商品名称
price: number; // 商品价格
coverImg: string; // 封面图URL
}
```
### 2. storeItemApi
**功能**:存入物品并分配格口,生成访问密码
**请求参数**`StoreItemToCellCommand`
```typescript
interface StoreItemToCellCommand {
shopId: number; // 店铺ID
cellType: number; // 格口类型1-小格2-中格3-大格4-超大格)
}
```
**响应数据结构**`CabinetCellEntity`
```typescript
interface CabinetCellEntity {
cellId: number; // 格口唯一ID
cabinetId: number; // 关联柜机ID
mainboardId?: number; // 主板ID
cellNo: number; // 格口号
pinNo: number; // 针脚序号
stock: number; // 库存数量
cellPrice?: number; // 格口价格
isRented: number; // 是否已租用0-未租用1-已租用
cellType: number; // 格口类型1小格 2中格 3大格 4超大格
usageStatus: number; // 使用状态1空闲 2已占用
availableStatus: number;// 可用状态1正常 2故障
goodsId?: number; // 商品ID
password?: string; // 密码(暂存模式使用)
}
```
### 3. openByPassword
**功能**:根据密码打开对应的格口
**请求参数**`OpenCellByPasswordCommand`
```typescript
interface OpenCellByPasswordCommand {
shopId: number; // 店铺ID
password: string; // 格口密码
}
```
**响应**无数据成功时HTTP状态码为200
## 状态管理usePopupState
### 状态机设计
弹窗流程采用状态机模式,确保业务流程的完整性和一致性:
| 状态类型 | 说明 | 显示内容 |
|----------|------|----------|
| `idle` | 空闲状态,无弹窗显示 | 无弹窗 |
| `password-show` | 显示生成的密码 | 密码显示弹窗 |
| `password-verify` | 验证用户输入的密码 | 密码输入框+验证按钮 |
| `retrieve-input` | 输入取出密码 | 密码输入框+确认按钮 |
| `processing` | 显示处理中的加载提示 | 加载动画+处理文本 |
### 状态转换图
```mermaid
graph LR
A[idle] -->|存入流程开始| B[password-show];
B -->|点击"已记住"| C[password-verify];
C -->|密码验证通过| D[processing];
C -->|密码验证失败| C;
A -->|取出流程开始| E[retrieve-input];
E -->|输入密码确认| D[processing];
D -->|操作完成| A;
B -->|取消| A;
C -->|取消| A;
E -->|取消| A;
```
### Hook接口
```typescript
interface UsePopupStateReturn {
currentState: Ref<PopupState>; // 当前弹窗状态
popupInputValue: Ref<string>; // 弹窗输入框的值
passwordLength: number; // 密码长度固定为4
popupVisible: ComputedRef<boolean>; // 弹窗显示状态
keyboardVisible: Ref<boolean>; // 键盘显示状态
popupTitle: ComputedRef<string>; // 弹窗标题
popupMessage: ComputedRef<string>; // 弹窗消息内容
popupConfirmText: ComputedRef<string>; // 确认按钮文本
showCancelButton: ComputedRef<boolean>; // 是否显示取消按钮
transitionTo: (state: PopupState) => void; // 状态转换函数
// ... 其他处理函数
}
```
## 使用方法
### 1. 基本使用
```vue
<template>
<storage-cells-summary
:shop-id="currentShopId"
:auto-load="true"
:show-buttons="true"
@deposit="handleDeposit"
@retrieve="handleRetrieve"
@refresh="handleRefresh"
@error="handleError"
@back-to-address-select="handleBack"
/>
</template>
```
### 2. 仅展示模式
```vue
<template>
<storage-cells-summary
:shop-id="currentShopId"
:show-buttons="false"
/>
</template>
```
### 3. 手动控制数据加载
```vue
<template>
<storage-cells-summary
ref="storageRef"
:shop-id="currentShopId"
:auto-load="false"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const storageRef = ref()
// 手动刷新数据
function refreshData() {
storageRef.value?.refresh()
}
</script>
```
## 样式与UI组件
### 使用的UI组件
- `wd-popup` - 弹窗容器
- `wd-password-input` - 密码输入框(格子模式)
- `wd-keyboard` - 数字键盘
- `wd-button` - 按钮
- `wd-loading` - 加载动画
- `wd-icon` - 图标
- `wd-row` / `wd-col` - 栅格布局
### 样式特点
- 使用 `rpx` 单位适配不同屏幕
- 响应式网格布局2列
- 交互状态反馈(点击效果、选中状态)
- 弹窗圆角设计border-top-left-radius: 24rpx
- 安全区域适配safe-area-inset-bottom
## 注意事项
### 1. 密码安全
- 密码为4位数字由系统自动生成
- 密码仅在存入流程中显示一次,用户需要牢记
- 密码验证失败会提示错误,但不会泄露正确密码
### 2. 格口状态同步
- 每次成功操作(存入/取出)后会自动刷新格口数据
- 可用格口数量实时更新
- 已被占用的格口hasPassword: true不会显示在可用列表中
### 3. 错误处理
- 网络请求失败会显示错误提示
- 用户可点击"重试"按钮重新加载
- 操作失败会回到初始状态,不会卡在中间状态
### 4. 向后兼容性
- 保留了 `deposit``retrieve` 事件发射
- 保留了 `generatedPassword` 状态变量
- 新增的 `handleDepositFlow``handleRetrieveFlow` 函数与原有事件处理并行
### 5. 性能考虑
- 按需加载数据autoLoad控制
- 计算属性缓存统计结果
- 避免不必要的重复请求
## 相关文件
- `src/components/storage-cells-summary/index.vue` - 主组件实现
- `src/components/storage-cells-summary/usePopupState.ts` - 弹窗状态管理
- `src/api/cabinet/index.ts` - 柜机相关API
- `src/api/cabinet/types.ts` - 数据类型定义
- `src/static/svg/` - 格口类型SVG图标
---
**最后更新**2025-12-22
**组件版本**:基于当前代码实现
**维护者**:项目开发团队