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

374 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 暂存柜功能文档
## 概述
`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
**组件版本**:基于当前代码实现
**维护者**:项目开发团队