✨ feat(mes): 添加条码相关组件和逻辑
新增条码格式枚举、条码生成组件及其相关 API,支持条码的创建、查看和配置功能。实现了条码的自动生成逻辑,并优化了条码配置管理界面,提升用户体验。 - 新增 Barcode 组件用于条码展示 - 实现条码生成和下载功能 - 添加条码配置管理功能pull/871/MERGE
parent
e275ef417e
commit
c12d7616f2
|
|
@ -53,6 +53,7 @@
|
|||
"element-plus": "2.11.1",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"highlight.js": "^11.9.0",
|
||||
"jsbarcode": "^3.12.3",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"jsoneditor": "^10.1.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@ importers:
|
|||
highlight.js:
|
||||
specifier: ^11.9.0
|
||||
version: 11.10.0
|
||||
jsbarcode:
|
||||
specifier: ^3.12.3
|
||||
version: 3.12.3
|
||||
jsencrypt:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2
|
||||
|
|
@ -3669,6 +3672,9 @@ packages:
|
|||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
||||
hasBin: true
|
||||
|
||||
jsbarcode@3.12.3:
|
||||
resolution: {integrity: sha512-CuHU9hC6dPsHF5oVFMo8NW76uQVjH4L22CsP4hW+dNnGywJHC/B0ThA1CTDVLnxKLrrpYdicBLnd2xsgTfRnvg==, tarball: https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.12.3.tgz}
|
||||
|
||||
jsencrypt@3.3.2:
|
||||
resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
|
||||
|
||||
|
|
@ -4603,7 +4609,7 @@ packages:
|
|||
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
||||
|
||||
source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
split2@4.2.0:
|
||||
|
|
@ -9023,6 +9029,8 @@ snapshots:
|
|||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
jsbarcode@3.12.3: {}
|
||||
|
||||
jsencrypt@3.3.2: {}
|
||||
|
||||
jsesc@3.0.2: {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="600px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<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)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<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)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- TODO @AI:需要根据 bizType,使用不同业务的 select; -->
|
||||
<el-form-item label="业务编号" prop="bizId">
|
||||
<el-input-number v-model="formData.bizId" :min="1" class="!w-240px" />
|
||||
</el-form-item>
|
||||
<!-- TODO @AI:bizCode、bizName 根据上面的 select 进行设置;必填!(后端校验也加下) -->
|
||||
<el-form-item label="业务编码" prop="bizCode">
|
||||
<el-input v-model="formData.bizCode" placeholder="请输入业务编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务名称" prop="bizName">
|
||||
<el-input v-model="formData.bizName" 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"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" type="textarea" 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 { 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 dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const formLoading = ref(false)
|
||||
const formType = ref('')
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
format: undefined,
|
||||
bizType: undefined,
|
||||
bizId: undefined,
|
||||
bizCode: '',
|
||||
bizName: '',
|
||||
status: 0,
|
||||
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' }]
|
||||
})
|
||||
const formRef = ref()
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = type === 'create' ? '新增条码' : '修改条码'
|
||||
formType.value = type
|
||||
resetForm()
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await BarcodeApi.getBarcode(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open })
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success'])
|
||||
const submitForm = async () => {
|
||||
await formRef.value.validate()
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as BarcodeVO
|
||||
if (formType.value === 'create') {
|
||||
await BarcodeApi.createBarcode(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await BarcodeApi.updateBarcode(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
format: undefined,
|
||||
bizType: undefined,
|
||||
bizId: undefined,
|
||||
bizCode: '',
|
||||
bizName: '',
|
||||
status: 0, // TODO @AI:枚举类;commonstatusenum;
|
||||
remark: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
<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)一种是目前这种 BarcodeData;2)在加一种是 bizId + bizType 组合,然后去加载 BarcodeData
|
||||
// TODO @AI:BarcodeData 去掉,直接使用 BarcodeVO 就好了;
|
||||
-->
|
||||
<Dialog title="查看条码" v-model="dialogVisible" width="500px" :close-on-click-modal="false">
|
||||
<div class="barcode-view-container">
|
||||
<!-- 条码显示区域 -->
|
||||
<div class="barcode-display">
|
||||
<div v-if="barcodeData.content" class="barcode-wrapper">
|
||||
<!-- TODO @AI:二维码不够大 -->
|
||||
<Barcode
|
||||
ref="barcodeRef"
|
||||
:content="barcodeData.content"
|
||||
:format="barcodeData.format"
|
||||
:width="300"
|
||||
: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-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>
|
||||
<el-descriptions-item label="条码内容" label-align="center" align="left">
|
||||
<el-tooltip :content="barcodeData.content" placement="top">
|
||||
<span class="content-text">{{ barcodeData.content }}</span>
|
||||
</el-tooltip>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="业务编码" label-align="center" align="left">
|
||||
{{ barcodeData.bizCode || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="业务名称" label-align="center" 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>
|
||||
<el-descriptions-item label="创建时间" label-align="center" align="left">
|
||||
{{ formatDate(barcodeData.createTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<!-- TODO @AI:如果没二维码的情况,需要支持【生成】 -->
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="handlePrint">
|
||||
<Icon icon="ep:printer" class="mr-5px" /> 打印
|
||||
</el-button>
|
||||
<el-button @click="handleDownload">
|
||||
<Icon icon="ep:download" class="mr-5px" /> 下载
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false">关 闭</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
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'
|
||||
|
||||
defineOptions({ name: 'BarcodeViewDialog' })
|
||||
|
||||
interface BarcodeData {
|
||||
id?: number
|
||||
format?: number
|
||||
bizType?: number
|
||||
content: string
|
||||
bizCode?: string
|
||||
bizName?: string
|
||||
status?: number
|
||||
createTime?: string
|
||||
}
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const barcodeRef = ref<InstanceType<typeof Barcode>>()
|
||||
const barcodeData = ref<BarcodeData>({
|
||||
format: undefined,
|
||||
bizType: undefined,
|
||||
content: '',
|
||||
bizCode: '',
|
||||
bizName: '',
|
||||
status: undefined,
|
||||
createTime: ''
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = (row: BarcodeData) => {
|
||||
dialogVisible.value = true
|
||||
barcodeData.value = { ...row }
|
||||
}
|
||||
defineExpose({ open })
|
||||
|
||||
/** 打印条码 */
|
||||
// TODO @AI:【晚点弄】打印可以在当前界面么?你先回复我;
|
||||
const handlePrint = () => {
|
||||
if (!barcodeRef.value) {
|
||||
message.warning('条码组件未加载')
|
||||
return
|
||||
}
|
||||
|
||||
const base64 = barcodeRef.value.getImageBase64?.()
|
||||
if (!base64) {
|
||||
message.warning('条码生成失败,无法打印')
|
||||
return
|
||||
}
|
||||
|
||||
// 创建打印窗口
|
||||
const printWindow = window.open('', '_blank')
|
||||
if (!printWindow) {
|
||||
message.error('无法打开打印窗口,请检查浏览器设置')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const html = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>打印条码</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; }
|
||||
body { font-family: Arial, sans-serif; padding: 20px; }
|
||||
.print-container { text-align: center; }
|
||||
.barcode-img { max-width: 100%; margin: 20px 0; }
|
||||
.info { margin-top: 20px; text-align: left; font-size: 12px; }
|
||||
.info p { margin: 5px 0; }
|
||||
@media print {
|
||||
body { padding: 0; }
|
||||
.print-container { padding: 20px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="print-container">
|
||||
<img src="${base64}" class="barcode-img" alt="条码" />
|
||||
<div class="info">
|
||||
<p><strong>业务编码:</strong> ${escapeHtml(barcodeData.value.bizCode || '')}</p>
|
||||
<p><strong>业务名称:</strong> ${escapeHtml(barcodeData.value.bizName || '')}</p>
|
||||
<p><strong>条码内容:</strong> ${escapeHtml(barcodeData.value.content || '')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
printWindow.document.write(html)
|
||||
printWindow.document.close()
|
||||
|
||||
// 延迟打印,确保内容加载完成
|
||||
printWindow.onload = () => {
|
||||
setTimeout(() => {
|
||||
printWindow.print()
|
||||
}, 500)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('打印失败:', error)
|
||||
message.error('打印失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
/** 下载条码 */
|
||||
// TODO @AI:下载有工具类的,看看复用下;download;
|
||||
const handleDownload = () => {
|
||||
if (!barcodeRef.value) {
|
||||
message.warning('条码组件未加载')
|
||||
return
|
||||
}
|
||||
|
||||
const base64 = barcodeRef.value.getImageBase64?.()
|
||||
if (!base64) {
|
||||
message.warning('条码生成失败,无法下载')
|
||||
return
|
||||
}
|
||||
|
||||
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 link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}.png`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
URL.revokeObjectURL(url)
|
||||
|
||||
message.success('下载成功')
|
||||
} catch (error) {
|
||||
console.error('下载失败:', error)
|
||||
message.error('下载失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
/** HTML 转义函数,防止 XSS */
|
||||
// TODO @AI:是不是搞成一个公共方法;
|
||||
const escapeHtml = (text: string): string => {
|
||||
const map: Record<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>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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)
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="业务类型" prop="bizType">
|
||||
<el-select
|
||||
v-model="queryParams.bizType"
|
||||
placeholder="请选择业务类型"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.MES_BARCODE_BIZ_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="业务编码" prop="bizCode">
|
||||
<el-input
|
||||
v-model="queryParams.bizCode"
|
||||
placeholder="请输入业务编码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- TODO @AI:前后端筛选,额外增加 bizName -->
|
||||
<el-form-item label="条码内容" prop="content">
|
||||
<el-input
|
||||
v-model="queryParams.content"
|
||||
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="['mes:wm-barcode:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="handleDelete()"
|
||||
:disabled="!selectedIds.length"
|
||||
v-hasPermi="['mes:wm-barcode:delete']"
|
||||
>
|
||||
<Icon icon="ep:delete" class="mr-5px" /> 删除
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleConfig"
|
||||
v-hasPermi="['mes:wm-barcode-config:query']"
|
||||
>
|
||||
<Icon icon="ep:setting" class="mr-5px" /> 条码设置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
|
||||
<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)">
|
||||
<Barcode
|
||||
v-if="scope.row.content"
|
||||
:content="scope.row.content"
|
||||
:format="scope.row.format"
|
||||
:width="120"
|
||||
:height="60"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="条码格式" align="center" prop="format">
|
||||
<template #default="scope">
|
||||
<!-- TODO @AI:MES_BARCODE_FORMAT => MES_WM_BARCODE_FORMAT -->
|
||||
<dict-tag :type="DICT_TYPE.MES_BARCODE_FORMAT" :value="scope.row.format" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="业务类型" align="center" prop="bizType">
|
||||
<!-- TODO @AI:MES_BARCODE_BIZ_TYPE => MES_WM_BARCODE_BIZ_TYPE -->
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.MES_BARCODE_BIZ_TYPE" :value="scope.row.bizType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="条码内容" align="center" prop="content" show-overflow-tooltip />
|
||||
<el-table-column label="业务编码" align="center" prop="bizCode" />
|
||||
<el-table-column label="业务名称" align="center" prop="bizName" show-overflow-tooltip />
|
||||
<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" width="180px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleView(scope.row)"
|
||||
v-hasPermi="['mes:wm-barcode:query']"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['mes:wm-barcode:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['mes:wm-barcode: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>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<BarcodeForm ref="formRef" @success="getList" />
|
||||
|
||||
<!-- 查看弹窗 -->
|
||||
<BarcodeViewDialog 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 BarcodeForm from './BarcodeForm.vue'
|
||||
import BarcodeViewDialog from './BarcodeViewDialog.vue'
|
||||
|
||||
defineOptions({ name: 'MesWmBarcode' })
|
||||
|
||||
const message = useMessage()
|
||||
const { t } = useI18n()
|
||||
const { push } = useRouter()
|
||||
|
||||
const loading = ref(true)
|
||||
const list = ref([])
|
||||
const total = ref(0)
|
||||
const selectedIds = ref<number[]>([])
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
bizType: undefined,
|
||||
bizCode: undefined,
|
||||
content: undefined
|
||||
})
|
||||
const queryFormRef = ref()
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await BarcodeApi.getBarcodePage(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 handleSelectionChange = (selection: any[]) => {
|
||||
selectedIds.value = selection.map((item) => item.id)
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id?: number) => {
|
||||
const ids = id ? [id] : selectedIds.value
|
||||
try {
|
||||
await message.delConfirm()
|
||||
await Promise.all(ids.map((id) => BarcodeApi.deleteBarcode(id)))
|
||||
message.success(t('common.delSuccess'))
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 查看条码 */
|
||||
const viewDialogRef = ref()
|
||||
const handleView = (row: any) => {
|
||||
viewDialogRef.value.open(row)
|
||||
}
|
||||
|
||||
/** 条码设置 */
|
||||
const handleConfig = () => {
|
||||
// TODO @AI:后续改成 name,方便路由调整!
|
||||
push('/mes/wm/barcode/config')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
// TODO @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>
|
||||
Loading…
Reference in New Issue