This commit is contained in:
sheng
2026-06-22 16:08:08 +08:00
6 changed files with 889 additions and 3 deletions

View File

@@ -3,8 +3,8 @@
> 根据 `后台Webman界面截图对照表.md` 生成。状态以当前 V2 项目中已落地的页面目录为准。
- 总功能数79
- 已迁移24
- 未迁移55
- 已迁移25
- 未迁移54
| 状态 | 一级模块 | 二级模块 | 三级模块 | 功能说明 | V2 目标路径 |
|:---:|---|---|---|---|---|
@@ -50,7 +50,7 @@
| ⬜ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 物料监控 (Material Monitoring) | 物料监控 | 待确认 |
| ⬜ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 电池复投管理 (Rework Management) | 返工管理 | 待确认 |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 托盘管理 (Tray Management) | 托盘管理 | `src/views/planning-production/production-monitoring/tray-management/` |
| | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 托盘登录 (Tray Registration) | 托盘登记 | 待确认 |
| | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 托盘登录 (Tray Registration) | 托盘登记 | `src/views/planning-production/production-monitoring/tray-registration/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 设备监控 (Equipment Monitoring) | 设备监控 | `src/views/planning-production/production-monitoring/equipment-monitoring/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 电池工序管理 (Process Execution) | 工序管理 | `src/views/planning-production/production-monitoring/process-execution/` |
| ⬜ | 质量管理 (Quality Management) | 过程控制 (Process Control) | 检验类别管理 (Inspection Type Management) | | 待确认 |

View File

@@ -0,0 +1,51 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/tray_login/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getBatchAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('planning_production_produce_traylogin_all', data)
})
}
export function getBatchTrayFormatAll (data) {
return request({
url: BASE + 'trayformat_all',
method: 'get',
params: apiParams('planning_production_produce_trayformat_all', data)
})
}
export function createBatchTrayFormat (data) {
return request({
url: BASE + 'create',
method: 'get',
params: apiParams('planning_production_produce_trayformat_create', data)
})
}
export function deleteBatchTrayFormat (data) {
return request({
url: BASE + 'delete',
method: 'get',
params: apiParams('planning_production_produce_trayformat_delete', data)
})
}
export function checkBatteryid (data) {
return request({
url: BASE + 'check_batteryid',
method: 'get',
params: apiParams('planning_production_produce_trayformat_check_batteryid', data)
})
}

View File

