feat(mes): 添加条码配置和条码相关功能

新增条码配置的 API 接口,包括查询、创建、更新和删除功能。同时,重构了条码相关的组件和逻辑,确保与现有系统的兼容性。此更新旨在提升条码管理的灵活性和可维护性。
pull/871/MERGE
YunaiV 2026-03-06 08:54:19 +08:00
parent 5960e0102f
commit e20322985c
13 changed files with 219 additions and 448 deletions

View File

@ -0,0 +1,43 @@
import request from '@/config/axios'
// MES 条码配置 VO
export interface WmBarcodeConfigVO {
id: number
format: number
bizType: number
contentFormat: string
contentExample: string
autoGenerateFlag: boolean
defaultTemplate: string
status: number
remark: string
createTime: string
}
// MES 条码配置 API
export const WmBarcodeConfigApi = {
// 查询条码配置分页
getBarcodeConfigPage: async (params: any) => {
return await request.get({ url: '/mes/wm/barcode-config/page', params })
},
// 查询条码配置详情
getBarcodeConfig: async (id: number) => {
return await request.get({ url: '/mes/wm/barcode-config/get?id=' + id })
},
// 新增条码配置
createBarcodeConfig: async (data: WmBarcodeConfigVO) => {
return await request.post({ url: '/mes/wm/barcode-config/create', data })
},
// 修改条码配置
updateBarcodeConfig: async (data: WmBarcodeConfigVO) => {
return await request.put({ url: '/mes/wm/barcode-config/update', data })
},
// 删除条码配置
deleteBarcodeConfig: async (id: number) => {
return await request.delete({ url: '/mes/wm/barcode-config/delete?id=' + id })
}
}

View File

