Pre Merge pull request !744 from 新的开始/gwj

pull/744/MERGE
新的开始 2025-03-20 09:46:40 +00:00 committed by Gitee
commit 9c1f5354db
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
61 changed files with 26150 additions and 445 deletions

2
.env
View File

@ -1,5 +1,5 @@
# 标题 # 标题
VITE_APP_TITLE=芋道管理系统 VITE_APP_TITLE=CINO综合系统3.0
# 项目本地运行端口号 # 项目本地运行端口号
VITE_PORT=80 VITE_PORT=80

View File

@ -4,7 +4,7 @@ NODE_ENV=production
VITE_DEV=true VITE_DEV=true
# 请求路径 # 请求路径
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn' VITE_BASE_URL='http://121.5.163.108:48080'
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务 # 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=server VITE_UPLOAD_TYPE=server

View File

@ -7,11 +7,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta <meta
name="keywords" name="keywords"
content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!" content="CINO综合系统3.0 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
/> />
<meta <meta
name="description" name="description"
content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!" content="CINO综合系统3.0 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
/> />
<title>%VITE_APP_TITLE%</title> <title>%VITE_APP_TITLE%</title>
</head> </head>

18848
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1", "pinia-plugin-persistedstate": "^3.2.1",
"qrcode": "^1.5.3", "qrcode": "^1.5.4",
"qs": "^6.12.0", "qs": "^6.12.0",
"sortablejs": "^1.15.3", "sortablejs": "^1.15.3",
"steady-xml": "^0.1.0", "steady-xml": "^0.1.0",

View File

@ -0,0 +1,61 @@
import request from '@/config/axios'
// erp商务预报价 VO
export interface BdOrderPreQuoteVO {
orderId: string // 报价单ID
sypplierId: number // 供应商id
orderStatusId: number // 工单状态
fpTime: Date // 分配时间
pickOrderTime: Date // 接单时间
startPriceTime: Date // 开始报价时间
needEndTime: Date // 最晚报价时间
endPriceTime: Date // 结束报价时间
closeOrderTime: Date // 关单时间
cancelRemark: string // 取消工单原因
priceUserRemark: string // 报价者备注
dispUserId: number // 派单者id
pickUserId: number // 接单者id
priceUserId: number // 报价者id
address: string // 地址
expedited: number // 加急
}
// erp商务预报价 API
export const BdOrderPreQuoteApi = {
// 查询erp商务预报价分页
getBdOrderPreQuotePage: async (params: any) => {
return await request.get({ url: `/erp/bd-order-pre-quote/page`, params })
},
// 查询erp商务预报价详情
getBdOrderPreQuote: async (id: number) => {
return await request.get({ url: `/erp/bd-order-pre-quote/get?id=` + id })
},
// 新增erp商务预报价
createBdOrderPreQuote: async (data: BdOrderPreQuoteVO) => {
return await request.post({ url: `/erp/bd-order-pre-quote/create`, data })
},
// 修改erp商务预报价
updateBdOrderPreQuote: async (data: BdOrderPreQuoteVO) => {
return await request.put({ url: `/erp/bd-order-pre-quote/update`, data })
},
// 删除erp商务预报价
deleteBdOrderPreQuote: async (id: number) => {
return await request.delete({ url: `/erp/bd-order-pre-quote/delete?id=` + id })
},
// 导出erp商务预报价 Excel
exportBdOrderPreQuote: async (params) => {
return await request.download({ url: `/erp/bd-order-pre-quote/export-excel`, params })
},
// ==================== 子表Erp单据文件 ====================
// 获得Erp单据文件列表
getOrderFileListByOrderId: async (orderId) => {
return await request.get({ url: `/erp/bd-order-pre-quote/order-file/list-by-order-id?orderId=` + orderId })
}
}

View File

@ -0,0 +1,48 @@
import request from '@/config/axios'
// ERP 产品分类故障 VO
export interface ProductCategoryFaultVO {
id: number // 类别故障编号
productCategoryId: number // 类别id
productFaultPart: string // 故障部位
productFault: string // 具体故障
ifAffectSale: boolean // 影响销售
affectSalePercentage: string // 影响销售%
affectSaleMoney: number // 影响销售金额
ifAffectRecycle: boolean // 影响回收
affectRecyclePercentage: string // 影响回收%
affectRecycleMoney: number // 影响回收金额
}
// ERP 产品分类故障 API
export const ProductCategoryFaultApi = {
// 查询ERP 产品分类故障分页
getProductCategoryFaultPage: async (params: any) => {
return await request.get({ url: `/erp/product-category-fault/page`, params })
},
// 查询ERP 产品分类故障详情
getProductCategoryFault: async (id: number) => {
return await request.get({ url: `/erp/product-category-fault/get?id=` + id })
},
// 新增ERP 产品分类故障
createProductCategoryFault: async (data: ProductCategoryFaultVO) => {
return await request.post({ url: `/erp/product-category-fault/create`, data })
},
// 修改ERP 产品分类故障
updateProductCategoryFault: async (data: ProductCategoryFaultVO) => {
return await request.put({ url: `/erp/product-category-fault/update`, data })
},
// 删除ERP 产品分类故障
deleteProductCategoryFault: async (id: number) => {
return await request.delete({ url: `/erp/product-category-fault/delete?id=` + id })
},
// 导出ERP 产品分类故障 Excel
exportProductCategoryFault: async (params) => {
return await request.download({ url: `/erp/product-category-fault/export-excel`, params })
}
}

View File

