全选
@@ -365,7 +382,7 @@
@@ -530,7 +547,9 @@ export default {
radarSpeedMin: 0,
radarSpeedMax: 120,
isAllDay: false,
- isAllWeek: false
+ isAllWeek: false,
+ play_time: 1,
+ pause_time: 0
},
playlistRules: {
audioId: [
@@ -541,8 +560,6 @@ export default {
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();
}
@@ -570,8 +587,16 @@ export default {
},
trigger: 'change'
}
+ ],
+ play_time: [
+ { required: true, message: '请输入播放时长', trigger: 'blur' }
+ ],
+ pause_time: [
+ { required: true, message: '请输入停顿时长', trigger: 'blur' }
]
},
+ isEditPlaylist: false,
+ editingPlaylistIndex: null,
};
},
mounted() {
@@ -610,6 +635,7 @@ export default {
};
//设备在线状态判断
if (this.device.status !== 3 && this.device.isShadow !== 1) {
+ let title = '';
if (this.device.status === 1) {
title = this.$t('device.device-variable.930930-0');
} else if (this.device.status === 2) {
@@ -678,36 +704,36 @@ export default {
if (!this.deviceInfo.thingsModels) return;
// 更新音频开关状态
- const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_en');
+ const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playEn');
if (playEnModel) {
this.basicSettings.audioEnabled = playEnModel.shadow === '1';
}
// 更新音量设置
- const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === 'volume');
+ const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === '103#volume');
if (volumeModel) {
this.basicSettings.volume = parseInt(volumeModel.shadow) || 50;
}
// 更新音频列表
- const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
+ const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#mp3List');
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;
+ // 更新音频列表
+ const mp3List = data.sound_card?.mp3_list || data.mp3_list;
+ if (mp3List) {
+ this.audioList = mp3List.map((item) => {
+ const [idStr, name] = item.split('_');
return {
- id: index + 1,
- name: name
+ id: parseInt(idStr, 10),
+ name: name || item,
+ raw: item
};
- });
+ }).sort((a, b) => a.id - b.id); // 按id从小到大排序
}
} catch (error) {
console.error('解析音频列表失败:', error);
@@ -715,14 +741,16 @@ export default {
}
// 更新播放列表
- const playListModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_list');
+ const playListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playList');
if (playListModel && playListModel.shadow) {
try {
const jsonStr = playListModel.shadow.replace('JSON=', '');
const data = JSON.parse(jsonStr);
- if (data.sound_card && data.sound_card.play_list) {
- this.defaultList = data.sound_card.play_list.map((item, index) => {
+ // 兼容 sound_card 层和根节点
+ const playList = data.sound_card?.play_list || data.play_list;
+ if (playList) {
+ this.defaultList = playList.map((item, index) => {
// 转换时间格式
const beginTime = this.formatSecondsToTime(item.time.begin);
const endTime = this.formatSecondsToTime(item.time.end);
@@ -733,11 +761,14 @@ export default {
return {
id: index + 1,
name: item.play.filename,
- playTime: `${beginTime} - ${endTime}`,
+ playTime: (item.time.begin === 0 && item.time.end === 86400)
+ ? '全天'
+ : `${beginTime} - ${endTime}`,
weekdays: weekdays.join(', '),
radarEnabled: item.speed.en === 1,
status: item.play.en === 1 ? '启用' : '禁用',
- radarSpeed: item.speed.en === 1 ? `${item.speed.min}-${item.speed.max}km/h` : ''
+ radarSpeed: item.speed.en === 1 ? `${item.speed.min}-${item.speed.max}km/h` : '',
+ rawIndex: index // 新增
};
});
}
@@ -761,7 +792,7 @@ export default {
},
handleVolumeChange(val) {
- const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === 'volume');
+ const volumeModel = this.deviceInfo.thingsModels.find(model => model.id === '103#volume');
if (volumeModel) {
volumeModel.shadow = val.toString();
this.mqttPublish(this.deviceInfo, volumeModel);
@@ -1229,7 +1260,7 @@ export default {
},
handleAudioSwitchChange(val) {
- const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_en');
+ const playEnModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playEn');
if (playEnModel) {
playEnModel.shadow = val ? '1' : '0';
this.mqttPublish(this.deviceInfo, playEnModel);
@@ -1249,39 +1280,37 @@ export default {
};
},
- // 获取未使用的最小ID
+ // 获取未使用的最小ID(从0开始)
getNextAvailableId() {
- const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
+ const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#mp3List');
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;
+ const mp3List = data.sound_card?.mp3_list || data.mp3_list || [];
+ // 获取所有已使用的ID
+ const usedIds = mp3List.map(item => {
+ const id = parseInt(item.split('_')[0]);
+ return isNaN(id) ? 0 : id;
+ });
+ // 找到最小的未使用ID(从0开始)
+ let nextId = 1;
+ while (usedIds.includes(nextId)) {
+ nextId++;
}
+ return nextId;
} catch (error) {
console.error('解析mp3_list失败:', error);
}
}
- return 1; // 如果出错,返回1
+ return 0; // 如果出错,返回0
},
submitAudioForm() {
this.$refs.audioForm.validate((valid) => {
if (valid) {
// 找到mp3_list物模型
- const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
+ const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#mp3List');
if (mp3ListModel) {
try {
// 获取下一个可用的ID
@@ -1293,16 +1322,16 @@ export default {
// 构建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
- }
+
+ 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值
@@ -1329,32 +1358,27 @@ export default {
type: 'warning'
}).then(() => {
// 找到mp3_list物模型
- const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === 'mp3_list');
+ const mp3ListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#mp3List');
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('删除失败');
- });
+ // 用 raw 字段精确匹配,只操作根节点
+ const audioRaw = row.raw;
+ if (data.mp3_list) {
+ data.mp3_list = data.mp3_list.filter(item => item !== audioRaw);
}
+ // 更新物模型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('删除失败');
@@ -1364,6 +1388,10 @@ export default {
},
showAddPlaylistDialog() {
+ // 重置编辑状态
+ this.isEditPlaylist = false;
+ this.editingPlaylistIndex = null;
+
this.addPlaylistDialogVisible = true;
this.newPlaylist = {
name: '',
@@ -1377,7 +1405,9 @@ export default {
radarSpeedMin: 0,
radarSpeedMax: 120,
isAllDay: false,
- isAllWeek: false
+ isAllWeek: false,
+ play_time: 1,
+ pause_time: 0
};
},
@@ -1385,12 +1415,17 @@ export default {
this.$refs.playlistForm.validate((valid) => {
if (valid) {
// 找到play_list物模型
- const playListModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_list');
+ const playListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playList');
if (playListModel) {
try {
- // 解析当前JSON
- const jsonStr = playListModel.shadow.replace('JSON=', '');
- const data = JSON.parse(jsonStr);
+ // 解析当前JSON,若为空则初始化
+ let jsonStr = playListModel.shadow ? playListModel.shadow.replace('JSON=', '') : '';
+ let data = {};
+ if (jsonStr) {
+ data = JSON.parse(jsonStr);
+ } else {
+ data = { play_list: [] };
+ }
// 获取选中的音频信息
const selectedAudio = this.audioList.find(audio => audio.id === this.newPlaylist.audioId);
@@ -1399,20 +1434,20 @@ export default {
return;
}
- // 构建新的播放项
- const newPlayItem = {
+ // 构建播放项
+ const playItem = {
play: {
- en: 1,
- num: this.defaultList.length + 1,
+ en: this.newPlaylist.status === '启用' ? 1 : 0,
+ num: this.isEditPlaylist ? (this.editingPlaylistIndex + 1) : (this.defaultList.length + 1),
sou: 0,
filename: `${selectedAudio.id}_${selectedAudio.name}`,
- play_time: 1,
- pause_time: 0
+ play_time: this.newPlaylist.play_time,
+ pause_time: this.newPlaylist.pause_time
},
time: {
en: 1,
begin: this.newPlaylist.isAllDay ? 0 : this.convertTimeToSeconds(this.newPlaylist.playTimeStart),
- end: this.newPlaylist.isAllDay ? 86399 : this.convertTimeToSeconds(this.newPlaylist.playTimeEnd),
+ end: this.newPlaylist.isAllDay ? 86400 : this.convertTimeToSeconds(this.newPlaylist.playTimeEnd),
week: this.convertWeekArrayToValue(this.newPlaylist.weekdays)
},
speed: {
@@ -1422,29 +1457,41 @@ export default {
}
};
- // 添加到播放列表
- if (!data.sound_card) {
- data.sound_card = {};
+ // 直接操作根节点的play_list
+ if (!data.play_list) {
+ data.play_list = [];
}
- if (!data.sound_card.play_list) {
- data.sound_card.play_list = [];
+
+ if (this.isEditPlaylist) {
+ // 编辑模式:更新现有播放项
+ if (data.play_list[this.editingPlaylistIndex]) {
+ data.play_list[this.editingPlaylistIndex] = playItem;
+ } else {
+ this.$message.error('未找到要编辑的播放项');
+ return;
+ }
+ } else {
+ // 添加模式:添加新播放项
+ data.play_list.push(playItem);
}
- data.sound_card.play_list.push(newPlayItem);
// 更新物模型shadow值
playListModel.shadow = 'JSON=' + JSON.stringify(data);
// 发送更新
this.mqttPublish(this.deviceInfo, playListModel).then(() => {
+ const isEdit = this.isEditPlaylist;
this.addPlaylistDialogVisible = false;
- this.$message.success('添加成功');
+ this.isEditPlaylist = false;
+ this.editingPlaylistIndex = null;
+ this.$message.success(isEdit ? '编辑成功' : '添加成功');
}).catch(error => {
console.error('发送播放列表更新失败:', error);
- this.$message.error('添加失败');
+ this.$message.error(this.isEditPlaylist ? '编辑失败' : '添加失败');
});
} catch (error) {
console.error('解析或更新播放列表失败:', error);
- this.$message.error('添加失败');
+ this.$message.error(this.isEditPlaylist ? '编辑失败' : '添加失败');
}
}
}
@@ -1506,30 +1553,35 @@ export default {
},
handleStatusChange(row) {
- const playListModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_list');
+ const playListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playList');
if (playListModel) {
try {
- const jsonStr = playListModel.shadow.replace('JSON=', '');
- const data = JSON.parse(jsonStr);
+ let jsonStr = playListModel.shadow ? playListModel.shadow.replace('JSON=', '') : '';
+ let data = {};
+ if (jsonStr) {
+ data = JSON.parse(jsonStr);
+ } else {
+ data = { play_list: [] };
+ }
- if (data.sound_card && data.sound_card.play_list) {
- // 找到对应的播放项
- const playItem = data.sound_card.play_list[row.id - 1];
- if (playItem) {
- // 更新状态
- playItem.play.en = row.status === '启用' ? 1 : 0;
-
- // 更新物模型shadow值
- playListModel.shadow = 'JSON=' + JSON.stringify(data);
-
- // 发送更新
- this.mqttPublish(this.deviceInfo, playListModel).then(() => {
- this.$message.success('状态更新成功');
- }).catch(error => {
- console.error('发送状态更新失败:', error);
- this.$message.error('状态更新失败');
- });
+ // 兼容 sound_card 和根节点
+ const playListArr = data.sound_card?.play_list || data.play_list;
+ if (playListArr && playListArr[row.rawIndex]) {
+ playListArr[row.rawIndex].play.en = row.status === '启用' ? 1 : 0;
+ // 更新物模型shadow值
+ if (data.sound_card) {
+ data.sound_card.play_list = playListArr;
+ } else {
+ data.play_list = playListArr;
}
+ playListModel.shadow = 'JSON=' + JSON.stringify(data);
+ // 发送更新
+ this.mqttPublish(this.deviceInfo, playListModel).then(() => {
+ this.$message.success('状态更新成功');
+ }).catch(error => {
+ console.error('发送状态更新失败:', error);
+ this.$message.error('状态更新失败');
+ });
}
} catch (error) {
console.error('解析或更新播放列表状态失败:', error);
@@ -1538,28 +1590,119 @@ export default {
}
},
+ handleEditPlaylist(row) {
+ // 设置编辑模式
+ this.isEditPlaylist = true;
+ this.editingPlaylistIndex = row.rawIndex;
+
+ // 找到对应的播放项数据
+ const playListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playList');
+ if (playListModel && playListModel.shadow) {
+ try {
+ const jsonStr = playListModel.shadow.replace('JSON=', '');
+ const data = JSON.parse(jsonStr);
+
+ if ((data.sound_card && data.sound_card.play_list && data.sound_card.play_list[row.rawIndex]) ||
+ (data.play_list && data.play_list[row.rawIndex])) {
+ const playItem = (data.sound_card?.play_list || data.play_list)[row.rawIndex];
+
+ // 填充表单数据
+ this.newPlaylist = {
+ name: playItem.play.filename,
+ type: '用户',
+ status: playItem.play.en === 1 ? '启用' : '禁用',
+ audioId: this.getAudioIdFromFilename(playItem.play.filename),
+ playTimeStart: this.convertSecondsToTime(playItem.time.begin),
+ playTimeEnd: this.convertSecondsToTime(playItem.time.end),
+ weekdays: this.convertWeekValueToArray(playItem.time.week),
+ radarEnabled: playItem.speed.en === 1,
+ radarSpeedMin: playItem.speed.min || 0,
+ radarSpeedMax: playItem.speed.max || 120,
+ isAllDay: playItem.time.begin === 0 && playItem.time.end === 86400,
+ isAllWeek: this.isAllWeekSelected(playItem.time.week),
+ play_time: playItem.play.play_time || 1,
+ pause_time: playItem.play.pause_time || 0
+ };
+
+ this.addPlaylistDialogVisible = true;
+ }
+ } catch (error) {
+ console.error('解析播放列表数据失败:', error);
+ this.$message.error('获取播放列表数据失败');
+ }
+ }
+ },
+
+ // 从文件名获取音频ID
+ getAudioIdFromFilename(filename) {
+ if (!filename) return '';
+ const parts = filename.split('_');
+ if (parts.length >= 2) {
+ const audioId = parseInt(parts[0]);
+ return isNaN(audioId) ? '' : audioId;
+ }
+ return '';
+ },
+
+ // 将秒数转换为时间对象
+ convertSecondsToTime(seconds) {
+ if (seconds === 0) return new Date(2000, 0, 1, 0, 0);
+ if (seconds === 86400) return new Date(2000, 0, 1, 0, 0);
+
+ const hours = Math.floor(seconds / 3600);
+ const minutes = Math.floor((seconds % 3600) / 60);
+ return new Date(2000, 0, 1, hours, minutes);
+ },
+
+ // 将星期位值转换为数组
+ convertWeekValueToArray(week) {
+ const result = [];
+ for (let i = 0; i < 7; i++) {
+ if (week & (1 << i)) {
+ result.push(i.toString());
+ }
+ }
+ return result;
+ },
+
+ // 检查是否全选星期
+ isAllWeekSelected(week) {
+ return week === 127; // 127 = 1111111 (二进制)
+ },
+
handleDeletePlaylist(row) {
this.$confirm('确认删除该播放项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
- const playListModel = this.deviceInfo.thingsModels.find(model => model.id === 'play_list');
+ const playListModel = this.deviceInfo.thingsModels.find(model => model.id === '103#playList');
if (playListModel) {
try {
- const jsonStr = playListModel.shadow.replace('JSON=', '');
- const data = JSON.parse(jsonStr);
+ let jsonStr = playListModel.shadow ? playListModel.shadow.replace('JSON=', '') : '';
+ let data = {};
+ if (jsonStr) {
+ data = JSON.parse(jsonStr);
+ } else {
+ data = { play_list: [] };
+ }
- if (data.sound_card && data.sound_card.play_list) {
+ if ((data.sound_card && data.sound_card.play_list) || data.play_list) {
// 删除对应的播放项
- data.sound_card.play_list.splice(row.id - 1, 1);
+ const playListArr = data.sound_card?.play_list || data.play_list;
+ playListArr.splice(row.rawIndex, 1);
// 更新序号
- data.sound_card.play_list.forEach((item, index) => {
+ playListArr.forEach((item, index) => {
item.play.num = index + 1;
});
// 更新物模型shadow值
+ if (data.sound_card) {
+ data.sound_card.play_list = playListArr;
+ } else {
+ data.play_list = playListArr;
+ }
playListModel.shadow = 'JSON=' + JSON.stringify(data);
// 发送更新
@@ -1583,7 +1726,7 @@ export default {
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);
+ this.newPlaylist.playTimeEnd = new Date(2000, 0, 1, 0, 0);
}
},
@@ -1597,6 +1740,12 @@ export default {
this.newPlaylist.weekdays = [];
}
},
+
+ cancelPlaylistDialog() {
+ this.addPlaylistDialogVisible = false;
+ this.isEditPlaylist = false;
+ this.editingPlaylistIndex = null;
+ },
},
};
@@ -1915,4 +2064,70 @@ export default {
flex-direction: column;
gap: 10px;
}
+
+// 自定义表格滚动条样式
+.el-table {
+
+ // 设置表格容器的滚动条样式
+ &::-webkit-scrollbar {
+ width: 12px;
+ height: 12px;
+ }
+
+ &::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 6px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 6px;
+
+ &:hover {
+ background: #a8a8a8;
+ }
+ }
+
+ // 表格内部的滚动条样式
+ .el-table__body-wrapper {
+ &::-webkit-scrollbar {
+ width: 12px;
+ height: 12px;
+ }
+
+ &::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 6px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 6px;
+
+ &:hover {
+ background: #a8a8a8;
+ }
+ }
+ }
+}
+
+// 全局滚动条样式(影响所有滚动条)
+::-webkit-scrollbar {
+ width: 12px;
+ height: 12px;
+}
+
+::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 6px;
+}
+
+::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 6px;
+
+ &:hover {
+ background: #a8a8a8;
+ }
+}
\ No newline at end of file
diff --git a/src/views/iot/group/index.vue b/src/views/iot/group/index.vue
index afa41ab..b2ffc17 100644
--- a/src/views/iot/group/index.vue
+++ b/src/views/iot/group/index.vue
@@ -57,7 +57,7 @@
- 区域控制
+ 批量控制
@@ -91,13 +91,13 @@
$t('update') }}
{{
$t('add')
- }}
+ }}
{{ $t('iot.group.index.637432-19') }}