Files
tiandihe/frontend/src/views/TrackCoil.vue
Joshi 538401017a feat(钢卷跟踪): 从哪开始获取计划?一次性获取多少个计划?不同批次的顺序号相同怎么处理?
已实现的功能:
Systemcount+信号变化才算有效
状态机逻辑:信号1必须配合计数器变化才触发,然后等待信号2
信号2必须配合计数器变化+保持2秒才触发
第一批1-5,第二批2-6,第三批3-7
每次取5个钢卷,顺序号滑动+1
信号2触发时更新Oracle追踪表
OPC页面配置点位
信号1(入口钢卷)节点配置
信号2(焊接完成)节点配置
计数器节点配置
保存后自动重启OPC服务
前端操作中间表 
TrackCoil页面可增删改查临时表
可手动调整顺序
模拟信号1/信号2按钮可测试

- 后端新增钢卷跟踪相关API和数据库表
- 前端添加钢卷跟踪管理页面
- OPC服务增加信号节点监控和状态机处理
- 实现钢卷跟踪的自动更新逻辑
2026-04-11 14:52:47 +08:00

232 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div class="panel" style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
<el-button size="small" @click="loadCoils">刷新</el-button>
<el-button size="small" type="primary" icon="el-icon-plus" @click="openAdd">新增钢卷</el-button>
<el-button size="small" type="danger" icon="el-icon-delete" @click="clearAll">清空全部</el-button>
<span style="flex:1"></span>
<el-button size="small" type="warning" @click="triggerSignal1">模拟信号1(入口)</el-button>
<el-button size="small" type="success" @click="triggerSignal2">模拟信号2(焊接完成)</el-button>
<span style="font-size:12px;color:#666">提示: Position 1对应产线入口(顺序号1), Position 5对应产线出口(顺序号5)</span>
</div>
<div class="panel" style="padding:0;margin-top:10px">
<el-table :data="coils" stripe border size="small" v-loading="loading" element-loading-text="加载中...">
<el-table-column prop="position" label="Position" width="90" />
<el-table-column prop="coilid" label="钢卷号" width="148" />
<el-table-column prop="sequencenb" label="顺序号" width="90" />
<el-table-column prop="rollprogramnb" label="批次号" width="108" />
<el-table-column prop="created_dt" label="创建时间" width="160" />
<el-table-column label="操作" width="180" fixed="right">
<template slot-scope="{row}">
<el-button type="text" size="mini" @click.stop="openEdit(row)">编辑</el-button>
<el-button type="text" size="mini" style="color:#e67e22" @click.stop="moveUp(row)" :disabled="row.position === 1">上移</el-button>
<el-button type="text" size="mini" style="color:#e67e22" @click.stop="moveDown(row)" :disabled="row.position === 5">下移</el-button>
<el-button type="text" size="mini" style="color:#c0392b" @click.stop="doDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="400px" :close-on-click-modal="false">
<el-form :model="form" :rules="rules" ref="trackForm" label-width="80px" size="small">
<el-form-item label="钢卷号" prop="coilid">
<el-input v-model="form.coilid" placeholder="12位钢卷号" />
</el-form-item>
<el-form-item label="顺序号" prop="sequencenb">
<el-input-number v-model="form.sequencenb" :controls="false" style="width:100%" />
</el-form-item>
<el-form-item label="批次号" prop="rollprogramnb">
<el-input-number v-model="form.rollprogramnb" :controls="false" style="width:100%" />
</el-form-item>
<el-form-item label="位置" prop="position">
<el-input-number v-model="form.position" :min="1" :max="5" :controls="false" style="width:100%" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button size="small" @click="dialogVisible = false">取消</el-button>
<el-button type="primary" size="small" @click="doSave" :loading="saving">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { trackApi } from '../api/index'
export default {
name: 'TrackCoil',
data() {
return {
loading: false,
saving: false,
coils: [],
dialogVisible: false,
isEdit: false,
form: {
id: null,
coilid: '',
sequencenb: 0,
rollprogramnb: 0,
position: 1
},
rules: {
coilid: [
{ required: true, message: '钢卷号不能为空', trigger: 'blur' }
]
}
}
},
computed: {
dialogTitle() {
return this.isEdit ? '编辑钢卷' : '新增钢卷'
}
},
created() {
this.loadCoils()
},
methods: {
async loadCoils() {
this.loading = true
try {
const res = await trackApi.getCoils()
this.coils = res.data || []
} catch (e) {
this.$message.error(e.message)
} finally {
this.loading = false
}
},
async fetchRangeCoils() {
try {
const res = await trackApi.getCoilsByRange(1, 5)
const coils = res.data || []
for (const coil of coils) {
await trackApi.addCoil({
coilid: coil.coilid,
sequencenb: coil.sequencenb,
rollprogramnb: coil.rollprogramnb
})
}
this.$message.success(`已添加 ${coils.length} 个钢卷`)
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
}
},
openAdd() {
this.isEdit = false
this.form = {
id: null,
coilid: '',
sequencenb: 0,
rollprogramnb: 0,
position: (this.coils.length || 0) + 1
}
this.dialogVisible = true
this.$nextTick(() => this.$refs.trackForm && this.$refs.trackForm.clearValidate())
},
openEdit(row) {
this.isEdit = true
this.form = { ...row }
this.dialogVisible = true
this.$nextTick(() => this.$refs.trackForm && this.$refs.trackForm.clearValidate())
},
doSave() {
this.$refs.trackForm.validate(async valid => {
if (!valid) return
this.saving = true
try {
if (this.isEdit) {
await trackApi.updateCoil(this.form.id, {
coilid: this.form.coilid,
sequencenb: this.form.sequencenb,
rollprogramnb: this.form.rollprogramnb,
position: this.form.position
})
this.$message.success('更新成功')
} else {
await trackApi.addCoil({
coilid: this.form.coilid,
sequencenb: this.form.sequencenb,
rollprogramnb: this.form.rollprogramnb
})
this.$message.success('添加成功')
}
this.dialogVisible = false
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
} finally {
this.saving = false
}
})
},
async doDelete(row) {
this.$confirm(`确认删除钢卷 [${row.coilid}]`, '删除确认', {
confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning'
}).then(async () => {
try {
await trackApi.deleteCoil(row.id)
this.$message.success('删除成功')
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
}
}).catch(() => {})
},
async clearAll() {
this.$confirm('确认清空所有钢卷?', '清空确认', {
confirmButtonText: '确认清空', cancelButtonText: '取消', type: 'warning'
}).then(async () => {
try {
await trackApi.clearCoils()
this.$message.success('清空成功')
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
}
}).catch(() => {})
},
async moveUp(row) {
if (row.position <= 1) return
const currentPos = row.position
const other = this.coils.find(c => c.position === currentPos - 1)
if (other) {
await trackApi.updateCoil(row.id, { ...row, position: currentPos - 1 })
await trackApi.updateCoil(other.id, { ...other, position: currentPos })
this.loadCoils()
}
},
async moveDown(row) {
if (row.position >= 5) return
const currentPos = row.position
const other = this.coils.find(c => c.position === currentPos + 1)
if (other) {
await trackApi.updateCoil(row.id, { ...row, position: currentPos + 1 })
await trackApi.updateCoil(other.id, { ...other, position: currentPos })
this.loadCoils()
}
},
async triggerSignal1() {
try {
await trackApi.simulateSignal1()
this.$message.success('信号1已触发 - 已获取下一批钢卷到临时表')
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
}
},
async triggerSignal2() {
try {
await trackApi.simulateSignal2()
this.$message.success('信号2已触发 - 已更新追踪表')
this.loadCoils()
} catch (e) {
this.$message.error(e.message)
}
}
}
}
</script>