大屏
This commit is contained in:
63
src/api/mes/board/screen.js
Normal file
63
src/api/mes/board/screen.js
Normal file
@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listBoardScreen(query) {
|
||||
return request({
|
||||
url: '/mes/board/screen/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getBoardScreen(screenId) {
|
||||
return request({
|
||||
url: '/mes/board/screen/' + screenId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addBoardScreen(data) {
|
||||
return request({
|
||||
url: '/mes/board/screen',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateBoardScreen(data) {
|
||||
return request({
|
||||
url: '/mes/board/screen',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function delBoardScreen(screenId) {
|
||||
return request({
|
||||
url: '/mes/board/screen/' + screenId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function getBoardScreenConfig(screenId) {
|
||||
return request({
|
||||
url: '/mes/board/screen/config',
|
||||
method: 'get',
|
||||
params: { screenId }
|
||||
})
|
||||
}
|
||||
|
||||
export function saveBoardScreenConfig(data) {
|
||||
return request({
|
||||
url: '/mes/board/screen/config',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function resetBoardScreenConfig(screenId) {
|
||||
return request({
|
||||
url: '/mes/board/screen/config',
|
||||
method: 'delete',
|
||||
params: { screenId }
|
||||
})
|
||||
}
|
||||
9
src/api/mes/board/workshop.js
Normal file
9
src/api/mes/board/workshop.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getWorkshopBoardData(screenCode) {
|
||||
return request({
|
||||
url: '/mes/board/workshop/data',
|
||||
method: 'get',
|
||||
params: { screenCode }
|
||||
})
|
||||
}
|
||||
130
src/api/mes/md/screenbinding.js
Normal file
130
src/api/mes/md/screenbinding.js
Normal file
@ -0,0 +1,130 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
const DEFAULT_SCREEN_CODE = 'WORKSHOP_BOARD_DEFAULT'
|
||||
|
||||
function createEmptyScreenBindingConfig(screenCode = DEFAULT_SCREEN_CODE) {
|
||||
return {
|
||||
screenCode,
|
||||
workshopId: null,
|
||||
workshopCode: '',
|
||||
workshopName: '',
|
||||
updatedAt: '',
|
||||
basicBindings: [],
|
||||
machineConfigs: []
|
||||
}
|
||||
}
|
||||
|
||||
function toUiBinding(binding) {
|
||||
return {
|
||||
bindingId: binding.bindingId,
|
||||
screenCode: binding.screenCode,
|
||||
workshopId: binding.workshopId,
|
||||
workshopCode: binding.workshopCode,
|
||||
workshopName: binding.workshopName,
|
||||
sourceType: binding.sourceType || 'FIXED',
|
||||
pointId: binding.pointId,
|
||||
pointCode: binding.pointCode || '',
|
||||
pointName: binding.pointName || '',
|
||||
fixedValue: binding.fixedValue || '',
|
||||
defaultValue: binding.defaultValue || '',
|
||||
displayUnit: binding.displayUnit || '',
|
||||
precisionDigit: binding.precisionDigit,
|
||||
sortNum: binding.sortNum,
|
||||
statusClass: binding.statusClass || 'is-running',
|
||||
enableFlag: binding.enableFlag || 'Y',
|
||||
key: binding.bindingKey,
|
||||
label: binding.bindingName
|
||||
}
|
||||
}
|
||||
|
||||
function toUiConfig(data) {
|
||||
const emptyConfig = createEmptyScreenBindingConfig(data.screenCode || DEFAULT_SCREEN_CODE)
|
||||
return {
|
||||
...emptyConfig,
|
||||
screenCode: data.screenCode || emptyConfig.screenCode,
|
||||
workshopId: data.workshopId === undefined ? emptyConfig.workshopId : data.workshopId,
|
||||
workshopCode: data.workshopCode || emptyConfig.workshopCode,
|
||||
workshopName: data.workshopName || emptyConfig.workshopName,
|
||||
updatedAt: data.updatedAt || emptyConfig.updatedAt,
|
||||
basicBindings: (data.basicBindings || []).map(toUiBinding),
|
||||
machineConfigs: (data.machineConfigs || []).map(item => ({
|
||||
id: item.id,
|
||||
statusClass: item.statusClass || 'is-running',
|
||||
bindings: (item.bindings || []).map(toUiBinding)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
function toApiBinding(binding, scope, machineId, statusClass) {
|
||||
return {
|
||||
bindingId: binding.bindingId,
|
||||
screenCode: binding.screenCode,
|
||||
workshopId: binding.workshopId,
|
||||
workshopCode: binding.workshopCode,
|
||||
workshopName: binding.workshopName,
|
||||
bindingScope: scope,
|
||||
machineId,
|
||||
bindingKey: binding.key,
|
||||
bindingName: binding.label,
|
||||
sourceType: binding.sourceType,
|
||||
pointId: binding.pointId,
|
||||
pointCode: binding.pointCode,
|
||||
pointName: binding.pointName,
|
||||
fixedValue: binding.fixedValue,
|
||||
defaultValue: binding.defaultValue,
|
||||
displayUnit: binding.displayUnit,
|
||||
precisionDigit: binding.precisionDigit,
|
||||
statusClass: statusClass || binding.statusClass,
|
||||
sortNum: binding.sortNum,
|
||||
enableFlag: binding.enableFlag,
|
||||
remark: binding.remark
|
||||
}
|
||||
}
|
||||
|
||||
function toApiConfig(config) {
|
||||
return {
|
||||
screenCode: config.screenCode,
|
||||
workshopId: config.workshopId,
|
||||
workshopCode: config.workshopCode,
|
||||
workshopName: config.workshopName,
|
||||
basicBindings: (config.basicBindings || []).map(item => toApiBinding(item, 'BASIC', 0, item.statusClass)),
|
||||
machineConfigs: (config.machineConfigs || []).map(machine => ({
|
||||
id: machine.id,
|
||||
statusClass: machine.statusClass,
|
||||
bindings: (machine.bindings || []).map(item => toApiBinding(item, 'MACHINE', machine.id, machine.statusClass))
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
export function getScreenBindingConfig(screenCode) {
|
||||
return request({
|
||||
url: '/mes/md/screenbinding/config',
|
||||
method: 'get',
|
||||
params: { screenCode }
|
||||
}).then(response => ({
|
||||
...response,
|
||||
data: toUiConfig(response.data || {})
|
||||
}))
|
||||
}
|
||||
|
||||
export function saveScreenBindingConfig(data) {
|
||||
return request({
|
||||
url: '/mes/md/screenbinding/config',
|
||||
method: 'post',
|
||||
data: toApiConfig(data)
|
||||
}).then(response => ({
|
||||
...response,
|
||||
data: toUiConfig(response.data || {})
|
||||
}))
|
||||
}
|
||||
|
||||
export function resetScreenBindingConfig(screenCode) {
|
||||
return request({
|
||||
url: '/mes/md/screenbinding/config',
|
||||
method: 'delete',
|
||||
params: { screenCode }
|
||||
}).then(response => ({
|
||||
...response,
|
||||
data: toUiConfig(response.data || {})
|
||||
}))
|
||||
}
|
||||
@ -3,11 +3,11 @@
|
||||
<div class="board-header">
|
||||
<div class="header-cell">
|
||||
<div class="header-label">看板编号</div>
|
||||
<div class="header-value">HY-CJKB-001</div>
|
||||
<div class="header-value">{{ header.screenCode }}</div>
|
||||
</div>
|
||||
<div class="header-cell">
|
||||
<div class="header-label">管理责任人</div>
|
||||
<div class="header-value">张主管</div>
|
||||
<div class="header-value">{{ header.ownerName }}</div>
|
||||
</div>
|
||||
<div class="header-cell">
|
||||
<div class="header-label">更新时间</div>
|
||||
@ -290,99 +290,62 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
function createMachine(id, name, model, statusText, statusClass, mode, runtime, output, workDate, batchNo, planQty, progress, productModel, color, remark, nextModel) {
|
||||
import { getWorkshopBoardData } from '@/api/mes/board/workshop'
|
||||
import { listRepair } from '@/api/mes/dv/repair'
|
||||
import { listCheckplan } from '@/api/mes/dv/checkplan'
|
||||
|
||||
const DEFAULT_SCREEN_CODE = 'WORKSHOP_BOARD_DEFAULT'
|
||||
|
||||
function createEmptyWorkshopBoardData() {
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
model,
|
||||
statusText,
|
||||
statusClass,
|
||||
mode,
|
||||
runtime,
|
||||
output,
|
||||
workDate,
|
||||
batchNo,
|
||||
planQty,
|
||||
progress,
|
||||
productModel,
|
||||
color,
|
||||
remark,
|
||||
nextModel
|
||||
header: {},
|
||||
summary: {},
|
||||
faultList: [],
|
||||
maintenanceList: [],
|
||||
machineList: [],
|
||||
detailRealtime: [],
|
||||
detailSetting: [],
|
||||
detailProduction: []
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'WorkshopBoard',
|
||||
data() {
|
||||
const boardData = createEmptyWorkshopBoardData()
|
||||
return {
|
||||
detailVisible: false,
|
||||
boardTimer: null,
|
||||
updateTime: '',
|
||||
previousTitle: '',
|
||||
activeMachine: {},
|
||||
header: boardData.header,
|
||||
faultTableRows: 8,
|
||||
planTableRows: 8,
|
||||
summary: boardData.summary,
|
||||
faultList: boardData.faultList,
|
||||
maintenanceList: boardData.maintenanceList,
|
||||
machineList: boardData.machineList,
|
||||
detailRealtime: boardData.detailRealtime,
|
||||
detailSetting: boardData.detailSetting,
|
||||
detailProduction: boardData.detailProduction
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
orderedMachineList() {
|
||||
return [...this.machineList].sort((a, b) => a.id - b.id)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
detailVisible: false,
|
||||
updateTime: '',
|
||||
clockTimer: null,
|
||||
previousTitle: '',
|
||||
activeMachine: {},
|
||||
faultTableRows: 8,
|
||||
planTableRows: 8,
|
||||
summary: {
|
||||
total: 17,
|
||||
online: 15,
|
||||
running: 15,
|
||||
stop: 2,
|
||||
startRate: '88.2%'
|
||||
},
|
||||
faultList: [
|
||||
{ deviceNo: '8#', faultTime: '09:25', faultDesc: '模温异常', owner: '李工', recoverTime: '10:10' },
|
||||
{ deviceNo: '16#', faultTime: '11:40', faultDesc: '液压压力波动', owner: '王工', recoverTime: '13:00' },
|
||||
{ deviceNo: '5#', faultTime: '13:18', faultDesc: '送料传感器告警', owner: '赵工', recoverTime: '13:45' }
|
||||
],
|
||||
maintenanceList: [
|
||||
{ deviceNo: '2#', project: '保养润滑系统', planTime: '2026-03-23 16:00', status: '待执行' },
|
||||
{ deviceNo: '11#', project: '校验温控模块', planTime: '2026-03-23 18:00', status: '待执行' },
|
||||
{ deviceNo: '14#', project: '更换过滤组件', planTime: '2026-03-24 09:00', status: '已排期' }
|
||||
],
|
||||
machineList: [
|
||||
createMachine(6, '6#', 'MA2500/1000G', '状态', 'is-running', '运行', '13小时', '600个', '2026.3.16-3.18', '25110914', '5000个', '30%', '23W 中间盖', '7037C 灰', '重点订单', '159BB'),
|
||||
createMachine(12, '12#', 'MA1600/540G', '状态', 'is-running', '运行', '8小时', '305个', '2026.3.23-3.25', '25110953', '2800个', '27%', '中盖件', '灰色', '正常生产', 'J20R'),
|
||||
createMachine(5, '5#', 'MA2500 2S/1000', '状态', 'is-running', '运行', '6小时', '210个', '2026.3.22-3.24', '25110937', '3600个', '19%', '卡扣件', '7035 灰', '待维修', '32QR'),
|
||||
createMachine(11, '11#', 'MA3600/2250G', '状态', 'is-running', '运行', '15小时', '720个', '2026.3.23-3.25', '25110950', '6500个', '33%', '大型壳体', '深蓝', '计划保养', 'LT9X'),
|
||||
createMachine(17, '17#', 'MA1600/540G', '状态', 'is-running', '运行', '12小时', '510个', '2026.3.23-3.25', '25110961', '3600个', '53%', '面框件', '冷白', '正常生产', 'AA17'),
|
||||
createMachine(4, '4#', 'MA2500/1000G', '状态', 'is-running', '运行', '10小时', '488个', '2026.3.21-3.22', '25110931', '4500个', '61%', '28W 外壳', '米白', '正常生产', '26WA'),
|
||||
createMachine(10, '10#', 'MA2500/1000G', '状态', 'is-running', '运行', '13小时', '610个', '2026.3.23-3.24', '25110946', '5100个', '44%', '挡板件', '黑色', '正常生产', 'M22A'),
|
||||
createMachine(16, '16#', '570', '状态', 'is-running', '运行', '5小时', '190个', '2026.3.23-3.25', '25110959', '2400个', '18%', '小型卡件', '浅灰', '液压检修', 'Q30E'),
|
||||
createMachine(3, '3#', 'MA2500/1000G', '状态', 'is-running', '运行', '8小时', '360个', '2026.3.20-3.22', '25110925', '3000个', '58%', '17W 支架', '银色', '等待换模', '90KT'),
|
||||
createMachine(9, '9#', 'MA2500/1000G', '状态', 'is-running', '运行', '14小时', '680个', '2026.3.23-3.24', '25110945', '5400个', '52%', '导流板', '银灰', '正常生产', 'C88L'),
|
||||
createMachine(15, '15#', 'MA1600/540G', '状态', 'is-running', '运行', '11小时', '460个', '2026.3.23-3.25', '25110957', '3500个', '41%', '转接件', '深灰', '正常生产', 'UV06'),
|
||||
createMachine(2, '2#', 'MA2500/1000G', '状态', 'is-running', '运行', '11小时', '520个', '2026.3.18-3.20', '25110918', '4200个', '42%', '26W 面板', '黑色', '夜班优先', '188AX'),
|
||||
createMachine(8, '8#', 'MA2500/1000G', '状态', 'is-running', '运行', '9小时', '430个', '2026.3.22-3.24', '25110941', '4600个', '36%', '封边件', '白色', '温控波动', 'B71S'),
|
||||
createMachine(14, '14#', 'MA1600/540G', '状态', 'is-running', '运行', '10小时', '395个', '2026.3.23-3.25', '25110955', '3200个', '38%', '扣合件', '亮黑', '正常生产', 'R81N'),
|
||||
createMachine(1, '1#', 'MA2500/1000G', '状态', 'is-running', '运行', '13小时', '600个', '2026.3.16-3.18', '25110914', '5000个', '30%', '23W 中间盖', '7037C 灰', '重点订单', '159BB'),
|
||||
createMachine(7, '7#', 'MA2500/1000G', '状态', 'is-running', '运行', '4小时', '120个', '2026.3.22-3.24', '25110940', '3000个', '12%', '结构件', '深灰', '人工调试', 'X09M'),
|
||||
createMachine(13, '13#', 'MA1600/540G', '状态', 'is-running', '运行', '7小时', '280个', '2026.3.23-3.25', '25110954', '2600个', '31%', '面罩件', '暖白', '待料', 'PK11')
|
||||
],
|
||||
detailRealtime: [
|
||||
{ name: '温度一段(A15)', current: '186℃', currentTime: '14:20:15', target: '185℃', targetTime: '14:05:00', orderValue: '188℃', orderTime: '08:30:00' },
|
||||
{ name: '温度二段(A16)', current: '192℃', currentTime: '14:20:15', target: '190℃', targetTime: '14:05:00', orderValue: '192℃', orderTime: '08:30:00' },
|
||||
{ name: '射胶压力(A243)', current: '12.3MPa', currentTime: '14:20:10', target: '12.0MPa', targetTime: '14:00:00', orderValue: '12.5MPa', orderTime: '08:30:00' }
|
||||
],
|
||||
detailSetting: [
|
||||
{ name: '开模行程(A060)', setting: '320mm', settingTime: '13:15:00', orderValue: '325mm', orderTime: '08:30:00' },
|
||||
{ name: '锁模压力(A061)', setting: '86%', settingTime: '13:15:00', orderValue: '85%', orderTime: '08:30:00' },
|
||||
{ name: '保压时间(A062)', setting: '4.5s', settingTime: '13:15:00', orderValue: '4.8s', orderTime: '08:30:00' }
|
||||
],
|
||||
detailProduction: [
|
||||
{ name: '上模循环时(A37)', value: '28.6s', collectTime: '14:20:11' },
|
||||
{ name: '一模产出数', value: '2', collectTime: '14:20:11' },
|
||||
{ name: '累计良品数', value: '598', collectTime: '14:20:11' }
|
||||
]
|
||||
workshopMachineCodeSet() {
|
||||
return new Set(
|
||||
(this.machineList || [])
|
||||
.map(item => this.normalizeMachineCode(item && item.name))
|
||||
.filter(Boolean)
|
||||
)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.refreshClock()
|
||||
this.clockTimer = setInterval(this.refreshClock, 1000)
|
||||
this.loadBoardData()
|
||||
this.boardTimer = setInterval(this.loadBoardData, 30000)
|
||||
this.activeMachine = this.machineList[0]
|
||||
},
|
||||
mounted() {
|
||||
@ -390,13 +353,111 @@ export default {
|
||||
this.tryEnterFullscreen()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.clockTimer) {
|
||||
clearInterval(this.clockTimer)
|
||||
this.clockTimer = null
|
||||
if (this.boardTimer) {
|
||||
clearInterval(this.boardTimer)
|
||||
this.boardTimer = null
|
||||
}
|
||||
this.restoreTitle()
|
||||
},
|
||||
methods: {
|
||||
loadBoardData() {
|
||||
const screenCode = this.$route && this.$route.query && this.$route.query.screenCode
|
||||
? this.$route.query.screenCode
|
||||
: DEFAULT_SCREEN_CODE
|
||||
getWorkshopBoardData(screenCode).then(response => {
|
||||
this.applyBoardData(response.data)
|
||||
this.loadFaultList()
|
||||
this.loadMaintenanceList()
|
||||
}).catch(() => {
|
||||
this.applyBoardData(createEmptyWorkshopBoardData())
|
||||
this.faultList = []
|
||||
this.maintenanceList = []
|
||||
})
|
||||
},
|
||||
loadFaultList() {
|
||||
if (!this.workshopMachineCodeSet.size) {
|
||||
this.faultList = []
|
||||
return
|
||||
}
|
||||
listRepair({
|
||||
pageNum: 1,
|
||||
pageSize: this.faultTableRows * 5
|
||||
}).then(response => {
|
||||
const rows = (response && response.rows) || []
|
||||
this.faultList = rows
|
||||
.filter(item => this.isWorkshopMachine(item && item.machineryCode))
|
||||
.slice(0, this.faultTableRows)
|
||||
.map(item => ({
|
||||
deviceNo: item.machineryCode || '--',
|
||||
faultTime: item.requireDate || '--',
|
||||
faultDesc: item.repairName || item.remark || '--',
|
||||
owner: item.acceptedName || item.acceptedBy || '--',
|
||||
recoverTime: item.finishDate || '--'
|
||||
}))
|
||||
}).catch(() => {
|
||||
this.faultList = []
|
||||
})
|
||||
},
|
||||
loadMaintenanceList() {
|
||||
if (!this.workshopMachineCodeSet.size) {
|
||||
this.maintenanceList = []
|
||||
return
|
||||
}
|
||||
listCheckplan({
|
||||
pageNum: 1,
|
||||
pageSize: this.planTableRows * 5
|
||||
}).then(response => {
|
||||
const rows = (response && response.rows) || []
|
||||
this.maintenanceList = rows
|
||||
.filter(item => this.hasWorkshopMachine(item && item.machineryCodes))
|
||||
.slice(0, this.planTableRows)
|
||||
.map(item => ({
|
||||
deviceNo: item.machineryCodes || '--',
|
||||
project: item.planName || '--',
|
||||
planTime: this.formatPlanTime(item),
|
||||
status: item.status || '--'
|
||||
}))
|
||||
}).catch(() => {
|
||||
this.maintenanceList = []
|
||||
})
|
||||
},
|
||||
normalizeMachineCode(code) {
|
||||
return code ? String(code).trim().toUpperCase() : ''
|
||||
},
|
||||
isWorkshopMachine(code) {
|
||||
return this.workshopMachineCodeSet.has(this.normalizeMachineCode(code))
|
||||
},
|
||||
hasWorkshopMachine(codes) {
|
||||
return String(codes || '')
|
||||
.split(',')
|
||||
.map(code => this.normalizeMachineCode(code))
|
||||
.filter(Boolean)
|
||||
.some(code => this.workshopMachineCodeSet.has(code))
|
||||
},
|
||||
formatPlanTime(item) {
|
||||
const startDate = item && item.startDate ? item.startDate : ''
|
||||
const endDate = item && item.endDate ? item.endDate : ''
|
||||
if (startDate && endDate) {
|
||||
return `${startDate} ~ ${endDate}`
|
||||
}
|
||||
return startDate || endDate || '--'
|
||||
},
|
||||
applyBoardData(boardData) {
|
||||
const normalizedBoardData = boardData || createEmptyWorkshopBoardData()
|
||||
this.header = normalizedBoardData.header || {}
|
||||
this.summary = normalizedBoardData.summary || {}
|
||||
this.machineList = normalizedBoardData.machineList || []
|
||||
this.detailRealtime = normalizedBoardData.detailRealtime || []
|
||||
this.detailSetting = normalizedBoardData.detailSetting || []
|
||||
this.detailProduction = normalizedBoardData.detailProduction || []
|
||||
this.refreshClock()
|
||||
if (!this.activeMachine || !this.activeMachine.id) {
|
||||
this.activeMachine = this.machineList[0] || {}
|
||||
} else {
|
||||
const currentMachine = this.machineList.find(item => item.id === this.activeMachine.id)
|
||||
this.activeMachine = currentMachine || this.machineList[0] || {}
|
||||
}
|
||||
},
|
||||
applyDisplayTitle() {
|
||||
const mode = this.$route && this.$route.query ? this.$route.query.displayMode : ''
|
||||
if (mode !== 'fullscreen') {
|
||||
|
||||
@ -36,9 +36,6 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['mes:md:measurepoint:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-refresh" size="mini" @click="refreshLatest" v-hasPermi="['mes:md:measurepoint:query']">刷新最新值</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
@ -53,12 +50,6 @@
|
||||
<el-table-column label="车间" align="center" prop="workshopName" min-width="120" />
|
||||
<el-table-column label="设备编码" align="center" prop="deviceCode" min-width="120" />
|
||||
<el-table-column label="节点编码" align="center" prop="nodeCode" min-width="120" />
|
||||
<el-table-column label="最新值" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatLatestValue(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最新时间" align="center" prop="latestTime" min-width="180" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="单位" align="center" prop="unit" width="80" />
|
||||
<el-table-column label="字段" align="center" prop="fieldKey" min-width="120" />
|
||||
<el-table-column label="启用" align="center" prop="enableFlag" width="80">
|
||||
@ -371,9 +362,6 @@ export default {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
refreshLatest() {
|
||||
this.getList()
|
||||
},
|
||||
formatLatestValue(row) {
|
||||
if (!row || row.latestValue === null || row.latestValue === undefined || row.latestValue === '') {
|
||||
return '-'
|
||||
|
||||
787
src/views/mes/md/screenbinding/index.vue
Normal file
787
src/views/mes/md/screenbinding/index.vue
Normal file
@ -0,0 +1,787 @@
|
||||
<template>
|
||||
<div class="app-container board-screen-page">
|
||||
<el-form :model="queryParams" size="small" :inline="true" label-width="80px">
|
||||
<el-form-item label="看板编码">
|
||||
<el-input v-model="queryParams.screenCode" placeholder="请输入看板编码" clearable style="width: 180px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="责任人">
|
||||
<el-input v-model="queryParams.ownerName" placeholder="请输入责任人" clearable style="width: 180px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属车间">
|
||||
<el-select v-model="queryParams.workshopId" placeholder="请选择车间" clearable filterable style="width: 180px">
|
||||
<el-option v-for="item in workshopOptions" :key="item.workshopId" :label="item.workshopName" :value="item.workshopId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="getScreenList">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
<el-button type="success" plain icon="el-icon-plus" size="mini" @click="openScreenDialog()">新增看板</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="9">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span>看板列表</span>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="screenLoading"
|
||||
:data="screenList"
|
||||
border
|
||||
height="620"
|
||||
highlight-current-row
|
||||
row-key="screenId"
|
||||
@current-change="handleCurrentScreenChange"
|
||||
>
|
||||
<el-table-column label="看板编码" prop="screenCode" min-width="140" />
|
||||
<el-table-column label="车间" prop="workshopName" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="责任人" prop="ownerName" min-width="100" />
|
||||
<el-table-column label="设备数" align="center" prop="deviceTotal" width="80" />
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click.stop="openScreenDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click.stop="removeScreen(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="15">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="card-header">
|
||||
<div>
|
||||
<div class="screen-title">{{ currentScreen ? currentScreen.screenCode : '请选择看板' }}</div>
|
||||
<div class="screen-subtitle">{{ currentScreenSummary }}</div>
|
||||
</div>
|
||||
<div v-if="currentScreen">
|
||||
<el-button type="primary" plain size="mini" icon="el-icon-plus" @click="openDeviceDialog">添加设备</el-button>
|
||||
<el-button type="warning" plain size="mini" icon="el-icon-delete" @click="resetConfig">清空绑定</el-button>
|
||||
<el-button type="primary" plain size="mini" icon="el-icon-monitor" @click="openBoard">打开看板</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!currentScreen" class="empty-block">
|
||||
请选择左侧看板,开始配置设备和点位绑定。
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<el-collapse v-model="activeMachines">
|
||||
<el-collapse-item
|
||||
v-for="machine in machineConfigs"
|
||||
:key="machine.machineCode"
|
||||
:name="machine.machineCode"
|
||||
>
|
||||
<template slot="title">
|
||||
<div class="machine-title-row">
|
||||
<span>{{ machine.machineCode }}</span>
|
||||
<span class="machine-name">{{ machine.machineName || '--' }}</span>
|
||||
<el-button type="text" size="mini" class="machine-remove" @click.stop="removeMachine(machine.machineCode)">移除设备</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="machine.bindings" border>
|
||||
<el-table-column label="字段名称" prop="fieldName" min-width="140" />
|
||||
<el-table-column label="字段键" prop="bindingField" min-width="140" />
|
||||
<el-table-column label="当前点位" min-width="220">
|
||||
<template slot-scope="scope">
|
||||
{{ getPointSummary(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="预览值" min-width="160">
|
||||
<template slot-scope="scope">
|
||||
{{ getPreviewValue(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openBindingEditor(machine, scope.row)">配置点位</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-dialog :title="screenDialogTitle" :visible.sync="screenDialogOpen" width="640px" append-to-body>
|
||||
<el-form ref="screenForm" :model="screenForm" :rules="screenRules" label-width="96px">
|
||||
<el-form-item label="看板编码" prop="screenCode">
|
||||
<el-input v-model="screenForm.screenCode" placeholder="请输入看板编码" :disabled="!!screenForm.screenId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="责任人" prop="ownerName">
|
||||
<el-input v-model="screenForm.ownerName" placeholder="请输入责任人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属车间" prop="workshopId">
|
||||
<el-select v-model="screenForm.workshopId" placeholder="请选择车间" filterable style="width: 100%" @change="handleWorkshopChange">
|
||||
<el-option v-for="item in workshopOptions" :key="item.workshopId" :label="item.workshopName" :value="item.workshopId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="screenForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitScreenForm">确 定</el-button>
|
||||
<el-button @click="screenDialogOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="添加设备" :visible.sync="deviceDialogOpen" width="1000px" append-to-body>
|
||||
<el-form :model="deviceQuery" size="small" :inline="true" label-width="80px">
|
||||
<el-form-item label="设备编码">
|
||||
<el-input v-model="deviceQuery.machineryCode" placeholder="请输入设备编码,支持模糊搜索" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称">
|
||||
<el-input v-model="deviceQuery.machineryName" placeholder="请输入设备名称,支持模糊搜索" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="getDeviceList">查询</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetDeviceQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="deviceLoading"
|
||||
:data="deviceList"
|
||||
border
|
||||
height="420"
|
||||
@selection-change="handleDeviceSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="设备编码" prop="machineryCode" min-width="140" />
|
||||
<el-table-column label="设备名称" prop="machineryName" min-width="160" />
|
||||
<el-table-column label="设备型号" prop="machinerySpec" min-width="160" />
|
||||
<el-table-column label="所属车间" prop="workshopName" min-width="140" />
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="appendSelectedDevices">确 定</el-button>
|
||||
<el-button @click="deviceDialogOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="配置点位" :visible.sync="editorOpen" width="760px" append-to-body>
|
||||
<el-form :model="editForm" label-width="96px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备编码">
|
||||
<el-input :value="editMachine.machineCode" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="字段名称">
|
||||
<el-input :value="editForm.fieldName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-form-item label="测量点">
|
||||
<el-input :value="getPointSummary(editForm)" readonly placeholder="请选择测量点" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label-width="0">
|
||||
<el-button icon="el-icon-search" @click="openPointDialog">选择点位</el-button>
|
||||
<el-button type="text" @click="clearPoint">清空</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="当前预览">
|
||||
<el-input :value="getPreviewValue(editForm)" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitBindingEdit">确 定</el-button>
|
||||
<el-button @click="editorOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="选择测量点" :visible.sync="pointDialogOpen" width="1000px" append-to-body>
|
||||
<el-form :model="pointQuery" size="small" :inline="true" label-width="84px">
|
||||
<el-form-item label="测量点编码">
|
||||
<el-input v-model="pointQuery.pointCode" placeholder="请输入测量点编码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="测量点名称">
|
||||
<el-input v-model="pointQuery.pointName" placeholder="请输入测量点名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备编码">
|
||||
<el-input v-model="pointQuery.deviceCode" placeholder="请输入设备编码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="getPointList">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetPointQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table v-loading="pointLoading" :data="pointList" border height="420">
|
||||
<el-table-column label="测量点编码" prop="pointCode" min-width="130" />
|
||||
<el-table-column label="测量点名称" prop="pointName" min-width="160" />
|
||||
<el-table-column label="设备编码" prop="deviceCode" min-width="120" />
|
||||
<el-table-column label="最新值" min-width="140">
|
||||
<template slot-scope="scope">
|
||||
{{ formatPointLatest(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最新时间" prop="latestTime" min-width="170" />
|
||||
<el-table-column label="操作" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="selectPoint(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listMeasurePoint, getMeasurePointLatest } from '@/api/mes/md/measurepoint'
|
||||
import { listAllWorkshop } from '@/api/mes/md/workshop'
|
||||
import { listMachinery } from '@/api/mes/dv/machinery'
|
||||
import {
|
||||
addBoardScreen,
|
||||
delBoardScreen,
|
||||
getBoardScreenConfig,
|
||||
listBoardScreen,
|
||||
resetBoardScreenConfig,
|
||||
saveBoardScreenConfig,
|
||||
updateBoardScreen
|
||||
} from '@/api/mes/board/screen'
|
||||
|
||||
const FIELD_OPTIONS = [
|
||||
{ bindingField: 'device_status', fieldName: '设备状态' },
|
||||
{ bindingField: 'run_mode', fieldName: '运行模式' },
|
||||
{ bindingField: 'today_run_time', fieldName: '今日开机时长' },
|
||||
{ bindingField: 'today_piece_count', fieldName: '今日计件数' },
|
||||
{ bindingField: 'batch_code', fieldName: '批次号' }
|
||||
]
|
||||
|
||||
function buildFieldMap() {
|
||||
return FIELD_OPTIONS.reduce((result, item) => {
|
||||
result[item.bindingField] = item.fieldName
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
const FIELD_NAME_MAP = buildFieldMap()
|
||||
|
||||
function createBindingSkeleton(machine, field) {
|
||||
return {
|
||||
bindingId: null,
|
||||
screenId: null,
|
||||
screenCode: '',
|
||||
machineryId: machine.machineryId,
|
||||
machineryCode: machine.machineryCode,
|
||||
bindingField: field.bindingField,
|
||||
fieldName: field.fieldName,
|
||||
pointId: null,
|
||||
pointCode: '',
|
||||
pointName: '',
|
||||
sortNum: FIELD_OPTIONS.findIndex(item => item.bindingField === field.bindingField) + 1,
|
||||
enableFlag: 'Y'
|
||||
}
|
||||
}
|
||||
|
||||
function createMachineConfig(machine) {
|
||||
return {
|
||||
machineryId: machine.machineryId,
|
||||
machineCode: machine.machineryCode,
|
||||
machineName: machine.machineryName || '',
|
||||
bindings: FIELD_OPTIONS.map(field => createBindingSkeleton(machine, field))
|
||||
}
|
||||
}
|
||||
|
||||
function groupBindings(bindings, deviceNameMap) {
|
||||
const grouped = {}
|
||||
;(bindings || []).forEach(item => {
|
||||
const machineCode = item.machineryCode
|
||||
if (!machineCode) {
|
||||
return
|
||||
}
|
||||
if (!grouped[machineCode]) {
|
||||
grouped[machineCode] = createMachineConfig({
|
||||
machineryId: item.machineryId,
|
||||
machineryCode: item.machineryCode,
|
||||
machineryName: deviceNameMap[item.machineryCode] || ''
|
||||
})
|
||||
}
|
||||
const target = grouped[machineCode].bindings.find(binding => binding.bindingField === item.bindingField)
|
||||
if (target) {
|
||||
Object.assign(target, item, {
|
||||
fieldName: FIELD_NAME_MAP[item.bindingField] || item.bindingField
|
||||
})
|
||||
}
|
||||
})
|
||||
return Object.keys(grouped).sort().map(key => grouped[key])
|
||||
}
|
||||
|
||||
function collectPointCodes(machineConfigs) {
|
||||
const pointCodeMap = {}
|
||||
;(machineConfigs || []).forEach(machine => {
|
||||
(machine.bindings || []).forEach(binding => {
|
||||
if (binding.pointCode) {
|
||||
pointCodeMap[binding.pointCode] = true
|
||||
}
|
||||
})
|
||||
})
|
||||
return Object.keys(pointCodeMap)
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'ScreenBinding',
|
||||
data() {
|
||||
return {
|
||||
screenLoading: false,
|
||||
saveLoading: false,
|
||||
pointLoading: false,
|
||||
deviceLoading: false,
|
||||
screenDialogOpen: false,
|
||||
deviceDialogOpen: false,
|
||||
editorOpen: false,
|
||||
pointDialogOpen: false,
|
||||
workshopOptions: [],
|
||||
screenList: [],
|
||||
pointList: [],
|
||||
deviceList: [],
|
||||
selectedDeviceRows: [],
|
||||
currentScreen: null,
|
||||
machineConfigs: [],
|
||||
activeMachines: [],
|
||||
latestMap: {},
|
||||
deviceNameMap: {},
|
||||
queryParams: {
|
||||
screenCode: '',
|
||||
ownerName: '',
|
||||
workshopId: null
|
||||
},
|
||||
screenForm: {
|
||||
screenId: null,
|
||||
screenCode: '',
|
||||
ownerName: '',
|
||||
workshopId: null,
|
||||
workshopCode: '',
|
||||
workshopName: '',
|
||||
remark: ''
|
||||
},
|
||||
screenRules: {
|
||||
screenCode: [{ required: true, message: '看板编码不能为空', trigger: 'blur' }],
|
||||
ownerName: [{ required: true, message: '责任人不能为空', trigger: 'blur' }],
|
||||
workshopId: [{ required: true, message: '所属车间不能为空', trigger: 'change' }]
|
||||
},
|
||||
deviceQuery: {
|
||||
pageNum: 1,
|
||||
pageSize: 200,
|
||||
machineryCode: '',
|
||||
machineryName: ''
|
||||
},
|
||||
pointQuery: {
|
||||
pageNum: 1,
|
||||
pageSize: 200,
|
||||
pointCode: '',
|
||||
pointName: '',
|
||||
deviceCode: '',
|
||||
enableFlag: 'Y'
|
||||
},
|
||||
editMachine: {},
|
||||
editForm: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentScreenSummary() {
|
||||
if (!this.currentScreen) {
|
||||
return ''
|
||||
}
|
||||
const workshopName = this.currentScreen.workshopName || '--'
|
||||
const ownerName = this.currentScreen.ownerName || '--'
|
||||
return `车间:${workshopName},责任人:${ownerName}`
|
||||
},
|
||||
screenDialogTitle() {
|
||||
return this.screenForm.screenId ? '编辑看板' : '新增看板'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getWorkshopOptions()
|
||||
this.getDeviceList()
|
||||
this.getScreenList()
|
||||
},
|
||||
methods: {
|
||||
getWorkshopOptions() {
|
||||
listAllWorkshop().then(response => {
|
||||
this.workshopOptions = Array.isArray(response) ? response : (response.data || [])
|
||||
})
|
||||
},
|
||||
getScreenList() {
|
||||
this.screenLoading = true
|
||||
listBoardScreen(this.queryParams).then(response => {
|
||||
this.screenList = response.rows || []
|
||||
if (!this.screenList.length) {
|
||||
this.currentScreen = null
|
||||
this.machineConfigs = []
|
||||
this.activeMachines = []
|
||||
return
|
||||
}
|
||||
const nextCurrent = this.currentScreen
|
||||
? this.screenList.find(item => item.screenId === this.currentScreen.screenId)
|
||||
: this.screenList[0]
|
||||
this.handleCurrentScreenChange(nextCurrent)
|
||||
}).finally(() => {
|
||||
this.screenLoading = false
|
||||
})
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
screenCode: '',
|
||||
ownerName: '',
|
||||
workshopId: null
|
||||
}
|
||||
this.getScreenList()
|
||||
},
|
||||
handleCurrentScreenChange(row) {
|
||||
if (!row || (this.currentScreen && this.currentScreen.screenId === row.screenId && this.machineConfigs.length)) {
|
||||
this.currentScreen = row || null
|
||||
return
|
||||
}
|
||||
this.currentScreen = row
|
||||
this.loadCurrentConfig()
|
||||
},
|
||||
loadCurrentConfig() {
|
||||
if (!this.currentScreen) {
|
||||
return
|
||||
}
|
||||
getBoardScreenConfig(this.currentScreen.screenId).then(response => {
|
||||
const bindings = response.data || []
|
||||
this.machineConfigs = groupBindings(bindings, this.deviceNameMap)
|
||||
this.activeMachines = this.machineConfigs.map(item => item.machineCode)
|
||||
this.refreshPreview()
|
||||
})
|
||||
},
|
||||
openScreenDialog(row) {
|
||||
if (this.$refs.screenForm) {
|
||||
this.$refs.screenForm.resetFields()
|
||||
}
|
||||
if (row) {
|
||||
this.screenForm = { ...row }
|
||||
} else {
|
||||
this.screenForm = {
|
||||
screenId: null,
|
||||
screenCode: '',
|
||||
ownerName: '',
|
||||
workshopId: null,
|
||||
workshopCode: '',
|
||||
workshopName: '',
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
this.screenDialogOpen = true
|
||||
},
|
||||
handleWorkshopChange(workshopId) {
|
||||
const workshop = this.workshopOptions.find(item => item.workshopId === workshopId)
|
||||
this.screenForm.workshopCode = workshop ? workshop.workshopCode : ''
|
||||
this.screenForm.workshopName = workshop ? workshop.workshopName : ''
|
||||
},
|
||||
submitScreenForm() {
|
||||
this.$refs.screenForm.validate(valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
const request = this.screenForm.screenId ? updateBoardScreen(this.screenForm) : addBoardScreen(this.screenForm)
|
||||
request.then(() => {
|
||||
this.screenDialogOpen = false
|
||||
this.$modal.msgSuccess(this.screenForm.screenId ? '修改成功' : '新增成功')
|
||||
this.getScreenList()
|
||||
})
|
||||
})
|
||||
},
|
||||
removeScreen(row) {
|
||||
this.$modal.confirm(`是否确认删除看板 ${row.screenCode}?`).then(() => {
|
||||
return delBoardScreen(row.screenId)
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
this.getScreenList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
getDeviceList() {
|
||||
this.deviceLoading = true
|
||||
listMachinery(this.deviceQuery).then(response => {
|
||||
this.deviceList = response.rows || []
|
||||
;(response.rows || []).forEach(item => {
|
||||
this.deviceNameMap[item.machineryCode] = item.machineryName
|
||||
})
|
||||
}).finally(() => {
|
||||
this.deviceLoading = false
|
||||
})
|
||||
},
|
||||
resetDeviceQuery() {
|
||||
this.deviceQuery.machineryCode = ''
|
||||
this.deviceQuery.machineryName = ''
|
||||
this.getDeviceList()
|
||||
},
|
||||
openDeviceDialog() {
|
||||
this.selectedDeviceRows = []
|
||||
this.deviceDialogOpen = true
|
||||
this.getDeviceList()
|
||||
},
|
||||
handleDeviceSelectionChange(rows) {
|
||||
this.selectedDeviceRows = rows || []
|
||||
},
|
||||
appendSelectedDevices() {
|
||||
if (!this.selectedDeviceRows.length) {
|
||||
this.$modal.msgWarning('请先选择设备')
|
||||
return
|
||||
}
|
||||
const codeMap = {}
|
||||
let changed = false
|
||||
this.machineConfigs.forEach(item => {
|
||||
codeMap[item.machineCode] = true
|
||||
})
|
||||
this.selectedDeviceRows.forEach(item => {
|
||||
if (codeMap[item.machineryCode]) {
|
||||
return
|
||||
}
|
||||
this.deviceNameMap[item.machineryCode] = item.machineryName
|
||||
this.machineConfigs.push(createMachineConfig(item))
|
||||
changed = true
|
||||
})
|
||||
if (!changed) {
|
||||
this.$modal.msgWarning('所选设备已存在')
|
||||
return
|
||||
}
|
||||
this.machineConfigs.sort((a, b) => a.machineCode.localeCompare(b.machineCode))
|
||||
this.activeMachines = this.machineConfigs.map(item => item.machineCode)
|
||||
this.persistConfig({
|
||||
successMessage: '设备添加成功',
|
||||
onSuccess: () => {
|
||||
this.deviceDialogOpen = false
|
||||
}
|
||||
})
|
||||
},
|
||||
removeMachine(machineCode) {
|
||||
this.machineConfigs = this.machineConfigs.filter(item => item.machineCode !== machineCode)
|
||||
this.activeMachines = this.machineConfigs.map(item => item.machineCode)
|
||||
this.persistConfig({
|
||||
successMessage: '设备移除成功'
|
||||
})
|
||||
},
|
||||
openBindingEditor(machine, binding) {
|
||||
this.editMachine = { ...machine }
|
||||
this.editForm = JSON.parse(JSON.stringify(binding))
|
||||
this.editorOpen = true
|
||||
},
|
||||
openPointDialog() {
|
||||
this.pointDialogOpen = true
|
||||
this.getPointList()
|
||||
},
|
||||
getPointList() {
|
||||
this.pointLoading = true
|
||||
listMeasurePoint(this.pointQuery).then(response => {
|
||||
this.pointList = response.rows || []
|
||||
}).finally(() => {
|
||||
this.pointLoading = false
|
||||
})
|
||||
},
|
||||
resetPointQuery() {
|
||||
this.pointQuery.pointCode = ''
|
||||
this.pointQuery.pointName = ''
|
||||
this.pointQuery.deviceCode = ''
|
||||
this.getPointList()
|
||||
},
|
||||
selectPoint(row) {
|
||||
this.editForm.pointId = row.pointId
|
||||
this.editForm.pointCode = row.pointCode
|
||||
this.editForm.pointName = row.pointName
|
||||
this.pointDialogOpen = false
|
||||
},
|
||||
clearPoint() {
|
||||
this.editForm.pointId = null
|
||||
this.editForm.pointCode = ''
|
||||
this.editForm.pointName = ''
|
||||
},
|
||||
submitBindingEdit() {
|
||||
const machine = this.machineConfigs.find(item => item.machineCode === this.editMachine.machineCode)
|
||||
if (!machine) {
|
||||
return
|
||||
}
|
||||
const target = machine.bindings.find(item => item.bindingField === this.editForm.bindingField)
|
||||
if (target) {
|
||||
Object.assign(target, this.editForm)
|
||||
}
|
||||
this.editorOpen = false
|
||||
this.refreshPreview()
|
||||
this.persistConfig({
|
||||
successMessage: '点位配置已保存'
|
||||
})
|
||||
},
|
||||
persistConfig({ successMessage, onSuccess } = {}) {
|
||||
if (!this.currentScreen) {
|
||||
return
|
||||
}
|
||||
const bindings = []
|
||||
this.machineConfigs.forEach(machine => {
|
||||
machine.bindings.forEach(binding => {
|
||||
bindings.push({
|
||||
bindingId: binding.bindingId,
|
||||
screenId: this.currentScreen.screenId,
|
||||
screenCode: this.currentScreen.screenCode,
|
||||
machineryId: machine.machineryId,
|
||||
machineryCode: machine.machineCode,
|
||||
bindingField: binding.bindingField,
|
||||
pointId: binding.pointId,
|
||||
pointCode: binding.pointCode || '',
|
||||
pointName: binding.pointName || '',
|
||||
sortNum: binding.sortNum,
|
||||
enableFlag: 'Y'
|
||||
})
|
||||
})
|
||||
})
|
||||
this.saveLoading = true
|
||||
saveBoardScreenConfig({
|
||||
screenId: this.currentScreen.screenId,
|
||||
screenCode: this.currentScreen.screenCode,
|
||||
bindings
|
||||
}).then(response => {
|
||||
this.machineConfigs = groupBindings(response.data || [], this.deviceNameMap)
|
||||
this.activeMachines = this.machineConfigs.map(item => item.machineCode)
|
||||
this.refreshPreview()
|
||||
if (typeof onSuccess === 'function') {
|
||||
onSuccess()
|
||||
}
|
||||
this.$modal.msgSuccess(successMessage || response.msg || '保存成功')
|
||||
this.getScreenList()
|
||||
}).finally(() => {
|
||||
this.saveLoading = false
|
||||
})
|
||||
},
|
||||
resetConfig() {
|
||||
if (!this.currentScreen) {
|
||||
return
|
||||
}
|
||||
this.$modal.confirm('是否确认清空当前看板的设备绑定和点位配置?').then(() => {
|
||||
return resetBoardScreenConfig(this.currentScreen.screenId)
|
||||
}).then(() => {
|
||||
this.machineConfigs = []
|
||||
this.activeMachines = []
|
||||
this.latestMap = {}
|
||||
this.$modal.msgSuccess('已清空绑定配置')
|
||||
this.getScreenList()
|
||||
}).catch(() => {})
|
||||
},
|
||||
refreshPreview() {
|
||||
const pointCodes = collectPointCodes(this.machineConfigs)
|
||||
if (!pointCodes.length) {
|
||||
this.latestMap = {}
|
||||
return
|
||||
}
|
||||
Promise.all(pointCodes.map(pointCode => {
|
||||
return getMeasurePointLatest(pointCode).then(response => {
|
||||
const payload = response && response.data !== undefined ? response.data : response
|
||||
return {
|
||||
pointCode,
|
||||
value: payload.latestValue !== undefined ? payload.latestValue : payload.value,
|
||||
latestTime: payload.latestTime || payload.collectTime || payload.time || ''
|
||||
}
|
||||
}).catch(() => ({
|
||||
pointCode,
|
||||
value: '',
|
||||
latestTime: ''
|
||||
}))
|
||||
})).then(list => {
|
||||
this.latestMap = list.reduce((result, item) => {
|
||||
result[item.pointCode] = item
|
||||
return result
|
||||
}, {})
|
||||
})
|
||||
},
|
||||
getPointSummary(binding) {
|
||||
if (!binding.pointCode) {
|
||||
return '未配置测量点'
|
||||
}
|
||||
return `${binding.pointCode} / ${binding.pointName || '--'}`
|
||||
},
|
||||
getPreviewValue(binding) {
|
||||
if (!binding.pointCode) {
|
||||
return '--'
|
||||
}
|
||||
const latest = this.latestMap[binding.pointCode] || {}
|
||||
const value = latest.value
|
||||
return value === undefined || value === null || value === '' ? '--' : value
|
||||
},
|
||||
formatPointLatest(row) {
|
||||
const value = row.latestValue === undefined || row.latestValue === null || row.latestValue === '' ? '--' : row.latestValue
|
||||
if (!row.unit || value === '--') {
|
||||
return value
|
||||
}
|
||||
return `${value}${row.unit}`
|
||||
},
|
||||
openBoard() {
|
||||
if (!this.currentScreen) {
|
||||
return
|
||||
}
|
||||
const routeData = this.$router.resolve({
|
||||
path: '/board/workshop',
|
||||
query: {
|
||||
screenCode: this.currentScreen.screenCode
|
||||
}
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.board-screen-page {
|
||||
min-width: 1200px;
|
||||
}
|
||||
|
||||
.panel-card {
|
||||
min-height: 680px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.screen-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.screen-subtitle {
|
||||
margin-top: 6px;
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.empty-block {
|
||||
min-height: 520px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.machine-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.machine-name {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.machine-remove {
|
||||
margin-left: auto;
|
||||
margin-right: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user