Skip to content

Commit 5224f66

Browse files
author
Sunser
committed
Refine web controls and region labels
1 parent ee92d14 commit 5224f66

5 files changed

Lines changed: 148 additions & 23 deletions

File tree

internal/monitor/service.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func (s *Service) refreshInstance(ctx context.Context, client *aliyun.Client, cf
265265
InstanceID: instance.InstanceID,
266266
InstanceName: instance.InstanceName,
267267
RegionID: instance.RegionID,
268-
RegionName: instance.RegionName,
268+
RegionName: regionDisplayName(instance.RegionID),
269269
Status: instance.Status,
270270
Spot: instance.IsSpot(),
271271
InstanceType: instance.InstanceType,
@@ -711,17 +711,37 @@ func trafficRegions(traffic aliyun.TrafficResult) []TrafficRegionSnapshot {
711711

712712
func regionDisplayName(regionID string) string {
713713
names := map[string]string{
714+
"cn-qingdao": "华北1(青岛)",
715+
"cn-beijing": "华北2(北京)",
716+
"cn-zhangjiakou": "华北3(张家口)",
717+
"cn-huhehaote": "华北5(呼和浩特)",
718+
"cn-wulanchabu": "华北6(乌兰察布)",
714719
"cn-hangzhou": "华东1(杭州)",
715720
"cn-shanghai": "华东2(上海)",
716-
"cn-beijing": "华北2(北京)",
721+
"cn-nanjing": "华东5(南京)",
722+
"cn-fuzhou": "华东6(福州)",
723+
"cn-wuhan-lr": "华中1(武汉)",
717724
"cn-shenzhen": "华南1(深圳)",
725+
"cn-heyuan": "华南2(河源)",
726+
"cn-guangzhou": "华南3(广州)",
727+
"cn-chengdu": "西南1(成都)",
728+
"cn-zhongwei": "西北2(中卫)",
718729
"cn-hongkong": "中国香港",
719730
"ap-southeast-1": "新加坡",
720-
"ap-northeast-1": "日本",
721-
"ap-southeast-5": "印尼",
722-
"us-west-1": "美国西部",
723-
"us-east-1": "美国东部",
724-
"eu-central-1": "德国",
731+
"ap-southeast-3": "马来西亚(吉隆坡)",
732+
"ap-southeast-5": "印度尼西亚(雅加达)",
733+
"ap-southeast-6": "菲律宾(马尼拉)",
734+
"ap-southeast-7": "泰国(曼谷)",
735+
"ap-northeast-1": "日本(东京)",
736+
"ap-northeast-2": "韩国(首尔)",
737+
"us-west-1": "美国(硅谷)",
738+
"us-east-1": "美国(弗吉尼亚)",
739+
"eu-central-1": "德国(法兰克福)",
740+
"eu-west-1": "英国(伦敦)",
741+
"eu-west-2": "法国(巴黎)",
742+
"me-east-1": "阿联酋(迪拜)",
743+
"me-central-1": "沙特(利雅得)",
744+
"na-south-1": "墨西哥",
725745
}
726746
if name := names[regionID]; name != "" {
727747
return name

internal/monitor/service_test.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func TestTrafficRegionsPreserveCDTRegionUsage(t *testing.T) {
4343
if regions[0].RegionID != "ap-southeast-1" || regions[0].Name != "新加坡" || regions[0].TrafficGB != 50 {
4444
t.Fatalf("first region = %#v, want Singapore 50GB", regions[0])
4545
}
46-
if regions[1].RegionID != "ap-northeast-1" || regions[1].Name != "日本" || regions[1].TrafficGB != 20 {
47-
t.Fatalf("second region = %#v, want Japan 20GB", regions[1])
46+
if regions[1].RegionID != "ap-northeast-1" || regions[1].Name != "日本(东京)" || regions[1].TrafficGB != 20 {
47+
t.Fatalf("second region = %#v, want 日本(东京) 20GB", regions[1])
4848
}
4949
}
5050

@@ -54,6 +54,48 @@ func TestRegionDisplayNameIncludesMainlandCity(t *testing.T) {
5454
}
5555
}
5656

57+
func TestRegionDisplayNamesFollowAliyunRegionTable(t *testing.T) {
58+
cases := map[string]string{
59+
"cn-qingdao": "华北1(青岛)",
60+
"cn-beijing": "华北2(北京)",
61+
"cn-zhangjiakou": "华北3(张家口)",
62+
"cn-huhehaote": "华北5(呼和浩特)",
63+
"cn-wulanchabu": "华北6(乌兰察布)",
64+
"cn-hangzhou": "华东1(杭州)",
65+
"cn-shanghai": "华东2(上海)",
66+
"cn-nanjing": "华东5(南京)",
67+
"cn-fuzhou": "华东6(福州)",
68+
"cn-wuhan-lr": "华中1(武汉)",
69+
"cn-shenzhen": "华南1(深圳)",
70+
"cn-heyuan": "华南2(河源)",
71+
"cn-guangzhou": "华南3(广州)",
72+
"cn-chengdu": "西南1(成都)",
73+
"cn-zhongwei": "西北2(中卫)",
74+
"cn-hongkong": "中国香港",
75+
"ap-southeast-1": "新加坡",
76+
"ap-southeast-3": "马来西亚(吉隆坡)",
77+
"ap-southeast-5": "印度尼西亚(雅加达)",
78+
"ap-southeast-6": "菲律宾(马尼拉)",
79+
"ap-southeast-7": "泰国(曼谷)",
80+
"ap-northeast-1": "日本(东京)",
81+
"ap-northeast-2": "韩国(首尔)",
82+
"us-west-1": "美国(硅谷)",
83+
"us-east-1": "美国(弗吉尼亚)",
84+
"eu-central-1": "德国(法兰克福)",
85+
"eu-west-1": "英国(伦敦)",
86+
"eu-west-2": "法国(巴黎)",
87+
"me-east-1": "阿联酋(迪拜)",
88+
"me-central-1": "沙特(利雅得)",
89+
"na-south-1": "墨西哥",
90+
}
91+
92+
for regionID, want := range cases {
93+
if got := regionDisplayName(regionID); got != want {
94+
t.Fatalf("regionDisplayName(%s) = %q, want %q", regionID, got, want)
95+
}
96+
}
97+
}
98+
5799
func TestRegionTrafficSelectsInstanceRegionQuotaPool(t *testing.T) {
58100
traffic := aliyun.TrafficResult{Source: "cdt", MainlandGB: 18, OverseasGB: 40}
59101

web/assets/app.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ document.getElementById('stopMode').onchange = renderOptionHelp;
3333
document.getElementById('notificationEnabled').onchange = renderOptionHelp;
3434
document.getElementById('manualRequiredNotifyInterval').onchange = renderOptionHelp;
3535
document.getElementById('trafficExceededNotifyInterval').onchange = renderOptionHelp;
36+
document.addEventListener('click', function() { closeStopMenus(); });
3637
document.querySelectorAll('.tab').forEach(function(button) {
3738
button.onclick = function() { switchTab(button.dataset.tab); };
3839
});
@@ -167,7 +168,7 @@ function renderInstanceRows(rows) {
167168
const tr = document.createElement('tr');
168169
tr.appendChild(cell(accountText(row)));
169170
tr.appendChild(cell(instanceText(row)));
170-
tr.appendChild(cell(esc(row.region_id || '-')));
171+
tr.appendChild(cell(regionText(row)));
171172
tr.appendChild(cell(statusBadge(row.status)));
172173
tr.appendChild(cell(ipText(row)));
173174
tr.appendChild(cell(instanceTrafficText(row)));
@@ -263,18 +264,38 @@ function actionCell(row) {
263264
start.onclick = function() { action(row, 'start'); };
264265
const stop = document.createElement('button');
265266
stop.className = 'danger';
266-
stop.textContent = '关机';
267-
const stopPauseMode = document.createElement('select');
268-
stopPauseMode.className = 'action-select';
269-
stopPauseMode.innerHTML = '<option value="pause">保持暂停</option><option value="pause_until_next_month">下月恢复保活</option>';
270-
stop.onclick = function() { action(row, 'stop', {pause_mode: stopPauseMode.value}); };
267+
stop.textContent = '关机 ▾';
268+
const stopWrap = document.createElement('div');
269+
stopWrap.className = 'stop-menu-wrap';
270+
const stopMenu = document.createElement('div');
271+
stopMenu.className = 'stop-menu hidden';
272+
stopMenu.innerHTML = '<button type="button" data-pause-mode="pause">关机,保持暂停</button><button type="button" data-pause-mode="pause_until_next_month">关机,下月恢复保活</button>';
273+
stop.onclick = function(event) {
274+
event.stopPropagation();
275+
closeStopMenus(stopMenu);
276+
stopMenu.classList.toggle('hidden');
277+
};
278+
stopMenu.onclick = function(event) {
279+
event.stopPropagation();
280+
const button = event.target.closest('button[data-pause-mode]');
281+
if (!button) return;
282+
stopMenu.classList.add('hidden');
283+
action(row, 'stop', {pause_mode: button.dataset.pauseMode});
284+
};
285+
stopWrap.appendChild(stop);
286+
stopWrap.appendChild(stopMenu);
271287
box.appendChild(start);
272-
box.appendChild(stopPauseMode);
273-
box.appendChild(stop);
288+
box.appendChild(stopWrap);
274289
td.appendChild(box);
275290
return td;
276291
}
277292

293+
function closeStopMenus(except) {
294+
document.querySelectorAll('.stop-menu').forEach(function(menu) {
295+
if (menu !== except) menu.classList.add('hidden');
296+
});
297+
}
298+
278299
function renderLogs(logs) {
279300
const box = document.getElementById('logRows');
280301
clear(box);
@@ -328,6 +349,13 @@ function instanceText(row) {
328349
return '<div class="row-title"><strong>' + esc(row.instance_name || row.instance_id || '-') + '</strong><span class="muted mono">' + esc(row.instance_id || '-') + '</span></div>';
329350
}
330351

352+
function regionText(row) {
353+
const name = row.region_name || row.region_id || '-';
354+
const id = row.region_id || '';
355+
if (!id || name === id) return '<span class="mono">' + esc(name) + '</span>';
356+
return '<div class="row-title"><strong>' + esc(name) + '</strong><span class="muted mono">' + esc(id) + '</span></div>';
357+
}
358+
331359
function ipText(row) {
332360
const parts = [];
333361
if (row.public_ip) parts.push({label: 'IPv4', value: row.public_ip});

web/assets/styles.css

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,31 @@ main { padding: 18px 22px 30px; }
9999
min-height: 34px;
100100
padding-right: 28px;
101101
}
102-
.action-select {
103-
width: auto;
104-
min-width: 118px;
105-
padding-right: 28px;
102+
.stop-menu-wrap {
103+
position: relative;
104+
display: inline-flex;
105+
}
106+
.stop-menu {
107+
position: absolute;
108+
top: calc(100% + 6px);
109+
right: 0;
110+
z-index: 30;
111+
width: 172px;
112+
padding: 6px;
113+
border: 1px solid var(--line);
114+
border-radius: 8px;
115+
background: #fff;
116+
box-shadow: 0 12px 28px rgba(16, 24, 40, .14);
117+
}
118+
.stop-menu button {
119+
width: 100%;
120+
justify-content: flex-start;
121+
border: 0;
122+
background: transparent;
123+
text-align: left;
124+
color: var(--text);
106125
}
126+
.stop-menu button:hover { background: #f5f7fb; }
107127
.button-row { margin-top: 14px; }
108128
.actions { flex-wrap: wrap; min-width: 160px; }
109129
.tabs {
@@ -340,6 +360,21 @@ tbody tr:hover { background: #fbfdff; }
340360
gap: 12px;
341361
padding: 14px;
342362
}
363+
.notify-form-grid {
364+
grid-template-columns: repeat(3, minmax(118px, 180px));
365+
align-items: end;
366+
}
367+
.notify-form-grid .wide-field {
368+
grid-column: 1 / -1;
369+
}
370+
.notify-form-grid input,
371+
.notify-form-grid select {
372+
max-width: 180px;
373+
}
374+
.notify-form-grid .wide-field input,
375+
.notify-form-grid .wide-field select {
376+
max-width: none;
377+
}
343378
.wide-field { grid-column: 1 / -1; }
344379
.settings-actions {
345380
grid-column: 1 / -1;

web/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ <h2>实例管理</h2>
130130
<label>启用保活<select id="keepAliveEnabled"><option value="true">启用</option><option value="false">关闭</option></select></label>
131131
<label>流量告警阈值<input id="warningPercent" type="number" min="1" step="1"></label>
132132
<label class="wide-field">保活目标<select id="keepAliveTarget"><option value="disabled">关闭保活(disabled)</option><option value="all">保活所有实例(all)</option><option value="spot_only">保活抢占式实例(spot_only)</option><option value="include_list">只保活指定实例(include_list)</option></select></label>
133-
<label class="wide-field">流量策略<select id="trafficPolicy"><option value="ignore_limit">忽略流量限制继续保活(ignore_limit)</option><option value="pause_when_exceeded">流量超阈值后暂停保活(pause_when_exceeded)</option><option value="manual_only_when_exceeded">流量超阈值后人工决策(manual_only_when_exceeded)</option></select></label>
134133
<label class="wide-field">超阈值处置<select id="trafficExceededAction"><option value="notify_only">只告警(notify_only)</option><option value="notify_and_stop">告警并关机(notify_and_stop)</option></select></label>
135134
<label class="wide-field">停机模式<select id="stopMode"><option value="StopCharging">节省停机(StopCharging)</option><option value="KeepCharging">普通停机(KeepCharging)</option></select></label>
135+
<label class="wide-field">流量策略<select id="trafficPolicy"><option value="ignore_limit">忽略流量限制继续保活(ignore_limit)</option><option value="pause_when_exceeded">流量超阈值后暂停保活(pause_when_exceeded)</option><option value="manual_only_when_exceeded">流量超阈值后人工决策(manual_only_when_exceeded)</option></select></label>
136136
<label class="wide-field">指定保活实例 ID<textarea id="includeIds" placeholder="每行一个实例 ID,例如 i-xxx"></textarea></label>
137137
</div>
138138
</div>
@@ -149,7 +149,7 @@ <h2>实例管理</h2>
149149
</div>
150150
<div class="panel settings-card notify-settings">
151151
<div class="panel-head"><h2>企业微信通知</h2></div>
152-
<div class="form-grid">
152+
<div class="form-grid notify-form-grid">
153153
<label>启用通知<select id="notificationEnabled"><option value="false">关闭</option><option value="true">启用</option></select></label>
154154
<label>人工决策通知间隔<input id="manualRequiredNotifyInterval" placeholder="1h"></label>
155155
<label>流量告警通知间隔<input id="trafficExceededNotifyInterval" placeholder="4h"></label>

0 commit comments

Comments
 (0)