feat(设备管理): 新增设备任务执行相关功能及优化界面

- 添加设备任务执行视图和路由配置
- 重构设备树选择组件,使用el-tree替换Treeselect
- 优化设备任务执行步骤界面,替换图标组件和图片预览组件
- 调整设备维修和设备任务执行界面的表单布局和样式
- 修改设备维修模块的报修类型为本地配置
- 修复设备任务执行中的扫码认证组件引用问题
This commit is contained in:
2025-10-11 17:01:03 +08:00
parent 924e6b8a54
commit 401cf32a13
5 changed files with 109 additions and 70 deletions

View File

@@ -1,31 +1,35 @@
<template>
<div>
<Treeselect
style="width: 240px"
<el-tree
v-bind="$attrs"
style="width: 240px"
:data="deptOptions"
:props="defaultProps"
default-expand-all
highlight-current
filterable
:options="deptOptions"
:normalizer="normalizer"
:filter-node-method="filterNode"
ref="tree"
@node-click="handleNodeClick"
placeholder="请选择设备"
clearable />
/>
</div>
</template>
<script>
import * as deviceAccountApi from '@/api/deviceManagement/deviceaccount'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { handleTree } from '@/utils/ruoyi'
export default {
name: 'BaseDeviceAccountTreeSelect',
components: {
Treeselect
},
data() {
return {
deptOptions: []
deptOptions: [],
defaultProps: {
children: 'children',
label: 'label',
value: 'id'
},
filterText: ''
}
},
mounted() {
@@ -36,20 +40,34 @@ export default {
this.deptOptions = []
deviceAccountApi.getSelectTree().then((res) => {
if (res.code == 200) {
console.log(res.data)
this.deptOptions = handleTree(res.data, 'id', 'parentId', 'children')
}
})
},
normalizer(node) {
return {
id: node.id,
label: node.label,
children: node.children
}
handleNodeClick(data) {
// 触发input事件将选中的值传递给父组件
this.$emit('input', data.id)
// 触发change事件
this.$emit('change', data.id)
},
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
}
},
watch: {
// 监听filterText变化实现过滤功能
filterText(val) {
this.$refs.tree.filter(val)
}
}
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.el-tree {
width: 100%;
max-height: 300px;
overflow-y: auto;
}
</style>

View File

@@ -4,13 +4,13 @@
* @Date: (2024-05-28)
-->
<template>
<div>
<div class="app-container">
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="维修单号" prop="repairOrder">
<el-input v-model.trim="queryParams.repairOrder" placeholder="请输入维修单号" clearable />
</el-form-item>
<el-form-item label="设备" prop="fkDeviceId">
<BaseDeviceAccountTreeSelect v-model="queryParams.fkDeviceId"></BaseDeviceAccountTreeSelect>
<el-input v-model.trim="queryParams.fkDeviceId" placeholder="请输入设备ID" clearable />
</el-form-item>
<el-form-item label="报修人" prop="repairPeron">
<el-input v-model.trim="queryParams.repairPeron" placeholder="请输入报修人" clearable />
@@ -38,8 +38,8 @@
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="queryParams.status" @change="handleQuery">
<el-radio-button :value="-1">全部</el-radio-button>
<el-radio-button v-for="item in options.statusOptions" :key="item.dictValue" :value="parseInt(item.dictValue)">
<el-radio-button :label="-1">全部</el-radio-button>
<el-radio-button v-for="item in options.statusOptions" :key="item.dictValue" :label="parseInt(item.dictValue)">
{{ item.dictLabel }}
</el-radio-button>
</el-radio-group>
@@ -104,7 +104,7 @@
<pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改报修单对话框 -->
<el-dialog :title="title" :lock-scroll="false" v-model="open">
<el-dialog :title="title" :lock-scroll="false" :visible.sync="open">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="12" v-if="opertype != 1">
@@ -115,7 +115,7 @@
<el-col :lg="12">
<el-form-item label="设备" prop="fkDeviceId">
<BaseDeviceAccountTreeSelect v-model="form.fkDeviceId"></BaseDeviceAccountTreeSelect>
<el-input v-model.trim="form.fkDeviceId" placeholder="请输入设备ID" />
</el-form-item>
</el-col>
@@ -185,15 +185,19 @@
</template>
<script>
import dayjs from 'dayjs'
import { listDeviceRepair, addDeviceRepair, delDeviceRepair, updateDeviceRepair, getDeviceRepair } from '@/api/deviceManagement/devicerepair.js'
import BaseDeviceAccountTreeSelect from '../components/BaseDeviceAccountTreeSelect'
export default {
name: 'devicerepair',
components: {
BaseDeviceAccountTreeSelect
},
data() {
// 计算本周的开始日期(周一)和结束日期(周日)
const now = dayjs()
const startOfWeek = now.startOf('week')
const endOfWeek = now.endOf('week')
return {
ids: [],
loading: false,
@@ -202,7 +206,7 @@ export default {
pageNum: 1,
pageSize: 10,
status: 1,
timeRange: [],
timeRange: [startOfWeek.toDate(), endOfWeek.toDate()],
type: '',
sort: '',
sortType: 'asc'
@@ -249,8 +253,14 @@ export default {
id: [{ required: true, message: '雪花id不能为空', trigger: 'blur' }]
},
options: {
// 报修类型 选项列表 格式 eg:{ dictLabel: '标签', dictValue: '0'}
typeOptions: [],
// 报修类型 选项列表 自动生成的类别
typeOptions: [
{ dictLabel: '机械故障', dictValue: '1', remark: '设备机械部件出现故障,需要检修或更换' },
{ dictLabel: '电气故障', dictValue: '2', remark: '设备电气系统出现故障,需要检查线路或更换部件' },
{ dictLabel: '软件故障', dictValue: '3', remark: '设备控制系统软件出现异常,需要重启或重新配置' },
{ dictLabel: '保养维护', dictValue: '4', remark: '设备定期保养维护,确保设备正常运行' },
{ dictLabel: '其他故障', dictValue: '5', remark: '其他类型的故障,请在故障描述中详细说明' }
],
// 状态(启用,停用 维修中) 选项列表 格式 eg:{ dictLabel: '标签', dictValue: '0'}
statusOptions: [
{ dictLabel: '未接单', dictValue: 0, listClass: 'danger' },
@@ -298,8 +308,9 @@ export default {
return this.columns.some(column => column.prop === prop && column.visible)
},
init() {
//this.getDict()
this.handleQuery()
this.getDict()
},
getList() {
this.loading = true
@@ -336,14 +347,9 @@ export default {
this.handleQuery()
},
getDict() {
this.getDicts('mes_device_fault_type').then((res) => {
const { code, data } = res
if (code == 200) {
this.options.typeOptions = data
// 更新pourText
this.updatePourText()
}
})
// 报修类型已改为自动生成,不需要从字典查询
// 更新pourText
this.updatePourText()
},
updatePourText() {
if (this.form.type) {

View File

@@ -20,7 +20,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设备图片">
<ImagePreview style="width: 150px; height: 150px" :src="deviceItem.deviceImage"></ImagePreview>
<el-image style="width: 150px; height: 150px" :src="deviceItem.deviceImage"></el-image>
</el-form-item>
</el-col>
<el-col :span="12">
@@ -34,7 +34,7 @@
<el-tag v-else type="danger" effect="dark"> 未认证 </el-tag>
</el-form-item>
<el-form-item label=" ">
<el-text type="danger" style="font-weight: 700" size="large">需要扫码认证后才可修改点检结果</el-text>
<div style="color: red;" v-if="!IsIdentification">需要扫码认证后才可修改点检结果</div>
</el-form-item>
</el-col>
</el-row>
@@ -53,7 +53,7 @@
<el-row :gutter="20">
<el-col :span="12" :xs="12" v-if="inspectStepData && inspectStepData.image">
<el-form-item label="检查项图片">
<ImagePreview :src="inspectStepData.image"></ImagePreview>
<el-image :src="inspectStepData.image"></el-image>
</el-form-item>
</el-col>
<el-col :span="12" :xs="12" v-if="inspectStepData">
@@ -87,10 +87,10 @@
</el-row>
</el-form>
<div class="tool-box">
<el-button class="tool-item" size="large" icon="Close" @click="close" circle></el-button>
<el-button class="tool-item" size="large" type="success" icon="Check" @click="over" circle></el-button>
<el-button class="tool-item" size="large" type="info" icon="DArrowLeft" @click="doDeviceStepsBack" circle></el-button>
<el-button class="tool-item" size="large" type="primary" icon="DArrowRight" @click="doDeviceStepsNext" circle></el-button>
<el-button class="tool-item" size="large" icon="el-icon-close" @click="close" circle></el-button>
<el-button class="tool-item" size="large" type="success" icon="el-icon-check" @click="over" circle></el-button>
<el-button class="tool-item" size="large" type="info" icon="el-icon-arrow-left" @click="doDeviceStepsBack" circle></el-button>
<el-button class="tool-item" size="large" type="primary" icon="el-icon-arrow-right" @click="doDeviceStepsNext" circle></el-button>
</div>
</el-col>
</el-row>
@@ -102,8 +102,8 @@
</template>
</el-card>
<!-- 添加或修改任务执行对话框 -->
<el-dialog title="扫码认证" :lock-scroll="false" v-model="IdentificationShow" :destroy-on-close="true">
<qr-stream @decode="getDeviceCode"></qr-stream>
<el-dialog title="扫码认证" :lock-scroll="false" :visible.sync="IdentificationShow" :destroy-on-close="true">
<qrcode-stream @decode="getDeviceCode"></qrcode-stream>
</el-dialog>
</div>
</template>
@@ -117,12 +117,12 @@ import {
updateTaskStatus,
setTaskEndTime
} from '@/api/deviceManagement/devicetaskexecute.js'
import { QrStream } from 'vue-qrcode-reader'
import { QrcodeStream } from 'vue-qrcode-reader'
export default {
name: 'TheTaskExecuteDeviceItemStep',
components: {
QrStream
QrcodeStream
},
props: {
// 设备信息

View File

@@ -4,7 +4,7 @@
* @Date: (2024-05-31)
-->
<template>
<div>
<div class="app-container">
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="任务名称" prop="taskName">
<el-input clearable v-model.trim="queryParams.taskName" placeholder="请输入任务名称" />
@@ -22,9 +22,9 @@
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="queryParams.status" @change="handleQuery">
<el-radio-button :value="-1"> 全部 </el-radio-button>
<el-radio-button :label="-1"> 全部 </el-radio-button>
<el-radio-button v-for="item in options.statusOptions" :key="item.dictValue"
:value="parseInt(item.dictValue)">
:label="item.dictValue">
{{ item.dictLabel }}
</el-radio-button>
</el-radio-group>
@@ -37,20 +37,19 @@
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" v-hasPermi="['deviceManagement:devicetaskexecute:add']" plain icon="RefreshRight"
<el-button type="primary" plain icon="RefreshRight"
@click="handleSynchronize">
同步
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" v-hasPermi="['deviceManagement:devicetaskexecute:delete']" plain icon="delete"
<el-button type="danger" plain icon="delete"
@click="handleClear">
清理
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="download" @click="handleExport"
v-hasPermi="['deviceManagement:devicetaskexecute:export']">
<el-button type="warning" plain icon="download" @click="handleExport">
导出
</el-button>
</el-col>
@@ -103,13 +102,11 @@
<el-button type="info" size="small" icon="EditPen" @click="handleExecute(scope.row)">执行</el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="160" fixed="right">
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<el-button type="primary" size="small" icon="view" title="详情" @click="handlePreview(scope.row)"></el-button>
<el-button type="success" size="small" icon="edit" title="编辑"
v-hasPermi="['deviceManagement:devicetaskexecute:edit']" @click="handleUpdate(scope.row)"></el-button>
<el-button type="danger" size="small" icon="delete" title="删除"
v-hasPermi="['deviceManagement:devicetaskexecute:delete']" @click="handleDelete(scope.row)"></el-button>
<el-button type="primary" size="small" icon="el-icon-view" title="详情" @click="handlePreview(scope.row)"></el-button>
<el-button type="success" size="small" icon="el-icon-edit" title="编辑" @click="handleUpdate(scope.row)"></el-button>
<el-button type="danger" size="small" icon="el-icon-delete" title="删除" @click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
@@ -117,7 +114,7 @@
@pagination="getList" />
<!-- 添加或修改任务执行对话框 -->
<el-dialog :title="title" :lock-scroll="false" v-model="open">
<el-dialog :title="title" :lock-scroll="false" append-to-body :visible.sync="open">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="24">