diff --git a/CloudServer/public/cablemanager.html b/CloudServer/public/cablemanager.html
index 4bfd57d..a6e2f82 100644
--- a/CloudServer/public/cablemanager.html
+++ b/CloudServer/public/cablemanager.html
@@ -1519,16 +1519,65 @@
async function reloadAll(options) {
const silent = !!(options && options.silent);
try {
+ const prevGroups = audioCableGroups.slice();
+ const prevStations = stations.slice();
await Promise.all([loadGroups(), loadStations()]);
- renderGroupList();
- renderQuickSelects();
+ const groupListChanged = JSON.stringify(prevGroups.map(g => ({ id: g.id, name: g.name, color: g.color, description: g.description })))
+ !== JSON.stringify(audioCableGroups.map(g => ({ id: g.id, name: g.name, color: g.color, description: g.description })));
+ const stationListChanged = prevStations.length !== stations.length
+ || prevStations.some((s, i) => stations[i] && (s.name !== stations[i].name || s.code !== stations[i].code));
+ if (groupListChanged || stationListChanged) {
+ renderGroupList();
+ renderQuickSelects();
+ }
if (currentGroupId) {
const g = audioCableGroups.find(g => g.id === currentGroupId);
- if (g) {
- detailTempMembers = [...(g.stationNames || [])];
- selectedAvailable.clear();
- selectedMembers.clear();
- renderDualLists();
+ if (!g) {
+ currentGroupId = null;
+ backToList();
+ } else {
+ const pg = prevGroups.find(x => x.id === currentGroupId) || null;
+ const membersChanged = !pg || JSON.stringify(pg.stationNames || []) !== JSON.stringify(g.stationNames || []);
+ const metaChanged = !pg || pg.name !== g.name || pg.color !== g.color || pg.description !== g.description;
+
+ if (silent) {
+ // 被动自动刷新:同步名字/描述/颜色的标题区,只在后台成员真的变了才同步成员(否则保留用户未保存的编辑)
+ const detailNameEl = document.getElementById('detail-name');
+ const detailDescEl = document.getElementById('detail-description');
+ const detailTitleEl = document.getElementById('detail-title');
+ if (metaChanged) {
+ if (detailTitleEl && detailNameEl && !detailNameEl.matches(':focus')) {
+ detailNameEl.value = g.name || '';
+ detailTitleEl.textContent = g.name || '';
+ }
+ if (detailDescEl && !detailDescEl.matches(':focus')) {
+ detailDescEl.value = g.description || '';
+ }
+ if (detailSelectedColor !== (g.color || PRESET_COLORS[0])) {
+ detailSelectedColor = g.color || PRESET_COLORS[0];
+ document.getElementById('detail-color').style.background = detailSelectedColor;
+ _rebuildDetailColorPicker();
+ }
+ }
+ if (membersChanged) {
+ // 后台分组成员已经变了(例如被别的端删除/改了分组)—— 同步掉成员,避免用户编辑的是已经不存在的状态
+ detailTempMembers = [...(g.stationNames || [])];
+ // 清理选择集中已经不存在的名字,保留仍然存在的
+ for (const n of Array.from(selectedAvailable)) {
+ if (!stations.some(s => s.name === n)) selectedAvailable.delete(n);
+ }
+ for (const n of Array.from(selectedMembers)) {
+ if (!detailTempMembers.includes(n)) selectedMembers.delete(n);
+ }
+ }
+ if (membersChanged || stationListChanged || metaChanged) renderDualLists();
+ } else {
+ // 用户主动点刷新:全同步(包括成员)
+ detailTempMembers = [...(g.stationNames || [])];
+ selectedAvailable.clear();
+ selectedMembers.clear();
+ renderDualLists();
+ }
}
}
if (!silent) showToast('成功', '数据已刷新', 'success');
diff --git a/station_broadcast.lua b/station_broadcast.lua
index 2ee9164..83a1a6f 100644
--- a/station_broadcast.lua
+++ b/station_broadcast.lua
@@ -1,6 +1,6 @@
-- 1. Configuration & Constants
-local APP_VERSION_TEXT = "v1.0.110"
+local APP_VERSION_TEXT = "v1.0.111"
local CONFIG = {
CLOUD_URL = "ws://stabadmin.fse-media.group",