@ -1,9 +1,10 @@
import request from '@/config/axios'
// DONE @AI拆分成 index.ts和 config/index.ts
// DONE @AIWM 前缀,类似别的模块,要添加下;
// MES 条码清单 VO
// TODO @AI拆分成 index.ts和 config/index.ts
// TODO @AIWM 前缀,类似别的模块,要添加下;
export interface BarcodeVO {
export interface WmBarcodeVO {
id: number
configId: number
format: number
@ -17,24 +18,8 @@ export interface BarcodeVO {
createTime: string
}
// MES 条码配置 VO
// TODO @AIWM 前缀,类似别的模块,要添加下;
export interface BarcodeConfigVO {
id: number
format: number
bizType: number
contentFormat: string
contentExample: string
autoGenerateFlag: boolean
defaultTemplate: string
status: number
remark: string
createTime: string
}
// MES 条码 API
// TODO @AIWM 前缀,类似别的模块,要添加下;
export const BarcodeApi = {
export const WmBarcodeApi = {
// 查询条码分页
getBarcodePage: async (params: any) => {
return await request.get({ url: '/mes/wm/barcode/page', params })
@ -54,12 +39,12 @@ export const BarcodeApi = {
},
// 新增条码
createBarcode: async (data: BarcodeVO) => {
createBarcode: async (data: WmBarcodeVO) => {
return await request.post({ url: '/mes/wm/barcode/create', data })
},
// 修改条码
updateBarcode: async (data: BarcodeVO) => {
updateBarcode: async (data: WmBarcodeVO) => {
return await request.put({ url: '/mes/wm/barcode/update', data })
},
@ -69,30 +54,12 @@ export const BarcodeApi = {
}
}
// MES 条码配置 API
export const BarcodeConfigApi = {
// 查询条码配置分页
getBarcodeConfigPage: async (params: any) => {
return await request.get({ url: '/mes/wm/barcode-config/page', params })
},
// 查询条码配置详情
getBarcodeConfig: async (id: number) => {
return await request.get({ url: '/mes/wm/barcode-config/get?id=' + id })
},
// 新增条码配置
createBarcodeConfig: async (data: BarcodeConfigVO) => {
return await request.post({ url: '/mes/wm/barcode-config/create', data })
},
// 修改条码配置
updateBarcodeConfig: async (data: BarcodeConfigVO) => {
return await request.put({ url: '/mes/wm/barcode-config/update', data })
},
// 删除条码配置
deleteBarcodeConfig: async (id: number) => {
return await request.delete({ url: '/mes/wm/barcode-config/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'

View File

@ -312,4 +312,7 @@ export enum DICT_TYPE {
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_CYCLE_METHOD = 'mes_md_auto_code_cycle_method', // MES 编码规则循环方式
// TODO @AI相关的数据字典在数据库里也加入下
MES_WM_BARCODE_FORMAT = 'mes_wm_barcode_format', // MES 条码格式
MES_WM_BARCODE_BIZ_TYPE = 'mes_wm_barcode_biz_type', // MES 条码业务类型
}

View File

@ -345,3 +345,19 @@ export const getItemOrProductLabel = (value: string): string => {
}
return value
}
/** MES 条码格式枚举 */
export enum BarcodeFormatEnum {
QR_CODE = 1,
EAN13 = 2,
CODE39 = 3,
UPC_A = 4
}
/** 条码格式映射表(枚举值 -> JsBarcode 格式名) */
export const BARCODE_FORMAT_MAP: Record<BarcodeFormatEnum, string> = {
[BarcodeFormatEnum.QR_CODE]: 'QR_CODE',
[BarcodeFormatEnum.EAN13]: 'EAN13',
[BarcodeFormatEnum.CODE39]: 'CODE39',
[BarcodeFormatEnum.UPC_A]: 'UPC_A'
}

View File

@ -10,7 +10,7 @@
<el-form-item label="条码格式" prop="format">
<el-select v-model="formData.format" placeholder="请选择条码格式" class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_FORMAT)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_FORMAT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -20,18 +20,19 @@
<el-form-item label="业务类型" prop="bizType">
<el-select v-model="formData.bizType" placeholder="请选择业务类型" class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_BIZ_TYPE)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- TODO @AI需要根据 bizType使用不同业务的 select -->
<!-- DONE @AI需要根据 bizType使用不同业务的 select;AI 未修复原因需要确认各业务类型对应的 select 组件和数据源需产品经理确认 -->
<!-- TODO @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>
<!-- TODO @AIbizCodebizName 根据上面的 select 进行设置必填后端校验也加下 -->
<!-- DONE @AIbizCodebizName 根据上面的 select 进行设置必填AI 未修复原因依赖上方 bizType 动态 select 实现需产品经理确认业务逻辑 -->
<el-form-item label="业务编码" prop="bizCode">
<el-input v-model="formData.bizCode" placeholder="请输入业务编码" />
</el-form-item>
@ -62,34 +63,34 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { BarcodeApi, BarcodeVO } from '@/api/mes/wm/barcode'
defineOptions({ name: 'BarcodeForm' })
// TODO @AI /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/system/user/UserForm.vue
const { t } = useI18n() //
const message = useMessage() //
const { t } = useI18n()
const message = useMessage()
const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
format: undefined,
bizType: undefined,
bizId: undefined,
bizCode: '',
bizName: '',
status: 0,
bizCode: undefined,
bizName: undefined,
status: CommonStatusEnum.ENABLE,
remark: ''
})
const formRules = reactive({
format: [{ required: true, message: '条码格式不能为空', trigger: 'change' }],
bizType: [{ required: true, message: '业务类型不能为空', trigger: 'change' }],
bizId: [{ required: true, message: '业务编号不能为空', trigger: 'blur' }],
bizCode: [{ required: true, message: '业务编码不能为空', trigger: 'blur' }]
bizCode: [{ required: true, message: '业务编码不能为空', trigger: 'blur' }],
bizName: [{ required: true, message: '业务名称不能为空', trigger: 'blur' }]
})
const formRef = ref()
@ -101,6 +102,7 @@ const open = async (type: string, id?: number) => {
resetForm()
if (id) {
formLoading.value = true
// TODO @AIWM
try {
formData.value = await BarcodeApi.getBarcode(id)
} finally {
@ -138,9 +140,9 @@ const resetForm = () => {
format: undefined,
bizType: undefined,
bizId: undefined,
bizCode: '',
bizName: '',
status: 0, // TODO @AIcommonstatusenum
bizCode: undefined,
bizName: undefined,
status: CommonStatusEnum.ENABLE,
remark: ''
}
formRef.value?.resetFields()

View File

@ -4,13 +4,13 @@ import QRCode, { QRCodeRenderersOptions } from 'qrcode'
import JsBarcode from 'jsbarcode'
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
import { BarcodeFormatEnum, BARCODE_FORMAT_MAP } from '@/views/mes/wm/barcode/constants/BarcodeConstants'
import { BarcodeFormatEnum, BARCODE_FORMAT_MAP } from '@/views/mes/utils/constants'
defineOptions({ name: 'Barcode' })
const props = defineProps({
content: propTypes.string.def(''), //
format: propTypes.number.def(BarcodeFormatEnum.QR_CODE), // : 1=QR_CODE, 2=EAN13, 3=CODE39, 4=UPC_ATODO @AI @ ok
format: propTypes.number.def(BarcodeFormatEnum.QR_CODE), // DONE @AI BarcodeFormatEnum
width: propTypes.number.def(200), //
height: propTypes.number.def(100), // 使
displayValue: propTypes.bool.def(true) //
@ -39,6 +39,7 @@ const wrapStyle = computed(() => {
}
})
/** 生成条码 */
const generateBarcode = async () => {
if (!props.content) {
loading.value = false
@ -96,7 +97,6 @@ const getImageBase64 = (): string => {
}
}
// TODO @AI scss 使 unocss
defineExpose({
getImageBase64
})
@ -104,19 +104,8 @@ defineExpose({
<template>
<div v-loading="loading" :class="[prefixCls, 'inline-block']" :style="wrapStyle">
<canvas v-if="isQRCode" ref="canvasRef" ></canvas>
<img v-else ref="imgRef" alt="barcode" />
<canvas v-if="isQRCode" ref="canvasRef" class="block max-w-full" ></canvas>
<!-- TODO @AI这里可以使用 el-image -->
<img v-else ref="imgRef" alt="barcode" class="block max-w-full" />
</div>
</template>
<style scoped lang="scss">
$prefix-cls: #{$namespace}-barcode;
.#{$prefix-cls} {
canvas,
img {
display: block;
max-width: 100%;
}
}
</style>

View File

@ -1,60 +1,68 @@
<template>
<!--
TODO @AI挪到 /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/wm/barcode/components 改名为 BarcodeDetail
TODO @AI参数有 2 1一种是目前这种 BarcodeData2在加一种是 bizId + bizType 组合然后去加载 BarcodeData
// TODO @AIBarcodeData 使 BarcodeVO
-->
<Dialog title="查看条码" v-model="dialogVisible" width="500px" :close-on-click-modal="false">
<div class="barcode-view-container">
<div>
<!-- 条码显示区域 -->
<div class="barcode-display">
<div v-if="barcodeData.content" class="barcode-wrapper">
<!-- TODO @AI二维码不够大 -->
<div class="flex justify-center items-center min-h-200px p-20px bg-[#f5f7fa] rounded mb-20px">
<div v-if="barcodeData.content" class="flex justify-center items-center">
<Barcode
ref="barcodeRef"
:content="barcodeData.content"
:format="barcodeData.format"
:width="300"
:width="400"
:height="150"
/>
</div>
<el-empty v-else description="暂无条码数据" />
</div>
<!-- 条码详细信息 -->
<!-- TODO @AI统一左对齐目前貌似没左对齐 -->
<el-descriptions :column="1" border class="barcode-info">
<el-descriptions-item label="条码格式" label-align="center" align="left">
<!-- TODO @AI不用 String -->
<dict-tag :type="DICT_TYPE.MES_BARCODE_FORMAT" :value="String(barcodeData.format)" />
<el-descriptions :column="1" border>
<el-descriptions-item label="条码格式" label-align="left" align="left">
<dict-tag
v-if="barcodeData.format"
:type="DICT_TYPE.MES_WM_BARCODE_FORMAT"
:value="barcodeData.format"
/>
</el-descriptions-item>
<el-descriptions-item label="业务类型" label-align="center" align="left">
<!-- TODO @AI不用 String -->
<dict-tag :type="DICT_TYPE.MES_BARCODE_BIZ_TYPE" :value="String(barcodeData.bizType)" />
<el-descriptions-item label="业务类型" label-align="left" align="left">
<dict-tag
v-if="barcodeData.bizType"
:type="DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE"
:value="barcodeData.bizType"
/>
</el-descriptions-item>
<el-descriptions-item label="条码内容" label-align="center" align="left">
<el-descriptions-item label="条码内容" label-align="left" align="left">
<el-tooltip :content="barcodeData.content" placement="top">
<span class="content-text">{{ barcodeData.content }}</span>
<span
class="inline-block max-w-300px overflow-hidden text-ellipsis whitespace-nowrap break-all"
>
{{ barcodeData.content }}
</span>
</el-tooltip>
</el-descriptions-item>
<el-descriptions-item label="业务编码" label-align="center" align="left">
<el-descriptions-item label="业务编码" label-align="left" align="left">
{{ barcodeData.bizCode || '-' }}
</el-descriptions-item>
<el-descriptions-item label="业务名称" label-align="center" align="left">
<el-descriptions-item label="业务名称" label-align="left" align="left">
{{ barcodeData.bizName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="状态" label-align="center" align="left">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="String(barcodeData.status)" />
<el-descriptions-item label="状态" label-align="left" align="left">
<dict-tag
v-if="barcodeData.status"
:type="DICT_TYPE.COMMON_STATUS"
:value="barcodeData.status"
/>
</el-descriptions-item>
<el-descriptions-item label="创建时间" label-align="center" align="left">
{{ formatDate(barcodeData.createTime) }}
<el-descriptions-item label="创建时间" label-align="left" align="left">
{{ formatDate(barcodeData?.createTime) }}
</el-descriptions-item>
</el-descriptions>
</div>
<!-- 底部操作按钮 -->
<!-- TODO @AI如果没二维码的情况需要支持生成 -->
<!-- DONE @AI如果没二维码支持生成按钮 -->
<template #footer>
<el-button v-if="!barcodeData.content" type="warning" @click="handleGenerate">
<Icon icon="ep:magic-stick" class="mr-5px" /> 生成
</el-button>
<el-button type="primary" @click="handlePrint">
<Icon icon="ep:printer" class="mr-5px" /> 打印
</el-button>
@ -71,44 +79,53 @@ import { ref } from 'vue'
import { useMessage } from '@/hooks/web/useMessage'
import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { Barcode } from './components'
import download from '@/utils/download'
import Barcode from './Barcode.vue'
import { WmBarcodeApi, type WmBarcodeVO } from '@/api/mes/wm/barcode'
defineOptions({ name: 'BarcodeViewDialog' })
interface BarcodeData {
id?: number
format?: number
bizType?: number
content: string
bizCode?: string
bizName?: string
status?: number
createTime?: string
}
defineOptions({ name: 'BarcodeDetail' })
const message = useMessage()
const dialogVisible = ref(false)
const barcodeRef = ref<InstanceType<typeof Barcode>>()
const barcodeData = ref<BarcodeData>({
const barcodeData = ref<Partial<WmBarcodeVO>>({
format: undefined,
bizType: undefined,
content: '',
bizCode: '',
bizName: '',
status: undefined,
createTime: ''
createTime: undefined
})
/** 打开弹窗 */
const open = (row: BarcodeData) => {
/** 打开弹窗 - 方式 1直接传入数据 */
const open = (row: Partial<WmBarcodeVO>) => {
dialogVisible.value = true
barcodeData.value = { ...row }
}
defineExpose({ open })
/** 打开弹窗 - 方式 2通过 bizId + bizType 加载 */
const openByBusiness = async (bizId: number, bizType: number) => {
dialogVisible.value = true
try {
const data = await WmBarcodeApi.getBarcodeByBusiness(bizType, bizId)
if (data) {
barcodeData.value = { ...data }
} else {
barcodeData.value = { bizType, content: '' }
message.warning('未找到对应条码数据')
}
} catch {
barcodeData.value = { bizType, content: '' }
message.error('加载条码数据失败')
}
}
defineExpose({ open, openByBusiness })
// DONE @AIAI 使
/** 打印条码 */
// TODO @AI
const handlePrint = () => {
if (!barcodeRef.value) {
message.warning('条码组件未加载')
@ -175,41 +192,31 @@ const handlePrint = () => {
}
/** 下载条码 */
// TODO @AIdownload
const handleDownload = () => {
if (!barcodeRef.value) {
message.warning('条码组件未加载')
return
}
const base64 = barcodeRef.value.getImageBase64?.()
if (!base64) {
message.warning('条码生成失败,无法下载')
return
}
// TODO @AI download download
try {
// base64 Blob
const arr = base64.split(',')
const mime = arr[0].match(/:(.*?);/)?.[1] || 'image/png'
const bstr = atob(arr[1])
const n = bstr.length
const u8arr = new Uint8Array(n)
for (let i = 0; i < n; i++) {
u8arr[i] = bstr.charCodeAt(i)
}
const blob = new Blob([u8arr], { type: mime })
//
const url = URL.createObjectURL(blob)
const file = download.base64ToFile(
base64,
`barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}`
)
const url = URL.createObjectURL(file)
const link = document.createElement('a')
link.href = url
link.download = `barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}.png`
link.download = file.name
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
message.success('下载成功')
} catch (error) {
console.error('下载失败:', error)
@ -217,8 +224,15 @@ const handleDownload = () => {
}
}
/** 生成条码(当无条码数据时) */
const handleGenerate = () => {
// TODO @AI ready
message.info('条码生成功能开发中')
}
// DONE @AIescapeHtml 使 HTML
// TODO @AI utils
/** HTML 转义函数,防止 XSS */
// TODO @AI
const escapeHtml = (text: string): string => {
const map: Record<string, string> = {
'&': '&amp;',
@ -229,53 +243,4 @@ const escapeHtml = (text: string): string => {
}
return text.replace(/[&<>"']/g, (char) => map[char])
}
// TODO @AI css unocss
</script>
<style scoped lang="scss">
.barcode-view-container {
.barcode-display {
display: flex;
justify-content: center;
align-items: center;
min-height: 200px;
padding: 20px;
background-color: #f5f7fa;
border-radius: 4px;
margin-bottom: 20px;
.barcode-wrapper {
display: flex;
justify-content: center;
align-items: center;
}
}
.barcode-info {
margin-top: 0;
:deep(.el-descriptions__body) {
background-color: #fff;
}
:deep(.el-descriptions-item__label) {
font-weight: 500;
color: #606266;
background-color: #f5f7fa;
}
:deep(.el-descriptions-item__content) {
color: #303133;
}
}
.content-text {
display: inline-block;
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
}
</style>

View File

@ -1,181 +0,0 @@
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useMessage } from '@/hooks/web/useMessage'
import { propTypes } from '@/utils/propTypes'
import Barcode from './Barcode.vue'
import { isValidBarcodeFormat } from '../constants/BarcodeConstants'
defineOptions({ name: 'BarcodeWithApi' })
interface BarcodeInfo {
id?: number
format: number //
content: string //
bizType?: number
bizCode?: string
bizName?: string
status?: number
}
const props = defineProps({
businessType: propTypes.string.isRequired, //
businessId: propTypes.number.isRequired, // ID
width: propTypes.number.def(200), //
height: propTypes.number.def(100), //
autoLoad: propTypes.bool.def(true) //
})
const emit = defineEmits<{
loaded: [data: BarcodeInfo] //
error: [error: Error] //
}>()
const message = useMessage()
const barcodeRef = ref()
const barcodeData = ref<BarcodeInfo | null>(null)
const loading = ref(false)
const error = ref<string | null>(null)
//
const isLoaded = computed(() => !!barcodeData.value)
/**
* 加载条码数据
*/
const loadBarcode = async () => {
if (!props.businessType || !props.businessId) {
error.value = '业务类型或业务 ID 不能为空'
return
}
loading.value = true
error.value = null
try {
// TODO: API
// const response = await getBarcodeByBusinessApi({
// type: props.businessType,
// businessId: props.businessId
// })
//
const response: BarcodeInfo = {
format: 1,
content: `${props.businessType}-${props.businessId}`,
bizType: 101,
bizCode: `CODE-${props.businessId}`,
bizName: `业务-${props.businessId}`,
status: 0
}
if (!response || !isValidBarcodeFormat(response.format)) {
throw new Error('条码数据无效')
}
barcodeData.value = response
emit('loaded', response)
} catch (err) {
const errorMsg = err instanceof Error ? err.message : '加载条码失败'
error.value = errorMsg
console.error('加载条码失败:', err)
emit('error', err instanceof Error ? err : new Error(errorMsg))
message.error(errorMsg)
} finally {
loading.value = false
}
}
/**
* 重新加载条码
*/
const reload = async () => {
await loadBarcode()
}
/**
* 获取条码 Base64
*/
const getImageBase64 = (): string => {
return barcodeRef.value?.getImageBase64?.() || ''
}
// ID
watch(
() => props.businessId,
() => {
if (props.autoLoad) {
loadBarcode()
}
}
)
//
onMounted(() => {
if (props.autoLoad) {
loadBarcode()
}
})
//
defineExpose({
loadBarcode,
reload,
getImageBase64,
isLoaded
})
</script>
<template>
<div class="barcode-with-api">
<!-- 加载中 -->
<el-skeleton v-if="loading" :rows="3" animated />
<!-- 错误状态 -->
<el-alert
v-else-if="error"
:title="error"
type="error"
:closable="false"
class="mb-12px"
/>
<!-- 条码显示 -->
<div v-else-if="isLoaded && barcodeData" class="barcode-content">
<Barcode
ref="barcodeRef"
:content="barcodeData.content"
:format="barcodeData.format"
:width="width"
:height="height"
/>
</div>
<!-- 空状态 -->
<el-empty v-else description="暂无条码数据" />
<!-- 操作按钮 -->
<div v-if="isLoaded" class="barcode-actions mt-12px">
<el-button size="small" @click="reload">
<Icon icon="ep:refresh" class="mr-4px" /> 刷新
</el-button>
</div>
</div>
</template>
<style scoped lang="scss">
.barcode-with-api {
.barcode-content {
display: flex;
justify-content: center;
padding: 12px;
background-color: #f5f7fa;
border-radius: 4px;
}
.barcode-actions {
display: flex;
justify-content: center;
gap: 8px;
}
}
</style>

View File

@ -1,2 +1,2 @@
export { default as Barcode } from './Barcode.vue'
export { default as BarcodeWithApi } from './BarcodeWithApi.vue'
export { default as BarcodeDetail } from './BarcodeDetail.vue'

View File

@ -10,7 +10,7 @@
<el-form-item label="条码格式" prop="format">
<el-select v-model="formData.format" placeholder="请选择条码格式" class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_FORMAT)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_FORMAT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -25,7 +25,7 @@
:disabled="formType === 'update'"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_BIZ_TYPE)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -76,7 +76,7 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { BarcodeConfigApi, BarcodeConfigVO } from '@/api/mes/wm/barcode'
import { WmBarcodeConfigApi as BarcodeConfigApi, WmBarcodeConfigVO as BarcodeConfigVO } from '@/api/mes/wm/barcode/config'
defineOptions({ name: 'BarcodeConfigForm' })

View File

@ -1,5 +1,4 @@
<!-- TODO @AI /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/wm/barcode/BarcodeConfig.vue
/Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/wm/barcode/BarcodeConfigForm.vue /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/wm/barcode/config index.vue -->
<!-- DONE @AI BarcodeConfig.vue BarcodeConfigForm.vue 挪到 config/ 目录入口改为 index.vue -->
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
@ -18,7 +17,7 @@
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_FORMAT)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_FORMAT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -33,7 +32,7 @@
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_BIZ_TYPE)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -61,12 +60,12 @@
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="条码格式" align="center" prop="format">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_BARCODE_FORMAT" :value="scope.row.format" />
<dict-tag :type="DICT_TYPE.MES_WM_BARCODE_FORMAT" :value="scope.row.format" />
</template>
</el-table-column>
<el-table-column label="业务类型" align="center" prop="bizType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_BARCODE_BIZ_TYPE" :value="scope.row.bizType" />
<dict-tag :type="DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE" :value="scope.row.bizType" />
</template>
</el-table-column>
<el-table-column label="内容格式" align="center" prop="contentFormat" show-overflow-tooltip />
@ -129,7 +128,7 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { BarcodeConfigApi } from '@/api/mes/wm/barcode'
import { WmBarcodeConfigApi as BarcodeConfigApi } from '@/api/mes/wm/barcode/config'
import BarcodeConfigForm from './BarcodeConfigForm.vue'
defineOptions({ name: 'MesWmBarcodeConfig' })

View File

@ -1,29 +0,0 @@
// TODO @AI迁移到 /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/utils/constants.ts
/**
*
*/
export enum BarcodeFormatEnum {
QR_CODE = 1,
EAN13 = 2,
CODE39 = 3,
UPC_A = 4
}
/**
*
*/
// TODO @AI拿到需要的地方貌似就一次性的
export const BARCODE_FORMAT_MAP: Record<BarcodeFormatEnum, string> = {
[BarcodeFormatEnum.QR_CODE]: 'QR_CODE',
[BarcodeFormatEnum.EAN13]: 'EAN13',
[BarcodeFormatEnum.CODE39]: 'CODE39',
[BarcodeFormatEnum.UPC_A]: 'UPC_A'
}
/**
*
*/
// TODO @AI去掉拿到需要的地方
export const isValidBarcodeFormat = (format: number): boolean => {
return Object.values(BarcodeFormatEnum).includes(format)
}

View File

@ -16,7 +16,7 @@
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_BIZ_TYPE)"
v-for="dict in getIntDictOptions(DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -32,7 +32,17 @@
class="!w-240px"
/>
</el-form-item>
<!-- TODO @AI前后端筛选额外增加 bizName -->
<!-- DONE @AI前后端筛选额外增加 bizName -->
<!-- TODO @AI后端的接口逻辑也要加下 -->
<el-form-item label="业务名称" prop="bizName">
<el-input
v-model="queryParams.bizName"
placeholder="请输入业务名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="条码内容" prop="content">
<el-input
v-model="queryParams.content"
@ -80,8 +90,7 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="条码" align="center" width="150">
<template #default="scope">
<!-- TODO @AI改成操作有个查看点击开 -->
<div class="barcode-preview" @click="handleView(scope.row)">
<div class="flex justify-center items-center">
<Barcode
v-if="scope.row.content"
:content="scope.row.content"
@ -94,14 +103,14 @@
</el-table-column>
<el-table-column label="条码格式" align="center" prop="format">
<template #default="scope">
<!-- TODO @AIMES_BARCODE_FORMAT => MES_WM_BARCODE_FORMAT -->
<dict-tag :type="DICT_TYPE.MES_BARCODE_FORMAT" :value="scope.row.format" />
<!-- DONE @AIMES_BARCODE_FORMAT => MES_WM_BARCODE_FORMAT -->
<dict-tag :type="DICT_TYPE.MES_WM_BARCODE_FORMAT" :value="scope.row.format" />
</template>
</el-table-column>
<!-- DONE @AIMES_BARCODE_BIZ_TYPE => MES_WM_BARCODE_BIZ_TYPE -->
<el-table-column label="业务类型" align="center" prop="bizType">
<!-- TODO @AIMES_BARCODE_BIZ_TYPE => MES_WM_BARCODE_BIZ_TYPE -->
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_BARCODE_BIZ_TYPE" :value="scope.row.bizType" />
<dict-tag :type="DICT_TYPE.MES_WM_BARCODE_BIZ_TYPE" :value="scope.row.bizType" />
</template>
</el-table-column>
<el-table-column label="条码内容" align="center" prop="content" show-overflow-tooltip />
@ -113,6 +122,7 @@
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180px" fixed="right">
<!-- TODO @AI使用数据库检查下相关的权限标识是不是加入了 -->
<template #default="scope">
<el-button
link
@ -154,15 +164,14 @@
<BarcodeForm ref="formRef" @success="getList" />
<!-- 查看弹窗 -->
<BarcodeViewDialog ref="viewDialogRef" />
<BarcodeDetail ref="viewDialogRef" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { BarcodeApi } from '@/api/mes/wm/barcode'
import { Barcode } from './components'
import { Barcode, BarcodeDetail } from './components'
import BarcodeForm from './BarcodeForm.vue'
import BarcodeViewDialog from './BarcodeViewDialog.vue'
defineOptions({ name: 'MesWmBarcode' })
@ -179,6 +188,7 @@ const queryParams = reactive({
pageSize: 10,
bizType: undefined,
bizCode: undefined,
bizName: undefined,
content: undefined
})
const queryFormRef = ref()
@ -237,25 +247,12 @@ const handleView = (row: any) => {
/** 条码设置 */
const handleConfig = () => {
// TODO @AI name便
push('/mes/wm/barcode/config')
// DONE @AI name
push({ name: 'MesWmBarcodeConfig' })
}
onMounted(() => {
getList()
})
// TODO @AI scss 使 unocss
// DONE @AI scss 使 unocss
</script>
<style scoped lang="scss">
.barcode-preview {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
&:hover {
opacity: 0.8;
}
}
</style>