diff --git a/static/app.js b/static/app.js
index 3cf208e..c85d6be 100644
--- a/static/app.js
+++ b/static/app.js
@@ -102,10 +102,13 @@ function mdToHtml(md) {
/* ---------- Markdown 区块(带 原文/Markdown 切换,默认 Markdown) ---------- */
const mdRaw = {}; // id -> {md: bool, text: string}
-function mdBlock(id, text, cls = '') {
+function mdToggleBtn(id) {
+ // 切换开关:放入区块标题行右侧(由调用方放到 .sec-title 内)
+ return ``;
+}
+function mdBody(id, text, cls = '') {
mdRaw[id] = {md: true, text: text || ''};
- return `
- ${mdToHtml(text)}
`;
+ return `${mdToHtml(text)}
`;
}
function mdToggle(id) {
const rec = mdRaw[id];
@@ -1436,10 +1439,10 @@ async function openTaskDetail(tid) {
创建/更新${fmtTime(t.created_at)} / ${fmtTime(t.updated_at)}
截止${t.deadline || '—'}
- 任务指令
- ${mdBlock('td-desc-' + t.id, t.description || t.title, 'sm')}
- ${t.output_text ? `产出物 v${t.output_version}(${t.output_text.length} 字)
- ${mdBlock('td-out-' + t.id, t.output_text)}` : ''}
+ 任务指令${mdToggleBtn('td-desc-' + t.id)}
+ ${mdBody('td-desc-' + t.id, t.description || t.title, 'sm')}
+ ${t.output_text ? `产出物 v${t.output_version}(${t.output_text.length} 字)${mdToggleBtn('td-out-' + t.id)}
+ ${mdBody('td-out-' + t.id, t.output_text)}` : ''}
${t.error ? `错误信息
${esc(t.error)}
` : ''}
执行日志
@@ -1839,6 +1842,7 @@ async function pageReports() {
/* ---------- 运行日志 ---------- */
let logsState = {page: 1, pageSize: 50, level: '', q: ''};
+window.logsState = logsState; // 供分页组件通过 window[stateVar] 读写
async function pageLogs() {
const st = logsState;
@@ -1861,9 +1865,10 @@ async function pageLogs() {
${st.q ? `` : ''}
+ ${pagerHtml(r.page, totalPages, r.total, 'logsState', 'pageLogs', 'top')}
${r.data.map(l => `
${fmtTime(l.created_at)}
[任务#${l.task_id} ${esc(l.task_title || '')}] ${esc(l.message)}
`).join('') || '
暂无日志
'}
- ${pagerHtml(r.page, totalPages, r.total, 'logsState', 'pageLogs')}`;
+ ${pagerHtml(r.page, totalPages, r.total, 'logsState', 'pageLogs', 'bottom')}`;
bindPagerGo('logsState', totalPages, 'pageLogs');
const qel = $('#logs-q');
if (qel) qel.addEventListener('keydown', e => { if (e.key === 'Enter') { logsState.q = qel.value.trim(); logsState.page = 1; pageLogs(); } });
@@ -1871,6 +1876,7 @@ async function pageLogs() {
/* ---------- 告警中心 ---------- */
let alertsState = {page: 1, pageSize: 20, level: '', type: '', read: ''};
+window.alertsState = alertsState; // 供分页组件通过 window[stateVar] 读写
async function pageAlerts() {
const st = alertsState;
@@ -1901,13 +1907,14 @@ async function pageAlerts() {
+ ${pagerHtml(r.page, totalPages, r.total, 'alertsState', 'pageAlerts', 'top')}
${r.data.map(a => `
${ALERT_LEVEL[a.level] || 'ℹ️'} ${esc(a.title)} ${a.read ? '' : '未读'}
${esc(a.detail)}
${fmtTime(a.created_at)} · ${esc(a.type)}
`).join('') || '
暂无告警 🎉
'}
- ${pagerHtml(r.page, totalPages, r.total, 'alertsState', 'pageAlerts')}`;
+ ${pagerHtml(r.page, totalPages, r.total, 'alertsState', 'pageAlerts', 'bottom')}`;
bindPagerGo('alertsState', totalPages, 'pageAlerts');
refreshAlertBadge();
}
@@ -1920,9 +1927,14 @@ async function readAllAlerts() {
toast('已全部标记为已读', 'ok'); pageAlerts();
}
-/* ---------- 分页组件(快速定位页数) ---------- */
-function pagerHtml(page, totalPages, total, stateVar, refreshFn) {
- if (totalPages <= 1) return total ? `` : '';
+/* ---------- 分页组件(快速定位页数,顶部/底部各一份 + 每页条数) ---------- */
+function pagerHtml(page, totalPages, total, stateVar, refreshFn, pos = 'bottom') {
+ const st = window[stateVar] || {};
+ const sizes = [10, 20, 50, 100];
+ const sizeSel = ``;
+ if (totalPages <= 1) return total ? `` : '';
const pages = [];
const add = p => { if (pages[pages.length - 1] !== p && p >= 1 && p <= totalPages) pages.push(p); };
add(1);
@@ -1931,27 +1943,36 @@ function pagerHtml(page, totalPages, total, stateVar, refreshFn) {
for (let p = lo; p <= hi; p++) add(p);
if (hi < totalPages - 1) pages.push('…');
add(totalPages);
- return `