@ -13,8 +13,8 @@ export interface ProductCategoryVO {
// ERP 产品分类 API // ERP 产品分类 API
export const ProductCategoryApi = { export const ProductCategoryApi = {
// 查询产品分类列表 // 查询产品分类列表
getProductCategoryList: async () => { getProductCategoryList: async (params: any) => {
return await request.get({ url: `/erp/product-category/list` }) return await request.get({ url: `/erp/product-category/list`, params })
}, },
// 查询产品分类精简列表 // 查询产品分类精简列表

View File

@ -0,0 +1,42 @@
import request from '@/config/axios'
// ERP 产品分类部位 VO
export interface ProductCategoryPartVO {
id: number // 编号
productCategoryId: number // 类别
productFaultPart: string // 部位
productFaultPartStr: string|undefined // 部位
}
// ERP 产品分类部位 API
export const ProductCategoryPartApi = {
// 查询ERP 产品分类部位分页
getProductCategoryPartPage: async (params: any) => {
return await request.get({ url: `/erp/product-category-part/page`, params })
},
// 查询ERP 产品分类部位详情
getProductCategoryPart: async (id: number) => {
return await request.get({ url: `/erp/product-category-part/get?id=` + id })
},
// 新增ERP 产品分类部位
createProductCategoryPart: async (data: ProductCategoryPartVO) => {
return await request.post({ url: `/erp/product-category-part/create`, data })
},
// 修改ERP 产品分类部位
updateProductCategoryPart: async (data: ProductCategoryPartVO) => {
return await request.put({ url: `/erp/product-category-part/update`, data })
},
// 删除ERP 产品分类部位
deleteProductCategoryPart: async (id: number) => {
return await request.delete({ url: `/erp/product-category-part/delete?id=` + id })
},
// 导出ERP 产品分类部位 Excel
exportProductCategoryPart: async (params) => {
return await request.download({ url: `/erp/product-category-part/export-excel`, params })
}
}

View File

@ -0,0 +1,46 @@
import request from '@/config/axios'
// ERP 产品分类属性 VO
export interface ProductCategoryPropertiesVO {
id: number // 类别属性编号
productCategoryId: number // 类别属性id
ifSingleProperty: boolean // 是否单数属性
productPropertiesEn: string // 设备属性英文
productPropertiesCn: string // 设备属性中文
productPropertiesCategory: string // 设备属性分类
ifRequired: boolean // 是否必填
ifSn: boolean // 是否允许记录sn
}
// ERP 产品分类属性 API
export const ProductCategoryPropertiesApi = {
// 查询ERP 产品分类属性分页
getProductCategoryPropertiesPage: async (params: any) => {
return await request.get({ url: `/erp/product-category-properties/page`, params })
},
// 查询ERP 产品分类属性详情
getProductCategoryProperties: async (id: number) => {
return await request.get({ url: `/erp/product-category-properties/get?id=` + id })
},
// 新增ERP 产品分类属性
createProductCategoryProperties: async (data: ProductCategoryPropertiesVO) => {
return await request.post({ url: `/erp/product-category-properties/create`, data })
},
// 修改ERP 产品分类属性
updateProductCategoryProperties: async (data: ProductCategoryPropertiesVO) => {
return await request.put({ url: `/erp/product-category-properties/update`, data })
},
// 删除ERP 产品分类属性
deleteProductCategoryProperties: async (id: number) => {
return await request.delete({ url: `/erp/product-category-properties/delete?id=` + id })
},
// 导出ERP 产品分类属性 Excel
exportProductCategoryProperties: async (params) => {
return await request.download({ url: `/erp/product-category-properties/export-excel`, params })
}
}

View File

@ -0,0 +1,41 @@
import request from '@/config/axios'
// ERP 产品分类属性值 VO
export interface ProductCategoryPropertiesValueVO {
id: number // 编号
productCategoryPropertiesId: number // 产品分类属性
productCategoryPropertiesValue: string // 产品分类属性值
}
// ERP 产品分类属性值 API
export const ProductCategoryPropertiesValueApi = {
// 查询ERP 产品分类属性值分页
getProductCategoryPropertiesValuePage: async (params: any) => {
return await request.get({ url: `/erp/product-category-properties-value/page`, params })
},
// 查询ERP 产品分类属性值详情
getProductCategoryPropertiesValue: async (id: number) => {
return await request.get({ url: `/erp/product-category-properties-value/get?id=` + id })
},
// 新增ERP 产品分类属性值
createProductCategoryPropertiesValue: async (data: ProductCategoryPropertiesValueVO) => {
return await request.post({ url: `/erp/product-category-properties-value/create`, data })
},
// 修改ERP 产品分类属性值
updateProductCategoryPropertiesValue: async (data: ProductCategoryPropertiesValueVO) => {
return await request.put({ url: `/erp/product-category-properties-value/update`, data })
},
// 删除ERP 产品分类属性值
deleteProductCategoryPropertiesValue: async (id: number) => {
return await request.delete({ url: `/erp/product-category-properties-value/delete?id=` + id })
},
// 导出ERP 产品分类属性值 Excel
exportProductCategoryPropertiesValue: async (params) => {
return await request.download({ url: `/erp/product-category-properties-value/export-excel`, params })
}
}

View File

@ -0,0 +1,42 @@
import request from '@/config/axios'
// ERP 产品分类属性绑定 VO
export interface ProductCategoryPropertiesCategoryMapVO {
id: number // 编号
productCategoryPropertiesId: number // 类别属性
productCategoryId: number // 产品分类
productCategoryPropertiesValue: string // 类别属性值
}
// ERP 产品分类属性绑定 API
export const ProductCategoryPropertiesCategoryMapApi = {
// 查询ERP 产品分类属性绑定分页
getProductCategoryPropertiesCategoryMapPage: async (params: any) => {
return await request.get({ url: `/erp/product-category-properties-category-map/page`, params })
},
// 查询ERP 产品分类属性绑定详情
getProductCategoryPropertiesCategoryMap: async (id: number) => {
return await request.get({ url: `/erp/product-category-properties-category-map/get?id=` + id })
},
// 新增ERP 产品分类属性绑定
createProductCategoryPropertiesCategoryMap: async (data: ProductCategoryPropertiesCategoryMapVO) => {
return await request.post({ url: `/erp/product-category-properties-category-map/create`, data })
},
// 修改ERP 产品分类属性绑定
updateProductCategoryPropertiesCategoryMap: async (data: ProductCategoryPropertiesCategoryMapVO) => {
return await request.put({ url: `/erp/product-category-properties-category-map/update`, data })
},
// 删除ERP 产品分类属性绑定
deleteProductCategoryPropertiesCategoryMap: async (id: number) => {
return await request.delete({ url: `/erp/product-category-properties-category-map/delete?id=` + id })
},
// 导出ERP 产品分类属性绑定 Excel
exportProductCategoryPropertiesCategoryMap: async (params) => {
return await request.download({ url: `/erp/product-category-properties-category-map/export-excel`, params })
}
}

View File

@ -53,5 +53,11 @@ export const ProductApi = {
// 导出产品 Excel // 导出产品 Excel
exportProduct: async (params) => { exportProduct: async (params) => {
return await request.download({ url: `/erp/product/export-excel`, params }) return await request.download({ url: `/erp/product/export-excel`, params })
},
//通过产品分类id查询产品list
getProductListByCategoryIds: async (productCategoryIds: number[]) => {
return await request.get({ url: `/erp/product/simple-list-by-category-ids`, params: { productCategoryIds } })
} }
} }

View File

@ -0,0 +1,43 @@
import request from '@/config/axios'
// ERP 产品属性映射 VO
export interface ProductPropertiesMapVO {
id: number // 编号
productId: number // 产品id
productCategoryPropertiesId: number // 产品类别属性id
productPropertiesProductId: number // 产品属性产品id
productCategoryPropertiesValue: string // 产品类别属性值
}
// ERP 产品属性映射 API
export const ProductPropertiesMapApi = {
// 查询ERP 产品属性映射分页
getProductPropertiesMapPage: async (params: any) => {
return await request.get({ url: `/erp/product-properties-map/page`, params })
},
// 查询ERP 产品属性映射详情
getProductPropertiesMap: async (id: number) => {
return await request.get({ url: `/erp/product-properties-map/get?id=` + id })
},
// 新增ERP 产品属性映射
createProductPropertiesMap: async (data: ProductPropertiesMapVO) => {
return await request.post({ url: `/erp/product-properties-map/create`, data })
},
// 修改ERP 产品属性映射
updateProductPropertiesMap: async (data: ProductPropertiesMapVO) => {
return await request.put({ url: `/erp/product-properties-map/update`, data })
},
// 删除ERP 产品属性映射
deleteProductPropertiesMap: async (id: number) => {
return await request.delete({ url: `/erp/product-properties-map/delete?id=` + id })
},
// 导出ERP 产品属性映射 Excel
exportProductPropertiesMap: async (params) => {
return await request.download({ url: `/erp/product-properties-map/export-excel`, params })
}
}

View File

@ -0,0 +1,50 @@
import request from '@/config/axios'
// ERP 销售退货项二维码 VO
export interface PurchaseReturnItemsQrVO {
id: number // 主键
qr: string // 二维码
returnId: number // 采购退货编号
orderItemId: number // 采购订单项编号
orderReturnItemId: number // 采购退货单项编号
warehouseId: number // 仓库编号
productId: number // 产品编号
productUnitId: number // 产品单位id
productPrice: number // 产品单价
taxPercent: number // 税率,百分比
taxPrice: number // 税额,单位:元
remark: string // 备注
}
// ERP 销售退货项二维码 API
export const PurchaseReturnItemsQrApi = {
// 查询ERP 销售退货项二维码分页
getPurchaseReturnItemsQrPage: async (params: any) => {
return await request.get({ url: `/erp/purchase-return-items-qr/page`, params })
},
// 查询ERP 销售退货项二维码详情
getPurchaseReturnItemsQr: async (id: number) => {
return await request.get({ url: `/erp/purchase-return-items-qr/get?id=` + id })
},
// 新增ERP 销售退货项二维码
createPurchaseReturnItemsQr: async (data: PurchaseReturnItemsQrVO) => {
return await request.post({ url: `/erp/purchase-return-items-qr/create`, data })
},
// 修改ERP 销售退货项二维码
updatePurchaseReturnItemsQr: async (data: PurchaseReturnItemsQrVO) => {
return await request.put({ url: `/erp/purchase-return-items-qr/update`, data })
},
// 删除ERP 销售退货项二维码
deletePurchaseReturnItemsQr: async (id: number) => {
return await request.delete({ url: `/erp/purchase-return-items-qr/delete?id=` + id })
},
// 导出ERP 销售退货项二维码 Excel
exportPurchaseReturnItemsQr: async (params) => {
return await request.download({ url: `/erp/purchase-return-items-qr/export-excel`, params })
}
}

View File

@ -0,0 +1,51 @@
import request from '@/config/axios'
// ERP 销售出库项二维码 VO
export interface SaleOutItemsQrVO {
id: number // 编号
outId: number // 销售出库编号
orderItemId: number // 销售订单项编号
outItemId: number // 销售出库单项编号
warehouseId: number // 仓库编号
productId: number // 产品编号
productUnitId: number // 产品单位单位
productPrice: number // 产品单价
count: number // 数量
totalPrice: number // 总价
taxPercent: number // 税率,百分比
taxPrice: number // 税额,单位:元
remark: string // 备注
}
// ERP 销售出库项二维码 API
export const SaleOutItemsQrApi = {
// 查询ERP 销售出库项二维码分页
getSaleOutItemsQrPage: async (params: any) => {
return await request.get({ url: `/erp/sale-out-items-qr/page`, params })
},
// 查询ERP 销售出库项二维码详情
getSaleOutItemsQr: async (id: number) => {
return await request.get({ url: `/erp/sale-out-items-qr/get?id=` + id })
},
// 新增ERP 销售出库项二维码
createSaleOutItemsQr: async (data: SaleOutItemsQrVO) => {
return await request.post({ url: `/erp/sale-out-items-qr/create`, data })
},
// 修改ERP 销售出库项二维码
updateSaleOutItemsQr: async (data: SaleOutItemsQrVO) => {
return await request.put({ url: `/erp/sale-out-items-qr/update`, data })
},
// 删除ERP 销售出库项二维码
deleteSaleOutItemsQr: async (id: number) => {
return await request.delete({ url: `/erp/sale-out-items-qr/delete?id=` + id })
},
// 导出ERP 销售出库项二维码 Excel
exportSaleOutItemsQr: async (params) => {
return await request.download({ url: `/erp/sale-out-items-qr/export-excel`, params })
}
}

View File

@ -0,0 +1,47 @@
import request from '@/config/axios'
// ERP 产品库存明细二维码 VO
export interface StockRecordQrVO {
id: number // 编号
recordId: number // 明细编号
productId: number // 产品编号
warehouseId: number // 仓库编号
warehouseLocationId: number // 货位编号
bizType: number // 业务类型
bizId: number // 业务编号
bizItemId: number // 业务项编号
bizNo: string // 业务单号
}
// ERP 产品库存明细二维码 API
export const StockRecordQrApi = {
// 查询ERP 产品库存明细二维码分页
getStockRecordQrPage: async (params: any) => {
return await request.get({ url: `/erp/stock-record-qr/page`, params })
},
// 查询ERP 产品库存明细二维码详情
getStockRecordQr: async (id: number) => {
return await request.get({ url: `/erp/stock-record-qr/get?id=` + id })
},
// 新增ERP 产品库存明细二维码
createStockRecordQr: async (data: StockRecordQrVO) => {
return await request.post({ url: `/erp/stock-record-qr/create`, data })
},
// 修改ERP 产品库存明细二维码
updateStockRecordQr: async (data: StockRecordQrVO) => {
return await request.put({ url: `/erp/stock-record-qr/update`, data })
},
// 删除ERP 产品库存明细二维码
deleteStockRecordQr: async (id: number) => {
return await request.delete({ url: `/erp/stock-record-qr/delete?id=` + id })
},
// 导出ERP 产品库存明细二维码 Excel
exportStockRecordQr: async (params) => {
return await request.download({ url: `/erp/stock-record-qr/export-excel`, params })
}
}

View File

@ -0,0 +1,42 @@
import request from '@/config/axios'
// ERP 产品库存二维码 VO
export interface StockQrVO {
id: number // 编号
qr: string // 二维码
productId: number // 产品编号
warehouseId: number // 仓库编号
}
// ERP 产品库存二维码 API
export const StockQrApi = {
// 查询ERP 产品库存二维码分页
getStockQrPage: async (params: any) => {
return await request.get({ url: `/erp/stock-qr/page`, params })
},
// 查询ERP 产品库存二维码详情
getStockQr: async (id: number) => {
return await request.get({ url: `/erp/stock-qr/get?id=` + id })
},
// 新增ERP 产品库存二维码
createStockQr: async (data: StockQrVO) => {
return await request.post({ url: `/erp/stock-qr/create`, data })
},
// 修改ERP 产品库存二维码
updateStockQr: async (data: StockQrVO) => {
return await request.put({ url: `/erp/stock-qr/update`, data })
},
// 删除ERP 产品库存二维码
deleteStockQr: async (id: number) => {
return await request.delete({ url: `/erp/stock-qr/delete?id=` + id })
},
// 导出ERP 产品库存二维码 Excel
exportStockQr: async (params) => {
return await request.download({ url: `/erp/stock-qr/export-excel`, params })
}
}

View File

@ -0,0 +1,98 @@
import request from '@/config/axios'
// ERP 仓库 VO
export interface WarehouseVO {
id: number // 仓库编号
name: string // 仓库名称
address: string // 仓库地址
sort: number // 排序
remark: string // 备注
principal: string // 负责人
warehousePrice: number // 仓储费,单位:元
truckagePrice: number // 搬运费,单位:元
status: number // 开启状态
defaultStatus: boolean // 是否默认
}
export interface WarehouseLocationVO {
id: number // 仓库编号
name: string // 仓库名称
sort: number // 排序
warehouseId: number //仓库编号
remark: string // 备注
principal: string // 负责人
warehousePrice: number // 仓储费,单位:元
truckagePrice: number // 搬运费,单位:元
status: number // 开启状态
defaultStatus: boolean // 是否默认
}
// ERP 仓库 API
export const WarehouseApi = {
// 查询ERP 仓库分页
getWarehousePage: async (params: any) => {
return await request.get({ url: `/erp/warehouse/page`, params })
},
// 查询ERP 仓库详情
getWarehouse: async (id: number) => {
return await request.get({ url: `/erp/warehouse/get?id=` + id })
},
// 新增ERP 仓库
createWarehouse: async (data: WarehouseVO) => {
return await request.post({ url: `/erp/warehouse/create`, data })
},
// 修改ERP 仓库
updateWarehouse: async (data: WarehouseVO) => {
return await request.put({ url: `/erp/warehouse/update`, data })
},
// 修改仓库默认状态
updateWarehouseDefaultStatus: async (id: number, defaultStatus: boolean) => {
return await request.put({
url: `/erp/warehouse/update-default-status`,
params: {
id,
defaultStatus
}
})
},
// 删除ERP 仓库
deleteWarehouse: async (id: number) => {
return await request.delete({ url: `/erp/warehouse/delete?id=` + id })
},
// 导出ERP 仓库 Excel
exportWarehouse: async (params) => {
return await request.download({ url: `/erp/warehouse/export-excel`, params })
},
// ==================== 子表ERP 仓库货位) ====================
// 获得ERP 仓库货位分页
getWarehouseLocationPage: async (params) => {
return await request.get({ url: `/erp/warehouse/warehouse-location/page`, params })
},
// 新增ERP 仓库货位
createWarehouseLocation: async (data) => {
return await request.post({ url: `/erp/warehouse/warehouse-location/create`, data })
},
// 修改ERP 仓库货位
updateWarehouseLocation: async (data) => {
return await request.put({ url: `/erp/warehouse/warehouse-location/update`, data })
},
// 删除ERP 仓库货位
deleteWarehouseLocation: async (id: number) => {
return await request.delete({ url: `/erp/warehouse/warehouse-location/delete?id=` + id })
},
// 获得ERP 仓库货位
getWarehouseLocation: async (id: number) => {
return await request.get({ url: `/erp/warehouse/warehouse-location/get?id=` + id })
}
}

View File

@ -216,6 +216,17 @@ export enum DICT_TYPE {
// ========== ERP - 企业资源计划模块 ========== // ========== ERP - 企业资源计划模块 ==========
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态 ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型 ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型
ERP_PRODUCT_FAULT_PART = 'erp_product_fault_part', // 产品的故障部位
ERP_FILE_ORDER_TYPE = 'erp_file_order_type', // 文件单据类型
ERP_ORDER_PRE_STATUS = 'erp_order_pre_status', // 订单预报价单状态
ERP_PRODUCT_PROPERTIES_CATEGORY = 'erp_product_properties_category', // 产品属性的分类
ERP_PRODUCT_PROPERTIES = 'erp_product_properties', // 产品配件属性
ERP_PRODUCT_COMMON_PROPERTIES = 'erp_product_common_properties', // 产品普通属性
ERP_PRODUCT_INPUT_PROPERTIES = 'erp_product_input_properties', // 产品输入属性
ERP_PRODUCT_BRAND = 'erp_product_brand', // 产品品牌
ERP_PRODUCT_QR_MATCH='erp_product_qr_match', // 产品二维码匹配方式
// ========== AI - 人工智能模块 ========== // ========== AI - 人工智能模块 ==========
AI_PLATFORM = 'ai_platform', // AI 平台 AI_PLATFORM = 'ai_platform', // AI 平台

View File

@ -1,4 +1,43 @@
import { toNumber } from 'lodash-es' import { toNumber } from 'lodash-es'
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
/**
*
*/
export const matchRulesFromDictOptions = (s : string) => {
// 从字典获取规则
const dictOptions = getStrDictOptions(DICT_TYPE.ERP_PRODUCT_QR_MATCH)
//获取长度相关
const longMatch = dictOptions.filter((item) => {
return item.value === 'long'
})
const longMatchValue = longMatch[0].label
//将长度拼接字符串转换为数组
const longMatchArr = longMatchValue.split(',')
//判断数组中元素是否包含传入的字符串长度
const longMatchResult = longMatchArr.some((item) => {
return item === s.length.toString()
})
if (!longMatchResult) {
return false
}
//获取头部正则相关
const headMatch = dictOptions.filter((item) => {
return item.value === 'head'
})
const headMatchValue = headMatch[0].label
//将头部正则拼接字符串转换为数组
const headMatchArr = headMatchValue.split(',')
//判断数组中元素是否包含传入的字符串头部
const headMatchResult = headMatchArr.some((item) => {
return s.startsWith(item)
})
if (!headMatchResult) {
return false
}
return true
}
/** /**
* *

View File

@ -0,0 +1,219 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="供应商id" prop="sypplierId">
<el-input v-model="formData.sypplierId" placeholder="请输入供应商id" />
</el-form-item>
<el-form-item label="工单状态" prop="orderStatusId">
<el-select v-model="formData.orderStatusId" placeholder="请选择工单状态">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_ORDER_PRE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="分配时间" prop="fpTime">
<el-date-picker
v-model="formData.fpTime"
type="date"
value-format="x"
placeholder="选择分配时间"
/>
</el-form-item>
<el-form-item label="接单时间" prop="pickOrderTime">
<el-date-picker
v-model="formData.pickOrderTime"
type="date"
value-format="x"
placeholder="选择接单时间"
/>
</el-form-item>
<el-form-item label="开始报价时间" prop="startPriceTime">
<el-date-picker
v-model="formData.startPriceTime"
type="date"
value-format="x"
placeholder="选择开始报价时间"
/>
</el-form-item>
<el-form-item label="最晚报价时间" prop="needEndTime">
<el-date-picker
v-model="formData.needEndTime"
type="date"
value-format="x"
placeholder="选择最晚报价时间"
/>
</el-form-item>
<el-form-item label="结束报价时间" prop="endPriceTime">
<el-date-picker
v-model="formData.endPriceTime"
type="date"
value-format="x"
placeholder="选择结束报价时间"
/>
</el-form-item>
<el-form-item label="关单时间" prop="closeOrderTime">
<el-date-picker
v-model="formData.closeOrderTime"
type="date"
value-format="x"
placeholder="选择关单时间"
/>
</el-form-item>
<el-form-item label="取消工单原因" prop="cancelRemark">
<el-input v-model="formData.cancelRemark" type="textarea" placeholder="请输入取消工单原因" />
</el-form-item>
<el-form-item label="报价者备注" prop="priceUserRemark">
<el-input v-model="formData.priceUserRemark" type="textarea" placeholder="请输入报价者备注" />
</el-form-item>
<el-form-item label="派单者id" prop="dispUserId">
<el-input v-model="formData.dispUserId" placeholder="请输入派单者id" />
</el-form-item>
<el-form-item label="接单者id" prop="pickUserId">
<el-input v-model="formData.pickUserId" placeholder="请输入接单者id" />
</el-form-item>
<el-form-item label="报价者id" prop="priceUserId">
<el-input v-model="formData.priceUserId" placeholder="请输入报价者id" />
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="加急" prop="expedited">
<el-input v-model="formData.expedited" placeholder="请输入加急" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="Erp单据文件" name="orderFile">
<OrderFileForm ref="orderFileFormRef" :order-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { BdOrderPreQuoteApi, BdOrderPreQuoteVO } from '@/api/erp/bdorderprequote'
import OrderFileForm from './components/OrderFileForm.vue'
/** erp商务预报价 表单 */
defineOptions({ name: 'BdOrderPreQuoteForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
orderId: undefined,
sypplierId: undefined,
orderStatusId: undefined,
fpTime: undefined,
pickOrderTime: undefined,
startPriceTime: undefined,
needEndTime: undefined,
endPriceTime: undefined,
closeOrderTime: undefined,
cancelRemark: undefined,
priceUserRemark: undefined,
dispUserId: undefined,
pickUserId: undefined,
priceUserId: undefined,
address: undefined,
expedited: undefined
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('orderFile')
const orderFileFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await BdOrderPreQuoteApi.getBdOrderPreQuote(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await orderFileFormRef.value.validate()
} catch (e) {
subTabsName.value = 'orderFile'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as BdOrderPreQuoteVO
//
data.orderFiles = orderFileFormRef.value.getData()
if (formType.value === 'create') {
await BdOrderPreQuoteApi.createBdOrderPreQuote(data)
message.success(t('common.createSuccess'))
} else {
await BdOrderPreQuoteApi.updateBdOrderPreQuote(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
orderId: undefined,
sypplierId: undefined,
orderStatusId: undefined,
fpTime: undefined,
pickOrderTime: undefined,
startPriceTime: undefined,
needEndTime: undefined,
endPriceTime: undefined,
closeOrderTime: undefined,
cancelRemark: undefined,
priceUserRemark: undefined,
dispUserId: undefined,
pickUserId: undefined,
priceUserId: undefined,
address: undefined,
expedited: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,105 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="文件单据类型" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.fileTypeId`" :rules="formRules.fileTypeId" class="mb-0px!">
<el-select v-model="row.fileTypeId" placeholder="请选择文件单据类型">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_FILE_ORDER_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="关联文件id" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.infraFileId`" :rules="formRules.infraFileId" class="mb-0px!">
<el-input v-model="row.infraFileId" placeholder="请输入关联文件id" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加Erp单据文件</el-button>
</el-row>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { BdOrderPreQuoteApi } from '@/api/erp/bdorderprequote'
const props = defineProps<{
orderId: undefined //
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.orderId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await BdOrderPreQuoteApi.getOrderFileListByOrderId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
orderId: undefined,
fileTypeId: undefined,
infraFileId: undefined
}
row.orderId = props.orderId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,56 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="文件单据类型" align="center" prop="fileTypeId">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_FILE_ORDER_TYPE" :value="scope.row.fileTypeId" />
</template>
</el-table-column>
<el-table-column label="关联文件id" align="center" prop="infraFileId" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
</ContentWrap>
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { BdOrderPreQuoteApi } from '@/api/erp/bdorderprequote'
const { t } = useI18n() //
const message = useMessage() //
const props = defineProps<{
orderId?: number //
}>()
const loading = ref(false) //
const list = ref([]) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
list.value = await BdOrderPreQuoteApi.getOrderFileListByOrderId(props.orderId)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,317 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="工单状态" prop="orderStatusId">
<el-select
v-model="queryParams.orderStatusId"
placeholder="请选择工单状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_ORDER_PRE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="分配时间" prop="fpTime">
<el-date-picker
v-model="queryParams.fpTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="接单时间" prop="pickOrderTime">
<el-date-picker
v-model="queryParams.pickOrderTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="关单时间" prop="closeOrderTime">
<el-date-picker
v-model="queryParams.closeOrderTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input
v-model="queryParams.address"
placeholder="请输入地址"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:bd-order-pre-quote:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:bd-order-pre-quote:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<el-tabs model-value="orderFile">
<el-tab-pane label="Erp单据文件" name="orderFile">
<OrderFileList :order-id="scope.row.id" />
</el-tab-pane>
</el-tabs>
</template>
</el-table-column>
<el-table-column label="报价单号" align="center" prop="orderId" />
<el-table-column label="供应商" align="center" prop="sypplierId" />
<el-table-column label="工单状态" align="center" prop="orderStatusId">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_ORDER_PRE_STATUS" :value="scope.row.orderStatusId" />
</template>
</el-table-column>
<el-table-column
label="分配时间"
align="center"
prop="fpTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="接单时间"
align="center"
prop="pickOrderTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="开始报价时间"
align="center"
prop="startPriceTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="最晚报价时间"
align="center"
prop="needEndTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="结束报价时间"
align="center"
prop="endPriceTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="关单时间"
align="center"
prop="closeOrderTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="取消工单原因" align="center" prop="cancelRemark" />
<el-table-column label="报价者备注" align="center" prop="priceUserRemark" />
<el-table-column label="派单者" align="center" prop="dispUserId" />
<el-table-column label="接单者" align="center" prop="pickUserId" />
<el-table-column label="报价者" align="center" prop="priceUserId" />
<el-table-column label="地址" align="center" prop="address" />
<el-table-column label="加急" align="center" prop="expedited" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:bd-order-pre-quote:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:bd-order-pre-quote:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<BdOrderPreQuoteForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { BdOrderPreQuoteApi, BdOrderPreQuoteVO } from '@/api/erp/bdorderprequote'
import BdOrderPreQuoteForm from './BdOrderPreQuoteForm.vue'
import OrderFileList from './components/OrderFileList.vue'
/** erp商务预报价 列表 */
defineOptions({ name: 'BdOrderPreQuote' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<BdOrderPreQuoteVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
sypplierId: undefined,
orderStatusId: undefined,
fpTime: [],
pickOrderTime: [],
startPriceTime: [],
needEndTime: [],
endPriceTime: [],
closeOrderTime: [],
cancelRemark: undefined,
priceUserRemark: undefined,
dispUserId: undefined,
pickUserId: undefined,
priceUserId: undefined,
address: undefined,
expedited: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await BdOrderPreQuoteApi.getBdOrderPreQuotePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await BdOrderPreQuoteApi.deleteBdOrderPreQuote(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await BdOrderPreQuoteApi.exportBdOrderPreQuote(queryParams)
download.excel(data, 'erp商务预报价.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,208 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="产品分类" prop="productCategoryId">
<!-- 普通显示 -->
<el-select v-model="formData.productCategoryId" placeholder="请选择产品分类" @change="limitFaultPart" disabled filterable clearable>
<el-option v-for="item in productCategoryList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="故障部位" prop="productFaultPart">
<el-select v-model="formData.productFaultPart" placeholder="请选择故障部位">
<el-option
v-for="dict in dictfaultPartListSelect"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="具体故障" prop="productFault">
<el-input v-model="formData.productFault" placeholder="请输入具体故障" />
</el-form-item>
<el-form-item label="影响销售" prop="ifAffectSale">
<el-radio-group v-model="formData.ifAffectSale">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item label="影响销售%" prop="affectSalePercentage">
<el-input v-model="formData.affectSalePercentage" placeholder="请输入影响销售%" />
</el-form-item>
<el-form-item label="影响销售金额" prop="affectSaleMoney">
<el-input v-model="formData.affectSaleMoney" placeholder="请输入影响销售金额" />
</el-form-item>
<el-form-item label="影响回收" prop="ifAffectRecycle">
<el-radio-group v-model="formData.ifAffectRecycle">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item label="影响回收%" prop="affectRecyclePercentage">
<el-input v-model="formData.affectRecyclePercentage" placeholder="请输入影响回收%" />
</el-form-item>
<el-form-item label="影响回收金额" prop="affectRecycleMoney">
<el-input v-model="formData.affectRecycleMoney" placeholder="请输入影响回收金额" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { defineProps } from 'vue';
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryFaultApi, ProductCategoryFaultVO } from '@/api/erp/product/category/erpproductcategoryfault'
import { ProductCategoryVO } from '@/api/erp/product/category'
import { ProductCategoryPartApi, ProductCategoryPartVO} from '@/api/erp/product/category/productcategorypart'
/** 从父组件取productCategoryList数组*/
const props = defineProps<{
productCategoryList: ProductCategoryVO[]
productCategoryId: number
}
>();
/** 定义一个类型部位数组 */
const productCategoryPartList = ref<ProductCategoryPartVO[]>([])
/** 定义一个字典类型的故障部位数组 */
let dictfaultPartList = ref<{ value: string, label: string }[]>([])
let dictfaultPartListSelect = ref<{ value: string, label: string }[]>([])
/** ERP 产品分类故障 表单 */
defineOptions({ name: 'ProductCategoryFaultForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productCategoryId: null as number | null,
productFaultPart: undefined,
productFault: undefined,
ifAffectSale: undefined,
affectSalePercentage: undefined,
affectSaleMoney: undefined,
ifAffectRecycle: undefined,
affectRecyclePercentage: undefined,
affectRecycleMoney: undefined
})
const formRules = reactive({
productCategoryId: [{ required: true, message: '产品分类不能为空', trigger: 'blur' }],
productFaultPart: [{ required: true, message: '故障部位不能为空', trigger: 'change' }],
productFault: [{ required: true, message: '具体故障不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.productCategoryId = props.productCategoryId
//
if (id) {
formLoading.value = true
try {
const data = await ProductCategoryFaultApi.getProductCategoryFault(id)
formData.value = {
...data,
ifAffectRecycle: data.ifAffectRecycle ? 'true' : 'false' ,//
ifAffectSale: data.ifAffectSale? 'true' : 'false' //
}
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryFaultVO
if (formType.value === 'create') {
await ProductCategoryFaultApi.createProductCategoryFault(data)
message.success(t('common.createSuccess'))
} else {
await ProductCategoryFaultApi.updateProductCategoryFault(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productCategoryId: null as number | null,
productFaultPart: undefined,
productFault: undefined,
ifAffectSale: undefined,
affectSalePercentage: undefined,
affectSaleMoney: undefined,
ifAffectRecycle: undefined,
affectRecyclePercentage: undefined,
affectRecycleMoney: undefined
}
formRef.value?.resetFields()
}
/** 获取现在的产品分类id通过产品分类id查询产品分类部位数组 */
const limitFaultPart = (productCategoryId: number) => {
if (productCategoryId) {
//
formData.value.productFaultPart = undefined
ProductCategoryPartApi.getProductCategoryPartPage({ productCategoryId })
.then(res => {
productCategoryPartList.value = res.list
//
const faultPartList = productCategoryPartList.value.map(item => item.productFaultPart)
// faultPartListdictfaultPartList
dictfaultPartListSelect.value = dictfaultPartList.value.filter(item => faultPartList.includes(item.value))
})
}
}
/** 创建页面 */
onMounted(() => {
dictfaultPartList.value = getStrDictOptions(DICT_TYPE.ERP_PRODUCT_FAULT_PART)
dictfaultPartListSelect.value = dictfaultPartList.value
})
</script>

View File

@ -0,0 +1,352 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品分类" prop="productCategoryId">
<el-select
v-model="queryParams.productCategoryId"
placeholder="请选择产品分类"
disabled
clearable
class="!w-240px"
>
<el-option
v-for="dict in productCategoryList"
:key="dict.id"
:label="dict.name"
:value="dict.id"
/>
</el-select>
</el-form-item>
<el-form-item label="故障部位" prop="productFaultPart">
<el-select
v-model="queryParams.productFaultPart"
placeholder="请选择故障部位"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_FAULT_PART)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="具体故障" prop="productFault">
<el-input
v-model="queryParams.productFault"
placeholder="请输入具体故障"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="影响销售" prop="ifAffectSale">
<el-select
v-model="queryParams.ifAffectSale"
placeholder="请选择影响销售"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="影响销售%" prop="affectSalePercentage">
<el-input
v-model="queryParams.affectSalePercentage"
placeholder="请输入影响销售%"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="影响销售金额" prop="affectSaleMoney">
<el-input
v-model="queryParams.affectSaleMoney"
placeholder="请输入影响销售金额"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="影响回收" prop="ifAffectRecycle">
<el-select
v-model="queryParams.ifAffectRecycle"
placeholder="请选择影响回收"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="影响回收%" prop="affectRecyclePercentage">
<el-input
v-model="queryParams.affectRecyclePercentage"
placeholder="请输入影响回收%"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="影响回收金额" prop="affectRecycleMoney">
<el-input
v-model="queryParams.affectRecycleMoney"
placeholder="请输入影响回收金额"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category-fault:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category-fault:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品分类" align="center" prop="productCategoryId">
<template #default="scope">
{{ getCategoryName(scope.row.productCategoryId) }}
</template>
</el-table-column>
<el-table-column label="故障部位" align="center" prop="productFaultPart">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_FAULT_PART" :value="scope.row.productFaultPart" />
</template>
</el-table-column>
<el-table-column label="具体故障" align="center" prop="productFault" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="影响销售" align="center" prop="ifAffectSale" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifAffectSale" />
</template>
</el-table-column>
<el-table-column label="影响销售%" align="center" prop="affectSalePercentage" />
<el-table-column label="影响销售金额" align="center" prop="affectSaleMoney" />
<el-table-column label="影响回收" align="center" prop="ifAffectRecycle" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifAffectRecycle" />
</template>
</el-table-column>
<el-table-column label="影响回收%" align="center" prop="affectRecyclePercentage" />
<el-table-column label="影响回收金额" align="center" prop="affectRecycleMoney" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category-fault:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category-fault:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryFaultForm ref="formRef" @success="getList" :product-category-list="productCategoryList" :product-category-id="queryParams.productCategoryId"/>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCategoryFaultApi, ProductCategoryFaultVO } from '@/api/erp/product/category/erpproductcategoryfault'
import ProductCategoryFaultForm from './ProductCategoryFaultForm.vue'
import { ProductCategoryApi , ProductCategoryVO } from '@/api/erp/product/category'
/** ERP 产品分类的数组 */
const productCategoryList = ref<ProductCategoryVO[]>([])
/** ERP 产品分类故障 列表 */
defineOptions({ name: 'ErpProductCategoryFault' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductCategoryFaultVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryId: null as any,
productFaultPart: undefined,
productFault: undefined,
createTime: [],
ifAffectSale: undefined,
affectSalePercentage: undefined,
affectSaleMoney: undefined,
ifAffectRecycle: undefined,
affectRecyclePercentage: undefined,
affectRecycleMoney: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const route = useRoute() //
let searchCount = 0
/** 查询列表 */
const getList = async () => {
loading.value = true
if(route.query.searchId && searchCount == 0){
searchCount++
queryParams.productCategoryId = Number(route.query.searchId)
}
try {
const data = await ProductCategoryFaultApi.getProductCategoryFaultPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCategoryFaultApi.deleteProductCategoryFault(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCategoryFaultApi.exportProductCategoryFault(queryParams)
download.excel(data, 'ERP 产品分类故障.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 根据用户输入搜索产品分类 */
const searchProductCategory = async () => {
//param
const params = {
status: 0
}
try {
productCategoryList.value = await ProductCategoryApi.getProductCategoryList(params)
} catch (error) {
productCategoryList.value = []
}
}
/** 根据 productCategoryId 获取产品分类名称 */
const getCategoryName = (id: number | undefined) => {
if (!id) return ''
const category = productCategoryList.value.find(item => item.id === id)
return category ? category.name : '' // name
}
/** 初始化 **/
onMounted(() => {
getList()
searchProductCategory()
})
</script>

View File

@ -89,6 +89,25 @@
/> />
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default="scope"> <template #default="scope">
<router-link :to="'/erp/product/product-category-properties?searchId=' + scope.row.id"
v-hasPermi="['erp:product-category-properties:query']"
v-show="scope.row.status === 0"
>
<el-button link type="primary"
>属性</el-button>
</router-link>
<router-link :to="'/erp/product/product-category-fault?searchId=' + scope.row.id"
v-hasPermi="['erp:product-category-fault:query']"
v-show="scope.row.status === 0"
>
<el-button link type="primary">故障</el-button>
</router-link>
<router-link :to="'/erp/product/product-category-part?searchId=' + scope.row.id"
v-hasPermi="['erp:product-category-part:query']"
v-show="scope.row.status === 0"
>
<el-button link type="primary">部位</el-button>
</router-link>
<el-button <el-button
link link
type="primary" type="primary"
@ -129,6 +148,7 @@ import download from '@/utils/download'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category' import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import ProductCategoryForm from './ProductCategoryForm.vue' import ProductCategoryForm from './ProductCategoryForm.vue'
/** ERP 产品分类 列表 */ /** ERP 产品分类 列表 */
defineOptions({ name: 'ErpProductCategory' }) defineOptions({ name: 'ErpProductCategory' })
@ -138,9 +158,12 @@ const { t } = useI18n() // 国际化
const loading = ref(true) // const loading = ref(true) //
const list = ref<ProductCategoryVO[]>([]) // const list = ref<ProductCategoryVO[]>([]) //
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined, name: undefined,
status: undefined status: undefined,
}) })
const total = ref(0) //
const queryFormRef = ref() // const queryFormRef = ref() //
const exportLoading = ref(false) // const exportLoading = ref(false) //
@ -172,7 +195,6 @@ const formRef = ref()
const openForm = (type: string, id?: number) => { const openForm = (type: string, id?: number) => {
formRef.value.open(type, id) formRef.value.open(type, id)
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {

View File

@ -0,0 +1,126 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="产品分类" prop="productCategoryId">
<el-select v-model="formData.productCategoryId" placeholder="请选择产品分类" disabled filterable clearable>
<el-option
v-for="item in productCategoryList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="部位" prop="productFaultPart">
<el-select v-model="formData.productFaultPart" placeholder="请选择部位">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_FAULT_PART)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { defineProps } from 'vue';
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryVO } from '@/api/erp/product/category'
import { ProductCategoryPartApi, ProductCategoryPartVO } from '@/api/erp/product/category/productcategorypart'
/** 从父组件取productCategoryList数组*/
const props = defineProps<{
productCategoryList: ProductCategoryVO[]
productCategoryId: number
}
>();
/** ERP 产品分类部位 表单 */
defineOptions({ name: 'ProductCategoryPartForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productCategoryId: null as number | null,
productFaultPart: undefined
})
const formRules = reactive({
productCategoryId: [{ required: true, message: '产品分类不能为空', trigger: 'change' }],
productFaultPart: [{ required: true, message: '部位不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.productCategoryId = props.productCategoryId
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCategoryPartApi.getProductCategoryPart(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryPartVO
if (formType.value === 'create') {
await ProductCategoryPartApi.createProductCategoryPart(data)
message.success(t('common.createSuccess'))
} else {
await ProductCategoryPartApi.updateProductCategoryPart(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productCategoryId: null as number | null,
productFaultPart: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,252 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品分类" prop="productCategoryId">
<el-select
v-model="queryParams.productCategoryId"
placeholder="请选择产品分类"
disabled
clearable
class="!w-240px"
>
<el-option
v-for="item in productCategoryList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="部位" prop="productFaultPart">
<el-select
v-model="queryParams.productFaultPart"
placeholder="请选择部位"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_FAULT_PART)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category-part:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category-part:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品分类" align="center" prop="productCategoryId">
<template #default="scope">
{{ getCategoryName(scope.row.productCategoryId) }}
</template>
</el-table-column>
<el-table-column label="部位" align="center" prop="productFaultPart">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_FAULT_PART" :value="scope.row.productFaultPart" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category-part:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category-part:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryPartForm ref="formRef" @success="getList" :product-category-list="productCategoryList" :product-category-id="queryParams.productCategoryId"/>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCategoryPartApi, ProductCategoryPartVO } from '@/api/erp/product/category/productcategorypart'
import ProductCategoryPartForm from './ProductCategoryPartForm.vue'
import { ProductCategoryApi , ProductCategoryVO } from '@/api/erp/product/category'
const route = useRoute() //
let searchCount = 0
/** ERP 产品分类的数组 */
const productCategoryList = ref<ProductCategoryVO[]>([])
/** ERP 产品分类部位 列表 */
defineOptions({ name: 'ErpProductCategoryPart' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductCategoryPartVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryId: null as any,
productFaultPart: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
if(route.query.searchId && searchCount == 0){
searchCount++
queryParams.productCategoryId = Number(route.query.searchId)
}
try {
const data = await ProductCategoryPartApi.getProductCategoryPartPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCategoryPartApi.deleteProductCategoryPart(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCategoryPartApi.exportProductCategoryPart(queryParams)
download.excel(data, 'ERP 产品分类部位.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 根据用户输入搜索产品分类 */
const searchProductCategory = async () => {
//param
const params = {
status: 0
}
try {
productCategoryList.value = await ProductCategoryApi.getProductCategoryList(params)
} catch (error) {
productCategoryList.value = []
}
}
/** 根据 productCategoryId 获取产品分类名称 */
const getCategoryName = (id: number | undefined) => {
if (!id) return ''
const category = productCategoryList.value.find(item => item.id === id)
return category ? category.name : '' // name
}
/** 初始化 **/
onMounted(() => {
getList()
searchProductCategory()
})
</script>

View File

@ -0,0 +1,211 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="产品分类" prop="productCategoryId">
<el-select v-model="formData.productCategoryId" disabled placeholder="请选择产品分类">
<el-option
v-for="dict in productCategoryList"
:key="dict.id"
:label="dict.name"
:value="dict.id"
/>
</el-select>
</el-form-item>
<el-form-item label="属性分类" prop="productPropertiesCategory">
<el-radio-group v-model="formData.productPropertiesCategory">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_PRODUCT_PROPERTIES_CATEGORY)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item label="单数属性" prop="ifSingleProperty">
<el-radio-group v-model="formData.ifSingleProperty">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item label="属性英文" prop="productPropertiesEn">
<el-select
v-model="formData.productPropertiesEn"
placeholder="请选择属性英文"
clearable
class="!w-240px"
>
<div v-if="formData.productPropertiesCategory===0">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_COMMON_PROPERTIES)"
:key="dict.value"
:label="dict.value+'#'+dict.label"
:value="dict.value"
/>
</div>
<div v-else-if="formData.productPropertiesCategory===1">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_PROPERTIES)"
:key="dict.value"
:label="dict.value+'#'+dict.label"
:value="dict.value"
/>
</div>
<div v-else-if="formData.productPropertiesCategory===2">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_INPUT_PROPERTIES)"
:key="dict.value"
:label="dict.value+'#'+dict.label"
:value="dict.value"
/>
</div>
</el-select>
</el-form-item>
<el-form-item label="必填" prop="ifRequired">
<el-radio-group v-model="formData.ifRequired">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.productPropertiesCategory===1"
label="记录sn" prop="ifSn">
<el-radio-group v-model="formData.ifSn">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { defineProps } from 'vue';
import { getBoolDictOptions,getStrDictOptions,getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryPropertiesApi, ProductCategoryPropertiesVO } from '@/api/erp/product/category/productcategoryproperties'
import { ProductCategoryVO } from '@/api/erp/product/category'
/** 从父组件取数据*/
const props = defineProps<{
productCategoryList: ProductCategoryVO[]
productCategoryId: number
}>();
/** ERP 产品分类属性 表单 */
defineOptions({ name: 'ProductCategoryPropertiesForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productCategoryId: null as number | null,
ifSingleProperty: [],
productPropertiesEn: undefined,
productPropertiesCn: undefined,
ifRequired: undefined,
productPropertiesCategory: undefined,
ifSn: false
})
const formRules = reactive({
productCategoryId: [{ required: true, message: '类别属性不能为空', trigger: 'change' }],
ifSingleProperty: [{ required: true, message: '单数属性不能为空', trigger: 'blur' }],
ifRequired: [{ required: true, message: '必填不能为空', trigger: 'change' }],
productPropertiesCategory: [{ required: true, message: '属性分类不能为空', trigger: 'change' }],
ifSn: [{ required: true, message: '记录sn不能为空', trigger: 'blur' }],
productPropertiesCn : [{ required: true, message: '属性中文不能为空', trigger: 'blur' }],
productPropertiesEn : [{ required: true, message: '属性英文不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.productCategoryId = props.productCategoryId
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCategoryPropertiesApi.getProductCategoryProperties(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryPropertiesVO
if (formType.value === 'create') {
await ProductCategoryPropertiesApi.createProductCategoryProperties(data)
message.success(t('common.createSuccess'))
} else {
await ProductCategoryPropertiesApi.updateProductCategoryProperties(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productCategoryId: null as number | null,
ifSingleProperty: [],
productPropertiesEn: undefined,
productPropertiesCn: undefined,
ifRequired: undefined,
productPropertiesCategory: undefined,
ifSn: false
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,349 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="类别" prop="productCategoryId">
<el-select
v-model="queryParams.productCategoryId"
placeholder="请选择类别"
disabled
clearable
class="!w-240px"
>
<el-option
v-for="dict in productCategoryList"
:key="dict.id"
:label="dict.name"
:value="dict.id"
/>
</el-select>
</el-form-item>
<el-form-item label="属性分类" prop="productPropertiesCategory">
<el-select
v-model="queryParams.productPropertiesCategory"
placeholder="请选择属性分类"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_PRODUCT_PROPERTIES_CATEGORY)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="单数属性" prop="ifSingleProperty">
<el-select
v-model="queryParams.ifSingleProperty"
placeholder="请选择单数属性"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="属性英文" prop="productPropertiesEn">
<el-input
v-model="queryParams.productPropertiesEn"
placeholder="请输入设备属性英文"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="属性中文" prop="productPropertiesCn">
<el-input
v-model="queryParams.productPropertiesCn"
placeholder="请输入设备属性中文"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="必填" prop="ifRequired">
<el-select
v-model="queryParams.ifRequired"
placeholder="请选择是否必填"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="记录sn" prop="ifSn">
<el-select
v-model="queryParams.ifSn"
placeholder="请选择是否记录sn"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category-properties:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category-properties:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品分类" align="center" prop="productCategoryId">
<template #default="scope">
{{ getCategoryName(scope.row.productCategoryId) }}
</template>
</el-table-column>
<el-table-column label="单数属性" align="center" prop="ifSingleProperty">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifSingleProperty" />
</template>
</el-table-column>
<el-table-column label="属性英文" align="center" prop="productPropertiesEn" />
<el-table-column label="属性中文" align="center" prop="productPropertiesCn" />
<el-table-column label="必填" align="center" prop="ifRequired">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifRequired" />
</template>
</el-table-column>
<el-table-column label="属性分类" align="center" prop="productPropertiesCategory">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_PROPERTIES_CATEGORY" :value="scope.row.productPropertiesCategory" />
</template>
</el-table-column>
<el-table-column label="记录sn" align="center" prop="ifSn">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifSn" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<router-link :to="'/erp/product/product-category-properties-category-map?productCategoryPropertiesId=' + scope.row.id+'&productPropertiesCategory='+scope.row.productPropertiesCategory"
v-show="scope.row.productPropertiesCategory !== 2"
v-hasPermi="['erp:product-category-properties-category-map:query']"
>
<el-button link type="primary"
>绑定</el-button>
</router-link>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category-properties:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category-properties:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryPropertiesForm ref="formRef" @success="getList" :product-category-id="queryParams.productCategoryId" :product-category-list="productCategoryList" />
</template>
<script setup lang="ts">
import { getBoolDictOptions,getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCategoryPropertiesApi, ProductCategoryPropertiesVO } from '@/api/erp/product/category/productcategoryproperties'
import ProductCategoryPropertiesForm from './ProductCategoryPropertiesForm.vue'
import { ProductCategoryApi , ProductCategoryVO } from '@/api/erp/product/category'
const route = useRoute() //
let searchCount = 0
/** ERP 产品分类的数组 */
const productCategoryList = ref<ProductCategoryVO[]>([])
/** ERP 产品分类属性 列表 */
defineOptions({ name: 'ProductCategoryProperties' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductCategoryPropertiesVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryId: null as any,
ifSingleProperty: undefined,
productPropertiesEn: undefined,
productPropertiesCn: undefined,
ifRequired: undefined,
productPropertiesCategory: undefined,
ifSn: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
if(route.query.searchId && searchCount == 0){
searchCount++
queryParams.productCategoryId = Number(route.query.searchId)
}
try {
const data = await ProductCategoryPropertiesApi.getProductCategoryPropertiesPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCategoryPropertiesApi.deleteProductCategoryProperties(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCategoryPropertiesApi.exportProductCategoryProperties(queryParams)
download.excel(data, 'ERP 产品分类属性.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 根据用户输入搜索类别 */
const searchProductCategory = async () => {
//param
const params = {
status: 0
}
try {
productCategoryList.value = await ProductCategoryApi.getProductCategoryList(params)
} catch (error) {
productCategoryList.value = []
}
}
/** 根据 productCategoryId 获取类别名称 */
const getCategoryName = (id: number | undefined) => {
if (!id) return ''
const category = productCategoryList.value.find(item => item.id === id)
return category ? category.name : '' // name
}
/** 初始化 **/
onMounted(() => {
getList()
searchProductCategory()
})
</script>

View File

@ -0,0 +1,106 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="产品分类属性" prop="productCategoryPropertiesId">
<el-select v-model="formData.productCategoryPropertiesId" placeholder="请选择产品分类属性">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_PRODUCT_COMMON_PROPERTIES)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="产品分类属性值" prop="productCategoryPropertiesValue">
<el-input v-model="formData.productCategoryPropertiesValue" placeholder="请输入产品分类属性值" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryPropertiesValueApi, ProductCategoryPropertiesValueVO } from '@/api/erp/product/category/productcategoryproperties/productcategorypropertiesvalue'
/** ERP 产品分类属性值 表单 */
defineOptions({ name: 'ProductCategoryPropertiesValueForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productCategoryPropertiesId: undefined,
productCategoryPropertiesValue: undefined
})
const formRules = reactive({
productCategoryPropertiesId: [{ required: true, message: '产品分类属性不能为空', trigger: 'change' }],
productCategoryPropertiesValue: [{ required: true, message: '产品分类属性值不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCategoryPropertiesValueApi.getProductCategoryPropertiesValue(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryPropertiesValueVO
if (formType.value === 'create') {
await ProductCategoryPropertiesValueApi.createProductCategoryPropertiesValue(data)
message.success(t('common.createSuccess'))
} else {
await ProductCategoryPropertiesValueApi.updateProductCategoryPropertiesValue(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productCategoryPropertiesId: undefined,
productCategoryPropertiesValue: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,209 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品分类属性" prop="productCategoryPropertiesId">
<el-select
v-model="queryParams.productCategoryPropertiesId"
placeholder="请选择产品分类属性"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_PRODUCT_COMMON_PROPERTIES)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="产品分类属性值" prop="productCategoryPropertiesValue">
<el-input
v-model="queryParams.productCategoryPropertiesValue"
placeholder="请输入产品分类属性值"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category-properties-value:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category-properties-value:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品分类属性" align="center" prop="productCategoryPropertiesId">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_COMMON_PROPERTIES" :value="scope.row.productCategoryPropertiesId" />
</template>
</el-table-column>
<el-table-column label="产品分类属性值" align="center" prop="productCategoryPropertiesValue" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category-properties-value:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category-properties-value:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryPropertiesValueForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCategoryPropertiesValueApi, ProductCategoryPropertiesValueVO } from '@/api/erp/product/category/productcategoryproperties/productcategorypropertiesvalue'
import ProductCategoryPropertiesValueForm from './ProductCategoryPropertiesValueForm.vue'
/** ERP 产品分类属性值 列表 */
defineOptions({ name: 'ErpProductCategoryPropertiesValue' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductCategoryPropertiesValueVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryPropertiesId: undefined,
productCategoryPropertiesValue: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProductCategoryPropertiesValueApi.getProductCategoryPropertiesValuePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCategoryPropertiesValueApi.deleteProductCategoryPropertiesValue(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCategoryPropertiesValueApi.exportProductCategoryPropertiesValue(queryParams)
download.excel(data, 'ERP 产品分类属性值.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,210 @@
<template>
<Dialog title="新增分类属性值" v-model="valueDialogVisible">
<el-form ref="valueFormRef" :model="valueFormData" :rules="valueFormRules" label-width="100px" v-loading="formLoading">
<el-form-item label="分类属性值" prop="productCategoryPropertiesValue">
<el-input v-model="valueFormData.productCategoryPropertiesValue" placeholder="请输入分类属性值" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="addProductCategoryPropertiesValue" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="valueDialogVisible = false"> </el-button>
</template>
</Dialog>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="分类属性" prop="productCategoryPropertiesId" v-show="false">
<el-input v-model="formData.productCategoryPropertiesId" placeholder="请输入分类属性" clearable />
</el-form-item>
<el-form-item label="分类属性" prop="productPropertiesCn">
<el-input v-model="formData.productPropertiesCn" placeholder="请输入分类属性" clearable disabled />
</el-form-item>
<el-form-item label="产品分类" prop="productCategoryId" v-if="productPropertiesCategory === 1">
<el-tree-select v-model="formData.productCategoryId" :data="productCategoryTree" :props="defaultProps"
check-strictly default-expand-all placeholder="请选择上级编号" />
</el-form-item>
<el-row v-if="productPropertiesCategory === 0">
<el-col :span="21">
<el-form-item label="分类属性值" prop="productCategoryPropertiesValue">
<el-select v-model="formData.productCategoryPropertiesValue" placeholder="请选择产品分类属性值" clearable>
<el-option v-for="dict in productCategoryPropertiesValueList" :key="dict.id"
:label="dict.productCategoryPropertiesValue" :value="dict.productCategoryPropertiesValue" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="1">
<span></span>
</el-col>
<el-col :span="1">
<el-button type="primary" @click="openValueForm"> </el-button>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ProductCategoryPropertiesCategoryMapApi, ProductCategoryPropertiesCategoryMapVO } from '@/api/erp/product/category/productcategoryproperties/propertiescategorymap'
import { ProductCategoryApi } from '@/api/erp/product/category'
import { defaultProps, handleTree } from '@/utils/tree'
import { ProductCategoryPropertiesApi } from '@/api/erp/product/category/productcategoryproperties'
import { ProductCategoryPropertiesValueApi, ProductCategoryPropertiesValueVO } from '@/api/erp/product/category/productcategoryproperties/productcategorypropertiesvalue'
/** 产品属性类别 */
let productPropertiesCategory = ref()
/** 产品分类的list */
const productCategoryTree = ref() //
/** 从父组件取数据*/
const props = defineProps<{
productPropertiesCn: string,
productCategoryPropertiesId: number,
}>();
/** ERP 产品分类属性绑定 表单 */
defineOptions({ name: 'ProductCategoryPropertiesCategoryMapForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
//
const valueDialogVisible = ref(false) //
const valueFormData = ref({
productCategoryPropertiesValue: null as any
})
const valueFormRules = reactive({
productCategoryPropertiesValue: [
{ required: true, message: '请输入分类属性值', trigger: 'blur' },
]
})
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productPropertiesCn: null as any,
productCategoryId: undefined,
productCategoryPropertiesValue: undefined,
productCategoryPropertiesId: null as any
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 分类属性值list */
const productCategoryPropertiesValueList = ref()
/** 新增分类属性值 */
const addProductCategoryPropertiesValue = async () => {
const data = {
productCategoryPropertiesId: props.productCategoryPropertiesId,
productCategoryPropertiesValue: valueFormData.value.productCategoryPropertiesValue
}
await ProductCategoryPropertiesValueApi.createProductCategoryPropertiesValue(data).then((res) => {
getAllProductCategoryPropertiesValue()
valueDialogVisible.value = false
message.success(t('common.createSuccess'))
})
}
/** 查询分类属性值的可选项 */
const getAllProductCategoryPropertiesValue = async () => {
await ProductCategoryPropertiesValueApi.getProductCategoryPropertiesValuePage({
pageNo: 1,
pageSize: 100,
productCategoryPropertiesId: props.productCategoryPropertiesId
}).then((res) => {
productCategoryPropertiesValueList.value = res.list
})
}
/** 判断使用下拉还是使用自定义属性 */
const getProductPropertiesCategory = async () => {
ProductCategoryPropertiesApi.getProductCategoryProperties(props.productCategoryPropertiesId).then((res) => {
productPropertiesCategory.value = res.productPropertiesCategory
})
}
/** 打开分类属性值弹窗 */
const openValueForm = () => {
valueDialogVisible.value = true
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.productCategoryPropertiesId = props.productCategoryPropertiesId
formData.value.productPropertiesCn = props.productPropertiesCn
await getProductPropertiesCategory()
await getAllProductCategoryPropertiesValue()
getAllProductCategory()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCategoryPropertiesCategoryMapApi.getProductCategoryPropertiesCategoryMap(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
console.log(formData.value)
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryPropertiesCategoryMapVO
if (formType.value === 'create') {
await ProductCategoryPropertiesCategoryMapApi.createProductCategoryPropertiesCategoryMap(data)
message.success(t('common.createSuccess'))
} else {
await ProductCategoryPropertiesCategoryMapApi.updateProductCategoryPropertiesCategoryMap(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productPropertiesCn: null as any,
productCategoryId: undefined,
productCategoryPropertiesValue: undefined,
productCategoryPropertiesId: null as any
}
formRef.value?.resetFields()
}
/** 获取所有产品分类 */
const getAllProductCategory = async () => {
productCategoryTree.value = []
const data = await ProductCategoryApi.getProductCategoryList({})
const root: Tree = { id: 0, name: '顶级产品分类', children: [] }
root.children = handleTree(data, 'id', 'parentId')
productCategoryTree.value.push(root)
}
/** 通过分类属性查询分类属性的详情 */
</script>

View File

@ -0,0 +1,224 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="分类属性">
<el-input
v-model="productPropertiesCn"
placeholder="请输入分类属性"
clearable
disabled
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-category-properties-category-map:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-category-properties-category-map:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品分类" align="center" prop="productCategoryValue" v-if="productPropertiesCategory===1"/>
<el-table-column label="分类属性值" align="center" prop="productCategoryPropertiesValue" v-if="productPropertiesCategory===0"/>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-category-properties-category-map:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-category-properties-category-map:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryPropertiesCategoryMapForm ref="formRef" @success="getList" :product-properties-cn="productPropertiesCn" :product-category-properties-id="Number(route.query.productCategoryPropertiesId)"/>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCategoryPropertiesCategoryMapApi, ProductCategoryPropertiesCategoryMapVO } from '@/api/erp/product/category/productcategoryproperties/propertiescategorymap'
import ProductCategoryPropertiesCategoryMapForm from './ProductCategoryPropertiesCategoryMapForm.vue'
import { ProductCategoryPropertiesApi } from '@/api/erp/product/category/productcategoryproperties'
const route = useRoute() //
let searchCount = 0
/** ERP 产品分类属性绑定 列表 */
defineOptions({ name: 'ErpProductCategoryPropertiesCategoryMap' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductCategoryPropertiesCategoryMapVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryPropertiesId: null as any,
productCategoryId: undefined,
productCategoryPropertiesValue: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 分类属性中文 */
let productPropertiesCn = ref('')
/** 产品属性分类 */
let productPropertiesCategory = ref()
/** 查询列表 */
const getList = async () => {
loading.value = true
if(route.query.productCategoryPropertiesId && searchCount == 0){
searchCount++
queryParams.productCategoryPropertiesId = Number(route.query.productCategoryPropertiesId)
}
if(route.query.productPropertiesCategory){
productPropertiesCategory.value = Number(route.query.productPropertiesCategory)
}
try {
const data = await ProductCategoryPropertiesCategoryMapApi.getProductCategoryPropertiesCategoryMapPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCategoryPropertiesCategoryMapApi.deleteProductCategoryPropertiesCategoryMap(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCategoryPropertiesCategoryMapApi.exportProductCategoryPropertiesCategoryMap(queryParams)
download.excel(data, 'ERP 产品分类属性绑定.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 根据用户输入搜索类别 */
const searchProductCategoryProperties = async () => {
//id
if (!route.query.productCategoryPropertiesId) {
return
}
try {
ProductCategoryPropertiesApi.getProductCategoryProperties(Number(route.query.productCategoryPropertiesId)).then(res => {
productPropertiesCn.value = res.productPropertiesCn
})
}catch (error) {
message.error('查询分类属性失败')
}
}
/** 初始化 **/
onMounted(() => {
getList()
searchProductCategoryProperties()
})
</script>

View File

@ -1,17 +1,11 @@
<!-- ERP 产品的新增/修改 --> <!-- ERP 产品的新增/修改 -->
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" /> <el-input v-model="formData.name" disabled placeholder="请输入名称" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -21,37 +15,46 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="分类" prop="categoryId"> <el-form-item label="分类" prop="categoryId">
<el-tree-select <el-tree-select filterable v-model="formData.categoryId" :data="categoryList" :props="defaultProps" check-strictly
v-model="formData.categoryId" default-expand-all placeholder="请选择分类" class="w-1/1" />
:data="categoryList" </el-form-item>
:props="defaultProps" </el-col>
check-strictly <el-col :span="12">
default-expand-all
placeholder="请选择分类" <el-form-item label="产品品牌" prop="brandId">
class="w-1/1" <el-select v-model="formData.brandId" placeholder="请输入产品品牌" filterable clearable class="!w-240px">
/> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_PRODUCT_BRAND)" :key="dict.value"
:label="dict.label" :value="dict.value" @click="handleBrandModelClick(dict.label)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="产品型号" prop="model">
<el-input v-model="formData.model" @blur="handleModelBlur" placeholder="请输入产品型号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="单位" prop="unitId"> <el-form-item label="单位" prop="unitId">
<el-select v-model="formData.unitId" clearable placeholder="请选择单位" class="w-1/1"> <el-select v-model="formData.unitId" clearable placeholder="请选择单位" class="w-1/1">
<el-option <el-option v-for="unit in unitList" :key="unit.id" :label="unit.name" :value="unit.id" />
v-for="unit in unitList"
:key="unit.id"
:label="unit.name"
:value="unit.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
<el-radio <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value"
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :value="dict.value">
:key="dict.value" {{ dict.label }}
:value="dict.value" </el-radio>
> </el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="一物一码" prop="ifQr">
<el-radio-group v-model="formData.ifQr">
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value"
:value="dict.value">
{{ dict.label }} {{ dict.label }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
@ -64,56 +67,31 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="保质期天数" prop="expiryDay"> <el-form-item label="保质期天数" prop="expiryDay">
<el-input-number <el-input-number v-model="formData.expiryDay" placeholder="请输入保质期天数" :min="0" :precision="0"
v-model="formData.expiryDay" class="!w-1/1" />
placeholder="请输入保质期天数"
:min="0"
:precision="0"
class="!w-1/1"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="重量kg" prop="weight"> <el-form-item label="重量kg" prop="weight">
<el-input-number <el-input-number v-model="formData.weight" placeholder="请输入重量kg" :min="0" class="!w-1/1" />
v-model="formData.weight"
placeholder="请输入重量kg"
:min="0"
class="!w-1/1"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="采购价格" prop="purchasePrice"> <el-form-item label="采购价格" prop="purchasePrice">
<el-input-number <el-input-number v-model="formData.purchasePrice" placeholder="请输入采购价格,单位:元" :min="0" :precision="2"
v-model="formData.purchasePrice" class="!w-1/1" />
placeholder="请输入采购价格,单位:元"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="销售价格" prop="salePrice"> <el-form-item label="销售价格" prop="salePrice">
<el-input-number <el-input-number v-model="formData.salePrice" placeholder="请输入销售价格,单位:元" :min="0" :precision="2"
v-model="formData.salePrice" class="!w-1/1" />
placeholder="请输入销售价格,单位:元"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="最低价格" prop="minPrice"> <el-form-item label="最低价格" prop="minPrice">
<el-input-number <el-input-number v-model="formData.minPrice" placeholder="请输入最低价格,单位:元" :min="0" :precision="2"
v-model="formData.minPrice" class="!w-1/1" />
placeholder="请输入最低价格,单位:元"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
@ -149,25 +127,32 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update - const formType = ref('') // create - update -
const formData = ref({ const formData = ref({
id: undefined, id: undefined,
name: undefined, name: '',
barCode: undefined, barCode: undefined,
categoryId: undefined, categoryId: undefined,
brandId: undefined,
model: undefined,
unitId: undefined, unitId: undefined,
status: undefined, status: 0,
standard: undefined, standard: undefined,
remark: undefined, remark: undefined,
expiryDay: undefined, expiryDay: undefined,
weight: undefined, weight: undefined,
purchasePrice: undefined, purchasePrice: undefined,
salePrice: undefined, salePrice: undefined,
minPrice: undefined minPrice: undefined,
ifQr: undefined
}) })
const formRules = reactive({ const formRules = reactive({
name: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }], name: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
barCode: [{ required: true, message: '产品条码不能为空', trigger: 'blur' }], barCode: [{ required: true, message: '产品条码不能为空', trigger: 'blur' }],
categoryId: [{ required: true, message: '产品分类编号不能为空', trigger: 'blur' }], categoryId: [{ required: true, message: '产品分类编号不能为空', trigger: 'blur' }],
brandId: [{ required: true, message: '产品品牌不能为空', trigger: 'blur' }],
model: [{ required: true, message: '产品型号不能为空', trigger: 'blur' }],
unitId: [{ required: true, message: '单位编号不能为空', trigger: 'blur' }], unitId: [{ required: true, message: '单位编号不能为空', trigger: 'blur' }],
status: [{ required: true, message: '产品状态不能为空', trigger: 'blur' }] status: [{ required: true, message: '产品状态不能为空', trigger: 'blur' }],
ifQr: [{ required: true, message: '一物一码不能为空', trigger: 'blur' }]
}) })
const formRef = ref() // Ref const formRef = ref() // Ref
const categoryList = ref<ProductCategoryVO[]>([]) // const categoryList = ref<ProductCategoryVO[]>([]) //
@ -219,14 +204,32 @@ const submitForm = async () => {
formLoading.value = false formLoading.value = false
} }
} }
let brand = ''
/** 品牌选择后 */
const handleBrandModelClick = (label?:string) => {
if (label) {
brand = label
if (formData.value.model) {
formData.value.name = brand + ' ' + formData.value.model
}
}
}
/** 型号失去焦点后 */
const handleModelBlur = () => {
if (formData.value.model && brand!=='') {
formData.value.name = brand +' ' + formData.value.model
}
}
/** 重置表单 */ /** 重置表单 */
const resetForm = () => { const resetForm = () => {
formData.value = { formData.value = {
id: undefined, id: undefined,
name: undefined, name: '',
barCode: undefined, barCode: undefined,
categoryId: undefined, categoryId: undefined,
brandId: undefined,
model: undefined,
unitId: undefined, unitId: undefined,
status: CommonStatusEnum.ENABLE, status: CommonStatusEnum.ENABLE,
standard: undefined, standard: undefined,
@ -235,7 +238,8 @@ const resetForm = () => {
weight: undefined, weight: undefined,
purchasePrice: undefined, purchasePrice: undefined,
salePrice: undefined, salePrice: undefined,
minPrice: undefined minPrice: undefined,
ifQr: undefined
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }

View File

@ -0,0 +1,108 @@
<template>
<!-- 列表 -->
<Dialog :title="dialogTitle" v-model="dialogVisible" width="70%">
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="单数属性" align="center" prop="ifSingleProperty">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifSingleProperty" />
</template>
</el-table-column>
<el-table-column label="属性英文" align="center" prop="productPropertiesEn" />
<el-table-column label="属性中文" align="center" prop="productPropertiesCn" />
<el-table-column label="必填" align="center" prop="ifRequired">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifRequired" />
</template>
</el-table-column>
<el-table-column label="属性分类" align="center" prop="productPropertiesCategory">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_PROPERTIES_CATEGORY" :value="scope.row.productPropertiesCategory" />
</template>
</el-table-column>
<el-table-column label="记录sn" align="center" prop="ifSn">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifRequired" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<!-- 普通属性 -->
<router-link
v-show="scope.row.productPropertiesCategory === 0"
:to="'/erp/product/product-category-properties-category-map?productCategoryPropertiesId=' + scope.row.id+'&productId='+fProductId+'&productPropertiesCategory='+scope.row.productPropertiesCategory+'&productCategoryId='+scope.row.productCategoryId+''"
v-hasPermi="['erp:product-properties-map:query']">
<el-button link type="primary">绑定</el-button>
</router-link>
<router-link
v-show="scope.row.productPropertiesCategory === 1"
:to="'/erp/product/product-properties-map?productCategoryPropertiesId=' + scope.row.id+'&productId='+fProductId+'&productPropertiesCategory='+scope.row.productPropertiesCategory+'&productCategoryId='+scope.row.productCategoryId+''"
v-hasPermi="['erp:product-properties-map:query']">
<el-button link type="primary">绑定</el-button>
</router-link>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { ProductCategoryPropertiesApi, ProductCategoryPropertiesVO } from '@/api/erp/product/category/productcategoryproperties'
/** 展示表格 */
const dialogVisible = ref(false)
const dialogTitle = ref('')
/** ERP 产品分类属性 列表 */
defineOptions({ name: 'ProductProperties' })
/** 传递过来的产品id */
let fProductId = ref()
const loading = ref(true) //
const list = ref<ProductCategoryPropertiesVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productCategoryId: null as any,
})
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProductCategoryPropertiesApi.getProductCategoryPropertiesPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 打开弹窗 */
const open = async (productId: any,productCategoryId?: number) => {
dialogVisible.value = true
dialogTitle.value = "产品属性"
queryParams.productCategoryId = productCategoryId
fProductId = productId
await getList()
}
defineExpose({ open }) // open
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -20,6 +20,7 @@
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="分类" prop="categoryId"> <el-form-item label="分类" prop="categoryId">
<el-tree-select <el-tree-select
v-model="queryParams.categoryId" v-model="queryParams.categoryId"
@ -31,6 +32,7 @@
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
@ -58,10 +60,15 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="条码" align="center" prop="barCode" /> <el-table-column label="条码" width="150" align="center" prop="barCode" />
<el-table-column label="名称" align="center" prop="name" /> <el-table-column label="名称" width="300" align="center" prop="name" />
<el-table-column label="规格" align="center" prop="standard" /> <el-table-column label="分类" width="150" align="center" prop="categoryName" />
<el-table-column label="分类" align="center" prop="categoryName" /> <el-table-column label="品牌" width="150" align="center" prop="brandId">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_PRODUCT_BRAND" :value="scope.row.brandId" />
</template>
</el-table-column>
<el-table-column label="型号" width="150" align="center" prop="model" />
<el-table-column label="单位" align="center" prop="unitName" /> <el-table-column label="单位" align="center" prop="unitName" />
<el-table-column <el-table-column
label="采购价格" label="采购价格"
@ -86,6 +93,11 @@
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="一物一码" align="center" prop="ifQr">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.ifQr" />
</template>
</el-table-column>
<el-table-column <el-table-column
label="创建时间" label="创建时间"
align="center" align="center"
@ -93,8 +105,16 @@
:formatter="dateFormatter" :formatter="dateFormatter"
width="180px" width="180px"
/> />
<el-table-column label="操作" align="center" width="110"> <el-table-column label="操作" align="center" fixed="right" width="160">
<template #default="scope"> <template #default="scope">
<el-button
link
type="primary"
@click="openPropertiesForm(scope.row.id,scope.row.categoryId)"
v-hasPermi="['erp:product-properties-map:query']"
>
属性
</el-button>
<el-button <el-button
link link
type="primary" type="primary"
@ -125,6 +145,10 @@
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<ProductForm ref="formRef" @success="getList" /> <ProductForm ref="formRef" @success="getList" />
<!-- 产品属性弹窗 -->
<ProductPropertiesForm ref="formPropertiesRef" @success="getList" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -133,9 +157,10 @@ import download from '@/utils/download'
import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category' import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import ProductForm from './ProductForm.vue' import ProductForm from './ProductForm.vue'
import { DICT_TYPE } from '@/utils/dict' import { getIntDictOptions,DICT_TYPE } from '@/utils/dict'
import { defaultProps, handleTree } from '@/utils/tree' import { defaultProps, handleTree } from '@/utils/tree'
import { erpPriceTableColumnFormatter } from '@/utils' import { erpPriceTableColumnFormatter } from '@/utils'
import ProductPropertiesForm from './ProductPropertiesForm.vue'
/** ERP 产品列表 */ /** ERP 产品列表 */
defineOptions({ name: 'ErpProduct' }) defineOptions({ name: 'ErpProduct' })
@ -150,7 +175,9 @@ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
categoryId: undefined categoryId: undefined,
brandId: undefined,
model: undefined,
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
const exportLoading = ref(false) // const exportLoading = ref(false) //
@ -186,6 +213,12 @@ const openForm = (type: string, id?: number) => {
formRef.value.open(type, id) formRef.value.open(type, id)
} }
/** 产品属性 */
const formPropertiesRef = ref()
const openPropertiesForm = (id: number,productCategoryId: number) => {
formPropertiesRef.value.open(id,productCategoryId)
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {

View File

@ -0,0 +1,166 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="产品id" prop="productId">
<el-input v-model="formData.productId" disabled placeholder="请输入产品id" />
</el-form-item>
<el-form-item label="分类属性" prop="productCategoryPropertiesId">
<el-input v-model="formData.productCategoryPropertiesId" disabled placeholder="请输入产品分类属性id" />
</el-form-item>
<el-form-item label="属性" prop="productPropertiesProductId">
<el-select v-model="formData.productPropertiesProductId" placeholder="请选择产品属性产品">
<el-option
v-for="item in products"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="分类属性值" prop="productCategoryPropertiesValue">
<el-input v-model="formData.productCategoryPropertiesValue" placeholder="请输入产品分类属性值" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ProductPropertiesMapApi, ProductPropertiesMapVO } from '@/api/erp/product/product/productpropertiesmap'
import { ProductCategoryPropertiesCategoryMapApi,ProductCategoryPropertiesCategoryMapVO } from '@/api/erp/product/category/productcategoryproperties/propertiescategorymap'
import { ProductCategoryApi,ProductCategoryVO } from '@/api/erp/product/category'
import { ProductApi,ProductVO } from '@/api/erp/product/product'
/** 从父组件取值 */
const props = defineProps({
productCategoryPropertiesId: {
type: Number,
default: undefined
},
productPropertiesCategory:{
type: Number,
default: () => {}
},
productId:{
type: Number,
default: () => {}
}
})
/** ERP 产品属性映射 表单 */
defineOptions({ name: 'ProductPropertiesMapForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productId: null as any,
productCategoryPropertiesId: null as any,
productPropertiesProductId: undefined,
productCategoryPropertiesValue: undefined
})
const formRules = reactive({
productCategoryPropertiesId: [{ required: true, message: '产品分类属性id不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品id不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
//
const products = ref<ProductVO[]>([])
/** 通过 productCategoryPropertiesId查询所有的分类id */
const getProductPropertiesCategoryList = async () => {
if (props.productCategoryPropertiesId) {
//
const params = {
productCategoryPropertiesId: props.productCategoryPropertiesId
}
ProductCategoryPropertiesCategoryMapApi.getProductCategoryPropertiesCategoryMapPage(params).then((res) => {
const data = res.list as ProductCategoryPropertiesCategoryMapVO[]
//productCategoryId
const productCategoryIds = data.map((item) => item.productCategoryId)
getProductList(productCategoryIds)
})
}
}
/** 通过productCategoryIds查询所有相关的product */
const getProductList = async (productCategoryIds: number[]) => {
if (productCategoryIds.length > 0) {
//
ProductApi.getProductListByCategoryIds(productCategoryIds).then((res) => {
products.value = res as ProductVO[]
})
}
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
formData.value.productId = props.productId
formData.value.productCategoryPropertiesId = props.productCategoryPropertiesId
await getProductPropertiesCategoryList()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductPropertiesMapApi.getProductPropertiesMap(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductPropertiesMapVO
if (formType.value === 'create') {
await ProductPropertiesMapApi.createProductPropertiesMap(data)
message.success(t('common.createSuccess'))
} else {
await ProductPropertiesMapApi.updateProductPropertiesMap(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productId: null as any,
productCategoryPropertiesId: null as any,
productPropertiesProductId: undefined,
productCategoryPropertiesValue: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,218 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品id" prop="productId">
<el-input
v-model="queryParams.productId"
placeholder="请输入产品id"
disabled
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="分类属性" prop="productCategoryPropertiesId">
<el-input
v-model="queryParams.productCategoryPropertiesId"
placeholder="请输入产品分类属性"
disabled
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:product-properties-map:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product-properties-map:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="分类属性" align="center" prop="productCategoryPropertiesValue" />
<el-table-column label="属性名称" align="center" prop="productPropertiesName" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product-properties-map:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product-properties-map:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductPropertiesMapForm ref="formRef" @success="getList" :product-id="route.query.productId" :product-category-properties-id="queryParams.productCategoryPropertiesId" :product-properties-category="productPropertiesCategory"/>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductPropertiesMapApi, ProductPropertiesMapVO } from '@/api/erp/product/product/productpropertiesmap'
import ProductPropertiesMapForm from './ProductPropertiesMapForm.vue'
const route = useRoute() //
let searchCount = 0
/** ERP 产品属性映射 列表 */
defineOptions({ name: 'ErpProductPropertiesMap' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ProductPropertiesMapVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productId: null as any,
productCategoryPropertiesId: null as any,
productPropertiesProductId: undefined,
productCategoryPropertiesValue: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const productPropertiesCategory = ref()
/** 通过路由获取次产品属性关联的所有的值 */
const getProductPropertiesProductList = async () => {
if(route.query.productCategoryPropertiesId){
queryParams.productCategoryPropertiesId = Number(route.query.productCategoryPropertiesId)
}
if(route.query.productId){
queryParams.productId = Number(route.query.productId)
}
getList()
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProductPropertiesMapApi.getProductPropertiesMapPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductPropertiesMapApi.deleteProductPropertiesMap(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductPropertiesMapApi.exportProductPropertiesMap(queryParams)
download.excel(data, 'ERP 产品属性映射.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getProductPropertiesProductList()
})
</script>

View File

@ -238,6 +238,11 @@ const open = async (type: string, id?: number) => {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await PurchaseInApi.getPurchaseIn(id) formData.value = await PurchaseInApi.getPurchaseIn(id)
formData.value.items.forEach((item) => {
if(item.ifQr===0){
item.qrCodeLineCount = item.count
}
})
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
@ -286,6 +291,19 @@ const submitForm = async () => {
// //
await formRef.value.validate() await formRef.value.validate()
await itemFormRef.value.validate() await itemFormRef.value.validate()
//
const items = formData.value.items
for (let i = 0; i < items.length; i++) {
const item = items[i]
//
if (item.ifQr) {
continue;
}
if (item.qrCodeLineCount !== item.count) {
message.error(`${i + 1} 行的入库数量和码的数量不同`)
return
}
}
// //
formLoading.value = true formLoading.value = true
try { try {

View File

@ -1,181 +1,247 @@
<template> <template>
<el-form <div>
ref="formRef" <div>
:model="formData" <el-form
:rules="formRules" ref="formRef"
v-loading="formLoading" :model="formData"
label-width="0px" :rules="formRules"
:inline-message="true" v-loading="formLoading"
:disabled="disabled" label-width="0px"
> :inline-message="true"
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px"> :disabled="disabled"
<el-table-column label="序号" type="index" align="center" width="60" /> >
<el-table-column label="仓库名称" min-width="125"> <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<template #default="{ row, $index }"> <el-table-column label="序号" type="index" align="center" width="60" />
<el-form-item <el-table-column label="仓库名称" min-width="125">
:prop="`${$index}.warehouseId`" <template #default="{ row, $index }">
:rules="formRules.warehouseId" <el-form-item
class="mb-0px!" :prop="`${$index}.warehouseId`"
:rules="formRules.warehouseId"
class="mb-0px!"
>
<el-select
v-model="row.warehouseId"
clearable
filterable
placeholder="请选择仓库"
@change="onChangeWarehouse(row)"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="货位" min-width="125">
<template #default="{ row, $index }">
<el-form-item
:prop="`${$index}.warehouseLocationId`"
:rules="formRules.warehouseLocationId"
class="mb-0px!"
>
<el-select
v-model="row.warehouseLocationId"
clearable
filterable
placeholder="请选择货位"
>
<el-option
v-for="item in locationList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品名称" min-width="180">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productName" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="库存" min-width="100">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="条码" min-width="150">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productBarCode" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单位" min-width="80">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productUnitName" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
label="已入库/原数量"
fixed="right"
min-width="120"
v-if="formData[0]?.totalCount != null"
> >
<el-select <template #default="{ row }">
v-model="row.warehouseId" <el-form-item class="mb-0px!">
clearable <el-input disabled :value="`${row.inCount}/${row.totalCount}`" />
filterable </el-form-item>
placeholder="请选择仓库" </template>
@change="onChangeWarehouse($event, row)" </el-table-column>
> <el-table-column label="码" fixed="right" min-width="40">
<el-option <template #default="{ row, $index }">
v-for="item in warehouseList" <el-form-item class="mb-0px!">
:key="item.id" <el-button :disabled="row.ifQr" @click="openQrDialog($index)" link>
:label="item.name" <Icon icon="fa:qrcode" />
:value="item.id" </el-button>
/> </el-form-item>
</el-select> </template>
</el-form-item> </el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
<el-input-number
v-model="row.count"
controls-position="right"
:min="1"
:max="row.totalCount"
:precision="3"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
<el-input-number
v-model="row.productPrice"
controls-position="right"
:min="0.01"
:precision="2"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!">
<el-input
disabled
v-model="row.totalProductPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!">
<el-input-number
v-model="row.taxPercent"
controls-position="right"
:min="0"
:precision="2"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!">
<el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="备注" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.remark`" class="mb-0px!">
<el-input v-model="row.remark" placeholder="请输入备注" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="120">
<template #default="{ $index }">
<el-button :disabled="formData.length === 1" @click="handleDelete($index)" link>
<span v-show="formData.length > 1 && !disabled" style="color: red"></span>
<span v-show="formData.length === 1 || disabled"></span>
</el-button>
<el-button
:disabled="formData[$index].count <= 1"
@click="openSplitDialog($index)"
link
style="color: blue"
>
拆分
</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</div>
<div>
<!-- 一物一码扫码弹窗 -->
<Dialog :title="productName" v-model="qrDialogVisible" :appendToBody="true">
<!-- 显示有效行数 -->
<div>输入的有效行数: {{ qrCodeLineCount }}</div>
<div>需要扫描数: {{ qrNeedCount }}</div>
<el-input type="textarea" v-model="qrCodes" :rows="10" @input="onQrCodeChange" />
<template #footer>
<el-button @click="submitQr" type="primary"> </el-button>
<el-button @click="qrDialogVisible = false"> </el-button>
</template> </template>
</el-table-column> </Dialog>
<el-table-column label="产品名称" min-width="180"> </div>
<template #default="{ row }"> <!-- 拆分弹窗 -->
<el-form-item class="mb-0px!"> <Dialog title="拆分" v-model="splitDialogVisible" :appendToBody="true">
<el-input disabled v-model="row.productName" /> <el-input-number
</el-form-item> v-model="splitCount"
</template> :min="1"
</el-table-column> :max="currentRow.count"
<el-table-column label="库存" min-width="100"> controls-position="right"
<template #default="{ row }"> />
<el-form-item class="mb-0px!"> <template #footer>
<el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /> <el-button @click="splitItem" type="primary"> </el-button>
</el-form-item> <el-button @click="splitDialogVisible = false"> </el-button>
</template> </template>
</el-table-column> </Dialog>
<el-table-column label="条码" min-width="150"> </div>
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productBarCode" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单位" min-width="80">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productUnitName" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
label="原数量"
fixed="right"
min-width="80"
v-if="formData[0]?.totalCount != null"
>
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.totalCount" :formatter="erpCountInputFormatter" />
</el-form-item>
</template>
</el-table-column>
<el-table-column
label="已入库"
fixed="right"
min-width="80"
v-if="formData[0]?.inCount != null"
>
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.inCount" :formatter="erpCountInputFormatter" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
<el-input-number
v-model="row.count"
controls-position="right"
:min="0.001"
:precision="3"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
<el-input-number
v-model="row.productPrice"
controls-position="right"
:min="0.01"
:precision="2"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!">
<el-input
disabled
v-model="row.totalProductPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!">
<el-input-number
v-model="row.taxPercent"
controls-position="right"
:min="0"
:precision="2"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!">
<el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="备注" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.remark`" class="mb-0px!">
<el-input v-model="row.remark" placeholder="请输入备注" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button :disabled="formData.length === 1" @click="handleDelete($index)" link>
</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { WarehouseApi as WarehouseLocactionApi, WarehouseLocationVO } from '@/api/erp/warehouse'
import { StockApi } from '@/api/erp/stock/stock' import { StockApi } from '@/api/erp/stock/stock'
import { import {
erpCountInputFormatter, erpCountInputFormatter,
erpPriceInputFormatter, erpPriceInputFormatter,
erpPriceMultiply, erpPriceMultiply,
getSumValue getSumValue,
matchRulesFromDictOptions
} from '@/utils' } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse' import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
@ -183,16 +249,100 @@ const props = defineProps<{
items: undefined items: undefined
disabled: false disabled: false
}>() }>()
const formLoading = ref(false) // const formLoading = ref(false) //
const formData = ref([]) const formData = ref([])
const formRules = reactive({ const formRules = reactive({
warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'blur' }], warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }], productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
warehouseLocationId: [{ required: true, message: '货位不能为空', trigger: 'blur' }],
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }] count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
}) })
const formRef = ref([]) // Ref const formRef = ref([]) // Ref
const warehouseList = ref<WarehouseVO[]>([]) // const warehouseList = ref<WarehouseVO[]>([]) //
const locationList = ref<WarehouseLocationVO[]>([]) //
const defaultWarehouse = ref<WarehouseVO>(undefined) // const defaultWarehouse = ref<WarehouseVO>(undefined) //
//
const qrDialogVisible = ref(false)
//
const qrCodes = ref('')
//
const currentRow = ref<(typeof props.items)[0]>(undefined)
//
const currentRowIndex = ref(-1)
//
const productName = ref('')
//
const qrCodeLineCount = ref(0)
const message = useMessage() //
//
const qrNeedCount = computed(() => {
return currentRow.value?.count
})
//
const onQrCodeChange = () => {
// qrCode.value undefined null
if (qrCodes.value) {
const lines = qrCodes.value.split('\n')
//
const trimmedLines = lines.map((line) => line.trim())
const validLines = trimmedLines.filter((line) => {
return matchRulesFromDictOptions(line)
})
//
const uniqueLines = [...new Set(validLines)]
qrCodeLineCount.value = uniqueLines.length
// row.count
if (currentRow.value && qrCodeLineCount.value > currentRow.value.count) {
message.warning('输入的有效行数不能超过该产品的数量!')
//
qrCodes.value = validLines.slice(0, currentRow.value.count).join('\n')
qrCodeLineCount.value = currentRow.value.count
}
} else {
qrCodeLineCount.value = 0
}
}
//
const openQrDialog = (index: number) => {
// currentRow
currentRow.value = formData.value[index] // 使
currentRowIndex.value = index
//
if (currentRow.value.qrcodes) {
qrCodes.value = currentRow.value.qrcodes
} else {
qrCodes.value = '' //
}
//
productName.value = currentRow.value.productName
//
onQrCodeChange()
//
qrDialogVisible.value = true
}
/** 提交扫码 */
const submitQr = async () => {
//
if (qrCodes.value == null || qrCodes.value == undefined || qrCodes.value === '') {
return
}
// formData
const index = currentRowIndex.value //
if (index !== -1 && formData.value[index]) {
//
// formData qrcode
formData.value[index].qrcodes = qrCodes.value
//
formData.value[index].qrCodeLineCount = qrCodeLineCount.value
}
//
qrDialogVisible.value = false
}
/** 初始化设置入库项 */ /** 初始化设置入库项 */
watch( watch(
@ -271,10 +421,56 @@ const handleAdd = () => {
} }
formData.value.push(row) formData.value.push(row)
} }
const queryLocationParams = reactive({
pageNo: 1,
pageSize: 100,
warehouseId: undefined as unknown
})
//
const onChangeWarehouse = async (row: (typeof props.items)[0]) => {
queryLocationParams.warehouseId = row.warehouseId
try {
const response = await WarehouseLocactionApi.getWarehouseLocationPage(queryLocationParams)
if (response) {
if (response.list.length !== 0) {
locationList.value = response.list
} else {
console.error('获取货位列表失败,错误码:', response.code, ',错误信息:', response.msg)
}
} else {
console.error('获取货位列表失败,响应为空')
}
} catch (error: any) {
if (error.response) {
// Axios
console.error(
'获取货位列表失败HTTP错误码:',
error.response.status,
',错误信息:',
error.response.data
)
} else if (error.request) {
//
console.error('获取货位列表失败,没有收到响应')
} else {
//
console.error('获取货位列表时发生错误:', error.message)
}
}
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = (index: number) => { const handleDelete = (index: number) => {
formData.value.splice(index, 1) const deletedRow = formData.value.splice(index, 1)[0]
const deletedCount = deletedRow.count
const productId = deletedRow.productId
formData.value.forEach((row) => {
if (row.productId === productId) {
row.totalCount += deletedCount // totalCount
}
})
} }
/** 加载库存 */ /** 加载库存 */
@ -296,5 +492,42 @@ defineExpose({ validate })
onMounted(async () => { onMounted(async () => {
warehouseList.value = await WarehouseApi.getWarehouseSimpleList() warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus) defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus)
locationList.value = onChangeWarehouse({
pageNo: 1,
pageSize: 100,
warehouseId: defaultWarehouse.value?.id
})
}) })
//
const splitDialogVisible = ref(false)
const splitCount = ref(1)
//
const openSplitDialog = (index: number) => {
currentRow.value = formData.value[index]
currentRowIndex.value = index
splitCount.value = 1
splitDialogVisible.value = true
}
//
const splitItem = () => {
if (splitCount.value >= currentRow.value.count) {
message.warning('拆分数量不能大于或等于当前数量!')
return
}
currentRow.value.count -= splitCount.value
currentRow.value.totalCount = currentRow.value.count // totalCount
const newRow = {
...currentRow.value,
count: splitCount.value,
inCount: 0,
totalCount: currentRow.value.totalCount // totalCount
}
formData.value.splice(currentRowIndex.value + 1, 0, newRow)
splitDialogVisible.value = false
}
</script> </script>

View File

@ -66,11 +66,7 @@
</el-table-column> </el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"> <el-table-column label="产品单价" fixed="right" min-width="120">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-form-item <el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
:prop="`${$index}.productPrice`"
:rules="formRules.productPrice"
class="mb-0px!"
>
<el-input-number <el-input-number
v-model="row.productPrice" v-model="row.productPrice"
controls-position="right" controls-position="right"
@ -157,7 +153,6 @@ const formLoading = ref(false) // 表单的加载中
const formData = ref([]) const formData = ref([])
const formRules = reactive({ const formRules = reactive({
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }], productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
productPrice: [{ required: true, message: '产品单价不能为空', trigger: 'blur' }],
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }] count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
}) })
const formRef = ref([]) // Ref const formRef = ref([]) // Ref

View File

@ -174,6 +174,7 @@ import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils'
import PurchaseOrderReturnEnableList from '@/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue' import PurchaseOrderReturnEnableList from '@/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue'
import { PurchaseOrderVO } from '@/api/erp/purchase/order' import { PurchaseOrderVO } from '@/api/erp/purchase/order'
import * as UserApi from '@/api/system/user' import * as UserApi from '@/api/system/user'
import { PurchaseInApi } from '@/api/erp/purchase/in'
/** ERP 采购退货表单 */ /** ERP 采购退货表单 */
defineOptions({ name: 'PurchaseReturnForm' }) defineOptions({ name: 'PurchaseReturnForm' })
@ -214,6 +215,12 @@ const userList = ref<UserApi.UserVO[]>([]) // 用户列表
const subTabsName = ref('item') const subTabsName = ref('item')
const itemFormRef = ref() const itemFormRef = ref()
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
orderNo: undefined
}) //
/** 计算 discountPrice、totalPrice 价格 */ /** 计算 discountPrice、totalPrice 价格 */
watch( watch(
() => formData.value, () => formData.value,
@ -242,6 +249,11 @@ const open = async (type: string, id?: number) => {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await PurchaseReturnApi.getPurchaseReturn(id) formData.value = await PurchaseReturnApi.getPurchaseReturn(id)
formData.value.items.forEach((item) => {
if (item.ifQr === 0) {
item.qrCodeLineCount = item.count
}
})
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
@ -265,7 +277,7 @@ const openPurchaseOrderReturnEnableList = () => {
purchaseOrderReturnEnableListRef.value.open() purchaseOrderReturnEnableListRef.value.open()
} }
const handlePurchaseOrderChange = (order: PurchaseOrderVO) => { const handlePurchaseOrderChange = async (order: PurchaseOrderVO) => {
// 退 // 退
formData.value.orderId = order.id formData.value.orderId = order.id
formData.value.orderNo = order.no formData.value.orderNo = order.no
@ -274,13 +286,25 @@ const handlePurchaseOrderChange = (order: PurchaseOrderVO) => {
formData.value.discountPercent = order.discountPercent formData.value.discountPercent = order.discountPercent
formData.value.remark = order.remark formData.value.remark = order.remark
formData.value.fileUrl = order.fileUrl formData.value.fileUrl = order.fileUrl
// 退
order.items.forEach((item) => { //
item.count = item.inCount - item.returnCount const data = await PurchaseInApi.getPurchaseInPage(queryParams)
item.orderItemId = item.id const purchaseInList = data.list
item.id = undefined const items: { productId: any; count: any; orderItemId: any; id: undefined }[] = []
purchaseInList.forEach((purchaseIn) => {
purchaseIn.items.forEach((item) => {
if (item.count > 0) {
items.push({
...item,
count: item.count,
orderItemId: item.id,
id: undefined
})
}
})
}) })
formData.value.items = order.items.filter((item) => item.count > 0) // items
formData.value.items = items
} }
/** 提交表单 */ /** 提交表单 */
@ -289,6 +313,19 @@ const submitForm = async () => {
// //
await formRef.value.validate() await formRef.value.validate()
await itemFormRef.value.validate() await itemFormRef.value.validate()
//
const items = formData.value.items
for (let i = 0; i < items.length; i++) {
const item = items[i]
//
if (item.ifQr) {
continue
}
if (item.qrcodes.split('\n').length !== item.count) {
message.error(`${i + 1} 行的退货数量和码的数量不同`)
return
}
}
// //
formLoading.value = true formLoading.value = true
try { try {

View File

@ -1,31 +1,37 @@
<template> <template>
<el-form <div>
ref="formRef" <div>
:model="formData" <el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px"
:rules="formRules" :inline-message="true" :disabled="disabled">
v-loading="formLoading" <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
label-width="0px" <el-table-column label="序号" type="index" align="center" width="60" />
:inline-message="true" <el-table-column label="仓库名称" min-width="125">
:disabled="disabled" <template #default="{ row, $index }">
> <el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px"> <el-select :disabled="!row.ifQr" v-model="row.warehouseId" clearable filterable placeholder="请选择仓库"
<el-table-column label="序号" type="index" align="center" width="60" /> @change="onChangeWarehouse($event, row)">
<el-table-column label="仓库名称" min-width="125"> <el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="货位" min-width="125">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-form-item <el-form-item
:prop="`${$index}.warehouseId`" :prop="`${$index}.warehouseLocationId`"
:rules="formRules.warehouseId" :rules="formRules.warehouseLocationId"
class="mb-0px!" class="mb-0px!"
> >
<el-select <el-select
v-model="row.warehouseId" v-model="row.warehouseLocationId"
:disabled="!row.ifQr"
clearable clearable
filterable filterable
placeholder="请选择仓库" placeholder="请选择货位"
@change="onChangeWarehouse($event, row)"
> >
<el-option <el-option
v-for="item in warehouseList" v-for="item in locationList"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
@ -34,148 +40,160 @@
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="产品名称" min-width="180"> <el-table-column label="产品名称" min-width="180">
<template #default="{ row }"> <template #default="{ row }">
<el-form-item class="mb-0px!"> <el-form-item class="mb-0px!">
<el-input disabled v-model="row.productName" /> <el-input disabled v-model="row.productName" />
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="库存" min-width="100"> <el-table-column label="库存" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-form-item class="mb-0px!"> <el-form-item class="mb-0px!">
<el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /> <el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="条码" min-width="150"> <el-table-column label="条码" min-width="150">
<template #default="{ row }"> <template #default="{ row }">
<el-form-item class="mb-0px!"> <el-form-item class="mb-0px!">
<el-input disabled v-model="row.productBarCode" /> <el-input disabled v-model="row.productBarCode" />
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="单位" min-width="80">
<template #default="{ row }"> <el-table-column label="单位" min-width="80">
<el-form-item class="mb-0px!"> <template #default="{ row }">
<el-input disabled v-model="row.productUnitName" /> <el-form-item class="mb-0px!">
</el-form-item> <el-input disabled v-model="row.productUnitName" />
</template> </el-form-item>
</el-table-column> </template>
<el-table-column </el-table-column>
label="已出库" <el-table-column label="已出库" fixed="right" min-width="80" v-if="formData[0]?.inCount != null">
fixed="right" <template #default="{ row }">
min-width="80" <el-form-item class="mb-0px!">
v-if="formData[0]?.inCount != null" <el-input disabled v-model="row.inCount" :formatter="erpCountInputFormatter" />
> </el-form-item>
<template #default="{ row }"> </template>
<el-form-item class="mb-0px!"> </el-table-column>
<el-input disabled v-model="row.inCount" :formatter="erpCountInputFormatter" /> <el-table-column label="已退货" fixed="right" min-width="80" v-if="formData[0]?.returnCount != null">
</el-form-item> <template #default="{ row }">
</template> <el-form-item class="mb-0px!">
</el-table-column> <el-input disabled v-model="row.returnCount" :formatter="erpCountInputFormatter" />
<el-table-column </el-form-item>
label="已退货" </template>
fixed="right" </el-table-column>
min-width="80" <el-table-column label="码" fixed="right" min-width="40">
v-if="formData[0]?.returnCount != null" <template #default="{ row ,$index}">
> <el-form-item class="mb-0px!">
<template #default="{ row }">
<el-form-item class="mb-0px!"> <el-button :disabled="row.ifQr" @click="openQrTable($index,row)" link>
<el-input disabled v-model="row.returnCount" :formatter="erpCountInputFormatter" /> <Icon icon="fa:qrcode" />
</el-form-item> </el-button>
</template> <!-- <el-button :disabled="row.ifQr" @click="openQrDialog($index)" link>
</el-table-column> <Icon icon="fa:qrcode" />
<el-table-column label="数量" prop="count" fixed="right" min-width="140"> </el-button> -->
<template #default="{ row, $index }"> </el-form-item>
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"> </template>
<el-input-number </el-table-column>
v-model="row.count" <el-table-column label="数量" prop="count" fixed="right" min-width="140">
controls-position="right" <template #default="{ row, $index }">
:min="0.001" <el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
:precision="3" <el-input-number v-model="row.count" controls-position="right" :min="0.001" :precision="3"
class="!w-100%" class="!w-100%" />
/> </el-form-item>
</el-form-item> </template>
</template> </el-table-column>
</el-table-column> <el-table-column label="产品单价" fixed="right" min-width="120">
<el-table-column label="产品单价" fixed="right" min-width="120"> <template #default="{ row, $index }">
<template #default="{ row, $index }"> <el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"> <el-input-number v-model="row.productPrice" controls-position="right" :min="0.01" :precision="2"
<el-input-number class="!w-100%" />
v-model="row.productPrice" </el-form-item>
controls-position="right" </template>
:min="0.01" </el-table-column>
:precision="2" <el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100">
class="!w-100%" <template #default="{ row, $index }">
/> <el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!">
</el-form-item> <el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" />
</template> </el-form-item>
</el-table-column> </template>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"> </el-table-column>
<template #default="{ row, $index }"> <el-table-column label="税率(%" fixed="right" min-width="115">
<el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"> <template #default="{ row, $index }">
<el-input <el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!">
disabled <el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="2"
v-model="row.totalProductPrice" class="!w-100%" />
:formatter="erpPriceInputFormatter" </el-form-item>
/> </template>
</el-form-item> </el-table-column>
</template> <el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120">
</el-table-column> <template #default="{ row, $index }">
<el-table-column label="税率(%" fixed="right" min-width="115"> <el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<template #default="{ row, $index }"> <el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
<el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"> <el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" />
<el-input-number </el-form-item>
v-model="row.taxPercent" </el-form-item>
controls-position="right" </template>
:min="0" </el-table-column>
:precision="2" <el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100">
class="!w-100%" <template #default="{ row, $index }">
/> <el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!">
</el-form-item> <el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
</template> </el-form-item>
</el-table-column> </template>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"> </el-table-column>
<template #default="{ row, $index }"> <el-table-column label="备注" min-width="150">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"> <template #default="{ row, $index }">
<el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"> <el-form-item :prop="`${$index}.remark`" class="mb-0px!">
<el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /> <el-input v-model="row.remark" placeholder="请输入备注" />
</el-form-item> </el-form-item>
</el-form-item> </template>
</template> </el-table-column>
</el-table-column> <el-table-column align="center" fixed="right" label="操作" width="60">
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"> <template #default="{ $index }">
<template #default="{ row, $index }"> <el-button :disabled="formData.length === 1" @click="handleDelete($index)" link>
<el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!">
<el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /> </el-button>
</el-form-item> </template>
</template> </el-table-column>
</el-table-column> </el-table>
<el-table-column label="备注" min-width="150"> </el-form>
<template #default="{ row, $index }"> </div>
<el-form-item :prop="`${$index}.remark`" class="mb-0px!">
<el-input v-model="row.remark" placeholder="请输入备注" /> <div>
</el-form-item> <!-- 一物一码扫码弹窗 -->
</template> <Dialog :title="productName" v-model="qrDialogVisible" :appendToBody="true">
</el-table-column> <!-- 显示有效行数 -->
<el-table-column align="center" fixed="right" label="操作" width="60"> <div>输入的有效行数: {{ qrCodeLineCount }}</div>
<template #default="{ $index }"> <div>需要扫描数: {{ qrNeedCount }}</div>
<el-button :disabled="formData.length === 1" @click="handleDelete($index)" link>
<el-input type="textarea" v-model="qrCodes" :rows="10" @input="onQrCodeChange" />
</el-button> <template #footer>
</template> <el-button @click="submitQr" type="primary">
</el-table-column>
</el-table> </el-button>
</el-form> <el-button @click="qrDialogVisible = false"> </el-button>
</template>
</Dialog>
</div>
<PurchaseReturnItemQrForm ref="qrCodeTableDialogRef" :currentRowIndex="currentRowIndex" :currentRow="currentRow" @close="onQrDialogClose" @submit-data="onQrCodeList" />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { WarehouseApi as WarehouseLocactionApi, WarehouseLocationVO } from '@/api/erp/warehouse'
import PurchaseReturnItemQrForm from './PurchaseReturnItemQrForm.vue';
import { StockApi } from '@/api/erp/stock/stock' import { StockApi } from '@/api/erp/stock/stock'
import { import {
erpCountInputFormatter, erpCountInputFormatter,
erpPriceInputFormatter, erpPriceInputFormatter,
erpPriceMultiply, erpPriceMultiply,
getSumValue getSumValue,
matchRulesFromDictOptions
} from '@/utils' } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse' import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
@ -187,12 +205,113 @@ const formLoading = ref(false) // 表单的加载中
const formData = ref([]) const formData = ref([])
const formRules = reactive({ const formRules = reactive({
warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'blur' }], warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'blur' }],
warehouseLocationId: [{ required: true, message: '货位不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }], productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }] count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
}) })
const formRef = ref([]) // Ref const formRef = ref([]) // Ref
const warehouseList = ref<WarehouseVO[]>([]) // const warehouseList = ref<WarehouseVO[]>([]) //
const locationList = ref<WarehouseLocationVO[]>([]) //
const defaultWarehouse = ref<WarehouseVO>(undefined) // const defaultWarehouse = ref<WarehouseVO>(undefined) //
//
const qrDialogVisible = ref(false)
//
const qrCodes = ref('')
//
const currentRow = ref<typeof props.items[0]>(undefined)
//
const currentRowIndex = ref()
//
const productName = ref('')
//
const qrCodeLineCount = ref(0);
const message = useMessage() //
//
const qrCodeTableDialogRef = ref();
const queryLocationParams = reactive({
pageNo: 1,
pageSize: 100,
warehouseId: undefined as unknown
})
//
const onQrCodeList = (qrCodeList, index) => {
//qrCodeList
if (qrCodeList.length === 0) {
return
}
//qrCodeListqrcodes
let qrcodes = ''
qrCodeList.forEach((item) => {
qrcodes += item.qr + '\n'
})
//
qrcodes = qrcodes.slice(0, -1)
//formDataqrcodes
formData.value[index].qrcodes = qrcodes
}
//
const openQrTable = (index:number,row) => {
currentRow.value =row;
currentRowIndex.value = index;
qrCodeTableDialogRef.value.open(row,index);
};
//
const onQrDialogClose = () => {
//
};
//
const qrNeedCount = computed(() => {
return currentRow.value?.count
})
//
const onQrCodeChange = () => {
// qrCode.value undefined null
if (qrCodes.value) {
const lines = qrCodes.value.split('\n');
//
const trimmedLines = lines.map(line => line.trim());
const validLines = trimmedLines.filter(line =>{
return matchRulesFromDictOptions(line)
});
//
const uniqueLines = [...new Set(validLines)];
qrCodeLineCount.value = uniqueLines.length;
// row.count
if (currentRow.value && qrCodeLineCount.value > currentRow.value.count) {
message.warning('输入的有效行数不能超过该产品的数量!');
//
qrCodes.value = validLines.slice(0, currentRow.value.count).join('\n');
qrCodeLineCount.value = currentRow.value.count;
}
} else {
qrCodeLineCount.value = 0;
}
};
/** 提交扫码 */
const submitQr = async () => {
//
if (qrCodes.value == null || qrCodes.value == undefined || qrCodes.value === '') {
return;
}
// formData
const index = currentRowIndex.value; //
if (index !== -1 && formData.value[index]) { //
// formData qrcode
formData.value[index].qrcodes = qrCodes.value;
//
formData.value[index].qrCodeLineCount = qrCodeLineCount.value;
}
//
qrDialogVisible.value = false;
};
/** 初始化设置出库项 */ /** 初始化设置出库项 */
watch( watch(
@ -232,6 +351,25 @@ watch(
{ deep: true } { deep: true }
) )
//
const openQrDialog = (index: number) => {
// currentRow
currentRow.value = formData.value[index]; // 使
currentRowIndex.value = index;
//
if (currentRow.value.qrcodes) {
qrCodes.value = currentRow.value.qrcodes;
} else {
qrCodes.value = ''; //
}
//
productName.value = currentRow.value.productName;
//
onQrCodeChange();
//
qrDialogVisible.value = true;
};
/** 合计 */ /** 合计 */
const getSummaries = (param: SummaryMethodProps) => { const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param const { columns, data } = param
@ -253,6 +391,36 @@ const getSummaries = (param: SummaryMethodProps) => {
return sums return sums
} }
//
const onChangeWarehouse = async (row: typeof props.items[0]) => {
queryLocationParams.warehouseId = row.warehouseId;
try {
const response = await WarehouseLocactionApi.getWarehouseLocationPage(queryLocationParams);
if (response) {
if (response.list.length !== 0) {
locationList.value = response.list;
} else {
console.error('获取货位列表失败,错误码:', response.code, ',错误信息:', response.msg);
}
} else {
console.error('获取货位列表失败,响应为空');
}
} catch (error: any) {
if (error.response) {
// Axios
console.error('获取货位列表失败HTTP错误码:', error.response.status, ',错误信息:', error.response.data);
} else if (error.request) {
//
console.error('获取货位列表失败,没有收到响应');
} else {
//
console.error('获取货位列表时发生错误:', error.message);
}
}
};
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = () => { const handleAdd = () => {
const row = { const row = {
@ -296,5 +464,7 @@ defineExpose({ validate })
onMounted(async () => { onMounted(async () => {
warehouseList.value = await WarehouseApi.getWarehouseSimpleList() warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus) defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus)
locationList.value = onChangeWarehouse({pageNo: 1,pageSize: 100,warehouseId: defaultWarehouse.value?.id})
}) })
</script> </script>

View File

@ -0,0 +1,147 @@
<template>
<Dialog v-model="dialogVisible" title="二维码列表" width="60%">
<el-form ref="formRef" label-width="100px">
<el-row :gutter="20">
<el-col :span="20">
<el-form-item label="二维码" prop="no">
<el-input v-model="qr" ref="qrInputRef" placeholder="扫描二维码" @keyup.enter="handleQrEnter" />
</el-form-item>
</el-col>
<el-form-item v-show="false" label="隐藏字段">
<el-input v-model="qrHiden" placeholder="隐藏字段" @keyup.enter="handleQrEnter" />
</el-form-item>
</el-row>
<ContentWrap>
<el-table :data="qrCodeRowList">
<!-- 序号 -->
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column prop="qr" label="二维码" />
<el-table-column prop="warehouseName" label="仓库" />
<el-table-column prop="warehouseLocationName" label="货位" />
<el-table-column prop="productName" label="产品名称" />
<el-table-column prop="productUnitName" label="产品单位" />
<!-- 操作列 -->
<el-table-column label="操作">
<template #default="scope">
<el-button @click="deleteRow(scope.$index)" link>
</el-button>
</template>
</el-table-column>
</el-table>
</ContentWrap>
</el-form>
<template #footer>
<el-button type="primary" @click="submitQr"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { ref, defineProps, defineEmits } from 'vue';
import {
matchRulesFromDictOptions
} from '@/utils'
import { PurchaseReturnItemsQrApi } from '@/api/erp/purchase/return/purchasereturnitemsqr/index';
const props = defineProps({
currentRow: {
type: Object,
required: true
},
currentRowIndex: {
type: Number,
required: true
}
});
// currentRowIndex
watch(() => props.currentRowIndex, (newIndex) => {
// currentRowIndex
console.log('currentRowIndex 已更新为:', newIndex);
});
const formRef = ref();
const qr = ref('');
const qrHiden = ref('');
// ref DOM
const qrInputRef = ref(null);
const emits = defineEmits(['submit-data', 'close']);
const dialogVisible = ref(false);
const qrCodeRowList = ref([]);
const message = useMessage() //
const open = async (row,index)=>{
// currentRow qrCodeRowList
qrCodeRowList.value = [];
if (row.qrcodes) {
row.qrcodes.split('\n').forEach((item) => {
const newRow = { ...row, qr: item };
qrCodeRowList.value.push(newRow);
});
}
dialogVisible.value = true;
};
const close = () => {
dialogVisible.value = false;
emits('close');
};
/** 提交扫码 */
const submitQr = async () => {
//
if (qrCodeRowList.value.length === 0) {
message.warning('请扫描二维码');
return;
}
//
if (qrCodeRowList.value.length !== props.currentRow.count) {
message.warning('扫码数量与数量不一致');
return;
}
// formData
const index = props.currentRowIndex; //
// 'submit-data' qrCodeRowList
emits('submit-data', qrCodeRowList.value, index);
dialogVisible.value = false;
};
//
const handleQrEnter = () => {
if (!matchRulesFromDictOptions(qr.value)) {
//
message.warning('二维码格式不正确');
return;
}
//
const newRow = { ...props.currentRow, qr: qr.value };
qrCodeRowList.value.push(newRow);
//
qr.value = '';
//
if (qrInputRef.value) {
qrInputRef.value.focus();
}
};
//
const deleteRow = (index: number) => {
qrCodeRowList.value.splice(index, 1);
};
defineExpose({
open,
close
});
</script>

View File

@ -303,6 +303,19 @@ const submitForm = async () => {
// //
await formRef.value.validate() await formRef.value.validate()
await itemFormRef.value.validate() await itemFormRef.value.validate()
//
const items = formData.value.items
for (let i = 0; i < items.length; i++) {
const item = items[i]
//
if (item.ifQr) {
continue;
}
if (item.qrCodeLineCount !== item.count) {
message.error(`${i + 1} 行的入库数量和码的数量不同`)
return
}
}
// //
formLoading.value = true formLoading.value = true
try { try {

View File

@ -1,4 +1,5 @@
<template> <template>
<div><div>
<el-form <el-form
ref="formRef" ref="formRef"
:model="formData" :model="formData"
@ -10,31 +11,7 @@
> >
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px"> <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" /> <el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"> <el-table-column label="产品名称" min-width="180">
<template #default="{ row, $index }">
<el-form-item
:prop="`${$index}.warehouseId`"
:rules="formRules.warehouseId"
class="mb-0px!"
>
<el-select
v-model="row.warehouseId"
clearable
filterable
placeholder="请选择仓库"
@change="onChangeWarehouse($event, row)"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品名称" min-width="180">
<template #default="{ row }"> <template #default="{ row }">
<el-form-item class="mb-0px!"> <el-form-item class="mb-0px!">
<el-input disabled v-model="row.productName" /> <el-input disabled v-model="row.productName" />
@ -62,6 +39,15 @@
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="码" fixed="right" min-width="40">
<template #default="{ row, $index }">
<el-form-item class="mb-0px!">
<el-button :disabled="row.ifQr" @click="openQrDialog($index)" link>
<Icon icon="fa:qrcode" />
</el-button>
</el-form-item>
</template>
</el-table-column>
<el-table-column <el-table-column
label="原数量" label="原数量"
fixed="right" fixed="right"
@ -168,6 +154,24 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-form> </el-form>
</div>
<div>
<!-- 一物一码扫码弹窗 -->
<Dialog :title="productName" v-model="qrDialogVisible" :appendToBody="true">
<!-- 显示有效行数 -->
<div>输入的有效行数: {{ qrCodeLineCount }}</div>
<div>需要扫描数: {{ qrNeedCount }}</div>
<el-input type="textarea" v-model="qrCodes" :rows="10" @input="onQrCodeChange" />
<template #footer>
<el-button @click="submitQr" type="primary">
</el-button>
<el-button @click="qrDialogVisible = false"> </el-button>
</template>
</Dialog>
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { StockApi } from '@/api/erp/stock/stock' import { StockApi } from '@/api/erp/stock/stock'
@ -175,7 +179,9 @@ import {
erpCountInputFormatter, erpCountInputFormatter,
erpPriceInputFormatter, erpPriceInputFormatter,
erpPriceMultiply, erpPriceMultiply,
getSumValue getSumValue,
matchRulesFromDictOptions
} from '@/utils' } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse' import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
@ -193,6 +199,86 @@ const formRules = reactive({
const formRef = ref([]) // Ref const formRef = ref([]) // Ref
const warehouseList = ref<WarehouseVO[]>([]) // const warehouseList = ref<WarehouseVO[]>([]) //
const defaultWarehouse = ref<WarehouseVO>(undefined) // const defaultWarehouse = ref<WarehouseVO>(undefined) //
//
const qrDialogVisible = ref(false)
//
const qrCodes = ref('')
//
const currentRow = ref<typeof props.items[0]>(undefined)
//
const currentRowIndex = ref(-1)
//
const productName = ref('')
//
const qrCodeLineCount = ref(0);
const message = useMessage() //
//
const qrNeedCount = computed(() => {
return currentRow.value?.count
})
//
const onQrCodeChange = () => {
// qrCode.value undefined null
if (qrCodes.value) {
const lines = qrCodes.value.split('\n');
//
const trimmedLines = lines.map(line => line.trim());
const validLines = trimmedLines.filter(line =>{
return matchRulesFromDictOptions(line)
});
//
const uniqueLines = [...new Set(validLines)];
qrCodeLineCount.value = uniqueLines.length;
// row.count
if (currentRow.value && qrCodeLineCount.value > currentRow.value.count) {
message.warning('输入的有效行数不能超过该产品的数量!');
//
qrCodes.value = validLines.slice(0, currentRow.value.count).join('\n');
qrCodeLineCount.value = currentRow.value.count;
}
} else {
qrCodeLineCount.value = 0;
}
};
/** 提交扫码 */
const submitQr = async () => {
//
if (qrCodes.value == null || qrCodes.value == undefined || qrCodes.value === '') {
return;
}
// formData
const index = currentRowIndex.value; //
if (index !== -1 && formData.value[index]) { //
// formData qrcode
formData.value[index].qrcodes = qrCodes.value;
//
formData.value[index].qrCodeLineCount = qrCodeLineCount.value;
}
//
qrDialogVisible.value = false;
};
//
const openQrDialog = (index: number) => {
// currentRow
currentRow.value = formData.value[index]; // 使
currentRowIndex.value = index;
//
if (currentRow.value.qrcodes) {
qrCodes.value = currentRow.value.qrcodes;
} else {
qrCodes.value = ''; //
}
//
productName.value = currentRow.value.productName;
//
onQrCodeChange();
//
qrDialogVisible.value = true;
};
/** 初始化设置出库项 */ /** 初始化设置出库项 */
watch( watch(

View File

@ -0,0 +1,146 @@
<template>
<Dialog v-model="dialogVisible" title="二维码列表" width="60%">
<el-form ref="formRef" label-width="100px">
<el-row :gutter="20">
<el-col :span="20">
<el-form-item label="二维码" prop="no">
<el-input v-model="qr" ref="qrInputRef" placeholder="扫描二维码" @keyup.enter="handleQrEnter" />
</el-form-item>
</el-col>
<el-form-item v-show="false" label="隐藏字段">
<el-input v-model="qrHiden" placeholder="隐藏字段" @keyup.enter="handleQrEnter" />
</el-form-item>
</el-row>
<ContentWrap>
<el-table :data="qrCodeRowList">
<!-- 序号 -->
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column prop="qr" label="二维码" />
<el-table-column prop="warehouseName" label="仓库" />
<el-table-column prop="warehouseLocationName" label="货位" />
<el-table-column prop="productName" label="产品名称" />
<el-table-column prop="productUnitName" label="产品单位" />
<!-- 操作列 -->
<el-table-column label="操作">
<template #default="scope">
<el-button @click="deleteRow(scope.$index)" link>
</el-button>
</template>
</el-table-column>
</el-table>
</ContentWrap>
</el-form>
<template #footer>
<el-button type="primary" @click="submitQr"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { ref, defineProps, defineEmits } from 'vue';
import {
matchRulesFromDictOptions
} from '@/utils'
const props = defineProps({
currentRow: {
type: Object,
required: true
},
currentRowIndex: {
type: Number,
required: true
}
});
// currentRowIndex
watch(() => props.currentRowIndex, (newIndex) => {
// currentRowIndex
console.log('currentRowIndex 已更新为:', newIndex);
});
const formRef = ref();
const qr = ref('');
const qrHiden = ref('');
// ref DOM
const qrInputRef = ref(null);
const emits = defineEmits(['submit-data', 'close']);
const dialogVisible = ref(false);
const qrCodeRowList = ref([]);
const message = useMessage() //
const open = async (row,index)=>{
// currentRow qrCodeRowList
qrCodeRowList.value = [];
if (row.qrcodes) {
row.qrcodes.split('\n').forEach((item) => {
const newRow = { ...row, qr: item };
qrCodeRowList.value.push(newRow);
});
}
dialogVisible.value = true;
};
const close = () => {
dialogVisible.value = false;
emits('close');
};
/** 提交扫码 */
const submitQr = async () => {
//
if (qrCodeRowList.value.length === 0) {
message.warning('请扫描二维码');
return;
}
//
if (qrCodeRowList.value.length !== props.currentRow.count) {
message.warning('扫码数量与数量不一致');
return;
}
// formData
const index = props.currentRowIndex; //
// 'submit-data' qrCodeRowList
emits('submit-data', qrCodeRowList.value, index);
dialogVisible.value = false;
};
//
const handleQrEnter = () => {
if (!matchRulesFromDictOptions(qr.value)) {
//
message.warning('二维码格式不正确');
return;
}
//
const newRow = { ...props.currentRow, qr: qr.value };
qrCodeRowList.value.push(newRow);
//
qr.value = '';
//
if (qrInputRef.value) {
qrInputRef.value.focus();
}
};
//
const deleteRow = (index: number) => {
qrCodeRowList.value.splice(index, 1);
};
defineExpose({
open,
close
});
</script>

View File

@ -0,0 +1,156 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="销售出库编号" prop="outId">
<el-input v-model="formData.outId" placeholder="请输入销售出库编号" />
</el-form-item>
<el-form-item label="销售订单项编号" prop="orderItemId">
<el-input v-model="formData.orderItemId" placeholder="请输入销售订单项编号" />
</el-form-item>
<el-form-item label="销售出库单项编号" prop="outItemId">
<el-input v-model="formData.outItemId" placeholder="请输入销售出库单项编号" />
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input v-model="formData.warehouseId" placeholder="请输入仓库编号" />
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-input v-model="formData.productId" placeholder="请输入产品编号" />
</el-form-item>
<el-form-item label="产品单位单位" prop="productUnitId">
<el-input v-model="formData.productUnitId" placeholder="请输入产品单位单位" />
</el-form-item>
<el-form-item label="产品单价" prop="productPrice">
<el-input v-model="formData.productPrice" placeholder="请输入产品单价" />
</el-form-item>
<el-form-item label="数量" prop="count">
<el-input v-model="formData.count" placeholder="请输入数量" />
</el-form-item>
<el-form-item label="总价" prop="totalPrice">
<el-input v-model="formData.totalPrice" placeholder="请输入总价" />
</el-form-item>
<el-form-item label="税率,百分比" prop="taxPercent">
<el-input v-model="formData.taxPercent" placeholder="请输入税率,百分比" />
</el-form-item>
<el-form-item label="税额,单位:元" prop="taxPrice">
<el-input v-model="formData.taxPrice" placeholder="请输入税额,单位:元" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { SaleOutItemsQrApi, SaleOutItemsQrVO } from '@/api/erp/sale/out/saleoutitemsqr'
/** ERP 销售出库项二维码 表单 */
defineOptions({ name: 'SaleOutItemsQrForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
outId: undefined,
orderItemId: undefined,
outItemId: undefined,
warehouseId: undefined,
productId: undefined,
productUnitId: undefined,
productPrice: undefined,
count: undefined,
totalPrice: undefined,
taxPercent: undefined,
taxPrice: undefined,
remark: undefined
})
const formRules = reactive({
outId: [{ required: true, message: '销售出库编号不能为空', trigger: 'blur' }],
orderItemId: [{ required: true, message: '销售订单项编号不能为空', trigger: 'blur' }],
outItemId: [{ required: true, message: '销售出库单项编号不能为空', trigger: 'blur' }],
warehouseId: [{ required: true, message: '仓库编号不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品编号不能为空', trigger: 'blur' }],
productUnitId: [{ required: true, message: '产品单位单位不能为空', trigger: 'blur' }],
productPrice: [{ required: true, message: '产品单价不能为空', trigger: 'blur' }],
count: [{ required: true, message: '数量不能为空', trigger: 'blur' }],
totalPrice: [{ required: true, message: '总价不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await SaleOutItemsQrApi.getSaleOutItemsQr(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as SaleOutItemsQrVO
if (formType.value === 'create') {
await SaleOutItemsQrApi.createSaleOutItemsQr(data)
message.success(t('common.createSuccess'))
} else {
await SaleOutItemsQrApi.updateSaleOutItemsQr(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
outId: undefined,
orderItemId: undefined,
outItemId: undefined,
warehouseId: undefined,
productId: undefined,
productUnitId: undefined,
productPrice: undefined,
count: undefined,
totalPrice: undefined,
taxPercent: undefined,
taxPrice: undefined,
remark: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,308 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="销售出库编号" prop="outId">
<el-input
v-model="queryParams.outId"
placeholder="请输入销售出库编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="销售订单项编号" prop="orderItemId">
<el-input
v-model="queryParams.orderItemId"
placeholder="请输入销售订单项编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="销售出库单项编号" prop="outItemId">
<el-input
v-model="queryParams.outItemId"
placeholder="请输入销售出库单项编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-input
v-model="queryParams.productId"
placeholder="请输入产品编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品单位单位" prop="productUnitId">
<el-input
v-model="queryParams.productUnitId"
placeholder="请输入产品单位单位"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品单价" prop="productPrice">
<el-input
v-model="queryParams.productPrice"
placeholder="请输入产品单价"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="数量" prop="count">
<el-input
v-model="queryParams.count"
placeholder="请输入数量"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="总价" prop="totalPrice">
<el-input
v-model="queryParams.totalPrice"
placeholder="请输入总价"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="税率,百分比" prop="taxPercent">
<el-input
v-model="queryParams.taxPercent"
placeholder="请输入税率,百分比"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="税额,单位:元" prop="taxPrice">
<el-input
v-model="queryParams.taxPrice"
placeholder="请输入税额,单位:元"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-out-items-qr:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-out-items-qr:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="销售出库编号" align="center" prop="outId" />
<el-table-column label="销售订单项编号" align="center" prop="orderItemId" />
<el-table-column label="销售出库单项编号" align="center" prop="outItemId" />
<el-table-column label="仓库编号" align="center" prop="warehouseId" />
<el-table-column label="产品编号" align="center" prop="productId" />
<el-table-column label="产品单位单位" align="center" prop="productUnitId" />
<el-table-column label="产品单价" align="center" prop="productPrice" />
<el-table-column label="数量" align="center" prop="count" />
<el-table-column label="总价" align="center" prop="totalPrice" />
<el-table-column label="税率,百分比" align="center" prop="taxPercent" />
<el-table-column label="税额,单位:元" align="center" prop="taxPrice" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-out-items-qr:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:sale-out-items-qr:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<SaleOutItemsQrForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { SaleOutItemsQrApi, SaleOutItemsQrVO } from '@/api/erp/sale/out/saleoutitemsqr'
import SaleOutItemsQrForm from './SaleOutItemsQrForm.vue'
/** ERP 销售出库项二维码 列表 */
defineOptions({ name: 'ErpSaleOutItemsQr' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<SaleOutItemsQrVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
outId: undefined,
orderItemId: undefined,
outItemId: undefined,
warehouseId: undefined,
productId: undefined,
productUnitId: undefined,
productPrice: undefined,
count: undefined,
totalPrice: undefined,
taxPercent: undefined,
taxPrice: undefined,
remark: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await SaleOutItemsQrApi.getSaleOutItemsQrPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await SaleOutItemsQrApi.deleteSaleOutItemsQr(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await SaleOutItemsQrApi.exportSaleOutItemsQr(queryParams)
download.excel(data, 'ERP 销售出库项二维码.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,137 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="明细编号" prop="recordId">
<el-input v-model="formData.recordId" placeholder="请输入明细编号" />
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-input v-model="formData.productId" placeholder="请输入产品编号" />
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input v-model="formData.warehouseId" placeholder="请输入仓库编号" />
</el-form-item>
<el-form-item label="货位编号" prop="warehouseLocationId">
<el-input v-model="formData.warehouseLocationId" placeholder="请输入货位编号" />
</el-form-item>
<el-form-item label="业务类型" prop="bizType">
<el-select v-model="formData.bizType" placeholder="请选择业务类型">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="业务编号" prop="bizId">
<el-input v-model="formData.bizId" placeholder="请输入业务编号" />
</el-form-item>
<el-form-item label="业务项编号" prop="bizItemId">
<el-input v-model="formData.bizItemId" placeholder="请输入业务项编号" />
</el-form-item>
<el-form-item label="业务单号" prop="bizNo">
<el-input v-model="formData.bizNo" placeholder="请输入业务单号" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { StockRecordQrApi, StockRecordQrVO } from '@/api/erp/stock/record/stockrecordqr'
/** ERP 产品库存明细二维码 表单 */
defineOptions({ name: 'StockRecordQrForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
recordId: undefined,
productId: undefined,
warehouseId: undefined,
warehouseLocationId: undefined,
bizType: undefined,
bizId: undefined,
bizItemId: undefined,
bizNo: undefined
})
const formRules = reactive({
recordId: [{ required: true, message: '明细编号不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品编号不能为空', trigger: 'blur' }],
warehouseId: [{ required: true, message: '仓库编号不能为空', trigger: 'blur' }],
warehouseLocationId: [{ required: true, message: '货位编号不能为空', trigger: 'blur' }],
bizType: [{ required: true, message: '业务类型不能为空', trigger: 'change' }],
bizId: [{ required: true, message: '业务编号不能为空', trigger: 'blur' }],
bizItemId: [{ required: true, message: '业务项编号不能为空', trigger: 'blur' }],
bizNo: [{ required: true, message: '业务单号不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await StockRecordQrApi.getStockRecordQr(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as StockRecordQrVO
if (formType.value === 'create') {
await StockRecordQrApi.createStockRecordQr(data)
message.success(t('common.createSuccess'))
} else {
await StockRecordQrApi.updateStockRecordQr(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
recordId: undefined,
productId: undefined,
warehouseId: undefined,
warehouseLocationId: undefined,
bizType: undefined,
bizId: undefined,
bizItemId: undefined,
bizNo: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,269 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="明细编号" prop="recordId">
<el-input
v-model="queryParams.recordId"
placeholder="请输入明细编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-input
v-model="queryParams.productId"
placeholder="请输入产品编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="货位编号" prop="warehouseLocationId">
<el-input
v-model="queryParams.warehouseLocationId"
placeholder="请输入货位编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="业务类型" prop="bizType">
<el-select
v-model="queryParams.bizType"
placeholder="请选择业务类型"
clearable
class="!w-240px"
>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="业务编号" prop="bizId">
<el-input
v-model="queryParams.bizId"
placeholder="请输入业务编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="业务项编号" prop="bizItemId">
<el-input
v-model="queryParams.bizItemId"
placeholder="请输入业务项编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="业务单号" prop="bizNo">
<el-input
v-model="queryParams.bizNo"
placeholder="请输入业务单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-record-qr:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-record-qr:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="二维码" align="center" prop="qr" min-width="100" />
<el-table-column label="明细编号" align="center" prop="recordId" />
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="货位" align="center" prop="warehouseLocationName" />
<el-table-column label="类型" align="center" prop="bizType" min-width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE" :value="scope.row.bizType" />
</template>
</el-table-column>
<el-table-column label="业务单号" align="center" prop="bizNo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:stock-record-qr:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:stock-record-qr:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<StockRecordQrForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { StockRecordQrApi, StockRecordQrVO } from '@/api/erp/stock/record/stockrecordqr'
import StockRecordQrForm from './StockRecordQrForm.vue'
/** ERP 产品库存明细二维码 列表 */
defineOptions({ name: 'ErpStockRecordQr' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<StockRecordQrVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
recordId: undefined,
productId: undefined,
warehouseId: undefined,
warehouseLocationId: undefined,
bizType: undefined,
bizId: undefined,
bizItemId: undefined,
bizNo: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StockRecordQrApi.getStockRecordQrPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await StockRecordQrApi.deleteStockRecordQr(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await StockRecordQrApi.exportStockRecordQr(queryParams)
download.excel(data, 'ERP 产品库存明细二维码.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -80,6 +80,7 @@
:formatter="erpCountTableColumnFormatter" :formatter="erpCountTableColumnFormatter"
/> />
<el-table-column label="仓库" align="center" prop="warehouseName" /> <el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="货位" align="center" prop="warehouseLocationName" />
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination

View File

@ -0,0 +1,106 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="二维码" prop="qr">
<el-input v-model="formData.qr" placeholder="请输入二维码" />
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-select v-model="formData.productId" placeholder="请选择产品编号">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input v-model="formData.warehouseId" placeholder="请输入仓库编号" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { StockQrApi, StockQrVO } from '@/api/erp/stock/stock/stockqr'
/** ERP 产品库存二维码 表单 */
defineOptions({ name: 'StockQrForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
qr: undefined,
productId: undefined,
warehouseId: undefined
})
const formRules = reactive({
qr: [{ required: true, message: '二维码不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品编号不能为空', trigger: 'change' }],
warehouseId: [{ required: true, message: '仓库编号不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await StockQrApi.getStockQr(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as StockQrVO
if (formType.value === 'create') {
await StockQrApi.createStockQr(data)
message.success(t('common.createSuccess'))
} else {
await StockQrApi.updateStockQr(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
qr: undefined,
productId: undefined,
warehouseId: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,181 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="二维码" prop="qr">
<el-input v-model="queryParams.qr" placeholder="请输入二维码" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="产品编号" prop="productId">
<el-select v-model="queryParams.productId" placeholder="请选择产品编号" clearable class="!w-240px">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="仓库编号" prop="warehouseId">
<el-input v-model="queryParams.warehouseId" placeholder="请输入仓库编号" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-220px" />
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:stock-qr:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['erp:stock-qr:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="二维码" align="center" prop="qr" />
<el-table-column label="二维码图片" align="center" prop="qrImg">
<template #default="scope">
<img :src="scope.row.qrImgUrl" alt="二维码图片" class="w-50px h-50px" />
</template>
</el-table-column>
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="货位" align="center" prop="warehouseLocationName" />
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:stock-qr:update']">
编辑
</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:stock-qr:delete']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<StockQrForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { StockQrApi, StockQrVO } from '@/api/erp/stock/stock/stockqr'
import StockQrForm from './StockQrForm.vue'
import QRCode from 'qrcode' // qrcode
/** ERP 产品库存二维码 列表 */
defineOptions({ name: 'ErpStockQr' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<StockQrVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
qr: undefined,
productId: undefined,
warehouseId: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
//
const generateQrCodeImage = async (qrValue: string): Promise<string> => {
try {
const base64 = await QRCode.toDataURL(qrValue)
return base64
} catch (error) {
console.error('生成二维码失败:', error)
return ''
}
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StockQrApi.getStockQrPage(queryParams)
list.value = data.list
total.value = data.total
//
for (const item of list.value) {
if (item.qr) {
const imageUrl = await generateQrCodeImage(item.qr)
item.qrImgUrl = imageUrl // qrImgUrl
}
}
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await StockQrApi.deleteStockQr(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch { }
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await StockQrApi.exportStockQr(queryParams)
download.excel(data, 'ERP 产品库存二维码.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,157 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="仓库名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入仓库名称" />
</el-form-item>
<el-form-item label="仓库地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入仓库地址" />
</el-form-item>
<el-form-item label="仓库状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="仓储费" prop="warehousePrice">
<el-input-number
v-model="formData.warehousePrice"
placeholder="请输入仓储费,单位:元/天/KG"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item>
<el-form-item label="搬运费" prop="truckagePrice">
<el-input-number
v-model="formData.truckagePrice"
placeholder="请输入搬运费,单位:元"
:min="0"
:precision="2"
class="!w-1/1"
/>
</el-form-item>
<el-form-item label="负责人" prop="principal">
<el-input v-model="formData.principal" placeholder="请输入负责人" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
placeholder="请输入排序"
:precision="0"
class="!w-1/1"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { WarehouseApi, WarehouseVO } from '@/api/erp/warehouse'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
/** ERP 仓库 表单 */
defineOptions({ name: 'WarehouseForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
address: undefined,
sort: undefined,
remark: undefined,
principal: undefined,
warehousePrice: undefined,
truckagePrice: undefined,
status: undefined,
defaultStatus: undefined
})
const formRules = reactive({
name: [{ required: true, message: '仓库名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await WarehouseApi.getWarehouse(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as WarehouseVO
if (formType.value === 'create') {
await WarehouseApi.createWarehouse(data)
message.success(t('common.createSuccess'))
} else {
await WarehouseApi.updateWarehouse(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
address: undefined,
sort: undefined,
remark: undefined,
principal: undefined,
warehousePrice: undefined,
truckagePrice: undefined,
status: undefined,
defaultStatus: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,125 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="货位名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入货位名称" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
placeholder="请输入排序"
:precision="0"
class="!w-1/1"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="货位状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { WarehouseApi } from '@/api/erp/warehouse'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
sort: undefined,
remark: undefined,
status: undefined,
warehouseId: 0
})
const formRules = reactive({
name: [{ required: true, message: '货位名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }],
warehouseId: [{ required: true, message: '仓库编号不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id: number, warehouseId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.warehouseId = warehouseId
//
if (id) {
formLoading.value = true
try {
formData.value = await WarehouseApi.getWarehouseLocation(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await WarehouseApi.createWarehouseLocation(data)
message.success(t('common.createSuccess'))
} else {
await WarehouseApi.updateWarehouseLocation(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
sort: undefined,
remark: undefined,
status: undefined,
warehouseId: 0
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,135 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:warehouse:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="货位编号" align="center" prop="id" />
<el-table-column label="货位名称" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="货位状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:warehouse:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:warehouse:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<WarehouseLocationForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import { WarehouseApi } from '@/api/erp/warehouse'
import WarehouseLocationForm from './WarehouseLocationForm.vue'
import { DICT_TYPE } from '@/utils/dict'
const { t } = useI18n() //
const message = useMessage() //
const props = defineProps<{
warehouseId?: number //
}>()
const loading = ref(false) //
const list = ref([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
warehouseId: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.warehouseId,
(val: number) => {
if (!val) {
return
}
queryParams.warehouseId = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await WarehouseApi.getWarehouseLocationPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.warehouseId) {
message.error('请选择一个ERP 仓库')
return
}
formRef.value.open(type, id, props.warehouseId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await WarehouseApi.deleteWarehouseLocation(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
</script>

View File

@ -0,0 +1,275 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="仓库名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入仓库名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择仓库状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:warehouse:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:warehouse:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="仓库名称" align="center" prop="name" />
<el-table-column label="仓库地址" align="center" prop="address" />
<el-table-column
label="仓储费"
align="center"
prop="warehousePrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="搬运费"
align="center"
prop="truckagePrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="是否默认" align="center" prop="defaultStatus">
<template #default="scope">
<el-switch
v-model="scope.row.defaultStatus"
:active-value="true"
:inactive-value="false"
@change="handleDefaultStatusChange(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:warehouse:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:warehouse:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<WarehouseForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="warehouseLocation">
<el-tab-pane label="ERP 仓库货位" name="warehouseLocation">
<WarehouseLocationList :warehouse-id="currentRow.id" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { WarehouseApi, WarehouseVO } from '@/api/erp/warehouse'
import WarehouseForm from './WarehouseForm.vue'
import WarehouseLocationList from './components/WarehouseLocationList.vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { erpPriceTableColumnFormatter } from '@/utils'
/** ERP 仓库 列表 */
defineOptions({ name: 'Warehouse' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<WarehouseVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined,
address: undefined,
sort: undefined,
remark: undefined,
principal: undefined,
warehousePrice: undefined,
truckagePrice: undefined,
status: undefined,
defaultStatus: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await WarehouseApi.getWarehousePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await WarehouseApi.deleteWarehouse(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 修改默认状态 */
const handleDefaultStatusChange = async (row: WarehouseVO) => {
try {
//
const text = row.defaultStatus ? '设置' : '取消'
await message.confirm('确认要' + text + '"' + row.name + '"默认吗?')
//
await WarehouseApi.updateWarehouseDefaultStatus(row.id, row.defaultStatus)
//
await getList()
} catch (e) {
//
row.defaultStatus = !row.defaultStatus
}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await WarehouseApi.exportWarehouse(queryParams)
download.excel(data, 'ERP 仓库.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({
id: undefined
})
//
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>