feat: implement sorting and search with UI and logic enhancements

- Add global/group sorting with status bar
- Implement global search functionality
- Adjust sort/search layout and positioning
- Add certificate expiration label support
- Apply language adaptation and background styling
- Add canonical annotations
This commit is contained in:
Marshu 2025-04-09 19:20:25 +08:00 committed by ehaoyue
parent 4b0a3df226
commit 4fdeba8cb0
5 changed files with 1185 additions and 44 deletions

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,8 @@ import {
faTachometerAlt,
faTimes,
faTimesCircle,
faTrash,
faCheckCircle,
faTrash,
faStream,
faSave,
faExclamationCircle,
@ -50,6 +50,8 @@ import {
faInfoCircle,
faClone,
faCertificate,
faArrowUp,
faArrowDown,
} from "@fortawesome/free-solid-svg-icons";
library.add(
@ -66,8 +68,8 @@ library.add(
faTachometerAlt,
faTimes,
faTimesCircle,
faTrash,
faCheckCircle,
faTrash,
faStream,
faSave,
faExclamationCircle,
@ -97,6 +99,8 @@ library.add(
faInfoCircle,
faClone,
faCertificate,
faArrowUp,
faArrowDown,
);
export { FontAwesomeIcon };

View File

@ -48,6 +48,7 @@
"Current": "Current",
"Uptime": "Uptime",
"Cert Exp.": "Cert Exp.",
"Sort By": "Sort By",
"Monitor": "Monitor | Monitors",
"now": "now",
"time ago": "{0} ago",

View File

@ -27,6 +27,7 @@
"notificationDescription": "通知必须被分配给监控项才能正常工作。",
"keywordDescription": "在纯 HTML 或 JSON 响应中搜索关键字,区分大小写。",
"pauseDashboardHome": "暂停",
"Sort By": "排序方式",
"deleteMonitorMsg": "确定要删除此监控项吗?",
"deleteMaintenanceMsg": "确定要删除此维护吗?",
"deleteNotificationMsg": "确定要为所有监控项删除此通知吗?",
@ -1117,5 +1118,7 @@
"wayToGetWahaApiKey": "API 密钥是你用于运行 WAHA 的 WHATSAPP_API_KEY 环境变量值。",
"telegramTemplateFormatDescription": "Telegram 允许在消息中使用不同的标记语言,具体细节请参见 Telegram {0}。",
"YZJ Webhook URL": "YZJ Webhook 地址",
"YZJ Robot Token": "YZJ 机器人令牌"
"YZJ Robot Token": "YZJ 机器人令牌",
"Search...": "搜索...",
"No services found": "未找到服务"
}

View File

@ -328,7 +328,7 @@
👀 {{ $t("statusPageNothing") }}
</div>
<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" :show-certificate-expiry="config.showCertificateExpiry" />
<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" :show-certificate-expiry="config.showCertificateExpiry" :slug="slug" />
</div>
<footer class="mt-5 mb-4">
@ -773,10 +773,26 @@ export default {
if (! this.editMode) {
axios.get("/api/status-page/heartbeat/" + this.slug).then((res) => {
const { heartbeatList, uptimeList } = res.data;
this.$root.heartbeatList = heartbeatList;
this.$root.uptimeList = uptimeList;
if (!this.enableEditMode) {
this.$root.publicGroupList.forEach((group) => {
const downs = [];
const others = [];
// Traverse all monitors in the current group
for (const monitor of group.monitorList) {
const hbArr = heartbeatList[monitor.id];
// Check if the last heartbeat status is Down (status === 0)
if (hbArr && hbArr.length > 0 && hbArr.at(-1).status === 0) {
downs.push(monitor);
} else {
others.push(monitor);
}
}
// Place Down monitors at the front, keep the original order for others
group.monitorList = downs.concat(others);
});
}
const heartbeatIds = Object.keys(heartbeatList);
const downMonitors = heartbeatIds.reduce((downMonitorsAmount, currentId) => {
const monitorHeartbeats = heartbeatList[currentId];