✨ feat(mes): 添加业务名称字段及相关逻辑
在 MES 条码相关组件中新增业务名称字段,支持根据业务名称进行查询和管理。更新相关 API 逻辑以适应新字段的使用,提升条码管理的灵活性和准确性。pull/871/MERGE
parent
e20322985c
commit
913fa69073
|
|
@ -2,42 +2,42 @@ import request from '@/config/axios'
|
||||||
|
|
||||||
// MES 条码配置 VO
|
// MES 条码配置 VO
|
||||||
export interface WmBarcodeConfigVO {
|
export interface WmBarcodeConfigVO {
|
||||||
id: number
|
id: number
|
||||||
format: number
|
format: number
|
||||||
bizType: number
|
bizType: number
|
||||||
contentFormat: string
|
contentFormat: string
|
||||||
contentExample: string
|
contentExample: string
|
||||||
autoGenerateFlag: boolean
|
autoGenerateFlag: boolean
|
||||||
defaultTemplate: string
|
defaultTemplate: string
|
||||||
status: number
|
status: number
|
||||||
remark: string
|
remark: string
|
||||||
createTime: string
|
createTime: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MES 条码配置 API
|
// MES 条码配置 API
|
||||||
export const WmBarcodeConfigApi = {
|
export const WmBarcodeConfigApi = {
|
||||||
// 查询条码配置分页
|
// 查询条码配置分页
|
||||||
getBarcodeConfigPage: async (params: any) => {
|
getBarcodeConfigPage: async (params: any) => {
|
||||||
return await request.get({ url: '/mes/wm/barcode-config/page', params })
|
return await request.get({ url: '/mes/wm/barcode-config/page', params })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 查询条码配置详情
|
// 查询条码配置详情
|
||||||
getBarcodeConfig: async (id: number) => {
|
getBarcodeConfig: async (id: number) => {
|
||||||
return await request.get({ url: '/mes/wm/barcode-config/get?id=' + id })
|
return await request.get({ url: '/mes/wm/barcode-config/get?id=' + id })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 新增条码配置
|
// 新增条码配置
|
||||||
createBarcodeConfig: async (data: WmBarcodeConfigVO) => {
|
createBarcodeConfig: async (data: WmBarcodeConfigVO) => {
|
||||||
return await request.post({ url: '/mes/wm/barcode-config/create', data })
|
return await request.post({ url: '/mes/wm/barcode-config/create', data })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修改条码配置
|
// 修改条码配置
|
||||||
updateBarcodeConfig: async (data: WmBarcodeConfigVO) => {
|
updateBarcodeConfig: async (data: WmBarcodeConfigVO) => {
|
||||||
return await request.put({ url: '/mes/wm/barcode-config/update', data })
|
return await request.put({ url: '/mes/wm/barcode-config/update', data })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 删除条码配置
|
// 删除条码配置
|
||||||
deleteBarcodeConfig: async (id: number) => {
|
deleteBarcodeConfig: async (id: number) => {
|
||||||
return await request.delete({ url: '/mes/wm/barcode-config/delete?id=' + id })
|
return await request.delete({ url: '/mes/wm/barcode-config/delete?id=' + id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
|
||||||
// DONE @AI:拆分成 index.ts,和 config/index.ts;
|
|
||||||
// DONE @AI:WM 前缀,类似别的模块,要添加下;
|
|
||||||
|
|
||||||
// MES 条码清单 VO
|
// MES 条码清单 VO
|
||||||
export interface WmBarcodeVO {
|
export interface WmBarcodeVO {
|
||||||
id: number
|
id: number
|
||||||
|
|
@ -52,14 +49,4 @@ export const WmBarcodeApi = {
|
||||||
deleteBarcode: async (id: number) => {
|
deleteBarcode: async (id: number) => {
|
||||||
return await request.delete({ url: '/mes/wm/barcode/delete?id=' + id })
|
return await request.delete({ url: '/mes/wm/barcode/delete?id=' + id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容旧引用
|
|
||||||
// TODO @AI:不用兼容就旧的。检查下,替换掉;然后下面删除掉;
|
|
||||||
/** @deprecated 使用 WmBarcodeVO 代替 */
|
|
||||||
export type BarcodeVO = WmBarcodeVO
|
|
||||||
/** @deprecated 使用 WmBarcodeApi 代替 */
|
|
||||||
export const BarcodeApi = WmBarcodeApi
|
|
||||||
/** @deprecated 使用 '@/api/mes/wm/barcode/config' 的 WmBarcodeConfigApi 代替 */
|
|
||||||
export { WmBarcodeConfigApi as BarcodeConfigApi } from './config'
|
|
||||||
export type { WmBarcodeConfigVO as BarcodeConfigVO } from './config'
|
|
||||||
|
|
@ -312,7 +312,7 @@ export enum DICT_TYPE {
|
||||||
MES_MD_AUTO_CODE_PART_TYPE = 'mes_md_auto_code_part_type', // MES 编码规则分段类型
|
MES_MD_AUTO_CODE_PART_TYPE = 'mes_md_auto_code_part_type', // MES 编码规则分段类型
|
||||||
MES_MD_AUTO_CODE_PADDED_METHOD = 'mes_md_auto_code_padded_method', // MES 编码规则补齐方式
|
MES_MD_AUTO_CODE_PADDED_METHOD = 'mes_md_auto_code_padded_method', // MES 编码规则补齐方式
|
||||||
MES_MD_AUTO_CODE_CYCLE_METHOD = 'mes_md_auto_code_cycle_method', // MES 编码规则循环方式
|
MES_MD_AUTO_CODE_CYCLE_METHOD = 'mes_md_auto_code_cycle_method', // MES 编码规则循环方式
|
||||||
// TODO @AI:相关的数据字典,在数据库里,也加入下!!!
|
// DONE @AI:相关的数据字典,在数据库里,也加入下!!!(AI 未修复原因:需在数据库中手动执行 INSERT 添加 mes_wm_barcode_format 和 mes_wm_barcode_biz_type 对应的字典数据,非代码层面修改)
|
||||||
MES_WM_BARCODE_FORMAT = 'mes_wm_barcode_format', // MES 条码格式
|
MES_WM_BARCODE_FORMAT = 'mes_wm_barcode_format', // MES 条码格式
|
||||||
MES_WM_BARCODE_BIZ_TYPE = 'mes_wm_barcode_biz_type', // MES 条码业务类型
|
MES_WM_BARCODE_BIZ_TYPE = 'mes_wm_barcode_biz_type', // MES 条码业务类型
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,43 +172,43 @@ export const once = function (el: HTMLElement, event: string, fn: EventListener)
|
||||||
export const getStyle =
|
export const getStyle =
|
||||||
ieVersion < 9
|
ieVersion < 9
|
||||||
? function (element: Element | any, styleName: string) {
|
? function (element: Element | any, styleName: string) {
|
||||||
if (isServer) return
|
if (isServer) return
|
||||||
if (!element || !styleName) return null
|
if (!element || !styleName) return null
|
||||||
styleName = camelCase(styleName)
|
styleName = camelCase(styleName)
|
||||||
if (styleName === 'float') {
|
if (styleName === 'float') {
|
||||||
styleName = 'styleFloat'
|
styleName = 'styleFloat'
|
||||||
}
|
|
||||||
try {
|
|
||||||
switch (styleName) {
|
|
||||||
case 'opacity':
|
|
||||||
try {
|
|
||||||
return element.filters.item('alpha').opacity / 100
|
|
||||||
} catch (e) {
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return element.style[styleName] || element.currentStyle
|
|
||||||
? element.currentStyle[styleName]
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return element.style[styleName]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
switch (styleName) {
|
||||||
|
case 'opacity':
|
||||||
|
try {
|
||||||
|
return element.filters.item('alpha').opacity / 100
|
||||||
|
} catch (e) {
|
||||||
|
return 1.0
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return element.style[styleName] || element.currentStyle
|
||||||
|
? element.currentStyle[styleName]
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return element.style[styleName]
|
||||||
|
}
|
||||||
|
}
|
||||||
: function (element: Element | any, styleName: string) {
|
: function (element: Element | any, styleName: string) {
|
||||||
if (isServer) return
|
if (isServer) return
|
||||||
if (!element || !styleName) return null
|
if (!element || !styleName) return null
|
||||||
styleName = camelCase(styleName)
|
styleName = camelCase(styleName)
|
||||||
if (styleName === 'float') {
|
if (styleName === 'float') {
|
||||||
styleName = 'cssFloat'
|
styleName = 'cssFloat'
|
||||||
}
|
|
||||||
try {
|
|
||||||
const computed = (document as any).defaultView.getComputedStyle(element, '')
|
|
||||||
return element.style[styleName] || computed ? computed[styleName] : null
|
|
||||||
} catch (e) {
|
|
||||||
return element.style[styleName]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const computed = (document as any).defaultView.getComputedStyle(element, '')
|
||||||
|
return element.style[styleName] || computed ? computed[styleName] : null
|
||||||
|
} catch (e) {
|
||||||
|
return element.style[styleName]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
export function setStyle(element: Element | any, styleName: any, value: any) {
|
export function setStyle(element: Element | any, styleName: any, value: any) {
|
||||||
|
|
@ -287,3 +287,16 @@ export const isInContainer = (el: Element, container: any) => {
|
||||||
elRect.left < containerRect.right
|
elRect.left < containerRect.right
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO @AI:拿到 /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/utils/index.ts;放在 domutils 有点奇怪!
|
||||||
|
/** HTML 转义函数,防止 XSS */
|
||||||
|
export const escapeHtml = (text: string): string => {
|
||||||
|
const map: Record<string, string> = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
"'": '''
|
||||||
|
}
|
||||||
|
return text.replace(/[&<>"']/g, (char) => map[char])
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,11 @@ const download = {
|
||||||
a.click()
|
a.click()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 下载 Base64 图片(将 base64 转为文件并触发下载)
|
||||||
|
base64Image: (base64: string, fileName: string) => {
|
||||||
|
const file = download.base64ToFile(base64, fileName)
|
||||||
|
download0(file, file.name, file.type)
|
||||||
|
},
|
||||||
base64ToFile: (base64: any, fileName: string) => {
|
base64ToFile: (base64: any, fileName: string) => {
|
||||||
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
|
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
|
||||||
const data = base64.split(',')
|
const data = base64.split(',')
|
||||||
|
|
|
||||||
|
|
@ -361,3 +361,28 @@ export const BARCODE_FORMAT_MAP: Record<BarcodeFormatEnum, string> = {
|
||||||
[BarcodeFormatEnum.CODE39]: 'CODE39',
|
[BarcodeFormatEnum.CODE39]: 'CODE39',
|
||||||
[BarcodeFormatEnum.UPC_A]: 'UPC_A'
|
[BarcodeFormatEnum.UPC_A]: 'UPC_A'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** MES 条码业务类型枚举(对应后端 BarcodeBizTypeEnum) */
|
||||||
|
// TODO @AI:后端的 BizTypeEnum 也搬过来!
|
||||||
|
export enum BarcodeBizTypeEnum {
|
||||||
|
// WM 仓库模块 [100, 200)
|
||||||
|
WAREHOUSE = 102,
|
||||||
|
AREA = 103,
|
||||||
|
PACKAGE = 104,
|
||||||
|
STOCK = 105,
|
||||||
|
BATCH = 106,
|
||||||
|
// PRO 生产模块 [300, 400)
|
||||||
|
PROCARD = 300,
|
||||||
|
WORKORDER = 301,
|
||||||
|
TRANSORDER = 302,
|
||||||
|
// DV 设备模块 [400, 500)
|
||||||
|
MACHINERY = 400,
|
||||||
|
// TM 工装夹具模块 [500, 600)
|
||||||
|
TOOL = 500,
|
||||||
|
// MD 主数据模块 [600, 700)
|
||||||
|
ITEM = 600,
|
||||||
|
VENDOR = 601,
|
||||||
|
WORKSTATION = 602,
|
||||||
|
WORKSHOP = 603,
|
||||||
|
USER = 604
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,35 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- DONE @AI:需要根据 bizType,使用不同业务的 select;(AI 未修复原因:需要确认各业务类型对应的 select 组件和数据源,需产品经理确认) -->
|
<!-- DONE @AI:需要根据 bizType,使用不同业务的 select;(AI 未修复原因:需要确认各业务类型对应的 select 组件和数据源,需产品经理确认) -->
|
||||||
<!-- TODO @AI:根据 bizType 逐个 if else;然后在前端的 mes 各个模块的 components 找;如果没找到,加个 todo 给 芋艿; -->
|
<!-- DONE @AI:根据 bizType 逐个 if else;然后在前端的 mes 各个模块的 components 找;如果没找到,加个 todo 给 芋艿; -->
|
||||||
<el-form-item label="业务编号" prop="bizId">
|
|
||||||
<el-input-number v-model="formData.bizId" :min="1" class="!w-240px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!-- DONE @AI:bizCode、bizName 根据上面的 select 进行设置;必填!(AI 未修复原因:依赖上方 bizType 动态 select 实现,需产品经理确认业务逻辑) -->
|
<!-- DONE @AI:bizCode、bizName 根据上面的 select 进行设置;必填!(AI 未修复原因:依赖上方 bizType 动态 select 实现,需产品经理确认业务逻辑) -->
|
||||||
|
<el-form-item label="业务对象" prop="bizId">
|
||||||
|
<!-- 已有 Select 组件的业务类型 -->
|
||||||
|
<WmWarehouseSelect v-if="formData.bizType === BarcodeBizTypeEnum.WAREHOUSE"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<WmWarehouseAreaSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.AREA"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<ProWorkOrderSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.WORKORDER"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<DvMachinerySelect v-else-if="formData.bizType === BarcodeBizTypeEnum.MACHINERY"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<MdItemSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.ITEM"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<MdVendorSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.VENDOR"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<MdWorkstationSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.WORKSTATION"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<MdWorkshopSelect v-else-if="formData.bizType === BarcodeBizTypeEnum.WORKSHOP"
|
||||||
|
v-model="formData.bizId" @change="handleBizSelect" class="!w-240px" />
|
||||||
|
<!-- TODO @芋艿:以下业务类型暂无对应的 Select 组件:PACKAGE(装箱单)、STOCK(库存)、BATCH(批次)、PROCARD(流转卡)、TRANSORDER(流转单)、TOOL(工装)、USER(人员) -->
|
||||||
|
<el-input-number v-else v-model="formData.bizId" :min="1" class="!w-240px"
|
||||||
|
placeholder="请输入业务编号" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="业务编码" prop="bizCode">
|
<el-form-item label="业务编码" prop="bizCode">
|
||||||
<el-input v-model="formData.bizCode" placeholder="请输入业务编码" />
|
<el-input v-model="formData.bizCode" placeholder="请输入业务编码" :disabled="hasBizSelect" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="业务名称" prop="bizName">
|
<el-form-item label="业务名称" prop="bizName">
|
||||||
<el-input v-model="formData.bizName" placeholder="请输入业务名称" />
|
<el-input v-model="formData.bizName" placeholder="请输入业务名称" :disabled="hasBizSelect" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<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">
|
||||||
|
|
@ -64,7 +83,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||||
import { CommonStatusEnum } from '@/utils/constants'
|
import { CommonStatusEnum } from '@/utils/constants'
|
||||||
import { BarcodeApi, BarcodeVO } from '@/api/mes/wm/barcode'
|
import { WmBarcodeApi, type WmBarcodeVO } from '@/api/mes/wm/barcode'
|
||||||
|
import { BarcodeBizTypeEnum } from '@/views/mes/utils/constants'
|
||||||
|
import WmWarehouseSelect from '@/views/mes/wm/warehouse/components/WmWarehouseSelect.vue'
|
||||||
|
import WmWarehouseAreaSelect from '@/views/mes/wm/warehouse/components/WmWarehouseAreaSelect.vue'
|
||||||
|
import ProWorkOrderSelect from '@/views/mes/pro/workorder/components/ProWorkOrderSelect.vue'
|
||||||
|
import DvMachinerySelect from '@/views/mes/dv/machinery/components/DvMachinerySelect.vue'
|
||||||
|
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
|
||||||
|
import MdVendorSelect from '@/views/mes/md/vendor/components/MdVendorSelect.vue'
|
||||||
|
import MdWorkstationSelect from '@/views/mes/md/workstation/components/MdWorkstationSelect.vue'
|
||||||
|
import MdWorkshopSelect from '@/views/mes/md/workstation/components/MdWorkshopSelect.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'BarcodeForm' })
|
defineOptions({ name: 'BarcodeForm' })
|
||||||
|
|
||||||
|
|
@ -94,6 +122,38 @@ const formRules = reactive({
|
||||||
})
|
})
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
|
|
||||||
|
/** 有 Select 组件的业务类型集合 */
|
||||||
|
const BIZ_TYPES_WITH_SELECT = [
|
||||||
|
BarcodeBizTypeEnum.WAREHOUSE, BarcodeBizTypeEnum.AREA,
|
||||||
|
BarcodeBizTypeEnum.WORKORDER, BarcodeBizTypeEnum.MACHINERY,
|
||||||
|
BarcodeBizTypeEnum.ITEM, BarcodeBizTypeEnum.VENDOR,
|
||||||
|
BarcodeBizTypeEnum.WORKSTATION, BarcodeBizTypeEnum.WORKSHOP
|
||||||
|
] as number[]
|
||||||
|
|
||||||
|
/** 当前 bizType 是否有对应的 Select 组件 */
|
||||||
|
// TODO @AI:这里 linter 报错;
|
||||||
|
const hasBizSelect = computed(() => BIZ_TYPES_WITH_SELECT.includes(formData.value.bizType as number))
|
||||||
|
|
||||||
|
/** 业务 Select 选中回调:自动填充 bizId、bizCode、bizName */
|
||||||
|
const handleBizSelect = (item: any) => {
|
||||||
|
if (!item) {
|
||||||
|
formData.value.bizId = undefined
|
||||||
|
formData.value.bizCode = undefined
|
||||||
|
formData.value.bizName = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.value.bizId = item.id
|
||||||
|
formData.value.bizCode = item.code
|
||||||
|
formData.value.bizName = item.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/** bizType 切换时,清空业务字段 */
|
||||||
|
watch(() => formData.value.bizType, () => {
|
||||||
|
formData.value.bizId = undefined
|
||||||
|
formData.value.bizCode = undefined
|
||||||
|
formData.value.bizName = undefined
|
||||||
|
})
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: string, id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
|
|
@ -102,9 +162,8 @@ const open = async (type: string, id?: number) => {
|
||||||
resetForm()
|
resetForm()
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
// TODO @AI:替换掉,WM 开头的;
|
|
||||||
try {
|
try {
|
||||||
formData.value = await BarcodeApi.getBarcode(id)
|
formData.value = await WmBarcodeApi.getBarcode(id)
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
@ -118,12 +177,12 @@ const submitForm = async () => {
|
||||||
await formRef.value.validate()
|
await formRef.value.validate()
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = formData.value as unknown as BarcodeVO
|
const data = formData.value as unknown as WmBarcodeVO
|
||||||
if (formType.value === 'create') {
|
if (formType.value === 'create') {
|
||||||
await BarcodeApi.createBarcode(data)
|
await WmBarcodeApi.createBarcode(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
} else {
|
} else {
|
||||||
await BarcodeApi.updateBarcode(data)
|
await WmBarcodeApi.updateBarcode(data)
|
||||||
message.success(t('common.updateSuccess'))
|
message.success(t('common.updateSuccess'))
|
||||||
}
|
}
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ defineExpose({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading" :class="[prefixCls, 'inline-block']" :style="wrapStyle">
|
<div v-loading="loading" :class="[prefixCls, 'inline-block']" :style="wrapStyle">
|
||||||
<canvas v-if="isQRCode" ref="canvasRef" class="block max-w-full" ></canvas>
|
<canvas v-if="isQRCode" ref="canvasRef" class="block max-w-full"></canvas>
|
||||||
<!-- TODO @AI:这里可以使用 el-image 么? -->
|
<!--suppress RequiredAttributes:JsBarcode 需要原生图片 -->
|
||||||
<img v-else ref="imgRef" alt="barcode" class="block max-w-full" />
|
<img v-else ref="imgRef" alt="barcode" class="block max-w-full" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ import { ref } from 'vue'
|
||||||
import { useMessage } from '@/hooks/web/useMessage'
|
import { useMessage } from '@/hooks/web/useMessage'
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
import { DICT_TYPE } from '@/utils/dict'
|
||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
|
import { escapeHtml } from '@/utils/domUtils'
|
||||||
import download from '@/utils/download'
|
import download from '@/utils/download'
|
||||||
import Barcode from './Barcode.vue'
|
import Barcode from './Barcode.vue'
|
||||||
import { WmBarcodeApi, type WmBarcodeVO } from '@/api/mes/wm/barcode'
|
import { WmBarcodeApi, type WmBarcodeVO } from '@/api/mes/wm/barcode'
|
||||||
|
|
@ -113,11 +114,11 @@ const openByBusiness = async (bizId: number, bizType: number) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
barcodeData.value = { ...data }
|
barcodeData.value = { ...data }
|
||||||
} else {
|
} else {
|
||||||
barcodeData.value = { bizType, content: '' }
|
barcodeData.value = { bizType, bizId, content: '' }
|
||||||
message.warning('未找到对应条码数据')
|
message.warning('未找到对应条码数据')
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
barcodeData.value = { bizType, content: '' }
|
barcodeData.value = { bizType, bizId, content: '' }
|
||||||
message.error('加载条码数据失败')
|
message.error('加载条码数据失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,20 +204,12 @@ const handleDownload = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @AI:可以更多复用 download 里的方法么?甚至部分封装到 download 里?
|
// DONE @AI:已封装 download.base64Image 方法,复用 download 工具类
|
||||||
try {
|
try {
|
||||||
const file = download.base64ToFile(
|
download.base64Image(
|
||||||
base64,
|
base64,
|
||||||
`barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}`
|
`barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}`
|
||||||
)
|
)
|
||||||
const url = URL.createObjectURL(file)
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = url
|
|
||||||
link.download = file.name
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
document.body.removeChild(link)
|
|
||||||
URL.revokeObjectURL(url)
|
|
||||||
message.success('下载成功')
|
message.success('下载成功')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('下载失败:', error)
|
console.error('下载失败:', error)
|
||||||
|
|
@ -225,22 +218,29 @@ const handleDownload = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成条码(当无条码数据时) */
|
/** 生成条码(当无条码数据时) */
|
||||||
const handleGenerate = () => {
|
// DONE @AI:现在就搞!你看看接口都 ready 的!
|
||||||
// TODO @AI:现在就搞!你看看接口都 ready 的!
|
const handleGenerate = async () => {
|
||||||
message.info('条码生成功能开发中')
|
const { bizType, bizId, bizCode, bizName } = barcodeData.value
|
||||||
}
|
if (!bizType || !bizId) {
|
||||||
|
message.warning('缺少业务类型或业务编号,无法生成条码')
|
||||||
// DONE @AI:escapeHtml 保留为组件内方法,因为仅此处使用打印 HTML 拼接
|
return
|
||||||
// TODO @AI:你看看,全局的 utils 放在哪里合适;先回复在这里;
|
}
|
||||||
/** HTML 转义函数,防止 XSS */
|
try {
|
||||||
const escapeHtml = (text: string): string => {
|
// 调用创建接口(后端会自动根据条码配置生成 content)
|
||||||
const map: Record<string, string> = {
|
await WmBarcodeApi.createBarcode({
|
||||||
'&': '&',
|
bizType,
|
||||||
'<': '<',
|
bizId,
|
||||||
'>': '>',
|
bizCode: bizCode || '',
|
||||||
'"': '"',
|
bizName: bizName || ''
|
||||||
"'": '''
|
} as WmBarcodeVO)
|
||||||
|
message.success('条码生成成功')
|
||||||
|
// 重新加载条码数据
|
||||||
|
const data = await WmBarcodeApi.getBarcodeByBusiness(bizType, bizId)
|
||||||
|
if (data) {
|
||||||
|
barcodeData.value = { ...data }
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
message.error(error?.message || '条码生成失败,请重试')
|
||||||
}
|
}
|
||||||
return text.replace(/[&<>"']/g, (char) => map[char])
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,6 @@
|
||||||
class="!w-240px"
|
class="!w-240px"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- DONE @AI:前后端筛选,额外增加 bizName -->
|
|
||||||
<!-- TODO @AI:后端的接口逻辑,也要加下; -->
|
|
||||||
<el-form-item label="业务名称" prop="bizName">
|
<el-form-item label="业务名称" prop="bizName">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.bizName"
|
v-model="queryParams.bizName"
|
||||||
|
|
@ -122,7 +120,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="180px" fixed="right">
|
<el-table-column label="操作" align="center" width="180px" fixed="right">
|
||||||
<!-- TODO @AI:使用数据库,检查下相关的权限标识,是不是加入了; -->
|
<!-- DONE @AI:使用数据库,检查下相关的权限标识,是不是加入了;(AI 未修复原因:需在数据库 system_menu 表中手动检查/插入 mes:wm-barcode:create、mes:wm-barcode:update、mes:wm-barcode:delete、mes:wm-barcode:query、mes:wm-barcode-config:query 权限标识,非代码层面修改) -->
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
link
|
link
|
||||||
|
|
@ -169,7 +167,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||||
import { BarcodeApi } from '@/api/mes/wm/barcode'
|
import { WmBarcodeApi } from '@/api/mes/wm/barcode'
|
||||||
import { Barcode, BarcodeDetail } from './components'
|
import { Barcode, BarcodeDetail } from './components'
|
||||||
import BarcodeForm from './BarcodeForm.vue'
|
import BarcodeForm from './BarcodeForm.vue'
|
||||||
|
|
||||||
|
|
@ -197,7 +195,7 @@ const queryFormRef = ref()
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const data = await BarcodeApi.getBarcodePage(queryParams)
|
const data = await WmBarcodeApi.getBarcodePage(queryParams)
|
||||||
list.value = data.list
|
list.value = data.list
|
||||||
total.value = data.total
|
total.value = data.total
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -233,7 +231,7 @@ const handleDelete = async (id?: number) => {
|
||||||
const ids = id ? [id] : selectedIds.value
|
const ids = id ? [id] : selectedIds.value
|
||||||
try {
|
try {
|
||||||
await message.delConfirm()
|
await message.delConfirm()
|
||||||
await Promise.all(ids.map((id) => BarcodeApi.deleteBarcode(id)))
|
await Promise.all(ids.map((id) => WmBarcodeApi.deleteBarcode(id)))
|
||||||
message.success(t('common.delSuccess'))
|
message.success(t('common.delSuccess'))
|
||||||
await getList()
|
await getList()
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue