diff --git a/src/api/erp/mold/index.ts b/src/api/erp/mold/index.ts index 6b4767e8..6e850d2d 100644 --- a/src/api/erp/mold/index.ts +++ b/src/api/erp/mold/index.ts @@ -26,6 +26,7 @@ export interface MoldBrandTreeVO extends MoldBrandVO { export interface MoldVO { id: number // ID code: string // 模具编码 + isCode?: boolean name: string // 模具名称 unitId: number // 单位ID machineId: number // 机台ID @@ -125,6 +126,9 @@ export const MoldBrandApi = { // 获得模具 getMold: async (id: number) => { return await request.get({ url: `/erp/mold-brand/mold/get?id=` + id }) + }, + regenerateCode: async (id: number, code: string) => { + return await request.post({ url: `/erp/mold-brand/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` }) }, // 根据状态获得模具 getMoldListByStatus: async (status: number) => { diff --git a/src/api/erp/product/product/index.ts b/src/api/erp/product/product/index.ts index c84f1831..e922d3d1 100644 --- a/src/api/erp/product/product/index.ts +++ b/src/api/erp/product/product/index.ts @@ -5,6 +5,8 @@ export interface ProductVO { id: number // 产品编号 name: string // 产品名称 barCode: string // 产品条码 + isCode?: boolean + qrcodeUrl?: string categoryId: number // 产品类型编号 subCategoryId: number // 产品类型子类编号 subCategoryName: string // 产品类型子类名称 @@ -63,6 +65,13 @@ export const ProductApi = { return await request.put({ url: `/erp/product/update`, data }) }, + // 刷新产品二维码 + regenerateCode: async (id: number, code: string) => { + return await request.post({ + url: `/erp/product/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` + }) + }, + // 删除产品 deleteProduct: async (id: number) => { return await request.delete({ url: `/erp/product/delete?id=` + id }) diff --git a/src/api/mes/criticalComponent/index.ts b/src/api/mes/criticalComponent/index.ts index c702953c..859192d8 100644 --- a/src/api/mes/criticalComponent/index.ts +++ b/src/api/mes/criticalComponent/index.ts @@ -3,10 +3,12 @@ import request from '@/config/axios' export interface CriticalComponentVO { id: number code: string + isCode?: boolean name: string description?: string count?: number remark?: string + qrcodeUrl?: string createTime?: string } @@ -17,6 +19,9 @@ export const CriticalComponentApi = { getCriticalComponentList: async () => { return await request.get({ url: `/mes/critical-component/list`, }) }, + getCriticalComponent: async (id: number) => { + return await request.get({ url: `/mes/critical-component/get?id=` + id }) + }, createCriticalComponent: async (data: Partial) => { return await request.post({ url: `/mes/critical-component/create`, data }) }, @@ -25,6 +30,12 @@ export const CriticalComponentApi = { return await request.put({ url: `/mes/critical-component/update`, data }) }, + regenerateCode: async (id: number, code: string) => { + return await request.post({ + url: `/mes/critical-component/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` + }) + }, + deleteCriticalComponent: async (ids: string) => { return await request.delete({ url: `/mes/critical-component/delete?ids=` + ids }) }, diff --git a/src/api/mes/deviceledger/index.ts b/src/api/mes/deviceledger/index.ts index 12ecc1b0..17e8f030 100644 --- a/src/api/mes/deviceledger/index.ts +++ b/src/api/mes/deviceledger/index.ts @@ -6,6 +6,7 @@ import { MoldVO } from '@/api/erp/mold' export interface DeviceLedgerVO { id: number // id deviceCode: string // 设备编号 + isCode?: boolean deviceName: string // 设备名称 deviceStatus: number // 设备状态 (0-正常, 1-停用, 2-维修, 3-报废) deviceBrand: string // 设备品牌 @@ -24,6 +25,7 @@ export interface DeviceLedgerVO { deviceRemark: string // 设备备注 remark: string // 备注 fileUrl?: string // 附件下载 + qrcodeUrl?: string componentId?: string // 关键件,ids集合 componentList?: CriticalComponentVO[] beijianId?: string // 备件,ids集合 @@ -73,6 +75,10 @@ export const DeviceLedgerApi = { return await request.put({ url: `/mes/device-ledger/update`, data }) }, + regenerateCode: async (id: number, code: string) => { + return await request.post({ url: `/mes/device-ledger/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` }) + }, + // 删除设备类型 deleteDeviceLedger: async (ids: string) => { return await request.delete({ url: `/mes/device-ledger/delete?ids=` + ids }) diff --git a/src/locales/en.ts b/src/locales/en.ts index 2edee44e..b6cde81d 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -1192,6 +1192,7 @@ export default { // Equipment Ledger EquipmentLedger: { deviceCode: 'Code', + qrcode: 'QR Code/Barcode', deviceName: 'Name', deviceStatus: 'Status', deviceType: 'Type', @@ -1261,11 +1262,15 @@ export default { fileUrl: 'File', serialNumber: 'No.', dvName: 'Device Name', - dvId: 'Please select device' + dvId: 'Please select device', + qrcodeLoadError: 'Failed to load QR code', + qrcodeEmpty: 'No QR code', + validatorDeviceCodeRequired: 'Code can not be empty' }, // Critical Component EquipmentKeyItems: { code: 'Code', + qrcode: 'QR Code/Barcode', name: 'Name', batchDelete: 'Batch Delete', description: 'Description', @@ -1277,7 +1282,11 @@ export default { placeholderCode: 'Please input code', placeholderName: 'Please input name', placeholderDescription: 'Please input description', - placeholderRemark: 'Please input remark' + placeholderRemark: 'Please input remark', + qrcodeLoadError: 'Failed to load QR code', + qrcodeEmpty: 'No QR code', + validatorCodeRequired: 'Code can not be empty', + validatorNameRequired: 'Name can not be empty' }, // Maintenance Project (Project Maintenance) DvSubject: { @@ -1536,6 +1545,7 @@ export default { SpareInfo: { name: 'Spare Part Name', code: 'Spare Part Code', + qrcode: 'QR Code/Barcode', standard: 'Specification', expiryDay: 'Shelf Life (days)', category: 'Category', @@ -1553,6 +1563,8 @@ export default { placeholderRemark: 'Please input remark', placeholderStandard: 'Please input specification', placeholderExpiryDay: 'Please input shelf life (days)', + qrcodeLoadError: 'Failed to load QR code', + qrcodeEmpty: 'No QR code', validatorNameRequired: 'Spare part name can not be empty', validatorCodeRequired: 'Spare part code can not be empty', validatorCategoryRequired: 'Category can not be empty', @@ -1837,6 +1849,7 @@ export default { tableOperateColumn: 'Operation', tableEditAction: 'Edit', tableDeleteAction: 'Delete', + qrcode: 'QR Code/Barcode', dialogBarCodeLabel: 'Code', dialogBarCodePlaceholder: 'Please enter code', dialogNameLabel: 'Name', @@ -1862,6 +1875,8 @@ export default { dialogRemarkPlaceholder: 'Please enter remark', dialogCancelButton: 'Cancel', dialogSubmitButton: 'Confirm', + qrcodeLoadError: 'Failed to load QR code', + qrcodeEmpty: 'No QR code', validatorNameRequired: 'Product name can not be empty', validatorBarCodeRequired: 'Product barcode can not be empty', validatorCategoryRequired: 'Product category id can not be empty', @@ -2214,6 +2229,7 @@ export default { unit: 'Unit', inTime: 'Stock In Time', status: 'Status', + qrcode: 'QR / Barcode', images: 'Mold Images', remark: 'Remark', isEnable: 'Is Enable', @@ -2240,7 +2256,9 @@ export default { validatorIsEnableRequired: 'Is enable can not be empty', validatorBrandRequired: 'Model can not be empty', selectBrandTip: 'Please select a mold model', - statusTooltip: 'Source: Data dictionary - Mold status' + statusTooltip: 'Source: Data dictionary - Mold status', + qrcodeLoadError: 'QR code load failed', + qrcodeEmpty: 'No QR code' }, MoldReturn: { diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 6f66ec17..c15a3152 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -1184,6 +1184,7 @@ export default { // 设备台账 EquipmentLedger: { deviceCode: '编码', + qrcode: '二维码/条形码', deviceName: '名称', deviceStatus: '状态', deviceType: '类型', @@ -1253,12 +1254,16 @@ export default { fileUrl: '资料', serialNumber: '序号', dvName: '关联采集设备', - dvId: '请选择设备' + dvId: '请选择设备', + qrcodeLoadError: '二维码加载失败', + qrcodeEmpty: '暂无二维码', + validatorDeviceCodeRequired: '编码不能为空' }, // 设备关键件 EquipmentKeyItems: { count: '数量', code: '编码', + qrcode: '二维码/条形码', name: '名称', batchDelete: '批量删除', description: '描述', @@ -1271,7 +1276,11 @@ export default { placeholderName: '请输入名称', placeholderDescription: '请输入描述', placeholderRemark: '请输入备注', - placeholderCount: '请输入数量' + placeholderCount: '请输入数量', + qrcodeLoadError: '二维码加载失败', + qrcodeEmpty: '暂无二维码', + validatorCodeRequired: '编码不能为空', + validatorNameRequired: '名称不能为空' }, // 项目维护 DvSubject: { @@ -1531,6 +1540,7 @@ export default { SpareInfo: { name: '备件名称', code: '备件编码', + qrcode: '二维码/条形码', standard: '规格', expiryDay: '保质期天数', category: '分类', @@ -1548,6 +1558,8 @@ export default { placeholderRemark: '请输入备注', placeholderStandard: '请输入规格', placeholderExpiryDay: '请输入保质期天数', + qrcodeLoadError: '二维码加载失败', + qrcodeEmpty: '暂无二维码', validatorNameRequired: '备件名称不能为空', validatorCodeRequired: '备件编码不能为空', validatorCategoryRequired: '分类不能为空', @@ -1731,6 +1743,7 @@ export default { unit: '单位', inTime: '入库时间', status: '状态', + qrcode: '二维码/条形码', images: '模具图片', remark: '备注', isEnable: '是否启用', @@ -1757,7 +1770,9 @@ export default { validatorIsEnableRequired: '是否启用不能为空', validatorBrandRequired: '型号不能为空', selectBrandTip: '请选择一个模具型号', - statusTooltip: '来源:数据字典-模具状态' + statusTooltip: '来源:数据字典-模具状态', + qrcodeLoadError: '二维码加载失败', + qrcodeEmpty: '暂无二维码' }, MoldReturn: { @@ -2642,6 +2657,7 @@ export default { tableOperateColumn: '操作', tableEditAction: '编辑', tableDeleteAction: '删除', + qrcode: '二维码/条形码', dialogBarCodeLabel: '编码', dialogBarCodePlaceholder: '请输入编码', dialogNameLabel: '名称', @@ -2667,6 +2683,8 @@ export default { dialogRemarkPlaceholder: '请输入备注', dialogCancelButton: '取 消', dialogSubmitButton: '确 定', + qrcodeLoadError: '二维码加载失败', + qrcodeEmpty: '暂无二维码', validatorNameRequired: '产品名称不能为空', validatorBarCodeRequired: '产品条码不能为空', validatorCategoryRequired: '产品分类编号不能为空', diff --git a/src/views/erp/component/product/ProductForm.vue b/src/views/erp/component/product/ProductForm.vue index 82be65c1..f5c2ef84 100644 --- a/src/views/erp/component/product/ProductForm.vue +++ b/src/views/erp/component/product/ProductForm.vue @@ -11,7 +11,24 @@ - + + + + + +
+ +
+
+
@@ -82,6 +99,39 @@ + + +
+ + + +
+ {{ t('SparePartsManagement.SpareInfo.qrcodeEmpty') }} +
+
+ + + +
+
+
+
@@ -99,7 +149,6 @@ import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit' import { CommonStatusEnum } from '@/utils/constants' -import { defaultProps, handleTree } from '@/utils/tree' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' /** ERP 产品 表单 */ @@ -112,10 +161,13 @@ const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const regenerateCodeLoading = ref(false) const formData = ref({ id: undefined, name: undefined, barCode: undefined, + isCode: undefined, + qrcodeUrl: undefined, categoryId: undefined, unitId: undefined, status: undefined, @@ -128,9 +180,20 @@ const formData = ref({ minPrice: undefined, safetyNumber: undefined }) +const validateBarCode = (_rule, value, callback) => { + if (Boolean(formData.value.isCode)) { + callback() + return + } + if (value === undefined || value === null || String(value).trim() === '') { + callback(new Error(t('SparePartsManagement.SpareInfo.validatorCodeRequired'))) + return + } + callback() +} const formRules = reactive({ name: [{ required: true, message: t('SparePartsManagement.SpareInfo.validatorNameRequired'), trigger: 'blur' }], - barCode: [{ required: true, message: t('SparePartsManagement.SpareInfo.validatorCodeRequired'), trigger: 'blur' }], + barCode: [{ validator: validateBarCode, trigger: ['blur', 'change'] }], categoryId: [{ required: true, message: t('SparePartsManagement.SpareInfo.validatorCategoryRequired'), trigger: 'blur' }], unitId: [{ required: true, message: t('SparePartsManagement.SpareInfo.validatorUnitRequired'), trigger: 'blur' }], status: [{ required: true, message: t('SparePartsManagement.SpareInfo.validatorStatusRequired'), trigger: 'blur' }] @@ -158,6 +221,31 @@ const open = async (type: string, id?: number) => { } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 +const handleCodeAutoChange = (value: boolean) => { + if (value) { + formData.value.barCode = undefined + } + formRef.value?.clearValidate('barCode') +} + +const handleRegenerateCode = async () => { + if (!formData.value.id || !formData.value.barCode) return + regenerateCodeLoading.value = true + try { + const data = await ProductApi.regenerateCode(formData.value.id, formData.value.barCode) + if (data?.qrcodeUrl) { + formData.value.qrcodeUrl = data.qrcodeUrl + } else { + const productData = await ProductApi.getProduct(formData.value.id) + formData.value.qrcodeUrl = productData?.qrcodeUrl + formData.value.barCode = productData?.barCode ?? formData.value.barCode + } + message.success(t('common.updateSuccess')) + } finally { + regenerateCodeLoading.value = false + } +} + /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { @@ -189,6 +277,8 @@ const resetForm = () => { id: undefined, name: undefined, barCode: undefined, + isCode: true, + qrcodeUrl: undefined, categoryId: undefined, unitId: undefined, status: CommonStatusEnum.ENABLE, @@ -203,3 +293,47 @@ const resetForm = () => { formRef.value?.resetFields() } + diff --git a/src/views/erp/mold/components/MoldForm.vue b/src/views/erp/mold/components/MoldForm.vue index 4865cb98..58bcf7fe 100644 --- a/src/views/erp/mold/components/MoldForm.vue +++ b/src/views/erp/mold/components/MoldForm.vue @@ -4,15 +4,28 @@ ref="formRef" :model="formData" :rules="formRules" - label-width="100px" + label-width="120px" v-loading="formLoading" > - + + + + + +
+ +
+
+
+ +
+ + + +
{{ t('MoldManagement.Mold.qrcodeEmpty') }}
+
+ + + +
+
+
@@ -117,9 +157,11 @@ const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const regenerateCodeLoading = ref(false) const formData = ref({ id: undefined, code: undefined, + isCode: undefined, name: undefined, unitId: undefined, machineId: undefined, @@ -127,14 +169,26 @@ const formData = ref({ inTime: undefined, status: undefined, images: undefined, + qrcodeUrl: undefined, remark: undefined, isEnable: undefined, fileUrl: '', brandId: undefined }) +const validateCode = (_rule, value, callback) => { + if (Boolean(formData.value.isCode)) { + callback() + return + } + if (value === undefined || value === null || String(value).trim() === '') { + callback(new Error(t('MoldManagement.Mold.validatorCodeRequired'))) + return + } + callback() +} const formRules = reactive({ code: [ - { required: true, message: t('MoldManagement.Mold.validatorCodeRequired'), trigger: 'blur' } + { validator: validateCode, trigger: ['blur', 'change'] } ], name: [ { required: true, message: t('MoldManagement.Mold.validatorNameRequired'), trigger: 'blur' } @@ -176,6 +230,31 @@ const open = async (type: string, id?: number, brandId: number) => { } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 +const handleCodeAutoChange = (value: boolean) => { + if (value) { + formData.value.code = undefined + } + formRef.value?.clearValidate('code') +} + +const handleRegenerateCode = async () => { + if (!formData.value.id || !formData.value.code) return + regenerateCodeLoading.value = true + try { + const data = await MoldBrandApi.regenerateCode(formData.value.id, formData.value.code) + if (data?.qrcodeUrl) { + formData.value.qrcodeUrl = data.qrcodeUrl + } else { + const moldData = await MoldBrandApi.getMold(formData.value.id) + formData.value.qrcodeUrl = moldData?.qrcodeUrl + formData.value.code = moldData?.code ?? formData.value.code + } + message.success(t('common.updateSuccess')) + } finally { + regenerateCodeLoading.value = false + } +} + /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { @@ -205,6 +284,7 @@ const resetForm = () => { formData.value = { id: undefined, code: undefined, + isCode: true, name: undefined, unitId: undefined, machineId: undefined, @@ -212,6 +292,7 @@ const resetForm = () => { inTime: undefined, status: 3, images: undefined, + qrcodeUrl: undefined, remark: undefined, isEnable: true, fileUrl: '', @@ -220,3 +301,47 @@ const resetForm = () => { formRef.value?.resetFields() } + diff --git a/src/views/erp/product/product/ProductForm.vue b/src/views/erp/product/product/ProductForm.vue index 042e1924..9016913e 100644 --- a/src/views/erp/product/product/ProductForm.vue +++ b/src/views/erp/product/product/ProductForm.vue @@ -11,7 +11,24 @@ - + + + + + +
+ +
+
+
@@ -116,6 +133,39 @@
+ + +
+ + + +
+ {{ t('FactoryModeling.ProductInformation.qrcodeEmpty') }} +
+
+ + + +
+
+
+
@@ -147,10 +197,13 @@ const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const regenerateCodeLoading = ref(false) const formData = ref({ id: undefined, name: undefined, barCode: undefined, + isCode: undefined, + qrcodeUrl: undefined, categoryId: undefined, unitId: undefined, status: undefined, @@ -163,9 +216,20 @@ const formData = ref({ minPrice: undefined, safetyNumber: undefined }) +const validateBarCode = (_rule, value, callback) => { + if (Boolean(formData.value.isCode)) { + callback() + return + } + if (value === undefined || value === null || String(value).trim() === '') { + callback(new Error(t('FactoryModeling.ProductInformation.validatorBarCodeRequired'))) + return + } + callback() +} const formRules = reactive({ name: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorNameRequired'), trigger: 'blur' }], - barCode: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorBarCodeRequired'), trigger: 'blur' }], + barCode: [{ validator: validateBarCode, trigger: ['blur', 'change'] }], categoryId: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorCategoryRequired'), trigger: 'blur' }], unitId: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorUnitRequired'), trigger: 'blur' }], status: [{ required: true, message: t('FactoryModeling.ProductInformation.validatorStatusRequired'), trigger: 'blur' }] @@ -197,6 +261,31 @@ const open = async (type: string, id?: number) => { } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 +const handleCodeAutoChange = (value: boolean) => { + if (value) { + formData.value.barCode = undefined + } + formRef.value?.clearValidate('barCode') +} + +const handleRegenerateCode = async () => { + if (!formData.value.id || !formData.value.barCode) return + regenerateCodeLoading.value = true + try { + const data = await ProductApi.regenerateCode(formData.value.id, formData.value.barCode) + if (data?.qrcodeUrl) { + formData.value.qrcodeUrl = data.qrcodeUrl + } else { + const productData = await ProductApi.getProduct(formData.value.id) + formData.value.qrcodeUrl = productData?.qrcodeUrl + formData.value.barCode = productData?.barCode ?? formData.value.barCode + } + message.success(t('common.updateSuccess')) + } finally { + regenerateCodeLoading.value = false + } +} + /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { @@ -227,6 +316,8 @@ const resetForm = () => { id: undefined, name: undefined, barCode: undefined, + isCode: true, + qrcodeUrl: undefined, categoryId: undefined, unitId: undefined, status: CommonStatusEnum.ENABLE, @@ -241,3 +332,47 @@ const resetForm = () => { formRef.value?.resetFields() } + diff --git a/src/views/iot/device/components/DeviceAttributeForm.vue b/src/views/iot/device/components/DeviceAttributeForm.vue index 69c086b6..f01bd941 100644 --- a/src/views/iot/device/components/DeviceAttributeForm.vue +++ b/src/views/iot/device/components/DeviceAttributeForm.vue @@ -2,22 +2,26 @@ - - - - @@ -25,17 +29,20 @@ - - - diff --git a/src/views/mes/calholiday/index.vue b/src/views/mes/calholiday/index.vue index 118cdaf9..4958400b 100644 --- a/src/views/mes/calholiday/index.vue +++ b/src/views/mes/calholiday/index.vue @@ -2,7 +2,7 @@
-