优化设备采购界面搜索
This commit is contained in:
parent
749b24a17f
commit
60deb39de8
|
@ -2,6 +2,10 @@
|
|||
* 设备列表查询请求
|
||||
*/
|
||||
export interface EquipmentListReq {
|
||||
/** 最低价格 */
|
||||
minPrice?: number
|
||||
/** 最高价格 */
|
||||
maxPrice?: number
|
||||
/** 设备名称 */
|
||||
equipmentName?: string
|
||||
/** 设备类型 */
|
||||
|
@ -74,6 +78,8 @@ export interface EquipmentListReq {
|
|||
orderDirection?: string
|
||||
/** 页码 */
|
||||
page?: number
|
||||
/** 库存条码 */
|
||||
inventoryBarcode?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,7 +83,7 @@ const storeSetup = () => {
|
|||
// 合并路由
|
||||
const setRoutes = (data: RouteRecordRaw[]) => {
|
||||
// 合并路由并排序
|
||||
routes.value = [...constantRoutes, ...systemRoutes].concat(data)
|
||||
routes.value = [...constantRoutes, ...systemRoutes, ...data]
|
||||
.sort((a, b) => (a.meta?.sort ?? 0) - (b.meta?.sort ?? 0))
|
||||
asyncRoutes.value = data
|
||||
}
|
||||
|
@ -181,8 +181,8 @@ const storeSetup = () => {
|
|||
}]
|
||||
// 使用已转换的数据生成路由
|
||||
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
||||
// 合并systemRoutes中的路由
|
||||
const allRoutes = [...asyncRoutes, ...systemRoutes]
|
||||
// 合并路由,避免重复
|
||||
const allRoutes = [...asyncRoutes]
|
||||
const flatRoutes = flatMultiLevelRoutes(cloneDeep(allRoutes))
|
||||
setRoutes(allRoutes)
|
||||
return flatRoutes
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
# 设备采购模块
|
||||
|
||||
## 功能概述
|
||||
|
||||
设备采购模块是一个完整的企业设备采购管理系统,提供设备采购的全生命周期管理,包括采购申请、订单管理、供应商管理、设备入库等功能。
|
||||
|
||||
## 主要功能
|
||||
|
||||
### 1. 采购记录管理
|
||||
- **新增采购记录**:支持完整的设备采购信息录入
|
||||
- **编辑采购记录**:修改已存在的采购记录信息
|
||||
- **查看采购记录**:查看采购记录的详细信息
|
||||
- **删除采购记录**:删除不需要的采购记录
|
||||
|
||||
### 2. 搜索功能
|
||||
- **多条件搜索**:支持按设备名称、型号、供应商、状态等条件搜索
|
||||
- **时间范围搜索**:支持按采购时间、入库时间、启用时间范围搜索
|
||||
- **价格范围搜索**:支持按价格范围搜索
|
||||
- **状态搜索**:支持按设备状态、位置状态、健康状态搜索
|
||||
|
||||
### 3. 数据展示
|
||||
- **统计卡片**:显示采购总数、待处理、已完成、采购总额等统计信息
|
||||
- **表格展示**:分页展示采购记录列表
|
||||
- **状态标签**:使用不同颜色的标签显示设备状态
|
||||
- **价格格式化**:自动格式化价格显示
|
||||
|
||||
### 4. 数据导出
|
||||
- **Excel导出**:支持将采购记录导出为Excel文件
|
||||
- **筛选导出**:支持按搜索条件导出数据
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 前端技术栈
|
||||
- **Vue 3**:使用Composition API
|
||||
- **TypeScript**:提供类型安全
|
||||
- **Arco Design Vue**:UI组件库
|
||||
- **Vite**:构建工具
|
||||
|
||||
### 后端技术栈
|
||||
- **Spring Boot**:后端框架
|
||||
- **MyBatis Plus**:ORM框架
|
||||
- **MySQL**:数据库
|
||||
- **Swagger**:API文档
|
||||
|
||||
### 数据模型
|
||||
- **EquipmentEntity**:设备实体类
|
||||
- **EquipmentReq**:设备请求类
|
||||
- **EquipmentResp**:设备响应类
|
||||
- **EquipmentListReq**:设备列表查询请求类
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
procurement/
|
||||
├── index.vue # 主页面
|
||||
├── components/
|
||||
│ ├── ProcurementSearch.vue # 搜索组件
|
||||
│ └── ProcurementModal.vue # 弹窗组件
|
||||
├── test.vue # 测试页面
|
||||
└── README.md # 说明文档
|
||||
```
|
||||
|
||||
## API接口
|
||||
|
||||
### 1. 分页查询
|
||||
- **接口**:`GET /equipment/procurement/page`
|
||||
- **参数**:EquipmentListReq
|
||||
- **返回**:PageResult<EquipmentResp>
|
||||
|
||||
### 2. 新增采购
|
||||
- **接口**:`POST /equipment/procurement`
|
||||
- **参数**:EquipmentReq
|
||||
- **返回**:Result<null>
|
||||
|
||||
### 3. 更新采购
|
||||
- **接口**:`PUT /equipment/procurement/{equipmentId}`
|
||||
- **参数**:EquipmentReq
|
||||
- **返回**:Result<null>
|
||||
|
||||
### 4. 删除采购
|
||||
- **接口**:`DELETE /equipment/procurement/{equipmentId}`
|
||||
- **参数**:equipmentId
|
||||
- **返回**:Result<null>
|
||||
|
||||
### 5. 获取详情
|
||||
- **接口**:`GET /equipment/procurement/detail/{equipmentId}`
|
||||
- **参数**:equipmentId
|
||||
- **返回**:Result<EquipmentResp>
|
||||
|
||||
### 6. 导出数据
|
||||
- **接口**:`GET /equipment/procurement/export`
|
||||
- **参数**:EquipmentListReq
|
||||
- **返回**:Blob
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 1. 访问页面
|
||||
在浏览器中访问设备采购模块页面。
|
||||
|
||||
### 2. 查看数据
|
||||
页面会自动加载采购记录列表,显示统计信息和数据表格。
|
||||
|
||||
### 3. 搜索数据
|
||||
点击"搜索采购"按钮,在弹出的搜索弹窗中输入搜索条件,点击"搜索"按钮。
|
||||
|
||||
### 4. 新增记录
|
||||
点击"新增采购"按钮,在弹出的表单中填写设备采购信息,点击"确定"按钮。
|
||||
|
||||
### 5. 编辑记录
|
||||
在表格中点击"编辑"按钮,在弹出的表单中修改信息,点击"确定"按钮。
|
||||
|
||||
### 6. 删除记录
|
||||
在表格中点击"删除"按钮,确认删除操作。
|
||||
|
||||
### 7. 导出数据
|
||||
点击"导出"按钮,选择保存位置下载Excel文件。
|
||||
|
||||
## 字段说明
|
||||
|
||||
### 基本信息
|
||||
- **设备名称**:设备的名称
|
||||
- **设备类型**:设备的分类(检测设备、安防设备、办公设备、车辆等)
|
||||
- **设备型号**:设备的具体型号
|
||||
- **序列号**:设备的唯一序列号
|
||||
- **品牌**:设备的品牌
|
||||
- **资产编号**:设备的资产编号
|
||||
- **配置规格**:设备的配置规格和参数
|
||||
|
||||
### 采购信息
|
||||
- **采购订单**:采购订单号
|
||||
- **供应商**:供应商名称
|
||||
- **数量**:采购数量
|
||||
- **单价**:设备单价
|
||||
- **总价**:设备总价
|
||||
- **采购价格**:采购价格
|
||||
- **当前净值**:设备的当前净值
|
||||
- **采购时间**:采购时间
|
||||
- **入库时间**:入库时间
|
||||
- **启用时间**:启用时间
|
||||
- **预计报废时间**:预计报废时间
|
||||
- **折旧方法**:折旧方法(直线折旧、余额递减、年数总和)
|
||||
- **折旧年限**:折旧年限
|
||||
- **残值**:设备残值
|
||||
- **保修截止日期**:保修截止日期
|
||||
|
||||
### 状态信息
|
||||
- **设备状态**:设备状态(正常、维修中、已报废、闲置、丢失)
|
||||
- **使用状态**:使用状态(空闲中、使用中)
|
||||
- **位置状态**:位置状态(库存中、使用中、维修中、已报废、外借中、丢失、闲置)
|
||||
- **健康状态**:健康状态(优秀、良好、一般、较差、危险)
|
||||
- **负责人**:设备负责人
|
||||
- **维护人员**:维护人员
|
||||
- **物理位置**:设备的物理位置
|
||||
- **库存条码**:库存条码
|
||||
- **上次维护日期**:上次维护日期
|
||||
- **下次维护日期**:下次维护日期
|
||||
|
||||
### 其他信息
|
||||
- **次户号**:次户号
|
||||
- **盘点依据**:盘点依据
|
||||
- **动态记录**:动态记录信息
|
||||
- **资产备注**:资产备注信息
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据验证**:所有必填字段都需要填写,系统会进行数据验证
|
||||
2. **权限控制**:不同用户可能有不同的操作权限
|
||||
3. **数据安全**:敏感数据会进行加密处理
|
||||
4. **性能优化**:大量数据时会进行分页处理
|
||||
5. **错误处理**:系统会显示友好的错误提示
|
||||
|
||||
## 开发说明
|
||||
|
||||
### 1. 开发环境
|
||||
- Node.js 16+
|
||||
- Vue 3.3+
|
||||
- TypeScript 5.0+
|
||||
|
||||
### 2. 安装依赖
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 3. 启动开发服务器
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 4. 构建生产版本
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 5. 代码规范
|
||||
- 使用ESLint进行代码检查
|
||||
- 使用Prettier进行代码格式化
|
||||
- 遵循Vue 3 Composition API最佳实践
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v1.0.0 (2025-01-XX)
|
||||
- 初始版本发布
|
||||
- 实现基本的CRUD功能
|
||||
- 实现搜索和导出功能
|
||||
- 实现统计信息展示
|
||||
- 实现响应式设计
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题或建议,请联系开发团队。
|
|
@ -0,0 +1,865 @@
|
|||
<template>
|
||||
<a-modal
|
||||
:visible="visible"
|
||||
:title="getModalTitle()"
|
||||
width="1200px"
|
||||
:confirm-loading="loading"
|
||||
:ok-button-props="{ disabled: !isFormValid || isView }"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
auto-label-width
|
||||
>
|
||||
<!-- 标签页导航 -->
|
||||
<div class="tab-navigation">
|
||||
<div
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
class="tab-item" :class="[{ active: activeTab === tab.key }]"
|
||||
@click="activeTab = tab.key"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 标签页内容 -->
|
||||
<div class="tab-content">
|
||||
<!-- 基本信息 -->
|
||||
<div v-show="activeTab === 'basic'">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="设备名称" field="equipmentName">
|
||||
<a-input
|
||||
v-model="formData.equipmentName"
|
||||
placeholder="请输入设备名称"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="设备类型" field="equipmentType">
|
||||
<a-select
|
||||
v-model="formData.equipmentType"
|
||||
:options="equipmentTypeOptions"
|
||||
placeholder="请选择设备类型"
|
||||
:disabled="isView"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="设备型号" field="equipmentModel">
|
||||
<a-input
|
||||
v-model="formData.equipmentModel"
|
||||
placeholder="请输入设备型号"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="序列号" field="equipmentSn">
|
||||
<a-input
|
||||
v-model="formData.equipmentSn"
|
||||
placeholder="请输入序列号"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="品牌" field="brand">
|
||||
<a-input
|
||||
v-model="formData.brand"
|
||||
placeholder="请输入品牌"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="资产编号" field="assetCode">
|
||||
<a-input
|
||||
v-model="formData.assetCode"
|
||||
placeholder="请输入资产编号"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="50"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="配置规格" field="specification">
|
||||
<a-textarea
|
||||
v-model="formData.specification"
|
||||
placeholder="请输入配置规格参数"
|
||||
:disabled="isView"
|
||||
:rows="3"
|
||||
show-word-limit
|
||||
:max-length="500"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 采购信息 -->
|
||||
<div v-show="activeTab === 'procurement'">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="采购订单" field="purchaseOrder">
|
||||
<a-input
|
||||
v-model="formData.purchaseOrder"
|
||||
placeholder="请输入采购订单号"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="供应商" field="supplierName">
|
||||
<a-input
|
||||
v-model="formData.supplierName"
|
||||
placeholder="请输入供应商名称"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-form-item label="数量" field="quantity">
|
||||
<a-input-number
|
||||
v-model="formData.quantity"
|
||||
placeholder="请输入数量"
|
||||
:min="1"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="单价" field="unitPrice">
|
||||
<a-input-number
|
||||
v-model="formData.unitPrice"
|
||||
placeholder="请输入单价"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="总价" field="totalPrice">
|
||||
<a-input-number
|
||||
v-model="formData.totalPrice"
|
||||
placeholder="请输入总价"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="采购价格" field="purchasePrice">
|
||||
<a-input-number
|
||||
v-model="formData.purchasePrice"
|
||||
placeholder="请输入采购价格"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="当前净值" field="currentNetValue">
|
||||
<a-input-number
|
||||
v-model="formData.currentNetValue"
|
||||
placeholder="请输入当前净值"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="采购时间" field="purchaseTime">
|
||||
<a-date-picker
|
||||
v-model="formData.purchaseTime"
|
||||
placeholder="请选择采购时间"
|
||||
:disabled="isView"
|
||||
show-time
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="入库时间" field="inStockTime">
|
||||
<a-date-picker
|
||||
v-model="formData.inStockTime"
|
||||
placeholder="请选择入库时间"
|
||||
:disabled="isView"
|
||||
show-time
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="启用时间" field="activationTime">
|
||||
<a-date-picker
|
||||
v-model="formData.activationTime"
|
||||
placeholder="请选择启用时间"
|
||||
:disabled="isView"
|
||||
show-time
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="预计报废时间" field="expectedScrapTime">
|
||||
<a-date-picker
|
||||
v-model="formData.expectedScrapTime"
|
||||
placeholder="请选择预计报废时间"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="折旧方法" field="depreciationMethod">
|
||||
<a-select
|
||||
v-model="formData.depreciationMethod"
|
||||
placeholder="请选择折旧方法"
|
||||
:disabled="isView"
|
||||
>
|
||||
<a-option value="straight_line">直线折旧</a-option>
|
||||
<a-option value="declining_balance">余额递减</a-option>
|
||||
<a-option value="sum_of_years">年数总和</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="折旧年限" field="depreciationYears">
|
||||
<a-input-number
|
||||
v-model="formData.depreciationYears"
|
||||
placeholder="请输入折旧年限"
|
||||
:min="1"
|
||||
:max="50"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="残值" field="salvageValue">
|
||||
<a-input-number
|
||||
v-model="formData.salvageValue"
|
||||
placeholder="请输入残值"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="保修截止日期" field="warrantyExpireDate">
|
||||
<a-date-picker
|
||||
v-model="formData.warrantyExpireDate"
|
||||
placeholder="请选择保修截止日期"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 状态信息 -->
|
||||
<div v-show="activeTab === 'status'">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="设备状态" field="equipmentStatus">
|
||||
<a-select
|
||||
v-model="formData.equipmentStatus"
|
||||
:options="equipmentStatusOptions"
|
||||
placeholder="请选择设备状态"
|
||||
:disabled="isView"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="使用状态" field="useStatus">
|
||||
<a-select
|
||||
v-model="formData.useStatus"
|
||||
:options="useStatusOptions"
|
||||
placeholder="请选择使用状态"
|
||||
:disabled="isView"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="位置状态" field="locationStatus">
|
||||
<a-select
|
||||
v-model="formData.locationStatus"
|
||||
:options="locationStatusOptions"
|
||||
placeholder="请选择位置状态"
|
||||
:disabled="isView"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="健康状态" field="healthStatus">
|
||||
<a-select
|
||||
v-model="formData.healthStatus"
|
||||
:options="healthStatusOptions"
|
||||
placeholder="请选择健康状态"
|
||||
:disabled="isView"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="负责人" field="responsiblePerson">
|
||||
<a-input
|
||||
v-model="formData.responsiblePerson"
|
||||
placeholder="请输入负责人"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="维护人员" field="maintenancePerson">
|
||||
<a-input
|
||||
v-model="formData.maintenancePerson"
|
||||
placeholder="请输入维护人员"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="物理位置" field="physicalLocation">
|
||||
<a-input
|
||||
v-model="formData.physicalLocation"
|
||||
placeholder="请输入物理位置"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="库存条码" field="inventoryBarcode">
|
||||
<a-input
|
||||
v-model="formData.inventoryBarcode"
|
||||
placeholder="请输入库存条码"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="上次维护日期" field="lastMaintenanceDate">
|
||||
<a-date-picker
|
||||
v-model="formData.lastMaintenanceDate"
|
||||
placeholder="请选择上次维护日期"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="下次维护日期" field="nextMaintenanceDate">
|
||||
<a-date-picker
|
||||
v-model="formData.nextMaintenanceDate"
|
||||
placeholder="请选择下次维护日期"
|
||||
:disabled="isView"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 其他信息 -->
|
||||
<div v-show="activeTab === 'other'">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="次户号" field="accountNumber">
|
||||
<a-input
|
||||
v-model="formData.accountNumber"
|
||||
placeholder="请输入次户号"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="盘点依据" field="inventoryBasis">
|
||||
<a-input
|
||||
v-model="formData.inventoryBasis"
|
||||
placeholder="请输入盘点依据"
|
||||
:disabled="isView"
|
||||
show-word-limit
|
||||
:max-length="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item label="动态记录" field="dynamicRecord">
|
||||
<a-textarea
|
||||
v-model="formData.dynamicRecord"
|
||||
placeholder="请输入动态记录"
|
||||
:disabled="isView"
|
||||
:rows="4"
|
||||
show-word-limit
|
||||
:max-length="1000"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="资产备注" field="assetRemark">
|
||||
<a-textarea
|
||||
v-model="formData.assetRemark"
|
||||
placeholder="请输入资产备注"
|
||||
:disabled="isView"
|
||||
:rows="3"
|
||||
show-word-limit
|
||||
:max-length="500"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import type { FormInstance } from '@arco-design/web-vue'
|
||||
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||||
import type { EquipmentResp, EquipmentReq } from '@/apis/equipment/type'
|
||||
|
||||
interface Props {
|
||||
visible: boolean
|
||||
procurementData?: EquipmentResp | null
|
||||
mode: 'add' | 'edit' | 'view'
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:visible', value: boolean): void
|
||||
(e: 'success'): void
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
procurementData: null,
|
||||
mode: 'add',
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(false)
|
||||
const activeTab = ref('basic')
|
||||
|
||||
// 标签页配置
|
||||
const tabs = [
|
||||
{ key: 'basic', label: '基本信息' },
|
||||
{ key: 'procurement', label: '采购信息' },
|
||||
{ key: 'status', label: '状态信息' },
|
||||
{ key: 'other', label: '其他信息' },
|
||||
]
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive<EquipmentReq>({
|
||||
equipmentName: '',
|
||||
equipmentModel: '',
|
||||
equipmentType: '',
|
||||
equipmentStatus: '',
|
||||
useStatus: '',
|
||||
equipmentSn: '',
|
||||
assetCode: '',
|
||||
brand: '',
|
||||
specification: '',
|
||||
locationStatus: '',
|
||||
physicalLocation: '',
|
||||
responsiblePerson: '',
|
||||
healthStatus: '',
|
||||
purchaseTime: '',
|
||||
inStockTime: '',
|
||||
activationTime: '',
|
||||
expectedScrapTime: '',
|
||||
actualScrapTime: '',
|
||||
purchaseOrder: '',
|
||||
supplierName: '',
|
||||
purchasePrice: undefined,
|
||||
currentNetValue: undefined,
|
||||
depreciationMethod: '',
|
||||
depreciationYears: undefined,
|
||||
salvageValue: undefined,
|
||||
warrantyExpireDate: '',
|
||||
lastMaintenanceDate: '',
|
||||
nextMaintenanceDate: '',
|
||||
maintenancePerson: '',
|
||||
inventoryBarcode: '',
|
||||
assetRemark: '',
|
||||
accountNumber: '',
|
||||
quantity: 1,
|
||||
unitPrice: undefined,
|
||||
totalPrice: undefined,
|
||||
inventoryBasis: '',
|
||||
dynamicRecord: '',
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
equipmentName: [{ required: true, message: '请输入设备名称' }],
|
||||
equipmentModel: [{ required: true, message: '请输入设备型号' }],
|
||||
equipmentType: [{ required: true, message: '请选择设备类型' }],
|
||||
equipmentSn: [{ required: true, message: '请输入设备序列号' }],
|
||||
equipmentStatus: [{ required: true, message: '请选择设备状态' }],
|
||||
useStatus: [{ required: true, message: '请选择使用状态' }],
|
||||
purchaseOrder: [{ required: true, message: '请输入采购订单号' }],
|
||||
supplierName: [{ required: true, message: '请输入供应商名称' }],
|
||||
purchasePrice: [{ required: true, message: '请输入采购价格' }],
|
||||
quantity: [{ required: true, message: '请输入数量' }],
|
||||
unitPrice: [{ required: true, message: '请输入单价' }],
|
||||
totalPrice: [{ required: true, message: '请输入总价' }],
|
||||
}
|
||||
|
||||
// 选项配置
|
||||
const equipmentTypeOptions = [
|
||||
{ label: '检测设备', value: 'detection' },
|
||||
{ label: '安防设备', value: 'security' },
|
||||
{ label: '办公设备', value: 'office' },
|
||||
{ label: '车辆', value: 'car' },
|
||||
{ label: '其他设备', value: 'other' },
|
||||
]
|
||||
|
||||
const equipmentStatusOptions = [
|
||||
{ label: '正常', value: 'normal' },
|
||||
{ label: '维修中', value: 'repair' },
|
||||
{ label: '已报废', value: 'scrap' },
|
||||
{ label: '闲置', value: 'idle' },
|
||||
{ label: '丢失', value: 'lost' },
|
||||
]
|
||||
|
||||
const useStatusOptions = [
|
||||
{ label: '空闲中', value: '0' },
|
||||
{ label: '使用中', value: '1' },
|
||||
]
|
||||
|
||||
const locationStatusOptions = [
|
||||
{ label: '库存中', value: 'in_stock' },
|
||||
{ label: '使用中', value: 'in_use' },
|
||||
{ label: '维修中', value: 'repair' },
|
||||
{ label: '已报废', value: 'scrapped' },
|
||||
{ label: '外借中', value: 'on_loan' },
|
||||
{ label: '丢失', value: 'lost' },
|
||||
{ label: '闲置', value: 'idle' },
|
||||
]
|
||||
|
||||
const healthStatusOptions = [
|
||||
{ label: '优秀', value: 'excellent' },
|
||||
{ label: '良好', value: 'good' },
|
||||
{ label: '一般', value: 'normal' },
|
||||
{ label: '较差', value: 'poor' },
|
||||
{ label: '危险', value: 'critical' },
|
||||
]
|
||||
|
||||
// 计算属性
|
||||
const isView = computed(() => props.mode === 'view')
|
||||
const isFormValid = computed(() => {
|
||||
return formData.equipmentName &&
|
||||
formData.equipmentModel &&
|
||||
formData.equipmentType &&
|
||||
formData.equipmentSn
|
||||
})
|
||||
|
||||
// 获取弹窗标题
|
||||
const getModalTitle = () => {
|
||||
const titles = {
|
||||
add: '新增采购记录',
|
||||
edit: '编辑采购记录',
|
||||
view: '查看采购记录',
|
||||
}
|
||||
return titles[props.mode]
|
||||
}
|
||||
|
||||
// 监听弹窗显示状态
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (newVal && props.procurementData) {
|
||||
initFormData()
|
||||
}
|
||||
})
|
||||
|
||||
// 初始化表单数据
|
||||
const initFormData = () => {
|
||||
if (props.procurementData) {
|
||||
Object.assign(formData, {
|
||||
equipmentName: props.procurementData.equipmentName || '',
|
||||
equipmentModel: props.procurementData.equipmentModel || '',
|
||||
equipmentType: props.procurementData.equipmentType || '',
|
||||
equipmentStatus: props.procurementData.equipmentStatus || '',
|
||||
useStatus: props.procurementData.useStatus || '',
|
||||
equipmentSn: props.procurementData.equipmentSn || '',
|
||||
assetCode: props.procurementData.assetCode || '',
|
||||
brand: props.procurementData.brand || '',
|
||||
specification: props.procurementData.specification || '',
|
||||
locationStatus: props.procurementData.locationStatus || '',
|
||||
physicalLocation: props.procurementData.physicalLocation || '',
|
||||
responsiblePerson: props.procurementData.responsiblePerson || '',
|
||||
healthStatus: props.procurementData.healthStatus || '',
|
||||
purchaseTime: props.procurementData.purchaseTime || '',
|
||||
inStockTime: props.procurementData.inStockTime || '',
|
||||
activationTime: props.procurementData.activationTime || '',
|
||||
expectedScrapTime: props.procurementData.expectedScrapTime || '',
|
||||
actualScrapTime: props.procurementData.actualScrapTime || '',
|
||||
purchaseOrder: props.procurementData.purchaseOrder || '',
|
||||
supplierName: props.procurementData.supplierName || '',
|
||||
purchasePrice: props.procurementData.purchasePrice,
|
||||
currentNetValue: props.procurementData.currentNetValue,
|
||||
depreciationMethod: props.procurementData.depreciationMethod || '',
|
||||
depreciationYears: props.procurementData.depreciationYears,
|
||||
salvageValue: props.procurementData.salvageValue,
|
||||
warrantyExpireDate: props.procurementData.warrantyExpireDate || '',
|
||||
lastMaintenanceDate: props.procurementData.lastMaintenanceDate || '',
|
||||
nextMaintenanceDate: props.procurementData.nextMaintenanceDate || '',
|
||||
maintenancePerson: props.procurementData.maintenancePerson || '',
|
||||
inventoryBarcode: props.procurementData.inventoryBarcode || '',
|
||||
assetRemark: props.procurementData.assetRemark || '',
|
||||
accountNumber: props.procurementData.accountNumber || '',
|
||||
quantity: props.procurementData.quantity || 1,
|
||||
unitPrice: props.procurementData.unitPrice,
|
||||
totalPrice: props.procurementData.totalPrice,
|
||||
inventoryBasis: props.procurementData.inventoryBasis || '',
|
||||
dynamicRecord: props.procurementData.dynamicRecord || '',
|
||||
})
|
||||
} else {
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
Object.assign(formData, {
|
||||
equipmentName: '',
|
||||
equipmentModel: '',
|
||||
equipmentType: '',
|
||||
equipmentStatus: '',
|
||||
useStatus: '',
|
||||
equipmentSn: '',
|
||||
assetCode: '',
|
||||
brand: '',
|
||||
specification: '',
|
||||
locationStatus: '',
|
||||
physicalLocation: '',
|
||||
responsiblePerson: '',
|
||||
healthStatus: '',
|
||||
purchaseTime: '',
|
||||
inStockTime: '',
|
||||
activationTime: '',
|
||||
expectedScrapTime: '',
|
||||
actualScrapTime: '',
|
||||
purchaseOrder: '',
|
||||
supplierName: '',
|
||||
purchasePrice: undefined,
|
||||
currentNetValue: undefined,
|
||||
depreciationMethod: '',
|
||||
depreciationYears: undefined,
|
||||
salvageValue: undefined,
|
||||
warrantyExpireDate: '',
|
||||
lastMaintenanceDate: '',
|
||||
nextMaintenanceDate: '',
|
||||
maintenancePerson: '',
|
||||
inventoryBarcode: '',
|
||||
assetRemark: '',
|
||||
accountNumber: '',
|
||||
quantity: 1,
|
||||
unitPrice: undefined,
|
||||
totalPrice: undefined,
|
||||
inventoryBasis: '',
|
||||
dynamicRecord: '',
|
||||
})
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
|
||||
loading.value = true
|
||||
|
||||
if (props.mode === 'edit' && props.procurementData) {
|
||||
await equipmentProcurementApi.update(props.procurementData.equipmentId, formData)
|
||||
Message.success('更新成功')
|
||||
} else {
|
||||
await equipmentProcurementApi.add(formData)
|
||||
Message.success('新增成功')
|
||||
}
|
||||
|
||||
emit('success')
|
||||
} catch (error: any) {
|
||||
console.error('操作失败:', error)
|
||||
Message.error(error?.message || '操作失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 取消
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false)
|
||||
resetForm()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tab-navigation {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
margin-bottom: 24px;
|
||||
|
||||
.tab-item {
|
||||
padding: 12px 24px;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-2);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--color-primary);
|
||||
border-bottom-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
.arco-form-item {
|
||||
margin-bottom: 24px;
|
||||
|
||||
.arco-form-item-label {
|
||||
font-weight: 500;
|
||||
color: var(--color-text-1);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-input,
|
||||
.arco-select,
|
||||
.arco-input-number,
|
||||
.arco-date-picker {
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--color-border);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--color-primary-light-3);
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&.arco-input-focus,
|
||||
&.arco-select-focus {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.arco-textarea {
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--color-border);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--color-primary-light-3);
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&.arco-textarea-focus {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.tab-navigation {
|
||||
.tab-item {
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
.arco-row {
|
||||
.arco-col {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,136 @@
|
|||
<template>
|
||||
<div class="procurement-test">
|
||||
<a-card title="设备采购模块测试" :bordered="false">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="testApi">
|
||||
测试API
|
||||
</a-button>
|
||||
<a-button @click="testSearch">
|
||||
测试搜索
|
||||
</a-button>
|
||||
<a-button @click="testAdd">
|
||||
测试新增
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<a-divider />
|
||||
|
||||
<div class="test-results">
|
||||
<h3>测试结果</h3>
|
||||
<a-textarea
|
||||
v-model="testResults"
|
||||
:rows="10"
|
||||
placeholder="测试结果将显示在这里..."
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
|
||||
<a-divider />
|
||||
|
||||
<div class="test-params">
|
||||
<h3>测试参数</h3>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-form-item label="设备名称">
|
||||
<a-input v-model="testParams.equipmentName" placeholder="测试设备" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="设备型号">
|
||||
<a-input v-model="testParams.equipmentModel" placeholder="测试型号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="供应商">
|
||||
<a-input v-model="testParams.supplierName" placeholder="测试供应商" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||||
|
||||
defineOptions({ name: 'ProcurementTest' })
|
||||
|
||||
const testResults = ref('')
|
||||
const testParams = reactive({
|
||||
equipmentName: '测试设备',
|
||||
equipmentModel: '测试型号',
|
||||
supplierName: '测试供应商',
|
||||
})
|
||||
|
||||
// 添加测试结果
|
||||
const addTestResult = (message: string) => {
|
||||
const timestamp = new Date().toLocaleString()
|
||||
testResults.value += `[${timestamp}] ${message}\n`
|
||||
}
|
||||
|
||||
// 测试API
|
||||
const testApi = async () => {
|
||||
try {
|
||||
addTestResult('开始测试API...')
|
||||
|
||||
const params = {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
equipmentName: testParams.equipmentName,
|
||||
equipmentModel: testParams.equipmentModel,
|
||||
supplierName: testParams.supplierName,
|
||||
}
|
||||
|
||||
addTestResult(`请求参数: ${JSON.stringify(params, null, 2)}`)
|
||||
|
||||
const response = await equipmentProcurementApi.page(params)
|
||||
|
||||
addTestResult(`API响应: ${JSON.stringify(response, null, 2)}`)
|
||||
Message.success('API测试成功')
|
||||
} catch (error: any) {
|
||||
addTestResult(`API测试失败: ${error.message}`)
|
||||
Message.error('API测试失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 测试搜索
|
||||
const testSearch = () => {
|
||||
addTestResult('测试搜索功能...')
|
||||
addTestResult(`搜索参数: ${JSON.stringify(testParams, null, 2)}`)
|
||||
Message.info('搜索测试完成')
|
||||
}
|
||||
|
||||
// 测试新增
|
||||
const testAdd = () => {
|
||||
addTestResult('测试新增功能...')
|
||||
addTestResult(`新增参数: ${JSON.stringify(testParams, null, 2)}`)
|
||||
Message.info('新增测试完成')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.procurement-test {
|
||||
.test-results {
|
||||
margin-bottom: 24px;
|
||||
|
||||
h3 {
|
||||
margin-bottom: 16px;
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
|
||||
.test-params {
|
||||
h3 {
|
||||
margin-bottom: 16px;
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue