修复工序单元预设设定值运行时模板错误
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled

This commit is contained in:
sheng
2026-06-26 14:23:33 +08:00
parent 9eacf495f1
commit 561e0413e8
6 changed files with 929 additions and 856 deletions

View File

@@ -0,0 +1,208 @@
<template>
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-divider content-position="left">{{ config.title }}</el-divider>
<el-form :model="form" label-position="right" label-width="160px" size="mini" class="device-setting-form">
<el-row :gutter="16">
<el-col v-for="field in config.fields" :key="field.prop" :span="12">
<el-form-item :label="field.label">
<el-checkbox
v-if="field.type === 'checkbox'"
v-model="form[field.prop]"
true-label="1"
false-label=""
/>
<el-select
v-else-if="field.type === 'select'"
v-model="form[field.prop]"
placeholder="请选择"
clearable
filterable
style="width:100%"
>
<el-option
v-for="option in field.options"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<el-input v-else v-model="form[field.prop]" placeholder="请输入内容" clearable>
<template v-if="field.unit" slot="append">{{ field.unit }}</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
</template>
<script>
function isJson (value) {
if (typeof value !== 'string') return false
try {
JSON.parse(value)
return true
} catch (e) {
return false
}
}
function parseSetting (value, fallback = { process: {} }) {
if (value === undefined || value === null || value === '') return JSON.parse(JSON.stringify(fallback))
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
if (isJson(value)) return JSON.parse(value)
return JSON.parse(JSON.stringify(fallback))
}
const deviceSettingForms = {
DvPlugin: {
title: 'OCV 通用设定',
fields: [
{ prop: 'ocv_min_read_range', label: 'OCV读取下限', unit: 'mV' },
{ prop: 'ocv_max_read_range', label: 'OCV读取上限', unit: 'mV' },
{ prop: 'ir_min_read_range', label: 'IR读取下限', unit: 'mΩ' },
{ prop: 'ir_max_read_range', label: 'IR读取上限', unit: 'mΩ' },
{ prop: 'NG_threshold', label: 'NG阈值', unit: '个' },
{ prop: 'pin_count', label: '接触检查不良报警次数', unit: '0不报警' },
{ prop: 'K_ext', label: 'K值开关', type: 'checkbox' },
{ prop: 'process_code', label: '工序编码' },
{ prop: 'K_min_read_range', label: 'K值读取下限', unit: 'mV/h' },
{ prop: 'K_max_read_range', label: 'K值读取上限', unit: 'mV/h' }
],
defaults: {
ocv_min_read_range: undefined,
ocv_max_read_range: undefined,
ir_min_read_range: undefined,
ir_max_read_range: undefined,
K_min_read_range: undefined,
K_max_read_range: undefined,
pin_count: undefined,
process_code: undefined,
NG_threshold: 0
}
},
OcvrPlugin: {
title: 'DCIR 通用设定',
fields: [
{
prop: 'SETWKMODE',
label: '工作模式',
type: 'select',
options: [
{ label: '静置-充电1', value: '0' },
{ label: '静置-放电1', value: '1' },
{ label: '静置-充电1-充电2', value: '2' },
{ label: '静置-放电1-放电2', value: '3' },
{ label: '静置-充电1-充电2-静置-充电1-充电2', value: '4' },
{ label: '静置-放电1-放电2-静置-放电1-放电2', value: '5' },
{ label: '静置-充电1-充电2-静置-放电1-放电2', value: '6' },
{ label: '静置-放电1-放电2-静置-充电1-充电2', value: '7' },
{ label: '静置-放电-静置-充电', value: '8' },
{ label: '静置-充电-静置-放电', value: '9' }
]
},
{ prop: 'VDROP', label: '最大压降' },
{ prop: 'SETUPV', label: '电压上限', unit: 'mV' },
{ prop: 'SETLWV', label: '电压下限', unit: 'mV' },
{ prop: 'DCR1_up', label: 'DCR1上限', unit: 'mΩ' },
{ prop: 'DCR1_low', label: 'DCR1下限', unit: 'mΩ' },
{ prop: 'DCR2_up', label: 'DCR2上限', unit: 'mΩ' },
{ prop: 'DCR2_low', label: 'DCR2下限', unit: 'mΩ' },
{ prop: 'REST_T', label: '静置时间', unit: 's' },
{ prop: 'NG_threshold', label: 'NG阈值', unit: '个' },
{ prop: 'contact_alarm', label: '接触报警次数', unit: '0不报警' },
{ prop: 'time_interval', label: '过程数据保存时间', unit: 'ms' },
{ prop: 'I1_1', label: '阶段1电流1', unit: 'mA' },
{ prop: 'I1_2', label: '阶段1电流2', unit: 'mA' },
{ prop: 'T1_1', label: '阶段1工作时间1', unit: 's' },
{ prop: 'T1_2', label: '阶段1工作时间2', unit: 's' },
{ prop: 'REST_T_1', label: '阶段1静置时间', unit: 's' },
{ prop: 'CT_1', label: '阶段1采样时间', unit: 's' },
{ prop: 'I2_1', label: '阶段2电流1', unit: 'mA' },
{ prop: 'I2_2', label: '阶段2电流2', unit: 'mA' },
{ prop: 'T2_1', label: '阶段2工作时间1', unit: 's' },
{ prop: 'T2_2', label: '阶段2工作时间2', unit: 's' },
{ prop: 'REST_T_2', label: '阶段2静置时间', unit: 's' },
{ prop: 'CT_2', label: '阶段2采样时间', unit: 's' }
],
defaults: {
SETUPV: undefined,
SETLWV: undefined,
REST_T: undefined,
VDROP: undefined,
contact_alarm: undefined,
time_interval: undefined,
DCR1_up: undefined,
DCR1_low: undefined,
DCR2_up: undefined,
DCR2_low: undefined,
I1_1: undefined,
I2_1: undefined,
I1_2: undefined,
I2_2: undefined,
T1_1: undefined,
T2_1: undefined,
T1_2: undefined,
T2_2: undefined,
REST_T_1: undefined,
REST_T_2: undefined,
CT_1: undefined,
CT_2: undefined,
SETWKMODE: undefined,
NG_threshold: 0
}
}
}
export default {
name: 'ProcessStepDeviceSettingPlugin',
props: {
type: { type: String, default: '' },
settingJson: { default: '' }
},
data () {
return {
activeTab: 'process',
json: { process: {} },
form: {}
}
},
computed: {
config () {
return deviceSettingForms[this.type] || deviceSettingForms.DvPlugin
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, { process: {} })
this.json = parsed
this.form = { ...this.config.defaults, ...(parsed.process || {}) }
},
immediate: true
},
form: {
handler (val) {
this.json = { ...this.json, process: { ...val } }
},
deep: true
}
},
methods: {
handleFormSubmit () {
this.$emit('submit', this.json)
}
}
}
</script>
<style scoped>
.device-setting-form /deep/ .el-form-item--mini.el-form-item {
margin-bottom: 10px;
}
</style>

View File

@@ -0,0 +1,331 @@
<template>
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-divider content-position="left">全局配置</el-divider>
<el-form :model="globalSetting" size="mini" label-width="130px" class="formation-global-form">
<el-row :gutter="12">
<el-col v-for="item in globalFields" :key="item.prop" :span="8">
<el-form-item :label="item.label">
<el-input v-model="globalSetting[item.prop]" placeholder="请输入内容" clearable>
<el-button slot="append">{{ item.unit }}</el-button>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">设置工步</el-divider>
<el-button type="primary" icon="el-icon-plus" size="mini" style="margin-bottom:10px" @click="addRow">新增一行</el-button>
<el-table
:data="tableData"
border
stripe
size="mini"
height="350"
:row-class-name="rowClassName"
style="width:100%"
>
<el-table-column width="56" fixed>
<template slot-scope="{ $index }">
<i v-if="$index > 0" class="el-icon-sort-up formation-sort" @click="moveUp($index)" />
<i v-if="$index < tableData.length - 1" class="el-icon-sort-down formation-sort" @click="moveDown($index)" />
</template>
</el-table-column>
<el-table-column label="工步" width="56" fixed>
<template slot-scope="{ $index }">{{ $index + 1 }}</template>
</el-table-column>
<el-table-column
v-for="column in processColumns"
:key="column.prop"
:label="column.label"
:width="column.width"
:fixed="column.prop === 'station'"
>
<template slot-scope="{ row }">
<el-select
v-if="column.type === 'select'"
v-model="row[column.prop]"
size="mini"
clearable
@change="column.prop === 'station' ? stationChange(row) : undefined"
>
<el-option
v-for="option in $data[column.options]"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<el-input v-else v-model="row[column.prop]" size="mini" type="number" clearable />
</template>
</el-table-column>
<el-table-column label="操作" width="80" fixed="right">
<template slot-scope="{ $index }">
<el-button type="text" size="mini" style="color:#F56C6C" @click="removeRow($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
</template>
<script>
function parseSetting (value, fallback) {
if (value === undefined || value === null || value === '') return JSON.parse(JSON.stringify(fallback))
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
try {
return JSON.parse(value)
} catch (e) {
return JSON.parse(JSON.stringify(fallback))
}
}
export default {
name: 'ProcessStepFormationSettingPlugin',
props: {
settingJson: { default: '' },
workingsubclassCode: { type: String, default: '' }
},
data () {
return {
activeTab: 'process',
json: { action: 'start', time: new Date(), process: [], setting: {} },
globalSetting: {},
tableData: [],
stationList: [
{ label: '结束', value: '6' },
{ label: '恒流充电', value: '1' },
{ label: '恒流恒压充电', value: '2' },
{ label: '搁置', value: '3' },
{ label: '恒流放电', value: '4' },
{ label: '循环', value: '5' },
{ label: '恒流恒压放电', value: '12' }
],
timeOverList: [
{ label: '', value: '' },
{ label: 'OFF', value: 'OFF' },
{ label: 'TYPE_A', value: 'TYPE_A' },
{ label: 'TYPE_B', value: 'TYPE_B' }
],
globalFields: [
{ prop: 'contact_check', label: '接触检查报警', unit: 'PIN' },
{ prop: 'curve_sampling_time', label: '曲线取样时间', unit: 's' },
{ prop: 'device_emg_voltage', label: '急停电压', unit: 'mV' },
{ prop: 'alarm_temperature_upper', label: '库位温度上限', unit: '℃' },
{ prop: 'fire_temperature_upper', label: '库位消防上限', unit: '℃' },
{ prop: 'upper_charging_voltage', label: '充电上限电压', unit: 'mV' },
{ prop: 'lower_charging_voltage', label: '充电下限电压', unit: 'mV' },
{ prop: 'upper_charging_current', label: '充电上限电流', unit: 'mA' },
{ prop: 'lower_charging_current', label: '充电下限电流', unit: 'mA' },
{ prop: 'upper_charging_capacity', label: '充电上限容量', unit: 'mA/h' },
{ prop: 'lower_charging_capacity', label: '充电下限容量', unit: 'mA/h' },
{ prop: 'upper_discharge_voltage', label: '放电上限电压', unit: 'mV' },
{ prop: 'lower_discharge_voltage', label: '放电下限电压', unit: 'mV' },
{ prop: 'upper_discharge_current', label: '放电上限电流', unit: 'mA' },
{ prop: 'lower_discharge_current', label: '放电下限电流', unit: 'mA' },
{ prop: 'upper_discharge_capacity', label: '放电上限容量', unit: 'mA/h' },
{ prop: 'lower_discharge_capacity', label: '放电下限容量', unit: 'mA/h' }
],
processColumns: [
{ prop: 'station', label: '工步状态', width: 120, type: 'select', options: 'stationList' },
{ prop: 'time', label: '时间(秒)', width: 120 },
{ prop: 'current', label: '电流(mA)', width: 120 },
{ prop: 'upperVoltage', label: '上限电压(mV)', width: 120 },
{ prop: 'lowerVoltage', label: '下限电压(mV)', width: 120 },
{ prop: 'stop_DeltaVoltage', label: 'ΔV(mV)', width: 100 },
{ prop: 'stop_Current', label: '终止电流(mA)', width: 120 },
{ prop: 'stop_Capacity', label: '终止容量(mA/h)', width: 130 },
{ prop: 'cct_begin', label: 'CCT下限(s)', width: 100 },
{ prop: 'cct_end', label: 'CCT上限(s)', width: 100 },
{ prop: 'time_over', label: 'TIMEOVER', width: 120, type: 'select', options: 'timeOverList' },
{ prop: 'temperature', label: '温度(℃)', width: 100 },
{ prop: 'upperTemperature', label: '温度上限(℃)', width: 120 },
{ prop: 'lowerTemperature', label: '温度下限(℃)', width: 120 },
{ prop: 'pressure', label: '压力kg', width: 100 }
]
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, {
action: 'start',
time: new Date(),
process: [],
setting: { contact_check: '0', curve_sampling_time: 10 }
})
parsed.process = Array.isArray(parsed.process) ? parsed.process : []
parsed.setting = parsed.setting || {}
this.json = parsed
this.globalSetting = { ...parsed.setting }
for (const key of this.globalFields.map(item => item.prop)) {
if (Object.prototype.hasOwnProperty.call(parsed, key) && !Object.prototype.hasOwnProperty.call(this.globalSetting, key)) {
this.$set(this.globalSetting, key, parsed[key])
}
}
this.tableData = parsed.process.map(row => ({
...row,
station: row.station !== undefined && row.station !== null ? String(row.station) : '',
time_over: row.time_over !== undefined && row.time_over !== null ? String(row.time_over) : ''
}))
},
immediate: true
},
globalSetting: {
handler () {
this.syncJson()
},
deep: true
},
tableData: {
handler () {
this.syncJson()
},
deep: true
}
},
methods: {
syncJson () {
const setting = {}
Object.keys(this.globalSetting || {}).forEach(key => {
const value = this.globalSetting[key]
if (value !== '' && value !== undefined && value !== null) {
setting[key] = this.toNumberIfNumeric(value)
}
})
const process = this.tableData.map(row => {
const item = {}
Object.keys(row).forEach(key => {
const value = row[key]
if (value !== '' && value !== undefined && value !== null) {
item[key] = key === 'time_over' ? value : this.toNumberIfNumeric(value)
}
})
return item
})
if (process[0] && setting.contact_check !== undefined) {
process[0].contact_check = setting.contact_check
}
this.json = {
...this.json,
process,
setting
}
},
toNumberIfNumeric (value) {
if (value === '' || value === null || value === undefined) return value
return /^-?\d+(\.\d+)?$/.test(String(value)) ? Number(value) : value
},
rowClassName ({ row }) {
const station = String(row.station)
if (station === '5') return 'formation-row-cycle'
if (station === '1') return 'formation-row-charge'
if (station === '2') return 'formation-row-charge-cv'
if (station === '3') return 'formation-row-rest'
if (station === '4') return 'formation-row-discharge'
return ''
},
addRow () {
if (this.tableData.some(row => String(row.station) === '6')) {
this.$message.info('已有结束工步,不能新增')
return
}
this.tableData.push({ station: '' })
},
removeRow (index) {
this.tableData.splice(index, 1)
},
moveUp (index) {
if (index <= 0) return
const row = this.tableData.splice(index, 1)[0]
this.tableData.splice(index - 1, 0, row)
},
moveDown (index) {
if (index >= this.tableData.length - 1) return
const row = this.tableData.splice(index, 1)[0]
this.tableData.splice(index + 1, 0, row)
},
stationChange (row) {
if (String(row.station) === '5') {
Object.keys(row).forEach(key => {
if (key !== 'station') this.$set(row, key, '')
})
}
if (String(row.station) === '6') {
const index = this.tableData.indexOf(row)
this.tableData = this.tableData.slice(0, index + 1)
}
},
showMsg (message) {
this.$message.warning(message)
},
validateProcess () {
if (!this.tableData.some(row => String(row.station) === '6')) {
this.$message.info('检测到没有添加结束工步')
return false
}
const process = this.json.process || []
for (let n = 0; n < process.length; n++) {
const row = process[n]
const station = Number(row.station)
const miss = name => {
this.showMsg(`${n + 1}工步的必填项 【${name}】 没有填写`)
return false
}
if ((this.workingsubclassCode === 'HC' || this.workingsubclassCode === 'FR') && station !== 6) {
if (row.pressure === undefined || row.pressure === '') return miss('压力')
if (row.temperature === undefined || row.temperature === '') return miss('温度')
}
if (station === 3) {
if (row.time === undefined || row.time === '') return miss('工作时间')
} else if (station === 12 || station === 2) {
if (row.time === undefined || row.time === '') return miss('工作时间')
if (row.current === undefined || row.current === '') return miss('电流')
if (row.stop_Current === undefined || row.stop_Current === '') return miss('终止电流')
if (station === 12 && (row.lowerVoltage === undefined || row.lowerVoltage === '')) return miss('下限电压')
if (station === 2 && (row.upperVoltage === undefined || row.upperVoltage === '')) return miss('上限电压')
} else if (station === 4 || station === 1) {
if (row.time === undefined || row.time === '') return miss('工作时间')
if (row.current === undefined || row.current === '') return miss('电流')
if (station === 4 && (row.lowerVoltage === undefined || row.lowerVoltage === '')) return miss('下限电压')
if (station === 1 && (row.upperVoltage === undefined || row.upperVoltage === '')) return miss('上限电压')
}
}
return true
},
handleFormSubmit () {
this.syncJson()
if (!this.validateProcess()) return
this.$emit('submit', this.json)
}
}
}
</script>
<style scoped>
.formation-global-form /deep/ .el-form-item--mini.el-form-item {
margin-bottom: 8px;
}
.formation-sort {
cursor: pointer;
margin-right: 4px;
color: #409EFF;
}
/deep/ .formation-row-cycle {
background-color: #ffc0ff !important;
}
/deep/ .formation-row-charge {
background-color: #ffff00 !important;
}
/deep/ .formation-row-charge-cv {
background-color: #ffffc0 !important;
}
/deep/ .formation-row-rest {
background-color: #e0e0e0 !important;
}
/deep/ .formation-row-discharge {
background-color: #c0c0c0 !important;
}
</style>

View File

@@ -0,0 +1,69 @@
<template>
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-alert
v-if="type || code"
:title="[type, code].filter(Boolean).join(' / ')"
type="info"
:closable="false"
show-icon
style="margin-bottom:12px"
/>
<el-input v-model="textarea" type="textarea" :rows="15" placeholder="请输入内容" />
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
</template>
<script>
function parseSetting (value) {
if (value === undefined || value === null || value === '') return { process: {} }
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
try {
return JSON.parse(value)
} catch (e) {
return { process: {} }
}
}
export default {
name: 'ProcessStepJsonSettingPlugin',
props: {
settingJson: { default: '' },
type: { type: String, default: '' },
code: { type: String, default: '' }
},
data () {
return {
activeTab: 'process',
json: { process: {} },
textarea: '{}'
}
},
watch: {
settingJson: {
handler (val) {
this.json = parseSetting(val)
this.textarea = JSON.stringify(this.json.process || {}, null, 2)
},
immediate: true
}
},
methods: {
handleFormSubmit () {
if (!this.textarea) {
this.$message.info('输入内容不能为空')
return
}
try {
this.json.process = JSON.parse(this.textarea)
this.$emit('submit', this.json)
} catch (e) {
this.$message.error('JSON 格式不正确')
}
}
}
}
</script>

View File

@@ -0,0 +1,237 @@
<template>
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<div class="non-standard-setting">
<div class="setting-search-card">
<el-card class="box-card" style="height:550px">
<div slot="header">
<span>查询</span>
</div>
<el-form label-position="top" :model="searchForm" size="mini">
<el-form-item label="名称">
<el-input v-model.trim="searchForm.name" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item label="参数">
<el-input v-model.trim="searchForm.code" placeholder="请输入参数" clearable />
</el-form-item>
</el-form>
</el-card>
</div>
<div class="setting-table">
<el-table :data="filteredRows" border height="550" style="width:100%">
<el-table-column prop="name" label="名称" width="220" show-overflow-tooltip />
<el-table-column prop="code" label="参数" width="180" show-overflow-tooltip />
<el-table-column prop="value" label="默认值" min-width="140" show-overflow-tooltip />
<el-table-column label="单位" width="140" show-overflow-tooltip>
<template slot-scope="{ row }">{{ unitMap[row.unit] || row.unit }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" width="100" fixed="right" align="center">
<template slot-scope="{ row }">
<el-button type="text" icon="el-icon-edit" @click="openEdit(row)" />
<el-button type="text" icon="el-icon-delete" style="color:#F56C6C" @click="removeRow(row)" />
</template>
</el-table-column>
</el-table>
<div class="setting-actions">
<el-button type="primary" size="small" @click="openAdd">新增一行</el-button>
</div>
</div>
</div>
<el-dialog
:title="editIndex >= 0 ? '编辑' : '新增'"
:visible.sync="dialogVisible"
append-to-body
width="800px"
>
<el-form ref="form" :model="form" :rules="rules" label-width="100px" size="mini">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="参数" prop="code">
<el-input v-model="form.code" placeholder="请输入参数" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="请输入名称" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="默认值" prop="value">
<el-input v-model="form.value" placeholder="请输入默认值" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位" prop="unit">
<el-select v-model="form.unit" placeholder="请选择单位" filterable clearable style="width:100%">
<el-option
v-for="item in unitOptions"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" placeholder="请输入备注" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitRow">确定</el-button>
</div>
</el-dialog>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
</template>
<script>
import { getUnitAll } from '@/api/production-master-data/material-unit'
function isJson (value) {
if (typeof value !== 'string') return false
try {
JSON.parse(value)
return true
} catch (e) {
return false
}
}
function parseSetting (value, fallback = { process: [] }) {
if (value === undefined || value === null || value === '') return JSON.parse(JSON.stringify(fallback))
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
if (isJson(value)) return JSON.parse(value)
return JSON.parse(JSON.stringify(fallback))
}
export default {
name: 'ProcessStepNonStandardSettingPlugin',
props: { settingJson: { default: '' } },
data () {
return {
activeTab: 'process',
json: { process: [] },
rows: [],
searchForm: { name: '', code: '' },
dialogVisible: false,
editIndex: -1,
form: { code: '', name: '', value: '', unit: '', remark: '' },
rules: {
code: [{ required: true, message: '请输入参数', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
value: [{ required: true, message: '请输入默认值', trigger: 'blur' }],
unit: [{ required: true, message: '请选择单位', trigger: 'change' }]
},
unitOptions: [],
unitMap: {}
}
},
computed: {
filteredRows () {
const name = (this.searchForm.name || '').trim()
const code = (this.searchForm.code || '').trim()
return this.rows.filter(row => {
const matchName = !name || String(row.name || '').includes(name)
const matchCode = !code || String(row.code || '').includes(code)
return matchName && matchCode
})
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, { process: [] })
const process = Array.isArray(parsed.process) ? parsed.process : []
this.json = { ...parsed, process }
this.rows = process.map(item => ({ ...item }))
},
immediate: true
},
rows: {
handler (val) {
this.json = { ...this.json, process: val.map(item => ({ ...item })) }
},
deep: true
}
},
created () {
getUnitAll().then(res => {
const list = (res && res.data && (res.data.data || res.data.list || res.data)) || []
this.unitOptions = Array.isArray(list) ? list : []
this.unitMap = this.unitOptions.reduce((map, item) => {
map[item.code] = item.name
return map
}, {})
}).catch(() => {
this.unitOptions = []
this.unitMap = {}
})
},
methods: {
openAdd () {
this.editIndex = -1
this.form = { code: '', name: '', value: '', unit: '', remark: '' }
this.dialogVisible = true
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
},
openEdit (row) {
this.editIndex = this.rows.indexOf(row)
this.form = { ...row }
this.dialogVisible = true
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
},
removeRow (row) {
const index = this.rows.indexOf(row)
if (index !== -1) this.rows.splice(index, 1)
},
submitRow () {
this.$refs.form.validate(valid => {
if (!valid) return
const duplicate = this.rows.some((item, index) => {
return index !== this.editIndex && (item.name === this.form.name || item.code === this.form.code)
})
if (duplicate) {
this.$message.error('名称或参数已存在')
return
}
if (this.editIndex >= 0) {
this.$set(this.rows, this.editIndex, { ...this.form })
} else {
this.rows.push({ ...this.form })
}
this.dialogVisible = false
})
},
handleFormSubmit () {
this.$emit('submit', this.json)
}
}
}
</script>
<style scoped>
.non-standard-setting {
display: flex;
flex-direction: row;
justify-content: center;
}
.setting-search-card {
width: 20%;
margin-right: 20px;
}
.setting-table {
width: 80%;
}
.setting-actions {
margin-top: 10px;
text-align: right;
}
</style>

View File

@@ -25,820 +25,21 @@
<script> <script>
import { i18nMixin } from '@/composables/useI18n' import { i18nMixin } from '@/composables/useI18n'
import { getUnitAll } from '@/api/production-master-data/material-unit' import WaitPlugin from './wait-setting-plugin.vue'
import JsonPlugin from './json-setting-plugin.vue'
function isJson (value) { import FormationPlugin from './formation-setting-plugin.vue'
if (typeof value !== 'string') return false import DeviceSettingPlugin from './device-setting-plugin.vue'
try { import NonStandardSettingPlugin from './non-standard-setting-plugin.vue'
JSON.parse(value)
return true
} catch (e) {
return false
}
}
function parseSetting (value, fallback = { process: {} }) {
if (value === undefined || value === null || value === '') return JSON.parse(JSON.stringify(fallback))
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
if (isJson(value)) return JSON.parse(value)
return JSON.parse(JSON.stringify(fallback))
}
const WaitPlugin = {
name: 'ProcessStepWaitPlugin',
mixins: [i18nMixin('page.production_master_data.process_model.process_step')],
props: { settingJson: { default: '' } },
data () {
return {
json: { process: {} },
form: { time: undefined, time_range: undefined, alert: '0' },
rules: {
time: [{ pattern: /^[0-9]\d*$/, message: '请输入大于等于 0 的整数', trigger: 'change' }],
time_range: [{ pattern: /^[0-9]\d*$/, message: '请输入大于等于 0 的整数', trigger: 'change' }]
}
}
},
watch: {
settingJson: {
handler (val) {
const json = parseSetting(val, { process: {} })
this.json = json
this.form = {
time: json.process && json.process.time !== undefined ? json.process.time : undefined,
time_range: json.process && json.process.time_range !== undefined ? json.process.time_range : undefined,
alert: json.process && json.process.alert !== undefined ? json.process.alert : '0'
}
},
immediate: true
},
form: {
handler (val) {
this.json = { process: { ...val } }
},
deep: true
}
},
methods: {
handleFormSubmit () {
this.$refs.form.validate(valid => {
if (!valid) {
this.$message.error(this.$t(this.key('validation_fail')))
return
}
this.$emit('submit', this.json)
})
}
},
template: `
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="mini">
<el-form-item label="静置时间" prop="time">
<el-input v-model="form.time" placeholder="请输入静置时间" clearable>
<template slot="append">分钟</template>
</el-input>
</el-form-item>
<el-form-item label="精度范围" prop="time_range">
<el-input v-model="form.time_range" placeholder="请输入精度范围" clearable>
<template slot="append">分钟</template>
</el-input>
</el-form-item>
</el-form>
`
}
const JsonPlugin = {
name: 'ProcessStepJsonPlugin',
mixins: [i18nMixin('page.production_master_data.process_model.process_step')],
props: {
settingJson: { default: '' },
type: { type: String, default: '' },
code: { type: String, default: '' }
},
data () {
return {
activeTab: 'process',
json: { process: {} },
textarea: '{}'
}
},
watch: {
settingJson: {
handler (val) {
this.json = parseSetting(val, { process: {} })
this.textarea = JSON.stringify(this.json.process || {}, null, 2)
},
immediate: true
}
},
methods: {
handleFormSubmit () {
if (!this.textarea) {
this.$message.info('输入内容不能为空')
return
}
try {
this.json.process = JSON.parse(this.textarea)
this.$emit('submit', this.json)
} catch (e) {
this.$message.error(this.$t(this.key('json_format_error')))
}
}
},
template: `
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-alert
v-if="type || code"
:title="[type, code].filter(Boolean).join(' / ')"
type="info"
:closable="false"
show-icon
style="margin-bottom:12px"
/>
<el-input v-model="textarea" type="textarea" :rows="15" placeholder="请输入内容" />
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
`
}
const deviceSettingForms = {
DvPlugin: {
title: 'OCV 通用设定',
fields: [
{ prop: 'ocv_min_read_range', label: 'OCV读取下限', unit: 'mV' },
{ prop: 'ocv_max_read_range', label: 'OCV读取上限', unit: 'mV' },
{ prop: 'ir_min_read_range', label: 'IR读取下限', unit: 'mΩ' },
{ prop: 'ir_max_read_range', label: 'IR读取上限', unit: 'mΩ' },
{ prop: 'NG_threshold', label: 'NG阈值', unit: '个' },
{ prop: 'pin_count', label: '接触检查不良报警次数', unit: '0不报警' },
{ prop: 'K_ext', label: 'K值开关', type: 'checkbox' },
{ prop: 'process_code', label: '工序编码' },
{ prop: 'K_min_read_range', label: 'K值读取下限', unit: 'mV/h' },
{ prop: 'K_max_read_range', label: 'K值读取上限', unit: 'mV/h' }
],
defaults: {
ocv_min_read_range: undefined,
ocv_max_read_range: undefined,
ir_min_read_range: undefined,
ir_max_read_range: undefined,
K_min_read_range: undefined,
K_max_read_range: undefined,
pin_count: undefined,
process_code: undefined,
NG_threshold: 0
}
},
OcvrPlugin: {
title: 'DCIR 通用设定',
fields: [
{
prop: 'SETWKMODE',
label: '工作模式',
type: 'select',
options: [
{ label: '静置-充电1', value: '0' },
{ label: '静置-放电1', value: '1' },
{ label: '静置-充电1-充电2', value: '2' },
{ label: '静置-放电1-放电2', value: '3' },
{ label: '静置-充电1-充电2-静置-充电1-充电2', value: '4' },
{ label: '静置-放电1-放电2-静置-放电1-放电2', value: '5' },
{ label: '静置-充电1-充电2-静置-放电1-放电2', value: '6' },
{ label: '静置-放电1-放电2-静置-充电1-充电2', value: '7' },
{ label: '静置-放电-静置-充电', value: '8' },
{ label: '静置-充电-静置-放电', value: '9' }
]
},
{ prop: 'VDROP', label: '最大压降' },
{ prop: 'SETUPV', label: '电压上限', unit: 'mV' },
{ prop: 'SETLWV', label: '电压下限', unit: 'mV' },
{ prop: 'DCR1_up', label: 'DCR1上限', unit: 'mΩ' },
{ prop: 'DCR1_low', label: 'DCR1下限', unit: 'mΩ' },
{ prop: 'DCR2_up', label: 'DCR2上限', unit: 'mΩ' },
{ prop: 'DCR2_low', label: 'DCR2下限', unit: 'mΩ' },
{ prop: 'REST_T', label: '静置时间', unit: 's' },
{ prop: 'NG_threshold', label: 'NG阈值', unit: '个' },
{ prop: 'contact_alarm', label: '接触报警次数', unit: '0不报警' },
{ prop: 'time_interval', label: '过程数据保存时间', unit: 'ms' },
{ prop: 'I1_1', label: '阶段1电流1', unit: 'mA' },
{ prop: 'I1_2', label: '阶段1电流2', unit: 'mA' },
{ prop: 'T1_1', label: '阶段1工作时间1', unit: 's' },
{ prop: 'T1_2', label: '阶段1工作时间2', unit: 's' },
{ prop: 'REST_T_1', label: '阶段1静置时间', unit: 's' },
{ prop: 'CT_1', label: '阶段1采样时间', unit: 's' },
{ prop: 'I2_1', label: '阶段2电流1', unit: 'mA' },
{ prop: 'I2_2', label: '阶段2电流2', unit: 'mA' },
{ prop: 'T2_1', label: '阶段2工作时间1', unit: 's' },
{ prop: 'T2_2', label: '阶段2工作时间2', unit: 's' },
{ prop: 'REST_T_2', label: '阶段2静置时间', unit: 's' },
{ prop: 'CT_2', label: '阶段2采样时间', unit: 's' }
],
defaults: {
SETUPV: undefined,
SETLWV: undefined,
REST_T: undefined,
VDROP: undefined,
contact_alarm: undefined,
time_interval: undefined,
DCR1_up: undefined,
DCR1_low: undefined,
DCR2_up: undefined,
DCR2_low: undefined,
I1_1: undefined,
I2_1: undefined,
I1_2: undefined,
I2_2: undefined,
T1_1: undefined,
T2_1: undefined,
T1_2: undefined,
T2_2: undefined,
REST_T_1: undefined,
REST_T_2: undefined,
CT_1: undefined,
CT_2: undefined,
SETWKMODE: undefined,
NG_threshold: 0
}
}
}
const DeviceSettingPlugin = {
name: 'ProcessStepDeviceSettingPlugin',
props: {
type: { type: String, default: '' },
settingJson: { default: '' }
},
data () {
return {
activeTab: 'process',
json: { process: {} },
form: {}
}
},
computed: {
config () {
return deviceSettingForms[this.type] || deviceSettingForms.DvPlugin
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, { process: {} })
this.json = parsed
this.form = { ...this.config.defaults, ...(parsed.process || {}) }
},
immediate: true
},
form: {
handler (val) {
this.json = { ...this.json, process: { ...val } }
},
deep: true
}
},
methods: {
handleFormSubmit () {
this.$emit('submit', this.json)
}
},
template: `
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-divider content-position="left">{{ config.title }}</el-divider>
<el-form :model="form" label-position="right" label-width="160px" size="mini" class="device-setting-form">
<el-row :gutter="16">
<el-col v-for="field in config.fields" :key="field.prop" :span="12">
<el-form-item :label="field.label">
<el-checkbox
v-if="field.type === 'checkbox'"
v-model="form[field.prop]"
true-label="1"
false-label=""
/>
<el-select
v-else-if="field.type === 'select'"
v-model="form[field.prop]"
placeholder="请选择"
clearable
filterable
style="width:100%"
>
<el-option
v-for="option in field.options"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<el-input v-else v-model="form[field.prop]" placeholder="请输入内容" clearable>
<template v-if="field.unit" slot="append">{{ field.unit }}</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
`
}
const NonStandardSettingPlugin = {
name: 'ProcessStepNonStandardSettingPlugin',
props: { settingJson: { default: '' } },
data () {
return {
activeTab: 'process',
json: { process: [] },
rows: [],
searchForm: { name: '', code: '' },
dialogVisible: false,
editIndex: -1,
form: { code: '', name: '', value: '', unit: '', remark: '' },
rules: {
code: [{ required: true, message: '请输入参数', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
value: [{ required: true, message: '请输入默认值', trigger: 'blur' }],
unit: [{ required: true, message: '请选择单位', trigger: 'change' }]
},
unitOptions: [],
unitMap: {}
}
},
computed: {
filteredRows () {
const name = (this.searchForm.name || '').trim()
const code = (this.searchForm.code || '').trim()
return this.rows.filter(row => {
const matchName = !name || String(row.name || '').includes(name)
const matchCode = !code || String(row.code || '').includes(code)
return matchName && matchCode
})
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, { process: [] })
const process = Array.isArray(parsed.process) ? parsed.process : []
this.json = { ...parsed, process }
this.rows = process.map(item => ({ ...item }))
},
immediate: true
},
rows: {
handler (val) {
this.json = { ...this.json, process: val.map(item => ({ ...item })) }
},
deep: true
}
},
created () {
getUnitAll().then(res => {
const list = (res && res.data && (res.data.data || res.data.list || res.data)) || []
this.unitOptions = Array.isArray(list) ? list : []
this.unitMap = this.unitOptions.reduce((map, item) => {
map[item.code] = item.name
return map
}, {})
}).catch(() => {
this.unitOptions = []
this.unitMap = {}
})
},
methods: {
openAdd () {
this.editIndex = -1
this.form = { code: '', name: '', value: '', unit: '', remark: '' }
this.dialogVisible = true
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
},
openEdit (row) {
this.editIndex = this.rows.indexOf(row)
this.form = { ...row }
this.dialogVisible = true
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
},
removeRow (row) {
const index = this.rows.indexOf(row)
if (index !== -1) this.rows.splice(index, 1)
},
submitRow () {
this.$refs.form.validate(valid => {
if (!valid) return
const duplicate = this.rows.some((item, index) => {
return index !== this.editIndex && (item.name === this.form.name || item.code === this.form.code)
})
if (duplicate) {
this.$message.error('名称或参数已存在')
return
}
if (this.editIndex >= 0) {
this.$set(this.rows, this.editIndex, { ...this.form })
} else {
this.rows.push({ ...this.form })
}
this.dialogVisible = false
})
},
handleFormSubmit () {
this.$emit('submit', this.json)
}
},
template: `
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<div class="non-standard-setting">
<div class="setting-search-card">
<el-card class="box-card" style="height:550px">
<div slot="header">
<span>查询</span>
</div>
<el-form label-position="top" :model="searchForm" size="mini">
<el-form-item label="名称">
<el-input v-model.trim="searchForm.name" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item label="参数">
<el-input v-model.trim="searchForm.code" placeholder="请输入参数" clearable />
</el-form-item>
</el-form>
</el-card>
</div>
<div class="setting-table">
<el-table :data="filteredRows" border height="550" style="width:100%">
<el-table-column prop="name" label="名称" width="220" show-overflow-tooltip />
<el-table-column prop="code" label="参数" width="180" show-overflow-tooltip />
<el-table-column prop="value" label="默认值" min-width="140" show-overflow-tooltip />
<el-table-column label="单位" width="140" show-overflow-tooltip>
<template slot-scope="{ row }">{{ unitMap[row.unit] || row.unit }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" width="100" fixed="right" align="center">
<template slot-scope="{ row }">
<el-button type="text" icon="el-icon-edit" @click="openEdit(row)" />
<el-button type="text" icon="el-icon-delete" style="color:#F56C6C" @click="removeRow(row)" />
</template>
</el-table-column>
</el-table>
<div class="setting-actions">
<el-button type="primary" size="small" @click="openAdd">新增一行</el-button>
</div>
</div>
</div>
<el-dialog
:title="editIndex >= 0 ? '编辑' : '新增'"
:visible.sync="dialogVisible"
append-to-body
width="800px"
>
<el-form ref="form" :model="form" :rules="rules" label-width="100px" size="mini">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="参数" prop="code">
<el-input v-model="form.code" placeholder="请输入参数" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="请输入名称" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="默认值" prop="value">
<el-input v-model="form.value" placeholder="请输入默认值" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位" prop="unit">
<el-select v-model="form.unit" placeholder="请选择单位" filterable clearable style="width:100%">
<el-option
v-for="item in unitOptions"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" placeholder="请输入备注" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitRow">确定</el-button>
</div>
</el-dialog>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
`
}
const FormationPlugin = {
name: 'ProcessStepFormationPlugin',
props: {
settingJson: { default: '' },
workingsubclassCode: { type: String, default: '' }
},
data () {
return {
activeTab: 'process',
json: { action: 'start', time: new Date(), process: [], setting: {} },
globalSetting: {},
tableData: [],
stationList: [
{ label: '结束', value: '6' },
{ label: '恒流充电', value: '1' },
{ label: '恒流恒压充电', value: '2' },
{ label: '搁置', value: '3' },
{ label: '恒流放电', value: '4' },
{ label: '循环', value: '5' },
{ label: '恒流恒压放电', value: '12' }
],
timeOverList: [
{ label: '', value: '' },
{ label: 'OFF', value: 'OFF' },
{ label: 'TYPE_A', value: 'TYPE_A' },
{ label: 'TYPE_B', value: 'TYPE_B' }
],
globalFields: [
{ prop: 'contact_check', label: '接触检查报警', unit: 'PIN' },
{ prop: 'curve_sampling_time', label: '曲线取样时间', unit: 's' },
{ prop: 'device_emg_voltage', label: '急停电压', unit: 'mV' },
{ prop: 'alarm_temperature_upper', label: '库位温度上限', unit: '℃' },
{ prop: 'fire_temperature_upper', label: '库位消防上限', unit: '℃' },
{ prop: 'upper_charging_voltage', label: '充电上限电压', unit: 'mV' },
{ prop: 'lower_charging_voltage', label: '充电下限电压', unit: 'mV' },
{ prop: 'upper_charging_current', label: '充电上限电流', unit: 'mA' },
{ prop: 'lower_charging_current', label: '充电下限电流', unit: 'mA' },
{ prop: 'upper_charging_capacity', label: '充电上限容量', unit: 'mA/h' },
{ prop: 'lower_charging_capacity', label: '充电下限容量', unit: 'mA/h' },
{ prop: 'upper_discharge_voltage', label: '放电上限电压', unit: 'mV' },
{ prop: 'lower_discharge_voltage', label: '放电下限电压', unit: 'mV' },
{ prop: 'upper_discharge_current', label: '放电上限电流', unit: 'mA' },
{ prop: 'lower_discharge_current', label: '放电下限电流', unit: 'mA' },
{ prop: 'upper_discharge_capacity', label: '放电上限容量', unit: 'mA/h' },
{ prop: 'lower_discharge_capacity', label: '放电下限容量', unit: 'mA/h' }
],
processColumns: [
{ prop: 'station', label: '工步状态', width: 120, type: 'select', options: 'stationList' },
{ prop: 'time', label: '时间(秒)', width: 120 },
{ prop: 'current', label: '电流(mA)', width: 120 },
{ prop: 'upperVoltage', label: '上限电压(mV)', width: 120 },
{ prop: 'lowerVoltage', label: '下限电压(mV)', width: 120 },
{ prop: 'stop_DeltaVoltage', label: 'ΔV(mV)', width: 100 },
{ prop: 'stop_Current', label: '终止电流(mA)', width: 120 },
{ prop: 'stop_Capacity', label: '终止容量(mA/h)', width: 130 },
{ prop: 'cct_begin', label: 'CCT下限(s)', width: 100 },
{ prop: 'cct_end', label: 'CCT上限(s)', width: 100 },
{ prop: 'time_over', label: 'TIMEOVER', width: 120, type: 'select', options: 'timeOverList' },
{ prop: 'temperature', label: '温度(℃)', width: 100 },
{ prop: 'upperTemperature', label: '温度上限(℃)', width: 120 },
{ prop: 'lowerTemperature', label: '温度下限(℃)', width: 120 },
{ prop: 'pressure', label: '压力kg', width: 100 }
]
}
},
watch: {
settingJson: {
handler (val) {
const parsed = parseSetting(val, {
action: 'start',
time: new Date(),
process: [],
setting: { contact_check: '0', curve_sampling_time: 10 }
})
parsed.process = Array.isArray(parsed.process) ? parsed.process : []
parsed.setting = parsed.setting || {}
this.json = parsed
this.globalSetting = { ...parsed.setting }
for (const key of this.globalFields.map(item => item.prop)) {
if (Object.prototype.hasOwnProperty.call(parsed, key) && !Object.prototype.hasOwnProperty.call(this.globalSetting, key)) {
this.$set(this.globalSetting, key, parsed[key])
}
}
this.tableData = parsed.process.map(row => ({
...row,
station: row.station !== undefined && row.station !== null ? String(row.station) : '',
time_over: row.time_over !== undefined && row.time_over !== null ? String(row.time_over) : ''
}))
},
immediate: true
},
globalSetting: {
handler () {
this.syncJson()
},
deep: true
},
tableData: {
handler () {
this.syncJson()
},
deep: true
}
},
methods: {
syncJson () {
const setting = {}
Object.keys(this.globalSetting || {}).forEach(key => {
const value = this.globalSetting[key]
if (value !== '' && value !== undefined && value !== null) {
setting[key] = this.toNumberIfNumeric(value)
}
})
const process = this.tableData.map(row => {
const item = {}
Object.keys(row).forEach(key => {
const value = row[key]
if (value !== '' && value !== undefined && value !== null) {
item[key] = key === 'time_over' ? value : this.toNumberIfNumeric(value)
}
})
return item
})
if (process[0] && setting.contact_check !== undefined) {
process[0].contact_check = setting.contact_check
}
this.json = {
...this.json,
process,
setting
}
},
toNumberIfNumeric (value) {
if (value === '' || value === null || value === undefined) return value
return /^-?\d+(\.\d+)?$/.test(String(value)) ? Number(value) : value
},
rowClassName ({ row }) {
const station = String(row.station)
if (station === '5') return 'formation-row-cycle'
if (station === '1') return 'formation-row-charge'
if (station === '2') return 'formation-row-charge-cv'
if (station === '3') return 'formation-row-rest'
if (station === '4') return 'formation-row-discharge'
return ''
},
addRow () {
if (this.tableData.some(row => String(row.station) === '6')) {
this.$message.info('已有结束工步,不能新增')
return
}
this.tableData.push({ station: '' })
},
removeRow (index) {
this.tableData.splice(index, 1)
},
moveUp (index) {
if (index <= 0) return
const row = this.tableData.splice(index, 1)[0]
this.tableData.splice(index - 1, 0, row)
},
moveDown (index) {
if (index >= this.tableData.length - 1) return
const row = this.tableData.splice(index, 1)[0]
this.tableData.splice(index + 1, 0, row)
},
stationChange (row) {
if (String(row.station) === '5') {
Object.keys(row).forEach(key => {
if (key !== 'station') this.$set(row, key, '')
})
}
if (String(row.station) === '6') {
const index = this.tableData.indexOf(row)
this.tableData = this.tableData.slice(0, index + 1)
}
},
showMsg (message) {
this.$message.warning(message)
},
validateProcess () {
if (!this.tableData.some(row => String(row.station) === '6')) {
this.$message.info('检测到没有添加结束工步')
return false
}
const process = this.json.process || []
for (let n = 0; n < process.length; n++) {
const row = process[n]
const station = Number(row.station)
const miss = name => {
this.showMsg(`${n + 1}工步的必填项 【${name}】 没有填写`)
return false
}
if ((this.workingsubclassCode === 'HC' || this.workingsubclassCode === 'FR') && station !== 6) {
if (row.pressure === undefined || row.pressure === '') return miss('压力')
if (row.temperature === undefined || row.temperature === '') return miss('温度')
}
if (station === 3) {
if (row.time === undefined || row.time === '') return miss('工作时间')
} else if (station === 12 || station === 2) {
if (row.time === undefined || row.time === '') return miss('工作时间')
if (row.current === undefined || row.current === '') return miss('电流')
if (row.stop_Current === undefined || row.stop_Current === '') return miss('终止电流')
if (station === 12 && (row.lowerVoltage === undefined || row.lowerVoltage === '')) return miss('下限电压')
if (station === 2 && (row.upperVoltage === undefined || row.upperVoltage === '')) return miss('上限电压')
} else if (station === 4 || station === 1) {
if (row.time === undefined || row.time === '') return miss('工作时间')
if (row.current === undefined || row.current === '') return miss('电流')
if (station === 4 && (row.lowerVoltage === undefined || row.lowerVoltage === '')) return miss('下限电压')
if (station === 1 && (row.upperVoltage === undefined || row.upperVoltage === '')) return miss('上限电压')
}
}
return true
},
handleFormSubmit () {
this.syncJson()
if (!this.validateProcess()) return
this.$emit('submit', this.json)
}
},
template: `
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="设定值" name="process">
<el-divider content-position="left">全局配置</el-divider>
<el-form :model="globalSetting" size="mini" label-width="130px" class="formation-global-form">
<el-row :gutter="12">
<el-col v-for="item in globalFields" :key="item.prop" :span="8">
<el-form-item :label="item.label">
<el-input v-model="globalSetting[item.prop]" placeholder="请输入内容" clearable>
<el-button slot="append">{{ item.unit }}</el-button>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">设置工步</el-divider>
<el-button type="primary" icon="el-icon-plus" size="mini" style="margin-bottom:10px" @click="addRow">新增一行</el-button>
<el-table
:data="tableData"
border
stripe
size="mini"
height="350"
:row-class-name="rowClassName"
style="width:100%"
>
<el-table-column width="56" fixed>
<template slot-scope="{ $index }">
<i v-if="$index > 0" class="el-icon-sort-up formation-sort" @click="moveUp($index)" />
<i v-if="$index < tableData.length - 1" class="el-icon-sort-down formation-sort" @click="moveDown($index)" />
</template>
</el-table-column>
<el-table-column label="工步" width="56" fixed>
<template slot-scope="{ $index }">{{ $index + 1 }}</template>
</el-table-column>
<el-table-column
v-for="column in processColumns"
:key="column.prop"
:label="column.label"
:width="column.width"
:fixed="column.prop === 'station'"
>
<template slot-scope="{ row }">
<el-select
v-if="column.type === 'select'"
v-model="row[column.prop]"
size="mini"
clearable
@change="column.prop === 'station' ? stationChange(row) : undefined"
>
<el-option
v-for="option in $data[column.options]"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<el-input v-else v-model="row[column.prop]" size="mini" type="number" clearable />
</template>
</el-table-column>
<el-table-column label="操作" width="80" fixed="right">
<template slot-scope="{ $index }">
<el-button type="text" size="mini" style="color:#F56C6C" @click="removeRow($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="json" name="json">
<tree-view :data="json" />
</el-tab-pane>
</el-tabs>
`
}
export default { export default {
name: 'ProcessStepSettingDialog', name: 'ProcessStepSettingDialog',
components: { WaitPlugin, JsonPlugin, FormationPlugin, DeviceSettingPlugin, NonStandardSettingPlugin }, components: {
WaitPlugin,
JsonPlugin,
FormationPlugin,
DeviceSettingPlugin,
NonStandardSettingPlugin
},
mixins: [i18nMixin('page.production_master_data.process_model.process_step')], mixins: [i18nMixin('page.production_master_data.process_model.process_step')],
props: { props: {
type: { type: String, default: '' }, type: { type: String, default: '' },
@@ -870,48 +71,3 @@ export default {
} }
} }
</script> </script>
<style scoped>
.formation-global-form /deep/ .el-form-item--mini.el-form-item {
margin-bottom: 8px;
}
.formation-sort {
cursor: pointer;
margin-right: 4px;
color: #409EFF;
}
.device-setting-form /deep/ .el-form-item--mini.el-form-item {
margin-bottom: 10px;
}
.non-standard-setting {
display: flex;
flex-direction: row;
justify-content: center;
}
.setting-search-card {
width: 20%;
margin-right: 20px;
}
.setting-table {
width: 80%;
}
.setting-actions {
margin-top: 10px;
text-align: right;
}
/deep/ .formation-row-cycle {
background-color: #ffc0ff !important;
}
/deep/ .formation-row-charge {
background-color: #ffff00 !important;
}
/deep/ .formation-row-charge-cv {
background-color: #ffffc0 !important;
}
/deep/ .formation-row-rest {
background-color: #e0e0e0 !important;
}
/deep/ .formation-row-discharge {
background-color: #c0c0c0 !important;
}
</style>

View File

@@ -0,0 +1,72 @@
<template>
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="mini">
<el-form-item label="静置时间" prop="time">
<el-input v-model="form.time" placeholder="请输入静置时间" clearable>
<template slot="append">分钟</template>
</el-input>
</el-form-item>
<el-form-item label="精度范围" prop="time_range">
<el-input v-model="form.time_range" placeholder="请输入精度范围" clearable>
<template slot="append">分钟</template>
</el-input>
</el-form-item>
</el-form>
</template>
<script>
function parseSetting (value) {
if (value === undefined || value === null || value === '') return { process: {} }
if (typeof value === 'object') return JSON.parse(JSON.stringify(value))
try {
return JSON.parse(value)
} catch (e) {
return { process: {} }
}
}
export default {
name: 'ProcessStepWaitSettingPlugin',
props: { settingJson: { default: '' } },
data () {
return {
json: { process: {} },
form: { time: undefined, time_range: undefined, alert: '0' },
rules: {
time: [{ pattern: /^[0-9]\d*$/, message: '请输入大于等于 0 的整数', trigger: 'change' }],
time_range: [{ pattern: /^[0-9]\d*$/, message: '请输入大于等于 0 的整数', trigger: 'change' }]
}
}
},
watch: {
settingJson: {
handler (val) {
const json = parseSetting(val)
this.json = json
this.form = {
time: json.process && json.process.time !== undefined ? json.process.time : undefined,
time_range: json.process && json.process.time_range !== undefined ? json.process.time_range : undefined,
alert: json.process && json.process.alert !== undefined ? json.process.alert : '0'
}
},
immediate: true
},
form: {
handler (val) {
this.json = { process: { ...val } }
},
deep: true
}
},
methods: {
handleFormSubmit () {
this.$refs.form.validate(valid => {
if (!valid) {
this.$message.error('校验失败')
return
}
this.$emit('submit', this.json)
})
}
}
}
</script>