vue完善

This commit is contained in:
1 2025-06-18 10:20:38 +08:00
parent f877f5f9a2
commit 8c7b69b208
10 changed files with 1814 additions and 295 deletions

View File

@ -11,6 +11,7 @@ VUE_APP_BASE_API = '/dev-api'
VUE_CLI_BABEL_TRANSPILE_MODULES = true
# 后端接口地址
# VUE_APP_SERVER_API_URL = 'http://1.94.62.14:8080/'
VUE_APP_SERVER_API_URL = 'http://localhost:8080/'
# Mqtt消息服务器连接地址

View File

@ -9,5 +9,8 @@
"i18n-ally.displayLanguage": "zh-CN",
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
} //
}

BIN
dist.zip

Binary file not shown.

View File

@ -109,7 +109,7 @@
"babel-eslint": "10.1.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"chalk": "4.1.0",
"code-inspector-plugin": "^0.20.10",
"code-inspector-plugin": "^0.20.12",
"compression-webpack-plugin": "5.0.2",
"connect": "3.6.6",
"eslint": "^7.28.0",

View File

@ -603,6 +603,7 @@
"device.running-status.866086-44": "查看版本",
"device.running-status.866086-45": "只读属性",
"device.running-status.866086-46": "非历史存储",
"device.running-status.866086-47": "您当前最新固件的版本号小于设备当前版本号,请检查固件版本是否正确",
"device.sub.083943-0": "添加子设备",
"device.sub.083943-1": "移除子设备",
"device.sub.083943-2": "设置子设备地址",

View File

