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