43fa1f7dbb
输入/下拉文字此前用 --ink(近白)太刺眼且与正文耦合。新增 --field-ink token (深 #a7b3a1 / 浅 #3c4838),Input/Select 组件引用之;改一个值即全改。 因项目无 DS 编译器,同步改 _ds_bundle.js(运行加载源)+ ambience.css 兜底,确保即时生效。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6187 lines
183 KiB
JavaScript
6187 lines
183 KiB
JavaScript
/* @ds-bundle: {"format":3,"namespace":"MaestroDesignSystem_a6a290","components":[{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"ComplexityBadge","sourcePath":"components/core/ComplexityBadge.jsx"},{"name":"CountBadge","sourcePath":"components/core/CountBadge.jsx"},{"name":"QuotaMeter","sourcePath":"components/core/QuotaMeter.jsx"},{"name":"SectionHead","sourcePath":"components/core/SectionHead.jsx"},{"name":"StatusChip","sourcePath":"components/core/StatusChip.jsx"},{"name":"ComplexitySeg","sourcePath":"components/forms/ComplexitySeg.jsx"},{"name":"Input","sourcePath":"components/forms/Input.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"EventItem","sourcePath":"components/surfaces/EventItem.jsx"},{"name":"GateCard","sourcePath":"components/surfaces/GateCard.jsx"},{"name":"GateStripe","sourcePath":"components/surfaces/GateCard.jsx"},{"name":"Panel","sourcePath":"components/surfaces/Panel.jsx"},{"name":"Timeline","sourcePath":"components/surfaces/Timeline.jsx"},{"name":"Toast","sourcePath":"components/surfaces/Toast.jsx"}],"sourceHashes":{"components/core/Button.jsx":"82f8de85de83","components/core/ComplexityBadge.jsx":"e71cc98656b7","components/core/CountBadge.jsx":"af4b823012b9","components/core/QuotaMeter.jsx":"117017318e01","components/core/SectionHead.jsx":"8981650002b2","components/core/StatusChip.jsx":"91c76c66e4e8","components/forms/ComplexitySeg.jsx":"f73ca6817593","components/forms/Input.jsx":"bfd5125bd134","components/forms/Select.jsx":"d92be9b2fe0e","components/forms/Textarea.jsx":"f3edac5339bb","components/surfaces/EventItem.jsx":"920a78b6471d","components/surfaces/GateCard.jsx":"b63adae94ec3","components/surfaces/Panel.jsx":"5b7d37e41487","components/surfaces/Timeline.jsx":"e1ba0c783e7f","components/surfaces/Toast.jsx":"5a232f396e93","ui_kits/console/ArchiveSection.jsx":"89fbdb79f86a","ui_kits/console/EventPanel.jsx":"52e17c973784","ui_kits/console/GateSection.jsx":"b204aa1c8247","ui_kits/console/Sidebar.jsx":"b620fd3f8eae","ui_kits/console/TaskTree.jsx":"91f34a1b00b2","ui_kits/console/Topbar.jsx":"0f5231451246","ui_kits/console/data.js":"60a42c054328","ui_kits/console/i18n.js":"275b4e5a8c43","ui_kits/console_mobile/MobileChrome.jsx":"9b8c0929ccd7","ui_kits/console_mobile/MobileViews.jsx":"1babdab6d1af"},"inlinedExternals":[],"unexposedExports":[{"name":"ensureFieldCss","sourcePath":"components/forms/Input.jsx"}]} */
|
||
|
||
(() => {
|
||
|
||
const __ds_ns = (window.MaestroDesignSystem_a6a290 = window.MaestroDesignSystem_a6a290 || {});
|
||
|
||
const __ds_scope = {};
|
||
|
||
(__ds_ns.__errors = __ds_ns.__errors || []);
|
||
|
||
// components/core/Button.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-btn{font-family:var(--mono);font-size:12px;font-weight:600;letter-spacing:.08em;background:transparent;color:var(--ink);border:1px solid var(--line);padding:6px 14px;cursor:pointer;transition:all .12s;border-radius:var(--radius-sm,4px);white-space:nowrap}
|
||
.m-btn:hover{border-color:var(--muted);background:var(--panel-2)}
|
||
.m-btn--xs{padding:2px 8px;font-size:11px}
|
||
.m-btn--ghost{border-color:transparent;color:var(--muted)}
|
||
.m-btn--ghost:hover{color:var(--green);border-color:var(--green-dim);background:transparent}
|
||
.m-btn--solid{background:var(--green);color:var(--bg-deep);border-color:var(--green)}
|
||
.m-btn--solid:hover{background:#79ec94;border-color:#79ec94;box-shadow:0 0 14px rgba(95,221,125,.35)}
|
||
.m-btn--accept{border-color:var(--green-dim);color:var(--green)}
|
||
.m-btn--accept:hover{background:var(--green);color:var(--bg-deep);border-color:var(--green);box-shadow:0 0 14px rgba(95,221,125,.3)}
|
||
.m-btn--reject{border-color:var(--red-dim);color:var(--red)}
|
||
.m-btn--reject:hover{background:var(--red);color:var(--bg-deep);border-color:var(--red);box-shadow:0 0 14px rgba(255,93,93,.3)}
|
||
.m-btn:disabled{opacity:.4;cursor:not-allowed}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-btn-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-btn-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Button({
|
||
variant = 'default',
|
||
size,
|
||
disabled,
|
||
onClick,
|
||
type = 'button',
|
||
style,
|
||
children
|
||
}) {
|
||
ensureCss();
|
||
const cls = ['m-btn'];
|
||
if (variant !== 'default') cls.push('m-btn--' + variant);
|
||
if (size === 'xs') cls.push('m-btn--xs');
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
type: type,
|
||
className: cls.join(' '),
|
||
disabled: disabled,
|
||
onClick: onClick,
|
||
style: style
|
||
}, children);
|
||
}
|
||
Object.assign(__ds_scope, { Button });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Button.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/ComplexityBadge.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-cplx{flex:none;display:inline-block;font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.14em;padding:1px 7px;border:1px solid;border-radius:var(--radius-xs,3px)}
|
||
.m-cplx--hard{color:var(--red);border-color:var(--red-dim);background:rgba(255,93,93,.07)}
|
||
.m-cplx--medium{color:var(--amber);border-color:var(--amber-dim);background:rgba(240,180,41,.07)}
|
||
.m-cplx--easy{color:var(--green);border-color:var(--green-dim);background:rgba(95,221,125,.07)}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-cplx-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-cplx-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
const LABEL = {
|
||
hard: 'HARD',
|
||
medium: 'MED',
|
||
easy: 'EASY'
|
||
};
|
||
function ComplexityBadge({
|
||
complexity = 'medium'
|
||
}) {
|
||
ensureCss();
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
className: 'm-cplx m-cplx--' + complexity
|
||
}, LABEL[complexity] || complexity);
|
||
}
|
||
Object.assign(__ds_scope, { ComplexityBadge });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/ComplexityBadge.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/CountBadge.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-bdg{display:inline-flex;align-items:center;font-family:var(--mono);font-size:11.5px;line-height:1;letter-spacing:.08em;height:28px;padding:0 10px;cursor:default;white-space:nowrap;border-radius:var(--radius-sm,4px)}
|
||
.m-bdg .m-bdg-ico{margin-right:5px;font-size:12px;line-height:1;font-family:var(--mono)}
|
||
.m-bdg .m-bdg-n{font-weight:700}
|
||
.m-bdg .m-bdg-label{max-width:0;opacity:0;overflow:hidden;transition:max-width .28s ease,opacity .22s ease,margin-left .28s ease}
|
||
.m-bdg:hover .m-bdg-label{max-width:8em;opacity:1;margin-left:5px}
|
||
.m-bdg--gate{color:var(--violet);border:1px solid var(--violet-dim)}
|
||
.m-bdg--gate:not(.m-bdg--zero){animation:maestro-pulse 2.2s infinite}
|
||
.m-bdg--ready{color:var(--green);border:1px solid var(--green-dim)}
|
||
.m-bdg--run{color:var(--cyan);border:1px solid var(--cyan-dim)}
|
||
.m-bdg--run:not(.m-bdg--zero) .m-bdg-ico{animation:maestro-pulse .9s infinite}
|
||
.m-bdg--blocked{color:var(--amber);border:1px dashed var(--amber-dim)}
|
||
.m-bdg--total{color:var(--ink);border:1px solid var(--line)}
|
||
.m-bdg--zero{color:var(--faint);border-color:var(--line-soft);animation:none}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-bdg-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-bdg-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
const META = {
|
||
gate: {
|
||
ico: '⚠',
|
||
label: '项待审批'
|
||
},
|
||
ready: {
|
||
ico: '▸',
|
||
label: '待执行'
|
||
},
|
||
run: {
|
||
ico: '◉',
|
||
label: '执行中'
|
||
},
|
||
blocked: {
|
||
ico: '⛓',
|
||
label: '被阻塞'
|
||
},
|
||
total: {
|
||
ico: 'Σ',
|
||
label: '总量'
|
||
}
|
||
};
|
||
function CountBadge({
|
||
kind = 'ready',
|
||
count = 0,
|
||
label,
|
||
title
|
||
}) {
|
||
ensureCss();
|
||
const m = META[kind] || META.ready;
|
||
const cls = 'm-bdg m-bdg--' + kind + (count === 0 ? ' m-bdg--zero' : '');
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
className: cls,
|
||
title: title
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-bdg-ico"
|
||
}, m.ico), /*#__PURE__*/React.createElement("span", {
|
||
className: "m-bdg-n"
|
||
}, count), /*#__PURE__*/React.createElement("span", {
|
||
className: "m-bdg-label"
|
||
}, label || m.label));
|
||
}
|
||
Object.assign(__ds_scope, { CountBadge });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/CountBadge.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/QuotaMeter.jsx
|
||
try { (() => {
|
||
// 额度计量条:LED 分段 + 用量分级变色(≤80% 青 / >80% 琥珀 / >95% 红,与产品 .agent-usage 阈值对齐)
|
||
function QuotaMeter({
|
||
label,
|
||
pct = 0,
|
||
detail,
|
||
cells = 16,
|
||
style
|
||
}) {
|
||
const p = Math.max(0, Math.min(100, pct));
|
||
const filled = Math.round(p / 100 * cells);
|
||
const color = p > 95 ? 'var(--red)' : p > 80 ? 'var(--amber)' : 'var(--cyan)';
|
||
const glow = p > 95 ? 'rgba(255,93,93,.4)' : p > 80 ? 'rgba(240,180,41,.35)' : 'rgba(89,200,216,.4)';
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
fontFamily: 'var(--mono)',
|
||
...style
|
||
},
|
||
title: (label ? label + ' · ' : '') + p + '%' + (detail ? ' · ' + detail : '')
|
||
}, label ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.08em',
|
||
flex: 'none'
|
||
}
|
||
}, label) : null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
gap: 2,
|
||
padding: 3,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderRadius: 3
|
||
}
|
||
}, Array.from({
|
||
length: cells
|
||
}, (_, i) => /*#__PURE__*/React.createElement("span", {
|
||
key: i,
|
||
style: {
|
||
width: 4,
|
||
height: 9,
|
||
borderRadius: 1,
|
||
background: i < filled ? color : 'var(--panel-2)',
|
||
boxShadow: i < filled ? '0 0 5px ' + glow : 'none'
|
||
}
|
||
}))), /*#__PURE__*/React.createElement("b", {
|
||
style: {
|
||
fontSize: 12,
|
||
color
|
||
}
|
||
}, p, "%"), detail ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, detail) : null);
|
||
}
|
||
Object.assign(__ds_scope, { QuotaMeter });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/QuotaMeter.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/SectionHead.jsx
|
||
try { (() => {
|
||
function SectionHead({
|
||
mark = 'green',
|
||
title,
|
||
action,
|
||
sticky,
|
||
style
|
||
}) {
|
||
const markColor = {
|
||
green: 'var(--green)',
|
||
amber: 'var(--amber)',
|
||
cyan: 'var(--cyan)',
|
||
violet: 'var(--violet)'
|
||
}[mark] || 'var(--green)';
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
letterSpacing: '.22em',
|
||
color: 'var(--muted)',
|
||
textTransform: 'uppercase',
|
||
padding: '18px 0 10px',
|
||
...(sticky ? {
|
||
position: 'sticky',
|
||
top: 0,
|
||
zIndex: 5,
|
||
background: 'linear-gradient(var(--bg) 75%, transparent)'
|
||
} : {}),
|
||
...style
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: markColor,
|
||
flex: 'none'
|
||
}
|
||
}, "\u258D"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
whiteSpace: 'nowrap',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
minWidth: 0
|
||
}
|
||
}, title), action ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
flex: 'none'
|
||
}
|
||
}, action) : null);
|
||
}
|
||
Object.assign(__ds_scope, { SectionHead });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/SectionHead.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/core/StatusChip.jsx
|
||
try { (() => {
|
||
const STATUS_LABEL = {
|
||
init: '新建',
|
||
analyzing: '分析拆解中',
|
||
plan_review: '待确认拆解',
|
||
decomposed: '已拆解',
|
||
speccing: '写方案中',
|
||
spec_review: '待确认方案',
|
||
ready: '可执行',
|
||
blocked: '被依赖阻塞',
|
||
queued: '排队中',
|
||
executing: '执行中',
|
||
exec_review: '待审/合',
|
||
failed: '失败',
|
||
needs_attention: '需人工',
|
||
done: '完成',
|
||
paused: '暂停',
|
||
cancelled: '取消'
|
||
};
|
||
const STATUS_GROUP = {
|
||
init: 'idle',
|
||
analyzing: 'work',
|
||
speccing: 'work',
|
||
plan_review: 'gate',
|
||
spec_review: 'gate',
|
||
exec_review: 'gate',
|
||
decomposed: 'container',
|
||
ready: 'go',
|
||
queued: 'go',
|
||
executing: 'run',
|
||
blocked: 'hold',
|
||
paused: 'hold',
|
||
failed: 'bad',
|
||
needs_attention: 'bad',
|
||
done: 'done',
|
||
cancelled: 'dead'
|
||
};
|
||
const css = `
|
||
.m-chip{flex:none;display:inline-flex;align-items:center;gap:5px;font-family:var(--mono);font-size:11px;padding:1px 8px;border:1px solid var(--line);color:var(--muted);white-space:nowrap;border-radius:var(--radius-xs,3px)}
|
||
.m-chip::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor}
|
||
.m-chip--work{color:var(--cyan);border-color:var(--cyan-dim)}
|
||
.m-chip--gate{color:var(--violet);border-color:var(--violet-dim)}
|
||
.m-chip--gate::before{animation:maestro-pulse 1.4s infinite}
|
||
.m-chip--container{color:#9bb4c8;border-color:#2c3c4a}
|
||
.m-chip--go{color:var(--green);border-color:var(--green-dim)}
|
||
.m-chip--run{color:var(--cyan);border-color:var(--cyan);box-shadow:0 0 10px rgba(89,200,216,.25)}
|
||
.m-chip--run::before{animation:maestro-pulse .8s infinite}
|
||
.m-chip--hold{color:var(--faint)}
|
||
.m-chip--bad{color:var(--red);border-color:var(--red-dim)}
|
||
.m-chip--bad::before{animation:maestro-pulse 1s infinite}
|
||
.m-chip--done{color:var(--bg-deep);background:var(--green);border-color:var(--green);font-weight:700}
|
||
.m-chip--dead{color:var(--faint);text-decoration:line-through}
|
||
.m-chip--dead::before{background:var(--faint)}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-chip-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-chip-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function StatusChip({
|
||
status = 'init',
|
||
label
|
||
}) {
|
||
ensureCss();
|
||
const group = STATUS_GROUP[status] || 'idle';
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
className: 'm-chip m-chip--' + group
|
||
}, label || STATUS_LABEL[status] || status);
|
||
}
|
||
Object.assign(__ds_scope, { StatusChip });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/StatusChip.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/ComplexitySeg.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-seg{display:inline-flex;border:1px solid var(--line);font-family:var(--mono);border-radius:var(--radius-sm,4px);overflow:hidden}
|
||
.m-seg button{font-family:var(--mono);padding:7px 13px;cursor:pointer;font-size:11px;font-weight:700;letter-spacing:.12em;color:var(--faint);background:transparent;border:none;border-radius:0}
|
||
.m-seg button + button{border-left:1px solid var(--line)}
|
||
.m-seg button.on-hard{background:var(--red-dim);color:var(--red)}
|
||
.m-seg button.on-medium{background:var(--amber-dim);color:var(--amber)}
|
||
.m-seg button.on-easy{background:var(--green-dim);color:var(--green)}
|
||
.m-seg button.on-auto{background:var(--cyan-dim);color:var(--cyan)}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-seg-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-seg-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
const BASE_OPTS = [['hard', 'HARD'], ['medium', 'MEDIUM'], ['easy', 'EASY']];
|
||
function ComplexitySeg({
|
||
value,
|
||
defaultValue = 'medium',
|
||
onChange,
|
||
includeAuto,
|
||
autoLabel = 'AUTO',
|
||
labels
|
||
}) {
|
||
ensureCss();
|
||
const [inner, setInner] = React.useState(defaultValue);
|
||
const cur = value !== undefined ? value : inner;
|
||
const opts = includeAuto ? [...BASE_OPTS, ['auto', autoLabel]] : BASE_OPTS;
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
className: "m-seg"
|
||
}, opts.map(([v, lab]) => /*#__PURE__*/React.createElement("button", {
|
||
key: v,
|
||
type: "button",
|
||
className: cur === v ? 'on-' + v : '',
|
||
onClick: () => {
|
||
setInner(v);
|
||
if (onChange) onChange(v);
|
||
}
|
||
}, labels && labels[v] || lab)));
|
||
}
|
||
Object.assign(__ds_scope, { ComplexitySeg });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/ComplexitySeg.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Input.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-label{display:flex;flex-direction:column;gap:4px;font-family:var(--mono);font-size:11px;color:var(--muted);letter-spacing:.08em}
|
||
.m-input{font-family:var(--mono);font-size:13px;background:var(--bg-deep);color:var(--field-ink);border:1px solid var(--line);padding:7px 10px;outline:none;transition:border-color .12s;border-radius:var(--radius-sm,4px)}
|
||
.m-input:focus{border-color:var(--green-dim);box-shadow:0 0 0 1px var(--green-dim)}
|
||
.m-input::placeholder{color:var(--faint)}
|
||
.m-req{color:var(--red)}
|
||
`;
|
||
function ensureFieldCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-field-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-field-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Input({
|
||
label,
|
||
required,
|
||
type = 'text',
|
||
placeholder,
|
||
value,
|
||
defaultValue,
|
||
onChange,
|
||
width,
|
||
style
|
||
}) {
|
||
ensureFieldCss();
|
||
const ctrl = /*#__PURE__*/React.createElement("input", {
|
||
className: "m-input",
|
||
type: type,
|
||
placeholder: placeholder,
|
||
value: value,
|
||
defaultValue: defaultValue,
|
||
style: {
|
||
width,
|
||
...style
|
||
},
|
||
autoComplete: "off",
|
||
onChange: onChange ? e => onChange(e.target.value) : undefined,
|
||
readOnly: value !== undefined && !onChange
|
||
});
|
||
if (!label) return ctrl;
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: "m-label"
|
||
}, /*#__PURE__*/React.createElement("span", null, label, required ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-req"
|
||
}, " *") : null), ctrl);
|
||
}
|
||
Object.assign(__ds_scope, { ensureFieldCss, Input });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Input.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Select.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-select{position:relative;display:inline-flex;flex-direction:column;min-width:120px}
|
||
.m-select-trigger{font-family:var(--mono);font-size:13px;background:var(--bg-deep);color:var(--field-ink);border:1px solid var(--line);border-radius:var(--radius-sm,4px);padding:7px 10px;cursor:pointer;outline:none;transition:border-color .12s;display:flex;align-items:center;gap:10px;text-align:left;width:100%}
|
||
.m-select-trigger:hover{border-color:var(--muted)}
|
||
.m-select-trigger.open,.m-select-trigger:focus{border-color:var(--green-dim);box-shadow:0 0 0 1px var(--green-dim)}
|
||
.m-select-value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.m-select-caret{flex:none;font-size:8px;color:var(--faint);transition:transform .12s}
|
||
.m-select-trigger.open .m-select-caret{transform:rotate(180deg)}
|
||
.m-select-menu{position:absolute;top:calc(100% + 5px);left:0;right:0;z-index:80;display:grid;background:var(--bg-deep);border:1px solid var(--line);border-radius:var(--radius-md,6px);padding:4px;box-shadow:0 10px 30px rgba(0,0,0,.65);animation:maestro-rise .12s ease both;max-height:260px;overflow-y:auto}
|
||
.m-select-opt{font-family:var(--mono);font-size:12.5px;text-align:left;background:transparent;color:var(--field-ink);border:none;border-radius:4px;padding:7px 10px 7px 8px;cursor:pointer;display:flex;align-items:center;gap:7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.m-select-opt:hover{background:var(--panel)}
|
||
.m-select-opt.on{background:var(--panel-2);color:var(--green);font-weight:700}
|
||
.m-select-mark{flex:none;width:8px;color:var(--green);font-size:10px}
|
||
`;
|
||
function ensureSelectCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-select-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-select-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Select({
|
||
label,
|
||
required,
|
||
options = [],
|
||
value,
|
||
defaultValue,
|
||
onChange,
|
||
style
|
||
}) {
|
||
__ds_scope.ensureFieldCss();
|
||
ensureSelectCss();
|
||
const opts = options.map(o => typeof o === 'string' ? {
|
||
value: o,
|
||
label: o
|
||
} : o);
|
||
const [inner, setInner] = React.useState(defaultValue !== undefined ? defaultValue : opts[0] ? opts[0].value : '');
|
||
const cur = value !== undefined ? value : inner;
|
||
const curOpt = opts.find(o => o.value === cur);
|
||
const [open, setOpen] = React.useState(false);
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||
};
|
||
const onKey = e => {
|
||
if (e.key === 'Escape') setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
document.addEventListener('keydown', onKey);
|
||
return () => {
|
||
document.removeEventListener('mousedown', onDoc);
|
||
document.removeEventListener('keydown', onKey);
|
||
};
|
||
}, [open]);
|
||
const pick = v => {
|
||
setInner(v);
|
||
setOpen(false);
|
||
if (onChange) onChange(v);
|
||
};
|
||
const ctrl = /*#__PURE__*/React.createElement("span", {
|
||
className: "m-select",
|
||
ref: ref,
|
||
style: style
|
||
}, /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
className: 'm-select-trigger' + (open ? ' open' : ''),
|
||
onClick: () => setOpen(!open)
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-select-value"
|
||
}, curOpt ? curOpt.label : cur), /*#__PURE__*/React.createElement("span", {
|
||
className: "m-select-caret"
|
||
}, "\u25BC")), open ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-select-menu"
|
||
}, opts.map(o => /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
key: o.value,
|
||
className: 'm-select-opt' + (o.value === cur ? ' on' : ''),
|
||
onClick: () => pick(o.value)
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-select-mark"
|
||
}, o.value === cur ? '▍' : ''), o.label))) : null);
|
||
if (!label) return ctrl;
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: "m-label"
|
||
}, /*#__PURE__*/React.createElement("span", null, label, required ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-req"
|
||
}, " *") : null), ctrl);
|
||
}
|
||
Object.assign(__ds_scope, { Select });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Select.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/forms/Textarea.jsx
|
||
try { (() => {
|
||
function Textarea({
|
||
label,
|
||
required,
|
||
placeholder,
|
||
value,
|
||
defaultValue,
|
||
onChange,
|
||
minHeight = 72,
|
||
danger,
|
||
style
|
||
}) {
|
||
__ds_scope.ensureFieldCss();
|
||
const ctrl = /*#__PURE__*/React.createElement("textarea", {
|
||
className: "m-input",
|
||
placeholder: placeholder,
|
||
value: value,
|
||
defaultValue: defaultValue,
|
||
style: {
|
||
resize: 'vertical',
|
||
minHeight,
|
||
width: '100%',
|
||
...(danger ? {
|
||
borderColor: 'var(--red-dim)'
|
||
} : {}),
|
||
...style
|
||
},
|
||
onChange: onChange ? e => onChange(e.target.value) : undefined,
|
||
readOnly: value !== undefined && !onChange
|
||
});
|
||
if (!label) return ctrl;
|
||
return /*#__PURE__*/React.createElement("label", {
|
||
className: "m-label",
|
||
style: {
|
||
width: '100%'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", null, label, required ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-req"
|
||
}, " *") : null), ctrl);
|
||
}
|
||
Object.assign(__ds_scope, { Textarea });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Textarea.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/surfaces/EventItem.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-ev{font-family:var(--mono);padding:7px 0 7px 12px;border-bottom:1px solid var(--line-soft);position:relative;font-size:11.5px;color:var(--ink);animation:maestro-rise .25s ease both;list-style:none}
|
||
.m-ev::before{content:'';position:absolute;left:0;top:13px;width:5px;height:5px;background:var(--m-ev-c,var(--muted));border-radius:1.5px}
|
||
.m-ev-head{display:flex;gap:8px;align-items:baseline}
|
||
.m-ev-type{font-weight:600;color:var(--m-ev-c,var(--ink));letter-spacing:.04em}
|
||
.m-ev-time{color:var(--faint);font-size:10.5px;margin-left:auto;flex:none}
|
||
.m-ev-detail{color:var(--muted);margin-top:1px;word-break:break-word}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-ev-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-ev-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
const TYPE_META = {
|
||
'task.created': ['任务创建', 'var(--green)'],
|
||
'task.updated': ['任务更新', 'var(--muted)'],
|
||
'status.changed': ['状态变更', 'var(--cyan)'],
|
||
'approval.requested': ['请求审批', 'var(--violet)'],
|
||
'approval.granted': ['审批通过', 'var(--green)'],
|
||
'approval.rejected': ['审批驳回', 'var(--red)'],
|
||
'run.started': ['运行开始', 'var(--cyan)'],
|
||
'run.finished': ['运行结束', 'var(--cyan)'],
|
||
'project.synced': ['todo 同步', 'var(--green)']
|
||
};
|
||
function EventItem({
|
||
type = 'task.updated',
|
||
time,
|
||
detail,
|
||
label
|
||
}) {
|
||
ensureCss();
|
||
const [lab, color] = TYPE_META[type] || [type, 'var(--muted)'];
|
||
return /*#__PURE__*/React.createElement("li", {
|
||
className: "m-ev",
|
||
style: {
|
||
'--m-ev-c': color
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
className: "m-ev-head"
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-ev-type"
|
||
}, label || lab), time ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-ev-time"
|
||
}, time) : null), detail ? /*#__PURE__*/React.createElement("div", {
|
||
className: "m-ev-detail"
|
||
}, detail) : null);
|
||
}
|
||
Object.assign(__ds_scope, { EventItem });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/surfaces/EventItem.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/surfaces/GateCard.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-gate{background:var(--panel);border:1px solid var(--violet-dim);font-family:var(--mono);color:var(--ink);animation:maestro-rise .25s ease both;border-radius:var(--radius-md,6px);overflow:hidden}
|
||
.m-gate-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 14px;border-bottom:1px solid var(--line-soft)}
|
||
.m-gate--collapsed .m-gate-head{border-bottom:none}
|
||
.m-gate-hx{margin-left:auto;display:flex;align-items:center;gap:6px;flex:none}
|
||
.m-gate-fold{font-family:var(--mono);font-size:12px;line-height:1;cursor:pointer;background:transparent;color:var(--muted);border:1px solid var(--line);border-radius:var(--radius-sm,4px);padding:3px 7px;transition:color .12s,border-color .12s}
|
||
.m-gate-fold:hover{color:var(--violet);border-color:var(--violet-dim)}
|
||
.m-gate-kind{font-size:10.5px;font-weight:700;letter-spacing:.18em;color:var(--bg);background:var(--violet);padding:2px 8px;border-radius:var(--radius-xs,3px)}
|
||
.m-gate-title{font-weight:600;font-size:13px}
|
||
.m-gate-body{padding:12px 14px;font-size:12.5px}
|
||
.m-gate-actions{display:flex;gap:10px;align-items:center;padding:10px 14px;border-top:1px solid var(--line-soft)}
|
||
.m-gate-doclabel{font-size:10.5px;color:var(--muted);letter-spacing:.18em;margin:8px 0 4px}
|
||
.m-gate-doclabel:first-child{margin-top:0}
|
||
.m-gate-doc{background:var(--bg-deep);border:1px solid var(--line-soft);border-left:2px solid var(--green-dim);padding:10px 12px;font-family:var(--mono);font-size:12.5px;line-height:1.55;white-space:pre-wrap;word-break:break-word;max-height:280px;overflow-y:auto;color:var(--ink);margin:0;border-radius:var(--radius-sm,4px)}
|
||
.m-gate-stripe{height:5px;background:repeating-linear-gradient(-45deg,var(--violet) 0 9px,transparent 9px 18px);opacity:.8;border-radius:3px}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-gate-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-gate-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
const GATE_LABEL = {
|
||
plan: '拆解评审',
|
||
spec: '方案评审',
|
||
exec: '结果评审'
|
||
};
|
||
function GateCard({
|
||
gate = 'spec',
|
||
kindLabel,
|
||
title,
|
||
meta,
|
||
docLabel,
|
||
doc,
|
||
actions,
|
||
children,
|
||
style,
|
||
collapsed,
|
||
foldable,
|
||
onToggleFold,
|
||
foldTitle,
|
||
headerExtra,
|
||
onHeaderDoubleClick,
|
||
headerTitle
|
||
}) {
|
||
ensureCss();
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: 'm-gate' + (collapsed ? ' m-gate--collapsed' : ''),
|
||
style: style,
|
||
onDoubleClick: onHeaderDoubleClick
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
className: "m-gate-head",
|
||
title: headerTitle
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-gate-kind"
|
||
}, kindLabel || GATE_LABEL[gate] || gate), /*#__PURE__*/React.createElement("span", {
|
||
className: "m-gate-title"
|
||
}, title), meta ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)'
|
||
}
|
||
}, meta) : null, headerExtra || foldable ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-gate-hx"
|
||
}, headerExtra, foldable ? /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
className: "m-gate-fold",
|
||
title: foldTitle,
|
||
onClick: e => {
|
||
e.stopPropagation();
|
||
onToggleFold && onToggleFold();
|
||
}
|
||
}, collapsed ? '▸' : '▾') : null) : null), !collapsed ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||
className: "m-gate-body"
|
||
}, docLabel ? /*#__PURE__*/React.createElement("div", {
|
||
className: "m-gate-doclabel"
|
||
}, docLabel) : null, doc ? /*#__PURE__*/React.createElement("pre", {
|
||
className: "m-gate-doc"
|
||
}, doc) : null, children), actions ? /*#__PURE__*/React.createElement("div", {
|
||
className: "m-gate-actions"
|
||
}, actions) : null) : null);
|
||
}
|
||
function GateStripe() {
|
||
ensureCss();
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: "m-gate-stripe"
|
||
});
|
||
}
|
||
Object.assign(__ds_scope, { GateCard, GateStripe });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/surfaces/GateCard.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/surfaces/Panel.jsx
|
||
try { (() => {
|
||
function Panel({
|
||
children,
|
||
padding = '14px',
|
||
style
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md, 6px)',
|
||
fontFamily: 'var(--mono)',
|
||
color: 'var(--ink)',
|
||
padding,
|
||
...style
|
||
}
|
||
}, children);
|
||
}
|
||
Object.assign(__ds_scope, { Panel });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/surfaces/Panel.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/surfaces/Timeline.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-tl{display:grid;font-family:var(--mono)}
|
||
.m-tl-item{display:flex;gap:12px;align-items:baseline;padding:5px 0 5px 14px;font-size:12px;border-left:2px solid var(--line);position:relative;color:var(--ink)}
|
||
.m-tl-item::before{content:'';position:absolute;left:-4px;top:11px;width:6px;height:6px;border-radius:50%;background:var(--m-tl-c,var(--muted))}
|
||
.m-tl-time{flex:none;color:var(--faint);font-size:11px;min-width:130px}
|
||
.m-tl-text{color:var(--ink)}
|
||
.m-tl-who{color:var(--muted);font-size:11px}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-tl-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-tl-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Timeline({
|
||
items = [],
|
||
style
|
||
}) {
|
||
ensureCss();
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: "m-tl",
|
||
style: style
|
||
}, items.map((it, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
className: "m-tl-item",
|
||
style: it.color ? {
|
||
'--m-tl-c': it.color
|
||
} : null
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-tl-time"
|
||
}, it.time), /*#__PURE__*/React.createElement("span", {
|
||
className: "m-tl-text"
|
||
}, it.text), it.who ? /*#__PURE__*/React.createElement("span", {
|
||
className: "m-tl-who"
|
||
}, it.who) : null)));
|
||
}
|
||
Object.assign(__ds_scope, { Timeline });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/surfaces/Timeline.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// components/surfaces/Toast.jsx
|
||
try { (() => {
|
||
const css = `
|
||
.m-toast{font-family:var(--mono);font-size:12.5px;background:var(--bg-deep);border:1px solid var(--line);color:var(--ink);padding:9px 16px;max-width:70vw;animation:m-toast-in .18s ease both;box-shadow:0 8px 30px rgba(0,0,0,.55);border-radius:var(--radius-md,6px)}
|
||
.m-toast--err{border-color:var(--red);color:var(--red)}
|
||
.m-toast--ok{border-color:var(--green-dim);color:var(--green)}
|
||
.m-toast--warn{border-color:var(--amber-dim);color:var(--amber)}
|
||
@keyframes m-toast-in{from{opacity:0;transform:translateY(8px)}}
|
||
`;
|
||
function ensureCss() {
|
||
if (typeof document === 'undefined' || document.getElementById('m-toast-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-toast-css';
|
||
s.textContent = css;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Toast({
|
||
kind,
|
||
children,
|
||
style
|
||
}) {
|
||
ensureCss();
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
className: 'm-toast' + (kind ? ' m-toast--' + kind : ''),
|
||
style: style
|
||
}, children);
|
||
}
|
||
Object.assign(__ds_scope, { Toast });
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/surfaces/Toast.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/ArchiveSection.jsx
|
||
try { (() => {
|
||
// 已归档区(done / 取消,时间倒序分页)+ 归档详情模态
|
||
function ArchiveRow({
|
||
item,
|
||
t,
|
||
onOpen
|
||
}) {
|
||
const {
|
||
ComplexityBadge,
|
||
StatusChip
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [hover, setHover] = React.useState(false);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => onOpen(item),
|
||
title: t.archiveTip,
|
||
onMouseEnter: () => setHover(true),
|
||
onMouseLeave: () => setHover(false),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
cursor: 'pointer',
|
||
padding: '7px 12px',
|
||
fontSize: 12.5,
|
||
borderBottom: '1px dashed var(--line-soft)',
|
||
background: hover ? 'var(--panel)' : 'transparent'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--muted)',
|
||
fontWeight: 500,
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, item.title, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--faint)',
|
||
fontSize: 10.5,
|
||
marginLeft: 6
|
||
}
|
||
}, item.id)), item.subs ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, t.archiveSubs.replace('{n}', item.subs)) : null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 8
|
||
}
|
||
}), /*#__PURE__*/React.createElement(ComplexityBadge, {
|
||
complexity: item.cplx
|
||
}), /*#__PURE__*/React.createElement(StatusChip, {
|
||
status: item.status,
|
||
label: t.status[item.status]
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 11,
|
||
color: 'var(--faint)'
|
||
},
|
||
title: item.timeFull
|
||
}, item.time));
|
||
}
|
||
function SizeSelect({
|
||
size,
|
||
setSize,
|
||
t
|
||
}) {
|
||
const [open, setOpen] = React.useState(false);
|
||
const [hover, setHover] = React.useState(false);
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'relative',
|
||
display: 'inline-flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("button", {
|
||
onClick: () => setOpen(!open),
|
||
onMouseEnter: () => setHover(true),
|
||
onMouseLeave: () => setHover(false),
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
letterSpacing: '.04em',
|
||
background: 'transparent',
|
||
color: hover || open ? 'var(--green)' : 'var(--muted)',
|
||
border: '1px solid ' + (hover || open ? 'var(--green-dim)' : 'var(--line)'),
|
||
borderRadius: 'var(--radius-sm, 4px)',
|
||
padding: '3px 9px',
|
||
cursor: 'pointer',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 7,
|
||
transition: 'color .12s, border-color .12s'
|
||
}
|
||
}, t.perPage, " ", /*#__PURE__*/React.createElement("b", {
|
||
style: {
|
||
color: 'var(--green)',
|
||
fontSize: 11.5
|
||
}
|
||
}, size), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 8,
|
||
color: 'var(--faint)',
|
||
transform: open ? 'rotate(180deg)' : 'none',
|
||
transition: 'transform .12s'
|
||
}
|
||
}, "\u25BC")), open ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
bottom: 'calc(100% + 5px)',
|
||
right: 0,
|
||
zIndex: 60,
|
||
display: 'grid',
|
||
minWidth: '100%',
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md, 6px)',
|
||
padding: 4,
|
||
boxShadow: '0 10px 30px rgba(0,0,0,.65)',
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, [10, 20, 50, 100].map(n => {
|
||
const active = n === size;
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
key: n,
|
||
onClick: () => {
|
||
setSize(n);
|
||
setOpen(false);
|
||
},
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 11.5,
|
||
fontWeight: active ? 700 : 400,
|
||
textAlign: 'left',
|
||
background: active ? 'var(--panel-2)' : 'transparent',
|
||
color: active ? 'var(--green)' : 'var(--ink)',
|
||
border: 'none',
|
||
borderRadius: 4,
|
||
padding: '6px 12px 6px 8px',
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7
|
||
},
|
||
onMouseEnter: e => {
|
||
if (!active) e.currentTarget.style.background = 'var(--panel)';
|
||
},
|
||
onMouseLeave: e => {
|
||
if (!active) e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 8,
|
||
color: 'var(--green)',
|
||
fontSize: 10
|
||
}
|
||
}, active ? '▍' : ''), n);
|
||
})) : null);
|
||
}
|
||
function ArchivePager({
|
||
page,
|
||
pages,
|
||
size,
|
||
setPage,
|
||
setSize,
|
||
t
|
||
}) {
|
||
const {
|
||
Button
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 12,
|
||
padding: '10px 0',
|
||
justifyContent: 'center',
|
||
fontFamily: 'var(--mono)'
|
||
}
|
||
}, pages > 1 ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
size: "xs",
|
||
disabled: page <= 1,
|
||
onClick: () => setPage(page - 1)
|
||
}, t.pagePrev), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)'
|
||
}
|
||
}, t.pageOf.replace('{a}', page).replace('{b}', pages)), /*#__PURE__*/React.createElement(Button, {
|
||
size: "xs",
|
||
disabled: page >= pages,
|
||
onClick: () => setPage(page + 1)
|
||
}, t.pageNext)) : null, /*#__PURE__*/React.createElement(SizeSelect, {
|
||
size: size,
|
||
setSize: setSize,
|
||
t: t
|
||
}));
|
||
}
|
||
function ArchiveSection({
|
||
items,
|
||
t,
|
||
onOpen
|
||
}) {
|
||
const [page, setPage] = React.useState(1);
|
||
const [size, setSize] = React.useState(20);
|
||
if (!items.length) return null;
|
||
const pages = Math.max(1, Math.ceil(items.length / size));
|
||
const cur = Math.min(page, pages);
|
||
const slice = items.slice((cur - 1) * size, cur * size);
|
||
return /*#__PURE__*/React.createElement("section", {
|
||
style: {
|
||
marginTop: 28,
|
||
opacity: .82
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
letterSpacing: '.22em',
|
||
color: 'var(--muted)',
|
||
textTransform: 'uppercase',
|
||
padding: '18px 0 10px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--faint)'
|
||
}
|
||
}, "\u25A3"), t.archive, " \xB7 ", items.length), /*#__PURE__*/React.createElement("div", null, slice.map(it => /*#__PURE__*/React.createElement(ArchiveRow, {
|
||
key: it.id,
|
||
item: it,
|
||
t: t,
|
||
onOpen: onOpen
|
||
}))), /*#__PURE__*/React.createElement(ArchivePager, {
|
||
page: cur,
|
||
pages: pages,
|
||
size: size,
|
||
setPage: setPage,
|
||
setSize: n => {
|
||
setSize(n);
|
||
setPage(1);
|
||
},
|
||
t: t
|
||
}));
|
||
}
|
||
|
||
// 归档详情模态(只读:属性 / 产出 / 执行历史 / 结果 / 审批 / 时间线)
|
||
function ArchiveModal({
|
||
item,
|
||
t,
|
||
onClose
|
||
}) {
|
||
const {
|
||
ComplexityBadge,
|
||
StatusChip,
|
||
Timeline
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
React.useEffect(() => {
|
||
const onKey = e => {
|
||
if (e.key === 'Escape') onClose();
|
||
};
|
||
window.addEventListener('keydown', onKey);
|
||
return () => window.removeEventListener('keydown', onKey);
|
||
}, [onClose]);
|
||
if (!item) return null;
|
||
const d = item.detail || {};
|
||
const label = text => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
margin: '14px 0 4px'
|
||
}
|
||
}, text);
|
||
const doc = text => /*#__PURE__*/React.createElement("pre", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
borderRadius: 4,
|
||
padding: '10px 12px',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12.5,
|
||
lineHeight: 1.7,
|
||
whiteSpace: 'pre-wrap',
|
||
wordBreak: 'break-word',
|
||
margin: 0,
|
||
color: 'var(--ink)'
|
||
}
|
||
}, text);
|
||
const kvGrid = {
|
||
fontSize: 12,
|
||
display: 'grid',
|
||
gridTemplateColumns: 'auto 1fr',
|
||
gap: '3px 12px',
|
||
margin: 0
|
||
};
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'fixed',
|
||
inset: 0,
|
||
zIndex: 1100,
|
||
display: 'grid',
|
||
placeItems: 'center'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
onClick: onClose,
|
||
style: {
|
||
position: 'absolute',
|
||
inset: 0,
|
||
background: 'rgba(4,6,5,.78)',
|
||
backdropFilter: 'blur(2px)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
width: 'min(860px, 94vw)',
|
||
maxHeight: '92vh',
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-lg, 10px)',
|
||
overflow: 'hidden',
|
||
boxShadow: '0 24px 64px rgba(0,0,0,.6)',
|
||
animation: 'maestro-rise .18s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
flexWrap: 'wrap',
|
||
padding: '12px 16px',
|
||
borderBottom: '1px solid var(--line)',
|
||
background: 'var(--panel-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--bg-deep)',
|
||
background: 'var(--muted)',
|
||
padding: '2px 8px',
|
||
borderRadius: 3
|
||
}
|
||
}, t.archiveDetail), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 700,
|
||
fontSize: 15
|
||
}
|
||
}, item.title), /*#__PURE__*/React.createElement(ComplexityBadge, {
|
||
complexity: item.cplx
|
||
}), /*#__PURE__*/React.createElement(StatusChip, {
|
||
status: item.status,
|
||
label: t.status[item.status]
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}), /*#__PURE__*/React.createElement("button", {
|
||
onClick: onClose,
|
||
title: t.closeTip,
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 13,
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
padding: '4px 8px'
|
||
}
|
||
}, "\u2715")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
overflowY: 'auto',
|
||
padding: '14px 20px 24px',
|
||
fontFamily: 'var(--mono)'
|
||
}
|
||
}, d.attrs ? /*#__PURE__*/React.createElement("dl", {
|
||
style: kvGrid
|
||
}, d.attrs.map(([k, v], i) => /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: i
|
||
}, /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
}
|
||
}, k), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0,
|
||
wordBreak: 'break-all'
|
||
}
|
||
}, v)))) : null, d.spec ? /*#__PURE__*/React.createElement(React.Fragment, null, label('SPEC · 方案'), doc(d.spec)) : null, d.ops ? /*#__PURE__*/React.createElement(React.Fragment, null, label('OPERATIONS · 操作'), doc(d.ops)) : null, d.runs && d.runs.length ? /*#__PURE__*/React.createElement(React.Fragment, null, label(t.runsLabel + '(' + d.runs.length + ')'), /*#__PURE__*/React.createElement("dl", {
|
||
style: kvGrid
|
||
}, d.runs.map((r, i) => /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: i
|
||
}, /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
}
|
||
}, r.kind, " \xB7 ", r.status), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0
|
||
}
|
||
}, r.span, r.ref ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'block',
|
||
color: 'var(--faint)',
|
||
fontSize: 10.5
|
||
}
|
||
}, r.ref) : null))))) : null, d.result ? /*#__PURE__*/React.createElement(React.Fragment, null, label(t.resultLabel), /*#__PURE__*/React.createElement("dl", {
|
||
style: kvGrid
|
||
}, /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
}
|
||
}, t.branch), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0
|
||
}
|
||
}, d.result.branch), /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
}
|
||
}, "commits"), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0
|
||
}
|
||
}, d.result.commits.join(' · ')), /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
}
|
||
}, "diff"), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0
|
||
}
|
||
}, d.result.diff))) : null, d.approvals && d.approvals.length ? /*#__PURE__*/React.createElement(React.Fragment, null, label(t.approvalsLabel), /*#__PURE__*/React.createElement("dl", {
|
||
style: kvGrid
|
||
}, d.approvals.map((a, i) => /*#__PURE__*/React.createElement(React.Fragment, {
|
||
key: i
|
||
}, /*#__PURE__*/React.createElement("dt", {
|
||
style: {
|
||
color: a.action === 'accept' ? 'var(--green)' : 'var(--red)',
|
||
fontWeight: 700
|
||
}
|
||
}, a.gate, " \xB7 ", a.action === 'accept' ? t.accepted : t.rejected), /*#__PURE__*/React.createElement("dd", {
|
||
style: {
|
||
margin: 0
|
||
}
|
||
}, t.approver, " ", a.actor, " \xB7 ", a.at, a.reason ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'block',
|
||
color: 'var(--amber)'
|
||
}
|
||
}, "\u21B3 ", a.reason) : null))))) : null, d.timeline && d.timeline.length ? /*#__PURE__*/React.createElement(React.Fragment, null, label(t.timelineLabel), /*#__PURE__*/React.createElement(Timeline, {
|
||
items: d.timeline
|
||
})) : null)));
|
||
}
|
||
Object.assign(window, {
|
||
MaestroKitArchiveSection: ArchiveSection,
|
||
MaestroKitArchiveModal: ArchiveModal
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/ArchiveSection.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/EventPanel.jsx
|
||
try { (() => {
|
||
// 右栏:事件流 · 可折叠(折叠后仅图标)
|
||
function MaestroEventIcon({
|
||
size = 16
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", {
|
||
width: size,
|
||
height: size,
|
||
viewBox: "0 0 24 24",
|
||
fill: "none",
|
||
stroke: "currentColor",
|
||
strokeWidth: "2",
|
||
strokeLinecap: "round",
|
||
strokeLinejoin: "round",
|
||
style: {
|
||
flex: 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("polyline", {
|
||
points: "2 12 7 12 10 5 14 19 17 12 22 12"
|
||
}));
|
||
}
|
||
function maestroPanelToggleProps(onClick, title) {
|
||
return {
|
||
onClick,
|
||
title,
|
||
style: {
|
||
cursor: 'pointer',
|
||
flex: 'none',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
lineHeight: 1,
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-sm, 4px)',
|
||
padding: '4px 7px'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.color = 'var(--green)';
|
||
e.currentTarget.style.borderColor = 'var(--green-dim)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.color = 'var(--muted)';
|
||
e.currentTarget.style.borderColor = 'var(--line)';
|
||
}
|
||
};
|
||
}
|
||
function EventPanel({
|
||
events,
|
||
collapsed,
|
||
onToggleCollapse,
|
||
t
|
||
}) {
|
||
const {
|
||
EventItem,
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
if (collapsed) {
|
||
return /*#__PURE__*/React.createElement("aside", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
borderLeft: '1px solid var(--line)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
padding: '16px 0',
|
||
gap: 14
|
||
}
|
||
}, /*#__PURE__*/React.createElement("button", maestroPanelToggleProps(onToggleCollapse, t.expandEvents), "\xAB"), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--muted)'
|
||
},
|
||
title: t.events + ' · ' + events.length
|
||
}, /*#__PURE__*/React.createElement(MaestroEventIcon, {
|
||
size: 18
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)',
|
||
letterSpacing: '.04em'
|
||
}
|
||
}, events.length));
|
||
}
|
||
return /*#__PURE__*/React.createElement("aside", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
borderLeft: '1px solid var(--line)',
|
||
overflowY: 'auto',
|
||
paddingBottom: 30
|
||
}
|
||
}, /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: t.events,
|
||
action: /*#__PURE__*/React.createElement("button", maestroPanelToggleProps(onToggleCollapse, t.collapseEvents), "\xBB"),
|
||
style: {
|
||
padding: '14px 14px 10px',
|
||
position: 'sticky',
|
||
top: 0,
|
||
zIndex: 5,
|
||
background: 'linear-gradient(var(--bg-deep) 75%, transparent)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("ul", {
|
||
style: {
|
||
listStyle: 'none',
|
||
padding: '0 14px',
|
||
margin: 0
|
||
}
|
||
}, events.map((e, i) => /*#__PURE__*/React.createElement(EventItem, {
|
||
key: i,
|
||
type: e.type,
|
||
label: t.eventTypes[e.type],
|
||
time: e.time,
|
||
detail: e.detail
|
||
}))));
|
||
}
|
||
window.MaestroKitEventPanel = EventPanel;
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/EventPanel.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/GateSection.jsx
|
||
try { (() => {
|
||
// 全屏预览:读完整方案 + 就地裁决
|
||
function GatePreview({
|
||
item,
|
||
t,
|
||
onDecide,
|
||
onClose
|
||
}) {
|
||
const {
|
||
ComplexityBadge,
|
||
Button,
|
||
Textarea
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [rejecting, setRejecting] = React.useState(false);
|
||
const [reason, setReason] = React.useState('');
|
||
React.useEffect(() => {
|
||
const onKey = e => {
|
||
if (e.key === 'Escape') onClose();
|
||
};
|
||
window.addEventListener('keydown', onKey);
|
||
return () => window.removeEventListener('keydown', onKey);
|
||
}, [onClose]);
|
||
if (!item) return null;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'fixed',
|
||
inset: 0,
|
||
zIndex: 1100,
|
||
display: 'grid',
|
||
placeItems: 'center'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
onClick: onClose,
|
||
style: {
|
||
position: 'absolute',
|
||
inset: 0,
|
||
background: 'rgba(4,6,5,.86)',
|
||
backdropFilter: 'blur(3px)'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
width: 'min(1080px, 94vw)',
|
||
height: '94vh',
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--violet-dim)',
|
||
borderRadius: 'var(--radius-lg, 10px)',
|
||
overflow: 'hidden',
|
||
boxShadow: '0 0 0 1px var(--line-soft), 0 24px 64px rgba(0,0,0,.6)',
|
||
animation: 'maestro-rise .18s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
flexWrap: 'wrap',
|
||
padding: '12px 16px',
|
||
borderBottom: '1px solid var(--line)',
|
||
background: 'var(--panel-2)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--bg)',
|
||
background: 'var(--violet)',
|
||
padding: '2px 8px',
|
||
borderRadius: 3
|
||
}
|
||
}, t.gates[item.gate]), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 700,
|
||
fontSize: 15
|
||
}
|
||
}, item.title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)'
|
||
}
|
||
}, item.meta), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}), /*#__PURE__*/React.createElement("button", {
|
||
onClick: onClose,
|
||
title: t.closeTip,
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 13,
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
padding: '4px 8px'
|
||
}
|
||
}, "\u2715")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
overflowY: 'auto',
|
||
padding: '16px 20px 28px',
|
||
fontFamily: 'var(--mono)'
|
||
}
|
||
}, item.docLabel ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
marginBottom: 6
|
||
}
|
||
}, item.docLabel) : null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
borderRadius: 4,
|
||
padding: '12px 16px',
|
||
fontSize: 13.5,
|
||
lineHeight: 1.7,
|
||
whiteSpace: 'pre-wrap',
|
||
wordBreak: 'break-word',
|
||
color: 'var(--ink)'
|
||
}
|
||
}, item.doc)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
flexWrap: 'wrap',
|
||
padding: '12px 16px',
|
||
borderTop: '1px solid var(--line)',
|
||
background: 'var(--panel-2)'
|
||
}
|
||
}, rejecting ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flexBasis: '100%',
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Textarea, {
|
||
danger: true,
|
||
placeholder: t.rejectPlaceholder,
|
||
minHeight: 56,
|
||
value: reason,
|
||
onChange: setReason
|
||
})), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
disabled: !reason.trim(),
|
||
onClick: () => {
|
||
onDecide(item, 'reject', reason);
|
||
onClose();
|
||
}
|
||
}, t.confirmReject), /*#__PURE__*/React.createElement(Button, {
|
||
onClick: () => {
|
||
setRejecting(false);
|
||
setReason('');
|
||
}
|
||
}, t.cancel)) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "accept",
|
||
onClick: () => {
|
||
onDecide(item, 'accept');
|
||
onClose();
|
||
}
|
||
}, t.accept), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
onClick: () => setRejecting(true)
|
||
}, t.reject)))));
|
||
}
|
||
|
||
// 审批闸区:斜纹条 + GateCard 列表(accept/reject + 驳回必填理由)
|
||
function GateSection({
|
||
approvals,
|
||
onDecide,
|
||
t
|
||
}) {
|
||
const {
|
||
GateCard,
|
||
GateStripe,
|
||
Button,
|
||
Textarea,
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [rejecting, setRejecting] = React.useState(null);
|
||
const [reason, setReason] = React.useState('');
|
||
const [preview, setPreview] = React.useState(null);
|
||
const [folded, setFolded] = React.useState(() => new Set());
|
||
const toggleFold = id => setFolded(prev => {
|
||
const next = new Set(prev);
|
||
next.has(id) ? next.delete(id) : next.add(id);
|
||
return next;
|
||
});
|
||
if (approvals.length === 0) return null;
|
||
return /*#__PURE__*/React.createElement("section", {
|
||
style: {
|
||
marginTop: 18
|
||
}
|
||
}, /*#__PURE__*/React.createElement(GateStripe, null), /*#__PURE__*/React.createElement(SectionHead, {
|
||
mark: "violet",
|
||
title: t.gateSection,
|
||
style: {
|
||
paddingTop: 12,
|
||
color: 'var(--violet)'
|
||
}
|
||
}), approvals.map(a => {
|
||
const isFolded = folded.has(a.id);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
key: a.id,
|
||
style: {
|
||
marginBottom: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(GateCard, {
|
||
gate: a.gate,
|
||
kindLabel: t.gates[a.gate],
|
||
title: a.title,
|
||
meta: a.meta,
|
||
docLabel: a.docLabel,
|
||
doc: a.doc,
|
||
collapsed: isFolded,
|
||
foldable: true,
|
||
onToggleFold: () => toggleFold(a.id),
|
||
foldTitle: isFolded ? t.gateExpand : t.gateCollapse,
|
||
onHeaderDoubleClick: () => setPreview(a),
|
||
headerTitle: t.gateDblTip,
|
||
headerExtra: /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
title: t.fullRead,
|
||
onClick: () => setPreview(a),
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
lineHeight: 1,
|
||
cursor: 'pointer',
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-sm,4px)',
|
||
padding: '3px 7px'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.color = 'var(--violet)';
|
||
e.currentTarget.style.borderColor = 'var(--violet-dim)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.color = 'var(--muted)';
|
||
e.currentTarget.style.borderColor = 'var(--line)';
|
||
}
|
||
}, "\u26F6"),
|
||
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "accept",
|
||
onClick: () => onDecide(a, 'accept')
|
||
}, t.accept), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
onClick: () => setRejecting(rejecting === a.id ? null : a.id)
|
||
}, t.reject), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
size: "xs",
|
||
title: t.fullRead,
|
||
onClick: () => setPreview(a)
|
||
}, "\u26F6 ", t.fullRead)))
|
||
}, rejecting === a.id ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10,
|
||
alignItems: 'flex-start',
|
||
marginTop: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Textarea, {
|
||
danger: true,
|
||
placeholder: t.rejectPlaceholder,
|
||
minHeight: 56,
|
||
value: reason,
|
||
onChange: setReason
|
||
}), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
disabled: !reason.trim(),
|
||
onClick: () => {
|
||
onDecide(a, 'reject', reason);
|
||
setRejecting(null);
|
||
setReason('');
|
||
}
|
||
}, t.confirmReject)) : null));
|
||
}), /*#__PURE__*/React.createElement(GatePreview, {
|
||
item: preview,
|
||
t: t,
|
||
onDecide: onDecide,
|
||
onClose: () => setPreview(null)
|
||
}));
|
||
}
|
||
window.MaestroKitGateSection = GateSection;
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/GateSection.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/Sidebar.jsx
|
||
try { (() => {
|
||
// 左栏:logo + 项目列表(git 图标)+ WS 状态脚 · 可折叠(折叠后仅图标)
|
||
// 项目 logo:图片优先(原型无图),回退首字母色块 hsl(h 45% 60%)
|
||
function ProjectLogo({
|
||
project,
|
||
size = 26
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
width: size,
|
||
height: size,
|
||
borderRadius: 5,
|
||
display: 'grid',
|
||
placeItems: 'center',
|
||
fontSize: size * 0.5,
|
||
fontWeight: 700,
|
||
color: '#0a0d0b',
|
||
background: 'hsl(' + (project.hue || 140) + ' 45% 60%)'
|
||
}
|
||
}, (project.name || '?')[0].toUpperCase());
|
||
}
|
||
function MaestroGitIcon({
|
||
size = 16
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", {
|
||
width: size,
|
||
height: size,
|
||
viewBox: "0 0 24 24",
|
||
fill: "none",
|
||
stroke: "currentColor",
|
||
strokeWidth: "2",
|
||
strokeLinecap: "round",
|
||
strokeLinejoin: "round",
|
||
style: {
|
||
flex: 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("line", {
|
||
x1: "6",
|
||
y1: "3",
|
||
x2: "6",
|
||
y2: "15"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "18",
|
||
cy: "6",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "6",
|
||
cy: "18",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M18 9a9 9 0 0 1-9 9"
|
||
}));
|
||
}
|
||
|
||
// 像素章鱼 mark(折叠态 logo)
|
||
function MaestroMark({
|
||
scale = 2.2
|
||
}) {
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
const MAP = ['.....LLLLL.....', '...LLLLLLLLL...', '..GGGGGGGGGGG..', '..GGEEGGGEEGG..', '..GGEEGGGEEGG..', '..GGGGGGGGGGG..', '...GGGGGGGGG...', '...G..G.G..G...', '...G..G.G..G...', '..G...G.G...G..', '..D...D.D...D..', '.D...D...D...D.'];
|
||
const INK = {
|
||
L: '#79ec94',
|
||
G: '#5fdd7d',
|
||
D: '#2e6b3d',
|
||
E: '#070908'
|
||
};
|
||
const ctx = ref.current.getContext('2d');
|
||
MAP.forEach((row, y) => [...row].forEach((ch, x) => {
|
||
if (INK[ch]) {
|
||
ctx.fillStyle = INK[ch];
|
||
ctx.fillRect(x, y, 1, 1);
|
||
}
|
||
}));
|
||
}, []);
|
||
return /*#__PURE__*/React.createElement("canvas", {
|
||
ref: ref,
|
||
width: "15",
|
||
height: "12",
|
||
style: {
|
||
width: 15 * scale,
|
||
height: 12 * scale,
|
||
imageRendering: 'pixelated',
|
||
filter: 'drop-shadow(0 0 6px rgba(95,221,125,.4))'
|
||
}
|
||
});
|
||
}
|
||
|
||
// 项目状态:运行中(青脉冲) / 暂停(faint) / 阻塞(琥珀) / 空闲(muted)
|
||
function projStateMeta(state, t) {
|
||
return {
|
||
running: {
|
||
color: 'var(--cyan)',
|
||
pulse: true,
|
||
label: t.projRunning
|
||
},
|
||
paused: {
|
||
color: 'var(--faint)',
|
||
pulse: false,
|
||
label: t.projPaused
|
||
},
|
||
blocked: {
|
||
color: 'var(--amber)',
|
||
pulse: true,
|
||
label: t.projBlocked
|
||
},
|
||
idle: {
|
||
color: 'var(--muted)',
|
||
pulse: false,
|
||
label: t.projIdle
|
||
}
|
||
}[state] || {
|
||
color: 'var(--muted)',
|
||
pulse: false,
|
||
label: t.projIdle
|
||
};
|
||
}
|
||
function ProjStatusDot({
|
||
meta,
|
||
size = 7
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
width: size,
|
||
height: size,
|
||
borderRadius: '50%',
|
||
background: meta.color,
|
||
boxShadow: '0 0 7px ' + meta.color,
|
||
animation: meta.pulse ? 'maestro-pulse 1.4s infinite' : 'none'
|
||
}
|
||
});
|
||
}
|
||
|
||
// 侧栏底部小行:图标 + 主文 + 副文(折叠时仅图标,hover 高亮)
|
||
function SideRow({
|
||
icon,
|
||
label,
|
||
detail,
|
||
onClick,
|
||
collapsed,
|
||
title,
|
||
accent
|
||
}) {
|
||
const interactive = !!onClick;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
onClick: onClick,
|
||
title: title || label,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: collapsed ? '9px 0' : '8px 12px',
|
||
minHeight: 40,
|
||
justifyContent: collapsed ? 'center' : 'flex-start',
|
||
cursor: interactive ? 'pointer' : 'default',
|
||
transition: 'background .1s'
|
||
},
|
||
onMouseEnter: interactive ? e => {
|
||
e.currentTarget.style.background = 'var(--panel)';
|
||
} : undefined,
|
||
onMouseLeave: interactive ? e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
} : undefined
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
color: accent || 'var(--muted)',
|
||
display: 'inline-flex'
|
||
}
|
||
}, icon), !collapsed ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 1,
|
||
minWidth: 0,
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 12,
|
||
fontWeight: 600,
|
||
color: 'var(--ink)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, label), detail ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10,
|
||
color: 'var(--faint)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, detail) : null) : null, !collapsed && interactive ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
color: 'var(--faint)',
|
||
fontSize: 11
|
||
}
|
||
}, "\u203A") : null);
|
||
}
|
||
const sIco = {
|
||
width: 16,
|
||
height: 16,
|
||
viewBox: '0 0 24 24',
|
||
fill: 'none',
|
||
stroke: 'currentColor',
|
||
strokeWidth: 2,
|
||
strokeLinecap: 'round',
|
||
strokeLinejoin: 'round',
|
||
style: {
|
||
flex: 'none'
|
||
}
|
||
};
|
||
function IcoAgents() {
|
||
return /*#__PURE__*/React.createElement("svg", sIco, /*#__PURE__*/React.createElement("circle", {
|
||
cx: "12",
|
||
cy: "12",
|
||
r: "8"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "12",
|
||
cy: "12",
|
||
r: "3",
|
||
fill: "currentColor",
|
||
stroke: "none"
|
||
}));
|
||
}
|
||
function IcoGlobalCfg() {
|
||
return /*#__PURE__*/React.createElement("svg", sIco, /*#__PURE__*/React.createElement("circle", {
|
||
cx: "12",
|
||
cy: "12",
|
||
r: "9"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "3",
|
||
y1: "12",
|
||
x2: "21",
|
||
y2: "12"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M12 3a14 14 0 0 0 0 18a14 14 0 0 0 0-18"
|
||
}));
|
||
}
|
||
function UserRow({
|
||
user,
|
||
t,
|
||
collapsed
|
||
}) {
|
||
const [open, setOpen] = React.useState(false);
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
const avatar = /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
width: 26,
|
||
height: 26,
|
||
borderRadius: '50%',
|
||
display: 'grid',
|
||
placeItems: 'center',
|
||
fontSize: 12,
|
||
fontWeight: 700,
|
||
color: '#0a0d0b',
|
||
background: 'hsl(' + (user.hue || 200) + ' 50% 62%)'
|
||
}
|
||
}, user.initial);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'relative',
|
||
borderTop: '1px solid var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => setOpen(!open),
|
||
title: user.name + ' · ' + user.plan,
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: collapsed ? '10px 0' : '10px 12px',
|
||
justifyContent: collapsed ? 'center' : 'flex-start',
|
||
cursor: 'pointer',
|
||
transition: 'background .1s'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--panel)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, avatar, !collapsed ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 1,
|
||
minWidth: 0,
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 12.5,
|
||
fontWeight: 600,
|
||
color: 'var(--ink)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, user.name), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10,
|
||
color: 'var(--green)',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, user.plan)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
color: 'var(--faint)',
|
||
fontSize: 11,
|
||
transform: open ? 'rotate(180deg)' : 'none',
|
||
transition: 'transform .12s'
|
||
}
|
||
}, "\u25B4")) : null), open ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: collapsed ? 'fixed' : 'absolute',
|
||
...(collapsed ? {
|
||
left: 58,
|
||
bottom: 14,
|
||
width: 180
|
||
} : {
|
||
bottom: 'calc(100% + 4px)',
|
||
left: 12,
|
||
right: 12,
|
||
minWidth: 160
|
||
}),
|
||
zIndex: 80,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md,6px)',
|
||
boxShadow: '0 10px 30px rgba(0,0,0,.65)',
|
||
padding: 6,
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '6px 10px',
|
||
borderBottom: '1px solid var(--line-soft)',
|
||
marginBottom: 4
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 12,
|
||
fontWeight: 600
|
||
}
|
||
}, user.name, " ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--faint)',
|
||
fontWeight: 400
|
||
}
|
||
}, user.handle)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--green)',
|
||
marginTop: 2
|
||
}
|
||
}, t.gUserPlan, " \xB7 ", user.plan)), [t.gUserSettings, t.gUserSignOut].map((label, i) => /*#__PURE__*/React.createElement("div", {
|
||
key: label,
|
||
style: {
|
||
padding: '6px 10px',
|
||
fontSize: 12,
|
||
color: i === 1 ? 'var(--red)' : 'var(--ink)',
|
||
cursor: 'pointer',
|
||
borderRadius: 3
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--panel-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, label))) : null);
|
||
}
|
||
function fmtTokens(n) {
|
||
if (n >= 1e6) return (n / 1e6).toFixed(1).replace(/\.0$/, '') + 'M';
|
||
if (n >= 1e3) return Math.round(n / 1e3) + 'K';
|
||
return String(n);
|
||
}
|
||
function AgentsRow({
|
||
global,
|
||
summary,
|
||
t,
|
||
collapsed
|
||
}) {
|
||
const [open, setOpen] = React.useState(false);
|
||
const [pos, setPos] = React.useState(null);
|
||
const ref = React.useRef(null);
|
||
const rowRef = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target) && rowRef.current && !rowRef.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
const toggle = () => {
|
||
if (!open && rowRef.current) {
|
||
const r = rowRef.current.getBoundingClientRect();
|
||
const W = 286;
|
||
const left = collapsed ? r.right + 6 : Math.min(r.left, window.innerWidth - W - 8);
|
||
setPos({
|
||
left,
|
||
bottom: window.innerHeight - r.top + 6,
|
||
width: W
|
||
});
|
||
}
|
||
setOpen(o => !o);
|
||
};
|
||
const maxTok = Math.max(...summary.byProject.map(p => p.tokens), 1);
|
||
const detail = t.gAgentsDetail.replace('{p}', global.runningProjects).replace('{P}', global.projectCount).replace('{a}', global.runningAgents);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
ref: rowRef
|
||
}, /*#__PURE__*/React.createElement(SideRow, {
|
||
collapsed: collapsed,
|
||
icon: /*#__PURE__*/React.createElement(IcoAgents, null),
|
||
accent: "var(--cyan)",
|
||
onClick: toggle,
|
||
label: t.gAgents,
|
||
detail: detail,
|
||
title: t.gAgents + ' · ' + detail
|
||
})), open && pos ? /*#__PURE__*/React.createElement("div", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'fixed',
|
||
left: pos.left,
|
||
bottom: pos.bottom,
|
||
width: pos.width,
|
||
zIndex: 1000,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md,6px)',
|
||
boxShadow: '0 12px 34px rgba(0,0,0,.7)',
|
||
padding: '12px 14px',
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7,
|
||
fontSize: 10.5,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--muted)',
|
||
marginBottom: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--cyan)'
|
||
}
|
||
}, "\u258D"), t.gAgents.toUpperCase(), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
fontWeight: 400,
|
||
letterSpacing: '.04em',
|
||
color: 'var(--faint)'
|
||
}
|
||
}, t.apWeek)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: '1fr 1fr',
|
||
gap: 1,
|
||
background: 'var(--line-soft)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderRadius: 4,
|
||
overflow: 'hidden',
|
||
marginBottom: 12
|
||
}
|
||
}, [[fmtTokens(summary.tokensWeek), t.apTokens, 'var(--cyan)'], ['$' + summary.costWeek.toFixed(1), t.apCost, 'var(--green)'], [summary.runsWeek, t.apRuns, 'var(--ink)'], [summary.activeNow + ' / ' + global.maxAgents, t.apActive, summary.activeNow ? 'var(--cyan)' : 'var(--faint)']].map(([v, k, c], i) => /*#__PURE__*/React.createElement("div", {
|
||
key: i,
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
padding: '8px 10px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 16,
|
||
fontWeight: 700,
|
||
color: c,
|
||
letterSpacing: '.02em'
|
||
}
|
||
}, v), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.06em',
|
||
marginTop: 1
|
||
}
|
||
}, k)))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--faint)',
|
||
marginBottom: 7
|
||
}
|
||
}, t.apPerProj), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gap: 9
|
||
}
|
||
}, summary.byProject.map(p => /*#__PURE__*/React.createElement("div", {
|
||
key: p.id
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
marginBottom: 3
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
width: 16,
|
||
height: 16,
|
||
borderRadius: 4,
|
||
display: 'grid',
|
||
placeItems: 'center',
|
||
fontSize: 9,
|
||
fontWeight: 700,
|
||
color: '#0a0d0b',
|
||
background: 'hsl(' + p.hue + ' 45% 60%)'
|
||
}
|
||
}, p.name[0].toUpperCase()), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 12,
|
||
fontWeight: 600,
|
||
color: 'var(--ink)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, p.name), p.active > 0 ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 4,
|
||
fontSize: 9.5,
|
||
color: 'var(--cyan)',
|
||
border: '1px solid var(--cyan-dim)',
|
||
borderRadius: 3,
|
||
padding: '0 5px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 5,
|
||
height: 5,
|
||
borderRadius: '50%',
|
||
background: 'var(--cyan)',
|
||
boxShadow: '0 0 6px var(--cyan)',
|
||
animation: 'maestro-pulse .9s infinite'
|
||
}
|
||
}), p.active) : /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 9.5,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, t.apIdle), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
flex: 'none',
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
color: 'var(--cyan)'
|
||
}
|
||
}, fmtTokens(p.tokens))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
paddingLeft: 24
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
height: 4,
|
||
background: 'var(--panel-2)',
|
||
borderRadius: 2,
|
||
overflow: 'hidden'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'block',
|
||
height: '100%',
|
||
width: p.tokens / maxTok * 100 + '%',
|
||
background: 'var(--cyan)',
|
||
boxShadow: '0 0 6px rgba(89,200,216,.5)'
|
||
}
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 10,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, p.runs, " ", t.apRuns)))))) : null);
|
||
}
|
||
function GlobalConfigRow({
|
||
global,
|
||
t,
|
||
collapsed
|
||
}) {
|
||
const {
|
||
Select
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [open, setOpen] = React.useState(false);
|
||
const [pos, setPos] = React.useState(null);
|
||
const ref = React.useRef(null);
|
||
const rowRef = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target) && rowRef.current && !rowRef.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
const toggle = () => {
|
||
if (!open && rowRef.current) {
|
||
const r = rowRef.current.getBoundingClientRect();
|
||
const W = 250;
|
||
// 优先在行上方对齐左缘;折叠态贴侧栏右侧
|
||
const left = collapsed ? r.right + 6 : Math.min(r.left, window.innerWidth - W - 8);
|
||
setPos({
|
||
left,
|
||
bottom: window.innerHeight - r.top + 6,
|
||
width: W
|
||
});
|
||
}
|
||
setOpen(o => !o);
|
||
};
|
||
const stat = (k, v, accent) => /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
justifyContent: 'space-between',
|
||
gap: 12,
|
||
padding: '5px 0',
|
||
borderBottom: '1px solid var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.06em'
|
||
}
|
||
}, k), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 12,
|
||
fontWeight: 600,
|
||
color: accent || 'var(--ink)'
|
||
}
|
||
}, v));
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'relative'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
ref: rowRef
|
||
}, /*#__PURE__*/React.createElement(SideRow, {
|
||
collapsed: collapsed,
|
||
icon: /*#__PURE__*/React.createElement(IcoGlobalCfg, null),
|
||
onClick: toggle,
|
||
label: t.gConfig,
|
||
detail: t.gConfigDetail.replace('{n}', global.maxAgents).replace('{v}', global.daemon),
|
||
title: t.gConfig
|
||
})), open && pos ? /*#__PURE__*/React.createElement("div", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'fixed',
|
||
left: pos.left,
|
||
bottom: pos.bottom,
|
||
width: pos.width,
|
||
zIndex: 1000,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md,6px)',
|
||
boxShadow: '0 12px 34px rgba(0,0,0,.7)',
|
||
padding: '12px 14px',
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7,
|
||
fontSize: 10.5,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--muted)',
|
||
marginBottom: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--cyan)'
|
||
}
|
||
}, "\u258D"), t.gConfig.toUpperCase()), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginBottom: 12
|
||
}
|
||
}, stat('daemon', global.daemon, 'var(--green)'), stat('port', ':' + global.port), stat('uptime', global.uptime), stat(t.gAgents, global.runningAgents + ' / ' + global.maxAgents, 'var(--cyan)')), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement("label", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 4,
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.08em'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", null, t.maxConcurrency), /*#__PURE__*/React.createElement(Select, {
|
||
defaultValue: String(global.maxAgents),
|
||
style: {
|
||
width: '100%'
|
||
},
|
||
options: ['1', '2', '4', '6', '8'].map(n => ({
|
||
value: n,
|
||
label: n
|
||
}))
|
||
})), /*#__PURE__*/React.createElement("label", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 4,
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.08em'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", null, t.workMode), /*#__PURE__*/React.createElement(Select, {
|
||
defaultValue: global.autonomy,
|
||
style: {
|
||
width: '100%'
|
||
},
|
||
options: Object.entries(t.autonomy).map(([value, label]) => ({
|
||
value,
|
||
label
|
||
}))
|
||
})))) : null);
|
||
}
|
||
function Sidebar({
|
||
projects,
|
||
currentId,
|
||
onSelect,
|
||
onNewProject,
|
||
collapsed,
|
||
onToggleCollapse,
|
||
t,
|
||
global,
|
||
user,
|
||
summary,
|
||
onGlobalConfig
|
||
}) {
|
||
const {
|
||
Button
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("aside", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
borderRight: '1px solid var(--line)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
overflowY: 'auto',
|
||
overflowX: 'hidden'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: collapsed ? '16px 0 12px' : '20px 16px 14px',
|
||
borderBottom: '1px solid var(--line-soft)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: collapsed ? 'center' : 'flex-start'
|
||
}
|
||
}, collapsed ? /*#__PURE__*/React.createElement(MaestroMark, null) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(MaestroMark, {
|
||
scale: 1.8
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 19,
|
||
fontWeight: 700,
|
||
letterSpacing: '.28em',
|
||
color: 'var(--green)',
|
||
textShadow: '0 0 12px rgba(95,221,125,.45)'
|
||
}
|
||
}, "MAESTRO", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 1,
|
||
animation: 'maestro-blink 1.1s steps(1) infinite'
|
||
}
|
||
}, "\u25AE"))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginTop: 5,
|
||
fontSize: 9,
|
||
fontWeight: 600,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.2em',
|
||
lineHeight: 1.7,
|
||
textTransform: 'uppercase'
|
||
}
|
||
}, t.logoSub))), !collapsed ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6,
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
letterSpacing: '.22em',
|
||
color: 'var(--muted)',
|
||
padding: '16px 16px 8px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--green)'
|
||
}
|
||
}, "\u258D"), t.projects, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
size: "xs",
|
||
onClick: onNewProject
|
||
}, t.newProject))) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
height: 12
|
||
}
|
||
}), /*#__PURE__*/React.createElement("ul", {
|
||
style: {
|
||
listStyle: 'none',
|
||
flex: 1,
|
||
margin: 0,
|
||
padding: 0
|
||
}
|
||
}, projects.map(p => {
|
||
const active = p.id === currentId;
|
||
const meta = projStateMeta(p.state, t);
|
||
return /*#__PURE__*/React.createElement("li", {
|
||
key: p.id,
|
||
onClick: () => onSelect(p.id),
|
||
title: p.name + ' · ' + meta.label + (p.pending ? ' · ' + t.projPendingTip.replace('{n}', p.pending) : ''),
|
||
style: {
|
||
position: 'relative',
|
||
padding: collapsed ? '10px 0' : '9px 14px 9px 12px',
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 9,
|
||
justifyContent: collapsed ? 'center' : 'flex-start',
|
||
borderLeft: '2px solid ' + (active ? 'var(--green)' : 'transparent'),
|
||
background: active ? 'var(--panel-2)' : 'transparent',
|
||
color: active ? 'var(--green)' : 'var(--muted)'
|
||
},
|
||
onMouseEnter: e => {
|
||
if (!active) e.currentTarget.style.background = 'var(--panel)';
|
||
},
|
||
onMouseLeave: e => {
|
||
if (!active) e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement(ProjectLogo, {
|
||
project: p,
|
||
size: collapsed ? 26 : 24
|
||
}), !collapsed ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 1,
|
||
minWidth: 0,
|
||
flex: 1
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 600,
|
||
fontSize: 13,
|
||
color: active ? 'var(--green)' : 'var(--ink)'
|
||
}
|
||
}, p.name), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, p.path)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 6
|
||
}
|
||
}, p.pending > 0 ? /*#__PURE__*/React.createElement("span", {
|
||
title: t.projPendingTip.replace('{n}', p.pending),
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 9.5,
|
||
fontWeight: 700,
|
||
lineHeight: '15px',
|
||
minWidth: 15,
|
||
height: 15,
|
||
textAlign: 'center',
|
||
padding: '0 4px',
|
||
color: 'var(--bg-deep)',
|
||
background: 'var(--violet)',
|
||
borderRadius: 8
|
||
}
|
||
}, p.pending) : null, /*#__PURE__*/React.createElement(ProjStatusDot, {
|
||
meta: meta
|
||
}))) : /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
top: 7,
|
||
right: 9,
|
||
display: 'flex',
|
||
alignItems: 'center'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(ProjStatusDot, {
|
||
meta: meta,
|
||
size: p.pending > 0 ? 8 : 6
|
||
})));
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
borderTop: '1px solid var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(AgentsRow, {
|
||
global: global,
|
||
summary: summary,
|
||
t: t,
|
||
collapsed: collapsed
|
||
}), /*#__PURE__*/React.createElement(GlobalConfigRow, {
|
||
global: global,
|
||
t: t,
|
||
collapsed: collapsed
|
||
})), /*#__PURE__*/React.createElement(UserRow, {
|
||
user: user,
|
||
t: t,
|
||
collapsed: collapsed
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
borderTop: '1px solid var(--line-soft)',
|
||
padding: collapsed ? '10px 0' : '10px 12px',
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 7,
|
||
justifyContent: collapsed ? 'center' : 'flex-start'
|
||
}
|
||
}, !collapsed ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: '50%',
|
||
background: 'var(--green)',
|
||
boxShadow: '0 0 8px var(--green)',
|
||
display: 'inline-block',
|
||
flex: 'none'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
overflow: 'hidden',
|
||
whiteSpace: 'nowrap',
|
||
textOverflow: 'ellipsis'
|
||
}
|
||
}, t.connected)) : null, /*#__PURE__*/React.createElement("button", {
|
||
onClick: onToggleCollapse,
|
||
title: collapsed ? t.expandSide : t.collapseSide,
|
||
style: {
|
||
marginLeft: collapsed ? 0 : 'auto',
|
||
flex: 'none',
|
||
cursor: 'pointer',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
lineHeight: 1,
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-sm, 4px)',
|
||
padding: '4px 7px'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.color = 'var(--green)';
|
||
e.currentTarget.style.borderColor = 'var(--green-dim)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.color = 'var(--muted)';
|
||
e.currentTarget.style.borderColor = 'var(--line)';
|
||
}
|
||
}, collapsed ? '»' : '«')));
|
||
}
|
||
window.MaestroKitSidebar = Sidebar;
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/Sidebar.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/TaskTree.jsx
|
||
try { (() => {
|
||
// 任务树:筛选栏(搜索+复杂度+状态分组)+ 折叠层级 + 复杂度可点换档 + 依赖可视化跳转 + 展开详情;新建任务表单
|
||
const KIT_FILTER_GROUPS = [['todo', ['init', 'ready', 'blocked']], ['doing', ['analyzing', 'speccing', 'queued', 'executing', 'decomposed']], ['gate', ['plan_review', 'spec_review', 'exec_review']], ['bad', ['failed', 'needs_attention']], ['hold', ['paused', 'cancelled']], ['done', ['done']]];
|
||
function kitFlatten(tasks, map = new Map()) {
|
||
for (const tk of tasks) {
|
||
map.set(tk.id, tk);
|
||
if (tk.children) kitFlatten(tk.children, map);
|
||
}
|
||
return map;
|
||
}
|
||
|
||
// 复杂度徽章 + 点击换档下拉
|
||
function CplxPicker({
|
||
task,
|
||
cplx,
|
||
onChange
|
||
}) {
|
||
const {
|
||
ComplexityBadge
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [open, setOpen] = React.useState(false);
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'relative',
|
||
display: 'inline-flex',
|
||
flex: 'none'
|
||
},
|
||
onClick: e => e.stopPropagation()
|
||
}, /*#__PURE__*/React.createElement("button", {
|
||
onClick: () => setOpen(!open),
|
||
title: "\u70B9\u51FB\u8C03\u6574\u590D\u6742\u5EA6",
|
||
style: {
|
||
background: 'none',
|
||
border: 'none',
|
||
padding: 0,
|
||
cursor: 'pointer',
|
||
display: 'inline-flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(ComplexityBadge, {
|
||
complexity: cplx
|
||
})), open ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
top: 'calc(100% + 5px)',
|
||
right: 0,
|
||
zIndex: 60,
|
||
display: 'flex',
|
||
gap: 5,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md, 6px)',
|
||
padding: 6,
|
||
boxShadow: '0 10px 30px rgba(0,0,0,.65)',
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, ['hard', 'medium', 'easy'].map(v => /*#__PURE__*/React.createElement("button", {
|
||
key: v,
|
||
onClick: () => {
|
||
onChange(task.id, v);
|
||
setOpen(false);
|
||
},
|
||
style: {
|
||
background: 'none',
|
||
border: 'none',
|
||
padding: 0,
|
||
cursor: 'pointer',
|
||
display: 'inline-flex',
|
||
outline: v === cplx ? '1px solid currentColor' : 'none',
|
||
outlineOffset: 1,
|
||
filter: 'none'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.filter = 'brightness(1.35)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.filter = 'none';
|
||
}
|
||
}, /*#__PURE__*/React.createElement(ComplexityBadge, {
|
||
complexity: v
|
||
})))) : null);
|
||
}
|
||
function FilterBar({
|
||
t,
|
||
kw,
|
||
setKw,
|
||
cplxSet,
|
||
toggleCplx,
|
||
statusSet,
|
||
toggleGroup,
|
||
matchCount,
|
||
filtering,
|
||
onClear
|
||
}) {
|
||
const {
|
||
Button
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const chip = (on, color, dim, label, onClick) => /*#__PURE__*/React.createElement("button", {
|
||
key: label,
|
||
onClick: onClick,
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 10,
|
||
fontWeight: 700,
|
||
letterSpacing: '.1em',
|
||
background: on ? 'rgba(95,221,125,.08)' : 'transparent',
|
||
color: on ? color : 'var(--faint)',
|
||
border: '1px solid ' + (on ? dim : 'var(--line)'),
|
||
borderRadius: 3,
|
||
padding: '2px 8px',
|
||
cursor: 'pointer',
|
||
transition: 'all .1s',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, label);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 6,
|
||
padding: '8px 10px',
|
||
marginBottom: 12,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 7
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
alignItems: 'center',
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("input", {
|
||
value: kw,
|
||
onChange: e => setKw(e.target.value),
|
||
placeholder: t.searchPh,
|
||
autoComplete: "off",
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
width: 190,
|
||
padding: '4px 9px',
|
||
background: 'var(--bg-deep)',
|
||
color: 'var(--ink)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-sm, 4px)',
|
||
outline: 'none'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'inline-flex',
|
||
gap: 6
|
||
}
|
||
}, chip(cplxSet.has('hard'), 'var(--red)', 'var(--red-dim)', 'HARD', () => toggleCplx('hard')), chip(cplxSet.has('medium'), 'var(--amber)', 'var(--amber-dim)', 'MED', () => toggleCplx('medium')), chip(cplxSet.has('easy'), 'var(--green)', 'var(--green-dim)', 'EASY', () => toggleCplx('easy'))), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}), filtering ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--amber)',
|
||
letterSpacing: '.08em'
|
||
}
|
||
}, t.matchCount.replace('{n}', matchCount)) : null, filtering ? /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
size: "xs",
|
||
onClick: onClear
|
||
}, t.clearFilter) : null), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
alignItems: 'center',
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, KIT_FILTER_GROUPS.map(([g, sts]) => {
|
||
const on = sts.every(s => statusSet.has(s));
|
||
const part = !on && sts.some(s => statusSet.has(s));
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
key: g,
|
||
onClick: () => toggleGroup(sts),
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 10.5,
|
||
letterSpacing: '.04em',
|
||
background: 'transparent',
|
||
color: on ? 'var(--green)' : part ? 'var(--amber)' : 'var(--muted)',
|
||
border: '1px dashed ' + (on ? 'var(--green-dim)' : part ? 'var(--amber-dim)' : 'var(--line-soft)'),
|
||
borderRadius: 3,
|
||
padding: '2px 9px',
|
||
cursor: 'pointer',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, t.fgroups[g]);
|
||
})));
|
||
}
|
||
function TaskRow({
|
||
task,
|
||
depth,
|
||
ctx,
|
||
expandedId,
|
||
setExpandedId,
|
||
openIds,
|
||
toggleOpen,
|
||
t,
|
||
byId,
|
||
cplxOf,
|
||
onChangeCplx,
|
||
flashId,
|
||
onJump,
|
||
visibleSet
|
||
}) {
|
||
const {
|
||
StatusChip
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const kids = (task.children || []).filter(k => !visibleSet || visibleSet.has(k.id));
|
||
const open = openIds.has(task.id) || !!visibleSet; // 筛选时自动展开可见节点
|
||
const expanded = expandedId === task.id;
|
||
const isGate = ['plan_review', 'spec_review', 'exec_review'].includes(task.status);
|
||
const flashing = flashId === task.id;
|
||
const [hover, setHover] = React.useState(false);
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: depth > 0 ? {
|
||
borderLeft: '1px solid var(--line-soft)'
|
||
} : null
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => setExpandedId(expanded ? null : task.id),
|
||
"data-task-id": task.id,
|
||
onMouseEnter: () => setHover(true),
|
||
onMouseLeave: () => setHover(false),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '8px 10px 8px 6px',
|
||
borderBottom: '1px solid var(--line-soft)',
|
||
cursor: 'pointer',
|
||
transition: 'background .1s',
|
||
background: expanded ? 'var(--panel-2)' : isGate ? 'rgba(184,142,245,.05)' : hover ? 'var(--panel)' : 'transparent',
|
||
opacity: ctx ? .55 : 1,
|
||
animation: flashing ? 'maestro-locate 1.8s ease-out' : 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
onClick: e => {
|
||
e.stopPropagation();
|
||
if (kids.length) toggleOpen(task.id);
|
||
},
|
||
style: {
|
||
width: 16,
|
||
flex: 'none',
|
||
textAlign: 'center',
|
||
fontSize: 10,
|
||
userSelect: 'none',
|
||
color: kids.length ? open ? 'var(--green)' : 'var(--muted)' : 'var(--faint)',
|
||
transform: kids.length && open ? 'rotate(90deg)' : 'none',
|
||
transition: 'transform .12s'
|
||
}
|
||
}, kids.length ? '▶' : '·'), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 500,
|
||
color: ctx ? 'var(--muted)' : 'var(--ink)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, task.title, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--faint)',
|
||
fontSize: 10.5,
|
||
marginLeft: 6
|
||
}
|
||
}, task.id)), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 8
|
||
}
|
||
}), task.deps ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 10.5,
|
||
letterSpacing: '.06em',
|
||
color: 'var(--amber)',
|
||
border: '1px dashed var(--amber-dim)',
|
||
borderRadius: 3,
|
||
padding: '1px 7px',
|
||
lineHeight: 1.5,
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, t.depsWait, " ", task.deps.length) : null, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: task.prio === 'P0' ? 'var(--amber)' : 'var(--faint)',
|
||
flex: 'none'
|
||
}
|
||
}, task.prio), /*#__PURE__*/React.createElement(CplxPicker, {
|
||
task: task,
|
||
cplx: cplxOf(task),
|
||
onChange: onChangeCplx
|
||
}), /*#__PURE__*/React.createElement(StatusChip, {
|
||
status: task.status,
|
||
label: t.status[task.status]
|
||
})), expanded ? /*#__PURE__*/React.createElement(TaskDetail, {
|
||
task: task,
|
||
t: t,
|
||
byId: byId,
|
||
onJump: onJump
|
||
}) : null, kids.length && open ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginLeft: 22
|
||
}
|
||
}, kids.map(k => /*#__PURE__*/React.createElement(TaskRow, {
|
||
key: k.id,
|
||
task: k,
|
||
depth: depth + 1,
|
||
ctx: visibleSet ? visibleSet.ctx.has(k.id) : false,
|
||
expandedId: expandedId,
|
||
setExpandedId: setExpandedId,
|
||
openIds: openIds,
|
||
toggleOpen: toggleOpen,
|
||
t: t,
|
||
byId: byId,
|
||
cplxOf: cplxOf,
|
||
onChangeCplx: onChangeCplx,
|
||
flashId: flashId,
|
||
onJump: onJump,
|
||
visibleSet: visibleSet
|
||
}))) : null);
|
||
}
|
||
function TaskDetail({
|
||
task,
|
||
t,
|
||
byId,
|
||
onJump
|
||
}) {
|
||
const label = task.doc ? t.specLabel : task.ops ? t.opsLabel : null;
|
||
const text = task.doc || task.ops;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--panel)',
|
||
borderBottom: '1px solid var(--line)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
padding: '14px 16px',
|
||
animation: 'maestro-rise .2s ease both',
|
||
display: 'grid',
|
||
gap: 14
|
||
}
|
||
}, label ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
marginBottom: 4
|
||
}
|
||
}, label), /*#__PURE__*/React.createElement("pre", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
padding: '10px 12px',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12.5,
|
||
whiteSpace: 'pre-wrap',
|
||
wordBreak: 'break-word',
|
||
margin: 0,
|
||
color: 'var(--ink)',
|
||
borderRadius: 4
|
||
}
|
||
}, text)) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '10px 12px',
|
||
border: '1px dashed var(--line)',
|
||
borderRadius: 6,
|
||
color: 'var(--faint)',
|
||
fontStyle: 'italic',
|
||
fontSize: 12
|
||
}
|
||
}, t.pendingDoc), task.deps && task.deps.length ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
marginBottom: 4
|
||
}
|
||
}, t.depsLabel), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gap: 4
|
||
}
|
||
}, task.deps.map(d => {
|
||
const dep = byId.get(d);
|
||
const ok = dep && dep.status === 'done';
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
key: d,
|
||
onClick: e => {
|
||
e.stopPropagation();
|
||
onJump(d);
|
||
},
|
||
title: "\u2192",
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
fontSize: 12,
|
||
padding: '4px 10px',
|
||
cursor: 'pointer',
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderRadius: 4,
|
||
borderLeft: '2px solid ' + (ok ? 'var(--green-dim)' : 'var(--amber-dim)'),
|
||
transition: 'border-color .12s, background .12s'
|
||
},
|
||
onMouseEnter: e => {
|
||
e.currentTarget.style.background = 'var(--panel-2)';
|
||
},
|
||
onMouseLeave: e => {
|
||
e.currentTarget.style.background = 'var(--bg-deep)';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: ok ? 'var(--green)' : 'var(--amber)',
|
||
flex: 'none'
|
||
}
|
||
}, ok ? '✓' : '◌'), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, dep ? dep.title : d), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 10.5,
|
||
color: ok ? 'var(--green)' : 'var(--amber)'
|
||
}
|
||
}, ok ? t.depDone : t.depWait), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
color: 'var(--faint)',
|
||
fontSize: 12
|
||
}
|
||
}, "\u2192"));
|
||
}))) : null);
|
||
}
|
||
function NewTaskPanel({
|
||
tasks,
|
||
onCancel,
|
||
onCreate,
|
||
t
|
||
}) {
|
||
const {
|
||
Button,
|
||
Input,
|
||
Select,
|
||
ComplexitySeg
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("form", {
|
||
style: {
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 6,
|
||
padding: 14,
|
||
marginBottom: 14
|
||
},
|
||
onSubmit: e => {
|
||
e.preventDefault();
|
||
onCreate();
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 14,
|
||
alignItems: 'flex-end',
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 320,
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: t.titleLabel,
|
||
required: true,
|
||
placeholder: t.titlePlaceholder,
|
||
style: {
|
||
width: '100%'
|
||
}
|
||
}))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 14,
|
||
alignItems: 'flex-end',
|
||
flexWrap: 'wrap',
|
||
marginTop: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("label", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 4,
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.08em'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", null, t.complexity, " ", /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--red)'
|
||
}
|
||
}, "*")), /*#__PURE__*/React.createElement(ComplexitySeg, {
|
||
defaultValue: "auto",
|
||
includeAuto: true,
|
||
autoLabel: t.cplxAuto
|
||
})), /*#__PURE__*/React.createElement(Select, {
|
||
label: t.priority,
|
||
defaultValue: "1",
|
||
options: [{
|
||
value: '0',
|
||
label: t.p0
|
||
}, {
|
||
value: '1',
|
||
label: t.p1
|
||
}, {
|
||
value: '2',
|
||
label: t.p2
|
||
}]
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 240,
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Select, {
|
||
label: t.parentTask,
|
||
style: {
|
||
width: '100%'
|
||
},
|
||
options: [{
|
||
value: '',
|
||
label: t.topLevel
|
||
}, ...tasks.map(tk => ({
|
||
value: tk.id,
|
||
label: tk.title
|
||
}))]
|
||
}))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10,
|
||
justifyContent: 'flex-end',
|
||
marginTop: 14,
|
||
paddingTop: 12,
|
||
borderTop: '1px solid var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
onClick: onCancel
|
||
}, t.cancel), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "solid",
|
||
type: "submit"
|
||
}, t.create)));
|
||
}
|
||
function TaskSection({
|
||
tasks,
|
||
onToast,
|
||
t
|
||
}) {
|
||
const {
|
||
Button,
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [expandedId, setExpandedId] = React.useState(null);
|
||
const [openIds, setOpenIds] = React.useState(() => new Set(['t1']));
|
||
const [showNew, setShowNew] = React.useState(false);
|
||
const [kw, setKw] = React.useState('');
|
||
const [cplxSet, setCplxSet] = React.useState(() => new Set());
|
||
const [statusSet, setStatusSet] = React.useState(() => new Set());
|
||
const [cplxOverride, setCplxOverride] = React.useState({});
|
||
const [flashId, setFlashId] = React.useState(null);
|
||
const byId = React.useMemo(() => kitFlatten(tasks), [tasks]);
|
||
const cplxOf = task => cplxOverride[task.id] || task.cplx;
|
||
const onChangeCplx = (id, v) => setCplxOverride(m => ({
|
||
...m,
|
||
[id]: v
|
||
}));
|
||
const toggleOpen = id => setOpenIds(prev => {
|
||
const next = new Set(prev);
|
||
next.has(id) ? next.delete(id) : next.add(id);
|
||
return next;
|
||
});
|
||
const toggleCplx = v => setCplxSet(prev => {
|
||
const next = new Set(prev);
|
||
next.has(v) ? next.delete(v) : next.add(v);
|
||
return next;
|
||
});
|
||
const toggleGroup = sts => setStatusSet(prev => {
|
||
const next = new Set(prev);
|
||
const allOn = sts.every(s => next.has(s));
|
||
for (const s of sts) allOn ? next.delete(s) : next.add(s);
|
||
return next;
|
||
});
|
||
const filtering = kw.trim() !== '' || cplxSet.size > 0 || statusSet.size > 0;
|
||
const clearFilters = () => {
|
||
setKw('');
|
||
setCplxSet(new Set());
|
||
setStatusSet(new Set());
|
||
};
|
||
|
||
// 筛选:自身命中 → 显示;祖先链作为上下文淡显;命中节点的父级自动展开
|
||
const {
|
||
visibleSet,
|
||
matchCount
|
||
} = React.useMemo(() => {
|
||
if (!filtering) return {
|
||
visibleSet: null,
|
||
matchCount: 0
|
||
};
|
||
const matches = tk => (kw.trim() === '' || tk.title.toLowerCase().includes(kw.trim().toLowerCase())) && (cplxSet.size === 0 || cplxSet.has(cplxOverride[tk.id] || tk.cplx)) && (statusSet.size === 0 || statusSet.has(tk.status));
|
||
const vis = new Set();
|
||
const ctx = new Set();
|
||
let count = 0;
|
||
const walk = tk => {
|
||
let childHit = false;
|
||
for (const k of tk.children || []) if (walk(k)) childHit = true;
|
||
const hit = matches(tk);
|
||
if (hit) count++;
|
||
if (hit || childHit) {
|
||
vis.add(tk.id);
|
||
if (!hit) ctx.add(tk.id);
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
for (const tk of tasks) walk(tk);
|
||
const set = new Set(vis);
|
||
set.ctx = ctx;
|
||
return {
|
||
visibleSet: set,
|
||
matchCount: count
|
||
};
|
||
}, [filtering, kw, cplxSet, statusSet, tasks, cplxOverride]);
|
||
|
||
// 依赖跳转:展开所有祖先 + flash 定位
|
||
const onJump = id => {
|
||
setOpenIds(prev => {
|
||
const next = new Set(prev);
|
||
const openAncestors = (list, chain) => {
|
||
for (const tk of list) {
|
||
if (tk.id === id) {
|
||
for (const c of chain) next.add(c);
|
||
return true;
|
||
}
|
||
if (tk.children && openAncestors(tk.children, [...chain, tk.id])) return true;
|
||
}
|
||
return false;
|
||
};
|
||
openAncestors(tasks, []);
|
||
return next;
|
||
});
|
||
setFlashId(null);
|
||
requestAnimationFrame(() => setFlashId(id));
|
||
setTimeout(() => setFlashId(f => f === id ? null : f), 1900);
|
||
};
|
||
const roots = visibleSet ? tasks.filter(tk => visibleSet.has(tk.id)) : tasks;
|
||
return /*#__PURE__*/React.createElement("section", null, /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: t.taskSection,
|
||
sticky: true,
|
||
action: /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
size: "xs",
|
||
onClick: () => setShowNew(!showNew)
|
||
}, t.newTask)
|
||
}), showNew ? /*#__PURE__*/React.createElement(NewTaskPanel, {
|
||
tasks: tasks,
|
||
t: t,
|
||
onCancel: () => setShowNew(false),
|
||
onCreate: () => {
|
||
setShowNew(false);
|
||
onToast('ok', t.toastCreated);
|
||
}
|
||
}) : null, /*#__PURE__*/React.createElement(FilterBar, {
|
||
t: t,
|
||
kw: kw,
|
||
setKw: setKw,
|
||
cplxSet: cplxSet,
|
||
toggleCplx: toggleCplx,
|
||
statusSet: statusSet,
|
||
toggleGroup: toggleGroup,
|
||
matchCount: matchCount,
|
||
filtering: filtering,
|
||
onClear: clearFilters
|
||
}), /*#__PURE__*/React.createElement("div", null, roots.map(tk => /*#__PURE__*/React.createElement(TaskRow, {
|
||
key: tk.id,
|
||
task: tk,
|
||
depth: 0,
|
||
ctx: visibleSet ? visibleSet.ctx.has(tk.id) : false,
|
||
expandedId: expandedId,
|
||
setExpandedId: setExpandedId,
|
||
openIds: openIds,
|
||
toggleOpen: toggleOpen,
|
||
t: t,
|
||
byId: byId,
|
||
cplxOf: cplxOf,
|
||
onChangeCplx: onChangeCplx,
|
||
flashId: flashId,
|
||
onJump: onJump,
|
||
visibleSet: visibleSet
|
||
}))));
|
||
}
|
||
Object.assign(window, {
|
||
MaestroKitTaskSection: TaskSection
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/TaskTree.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/Topbar.jsx
|
||
try { (() => {
|
||
// 顶栏动作:默认仅图标,hover 横向展开文字(与 CountBadge 同交互)
|
||
const maestroIconActionCss = `
|
||
.m-iact{display:inline-flex;align-items:center;height:28px;padding:0 8px;cursor:pointer;font-family:var(--mono);font-size:11.5px;font-weight:600;letter-spacing:.08em;line-height:1;background:transparent;color:var(--muted);border:1px solid var(--line);border-radius:var(--radius-sm,4px);transition:color .12s,border-color .12s;white-space:nowrap}
|
||
.m-iact svg{flex:none}
|
||
.m-iact .m-iact-label{max-width:0;opacity:0;overflow:hidden;transition:max-width .28s ease,opacity .22s ease,margin-left .28s ease}
|
||
.m-iact:hover{color:var(--green);border-color:var(--green-dim)}
|
||
.m-iact:hover .m-iact-label{max-width:9em;opacity:1;margin-left:6px}
|
||
`;
|
||
function ensureIconActionCss() {
|
||
if (document.getElementById('m-iact-css')) return;
|
||
const s = document.createElement('style');
|
||
s.id = 'm-iact-css';
|
||
s.textContent = maestroIconActionCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function IconAction({
|
||
icon,
|
||
label,
|
||
title,
|
||
onClick
|
||
}) {
|
||
ensureIconActionCss();
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
type: "button",
|
||
className: "m-iact",
|
||
title: title || label,
|
||
onClick: onClick
|
||
}, icon, /*#__PURE__*/React.createElement("span", {
|
||
className: "m-iact-label"
|
||
}, label));
|
||
}
|
||
const iactSvg = {
|
||
fill: 'none',
|
||
stroke: 'currentColor',
|
||
strokeWidth: 2,
|
||
strokeLinecap: 'round',
|
||
strokeLinejoin: 'round',
|
||
width: 14,
|
||
height: 14,
|
||
viewBox: '0 0 24 24'
|
||
};
|
||
function SyncIcon() {
|
||
return /*#__PURE__*/React.createElement("svg", iactSvg, /*#__PURE__*/React.createElement("path", {
|
||
d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M21 3v5h-5"
|
||
}));
|
||
}
|
||
function ConfigIcon() {
|
||
return /*#__PURE__*/React.createElement("svg", iactSvg, /*#__PURE__*/React.createElement("line", {
|
||
x1: "3",
|
||
y1: "6",
|
||
x2: "12",
|
||
y2: "6"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "15",
|
||
cy: "6",
|
||
r: "2.5"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "18",
|
||
y1: "6",
|
||
x2: "21",
|
||
y2: "6"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "3",
|
||
y1: "12",
|
||
x2: "5.5",
|
||
y2: "12"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "9",
|
||
cy: "12",
|
||
r: "2.5"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "12.5",
|
||
y1: "12",
|
||
x2: "21",
|
||
y2: "12"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "3",
|
||
y1: "18",
|
||
x2: "12.5",
|
||
y2: "18"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "16",
|
||
cy: "18",
|
||
r: "2.5"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "19.5",
|
||
y1: "18",
|
||
x2: "21",
|
||
y2: "18"
|
||
}));
|
||
}
|
||
function LangIcon() {
|
||
return /*#__PURE__*/React.createElement("svg", iactSvg, /*#__PURE__*/React.createElement("circle", {
|
||
cx: "12",
|
||
cy: "12",
|
||
r: "9"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M3 12h18"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M12 3a14 14 0 0 1 0 18a14 14 0 0 1 0-18"
|
||
}));
|
||
}
|
||
function SunIcon() {
|
||
return /*#__PURE__*/React.createElement("svg", iactSvg, /*#__PURE__*/React.createElement("circle", {
|
||
cx: "12",
|
||
cy: "12",
|
||
r: "4"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "12",
|
||
y1: "2",
|
||
x2: "12",
|
||
y2: "5"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "12",
|
||
y1: "19",
|
||
x2: "12",
|
||
y2: "22"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "2",
|
||
y1: "12",
|
||
x2: "5",
|
||
y2: "12"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "19",
|
||
y1: "12",
|
||
x2: "22",
|
||
y2: "12"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "4.9",
|
||
y1: "4.9",
|
||
x2: "7",
|
||
y2: "7"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "17",
|
||
y1: "17",
|
||
x2: "19.1",
|
||
y2: "19.1"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "4.9",
|
||
y1: "19.1",
|
||
x2: "7",
|
||
y2: "17"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "17",
|
||
y1: "7",
|
||
x2: "19.1",
|
||
y2: "4.9"
|
||
}));
|
||
}
|
||
function MoonIcon() {
|
||
return /*#__PURE__*/React.createElement("svg", iactSvg, /*#__PURE__*/React.createElement("path", {
|
||
d: "M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"
|
||
}));
|
||
}
|
||
function LangMenu({
|
||
t,
|
||
lang,
|
||
onSelectLang
|
||
}) {
|
||
const [open, setOpen] = React.useState(false);
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
if (!open) return;
|
||
const onDoc = e => {
|
||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||
};
|
||
document.addEventListener('mousedown', onDoc);
|
||
return () => document.removeEventListener('mousedown', onDoc);
|
||
}, [open]);
|
||
return /*#__PURE__*/React.createElement("span", {
|
||
ref: ref,
|
||
style: {
|
||
position: 'relative',
|
||
display: 'inline-flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
onClick: () => setOpen(!open)
|
||
}, /*#__PURE__*/React.createElement(IconAction, {
|
||
icon: /*#__PURE__*/React.createElement(LangIcon, null),
|
||
label: t.lang,
|
||
title: t.langTip,
|
||
onClick: () => {}
|
||
})), open ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'absolute',
|
||
top: 'calc(100% + 5px)',
|
||
right: 0,
|
||
zIndex: 60,
|
||
display: 'grid',
|
||
minWidth: 124,
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 'var(--radius-md, 6px)',
|
||
padding: 4,
|
||
boxShadow: '0 10px 30px rgba(0,0,0,.65)',
|
||
animation: 'maestro-rise .12s ease both'
|
||
}
|
||
}, window.MAESTRO_LANGS.map(([code, name]) => {
|
||
const active = code === lang;
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
key: code,
|
||
onClick: () => {
|
||
onSelectLang(code);
|
||
setOpen(false);
|
||
},
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
textAlign: 'left',
|
||
background: active ? 'var(--panel-2)' : 'transparent',
|
||
color: active ? 'var(--green)' : 'var(--ink)',
|
||
border: 'none',
|
||
borderRadius: 4,
|
||
padding: '7px 10px',
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8
|
||
},
|
||
onMouseEnter: e => {
|
||
if (!active) e.currentTarget.style.background = 'var(--panel)';
|
||
},
|
||
onMouseLeave: e => {
|
||
if (!active) e.currentTarget.style.background = 'transparent';
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 12,
|
||
color: 'var(--green)'
|
||
}
|
||
}, active ? '▍' : ''), name);
|
||
})) : null);
|
||
}
|
||
|
||
// 顶栏:项目标题 + 徽章组 + 动作;agent 执行面板
|
||
function Topbar({
|
||
project,
|
||
counts,
|
||
onSync,
|
||
onToggleConfig,
|
||
t,
|
||
theme,
|
||
onToggleTheme,
|
||
lang,
|
||
onSelectLang
|
||
}) {
|
||
const {
|
||
Button,
|
||
CountBadge
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'flex-end',
|
||
gap: 14,
|
||
padding: '22px 0 14px',
|
||
borderBottom: '1px solid var(--line)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
minWidth: 0,
|
||
flex: '0 1 auto'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 20,
|
||
fontWeight: 700,
|
||
letterSpacing: '.04em',
|
||
whiteSpace: 'nowrap',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis'
|
||
}
|
||
}, project.name), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
marginTop: 2,
|
||
whiteSpace: 'nowrap',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis'
|
||
},
|
||
title: project.path + ' · ' + project.branch + ' · ' + project.autonomy
|
||
}, project.path, " \xB7 ", project.branch, " \xB7 ", project.autonomy)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "gate",
|
||
count: counts.gate,
|
||
label: t.badgeGate,
|
||
title: t.badgeGateTip
|
||
}), /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "ready",
|
||
count: counts.ready,
|
||
label: t.badgeReady,
|
||
title: t.badgeReadyTip
|
||
}), /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "run",
|
||
count: counts.run,
|
||
label: t.badgeRun,
|
||
title: t.badgeRunTip
|
||
}), /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "blocked",
|
||
count: counts.blocked,
|
||
label: t.badgeBlocked,
|
||
title: t.badgeBlockedTip
|
||
}), /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "total",
|
||
count: counts.total,
|
||
label: t.badgeTotal,
|
||
title: t.badgeTotalTip
|
||
})), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement(IconAction, {
|
||
icon: /*#__PURE__*/React.createElement(ConfigIcon, null),
|
||
label: t.config,
|
||
title: t.configTip,
|
||
onClick: onToggleConfig
|
||
}), /*#__PURE__*/React.createElement(LangMenu, {
|
||
t: t,
|
||
lang: lang,
|
||
onSelectLang: onSelectLang
|
||
}), /*#__PURE__*/React.createElement(IconAction, {
|
||
icon: theme === 'light' ? /*#__PURE__*/React.createElement(MoonIcon, null) : /*#__PURE__*/React.createElement(SunIcon, null),
|
||
label: theme === 'light' ? t.themeDark : t.themeLight,
|
||
title: t.themeTip,
|
||
onClick: onToggleTheme
|
||
})));
|
||
}
|
||
function ConfigPanel({
|
||
project,
|
||
onSave,
|
||
onClose,
|
||
onSync,
|
||
t
|
||
}) {
|
||
const {
|
||
Button,
|
||
Input,
|
||
Select
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("section", {
|
||
style: {
|
||
position: 'relative',
|
||
zIndex: 30,
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 6,
|
||
padding: '12px 14px',
|
||
marginTop: 12,
|
||
animation: 'maestro-rise .18s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 14,
|
||
alignItems: 'flex-end',
|
||
flexWrap: 'wrap'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: t.maxConcurrency,
|
||
type: "number",
|
||
defaultValue: String(project.concurrency),
|
||
width: 76
|
||
}), /*#__PURE__*/React.createElement(Select, {
|
||
label: t.workMode,
|
||
defaultValue: project.autonomy,
|
||
options: Object.entries(t.autonomy).map(([value, label]) => ({
|
||
value,
|
||
label
|
||
}))
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.06em',
|
||
marginLeft: 'auto',
|
||
paddingBottom: 7
|
||
}
|
||
}, t.current, "\uFF1A", project.concurrency, " \xB7 ", project.autonomy), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "solid",
|
||
onClick: onSave
|
||
}, t.save), /*#__PURE__*/React.createElement(Button, {
|
||
onClick: onClose
|
||
}, t.collapse)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 14,
|
||
alignItems: 'flex-end',
|
||
flexWrap: 'wrap',
|
||
marginTop: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 2,
|
||
minWidth: 220,
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: t.projLogo,
|
||
placeholder: t.logoPh,
|
||
style: {
|
||
width: '100%'
|
||
}
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 170,
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: t.verifyCmd,
|
||
placeholder: t.verifyPh,
|
||
style: {
|
||
width: '100%'
|
||
}
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1,
|
||
minWidth: 170,
|
||
display: 'flex'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: t.model,
|
||
placeholder: t.modelPh,
|
||
style: {
|
||
width: '100%'
|
||
}
|
||
}))), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
marginTop: 10,
|
||
paddingTop: 10,
|
||
borderTop: '1px dashed var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)',
|
||
letterSpacing: '.06em'
|
||
}
|
||
}, t.lastSync), /*#__PURE__*/React.createElement(Button, {
|
||
size: "xs",
|
||
onClick: onSync
|
||
}, "\u27F3 ", t.sync)));
|
||
}
|
||
function AgentSection({
|
||
agents,
|
||
quota,
|
||
t
|
||
}) {
|
||
const {
|
||
SectionHead,
|
||
QuotaMeter
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("section", null, /*#__PURE__*/React.createElement(SectionHead, {
|
||
mark: "cyan",
|
||
title: /*#__PURE__*/React.createElement("span", null, t.agentSection, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--cyan)',
|
||
letterSpacing: '.08em',
|
||
marginLeft: 8
|
||
}
|
||
}, agents.length > 0 ? agents.length : '')),
|
||
sticky: true
|
||
}), quota ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 22,
|
||
flexWrap: 'wrap',
|
||
fontFamily: 'var(--mono)',
|
||
margin: '0 0 12px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.08em'
|
||
}
|
||
}, t.quota), /*#__PURE__*/React.createElement(QuotaMeter, {
|
||
label: "5h",
|
||
pct: quota.five.pct,
|
||
detail: t.quotaReset.replace('{t}', quota.five.reset)
|
||
}), /*#__PURE__*/React.createElement(QuotaMeter, {
|
||
label: t.quotaWeek,
|
||
pct: quota.week.pct,
|
||
detail: t.quotaReset.replace('{t}', quota.week.reset)
|
||
})) : null, agents.length === 0 ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '12px 14px',
|
||
color: 'var(--faint)',
|
||
fontSize: 12,
|
||
border: '1px dashed var(--line)',
|
||
borderRadius: 6
|
||
}
|
||
}, t.agentEmpty) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 20,
|
||
alignItems: 'stretch',
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--cyan-dim)',
|
||
borderRadius: 6,
|
||
padding: '12px 16px',
|
||
animation: 'maestro-rise .2s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
minWidth: 64,
|
||
padding: '4px 8px',
|
||
borderRight: '1px solid var(--line-soft)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 40,
|
||
fontWeight: 700,
|
||
lineHeight: 1,
|
||
color: 'var(--cyan)',
|
||
textShadow: '0 0 18px rgba(89,200,216,.5)'
|
||
}
|
||
}, agents.length), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 9,
|
||
fontWeight: 600,
|
||
letterSpacing: '.3em',
|
||
color: 'var(--muted)',
|
||
marginTop: 6
|
||
}
|
||
}, "RUNNING")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
display: 'grid',
|
||
gap: 10,
|
||
minWidth: 0,
|
||
alignContent: 'center'
|
||
}
|
||
}, agents.map(a => /*#__PURE__*/React.createElement("div", {
|
||
key: a.id,
|
||
style: {
|
||
display: 'flex',
|
||
gap: 8,
|
||
alignItems: 'center',
|
||
fontSize: 12,
|
||
padding: '3px 0'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: '50%',
|
||
background: 'var(--cyan)',
|
||
boxShadow: '0 0 8px var(--cyan)',
|
||
animation: 'maestro-pulse .9s infinite'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, a.title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
fontSize: 10,
|
||
letterSpacing: '.1em',
|
||
color: 'var(--cyan)',
|
||
border: '1px solid var(--cyan-dim)',
|
||
padding: '0 6px',
|
||
borderRadius: 3
|
||
}
|
||
}, a.kind), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 'none',
|
||
marginLeft: 'auto',
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, a.meta, " \xB7 ", a.time, " ", t.since))))));
|
||
}
|
||
Object.assign(window, {
|
||
MaestroKitTopbar: Topbar,
|
||
MaestroKitConfigPanel: ConfigPanel,
|
||
MaestroKitAgentSection: AgentSection
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/Topbar.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/data.js
|
||
try { (() => {
|
||
// MAESTRO 调度台 · UI kit 假数据(与 src/model 状态机对齐)
|
||
window.MAESTRO_MOCK = {
|
||
projects: [{
|
||
id: 'p1',
|
||
name: 'maestro',
|
||
path: '~/dev/maestro',
|
||
branch: 'main',
|
||
autonomy: 'auto-easy',
|
||
concurrency: 2,
|
||
hue: 140,
|
||
state: 'running',
|
||
pending: 1,
|
||
agents: 1
|
||
}, {
|
||
id: 'p2',
|
||
name: 'blog-engine',
|
||
path: '~/dev/blog-engine',
|
||
branch: 'main',
|
||
autonomy: 'manual',
|
||
concurrency: 1,
|
||
hue: 38,
|
||
state: 'paused',
|
||
pending: 0,
|
||
agents: 0
|
||
}, {
|
||
id: 'p3',
|
||
name: 'dotfiles',
|
||
path: '~/.dotfiles',
|
||
branch: 'master',
|
||
autonomy: 'auto-approved',
|
||
concurrency: 1,
|
||
hue: 265,
|
||
state: 'blocked',
|
||
pending: 0,
|
||
agents: 0
|
||
}],
|
||
agents: [{
|
||
id: 'r1',
|
||
project: 'maestro',
|
||
title: '把轮询改为 WS 推送',
|
||
kind: 'EXECUTOR',
|
||
time: '06:12',
|
||
meta: 'wt-127 · claude-sonnet'
|
||
}],
|
||
// 全局:跨项目 agent 概览 / daemon 配置 / 当前用户
|
||
global: {
|
||
projectCount: 3,
|
||
runningProjects: 1,
|
||
runningAgents: 1,
|
||
maxAgents: 4,
|
||
autonomy: 'auto-easy',
|
||
daemon: 'v0.4.2',
|
||
port: 4517,
|
||
uptime: '3d 04h'
|
||
},
|
||
// Agent 汇总:本周窗口,按项目 + 总结
|
||
agentSummary: {
|
||
tokensWeek: 12400000,
|
||
runsWeek: 47,
|
||
costWeek: 38.6,
|
||
activeNow: 1,
|
||
byProject: [{
|
||
id: 'p1',
|
||
name: 'maestro',
|
||
hue: 140,
|
||
active: 1,
|
||
runs: 32,
|
||
tokens: 8900000
|
||
}, {
|
||
id: 'p2',
|
||
name: 'blog-engine',
|
||
hue: 38,
|
||
active: 0,
|
||
runs: 9,
|
||
tokens: 2100000
|
||
}, {
|
||
id: 'p3',
|
||
name: 'dotfiles',
|
||
hue: 265,
|
||
active: 0,
|
||
runs: 6,
|
||
tokens: 1400000
|
||
}]
|
||
},
|
||
user: {
|
||
name: 'jun',
|
||
handle: '@jun',
|
||
plan: 'Claude Max',
|
||
initial: 'J',
|
||
hue: 200
|
||
},
|
||
quota: {
|
||
five: {
|
||
pct: 50,
|
||
reset: '3h 8m'
|
||
},
|
||
week: {
|
||
pct: 58,
|
||
reset: '16h 38m'
|
||
}
|
||
},
|
||
approvals: [{
|
||
id: 'a1',
|
||
gate: 'spec',
|
||
taskId: 't4',
|
||
title: '重构 sync 模块',
|
||
meta: 'maestro · MED',
|
||
docLabel: '改动方案(SPEC)',
|
||
doc: '把轮询改为 WS 推送:\n1. store 层加 events 订阅接口\n2. daemon 广播 status.changed\n3. web 端断线重连 + 指数退避\n\n为什么:轮询 2s 间隔在多项目下放大为 N 路请求;WS 已有依赖,无新增包。'
|
||
}],
|
||
tasks: [{
|
||
id: 't1',
|
||
title: '接入 Claude Agent SDK',
|
||
cplx: 'hard',
|
||
status: 'decomposed',
|
||
prio: 'P0',
|
||
children: [{
|
||
id: 't1a',
|
||
title: 'PoC:worktree 起 headless CC',
|
||
cplx: 'medium',
|
||
status: 'done',
|
||
prio: 'P0'
|
||
}, {
|
||
id: 't1b',
|
||
title: 'executor 封装 + verify 钩子',
|
||
cplx: 'medium',
|
||
status: 'executing',
|
||
prio: 'P0'
|
||
}, {
|
||
id: 't1c',
|
||
title: '失败重试 n 次 → needs_attention',
|
||
cplx: 'easy',
|
||
status: 'blocked',
|
||
prio: 'P1',
|
||
deps: ['t1b']
|
||
}]
|
||
}, {
|
||
id: 't4',
|
||
title: '重构 sync 模块',
|
||
cplx: 'medium',
|
||
status: 'spec_review',
|
||
prio: 'P1',
|
||
doc: '把轮询改为 WS 推送:store 层加 events 订阅…'
|
||
}, {
|
||
id: 't5',
|
||
title: '看板移动端单栏适配',
|
||
cplx: 'easy',
|
||
status: 'ready',
|
||
prio: 'P2',
|
||
ops: '将执行的操作:@media 1100px 断点改单栏;侧栏折叠为顶部条。'
|
||
}, {
|
||
id: 't6',
|
||
title: '事件流 append-only 审计导出',
|
||
cplx: 'easy',
|
||
status: 'done',
|
||
prio: 'P2'
|
||
}],
|
||
archived: [{
|
||
id: 't6',
|
||
title: '事件流 append-only 审计导出',
|
||
cplx: 'easy',
|
||
status: 'done',
|
||
subs: 0,
|
||
time: '2 小时前',
|
||
timeFull: '2026-06-13 04:21:09',
|
||
detail: {
|
||
attrs: [['id', 't6'], ['复杂度', 'EASY'], ['优先级', 'P2'], ['状态', '完成'], ['深度', '1'], ['创建时间', '2026-06-12 22:03:44'], ['最后更新', '2026-06-13 04:21:09']],
|
||
ops: '将执行的操作:store 层加 events 导出接口(JSONL);CLI 加 maestro events export。',
|
||
runs: [{
|
||
kind: '执行',
|
||
status: '成功',
|
||
span: '2026-06-13 03:58:12 → 2026-06-13 04:11:47 · 时长 13 分 35 秒',
|
||
ref: '转录 runs/r-0613-0358.jsonl'
|
||
}],
|
||
result: {
|
||
branch: 'maestro/t6-events-export',
|
||
commits: ['a3f9c21 feat(store): events export JSONL'],
|
||
diff: '+182 −12 · 4 files'
|
||
},
|
||
approvals: [{
|
||
gate: '结果评审',
|
||
action: 'accept',
|
||
actor: 'you',
|
||
at: '2026-06-13 04:21:09'
|
||
}],
|
||
timeline: [{
|
||
time: '06-12 22:03',
|
||
text: '任务创建',
|
||
who: 'you'
|
||
}, {
|
||
time: '06-13 03:58',
|
||
text: 'run 开始(执行)',
|
||
who: '编排器',
|
||
color: 'var(--cyan)'
|
||
}, {
|
||
time: '06-13 04:11',
|
||
text: '执行中 → 待审/合',
|
||
who: '编排器',
|
||
color: 'var(--violet)'
|
||
}, {
|
||
time: '06-13 04:21',
|
||
text: '审批通过(结果评审)· 合并',
|
||
who: 'you',
|
||
color: 'var(--green)'
|
||
}]
|
||
}
|
||
}, {
|
||
id: 't3',
|
||
title: '旧 todo.json 导入器',
|
||
cplx: 'medium',
|
||
status: 'done',
|
||
subs: 2,
|
||
time: '昨天',
|
||
timeFull: '2026-06-12 09:14:02',
|
||
detail: {
|
||
attrs: [['id', 't3'], ['复杂度', 'MED'], ['优先级', 'P1'], ['状态', '完成'], ['深度', '1'], ['创建时间', '2026-06-10 11:40:12'], ['最后更新', '2026-06-12 09:14:02']],
|
||
spec: '读旧 todo/todo.json,tier1/2/3 → hard/medium/easy,导入为一个项目;重复标题跳过。',
|
||
runs: [{
|
||
kind: '执行',
|
||
status: '成功',
|
||
span: '2026-06-12 08:31:00 → 2026-06-12 08:54:18 · 时长 23 分 18 秒',
|
||
ref: '转录 runs/r-0612-0831.jsonl'
|
||
}],
|
||
approvals: [{
|
||
gate: '方案评审',
|
||
action: 'reject',
|
||
actor: 'you',
|
||
at: '2026-06-11 19:02:51',
|
||
reason: '未处理重复导入'
|
||
}, {
|
||
gate: '方案评审',
|
||
action: 'accept',
|
||
actor: 'you',
|
||
at: '2026-06-12 07:48:20'
|
||
}, {
|
||
gate: '结果评审',
|
||
action: 'accept',
|
||
actor: 'you',
|
||
at: '2026-06-12 09:14:02'
|
||
}],
|
||
timeline: [{
|
||
time: '06-10 11:40',
|
||
text: '任务创建',
|
||
who: 'you'
|
||
}, {
|
||
time: '06-11 19:02',
|
||
text: '审批驳回(方案评审):未处理重复导入',
|
||
who: 'you',
|
||
color: 'var(--red)'
|
||
}, {
|
||
time: '06-12 07:48',
|
||
text: '审批通过(方案评审)',
|
||
who: 'you',
|
||
color: 'var(--green)'
|
||
}, {
|
||
time: '06-12 08:31',
|
||
text: 'run 开始(执行)',
|
||
who: '编排器',
|
||
color: 'var(--cyan)'
|
||
}, {
|
||
time: '06-12 09:14',
|
||
text: '审批通过(结果评审)· 合并',
|
||
who: 'you',
|
||
color: 'var(--green)'
|
||
}]
|
||
}
|
||
}, {
|
||
id: 't2',
|
||
title: '远程看板(可选)调研',
|
||
cplx: 'easy',
|
||
status: 'cancelled',
|
||
subs: 0,
|
||
time: '3 天前',
|
||
timeFull: '2026-06-10 16:02:33',
|
||
detail: {
|
||
attrs: [['id', 't2'], ['复杂度', 'EASY'], ['优先级', 'P2'], ['状态', '取消'], ['深度', '1'], ['创建时间', '2026-06-09 10:12:00'], ['最后更新', '2026-06-10 16:02:33']],
|
||
timeline: [{
|
||
time: '06-09 10:12',
|
||
text: '任务创建',
|
||
who: 'you'
|
||
}, {
|
||
time: '06-10 16:02',
|
||
text: '可执行 → 取消',
|
||
who: 'you',
|
||
color: 'var(--faint)'
|
||
}]
|
||
}
|
||
}],
|
||
events: [{
|
||
type: 'run.started',
|
||
time: '06:12:09',
|
||
detail: 'executor · 把轮询改为 WS 推送 · wt-127'
|
||
}, {
|
||
type: 'approval.requested',
|
||
time: '06:10:44',
|
||
detail: 'spec_review · 重构 sync 模块'
|
||
}, {
|
||
type: 'approval.rejected',
|
||
time: '05:58:02',
|
||
detail: '重构 sync 模块 ↳ 缺少回滚方案'
|
||
}, {
|
||
type: 'status.changed',
|
||
time: '05:31:18',
|
||
detail: 'PoC:worktree 起 headless CC:执行中 → 完成'
|
||
}, {
|
||
type: 'task.created',
|
||
time: '05:02:51',
|
||
detail: '看板移动端单栏适配'
|
||
}, {
|
||
type: 'project.synced',
|
||
time: '04:48:00',
|
||
detail: 'maestro · 3 项导入'
|
||
}]
|
||
};
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/data.js", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console/i18n.js
|
||
try { (() => {
|
||
// MAESTRO 调度台 · 界面语言包(zh / en / es / ja / fr)— UI chrome 文案;任务/事件内容为用户数据不翻译
|
||
window.MAESTRO_LANGS = [['zh', '中文'], ['en', 'English'], ['es', 'Español'], ['ja', '日本語'], ['fr', 'Français']];
|
||
window.MAESTRO_I18N = {
|
||
zh: {
|
||
logoSub: '多项目任务调度台',
|
||
projects: '项目',
|
||
newProject: '+ 新建',
|
||
connected: '已连接 · :4517',
|
||
expandSide: '展开侧栏',
|
||
collapseSide: '折叠侧栏',
|
||
badgeGate: '项待审批',
|
||
badgeReady: '待执行',
|
||
badgeRun: '执行中',
|
||
badgeBlocked: '被阻塞',
|
||
badgeTotal: '总量',
|
||
badgeGateTip: '等待你裁决的审批闸',
|
||
badgeReadyTip: '可执行(依赖已满足)+ 排队中',
|
||
badgeRunTip: 'agent 正在执行',
|
||
badgeBlockedTip: '被依赖阻塞(依赖完成后自动放行)',
|
||
badgeTotalTip: '未完成任务总量(不含 done / 已拆解容器 / 取消)',
|
||
sync: '同步 todo',
|
||
lastSync: '上次同步 06:12',
|
||
config: '配置',
|
||
configTip: '项目配置(并发 / 工作模式 / todo 同步)',
|
||
archive: '已归档',
|
||
archiveTip: '点击查看完整详情',
|
||
archiveSubs: '含 {n} 子任务',
|
||
archiveDetail: '归档详情',
|
||
pagePrev: '‹ 上一页',
|
||
pageNext: '下一页 ›',
|
||
pageOf: '第 {a} / {b} 页',
|
||
perPage: '每页',
|
||
attrsLabel: '属性',
|
||
runsLabel: '执行历史',
|
||
resultLabel: '执行结果',
|
||
approvalsLabel: '审批记录',
|
||
timelineLabel: '状态流转时间线',
|
||
branch: '分支',
|
||
accepted: '接受',
|
||
rejected: '驳回',
|
||
approver: '审批人',
|
||
opinion: '意见',
|
||
closeTip: '关闭(Esc)',
|
||
lang: '中文',
|
||
langTip: '切换语言 / Language',
|
||
themeLight: '浅色',
|
||
themeDark: '深色',
|
||
themeTip: '切换 light/dark',
|
||
maxConcurrency: '最大并发',
|
||
workMode: '工作模式',
|
||
current: '当前',
|
||
save: '保存配置',
|
||
collapse: '收起',
|
||
autonomy: {
|
||
manual: '手动',
|
||
'auto-easy': '自动 · Easy',
|
||
'auto-approved': '自动 · 已批准'
|
||
},
|
||
agentSection: 'Agent 执行',
|
||
agentEmpty: '无运行中的 agent',
|
||
running: 'RUNNING',
|
||
since: '起',
|
||
projRunning: '运行中',
|
||
projPaused: '暂停',
|
||
projBlocked: '阻塞',
|
||
projIdle: '空闲',
|
||
projPendingTip: '{n} 项待你审批',
|
||
gAgents: '全局 Agent',
|
||
gAgentsDetail: '{p}/{P} 个项目运行 · {a} 个 agent',
|
||
apActive: '运行',
|
||
apRuns: '次运行',
|
||
apTokens: 'token',
|
||
apWeek: '本周',
|
||
apCost: '花费',
|
||
apTotal: '所有项目',
|
||
apPerProj: '按项目',
|
||
apIdle: '空闲',
|
||
gConfig: '全局配置',
|
||
gConfigDetail: '并发上限 {n} · daemon {v}',
|
||
gUserPlan: '订阅',
|
||
gUserSignOut: '退出登录',
|
||
gUserSettings: '账户设置',
|
||
gateExpand: '展开',
|
||
gateCollapse: '折叠',
|
||
gateDblTip: '双击全屏阅读',
|
||
quota: '额度',
|
||
quotaWeek: '周',
|
||
quotaReset: '{t} 后重置',
|
||
projLogo: '项目 Logo',
|
||
logoPh: '图片 URL 或仓库内相对路径;留空=自动',
|
||
verifyCmd: '校验命令',
|
||
verifyPh: 'npm test · go test ./...(可空)',
|
||
model: '模型',
|
||
modelPh: 'claude-opus-4-5(可空)',
|
||
searchPh: '⌕ 搜索标题…',
|
||
clearFilter: '✕ 清除筛选',
|
||
matchCount: '{n} 项匹配',
|
||
fgroups: {
|
||
todo: '待办',
|
||
doing: '进行中',
|
||
gate: '待审批',
|
||
bad: '异常',
|
||
hold: '挂起',
|
||
done: '完成'
|
||
},
|
||
fullRead: '全屏阅读',
|
||
depsLabel: 'DEPS · 依赖(全部完成才可执行)',
|
||
depDone: '完成',
|
||
depWait: '等待',
|
||
gateSection: '审批闸 · 等待裁决',
|
||
accept: '✓ 通过',
|
||
reject: '✕ 驳回',
|
||
confirmReject: '确认驳回',
|
||
rejectPlaceholder: '改进意见(必填)',
|
||
taskSection: '任务树',
|
||
newTask: '+ 新建任务',
|
||
titleLabel: '标题',
|
||
titlePlaceholder: '要做什么',
|
||
complexity: '复杂度',
|
||
cplxAuto: '智能',
|
||
parentTask: '父任务',
|
||
topLevel: '(顶层)',
|
||
priority: '优先级',
|
||
p0: 'P0 · 高',
|
||
p1: 'P1 · 中',
|
||
p2: 'P2 · 低',
|
||
create: '创建任务',
|
||
cancel: '取消',
|
||
depsWait: '待依赖',
|
||
specLabel: '改动方案(SPEC)',
|
||
opsLabel: '将执行的操作(OPERATIONS)',
|
||
pendingDoc: '待 Claude Code 产出(经 MCP 写入并提交评审)',
|
||
emptyTasks: '该项目暂无任务 —— 点「+ 新建任务」或经 MCP 创建',
|
||
empty: '空',
|
||
events: '事件流',
|
||
expandEvents: '展开事件流',
|
||
collapseEvents: '折叠事件流',
|
||
toastCreated: '任务已创建 · init',
|
||
toastAccepted: '已通过 · ',
|
||
toastRejected: '已驳回 · 退回重做',
|
||
toastSynced: 'todo 已同步 · 0 项变更',
|
||
toastSaved: '配置已保存',
|
||
toastModal: '原型:新建项目模态未接',
|
||
gatePassed: ' 通过',
|
||
status: {
|
||
init: '新建',
|
||
analyzing: '分析拆解中',
|
||
plan_review: '待确认拆解',
|
||
decomposed: '已拆解',
|
||
speccing: '写方案中',
|
||
spec_review: '待确认方案',
|
||
ready: '可执行',
|
||
blocked: '被依赖阻塞',
|
||
queued: '排队中',
|
||
executing: '执行中',
|
||
exec_review: '待审/合',
|
||
failed: '失败',
|
||
needs_attention: '需人工',
|
||
done: '完成',
|
||
paused: '暂停',
|
||
cancelled: '取消'
|
||
},
|
||
gates: {
|
||
plan: '拆解评审',
|
||
spec: '方案评审',
|
||
exec: '结果评审'
|
||
},
|
||
eventTypes: {
|
||
'task.created': '任务创建',
|
||
'task.updated': '任务更新',
|
||
'status.changed': '状态变更',
|
||
'approval.requested': '请求审批',
|
||
'approval.granted': '审批通过',
|
||
'approval.rejected': '审批驳回',
|
||
'run.started': '运行开始',
|
||
'run.finished': '运行结束',
|
||
'project.synced': 'todo 同步'
|
||
}
|
||
},
|
||
en: {
|
||
logoSub: 'MULTI-PROJECT ORCHESTRATOR',
|
||
projects: 'PROJECTS',
|
||
newProject: '+ New',
|
||
connected: 'Connected · :4517',
|
||
expandSide: 'Expand sidebar',
|
||
collapseSide: 'Collapse sidebar',
|
||
badgeGate: 'pending review',
|
||
badgeReady: 'to run',
|
||
badgeRun: 'running',
|
||
badgeBlocked: 'blocked',
|
||
badgeTotal: 'total',
|
||
badgeGateTip: 'Approval gates awaiting your decision',
|
||
badgeReadyTip: 'Ready (deps met) + queued',
|
||
badgeRunTip: 'Agents currently executing',
|
||
badgeBlockedTip: 'Blocked (auto-released when deps complete)',
|
||
badgeTotalTip: 'Open tasks (excl. done / decomposed containers / cancelled)',
|
||
sync: 'Sync todo',
|
||
lastSync: 'Last sync 06:12',
|
||
config: 'Config',
|
||
configTip: 'Project config (concurrency / autonomy / todo sync)',
|
||
archive: 'Archive',
|
||
archiveTip: 'Click for full detail',
|
||
archiveSubs: '{n} subtasks',
|
||
archiveDetail: 'ARCHIVE',
|
||
pagePrev: '‹ Prev',
|
||
pageNext: 'Next ›',
|
||
pageOf: 'Page {a} / {b}',
|
||
perPage: 'Per page',
|
||
attrsLabel: 'ATTRIBUTES',
|
||
runsLabel: 'RUN HISTORY',
|
||
resultLabel: 'RESULT',
|
||
approvalsLabel: 'APPROVALS',
|
||
timelineLabel: 'STATUS TIMELINE',
|
||
branch: 'Branch',
|
||
accepted: 'accepted',
|
||
rejected: 'rejected',
|
||
approver: 'Approver',
|
||
opinion: 'Feedback',
|
||
closeTip: 'Close (Esc)',
|
||
lang: 'English',
|
||
langTip: 'Switch language',
|
||
themeLight: 'Light',
|
||
themeDark: 'Dark',
|
||
themeTip: 'Toggle light/dark',
|
||
maxConcurrency: 'Max concurrency',
|
||
workMode: 'Autonomy',
|
||
current: 'Current',
|
||
save: 'Save config',
|
||
collapse: 'Close',
|
||
autonomy: {
|
||
manual: 'Manual',
|
||
'auto-easy': 'Auto · Easy',
|
||
'auto-approved': 'Auto · Approved'
|
||
},
|
||
agentSection: 'Agent runs',
|
||
agentEmpty: 'No running agents',
|
||
running: 'RUNNING',
|
||
since: '',
|
||
projRunning: 'Running',
|
||
projPaused: 'Paused',
|
||
projBlocked: 'Blocked',
|
||
projIdle: 'Idle',
|
||
projPendingTip: '{n} awaiting your review',
|
||
gAgents: 'Agents',
|
||
gAgentsDetail: '{p}/{P} projects · {a} agents',
|
||
apActive: 'active',
|
||
apRuns: 'runs',
|
||
apTokens: 'tokens',
|
||
apWeek: 'this week',
|
||
apCost: 'cost',
|
||
apTotal: 'All projects',
|
||
apPerProj: 'BY PROJECT',
|
||
apIdle: 'idle',
|
||
gConfig: 'Settings',
|
||
gConfigDetail: 'Max concurrency {n} · daemon {v}',
|
||
gUserPlan: 'Plan',
|
||
gUserSignOut: 'Sign out',
|
||
gUserSettings: 'Account settings',
|
||
gateExpand: 'Expand',
|
||
gateCollapse: 'Collapse',
|
||
gateDblTip: 'Double-click for fullscreen',
|
||
quota: 'Quota',
|
||
quotaWeek: 'week',
|
||
quotaReset: 'resets in {t}',
|
||
projLogo: 'Project logo',
|
||
logoPh: 'Image URL or repo-relative path; empty = auto',
|
||
verifyCmd: 'Verify command',
|
||
verifyPh: 'npm test · go test ./... (optional)',
|
||
model: 'Model',
|
||
modelPh: 'claude-opus-4-5 (optional)',
|
||
searchPh: '⌕ Search titles…',
|
||
clearFilter: '✕ Clear filters',
|
||
matchCount: '{n} matches',
|
||
fgroups: {
|
||
todo: 'To do',
|
||
doing: 'In progress',
|
||
gate: 'Pending review',
|
||
bad: 'Issues',
|
||
hold: 'On hold',
|
||
done: 'Done'
|
||
},
|
||
fullRead: 'Read fullscreen',
|
||
depsLabel: 'DEPS (all must complete to run)',
|
||
depDone: 'done',
|
||
depWait: 'waiting',
|
||
gateSection: 'Approval gates · awaiting decision',
|
||
accept: '✓ Accept',
|
||
reject: '✕ Reject',
|
||
confirmReject: 'Confirm reject',
|
||
rejectPlaceholder: 'Improvement feedback (required)',
|
||
taskSection: 'Task tree',
|
||
newTask: '+ New task',
|
||
titleLabel: 'Title',
|
||
titlePlaceholder: 'What needs doing',
|
||
complexity: 'Complexity',
|
||
cplxAuto: 'AUTO',
|
||
parentTask: 'Parent',
|
||
topLevel: '(top level)',
|
||
priority: 'Priority',
|
||
p0: 'P0 · high',
|
||
p1: 'P1 · medium',
|
||
p2: 'P2 · low',
|
||
create: 'Create task',
|
||
cancel: 'Cancel',
|
||
depsWait: 'deps',
|
||
specLabel: 'CHANGE SPEC',
|
||
opsLabel: 'PLANNED OPERATIONS',
|
||
pendingDoc: 'Awaiting Claude Code output (written via MCP, then submitted for review)',
|
||
emptyTasks: 'No tasks in this project — hit "+ New task" or create via MCP',
|
||
empty: 'EMPTY',
|
||
events: 'Events',
|
||
expandEvents: 'Expand events',
|
||
collapseEvents: 'Collapse events',
|
||
toastCreated: 'Task created · init',
|
||
toastAccepted: 'Accepted · ',
|
||
toastRejected: 'Rejected · sent back',
|
||
toastSynced: 'Todo synced · 0 changes',
|
||
toastSaved: 'Config saved',
|
||
toastModal: 'Prototype: new-project modal not wired',
|
||
gatePassed: ' approved',
|
||
status: {
|
||
init: 'New',
|
||
analyzing: 'Analyzing',
|
||
plan_review: 'Plan review',
|
||
decomposed: 'Decomposed',
|
||
speccing: 'Drafting spec',
|
||
spec_review: 'Spec review',
|
||
ready: 'Ready',
|
||
blocked: 'Blocked',
|
||
queued: 'Queued',
|
||
executing: 'Executing',
|
||
exec_review: 'Review & merge',
|
||
failed: 'Failed',
|
||
needs_attention: 'Needs attention',
|
||
done: 'Done',
|
||
paused: 'Paused',
|
||
cancelled: 'Cancelled'
|
||
},
|
||
gates: {
|
||
plan: 'PLAN REVIEW',
|
||
spec: 'SPEC REVIEW',
|
||
exec: 'EXEC REVIEW'
|
||
},
|
||
eventTypes: {
|
||
'task.created': 'Task created',
|
||
'task.updated': 'Task updated',
|
||
'status.changed': 'Status changed',
|
||
'approval.requested': 'Approval requested',
|
||
'approval.granted': 'Approval granted',
|
||
'approval.rejected': 'Approval rejected',
|
||
'run.started': 'Run started',
|
||
'run.finished': 'Run finished',
|
||
'project.synced': 'Todo synced'
|
||
}
|
||
},
|
||
es: {
|
||
logoSub: 'ORQUESTADOR MULTIPROYECTO',
|
||
projects: 'PROYECTOS',
|
||
newProject: '+ Nuevo',
|
||
connected: 'Conectado · :4517',
|
||
expandSide: 'Expandir panel',
|
||
collapseSide: 'Plegar panel',
|
||
badgeGate: 'por revisar',
|
||
badgeReady: 'por ejecutar',
|
||
badgeRun: 'en curso',
|
||
badgeBlocked: 'bloqueadas',
|
||
badgeTotal: 'total',
|
||
badgeGateTip: 'Puertas de aprobación esperando tu decisión',
|
||
badgeReadyTip: 'Listas (deps cumplidas) + en cola',
|
||
badgeRunTip: 'Agents en ejecución',
|
||
badgeBlockedTip: 'Bloqueadas (se liberan al completar deps)',
|
||
badgeTotalTip: 'Tareas abiertas (sin done / contenedores / canceladas)',
|
||
sync: 'Sincronizar todo',
|
||
lastSync: 'Última sinc. 06:12',
|
||
config: 'Config',
|
||
configTip: 'Configuración (concurrencia / modo / sinc. todo)',
|
||
archive: 'Archivo',
|
||
archiveTip: 'Clic para ver detalle',
|
||
archiveSubs: '{n} subtareas',
|
||
archiveDetail: 'ARCHIVO',
|
||
pagePrev: '‹ Anterior',
|
||
pageNext: 'Siguiente ›',
|
||
pageOf: 'Página {a} / {b}',
|
||
perPage: 'Por página',
|
||
attrsLabel: 'ATRIBUTOS',
|
||
runsLabel: 'HISTORIAL DE RUNS',
|
||
resultLabel: 'RESULTADO',
|
||
approvalsLabel: 'APROBACIONES',
|
||
timelineLabel: 'LÍNEA DE TIEMPO',
|
||
branch: 'Rama',
|
||
accepted: 'aceptada',
|
||
rejected: 'rechazada',
|
||
approver: 'Aprobador',
|
||
opinion: 'Comentario',
|
||
closeTip: 'Cerrar (Esc)',
|
||
lang: 'Español',
|
||
langTip: 'Cambiar idioma',
|
||
themeLight: 'Claro',
|
||
themeDark: 'Oscuro',
|
||
themeTip: 'Cambiar tema',
|
||
maxConcurrency: 'Concurrencia máx.',
|
||
workMode: 'Modo',
|
||
current: 'Actual',
|
||
save: 'Guardar',
|
||
collapse: 'Cerrar',
|
||
autonomy: {
|
||
manual: 'manual',
|
||
'auto-easy': 'auto · Easy',
|
||
'auto-approved': 'auto · aprob.'
|
||
},
|
||
agentSection: 'Ejecución de agents',
|
||
agentEmpty: 'Sin agents en ejecución',
|
||
running: 'RUNNING',
|
||
since: '',
|
||
projRunning: 'En curso',
|
||
projPaused: 'Pausado',
|
||
projBlocked: 'Bloqueado',
|
||
projIdle: 'Inactivo',
|
||
projPendingTip: '{n} esperan tu revisión',
|
||
gAgents: 'Agents globales',
|
||
gAgentsDetail: '{p}/{P} proyectos · {a} agents',
|
||
apActive: 'activos',
|
||
apRuns: 'ejecuciones',
|
||
apTokens: 'tokens',
|
||
apWeek: 'esta semana',
|
||
apCost: 'coste',
|
||
apTotal: 'Todos los proyectos',
|
||
apPerProj: 'POR PROYECTO',
|
||
apIdle: 'inactivo',
|
||
gConfig: 'Config global',
|
||
gConfigDetail: 'Concurrencia máx {n} · daemon {v}',
|
||
gUserPlan: 'Plan',
|
||
gUserSignOut: 'Cerrar sesión',
|
||
gUserSettings: 'Ajustes de cuenta',
|
||
gateExpand: 'Expandir',
|
||
gateCollapse: 'Plegar',
|
||
gateDblTip: 'Doble clic para pantalla completa',
|
||
quota: 'Cuota',
|
||
quotaWeek: 'semana',
|
||
quotaReset: 'reinicio en {t}',
|
||
projLogo: 'Logo del proyecto',
|
||
logoPh: 'URL o ruta relativa; vacío = auto',
|
||
verifyCmd: 'Comando de verificación',
|
||
verifyPh: 'npm test · go test ./... (opcional)',
|
||
model: 'Modelo',
|
||
modelPh: 'claude-opus-4-5 (opcional)',
|
||
searchPh: '⌕ Buscar títulos…',
|
||
clearFilter: '✕ Limpiar filtros',
|
||
matchCount: '{n} coincidencias',
|
||
fgroups: {
|
||
todo: 'Pendientes',
|
||
doing: 'En curso',
|
||
gate: 'Por revisar',
|
||
bad: 'Incidencias',
|
||
hold: 'En pausa',
|
||
done: 'Hechas'
|
||
},
|
||
fullRead: 'Pantalla completa',
|
||
depsLabel: 'DEPS (todas deben completarse)',
|
||
depDone: 'hecha',
|
||
depWait: 'esperando',
|
||
gateSection: 'Puertas de aprobación · pendientes',
|
||
accept: '✓ Aceptar',
|
||
reject: '✕ Rechazar',
|
||
confirmReject: 'Confirmar rechazo',
|
||
rejectPlaceholder: 'Comentario de mejora (obligatorio)',
|
||
taskSection: 'Árbol de tareas',
|
||
newTask: '+ Nueva tarea',
|
||
titleLabel: 'Título',
|
||
titlePlaceholder: 'Qué hay que hacer',
|
||
complexity: 'Complejidad',
|
||
cplxAuto: 'AUTO',
|
||
parentTask: 'Padre',
|
||
topLevel: '(raíz)',
|
||
priority: 'Prioridad',
|
||
p0: 'P0 · alta',
|
||
p1: 'P1 · media',
|
||
p2: 'P2 · baja',
|
||
create: 'Crear tarea',
|
||
cancel: 'Cancelar',
|
||
depsWait: 'deps',
|
||
specLabel: 'SPEC DE CAMBIOS',
|
||
opsLabel: 'OPERACIONES PREVISTAS',
|
||
pendingDoc: 'Esperando salida de Claude Code (vía MCP, luego a revisión)',
|
||
emptyTasks: 'Sin tareas — pulsa "+ Nueva tarea" o crea vía MCP',
|
||
empty: 'VACÍO',
|
||
events: 'Eventos',
|
||
expandEvents: 'Expandir eventos',
|
||
collapseEvents: 'Plegar eventos',
|
||
toastCreated: 'Tarea creada · init',
|
||
toastAccepted: 'Aceptada · ',
|
||
toastRejected: 'Rechazada · devuelta',
|
||
toastSynced: 'Todo sincronizado · 0 cambios',
|
||
toastSaved: 'Config guardada',
|
||
toastModal: 'Prototipo: modal no conectado',
|
||
gatePassed: ' aprobada',
|
||
status: {
|
||
init: 'Nueva',
|
||
analyzing: 'Analizando',
|
||
plan_review: 'Revisión de plan',
|
||
decomposed: 'Descompuesta',
|
||
speccing: 'Redactando spec',
|
||
spec_review: 'Revisión de spec',
|
||
ready: 'Lista',
|
||
blocked: 'Bloqueada',
|
||
queued: 'En cola',
|
||
executing: 'Ejecutando',
|
||
exec_review: 'Revisar y fusionar',
|
||
failed: 'Fallida',
|
||
needs_attention: 'Requiere atención',
|
||
done: 'Hecha',
|
||
paused: 'Pausada',
|
||
cancelled: 'Cancelada'
|
||
},
|
||
gates: {
|
||
plan: 'REVISIÓN DE PLAN',
|
||
spec: 'REVISIÓN DE SPEC',
|
||
exec: 'REVISIÓN DE RESULTADO'
|
||
},
|
||
eventTypes: {
|
||
'task.created': 'Tarea creada',
|
||
'task.updated': 'Tarea actualizada',
|
||
'status.changed': 'Cambio de estado',
|
||
'approval.requested': 'Aprobación solicitada',
|
||
'approval.granted': 'Aprobación concedida',
|
||
'approval.rejected': 'Aprobación rechazada',
|
||
'run.started': 'Run iniciado',
|
||
'run.finished': 'Run terminado',
|
||
'project.synced': 'Todo sincronizado'
|
||
}
|
||
},
|
||
ja: {
|
||
logoSub: 'マルチプロジェクト・オーケストレーター',
|
||
projects: 'プロジェクト',
|
||
newProject: '+ 新規',
|
||
connected: '接続済み · :4517',
|
||
expandSide: 'サイドバーを開く',
|
||
collapseSide: 'サイドバーを畳む',
|
||
badgeGate: '件 承認待ち',
|
||
badgeReady: '実行待ち',
|
||
badgeRun: '実行中',
|
||
badgeBlocked: 'ブロック中',
|
||
badgeTotal: '合計',
|
||
badgeGateTip: 'あなたの裁定を待つ承認ゲート',
|
||
badgeReadyTip: '実行可能(依存解決済み)+ キュー',
|
||
badgeRunTip: 'agent が実行中',
|
||
badgeBlockedTip: '依存でブロック(解決後に自動開放)',
|
||
badgeTotalTip: '未完了タスク数(done / 分解済み / キャンセル除く)',
|
||
sync: 'todo 同期',
|
||
lastSync: '最終同期 06:12',
|
||
config: '設定',
|
||
configTip: 'プロジェクト設定(並列数 / モード / todo 同期)',
|
||
archive: 'アーカイブ',
|
||
archiveTip: 'クリックで詳細表示',
|
||
archiveSubs: 'サブタスク {n} 件',
|
||
archiveDetail: 'アーカイブ詳細',
|
||
pagePrev: '‹ 前へ',
|
||
pageNext: '次へ ›',
|
||
pageOf: '{a} / {b} ページ',
|
||
perPage: '表示件数',
|
||
attrsLabel: '属性',
|
||
runsLabel: '実行履歴',
|
||
resultLabel: '実行結果',
|
||
approvalsLabel: '承認記録',
|
||
timelineLabel: 'ステータス・タイムライン',
|
||
branch: 'ブランチ',
|
||
accepted: '承認',
|
||
rejected: '却下',
|
||
approver: '承認者',
|
||
opinion: 'コメント',
|
||
closeTip: '閉じる(Esc)',
|
||
lang: '日本語',
|
||
langTip: '言語を切替',
|
||
themeLight: 'ライト',
|
||
themeDark: 'ダーク',
|
||
themeTip: 'テーマ切替',
|
||
maxConcurrency: '最大並列数',
|
||
workMode: 'モード',
|
||
current: '現在',
|
||
save: '保存',
|
||
collapse: '閉じる',
|
||
autonomy: {
|
||
manual: '手動',
|
||
'auto-easy': '自動 · Easy',
|
||
'auto-approved': '自動 · 承認済'
|
||
},
|
||
agentSection: 'Agent 実行',
|
||
agentEmpty: '実行中の agent はありません',
|
||
running: 'RUNNING',
|
||
since: '開始',
|
||
projRunning: '実行中',
|
||
projPaused: '一時停止',
|
||
projBlocked: 'ブロック',
|
||
projIdle: 'アイドル',
|
||
projPendingTip: '{n} 件があなたの承認待ち',
|
||
gAgents: 'グローバル Agent',
|
||
gAgentsDetail: '{p}/{P} プロジェクト · {a} 個の agent',
|
||
apActive: '実行中',
|
||
apRuns: '回実行',
|
||
apTokens: 'token',
|
||
apWeek: '今週',
|
||
apCost: 'コスト',
|
||
apTotal: '全プロジェクト',
|
||
apPerProj: 'プロジェクト別',
|
||
apIdle: 'アイドル',
|
||
gConfig: 'グローバル設定',
|
||
gConfigDetail: '並列上限 {n} · daemon {v}',
|
||
gUserPlan: 'プラン',
|
||
gUserSignOut: 'ログアウト',
|
||
gUserSettings: 'アカウント設定',
|
||
gateExpand: '展開',
|
||
gateCollapse: '折り畳む',
|
||
gateDblTip: 'ダブルクリックで全画面',
|
||
quota: 'クォータ',
|
||
quotaWeek: '週',
|
||
quotaReset: '{t} 後にリセット',
|
||
projLogo: 'プロジェクトロゴ',
|
||
logoPh: '画像 URL またはリポジトリ相対パス;空=自動',
|
||
verifyCmd: '検証コマンド',
|
||
verifyPh: 'npm test · go test ./...(任意)',
|
||
model: 'モデル',
|
||
modelPh: 'claude-opus-4-5(任意)',
|
||
searchPh: '⌕ タイトルを検索…',
|
||
clearFilter: '✕ フィルタをクリア',
|
||
matchCount: '{n} 件一致',
|
||
fgroups: {
|
||
todo: '未着手',
|
||
doing: '進行中',
|
||
gate: '承認待ち',
|
||
bad: '異常',
|
||
hold: '保留',
|
||
done: '完了'
|
||
},
|
||
fullRead: '全画面で読む',
|
||
depsLabel: 'DEPS · 依存(全完了で実行可)',
|
||
depDone: '完了',
|
||
depWait: '待機',
|
||
gateSection: '承認ゲート · 裁定待ち',
|
||
accept: '✓ 承認',
|
||
reject: '✕ 却下',
|
||
confirmReject: '却下を確定',
|
||
rejectPlaceholder: '改善フィードバック(必須)',
|
||
taskSection: 'タスクツリー',
|
||
newTask: '+ 新規タスク',
|
||
titleLabel: 'タイトル',
|
||
titlePlaceholder: '何をしますか',
|
||
complexity: '複雑度',
|
||
cplxAuto: '智能',
|
||
parentTask: '親タスク',
|
||
topLevel: '(トップ)',
|
||
priority: '優先度',
|
||
p0: 'P0 · 高',
|
||
p1: 'P1 · 中',
|
||
p2: 'P2 · 低',
|
||
create: 'タスク作成',
|
||
cancel: 'キャンセル',
|
||
depsWait: '依存待ち',
|
||
specLabel: 'SPEC · 変更案',
|
||
opsLabel: 'OPERATIONS · 操作',
|
||
pendingDoc: 'Claude Code の出力待ち(MCP 経由で書き込み後レビューへ)',
|
||
emptyTasks: 'タスクなし — 「+ 新規タスク」または MCP で作成',
|
||
empty: '空',
|
||
events: 'イベント',
|
||
expandEvents: 'イベントを開く',
|
||
collapseEvents: 'イベントを畳む',
|
||
toastCreated: 'タスク作成済み · init',
|
||
toastAccepted: '承認済み · ',
|
||
toastRejected: '却下 · 差し戻し',
|
||
toastSynced: 'todo 同期完了 · 変更 0 件',
|
||
toastSaved: '設定を保存しました',
|
||
toastModal: 'プロトタイプ:新規モーダル未接続',
|
||
gatePassed: ' 承認',
|
||
status: {
|
||
init: '新規',
|
||
analyzing: '分析・分解中',
|
||
plan_review: '分解確認待ち',
|
||
decomposed: '分解済み',
|
||
speccing: '方針作成中',
|
||
spec_review: '方針確認待ち',
|
||
ready: '実行可能',
|
||
blocked: '依存ブロック',
|
||
queued: 'キュー待ち',
|
||
executing: '実行中',
|
||
exec_review: 'レビュー/マージ',
|
||
failed: '失敗',
|
||
needs_attention: '要対応',
|
||
done: '完了',
|
||
paused: '一時停止',
|
||
cancelled: 'キャンセル'
|
||
},
|
||
gates: {
|
||
plan: '分解レビュー',
|
||
spec: '方針レビュー',
|
||
exec: '結果レビュー'
|
||
},
|
||
eventTypes: {
|
||
'task.created': 'タスク作成',
|
||
'task.updated': 'タスク更新',
|
||
'status.changed': 'ステータス変更',
|
||
'approval.requested': '承認リクエスト',
|
||
'approval.granted': '承認',
|
||
'approval.rejected': '却下',
|
||
'run.started': 'run 開始',
|
||
'run.finished': 'run 終了',
|
||
'project.synced': 'todo 同期'
|
||
}
|
||
},
|
||
fr: {
|
||
logoSub: 'ORCHESTRATEUR MULTI-PROJETS',
|
||
projects: 'PROJETS',
|
||
newProject: '+ Nouveau',
|
||
connected: 'Connecté · :4517',
|
||
expandSide: 'Déplier le panneau',
|
||
collapseSide: 'Replier le panneau',
|
||
badgeGate: 'à approuver',
|
||
badgeReady: 'à exécuter',
|
||
badgeRun: 'en cours',
|
||
badgeBlocked: 'bloquées',
|
||
badgeTotal: 'total',
|
||
badgeGateTip: "Portes d'approbation en attente de décision",
|
||
badgeReadyTip: 'Prêtes (deps OK) + en file',
|
||
badgeRunTip: 'Agents en cours d’exécution',
|
||
badgeBlockedTip: 'Bloquées (libérées quand les deps aboutissent)',
|
||
badgeTotalTip: 'Tâches ouvertes (hors done / conteneurs / annulées)',
|
||
sync: 'Synchroniser todo',
|
||
lastSync: 'Dernière sync 06:12',
|
||
config: 'Config',
|
||
configTip: 'Config projet (concurrence / mode / sync todo)',
|
||
archive: 'Archives',
|
||
archiveTip: 'Cliquer pour le détail',
|
||
archiveSubs: '{n} sous-tâches',
|
||
archiveDetail: 'ARCHIVE',
|
||
pagePrev: '‹ Préc.',
|
||
pageNext: 'Suiv. ›',
|
||
pageOf: 'Page {a} / {b}',
|
||
perPage: 'Par page',
|
||
attrsLabel: 'ATTRIBUTS',
|
||
runsLabel: 'HISTORIQUE DES RUNS',
|
||
resultLabel: 'RÉSULTAT',
|
||
approvalsLabel: 'APPROBATIONS',
|
||
timelineLabel: 'CHRONOLOGIE',
|
||
branch: 'Branche',
|
||
accepted: 'acceptée',
|
||
rejected: 'rejetée',
|
||
approver: 'Approbateur',
|
||
opinion: 'Retour',
|
||
closeTip: 'Fermer (Échap)',
|
||
lang: 'Français',
|
||
langTip: 'Changer de langue',
|
||
themeLight: 'Clair',
|
||
themeDark: 'Sombre',
|
||
themeTip: 'Basculer le thème',
|
||
maxConcurrency: 'Concurrence max',
|
||
workMode: 'Mode',
|
||
current: 'Actuel',
|
||
save: 'Enregistrer',
|
||
collapse: 'Fermer',
|
||
autonomy: {
|
||
manual: 'manual',
|
||
'auto-easy': 'auto · Easy',
|
||
'auto-approved': 'auto · approuv.'
|
||
},
|
||
agentSection: 'Exécutions agent',
|
||
agentEmpty: 'Aucun agent en cours',
|
||
running: 'RUNNING',
|
||
since: '',
|
||
projRunning: 'En cours',
|
||
projPaused: 'En pause',
|
||
projBlocked: 'Bloqué',
|
||
projIdle: 'Inactif',
|
||
projPendingTip: '{n} en attente de votre revue',
|
||
gAgents: 'Agents globaux',
|
||
gAgentsDetail: '{p}/{P} projets · {a} agents',
|
||
apActive: 'actifs',
|
||
apRuns: 'exécutions',
|
||
apTokens: 'tokens',
|
||
apWeek: 'cette semaine',
|
||
apCost: 'coût',
|
||
apTotal: 'Tous les projets',
|
||
apPerProj: 'PAR PROJET',
|
||
apIdle: 'inactif',
|
||
gConfig: 'Config globale',
|
||
gConfigDetail: 'Concurrence max {n} · daemon {v}',
|
||
gUserPlan: 'Forfait',
|
||
gUserSignOut: 'Se déconnecter',
|
||
gUserSettings: 'Paramètres du compte',
|
||
gateExpand: 'Déplier',
|
||
gateCollapse: 'Replier',
|
||
gateDblTip: 'Double-clic pour le plein écran',
|
||
quota: 'Quota',
|
||
quotaWeek: 'semaine',
|
||
quotaReset: 'reset dans {t}',
|
||
projLogo: 'Logo du projet',
|
||
logoPh: 'URL ou chemin relatif ; vide = auto',
|
||
verifyCmd: 'Commande de vérification',
|
||
verifyPh: 'npm test · go test ./... (optionnel)',
|
||
model: 'Modèle',
|
||
modelPh: 'claude-opus-4-5 (optionnel)',
|
||
searchPh: '⌕ Rechercher…',
|
||
clearFilter: '✕ Effacer les filtres',
|
||
matchCount: '{n} résultats',
|
||
fgroups: {
|
||
todo: 'À faire',
|
||
doing: 'En cours',
|
||
gate: 'À approuver',
|
||
bad: 'Anomalies',
|
||
hold: 'En attente',
|
||
done: 'Terminées'
|
||
},
|
||
fullRead: 'Plein écran',
|
||
depsLabel: 'DEPS (toutes requises)',
|
||
depDone: 'terminée',
|
||
depWait: 'en attente',
|
||
gateSection: "Portes d'approbation · en attente",
|
||
accept: '✓ Accepter',
|
||
reject: '✕ Rejeter',
|
||
confirmReject: 'Confirmer le rejet',
|
||
rejectPlaceholder: "Retour d'amélioration (obligatoire)",
|
||
taskSection: 'Arbre des tâches',
|
||
newTask: '+ Nouvelle tâche',
|
||
titleLabel: 'Titre',
|
||
titlePlaceholder: 'Que faut-il faire',
|
||
complexity: 'Complexité',
|
||
cplxAuto: 'AUTO',
|
||
parentTask: 'Parent',
|
||
topLevel: '(racine)',
|
||
priority: 'Priorité',
|
||
p0: 'P0 · haute',
|
||
p1: 'P1 · moyenne',
|
||
p2: 'P2 · basse',
|
||
create: 'Créer la tâche',
|
||
cancel: 'Annuler',
|
||
depsWait: 'deps',
|
||
specLabel: 'SPEC DES CHANGEMENTS',
|
||
opsLabel: 'OPÉRATIONS PRÉVUES',
|
||
pendingDoc: 'En attente de la sortie de Claude Code (via MCP, puis revue)',
|
||
emptyTasks: 'Aucune tâche — « + Nouvelle tâche » ou via MCP',
|
||
empty: 'VIDE',
|
||
events: 'Événements',
|
||
expandEvents: 'Déplier les événements',
|
||
collapseEvents: 'Replier les événements',
|
||
toastCreated: 'Tâche créée · init',
|
||
toastAccepted: 'Acceptée · ',
|
||
toastRejected: 'Rejetée · renvoyée',
|
||
toastSynced: 'Todo synchronisé · 0 changement',
|
||
toastSaved: 'Config enregistrée',
|
||
toastModal: 'Prototype : modale non câblée',
|
||
gatePassed: ' approuvée',
|
||
status: {
|
||
init: 'Nouvelle',
|
||
analyzing: 'Analyse',
|
||
plan_review: 'Revue du plan',
|
||
decomposed: 'Décomposée',
|
||
speccing: 'Rédaction spec',
|
||
spec_review: 'Revue de spec',
|
||
ready: 'Prête',
|
||
blocked: 'Bloquée',
|
||
queued: 'En file',
|
||
executing: 'En exécution',
|
||
exec_review: 'Revue & fusion',
|
||
failed: 'Échouée',
|
||
needs_attention: 'À traiter',
|
||
done: 'Terminée',
|
||
paused: 'En pause',
|
||
cancelled: 'Annulée'
|
||
},
|
||
gates: {
|
||
plan: 'REVUE DU PLAN',
|
||
spec: 'REVUE DE SPEC',
|
||
exec: 'REVUE DU RÉSULTAT'
|
||
},
|
||
eventTypes: {
|
||
'task.created': 'Tâche créée',
|
||
'task.updated': 'Tâche mise à jour',
|
||
'status.changed': "Changement d'état",
|
||
'approval.requested': 'Approbation demandée',
|
||
'approval.granted': 'Approbation accordée',
|
||
'approval.rejected': 'Approbation rejetée',
|
||
'run.started': 'Run démarré',
|
||
'run.finished': 'Run terminé',
|
||
'project.synced': 'Todo synchronisé'
|
||
}
|
||
}
|
||
};
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console/i18n.js", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console_mobile/MobileChrome.jsx
|
||
try { (() => {
|
||
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
||
// 移动版 · 头部 + 底部 Tab 栏
|
||
const mIcon = {
|
||
fill: 'none',
|
||
stroke: 'currentColor',
|
||
strokeWidth: 2,
|
||
strokeLinecap: 'round',
|
||
strokeLinejoin: 'round',
|
||
viewBox: '0 0 24 24'
|
||
};
|
||
function MIconTask({
|
||
s = 22
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", _extends({}, mIcon, {
|
||
width: s,
|
||
height: s
|
||
}), /*#__PURE__*/React.createElement("rect", {
|
||
x: "4",
|
||
y: "4",
|
||
width: "16",
|
||
height: "16",
|
||
rx: "2.5"
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: "8 12 11 15 16 9"
|
||
}));
|
||
}
|
||
function MIconGate({
|
||
s = 22
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", _extends({}, mIcon, {
|
||
width: s,
|
||
height: s
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M12 3 L22 21 L2 21 Z"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "12",
|
||
y1: "10",
|
||
x2: "12",
|
||
y2: "14"
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "12",
|
||
y1: "17.5",
|
||
x2: "12",
|
||
y2: "17.51"
|
||
}));
|
||
}
|
||
function MIconEvent({
|
||
s = 22
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", _extends({}, mIcon, {
|
||
width: s,
|
||
height: s
|
||
}), /*#__PURE__*/React.createElement("polyline", {
|
||
points: "2 12 7 12 10 5 14 19 17 12 22 12"
|
||
}));
|
||
}
|
||
function MIconGit({
|
||
s = 22
|
||
}) {
|
||
return /*#__PURE__*/React.createElement("svg", _extends({}, mIcon, {
|
||
width: s,
|
||
height: s
|
||
}), /*#__PURE__*/React.createElement("line", {
|
||
x1: "6",
|
||
y1: "3",
|
||
x2: "6",
|
||
y2: "15"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "18",
|
||
cy: "6",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "6",
|
||
cy: "18",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M18 9a9 9 0 0 1-9 9"
|
||
}));
|
||
}
|
||
function MobileMark({
|
||
scale = 1.6
|
||
}) {
|
||
const ref = React.useRef(null);
|
||
React.useEffect(() => {
|
||
const MAP = ['.....LLLLL.....', '...LLLLLLLLL...', '..GGGGGGGGGGG..', '..GGEEGGGEEGG..', '..GGEEGGGEEGG..', '..GGGGGGGGGGG..', '...GGGGGGGGG...', '...G..G.G..G...', '...G..G.G..G...', '..G...G.G...G..', '..D...D.D...D..', '.D...D...D...D.'];
|
||
const INK = {
|
||
L: '#79ec94',
|
||
G: '#5fdd7d',
|
||
D: '#2e6b3d',
|
||
E: '#070908'
|
||
};
|
||
const ctx = ref.current.getContext('2d');
|
||
MAP.forEach((row, y) => [...row].forEach((ch, x) => {
|
||
if (INK[ch]) {
|
||
ctx.fillStyle = INK[ch];
|
||
ctx.fillRect(x, y, 1, 1);
|
||
}
|
||
}));
|
||
}, []);
|
||
return /*#__PURE__*/React.createElement("canvas", {
|
||
ref: ref,
|
||
width: "15",
|
||
height: "12",
|
||
style: {
|
||
width: 15 * scale,
|
||
height: 12 * scale,
|
||
imageRendering: 'pixelated',
|
||
filter: 'drop-shadow(0 0 5px rgba(95,221,125,.4))'
|
||
}
|
||
});
|
||
}
|
||
function MobileHeader({
|
||
project,
|
||
counts
|
||
}) {
|
||
const {
|
||
CountBadge
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("header", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
padding: '12px 14px',
|
||
borderBottom: '1px solid var(--line)',
|
||
background: 'var(--bg-deep)',
|
||
position: 'sticky',
|
||
top: 0,
|
||
zIndex: 20
|
||
}
|
||
}, /*#__PURE__*/React.createElement(MobileMark, null), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 15,
|
||
fontWeight: 700,
|
||
letterSpacing: '.04em',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, project.name), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10,
|
||
color: 'var(--faint)',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, project.branch, " \xB7 ", project.autonomy)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
display: 'flex',
|
||
gap: 6
|
||
}
|
||
}, /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "gate",
|
||
count: counts.gate
|
||
}), /*#__PURE__*/React.createElement(CountBadge, {
|
||
kind: "run",
|
||
count: counts.run
|
||
})));
|
||
}
|
||
function MobileTabBar({
|
||
tab,
|
||
setTab,
|
||
gateCount
|
||
}) {
|
||
const tabs = [{
|
||
id: 'tasks',
|
||
label: '任务',
|
||
icon: MIconTask
|
||
}, {
|
||
id: 'gates',
|
||
label: '审批',
|
||
icon: MIconGate,
|
||
badge: gateCount
|
||
}, {
|
||
id: 'events',
|
||
label: '事件',
|
||
icon: MIconEvent
|
||
}, {
|
||
id: 'projects',
|
||
label: '项目',
|
||
icon: MIconGit
|
||
}];
|
||
return /*#__PURE__*/React.createElement("nav", {
|
||
style: {
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(4,1fr)',
|
||
borderTop: '1px solid var(--line)',
|
||
background: 'var(--bg-deep)',
|
||
position: 'sticky',
|
||
bottom: 0,
|
||
zIndex: 20
|
||
}
|
||
}, tabs.map(t => {
|
||
const active = tab === t.id;
|
||
const Icon = t.icon;
|
||
return /*#__PURE__*/React.createElement("button", {
|
||
key: t.id,
|
||
onClick: () => setTab(t.id),
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
background: 'transparent',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'center',
|
||
gap: 3,
|
||
padding: '9px 0 10px',
|
||
minHeight: 56,
|
||
position: 'relative',
|
||
color: active ? 'var(--green)' : 'var(--faint)',
|
||
textShadow: active ? '0 0 10px rgba(95,221,125,.45)' : 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'relative',
|
||
filter: active ? 'drop-shadow(0 0 6px rgba(95,221,125,.5))' : 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Icon, null), t.badge ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
position: 'absolute',
|
||
top: -4,
|
||
right: -8,
|
||
minWidth: 15,
|
||
height: 15,
|
||
fontSize: 9.5,
|
||
fontWeight: 700,
|
||
lineHeight: '15px',
|
||
textAlign: 'center',
|
||
background: 'var(--violet)',
|
||
color: 'var(--bg-deep)',
|
||
borderRadius: 8,
|
||
padding: '0 3px'
|
||
}
|
||
}, t.badge) : null), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10,
|
||
letterSpacing: '.12em'
|
||
}
|
||
}, t.label));
|
||
}));
|
||
}
|
||
Object.assign(window, {
|
||
MaestroMobHeader: MobileHeader,
|
||
MaestroMobTabBar: MobileTabBar
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console_mobile/MobileChrome.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
// ui_kits/console_mobile/MobileViews.jsx
|
||
try { (() => {
|
||
// 移动版 · 四个 Tab 视图:任务 / 审批 / 事件 / 项目
|
||
function MobTaskRow({
|
||
task,
|
||
depth = 0,
|
||
expandedId,
|
||
setExpandedId
|
||
}) {
|
||
const {
|
||
ComplexityBadge,
|
||
StatusChip
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const kids = task.children || [];
|
||
const expanded = expandedId === task.id;
|
||
const isGate = ['plan_review', 'spec_review', 'exec_review'].includes(task.status);
|
||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||
onClick: () => setExpandedId(expanded ? null : task.id),
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 6,
|
||
padding: '12px 14px',
|
||
minHeight: 44,
|
||
cursor: 'pointer',
|
||
paddingLeft: 14 + depth * 16,
|
||
borderBottom: '1px solid var(--line-soft)',
|
||
borderLeft: depth ? '1px solid var(--line-soft)' : 'none',
|
||
background: expanded ? 'var(--panel-2)' : isGate ? 'rgba(184,142,245,.05)' : 'transparent'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'baseline',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 500,
|
||
fontSize: 14,
|
||
minWidth: 0,
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, task.title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
color: 'var(--faint)',
|
||
fontSize: 10.5,
|
||
flex: 'none'
|
||
}
|
||
}, task.id)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8
|
||
}
|
||
}, /*#__PURE__*/React.createElement(ComplexityBadge, {
|
||
complexity: task.cplx
|
||
}), /*#__PURE__*/React.createElement(StatusChip, {
|
||
status: task.status
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
fontSize: 10.5,
|
||
color: task.prio === 'P0' ? 'var(--amber)' : 'var(--faint)'
|
||
}
|
||
}, task.prio))), expanded ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--panel)',
|
||
borderBottom: '1px solid var(--line)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
padding: '12px 14px',
|
||
animation: 'maestro-rise .2s ease both'
|
||
}
|
||
}, task.doc || task.ops ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
marginBottom: 4
|
||
}
|
||
}, task.doc ? '改动方案(SPEC)' : '将执行的操作(OPERATIONS)'), /*#__PURE__*/React.createElement("pre", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
borderRadius: 4,
|
||
padding: '10px 12px',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 12,
|
||
whiteSpace: 'pre-wrap',
|
||
wordBreak: 'break-word',
|
||
margin: 0,
|
||
color: 'var(--ink)',
|
||
lineHeight: 1.6
|
||
}
|
||
}, task.doc || task.ops)) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '10px 12px',
|
||
border: '1px dashed var(--line)',
|
||
borderRadius: 6,
|
||
color: 'var(--faint)',
|
||
fontStyle: 'italic',
|
||
fontSize: 12
|
||
}
|
||
}, "\u5F85 Claude Code \u4EA7\u51FA\uFF08\u7ECF MCP \u5199\u5165\u5E76\u63D0\u4EA4\u8BC4\u5BA1\uFF09")) : null, kids.map(k => /*#__PURE__*/React.createElement(MobTaskRow, {
|
||
key: k.id,
|
||
task: k,
|
||
depth: depth + 1,
|
||
expandedId: expandedId,
|
||
setExpandedId: setExpandedId
|
||
})));
|
||
}
|
||
function MobTasks({
|
||
tasks,
|
||
agents
|
||
}) {
|
||
const {
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [expandedId, setExpandedId] = React.useState(null);
|
||
return /*#__PURE__*/React.createElement("div", null, agents.length ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
margin: '12px 14px 0',
|
||
display: 'flex',
|
||
gap: 10,
|
||
alignItems: 'center',
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--cyan-dim)',
|
||
borderRadius: 6,
|
||
padding: '10px 12px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
width: 6,
|
||
height: 6,
|
||
borderRadius: '50%',
|
||
background: 'var(--cyan)',
|
||
boxShadow: '0 0 8px var(--cyan)',
|
||
animation: 'maestro-pulse .9s infinite',
|
||
flex: 'none'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 12,
|
||
minWidth: 0,
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, agents[0].title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
flex: 'none',
|
||
fontSize: 10,
|
||
letterSpacing: '.1em',
|
||
color: 'var(--cyan)',
|
||
border: '1px solid var(--cyan-dim)',
|
||
borderRadius: 3,
|
||
padding: '0 6px'
|
||
}
|
||
}, agents[0].kind)) : null, /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: "\u4EFB\u52A1\u6811",
|
||
style: {
|
||
padding: '14px 14px 8px'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", null, tasks.map(t => /*#__PURE__*/React.createElement(MobTaskRow, {
|
||
key: t.id,
|
||
task: t,
|
||
expandedId: expandedId,
|
||
setExpandedId: setExpandedId
|
||
}))));
|
||
}
|
||
function MobGatePreview({
|
||
item,
|
||
onDecide,
|
||
onClose
|
||
}) {
|
||
const {
|
||
ComplexityBadge,
|
||
Button,
|
||
Textarea
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [rejecting, setRejecting] = React.useState(false);
|
||
const [reason, setReason] = React.useState('');
|
||
if (!item) return null;
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
position: 'fixed',
|
||
inset: 0,
|
||
zIndex: 1300,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
background: 'var(--bg)',
|
||
animation: 'maestro-rise .18s ease both'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
padding: '12px 14px',
|
||
borderBottom: '1px solid var(--line)',
|
||
background: 'var(--panel-2)',
|
||
flex: 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
fontWeight: 700,
|
||
letterSpacing: '.18em',
|
||
color: 'var(--bg)',
|
||
background: 'var(--violet)',
|
||
padding: '2px 8px',
|
||
borderRadius: 3,
|
||
flex: 'none'
|
||
}
|
||
}, item.gateLabel), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 700,
|
||
fontSize: 14,
|
||
minWidth: 0,
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap'
|
||
}
|
||
}, item.title), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
flex: 1
|
||
}
|
||
}), /*#__PURE__*/React.createElement("button", {
|
||
onClick: onClose,
|
||
title: "\u5173\u95ED",
|
||
style: {
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 15,
|
||
background: 'transparent',
|
||
color: 'var(--muted)',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
padding: '8px 10px',
|
||
minHeight: 44
|
||
}
|
||
}, "\u2715")), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 1,
|
||
overflowY: 'auto',
|
||
padding: '14px 16px 24px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 11,
|
||
color: 'var(--muted)',
|
||
marginBottom: 10
|
||
}
|
||
}, item.meta), item.docLabel ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--muted)',
|
||
letterSpacing: '.18em',
|
||
margin: '0 0 6px'
|
||
}
|
||
}, item.docLabel) : null, /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
background: 'var(--bg-deep)',
|
||
border: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid var(--green-dim)',
|
||
borderRadius: 4,
|
||
padding: '12px 14px',
|
||
fontFamily: 'var(--mono)',
|
||
fontSize: 13.5,
|
||
lineHeight: 1.7,
|
||
whiteSpace: 'pre-wrap',
|
||
wordBreak: 'break-word',
|
||
color: 'var(--ink)'
|
||
}
|
||
}, item.doc)), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
flex: 'none',
|
||
padding: '12px 14px calc(12px + env(safe-area-inset-bottom))',
|
||
borderTop: '1px solid var(--line)',
|
||
background: 'var(--panel-2)',
|
||
display: 'grid',
|
||
gap: 10
|
||
}
|
||
}, rejecting ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Textarea, {
|
||
danger: true,
|
||
placeholder: "\u6539\u8FDB\u610F\u89C1\uFF08\u5FC5\u586B\uFF09",
|
||
minHeight: 56,
|
||
value: reason,
|
||
onChange: setReason
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
disabled: !reason.trim(),
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => {
|
||
onDecide(item, 'reject', reason);
|
||
onClose();
|
||
}
|
||
}, "\u786E\u8BA4\u9A73\u56DE"), /*#__PURE__*/React.createElement(Button, {
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => {
|
||
setRejecting(false);
|
||
setReason('');
|
||
}
|
||
}, "\u53D6\u6D88"))) : /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'flex',
|
||
gap: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "accept",
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => {
|
||
onDecide(item, 'accept');
|
||
onClose();
|
||
}
|
||
}, "\u2713 \u901A\u8FC7"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => setRejecting(true)
|
||
}, "\u2715 \u9A73\u56DE"))));
|
||
}
|
||
function MobGates({
|
||
approvals,
|
||
onDecide
|
||
}) {
|
||
const {
|
||
GateCard,
|
||
GateStripe,
|
||
Button,
|
||
Textarea,
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
const [rejecting, setRejecting] = React.useState(null);
|
||
const [reason, setReason] = React.useState('');
|
||
const [preview, setPreview] = React.useState(null);
|
||
if (!approvals.length) {
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
margin: '24px 14px',
|
||
padding: '38px 0',
|
||
textAlign: 'center',
|
||
color: 'var(--faint)',
|
||
border: '1px dashed var(--line)',
|
||
borderRadius: 6,
|
||
fontSize: 12
|
||
}
|
||
}, "\u65E0\u5F85\u88C1\u51B3\u5BA1\u6279");
|
||
}
|
||
return /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
padding: '12px 14px'
|
||
}
|
||
}, /*#__PURE__*/React.createElement(GateStripe, null), /*#__PURE__*/React.createElement(SectionHead, {
|
||
mark: "violet",
|
||
title: "\u5BA1\u6279\u95F8 \xB7 \u7B49\u5F85\u88C1\u51B3",
|
||
style: {
|
||
padding: '10px 0 8px',
|
||
color: 'var(--violet)'
|
||
}
|
||
}), approvals.map(a => /*#__PURE__*/React.createElement("div", {
|
||
key: a.id,
|
||
style: {
|
||
marginBottom: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(GateCard, {
|
||
gate: a.gate,
|
||
title: a.title,
|
||
meta: a.meta,
|
||
docLabel: a.docLabel,
|
||
doc: a.doc,
|
||
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
||
variant: "accept",
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => onDecide(a, 'accept')
|
||
}, "\u2713 \u901A\u8FC7"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
style: {
|
||
flex: 1,
|
||
minHeight: 44
|
||
},
|
||
onClick: () => setRejecting(rejecting === a.id ? null : a.id)
|
||
}, "\u2715 \u9A73\u56DE"), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "ghost",
|
||
style: {
|
||
minHeight: 44
|
||
},
|
||
title: "\u5168\u5C4F\u9605\u8BFB",
|
||
onClick: () => setPreview({
|
||
...a,
|
||
gateLabel: {
|
||
plan: '拆解评审',
|
||
spec: '方案评审',
|
||
exec: '结果评审'
|
||
}[a.gate] || a.gate
|
||
})
|
||
}, "\u26F6"))
|
||
}, rejecting === a.id ? /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
display: 'grid',
|
||
gap: 10,
|
||
marginTop: 10
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Textarea, {
|
||
danger: true,
|
||
placeholder: "\u6539\u8FDB\u610F\u89C1\uFF08\u5FC5\u586B\uFF09",
|
||
minHeight: 56,
|
||
value: reason,
|
||
onChange: setReason
|
||
}), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "reject",
|
||
disabled: !reason.trim(),
|
||
style: {
|
||
minHeight: 44
|
||
},
|
||
onClick: () => {
|
||
onDecide(a, 'reject', reason);
|
||
setRejecting(null);
|
||
setReason('');
|
||
}
|
||
}, "\u786E\u8BA4\u9A73\u56DE")) : null))), /*#__PURE__*/React.createElement(MobGatePreview, {
|
||
item: preview,
|
||
onDecide: onDecide,
|
||
onClose: () => setPreview(null)
|
||
}));
|
||
}
|
||
function MobEvents({
|
||
events
|
||
}) {
|
||
const {
|
||
EventItem,
|
||
SectionHead
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: "\u4E8B\u4EF6\u6D41",
|
||
style: {
|
||
padding: '14px 14px 8px'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("ul", {
|
||
style: {
|
||
listStyle: 'none',
|
||
padding: '0 14px',
|
||
margin: 0
|
||
}
|
||
}, events.map((e, i) => /*#__PURE__*/React.createElement(EventItem, {
|
||
key: i,
|
||
type: e.type,
|
||
time: e.time,
|
||
detail: e.detail
|
||
}))));
|
||
}
|
||
function MobProjects({
|
||
projects,
|
||
currentId,
|
||
onSelect,
|
||
project
|
||
}) {
|
||
const {
|
||
SectionHead,
|
||
Select,
|
||
Input,
|
||
Button
|
||
} = window.MaestroDesignSystem_a6a290;
|
||
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: "\u9879\u76EE",
|
||
style: {
|
||
padding: '14px 14px 8px'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("ul", {
|
||
style: {
|
||
listStyle: 'none',
|
||
margin: 0,
|
||
padding: 0
|
||
}
|
||
}, projects.map(p => {
|
||
const active = p.id === currentId;
|
||
return /*#__PURE__*/React.createElement("li", {
|
||
key: p.id,
|
||
onClick: () => onSelect(p.id),
|
||
style: {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 10,
|
||
minHeight: 52,
|
||
padding: '10px 14px',
|
||
cursor: 'pointer',
|
||
borderBottom: '1px solid var(--line-soft)',
|
||
borderLeft: '2px solid ' + (active ? 'var(--green)' : 'transparent'),
|
||
background: active ? 'var(--panel-2)' : 'transparent',
|
||
color: active ? 'var(--green)' : 'var(--muted)'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("svg", {
|
||
width: "16",
|
||
height: "16",
|
||
viewBox: "0 0 24 24",
|
||
fill: "none",
|
||
stroke: "currentColor",
|
||
strokeWidth: "2",
|
||
strokeLinecap: "round",
|
||
strokeLinejoin: "round",
|
||
style: {
|
||
flex: 'none'
|
||
}
|
||
}, /*#__PURE__*/React.createElement("line", {
|
||
x1: "6",
|
||
y1: "3",
|
||
x2: "6",
|
||
y2: "15"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "18",
|
||
cy: "6",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("circle", {
|
||
cx: "6",
|
||
cy: "18",
|
||
r: "3"
|
||
}), /*#__PURE__*/React.createElement("path", {
|
||
d: "M18 9a9 9 0 0 1-9 9"
|
||
})), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 1,
|
||
minWidth: 0
|
||
}
|
||
}, /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontWeight: 600,
|
||
fontSize: 13,
|
||
color: active ? 'var(--green)' : 'var(--ink)'
|
||
}
|
||
}, p.name), /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
fontSize: 10.5,
|
||
color: 'var(--faint)'
|
||
}
|
||
}, p.path)), active ? /*#__PURE__*/React.createElement("span", {
|
||
style: {
|
||
marginLeft: 'auto',
|
||
fontSize: 10,
|
||
letterSpacing: '.12em',
|
||
color: 'var(--green)'
|
||
}
|
||
}, "\u5F53\u524D") : null);
|
||
})), /*#__PURE__*/React.createElement(SectionHead, {
|
||
title: "\u9879\u76EE\u914D\u7F6E",
|
||
style: {
|
||
padding: '18px 14px 8px'
|
||
}
|
||
}), /*#__PURE__*/React.createElement("div", {
|
||
style: {
|
||
margin: '0 14px',
|
||
background: 'var(--panel)',
|
||
border: '1px solid var(--line)',
|
||
borderRadius: 6,
|
||
padding: 14,
|
||
display: 'grid',
|
||
gap: 12
|
||
}
|
||
}, /*#__PURE__*/React.createElement(Input, {
|
||
label: "\u6700\u5927\u5E76\u53D1",
|
||
type: "number",
|
||
defaultValue: String(project.concurrency)
|
||
}), /*#__PURE__*/React.createElement(Select, {
|
||
label: "\u5DE5\u4F5C\u6A21\u5F0F",
|
||
defaultValue: project.autonomy,
|
||
options: [{
|
||
value: 'manual',
|
||
label: 'manual · 手动'
|
||
}, {
|
||
value: 'auto-easy',
|
||
label: 'auto-easy · 自动执行 Easy'
|
||
}, {
|
||
value: 'auto-approved',
|
||
label: 'auto-approved · 自动执行已批准'
|
||
}]
|
||
}), /*#__PURE__*/React.createElement(Button, {
|
||
variant: "solid",
|
||
style: {
|
||
minHeight: 44
|
||
}
|
||
}, "\u4FDD\u5B58\u914D\u7F6E")));
|
||
}
|
||
Object.assign(window, {
|
||
MaestroMobTasks: MobTasks,
|
||
MaestroMobGates: MobGates,
|
||
MaestroMobEvents: MobEvents,
|
||
MaestroMobProjects: MobProjects
|
||
});
|
||
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/console_mobile/MobileViews.jsx", error: String((e && e.message) || e) }); }
|
||
|
||
__ds_ns.Button = __ds_scope.Button;
|
||
|
||
__ds_ns.ComplexityBadge = __ds_scope.ComplexityBadge;
|
||
|
||
__ds_ns.CountBadge = __ds_scope.CountBadge;
|
||
|
||
__ds_ns.QuotaMeter = __ds_scope.QuotaMeter;
|
||
|
||
__ds_ns.SectionHead = __ds_scope.SectionHead;
|
||
|
||
__ds_ns.StatusChip = __ds_scope.StatusChip;
|
||
|
||
__ds_ns.ComplexitySeg = __ds_scope.ComplexitySeg;
|
||
|
||
__ds_ns.Input = __ds_scope.Input;
|
||
|
||
__ds_ns.Select = __ds_scope.Select;
|
||
|
||
__ds_ns.Textarea = __ds_scope.Textarea;
|
||
|
||
__ds_ns.EventItem = __ds_scope.EventItem;
|
||
|
||
__ds_ns.GateCard = __ds_scope.GateCard;
|
||
|
||
__ds_ns.GateStripe = __ds_scope.GateStripe;
|
||
|
||
__ds_ns.Panel = __ds_scope.Panel;
|
||
|
||
__ds_ns.Timeline = __ds_scope.Timeline;
|
||
|
||
__ds_ns.Toast = __ds_scope.Toast;
|
||
|
||
})();
|