ework-web 0.10.55 → 0.10.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/render/layout.ts +26 -18
package/package.json
CHANGED
package/src/render/layout.ts
CHANGED
|
@@ -49,6 +49,8 @@ header.topbar .num{opacity:.7}
|
|
|
49
49
|
.meta-bar{display:flex;flex-direction:column;gap:.3rem;padding:.7rem max(1rem,calc((100% - 900px)/2));border-bottom:1px solid var(--border);background:var(--bg-muted)}
|
|
50
50
|
.meta-bar h1{font-size:18px;margin:0;font-weight:600;overflow-wrap:anywhere;word-break:break-word}
|
|
51
51
|
.meta-status{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;font-size:13px;color:var(--text-muted)}
|
|
52
|
+
.action-group{display:flex;gap:.3rem;align-items:center;padding-left:.5rem;margin-left:.2rem;border-left:1px solid var(--border)}
|
|
53
|
+
.label-group{display:flex;gap:.3rem;align-items:center;padding-left:.5rem;margin-left:.2rem;border-left:1px solid var(--border);flex-wrap:wrap}
|
|
52
54
|
.count{color:var(--text-muted);font-size:12px;white-space:nowrap}
|
|
53
55
|
#list{padding:.5rem .6rem 4rem;max-width:900px;margin:0 auto}
|
|
54
56
|
.sentinel{height:1px}
|
|
@@ -141,10 +143,14 @@ header.topbar .num{opacity:.7}
|
|
|
141
143
|
.ai-completed{background:#1a7f37;color:#fff}
|
|
142
144
|
.ai-failed{background:#cf222e;color:#fff}
|
|
143
145
|
@keyframes ai-pulse{0%,100%{opacity:1}50%{opacity:.6}}
|
|
144
|
-
.
|
|
145
|
-
.
|
|
146
|
-
.
|
|
147
|
-
.
|
|
146
|
+
.action-btn{font-size:12px;padding:.15rem .6rem;border-radius:6px;border:1px solid var(--border);background:var(--bg-elev);color:#cf222e;cursor:pointer;font-weight:600}
|
|
147
|
+
.action-btn:hover{background:#cf222e;color:#fff}
|
|
148
|
+
.action-btn.resume-btn{color:#1a7f37}
|
|
149
|
+
.action-btn.resume-btn:hover{background:#1a7f37;color:#fff}
|
|
150
|
+
.action-btn.dispatch-btn{color:#6f7781}
|
|
151
|
+
.action-btn.dispatch-btn:hover{background:#6f7781;color:#fff}
|
|
152
|
+
.action-btn.custom-btn{color:var(--accent)}
|
|
153
|
+
.action-btn.custom-btn:hover{background:var(--accent);color:#fff}
|
|
148
154
|
`;
|
|
149
155
|
|
|
150
156
|
export function renderLayout(props: LayoutProps, inner: string, initialItems: string): string {
|
|
@@ -165,11 +171,10 @@ export function renderLayout(props: LayoutProps, inner: string, initialItems: st
|
|
|
165
171
|
: "";
|
|
166
172
|
const aiBadgeHtml = (() => {
|
|
167
173
|
const s = props.aiStatus ?? "";
|
|
168
|
-
|
|
174
|
+
// halted/dispatch_off are represented by their action buttons — skip badge
|
|
175
|
+
if (!s || s === "halted" || s === "dispatch_off") return "";
|
|
169
176
|
const map: Record<string, { cls: string; label: string }> = {
|
|
170
177
|
processing: { cls: "ai-processing", label: "⚙️ 处理中" },
|
|
171
|
-
halted: { cls: "ai-halted", label: "⏸️ 已暂停" },
|
|
172
|
-
dispatch_off: { cls: "ai-dispatch-off", label: "🔕 不接单" },
|
|
173
178
|
completed: { cls: "ai-completed", label: "✓ 已完成" },
|
|
174
179
|
failed: { cls: "ai-failed", label: "✗ 失败" },
|
|
175
180
|
...props.extraStatusBadges,
|
|
@@ -178,15 +183,17 @@ export function renderLayout(props: LayoutProps, inner: string, initialItems: st
|
|
|
178
183
|
if (!m) return "";
|
|
179
184
|
return `<span class="ai-badge ${m.cls}">${m.label}</span>`;
|
|
180
185
|
})();
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
const isTerminal = props.aiStatus === "completed";
|
|
187
|
+
const showActions = props.writesEnabled !== false && !isTerminal;
|
|
188
|
+
const haltBtnHtml = showActions
|
|
189
|
+
? (props.aiStatus === "halted" || props.aiStatus === "failed")
|
|
190
|
+
? `<button type="button" class="action-btn resume-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/resume" data-action-confirm="确认恢复 AI 处理?" title="恢复 AI 处理">▶ 恢复</button>`
|
|
191
|
+
: `<button type="button" class="action-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/halt" data-action-confirm="确认停止 AI 处理?" title="停止 AI 处理">⏹ 停止</button>`
|
|
185
192
|
: "";
|
|
186
|
-
const dispatchBtnHtml =
|
|
193
|
+
const dispatchBtnHtml = showActions
|
|
187
194
|
? props.aiStatus === "dispatch_off"
|
|
188
|
-
? `<button type="button" class="dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-on" title="允许自动接单">🔔 接单</button>`
|
|
189
|
-
: `<button type="button" class="dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-off" data-action-confirm="设为不自动接单?" title="设为不自动接单">🔕 不接单</button>`
|
|
195
|
+
? `<button type="button" class="action-btn dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-on" title="允许自动接单">🔔 接单</button>`
|
|
196
|
+
: `<button type="button" class="action-btn dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-off" data-action-confirm="设为不自动接单?" title="设为不自动接单">🔕 不接单</button>`
|
|
190
197
|
: "";
|
|
191
198
|
return `<!doctype html>
|
|
192
199
|
<html lang="zh">
|
|
@@ -209,15 +216,16 @@ export function renderLayout(props: LayoutProps, inner: string, initialItems: st
|
|
|
209
216
|
<h1>${escapeHtml(props.issueTitle)}</h1>
|
|
210
217
|
<div class="meta-status">
|
|
211
218
|
<span class="state-badge ${stateClass}">${stateLabel}</span>
|
|
212
|
-
${aiBadgeHtml}
|
|
219
|
+
${aiBadgeHtml}
|
|
220
|
+
${(haltBtnHtml || dispatchBtnHtml || (props.customActions ?? []).length) ? `<span class="action-group">${haltBtnHtml}${dispatchBtnHtml}${(props.customActions ?? []).map((a) => {
|
|
213
221
|
const attrs = [`data-action-href="${escapeAttr(a.href)}"`];
|
|
214
222
|
if (a.method && a.method !== "POST") attrs.push(`data-action-method="${escapeAttr(a.method)}"`);
|
|
215
223
|
if (a.confirm) attrs.push(`data-action-confirm="${escapeAttr(a.confirm)}"`);
|
|
216
224
|
if (a.reloadOnOk === false) attrs.push(`data-action-reload="false"`);
|
|
217
|
-
const cls = a.className ? `${escapeAttr(a.className)}` : "
|
|
225
|
+
const cls = a.className ? `${escapeAttr(a.className)}` : "action-btn custom-btn";
|
|
218
226
|
return `<button type="button" class="${cls}" ${attrs.join(" ")}${a.title ? ` title="${escapeAttr(a.title)}"` : ""}>${escapeHtml(a.label)}</button>`;
|
|
219
|
-
}).join("")}
|
|
220
|
-
${labelsHtml}${labelPickerBtn}
|
|
227
|
+
}).join("")}</span>` : ""}
|
|
228
|
+
${(labelsHtml || labelPickerBtn) ? `<span class="label-group">${labelsHtml}${labelPickerBtn}</span>` : ""}
|
|
221
229
|
<span class="count" id="count">…</span>
|
|
222
230
|
${props.upstreamWebUrl ? `<a class="upstream-link" href="${escapeAttr(props.upstreamWebUrl)}" target="_blank" rel="noopener noreferrer" title="跳转到上游仓库">🔗 查看上游</a>` : ""}
|
|
223
231
|
</div>
|