@@ -1078,6 +1078,73 @@
"exception": "Exception",
"offline": "Offline",
"idle": "Waiting for Material"
},
"tray_registration": {
"query": "Search",
"reset": "Reset",
"login": "Register",
"tray_unbind": "Unbind Tray",
"tray_stop": "Stop Tray",
"add": "Add",
"delete": "Delete",
"confirm": "Confirm",
"cancel": "Cancel",
"prompt": "Notice",
"data_table": "Data Table",
"process_channel": "Channel",
"battery_id": "Battery ID",
"previous_batch": "Previous Batch",
"previous_tray": "Previous Tray",
"completed_process": "Completed Process",
"tray_barcode_format": "Tray Barcode Format",
"battery_barcode_format": "Battery Barcode Format",
"tray_battery_count": "Tray Capacity",
"operation": "Actions",
"batch_no": "Batch No.",
"enter_batch_no": "Enter batch number",
"tray_code": "Tray Code",
"enter_tray_code": "Enter tray code",
"battery_code": "Battery Code",
"enter_battery_code": "Enter battery code",
"tray_code_format": "Tray Code Format",
"battery_code_format": "Battery Code Format",
"tray_battery_format_edit": "Tray & Battery Format Editor",
"format_dialog_title": "Tray & Battery Format",
"submit_login": "Submit Registration",
"add_format_title": "Add Format",
"format_error": "Invalid format",
"process_flow_name": "Process Flow Name",
"format_error_exclamation": "Invalid format!",
"insert_duplicate_battery": "Duplicate battery",
"delete_confirm": "Delete this format?",
"delete_success": "Deleted successfully",
"add_tray_format": "Add tray format",
"add_battery_format": "Add battery format",
"add_battery_count": "Add battery count",
"tray_unbind_desc": "Note: unbinding deactivates the tray, but batteries remain activated.",
"tray_unbind_success": "Tray unbound successfully",
"tray_stop_desc": "Note: stopping deactivates both tray and batteries.",
"tray_stop_success": "Tray stopped successfully",
"enter_tray_no": "Enter tray number",
"batch_create_time": "Batch Create Time",
"tray_load_battery_count": "Loaded Count",
"batch_deactivate": "Batch Deactivate",
"please_enter_tray_code": "Please enter tray code",
"upload_success": "Upload successful",
"no_batch_no": "No batch number",
"has_active_battery_login_forbidden": "Cannot register: contains activated batteries.",
"select_battery_to_deactivate": "Select batteries to deactivate",
"battery_deactivate": "Battery Deactivation",
"batch_battery_deactivate_success": "Batch deactivation successful",
"channel": "Channel:",
"select_format": "Select format",
"select_format_first": "Select tray and battery format first",
"activation_status": "Activation Status",
"activated": "Activated",
"not_activated": "Not Activated",
"operation_success": "Operation successful",
"operation_failed": "Operation failed",
"format_rule": "Format rule: fixed characters are literal; use * for variable characters, e.g. A** or ******."
}
},
"alert_center": {

View File

@@ -1078,6 +1078,73 @@
"exception": "异常中",
"offline": "离线中",
"idle": "待料中"
},
"tray_registration": {
"query": "查询",
"reset": "重置",
"login": "登录",
"tray_unbind": "托盘解绑",
"tray_stop": "托盘停止",
"add": "新增",
"delete": "删除",
"confirm": "确定",
"cancel": "取消",
"prompt": "提示",
"data_table": "数据表",
"process_channel": "通道",
"battery_id": "电池ID",
"previous_batch": "上一个批次",
"previous_tray": "上一个托盘",
"completed_process": "电池已完成工序",
"tray_barcode_format": "托盘条码格式",
"battery_barcode_format": "电池条码格式",
"tray_battery_count": "托盘装载电池数量",
"operation": "操作",
"batch_no": "批次号",
"enter_batch_no": "请输入批次号",
"tray_code": "托盘编码",
"enter_tray_code": "请输入托盘编码",
"battery_code": "电池编码",
"enter_battery_code": "请输入电池编码",
"tray_code_format": "托盘编码格式",
"battery_code_format": "电池编码格式",
"tray_battery_format_edit": "托盘与电池格式编辑",
"format_dialog_title": "托盘与电池格式",
"submit_login": "提交登录",
"add_format_title": "新增格式",
"format_error": "格式不对",
"process_flow_name": "工艺流程名称",
"format_error_exclamation": "格式不对!",
"insert_duplicate_battery": "插入重复电池",
"delete_confirm": "删除这条格式?",
"delete_success": "删除成功",
"add_tray_format": "请添加托盘格式",
"add_battery_format": "请添加电池格式",
"add_battery_count": "请添加电池数量",
"tray_unbind_desc": "说明:托盘解绑后,该托盘的状态是取消激活的,与它装载的电池还是激活状态",
"tray_unbind_success": "托盘解绑成功",
"tray_stop_desc": "说明:托盘停止后,该托盘和它装载的电池会一同取消激活",
"tray_stop_success": "托盘停止成功",
"enter_tray_no": "请输入托盘号",
"batch_create_time": "批次创建时间",
"tray_load_battery_count": "装载电池数量",
"batch_deactivate": "批量取消激活",
"please_enter_tray_code": "请填写托盘编码",
"upload_success": "上传成功",
"no_batch_no": "没有批次号",
"has_active_battery_login_forbidden": "有电池属于激活状态,无法登录",
"select_battery_to_deactivate": "请选择需要取消激活的电池",
"battery_deactivate": "电池取消激活",
"batch_battery_deactivate_success": "批量取消电池激活成功",
"channel": "通道:",
"select_format": "请选择格式",
"select_format_first": "请先选择托盘与电池格式",
"activation_status": "激活状态",
"activated": "已激活",
"not_activated": "未激活",
"operation_success": "操作成功",
"operation_failed": "操作失败",
"format_rule": "格式规则:固定字符直接填写,可变字符使用 * 代替,例如 A** 或 ******。"
}
},
"alert_center": {

View File

@@ -44,6 +44,12 @@ export default {
meta: { ...meta, cache: true, title: '托盘管理' },
component: _import('planning-production/production-monitoring/tray-management')
},
{
path: 'produce/monitor/tray_login',
name: `${pre}monitor-tray_login`,
meta: { ...meta, cache: true, title: '托盘登录' },
component: _import('planning-production/production-monitoring/tray-registration')
},
{
path: 'produce/monitor/device',
name: `${pre}monitor-device`,

View File

@@ -0,0 +1,695 @@
<template>
<d2-container>
<template #header>
<div class="search-bar">
<el-form ref="form" :inline="true" :model="form" size="mini">
<el-form-item :label="$t(key('batch_no'))" prop="batch">
<el-input
v-model="form.batch"
:placeholder="$t(key('enter_batch_no'))"
clearable
readonly
style="width:220px"
@focus="openBatchDialog"
>
<el-button slot="append" icon="el-icon-search" @click="openBatchDialog" />
</el-input>
</el-form-item>
<el-form-item :label="$t(key('tray_code_format'))">
<el-select
v-model="selectedFormatId"
:placeholder="$t(key('select_format'))"
filterable
style="width:220px"
@change="selectFormat"
>
<el-option
v-for="item in formatList"
:key="item.id"
:label="formatLabel(item)"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="$t(key('tray_code'))" prop="tray">
<el-input
v-model="form.tray"
:placeholder="$t(key('enter_tray_code'))"
:disabled="!currentFormat"
clearable
style="width:220px"
@keyup.enter.native="focusFirstChannel"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-check" :disabled="submitting" @click="openSubmitDialog">
{{ $t(key('login')) }}
</el-button>
<el-button type="warning" icon="el-icon-unlock" :disabled="submitting" @click="unbindTray">
{{ $t(key('tray_unbind')) }}
</el-button>
<el-button type="danger" icon="el-icon-switch-button" :disabled="submitting" @click="stopTray">
{{ $t(key('tray_stop')) }}
</el-button>
<el-button icon="el-icon-edit" :disabled="loadingFormats" @click="openFormatDialog">
{{ $t(key('tray_battery_format_edit')) }}
</el-button>
<el-button icon="el-icon-refresh" :disabled="submitting" @click="resetPage">
{{ $t(key('reset')) }}
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<div class="registration-layout">
<section class="channel-panel">
<div class="panel-head">
<span>{{ $t(key('data_table')) }}</span>
<el-tag size="mini">{{ loadedCount }} / {{ capacity }}</el-tag>
</div>
<el-empty v-if="!currentFormat" :description="$t(key('select_format_first'))" :image-size="80" />
<div v-else class="channel-grid">
<el-form label-width="74px" size="mini">
<el-form-item
v-for="channel in channelList"
:key="channel"
:label="$t(key('channel')) + channel"
>
<el-input
:ref="inputRef(channel)"
v-model="batteryInputs[channel]"
:placeholder="$t(key('enter_battery_code'))"
clearable
@keyup.enter.native="scanBattery(channel)"
@clear="removeBattery(channel)"
/>
</el-form-item>
</el-form>
</div>
</section>
<section class="battery-panel">
<div class="panel-head">
<span>{{ $t(key('tray_load_battery_count')) }}</span>
<el-button
type="text"
class="danger-action"
:disabled="!selectedRows.length"
@click="batchInactivity"
>
{{ $t(key('batch_deactivate')) }}
</el-button>
</div>
<page-table
:columns="columns"
:data="tableData"
:loading="loadingBattery"
:toolbar-buttons="[]"
:row-buttons="[]"
:pagination="null"
:table-attrs="{ size: 'mini', rowKey: 'index', highlightCurrentRow: true, rowClassName: rowClassName }"
height="520px"
@selection-change="selectedRows = $event"
>
<template #col-battery="{ row }">
<span>{{ row.Battery || row.battery_id }}</span>
</template>
<template #col-active="{ row }">
<el-tag :type="Number(row.active) === 1 ? 'danger' : 'success'" size="mini">
{{ Number(row.active) === 1 ? $t(key('activated')) : $t(key('not_activated')) }}
</el-tag>
</template>
<template #empty>
<el-empty :description="$t('暂无数据')" :image-size="80" />
</template>
</page-table>
</section>
</div>
<el-dialog :title="$t(key('batch_no'))" :visible.sync="batchDialogVisible" width="760px">
<page-table
:columns="batchColumns"
:data="batchList"
:loading="loadingBatches"
:toolbar-buttons="[]"
:row-buttons="[]"
:pagination="null"
:table-attrs="{ size: 'mini', rowKey: 'batch', highlightCurrentRow: true }"
height="420px"
@row-dblclick="selectBatch"
/>
</el-dialog>
<el-dialog :title="$t(key('format_dialog_title'))" :visible.sync="formatDialogVisible" width="820px">
<el-button type="primary" size="mini" icon="el-icon-plus" @click="openFormatForm">
{{ $t(key('add')) }}
</el-button>
<page-table
class="format-table"
:columns="formatColumns"
:data="formatList"
:loading="loadingFormats"
:toolbar-buttons="[]"
:row-buttons="[]"
:pagination="null"
:table-attrs="{ size: 'mini', rowKey: 'id', highlightCurrentRow: true }"
height="360px"
@row-dblclick="selectFormatRow"
>
<template #col-actions="{ row }">
<el-button type="text" class="danger-action" @click="deleteFormat(row)">
{{ $t(key('delete')) }}
</el-button>
</template>
</page-table>
</el-dialog>
<el-dialog :title="$t(key('add_format_title'))" :visible.sync="formatFormVisible" width="620px">
<el-form :model="formatForm" label-width="150px" size="mini">
<el-form-item :label="$t(key('tray_barcode_format'))">
<el-input v-model="formatForm.tray_format" clearable />
</el-form-item>
<el-form-item :label="$t(key('battery_barcode_format'))">
<el-input v-model="formatForm.battery_format" clearable />
</el-form-item>
<el-form-item :label="$t(key('tray_battery_count'))">
<el-input-number v-model="formatForm.battery_count" :min="1" :max="96" />
</el-form-item>
</el-form>
<el-alert :title="$t(key('format_rule'))" type="warning" :closable="false" />
<span slot="footer">
<el-button size="mini" @click="formatFormVisible = false">{{ $t(key('cancel')) }}</el-button>
<el-button size="mini" type="primary" @click="createFormat">{{ $t(key('confirm')) }}</el-button>
</span>
</el-dialog>
<el-dialog :title="$t(key('submit_login'))" :visible.sync="submitDialogVisible" width="640px">
<page-table
:columns="submitColumns"
:data="tableData"
:loading="submitting"
:toolbar-buttons="[]"
:row-buttons="[]"
:pagination="null"
:table-attrs="{ size: 'mini', rowKey: 'index' }"
height="360px"
>
<template #col-battery="{ row }">
<span>{{ row.Battery || row.battery_id }}</span>
</template>
</page-table>
<span slot="footer">
<el-button size="mini" @click="submitDialogVisible = false">{{ $t(key('cancel')) }}</el-button>
<el-button size="mini" type="primary" :disabled="submitting" @click="submitRegistration">
{{ $t(key('confirm')) }}
</el-button>
</span>
</el-dialog>
</d2-container>
</template>
<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { i18nMixin } from '@/composables/useI18n'
import PageTable from '@/components/page-table'
import { sendWorkerman } from '@/api/production-master-data/workerman'
import {
getBatchAll,
getBatchTrayFormatAll,
createBatchTrayFormat,
deleteBatchTrayFormat,
checkBatteryid
} from '@/api/planning-production/tray-registration'
export default {
name: 'planning-production-tray-registration',
components: { PageTable },
mixins: [i18nMixin('page.planning_production.production_monitoring.tray_registration')],
data () {
return {
form: {
batch: '',
tray: ''
},
selectedFormatId: '',
currentFormat: null,
batteryInputs: {},
tableData: [],
batchList: [],
formatList: [],
selectedRows: [],
batchDialogVisible: false,
formatDialogVisible: false,
formatFormVisible: false,
submitDialogVisible: false,
loadingBatches: false,
loadingFormats: false,
loadingBattery: false,
submitting: false,
formatForm: {
tray_format: '',
battery_format: '',
battery_count: 1
}
}
},
computed: {
capacity () {
return Number((this.currentFormat && this.currentFormat.battery_count) || 0)
},
loadedCount () {
return this.tableData.length
},
channelList () {
return Array.from({ length: this.capacity }, (_, index) => index + 1)
},
trayRegExp () {
return this.createFormatRegExp(this.currentFormat && this.currentFormat.tray_format)
},
batteryRegExp () {
return this.createFormatRegExp(this.currentFormat && this.currentFormat.battery_format)
},
columns () {
return useTableColumns([
{ prop: 'index', label: this.key('process_channel'), width: 90 },
{ prop: 'Battery', label: this.key('battery_id'), minWidth: 180, slot: 'battery', showOverflowTooltip: true },
{ prop: 'active', label: this.key('activation_status'), width: 110, slot: 'active' },
{ prop: 'batch', label: this.key('previous_batch'), minWidth: 150, showOverflowTooltip: true },
{ prop: 'tray', label: this.key('previous_tray'), minWidth: 150, showOverflowTooltip: true },
{ prop: 'process_code', label: this.key('completed_process'), minWidth: 160, showOverflowTooltip: true }
], {
selectionWidth: 55,
indexWidth: 0
})
},
batchColumns () {
return useTableColumns([
{ prop: 'batch', label: this.key('batch_no'), minWidth: 200, showOverflowTooltip: true },
{ prop: 'flow_name', label: this.key('process_flow_name'), minWidth: 200, showOverflowTooltip: true },
{ prop: 'create_time', label: this.key('batch_create_time'), minWidth: 180, showOverflowTooltip: true }
], {
selectionWidth: 0,
indexWidth: 55
})
},
formatColumns () {
return useTableColumns([
{ prop: 'tray_format', label: this.key('tray_barcode_format'), minWidth: 160, showOverflowTooltip: true },
{ prop: 'battery_format', label: this.key('battery_barcode_format'), minWidth: 180, showOverflowTooltip: true },
{ prop: 'battery_count', label: this.key('tray_battery_count'), width: 140 },
{ prop: 'actions', label: this.key('operation'), width: 90, slot: 'actions' }
], {
selectionWidth: 0,
indexWidth: 55
})
},
submitColumns () {
return useTableColumns([
{ prop: 'index', label: this.key('process_channel'), width: 120 },
{ prop: 'Battery', label: this.key('battery_id'), minWidth: 220, slot: 'battery', showOverflowTooltip: true }
], {
selectionWidth: 0,
indexWidth: 0
})
}
},
created () {
this.fetchBatchList()
this.fetchFormatList()
},
methods: {
responseData (res) {
const payload = res && res.data ? res.data : (res || {})
return payload.data || payload
},
formatLabel (item) {
return `${item.tray_format} / ${item.battery_format} / ${item.battery_count}`
},
inputRef (channel) {
return `batteryInput${channel}`
},
createFormatRegExp (format) {
if (!format) return null
const escaped = String(format).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[A-Z0-9-]')
return new RegExp(`^${escaped}$`)
},
openBatchDialog () {
this.batchDialogVisible = true
if (!this.batchList.length) this.fetchBatchList()
},
selectBatch (row) {
this.form.batch = row.batch
this.batchDialogVisible = false
},
async fetchBatchList () {
this.loadingBatches = true
try {
const res = await getBatchAll({ action: 'get_batch' })
const data = this.responseData(res)
this.batchList = Array.isArray(data) ? data : []
} finally {
this.loadingBatches = false
}
},
async fetchFormatList () {
this.loadingFormats = true
try {
const res = await getBatchTrayFormatAll({ action: 'get_login_format' })
const data = this.responseData(res)
this.formatList = Array.isArray(data) ? data : []
if (!this.currentFormat && this.formatList.length) {
this.selectFormat(this.formatList[0].id)
}
} finally {
this.loadingFormats = false
}
},
selectFormat (id) {
const target = this.formatList.find(item => String(item.id) === String(id))
if (!target) return
this.currentFormat = target
this.selectedFormatId = target.id
this.tableData = []
this.selectedRows = []
this.batteryInputs = {}
},
selectFormatRow (row) {
this.selectFormat(row.id)
this.formatDialogVisible = false
},
focusFirstChannel () {
if (!this.validateTray()) return
this.$nextTick(() => {
const refs = this.$refs[this.inputRef(1)]
const input = Array.isArray(refs) ? refs[0] : refs
if (input) input.focus()
})
},
validateTray () {
if (!this.currentFormat) {
this.$message.warning(this.$t(this.key('select_format_first')))
return false
}
if (!this.form.tray) {
this.$message.warning(this.$t(this.key('please_enter_tray_code')))
return false
}
if (this.trayRegExp && !this.trayRegExp.test(this.form.tray)) {
this.$message.warning(this.$t(this.key('format_error_exclamation')))
return false
}
return true
},
async scanBattery (channel) {
if (!this.validateTray()) return
const batteryId = this.batteryInputs[channel]
if (!batteryId) {
this.removeBattery(channel)
return
}
if (this.batteryRegExp && !this.batteryRegExp.test(batteryId)) {
this.$message.warning(this.$t(this.key('format_error')))
this.removeBattery(channel)
return
}
const duplicate = this.tableData.find(item => item.index !== channel && item.Battery === batteryId)
if (duplicate) {
this.$message.warning(this.$t(this.key('insert_duplicate_battery')))
this.removeBattery(channel)
return
}
this.loadingBattery = true
try {
const res = await checkBatteryid({
action: 'check_elements_code',
battery_id: batteryId
})
const payload = res && res.data ? res.data : (res || {})
const data = payload.data || {}
if (payload.code !== undefined && Number(payload.code) !== 0) {
this.$message.error(payload.msg || payload.errmsg || this.$t(this.key('format_error')))
this.removeBattery(channel)
return
}
const row = {
...data,
Battery: batteryId,
battery_id: data.battery_id || batteryId,
index: channel
}
const exists = this.tableData.findIndex(item => item.index === channel)
if (exists >= 0) {
this.$set(this.tableData, exists, row)
} else {
this.tableData.push(row)
}
this.tableData.sort((a, b) => a.index - b.index)
this.focusNextChannel(channel)
} finally {
this.loadingBattery = false
}
},
focusNextChannel (channel) {
const next = channel + 1
if (next > this.capacity) return
this.$nextTick(() => {
const refs = this.$refs[this.inputRef(next)]
const input = Array.isArray(refs) ? refs[0] : refs
if (input) {
input.focus()
input.select()
}
})
},
removeBattery (channel) {
this.$delete(this.batteryInputs, channel)
this.tableData = this.tableData.filter(item => item.index !== channel)
},
openFormatDialog () {
this.formatDialogVisible = true
this.fetchFormatList()
},
openFormatForm () {
this.formatForm = {
tray_format: '',
battery_format: '',
battery_count: 1
}
this.formatFormVisible = true
},
async createFormat () {
if (!this.formatForm.tray_format) {
this.$message.warning(this.$t(this.key('add_tray_format')))
return
}
if (!this.formatForm.battery_format) {
this.$message.warning(this.$t(this.key('add_battery_format')))
return
}
if (!this.formatForm.battery_count || Number(this.formatForm.battery_count) <= 0) {
this.$message.warning(this.$t(this.key('add_battery_count')))
return
}
await createBatchTrayFormat({
action: 'set_login_format',
...this.formatForm
})
this.$message.success(this.$t(this.key('operation_success')))
this.formatFormVisible = false
this.fetchFormatList()
},
deleteFormat (row) {
this.$confirm(this.$t(this.key('delete_confirm')), this.$t(this.key('prompt')), {
confirmButtonText: this.$t(this.key('confirm')),
cancelButtonText: this.$t(this.key('cancel')),
type: 'warning'
}).then(async () => {
await deleteBatchTrayFormat({
action: 'set_login_format',
id: row.id
})
this.$message.success(this.$t(this.key('delete_success')))
this.fetchFormatList()
}).catch(() => {})
},
openSubmitDialog () {
if (!this.validateSubmit()) return
this.submitDialogVisible = true
},
validateSubmit () {
if (!this.validateTray()) return false
if (!this.form.batch) {
this.$message.warning(this.$t(this.key('no_batch_no')))
return false
}
if (!this.tableData.length) {
this.$message.warning(this.$t(this.key('enter_battery_code')))
return false
}
if (this.tableData.some(item => Number(item.active) === 1)) {
this.$message.warning(this.$t(this.key('has_active_battery_login_forbidden')))
return false
}
return true
},
batteryIdsForSubmit () {
return this.channelList.map(channel => {
const row = this.tableData.find(item => item.index === channel)
return row ? row.Battery : '0'
})
},
async submitRegistration () {
if (!this.validateSubmit()) return
this.submitting = true
try {
const res = await sendWorkerman({
sendData: {
action: 'set_tray_login',
param: {
workingsubclass: 'LOGIN',
tray: this.form.tray,
batch: this.form.batch,
device_code: 'WEBMAN_LOGIN',
direction_sign: '',
lot: String(new Date().valueOf()),
battery_ids: this.batteryIdsForSubmit(),
Manual: true
}
}
})
const payload = res && res.data ? res.data : (res || {})
if (payload.code !== undefined && Number(payload.code) !== 0) {
this.$message.warning(payload.errmsg || payload.msg || this.$t(this.key('operation_failed')))
return
}
this.$message.success(this.$t(this.key('upload_success')))
this.submitDialogVisible = false
this.resetPage()
} finally {
this.submitting = false
}
},
unbindTray () {
this.promptTray('tray_unbind_desc', 'tray_unbind', 'set_tray_unbinding', 'tray_unbind_success')
},
stopTray () {
this.promptTray('tray_stop_desc', 'tray_stop', 'set_tray_inactivity', 'tray_stop_success')
},
promptTray (messageKey, titleKey, action, successKey) {
this.$prompt(this.$t(this.key(messageKey)), this.$t(this.key(titleKey)), {
confirmButtonText: this.$t(this.key('confirm')),
cancelButtonText: this.$t(this.key('cancel')),
inputValue: this.form.tray,
inputValidator: value => {
if (!value) return this.$t(this.key('enter_tray_no'))
return true
}
}).then(async ({ value }) => {
const param = action === 'set_tray_inactivity'
? { data: [{ tray: value }] }
: { tray: value }
await sendWorkerman({
sendData: {
action,
param
}
})
this.$message.success(this.$t(this.key(successKey)))
}).catch(() => {})
},
batchInactivity () {
if (!this.selectedRows.length) {
this.$message.warning(this.$t(this.key('select_battery_to_deactivate')))
return
}
this.$confirm(this.$t(this.key('battery_deactivate')), this.$t(this.key('prompt')), {
confirmButtonText: this.$t(this.key('confirm')),
cancelButtonText: this.$t(this.key('cancel')),
type: 'warning'
}).then(async () => {
await sendWorkerman({
sendData: {
action: 'set_battery_inactivity',
param: {
data: this.selectedRows.map(row => ({
battery_id: row.Battery || row.battery_id,
class: 'NG',
classname: 'web_inactivity'
}))
}
}
})
this.selectedRows.forEach(row => {
const target = this.tableData.find(item => item.index === row.index)
if (target) this.$set(target, 'active', 0)
})
this.$message.success(this.$t(this.key('batch_battery_deactivate_success')))
}).catch(() => {})
},
rowClassName ({ row }) {
return Number(row.active) === 1 ? 'is-active-battery' : ''
},
resetPage () {
this.form.tray = ''
this.batteryInputs = {}
this.tableData = []
this.selectedRows = []
this.submitDialogVisible = false
}
}
}
</script>
<style lang="scss" scoped>
.registration-layout {
display: grid;
grid-template-columns: minmax(360px, 1fr) minmax(520px, 1fr);
gap: 12px;
}
.channel-panel,
.battery-panel {
min-width: 0;
}
.panel-head {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 32px;
margin-bottom: 8px;
color: #303133;
font-weight: 600;
}
.channel-grid {
max-height: 560px;
padding-right: 8px;
overflow: auto;
::v-deep .el-form {
display: grid;
grid-template-columns: repeat(2, minmax(220px, 1fr));
column-gap: 10px;
}
}
.format-table {
margin-top: 10px;
}
.danger-action {
color: #f56c6c;
}
::v-deep .el-table .is-active-battery td {
background-color: rgba(245, 108, 108, 0.12);
}
@media (max-width: 1100px) {
.registration-layout {
grid-template-columns: 1fr;
}
}
</style>