This commit is contained in:
1 2025-06-06 06:26:26 +08:00
parent d832944320
commit ddc740eab2
3 changed files with 790 additions and 22 deletions

View File

@ -622,7 +622,7 @@ export default {
this.$nextTick(function () { this.$nextTick(function () {
this.MonitorChart(); this.MonitorChart();
}); });
// console.log("", JSON.stringify(this.deviceInfo.thingsModels)); console.log("物模型", JSON.stringify(this.deviceInfo.thingsModels));
// //
if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) { if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) {
this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order); this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order);

View File

@ -515,6 +515,7 @@ export default {
this.$nextTick(function () { this.$nextTick(function () {
this.MonitorChart(); this.MonitorChart();
}); });
// console.log("", JSON.stringify(this.deviceInfo.thingsModels));
// //
if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) { if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) {
this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order); this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order);
@ -631,6 +632,7 @@ export default {
// //
this.$busEvent.$on('updateData', (params) => { this.$busEvent.$on('updateData', (params) => {
this.updateParam(params); this.updateParam(params);
// console.log("", JSON.stringify(this.deviceInfo.thingsModels));
}); });
}, },
initDataStatus() { initDataStatus() {

View File

@ -13,6 +13,9 @@
</div> </div>
<div class="mode-content"> <div class="mode-content">
<span class="title" :style="{ color: statusColor.background }">{{ title }}</span> <span class="title" :style="{ color: statusColor.background }">{{ title }}</span>
<el-button type="text" @click="printThingsModels" style="margin-left: 10px">
<i class="el-icon-printer"></i> 打印物模型
</el-button>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
@ -38,10 +41,15 @@
<div slot="header" class="settings-header"> <div slot="header" class="settings-header">
<span class="settings-title">基础设置</span> <span class="settings-title">基础设置</span>
</div> </div>
<el-form :model="basicSettings" label-width="100px"> <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-form-item label="音量设置">
<el-slider v-model="basicSettings.volume" :min="0" :max="100" :format-tooltip="formatVolume" <el-slider v-model="basicSettings.volume" :min="0" :max="100" :format-tooltip="formatVolume"
@change="handleVolumeChange" style="width: 80%"> @change="handleVolumeChange" style="width: 80%" :disabled="!basicSettings.audioEnabled">
</el-slider> </el-slider>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -51,6 +59,9 @@
<el-card class="audio-list-card" shadow="hover"> <el-card class="audio-list-card" shadow="hover">
<div slot="header" class="audio-list-header"> <div slot="header" class="audio-list-header">
<span class="audio-list-title">音频列表</span> <span class="audio-list-title">音频列表</span>
<el-button type="primary" size="mini" icon="el-icon-plus" @click="showAddAudioDialog">
添加音频
</el-button>
</div> </div>
<el-table :data="audioList" style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }" <el-table :data="audioList" style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }"
border> border>
@ -58,9 +69,11 @@
</el-table-column> </el-table-column>
<el-table-column prop="name" label="音频名称" min-width="150"> <el-table-column prop="name" label="音频名称" min-width="150">
</el-table-column> </el-table-column>
<el-table-column prop="duration" label="时长" width="120" align="center"> <el-table-column label="操作" width="120" align="center">
</el-table-column> <template slot-scope="scope">
<el-table-column prop="size" label="大小" width="120" align="center"> <el-button type="text" icon="el-icon-delete" @click="handleDeleteAudio(scope.row)">
</el-button>
</template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-card> </el-card>
@ -68,7 +81,10 @@
<!-- 默认列表 --> <!-- 默认列表 -->
<el-card class="default-list-card" shadow="hover"> <el-card class="default-list-card" shadow="hover">
<div slot="header" class="default-list-header"> <div slot="header" class="default-list-header">
<span class="default-list-title">默认列表</span> <span class="default-list-title">播放列表</span>
<el-button type="primary" size="mini" icon="el-icon-plus" @click="showAddPlaylistDialog">
添加音频
</el-button>
</div> </div>
<el-table :data="defaultList" style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }" <el-table :data="defaultList" style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }"
border> border>
@ -76,15 +92,30 @@
</el-table-column> </el-table-column>
<el-table-column prop="name" label="音频名称" min-width="150"> <el-table-column prop="name" label="音频名称" min-width="150">
</el-table-column> </el-table-column>
<el-table-column prop="type" label="类型" width="120" align="center"> <el-table-column prop="playTime" label="播放时间" width="120" align="center">
</el-table-column> </el-table-column>
<el-table-column prop="status" label="状态" width="120" align="center"> <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"> <template slot-scope="scope">
<el-tag :type="scope.row.status === '启用' ? 'success' : 'info'"> <el-tag :type="scope.row.radarEnabled ? 'success' : 'info'">
{{ scope.row.status }} {{ scope.row.radarEnabled ? '开启' : '关闭' }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </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>
</el-table> </el-table>
</el-card> </el-card>
</el-col> </el-col>
@ -219,6 +250,101 @@
<el-button @click="cancel">{{ $t('cancel') }}</el-button> <el-button @click="cancel">{{ $t('cancel') }}</el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 添加音频对话框 -->
<el-dialog title="添加音频" :visible.sync="addAudioDialogVisible" width="600px" append-to-body>
<el-form :model="newAudio" :rules="audioRules" ref="audioForm" label-width="120px">
<el-form-item label="备注" prop="remark">
<el-input v-model="newAudio.remark" placeholder="请输入备注"></el-input>
</el-form-item>
<el-form-item label="主持人声音" prop="per">
<el-select v-model="newAudio.per" placeholder="请选择主持人声音" style="width: 100%">
<el-option label="小美" :value="0"></el-option>
<el-option label="小宇" :value="1"></el-option>
<el-option label="逍遥" :value="3"></el-option>
<el-option label="丫丫" :value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="合成语速" prop="spd">
<el-slider v-model="newAudio.spd" :min="0" :max="15" :step="1" :format-tooltip="formatSpeed">
</el-slider>
</el-form-item>
<el-form-item label="合成音调" prop="pit">
<el-slider v-model="newAudio.pit" :min="0" :max="15" :step="1" :format-tooltip="formatPitch">
</el-slider>
</el-form-item>
<el-form-item label="合成音量" prop="vol">
<el-slider v-model="newAudio.vol" :min="0" :max="15" :step="1" :format-tooltip="formatVolume">
</el-slider>
</el-form-item>
<el-form-item label="合成文本" prop="tex_utf8">
<el-input type="textarea" :rows="4" v-model="newAudio.tex_utf8" placeholder="请输入需要合成的文本">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="addAudioDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAudioForm"> </el-button>
</div>
</el-dialog>
<!-- 添加播放列表对话框 -->
<el-dialog title="添加播放列表" :visible.sync="addPlaylistDialogVisible" width="600px" append-to-body>
<el-form :model="newPlaylist" :rules="playlistRules" ref="playlistForm" label-width="120px">
<el-form-item label="音频选择" prop="audioId">
<el-select v-model="newPlaylist.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">
<el-time-picker v-model="newPlaylist.playTimeStart" format="HH:mm" placeholder="开始时间"
style="width: 45%">
</el-time-picker>
<span class="time-separator"></span>
<el-time-picker v-model="newPlaylist.playTimeEnd" format="HH:mm" placeholder="结束时间"
style="width: 45%">
</el-time-picker>
</div>
</el-form-item>
<el-form-item label="星期重复" prop="weekdays">
<el-checkbox-group v-model="newPlaylist.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>
</el-form-item>
<el-form-item label="雷达开关" prop="radarEnabled">
<el-switch v-model="newPlaylist.radarEnabled" active-color="#13ce66" inactive-color="#ff4949">
</el-switch>
</el-form-item>
<el-collapse-transition>
<div v-show="newPlaylist.radarEnabled" class="radar-settings">
<el-form-item label="速度范围" prop="radarSpeed">
<div class="speed-range">
<el-input-number v-model="newPlaylist.radarSpeedMin" :min="0"
:max="newPlaylist.radarSpeedMax" :step="1" placeholder="最小速度">
</el-input-number>
<span class="speed-separator">-</span>
<el-input-number v-model="newPlaylist.radarSpeedMax" :min="newPlaylist.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> </div>
</template> </template>
@ -244,6 +370,8 @@ export default {
this.$nextTick(function () { this.$nextTick(function () {
this.MonitorChart(); this.MonitorChart();
}); });
console.log("物模型", JSON.stringify(this.deviceInfo.thingsModels));
if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) { if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) {
this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order); this.deviceInfo.thingsModels = this.device.thingsModels.sort((a, b) => b.order - a.order);
} }
@ -318,17 +446,39 @@ export default {
}, },
// //
basicSettings: { basicSettings: {
volume: 50 volume: 50,
audioEnabled: true
}, },
audioList: [ audioList: [
{ id: 1, name: '音频1', duration: '00:30', size: '2.5MB' }, { id: 1, name: '音频1' },
{ id: 2, name: '音频2', duration: '01:15', size: '3.8MB' }, { id: 2, name: '音频2' },
{ id: 3, name: '音频3', duration: '00:45', size: '2.1MB' } { id: 3, name: '音频3' }
], ],
defaultList: [ defaultList: [
{ id: 1, name: '默认音频1', type: '系统', status: '启用' }, {
{ id: 2, name: '默认音频2', type: '用户', status: '启用' }, id: 1,
{ id: 3, name: '默认音频3', type: '系统', status: '禁用' } name: '默认音频1',
playTime: '08:00',
weekdays: '周一, 周三, 周五',
radarEnabled: true,
status: '启用'
},
{
id: 2,
name: '默认音频2',
playTime: '12:30',
weekdays: '周二, 周四',
radarEnabled: false,
status: '启用'
},
{
id: 3,
name: '默认音频3',
playTime: '18:00',
weekdays: '周六, 周日',
radarEnabled: true,
status: '禁用'
}
], ],
// //
isRecording: false, isRecording: false,
@ -340,6 +490,91 @@ export default {
recordings: [], recordings: [],
timer: null, timer: null,
audioUrl: null, audioUrl: null,
//
addAudioDialogVisible: false,
newAudio: {
remark: '',
per: 0,
spd: 5,
pit: 5,
vol: 5,
tex_utf8: '',
filename: ''
},
audioRules: {
remark: [
{ required: true, message: '请输入备注', trigger: 'blur' }
],
per: [
{ required: true, message: '请选择主持人声音', trigger: 'change' }
],
spd: [
{ required: true, message: '请设置合成语速', trigger: 'change' }
],
pit: [
{ required: true, message: '请设置合成音调', trigger: 'change' }
],
vol: [
{ required: true, message: '请设置合成音量', trigger: 'change' }
],
tex_utf8: [
{ required: true, message: '请输入合成文本', trigger: 'blur' }
]
},
//
addPlaylistDialogVisible: false,
newPlaylist: {
name: '',
type: '用户',
status: '启用',
audioId: '',
playTimeStart: null,
playTimeEnd: null,
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120
},
playlistRules: {
audioId: [
{ required: true, message: '请选择音频', trigger: 'change' }
],
playTime: [
{
validator: (rule, value, callback) => {
if (!this.newPlaylist.playTimeStart || !this.newPlaylist.playTimeEnd) {
callback(new Error('请选择播放时间段'));
} else if (this.newPlaylist.playTimeStart >= this.newPlaylist.playTimeEnd) {
callback(new Error('开始时间必须小于结束时间'));
} else {
callback();
}
},
trigger: 'change'
}
],
weekdays: [
{ required: true, message: '请选择重复日期', trigger: 'change' }
],
radarSpeed: [
{
validator: (rule, value, callback) => {
if (this.newPlaylist.radarEnabled) {
if (!this.newPlaylist.radarSpeedMin || !this.newPlaylist.radarSpeedMax) {
callback(new Error('请设置速度范围'));
} else if (this.newPlaylist.radarSpeedMin >= this.newPlaylist.radarSpeedMax) {
callback(new Error('最小速度必须小于最大速度'));
} else {
callback();
}
} else {
callback();
}
},
trigger: 'change'
}
]
},
}; };
}, },
mounted() { mounted() {
@ -351,6 +586,71 @@ export default {
}, },
methods: { methods: {
//
async mqttPublish(device, model) {
const command = {};
command[model.id] = model.shadow;
const params = {
deviceId: device.deviceId,
modelId: model.modelId,
};
const response = await getOrderControl(params);
if (response.code != 200) {
this.$message({
type: 'warning',
message: response.msg,
});
return;
}
const data = {
serialNumber: device.serialNumber,
productId: device.productId,
remoteCommand: command,
identifier: model.id,
modelName: model.name,
isShadow: device.status != 3,
type: model.type,
};
//线
if (this.device.status !== 3 && this.device.isShadow !== 1) {
if (this.device.status === 1) {
title = this.$t('device.device-variable.930930-0');
} else if (this.device.status === 2) {
title = this.$t('device.device-variable.930930-1');
} else {
title = this.$t('device.device-variable.930930-2');
}
this.$message({
type: 'warning',
message: title,
});
return;
}
if ((this.deviceInfo.protocolCode === 'MODBUS-TCP' || this.deviceInfo.protocolCode === 'MODBUS-RTU') && this.device.status === 3) {
await serviceInvokeReply(data).then((response) => {
if (response.code === 200) {
this.$message({
type: 'success',
message: this.$t('device.running-status.866086-25'),
});
} else {
this.$message.error(response.msg);
}
});
} else {
await serviceInvoke(data).then((response) => {
if (response.code === 200) {
this.$message({
type: 'success',
message: this.$t('device.running-status.866086-25'),
});
} else {
this.$message.error(response.msg);
}
});
}
},
// //
handleDeviceChange(device) { handleDeviceChange(device) {
if (device && device.deviceId != 0) { if (device && device.deviceId != 0) {
@ -367,6 +667,8 @@ export default {
}); });
if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) { if (this.deviceInfo.thingsModels && this.deviceInfo.thingsModels.length > 0) {
this.deviceInfo.thingsModels = this.deviceInfo.thingsModels.sort((a, b) => b.order - a.order); this.deviceInfo.thingsModels = this.deviceInfo.thingsModels.sort((a, b) => b.order - a.order);
this.updateBasicSettings(); //
this.printThingsModels();
} }
if (this.deviceInfo.chartList && this.deviceInfo.chartList.length > 0) { if (this.deviceInfo.chartList && this.deviceInfo.chartList.length > 0) {
this.deviceInfo.chartList = this.deviceInfo.chartList.sort((a, b) => b.order - a.order); this.deviceInfo.chartList = this.deviceInfo.chartList.sort((a, b) => b.order - a.order);
@ -374,15 +676,67 @@ export default {
} }
}, },
//
updateBasicSettings() {
if (!this.deviceInfo.thingsModels) return;
//
const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_en');
if (playEnModel) {
this.basicSettings.audioEnabled = playEnModel.shadow === '1';
}
//
const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === 'volume');
if (volumeModel) {
this.basicSettings.volume = parseInt(volumeModel.shadow) || 50;
}
//
const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
if (mp3ListModel && mp3ListModel.shadow) {
try {
// JSON
const jsonStr = mp3ListModel.shadow.replace('JSON=', '');
const data = JSON.parse(jsonStr);
// mp3_list
if (data.sound_card && data.sound_card.mp3_list) {
//
this.audioList = data.sound_card.mp3_list.map((item, index) => {
// "1_def"
const name = item.split('_')[1] || item;
return {
id: index + 1,
name: name
};
});
}
} catch (error) {
console.error('解析音频列表失败:', error);
}
}
},
printThingsModels() {
console.log('当前物模型数据:', JSON.stringify(this.deviceInfo.thingsModels, null, 2));
this.$message({
message: '物模型数据已打印到控制台',
type: 'success'
});
},
// //
formatVolume(val) { formatVolume(val) {
return val + '%'; return val + '%';
}, },
handleVolumeChange(val) { handleVolumeChange(val) {
// const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === 'volume');
console.log('音量变化:', val); if (volumeModel) {
// TODO: API volumeModel.shadow = val.toString();
this.mqttPublish(this.deviceInfo, volumeModel);
}
}, },
// //
@ -392,6 +746,157 @@ export default {
}); });
}, },
//
// updateParam(params) {
// console.log(1111111111)
// if (!params || !this.deviceInfo.thingsModels) return;
// const { serialNumber, productId, data } = params;
// if (data && this.deviceInfo.serialNumber === serialNumber) {
// //
// this.deviceInfo.thingsModels.forEach(model => {
// if (data[model.id] !== undefined) {
// model.shadow = data[model.id];
// }
// });
// //
// this.updateBasicSettings();
// }
// },
//
updateParam(params) {
let { serialNumber, productId, data } = params;
let isComplete = false;
data = data.message;
if (data) {
for (let j = 0; j < data.length; j++) {
for (let k = 0; k < this.deviceInfo.thingsModels.length && !isComplete; k++) {
if (this.deviceInfo.thingsModels[k].id == data[j].id) {
const variable = this.deviceInfo.thingsModels[k];
// (////)
if (this.deviceInfo.thingsModels[k].datatype.type == 'decimal' || this.deviceInfo.thingsModels[k].datatype.type == 'integer') {
variable.shadow = Number(data[j].value);
} else {
variable.shadow = data[j].value;
}
}
if (this.deviceInfo.thingsModels[k].datatype.type == 'object') {
//
for (let n = 0; n < this.deviceInfo.thingsModels[k].datatype.params.length; n++) {
if (this.deviceInfo.thingsModels[k].datatype.params[n].id == data[j].id) {
this.deviceInfo.thingsModels[k].datatype.params[n].shadow = data[j].value;
isComplete = true;
break;
}
}
} else if (this.deviceInfo.thingsModels[k].datatype.type == 'array') {
//
if (this.deviceInfo.thingsModels[k].datatype.arrayType == 'object') {
// 1.,id,array_01_gateway_temperature
if (String(data[j].id).indexOf('array_') == 0) {
for (let n = 0; n < this.deviceInfo.thingsModels[k].datatype.arrayParams.length; n++) {
for (let m = 0; m < this.deviceInfo.thingsModels[k].datatype.arrayParams[n].length; m++) {
if (this.deviceInfo.thingsModels[k].datatype.arrayParams[n][m].id == data[j].id) {
this.deviceInfo.thingsModels[k].datatype.arrayParams[n][m].shadow = data[j].value;
isComplete = true;
break;
}
}
if (isComplete) {
break;
}
}
} else {
// 2.gateway_temperature,ID
for (let n = 0; n < this.deviceInfo.thingsModels[k].datatype.arrayParams.length; n++) {
for (let m = 0; m < this.deviceInfo.thingsModels[k].datatype.arrayParams[n].length; m++) {
let index = n > 9 ? String(n) : '0' + k;
let prefix = 'array_' + index + '_';
if (this.deviceInfo.thingsModels[k].datatype.arrayParams[n][m].id == prefix + data[j].id) {
this.deviceInfo.thingsModels[k].datatype.arrayParams[n][m].shadow = data[j].value;
}
}
}
}
} else {
//
for (let n = 0; n < this.deviceInfo.thingsModels[k].datatype.arrayModel.length; n++) {
if (this.deviceInfo.thingsModels[k].datatype.arrayModel[n].id == data[j].id) {
this.deviceInfo.thingsModels[k].datatype.arrayModel[n].shadow = data[j].value;
break;
}
}
}
}
}
//
for (let k = 0; k < this.deviceInfo.chartList.length; k++) {
if (this.deviceInfo.chartList[k].id.indexOf('array_') == 0) {
// ,array_00_gateway_temperature
if (this.deviceInfo.chartList[k].id == data[j].id) {
this.deviceInfo.chartList[k].shadow = data[j].value;
//
for (let m = 0; m < this.monitorChart.length; m++) {
if (data[j].id == this.monitorChart[m].data.id) {
let data = [
{
value: this.deviceInfo.chartList[k].shadow,
name: this.monitorChart[m].data.name,
},
];
this.monitorChart[m].chart.setOption({
series: [
{
data: data,
},
],
});
break;
}
}
}
} else {
//
if (this.deviceInfo.chartList[k].id == data[j].id) {
this.deviceInfo.chartList[k].shadow = data[j].value;
//
for (let m = 0; m < this.monitorChart.length; m++) {
if (data[j].id == this.monitorChart[m].data.id) {
let data = [
{
value: this.deviceInfo.chartList[k].shadow,
name: this.monitorChart[m].data.name,
},
];
this.monitorChart[m].chart.setOption({
series: [
{
data: data,
},
],
});
break;
}
}
}
}
if (isComplete) {
break;
}
}
}
}
this.updateBasicSettings();
},
initDataStatus() { initDataStatus() {
this.$busEvent.$on('updateStatus', (status) => { this.$busEvent.$on('updateStatus', (status) => {
this.updateStatus(status); this.updateStatus(status);
@ -637,7 +1142,230 @@ export default {
deleteRecording(index) { deleteRecording(index) {
this.recordings.splice(index, 1); this.recordings.splice(index, 1);
} },
handleAudioSwitchChange(val) {
const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_en');
if (playEnModel) {
playEnModel.shadow = val ? '1' : '0';
this.mqttPublish(this.deviceInfo, playEnModel);
}
},
showAddAudioDialog() {
this.addAudioDialogVisible = true;
this.newAudio = {
remark: '',
per: 0,
spd: 5,
pit: 5,
vol: 5,
tex_utf8: '',
filename: ''
};
},
// 使ID
getNextAvailableId() {
const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
if (mp3ListModel) {
try {
const jsonStr = mp3ListModel.shadow.replace('JSON=', '');
const data = JSON.parse(jsonStr);
if (data.sound_card && data.sound_card.mp3_list) {
// 使ID
const usedIds = data.sound_card.mp3_list.map(item => {
const id = parseInt(item.split('_')[0]);
return isNaN(id) ? 0 : id;
});
// 使ID
let nextId = 1;
while (usedIds.includes(nextId)) {
nextId++;
}
return nextId;
}
} catch (error) {
console.error('解析mp3_list失败:', error);
}
}
return 1; // 1
},
submitAudioForm() {
this.$refs.audioForm.validate((valid) => {
if (valid) {
// mp3_list
const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
if (mp3ListModel) {
try {
// ID
const nextId = this.getNextAvailableId();
//
const filename = `${nextId}_${this.newAudio.remark}`;
// TTS
const ttsData = {
JSON_id: 1,
sound_card: {
TTS: {
per: this.newAudio.per,
spd: this.newAudio.spd,
pit: this.newAudio.pit,
vol: this.newAudio.vol,
tex_utf8: this.newAudio.tex_utf8,
filename: filename
}
}
};
// shadow
mp3ListModel.shadow = 'JSON=' + JSON.stringify(ttsData);
//
this.mqttPublish(this.deviceInfo, mp3ListModel);
this.addAudioDialogVisible = false;
this.$message.success('添加成功');
} catch (error) {
console.error('添加音频失败:', error);
this.$message.error('添加失败');
}
}
}
});
},
handleDeleteAudio(row) {
this.$confirm('确认删除该音频吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// mp3_list
const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
if (mp3ListModel) {
try {
// JSON
const jsonStr = mp3ListModel.shadow.replace('JSON=', '');
const data = JSON.parse(jsonStr);
// ID
const audioId = row.name;
// mp3_list
if (data.sound_card && data.sound_card.mp3_list) {
data.sound_card.mp3_list = data.sound_card.mp3_list.filter(item => !item.endsWith(audioId));
// shadow
const newShadow = 'JSON=' + JSON.stringify(data);
mp3ListModel.shadow = newShadow;
//
this.mqttPublish(this.deviceInfo, mp3ListModel).then(() => {
this.$message.success('删除成功');
}).catch(error => {
console.error('发送删除命令失败:', error);
this.$message.error('删除失败');
});
}
} catch (error) {
console.error('解析或更新mp3_list失败:', error);
this.$message.error('删除失败');
}
}
}).catch(() => { });
},
showAddPlaylistDialog() {
this.addPlaylistDialogVisible = true;
this.newPlaylist = {
name: '',
type: '用户',
status: '启用',
audioId: '',
playTimeStart: null,
playTimeEnd: null,
weekdays: [],
radarEnabled: false,
radarSpeedMin: 0,
radarSpeedMax: 120
};
},
submitPlaylistForm() {
this.$refs.playlistForm.validate((valid) => {
if (valid) {
const selectedAudio = this.audioList.find(audio => audio.id === this.newPlaylist.audioId);
this.defaultList.push({
id: this.defaultList.length + 1,
name: selectedAudio ? selectedAudio.name : '',
type: this.newPlaylist.type,
status: this.newPlaylist.status,
playTime: `${this.formatTime(this.newPlaylist.playTimeStart)} - ${this.formatTime(this.newPlaylist.playTimeEnd)}`,
weekdays: this.formatWeekdays(this.newPlaylist.weekdays),
radarEnabled: this.newPlaylist.radarEnabled,
radarSpeed: this.newPlaylist.radarEnabled ?
`${this.newPlaylist.radarSpeedMin}-${this.newPlaylist.radarSpeedMax}km/h` : ''
});
this.addPlaylistDialogVisible = false;
this.$message.success('添加成功');
}
});
},
formatTime(time) {
if (!time) return '';
const hours = time.getHours().toString().padStart(2, '0');
const minutes = time.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
},
formatWeekdays(weekdays) {
const weekMap = {
'0': '周日',
'1': '周一',
'2': '周二',
'3': '周三',
'4': '周四',
'5': '周五',
'6': '周六'
};
return weekdays.map(day => weekMap[day]).join(', ');
},
handleStatusChange(row) {
// TODO: API
console.log('状态变更:', row);
},
handleDeletePlaylist(row) {
this.$confirm('确认删除该音频吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const index = this.defaultList.findIndex(item => item.id === row.id);
if (index > -1) {
this.defaultList.splice(index, 1);
}
this.$message.success('删除成功');
}).catch(() => { });
},
formatSpeed(val) {
return val;
},
formatPitch(val) {
return val;
},
formatVolume(val) {
return val;
},
}, },
}; };
</script> </script>
@ -903,4 +1631,42 @@ export default {
box-shadow: 0 0 0 0 rgba(245, 108, 108, 0); box-shadow: 0 0 0 0 rgba(245, 108, 108, 0);
} }
} }
.radar-settings {
margin-top: -20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 4px;
.speed-range {
display: flex;
align-items: center;
gap: 10px;
.el-input-number {
width: 120px;
}
.speed-separator {
color: #606266;
font-size: 16px;
}
.speed-unit {
color: #606266;
margin-left: 5px;
}
}
}
.time-range {
display: flex;
align-items: center;
gap: 10px;
.time-separator {
color: #606266;
font-size: 14px;
}
}
</style> </style>