fastbee/yack-web/src/views/iot/device/device-modbus-task.vue

1283 lines
56 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<div class="instruction-parsing">
<el-row :gutter="12" class="modbus-task-row">
<!-- 左侧子设备面板(网关模式,仅展示) -->
<el-col v-if="isGatewayMode" :span="5">
<div class="sub-device-side-panel" v-loading="subListLoading">
<div class="side-panel-title">
<i class="el-icon-connection"></i>
<span>{{$t('device.sub-device-create.deviceListTitle')}}</span>
<el-tag size="mini" type="info" style="margin-left: 6px">{{ subDeviceList.length }}</el-tag>
</div>
<div class="side-panel-list">
<div
v-for="item in subDeviceList"
:key="item.subDeviceId"
class="side-panel-item"
>
<div class="side-panel-item__name">
<i class="el-icon-cpu"></i>
{{ item.subDeviceName || item.subDeviceNo }}
</div>
<div class="side-panel-item__meta" style="color: blue;">
<span>{{$t('device.sub-device-create.slaveIdLabel')}}: {{ item.slaveId || '-' }}</span>
<el-badge
:type="item.status === 3 ? 'success' : 'info'"
is-dot
style="margin-left: 6px"
/>
</div>
<div class="side-panel-item__sn" style="color: red;">{{ item.subDeviceNo }}</div>
</div>
<el-empty
v-if="!subListLoading && subDeviceList.length === 0"
description="暂无子设备"
:image-size="60"
/>
</div>
</div>
</el-col>
<!-- 右侧任务内容 -->
<el-col :span="isGatewayMode ? 19 : 24">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="70px">
<el-form-item :label="$t('device.device-modbus-task.384302-0')" prop="jobName">
<el-input v-model="queryParams.jobName" :placeholder="$t('device.device-modbus-task.384302-1')" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item :label="$t('device.device-modbus-task.384302-2')" prop="status">
<el-select v-model="queryParams.status" :placeholder="$t('device.device-modbus-task.384302-3')" clearable size="small">
<el-option v-for="dict in dict.type.sys_job_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ $t('device.device-modbus-task.384302-4') }}</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ $t('device.device-modbus-task.384302-5') }}</el-button>
</el-form-item>
<el-form-item style="float: right">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openEdit">{{ $t('device.device-modbus.433390-1') }}</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="jobList" :border="false">
<el-table-column :label="$t('device.device-modbus-task.384302-56')" align="center" prop="taskId" />
<el-table-column :label="$t('device.device-timer.433369-7')" align="center" prop="jobName" />
<el-table-column label="触发类型" align="center" prop="cycleType" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.cycleType === 1" type="primary" size="small">周期循环</el-tag>
<el-tag v-else-if="scope.row.cycleType === 2" type="warning" size="small">自定义时间段</el-tag>
<el-tag v-else-if="scope.row.cycleType === 3" type="success" size="small">设备上电触发</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="$t('device.device-modbus-task.384302-57')" align="center" prop="command" />
<el-table-column :label="$t('device.device-modbus-task.384302-58')" align="center" prop="status">
<template slot-scope="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="执行时间" align="center" prop="executeTime" width="180">
<template slot-scope="scope">
<span v-if="scope.row.executeTime && showExecuteTime(scope.row)">
{{ parseTime(scope.row.executeTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="$t('device.device-modbus-task.384302-59')" align="center" prop="remarkStr"></el-table-column>
<el-table-column :label="$t('device.device-modbus-task.384302-60')" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleEdit(scope.row)" v-hasPermi="['modbus:job:edit']">编辑</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['modbus:job:remove']">{{ $t('device.device-modbus-task.384302-61') }}</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-col>
</el-row>
<el-dialog :title="editName ? $t('device.device-modbus-task.384302-12') : $t('device.device-modbus-task.384302-13')" :visible.sync="editDialog" :width="editName ? '30%' : '40%'" v-dialogDrag>
<div class="dialog-content beautify-scroll-def">
<el-form :model="createForm" label-position="top">
<el-form-item :label="$t('device.device-modbus-task.384302-0')" prop="jobName">
<el-input v-model="createForm.jobName" :placeholder="$t('device.device-modbus-task.384302-1')" class="input-item" />
</el-form-item>
<el-row :gutter="40">
<!-- 从机地址 -->
<el-col :span="12">
<el-form-item :label="$t('device.device-modbus-task.384302-14')" prop="path">
<el-input v-model="createForm.path" class="input-item"></el-input>
</el-form-item>
</el-col>
<!-- 功能码 -->
<el-col :span="12">
<el-form-item :label="$t('device.device-modbus-task.384302-15')" prop="functionCode">
<el-select v-model="createForm.functionCode" @change="changeNum" class="input-item">
<el-option :label="functionCode.label" :value="functionCode.value" v-for="functionCode in functionCodeList" :key="functionCode.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<!--起始寄存器地址-->
<el-col :span="12">
<el-form-item prop="startPath">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">{{ $t('device.device-modbus-task.384302-16') }}</div>
<el-tooltip :content="createForm.startPathSwitch" placement="top">
<el-switch v-model="createForm.startPathSwitch" size="mini" active-color="#13ce66" inactive-color="#ff4949" active-value="Dec" inactive-value="Hex" />
</el-tooltip>
</div>
<el-input
v-model="createForm.startPath"
type="number"
class="input-item"
v-show="createForm.startPathSwitch == 'Dec'"
:min="0"
@change="
() => {
createForm.startPath16 = int2hex(createForm.startPath);
}
"
@input="
() => {
createForm.startPath16 = int2hex(createForm.startPath);
}
"
>
<div slot="append">0x{{ createForm.startPath16 }}</div>
</el-input>
<el-input
v-model="createForm.startPath16"
v-show="createForm.startPathSwitch != 'Dec'"
@input="
() => {
createForm.startPath = hex2int(createForm.startPath16);
}
"
>
<div slot="append">{{ createForm.startPath }}</div>
</el-input>
</el-form-item>
</el-col>
<!-- 个数或写值 -->
<el-col :span="12">
<!-- 个数 -->
<el-form-item :label="registerNumTitle" prop="registerNum" v-show="!['05', '06'].includes(createForm.functionCode)">
<el-input-number v-model="createForm.registerNum" controls-position="right" :min="0" class="input-item" @change="changeNum" />
</el-form-item>
<!-- 写值 -->
<el-form-item prop="setValue" v-show="['05', '06'].includes(createForm.functionCode)">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">{{ registerNumTitle }}</div>
<el-tooltip :content="createForm.setValueSwitch" placement="top">
<el-switch v-model="createForm.setValueSwitch" size="mini" active-color="#13ce66" inactive-color="#ff4949" active-value="Dec" inactive-value="Hex" />
</el-tooltip>
</div>
<el-input
v-model="createForm.setValue"
type="number"
v-show="createForm.setValueSwitch == 'Dec'"
@change="
() => {
createForm.setValue16 = int2hex(createForm.setValue);
}
"
@input="
() => {
createForm.setValue16 = int2hex(createForm.setValue);
}
"
>
<div slot="append">0x{{ createForm.setValue16 }}</div>
</el-input>
<el-input
v-model="createForm.setValue16"
v-show="createForm.setValueSwitch != 'Dec'"
@input="
() => {
createForm.setValue = hex2int(createForm.setValue16);
}
"
>
<div slot="append">{{ createForm.setValue }}</div>
</el-input>
</el-form-item>
</el-col>
<!-- 批量写寄存器值 -->
<el-col :span="12" v-for="(item, index) in registerValList" :key="'register' + index" v-show="createForm.functionCode == '16'">
<el-form-item prop="registerValList">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">#{{ index }} {{ $t('device.device-modbus-task.384302-17') }}</div>
<el-tooltip :content="item.switch" placement="top">
<el-switch
v-model="item.switch"
size="mini"
active-color="#13ce66"
@change="
() => {
refreshRegisterInpust(item, index);
}
"
inactive-color="#ff4949"
active-value="Dec"
inactive-value="Hex"
/>
</el-tooltip>
</div>
<el-input
v-model="item.value"
type="number"
v-show="item.switch == 'Dec'"
:min="0"
@change="
() => {
item.value16 = int2hex(item.value);
refreshRegisterInpust(item, index);
}
"
@input="
() => {
item.value16 = int2hex(item.value);
refreshRegisterInpust(item, index);
}
"
>
<div slot="append">0x{{ item.value16 }}</div>
</el-input>
<el-input
v-model="item.value16"
v-show="item.switch != 'Dec'"
@input="
() => {
item.value = hex2int(item.value16);
refreshRegisterInpust(item, index);
}
"
>
<div slot="append">{{ item.value }}</div>
</el-input>
</el-form-item>
</el-col>
<!-- 批量写线圈值 -->
<el-col :span="6" v-for="(item, index) in IOValList" :key="'IO' + index" v-show="createForm.functionCode == '15'">
<el-form-item prop="registerValList">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">#{{ index }} {{ $t('device.device-modbus-task.384302-18') }}</div>
</div>
<el-switch
v-model="item.value"
active-value="1"
inactive-value="0"
@change="
() => {
refreshIOInpust(item, index);
}
"
/>
</el-form-item>
</el-col>
</el-row>
<!-- 任务状态-->
<el-form-item :label="$t('device.device-timer.433369-2')" prop="status">
<el-radio-group v-model="createForm.status">
<el-radio v-for="dict in dict.type.sys_job_status" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 时间周期-->
<el-form-item :label="$t('device.device-modbus-task.384302-19')" prop="cycleType">
<div class="timer-wrap">
<el-radio-group v-model="createForm.cycleType" @input="handleCycleTypeInput">
<el-radio :label="1" style="display: block">
{{ $t('device.device-modbus-task.384302-20') }}
<el-tooltip placement="right">
<div slot="content">
{{ $t('device.device-modbus-task.384302-21') }}
<br />
{{ $t('device.device-modbus-task.384302-22') }}
</div>
<i class="el-icon-question" style="color: #909399"></i>
</el-tooltip>
<div class="timer-period" v-show="createForm.cycleType === 1">
<span>{{ $t('device.device-modbus-task.384302-23') }}</span>
<el-select style="width: 100px; margin-left: 10px" v-model="cycles1[0].interval" size="mini" :disabled="createForm.cycleType !== 1" @change="handleCycleInterval">
<el-option v-for="dict in dict.type.variable_operation_interval" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
<el-select v-if="cycles1[0].interval === 'week'" style="width: 100px; margin-left: 5px" v-model="cycles1[0].week" size="mini" :disabled="createForm.cycleType !== 1">
<el-option v-for="dict in dict.type.variable_operation_week" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
<el-select v-if="cycles1[0].interval === 'month'" style="width: 100px; margin-left: 5px" v-model="cycles1[0].day" size="mini" :disabled="createForm.cycleType !== 1">
<el-option v-for="dict in dict.type.variable_operation_day" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
<el-select
v-if="cycles1[0].interval === 'day' || cycles1[0].interval === 'week' || cycles1[0].interval === 'month'"
style="width: 100px; margin-left: 5px"
v-model="cycles1[0].time"
size="mini"
:disabled="createForm.cycleType !== 1"
@change="handleCycleTime"
>
<el-option v-for="dict in dict.type.variable_operation_time" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
<span style="margin-left: 10px">{{ $t('device.device-modbus-task.384302-24') }}</span>
</div>
</el-radio>
<!-- 设备上电触发 -->
<el-radio :label="3" style="display: block; margin-top: 10px;">
<span>设备上电触发</span>
<el-tooltip placement="right">
<div slot="content">
设备上电时自动发送指令,发送成功后不再重复发送
</div>
<i class="el-icon-question" style="color: #909399; margin-left: 5px;"></i>
</el-tooltip>
</el-radio>
</el-radio-group>
</div>
</el-form-item>
</el-form>
<div v-loading="createLoading">
<div class="create-title">
<el-button type="text" @click.stop="encode">{{ $t('device.device-modbus-task.384302-25') }}</el-button>
<div class="title-right">
<el-button type="primary" size="mini" @click="copyText(createCode)">{{ $t('device.device-modbus-task.384302-26') }}</el-button>
</div>
</div>
<el-input
v-model="createCode"
class="create-code-input"
:placeholder="$t('device.device-modbus-task.384302-25')"
></el-input>
</div>
</div>
<div slot="footer" class="dialog-btn">
<el-button type="" size="mini" @click="editDialog = false">{{ $t('device.device-modbus-task.384302-27') }}</el-button>
<el-button type="primary" size="mini" @click="handleAdd">{{ $t('confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { hex2int, int2hex, copyText } from '@/utils/common';
import { parseTime } from '@/utils/ruoyi';
import { encode } from '@/api/iot/mqttTest';
import { listJob, getJob, delJob, addJob, updateJob, getSlaveId } from '@/api/iot/modbusJob';
import { listGateway } from '@/api/iot/gateway';
export default {
name: 'device-modbus-task',
dicts: ['sys_job_group', 'sys_job_status', 'variable_operation_interval', 'variable_operation_time', 'variable_operation_week', 'variable_operation_day', 'variable_operation_type'],
props: {
device: {
type: Object,
default: null,
},
// 是否启用左侧子设备面板(网关模式下有效),嵌套使用时传 false 避免重复
showSubPanel: {
type: Boolean,
default: true,
},
},
watch: {
device: {
deep: true,
handler(newVal, oldVal) {
if (newVal.deviceId && newVal.deviceId !== oldVal.deviceId) {
this.deviceInfo = newVal;
if (this.isGatewayMode) {
this.subDeviceList = [];
this.queryParams.subDeviceId = newVal.deviceId;
this.loadSubDeviceList();
this.getList();
} else {
this.queryParams.subDeviceId = newVal.deviceId;
this.getList();
}
}
},
},
},
computed: {
/**编辑寄存器个数显示的标题 */
registerNumTitle() {
switch (this.createForm.functionCode) {
case '01':
case '02':
case '15':
return this.$t('device.device-modbus-task.384302-29');
case '03':
case '04':
case '16':
return this.$t('device.device-modbus-task.384302-30');
case '05':
return this.$t('device.device-modbus-task.384302-31');
case '06':
return this.$t('device.device-modbus-task.384302-32');
}
},
/** 是否为网关模式(显示左侧子设备面板) */
isGatewayMode() {
return this.showSubPanel && this.device && this.device.deviceType === 2;
},
},
data() {
return {
//选中的格式
format: 'Hex',
// 遮罩层
loading: false,
//编辑框
editDialog: false,
//生成表单
createForm: {
cycleType: 1, // 1周期,2自定义
status: '0',
},
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 总条数
total: 0,
//功能码列表
functionCodeList: [
{
label: this.$t('device.device-modbus-task.384302-33'),
value: '01',
},
{
label: this.$t('device.device-modbus-task.384302-34'),
value: '02',
},
{
label: this.$t('device.device-modbus-task.384302-35'),
value: '03',
},
{
label: this.$t('device.device-modbus-task.384302-36'),
value: '04',
},
{
label: this.$t('device.device-modbus-task.384302-37'),
value: '05',
},
{
label: this.$t('device.device-modbus-task.384302-38'),
value: '06',
},
{
label: this.$t('device.device-modbus-task.384302-39'),
value: '15',
},
{
label: this.$t('device.device-modbus-task.384302-40'),
value: '16',
},
],
jobList: [],
// 显示搜索条件
showSearch: true,
//生成的指令码
createCode: '',
//批量写的寄存器值数组
registerValList: [],
//批量写的线圈个数
IOValList: [],
//编辑名称
editName: false,
//编辑名称表单
editNameForm: {},
//生成刷新
createLoading: false,
//删除快捷指令
delDialog: false,
//选择删除的快捷指令
delItem: {},
//父组件传过来的对象
deviceInfo: {},
subdeviceId: '',
// 网关模式:子设备列表(仅展示)
subDeviceList: [],
subListLoading: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
subDeviceId: null,
subSerialNumber: null,
command: null,
jobId: null,
status: null,
},
cycles1: [{ interval: '300', time: '', week: '', day: '' }],
cycles2: [{ type: 'day', time: '00', week: '', day: '', toType: '1', toTime: '02', toWeek: '', toDay: '' }],
};
},
methods: {
/** 执行时间列:周期/自定义有记录即展示;上电触发保持「已暂停且有记录」再展示 */
showExecuteTime(row) {
const t = row.cycleType;
if (t === 1 || t === 2) return true;
if (t === 3) return row.status === '1';
return false;
},
// 回填时间周期(remark -> cycles1/cycles2)
parseRemarkToCycles(cycleType, remark) {
// 默认值
this.cycles1 = [{ interval: '300', time: '', week: '', day: '' }];
this.cycles2 = [{ type: 'day', time: '00', week: '', day: '', toType: '1', toTime: '02', toWeek: '', toDay: '' }];
if (!remark) return;
let list = [];
try {
list = JSON.parse(remark);
} catch (e) {
return;
}
if (!Array.isArray(list) || list.length === 0) return;
const first = list[0] || {};
if (cycleType === 2) {
// 自定义时间段(当前页面若未展示 cycles2,则仅做数据回填保底)
this.cycles2 = list;
return;
}
// 周期循环
if (first.interval != null) {
this.cycles1 = [{ interval: String(first.interval), time: '', week: '', day: '' }];
return;
}
if (first.type === 'hour') {
this.cycles1 = [{ interval: 'hour', time: '', week: '', day: '' }];
return;
}
if (first.type === 'day') {
this.cycles1 = [{ interval: 'day', time: String(first.time || '01'), week: '', day: '' }];
return;
}
if (first.type === 'week') {
this.cycles1 = [{ interval: 'week', week: String(first.week || '1'), time: String(first.time || '01'), day: '' }];
return;
}
if (first.type === 'month') {
this.cycles1 = [{ interval: 'month', day: String(first.day || '1'), time: String(first.time || '01'), week: '' }];
return;
}
},
/** 查询轮训任务列列表 */
getList() {
this.loading = true;
listJob(this.queryParams).then((response) => {
this.jobList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 提交按钮 */
submitForm() {
if (this.createForm.taskId != null) {
updateJob(this.createForm).then((response) => {
this.$modal.msgSuccess(this.$t('device.device-modbus-task.384302-62'));
this.open = false;
this.getList();
});
} else {
addJob(this.createForm).then((response) => {
this.$modal.msgSuccess(this.$t('device.device-modbus-task.384302-63'));
this.open = false;
this.getList();
});
}
},
/** 删除按钮操作 */
handleDelete(row) {
const taskIds = row.taskId || this.ids;
const data = {
taskId: taskIds,
jobId: row.jobId,
};
this.$modal
.confirm(this.$t('device.device-modbus-task.384302-64', [taskIds]))
.then(function () {
return delJob(data);
})
.then(() => {
this.getList();
this.$modal.msgSuccess(this.$t('device.device-modbus-task.384302-65'));
})
.catch(() => {});
},
/**新增确认按钮*/
handleAdd() {
// 如果已经生成了指令(可能用户已编辑),直接使用当前的 createCode
if (this.createCode && this.createCode.trim()) {
this.handlePush();
return;
}
// 如果指令为空,才生成新的指令
let params = {
slaveId: parseInt(this.createForm.path), //从机地址
address: this.createForm.startPath, //起始寄存器地址
code: parseInt(this.createForm.functionCode), //功能码
protocolCode: this.device.protocolCode,
serialNumber: this.device.serialNumber,
};
switch (this.createForm.functionCode) {
case '01':
case '02':
case '03':
case '04':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
break;
case '05':
case '06':
//线圈值/寄存器值
params.writeData = this.createForm.setValue;
break;
case '15':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
//线圈值数组
const IOValList = this.IOValList.map((item) => {
return item.value;
});
params.bitString = IOValList.join('');
break;
case '16':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
//寄存器值数组
const registerValList = this.registerValList.map((item) => {
return item.value;
});
params.tenWriteData = registerValList;
break;
}
const res = encode(params).then((response) => {
this.createCode = response.msg;
this.handlePush();
});
},
handlePush() {
/**计算定时时间*/
let cycle = '';
// 如果是设备上电触发,不需要 cron 表达式
if (this.createForm.cycleType === 3) {
this.createForm.subDeviceId = this.device.deviceId;
this.createForm.subSerialNumber = this.device.serialNumber;
this.createForm.command = this.createCode;
this.createForm.remark = '';
this.createForm.cronExpression = '';
this.submitForm();
this.editDialog = false;
return;
}
// 原有的周期循环和自定义时间段逻辑
const c = this.cycles1.map((item) => {
if (item.interval === 'hour') {
return { type: 'hour' };
} else if (item.interval === 'day') {
return { type: 'day', time: item.time };
} else if (item.interval === 'week') {
return { type: 'week', week: item.week, time: item.time };
} else if (item.interval === 'month') {
return { type: 'month', day: item.day, time: item.time };
} else {
return { interval: item.interval };
}
});
cycle = JSON.stringify(c);
this.createForm.subDeviceId = this.device.deviceId;
this.createForm.subSerialNumber = this.device.serialNumber;
this.createForm.command = this.createCode;
this.createForm.remark = cycle;
this.submitForm();
this.editDialog = false;
},
/**打开编辑框 */
openEdit() {
this.resetCreateForm();
// 网关设备(deviceType=2)直接轮询:跳过从机地址校验,由用户手动填写
if (this.device && this.device.deviceType === 2) {
this.createForm.path = '';
this.editDialog = true;
} else {
this.getSlaveId();
}
this.editName = false;
},
// 表单重置
reset() {
this.form = {
taskId: null,
subDeviceId: null,
subSerialNumber: null,
command: null,
jobId: null,
status: null,
createBy: null,
createTime: null,
remark: null,
};
this.resetForm('form');
},
/**重置编辑框 */
resetCreateForm() {
this.createForm = {
path: '01',
functionCode: '01',
startPath: 0,
startPath16: '0000',
registerNum: 1,
startPathSwitch: 'Dec',
setValue: 0,
setValue16: '0000',
setValueSwitch: 'Dec',
status: '0',
cycleType: 1, // 1周期,2自定义
};
this.createCode = '';
},
/**十进制变成十六进制 */
int2hex(str) {
return int2hex(str);
},
/**十六进制变成十进制 */
hex2int(str) {
return hex2int(str);
},
/**修改批量写的寄存器个数或者线圈个数 */
changeNum() {
//批量写寄存器
if (this.createForm.functionCode == '16') {
for (let index = 0; index < this.createForm.registerNum; index++) {
const item = this.registerValList[index];
if (!item) {
this.registerValList[index] = {
value: 0,
value16: '0000',
switch: 'Dec',
};
}
}
//如果编写数组大于他需要写的数字,就到写的个数
if (this.registerValList.length > this.createForm.registerNum) {
//多的个数
const num = this.registerValList.length - this.createForm.registerNum;
this.registerValList.splice(this.createForm.registerNum, num);
}
}
//批量写线圈
if (this.createForm.functionCode == '15') {
for (let index = 0; index < this.createForm.registerNum; index++) {
const item = this.IOValList[index];
if (!item) {
this.IOValList[index] = {
value: '0',
};
}
}
//如果编写数组大于他需要写的数字,就到写的个数
if (this.IOValList.length > this.createForm.registerNum) {
//多的个数
const num = this.IOValList.length - this.createForm.registerNum;
this.IOValList.splice(this.createForm.registerNum, num);
}
}
},
/**刷新寄存器输入框 */
refreshRegisterInpust(item, index) {
this.$set(this.registerValList, index, item);
},
/**刷新线圈值 */
refreshIOInpust(item, index) {
this.$set(this.IOValList, index, item);
},
/**复制 */
copyText(code) {
const res = copyText(code);
this.$message({
type: res.type,
message: res.message,
});
},
/**编码 */
async encode() {
try {
this.createLoading = true;
let params = {
slaveId: parseInt(this.createForm.path), //从机地址
address: this.createForm.startPath, //起始寄存器地址
code: parseInt(this.createForm.functionCode), //功能码
protocolCode: this.device.protocolCode,
serialNumber: this.device.serialNumber,
};
switch (this.createForm.functionCode) {
case '01':
case '02':
case '03':
case '04':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
break;
case '05':
case '06':
//线圈值/寄存器值
params.writeData = this.createForm.setValue;
break;
case '15':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
//线圈值数组
const IOValList = this.IOValList.map((item) => {
return item.value;
});
params.bitString = IOValList.join('');
break;
case '16':
//线圈个数/寄存器个数
params.count = this.createForm.registerNum;
//寄存器值数组
const registerValList = this.registerValList.map((item) => {
return item.value;
});
params.tenWriteData = registerValList;
break;
}
const res = await encode(params);
this.createCode = res.msg;
} catch (err) {
this.$message({
type: 'error',
message: err.message || this.$t('device.device-modbus-task.384302-41'),
});
} finally {
this.createLoading = false;
}
},
// 搜索按钮操作
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
// 重置按钮操作
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
/** 加载子设备列表(仅展示,网关模式) */
loadSubDeviceList() {
if (!this.isGatewayMode) return;
this.subListLoading = true;
listGateway({ gwDeviceId: this.device.deviceId, pageSize: 999 })
.then((res) => {
this.subDeviceList = res.rows || [];
})
.finally(() => {
this.subListLoading = false;
});
},
getSlaveId() {
const productId = this.device.productId;
const subDeviceId = this.subdeviceId;
getSlaveId(productId, subDeviceId).then((response) => {
if (!response.data) {
this.$confirm(this.$t('device.device-modbus-task.384302-66'), this.$t('device.device-modbus-task.384302-67'), {
confirmButtonText: this.$t('device.device-modbus-task.384302-68'),
cancelButtonText: this.$t('device.device-modbus-task.384302-69'),
type: 'warning',
})
.then(() => {
//跳转modbus配置页签
})
.catch(() => {
this.editDialog = false;
this.$message({
type: 'info',
message: this.$t('device.device-modbus-task.384302-70'),
});
});
} else {
this.editDialog = true;
}
this.createForm.path = response.data;
});
},
// 定时状态修改
handleStatusChange(row) {
let text = row.status === '0' ? this.$t('device.device-modbus-task.384302-42') : this.$t('device.device-modbus-task.384302-43');
this.$modal
.confirm(this.$t('device.device-modbus-task.384302-44', [text + '""' + row.jobName]))
.then(function () {
return updateJob({ taskId: row.taskId, status: row.status });
})
.then(() => {
this.$modal.msgSuccess(text + this.$t('device.device-modbus-task.384302-45'));
})
.catch(function () {
row.status = row.status === '0' ? '1' : '0';
});
},
// 编辑轮询任务(修改时间周期/指令等)
handleEdit(row) {
this.resetCreateForm();
this.editName = true;
getJob(row.taskId).then((res) => {
const data = (res && res.data) || {};
this.createForm = Object.assign({}, this.createForm, data);
// 回填指令
this.createCode = data.command || '';
// 回填周期
const cycleType = data.cycleType != null ? data.cycleType : 1;
this.createForm.cycleType = cycleType;
this.parseRemarkToCycles(cycleType, data.remark);
// 打开弹窗
this.editDialog = true;
});
},
// 格式化显示CRON描述
formatCronDisplay(item) {
let result = '';
if (item.isAdvance == 0) {
let time = '<br /><span style="color:#F56C6C">时间 ' + item.cronExpression.substring(5, 7) + ':' + item.cronExpression.substring(2, 4) + '</span>';
let week = item.cronExpression.substring(12);
if (week == '1,2,3,4,5,6,7') {
(result = this.$t('device.device-modbus-task.384302-47')), +time;
} else {
let weekArray = week.split(',');
for (let i = 0; i < weekArray.length; i++) {
if (weekArray[i] == '1') {
result = result + this.$t('device.device-modbus-task.384302-48');
} else if (weekArray[i] == '2') {
result = result + this.$t('device.device-modbus-task.384302-49');
} else if (weekArray[i] == '3') {
result = result + this.$t('device.device-modbus-task.384302-50');
} else if (weekArray[i] == '4') {
result = result + this.$t('device.device-modbus-task.384302-51');
} else if (weekArray[i] == '5') {
result = result + this.$t('device.device-modbus-task.384302-52');
} else if (weekArray[i] == '6') {
result = result + this.$t('device.device-modbus-task.384302-53');
} else if (weekArray[i] == '7') {
result = result + this.$t('device.device-modbus-task.384302-54');
}
}
result = result.substring(0, result.length - 1) + ' ' + time;
}
} else {
result = this.$t('device.device-modbus-task.384302-55');
}
return result;
},
// 修改按钮操作
handleUpdate(row) {
this.reset();
const jobId = row.jobId || this.ids;
getJob(jobId).then((response) => {
this.form = response.data;
// actionList赋值
this.actionList = JSON.parse(this.form.actions);
for (let i = 0; i < this.actionList.length; i++) {
if (this.actionList[i].type == 1) {
this.setParentAndModelData(this.actionList[i], this.thingsModel.properties);
} else if (this.actionList[i].type == 2) {
this.setParentAndModelData(this.actionList[i], this.thingsModel.functions);
}
}
if (this.form.isAdvance == 0) {
let arrayValue = this.form.cronExpression.substring(12).split(',').map(Number);
this.timerWeekValue = arrayValue;
this.timerTimeValue = this.form.cronExpression.substring(5, 7) + ':' + this.form.cronExpression.substring(2, 4);
}
this.open = true;
this.title = this.$t('device.device-timer.433369-71');
});
},
// 时间周期-自定义-添加
handleCustomIntervalAdd() {
this.cycles2.push({ type: 'day', time: '00', week: '', day: '', toType: '1', toTime: '02', toWeek: '', toDay: '' });
},
// 时间周期类型切换
handleCycleTypeInput(val) {
if (val === 1) {
// 周期循环
this.cycles2 = [{ type: 'day', time: '00', week: '', day: '', toType: '1', toTime: '02', toWeek: '', toDay: '' }];
} else if (val === 2) {
// 自定义时间段
this.cycles1 = [{ interval: 'hour', time: '', week: '', day: '' }];
} else if (val === 3) {
// 设备上电触发,不需要时间周期配置
// 可以清空或保留,但不使用
}
},
handleCustomIntervalDelete(index) {
this.cycles2.splice(index, 1);
},
// 时间周期-周期循环
handleCycleInterval(val) {
if (val === 'hour') {
this.$set(this.cycles1, 0, { interval: val, time: '', week: '', day: '' });
} else if (val === 'day') {
this.$set(this.cycles1, 0, { interval: val, time: '01', week: '', day: '' });
} else if (val === 'week') {
this.$set(this.cycles1, 0, { interval: val, time: '01', week: '1', day: '' });
} else if (val === 'month') {
this.$set(this.cycles1, 0, { interval: val, time: '01', week: '', day: '1' });
} else {
this.$set(this.cycles1, 0, { interval: val, time: '', week: '', day: '' });
}
},
// 时间周期-自定义
handleCustomInterval(index, val) {
if (val === 'day') {
this.$set(this.cycles2, index, { type: val, time: '00', week: '', day: '', toType: '1', toTime: '02', toWeek: '', toDay: '' });
} else if (val === 'week') {
this.$set(this.cycles2, index, { type: val, time: '00', week: '1', day: '', toType: '3', toTime: '02', toWeek: '2', toDay: '' });
} else if (val === 'month') {
this.$set(this.cycles2, index, { type: val, time: '00', week: '', day: '1', toType: '4', toTime: '02', toWeek: '', toDay: '2' });
}
},
},
mounted() {
const { deviceId } = this.device;
if (deviceId) {
if (this.isGatewayMode) {
// 网关模式:加载子设备列表(仅展示),任务列表始终查网关自身
this.queryParams.subDeviceId = deviceId;
this.loadSubDeviceList();
this.getList();
} else {
this.queryParams.subDeviceId = deviceId;
this.getList();
}
}
this.resetCreateForm();
},
};
</script>
<style lang="scss" scoped>
$border-color: #dcdfe6;
$right-btn-color: #1890ff;
.modbus-task-row {
min-height: 400px;
}
.sub-device-side-panel {
border: 1px solid $border-color;
border-radius: 4px;
min-height: 400px;
display: flex;
flex-direction: column;
overflow: hidden;
.side-panel-title {
padding: 10px 14px;
font-size: 13px;
font-weight: 600;
color: #303133;
background: #f5f7fa;
border-bottom: 1px solid $border-color;
display: flex;
align-items: center;
i {
margin-right: 6px;
color: #409eff;
}
}
.side-panel-list {
flex: 1;
overflow-y: auto;
padding: 6px 0;
}
.side-panel-item {
padding: 8px 14px;
cursor: pointer;
border-left: 3px solid transparent;
transition: all 0.2s;
&:hover {
background: #f0f7ff;
}
&.is-active {
background: #ecf5ff;
border-left-color: #409eff;
.side-panel-item__name {
color: #409eff;
}
}
&__name {
font-size: 13px;
font-weight: 500;
color: #303133;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
i {
margin-right: 4px;
font-size: 12px;
}
}
&__meta {
display: flex;
align-items: center;
margin-top: 3px;
font-size: 11px;
color: #909399;
.self-tag {
color: #409eff;
}
}
&__sn {
font-size: 11px;
color: #c0c4cc;
margin-top: 2px;
font-family: monospace;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
::v-deep .el-dialog__body {
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
box-sizing: border-box;
padding: 0;
}
.dialog-content {
//max-height:1000px;
width: 100%;
box-sizing: border-box;
padding: 30px 20px;
overflow: auto;
.create-title {
display: flex;
line-height: 36px;
margin-bottom: 16px;
.title-right {
margin-left: auto;
}
}
.input-item {
width: 250px;
}
.create-code {
font-size: 18px;
line-height: 36px;
font-weight: 800;
}
.create-code-input {
::v-deep .el-input__inner {
font-size: 18px;
line-height: 36px;
font-weight: 800;
font-family: monospace;
}
}
.form-item-label {
display: flex;
align-items: center;
width: 100%;
::v-deep .el-form-item__label {
width: 100%;
}
}
.timer-wrap {
.timer-period {
display: inline-block;
margin-left: 30px;
color: #000000;
font-size: 12px;
font-weight: normal;
}
.timer-custom {
display: block;
margin-top: 12px;
color: #000000;
font-size: 12px;
font-weight: normal;
}
}
.comp-add-edit {
display: flex;
flex-direction: column;
::v-deep .el-form-item__content {
margin-left: 0 !important;
}
.comput-formula-box {
padding: 20px 0;
border: 1px solid #e7e9f1;
margin-left: 50px;
display: flex;
.title {
text-align: right;
width: 96px;
padding-right: 16px;
}
.content {
font-size: 12px;
line-height: 32px;
.alias-wrap {
width: 28px;
height: 28px;
background-image: linear-gradient(180deg, #6fb0ff, #3c78ff);
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2);
font-size: 12px;
font-weight: 400;
line-height: 28px;
text-align: center;
margin-top: 2px;
color: #fff;
}
}
}
}
}
</style>