1.每次 点击手动上线时 记录 物料编码与版本号关系到数据库
2.当人工扫码时 收到MQTT消息 弹出窗口显示该物料号历史程序号 可人工选择或自行输入新版本号 3.点击上线按钮 需要二次确认信息弹窗 弹窗 显示产品或者工件的详细信息 需要二次确认或者取消 4.二次确认弹窗 中增加 程序号 版本号+物料编码 5.版本号 和 物料编码 放在一行显示 分两个框
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -17,63 +17,55 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">扫码上线验证信息</div>
|
<div class="section-title">扫码上线验证信息</div>
|
||||||
<el-form :inline="true" label-width="50px" label-position="right" style="width: 100%;">
|
<el-form :inline="true" label-width="70px" label-position="right" class="upline-form" style="width: 100%;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
<el-form-item label="扫码值" style="width: 100%;" class="SmallLabel">
|
<el-form-item label="扫码值" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.扫码值" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws1Result.扫码值" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="12">
|
||||||
<el-form-item label="物料编码" style="width: 100%;">
|
|
||||||
<el-input v-model="ws1Result.扫码物料编码" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<el-form-item label="工单号" style="width: 100%;">
|
|
||||||
<el-input v-model="ws1Result.工单号" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="序列号" style="width: 100%;">
|
<el-form-item label="序列号" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws1Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
|
<el-form-item label="工单号" style="width: 100%;">
|
||||||
|
<el-input v-model="ws1Result.工单号" readonly size="small" style="width: 100%;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="错误消息" style="width: 100%;">
|
<el-form-item label="错误消息" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
<el-input v-model="ws1Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="程序版本" style="width: 100%;">
|
|
||||||
<el-select v-model="ws1Result.程序版本" filterable allow-create default-first-option size="small" style="width: 100%;">
|
|
||||||
<el-option v-for="item in programVersionOptions" :key="item" :label="item" :value="item" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<div style="height: 32px;"></div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="验证结果" style="width: 100%;">
|
|
||||||
<div v-if="ws1Result.验证结果 == 1"
|
|
||||||
style="background:#aaff33;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证通过</div>
|
|
||||||
<div v-else-if="ws1Result.验证结果 == 2"
|
|
||||||
style="background:#ff3b3b;color:#fff;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证失败</div>
|
|
||||||
<div v-else-if="ws1Result.验证结果 == -1"
|
|
||||||
style="background:#ffe066;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
解析错误</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<div class="material-version-row">
|
||||||
|
<div class="mv-version">
|
||||||
|
<div class="top-label">程序版本</div>
|
||||||
|
<el-input
|
||||||
|
v-model="ws1Result.程序版本"
|
||||||
|
readonly
|
||||||
|
size="small"
|
||||||
|
placeholder="双击选择"
|
||||||
|
class="version-input"
|
||||||
|
@dblclick.native="openVersionDialog(opNameList[0])" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-material">
|
||||||
|
<div class="top-label">物料编码</div>
|
||||||
|
<el-input v-model="ws1Result.扫码物料编码" readonly size="small" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-result">
|
||||||
|
<div class="top-label">验证结果</div>
|
||||||
|
<div class="result-display">
|
||||||
|
<span v-if="ws1Result.验证结果 == 1" class="result-pass">验证通过</span>
|
||||||
|
<span v-else-if="ws1Result.验证结果 == 2" class="result-fail">验证失败</span>
|
||||||
|
<span v-else-if="ws1Result.验证结果 == -1" class="result-error">解析错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="display: flex; align-items: center; margin: 8px 0;">
|
<div style="display: flex; align-items: center; margin: 8px 0;">
|
||||||
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
||||||
@@ -192,63 +184,55 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">扫码上线验证信息</div>
|
<div class="section-title">扫码上线验证信息</div>
|
||||||
<el-form :inline="true" label-width="50px" label-position="right" style="width: 100%;">
|
<el-form :inline="true" label-width="70px" label-position="right" class="upline-form" style="width: 100%;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
<el-form-item label="扫码值" style="width: 100%;" class="SmallLabel">
|
<el-form-item label="扫码值" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.扫码值" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws2Result.扫码值" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="12">
|
||||||
<el-form-item label="物料编码" style="width: 100%;">
|
|
||||||
<el-input v-model="ws2Result.扫码物料编码" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<el-form-item label="工单号" style="width: 100%;">
|
|
||||||
<el-input v-model="ws2Result.工单号" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="序列号" style="width: 100%;">
|
<el-form-item label="序列号" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws2Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
|
<el-form-item label="工单号" style="width: 100%;">
|
||||||
|
<el-input v-model="ws2Result.工单号" readonly size="small" style="width: 100%;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="错误消息" style="width: 100%;">
|
<el-form-item label="错误消息" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
<el-input v-model="ws2Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="程序版本" style="width: 100%;">
|
|
||||||
<el-select v-model="ws2Result.程序版本" filterable allow-create default-first-option size="small" style="width: 100%;">
|
|
||||||
<el-option v-for="item in programVersionOptions" :key="item" :label="item" :value="item" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<div style="height: 32px;"></div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="验证结果" style="width: 100%;">
|
|
||||||
<div v-if="ws2Result.验证结果 == 1"
|
|
||||||
style="background:#aaff33;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证通过</div>
|
|
||||||
<div v-else-if="ws2Result.验证结果 == 2"
|
|
||||||
style="background:#ff3b3b;color:#fff;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证失败</div>
|
|
||||||
<div v-else-if="ws2Result.验证结果 == -1"
|
|
||||||
style="background:#ffe066;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
解析错误</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<div class="material-version-row">
|
||||||
|
<div class="mv-version">
|
||||||
|
<div class="top-label">程序版本</div>
|
||||||
|
<el-input
|
||||||
|
v-model="ws2Result.程序版本"
|
||||||
|
readonly
|
||||||
|
size="small"
|
||||||
|
placeholder="双击选择"
|
||||||
|
class="version-input"
|
||||||
|
@dblclick.native="openVersionDialog(opNameList[1])" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-material">
|
||||||
|
<div class="top-label">物料编码</div>
|
||||||
|
<el-input v-model="ws2Result.扫码物料编码" readonly size="small" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-result">
|
||||||
|
<div class="top-label">验证结果</div>
|
||||||
|
<div class="result-display">
|
||||||
|
<span v-if="ws2Result.验证结果 == 1" class="result-pass">验证通过</span>
|
||||||
|
<span v-else-if="ws2Result.验证结果 == 2" class="result-fail">验证失败</span>
|
||||||
|
<span v-else-if="ws2Result.验证结果 == -1" class="result-error">解析错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="display: flex; align-items: center; margin: 8px 0;">
|
<div style="display: flex; align-items: center; margin: 8px 0;">
|
||||||
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
||||||
@@ -352,6 +336,113 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="versionDialog.visible"
|
||||||
|
width="520px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
custom-class="version-dialog"
|
||||||
|
:show-close="true">
|
||||||
|
<div slot="title" class="vd-header">
|
||||||
|
<div class="vd-title">选择程序版本</div>
|
||||||
|
<div class="vd-subtitle">物料编码 · {{ versionDialog.partCode || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vd-body">
|
||||||
|
<div class="vd-section-title">
|
||||||
|
<span>历史程序版本</span>
|
||||||
|
<span class="vd-count" v-if="versionDialog.historyList.length">共 {{ versionDialog.historyList.length }} 条</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="versionDialog.historyList.length" class="vd-tag-list">
|
||||||
|
<div
|
||||||
|
v-for="item in versionDialog.historyList"
|
||||||
|
:key="item"
|
||||||
|
class="vd-tag"
|
||||||
|
:class="{ 'is-active': versionDialog.selectedVersion === item }"
|
||||||
|
@click="versionDialog.selectedVersion = item">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="vd-empty">
|
||||||
|
<div class="vd-empty-text">该物料暂无历史程序版本</div>
|
||||||
|
<div class="vd-empty-hint">请在下方手动输入新版本号</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vd-section-title vd-section-title-spaced">手动输入版本号</div>
|
||||||
|
<el-input
|
||||||
|
v-model="versionDialog.selectedVersion"
|
||||||
|
size="medium"
|
||||||
|
maxlength="32"
|
||||||
|
placeholder=""
|
||||||
|
clearable />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="vd-footer">
|
||||||
|
<el-button @click="versionDialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :disabled="!versionDialog.selectedVersion" @click="confirmVersionDialog">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="loadConfirmDialog.visible"
|
||||||
|
width="560px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
custom-class="load-confirm-dialog"
|
||||||
|
:show-close="true">
|
||||||
|
<div slot="title" class="lcd-header">
|
||||||
|
<div class="lcd-title">上线信息确认</div>
|
||||||
|
<div class="lcd-subtitle">请确认以下信息无误后再点击"确认上线"</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lcd-body">
|
||||||
|
<div class="lcd-card lcd-card-primary">
|
||||||
|
<div class="lcd-card-tag">关键信息</div>
|
||||||
|
<div class="lcd-row-2col lcd-row-2col-key">
|
||||||
|
<div class="lcd-field">
|
||||||
|
<div class="lcd-label">程序版本</div>
|
||||||
|
<div class="lcd-value lcd-value-strong lcd-value-right">{{ loadConfirmDialog.detail.程序版本 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-field">
|
||||||
|
<div class="lcd-label">物料编码</div>
|
||||||
|
<div class="lcd-value lcd-value-strong">{{ loadConfirmDialog.detail.扫码物料编码 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-field lcd-field-program-no">
|
||||||
|
<div class="lcd-label">程序号</div>
|
||||||
|
<div class="lcd-value lcd-value-mono">{{ loadConfirmProgramNo || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lcd-card">
|
||||||
|
<div class="lcd-info-grid">
|
||||||
|
<div class="lcd-info-item">
|
||||||
|
<div class="lcd-info-label">工位号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.工位号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item">
|
||||||
|
<div class="lcd-info-label">序列号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.扫码序列号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item lcd-info-item-full">
|
||||||
|
<div class="lcd-info-label">工单号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.工单号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item lcd-info-item-full">
|
||||||
|
<div class="lcd-info-label">扫码值</div>
|
||||||
|
<div class="lcd-info-value lcd-info-value-mono">{{ loadConfirmDialog.detail.扫码值 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="lcd-footer">
|
||||||
|
<el-button @click="loadConfirmDialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="loadConfirmDialog.loading" @click="confirmLoadDialog">确 认 上 线</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -366,10 +457,14 @@ import { mqttIp, mqttTopic, mqttInitRequestTopic, writePlcApi_BtnType, selectOpN
|
|||||||
const PROGRAM_VERSION_TAG_ID = '208640'
|
const PROGRAM_VERSION_TAG_ID = '208640'
|
||||||
|
|
||||||
/** 程序版本下拉选项 */
|
/** 程序版本下拉选项 */
|
||||||
const PROGRAM_VERSION_OPTIONS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
/** 程序版本可选项(PLC 实际可写的字符值) */
|
||||||
|
const PROGRAM_VERSION_OPTIONS = []
|
||||||
|
|
||||||
/** 轮询读取的所有 PLC 信号标识 */
|
/** 轮询读取的所有 PLC 信号标识 */
|
||||||
const POLL_TAG_IDS = ['200004', '200005', '200006', '200007', '200380', '203240', '200440', PROGRAM_VERSION_TAG_ID]
|
const POLL_TAG_IDS = ['200004', '200005', '200006', '200007', '200380', '203240', '200440']
|
||||||
|
|
||||||
|
/** 上次使用的程序版本 localStorage key 前缀(按工位独立) */
|
||||||
|
const LAST_VERSION_STORAGE_PREFIX = 'ZL_DJ_LastProgramVersion_'
|
||||||
|
|
||||||
/** 状态灯信号 → data 属性映射 */
|
/** 状态灯信号 → data 属性映射 */
|
||||||
const STATUS_TAG_MAP = {
|
const STATUS_TAG_MAP = {
|
||||||
@@ -404,6 +499,9 @@ export default {
|
|||||||
// 双工位扫码验证数据
|
// 双工位扫码验证数据
|
||||||
ws1Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
ws1Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
||||||
ws2Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
ws2Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
||||||
|
// 是否已处理过首次扫码(首次:自动取最近一次版本,不弹窗;之后:弹窗手动选)
|
||||||
|
ws1FirstVerifyHandled: false,
|
||||||
|
ws2FirstVerifyHandled: false,
|
||||||
programVersionOptions: PROGRAM_VERSION_OPTIONS,
|
programVersionOptions: PROGRAM_VERSION_OPTIONS,
|
||||||
// 双工位托盘信息
|
// 双工位托盘信息
|
||||||
ws1Tray: { 托盘号: '', 托盘物料编码: '', 托盘工件状态: '' },
|
ws1Tray: { 托盘号: '', 托盘物料编码: '', 托盘工件状态: '' },
|
||||||
@@ -424,10 +522,41 @@ export default {
|
|||||||
isResetSerialLoading: false,
|
isResetSerialLoading: false,
|
||||||
// 轮询定时器(按工位分别存储,支持双工位同时轮询)
|
// 轮询定时器(按工位分别存储,支持双工位同时轮询)
|
||||||
pollTimers: {},
|
pollTimers: {},
|
||||||
|
// 历史程序版本选择弹窗
|
||||||
|
versionDialog: {
|
||||||
|
visible: false,
|
||||||
|
opName: '',
|
||||||
|
partCode: '',
|
||||||
|
historyList: [],
|
||||||
|
selectedVersion: ''
|
||||||
|
},
|
||||||
|
// 手动上线二次确认弹窗
|
||||||
|
loadConfirmDialog: {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
opName: '',
|
||||||
|
detail: {
|
||||||
|
工位号: '', 扫码值: '', 工单号: '', 扫码序列号: '', 扫码物料编码: '', 程序版本: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['id', 'token'])
|
...mapGetters(['id', 'token', 'name']),
|
||||||
|
versionDialogOptions() {
|
||||||
|
const merged = [...this.versionDialog.historyList]
|
||||||
|
this.programVersionOptions.forEach(v => {
|
||||||
|
if (!merged.includes(v)) merged.push(v)
|
||||||
|
})
|
||||||
|
return merged
|
||||||
|
},
|
||||||
|
/** 上线信息确认弹窗 - 程序号 = 程序版本 + 物料编码 */
|
||||||
|
loadConfirmProgramNo() {
|
||||||
|
const ver = this.loadConfirmDialog.detail.程序版本 || ''
|
||||||
|
const code = this.loadConfirmDialog.detail.扫码物料编码 || ''
|
||||||
|
if (!ver && !code) return ''
|
||||||
|
return `${ver}${code}`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.opNameType === '转台上线') {
|
if (this.opNameType === '转台上线') {
|
||||||
@@ -518,7 +647,6 @@ export default {
|
|||||||
if (valueMap['200380'] !== undefined) tray.托盘号 = valueMap['200380']
|
if (valueMap['200380'] !== undefined) tray.托盘号 = valueMap['200380']
|
||||||
if (valueMap['203240'] !== undefined) this.convertMaterialCode(opName, valueMap['203240'])
|
if (valueMap['203240'] !== undefined) this.convertMaterialCode(opName, valueMap['203240'])
|
||||||
if (valueMap['200440'] !== undefined) tray.托盘工件状态 = TRAY_STATUS_TEXT[valueMap['200440']] || ''
|
if (valueMap['200440'] !== undefined) tray.托盘工件状态 = TRAY_STATUS_TEXT[valueMap['200440']] || ''
|
||||||
if (valueMap[PROGRAM_VERSION_TAG_ID] !== undefined) result.程序版本 = valueMap[PROGRAM_VERSION_TAG_ID] || ''
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 将PLC读取到的物料号通过存储过程转换为物料编码 */
|
/** 将PLC读取到的物料号通过存储过程转换为物料编码 */
|
||||||
@@ -715,7 +843,7 @@ export default {
|
|||||||
|
|
||||||
switch (interFaceType) {
|
switch (interFaceType) {
|
||||||
case 'VerifyResult': {
|
case 'VerifyResult': {
|
||||||
if (arrays_signal.length < 11) {
|
if (arrays_signal.length < 9) {
|
||||||
this.$message.warning('收到扫码结果,但是数据异常,不予处理!')
|
this.$message.warning('收到扫码结果,但是数据异常,不予处理!')
|
||||||
console.log(msg)
|
console.log(msg)
|
||||||
return
|
return
|
||||||
@@ -737,10 +865,22 @@ export default {
|
|||||||
targetResult.扫码物料编码 = arrays_signal[6]
|
targetResult.扫码物料编码 = arrays_signal[6]
|
||||||
targetResult.扫码序列号 = arrays_signal[7]
|
targetResult.扫码序列号 = arrays_signal[7]
|
||||||
targetResult.工单号 = arrays_signal[8]
|
targetResult.工单号 = arrays_signal[8]
|
||||||
targetResult.工单物料编号 = arrays_signal[9]
|
// targetResult.工单物料编号 = arrays_signal[9]
|
||||||
targetResult.工单序列号 = arrays_signal[10]
|
// targetResult.工单序列号 = arrays_signal[10]
|
||||||
if (targetResult.验证结果 == 1) {
|
if (targetResult.验证结果 == 1) {
|
||||||
this.$message.success('收到校验结果,校验通过!' + targetResult.错误消息)
|
this.$message.success('收到校验结果,校验通过!' + targetResult.错误消息)
|
||||||
|
if (pos === this.clickOpName) {
|
||||||
|
const isFirst = pos === this.opNameList[0]
|
||||||
|
? !this.ws1FirstVerifyHandled
|
||||||
|
: !this.ws2FirstVerifyHandled
|
||||||
|
if (isFirst) {
|
||||||
|
this.autoFillFirstVersion(pos)
|
||||||
|
if (pos === this.opNameList[0]) this.ws1FirstVerifyHandled = true
|
||||||
|
else this.ws2FirstVerifyHandled = true
|
||||||
|
} else {
|
||||||
|
this.openVersionDialog(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.isAutoPartLoad && this.clickOpName === pos) {
|
if (this.isAutoPartLoad && this.clickOpName === pos) {
|
||||||
this.partLoadOpName(targetResult.扫码工位)
|
this.partLoadOpName(targetResult.扫码工位)
|
||||||
}
|
}
|
||||||
@@ -804,17 +944,50 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
this.loadConfirmDialog.opName = opName
|
||||||
await this.$confirm('确定要执行手动请求上线操作吗?', '确认操作', {
|
this.loadConfirmDialog.detail = {
|
||||||
confirmButtonText: '确定',
|
工位号: opName,
|
||||||
cancelButtonText: '取消',
|
扫码值: result.扫码值 || '',
|
||||||
type: 'warning'
|
工单号: result.工单号 || '',
|
||||||
})
|
扫码序列号: result.扫码序列号 || '',
|
||||||
} catch (error) {
|
扫码物料编码: result.扫码物料编码 || '',
|
||||||
|
程序版本: programVersion
|
||||||
|
}
|
||||||
|
this.loadConfirmDialog.loading = false
|
||||||
|
this.loadConfirmDialog.visible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 二次确认弹窗"确定":把弹窗里的程序版本写回扫码结果,再走 PLC 写值流程 */
|
||||||
|
async confirmLoadDialog() {
|
||||||
|
const opName = this.loadConfirmDialog.opName
|
||||||
|
const version = this.loadConfirmDialog.detail.程序版本
|
||||||
|
? this.loadConfirmDialog.detail.程序版本.toString()
|
||||||
|
: ''
|
||||||
|
if (!version) {
|
||||||
|
this.$message.warning('请选择或输入程序版本!')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
result.程序版本 = version
|
||||||
|
this.setLastUsedVersion(opName, version)
|
||||||
|
|
||||||
|
this.loadConfirmDialog.loading = true
|
||||||
|
try {
|
||||||
|
await this.doPartLoad(opName)
|
||||||
|
} finally {
|
||||||
|
this.loadConfirmDialog.loading = false
|
||||||
|
this.loadConfirmDialog.visible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 实际执行 PLC 写值上线流程;成功后写入手动上线记录 */
|
||||||
|
async doPartLoad(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
const partLoadStatus = opName === this.opNameList[0] ? this.ws1PartLoadStatus : this.ws2PartLoadStatus
|
const partLoadStatus = opName === this.opNameList[0] ? this.ws1PartLoadStatus : this.ws2PartLoadStatus
|
||||||
|
const programVersion = result.程序版本 ? result.程序版本.toString() : ''
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
|
||||||
const plcValue = await this.getPLCValue(opName, '205015')
|
const plcValue = await this.getPLCValue(opName, '205015')
|
||||||
if (plcValue === 'True') {
|
if (plcValue === 'True') {
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
@@ -824,34 +997,112 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.writePLCValue(opName, PROGRAM_VERSION_TAG_ID, programVersion)
|
try {
|
||||||
.then(response => {
|
const r1 = await this.writePLCValue(opName, PROGRAM_VERSION_TAG_ID, programVersion)
|
||||||
if (response.data.code != 0) {
|
if (r1.data.code != 0) throw new Error(r1.data.msg || '程序版本写入失败')
|
||||||
return Promise.reject(new Error(response.data.msg || '程序版本写入失败'))
|
const r2 = await this.writePLCValue(opName, '205015', 'true')
|
||||||
}
|
if (r2.data.code == 0) {
|
||||||
return this.writePLCValue(opName, '205015', 'true')
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.code == 0) {
|
|
||||||
partLoadStatus.success = true
|
partLoadStatus.success = true
|
||||||
partLoadStatus.message = ''
|
partLoadStatus.message = ''
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.success('申请上线成功!')
|
this.$message.success('申请上线成功!')
|
||||||
|
this.recordManualLoad(opName, partCode, programVersion)
|
||||||
} else {
|
} else {
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
partLoadStatus.message = response.data.msg || '申请失败'
|
partLoadStatus.message = r2.data.msg || '申请失败'
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.error(response.data.msg)
|
this.$message.error(r2.data.msg)
|
||||||
}
|
}
|
||||||
})
|
} catch (error) {
|
||||||
.catch(error => {
|
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
partLoadStatus.message = error.message
|
partLoadStatus.message = error.message
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.error('申请上线失败' + error.message)
|
this.$message.error('申请上线失败' + error.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 写入手动上线 (物料编码,程序版本) 记录 */
|
||||||
|
recordManualLoad(opName, partCode, version) {
|
||||||
|
if (!partCode || !version) return
|
||||||
|
const param = []
|
||||||
|
param[0] = ['物料编码', partCode]
|
||||||
|
param[1] = ['程序版本', version]
|
||||||
|
param[2] = ['工位号', opName]
|
||||||
|
param[3] = ['操作人', this.name || '']
|
||||||
|
const Data = this.CreateData('12', 'ZL_物料程序版本_手动上线记录_Insert', param)
|
||||||
|
this.ExecDatabase(Data).catch(err => console.error('记录手动上线失败:', err))
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 历史程序版本弹窗 ====================
|
||||||
|
|
||||||
|
/** 查询某物料编码的历史程序版本(按最近使用时间倒序) */
|
||||||
|
loadHistoryVersions(partCode) {
|
||||||
|
if (!partCode) return Promise.resolve([])
|
||||||
|
const param = [['物料编码', partCode]]
|
||||||
|
const Data = this.CreateData('11', 'ZL_物料程序版本_手动上线记录_查询历史版本', param)
|
||||||
|
return this.ExecDatabase(Data)
|
||||||
|
.then(resp => Array.isArray(resp.data) ? resp.data.map(r => r.程序版本).filter(v => !!v) : [])
|
||||||
|
.catch(err => {
|
||||||
|
console.error('查询历史程序版本失败:', err)
|
||||||
|
return []
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 打开"选择程序版本"弹窗:扫码验证通过且为当前工位时触发 */
|
||||||
|
async openVersionDialog(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
const historyList = await this.loadHistoryVersions(partCode)
|
||||||
|
const lastUsed = this.getLastUsedVersion(opName)
|
||||||
|
this.versionDialog.opName = opName
|
||||||
|
this.versionDialog.partCode = partCode
|
||||||
|
this.versionDialog.historyList = historyList
|
||||||
|
this.versionDialog.selectedVersion = (result.程序版本 || lastUsed || historyList[0] || '')
|
||||||
|
this.versionDialog.visible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 首次扫码:从数据库取该物料最近一次的程序版本,直接回填,不弹窗 */
|
||||||
|
async autoFillFirstVersion(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
if (!partCode) return
|
||||||
|
const historyList = await this.loadHistoryVersions(partCode)
|
||||||
|
if (historyList && historyList.length > 0) {
|
||||||
|
result.程序版本 = historyList[0]
|
||||||
|
this.setLastUsedVersion(opName, historyList[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** "选择程序版本"弹窗确定:把版本回填到对应工位,不自动上线 */
|
||||||
|
confirmVersionDialog() {
|
||||||
|
const version = this.versionDialog.selectedVersion ? this.versionDialog.selectedVersion.toString() : ''
|
||||||
|
if (!version) {
|
||||||
|
this.$message.warning('请选择或输入程序版本!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const opName = this.versionDialog.opName
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
result.程序版本 = version
|
||||||
|
this.setLastUsedVersion(opName, version)
|
||||||
|
this.versionDialog.visible = false
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 读取该工位上一次使用的程序版本(localStorage) */
|
||||||
|
getLastUsedVersion(opName) {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(LAST_VERSION_STORAGE_PREFIX + opName) || ''
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 持久化保存该工位本次使用的程序版本(localStorage) */
|
||||||
|
setLastUsedVersion(opName, version) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(LAST_VERSION_STORAGE_PREFIX + opName, version || '')
|
||||||
|
} catch (e) { /* ignore */ }
|
||||||
|
},
|
||||||
|
|
||||||
// ==================== 读码 / 写码 / 清码 ====================
|
// ==================== 读码 / 写码 / 清码 ====================
|
||||||
|
|
||||||
/** 写码 - 发送写码请求并启动10秒轮询 */
|
/** 写码 - 发送写码请求并启动10秒轮询 */
|
||||||
@@ -1035,4 +1286,400 @@ export default {
|
|||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.material-version-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
|
||||||
|
.mv-version {
|
||||||
|
flex: 0 0 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-material {
|
||||||
|
flex: 2 1 0;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-result {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 0 0 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-input {
|
||||||
|
::v-deep .el-input__inner {
|
||||||
|
text-align: right;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-display {
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.result-pass,
|
||||||
|
.result-fail,
|
||||||
|
.result-error {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-pass { background: #aaff33; color: #222; }
|
||||||
|
.result-fail { background: #ff3b3b; color: #fff; }
|
||||||
|
.result-error { background: #ffe066; color: #222; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upline-form {
|
||||||
|
::v-deep .el-form-item__label {
|
||||||
|
width: 70px !important;
|
||||||
|
padding-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
|
width: calc(100% - 70px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.version-dialog {
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
padding: 18px 24px 14px;
|
||||||
|
background: linear-gradient(135deg, #f5f9ff 0%, #ffffff 100%);
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
top: 18px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 18px 24px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 12px 24px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-header {
|
||||||
|
.vd-title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.vd-subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-body {
|
||||||
|
.vd-section-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #606266;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.vd-count {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-section-title-spaced {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-tag-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
max-height: 180px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 4px 4px 4px 0;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 14px;
|
||||||
|
min-width: 56px;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #f4f6fa;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all 0.18s ease;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #e8f0ff;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #409eff;
|
||||||
|
box-shadow: 0 4px 10px rgba(64, 158, 255, 0.28);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-empty {
|
||||||
|
padding: 18px 12px;
|
||||||
|
background: #fafbfc;
|
||||||
|
border: 1px dashed #dcdfe6;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.vd-empty-text {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
.vd-empty-hint {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-footer {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-confirm-dialog {
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.18);
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
padding: 18px 24px 14px;
|
||||||
|
background: linear-gradient(135deg, #fff7eb 0%, #ffffff 100%);
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
top: 18px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 18px 22px 6px;
|
||||||
|
background: #f7f9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 14px 22px 18px;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-header {
|
||||||
|
.lcd-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.lcd-subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-card {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.lcd-card-primary {
|
||||||
|
background: linear-gradient(180deg, #ffffff 0%, #fafcff 100%);
|
||||||
|
border-color: #d9e7ff;
|
||||||
|
padding-top: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-card-tag {
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
left: 14px;
|
||||||
|
background: #ff9d00;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
box-shadow: 0 2px 6px rgba(255, 157, 0, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-row-2col {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.4fr 1fr;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-row-2col-key {
|
||||||
|
grid-template-columns: 0.5fr 1.5fr;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-field {
|
||||||
|
.lcd-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.lcd-value {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 500;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 7px 12px;
|
||||||
|
background: #f4f6fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
min-height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.lcd-value-strong {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ff7a00;
|
||||||
|
background: #fff5e6;
|
||||||
|
border: 1px solid #ffe1b3;
|
||||||
|
}
|
||||||
|
.lcd-value-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.lcd-value-mono {
|
||||||
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-field-program-no {
|
||||||
|
.lcd-value {
|
||||||
|
background: #f0f7ff;
|
||||||
|
border: 1px dashed #b3d4ff;
|
||||||
|
color: #1f6feb;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-select {
|
||||||
|
width: 100%;
|
||||||
|
.el-input__inner {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&.lcd-info-item-full {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-value {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #303133;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-value-mono {
|
||||||
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||||
|
font-size: 12.5px;
|
||||||
|
color: #606266;
|
||||||
|
background: #f4f6fa;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-footer {
|
||||||
|
text-align: right;
|
||||||
|
.el-button {
|
||||||
|
min-width: 90px;
|
||||||
|
}
|
||||||
|
.el-button--primary {
|
||||||
|
min-width: 130px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -17,63 +17,55 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">扫码上线验证信息</div>
|
<div class="section-title">扫码上线验证信息</div>
|
||||||
<el-form :inline="true" label-width="50px" label-position="right" style="width: 100%;">
|
<el-form :inline="true" label-width="70px" label-position="right" class="upline-form" style="width: 100%;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
<el-form-item label="扫码值" style="width: 100%;" class="SmallLabel">
|
<el-form-item label="扫码值" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.扫码值" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws1Result.扫码值" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="12">
|
||||||
<el-form-item label="物料编码" style="width: 100%;">
|
|
||||||
<el-input v-model="ws1Result.扫码物料编码" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<el-form-item label="工单号" style="width: 100%;">
|
|
||||||
<el-input v-model="ws1Result.工单号" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="序列号" style="width: 100%;">
|
<el-form-item label="序列号" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws1Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
|
<el-form-item label="工单号" style="width: 100%;">
|
||||||
|
<el-input v-model="ws1Result.工单号" readonly size="small" style="width: 100%;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="错误消息" style="width: 100%;">
|
<el-form-item label="错误消息" style="width: 100%;">
|
||||||
<el-input v-model="ws1Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
<el-input v-model="ws1Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="程序版本" style="width: 100%;">
|
|
||||||
<el-select v-model="ws1Result.程序版本" filterable allow-create default-first-option size="small" style="width: 100%;">
|
|
||||||
<el-option v-for="item in programVersionOptions" :key="item" :label="item" :value="item" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<div style="height: 32px;"></div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="验证结果" style="width: 100%;">
|
|
||||||
<div v-if="ws1Result.验证结果 == 1"
|
|
||||||
style="background:#aaff33;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证通过</div>
|
|
||||||
<div v-else-if="ws1Result.验证结果 == 2"
|
|
||||||
style="background:#ff3b3b;color:#fff;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证失败</div>
|
|
||||||
<div v-else-if="ws1Result.验证结果 == -1"
|
|
||||||
style="background:#ffe066;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
解析错误</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<div class="material-version-row">
|
||||||
|
<div class="mv-version">
|
||||||
|
<div class="top-label">程序版本</div>
|
||||||
|
<el-input
|
||||||
|
v-model="ws1Result.程序版本"
|
||||||
|
readonly
|
||||||
|
size="small"
|
||||||
|
placeholder="双击选择"
|
||||||
|
class="version-input"
|
||||||
|
@dblclick.native="openVersionDialog(opNameList[0])" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-material">
|
||||||
|
<div class="top-label">物料编码</div>
|
||||||
|
<el-input v-model="ws1Result.扫码物料编码" readonly size="small" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-result">
|
||||||
|
<div class="top-label">验证结果</div>
|
||||||
|
<div class="result-display">
|
||||||
|
<span v-if="ws1Result.验证结果 == 1" class="result-pass">验证通过</span>
|
||||||
|
<span v-else-if="ws1Result.验证结果 == 2" class="result-fail">验证失败</span>
|
||||||
|
<span v-else-if="ws1Result.验证结果 == -1" class="result-error">解析错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="display: flex; align-items: center; margin: 8px 0;">
|
<div style="display: flex; align-items: center; margin: 8px 0;">
|
||||||
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
||||||
@@ -192,63 +184,55 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">扫码上线验证信息</div>
|
<div class="section-title">扫码上线验证信息</div>
|
||||||
<el-form :inline="true" label-width="50px" label-position="right" style="width: 100%;">
|
<el-form :inline="true" label-width="70px" label-position="right" class="upline-form" style="width: 100%;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
<el-form-item label="扫码值" style="width: 100%;" class="SmallLabel">
|
<el-form-item label="扫码值" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.扫码值" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws2Result.扫码值" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="12">
|
||||||
<el-form-item label="物料编码" style="width: 100%;">
|
|
||||||
<el-input v-model="ws2Result.扫码物料编码" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<el-form-item label="工单号" style="width: 100%;">
|
|
||||||
<el-input v-model="ws2Result.工单号" readonly size="small" style="width: 100%;" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="序列号" style="width: 100%;">
|
<el-form-item label="序列号" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
<el-input v-model="ws2Result.扫码序列号" readonly size="small" style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="14">
|
<el-col :span="12">
|
||||||
|
<el-form-item label="工单号" style="width: 100%;">
|
||||||
|
<el-input v-model="ws2Result.工单号" readonly size="small" style="width: 100%;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="错误消息" style="width: 100%;">
|
<el-form-item label="错误消息" style="width: 100%;">
|
||||||
<el-input v-model="ws2Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
<el-input v-model="ws2Result.错误消息" readonly size="small" style="width: 100%;color:red;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="程序版本" style="width: 100%;">
|
|
||||||
<el-select v-model="ws2Result.程序版本" filterable allow-create default-first-option size="small" style="width: 100%;">
|
|
||||||
<el-option v-for="item in programVersionOptions" :key="item" :label="item" :value="item" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :span="14">
|
|
||||||
<div style="height: 32px;"></div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="验证结果" style="width: 100%;">
|
|
||||||
<div v-if="ws2Result.验证结果 == 1"
|
|
||||||
style="background:#aaff33;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证通过</div>
|
|
||||||
<div v-else-if="ws2Result.验证结果 == 2"
|
|
||||||
style="background:#ff3b3b;color:#fff;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
验证失败</div>
|
|
||||||
<div v-else-if="ws2Result.验证结果 == -1"
|
|
||||||
style="background:#ffe066;color:#222;font-weight:bold;font-size:14px;padding:2px 8px;border-radius:4px;width:100%;text-align:center;">
|
|
||||||
解析错误</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<div class="material-version-row">
|
||||||
|
<div class="mv-version">
|
||||||
|
<div class="top-label">程序版本</div>
|
||||||
|
<el-input
|
||||||
|
v-model="ws2Result.程序版本"
|
||||||
|
readonly
|
||||||
|
size="small"
|
||||||
|
placeholder="双击选择"
|
||||||
|
class="version-input"
|
||||||
|
@dblclick.native="openVersionDialog(opNameList[1])" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-material">
|
||||||
|
<div class="top-label">物料编码</div>
|
||||||
|
<el-input v-model="ws2Result.扫码物料编码" readonly size="small" />
|
||||||
|
</div>
|
||||||
|
<div class="mv-result">
|
||||||
|
<div class="top-label">验证结果</div>
|
||||||
|
<div class="result-display">
|
||||||
|
<span v-if="ws2Result.验证结果 == 1" class="result-pass">验证通过</span>
|
||||||
|
<span v-else-if="ws2Result.验证结果 == 2" class="result-fail">验证失败</span>
|
||||||
|
<span v-else-if="ws2Result.验证结果 == -1" class="result-error">解析错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="display: flex; align-items: center; margin: 8px 0;">
|
<div style="display: flex; align-items: center; margin: 8px 0;">
|
||||||
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
<el-button type="primary" style="width: 200px;height: 50px; font-size: 14px;"
|
||||||
@@ -352,6 +336,113 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="versionDialog.visible"
|
||||||
|
width="520px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
custom-class="version-dialog"
|
||||||
|
:show-close="true">
|
||||||
|
<div slot="title" class="vd-header">
|
||||||
|
<div class="vd-title">选择程序版本</div>
|
||||||
|
<div class="vd-subtitle">物料编码 · {{ versionDialog.partCode || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vd-body">
|
||||||
|
<div class="vd-section-title">
|
||||||
|
<span>历史程序版本</span>
|
||||||
|
<span class="vd-count" v-if="versionDialog.historyList.length">共 {{ versionDialog.historyList.length }} 条</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="versionDialog.historyList.length" class="vd-tag-list">
|
||||||
|
<div
|
||||||
|
v-for="item in versionDialog.historyList"
|
||||||
|
:key="item"
|
||||||
|
class="vd-tag"
|
||||||
|
:class="{ 'is-active': versionDialog.selectedVersion === item }"
|
||||||
|
@click="versionDialog.selectedVersion = item">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="vd-empty">
|
||||||
|
<div class="vd-empty-text">该物料暂无历史程序版本</div>
|
||||||
|
<div class="vd-empty-hint">请在下方手动输入新版本号</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vd-section-title vd-section-title-spaced">手动输入版本号</div>
|
||||||
|
<el-input
|
||||||
|
v-model="versionDialog.selectedVersion"
|
||||||
|
size="medium"
|
||||||
|
maxlength="32"
|
||||||
|
placeholder=""
|
||||||
|
clearable />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="vd-footer">
|
||||||
|
<el-button @click="versionDialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :disabled="!versionDialog.selectedVersion" @click="confirmVersionDialog">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="loadConfirmDialog.visible"
|
||||||
|
width="560px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
custom-class="load-confirm-dialog"
|
||||||
|
:show-close="true">
|
||||||
|
<div slot="title" class="lcd-header">
|
||||||
|
<div class="lcd-title">上线信息确认</div>
|
||||||
|
<div class="lcd-subtitle">请确认以下信息无误后再点击"确认上线"</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lcd-body">
|
||||||
|
<div class="lcd-card lcd-card-primary">
|
||||||
|
<div class="lcd-card-tag">关键信息</div>
|
||||||
|
<div class="lcd-row-2col lcd-row-2col-key">
|
||||||
|
<div class="lcd-field">
|
||||||
|
<div class="lcd-label">程序版本</div>
|
||||||
|
<div class="lcd-value lcd-value-strong lcd-value-right">{{ loadConfirmDialog.detail.程序版本 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-field">
|
||||||
|
<div class="lcd-label">物料编码</div>
|
||||||
|
<div class="lcd-value lcd-value-strong">{{ loadConfirmDialog.detail.扫码物料编码 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-field lcd-field-program-no">
|
||||||
|
<div class="lcd-label">程序号</div>
|
||||||
|
<div class="lcd-value lcd-value-mono">{{ loadConfirmProgramNo || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lcd-card">
|
||||||
|
<div class="lcd-info-grid">
|
||||||
|
<div class="lcd-info-item">
|
||||||
|
<div class="lcd-info-label">工位号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.工位号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item">
|
||||||
|
<div class="lcd-info-label">序列号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.扫码序列号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item lcd-info-item-full">
|
||||||
|
<div class="lcd-info-label">工单号</div>
|
||||||
|
<div class="lcd-info-value">{{ loadConfirmDialog.detail.工单号 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="lcd-info-item lcd-info-item-full">
|
||||||
|
<div class="lcd-info-label">扫码值</div>
|
||||||
|
<div class="lcd-info-value lcd-info-value-mono">{{ loadConfirmDialog.detail.扫码值 || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="lcd-footer">
|
||||||
|
<el-button @click="loadConfirmDialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="loadConfirmDialog.loading" @click="confirmLoadDialog">确 认 上 线</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -366,10 +457,14 @@ import { mqttIp, mqttTopic, mqttInitRequestTopic, writePlcApi_BtnType, selectOpN
|
|||||||
const PROGRAM_VERSION_TAG_ID = '208640'
|
const PROGRAM_VERSION_TAG_ID = '208640'
|
||||||
|
|
||||||
/** 程序版本下拉选项 */
|
/** 程序版本下拉选项 */
|
||||||
const PROGRAM_VERSION_OPTIONS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
/** 程序版本可选项(PLC 实际可写的字符值) */
|
||||||
|
const PROGRAM_VERSION_OPTIONS = []
|
||||||
|
|
||||||
/** 轮询读取的所有 PLC 信号标识 */
|
/** 轮询读取的所有 PLC 信号标识 */
|
||||||
const POLL_TAG_IDS = ['200004', '200005', '200006', '200007', '200380', '203240', '200440', PROGRAM_VERSION_TAG_ID]
|
const POLL_TAG_IDS = ['200004', '200005', '200006', '200007', '200380', '203240', '200440']
|
||||||
|
|
||||||
|
/** 上次使用的程序版本 localStorage key 前缀(按工位独立) */
|
||||||
|
const LAST_VERSION_STORAGE_PREFIX = 'ZL_DJ_LastProgramVersion_'
|
||||||
|
|
||||||
/** 状态灯信号 → data 属性映射 */
|
/** 状态灯信号 → data 属性映射 */
|
||||||
const STATUS_TAG_MAP = {
|
const STATUS_TAG_MAP = {
|
||||||
@@ -404,6 +499,9 @@ export default {
|
|||||||
// 双工位扫码验证数据
|
// 双工位扫码验证数据
|
||||||
ws1Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
ws1Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
||||||
ws2Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
ws2Result: { 扫码值: '', 工单号: '', 扫码物料编码: '', 扫码序列号: '', 错误消息: '', 验证结果: '', 程序版本: '' },
|
||||||
|
// 是否已处理过首次扫码(首次:自动取最近一次版本,不弹窗;之后:弹窗手动选)
|
||||||
|
ws1FirstVerifyHandled: false,
|
||||||
|
ws2FirstVerifyHandled: false,
|
||||||
programVersionOptions: PROGRAM_VERSION_OPTIONS,
|
programVersionOptions: PROGRAM_VERSION_OPTIONS,
|
||||||
// 双工位托盘信息
|
// 双工位托盘信息
|
||||||
ws1Tray: { 托盘号: '', 托盘物料编码: '', 托盘工件状态: '' },
|
ws1Tray: { 托盘号: '', 托盘物料编码: '', 托盘工件状态: '' },
|
||||||
@@ -424,10 +522,41 @@ export default {
|
|||||||
isResetSerialLoading: false,
|
isResetSerialLoading: false,
|
||||||
// 轮询定时器(按工位分别存储,支持双工位同时轮询)
|
// 轮询定时器(按工位分别存储,支持双工位同时轮询)
|
||||||
pollTimers: {},
|
pollTimers: {},
|
||||||
|
// 历史程序版本选择弹窗
|
||||||
|
versionDialog: {
|
||||||
|
visible: false,
|
||||||
|
opName: '',
|
||||||
|
partCode: '',
|
||||||
|
historyList: [],
|
||||||
|
selectedVersion: ''
|
||||||
|
},
|
||||||
|
// 手动上线二次确认弹窗
|
||||||
|
loadConfirmDialog: {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
opName: '',
|
||||||
|
detail: {
|
||||||
|
工位号: '', 扫码值: '', 工单号: '', 扫码序列号: '', 扫码物料编码: '', 程序版本: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['id', 'token'])
|
...mapGetters(['id', 'token', 'name']),
|
||||||
|
versionDialogOptions() {
|
||||||
|
const merged = [...this.versionDialog.historyList]
|
||||||
|
this.programVersionOptions.forEach(v => {
|
||||||
|
if (!merged.includes(v)) merged.push(v)
|
||||||
|
})
|
||||||
|
return merged
|
||||||
|
},
|
||||||
|
/** 上线信息确认弹窗 - 程序号 = 程序版本 + 物料编码 */
|
||||||
|
loadConfirmProgramNo() {
|
||||||
|
const ver = this.loadConfirmDialog.detail.程序版本 || ''
|
||||||
|
const code = this.loadConfirmDialog.detail.扫码物料编码 || ''
|
||||||
|
if (!ver && !code) return ''
|
||||||
|
return `${ver}${code}`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.opNameType === '转台上线') {
|
if (this.opNameType === '转台上线') {
|
||||||
@@ -518,7 +647,6 @@ export default {
|
|||||||
if (valueMap['200380'] !== undefined) tray.托盘号 = valueMap['200380']
|
if (valueMap['200380'] !== undefined) tray.托盘号 = valueMap['200380']
|
||||||
if (valueMap['203240'] !== undefined) this.convertMaterialCode(opName, valueMap['203240'])
|
if (valueMap['203240'] !== undefined) this.convertMaterialCode(opName, valueMap['203240'])
|
||||||
if (valueMap['200440'] !== undefined) tray.托盘工件状态 = TRAY_STATUS_TEXT[valueMap['200440']] || ''
|
if (valueMap['200440'] !== undefined) tray.托盘工件状态 = TRAY_STATUS_TEXT[valueMap['200440']] || ''
|
||||||
if (valueMap[PROGRAM_VERSION_TAG_ID] !== undefined) result.程序版本 = valueMap[PROGRAM_VERSION_TAG_ID] || ''
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 将PLC读取到的物料号通过存储过程转换为物料编码 */
|
/** 将PLC读取到的物料号通过存储过程转换为物料编码 */
|
||||||
@@ -715,7 +843,7 @@ export default {
|
|||||||
|
|
||||||
switch (interFaceType) {
|
switch (interFaceType) {
|
||||||
case 'VerifyResult': {
|
case 'VerifyResult': {
|
||||||
if (arrays_signal.length < 11) {
|
if (arrays_signal.length < 9) {
|
||||||
this.$message.warning('收到扫码结果,但是数据异常,不予处理!')
|
this.$message.warning('收到扫码结果,但是数据异常,不予处理!')
|
||||||
console.log(msg)
|
console.log(msg)
|
||||||
return
|
return
|
||||||
@@ -737,10 +865,22 @@ export default {
|
|||||||
targetResult.扫码物料编码 = arrays_signal[6]
|
targetResult.扫码物料编码 = arrays_signal[6]
|
||||||
targetResult.扫码序列号 = arrays_signal[7]
|
targetResult.扫码序列号 = arrays_signal[7]
|
||||||
targetResult.工单号 = arrays_signal[8]
|
targetResult.工单号 = arrays_signal[8]
|
||||||
targetResult.工单物料编号 = arrays_signal[9]
|
// targetResult.工单物料编号 = arrays_signal[9]
|
||||||
targetResult.工单序列号 = arrays_signal[10]
|
// targetResult.工单序列号 = arrays_signal[10]
|
||||||
if (targetResult.验证结果 == 1) {
|
if (targetResult.验证结果 == 1) {
|
||||||
this.$message.success('收到校验结果,校验通过!' + targetResult.错误消息)
|
this.$message.success('收到校验结果,校验通过!' + targetResult.错误消息)
|
||||||
|
if (pos === this.clickOpName) {
|
||||||
|
const isFirst = pos === this.opNameList[0]
|
||||||
|
? !this.ws1FirstVerifyHandled
|
||||||
|
: !this.ws2FirstVerifyHandled
|
||||||
|
if (isFirst) {
|
||||||
|
this.autoFillFirstVersion(pos)
|
||||||
|
if (pos === this.opNameList[0]) this.ws1FirstVerifyHandled = true
|
||||||
|
else this.ws2FirstVerifyHandled = true
|
||||||
|
} else {
|
||||||
|
this.openVersionDialog(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.isAutoPartLoad && this.clickOpName === pos) {
|
if (this.isAutoPartLoad && this.clickOpName === pos) {
|
||||||
this.partLoadOpName(targetResult.扫码工位)
|
this.partLoadOpName(targetResult.扫码工位)
|
||||||
}
|
}
|
||||||
@@ -804,17 +944,50 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
this.loadConfirmDialog.opName = opName
|
||||||
await this.$confirm('确定要执行手动请求上线操作吗?', '确认操作', {
|
this.loadConfirmDialog.detail = {
|
||||||
confirmButtonText: '确定',
|
工位号: opName,
|
||||||
cancelButtonText: '取消',
|
扫码值: result.扫码值 || '',
|
||||||
type: 'warning'
|
工单号: result.工单号 || '',
|
||||||
})
|
扫码序列号: result.扫码序列号 || '',
|
||||||
} catch (error) {
|
扫码物料编码: result.扫码物料编码 || '',
|
||||||
|
程序版本: programVersion
|
||||||
|
}
|
||||||
|
this.loadConfirmDialog.loading = false
|
||||||
|
this.loadConfirmDialog.visible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 二次确认弹窗"确定":把弹窗里的程序版本写回扫码结果,再走 PLC 写值流程 */
|
||||||
|
async confirmLoadDialog() {
|
||||||
|
const opName = this.loadConfirmDialog.opName
|
||||||
|
const version = this.loadConfirmDialog.detail.程序版本
|
||||||
|
? this.loadConfirmDialog.detail.程序版本.toString()
|
||||||
|
: ''
|
||||||
|
if (!version) {
|
||||||
|
this.$message.warning('请选择或输入程序版本!')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
result.程序版本 = version
|
||||||
|
this.setLastUsedVersion(opName, version)
|
||||||
|
|
||||||
|
this.loadConfirmDialog.loading = true
|
||||||
|
try {
|
||||||
|
await this.doPartLoad(opName)
|
||||||
|
} finally {
|
||||||
|
this.loadConfirmDialog.loading = false
|
||||||
|
this.loadConfirmDialog.visible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 实际执行 PLC 写值上线流程;成功后写入手动上线记录 */
|
||||||
|
async doPartLoad(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
const partLoadStatus = opName === this.opNameList[0] ? this.ws1PartLoadStatus : this.ws2PartLoadStatus
|
const partLoadStatus = opName === this.opNameList[0] ? this.ws1PartLoadStatus : this.ws2PartLoadStatus
|
||||||
|
const programVersion = result.程序版本 ? result.程序版本.toString() : ''
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
|
||||||
const plcValue = await this.getPLCValue(opName, '205015')
|
const plcValue = await this.getPLCValue(opName, '205015')
|
||||||
if (plcValue === 'True') {
|
if (plcValue === 'True') {
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
@@ -824,34 +997,112 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.writePLCValue(opName, PROGRAM_VERSION_TAG_ID, programVersion)
|
try {
|
||||||
.then(response => {
|
const r1 = await this.writePLCValue(opName, PROGRAM_VERSION_TAG_ID, programVersion)
|
||||||
if (response.data.code != 0) {
|
if (r1.data.code != 0) throw new Error(r1.data.msg || '程序版本写入失败')
|
||||||
return Promise.reject(new Error(response.data.msg || '程序版本写入失败'))
|
const r2 = await this.writePLCValue(opName, '205015', 'true')
|
||||||
}
|
if (r2.data.code == 0) {
|
||||||
return this.writePLCValue(opName, '205015', 'true')
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.code == 0) {
|
|
||||||
partLoadStatus.success = true
|
partLoadStatus.success = true
|
||||||
partLoadStatus.message = ''
|
partLoadStatus.message = ''
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.success('申请上线成功!')
|
this.$message.success('申请上线成功!')
|
||||||
|
this.recordManualLoad(opName, partCode, programVersion)
|
||||||
} else {
|
} else {
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
partLoadStatus.message = response.data.msg || '申请失败'
|
partLoadStatus.message = r2.data.msg || '申请失败'
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.error(response.data.msg)
|
this.$message.error(r2.data.msg)
|
||||||
}
|
}
|
||||||
})
|
} catch (error) {
|
||||||
.catch(error => {
|
|
||||||
partLoadStatus.success = false
|
partLoadStatus.success = false
|
||||||
partLoadStatus.message = error.message
|
partLoadStatus.message = error.message
|
||||||
partLoadStatus.show = true
|
partLoadStatus.show = true
|
||||||
this.$message.error('申请上线失败' + error.message)
|
this.$message.error('申请上线失败' + error.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 写入手动上线 (物料编码,程序版本) 记录 */
|
||||||
|
recordManualLoad(opName, partCode, version) {
|
||||||
|
if (!partCode || !version) return
|
||||||
|
const param = []
|
||||||
|
param[0] = ['物料编码', partCode]
|
||||||
|
param[1] = ['程序版本', version]
|
||||||
|
param[2] = ['工位号', opName]
|
||||||
|
param[3] = ['操作人', this.name || '']
|
||||||
|
const Data = this.CreateData('12', 'ZL_物料程序版本_手动上线记录_Insert', param)
|
||||||
|
this.ExecDatabase(Data).catch(err => console.error('记录手动上线失败:', err))
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 历史程序版本弹窗 ====================
|
||||||
|
|
||||||
|
/** 查询某物料编码的历史程序版本(按最近使用时间倒序) */
|
||||||
|
loadHistoryVersions(partCode) {
|
||||||
|
if (!partCode) return Promise.resolve([])
|
||||||
|
const param = [['物料编码', partCode]]
|
||||||
|
const Data = this.CreateData('11', 'ZL_物料程序版本_手动上线记录_查询历史版本', param)
|
||||||
|
return this.ExecDatabase(Data)
|
||||||
|
.then(resp => Array.isArray(resp.data) ? resp.data.map(r => r.程序版本).filter(v => !!v) : [])
|
||||||
|
.catch(err => {
|
||||||
|
console.error('查询历史程序版本失败:', err)
|
||||||
|
return []
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 打开"选择程序版本"弹窗:扫码验证通过且为当前工位时触发 */
|
||||||
|
async openVersionDialog(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
const historyList = await this.loadHistoryVersions(partCode)
|
||||||
|
const lastUsed = this.getLastUsedVersion(opName)
|
||||||
|
this.versionDialog.opName = opName
|
||||||
|
this.versionDialog.partCode = partCode
|
||||||
|
this.versionDialog.historyList = historyList
|
||||||
|
this.versionDialog.selectedVersion = (result.程序版本 || lastUsed || historyList[0] || '')
|
||||||
|
this.versionDialog.visible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 首次扫码:从数据库取该物料最近一次的程序版本,直接回填,不弹窗 */
|
||||||
|
async autoFillFirstVersion(opName) {
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
const partCode = result.扫码物料编码 || ''
|
||||||
|
if (!partCode) return
|
||||||
|
const historyList = await this.loadHistoryVersions(partCode)
|
||||||
|
if (historyList && historyList.length > 0) {
|
||||||
|
result.程序版本 = historyList[0]
|
||||||
|
this.setLastUsedVersion(opName, historyList[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** "选择程序版本"弹窗确定:把版本回填到对应工位,不自动上线 */
|
||||||
|
confirmVersionDialog() {
|
||||||
|
const version = this.versionDialog.selectedVersion ? this.versionDialog.selectedVersion.toString() : ''
|
||||||
|
if (!version) {
|
||||||
|
this.$message.warning('请选择或输入程序版本!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const opName = this.versionDialog.opName
|
||||||
|
const result = opName === this.opNameList[0] ? this.ws1Result : this.ws2Result
|
||||||
|
result.程序版本 = version
|
||||||
|
this.setLastUsedVersion(opName, version)
|
||||||
|
this.versionDialog.visible = false
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 读取该工位上一次使用的程序版本(localStorage) */
|
||||||
|
getLastUsedVersion(opName) {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(LAST_VERSION_STORAGE_PREFIX + opName) || ''
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 持久化保存该工位本次使用的程序版本(localStorage) */
|
||||||
|
setLastUsedVersion(opName, version) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(LAST_VERSION_STORAGE_PREFIX + opName, version || '')
|
||||||
|
} catch (e) { /* ignore */ }
|
||||||
|
},
|
||||||
|
|
||||||
// ==================== 读码 / 写码 / 清码 ====================
|
// ==================== 读码 / 写码 / 清码 ====================
|
||||||
|
|
||||||
/** 写码 - 发送写码请求并启动10秒轮询 */
|
/** 写码 - 发送写码请求并启动10秒轮询 */
|
||||||
@@ -1035,4 +1286,400 @@ export default {
|
|||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.material-version-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
|
||||||
|
.mv-version {
|
||||||
|
flex: 0 0 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-material {
|
||||||
|
flex: 2 1 0;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-result {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 0 0 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-input {
|
||||||
|
::v-deep .el-input__inner {
|
||||||
|
text-align: right;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-display {
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.result-pass,
|
||||||
|
.result-fail,
|
||||||
|
.result-error {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-pass { background: #aaff33; color: #222; }
|
||||||
|
.result-fail { background: #ff3b3b; color: #fff; }
|
||||||
|
.result-error { background: #ffe066; color: #222; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upline-form {
|
||||||
|
::v-deep .el-form-item__label {
|
||||||
|
width: 70px !important;
|
||||||
|
padding-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
|
width: calc(100% - 70px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.version-dialog {
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
padding: 18px 24px 14px;
|
||||||
|
background: linear-gradient(135deg, #f5f9ff 0%, #ffffff 100%);
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
top: 18px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 18px 24px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 12px 24px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-header {
|
||||||
|
.vd-title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.vd-subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-body {
|
||||||
|
.vd-section-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #606266;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.vd-count {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-section-title-spaced {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-tag-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
max-height: 180px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 4px 4px 4px 0;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 14px;
|
||||||
|
min-width: 56px;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #f4f6fa;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all 0.18s ease;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #e8f0ff;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #409eff;
|
||||||
|
box-shadow: 0 4px 10px rgba(64, 158, 255, 0.28);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-empty {
|
||||||
|
padding: 18px 12px;
|
||||||
|
background: #fafbfc;
|
||||||
|
border: 1px dashed #dcdfe6;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.vd-empty-text {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
.vd-empty-hint {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vd-footer {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-confirm-dialog {
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.18);
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
padding: 18px 24px 14px;
|
||||||
|
background: linear-gradient(135deg, #fff7eb 0%, #ffffff 100%);
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
top: 18px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 18px 22px 6px;
|
||||||
|
background: #f7f9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 14px 22px 18px;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-header {
|
||||||
|
.lcd-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.lcd-subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-card {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.lcd-card-primary {
|
||||||
|
background: linear-gradient(180deg, #ffffff 0%, #fafcff 100%);
|
||||||
|
border-color: #d9e7ff;
|
||||||
|
padding-top: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-card-tag {
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
left: 14px;
|
||||||
|
background: #ff9d00;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
box-shadow: 0 2px 6px rgba(255, 157, 0, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-row-2col {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.4fr 1fr;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-row-2col-key {
|
||||||
|
grid-template-columns: 0.5fr 1.5fr;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-field {
|
||||||
|
.lcd-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.lcd-value {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 500;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 7px 12px;
|
||||||
|
background: #f4f6fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
min-height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.lcd-value-strong {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ff7a00;
|
||||||
|
background: #fff5e6;
|
||||||
|
border: 1px solid #ffe1b3;
|
||||||
|
}
|
||||||
|
.lcd-value-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.lcd-value-mono {
|
||||||
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-field-program-no {
|
||||||
|
.lcd-value {
|
||||||
|
background: #f0f7ff;
|
||||||
|
border: 1px dashed #b3d4ff;
|
||||||
|
color: #1f6feb;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-select {
|
||||||
|
width: 100%;
|
||||||
|
.el-input__inner {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&.lcd-info-item-full {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-value {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #303133;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-info-value-mono {
|
||||||
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||||
|
font-size: 12.5px;
|
||||||
|
color: #606266;
|
||||||
|
background: #f4f6fa;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lcd-footer {
|
||||||
|
text-align: right;
|
||||||
|
.el-button {
|
||||||
|
min-width: 90px;
|
||||||
|
}
|
||||||
|
.el-button--primary {
|
||||||
|
min-width: 130px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ export const name4_config = `OP9999`
|
|||||||
// 工厂网段 192.168.0.180 生产环境需使用
|
// 工厂网段 192.168.0.180 生产环境需使用
|
||||||
// 开发环境使用 127.0.0.1
|
// 开发环境使用 127.0.0.1
|
||||||
|
|
||||||
// var url = `http://192.168.0.180:10140`
|
var url = `http://192.168.0.180:10140`
|
||||||
// var api = `http://192.168.0.180:9981`
|
var api = `http://192.168.0.180:9981`
|
||||||
|
|
||||||
var url = `http://127.0.0.1:10140`
|
// var url = `http://127.0.0.1:10140`
|
||||||
var api = `http://127.0.0.1:9981`
|
// var api = `http://127.0.0.1:9981`
|
||||||
|
|
||||||
// var url = `http://192.168.0.180:10140`
|
// var url = `http://192.168.0.180:10140`
|
||||||
// export const mqttIp = `192.168.0.180`
|
// export const mqttIp = `127.0.0.1`
|
||||||
export const mqttIp = `192.168.0.180`
|
export const mqttIp = `192.168.0.180`
|
||||||
export const mqttTopic = `VerifyResult`
|
export const mqttTopic = `VerifyResult`
|
||||||
export const mqttInitRequestTopic = `MesServer`
|
export const mqttInitRequestTopic = `MesServer`
|
||||||
|
|||||||
Reference in New Issue
Block a user