黄伟杰 2 weeks ago
commit cdaf1e54df

@ -1,4 +1,4 @@
import request from '@/config/axios' import request from '@/config/axios'
// 打印机配置 VO // 打印机配置 VO
export interface ConfigVO { export interface ConfigVO {
@ -7,6 +7,9 @@ export interface ConfigVO {
systemPrinterName: string // 系统打印机名称,关联下拉选项 systemPrinterName: string // 系统打印机名称,关联下拉选项
isDefault: boolean // 是否默认0-否1-是 isDefault: boolean // 是否默认0-否1-是
isEnabled: boolean // 是否启用0-禁用1-启用 isEnabled: boolean // 是否启用0-禁用1-启用
businessScenarioCode: string // 业务场景编码
businessScenario: string // 业务场景(字典标签)
scenarioCount: number // 场景数
remark: string // 备注,记录打印机用途说明,用户不可修改 remark: string // 备注,记录打印机用途说明,用户不可修改
createdAt: Date // 创建时间 createdAt: Date // 创建时间
updatedAt: Date // 更新时间 updatedAt: Date // 更新时间

@ -1,4 +1,4 @@
<template> <template>
<div class="qrcode-action-card"> <div class="qrcode-action-card">
<el-image <el-image
v-if="imageUrl" v-if="imageUrl"
@ -40,6 +40,8 @@ import HiprintPreviewDialog from '@/components/HiprintPreviewDialog/index.vue'
import { createImageViewer } from '@/components/ImageViewer' import { createImageViewer } from '@/components/ImageViewer'
import { ElLoading } from 'element-plus' import { ElLoading } from 'element-plus'
import { getSimpleDictDataList } from '@/api/system/dict/dict.data' import { getSimpleDictDataList } from '@/api/system/dict/dict.data'
import { ConfigApi } from '@/api/mes/printconfig'
import { autoConnect, defaultElementTypeProvider, hiwebSocket, hiprint } from 'vue-plugin-hiprint'
const { t } = useI18n() const { t } = useI18n()
const message = useMessage() const message = useMessage()
@ -68,6 +70,7 @@ const props = withDefaults(
templateJson?: any templateJson?: any
printData?: Record<string, any> printData?: Record<string, any>
printTemplateType?: string | number printTemplateType?: string | number
businessScene?: string
}>(), }>(),
{ {
imageUrl: '', imageUrl: '',
@ -91,7 +94,8 @@ const props = withDefaults(
templateJsonUrl: '', templateJsonUrl: '',
templateJson: undefined, templateJson: undefined,
printData: () => ({}), printData: () => ({}),
printTemplateType: undefined printTemplateType: undefined,
businessScene: ''
} }
) )
@ -110,6 +114,17 @@ type TemplateFieldMap = {
let printTemplateDictCache: any[] | undefined let printTemplateDictCache: any[] | undefined
// ========== ==========
let hiprintInited = false
const clientConnected = ref(false)
const clientConnecting = ref(false)
const clientPrinting = ref(false)
const clientHostStorageKey = 'hiprint-client-host'
const defaultClientHost = 'http://192.168.2.58:17521'
const clientHost = ref(localStorage.getItem(clientHostStorageKey) || defaultClientHost)
const selectedPrinter = ref('')
const printerList = ref<Array<{ name: string; [key: string]: any }>>([])
const showActionMask = computed(() => props.showPreview || props.showPrint || props.showRefresh) const showActionMask = computed(() => props.showPreview || props.showPrint || props.showRefresh)
const parseTemplateFieldMap = (remark: any): TemplateFieldMap | undefined => { const parseTemplateFieldMap = (remark: any): TemplateFieldMap | undefined => {
@ -331,6 +346,52 @@ const replaceTemplateValues = (templateJson: any, printData: Record<string, any>
} }
} }
// ========== ==========
const getHiwebSocket = () => {
return ((hiwebSocket as any) || (window as any).hiwebSocket) as any
}
const normalizeClientHost = () => {
const host = clientHost.value.trim()
if (!host) return defaultClientHost
if (/^https?:\/\//i.test(host)) return host
return 'http://' + host
}
const ensureHiprintInit = () => {
if (hiprintInited) return
hiprint.init({
host: normalizeClientHost(),
providers: [defaultElementTypeProvider()]
})
hiprintInited = true
}
const syncClientState = (printersFromCallback?: Array<{ name: string; [key: string]: any }>) => {
const socket = getHiwebSocket()
clientConnected.value = !!socket?.opened
const printers = printersFromCallback || socket?.printerList || []
printerList.value = Array.isArray(printers) ? printers : []
}
const connectClient = () => {
ensureHiprintInit()
const socket = getHiwebSocket()
let host = normalizeClientHost()
clientHost.value = host
localStorage.setItem(clientHostStorageKey, host)
if (socket?.host !== host) {
socket?.stop?.()
socket.host = host
}
clientConnecting.value = true
autoConnect((status: boolean) => {
clientConnecting.value = false
clientConnected.value = !!status
syncClientState()
})
}
const handlePrint = async () => { const handlePrint = async () => {
if (!props.imageUrl || !props.showPrint) return if (!props.imageUrl || !props.showPrint) return
@ -368,6 +429,55 @@ const handlePrint = async () => {
templateJson = buildQrcodeTemplateJson(props.imageUrl, printData, imageWidth, imageHeight, paperHeight, templateFieldMap) templateJson = buildQrcodeTemplateJson(props.imageUrl, printData, imageWidth, imageHeight, paperHeight, templateFieldMap)
} }
// businessScene
if (props.businessScene) {
try {
const pageRes = await ConfigApi.getConfigPage({
pageNo: 1,
pageSize: 100,
businessScenario: props.businessScene
})
const configs = pageRes?.list || []
if (!configs.length) {
message.warning('未找到匹配业务场景「' + props.businessScene + '」的打印机配置')
return
}
const printerConfig = configs[0]
const printerName = printerConfig.systemPrinterName
ensureHiprintInit()
syncClientState()
if (!clientConnected.value) {
connectClient()
message.warning('正在连接本地打印客户端,请稍后重试')
return
}
const hiprintTmpl = new hiprint.PrintTemplate({ template: templateJson })
hiprintTmpl.on('printSuccess', () => {
message.success('打印已发送到: ' + printerName)
})
hiprintTmpl.on('printError', (err: any) => {
message.error(err?.msg || err?.message || '打印失败')
})
clientPrinting.value = true
try {
hiprintTmpl.print2(printData, {
printer: printerName,
title: props.printTitle
})
} finally {
clientPrinting.value = false
}
} catch (error) {
console.error('打印机配置查询或打印失败', error)
message.error('打印机配置查询或打印失败')
}
return
}
const paperSize = templateJson?.panels?.[0] ? { const paperSize = templateJson?.panels?.[0] ? {
width: templateJson.panels[0].width, width: templateJson.panels[0].width,
height: templateJson.panels[0].height height: templateJson.panels[0].height

@ -1,4 +1,4 @@
export default { export default {
common: { common: {
loading: 'Loading...', loading: 'Loading...',
inputText: 'Please input', inputText: 'Please input',
@ -3373,7 +3373,11 @@ export default {
placeholderHostName: 'Please input host name', placeholderHostName: 'Please input host name',
placeholderSystemPrinterName: 'Please input printer name', placeholderSystemPrinterName: 'Please input printer name',
placeholderRemark: 'Please input printer remark', placeholderRemark: 'Please input printer remark',
testPrint:'Test Print' businessScenarioCode:'Biz Scenario Code',
businessScenario:'Biz Scenario',
scenarioCount:'Scenario Count',
placeholderBusinessScenario:'Please select biz scenario',
testPrint:'Test Print'
} }
}, },
QualityManagement: { QualityManagement: {

@ -1,4 +1,4 @@
export default { export default {
common: { common: {
loading: '加载中...', loading: '加载中...',
inputText: '请输入', inputText: '请输入',
@ -2866,6 +2866,10 @@ export default {
validatorTypeRequired: '模板类型不能为空', validatorTypeRequired: '模板类型不能为空',
design: '配置', design: '配置',
designTitle: '模板配置', designTitle: '模板配置',
businessScenarioCode:'业务场景编码',
businessScenario:'业务场景',
scenarioCount:'场景数',
placeholderBusinessScenario:'请选择业务场景',
testPrint:'测试打印' testPrint:'测试打印'
} }
}, },

@ -1,4 +1,4 @@
/** /**
* *
*/ */
import { useDictStoreWithOut } from '@/store/modules/dict' import { useDictStoreWithOut } from '@/store/modules/dict'
@ -297,6 +297,8 @@ export enum DICT_TYPE {
IOT_DEVICE_ATTRIBUTE_UNIT = "iot_device_attribute_unit", IOT_DEVICE_ATTRIBUTE_UNIT = "iot_device_attribute_unit",
IOT_ALARM_REGISTRATION = "alarm_registration", IOT_ALARM_REGISTRATION = "alarm_registration",
MES_BUSINESS_SCENARIO = "mes_business_scenario",
PRIMARY_FLAG = "primary_flag", PRIMARY_FLAG = "primary_flag",
IS_DEFAULT = 'is_default', // 是否默认 IS_DEFAULT = 'is_default', // 是否默认

@ -1,4 +1,4 @@
<template> <template>
<div ref="detailPageRef" class="device-ledger-detail-page"> <div ref="detailPageRef" class="device-ledger-detail-page">
<ContentWrap> <ContentWrap>
<div v-loading="detailLoading" class="device-ledger-detail-body"> <div v-loading="detailLoading" class="device-ledger-detail-body">
@ -157,6 +157,7 @@
<span class="device-media-label">{{ t('EquipmentManagement.EquipmentLedger.qrcode') }}</span> <span class="device-media-label">{{ t('EquipmentManagement.EquipmentLedger.qrcode') }}</span>
<div class="device-media-code"> <div class="device-media-code">
<QrcodeActionCard :image-url="formData.qrcodeUrl" :print-id="formData.id" <QrcodeActionCard :image-url="formData.qrcodeUrl" :print-id="formData.id"
business-scene="设备二维码打印"
:print-title="`${formData.deviceName || 'Device'} QR Code`" :print-paper-width="80" :print-paper-height="80" :print-title="`${formData.deviceName || 'Device'} QR Code`" :print-paper-width="80" :print-paper-height="80"
:print-max-width="220" :empty-text="t('EquipmentManagement.EquipmentLedger.qrcodeEmpty')" :print-max-width="220" :empty-text="t('EquipmentManagement.EquipmentLedger.qrcodeEmpty')"
:error-text="t('EquipmentManagement.EquipmentLedger.qrcodeLoadError')" :error-text="t('EquipmentManagement.EquipmentLedger.qrcodeLoadError')"

@ -1,4 +1,4 @@
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form <el-form
ref="formRef" ref="formRef"
@ -33,6 +33,29 @@
<el-form-item :label="t('TemplateManagement.PrintConfig.isEnabled')" prop="isEnabled"> <el-form-item :label="t('TemplateManagement.PrintConfig.isEnabled')" prop="isEnabled">
<el-switch v-model="formData.isEnabled" /> <el-switch v-model="formData.isEnabled" />
</el-form-item> </el-form-item>
<el-form-item :label="t('TemplateManagement.PrintConfig.businessScenario')" prop="businessScenario">
<el-select
v-model="formData.businessScenario"
multiple
clearable
filterable
:placeholder="t('TemplateManagement.PrintConfig.placeholderBusinessScenario')"
style="width:100%"
>
<el-option
v-for="dict in businessScenarioOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('TemplateManagement.PrintConfig.businessScenarioCode')" prop="businessScenarioCode">
<el-input v-model="formData.businessScenarioCode" :disabled="true" placeholder="选择业务场景后自动回填" />
</el-form-item>
<el-form-item :label="t('TemplateManagement.PrintConfig.scenarioCount')" prop="scenarioCount">
<el-input-number v-model="formData.scenarioCount" :disabled="true" :min="0" style="width: 200px" />
</el-form-item>
<el-form-item :label="t('TemplateManagement.PrintConfig.remark')" prop="remark"> <el-form-item :label="t('TemplateManagement.PrintConfig.remark')" prop="remark">
<el-input v-model="formData.remark" :placeholder="t('TemplateManagement.PrintConfig.placeholderRemark')" /> <el-input v-model="formData.remark" :placeholder="t('TemplateManagement.PrintConfig.placeholderRemark')" />
</el-form-item> </el-form-item>
@ -46,6 +69,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ConfigApi, ConfigVO } from '@/api/mes/printconfig/index' import { ConfigApi, ConfigVO } from '@/api/mes/printconfig/index'
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { import {
autoConnect, autoConnect,
defaultElementTypeProvider, defaultElementTypeProvider,
@ -68,10 +92,26 @@ const formData = ref({
systemPrinterName: undefined, systemPrinterName: undefined,
isDefault: false, isDefault: false,
isEnabled: true, isEnabled: true,
businessScenario: [],
businessScenarioCode: undefined,
scenarioCount: 0,
remark: undefined, remark: undefined,
createdAt: undefined, createdAt: undefined,
updatedAt: undefined, updatedAt: undefined,
}) })
const businessScenarioOptions = computed(() => getStrDictOptions(DICT_TYPE.MES_BUSINESS_SCENARIO))
// watch businessScenario multi-select, auto-fill code and count
watch(() => formData.value.businessScenario, (val) => {
if (val && val.length > 0) {
formData.value.businessScenarioCode = val.join(',')
formData.value.scenarioCount = val.length
} else {
formData.value.businessScenarioCode = undefined
formData.value.scenarioCount = 0
}
}, { deep: true })
const formRules = reactive({ const formRules = reactive({
hostName: [{ required: false, message: '主机名如PACKING-PC-01不可修改不能为空', trigger: 'blur' }], hostName: [{ required: false, message: '主机名如PACKING-PC-01不可修改不能为空', trigger: 'blur' }],
systemPrinterName: [{ required: true, message: '系统打印机名称,关联下拉选项不能为空', trigger: 'blur' }], systemPrinterName: [{ required: true, message: '系统打印机名称,关联下拉选项不能为空', trigger: 'blur' }],
@ -118,7 +158,12 @@ const open = async (type: string, host: string, id?: number) => {
if (id) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await ConfigApi.getConfig(id) const data = await ConfigApi.getConfig(id)
formData.value = data
if (data.businessScenarioCode) {
formData.value.businessScenario = data.businessScenarioCode.split(',')
formData.value.scenarioCount = formData.value.businessScenario.length
}
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
@ -134,6 +179,13 @@ const submitForm = async () => {
// //
formLoading.value = true formLoading.value = true
try { try {
//
if (formData.value.businessScenario && formData.value.businessScenario.length > 0) {
const dictMap = new Map(businessScenarioOptions.value.map(d => [d.value, d.label]))
formData.value.businessScenario = formData.value.businessScenario.map((v: string) => dictMap.get(v) || v).join(',')
} else {
formData.value.businessScenario = undefined
}
const data = formData.value as unknown as ConfigVO const data = formData.value as unknown as ConfigVO
if (formType.value === 'create') { if (formType.value === 'create') {
await ConfigApi.createConfig(data) await ConfigApi.createConfig(data)
@ -301,6 +353,9 @@ const resetForm = () => {
systemPrinterName: undefined, systemPrinterName: undefined,
isDefault: false, isDefault: false,
isEnabled: true, isEnabled: true,
businessScenario: [],
businessScenarioCode: undefined,
scenarioCount: 0,
remark: undefined, remark: undefined,
createdAt: undefined, createdAt: undefined,
updatedAt: undefined, updatedAt: undefined,

@ -74,17 +74,20 @@
<!-- <el-table-column label="主键ID" align="center" prop="id" />--> <!-- <el-table-column label="主键ID" align="center" prop="id" />-->
<!-- <el-table-column type="selection" width="55" fixed="left" reserve-selection />--> <!-- <el-table-column type="selection" width="55" fixed="left" reserve-selection />-->
<el-table-column :label="t('TemplateManagement.PrintConfig.hostName')" align="center" prop="hostName" /> <el-table-column :label="t('TemplateManagement.PrintConfig.hostName')" align="center" prop="hostName" />
<el-table-column :label="t('TemplateManagement.PrintConfig.systemPrinterName')" align="center" prop="systemPrinterName" /> <el-table-column :label="t('TemplateManagement.PrintConfig.systemPrinterName')" align="center" prop="systemPrinterName" min-width="180px"/>
<el-table-column :label="t('TemplateManagement.PrintConfig.defaultStatus')" align="center" prop="isDefault" > <el-table-column :label="t('TemplateManagement.PrintConfig.defaultStatus')" align="center" prop="isDefault" width="90px">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.IS_DEFAULT" :value="scope.row.isDefault" /> <dict-tag :type="DICT_TYPE.IS_DEFAULT" :value="scope.row.isDefault" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="t('TemplateManagement.PrintConfig.isEnabled')" align="center" prop="isEnabled" > <el-table-column :label="t('TemplateManagement.PrintConfig.isEnabled')" align="center" prop="isEnabled" width="90px">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.IS_ENABLED" :value="scope.row.isEnabled" /> <dict-tag :type="DICT_TYPE.IS_ENABLED" :value="scope.row.isEnabled" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="t('TemplateManagement.PrintConfig.businessScenarioCode')" align="center" prop="businessScenarioCode" min-width="180px"/>
<el-table-column :label="t('TemplateManagement.PrintConfig.businessScenario')" align="center" prop="businessScenario" min-width="180px"/>
<el-table-column :label="t('TemplateManagement.PrintConfig.scenarioCount')" align="center" prop="scenarioCount" width="70px" />
<el-table-column :label="t('TemplateManagement.PrintConfig.remark')" align="center" prop="remark" /> <el-table-column :label="t('TemplateManagement.PrintConfig.remark')" align="center" prop="remark" />
<el-table-column <el-table-column
:label="t('TemplateManagement.PrintConfig.createTime')" :label="t('TemplateManagement.PrintConfig.createTime')"

Loading…
Cancel
Save