为双机架完成轧辊,质量,模型等内容
This commit is contained in:
21
ruoyi-ui/src/api/mill/equipmentChecklist.js
Normal file
21
ruoyi-ui/src/api/mill/equipmentChecklist.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listEquipmentChecklist(query) {
|
||||
return request({ url: '/mill/eqp/checklist/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getEquipmentChecklist(checkId) {
|
||||
return request({ url: '/mill/eqp/checklist/' + checkId, method: 'get' })
|
||||
}
|
||||
|
||||
export function addEquipmentChecklist(data) {
|
||||
return request({ url: '/mill/eqp/checklist', method: 'post', data: data })
|
||||
}
|
||||
|
||||
export function updateEquipmentChecklist(data) {
|
||||
return request({ url: '/mill/eqp/checklist', method: 'put', data: data })
|
||||
}
|
||||
|
||||
export function delEquipmentChecklist(checkId) {
|
||||
return request({ url: '/mill/eqp/checklist/' + checkId, method: 'delete' })
|
||||
}
|
||||
21
ruoyi-ui/src/api/mill/equipmentInspectionRecord.js
Normal file
21
ruoyi-ui/src/api/mill/equipmentInspectionRecord.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listEquipmentInspectionRecord(query) {
|
||||
return request({ url: '/mill/eqp/record/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getEquipmentInspectionRecord(recordId) {
|
||||
return request({ url: '/mill/eqp/record/' + recordId, method: 'get' })
|
||||
}
|
||||
|
||||
export function addEquipmentInspectionRecord(data) {
|
||||
return request({ url: '/mill/eqp/record', method: 'post', data: data })
|
||||
}
|
||||
|
||||
export function updateEquipmentInspectionRecord(data) {
|
||||
return request({ url: '/mill/eqp/record', method: 'put', data: data })
|
||||
}
|
||||
|
||||
export function delEquipmentInspectionRecord(recordId) {
|
||||
return request({ url: '/mill/eqp/record/' + recordId, method: 'delete' })
|
||||
}
|
||||
21
ruoyi-ui/src/api/mill/equipmentPart.js
Normal file
21
ruoyi-ui/src/api/mill/equipmentPart.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listEquipmentPart(query) {
|
||||
return request({ url: '/mill/eqp/part/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getEquipmentPart(partId) {
|
||||
return request({ url: '/mill/eqp/part/' + partId, method: 'get' })
|
||||
}
|
||||
|
||||
export function addEquipmentPart(data) {
|
||||
return request({ url: '/mill/eqp/part', method: 'post', data: data })
|
||||
}
|
||||
|
||||
export function updateEquipmentPart(data) {
|
||||
return request({ url: '/mill/eqp/part', method: 'put', data: data })
|
||||
}
|
||||
|
||||
export function delEquipmentPart(partId) {
|
||||
return request({ url: '/mill/eqp/part/' + partId, method: 'delete' })
|
||||
}
|
||||
57
ruoyi-ui/src/api/mill/qc.js
Normal file
57
ruoyi-ui/src/api/mill/qc.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// ---- 检验任务 ----
|
||||
export function listQcTask(query) {
|
||||
return request({ url: '/mill/qc/task/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getQcTask(taskId) {
|
||||
return request({ url: `/mill/qc/task/${taskId}`, method: 'get' })
|
||||
}
|
||||
|
||||
export function addQcTask(data) {
|
||||
return request({ url: '/mill/qc/task', method: 'post', data })
|
||||
}
|
||||
|
||||
export function updateQcTask(data) {
|
||||
return request({ url: '/mill/qc/task', method: 'put', data })
|
||||
}
|
||||
|
||||
export function delQcTask(taskIds) {
|
||||
return request({ url: `/mill/qc/task/${taskIds}`, method: 'delete' })
|
||||
}
|
||||
|
||||
// 双机架钢卷列表(供下拉选择)
|
||||
export function listDoubleRackCoils() {
|
||||
return request({ url: '/mill/qc/task/coils', method: 'get' })
|
||||
}
|
||||
|
||||
// ---- 检验项目 ----
|
||||
export function listQcItemByTask(taskId) {
|
||||
return request({ url: `/mill/qc/item/byTask/${taskId}`, method: 'get' })
|
||||
}
|
||||
|
||||
export function updateQcItem(data) {
|
||||
return request({ url: '/mill/qc/item', method: 'put', data })
|
||||
}
|
||||
|
||||
// ---- 质量异常 ----
|
||||
export function listQcAbnormal(query) {
|
||||
return request({ url: '/mill/qc/abnormal/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getQcAbnormal(abnormalId) {
|
||||
return request({ url: `/mill/qc/abnormal/${abnormalId}`, method: 'get' })
|
||||
}
|
||||
|
||||
export function addQcAbnormal(data) {
|
||||
return request({ url: '/mill/qc/abnormal', method: 'post', data })
|
||||
}
|
||||
|
||||
export function updateQcAbnormal(data) {
|
||||
return request({ url: '/mill/qc/abnormal', method: 'put', data })
|
||||
}
|
||||
|
||||
export function delQcAbnormal(abnormalIds) {
|
||||
return request({ url: `/mill/qc/abnormal/${abnormalIds}`, method: 'delete' })
|
||||
}
|
||||
21
ruoyi-ui/src/api/mill/rollGrind.js
Normal file
21
ruoyi-ui/src/api/mill/rollGrind.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listRollGrind(rollId) {
|
||||
return request({ url: '/mill/roll/grind/list', method: 'get', params: { rollId } })
|
||||
}
|
||||
|
||||
export function getMonthlyStats(rollId, year) {
|
||||
return request({ url: '/mill/roll/grind/monthlyStats', method: 'get', params: { rollId, year } })
|
||||
}
|
||||
|
||||
export function addRollGrind(data) {
|
||||
return request({ url: '/mill/roll/grind', method: 'post', data })
|
||||
}
|
||||
|
||||
export function updateRollGrind(data) {
|
||||
return request({ url: '/mill/roll/grind', method: 'put', data })
|
||||
}
|
||||
|
||||
export function delRollGrind(grindId) {
|
||||
return request({ url: '/mill/roll/grind/' + grindId, method: 'delete' })
|
||||
}
|
||||
33
ruoyi-ui/src/api/mill/rollInfo.js
Normal file
33
ruoyi-ui/src/api/mill/rollInfo.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listRollInfo(query) {
|
||||
return request({ url: '/mill/roll/info/list', method: 'get', params: query })
|
||||
}
|
||||
|
||||
export function getRollStats() {
|
||||
return request({ url: '/mill/roll/info/stats', method: 'get' })
|
||||
}
|
||||
|
||||
export function listRollOptions(rollType, status) {
|
||||
return request({ url: '/mill/roll/info/options', method: 'get', params: { rollType, status } })
|
||||
}
|
||||
|
||||
export function getRollInfo(rollId) {
|
||||
return request({ url: '/mill/roll/info/' + rollId, method: 'get' })
|
||||
}
|
||||
|
||||
export function addRollInfo(data) {
|
||||
return request({ url: '/mill/roll/info', method: 'post', data })
|
||||
}
|
||||
|
||||
export function updateRollInfo(data) {
|
||||
return request({ url: '/mill/roll/info', method: 'put', data })
|
||||
}
|
||||
|
||||
export function delRollInfo(rollIds) {
|
||||
return request({ url: '/mill/roll/info/' + rollIds, method: 'delete' })
|
||||
}
|
||||
|
||||
export function scrapRollInfo(rollId) {
|
||||
return request({ url: '/mill/roll/info/' + rollId + '/scrap', method: 'put' })
|
||||
}
|
||||
160
ruoyi-ui/src/views/mill/eqp/day.vue
Normal file
160
ruoyi-ui/src/views/mill/eqp/day.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="app-container" v-loading="loading">
|
||||
<el-form size="small" :inline="true" style="margin-bottom: 10px;">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker v-model="queryDate" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="选择日期" @change="handleQuery" style="width: 160px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产线段">
|
||||
<el-input v-model="lineSection" placeholder="请输入产线段" clearable style="width: 130px;" @change="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-descriptions title="巡检日报" :column="6" border style="margin-bottom: 16px;">
|
||||
<el-descriptions-item label="巡检部位数">{{ summary.partCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="巡检项数">{{ summary.checklistCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总巡检次数">{{ summary.totalCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="通过">
|
||||
<el-tag type="success" size="small">{{ summary.passCount }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="故障">
|
||||
<el-tag type="danger" size="small">{{ summary.failCount }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通过率">{{ summary.passRate }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-table :data="tableData" border stripe style="width: 100%;" :cell-style="cellStyle">
|
||||
<el-table-column label="巡检部位" prop="inspectPart" align="center" width="130" />
|
||||
<el-table-column label="巡检内容" prop="checkContent" align="center" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="检验标准" prop="checkStandard" align="center" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="白班" align="center" width="160">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.dayRecords && scope.row.dayRecords.length" style="display: flex; flex-wrap: wrap; gap: 4px; justify-content: center;">
|
||||
<el-tooltip v-for="(r, idx) in scope.row.dayRecords" :key="idx" placement="top">
|
||||
<div slot="content">
|
||||
{{ r.inspectTime }} | 白班 | {{ r.inspector }}<br/>
|
||||
{{ r.runStatus === 1 ? '✓ 正常' : '✗ 故障' }}
|
||||
<span v-if="r.abnormalDesc"> — {{ r.abnormalDesc }}</span>
|
||||
</div>
|
||||
<span :class="r.runStatus === 1 ? 'result-pass' : 'result-fail'" class="result-icon">
|
||||
{{ r.runStatus === 1 ? '✓' : '✗' }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<span v-else class="result-none">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="夜班" align="center" width="160">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.nightRecords && scope.row.nightRecords.length" style="display: flex; flex-wrap: wrap; gap: 4px; justify-content: center;">
|
||||
<el-tooltip v-for="(r, idx) in scope.row.nightRecords" :key="idx" placement="top">
|
||||
<div slot="content">
|
||||
{{ r.inspectTime }} | 夜班 | {{ r.inspector }}<br/>
|
||||
{{ r.runStatus === 1 ? '✓ 正常' : '✗ 故障' }}
|
||||
<span v-if="r.abnormalDesc"> — {{ r.abnormalDesc }}</span>
|
||||
</div>
|
||||
<span :class="r.runStatus === 1 ? 'result-pass' : 'result-fail'" class="result-icon">
|
||||
{{ r.runStatus === 1 ? '✓' : '✗' }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<span v-else class="result-none">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listEquipmentPart } from '@/api/mill/equipmentPart'
|
||||
import { listEquipmentChecklist } from '@/api/mill/equipmentChecklist'
|
||||
import { listEquipmentInspectionRecord } from '@/api/mill/equipmentInspectionRecord'
|
||||
|
||||
export default {
|
||||
name: 'EqpDay',
|
||||
data() {
|
||||
const today = new Date()
|
||||
const pad = n => String(n).padStart(2, '0')
|
||||
return {
|
||||
loading: false,
|
||||
queryDate: `${today.getFullYear()}-${pad(today.getMonth() + 1)}-${pad(today.getDate())}`,
|
||||
lineSection: undefined,
|
||||
partList: [],
|
||||
checklistList: [],
|
||||
records: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tableData() {
|
||||
const recordMap = {}
|
||||
this.records.forEach(r => {
|
||||
const key = `${r.checkId}_${r.shift}`
|
||||
if (!recordMap[key]) recordMap[key] = []
|
||||
recordMap[key].push(r)
|
||||
})
|
||||
return this.checklistList.map(cl => {
|
||||
const part = this.partList.find(p => p.partId === cl.partId) || {}
|
||||
return {
|
||||
checkId: cl.checkId,
|
||||
inspectPart: part.inspectPart || cl.partName,
|
||||
checkContent: cl.checkContent,
|
||||
checkStandard: cl.checkStandard,
|
||||
dayRecords: recordMap[`${cl.checkId}_1`] || [],
|
||||
nightRecords: recordMap[`${cl.checkId}_2`] || []
|
||||
}
|
||||
})
|
||||
},
|
||||
summary() {
|
||||
const totalCount = this.records.length
|
||||
const passCount = this.records.filter(r => r.runStatus === 1).length
|
||||
const failCount = this.records.filter(r => r.runStatus === 2).length
|
||||
return {
|
||||
partCount: this.partList.length,
|
||||
checklistCount: this.checklistList.length,
|
||||
totalCount,
|
||||
passCount,
|
||||
failCount,
|
||||
passRate: totalCount > 0 ? (passCount / totalCount * 100).toFixed(1) + '%' : '0%'
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handleQuery()
|
||||
},
|
||||
methods: {
|
||||
cellStyle({ columnIndex }) {
|
||||
if (columnIndex === 3 || columnIndex === 4) return { fontSize: '20px', padding: '4px 8px' }
|
||||
},
|
||||
async handleQuery() {
|
||||
if (!this.queryDate) return
|
||||
this.loading = true
|
||||
try {
|
||||
const partParams = { pageNum: 1, pageSize: 9999 }
|
||||
if (this.lineSection) partParams.lineSection = this.lineSection
|
||||
const [partRes, checklistRes, recordRes] = await Promise.all([
|
||||
listEquipmentPart(partParams),
|
||||
listEquipmentChecklist(partParams),
|
||||
listEquipmentInspectionRecord({ startInspectTime: this.queryDate, endInspectTime: this.queryDate, pageNum: 1, pageSize: 9999 })
|
||||
])
|
||||
this.partList = partRes.rows || []
|
||||
this.checklistList = checklistRes.rows || []
|
||||
this.records = recordRes.rows || []
|
||||
} catch (e) {
|
||||
console.error('查询失败', e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.result-icon { display: inline-block; font-size: 20px; font-weight: bold; line-height: 1; cursor: default; }
|
||||
.result-pass { color: #67c23a; }
|
||||
.result-fail { color: #f56c6c; }
|
||||
.result-none { color: #c0c4cc; font-size: 16px; }
|
||||
</style>
|
||||
341
ruoyi-ui/src/views/mill/eqp/index.vue
Normal file
341
ruoyi-ui/src/views/mill/eqp/index.vue
Normal file
@@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="16" style="height: calc(100vh - 135px);">
|
||||
|
||||
<!-- 左侧:设备(巡检部位)列表 -->
|
||||
<el-col :span="7" style="height: 100%;">
|
||||
<el-card style="height: 100%; display: flex; flex-direction: column;" :body-style="{flex:1, overflow:'hidden', display:'flex', flexDirection:'column', padding:'10px'}">
|
||||
<div slot="header" style="display:flex; align-items:center; justify-content:space-between;">
|
||||
<span style="font-weight:bold;">设备列表</span>
|
||||
</div>
|
||||
|
||||
<el-form size="small" :inline="true" style="flex-shrink:0; margin-bottom:6px;">
|
||||
<el-form-item style="margin-bottom:0;">
|
||||
<el-input v-model="partKeyword" placeholder="搜索设备名称" prefix-icon="el-icon-search"
|
||||
clearable style="width:180px;" @input="filterParts" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div style="flex-shrink:0; margin-bottom:6px;">
|
||||
<el-button type="primary" plain size="mini" icon="el-icon-plus" @click="handlePartAdd">新增</el-button>
|
||||
<el-button type="success" plain size="mini" icon="el-icon-edit" :disabled="!currentPart" @click="handlePartUpdate(currentPart)">修改</el-button>
|
||||
<el-button type="danger" plain size="mini" icon="el-icon-delete" :disabled="!currentPart" @click="handlePartDelete(currentPart)">删除</el-button>
|
||||
</div>
|
||||
|
||||
<div v-loading="partLoading" style="flex:1; overflow-y:auto;">
|
||||
<div v-if="filteredPartList.length === 0" style="color:#909399; text-align:center; padding:20px; font-size:13px;">暂无数据</div>
|
||||
<div v-for="item in filteredPartList" :key="item.partId"
|
||||
class="part-card" :class="{ 'part-card-active': currentPart && currentPart.partId === item.partId }"
|
||||
@click="handleSelectPart(item)">
|
||||
<div style="flex:1; min-width:0;">
|
||||
<div class="part-name">{{ item.inspectPart }}</div>
|
||||
<div class="part-meta">
|
||||
<span v-if="item.lineSection">{{ item.lineSection }}</span>
|
||||
<span v-if="item.lineSection && item.remark"> · </span>
|
||||
<span v-if="item.remark">{{ item.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-tag v-if="item.checklistCount > 0" size="mini" type="info" style="flex-shrink:0; margin-left:4px;">{{ item.checklistCount }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:该设备的巡检清单 -->
|
||||
<el-col :span="17" style="height: 100%;">
|
||||
<el-card style="height: 100%; display: flex; flex-direction: column;" :body-style="{flex:1, overflow:'hidden', display:'flex', flexDirection:'column', padding:'10px'}">
|
||||
<div slot="header" style="display:flex; align-items:center; justify-content:space-between;">
|
||||
<span style="font-weight:bold;">
|
||||
巡检要求清单
|
||||
<span v-if="currentPart" style="font-weight:normal; color:#606266; font-size:13px; margin-left:8px;">
|
||||
— {{ currentPart.inspectPart }}
|
||||
</span>
|
||||
<span v-else style="font-weight:normal; color:#c0c4cc; font-size:13px; margin-left:8px;">请从左侧选择设备</span>
|
||||
</span>
|
||||
<el-button v-if="currentPart" size="mini" type="primary" plain icon="el-icon-tickets"
|
||||
@click="goToRecord(currentPart)">查看巡检记录</el-button>
|
||||
</div>
|
||||
|
||||
<div style="flex-shrink:0; margin-bottom:6px;">
|
||||
<el-button type="primary" plain size="mini" icon="el-icon-plus" :disabled="!currentPart" @click="handleChecklistAdd">新增</el-button>
|
||||
<el-button type="success" plain size="mini" icon="el-icon-edit" :disabled="checklistIds.length !== 1" @click="handleChecklistUpdate()">修改</el-button>
|
||||
<el-button type="danger" plain size="mini" icon="el-icon-delete" :disabled="checklistIds.length === 0" @click="handleChecklistDelete()">删除</el-button>
|
||||
</div>
|
||||
|
||||
<div v-loading="checklistLoading" style="flex:1; overflow:hidden;">
|
||||
<div v-if="!currentPart" style="display:flex; align-items:center; justify-content:center; height:100%; color:#c0c4cc;">
|
||||
<div style="text-align:center;">
|
||||
<i class="el-icon-d-arrow-left" style="font-size:40px;"></i>
|
||||
<div style="margin-top:10px; font-size:14px;">点击左侧设备查看巡检要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table v-else :data="checklistData" height="100%" @selection-change="handleChecklistSelectionChange">
|
||||
<el-table-column type="selection" width="45" align="center" />
|
||||
<el-table-column label="检验编号" prop="checkNo" width="100" />
|
||||
<el-table-column label="部件名称" prop="partName" width="120" />
|
||||
<el-table-column label="检验内容" prop="checkContent" show-overflow-tooltip min-width="180" />
|
||||
<el-table-column label="设备状态" prop="equipmentState" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.equipmentState === '运行' ? 'success' : 'warning'" size="mini">
|
||||
{{ scope.row.equipmentState || '—' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检验标准" prop="checkStandard" show-overflow-tooltip min-width="150" />
|
||||
<el-table-column label="责任人" prop="responsiblePerson" width="90" align="center" />
|
||||
<el-table-column label="操作" width="80" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleChecklistUpdate(scope.row)" />
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleChecklistDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 巡检部位对话框 -->
|
||||
<el-dialog :title="partTitle" :visible.sync="partOpen" width="450px" append-to-body>
|
||||
<el-form ref="partForm" :model="partForm" :rules="partRules" label-width="80px">
|
||||
<el-form-item label="产线段" prop="lineSection">
|
||||
<el-input v-model="partForm.lineSection" placeholder="请输入产线段" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称" prop="inspectPart">
|
||||
<el-input v-model="partForm.inspectPart" placeholder="请输入设备/巡检部位名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="partForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button :loading="partButtonLoading" type="primary" @click="submitPartForm">确 定</el-button>
|
||||
<el-button @click="partOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 检验清单对话框 -->
|
||||
<el-dialog :title="checklistTitle" :visible.sync="checklistOpen" width="520px" append-to-body>
|
||||
<el-form ref="checklistForm" :model="checklistForm" :rules="checklistRules" label-width="90px">
|
||||
<el-form-item label="检验编号">
|
||||
<el-input v-model="checklistForm.checkNo" placeholder="请输入检验编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="部件名称">
|
||||
<el-input v-model="checklistForm.partName" placeholder="请输入设备部件名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验内容">
|
||||
<el-input v-model="checklistForm.checkContent" type="textarea" :rows="3" placeholder="请输入检验内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备状态">
|
||||
<el-select v-model="checklistForm.equipmentState" placeholder="请选择" clearable style="width:100%;">
|
||||
<el-option label="运行" value="运行" />
|
||||
<el-option label="停止" value="停止" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="检验标准">
|
||||
<el-input v-model="checklistForm.checkStandard" type="textarea" :rows="3" placeholder="请输入检验标准" />
|
||||
</el-form-item>
|
||||
<el-form-item label="责任人">
|
||||
<el-input v-model="checklistForm.responsiblePerson" placeholder="请输入责任人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="checklistForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button :loading="checklistButtonLoading" type="primary" @click="submitChecklistForm">确 定</el-button>
|
||||
<el-button @click="checklistOpen = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listEquipmentPart, getEquipmentPart, addEquipmentPart, updateEquipmentPart, delEquipmentPart } from '@/api/mill/equipmentPart'
|
||||
import { listEquipmentChecklist, getEquipmentChecklist, addEquipmentChecklist, updateEquipmentChecklist, delEquipmentChecklist } from '@/api/mill/equipmentChecklist'
|
||||
|
||||
export default {
|
||||
name: 'EqpCheck',
|
||||
data() {
|
||||
return {
|
||||
// 设备列表
|
||||
partLoading: false,
|
||||
partButtonLoading: false,
|
||||
allPartList: [],
|
||||
filteredPartList: [],
|
||||
partKeyword: '',
|
||||
currentPart: null,
|
||||
partOpen: false,
|
||||
partTitle: '',
|
||||
partForm: {},
|
||||
partRules: {
|
||||
inspectPart: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }]
|
||||
},
|
||||
|
||||
// 检验清单
|
||||
checklistLoading: false,
|
||||
checklistButtonLoading: false,
|
||||
checklistData: [],
|
||||
checklistIds: [],
|
||||
checklistOpen: false,
|
||||
checklistTitle: '',
|
||||
checklistForm: {},
|
||||
checklistRules: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getPartList()
|
||||
// 如果路由带了 partId 参数,自动选中
|
||||
const partId = this.$route.query.partId
|
||||
if (partId) {
|
||||
this._autoSelectPartId = Number(partId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// ===== 设备列表 =====
|
||||
getPartList() {
|
||||
this.partLoading = true
|
||||
listEquipmentPart({ pageNum: 1, pageSize: 1000 }).then(res => {
|
||||
this.allPartList = res.rows || []
|
||||
// 为每个设备附上检验项数(后续可优化为批量接口)
|
||||
this.filteredPartList = [...this.allPartList]
|
||||
this.partLoading = false
|
||||
// 自动选中路由传来的 partId
|
||||
if (this._autoSelectPartId) {
|
||||
const found = this.allPartList.find(p => p.partId === this._autoSelectPartId)
|
||||
if (found) this.handleSelectPart(found)
|
||||
this._autoSelectPartId = null
|
||||
}
|
||||
})
|
||||
},
|
||||
filterParts() {
|
||||
const kw = (this.partKeyword || '').trim().toLowerCase()
|
||||
this.filteredPartList = kw
|
||||
? this.allPartList.filter(p => (p.inspectPart || '').toLowerCase().includes(kw) || (p.lineSection || '').toLowerCase().includes(kw))
|
||||
: [...this.allPartList]
|
||||
},
|
||||
handleSelectPart(part) {
|
||||
this.currentPart = part
|
||||
this.checklistData = []
|
||||
this.checklistIds = []
|
||||
this.loadChecklistForPart(part.partId)
|
||||
},
|
||||
loadChecklistForPart(partId) {
|
||||
this.checklistLoading = true
|
||||
listEquipmentChecklist({ partId, pageNum: 1, pageSize: 1000 }).then(res => {
|
||||
this.checklistData = res.rows || []
|
||||
this.checklistLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handlePartAdd() {
|
||||
this.partForm = {}
|
||||
this.$nextTick(() => { this.$refs.partForm && this.$refs.partForm.clearValidate() })
|
||||
this.partTitle = '新增设备'
|
||||
this.partOpen = true
|
||||
},
|
||||
handlePartUpdate(row) {
|
||||
if (!row) return
|
||||
this.partLoading = true
|
||||
getEquipmentPart(row.partId).then(res => {
|
||||
this.partLoading = false
|
||||
this.partForm = res.data
|
||||
this.partTitle = '修改设备'
|
||||
this.partOpen = true
|
||||
})
|
||||
},
|
||||
submitPartForm() {
|
||||
this.$refs.partForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.partButtonLoading = true
|
||||
const fn = this.partForm.partId ? updateEquipmentPart : addEquipmentPart
|
||||
fn(this.partForm).then(() => {
|
||||
this.$modal.msgSuccess(this.partForm.partId ? '修改成功' : '新增成功')
|
||||
this.partOpen = false
|
||||
this.getPartList()
|
||||
}).finally(() => { this.partButtonLoading = false })
|
||||
})
|
||||
},
|
||||
handlePartDelete(row) {
|
||||
if (!row) return
|
||||
this.$modal.confirm(`确认删除设备"${row.inspectPart}"?`).then(() => {
|
||||
this.partLoading = true
|
||||
return delEquipmentPart(row.partId)
|
||||
}).then(() => {
|
||||
if (this.currentPart && this.currentPart.partId === row.partId) {
|
||||
this.currentPart = null
|
||||
this.checklistData = []
|
||||
}
|
||||
this.getPartList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {}).finally(() => { this.partLoading = false })
|
||||
},
|
||||
|
||||
// ===== 检验清单 =====
|
||||
handleChecklistSelectionChange(selection) {
|
||||
this.checklistIds = selection.map(i => i.checkId)
|
||||
},
|
||||
handleChecklistAdd() {
|
||||
if (!this.currentPart) return
|
||||
this.checklistForm = { partId: this.currentPart.partId }
|
||||
this.$nextTick(() => { this.$refs.checklistForm && this.$refs.checklistForm.clearValidate() })
|
||||
this.checklistTitle = '新增巡检要求'
|
||||
this.checklistOpen = true
|
||||
},
|
||||
handleChecklistUpdate(row) {
|
||||
const checkId = row ? row.checkId : this.checklistIds[0]
|
||||
this.checklistLoading = true
|
||||
getEquipmentChecklist(checkId).then(res => {
|
||||
this.checklistLoading = false
|
||||
this.checklistForm = res.data
|
||||
this.checklistTitle = '修改巡检要求'
|
||||
this.checklistOpen = true
|
||||
})
|
||||
},
|
||||
submitChecklistForm() {
|
||||
this.$refs.checklistForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.checklistButtonLoading = true
|
||||
const fn = this.checklistForm.checkId ? updateEquipmentChecklist : addEquipmentChecklist
|
||||
fn(this.checklistForm).then(() => {
|
||||
this.$modal.msgSuccess(this.checklistForm.checkId ? '修改成功' : '新增成功')
|
||||
this.checklistOpen = false
|
||||
if (this.currentPart) this.loadChecklistForPart(this.currentPart.partId)
|
||||
}).finally(() => { this.checklistButtonLoading = false })
|
||||
})
|
||||
},
|
||||
handleChecklistDelete(row) {
|
||||
const ids = row ? [row.checkId] : this.checklistIds
|
||||
this.$modal.confirm('确认删除选中的巡检要求?').then(() => {
|
||||
this.checklistLoading = true
|
||||
return delEquipmentChecklist(ids.join(','))
|
||||
}).then(() => {
|
||||
if (this.currentPart) this.loadChecklistForPart(this.currentPart.partId)
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {}).finally(() => { this.checklistLoading = false })
|
||||
},
|
||||
|
||||
// ===== 路由跳转 =====
|
||||
goToRecord(part) {
|
||||
this.$router.push({ path: '/mill/eqp/record', query: { partId: part.partId, partName: part.inspectPart } })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.part-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
border-left: 3px solid transparent;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.part-card:hover { background: #f5f7fa; }
|
||||
.part-card-active { background: #ecf5ff; border-left-color: #409eff; }
|
||||
.part-name { font-size: 13px; font-weight: 500; color: #303133; line-height: 1.4; }
|
||||
.part-meta { font-size: 11px; color: #909399; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
</style>
|
||||
300
ruoyi-ui/src/views/mill/eqp/record.vue
Normal file
300
ruoyi-ui/src/views/mill/eqp/record.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="设备" prop="partId">
|
||||
<el-select v-model="queryParams.partId" placeholder="请选择设备" clearable filterable
|
||||
style="width: 180px;" @change="handleQuery">
|
||||
<el-option v-for="p in partOptions" :key="p.partId" :label="p.inspectPart" :value="p.partId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="班次" prop="shift">
|
||||
<el-select v-model="queryParams.shift" placeholder="班次" clearable style="width: 90px;" @change="handleQuery">
|
||||
<el-option label="白班" :value="1" />
|
||||
<el-option label="夜班" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检时间">
|
||||
<el-date-picker v-model="dateRange" type="daterange" value-format="yyyy-MM-dd"
|
||||
range-separator="-" start-placeholder="开始" end-placeholder="结束" clearable
|
||||
@change="handleDateRangeChange" style="width: 220px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="runStatus">
|
||||
<el-select v-model="queryParams.runStatus" placeholder="运行状态" clearable style="width: 90px;" @change="handleQuery">
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="故障" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检人" prop="inspector">
|
||||
<el-input v-model="queryParams.inspector" placeholder="巡检人" clearable style="width: 110px;" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<!-- 返回按钮:如果是从设备页跳过来的 -->
|
||||
<el-col :span="1.5" v-if="fromPartId">
|
||||
<el-button size="mini" icon="el-icon-back" @click="goBack">返回设备</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- 来自设备的筛选提示 -->
|
||||
<el-alert v-if="fromPartName" :title="`当前显示设备「${fromPartName}」的巡检记录`"
|
||||
type="info" show-icon :closable="false" style="margin-bottom:10px;" />
|
||||
|
||||
<el-table v-loading="loading" :data="recordList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="设备/部位" prop="partName" align="center" width="130" />
|
||||
<el-table-column label="检验内容" prop="checkContent" align="center" show-overflow-tooltip min-width="160" />
|
||||
<el-table-column label="班次" align="center" width="70">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.shift === 1 ? 'primary' : 'info'" size="mini">
|
||||
{{ scope.row.shift === 1 ? '白班' : '夜班' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="巡检时间" align="center" prop="inspectTime" width="155">
|
||||
<template slot-scope="scope">{{ parseTime(scope.row.inspectTime, '{y}-{m}-{d} {h}:{i}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运行状态" align="center" width="85">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.runStatus === 1 ? 'success' : 'danger'" size="mini">
|
||||
{{ scope.row.runStatus === 1 ? '正常' : '故障' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="巡检人" prop="inspector" align="center" width="90" />
|
||||
<el-table-column label="异常描述" prop="abnormalDesc" align="center" show-overflow-tooltip min-width="130" />
|
||||
<el-table-column label="现场图像" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-image v-if="scope.row.photo" :src="scope.row.photo" fit="cover"
|
||||
:preview-src-list="[scope.row.photo]" style="width:50px; height:50px;" />
|
||||
<span v-else style="color:#c0c4cc;">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="110" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="goToDevice(scope.row)">设备</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<!-- 新增/修改对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="520px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="设备" prop="partId">
|
||||
<el-select v-model="form.partId" placeholder="请选择设备" filterable clearable style="width:100%;"
|
||||
@change="onFormPartChange">
|
||||
<el-option v-for="p in partOptions" :key="p.partId" :label="p.inspectPart" :value="p.partId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="检验项" prop="checkId">
|
||||
<el-select v-model="form.checkId" placeholder="请选择检验项" filterable clearable style="width:100%;"
|
||||
:disabled="!form.partId">
|
||||
<el-option v-for="c in formChecklistOptions" :key="c.checkId"
|
||||
:label="(c.partName || '') + (c.checkContent ? ' — ' + c.checkContent : '')"
|
||||
:value="c.checkId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="班次" prop="shift">
|
||||
<el-select v-model="form.shift" style="width:100%;">
|
||||
<el-option label="白班" :value="1" />
|
||||
<el-option label="夜班" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检时间" prop="inspectTime">
|
||||
<el-date-picker v-model="form.inspectTime" type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择巡检时间" style="width:100%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="运行状态" prop="runStatus">
|
||||
<el-select v-model="form.runStatus" style="width:100%;">
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="故障" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="巡检人" prop="inspector">
|
||||
<el-input v-model="form.inspector" placeholder="请输入巡检人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="异常描述">
|
||||
<el-input v-model="form.abnormalDesc" type="textarea" :rows="2" placeholder="请输入异常描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listEquipmentInspectionRecord, getEquipmentInspectionRecord, addEquipmentInspectionRecord, updateEquipmentInspectionRecord, delEquipmentInspectionRecord } from '@/api/mill/equipmentInspectionRecord'
|
||||
import { listEquipmentPart } from '@/api/mill/equipmentPart'
|
||||
import { listEquipmentChecklist } from '@/api/mill/equipmentChecklist'
|
||||
|
||||
export default {
|
||||
name: 'EqpRecord',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
buttonLoading: false,
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
ids: [],
|
||||
single: true,
|
||||
multiple: true,
|
||||
recordList: [],
|
||||
partOptions: [],
|
||||
formChecklistOptions: [],
|
||||
title: '',
|
||||
open: false,
|
||||
dateRange: undefined,
|
||||
fromPartId: null,
|
||||
fromPartName: '',
|
||||
queryParams: {
|
||||
pageNum: 1, pageSize: 15,
|
||||
partId: undefined, shift: undefined, runStatus: undefined,
|
||||
inspector: undefined, startInspectTime: undefined, endInspectTime: undefined
|
||||
},
|
||||
form: {},
|
||||
rules: {
|
||||
checkId: [{ required: true, message: '请选择检验项', trigger: 'change' }],
|
||||
shift: [{ required: true, message: '请选择班次', trigger: 'change' }],
|
||||
inspectTime: [{ required: true, message: '请选择巡检时间', trigger: 'change' }],
|
||||
runStatus: [{ required: true, message: '请选择运行状态', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 从路由参数读取设备过滤条件
|
||||
const { partId, partName } = this.$route.query
|
||||
if (partId) {
|
||||
this.queryParams.partId = Number(partId)
|
||||
this.fromPartId = Number(partId)
|
||||
this.fromPartName = partName || ''
|
||||
}
|
||||
listEquipmentPart({ pageNum: 1, pageSize: 1000 }).then(res => {
|
||||
this.partOptions = res.rows || []
|
||||
})
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listEquipmentInspectionRecord(this.queryParams).then(res => {
|
||||
this.recordList = res.rows || []
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
handleDateRangeChange(val) {
|
||||
if (val && val.length === 2) {
|
||||
this.queryParams.startInspectTime = val[0]
|
||||
this.queryParams.endInspectTime = val[1]
|
||||
} else {
|
||||
this.queryParams.startInspectTime = undefined
|
||||
this.queryParams.endInspectTime = undefined
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
resetQuery() {
|
||||
this.dateRange = undefined
|
||||
this.queryParams = { pageNum: 1, pageSize: 15, partId: this.fromPartId || undefined, shift: undefined, runStatus: undefined, inspector: undefined, startInspectTime: undefined, endInspectTime: undefined }
|
||||
this.getList()
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(i => i.recordId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
handleAdd() {
|
||||
this.form = { partId: this.queryParams.partId }
|
||||
if (this.form.partId) this.loadFormChecklist(this.form.partId)
|
||||
this.$nextTick(() => { this.$refs.form && this.$refs.form.clearValidate() })
|
||||
this.title = '新增巡检记录'
|
||||
this.open = true
|
||||
},
|
||||
handleUpdate(row) {
|
||||
const recordId = row ? row.recordId : this.ids[0]
|
||||
getEquipmentInspectionRecord(recordId).then(res => {
|
||||
this.form = res.data
|
||||
if (this.form.partId) this.loadFormChecklist(this.form.partId)
|
||||
this.title = '修改巡检记录'
|
||||
this.open = true
|
||||
})
|
||||
},
|
||||
onFormPartChange(partId) {
|
||||
this.form.checkId = undefined
|
||||
this.formChecklistOptions = []
|
||||
if (partId) this.loadFormChecklist(partId)
|
||||
},
|
||||
loadFormChecklist(partId) {
|
||||
listEquipmentChecklist({ partId, pageNum: 1, pageSize: 1000 }).then(res => {
|
||||
this.formChecklistOptions = res.rows || []
|
||||
})
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (!valid) return
|
||||
this.buttonLoading = true
|
||||
const fn = this.form.recordId ? updateEquipmentInspectionRecord : addEquipmentInspectionRecord
|
||||
fn(this.form).then(() => {
|
||||
this.$modal.msgSuccess(this.form.recordId ? '修改成功' : '新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
}).finally(() => { this.buttonLoading = false })
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
const ids = row ? [row.recordId] : this.ids
|
||||
this.$modal.confirm('确认删除选中的巡检记录?').then(() => {
|
||||
this.loading = true
|
||||
return delEquipmentInspectionRecord(ids.join(','))
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {}).finally(() => { this.loading = false })
|
||||
},
|
||||
handleExport() {
|
||||
this.download('/mill/eqp/record/export', { ...this.queryParams }, `巡检记录_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
// 返回设备页并自动选中该设备
|
||||
goBack() {
|
||||
this.$router.push({ path: '/mill/eqp/check', query: { partId: this.fromPartId } })
|
||||
},
|
||||
// 从记录跳到设备查看
|
||||
goToDevice(row) {
|
||||
if (row.partId) {
|
||||
this.$router.push({ path: '/mill/eqp/check', query: { partId: row.partId } })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
2594
ruoyi-ui/src/views/mill/model-prediction.vue
Normal file
2594
ruoyi-ui/src/views/mill/model-prediction.vue
Normal file
File diff suppressed because it is too large
Load Diff
126
ruoyi-ui/src/views/mill/qc/abnormal/index.vue
Normal file
126
ruoyi-ui/src/views/mill/qc/abnormal/index.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="钢卷号" prop="coilId">
|
||||
<el-select v-model="queryParams.coilId" placeholder="选择钢卷" clearable filterable style="width:200px">
|
||||
<el-option v-for="c in coilOptions" :key="c.coilId" :label="c.coilNo" :value="c.coilId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷类型" prop="defectType">
|
||||
<el-input v-model="queryParams.defectType" placeholder="缺陷类型" clearable @keyup.enter.native="handleQuery" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="严重程度" prop="degree">
|
||||
<el-select v-model="queryParams.degree" placeholder="全部" clearable style="width:110px">
|
||||
<el-option label="轻微" value="light" />
|
||||
<el-option label="一般" value="normal" />
|
||||
<el-option label="严重" value="serious" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="判定等级" prop="judgeLevel">
|
||||
<el-input v-model="queryParams.judgeLevel" placeholder="判定等级" clearable style="width:110px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期" prop="beginTime">
|
||||
<el-date-picker v-model="queryParams.beginTime" type="date" value-format="yyyy-MM-dd" placeholder="开始" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="endTime">
|
||||
<el-date-picker v-model="queryParams.endTime" type="date" value-format="yyyy-MM-dd" placeholder="结束" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="abnormalList" border>
|
||||
<el-table-column label="钢卷号" prop="coilNo" align="center" width="160" />
|
||||
<el-table-column label="产线" prop="productionLine" align="center" width="100" />
|
||||
<el-table-column label="位置" prop="position" align="center" width="80" />
|
||||
<el-table-column label="板面" prop="plateSurface" align="center" width="80" />
|
||||
<el-table-column label="缺陷代码" prop="defectCode" align="center" width="100" />
|
||||
<el-table-column label="缺陷类型" prop="defectType" align="center" width="120" />
|
||||
<el-table-column label="缺陷率(%)" prop="defectRate" align="center" width="100" />
|
||||
<el-table-column label="缺陷重量(kg)" prop="defectWeight" align="center" width="110" />
|
||||
<el-table-column label="严重程度" prop="degree" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="degreeType(scope.row.degree)" size="small">{{ scope.row.degree || '-' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="判定等级" prop="judgeLevel" align="center" width="90" />
|
||||
<el-table-column label="判定人" prop="judgeBy" align="center" width="90" />
|
||||
<el-table-column label="判定时间" prop="judgeTime" align="center" width="160" />
|
||||
<el-table-column label="全卷标记" prop="wholeCoilMark" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.wholeCoilMark === 1" type="danger" size="small">全卷</el-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="remark" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listQcAbnormal, listDoubleRackCoils } from '@/api/mill/qc'
|
||||
|
||||
export default {
|
||||
name: 'QcAbnormal',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
abnormalList: [],
|
||||
coilOptions: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
coilId: undefined,
|
||||
defectType: undefined,
|
||||
degree: undefined,
|
||||
judgeLevel: undefined,
|
||||
beginTime: undefined,
|
||||
endTime: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.loadCoilOptions()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listQcAbnormal(this.queryParams).then(res => {
|
||||
this.abnormalList = res.rows
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
loadCoilOptions() {
|
||||
listDoubleRackCoils().then(res => {
|
||||
this.coilOptions = res.data || []
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
degreeType(degree) {
|
||||
const map = { 'light': 'success', 'normal': 'warning', 'serious': 'danger' }
|
||||
return map[degree] || 'info'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
211
ruoyi-ui/src/views/mill/qc/task/index.vue
Normal file
211
ruoyi-ui/src/views/mill/qc/task/index.vue
Normal file
@@ -0,0 +1,211 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="任务编号" prop="taskCode">
|
||||
<el-input v-model="queryParams.taskCode" placeholder="任务编号" clearable @keyup.enter.native="handleQuery" style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验人员" prop="inspectUser">
|
||||
<el-input v-model="queryParams.inspectUser" placeholder="检验人员" clearable @keyup.enter.native="handleQuery" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width:110px">
|
||||
<el-option label="待检验" :value="0" />
|
||||
<el-option label="检验中" :value="1" />
|
||||
<el-option label="待审核" :value="2" />
|
||||
<el-option label="已完成" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结果" prop="result">
|
||||
<el-select v-model="queryParams.result" placeholder="全部" clearable style="width:100px">
|
||||
<el-option label="合格" value="qualified" />
|
||||
<el-option label="不合格" value="unqualified" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="钢卷号" prop="coilId">
|
||||
<el-select v-model="queryParams.coilId" placeholder="选择钢卷" clearable filterable style="width:180px">
|
||||
<el-option v-for="c in coilOptions" :key="c.coilId" :label="c.coilNo" :value="c.coilId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期" prop="beginTime">
|
||||
<el-date-picker v-model="queryParams.beginTime" type="date" value-format="yyyy-MM-dd" placeholder="开始" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="endTime">
|
||||
<el-date-picker v-model="queryParams.endTime" type="date" value-format="yyyy-MM-dd" placeholder="结束" style="width:140px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- 任务列表 -->
|
||||
<el-table v-loading="loading" :data="taskList" highlight-current-row @row-click="handleRowClick"
|
||||
:row-class-name="tableRowClassName" border>
|
||||
<el-table-column label="任务编号" prop="taskCode" align="center" width="160" />
|
||||
<el-table-column label="方案名称" prop="schemeName" align="center" />
|
||||
<el-table-column label="检验人员" prop="inspectUser" align="center" width="100" />
|
||||
<el-table-column label="检验时间" prop="inspectTime" align="center" width="160" />
|
||||
<el-table-column label="审核人员" prop="auditUser" align="center" width="100" />
|
||||
<el-table-column label="状态" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结果" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.result" :type="scope.row.result === 'qualified' ? 'success' : 'danger'" size="small">
|
||||
{{ scope.row.result === 'qualified' ? '合格' : '不合格' }}
|
||||
</el-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime" align="center" width="160" />
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 检验项目详情 -->
|
||||
<div class="detail-card" v-if="selectedTask">
|
||||
<div class="detail-header">
|
||||
<span class="detail-title">检验项目 — {{ selectedTask.taskCode }}</span>
|
||||
<el-tag :type="statusType(selectedTask.status)" size="small">{{ statusLabel(selectedTask.status) }}</el-tag>
|
||||
</div>
|
||||
<el-table v-loading="itemLoading" :data="itemList" border size="small">
|
||||
<el-table-column label="检验项名称" prop="itemName" align="center" />
|
||||
<el-table-column label="类型" prop="itemType" align="center" width="80" />
|
||||
<el-table-column label="标准值" align="center" width="90">
|
||||
<template slot-scope="scope">{{ scope.row.standardValue }} {{ scope.row.unit }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上限" align="center" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.upperLimit }} {{ scope.row.unit }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下限" align="center" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.lowerLimit }} {{ scope.row.unit }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实测值" align="center" width="90">
|
||||
<template slot-scope="scope">{{ scope.row.inspectValue }} {{ scope.row.unit }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否合格" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.isQualified === 1" type="success" size="small">合格</el-tag>
|
||||
<el-tag v-else-if="scope.row.isQualified === 0" type="danger" size="small">不合格</el-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="判定结果" prop="judgeResult" align="center" />
|
||||
<el-table-column label="检验人" prop="inspectUser" align="center" width="90" />
|
||||
<el-table-column label="检验时间" prop="inspectTime" align="center" width="160" />
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-else class="empty-tip">
|
||||
<el-empty description="点击任务行查看检验项目" :image-size="60" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listQcTask, listQcItemByTask, listDoubleRackCoils } from '@/api/mill/qc'
|
||||
|
||||
export default {
|
||||
name: 'QcTask',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
itemLoading: false,
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
taskList: [],
|
||||
itemList: [],
|
||||
selectedTask: null,
|
||||
coilOptions: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
taskCode: undefined,
|
||||
inspectUser: undefined,
|
||||
status: undefined,
|
||||
result: undefined,
|
||||
coilId: undefined,
|
||||
beginTime: undefined,
|
||||
endTime: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.loadCoilOptions()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listQcTask(this.queryParams).then(res => {
|
||||
this.taskList = res.rows
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
loadCoilOptions() {
|
||||
listDoubleRackCoils().then(res => {
|
||||
this.coilOptions = res.data || []
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
handleRowClick(row) {
|
||||
this.selectedTask = row
|
||||
this.itemLoading = true
|
||||
listQcItemByTask(row.taskId).then(res => {
|
||||
this.itemList = res.data || []
|
||||
this.itemLoading = false
|
||||
}).catch(() => { this.itemLoading = false })
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.selectedTask && row.taskId === this.selectedTask.taskId ? 'selected-row' : ''
|
||||
},
|
||||
statusType(status) {
|
||||
const map = { 0: 'info', 1: 'warning', 2: '', 3: 'success' }
|
||||
return map[status] || 'info'
|
||||
},
|
||||
statusLabel(status) {
|
||||
const map = { 0: '待检验', 1: '检验中', 2: '待审核', 3: '已完成' }
|
||||
return map[status] || status
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.detail-card {
|
||||
margin-top: 16px;
|
||||
border: 1px solid #e6e8eb;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
}
|
||||
.detail-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.detail-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
.empty-tip {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
382
ruoyi-ui/src/views/mill/roll/grind/index.vue
Normal file
382
ruoyi-ui/src/views/mill/roll/grind/index.vue
Normal file
@@ -0,0 +1,382 @@
|
||||
<template>
|
||||
<div class="app-container grind-page">
|
||||
<div class="grind-layout">
|
||||
|
||||
<!-- 左侧:轧辊列表 -->
|
||||
<div class="grind-left">
|
||||
<el-card shadow="never" class="grind-card h-full">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title"><i class="el-icon-s-order" /> 轧辊列表</span>
|
||||
</div>
|
||||
<div class="roll-filter">
|
||||
<el-input v-model="filterNo" size="small" placeholder="编号搜索" prefix-icon="el-icon-search"
|
||||
clearable @input="filterRolls" style="margin-bottom:8px" />
|
||||
<el-radio-group v-model="filterType" size="small" @change="filterRolls" style="margin-bottom:8px">
|
||||
<el-radio-button label="">全部</el-radio-button>
|
||||
<el-radio-button label="WR">WR</el-radio-button>
|
||||
<el-radio-button label="BR">BR</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-loading="rollLoading" class="roll-list">
|
||||
<div v-for="r in filteredRolls" :key="r.rollId"
|
||||
:class="['roll-item', selectedRollId === r.rollId ? 'roll-item--active' : '']"
|
||||
@click="selectRoll(r)">
|
||||
<div class="ri-no">{{ r.rollNo }}</div>
|
||||
<div class="ri-meta">
|
||||
<el-tag size="mini" :type="r.rollType === 'WR' ? 'primary' : 'warning'">{{ r.rollType }}</el-tag>
|
||||
<span :class="['ri-status', 'st-' + r.status]">{{ statusLabel(r.status) }}</span>
|
||||
<span class="ri-dia">φ{{ r.currentDia != null ? r.currentDia : r.initialDia }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!rollLoading && filteredRolls.length === 0" class="roll-empty">暂无数据</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:磨削台账 -->
|
||||
<div class="grind-right">
|
||||
<div v-if="!selectedRoll" class="grind-empty">
|
||||
<i class="el-icon-arrow-left" /> 请从左侧选择一个轧辊
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<!-- 轧辊基本信息 -->
|
||||
<el-card shadow="never" class="grind-card" style="margin-bottom:12px">
|
||||
<div class="roll-header-grid">
|
||||
<div class="rh-item"><span class="rh-k">轧辊编号</span><span class="rh-v bold">{{ selectedRoll.rollNo }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">辊型</span><span class="rh-v">{{ selectedRoll.rollType === 'WR' ? '工作辊' : '支撑辊' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">材质</span><span class="rh-v">{{ selectedRoll.material || '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">初始辊径</span><span class="rh-v">{{ selectedRoll.initialDia != null ? selectedRoll.initialDia + ' mm' : '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">当前辊径</span><span class="rh-v bold accent">{{ effectiveCurrentDia != null ? effectiveCurrentDia + ' mm' : '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">最小辊径</span><span class="rh-v">{{ selectedRoll.minDia != null ? selectedRoll.minDia + ' mm' : '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">磨削次数</span><span class="rh-v">{{ grindList.length + ' 次' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">粗糙度</span><span class="rh-v">{{ selectedRoll.roughness != null ? selectedRoll.roughness + ' μm' : '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">凸度</span><span class="rh-v">{{ selectedRoll.crown != null ? selectedRoll.crown + ' mm' : '—' }}</span></div>
|
||||
<div class="rh-item">
|
||||
<span class="rh-k">状态</span>
|
||||
<span :class="['rh-v', 'st-' + selectedRoll.status]">{{ statusLabel(selectedRoll.status) }}</span>
|
||||
</div>
|
||||
<div class="rh-item"><span class="rh-k">制造日期</span><span class="rh-v">{{ selectedRoll.manufactureDate || '—' }}</span></div>
|
||||
<div class="rh-item"><span class="rh-k">备注</span><span class="rh-v">{{ selectedRoll.remark || '—' }}</span></div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 磨削台账 -->
|
||||
<el-card shadow="never" class="grind-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="card-title"><i class="el-icon-document" /> 磨削台账</span>
|
||||
<el-button type="primary" size="mini" icon="el-icon-plus"
|
||||
style="margin-left:auto" :disabled="!!editRow" @click="startAdd">新增磨削记录</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="grindLoading" :data="tableData" size="small" border
|
||||
style="width:100%" :row-class-name="rowClassName">
|
||||
<el-table-column label="序号" type="index" width="46" align="center" />
|
||||
<el-table-column label="磨削时间" align="center" width="200">
|
||||
<template slot-scope="{row}">
|
||||
<el-date-picker v-if="isEditing(row)" v-model="editRow.grindTime"
|
||||
type="datetime" size="mini" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width:182px" placeholder="请选择" />
|
||||
<span v-else>{{ row.grindTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="班组" align="center" width="80">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.team" size="mini" style="width:64px" />
|
||||
<span v-else>{{ row.team || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="磨前径(mm)" align="center" width="100">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model.number="editRow.diaBefore" type="number" size="mini" style="width:80px" />
|
||||
<span v-else>{{ row.diaBefore }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="磨后径(mm)" align="center" width="100">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model.number="editRow.diaAfter" type="number" size="mini" style="width:80px" />
|
||||
<span v-else>{{ row.diaAfter }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="磨削量(mm)" align="center" width="88">
|
||||
<template slot-scope="{row}">
|
||||
<span v-if="isEditing(row)" class="computed-val">{{ grindAmountOf(editRow) }}</span>
|
||||
<span v-else>{{ row.grindAmount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="辊型" align="center" width="100">
|
||||
<template slot-scope="{row}">
|
||||
<el-select v-if="isEditing(row)" v-model="editRow.rollShape" size="mini" style="width:84px">
|
||||
<el-option label="平" value="平" />
|
||||
<el-option label="凸" value="凸" />
|
||||
<el-option label="凹" value="凹" />
|
||||
</el-select>
|
||||
<span v-else>{{ row.rollShape || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="探伤结果" align="center" width="110">
|
||||
<template slot-scope="{row}">
|
||||
<el-select v-if="isEditing(row)" v-model="editRow.flawResult" size="mini" style="width:94px">
|
||||
<el-option label="合格" value="合格" />
|
||||
<el-option label="不合格" value="不合格" />
|
||||
</el-select>
|
||||
<el-tag v-else size="mini" :type="row.flawResult === '合格' ? 'success' : 'danger'">
|
||||
{{ row.flawResult || '—' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="硬度" align="center" width="80">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model.number="editRow.hardness" type="number" size="mini" style="width:64px" />
|
||||
<span v-else>{{ row.hardness || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作者" align="center" width="100">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.operator" size="mini" placeholder="选填" />
|
||||
<span v-else>{{ row.operator || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="left" width="120">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.remark" size="mini" placeholder="选填" />
|
||||
<span v-else class="remark-text">{{ row.remark || '' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="100" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<template v-if="isEditing(row)">
|
||||
<el-button size="mini" type="text" icon="el-icon-check"
|
||||
:loading="grindSaving" @click="saveRow">保存</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-close"
|
||||
style="color:#909399" @click="cancelEdit">取消</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit"
|
||||
:disabled="!!editRow" @click="startEdit(row)">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete"
|
||||
style="color:#c5221f" :disabled="!!editRow" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 月度汇总 -->
|
||||
<div class="monthly-wrap" v-if="grindList.length > 0">
|
||||
<div class="monthly-title">
|
||||
<span>{{ currentYear }} 年月度汇总</span>
|
||||
<el-button-group size="mini" style="margin-left:8px">
|
||||
<el-button icon="el-icon-arrow-left" @click="changeYear(-1)" />
|
||||
<el-button icon="el-icon-arrow-right" @click="changeYear(1)" />
|
||||
</el-button-group>
|
||||
</div>
|
||||
<el-table :data="monthlyList" size="mini" border style="width:100%;margin-top:8px">
|
||||
<el-table-column label="月份" prop="month" align="center" width="90" />
|
||||
<el-table-column label="磨削次数" prop="grindCount" align="center" width="90" />
|
||||
<el-table-column label="累计磨削量(mm)" prop="totalGrindAmount" align="center" min-width="120" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRollInfo, getRollInfo } from '@/api/mill/rollInfo'
|
||||
import { listRollGrind, addRollGrind, updateRollGrind, delRollGrind, getMonthlyStats } from '@/api/mill/rollGrind'
|
||||
|
||||
export default {
|
||||
name: 'MillGrindRoom',
|
||||
data() {
|
||||
return {
|
||||
rollLoading: false,
|
||||
allRolls: [],
|
||||
filteredRolls: [],
|
||||
filterNo: '',
|
||||
filterType: '',
|
||||
selectedRollId: null,
|
||||
selectedRoll: null,
|
||||
grindLoading: false,
|
||||
grindList: [],
|
||||
currentYear: new Date().getFullYear(),
|
||||
monthlyList: [],
|
||||
editRow: null,
|
||||
grindSaving: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
effectiveCurrentDia() {
|
||||
if (this.selectedRoll && this.selectedRoll.currentDia != null) {
|
||||
return parseFloat(this.selectedRoll.currentDia)
|
||||
}
|
||||
if (this.grindList.length > 0) {
|
||||
const latest = [...this.grindList].sort((a, b) => {
|
||||
return new Date(b.grindTime || 0) - new Date(a.grindTime || 0)
|
||||
})[0]
|
||||
if (latest && latest.diaAfter != null) return parseFloat(latest.diaAfter)
|
||||
}
|
||||
return null
|
||||
},
|
||||
tableData() {
|
||||
if (this.editRow && this.editRow.__isNew) {
|
||||
return [this.editRow, ...this.grindList]
|
||||
}
|
||||
return this.grindList
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadRolls()
|
||||
},
|
||||
methods: {
|
||||
loadRolls() {
|
||||
this.rollLoading = true
|
||||
listRollInfo({ pageNum: 1, pageSize: 500 }).then(res => {
|
||||
this.allRolls = res.rows || []
|
||||
this.filterRolls()
|
||||
}).finally(() => { this.rollLoading = false })
|
||||
},
|
||||
filterRolls() {
|
||||
this.filteredRolls = this.allRolls.filter(r => {
|
||||
const matchNo = !this.filterNo || r.rollNo.includes(this.filterNo)
|
||||
const matchType = !this.filterType || r.rollType === this.filterType
|
||||
return matchNo && matchType
|
||||
})
|
||||
},
|
||||
selectRoll(r) {
|
||||
if (this.editRow) this.cancelEdit()
|
||||
this.selectedRollId = r.rollId
|
||||
getRollInfo(r.rollId).then(res => {
|
||||
this.selectedRoll = res.data || r
|
||||
}).catch(() => { this.selectedRoll = r })
|
||||
this.loadGrindList(r.rollId)
|
||||
},
|
||||
loadGrindList(rollId) {
|
||||
this.grindLoading = true
|
||||
listRollGrind(rollId).then(res => {
|
||||
this.grindList = res.data || []
|
||||
this.loadMonthlyStats()
|
||||
}).finally(() => { this.grindLoading = false })
|
||||
},
|
||||
loadMonthlyStats() {
|
||||
if (!this.selectedRollId) return
|
||||
getMonthlyStats(this.selectedRollId, this.currentYear).then(res => {
|
||||
this.monthlyList = res.data || []
|
||||
})
|
||||
},
|
||||
changeYear(delta) {
|
||||
this.currentYear += delta
|
||||
this.loadMonthlyStats()
|
||||
},
|
||||
isEditing(row) {
|
||||
if (!this.editRow) return false
|
||||
if (row.__isNew && this.editRow.__isNew) return true
|
||||
return !!row.grindId && row.grindId === this.editRow.grindId
|
||||
},
|
||||
rowClassName({ row }) {
|
||||
return this.isEditing(row) ? 'editing-row' : ''
|
||||
},
|
||||
startAdd() {
|
||||
const now = new Date()
|
||||
const pad = n => String(n).padStart(2, '0')
|
||||
const grindTime = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ` +
|
||||
`${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||
this.editRow = {
|
||||
__isNew: true,
|
||||
rollId: this.selectedRollId,
|
||||
grindTime,
|
||||
diaBefore: this.effectiveCurrentDia != null ? this.effectiveCurrentDia : undefined,
|
||||
rollShape: '平',
|
||||
flawResult: '合格'
|
||||
}
|
||||
},
|
||||
startEdit(row) {
|
||||
this.editRow = { ...row }
|
||||
},
|
||||
cancelEdit() {
|
||||
this.editRow = null
|
||||
},
|
||||
saveRow() {
|
||||
const r = this.editRow
|
||||
if (!r.grindTime) { this.$modal.msgWarning('请填写磨削时间'); return }
|
||||
if (r.diaBefore == null) { this.$modal.msgWarning('请填写磨前直径'); return }
|
||||
if (r.diaAfter == null) { this.$modal.msgWarning('请填写磨后直径'); return }
|
||||
this.grindSaving = true
|
||||
const isNew = !!r.__isNew
|
||||
const payload = { ...r }
|
||||
delete payload.__isNew
|
||||
const api = isNew ? addRollGrind : updateRollGrind
|
||||
api(payload).then(() => {
|
||||
this.$modal.msgSuccess(isNew ? '新增成功' : '修改成功')
|
||||
this.editRow = null
|
||||
this.loadGrindList(this.selectedRollId)
|
||||
getRollInfo(this.selectedRollId).then(res => {
|
||||
this.selectedRoll = res.data
|
||||
const idx = this.allRolls.findIndex(x => x.rollId === this.selectedRollId)
|
||||
if (idx !== -1) this.$set(this.allRolls, idx, { ...this.allRolls[idx], ...res.data })
|
||||
})
|
||||
}).finally(() => { this.grindSaving = false })
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$modal.confirm('确认删除该磨削记录?').then(() => {
|
||||
return delRollGrind(row.grindId)
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('已删除')
|
||||
this.loadGrindList(this.selectedRollId)
|
||||
}).catch(() => {})
|
||||
},
|
||||
grindAmountOf(row) {
|
||||
const b = parseFloat(row.diaBefore)
|
||||
const a = parseFloat(row.diaAfter)
|
||||
if (!isNaN(b) && !isNaN(a)) return (b - a).toFixed(2)
|
||||
return '—'
|
||||
},
|
||||
statusLabel(s) {
|
||||
return { Online: '在线', Standby: '备用', Offline: '离线', Scrapped: '报废' }[s] || s
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.grind-page { background: #f4f5f7; height: 100%; }
|
||||
.grind-layout { display: flex; gap: 12px; height: 100%; }
|
||||
.grind-left { width: 220px; flex-shrink: 0; }
|
||||
.grind-right { flex: 1; min-width: 0; }
|
||||
.grind-card { border: 1px solid #dcdee0; border-radius: 4px; }
|
||||
.h-full { height: calc(100vh - 120px); display: flex; flex-direction: column; }
|
||||
.card-header { display: flex; align-items: center; gap: 8px; }
|
||||
.card-title { font-size: 13px; font-weight: 600; color: #3d4b5c; }
|
||||
.roll-filter { padding: 0 0 4px; }
|
||||
.roll-list { overflow-y: auto; flex: 1; min-height: 0; }
|
||||
.roll-item { padding: 8px 12px; cursor: pointer; border-bottom: 1px solid #f0f2f5; }
|
||||
.roll-item:hover { background: #f5f7fa; }
|
||||
.roll-item--active { background: #e8f4ff !important; border-left: 3px solid #409eff; }
|
||||
.ri-no { font-family: 'Consolas', monospace; font-size: 13px; font-weight: 600; color: #1f2329; }
|
||||
.ri-meta { display: flex; align-items: center; gap: 6px; margin-top: 3px; }
|
||||
.ri-dia { font-size: 11px; color: #9aa0a6; }
|
||||
.ri-status { font-size: 11px; }
|
||||
.roll-empty { text-align: center; color: #c0c4cc; padding: 20px 0; font-size: 12px; }
|
||||
.grind-empty { display: flex; align-items: center; justify-content: center;
|
||||
height: 300px; color: #c0c4cc; font-size: 14px; gap: 6px; }
|
||||
.roll-header-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 16px; }
|
||||
.rh-item { display: flex; flex-direction: column; gap: 2px; }
|
||||
.rh-k { font-size: 11px; color: #9aa0a6; }
|
||||
.rh-v { font-size: 13px; color: #3d4b5c; }
|
||||
.rh-v.bold { font-weight: 600; }
|
||||
.rh-v.accent { color: #0a7c42; }
|
||||
.st-Online { color: #0a7c42; }
|
||||
.st-Standby { color: #d4860a; }
|
||||
.st-Offline { color: #9aa0a6; }
|
||||
.st-Scrapped { color: #c5221f; }
|
||||
.monthly-wrap { margin-top: 16px; border-top: 1px solid #f0f2f5; padding-top: 12px; }
|
||||
.monthly-title { font-size: 12px; color: #5f6368; display: flex; align-items: center; }
|
||||
.computed-val { color: #409eff; font-weight: 600; font-size: 13px; }
|
||||
.remark-text { font-size: 12px; color: #5f6368; }
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.el-table .editing-row { background: #fffbf0 !important; }
|
||||
.el-table .editing-row:hover > td { background: #fffbf0 !important; }
|
||||
</style>
|
||||
372
ruoyi-ui/src/views/mill/roll/overview/index.vue
Normal file
372
ruoyi-ui/src/views/mill/roll/overview/index.vue
Normal file
@@ -0,0 +1,372 @@
|
||||
<template>
|
||||
<div class="app-container roll-overview">
|
||||
|
||||
<!-- 状态统计看板 -->
|
||||
<div class="stat-panel mb16">
|
||||
<div class="stat-item">
|
||||
<div class="stat-icon-wrap total-icon"><i class="el-icon-data-line" /></div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-num">{{ stats.total || 0 }}</div>
|
||||
<div class="stat-label">轧辊总数</div>
|
||||
</div>
|
||||
<div class="stat-divider" />
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-icon-wrap online-icon"><i class="el-icon-circle-check" /></div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-num online-num">{{ stats.Online || 0 }}</div>
|
||||
<div class="stat-label">在 线</div>
|
||||
</div>
|
||||
<div class="stat-divider" />
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-icon-wrap standby-icon"><i class="el-icon-time" /></div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-num standby-num">{{ stats.Standby || 0 }}</div>
|
||||
<div class="stat-label">备 用</div>
|
||||
</div>
|
||||
<div class="stat-divider" />
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-icon-wrap offline-icon"><i class="el-icon-remove-outline" /></div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-num offline-num">{{ stats.Offline || 0 }}</div>
|
||||
<div class="stat-label">离 线</div>
|
||||
</div>
|
||||
<div class="stat-divider" />
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-icon-wrap scrapped-icon"><i class="el-icon-warning-outline" /></div>
|
||||
<div class="stat-body">
|
||||
<div class="stat-num scrapped-num">{{ stats.Scrapped || 0 }}</div>
|
||||
<div class="stat-label">报 废</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="轧辊编号" prop="rollNo">
|
||||
<el-input v-model="queryParams.rollNo" placeholder="轧辊编号" clearable style="width:140px"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="辊型" prop="rollType">
|
||||
<el-select v-model="queryParams.rollType" placeholder="全部" clearable style="width:120px">
|
||||
<el-option label="工作辊 WR" value="WR" />
|
||||
<el-option label="支撑辊 BR" value="BR" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width:110px">
|
||||
<el-option label="在线" value="Online" />
|
||||
<el-option label="备用" value="Standby" />
|
||||
<el-option label="离线" value="Offline" />
|
||||
<el-option label="报废" value="Scrapped" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="rollList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="轧辊编号" align="center" prop="rollNo" min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span class="roll-no-text">{{ scope.row.rollNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="辊型" align="center" prop="rollType" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span :class="['roll-type-tag', scope.row.rollType === 'WR' ? 'wr-tag' : 'br-tag']">
|
||||
{{ scope.row.rollType === 'WR' ? '工作辊 WR' : '支撑辊 BR' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" width="90">
|
||||
<template slot-scope="scope">
|
||||
<span :class="['status-dot-wrap', 'status-' + scope.row.status]">
|
||||
<span class="status-dot" />{{ statusLabel(scope.row.status) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="初始直径(mm)" align="right" prop="initialDia" width="120" />
|
||||
<el-table-column label="当前直径(mm)" align="right" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span :class="{ 'warn-text': isDiaLow(scope.row) }">{{ scope.row.currentDia }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最小直径(mm)" align="right" prop="minDia" width="120" />
|
||||
<el-table-column label="粗糙度" align="right" prop="roughness" width="90" />
|
||||
<el-table-column label="凸度" align="right" prop="crown" width="90" />
|
||||
<el-table-column label="材质" align="center" prop="material" width="100" />
|
||||
<el-table-column label="磨削次数" align="center" prop="grindCount" width="90" />
|
||||
<el-table-column label="累计轧制量(t)" align="right" prop="totalRolledWeight" width="130" />
|
||||
<el-table-column label="制造日期" align="center" width="110">
|
||||
<template slot-scope="scope">{{ parseTime(scope.row.manufactureDate, '{y}-{m}-{d}') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="left" prop="remark" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" width="160" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button v-if="scope.row.status === 'Offline'" size="mini" type="text"
|
||||
class="scrap-btn" icon="el-icon-lock" @click="handleScrap(scope.row)">封闭</el-button>
|
||||
<el-button v-if="scope.row.status === 'Scrapped'" size="mini" type="text"
|
||||
class="del-btn" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<!-- 新增/修改对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="620px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="110px">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="轧辊编号" prop="rollNo">
|
||||
<el-input v-model="form.rollNo" placeholder="请输入轧辊编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="辊型" prop="rollType">
|
||||
<el-select v-model="form.rollType" placeholder="请选择辊型" style="width:100%">
|
||||
<el-option label="工作辊 WR" value="WR" />
|
||||
<el-option label="支撑辊 BR" value="BR" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="初始直径(mm)" prop="initialDia">
|
||||
<el-input-number v-model="form.initialDia" :precision="2" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="当前直径(mm)">
|
||||
<el-input-number v-model="form.currentDia" :precision="2" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最小直径(mm)">
|
||||
<el-input-number v-model="form.minDia" :precision="2" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="材质">
|
||||
<el-input v-model="form.material" placeholder="请输入材质" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="粗糙度">
|
||||
<el-input-number v-model="form.roughness" :precision="4" :min="0" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="凸度">
|
||||
<el-input-number v-model="form.crown" :precision="4" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="制造日期">
|
||||
<el-date-picker v-model="form.manufactureDate" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="制造日期" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="厂家">
|
||||
<el-input v-model="form.manufacturer" placeholder="厂家" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRollInfo, getRollStats, getRollInfo, addRollInfo, updateRollInfo, delRollInfo, scrapRollInfo } from '@/api/mill/rollInfo'
|
||||
|
||||
export default {
|
||||
name: 'MillRollOverview',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
showSearch: true,
|
||||
single: true,
|
||||
multiple: true,
|
||||
total: 0,
|
||||
rollList: [],
|
||||
stats: {},
|
||||
title: '',
|
||||
open: false,
|
||||
ids: [],
|
||||
queryParams: { pageNum: 1, pageSize: 20, rollNo: undefined, rollType: undefined, status: undefined },
|
||||
form: {},
|
||||
rules: {
|
||||
rollNo: [{ required: true, message: '轧辊编号不能为空', trigger: 'blur' }],
|
||||
rollType: [{ required: true, message: '请选择辊型', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getStats()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
listRollInfo(this.queryParams).then(res => {
|
||||
this.rollList = res.rows || []
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getStats() {
|
||||
getRollStats().then(res => { this.stats = res.data || {} })
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = { pageNum: 1, pageSize: 20 }
|
||||
this.getList()
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(i => i.rollId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
handleAdd() {
|
||||
this.form = { status: 'Offline', grindCount: 0 }
|
||||
this.$nextTick(() => { this.$refs.form && this.$refs.form.clearValidate() })
|
||||
this.title = '新增轧辊'
|
||||
this.open = true
|
||||
},
|
||||
handleUpdate(row) {
|
||||
const rollId = row ? row.rollId : this.ids[0]
|
||||
getRollInfo(rollId).then(res => {
|
||||
this.form = res.data
|
||||
this.title = '修改轧辊'
|
||||
this.open = true
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
const rollIds = row ? [row.rollId] : this.ids
|
||||
this.$modal.confirm('确认删除该报废轧辊记录?此操作不可恢复。').then(() => {
|
||||
return delRollInfo(rollIds.join(','))
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.getStats()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleScrap(row) {
|
||||
this.$modal.confirm('确认封闭轧辊【' + row.rollNo + '】?封闭后状态变为报废,不可恢复。').then(() => {
|
||||
return scrapRollInfo(row.rollId)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.getStats()
|
||||
this.$modal.msgSuccess('封闭成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (!valid) return
|
||||
const action = this.form.rollId ? updateRollInfo : addRollInfo
|
||||
action(this.form).then(() => {
|
||||
this.$modal.msgSuccess(this.form.rollId ? '修改成功' : '新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
this.getStats()
|
||||
})
|
||||
})
|
||||
},
|
||||
statusLabel(s) {
|
||||
return { Online: '在线', Standby: '备用', Offline: '离线', Scrapped: '报废' }[s] || s
|
||||
},
|
||||
isDiaLow(row) {
|
||||
if (!row.currentDia || !row.minDia) return false
|
||||
return Number(row.currentDia) - Number(row.minDia) < 5
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.roll-overview { background: #f4f5f7; }
|
||||
.mb16 { margin-bottom: 16px; }
|
||||
|
||||
.stat-panel {
|
||||
display: flex; background: #fff; border: 1px solid #dcdee0;
|
||||
border-radius: 4px; overflow: hidden;
|
||||
}
|
||||
.stat-item { flex: 1; display: flex; align-items: center; padding: 18px 20px; gap: 14px; position: relative; }
|
||||
.stat-divider { position: absolute; right: 0; top: 16px; bottom: 16px; width: 1px; background: #e4e6ea; }
|
||||
.stat-icon-wrap {
|
||||
width: 42px; height: 42px; border-radius: 4px;
|
||||
display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0;
|
||||
}
|
||||
.total-icon { background: #edf0f3; color: #3d4b5c; }
|
||||
.online-icon { background: #e8f5ef; color: #0a7c42; }
|
||||
.standby-icon { background: #fdf3e3; color: #8b5c00; }
|
||||
.offline-icon { background: #f0f1f2; color: #5f6368; }
|
||||
.scrapped-icon { background: #fdecea; color: #a61c00; }
|
||||
.stat-body { display: flex; flex-direction: column; }
|
||||
.stat-num { font-size: 26px; font-weight: 700; line-height: 1; color: #1f2329; }
|
||||
.online-num { color: #0a7c42; }
|
||||
.standby-num { color: #8b5c00; }
|
||||
.offline-num { color: #5f6368; }
|
||||
.scrapped-num { color: #a61c00; }
|
||||
.stat-label { font-size: 12px; color: #8f9099; margin-top: 4px; letter-spacing: 1px; }
|
||||
|
||||
.roll-no-text { font-family: 'Consolas','Courier New',monospace; font-weight: 600; color: #1f2329; }
|
||||
.roll-type-tag { display: inline-block; padding: 1px 8px; border-radius: 2px; font-size: 11px; font-weight: 600; }
|
||||
.wr-tag { background: #e8edf5; color: #2b4c8c; border: 1px solid #c5d0e8; }
|
||||
.br-tag { background: #f0eae0; color: #6b4c1e; border: 1px solid #dccfb8; }
|
||||
|
||||
.status-dot-wrap { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 500; }
|
||||
.status-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
|
||||
.status-Online { color: #0a7c42; }
|
||||
.status-Online .status-dot { background: #0a7c42; box-shadow: 0 0 0 2px #c8ead8; }
|
||||
.status-Standby { color: #8b5c00; }
|
||||
.status-Standby .status-dot { background: #d4860a; box-shadow: 0 0 0 2px #f5e2b8; }
|
||||
.status-Offline { color: #5f6368; }
|
||||
.status-Offline .status-dot { background: #9aa0a6; box-shadow: 0 0 0 2px #e0e2e4; }
|
||||
.status-Scrapped { color: #a61c00; }
|
||||
.status-Scrapped .status-dot { background: #c5221f; box-shadow: 0 0 0 2px #f5c6c4; }
|
||||
|
||||
.warn-text { color: #a61c00; font-weight: 600; }
|
||||
.scrap-btn { color: #8b5c00 !important; }
|
||||
.del-btn { color: #c5221f !important; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user