@ -0,0 +1,716 @@
<template>
<div class="modbus-task">
<el-row :gutter="10" style="margin-bottom: 8px">
<el-col :span="1.5">
<div class="btn-group">
<el-button type="primary" plain icon="el-icon-edit" size="small" @click="setSlave"
v-if="!enableSetSlave">
{{ $t('product.product-modbus.562372-2') }}
</el-button>
<el-button type="primary" plain icon="el-icon-edit" size="small" @click="saveSlave"
v-if="enableSetSlave" v-hasPermi="['modbus:config:edit']">
{{ $t('product.product-modbus.562372-3') }}
</el-button>
<el-button type="info" plain icon="el-icon-close" size="small" @click="cancelSlave"
v-if="enableSetSlave">{{ $t('product.product-modbus.562372-4') }}</el-button>
</div>
</el-col>
<div style="float: right; margin-right: 10px">
<el-tooltip :content="$t('device.device-edit.148398-107')" placement="top">
<el-button type="primary" plain icon="el-icon-edit" size="small" @click="handleInstruction"
:disabled="device.status !== 3">{{ $t('device.instruction-parsing.830424-56') }}</el-button>
</el-tooltip>
</div>
</el-row>
<el-table v-loading="loading" :data="commandList" :border="false" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column :label="$t('product.product-modbus-task.894593-71')" align="center" prop="address"
width="200px">
<template slot-scope="scope">
<el-input-number style="width: 100%" :disabled="!enableSetSlave" v-model="scope.row.address"
:min="0" :max="400000" :label="$t('product.product-modbus.562372-30')"></el-input-number>
</template>
</el-table-column>
<el-table-column :label="$t('product.product-modbus-task.894593-72')" align="center" prop="register"
width="200px">
<template slot-scope="scope">
<el-input-number style="width: 100%" :disabled="!enableSetSlave" v-model="scope.row.register"
:min="0"></el-input-number>
</template>
</el-table-column>
<el-table-column :label="$t('product.product-modbus-task.894593-73')" align="center" prop="functioncode"
width="260px">
<template slot-scope="scope">
<el-select v-model="scope.row.code" style="width: 100%" :disabled="!enableSetSlave"
@change="changeFunctionCode(scope.row)">
<el-option v-for="code in codeList" :key="code.value" :label="code.label"
:value="code.value"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column :label="$t('device.instruction-config.984980-0')" align="center" prop="quantity"
width="200px">
<template slot-scope="scope">
<el-input-number style="width: 100%"
:disabled="!enableSetSlave || ['05', '06'].includes(scope.row.code)"
v-model="scope.row.quantity" :min="0" @change="changeQuentity(scope.row)"></el-input-number>
</template>
</el-table-column>
<el-table-column :label="$t('device.instruction-config.984980-1')" align="center" prop="values"
width="300px">
<template slot-scope="scope">
<template v-if="['05', '06', '15', '16'].includes(scope.row.code)">
{{ scope.row.values ? scope.row.values : '' }}
<el-button icon="el-icon-edit" type="text" size="mini" :disabled="!enableSetSlave"
@click="openEdit(scope.row, scope.$index, commandList)"></el-button>
</template>
<template v-else>
<!-- 其他情况显示空或默认值 -->
-
</template>
</template>
</el-table-column>
<el-table-column :label="$t('product.product-modbus.562372-34')" align="center"
class-name="small-padding fixed-width" fixed="right">
<template slot-scope="scope">
<el-button size="small" type="text" icon="el-icon-delete" v-if="enableSetSlave"
@click="handleDelete(scope.row, scope.$index, commandList)" v-hasPermi="['iot:config:remove']">
{{ $t('product.product-modbus.562372-35') }}
</el-button>
</template>
</el-table-column>
</el-table>
<el-row :gutter="10" class="mb8" style="margin-top: 20px">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="small" @click="handleAddData"
v-if="enableSetSlave">{{
$t('device.instruction-config.984980-5') }}</el-button>
</el-col>
</el-row>
<el-dialog :title="$t('device.instruction-config.984980-4')" :visible.sync="editDialog" width="600px">
<div class="dialog-content">
<el-form :model="createForm" label-position="top">
<el-row :gutter="40">
<!-- 写值 -->
<el-form-item prop="setValueSwitch1" v-show="['05'].includes(createForm.code)">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">{{ $t('product.product-modbus-task.894593-18') }}</div>
</div>
<el-switch v-model="createForm.setValueSwitch1" active-value="1" inactive-value="0" />
</el-form-item>
<!-- 写值 -->
<el-form-item prop="setValue" v-show="['06'].includes(createForm.code)">
<div slot="label" class="form-item-label">
<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 :span="12" v-for="(item, index) in registerValList" :key="'register' + index"
v-show="createForm.code == '16'">
<el-form-item prop="registerValList">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">#{{ index }} {{
$t('product.product-modbus-task.894593-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 dataList" :key="'IO' + index"
v-show="createForm.code == '15'">
<el-form-item prop="registerValList">
<div slot="label" class="form-item-label">
<div style="margin-right: auto">#{{ index }} {{
$t('product.product-modbus-task.894593-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>
</div>
<div slot="footer" class="dialog-btn">
<el-button type="" @click="editDialog = false">{{ $t('product.product-modbus-task.894593-27')
}}</el-button>
<el-button type="primary" @click="handleAdd" v-hasPermi="['modbus:job:add']">{{ $t('confirm')
}}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { hex2int, int2hex } from '@/utils/common';
import { listJob, batchIntruction, delJob, addJob, updateJob } from '@/api/iot/modbusJob';
export default {
name: 'device-instruction-config',
props: {
device: {
type: Object,
default: null,
},
},
watch: {
device: {
handler(newVal, oldVal) {
if (newVal.deviceId && newVal.deviceId !== oldVal.deviceId) {
this.queryParams.deviceId = newVal.deviceId;
this.deviceInfo = newVal;
this.getList();
}
},
},
enableSetSlave: function (n, old) {
//
if (!n) {
this.getList();
}
this.delDataIds = [];
},
},
data() {
return {
//
loading: false,
//
editDialog: false,
enableSetSlave: false,
//
ids: [],
//
single: true,
//
multiple: true,
//
total: 0,
deviceInfo: {},
//
codeList: [
{
label: this.$t('product.product-modbus-task.894593-33'),
value: '01',
},
{
label: this.$t('product.product-modbus-task.894593-34'),
value: '02',
},
{
label: this.$t('product.product-modbus-task.894593-35'),
value: '03',
},
{
label: this.$t('product.product-modbus-task.894593-36'),
value: '04',
},
{
label: this.$t('product.product-modbus-task.894593-37'),
value: '05',
},
{
label: this.$t('product.product-modbus-task.894593-38'),
value: '06',
},
{
label: this.$t('product.product-modbus-task.894593-39'),
value: '15',
},
{
label: this.$t('product.product-modbus-task.894593-40'),
value: '16',
},
],
jobList: [],
//
createCode: '',
//
registerValList: [],
//线
dataList: [],
//
deviceInfo: {},
commandList: [],
selectDatas: [], //
//
queryParams: {
pageNum: 1,
pageSize: 10,
deviceId: null,
command: null,
taskId: null,
status: null,
commandType: 2,
},
//
createForm: {
cycleType: 1, // 1,2
status: 0,
register: 1,
code: '03',
address: 1,
quantity: 1,
},
currentEditIndex: 0,
//dataTableid
delDataIds: [],
};
},
mounted() {
const { deviceId } = this.device;
if (deviceId) {
this.queryParams.deviceId = deviceId;
this.queryParams.commandType = 2;
this.getList();
}
this.resetCreateForm();
},
methods: {
/** 查询轮训任务列列表 */
getList() {
this.loading = true;
this.commandList = [];
listJob(this.queryParams).then((response) => {
this.jobList = response.rows;
if (response.rows.length > 0) {
if (response.rows[0].command.includes('{"register":')) {
this.commandList = JSON.parse(response.rows[0].command);
}
this.createForm.taskId = response.rows[0].taskId;
} else {
this.createForm.taskId = '';
}
this.total = response.total;
this.loading = false;
});
},
setSlave() {
this.enableSetSlave = !this.enableSetSlave;
},
//
handleInstruction() {
if (this.selectDatas.length === 0) {
this.$message.error(this.$t('device.instruction-config.984980-6'));
return;
}
const params = {
clientId: this.device.serialNumber,
commands: this.selectDatas,
};
this.$modal
.confirm(this.$t('device.instruction-config.984980-2'))
.then(function () {
batchIntruction(params)
.then((response) => {
if (response.code === 200) {
this.$message.success(this.$t('device.realTime-status.845353-6'));
} else {
this.$message.error(response.msg);
}
})
.catch(() => { });
})
.then(() => { });
},
/** 保存modbus配置参数 */
saveSlave() {
const data = {
taskId: this.createForm.taskId,
deviceId: this.device.deviceId,
command: JSON.stringify(this.commandList),
status: 0,
commandType: 2,
serialNumber: this.device.serialNumber,
};
updateJob(data).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-modbus.562372-53'));
this.getList();
this.setSlave();
});
},
//
handleSelectionChange(selection) {
this.selectDatas = selection;
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/**取消*/
cancelSlave() {
this.enableSetSlave = !this.enableSetSlave;
},
/** 提交按钮 */
submitForm() {
if (this.createForm.taskId != null) {
updateJob(this.createForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-modbus-task.894593-62'));
this.open = false;
this.getList();
});
} else {
addJob(this.createForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-modbus-task.894593-63'));
this.open = false;
this.getList();
});
}
},
/** 新增数据行操作 */
handleAddData() {
var d = {
register: 0,
address: 1,
code: '03',
quantity: 1,
values: [],
};
this.commandList.push(d);
},
/** 删除按钮操作 */
handleDelete(row, index, list, justiceSelect) {
if (this.device.protocolCode !== 'MODBUS-TCP') {
const taskIds = row.taskId || this.ids;
this.$modal
.confirm(this.$t('device.instruction-config.984980-3'), [taskIds])
.then(function () {
return delJob(taskIds);
})
.then(() => {
this.getList();
this.$modal.msgSuccess(this.$t('product.product-modbus-task.894593-65'));
})
.catch(() => { });
} else {
const item = list.splice(index, 1)[0];
this.delDataIds.push(row.id);
}
},
/**新增确认按钮*/
handleAdd() {
const index = this.currentEditIndex;
switch (this.createForm.code) {
case '05':
this.$set(this.commandList[index], 'values', [this.createForm.setValueSwitch1]);
break;
case '06':
this.$set(this.commandList[index], 'values', [this.createForm.setValue]);
break;
case '15':
//线
this.$set(
this.commandList[index],
'values',
this.dataList.map((item) => item.value)
);
break;
case '16':
//
this.$set(
this.commandList[index],
'values',
this.registerValList.map((item) => item.value)
);
break;
}
this.editDialog = false;
},
/**打开编辑框 */
openEdit(row, index, list) {
this.editDialog = true;
this.resetCreateForm();
this.createForm.code = row.code;
this.createForm.quantity = row.quantity;
this.createForm.values = row.values;
this.currentEditIndex = index;
if (this.createForm.code == '15') {
// dataList
if (row.values.length > 0) {
this.dataList = row.values.map((value, idx) => ({
value: value,
//
}));
} else {
for (let index = 0; index < this.createForm.quantity; index++) {
const item = this.dataList[index];
if (!item) {
this.dataList[index] = {
value: '0',
};
}
}
//
if (this.dataList.length > this.createForm.quantity) {
//
const num = this.dataList.length - this.createForm.quantity;
this.dataList.splice(this.createForm.quantity, num);
}
}
} else if (this.createForm.code == '16') {
// registerValList
if (row.values.length > 0) {
this.registerValList = row.values.map((value, idx) => ({
value: value,
value16: value.toString(16).padStart(4, '0'), // 164
switch: 'Dec', // 使
}));
} else {
for (let index = 0; index < this.createForm.quantity; index++) {
const item = this.registerValList[index];
if (!item) {
this.registerValList[index] = {
value: 0,
value16: '0000',
switch: 'Dec',
};
}
}
//
if (this.registerValList.length > this.createForm.quantity) {
//
const num = this.registerValList.length - this.createForm.quantity;
this.registerValList.splice(this.createForm.quantity, num);
}
}
} else if (this.createForm.code == '05') {
if (row.values.length > 0) {
//
this.createForm.setValueSwitch1 = row.values[0];
} else {
this.createForm.setValueSwitch1 = '0';
}
} else if (this.createForm.code == '06') {
if (row.values.length > 0) {
//
this.createForm.setValue = row.values[0];
} else {
this.createForm.setValue = 0;
}
}
},
//
changeFunctionCode(row) {
row.quantity = 1;
if (['05', '06', '15', '16'].includes(row.code)) {
row.values = [];
} else {
this.commandList.forEach((item) => {
delete item.values;
});
}
},
//
changeQuentity(row) {
if (['05', '06', '15', '16'].includes(row.code)) {
row.values = [];
} else {
this.commandList.forEach((item) => {
delete item.values;
});
}
},
/**重置编辑框 */
resetCreateForm() {
this.createForm = {
path: '1',
code: '01',
startPath: 0,
startPath16: '0000',
quantity: 1,
startPathSwitch: 'Dec',
setValue: 0,
setValue16: '0000',
setValueSwitch: 'Dec',
setValueSwitch1: '0',
status: 0,
cycleType: 1, // 1,2
};
this.createCode = '';
},
/**十进制变成十六进制 */
int2hex(str) {
return int2hex(str);
},
/**十六进制变成十进制 */
hex2int(str) {
return hex2int(str);
},
/**刷新寄存器输入框 */
refreshRegisterInpust(item, index) {
this.$set(this.registerValList, index, item);
},
/**刷新线圈值 */
refreshIOInpust(item, index) {
this.$set(this.dataList, index, item);
},
},
};
</script>
<style lang="scss" scoped>
$border-color: #dcdfe6;
$right-btn-color: #1890ff;
::v-deep {
.el-button--text .el-icon-edit {
color: #409eff;
}
}
.modbus-task {
width: 100%;
padding: 10px;
}
.dialog-content {
width: 100%;
box-sizing: border-box;
padding: 0px 20px;
overflow: auto;
.input-item {
width: 250px;
}
.create-title {
display: flex;
line-height: 36px;
margin-bottom: 16px;
.title-right {
margin-left: auto;
}
}
.create-code {
font-size: 18px;
line-height: 36px;
font-weight: 800;
}
.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>

View File

@ -495,7 +495,7 @@
<el-form ref="firmwareForm" label-width="100px" :model="firmwareParams" :inline="true" :rules="rules">
<el-form-item :label="$t('device.running-status.866086-38')" prop="firmwareType">
<el-select v-model="deviceInfo.firmwareType" :placeholder="$t('firmware.index.222541-51')"
@change="handleVersionInputChange" style="width: 350px" disabled>
style="width: 350px" disabled>
<el-option v-for="item in firmwareTypeList" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
@ -507,6 +507,7 @@
</el-input>
</el-form-item>
</el-form>
<div slot="footer">
<el-tooltip effect="dark" :content="$t('device.running-status.866086-41')" placement="top-start">
<el-button type="primary" @click="getLatestFirmware" :disabled="device.status !== 3">{{
@ -519,12 +520,16 @@
<!-- 添加或修改产品固件对话框 -->
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openFirmware" width="600px"
append-to-body>
<div v-if="firmware == null" style="text-align: center; font-size: 16px">
<div v-if="!firmware" style="text-align: center; font-size: 16px">
<i class="el-icon-success" style="color: #67c23a"></i>
{{ $t('device.running-status.866086-11') }}
</div>
<el-descriptions :column="1" border size="large"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version"
<div v-else-if="!compareVersions(deviceInfo.firmwareVersion, firmware.version)"
style="text-align: center; font-size: 16px">
<i class="el-icon-warning" style="color: #E6A23C"></i>
{{ $t('device.running-status.866086-47') }}
</div>
<el-descriptions v-else :column="1" border size="large"
:labelStyle="{ width: '150px', 'font-weight': 'bold' }">
<template slot="title">
<el-link icon="el-icon-success" type="success" :underline="false">{{
@ -545,8 +550,9 @@
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button type="success" @click="otaUpgrade"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version">{{
$t('device.running-status.866086-18') }}</el-button>
v-if="firmware && compareVersions(deviceInfo.firmwareVersion, firmware.version)">
{{ $t('device.running-status.866086-18') }}
</el-button>
<el-button @click="cancel">{{ $t('cancel') }}</el-button>
</div>
</el-dialog>
@ -1066,6 +1072,24 @@ export default {
cancel1() {
this.openVersion = false;
},
//
compareVersions(version1, version2) {
// 'Version'
version1 = String(version1).replace('Version', '').trim();
version2 = String(version2).replace('Version', '').trim();
const v1Parts = version1.split('.').map(Number);
const v2Parts = version2.split('.').map(Number);
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1 = v1Parts[i] || 0;
const v2 = v2Parts[i] || 0;
if (v1 < v2) return true;
if (v1 > v2) return false;
}
return false;
},
/** 更新设备状态 */
updateDeviceStatus(device) {
if (device.status == 3) {

View File

@ -17,133 +17,180 @@
<svg-icon icon-class="ota" />
{{ $t('device.running-status.866086-1') }}
</template>
<el-button type="primary" size="mini" :plain="true" @click="viewVersion()">{{
$t('device.running-status.866086-44')
}}</el-button>
<el-button type="primary" size="mini" :plain="true" @click="viewVersion()">{{ $t('device.running-status.866086-44') }}</el-button>
</el-descriptions-item>
<!-- 设备物模型-->
<el-descriptions-item v-for="(item, index) in deviceInfo.thingsModels" :key="index"
:labelStyle="statusColor">
<el-descriptions-item v-for="(item, index) in deviceInfo.thingsModels" :key="index" :labelStyle="statusColor">
<template slot="label">
<i class="el-icon-open"></i>
{{ item.name }}
</template>
<div v-if="item.datatype.type == 'bool'">
<el-switch v-model="item.shadow" @change="mqttPublish(deviceInfo, item)" active-text=""
inactive-text="" active-value="1" inactive-value="0" style="min-width: 100px"
:disabled="shadowUnEnable || item.isReadonly == 1" />
<el-switch
v-model="item.shadow"
@change="mqttPublish(deviceInfo, item)"
active-text=""
inactive-text=""
active-value="1"
inactive-value="0"
style="min-width: 100px"
:disabled="shadowUnEnable || item.isReadonly == 1"
/>
</div>
<div v-if="item.datatype.type == 'enum'" class="emum-wrap">
<div v-if="item.datatype.showWay && item.datatype.showWay == 'button'">
<el-button class="btn" size="mini"
<el-button
class="btn"
size="mini"
@click="enumButtonClick(deviceInfo, item, subItem.value)"
v-for="subItem in item.datatype.enumList" :key="subItem.value"
v-for="subItem in item.datatype.enumList"
:key="subItem.value"
:disabled="shadowUnEnable || item.isReadonly == 1"
:class="{ 'is-active-btn': subItem.value === item.shadow }">
:class="{ 'is-active-btn': subItem.value === item.shadow }"
>
{{ subItem.text }}
</el-button>
</div>
<el-select v-else v-model="item.shadow" :placeholder="$t('device.running-status.866086-3')"
@change="mqttPublish(deviceInfo, item)"
:disabled="shadowUnEnable || item.isReadonly == 1">
<el-option v-for="subItem in item.datatype.enumList" :key="subItem.value"
:label="subItem.text" :value="subItem.value" />
<el-select v-else v-model="item.shadow" :placeholder="$t('device.running-status.866086-3')" @change="mqttPublish(deviceInfo, item)" :disabled="shadowUnEnable || item.isReadonly == 1">
<el-option v-for="subItem in item.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="item.datatype.type == 'string'">
<el-input v-model="item.shadow"
<el-input
v-model="item.shadow"
:placeholder="item.datatype.unit ? $t('device.running-status.866086-5', [item.datatype.unit]) : $t('device.running-status.866086-4')"
:disabled="shadowUnEnable || item.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, item)" style="font-size: 20px"
:disabled="shadowUnEnable || item.isReadonly == 1"
>
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, item)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && item.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="item.datatype.type == 'decimal'">
<div style="width: 80%; float: left">
<el-slider v-model="item.shadow" :min="item.datatype.min" :max="item.datatype.max"
:step="item.datatype.step" :format-tooltip="(x) => x + ' ' + item.datatype.unit"
:disabled="shadowUnEnable || item.isReadonly == 1"></el-slider>
<el-slider
v-model="item.shadow"
:min="item.datatype.min"
:max="item.datatype.max"
:step="item.datatype.step"
:format-tooltip="(x) => x + ' ' + item.datatype.unit"
:disabled="shadowUnEnable || item.isReadonly == 1"
></el-slider>
</div>
<div style="width: 20%; float: left">
<el-button icon="el-icon-s-promotion" type="info" @click="mqttPublish(deviceInfo, item)"
<el-button
icon="el-icon-s-promotion"
type="info"
@click="mqttPublish(deviceInfo, item)"
style="font-size: 16px; padding: 1px 8px; margin: 2px 0 0 5px; border-radius: 3px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && item.isReadonly == 0"
></el-button>
</div>
</div>
<div v-if="item.datatype.type == 'integer'">
<div style="width: 80%; float: left">
<el-slider style="margin-left: 10px" v-model="item.shadow" :min="item.datatype.min"
:max="item.datatype.max" :step="item.datatype.step"
<el-slider
style="margin-left: 10px"
v-model="item.shadow"
:min="item.datatype.min"
:max="item.datatype.max"
:step="item.datatype.step"
:format-tooltip="(x) => x + ' ' + item.datatype.unit"
:disabled="shadowUnEnable || item.isReadonly == 1"></el-slider>
:disabled="shadowUnEnable || item.isReadonly == 1"
></el-slider>
</div>
<div style="width: 20%; float: left">
<el-button icon="el-icon-s-promotion" type="info" @click="mqttPublish(deviceInfo, item)"
<el-button
icon="el-icon-s-promotion"
type="info"
@click="mqttPublish(deviceInfo, item)"
style="font-size: 16px; padding: 1px 8px; margin: 4px 0 0 10px; border-radius: 3px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && item.isReadonly == 0"
></el-button>
</div>
</div>
<div v-if="item.datatype.type == 'object'">
<el-descriptions :column="1" size="mini" border>
<el-descriptions-item v-for="(param, index) in item.datatype.params" :key="index"
:label="param.name">
<el-descriptions-item v-for="(param, index) in item.datatype.params" :key="index" :label="param.name">
<div v-if="param.datatype.type == 'bool'">
<el-switch v-model="param.shadow" @change="mqttPublish(deviceInfo, param)"
active-text="" inactive-text="" active-value="1" inactive-value="0"
<el-switch
v-model="param.shadow"
@change="mqttPublish(deviceInfo, param)"
active-text=""
inactive-text=""
active-value="1"
inactive-value="0"
style="min-width: 100px"
:disabled="shadowUnEnable || param.isReadonly == 1" />
:disabled="shadowUnEnable || param.isReadonly == 1"
/>
</div>
<div v-if="param.datatype.type == 'enum'">
<div v-if="param.datatype.showWay && param.datatype.showWay == 'button'">
<el-button style="margin: 5px" size="mini"
<el-button
style="margin: 5px"
size="mini"
@click="enumButtonClick(deviceInfo, param, subItem.value)"
v-for="subItem in param.datatype.enumList" :key="subItem.value"
v-for="subItem in param.datatype.enumList"
:key="subItem.value"
:disabled="shadowUnEnable || param.isReadonly == 1"
:class="{ 'is-active-btn': subItem.value === param.shadow }">
:class="{ 'is-active-btn': subItem.value === param.shadow }"
>
{{ subItem.text }}
</el-button>
</div>
<el-select size="small" v-else v-model="param.shadow"
<el-select
size="small"
v-else
v-model="param.shadow"
:placeholder="$t('device.running-status.866086-3')"
@change="mqttPublish(deviceInfo, param)"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value"
:label="subItem.text" :value="subItem.value" />
:disabled="shadowUnEnable || param.isReadonly == 1"
>
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="param.datatype.type == 'string'">
<el-input v-model="param.shadow"
:placeholder="$t('device.running-status.866086-4')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" :placeholder="$t('device.running-status.866086-4')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="param.datatype.type == 'decimal'">
<el-input v-model="param.shadow" type="number"
:placeholder="$t('device.running-status.866086-7')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" type="number" :placeholder="$t('device.running-status.866086-7')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="param.datatype.type == 'integer'">
<el-input v-model="param.shadow" type="integer"
:placeholder="$t('device.running-status.866086-8')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" type="integer" :placeholder="$t('device.running-status.866086-8')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
</el-descriptions-item>
@ -151,38 +198,61 @@
</div>
<div v-if="item.datatype.type == 'array'">
<el-descriptions :column="1" size="mini" border v-if="item.datatype.arrayType != 'object'">
<el-descriptions-item v-for="(model, index) in item.datatype.arrayModel" :key="index"
:label="item.name + (index + 1)">
<el-descriptions-item v-for="(model, index) in item.datatype.arrayModel" :key="index" :label="item.name + (index + 1)">
<div v-if="item.datatype.arrayType == 'string'">
<el-input :placeholder="$t('device.running-status.866086-4')" size="mini"
v-model="model.shadow" :disabled="shadowUnEnable || item.isReadonly == 1"
@input="arrayItemChange($event, item)">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)" style="font-size: 20px"
<el-input
:placeholder="$t('device.running-status.866086-4')"
size="mini"
v-model="model.shadow"
:disabled="shadowUnEnable || item.isReadonly == 1"
@input="arrayItemChange($event, item)"
>
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable || item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable || item.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="item.datatype.arrayType == 'decimal'">
<el-input type="number" :placeholder="$t('device.running-status.866086-7')"
size="mini" v-model="model.shadow"
<el-input
type="number"
:placeholder="$t('device.running-status.866086-7')"
size="mini"
v-model="model.shadow"
:disabled="shadowUnEnable || item.isReadonly == 1"
@input="arrayItemChange($event, item)">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)" style="font-size: 20px"
@input="arrayItemChange($event, item)"
>
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable || item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable || item.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="item.datatype.arrayType == 'integer'">
<el-input type="integer" :placeholder="$t('device.running-status.866086-8')"
size="mini" v-model="model.shadow"
<el-input
type="integer"
:placeholder="$t('device.running-status.866086-8')"
size="mini"
v-model="model.shadow"
:disabled="shadowUnEnable || item.isReadonly == 1"
@input="arrayItemChange($event, item)">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)" style="font-size: 20px"
@input="arrayItemChange($event, item)"
>
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, model)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable || item.isReadonly == 0"></el-button>
v-if="!shadowUnEnable || item.isReadonly == 0"
></el-button>
</el-input>
</div>
</el-descriptions-item>
@ -196,63 +266,78 @@
</span>
</template>
<el-descriptions :column="1" size="mini" border>
<el-descriptions-item v-for="(param, index) in arrayParam" :key="index"
:label="param.name">
<el-descriptions-item v-for="(param, index) in arrayParam" :key="index" :label="param.name">
<div v-if="param.datatype.type == 'bool'">
<el-switch v-model="param.shadow"
@change="mqttPublish(deviceInfo, param)" active-text=""
inactive-text="" active-value="1" inactive-value="0"
<el-switch
v-model="param.shadow"
@change="mqttPublish(deviceInfo, param)"
active-text=""
inactive-text=""
active-value="1"
inactive-value="0"
style="min-width: 100px"
:disabled="shadowUnEnable || param.isReadonly == 1" />
:disabled="shadowUnEnable || param.isReadonly == 1"
/>
</div>
<div v-if="param.datatype.type == 'enum'">
<div
v-if="param.datatype.showWay && param.datatype.showWay == 'button'">
<el-button style="margin: 5px" size="mini"
<div v-if="param.datatype.showWay && param.datatype.showWay == 'button'">
<el-button
style="margin: 5px"
size="mini"
@click="enumButtonClick(deviceInfo, param, subItem.value)"
v-for="subItem in param.datatype.enumList" :key="subItem.value"
v-for="subItem in param.datatype.enumList"
:key="subItem.value"
:disabled="shadowUnEnable || param.isReadonly == 1"
:class="{ 'is-active-btn': subItem.value === param.shadow }">
:class="{ 'is-active-btn': subItem.value === param.shadow }"
>
{{ subItem.text }}
</el-button>
</div>
<el-select v-else v-model="param.shadow"
:placeholder="$t('device.running-status.866086-3')" size="small"
<el-select
v-else
v-model="param.shadow"
:placeholder="$t('device.running-status.866086-3')"
size="small"
@change="mqttPublish(deviceInfo, param)"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-option v-for="subItem in param.datatype.enumList"
:key="subItem.value" :label="subItem.text"
:value="subItem.value" />
:disabled="shadowUnEnable || param.isReadonly == 1"
>
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="param.datatype.type == 'string'">
<el-input v-model="param.shadow"
:placeholder="$t('device.running-status.866086-4')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" :placeholder="$t('device.running-status.866086-4')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="param.datatype.type == 'decimal'">
<el-input v-model="param.shadow" type="number"
:placeholder="$t('device.running-status.866086-7')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" type="number" :placeholder="$t('device.running-status.866086-7')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
<div v-if="param.datatype.type == 'integer'">
<el-input v-model="param.shadow" type="integer"
:placeholder="$t('device.running-status.866086-8')"
:disabled="shadowUnEnable || param.isReadonly == 1">
<el-button slot="append" icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)" style="font-size: 20px"
<el-input v-model="param.shadow" type="integer" :placeholder="$t('device.running-status.866086-8')" :disabled="shadowUnEnable || param.isReadonly == 1">
<el-button
slot="append"
icon="el-icon-s-promotion"
@click="mqttPublish(deviceInfo, param)"
style="font-size: 20px"
:title="$t('device.running-status.866086-6')"
v-if="!shadowUnEnable && param.isReadonly == 0"></el-button>
v-if="!shadowUnEnable && param.isReadonly == 0"
></el-button>
</el-input>
</div>
</el-descriptions-item>
@ -264,100 +349,80 @@
</el-descriptions>
<!---设备状态(影子模式value值不会更新)-->
<el-descriptions style="margin-top: 30px" :column="1" border
v-if="deviceInfo.isShadow == 1 && deviceInfo.status != 3">
<el-descriptions style="margin-top: 30px" :column="1" border v-if="deviceInfo.isShadow == 1 && deviceInfo.status != 3">
<template slot="title" v-if="deviceInfo.thingsModels.length > 0">
<span style="font-size: 14px; color: #606266">{{ $t('device.running-status.866086-9') }}</span>
</template>
<!-- 设备物模型-->
<el-descriptions-item v-for="(item, index) in deviceInfo.thingsModels" :key="index"
:labelStyle="{ minWidth: '100px' }">
<el-descriptions-item v-for="(item, index) in deviceInfo.thingsModels" :key="index" :labelStyle="{ minWidth: '100px' }">
<template slot="label">
<i class="el-icon-open"></i>
{{ item.name }}
</template>
<div v-if="item.datatype.type == 'bool'">
<el-switch v-model="item.value" @change="mqttPublish(deviceInfo, item)" active-text=""
inactive-text="" active-value="1" inactive-value="0" style="min-width: 100px"
disabled />
<el-switch v-model="item.value" @change="mqttPublish(deviceInfo, item)" active-text="" inactive-text="" active-value="1" inactive-value="0" style="min-width: 100px" disabled />
</div>
<div v-if="item.datatype.type == 'enum'">
<div v-if="item.datatype.showWay && item.datatype.showWay == 'button'">
<el-button style="margin: 5px" size="mini" disabled
v-for="subItem in item.datatype.enumList" :key="subItem.value">{{ subItem.text
}}</el-button>
<el-button style="margin: 5px" size="mini" disabled v-for="subItem in item.datatype.enumList" :key="subItem.value">{{ subItem.text }}</el-button>
</div>
<el-select v-else v-model="item.value" :placeholder="$t('device.running-status.866086-3')"
@change="mqttPublish(deviceInfo, item)" disabled>
<el-option v-for="subItem in item.datatype.enumList" :key="subItem.value"
:label="subItem.text" :value="subItem.value" />
<el-select v-else v-model="item.value" :placeholder="$t('device.running-status.866086-3')" @change="mqttPublish(deviceInfo, item)" disabled>
<el-option v-for="subItem in item.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="item.datatype.type == 'string'">
<el-input v-model="item.value" :placeholder="$t('device.running-status.866086-4')"
disabled></el-input>
<el-input v-model="item.value" :placeholder="$t('device.running-status.866086-4')" disabled></el-input>
</div>
<div v-if="item.datatype.type == 'decimal'">
<el-input v-model="item.value" type="number"
:placeholder="$t('device.running-status.866086-7')" disabled></el-input>
<el-input v-model="item.value" type="number" :placeholder="$t('device.running-status.866086-7')" disabled></el-input>
</div>
<div v-if="item.datatype.type == 'integer'">
<el-input v-model="item.value" type="integer"
:placeholder="$t('device.running-status.866086-8')" disabled></el-input>
<el-input v-model="item.value" type="integer" :placeholder="$t('device.running-status.866086-8')" disabled></el-input>
</div>
<div v-if="item.datatype.type == 'object'">
<el-descriptions :column="1" size="mini" border>
<el-descriptions-item v-for="(param, index) in item.datatype.params" :key="index"
:label="param.name">
<el-descriptions-item v-for="(param, index) in item.datatype.params" :key="index" :label="param.name">
<div v-if="param.datatype.type == 'bool'">
<el-switch v-model="param.value" size="mini"
@change="mqttPublish(deviceInfo, param)" active-text="" inactive-text=""
active-value="1" inactive-value="0" style="min-width: 100px" disabled />
<el-switch
v-model="param.value"
size="mini"
@change="mqttPublish(deviceInfo, param)"
active-text=""
inactive-text=""
active-value="1"
inactive-value="0"
style="min-width: 100px"
disabled
/>
</div>
<div v-if="param.datatype.type == 'enum'">
<el-select v-model="param.value"
:placeholder="$t('device.running-status.866086-3')"
@change="mqttPublish(deviceInfo, param)" disabled size="mini">
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value"
:label="subItem.text" :value="subItem.value" />
<el-select v-model="param.value" :placeholder="$t('device.running-status.866086-3')" @change="mqttPublish(deviceInfo, param)" disabled size="mini">
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="param.datatype.type == 'string'">
<el-input v-model="param.value"
:placeholder="$t('device.running-status.866086-4')" disabled
size="mini"></el-input>
<el-input v-model="param.value" :placeholder="$t('device.running-status.866086-4')" disabled size="mini"></el-input>
</div>
<div v-if="param.datatype.type == 'decimal'">
<el-input v-model="param.value" type="number"
:placeholder="$t('device.running-status.866086-7')" disabled
size="mini"></el-input>
<el-input v-model="param.value" type="number" :placeholder="$t('device.running-status.866086-7')" disabled size="mini"></el-input>
</div>
<div v-if="param.datatype.type == 'integer'">
<el-input v-model="param.value" type="integer"
:placeholder="$t('device.running-status.866086-8')" disabled
size="mini"></el-input>
<el-input v-model="param.value" type="integer" :placeholder="$t('device.running-status.866086-8')" disabled size="mini"></el-input>
</div>
</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="item.datatype.type == 'array'">
<el-descriptions :column="1" size="mini" border v-if="item.datatype.arrayType != 'object'">
<el-descriptions-item v-for="(model, index) in item.datatype.arrayModel" :key="index"
:label="item.name + (index + 1)">
<el-descriptions-item v-for="(model, index) in item.datatype.arrayModel" :key="index" :label="item.name + (index + 1)">
<div v-if="item.datatype.arrayType == 'string'">
<el-input v-model="model.value"
:placeholder="$t('device.running-status.866086-4')" size="mini"
disabled></el-input>
<el-input v-model="model.value" :placeholder="$t('device.running-status.866086-4')" size="mini" disabled></el-input>
</div>
<div v-if="item.datatype.arrayType == 'decimal'">
<el-input v-model="model.value" type="number"
:placeholder="$t('device.running-status.866086-7')" size="mini"
disabled></el-input>
<el-input v-model="model.value" type="number" :placeholder="$t('device.running-status.866086-7')" size="mini" disabled></el-input>
</div>
<div v-if="item.datatype.arrayType == 'integer'">
<el-input v-model="model.value" type="integer"
:placeholder="$t('device.running-status.866086-8')" size="mini"
disabled></el-input>
<el-input v-model="model.value" type="integer" :placeholder="$t('device.running-status.866086-8')" size="mini" disabled></el-input>
</div>
</el-descriptions-item>
</el-descriptions>
@ -370,37 +435,32 @@
</span>
</template>
<el-descriptions :column="1" size="mini" border>
<el-descriptions-item v-for="(param, index) in arrayParam" :key="index"
:label="param.name">
<el-descriptions-item v-for="(param, index) in arrayParam" :key="index" :label="param.name">
<div v-if="param.datatype.type == 'bool'">
<el-switch v-model="param.value"
@change="mqttPublish(deviceInfo, param)" active-text=""
inactive-text="" active-value="1" inactive-value="0"
style="min-width: 100px" disabled />
<el-switch
v-model="param.value"
@change="mqttPublish(deviceInfo, param)"
active-text=""
inactive-text=""
active-value="1"
inactive-value="0"
style="min-width: 100px"
disabled
/>
</div>
<div v-if="param.datatype.type == 'enum'">
<el-select v-model="param.value"
:placeholder="$t('device.running-status.866086-3')"
@change="mqttPublish(deviceInfo, param)" disabled size="mini">
<el-option v-for="subItem in param.datatype.enumList"
:key="subItem.value" :label="subItem.text"
:value="subItem.value" />
<el-select v-model="param.value" :placeholder="$t('device.running-status.866086-3')" @change="mqttPublish(deviceInfo, param)" disabled size="mini">
<el-option v-for="subItem in param.datatype.enumList" :key="subItem.value" :label="subItem.text" :value="subItem.value" />
</el-select>
</div>
<div v-if="param.datatype.type == 'string'">
<el-input v-model="param.value"
:placeholder="$t('device.running-status.866086-4')" disabled
size="mini"></el-input>
<el-input v-model="param.value" :placeholder="$t('device.running-status.866086-4')" disabled size="mini"></el-input>
</div>
<div v-if="param.datatype.type == 'decimal'">
<el-input v-model="param.value" type="number"
:placeholder="$t('device.running-status.866086-7')" disabled
size="mini"></el-input>
<el-input v-model="param.value" type="number" :placeholder="$t('device.running-status.866086-7')" disabled size="mini"></el-input>
</div>
<div v-if="param.datatype.type == 'integer'">
<el-input v-model="param.value" type="integer"
:placeholder="$t('device.running-status.866086-8')" disabled
size="mini"></el-input>
<el-input v-model="param.value" type="integer" :placeholder="$t('device.running-status.866086-8')" disabled size="mini"></el-input>
</div>
</el-descriptions-item>
</el-descriptions>
@ -414,77 +474,57 @@
<el-col :xs="24" :sm="24" :md="24" :lg="10" :xl="14">
<!-- 设备监测图表-->
<el-row :gutter="20" v-if="deviceInfo.chartList.length > 0">
<el-col :xs="24" :sm="12" :md="12" :lg="24" :xl="8" v-for="(item, index) in deviceInfo.chartList"
:key="index">
<el-col :xs="24" :sm="12" :md="12" :lg="24" :xl="8" v-for="(item, index) in deviceInfo.chartList" :key="index">
<el-card shadow="hover" style="border-radius: 8px; margin-bottom: 20px">
<div ref="map" style="height: 230px; width: 185px; margin: 0 auto; margin-bottom: 15px">
</div>
<div ref="map" style="height: 230px; width: 185px; margin: 0 auto; margin-bottom: 15px"></div>
</el-card>
</el-col>
</el-row>
</el-col>
<!-- <iframe src="https://example.com" width="20%" height="800px" style="border: none;"></iframe> -->
</el-row>
<!-- 固件版本查看对话框 -->
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openVersion" width="550px"
append-to-body>
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openVersion" width="550px" append-to-body>
<el-form ref="firmwareForm" label-width="100px" :model="firmwareParams" :inline="true" :rules="rules">
<el-form-item :label="$t('device.running-status.866086-38')" prop="firmwareType">
<el-select v-model="deviceInfo.firmwareType" :placeholder="$t('firmware.index.222541-51')"
@change="handleVersionInputChange" style="width: 350px" disabled>
<el-option v-for="item in firmwareTypeList" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-select v-model="deviceInfo.firmwareType" :placeholder="$t('firmware.index.222541-51')" @change="handleVersionInputChange" style="width: 350px" disabled>
<el-option v-for="item in firmwareTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('device.running-status.866086-39')" prop="">
<el-input :placeholder="$t('device.running-status.866086-40')" v-model="deviceInfo.firmwareVersion"
style="width: 350px" disabled>
<el-input :placeholder="$t('device.running-status.866086-40')" v-model="deviceInfo.firmwareVersion" style="width: 350px" disabled>
<template slot="prepend">Version</template>
</el-input>
</el-form-item>
</el-form>
<div slot="footer">
<el-tooltip effect="dark" :content="$t('device.running-status.866086-41')" placement="top-start">
<el-button type="primary" @click="getLatestFirmware" :disabled="device.status !== 3">{{
$t('device.running-status.866086-42') }}</el-button>
<el-button type="primary" @click="getLatestFirmware" :disabled="device.status !== 3">{{ $t('device.running-status.866086-42') }}</el-button>
</el-tooltip>
<el-button @click="cancel1">{{ $t('cancel') }}</el-button>
</div>
</el-dialog>
<!-- 添加或修改产品固件对话框 -->
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openFirmware" width="600px"
append-to-body>
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openFirmware" width="600px" append-to-body>
<div v-if="firmware == null" style="text-align: center; font-size: 16px">
<i class="el-icon-success" style="color: #67c23a"></i>
{{ $t('device.running-status.866086-11') }}
</div>
<el-descriptions :column="1" border size="large"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version"
:labelStyle="{ width: '150px', 'font-weight': 'bold' }">
<el-descriptions :column="1" border size="large" v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version" :labelStyle="{ width: '150px', 'font-weight': 'bold' }">
<template slot="title">
<el-link icon="el-icon-success" type="success" :underline="false">{{
$t('device.running-status.866086-12') }}</el-link>
<el-link icon="el-icon-success" type="success" :underline="false">{{ $t('device.running-status.866086-12') }}</el-link>
</template>
<el-descriptions-item :label="$t('device.running-status.866086-13')">{{ firmware.firmwareName
}}</el-descriptions-item>
<el-descriptions-item :label="$t('device.device-edit.148398-4')">{{ firmware.productName
}}</el-descriptions-item>
<el-descriptions-item :label="$t('device.device-edit.148398-12')">Version {{ firmware.version
}}</el-descriptions-item>
<el-descriptions-item :label="$t('device.running-status.866086-13')">{{ firmware.firmwareName }}</el-descriptions-item>
<el-descriptions-item :label="$t('device.device-edit.148398-4')">{{ firmware.productName }}</el-descriptions-item>
<el-descriptions-item :label="$t('device.device-edit.148398-12')">Version {{ firmware.version }}</el-descriptions-item>
<el-descriptions-item :label="$t('device.running-status.866086-16')">
<el-link :href="getDownloadUrl(firmware.filePath)" :underline="false" type="primary">{{
getDownloadUrl(firmware.filePath) }}</el-link>
<el-link :href="getDownloadUrl(firmware.filePath)" :underline="false" type="primary">{{ getDownloadUrl(firmware.filePath) }}</el-link>
</el-descriptions-item>
<el-descriptions-item :label="$t('device.running-status.866086-17')">{{ firmware.remark
}}</el-descriptions-item>
<el-descriptions-item :label="$t('device.running-status.866086-17')">{{ firmware.remark }}</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button type="success" @click="otaUpgrade"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version">{{
$t('device.running-status.866086-18') }}</el-button>
<el-button type="success" @click="otaUpgrade" v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version">{{ $t('device.running-status.866086-18') }}</el-button>
<el-button @click="cancel">{{ $t('cancel') }}</el-button>
</div>
</el-dialog>
@ -515,7 +555,6 @@ export default {
this.$nextTick(function () {
this.MonitorChart();
});
// console.log("", JSON.stringify(this.deviceInfo.thingsModels));
//
if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) {
this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order);
@ -632,7 +671,6 @@ export default {
//
this.$busEvent.$on('updateData', (params) => {
this.updateParam(params);
// console.log("", JSON.stringify(this.deviceInfo.thingsModels));
});
},
initDataStatus() {

View File

@ -83,7 +83,7 @@
</el-table>
</el-card>
<!-- 默认列表 -->
<!-- 播放列表 -->
<el-card class="default-list-card" shadow="hover">
<div slot="header" class="default-list-header">
<span class="default-list-title">播放列表</span>
@ -205,7 +205,7 @@
<el-form ref="firmwareForm" label-width="100px" :model="firmwareParams" :inline="true" :rules="rules">
<el-form-item :label="$t('device.running-status.866086-38')" prop="firmwareType">
<el-select v-model="deviceInfo.firmwareType" :placeholder="$t('firmware.index.222541-51')"
@change="handleVersionInputChange" style="width: 350px" disabled>
style="width: 350px" disabled>
<el-option v-for="item in firmwareTypeList" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
@ -217,6 +217,7 @@
</el-input>
</el-form-item>
</el-form>
<div slot="footer">
<el-tooltip effect="dark" :content="$t('device.running-status.866086-41')" placement="top-start">
<el-button type="primary" @click="getLatestFirmware" :disabled="device.status !== 3">{{
@ -229,12 +230,16 @@
<!-- 添加或修改产品固件对话框 -->
<el-dialog :title="$t('device.running-status.866086-10')" :visible.sync="openFirmware" width="600px"
append-to-body>
<div v-if="firmware == null" style="text-align: center; font-size: 16px">
<div v-if="!firmware" style="text-align: center; font-size: 16px">
<i class="el-icon-success" style="color: #67c23a"></i>
{{ $t('device.running-status.866086-11') }}
</div>
<el-descriptions :column="1" border size="large"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version"
<div v-else-if="!compareVersions(deviceInfo.firmwareVersion, firmware.version)"
style="text-align: center; font-size: 16px">
<i class="el-icon-warning" style="color: #E6A23C"></i>
{{ $t('device.running-status.866086-47') }}
</div>
<el-descriptions v-else :column="1" border size="large"
:labelStyle="{ width: '150px', 'font-weight': 'bold' }">
<template slot="title">
<el-link icon="el-icon-success" type="success" :underline="false">{{
@ -255,8 +260,9 @@
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button type="success" @click="otaUpgrade"
v-if="firmware != null && deviceInfo.firmwareVersion < firmware.version">{{
$t('device.running-status.866086-18') }}</el-button>
v-if="firmware && compareVersions(deviceInfo.firmwareVersion, firmware.version)">
{{ $t('device.running-status.866086-18') }}
</el-button>
<el-button @click="cancel">{{ $t('cancel') }}</el-button>
</div>
</el-dialog>
@ -309,6 +315,10 @@
</el-form-item>
<el-form-item label="播放时间" prop="playTime">
<div class="time-range">
<div class="time-header">
<el-checkbox v-model="newPlaylist.isAllDay" @change="handleAllDayChange">全天</el-checkbox>
</div>
<div class="time-pickers" v-if="!newPlaylist.isAllDay">
<el-time-picker v-model="newPlaylist.playTimeStart" format="HH:mm" placeholder="开始时间"
style="width: 45%">
</el-time-picker>
@ -317,8 +327,11 @@
style="width: 45%">
</el-time-picker>
</div>
</div>
</el-form-item>
<el-form-item label="星期重复" prop="weekdays">
<div class="weekday-select">
<el-checkbox v-model="newPlaylist.isAllWeek" @change="handleAllWeekChange">全选</el-checkbox>
<el-checkbox-group v-model="newPlaylist.weekdays">
<el-checkbox label="1">周一</el-checkbox>
<el-checkbox label="2">周二</el-checkbox>
@ -328,6 +341,7 @@
<el-checkbox label="6">周六</el-checkbox>
<el-checkbox label="0">周日</el-checkbox>
</el-checkbox-group>
</div>
</el-form-item>
<el-form-item label="雷达开关" prop="radarEnabled">
<el-switch v-model="newPlaylist.radarEnabled" active-color="#13ce66" inactive-color="#ff4949">
@ -514,7 +528,9 @@ export default {
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120
radarSpeedMax: 120,
isAllDay: false,
isAllWeek: false
},
playlistRules: {
audioId: [
@ -955,6 +971,7 @@ export default {
this.handleVersionInputChange();
},
//
handleVersionInputChange() {
if (this.firmwareParams.firmwareType == 1) {
this.firmwareParams.versionInput = 'Version' + this.device.firmwareVersion;
@ -962,25 +979,79 @@ export default {
this.firmwareParams.versionInput = 'Version' + this.device.wirelessVersion;
}
},
cancel1() {
this.openVersion = false;
},
//
compareVersions(version1, version2) {
// 'Version'
version1 = String(version1).replace('Version', '').trim();
version2 = String(version2).replace('Version', '').trim();
const v1Parts = version1.split('.').map(Number);
const v2Parts = version2.split('.').map(Number);
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1 = v1Parts[i] || 0;
const v2 = v2Parts[i] || 0;
if (v1 < v2) return true;
if (v1 > v2) return false;
}
return false;
},
/** 获取最新固件 */
getLatestFirmware() {
const { deviceId, firmwareType } = this.deviceInfo;
if (!deviceId || !firmwareType) {
this.$message.error('设备信息不完整');
return;
}
getLatestFirmware(deviceId, firmwareType).then((response) => {
if (response.code === 200) {
if (response.data) {
this.firmware = response.data;
//
console.log('当前版本:', this.deviceInfo.firmwareVersion);
console.log('新版本:', this.firmware.version);
console.log('版本比较结果:', this.compareVersions(this.deviceInfo.firmwareVersion, this.firmware.version));
this.openFirmware = true;
} else {
this.$message.info('当前已是最新版本');
this.openFirmware = true;
}
} else {
this.$message.error(response.msg || '获取固件信息失败');
}
}).catch(error => {
console.error('获取固件信息失败:', error);
this.$message.error('获取固件信息失败');
});
},
/** 设备升级 */
otaUpgrade() {
// OTA
let topic = '/' + this.deviceInfo.productId + '/' + this.deviceInfo.serialNumber + '/ota/get';
let message = '{"version":' + this.firmware.version + ',"downloadUrl":"' + this.getDownloadUrl(this.firmware.filePath) + '"}';
//
this.$mqttTool
.publish(topic, message, this.$t('device.running-status.866086-31'))
.then((res) => {
this.$modal.notifySuccess(res);
})
.catch((res) => {
this.$modal.notifyError(res);
});
this.openFirmware = false;
},
cancel() {
this.openFirmware = false;
},
/** 获取下载路径 */
getDownloadUrl(path) {
return window.location.origin + process.env.VUE_APP_BASE_API + path;
},
@ -1304,7 +1375,9 @@ export default {
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120
radarSpeedMax: 120,
isAllDay: false,
isAllWeek: false
};
},
@ -1338,8 +1411,8 @@ export default {
},
time: {
en: 1,
begin: this.convertTimeToSeconds(this.newPlaylist.playTimeStart),
end: this.convertTimeToSeconds(this.newPlaylist.playTimeEnd),
begin: this.newPlaylist.isAllDay ? 0 : this.convertTimeToSeconds(this.newPlaylist.playTimeStart),
end: this.newPlaylist.isAllDay ? 86399 : this.convertTimeToSeconds(this.newPlaylist.playTimeEnd),
week: this.convertWeekArrayToValue(this.newPlaylist.weekdays)
},
speed: {
@ -1504,6 +1577,26 @@ export default {
}
}).catch(() => { });
},
/** 处理全天选择变化 */
handleAllDayChange(val) {
if (val) {
// 00:00 23:59
this.newPlaylist.playTimeStart = new Date(2000, 0, 1, 0, 0);
this.newPlaylist.playTimeEnd = new Date(2000, 0, 1, 23, 59);
}
},
/** 处理全选星期变化 */
handleAllWeekChange(val) {
if (val) {
//
this.newPlaylist.weekdays = ['0', '1', '2', '3', '4', '5', '6'];
} else {
//
this.newPlaylist.weekdays = [];
}
},
},
};
</script>
@ -1799,12 +1892,27 @@ export default {
.time-range {
display: flex;
align-items: center;
flex-direction: column;
gap: 10px;
.time-separator {
color: #606266;
font-size: 14px;
.time-header {
margin-bottom: 5px;
}
.time-pickers {
display: flex;
align-items: center;
width: 100%;
.time-separator {
margin: 0 10px;
}
}
}
.weekday-select {
display: flex;
flex-direction: column;
gap: 10px;
}
</style>

View File

@ -1,9 +1,11 @@
<template>
<div class="iot-group">
<el-card v-show="showSearch" style="margin-bottom: 15px; border-radius: 8px; width: 100%">
<el-form ref="queryForm" :model="queryParams" :inline="true" @submit.native.prevent label-width="68px" style="margin-bottom: -18px; padding: 3px 0 0 0">
<el-form ref="queryForm" :model="queryParams" :inline="true" @submit.native.prevent label-width="68px"
style="margin-bottom: -18px; padding: 3px 0 0 0">
<el-form-item prop="groupName">
<el-input v-model="queryParams.groupName" :placeholder="$t('iot.group.index.637432-1')" clearable @keyup.enter.native="handleQuery" />
<el-input v-model="queryParams.groupName" :placeholder="$t('iot.group.index.637432-1')" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<div style="float: right">
@ -16,17 +18,20 @@
<el-card>
<el-row :gutter="10" style="margin-bottom: 15px">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="small" @click="handleAdd" v-hasPermi="['iot:group:add']">{{ $t('iot.group.index.637432-5') }}</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="small" @click="handleAdd"
v-hasPermi="['iot:group:add']">{{ $t('iot.group.index.637432-5') }}</el-button>
</el-col>
<el-col :span="1.5">
<el-button plain icon="el-icon-delete" size="small" :disabled="multiple" @click="handleDelete" v-hasPermi="['iot:group:remove']">{{ $t('del') }}</el-button>
<el-button plain icon="el-icon-delete" size="small" :disabled="multiple" @click="handleDelete"
v-hasPermi="['iot:group:remove']">{{ $t('del') }}</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="groupList" :border="false" @selection-change="handleSelectionChange">
<el-table-column type="selection" align="center" width="55" />
<el-table-column :label="$t('iot.group.index.637432-0')" align="left" prop="groupName" min-width="200" />
<el-table-column :label="$t('iot.group.index.637432-0')" align="left" prop="groupName"
min-width="200" />
<el-table-column :label="$t('iot.group.index.637432-6')" align="center" prop="groupOrder" width="100" />
<el-table-column :label="$t('iot.group.index.637432-7')" align="center" prop="createTime" width="160">
<template slot-scope="scope">
@ -35,21 +40,31 @@
</el-table-column>
<el-table-column :label="$t('iot.group.index.637432-8')" align="center" prop="userName" width="100" />
<el-table-column :label="$t('iot.group.index.637432-9')" align="left" prop="remark" min-width="150" />
<el-table-column fixed="right" :label="$t('iot.group.index.637432-10')" align="center" class-name="small-padding fixed-width" width="290">
<el-table-column fixed="right" :label="$t('iot.group.index.637432-10')" align="center"
class-name="small-padding fixed-width" width="290">
<template slot-scope="scope">
<el-button size="small" type="text" icon="el-icon-search" @click="handleViewDevice(scope.row.groupId)" v-hasPermi="['iot:device:list']">
<el-button size="small" type="text" icon="el-icon-search"
@click="handleViewDevice(scope.row.groupId)" v-hasPermi="['iot:device:list']">
{{ $t('iot.group.index.637432-11') }}
</el-button>
<el-button size="small" type="text" icon="el-icon-plus" @click="selectDevice(scope.row)" v-hasPermi="['iot:group:add']">{{ $t('iot.group.index.637432-12') }}</el-button>
<el-button size="small" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['iot:group:query']">{{ $t('update') }}</el-button>
<el-button size="small" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['iot:group:remove']">
<el-button size="small" type="text" icon="el-icon-plus" @click="selectDevice(scope.row)"
v-hasPermi="['iot:group:add']">{{ $t('iot.group.index.637432-12') }}</el-button>
<el-button size="small" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['iot:group:query']">{{ $t('update') }}</el-button>
<el-button size="small" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['iot:group:remove']">
{{ $t('iot.group.index.637432-14') }}
</el-button>
<el-button size="small" type="text" icon="el-icon-setting" @click="handleAreaControl(scope.row)"
v-hasPermi="['iot:group:query']">
区域控制
</el-button>
</template>
</el-table-column>
</el-table>
<pagination style="margin-bottom: 20px" v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<pagination style="margin-bottom: 20px" v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 分组设备列表 -->
@ -59,21 +74,171 @@
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item :label="$t('iot.group.index.637432-0')" prop="groupName">
<el-input v-model="form.groupName" :placeholder="$t('iot.group.index.637432-1')" style="width: 400px" />
<el-input v-model="form.groupName" :placeholder="$t('iot.group.index.637432-1')"
style="width: 400px" />
</el-form-item>
<el-form-item :label="$t('iot.group.index.637432-6')" prop="groupOrder">
<el-input v-model="form.groupOrder" type="number" :placeholder="$t('iot.group.index.637432-15')" style="width: 400px" />
<el-input v-model="form.groupOrder" type="number" :placeholder="$t('iot.group.index.637432-15')"
style="width: 400px" />
</el-form-item>
<el-form-item :label="$t('iot.group.index.637432-9')" prop="remark">
<el-input v-model="form.remark" type="textarea" :placeholder="$t('iot.group.index.637432-16')" :autosize="{ minRows: 3, maxRows: 5 }" style="width: 400px" />
<el-input v-model="form.remark" type="textarea" :placeholder="$t('iot.group.index.637432-16')"
:autosize="{ minRows: 3, maxRows: 5 }" style="width: 400px" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm" v-show="form.groupId" v-hasPermi="['iot:group:edit']">{{ $t('update') }}</el-button>
<el-button type="primary" @click="submitForm" v-hasPermi="['iot:group:add']" v-show="!form.groupId">{{ $t('add') }}</el-button>
<el-button type="primary" @click="submitForm" v-show="form.groupId" v-hasPermi="['iot:group:edit']">{{
$t('update') }}</el-button>
<el-button type="primary" @click="submitForm" v-hasPermi="['iot:group:add']" v-show="!form.groupId">{{
$t('add')
}}</el-button>
<el-button @click="cancel">{{ $t('iot.group.index.637432-19') }}</el-button>
</div>
</el-dialog>
<!-- 添加区域控制对话框 -->
<el-dialog title="区域控制" :visible.sync="areaControlDialogVisible" width="1200px" append-to-body>
<el-form :model="areaControlForm" ref="areaControlForm" label-width="120px">
<!-- 基础设置 -->
<el-card class="settings-card" shadow="hover">
<div slot="header" class="settings-header">
<span class="settings-title">基础设置</span>
</div>
<el-form :model="basicSettings" label-width="100px" style="margin-top: 20px;">
<el-form-item label="音频开关">
<el-switch v-model="basicSettings.audioEnabled" active-color="#13ce66"
inactive-color="#ff4949" @change="handleAudioSwitchChange">
</el-switch>
</el-form-item>
<el-form-item label="音量设置">
<el-slider v-model="basicSettings.volume" :min="0" :max="100" :format-tooltip="formatVolume"
@change="handleVolumeChange" style="width: 80%" :disabled="!basicSettings.audioEnabled">
</el-slider>
</el-form-item>
</el-form>
</el-card>
<!-- 播放列表 -->
<el-card class="default-list-card" shadow="hover" style="margin-top: 20px;">
<div slot="header" class="default-list-header">
<div class="header-left">
<span class="default-list-title">播放列表</span>
</div>
<div class="header-right">
<el-button type="primary" size="mini" icon="el-icon-plus" @click="showAddPlaylistDialog">
添加音频
</el-button>
</div>
</div>
<el-table :data="areaControlForm.playList" style="width: 100%"
:header-cell-style="{ background: '#f5f7fa' }" border>
<el-table-column prop="id" label="序号" width="80" align="center">
</el-table-column>
<el-table-column prop="name" label="音频名称" min-width="150">
</el-table-column>
<el-table-column prop="playTime" label="播放时间" width="120" align="center">
</el-table-column>
<el-table-column prop="weekdays" label="重复" width="200" align="center">
</el-table-column>
<el-table-column label="雷达" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.radarEnabled ? 'success' : 'info'">
{{ scope.row.radarEnabled ? '开启' : '关闭' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" width="120" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.status" :active-value="'启用'" :inactive-value="'禁用'"
@change="handleStatusChange(scope.row)">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-delete" @click="handleDeletePlaylist(scope.row)">
</el-button>
</template>
</el-table-column>
<template slot="empty">
<div style="padding: 20px 0;">
<el-empty description="暂无播放列表数据"></el-empty>
</div>
</template>
</el-table>
</el-card>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="areaControlDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAreaControlForm"> </el-button>
</div>
</el-dialog>
<!-- 添加音频对话框 -->
<el-dialog title="添加音频" :visible.sync="addPlaylistDialogVisible" width="600px" append-to-body>
<el-form :model="playlistForm" :rules="playlistRules" ref="playlistForm" label-width="120px">
<el-form-item label="音频选择" prop="audioId">
<el-select v-model="playlistForm.audioId" placeholder="请选择音频" style="width: 100%">
<el-option v-for="item in audioList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="播放时间" prop="playTime">
<div class="time-range">
<div class="time-header">
<el-checkbox v-model="playlistForm.isAllDay" @change="handleAllDayChange">全天</el-checkbox>
</div>
<div class="time-pickers" v-if="!playlistForm.isAllDay">
<el-time-picker v-model="playlistForm.playTimeStart" format="HH:mm" placeholder="开始时间"
style="width: 45%">
</el-time-picker>
<span class="time-separator"></span>
<el-time-picker v-model="playlistForm.playTimeEnd" format="HH:mm" placeholder="结束时间"
style="width: 45%">
</el-time-picker>
</div>
</div>
</el-form-item>
<el-form-item label="星期重复" prop="weekdays">
<div class="weekday-select">
<el-checkbox v-model="playlistForm.isAllWeek" @change="handleAllWeekChange">全选</el-checkbox>
<el-checkbox-group v-model="playlistForm.weekdays">
<el-checkbox label="1">周一</el-checkbox>
<el-checkbox label="2">周二</el-checkbox>
<el-checkbox label="3">周三</el-checkbox>
<el-checkbox label="4">周四</el-checkbox>
<el-checkbox label="5">周五</el-checkbox>
<el-checkbox label="6">周六</el-checkbox>
<el-checkbox label="0">周日</el-checkbox>
</el-checkbox-group>
</div>
</el-form-item>
<el-form-item label="雷达开关" prop="radarEnabled">
<el-switch v-model="playlistForm.radarEnabled" active-color="#13ce66" inactive-color="#ff4949">
</el-switch>
</el-form-item>
<el-collapse-transition>
<div v-show="playlistForm.radarEnabled" class="radar-settings">
<el-form-item label="速度范围" prop="radarSpeed">
<div class="speed-range">
<el-input-number v-model="playlistForm.radarSpeedMin" :min="0"
:max="playlistForm.radarSpeedMax" :step="1" placeholder="最小速度">
</el-input-number>
<span class="speed-separator">-</span>
<el-input-number v-model="playlistForm.radarSpeedMax" :min="playlistForm.radarSpeedMin"
:max="200" :step="1" placeholder="最大速度">
</el-input-number>
<span class="speed-unit">km/h</span>
</div>
</el-form-item>
</div>
</el-collapse-transition>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="addPlaylistDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitPlaylistForm"> </el-button>
</div>
</el-dialog>
</div>
</template>
@ -81,6 +246,10 @@
import deviceList from './device-list';
import { listGroup, getGroup, delGroup, addGroup, updateGroup } from '@/api/iot/group';
import { getUserId } from '@/utils/auth';
import { listDevice } from '@/api/iot/device';
import { getDeviceRunningStatus } from '@/api/iot/device';
import { serviceInvoke } from '@/api/iot/runstatus';
import { listThingsModel } from '@/api/iot/device';
export default {
name: 'Group',
@ -139,6 +308,45 @@ export default {
},
],
},
//
areaControlDialogVisible: false,
areaControlForm: {
playList: []
},
basicSettings: {
audioEnabled: true,
volume: 50
},
addPlaylistDialogVisible: false,
playlistForm: {
audioId: '',
playTimeStart: null,
playTimeEnd: null,
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120,
isAllDay: false,
isAllWeek: false,
status: '启用'
},
playlistRules: {
audioId: [
{ required: true, message: '请选择音频', trigger: 'change' }
],
playTimeStart: [
{ required: true, message: '请选择开始时间', trigger: 'change' }
],
playTimeEnd: [
{ required: true, message: '请选择结束时间', trigger: 'change' }
],
weekdays: [
{ required: true, message: '请选择星期', trigger: 'change' }
]
},
audioList: [],
currentGroup: null,
deviceList: []
};
},
created() {
@ -278,6 +486,331 @@ export default {
`group_${new Date().getTime()}.xlsx`
);
},
/** 区域控制按钮操作 */
async handleAreaControl(row) {
this.currentGroup = row;
this.areaControlDialogVisible = true;
this.areaControlForm.playList = []; //
this.basicSettings = {
audioEnabled: true,
volume: 50
};
try {
//
const params = {
groupId: row.groupId,
pageNum: 1,
pageSize: 1 //
};
const response = await listDevice(params);
if (response.rows && response.rows.length > 0) {
const device = response.rows[0];
// 使getDeviceRunningStatus
const runningStatusResponse = await getDeviceRunningStatus({
deviceId: device.deviceId
});
if (runningStatusResponse.code === 200 && runningStatusResponse.data) {
const thingsModels = runningStatusResponse.data.thingsModels;
if (thingsModels) {
const playListModel = thingsModels.find(model => model.id === 'play_list');
console.log("data", JSON.stringify(playListModel));
if (playListModel && playListModel.value) {
try {
const jsonStr = playListModel.value.replace('JSON=', '');
const data = JSON.parse(jsonStr);
if (data.sound_card) {
//
if (data.sound_card.audio_enabled !== undefined) {
this.basicSettings.audioEnabled = data.sound_card.audio_enabled === 1;
}
if (data.sound_card.volume !== undefined) {
this.basicSettings.volume = data.sound_card.volume;
}
//
if (data.sound_card.play_list && data.sound_card.play_list.length > 0) {
//
const uniqueFilenames = new Set();
data.sound_card.play_list.forEach(item => {
if (item.play && item.play.filename) {
uniqueFilenames.add(item.play.filename);
}
});
//
this.audioList = Array.from(uniqueFilenames).map((filename, index) => {
const name = filename.split('_')[1] || filename;
return {
id: index + 1,
name: name,
filename: filename
};
});
}
}
} catch (error) {
console.error('解析物模型数据失败:', error);
this.$message.error('获取设备配置失败');
}
}
}
}
}
} catch (error) {
console.error('获取设备列表失败:', error);
this.$message.error('获取设备列表失败');
}
},
/** 处理音频开关变化 */
async handleAudioSwitchChange(val) {
try {
const params = {
groupId: this.currentGroup.groupId,
pageNum: 1,
pageSize: 1000
};
const response = await listDevice(params);
if (response.rows && response.rows.length > 0) {
for (const device of response.rows) {
const data = {
serialNumber: device.serialNumber,
productId: device.productId,
remoteCommand: {
'play_en': val ? 1 : 0
},
identifier: 'play_en',
modelName: '音频开关',
isShadow: device.status != 3,
type: 1
};
await serviceInvoke(data);
}
}
} catch (error) {
console.error('设置音频开关失败:', error);
this.$message.error('设置音频开关失败');
}
},
/** 处理音量变化 */
async handleVolumeChange(val) {
try {
const params = {
groupId: this.currentGroup.groupId,
pageNum: 1,
pageSize: 1000
};
const response = await listDevice(params);
if (response.rows && response.rows.length > 0) {
for (const device of response.rows) {
const data = {
serialNumber: device.serialNumber,
productId: device.productId,
remoteCommand: {
'volume': val
},
identifier: 'volume',
modelName: '音量设置',
isShadow: device.status != 3,
type: 1
};
await serviceInvoke(data);
}
}
} catch (error) {
console.error('设置音量失败:', error);
this.$message.error('设置音量失败');
}
},
/** 格式化音量显示 */
formatVolume(val) {
return `${val}%`;
},
/** 显示添加播放列表对话框 */
showAddPlaylistDialog() {
this.addPlaylistDialogVisible = true;
this.playlistForm = {
audioId: '',
playTimeStart: null,
playTimeEnd: null,
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120,
isAllDay: false,
isAllWeek: false,
status: '启用'
};
},
/** 提交播放列表表单 */
submitPlaylistForm() {
this.$refs.playlistForm.validate((valid) => {
if (valid) {
const audio = this.audioList.find(a => a.id === this.playlistForm.audioId);
const newItem = {
id: this.areaControlForm.playList.length + 1,
name: audio.name,
audioId: this.playlistForm.audioId,
filename: audio.filename,
playTime: this.playlistForm.isAllDay ? '全天' :
`${this.formatTime(this.playlistForm.playTimeStart)}-${this.formatTime(this.playlistForm.playTimeEnd)}`,
weekdays: this.playlistForm.weekdays.sort().map(day => {
const weekMap = { '0': '周日', '1': '周一', '2': '周二', '3': '周三', '4': '周四', '5': '周五', '6': '周六' };
return weekMap[day];
}).join(','),
radarEnabled: this.playlistForm.radarEnabled,
radarSpeedMin: this.playlistForm.radarSpeedMin,
radarSpeedMax: this.playlistForm.radarSpeedMax,
status: this.playlistForm.status
};
this.areaControlForm.playList.push(newItem);
this.addPlaylistDialogVisible = false;
}
});
},
/** 删除播放列表项 */
handleDeletePlaylist(row) {
const index = this.areaControlForm.playList.findIndex(item => item.id === row.id);
if (index > -1) {
this.areaControlForm.playList.splice(index, 1);
//
this.areaControlForm.playList.forEach((item, idx) => {
item.id = idx + 1;
});
}
},
/** 处理状态变化 */
handleStatusChange(row) {
//
},
/** 格式化时间 */
formatTime(time) {
if (!time) return '';
const hours = time.getHours().toString().padStart(2, '0');
const minutes = time.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
},
/** 提交区域控制表单 */
async submitAreaControlForm() {
try {
//
const params = {
groupId: this.currentGroup.groupId,
pageNum: 1,
pageSize: 1000 // 1000
};
const response = await listDevice(params);
if (response.rows && response.rows.length > 0) {
this.deviceList = response.rows;
//
const playListData = {
sound_card: {
play_list: this.areaControlForm.playList.map(item => ({
play: {
en: item.status === '启用' ? 1 : 0,
num: 1,
sou: 0,
filename: item.filename,
play_time: 1,
pause_time: 0
},
time: {
en: 1,
begin: item.playTime === '全天' ? 0 : this.convertTimeToSeconds(item.playTimeStart),
end: item.playTime === '全天' ? 86399 : this.convertTimeToSeconds(item.playTimeEnd),
week: this.convertWeekArrayToValue(item.weekdays.split(',').map(day => {
const weekMap = { '周日': '0', '周一': '1', '周二': '2', '周三': '3', '周四': '4', '周五': '5', '周六': '6' };
return weekMap[day];
}))
},
speed: {
en: item.radarEnabled ? 1 : 0,
min: item.radarEnabled ? item.radarSpeedMin : 0,
max: item.radarEnabled ? item.radarSpeedMax : 0
}
}))
}
};
//
for (const device of this.deviceList) {
const data = {
serialNumber: device.serialNumber,
productId: device.productId,
remoteCommand: {
'play_list': 'JSON=' + JSON.stringify(playListData)
},
identifier: 'play_list',
modelName: '播放列表',
isShadow: device.status != 3,
type: 1
};
await serviceInvoke(data);
}
this.$message.success('区域控制设置成功');
this.areaControlDialogVisible = false;
}
} catch (error) {
console.error('设置区域控制失败:', error);
this.$message.error('设置区域控制失败');
}
},
//
convertTimeToSeconds(time) {
if (!time) return 0;
return time.getHours() * 3600 + time.getMinutes() * 60;
},
//
convertWeekArrayToValue(weekdays) {
let value = 0;
weekdays.forEach(day => {
value |= (1 << parseInt(day));
});
return value;
},
/** 处理全天选择变化 */
handleAllDayChange(val) {
if (val) {
// 00:00 23:59
this.playlistForm.playTimeStart = new Date(2000, 0, 1, 0, 0);
this.playlistForm.playTimeEnd = new Date(2000, 0, 1, 23, 59);
}
},
/** 处理全选星期变化 */
handleAllWeekChange(val) {
if (val) {
//
this.playlistForm.weekdays = ['0', '1', '2', '3', '4', '5', '6'];
} else {
//
this.playlistForm.weekdays = [];
}
}
},
};
</script>
@ -286,8 +819,103 @@ export default {
.iot-group {
padding: 20px;
}
::v-deep .el-dialog__body {
box-sizing: border-box;
padding: 20px;
}
.settings-card {
margin-bottom: 20px;
}
.settings-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.settings-title {
font-size: 16px;
font-weight: bold;
color: #303133;
}
.default-list-card {
margin-top: 20px;
}
.default-list-header {
display: flex;
align-items: center;
justify-content: space-between;
.header-left {
.default-list-title {
font-size: 16px;
font-weight: bold;
color: #303133;
}
}
.header-right {
display: flex;
align-items: center;
}
}
.time-range {
display: flex;
flex-direction: column;
gap: 10px;
.time-header {
margin-bottom: 5px;
}
.time-pickers {
display: flex;
align-items: center;
width: 100%;
.time-separator {
margin: 0 10px;
}
}
}
.weekday-select {
display: flex;
flex-direction: column;
gap: 10px;
.el-checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
}
.speed-range {
display: flex;
align-items: center;
gap: 10px;
.speed-separator {
margin: 0 5px;
}
.speed-unit {
margin-left: 5px;
color: #909399;
}
}
::v-deep .el-slider__runway {
margin: 16px 0;
}
::v-deep .el-form-item__label {
font-weight: normal;
}
</style>