dsh-skill-tag 0.1.18 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +191 -152
- package/lib/index.js +88 -14
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +4 -2
- package/src/api.js +44 -10
package/lib/client.js
CHANGED
|
@@ -85,7 +85,7 @@ window.__ModuleLoader__.load({
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** 失效技能的统一配色(与「全局删除」的红一致,但更暗一点,避免抢眼)。 */
|
|
88
|
-
const STALE_COLOR = "
|
|
88
|
+
const STALE_COLOR = "var(--dsw-alias-state-error-primary)";
|
|
89
89
|
|
|
90
90
|
// zoneOf: §7 four-zone classification of a conversation tag entry.
|
|
91
91
|
function zoneOf(entry) {
|
|
@@ -352,13 +352,13 @@ window.__ModuleLoader__.load({
|
|
|
352
352
|
// 只提示不自动删;给一个显式清理入口(点击会二次确认)。
|
|
353
353
|
!loading && (state.stale ?? []).length > 0 && react.createElement("div", {
|
|
354
354
|
key: "stale",
|
|
355
|
-
style: { background: "
|
|
355
|
+
style: { background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent)", border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent)", borderRadius: "8px", padding: "8px 10px", marginBottom: "12px", fontSize: "12px", color: "var(--dsw-alias-state-warn-primary)", display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap" },
|
|
356
356
|
}, [
|
|
357
357
|
react.createElement("span", { key: "t", style: { flex: 1 } },
|
|
358
358
|
`有 ${(state.stale ?? []).length} 个技能仍有标签关联,但当前发现不到(通常是贡献它的插件被关闭)。`),
|
|
359
359
|
react.createElement("button", {
|
|
360
360
|
key: "p",
|
|
361
|
-
style: { ...btn, padding: "2px 10px", fontSize: "12px", color: "
|
|
361
|
+
style: { ...btn, padding: "2px 10px", fontSize: "12px", color: "var(--dsw-alias-state-warn-primary)" },
|
|
362
362
|
disabled: busy,
|
|
363
363
|
"data-skill-tag-purge": "1",
|
|
364
364
|
onClick: () => void purgeStale(),
|
|
@@ -369,12 +369,12 @@ window.__ModuleLoader__.load({
|
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
const pad = { fontFamily: "ui-sans-serif,system-ui", fontSize: "13px", padding: "14px 16px" };
|
|
372
|
-
const noteStyle = { padding: "6px 10px", borderRadius: "6px", background: "var(--
|
|
373
|
-
const card = { border: "1px solid var(--
|
|
374
|
-
const btn = { padding: "3px 10px", borderRadius: "6px", border: "1px solid var(--
|
|
375
|
-
const input = { padding: "4px 8px", borderRadius: "6px", border: "1px solid var(--
|
|
376
|
-
const thTd = { border: "1px solid var(--
|
|
377
|
-
const zoneColor = { loaded: "
|
|
372
|
+
const noteStyle = { padding: "6px 10px", borderRadius: "6px", background: "var(--dsw-alias-bg-layer-2)", marginBottom: "10px", whiteSpace: "pre-wrap" };
|
|
373
|
+
const card = { border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", marginBottom: "12px" };
|
|
374
|
+
const btn = { padding: "3px 10px", borderRadius: "6px", border: "1px solid var(--dsw-alias-border-l2)", background: "transparent", color: "inherit", cursor: "pointer", fontSize: "12px" };
|
|
375
|
+
const input = { padding: "4px 8px", borderRadius: "6px", border: "1px solid var(--dsw-alias-border-l2)", background: "transparent", color: "inherit", fontSize: "12px" };
|
|
376
|
+
const thTd = { border: "1px solid var(--dsw-alias-border-l1)", padding: "4px 8px" };
|
|
377
|
+
const zoneColor = { loaded: "var(--dsw-alias-state-success-primary)", exempt: "var(--dsw-alias-label-secondary)", unloaded: "var(--dsw-alias-label-secondary)", blocked: "var(--dsw-alias-state-error-primary)" };
|
|
378
378
|
|
|
379
379
|
function TagCreateForm({ state, setState, act, busy }) {
|
|
380
380
|
return react.createElement("div", { style: card }, [
|
|
@@ -409,7 +409,7 @@ window.__ModuleLoader__.load({
|
|
|
409
409
|
}));
|
|
410
410
|
return react.createElement("div", { style: card }, [
|
|
411
411
|
react.createElement("div", { key: "t", style: { fontWeight: 600, marginBottom: "6px" } }, `标签 (${tags.length})`),
|
|
412
|
-
tags.length === 0 && react.createElement("div", { key: "empty", style: { color: "
|
|
412
|
+
tags.length === 0 && react.createElement("div", { key: "empty", style: { color: "var(--dsw-alias-label-secondary)" } }, "暂无标签"),
|
|
413
413
|
...tags.map((t) => {
|
|
414
414
|
const skills = links.filter((l) => l.tagIds.includes(t.tagId)).map((l) => l.skillId);
|
|
415
415
|
// 标签内技能分区:存活在前、失效在后(分区稳定,内部保序)
|
|
@@ -417,7 +417,7 @@ window.__ModuleLoader__.load({
|
|
|
417
417
|
const hasStale = split.stale.length > 0;
|
|
418
418
|
const usedBy = workspaces.filter((w) => (w.config?.orTags ?? []).includes(t.tagId) || (w.config?.andGroups ?? []).some((g) => g.tagIds.includes(t.tagId))).map((w) => w.workspaceId);
|
|
419
419
|
const isOpen = !!open[t.tagId];
|
|
420
|
-
return react.createElement("div", { key: t.tagId, style: { padding: "4px 0", borderBottom: "1px solid var(--
|
|
420
|
+
return react.createElement("div", { key: t.tagId, style: { padding: "4px 0", borderBottom: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
421
421
|
react.createElement("div", { key: "row", style: { display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap" } }, [
|
|
422
422
|
skills.length === 0
|
|
423
423
|
? react.createElement("span", { key: "tw", style: { width: "14px", display: "inline-block" } })
|
|
@@ -436,15 +436,15 @@ window.__ModuleLoader__.load({
|
|
|
436
436
|
title: hasStale ? `该标签含 ${split.stale.length} 个失效技能(当前发现不到)` : undefined,
|
|
437
437
|
"data-skill-tag-stale-tag": hasStale ? t.tagId : undefined,
|
|
438
438
|
}, t.name),
|
|
439
|
-
react.createElement("span", { key: "id", style: { color: "
|
|
439
|
+
react.createElement("span", { key: "id", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, t.tagId),
|
|
440
440
|
react.createElement("span", {
|
|
441
|
-
key: "cnt", style: { color: "
|
|
441
|
+
key: "cnt", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" },
|
|
442
442
|
"data-skill-tag-count": t.tagId,
|
|
443
443
|
}, skills.length === 0
|
|
444
444
|
? "无 Skill 关联"
|
|
445
445
|
: `${skills.length} 个 Skill` + (hasStale ? `(${split.stale.length} 失效)` : "")),
|
|
446
446
|
react.createElement("button", {
|
|
447
|
-
key: "del", style: { ...btn, color: "
|
|
447
|
+
key: "del", style: { ...btn, color: "var(--dsw-alias-state-error-primary)" }, disabled: busy,
|
|
448
448
|
onClick: () => {
|
|
449
449
|
const msg = usedBy.length ? `该标签被工作区使用: ${usedBy.join(", ")}。全局删除将清理所有引用, 确定?` : "全局删除该标签? 所有引用将被清理。";
|
|
450
450
|
if (window.confirm(msg)) void act("/tags/delete", { tagId: t.tagId }, "已删除(工作区引用已清理)");
|
|
@@ -452,7 +452,7 @@ window.__ModuleLoader__.load({
|
|
|
452
452
|
}, "全局删除"),
|
|
453
453
|
]),
|
|
454
454
|
// 展开后才列出技能(每行仍带「打开文件夹」,这里也是"列出 skill 的界面")
|
|
455
|
-
isOpen && skills.length > 0 && react.createElement("div", { key: "sk", style: { display: "flex", gap: "6px", alignItems: "center", flexWrap: "wrap", fontSize: "11px", color: "
|
|
455
|
+
isOpen && skills.length > 0 && react.createElement("div", { key: "sk", style: { display: "flex", gap: "6px", alignItems: "center", flexWrap: "wrap", fontSize: "11px", color: "var(--dsw-alias-label-secondary)", padding: "4px 0 2px 22px" } }, [
|
|
456
456
|
// 存活技能在前
|
|
457
457
|
...split.alive.map((sid, i) => react.createElement("span", { key: sid + i, style: { display: "inline-flex", gap: "2px", alignItems: "center" } }, [
|
|
458
458
|
sid,
|
|
@@ -480,9 +480,9 @@ window.__ModuleLoader__.load({
|
|
|
480
480
|
.filter((s) => !state.pickSearch.trim() || s.skillId.toLowerCase().includes(state.pickSearch.trim().toLowerCase()));
|
|
481
481
|
const [picked, setPicked] = react.useState(() => new Set());
|
|
482
482
|
const toggle = (id) => setPicked((p) => { const n = new Set(p); n.has(id) ? n.delete(id) : n.add(id); return n; });
|
|
483
|
-
const overlay = { position: "fixed", inset: 0, zIndex: 900, background: "
|
|
484
|
-
const box = { width: "560px", maxWidth: "92vw", maxHeight: "70vh", display: "flex", flexDirection: "column", background: "var(--
|
|
485
|
-
const row = { display: "flex", alignItems: "center", gap: "8px", padding: "6px 4px", borderBottom: "1px solid var(--
|
|
483
|
+
const overlay = { position: "fixed", inset: 0, zIndex: 900, background: "var(--dsw-alias-bg-mask-1)", display: "flex", alignItems: "center", justifyContent: "center" };
|
|
484
|
+
const box = { width: "560px", maxWidth: "92vw", maxHeight: "70vh", display: "flex", flexDirection: "column", background: "var(--dsw-alias-bg-layer-1)", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "12px", padding: "14px 16px", boxShadow: "var(--dsw-elevation-prominent, 0 8px 30px rgba(0,0,0,0.5))" };
|
|
485
|
+
const row = { display: "flex", alignItems: "center", gap: "8px", padding: "6px 4px", borderBottom: "1px solid var(--dsw-alias-border-l1)", fontSize: "12px", cursor: "pointer" };
|
|
486
486
|
// 每行 = 勾选区 + 「打开文件夹」,所以行本身不再是 <label>
|
|
487
487
|
const rrow = { ...row, cursor: "default" };
|
|
488
488
|
const confirm = async () => {
|
|
@@ -505,7 +505,7 @@ window.__ModuleLoader__.load({
|
|
|
505
505
|
value: state.pickSearch, onChange: (e) => setState((s) => ({ ...s, pickSearch: e.target.value })),
|
|
506
506
|
}),
|
|
507
507
|
react.createElement("div", { key: "list", style: { flex: 1, overflowY: "auto", minHeight: "120px" } }, [
|
|
508
|
-
all.length === 0 && react.createElement("div", { style: { color: "
|
|
508
|
+
all.length === 0 && react.createElement("div", { style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "10px 2px" } }, "没有可添加的 Skill(全部已关联, 或本机未扫描到)"),
|
|
509
509
|
...all.map((s) => {
|
|
510
510
|
const ghost = s.ghost || !(state.skills ?? []).some((x) => x.name === s.skillId);
|
|
511
511
|
return react.createElement("div", { key: s.skillId, style: rrow }, [
|
|
@@ -518,12 +518,12 @@ window.__ModuleLoader__.load({
|
|
|
518
518
|
}),
|
|
519
519
|
]),
|
|
520
520
|
react.createElement("div", { key: "f", style: { display: "flex", justifyContent: "flex-end", gap: "8px", marginTop: "10px" } }, [
|
|
521
|
-
react.createElement("span", { key: "cnt", style: { color: "
|
|
521
|
+
react.createElement("span", { key: "cnt", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", marginRight: "auto" } }, picked.size ? `已选 ${picked.size} 个` : ""),
|
|
522
522
|
react.createElement("button", { key: "c", style: btn, onClick: () => setState((s) => ({ ...s, pickOpen: false, pickSearch: "" })) }, "取消"),
|
|
523
|
-
react.createElement("button", { key: "ok", style: { ...btn, color: "
|
|
523
|
+
react.createElement("button", { key: "ok", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" }, disabled: busy || picked.size === 0, onClick: () => void confirm() }, `添加(${picked.size})`),
|
|
524
524
|
]),
|
|
525
525
|
(data.skillLinks ?? []).some((l) => !(state.skills ?? []).some((s) => s.name === l.skillId)) &&
|
|
526
|
-
react.createElement("div", { key: "g", style: { color: "
|
|
526
|
+
react.createElement("div", { key: "g", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "6px" } }, "* 未在本机扫描到的关联仍生效; 带星号项同样可以添加。"),
|
|
527
527
|
]));
|
|
528
528
|
}
|
|
529
529
|
|
|
@@ -557,14 +557,14 @@ window.__ModuleLoader__.load({
|
|
|
557
557
|
? act("/tags/unlink", { skillId }, `已移除 ${skillId}`)
|
|
558
558
|
: act("/tags/link", { skillId, tagIds: next }, `已移除 ${skillId}`));
|
|
559
559
|
};
|
|
560
|
-
const colStyle = { flex: "1 1 0", minWidth: "260px", border: "1px solid var(--
|
|
561
|
-
const rowStyle = { display: "flex", gap: "8px", alignItems: "center", padding: "5px 4px", borderBottom: "1px solid var(--
|
|
562
|
-
const selRowStyle = { ...rowStyle, background: "var(--
|
|
560
|
+
const colStyle = { flex: "1 1 0", minWidth: "260px", border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", display: "flex", flexDirection: "column" };
|
|
561
|
+
const rowStyle = { display: "flex", gap: "8px", alignItems: "center", padding: "5px 4px", borderBottom: "1px solid var(--dsw-alias-border-l1)", fontSize: "12px" };
|
|
562
|
+
const selRowStyle = { ...rowStyle, background: "var(--dsw-alias-bg-layer-2)", borderRadius: "6px" };
|
|
563
563
|
return react.createElement("div", { style: { ...pad, maxWidth: "960px" } }, [
|
|
564
564
|
react.createElement("div", { key: "head", style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "10px" } }, [
|
|
565
565
|
react.createElement("button", { key: "back", style: btn, disabled: busy, onClick: () => setState((s) => ({ ...s, view: "main", linkTagId: null })) }, "← 返回"),
|
|
566
566
|
react.createElement("h3", { key: "t", style: { margin: 0 } }, "tag 联系 skill"),
|
|
567
|
-
sel && react.createElement("span", { key: "cur", style: { color: "
|
|
567
|
+
sel && react.createElement("span", { key: "cur", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, `当前标签: ${sel.name}`),
|
|
568
568
|
]),
|
|
569
569
|
notice && react.createElement("div", { key: "n", style: noteStyle }, notice),
|
|
570
570
|
react.createElement("div", { key: "cols", style: { display: "flex", gap: "12px", alignItems: "flex-start" } }, [
|
|
@@ -576,7 +576,7 @@ window.__ModuleLoader__.load({
|
|
|
576
576
|
value: state.tagSearch, onChange: (e) => setState((s) => ({ ...s, tagSearch: e.target.value })),
|
|
577
577
|
}),
|
|
578
578
|
react.createElement("div", { key: "rows", style: { maxHeight: "420px", overflowY: "auto" } }, [
|
|
579
|
-
tags.filter(tagMatch).length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
579
|
+
tags.filter(tagMatch).length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 2px" } }, "无匹配标签"),
|
|
580
580
|
...tags.filter(tagMatch).map((t) => {
|
|
581
581
|
const n = links.filter((l) => l.tagIds.includes(t.tagId)).length;
|
|
582
582
|
// 含失效技能的标签:只把**标签名**标红(图三的要求),其余样式不变
|
|
@@ -591,9 +591,9 @@ window.__ModuleLoader__.load({
|
|
|
591
591
|
style: { fontWeight: t.tagId === selId ? 600 : 400, flex: 1, cursor: "pointer", ...(hasStale ? { color: STALE_COLOR } : {}) },
|
|
592
592
|
"data-skill-tag-stale-tag": hasStale ? t.tagId : undefined,
|
|
593
593
|
}, t.name),
|
|
594
|
-
react.createElement("span", { key: "c", style: { color: "
|
|
594
|
+
react.createElement("span", { key: "c", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, n ? `${n} skill` : ""),
|
|
595
595
|
react.createElement("button", {
|
|
596
|
-
key: "del", style: { ...btn, color: "
|
|
596
|
+
key: "del", style: { ...btn, color: "var(--dsw-alias-state-error-primary)", padding: "1px 8px" }, disabled: busy,
|
|
597
597
|
onClick: (e) => {
|
|
598
598
|
e.stopPropagation();
|
|
599
599
|
const usedBy = (data.workspaces ?? []).filter((w) => (w.config?.orTags ?? []).includes(t.tagId) || (w.config?.andGroups ?? []).some((g) => g.tagIds.includes(t.tagId))).map((w) => w.workspaceId);
|
|
@@ -608,7 +608,7 @@ window.__ModuleLoader__.load({
|
|
|
608
608
|
]);
|
|
609
609
|
}),
|
|
610
610
|
]),
|
|
611
|
-
react.createElement("div", { key: "create", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
611
|
+
react.createElement("div", { key: "create", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
612
612
|
react.createElement("input", {
|
|
613
613
|
key: "name", style: { ...input, flex: 1 }, placeholder: "新标签名称",
|
|
614
614
|
value: state.newTagName, onChange: (e) => setState((s) => ({ ...s, newTagName: e.target.value })),
|
|
@@ -620,14 +620,14 @@ window.__ModuleLoader__.load({
|
|
|
620
620
|
// ── right column: skills of the selected tag ──────────────
|
|
621
621
|
react.createElement("div", { key: "right", style: colStyle }, [
|
|
622
622
|
react.createElement("div", { key: "rt", style: { fontWeight: 600, marginBottom: "6px" } }, sel ? `关联 Skill — ${sel.name}` : "关联 Skill"),
|
|
623
|
-
!sel && react.createElement("div", { key: "hint", style: { color: "
|
|
623
|
+
!sel && react.createElement("div", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "8px 0" } }, "← 先在左侧选中一个标签"),
|
|
624
624
|
sel && react.createElement(react.Fragment, { key: "panel" }, [
|
|
625
625
|
react.createElement("input", {
|
|
626
626
|
key: "search", style: { ...input, width: "100%", marginBottom: "6px" }, placeholder: "搜索 Skill…",
|
|
627
627
|
value: state.skillSearch, onChange: (e) => setState((s) => ({ ...s, skillSearch: e.target.value })),
|
|
628
628
|
}),
|
|
629
629
|
react.createElement("div", { key: "rows", style: { maxHeight: "340px", overflowY: "auto" } }, [
|
|
630
|
-
linkedSkills.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
630
|
+
linkedSkills.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 2px" } }, "该标签暂未关联任何 Skill"),
|
|
631
631
|
// 存活技能在前
|
|
632
632
|
...linkedSplit.alive.map((s) => {
|
|
633
633
|
const ghost = !skills.some((x) => x.name === s.skillId);
|
|
@@ -635,7 +635,7 @@ window.__ModuleLoader__.load({
|
|
|
635
635
|
react.createElement("span", { key: "n", style: { flex: 1 } }, s.skillId + (ghost ? " *" : "")),
|
|
636
636
|
react.createElement(RevealButton, { key: "rev", skillName: s.skillId, skills }),
|
|
637
637
|
react.createElement("button", {
|
|
638
|
-
key: "rm", style: { ...btn, color: "
|
|
638
|
+
key: "rm", style: { ...btn, color: "var(--dsw-alias-state-warn-primary)", padding: "1px 8px" }, disabled: busy,
|
|
639
639
|
onClick: () => void removeSkill(s.skillId),
|
|
640
640
|
}, "移除"),
|
|
641
641
|
]);
|
|
@@ -650,14 +650,14 @@ window.__ModuleLoader__.load({
|
|
|
650
650
|
react.createElement("span", { key: "n", style: { flex: 1, color: STALE_COLOR, textDecoration: "line-through" } }, s.skillId),
|
|
651
651
|
// 仍允许移除(用户可能就是想清掉它)
|
|
652
652
|
react.createElement("button", {
|
|
653
|
-
key: "rm", style: { ...btn, color: "
|
|
653
|
+
key: "rm", style: { ...btn, color: "var(--dsw-alias-state-warn-primary)", padding: "1px 8px" }, disabled: busy,
|
|
654
654
|
onClick: () => void removeSkill(s.skillId),
|
|
655
655
|
}, "移除"),
|
|
656
656
|
])),
|
|
657
657
|
]),
|
|
658
|
-
react.createElement("div", { key: "add", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
658
|
+
react.createElement("div", { key: "add", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
659
659
|
react.createElement("button", {
|
|
660
|
-
key: "open", style: { ...btn, color: "
|
|
660
|
+
key: "open", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" }, disabled: busy,
|
|
661
661
|
onClick: () => setState((s) => ({ ...s, pickOpen: true, pickSearch: "" })),
|
|
662
662
|
}, "添加关联…"),
|
|
663
663
|
]),
|
|
@@ -665,7 +665,7 @@ window.__ModuleLoader__.load({
|
|
|
665
665
|
]),
|
|
666
666
|
]),
|
|
667
667
|
links.some((l) => !skills.some((s) => s.name === l.skillId)) &&
|
|
668
|
-
react.createElement("div", { key: "ghost", style: { color: "
|
|
668
|
+
react.createElement("div", { key: "ghost", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "8px" } }, "* 带星号的关联在本机扫描中未找到对应 Skill(关联仍生效)。"),
|
|
669
669
|
state.pickOpen && sel && react.createElement(SkillPickerModal, { key: "modal", data, state, setState, act, busy }),
|
|
670
670
|
]);
|
|
671
671
|
}
|
|
@@ -714,15 +714,15 @@ window.__ModuleLoader__.load({
|
|
|
714
714
|
void saveTags(next);
|
|
715
715
|
};
|
|
716
716
|
|
|
717
|
-
const colStyle = { flex: "1 1 0", minWidth: "260px", border: "1px solid var(--
|
|
718
|
-
const rowStyle = { display: "flex", gap: "8px", alignItems: "center", padding: "5px 4px", borderBottom: "1px solid var(--
|
|
719
|
-
const selRowStyle = { ...rowStyle, background: "var(--
|
|
717
|
+
const colStyle = { flex: "1 1 0", minWidth: "260px", border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", display: "flex", flexDirection: "column" };
|
|
718
|
+
const rowStyle = { display: "flex", gap: "8px", alignItems: "center", padding: "5px 4px", borderBottom: "1px solid var(--dsw-alias-border-l1)", fontSize: "12px" };
|
|
719
|
+
const selRowStyle = { ...rowStyle, background: "var(--dsw-alias-bg-layer-2)", borderRadius: "6px" };
|
|
720
720
|
|
|
721
721
|
return react.createElement("div", { style: { ...pad, maxWidth: "960px" } }, [
|
|
722
722
|
react.createElement("div", { key: "head", style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "10px", flexWrap: "wrap" } }, [
|
|
723
723
|
react.createElement("button", { key: "back", style: btn, disabled: busy, onClick: () => setState((s) => ({ ...s, view: "main", linkSkillName: null })) }, "← 返回"),
|
|
724
724
|
react.createElement("h3", { key: "t", style: { margin: 0 } }, "skill 联系 tag"),
|
|
725
|
-
selName && react.createElement("span", { key: "cur", style: { color: "
|
|
725
|
+
selName && react.createElement("span", { key: "cur", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, `当前技能: ${selName}`),
|
|
726
726
|
// 刷新技能列表:插件关停/启用后手动同步(服务端每次都是实时查询,
|
|
727
727
|
// 这里只是把前端那份缓存重新拉一遍)。
|
|
728
728
|
react.createElement("button", {
|
|
@@ -738,7 +738,7 @@ window.__ModuleLoader__.load({
|
|
|
738
738
|
// 选中了一个当前已经失效的技能:右侧标签仍可看/可改,但要讲清原因。
|
|
739
739
|
selIsStale && react.createElement("div", {
|
|
740
740
|
key: "staleSel",
|
|
741
|
-
style: { background: "
|
|
741
|
+
style: { background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent)", border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent)", borderRadius: "8px", padding: "6px 10px", marginBottom: "10px", fontSize: "12px", color: "var(--dsw-alias-state-warn-primary)" },
|
|
742
742
|
}, `「${selName}」当前发现不到(通常是贡献它的插件被关闭)。标签关联仍保留,重新启用插件后自动恢复可见。`),
|
|
743
743
|
react.createElement("div", { key: "cols", style: { display: "flex", gap: "12px", alignItems: "flex-start" } }, [
|
|
744
744
|
// ── 左列:技能 ──────────────────────────────────────────
|
|
@@ -750,7 +750,7 @@ window.__ModuleLoader__.load({
|
|
|
750
750
|
value: state.skillPickSearch, onChange: (e) => setState((s) => ({ ...s, skillPickSearch: e.target.value })),
|
|
751
751
|
}),
|
|
752
752
|
react.createElement("div", { key: "rows", style: { maxHeight: "420px", overflowY: "auto" } }, [
|
|
753
|
-
shown.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
753
|
+
shown.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 2px" } },
|
|
754
754
|
names.length === 0 ? "本机没有扫描到任何技能" : "无匹配技能"),
|
|
755
755
|
...shown.map((n) => {
|
|
756
756
|
const nTags = links.find((l) => l.skillId === n.name)?.tagIds?.length ?? 0;
|
|
@@ -760,7 +760,7 @@ window.__ModuleLoader__.load({
|
|
|
760
760
|
title: n.ghost ? "本机扫描中未找到该技能(连接记录仍生效)" : "点击选中",
|
|
761
761
|
}, [
|
|
762
762
|
react.createElement("span", { key: "n", style: { fontWeight: n.name === selName ? 600 : 400, flex: 1, cursor: "pointer" } }, n.name + (n.ghost ? " *" : "")),
|
|
763
|
-
react.createElement("span", { key: "c", style: { color: "
|
|
763
|
+
react.createElement("span", { key: "c", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, nTags ? `${nTags} tag` : ""),
|
|
764
764
|
!n.ghost && react.createElement(RevealButton, { key: "rev", skillName: n.name, skills: scanned, label: "📁" }),
|
|
765
765
|
]);
|
|
766
766
|
}),
|
|
@@ -768,12 +768,12 @@ window.__ModuleLoader__.load({
|
|
|
768
768
|
// 失效技能单列:只在有标签关联、但当前发现不到时出现。
|
|
769
769
|
// 位置固定在最底部(图一的要求),名字标红 + 删除线;
|
|
770
770
|
// 计数不算进上面的「技能 (N)」;默认不删,给一个显式清理入口。
|
|
771
|
-
stale.length > 0 && react.createElement("div", { key: "staleBox", style: { marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
772
|
-
react.createElement("div", { key: "h", style: { display: "flex", alignItems: "center", gap: "8px", fontSize: "12px", color: "
|
|
771
|
+
stale.length > 0 && react.createElement("div", { key: "staleBox", style: { marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
772
|
+
react.createElement("div", { key: "h", style: { display: "flex", alignItems: "center", gap: "8px", fontSize: "12px", color: "var(--dsw-alias-state-warn-primary)", marginBottom: "4px" } }, [
|
|
773
773
|
react.createElement("span", { key: "t", style: { flex: 1 } }, `失效 ${stale.length} 个(有标签关联,但当前发现不到)`),
|
|
774
774
|
react.createElement("button", {
|
|
775
775
|
key: "p",
|
|
776
|
-
style: { ...btn, padding: "1px 8px", fontSize: "11px", color: "
|
|
776
|
+
style: { ...btn, padding: "1px 8px", fontSize: "11px", color: "var(--dsw-alias-state-warn-primary)" },
|
|
777
777
|
disabled: busy,
|
|
778
778
|
"data-skill-tag-purge": "1",
|
|
779
779
|
onClick: () => void purgeStale(),
|
|
@@ -788,25 +788,25 @@ window.__ModuleLoader__.load({
|
|
|
788
788
|
react.createElement("span", { key: "n", style: { flex: 1, color: STALE_COLOR, textDecoration: "line-through" } }, s.skillId),
|
|
789
789
|
react.createElement("span", { key: "c", style: { fontSize: "11px" } }, `${(s.tagIds ?? []).length} tag`),
|
|
790
790
|
])),
|
|
791
|
-
stale.length > 30 && react.createElement("div", { key: "more", style: { color: "
|
|
791
|
+
stale.length > 30 && react.createElement("div", { key: "more", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", padding: "2px 4px" } }, `…还有 ${stale.length - 30} 个`),
|
|
792
792
|
]),
|
|
793
793
|
]),
|
|
794
794
|
// ── 右列:该技能的标签 ──────────────────────────────────
|
|
795
795
|
react.createElement("div", { key: "right", style: colStyle }, [
|
|
796
796
|
react.createElement("div", { key: "rt", style: { fontWeight: 600, marginBottom: "6px" } },
|
|
797
797
|
selName ? `标签 — ${selName} (${ownedIds.length})` : "标签"),
|
|
798
|
-
!selName && react.createElement("div", { key: "hint", style: { color: "
|
|
798
|
+
!selName && react.createElement("div", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "8px 0" } }, "← 先在左侧选中一个技能"),
|
|
799
799
|
selName && react.createElement(react.Fragment, { key: "panel" }, [
|
|
800
|
-
react.createElement("div", { key: "hint", style: { color: "
|
|
800
|
+
react.createElement("div", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginBottom: "6px" } },
|
|
801
801
|
"勾选即保存:这个技能拥有的标签决定它在各工作区/对话里是否被标签规则命中。"),
|
|
802
802
|
react.createElement("input", {
|
|
803
803
|
key: "search", style: { ...input, width: "100%", marginBottom: "6px" }, placeholder: "搜索标签…",
|
|
804
804
|
value: state.skillTagSearch, onChange: (e) => setState((s) => ({ ...s, skillTagSearch: e.target.value })),
|
|
805
805
|
}),
|
|
806
806
|
react.createElement("div", { key: "rows", style: { maxHeight: "360px", overflowY: "auto" } }, [
|
|
807
|
-
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
807
|
+
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 2px" } }, "还没有任何标签,请先在主页面新建"),
|
|
808
808
|
tagsShown.length === 0 && tags.length > 0 &&
|
|
809
|
-
react.createElement("div", { key: "e2", style: { color: "
|
|
809
|
+
react.createElement("div", { key: "e2", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 2px" } }, "无匹配标签"),
|
|
810
810
|
...tagsShown.map((t) => react.createElement("label", { key: t.tagId, style: { ...rowStyle, cursor: "pointer" } }, [
|
|
811
811
|
react.createElement("input", {
|
|
812
812
|
key: "c", type: "checkbox", checked: owned.has(t.tagId), disabled: busy,
|
|
@@ -816,11 +816,11 @@ window.__ModuleLoader__.load({
|
|
|
816
816
|
...ownedIds.slice(0, 0),
|
|
817
817
|
])),
|
|
818
818
|
]),
|
|
819
|
-
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
820
|
-
react.createElement("span", { key: "cnt", style: { color: "
|
|
819
|
+
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)", flexWrap: "wrap" } }, [
|
|
820
|
+
react.createElement("span", { key: "cnt", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginRight: "auto" } },
|
|
821
821
|
ownedIds.length ? "已拥有: " + ownedIds.map((id) => tags.find((t) => t.tagId === id)?.name ?? id).join(", ") : "该技能没有任何标签"),
|
|
822
822
|
react.createElement("button", {
|
|
823
|
-
key: "clr", style: { ...btn, color: "
|
|
823
|
+
key: "clr", style: { ...btn, color: "var(--dsw-alias-state-error-primary)" }, disabled: busy || ownedIds.length === 0,
|
|
824
824
|
onClick: () => void saveTags([]),
|
|
825
825
|
}, "清空标签"),
|
|
826
826
|
]),
|
|
@@ -828,7 +828,7 @@ window.__ModuleLoader__.load({
|
|
|
828
828
|
]),
|
|
829
829
|
]),
|
|
830
830
|
links.some((l) => !scanned.some((s) => s.name === l.skillId)) &&
|
|
831
|
-
react.createElement("div", { key: "ghost", style: { color: "
|
|
831
|
+
react.createElement("div", { key: "ghost", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "8px" } }, "* 带星号的技能在本机扫描中未找到(连接记录仍生效)。"),
|
|
832
832
|
]);
|
|
833
833
|
}
|
|
834
834
|
|
|
@@ -940,13 +940,13 @@ window.__ModuleLoader__.load({
|
|
|
940
940
|
if (ok !== null && id === state.tplId) closeEditor();
|
|
941
941
|
};
|
|
942
942
|
|
|
943
|
-
const panel = { border: "1px solid var(--
|
|
943
|
+
const panel = { border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", marginBottom: "10px" };
|
|
944
944
|
const panelTitle = { fontWeight: 600, marginBottom: "6px", fontSize: "12px" };
|
|
945
|
-
const chip = { display: "inline-flex", alignItems: "center", gap: "4px", border: "1px solid var(--
|
|
945
|
+
const chip = { display: "inline-flex", alignItems: "center", gap: "4px", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "8px", padding: "2px 8px", margin: "0 6px 6px 0", fontSize: "12px" };
|
|
946
946
|
const mono = { fontFamily: "ui-monospace,monospace" };
|
|
947
|
-
const errText = { color: "
|
|
948
|
-
const okText = { color: "
|
|
949
|
-
const warnText = { color: "
|
|
947
|
+
const errText = { color: "var(--dsw-alias-state-error-primary)", fontSize: "12px", marginTop: "4px" };
|
|
948
|
+
const okText = { color: "var(--dsw-alias-state-success-primary)", fontSize: "12px", marginTop: "4px" };
|
|
949
|
+
const warnText = { color: "var(--dsw-alias-state-warn-primary)", fontSize: "12px", marginTop: "4px" };
|
|
950
950
|
|
|
951
951
|
const visibleTags = tags.filter((t) => !tagQuery.trim() || t.name.toLowerCase().includes(tagQuery.trim().toLowerCase()));
|
|
952
952
|
const errors = validation?.errors ?? [];
|
|
@@ -962,27 +962,27 @@ window.__ModuleLoader__.load({
|
|
|
962
962
|
react.createElement("div", { key: "head", style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "10px", flexWrap: "wrap" } }, [
|
|
963
963
|
react.createElement("button", { key: "back", style: btn, disabled: busy, onClick: () => setState((s) => ({ ...s, view: "main" })) }, "← 返回"),
|
|
964
964
|
react.createElement("h3", { key: "t", style: { margin: 0 } }, "标签组配置"),
|
|
965
|
-
react.createElement("button", { key: "new", style: { ...btn, color: "
|
|
966
|
-
sel && react.createElement("span", { key: "cur", style: { color: "
|
|
967
|
-
!sel && state.tplIsNew && react.createElement("span", { key: "draft", style: { color: "
|
|
965
|
+
react.createElement("button", { key: "new", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" }, disabled: busy, onClick: newTpl }, "+ 新建标签组"),
|
|
966
|
+
sel && react.createElement("span", { key: "cur", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, `当前: ${sel.name}`),
|
|
967
|
+
!sel && state.tplIsNew && react.createElement("span", { key: "draft", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "新标签组(未保存)"),
|
|
968
968
|
]),
|
|
969
969
|
notice && react.createElement("div", { key: "n", style: noteStyle }, notice),
|
|
970
|
-
localNotice && react.createElement("div", { key: "ln", style: { ...noteStyle, color: "
|
|
970
|
+
localNotice && react.createElement("div", { key: "ln", style: { ...noteStyle, color: "var(--dsw-alias-state-error-primary)" } }, localNotice),
|
|
971
971
|
|
|
972
972
|
// ── 标签组列表(选择/删除)──────────────────────────────────
|
|
973
973
|
react.createElement("div", { key: "list", style: panel }, [
|
|
974
974
|
react.createElement("div", { key: "lt", style: panelTitle }, `标签组 (${templates.length})`),
|
|
975
|
-
templates.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
975
|
+
templates.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "暂无标签组,点上方「+ 新建标签组」开始"),
|
|
976
976
|
react.createElement("div", { key: "chips" }, templates.map((t) => react.createElement("span", {
|
|
977
977
|
key: t.templateId,
|
|
978
|
-
style: { ...chip, cursor: "pointer", borderColor: t.templateId === state.tplId ? "
|
|
978
|
+
style: { ...chip, cursor: "pointer", borderColor: t.templateId === state.tplId ? "var(--dsw-alias-state-success-primary)" : "var(--dsw-alias-border-l2)" },
|
|
979
979
|
title: "点击编辑",
|
|
980
980
|
onClick: () => openTpl(t),
|
|
981
981
|
}, [
|
|
982
982
|
react.createElement("strong", { key: "n" }, t.name),
|
|
983
|
-
react.createElement("span", { key: "x", style: { ...mono, color: "
|
|
983
|
+
react.createElement("span", { key: "x", style: { ...mono, color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, t.expression || "(空)"),
|
|
984
984
|
react.createElement("button", {
|
|
985
|
-
key: "d", style: { ...btn, padding: "0 5px", fontSize: "11px", color: "
|
|
985
|
+
key: "d", style: { ...btn, padding: "0 5px", fontSize: "11px", color: "var(--dsw-alias-state-error-primary)" }, disabled: busy,
|
|
986
986
|
onClick: (e) => { e.stopPropagation(); void deleteTpl(t.templateId, t.name); },
|
|
987
987
|
}, "×"),
|
|
988
988
|
]))),
|
|
@@ -996,11 +996,11 @@ window.__ModuleLoader__.load({
|
|
|
996
996
|
key: "q", style: { ...input, width: "180px" }, placeholder: "搜索标签…",
|
|
997
997
|
value: tagQuery, onChange: (e) => setTagQuery(e.target.value),
|
|
998
998
|
}),
|
|
999
|
-
react.createElement("span", { key: "hint", style: { color: "
|
|
999
|
+
react.createElement("span", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", fontWeight: 400 } },
|
|
1000
1000
|
"点击标签插入到表达式光标处;含空格或运算符的名称会自动加引号"),
|
|
1001
1001
|
]),
|
|
1002
|
-
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
1003
|
-
tags.length > 0 && visibleTags.length === 0 && react.createElement("div", { key: "nf", style: { color: "
|
|
1002
|
+
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "还没有标签 — 请先回到「Skill 标签」页创建标签"),
|
|
1003
|
+
tags.length > 0 && visibleTags.length === 0 && react.createElement("div", { key: "nf", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "无匹配标签"),
|
|
1004
1004
|
react.createElement("div", { key: "chips" }, visibleTags.map((t) => react.createElement("button", {
|
|
1005
1005
|
key: t.tagId,
|
|
1006
1006
|
style: { ...chip, cursor: editing ? "pointer" : "not-allowed", opacity: editing ? 1 : 0.5, background: "transparent", color: "inherit" },
|
|
@@ -1008,14 +1008,14 @@ window.__ModuleLoader__.load({
|
|
|
1008
1008
|
title: editing ? "插入表达式" : "请先新建或选中一个标签组",
|
|
1009
1009
|
onClick: () => insertAtCursor(quoteTagName(t.name), { operand: true }),
|
|
1010
1010
|
}, t.name))),
|
|
1011
|
-
!editing && react.createElement("div", { key: "need", style: { color: "
|
|
1011
|
+
!editing && react.createElement("div", { key: "need", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "4px" } },
|
|
1012
1012
|
"提示:先在下方「新建标签组」或点列表中的标签组,标签才可点击插入"),
|
|
1013
1013
|
]),
|
|
1014
1014
|
|
|
1015
1015
|
// ── 下方:表达式输入区 ──────────────────────────────────────
|
|
1016
1016
|
react.createElement("div", { key: "expr", style: panel }, [
|
|
1017
1017
|
react.createElement("div", { key: "et", style: panelTitle }, "表达式"),
|
|
1018
|
-
!editing && react.createElement("div", { key: "idle", style: { color: "
|
|
1018
|
+
!editing && react.createElement("div", { key: "idle", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "6px 0" } },
|
|
1019
1019
|
"未在编辑。点上方「+ 新建标签组」创建,或点列表中的标签组编辑(将回显已保存的表达式)。"),
|
|
1020
1020
|
editing && react.createElement(react.Fragment, { key: "form" }, [
|
|
1021
1021
|
react.createElement("div", { key: "name", style: { display: "flex", gap: "8px", alignItems: "center", marginBottom: "8px" } }, [
|
|
@@ -1036,20 +1036,20 @@ window.__ModuleLoader__.load({
|
|
|
1036
1036
|
}),
|
|
1037
1037
|
// 运算符工具条
|
|
1038
1038
|
react.createElement("div", { key: "ops", style: { display: "flex", gap: "6px", alignItems: "center", flexWrap: "wrap", marginTop: "6px" } }, [
|
|
1039
|
-
react.createElement("span", { key: "l", style: { color: "
|
|
1039
|
+
react.createElement("span", { key: "l", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, "插入:"),
|
|
1040
1040
|
...[[ "+", "OR" ], [ "*", "AND" ], [ "(", "" ], [ ")", "" ]].map(([sym, label]) => react.createElement("button", {
|
|
1041
1041
|
key: sym, style: { ...btn, ...mono, padding: "1px 9px" }, disabled: busy,
|
|
1042
1042
|
title: label ? `${sym} = ${label}` : `插入 ${sym}`,
|
|
1043
1043
|
onClick: () => insertAtCursor(sym),
|
|
1044
1044
|
}, sym + (label ? ` ${label}` : ""))),
|
|
1045
1045
|
react.createElement("button", {
|
|
1046
|
-
key: "clr", style: { ...btn, color: "
|
|
1046
|
+
key: "clr", style: { ...btn, color: "var(--dsw-alias-state-warn-primary)", marginLeft: "auto" }, disabled: busy || !expr,
|
|
1047
1047
|
onClick: () => { setState((s) => ({ ...s, tplExpression: "" })); setLocalNotice(null); },
|
|
1048
1048
|
}, "清空"),
|
|
1049
1049
|
]),
|
|
1050
1050
|
// 校验结果
|
|
1051
1051
|
react.createElement("div", { key: "val", style: { marginTop: "8px" } }, [
|
|
1052
|
-
checking && react.createElement("div", { key: "c", style: { color: "
|
|
1052
|
+
checking && react.createElement("div", { key: "c", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "校验中…"),
|
|
1053
1053
|
!checking && validation && validation.ok && react.createElement("div", { key: "ok", style: okText }, "✓ 表达式合法"),
|
|
1054
1054
|
!checking && validation && !validation.ok && react.createElement("div", { key: "err" },
|
|
1055
1055
|
errors.map((er, i) => react.createElement("div", { key: i, style: errText }, [
|
|
@@ -1067,26 +1067,26 @@ window.__ModuleLoader__.load({
|
|
|
1067
1067
|
]))),
|
|
1068
1068
|
!checking && warnings.map((w, i) => react.createElement("div", { key: "w" + i, style: warnText }, "⚠ " + w.message)),
|
|
1069
1069
|
!checking && validation && validation.ok && validation.normalized && validation.normalized !== expr.trim() &&
|
|
1070
|
-
react.createElement("div", { key: "norm", style: { color: "
|
|
1070
|
+
react.createElement("div", { key: "norm", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "4px" } },
|
|
1071
1071
|
"规范化: " + validation.normalized),
|
|
1072
|
-
!checking && preview && react.createElement("div", { key: "pv", style: { color: "
|
|
1072
|
+
!checking && preview && react.createElement("div", { key: "pv", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "2px" } },
|
|
1073
1073
|
"解析结果: " + preview),
|
|
1074
1074
|
]),
|
|
1075
1075
|
// 保存 / 删除
|
|
1076
|
-
react.createElement("div", { key: "acts", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
1076
|
+
react.createElement("div", { key: "acts", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
1077
1077
|
react.createElement("button", {
|
|
1078
|
-
key: "save", style: { ...btn, color: "
|
|
1078
|
+
key: "save", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" },
|
|
1079
1079
|
disabled: busy || checking || !(state.tplName ?? "").trim() || !validation?.ok,
|
|
1080
1080
|
title: !validation?.ok ? "表达式需先通过校验" : "",
|
|
1081
1081
|
onClick: () => void saveTpl(),
|
|
1082
1082
|
}, state.tplIsNew ? "保存新建" : "保存"),
|
|
1083
1083
|
!state.tplIsNew && react.createElement("button", {
|
|
1084
|
-
key: "del", style: { ...btn, color: "
|
|
1084
|
+
key: "del", style: { ...btn, color: "var(--dsw-alias-state-error-primary)" }, disabled: busy,
|
|
1085
1085
|
onClick: () => void deleteTpl(state.tplId, sel?.name),
|
|
1086
1086
|
}, "删除标签组"),
|
|
1087
1087
|
react.createElement("button", { key: "cancel", style: btn, disabled: busy, onClick: closeEditor }, "关闭编辑"),
|
|
1088
1088
|
]),
|
|
1089
|
-
react.createElement("div", { key: "use", style: { color: "
|
|
1089
|
+
react.createElement("div", { key: "use", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "8px" } },
|
|
1090
1090
|
"语法: + 表示 OR,* 表示 AND,优先级 * 高于 +,可用括号。例 A+B*C = A OR (B AND C); (A+B)*C = (A OR B) AND C。"),
|
|
1091
1091
|
]),
|
|
1092
1092
|
]),
|
|
@@ -1176,7 +1176,7 @@ window.__ModuleLoader__.load({
|
|
|
1176
1176
|
"background:transparent", "color:inherit", "cursor:pointer",
|
|
1177
1177
|
"font:inherit", "text-align:left",
|
|
1178
1178
|
].join(";");
|
|
1179
|
-
button.addEventListener("mouseenter", () => { button.style.background = "var(--
|
|
1179
|
+
button.addEventListener("mouseenter", () => { button.style.background = "var(--dsw-alias-bg-layer-1)"; });
|
|
1180
1180
|
button.addEventListener("mouseleave", () => { button.style.background = "transparent"; });
|
|
1181
1181
|
button.addEventListener("click", (e) => {
|
|
1182
1182
|
e.preventDefault();
|
|
@@ -1307,10 +1307,10 @@ window.__ModuleLoader__.load({
|
|
|
1307
1307
|
});
|
|
1308
1308
|
}
|
|
1309
1309
|
|
|
1310
|
-
const overlayStyle = { position: "fixed", inset: 0, zIndex: 1100, background: "
|
|
1311
|
-
const modalBox = { width: "900px", maxWidth: "94vw", maxHeight: "82vh", display: "flex", flexDirection: "column", background: "var(--
|
|
1312
|
-
const colStyle = { border: "1px solid var(--
|
|
1313
|
-
const listRow = { display: "flex", alignItems: "center", gap: "8px", padding: "5px 2px", borderBottom: "1px solid var(--
|
|
1310
|
+
const overlayStyle = { position: "fixed", inset: 0, zIndex: 1100, background: "var(--dsw-alias-bg-mask-1)", display: "flex", alignItems: "center", justifyContent: "center" };
|
|
1311
|
+
const modalBox = { width: "900px", maxWidth: "94vw", maxHeight: "82vh", display: "flex", flexDirection: "column", background: "var(--dsw-alias-bg-layer-1)", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "12px", padding: "14px 16px", boxShadow: "var(--dsw-elevation-prominent, 0 10px 40px rgba(0,0,0,0.55))", fontFamily: "ui-sans-serif,system-ui", fontSize: "13px" };
|
|
1312
|
+
const colStyle = { border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", display: "flex", flexDirection: "column", minHeight: 0 };
|
|
1313
|
+
const listRow = { display: "flex", alignItems: "center", gap: "8px", padding: "5px 2px", borderBottom: "1px solid var(--dsw-alias-border-l1)", fontSize: "12px" };
|
|
1314
1314
|
const monoStyle = { fontFamily: "ui-monospace,monospace" };
|
|
1315
1315
|
|
|
1316
1316
|
// ── 「一键下发」确认框(工作区版专用) ───────────────────────────
|
|
@@ -1368,27 +1368,27 @@ window.__ModuleLoader__.load({
|
|
|
1368
1368
|
react.createElement("strong", { key: "t" }, "下发到该工作区下的所有对话"),
|
|
1369
1369
|
react.createElement("button", { key: "x", style: btn, onClick: onClose }, "✕"),
|
|
1370
1370
|
]),
|
|
1371
|
-
loading && react.createElement("div", { key: "l", style: { color: "
|
|
1372
|
-
err && react.createElement("div", { key: "e", style: { color: "
|
|
1371
|
+
loading && react.createElement("div", { key: "l", style: { color: "var(--dsw-alias-label-secondary)", padding: "14px 0" } }, "正在统计受影响的对话…"),
|
|
1372
|
+
err && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-state-error-primary)", padding: "8px 0" } }, err),
|
|
1373
1373
|
!loading && !err && info && react.createElement(react.Fragment, { key: "body" }, [
|
|
1374
1374
|
// 工作区为空时:必须让用户看见"这等于全部技能"
|
|
1375
|
-
isEmpty && react.createElement("div", { key: "warn", style: { background: "
|
|
1375
|
+
isEmpty && react.createElement("div", { key: "warn", style: { background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent)", border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 45%, transparent)", borderRadius: "8px", padding: "8px 10px", marginBottom: "10px", color: "var(--dsw-alias-state-warn-primary)", fontSize: "12px" } },
|
|
1376
1376
|
"⚠ 当前工作区的标签条件为空、且没有手动添加/禁用的技能。下发后这些对话会变成「空条件 = 掌握全部技能」。"),
|
|
1377
1377
|
react.createElement("div", { key: "sum", style: { fontSize: "12px", marginBottom: "8px", lineHeight: 1.7 } }, [
|
|
1378
1378
|
react.createElement("div", { key: "a" }, `该工作区下共 ${info.total ?? 0} 个对话`),
|
|
1379
|
-
react.createElement("div", { key: "b", style: { color: "
|
|
1380
|
-
react.createElement("div", { key: "c", style: { color: "
|
|
1379
|
+
react.createElement("div", { key: "b", style: { color: "var(--dsw-alias-state-success-primary)" } }, `· 从未配置过:${fresh.length} 个(默认下发)`),
|
|
1380
|
+
react.createElement("div", { key: "c", style: { color: "var(--dsw-alias-label-secondary)" } }, `· 已有自己的配置:${configured.length} 个(默认跳过)`),
|
|
1381
1381
|
]),
|
|
1382
|
-
configured.length > 0 && react.createElement("label", { key: "ow", style: { ...rowStyle, cursor: "pointer", padding: "6px 0", borderTop: "1px solid var(--
|
|
1382
|
+
configured.length > 0 && react.createElement("label", { key: "ow", style: { ...rowStyle, cursor: "pointer", padding: "6px 0", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
1383
1383
|
react.createElement("input", {
|
|
1384
1384
|
key: "c", type: "checkbox", checked: overwrite,
|
|
1385
1385
|
"data-skill-tag-push-overwrite": "1",
|
|
1386
1386
|
onChange: (e) => setOverwrite(e.target.checked),
|
|
1387
1387
|
}),
|
|
1388
|
-
react.createElement("span", { key: "t", style: { color: "
|
|
1388
|
+
react.createElement("span", { key: "t", style: { color: "var(--dsw-alias-state-warn-primary)" } },
|
|
1389
1389
|
`同时覆盖那 ${configured.length} 个已有配置的对话(会抹掉它们各自的调整)`),
|
|
1390
1390
|
]),
|
|
1391
|
-
react.createElement("div", { key: "cnt", style: { fontSize: "12px", color: "
|
|
1391
|
+
react.createElement("div", { key: "cnt", style: { fontSize: "12px", color: "var(--dsw-alias-label-secondary)", marginTop: "8px" } },
|
|
1392
1392
|
targetCount === 0
|
|
1393
1393
|
? "没有需要下发的对话。勾选上面的复选框可以覆盖已配置的对话。"
|
|
1394
1394
|
: `将实际写入 ${targetCount} 个对话`),
|
|
@@ -1396,7 +1396,7 @@ window.__ModuleLoader__.load({
|
|
|
1396
1396
|
react.createElement("div", { key: "f", style: { display: "flex", justifyContent: "flex-end", gap: "8px", marginTop: "14px" } }, [
|
|
1397
1397
|
react.createElement("button", { key: "c", style: btn, disabled: running, onClick: onClose }, "取消"),
|
|
1398
1398
|
react.createElement("button", {
|
|
1399
|
-
key: "go", style: { ...btn, background: "
|
|
1399
|
+
key: "go", style: { ...btn, background: "var(--dsw-alias-state-warn-primary)", color: "var(--dsw-alias-bg-layer-1)", borderColor: "var(--dsw-alias-state-warn-primary)" },
|
|
1400
1400
|
disabled: running || busy || loading || !!err || targetCount === 0,
|
|
1401
1401
|
"data-skill-tag-push-confirm": "1",
|
|
1402
1402
|
onClick: () => void run(),
|
|
@@ -1554,23 +1554,23 @@ window.__ModuleLoader__.load({
|
|
|
1554
1554
|
const expressionIssue = ws?.expressionIssue ?? null;
|
|
1555
1555
|
|
|
1556
1556
|
const body = () => {
|
|
1557
|
-
if (loading) return react.createElement("div", { style: { color: "
|
|
1558
|
-
if (err) return react.createElement("div", { style: { color: "
|
|
1557
|
+
if (loading) return react.createElement("div", { style: { color: "var(--dsw-alias-label-secondary)", padding: "20px 0" } }, "加载中…");
|
|
1558
|
+
if (err) return react.createElement("div", { style: { color: "var(--dsw-alias-state-error-primary)", padding: "20px 0" } }, "加载失败: " + err);
|
|
1559
1559
|
return react.createElement("div", { key: "cols", style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px", flex: 1, minHeight: 0, overflow: "hidden" } }, [
|
|
1560
1560
|
// ── 左列:标签配置 ──
|
|
1561
1561
|
react.createElement("div", { key: "left", style: colStyle }, [
|
|
1562
1562
|
react.createElement("div", { key: "h", style: { fontWeight: 600, marginBottom: "8px" } }, "标签配置"),
|
|
1563
|
-
react.createElement("div", { key: "lbl", style: { color: "
|
|
1564
|
-
react.createElement("div", { key: "expr", style: { ...monoStyle, fontSize: "12px", padding: "8px 10px", borderRadius: "8px", border: "1px solid var(--
|
|
1563
|
+
react.createElement("div", { key: "lbl", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginBottom: "4px" } }, scope.scopeLabel + "的标签条件"),
|
|
1564
|
+
react.createElement("div", { key: "expr", style: { ...monoStyle, fontSize: "12px", padding: "8px 10px", borderRadius: "8px", border: "1px solid var(--dsw-alias-border-l1)", minHeight: "44px", whiteSpace: "pre-wrap", wordBreak: "break-all" } },
|
|
1565
1565
|
expr.trim() === "" ? scope.emptyHint : expr),
|
|
1566
|
-
react.createElement("div", { key: "pv", style: { color: "
|
|
1566
|
+
react.createElement("div", { key: "pv", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "6px" } },
|
|
1567
1567
|
"解析结果: " + parsed),
|
|
1568
|
-
react.createElement("div", { key: "st", style: { color: "
|
|
1568
|
+
react.createElement("div", { key: "st", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "2px" } },
|
|
1569
1569
|
`状态: ${view.hasFilter ? "有条件筛选(严格子集)" : "无筛选(全部技能)"}`),
|
|
1570
1570
|
// 继承状态:让用户知道「这份条件是从哪来的、什么时候来的」
|
|
1571
1571
|
// configured=false(own 为 null)= 从未配置过 = 空条件 = 掌握全部技能。
|
|
1572
1572
|
// 这不是「继承来源 null」,而是「你还没配过」,所以单独一条文案。
|
|
1573
|
-
scope.isConv && react.createElement("div", { key: "inh", style: { color: "
|
|
1573
|
+
scope.isConv && react.createElement("div", { key: "inh", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "2px" } },
|
|
1574
1574
|
configured === false
|
|
1575
1575
|
? "尚未配置过(未继承工作区;当前为空条件 = 掌握全部技能)"
|
|
1576
1576
|
: (inheritedFrom
|
|
@@ -1578,10 +1578,10 @@ window.__ModuleLoader__.load({
|
|
|
1578
1578
|
: "该对话有独立配置(未继承工作区)")),
|
|
1579
1579
|
// 只读提示:已冻结的表达式引用了不存在的标签(旧版 bug 遗留)。
|
|
1580
1580
|
// 不自动修复 —— 数据是用户意志,告诉他原因即可。
|
|
1581
|
-
scope.isConv && expressionIssue && !expressionIssue.ok && react.createElement("div", { key: "isq", style: { color: "
|
|
1581
|
+
scope.isConv && expressionIssue && !expressionIssue.ok && react.createElement("div", { key: "isq", style: { color: "var(--dsw-alias-state-warn-primary)", fontSize: "11px", marginTop: "2px" } },
|
|
1582
1582
|
`⚠ 表达式引用了已不存在的标签(${expressionIssue.message})。点「tag 设置」可重新选择;保存前需修正。`),
|
|
1583
1583
|
react.createElement("div", { key: "sp", style: { flex: 1 } }),
|
|
1584
|
-
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", flexWrap: "wrap", paddingTop: "8px", borderTop: "1px solid var(--
|
|
1584
|
+
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", flexWrap: "wrap", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
1585
1585
|
react.createElement("button", {
|
|
1586
1586
|
key: "set", style: btn, disabled: busy,
|
|
1587
1587
|
onClick: () => setSettingsOpen(true),
|
|
@@ -1589,14 +1589,14 @@ window.__ModuleLoader__.load({
|
|
|
1589
1589
|
// 「一键下发」只在工作区版出现:把当前工作区配置推给该工作区下所有对话。
|
|
1590
1590
|
// 与对话版的「继承」是同一个数据动作,区别是批量 + 带选择性覆盖。
|
|
1591
1591
|
!scope.isConv && react.createElement("button", {
|
|
1592
|
-
key: "push", style: { ...btn, color: "
|
|
1592
|
+
key: "push", style: { ...btn, color: "var(--dsw-alias-state-warn-primary)" }, disabled: busy,
|
|
1593
1593
|
title: "把本工作区的标签条件 / 手动添加 / 禁用一次性下发到该工作区下的所有对话",
|
|
1594
1594
|
"data-skill-tag-push": "1",
|
|
1595
1595
|
onClick: () => setPushOpen(true),
|
|
1596
1596
|
}, "下发到所有对话"),
|
|
1597
1597
|
// 「继承工作区配置」只在对话版出现:把当前工作区的三件套整体搬过来
|
|
1598
1598
|
scope.isConv && react.createElement("button", {
|
|
1599
|
-
key: "inh", style: { ...btn, color: "
|
|
1599
|
+
key: "inh", style: { ...btn, color: "var(--dsw-alias-label-secondary)" }, disabled: busy,
|
|
1600
1600
|
title: "用当前工作区的标签条件 / 手动添加 / 禁用整体覆盖本对话的配置",
|
|
1601
1601
|
onClick: () => void inherit(),
|
|
1602
1602
|
}, "继承工作区配置"),
|
|
@@ -1612,7 +1612,7 @@ window.__ModuleLoader__.load({
|
|
|
1612
1612
|
// 两套口径不一致时必须讲清差在哪,否则用户只会看到"数字对不上"。
|
|
1613
1613
|
(userOnlyCount > 0 || unregisteredCount > 0 || undeterminableCount > 0) && react.createElement("div", {
|
|
1614
1614
|
key: "gap",
|
|
1615
|
-
style: { color: "
|
|
1615
|
+
style: { color: "var(--dsw-alias-state-warn-primary)", fontSize: "11px", marginBottom: "6px", lineHeight: "1.5" },
|
|
1616
1616
|
}, [
|
|
1617
1617
|
userOnlyCount > 0 && react.createElement("div", { key: "u" },
|
|
1618
1618
|
`其中 ${userOnlyCount} 个只能 /名字 手动调用(disable-model-invocation),模型不会自己看到`),
|
|
@@ -1620,7 +1620,7 @@ window.__ModuleLoader__.load({
|
|
|
1620
1620
|
`其中 ${unregisteredCount} 个本机有、但宿主没注册,模型侧根本不存在`),
|
|
1621
1621
|
// 2026-11-03(#1):三种状态各说各话,绝不共用「宿主没注册」这句断言。
|
|
1622
1622
|
undeterminableCount > 0 && react.createElement("div", {
|
|
1623
|
-
key: "ud", style: { color: "
|
|
1623
|
+
key: "ud", style: { color: "var(--dsw-alias-label-secondary)" },
|
|
1624
1624
|
title: "这一趟没拿到宿主技能的完整快照(会话未运行 / 拿不到 agent 视角),注册状态未知",
|
|
1625
1625
|
}, scope.isConv
|
|
1626
1626
|
? `该会话未运行,以下为全局视角:${undeterminableCount} 个本次未取到宿主快照,暂不可判定(不代表没注册)`
|
|
@@ -1638,9 +1638,9 @@ window.__ModuleLoader__.load({
|
|
|
1638
1638
|
}, "清除"),
|
|
1639
1639
|
]),
|
|
1640
1640
|
react.createElement("div", { key: "list", style: { flex: 1, overflowY: "auto", minHeight: "80px" } }, [
|
|
1641
|
-
(view.visible ?? []).length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
1641
|
+
(view.visible ?? []).length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } },
|
|
1642
1642
|
"没有技能。可在下方「+ 精细化添加技能」手动加入,或清空标签条件回到全部技能。"),
|
|
1643
|
-
(view.visible ?? []).length > 0 && shownSkills.length === 0 && react.createElement("div", { key: "nf", style: { color: "
|
|
1643
|
+
(view.visible ?? []).length > 0 && shownSkills.length === 0 && react.createElement("div", { key: "nf", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } },
|
|
1644
1644
|
`没有匹配「${skillSearch.trim()}」的技能。`),
|
|
1645
1645
|
...shownSkills.map((name) => {
|
|
1646
1646
|
const onlyManual = userOnlyMap.has(name);
|
|
@@ -1648,24 +1648,24 @@ window.__ModuleLoader__.load({
|
|
|
1648
1648
|
// 未知 ≠ 未注册:不知道该不该置灰,就不置灰(2026-11-03 #1)。
|
|
1649
1649
|
const undetermined = undeterminableSet.has(name);
|
|
1650
1650
|
return react.createElement("div", { key: name, style: { ...listRow, flexWrap: "wrap" } }, [
|
|
1651
|
-
react.createElement("span", { key: "n", style: { flex: 1, color: (onlyManual || notRegistered) ? "
|
|
1651
|
+
react.createElement("span", { key: "n", style: { flex: 1, color: (onlyManual || notRegistered) ? "var(--dsw-alias-label-secondary)" : "inherit" } }, name),
|
|
1652
1652
|
// 逐行标注它为什么不在「模型可见」那一份里,避免用户以为插件少发了。
|
|
1653
1653
|
notRegistered && react.createElement("span", {
|
|
1654
1654
|
key: "nr",
|
|
1655
|
-
style: { color: "
|
|
1655
|
+
style: { color: "var(--dsw-alias-state-warn-primary)", fontSize: "10px", border: "1px solid var(--dsw-alias-state-warn-primary)", borderRadius: "4px", padding: "0 4px" },
|
|
1656
1656
|
title: "宿主 skills 注册表里没有这个名字:本机文件存在,但模型侧看不到(插件范围外)",
|
|
1657
1657
|
}, "未注册"),
|
|
1658
1658
|
!notRegistered && undetermined && react.createElement("span", {
|
|
1659
1659
|
key: "ud",
|
|
1660
|
-
style: { color: "
|
|
1660
|
+
style: { color: "var(--dsw-alias-label-secondary)", fontSize: "10px", border: "1px dashed var(--dsw-alias-border-l2)", borderRadius: "4px", padding: "0 4px" },
|
|
1661
1661
|
title: "这一趟没拿到宿主技能的完整快照(会话未运行 / 拿不到 agent 视角),它到底注没注册还不知道",
|
|
1662
1662
|
}, "暂不可判定"),
|
|
1663
1663
|
!notRegistered && !undetermined && onlyManual && react.createElement("span", {
|
|
1664
1664
|
key: "uo",
|
|
1665
|
-
style: { color: "
|
|
1665
|
+
style: { color: "var(--dsw-alias-label-secondary)", fontSize: "10px", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "4px", padding: "0 4px" },
|
|
1666
1666
|
title: "SKILL.md 写了 disable-model-invocation: true:模型不会自动看到,只能由你用 /名字 手动调用",
|
|
1667
1667
|
}, "仅手动"),
|
|
1668
|
-
manualSet.has(name) && react.createElement("span", { key: "m", style: { color: "
|
|
1668
|
+
manualSet.has(name) && react.createElement("span", { key: "m", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, "手动"),
|
|
1669
1669
|
// 说明这一行到底进没进"下发给模型"那一份。
|
|
1670
1670
|
react.createElement(RevealButton, { key: "rev", skillName: name, path: pathOf(name), label: "📁" }),
|
|
1671
1671
|
react.createElement("button", {
|
|
@@ -1673,15 +1673,15 @@ window.__ModuleLoader__.load({
|
|
|
1673
1673
|
onClick: () => setTagOfSkill((v) => (v === name ? null : name)),
|
|
1674
1674
|
}, "查看 tag"),
|
|
1675
1675
|
react.createElement("button", {
|
|
1676
|
-
key: "d", style: { ...btn, padding: "1px 7px", fontSize: "11px", color: "
|
|
1676
|
+
key: "d", style: { ...btn, padding: "1px 7px", fontSize: "11px", color: "var(--dsw-alias-state-error-primary)" }, disabled: busy,
|
|
1677
1677
|
onClick: () => void call(scope.skillsPrefix + "/disable", { skillName: name }, `已禁用 ${name}`),
|
|
1678
1678
|
}, "禁用"),
|
|
1679
|
-
tagOfSkill === name && react.createElement("div", { key: "tags", style: { flexBasis: "100%", color: "
|
|
1679
|
+
tagOfSkill === name && react.createElement("div", { key: "tags", style: { flexBasis: "100%", color: "var(--dsw-alias-label-secondary)", fontSize: "11px", padding: "2px 0 2px 8px" } },
|
|
1680
1680
|
(tagsOf(name).length ? "tag: " + tagsOf(name).join(", ") : "该技能没有任何 tag")),
|
|
1681
1681
|
]);
|
|
1682
1682
|
}),
|
|
1683
1683
|
]),
|
|
1684
|
-
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", flexWrap: "wrap", paddingTop: "8px", borderTop: "1px solid var(--
|
|
1684
|
+
react.createElement("div", { key: "f", style: { display: "flex", gap: "8px", flexWrap: "wrap", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
1685
1685
|
react.createElement("button", { key: "add", style: btn, disabled: busy, onClick: () => setPickOpen(true) }, "+ 精细化添加技能"),
|
|
1686
1686
|
react.createElement("button", { key: "dis", style: btn, disabled: busy, onClick: () => setDisabledOpen(true) },
|
|
1687
1687
|
`查看被禁用的技能 (${(ws?.disabledSkills ?? []).length})`),
|
|
@@ -1695,7 +1695,7 @@ window.__ModuleLoader__.load({
|
|
|
1695
1695
|
react.createElement("div", { style: { ...modalBox, height: "82vh" }, onClick: (e) => e.stopPropagation() }, [
|
|
1696
1696
|
react.createElement("div", { key: "head", style: { display: "flex", alignItems: "center", gap: "10px", marginBottom: "10px" } }, [
|
|
1697
1697
|
react.createElement("strong", { key: "t", style: { fontSize: "14px" } }, scope.title),
|
|
1698
|
-
react.createElement("span", { key: "w", style: { color: "
|
|
1698
|
+
react.createElement("span", { key: "w", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", ...monoStyle } }, scope.id),
|
|
1699
1699
|
react.createElement("button", { key: "x", style: { ...btn, marginLeft: "auto" }, onClick: onClose }, "✕"),
|
|
1700
1700
|
]),
|
|
1701
1701
|
notice && react.createElement("div", { key: "n", style: noteStyle }, notice),
|
|
@@ -1775,6 +1775,14 @@ window.__ModuleLoader__.load({
|
|
|
1775
1775
|
// 与「编辑标签组」页共用同一套表达式引擎(服务端 src/domain/expr.js)。
|
|
1776
1776
|
// 保存目标由调用方注入(save/saveLabel):工作区版存到工作区,对话版存到对话。
|
|
1777
1777
|
// 「添加标签组」只是把已存标签组的表达式载入运算区当起点,不改原标签组。
|
|
1778
|
+
// 标签组选项的显示文本:原生 <select> 的弹出层宽度由最长 option 决定,
|
|
1779
|
+
// 只约束 select 盒宽挡不住(#8 二次反馈)。这里按字符数截断,完整内容放 title。
|
|
1780
|
+
const OPTION_LABEL_MAX = 60;
|
|
1781
|
+
function optionLabel(name, expression) {
|
|
1782
|
+
const full = `${name} — ${expression || "(空)"}`;
|
|
1783
|
+
return full.length <= OPTION_LABEL_MAX ? full : full.slice(0, OPTION_LABEL_MAX - 1) + "…";
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1778
1786
|
function TagSettingsDialog({ initialExpression, tags, templates, busy, onClose, onSaved, subtitle, saveLabel, save }) {
|
|
1779
1787
|
const [expr, setExpr] = react.useState(initialExpression ?? "");
|
|
1780
1788
|
const [validation, setValidation] = react.useState(null);
|
|
@@ -1858,26 +1866,45 @@ window.__ModuleLoader__.load({
|
|
|
1858
1866
|
? (expr.trim() === "" ? "无条件(掌握全部技能)" : configDisplay({ tags }, validation.config))
|
|
1859
1867
|
: null;
|
|
1860
1868
|
const visibleTags = tags.filter((t) => !tagQuery.trim() || t.name.toLowerCase().includes(tagQuery.trim().toLowerCase()));
|
|
1861
|
-
const panel = { border: "1px solid var(--
|
|
1869
|
+
const panel = { border: "1px solid var(--dsw-alias-border-l1)", borderRadius: "10px", padding: "10px 12px", marginBottom: "10px" };
|
|
1862
1870
|
const panelTitle = { fontWeight: 600, marginBottom: "6px", fontSize: "12px" };
|
|
1863
|
-
const chip = { display: "inline-flex", alignItems: "center", gap: "4px", border: "1px solid var(--
|
|
1871
|
+
const chip = { display: "inline-flex", alignItems: "center", gap: "4px", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: "8px", padding: "2px 8px", margin: "0 6px 6px 0", fontSize: "12px" };
|
|
1864
1872
|
|
|
1865
1873
|
return react.createElement("div", { style: { ...overlayStyle, zIndex: 1200 }, onMouseDown: (e) => { if (e.target === e.currentTarget) onClose(); } },
|
|
1866
|
-
|
|
1874
|
+
// 定高(不是只给 maxHeight):标签多或表达式长时,窗口高度必须不变,
|
|
1875
|
+
// 只有中间两个内容区各自滚动,底部语法说明与按钮始终留在弹窗内。
|
|
1876
|
+
// 这是「管理标签」双列浮层同样的处理(见该处 height: "82vh" 的注释)。
|
|
1877
|
+
// overflowY: 兜底 —— 即便窗口很矮、两个内容区都顶到各自上限,内容也只在
|
|
1878
|
+
// 弹窗内滚动,不会画到弹窗边框之外。overflowX: 抑制长名称造成的横向溢出。
|
|
1879
|
+
// 高度按内容自适应:定高会在一屏装得下时留出一大片空白(用户反馈)。
|
|
1880
|
+
// maxHeight + overflowY 仍然兜底 —— 内容超长时只在弹窗内滚动,
|
|
1881
|
+
// 不会像最初那样把底部说明画到边框外。
|
|
1882
|
+
react.createElement("div", { style: { ...modalBox, width: "760px", maxHeight: "82vh", overflowY: "auto", overflowX: "hidden" }, onClick: (e) => e.stopPropagation() }, [
|
|
1867
1883
|
react.createElement("div", { key: "head", style: { display: "flex", alignItems: "center", gap: "10px", marginBottom: "10px" } }, [
|
|
1868
1884
|
react.createElement("strong", { key: "t", style: { fontSize: "14px" } }, "tag 设置"),
|
|
1869
|
-
react.createElement("span", { key: "w", style: { color: "
|
|
1885
|
+
react.createElement("span", { key: "w", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, subtitle ?? "保存到当前工作区"),
|
|
1870
1886
|
react.createElement("button", { key: "x", style: { ...btn, marginLeft: "auto" }, onClick: onClose }, "✕"),
|
|
1871
1887
|
]),
|
|
1872
|
-
localNotice && react.createElement("div", { key: "n", style: { ...noteStyle, color: "
|
|
1888
|
+
localNotice && react.createElement("div", { key: "n", style: { ...noteStyle, color: "var(--dsw-alias-state-error-primary)" } }, localNotice),
|
|
1873
1889
|
|
|
1874
1890
|
// ── 添加标签组:把已存表达式载入运算区 ──
|
|
1875
1891
|
react.createElement("div", { key: "tpl", style: panel }, [
|
|
1876
1892
|
react.createElement("div", { key: "tt", style: panelTitle }, "添加标签组"),
|
|
1877
|
-
templates.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
1878
|
-
templates.length > 0 && react.createElement("div", { key: "row", style: { display: "flex",
|
|
1893
|
+
templates.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "还没有标签组 — 可在设置页「编辑标签组」创建"),
|
|
1894
|
+
templates.length > 0 && react.createElement("div", { key: "row", style: { display: "flex", flexDirection: "column", gap: "4px", alignItems: "stretch" } }, [
|
|
1895
|
+
// 原生 <select> 由浏览器/系统层绘制,不吃 React 的 color:inherit,
|
|
1896
|
+
// 选项文字与底色都可能沿用 UA 皮肤。所以前景与背景必须显式给到
|
|
1897
|
+
// select 和每个 option:否则深色下文字与底同色(只有 hover 反色
|
|
1898
|
+
// 才可见),浅色下则相反。
|
|
1899
|
+
//
|
|
1900
|
+
// 不要在这里写 color-scheme:宿主已在 documentElement 上按主题设了
|
|
1901
|
+
// style.colorScheme,子元素继承即可;在控件上写 "light dark" 会让 UA
|
|
1902
|
+
// 改按「系统偏好」挑皮肤,宿主主题与系统偏好不一致时反而出错。
|
|
1879
1903
|
react.createElement("select", {
|
|
1880
|
-
key: "sel",
|
|
1904
|
+
key: "sel",
|
|
1905
|
+
// flex 子项默认 min-width:auto,长选项文本会把整行撑宽顶出弹窗;
|
|
1906
|
+
// minWidth:0 才允许它收缩,flex:"1 1 0" 让它占据剩余宽度而非按内容撑开。
|
|
1907
|
+
style: { ...input, flex: "1 1 0", minWidth: 0, maxWidth: "100%", color: "var(--dsw-alias-label-primary)", background: "var(--dsw-alias-bg-layer-2)" }, value: "",
|
|
1881
1908
|
onChange: (e) => {
|
|
1882
1909
|
const tpl = templates.find((t) => t.templateId === e.target.value);
|
|
1883
1910
|
if (!tpl) return;
|
|
@@ -1886,11 +1913,20 @@ window.__ModuleLoader__.load({
|
|
|
1886
1913
|
setLocalNotice(`已载入标签组「${tpl.name}」的运算,可继续编辑`);
|
|
1887
1914
|
},
|
|
1888
1915
|
}, [
|
|
1889
|
-
react.createElement("option", {
|
|
1890
|
-
|
|
1891
|
-
|
|
1916
|
+
react.createElement("option", {
|
|
1917
|
+
key: "h", value: "",
|
|
1918
|
+
style: { color: "var(--dsw-alias-label-secondary)", background: "var(--dsw-alias-bg-layer-2)" },
|
|
1919
|
+
}, "选择标签组载入…"),
|
|
1920
|
+
// 原生下拉的弹出层宽度由最长 option 文本决定,只给 select 设宽度没用。
|
|
1921
|
+
// 所以把选项文本截断:完整内容放进 title(收起态仍由 select 自身省略号截断)。
|
|
1922
|
+
...templates.map((t) => react.createElement("option", {
|
|
1923
|
+
key: t.templateId, value: t.templateId,
|
|
1924
|
+
title: `${t.name} — ${t.expression || "(空)"}`,
|
|
1925
|
+
style: { color: "var(--dsw-alias-label-primary)", background: "var(--dsw-alias-bg-layer-2)" },
|
|
1926
|
+
}, optionLabel(t.name, t.expression))),
|
|
1892
1927
|
]),
|
|
1893
|
-
|
|
1928
|
+
// 提示小字放在选择框下面(原来在右侧,挤压了选择框宽度)
|
|
1929
|
+
react.createElement("span", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } },
|
|
1894
1930
|
"载入后可在下方继续编辑;原标签组不受影响"),
|
|
1895
1931
|
]),
|
|
1896
1932
|
]),
|
|
@@ -1904,8 +1940,10 @@ window.__ModuleLoader__.load({
|
|
|
1904
1940
|
value: tagQuery, onChange: (e) => setTagQuery(e.target.value),
|
|
1905
1941
|
}),
|
|
1906
1942
|
]),
|
|
1907
|
-
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
1908
|
-
|
|
1943
|
+
tags.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "还没有标签"),
|
|
1944
|
+
// 标签多时这一区自己滚,不把整窗撑高(maxHeight 与同文件既有的
|
|
1945
|
+
// 标签/技能行列表一致,见 :578 / :752 的 420px 用法)。
|
|
1946
|
+
react.createElement("div", { key: "chips", style: { maxHeight: "240px", overflowY: "auto" } }, visibleTags.map((t) => react.createElement("button", {
|
|
1909
1947
|
key: t.tagId,
|
|
1910
1948
|
style: { ...chip, cursor: "pointer", background: "transparent", color: "inherit" },
|
|
1911
1949
|
disabled: busy,
|
|
@@ -1926,22 +1964,23 @@ window.__ModuleLoader__.load({
|
|
|
1926
1964
|
onChange: (e) => setExpr(e.target.value),
|
|
1927
1965
|
}),
|
|
1928
1966
|
react.createElement("div", { key: "ops", style: { display: "flex", gap: "6px", alignItems: "center", flexWrap: "wrap", marginTop: "6px" } }, [
|
|
1929
|
-
react.createElement("span", { key: "l", style: { color: "
|
|
1967
|
+
react.createElement("span", { key: "l", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px" } }, "插入:"),
|
|
1930
1968
|
...[["+", "OR"], ["*", "AND"], ["(", ""], [")", ""]].map(([sym, label]) => react.createElement("button", {
|
|
1931
1969
|
key: sym, style: { ...btn, ...monoStyle, padding: "1px 9px" }, disabled: busy,
|
|
1932
1970
|
title: label ? `${sym} = ${label}` : `插入 ${sym}`,
|
|
1933
1971
|
onClick: () => insertAtCursor(sym),
|
|
1934
1972
|
}, sym + (label ? ` ${label}` : ""))),
|
|
1935
1973
|
react.createElement("button", {
|
|
1936
|
-
key: "clr", style: { ...btn, color: "
|
|
1974
|
+
key: "clr", style: { ...btn, color: "var(--dsw-alias-state-warn-primary)", marginLeft: "auto" }, disabled: busy || !expr,
|
|
1937
1975
|
onClick: () => { setExpr(""); setLocalNotice(null); },
|
|
1938
1976
|
}, "清空"),
|
|
1939
1977
|
]),
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1978
|
+
// 校验/解析结果跟着表达式变长:给它自己的滚动区,避免把底部语法说明推出弹窗。
|
|
1979
|
+
react.createElement("div", { key: "val", style: { marginTop: "8px", maxHeight: "120px", overflowY: "auto" } }, [
|
|
1980
|
+
checking && react.createElement("div", { key: "c", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "校验中…"),
|
|
1981
|
+
!checking && validation && validation.ok && react.createElement("div", { key: "ok", style: { color: "var(--dsw-alias-state-success-primary)", fontSize: "12px" } },
|
|
1943
1982
|
expr.trim() === "" ? "✓ 空条件 — 该工作区掌握全部技能" : "✓ 表达式合法"),
|
|
1944
|
-
!checking && validation && !validation.ok && errors.map((er, i) => react.createElement("div", { key: i, style: { color: "
|
|
1983
|
+
!checking && validation && !validation.ok && errors.map((er, i) => react.createElement("div", { key: i, style: { color: "var(--dsw-alias-state-error-primary)", fontSize: "12px", marginTop: "4px" } }, [
|
|
1945
1984
|
react.createElement("span", { key: "m" }, "✗ " + er.message),
|
|
1946
1985
|
typeof er.position === "number" && er.position >= 0 && react.createElement("button", {
|
|
1947
1986
|
key: "loc", style: { ...btn, marginLeft: "8px", padding: "0 6px", fontSize: "11px" },
|
|
@@ -1954,18 +1993,18 @@ window.__ModuleLoader__.load({
|
|
|
1954
1993
|
},
|
|
1955
1994
|
}, `定位 第${er.position + 1}字符`),
|
|
1956
1995
|
])),
|
|
1957
|
-
!checking && warnings.map((w, i) => react.createElement("div", { key: "w" + i, style: { color: "
|
|
1958
|
-
!checking && preview && react.createElement("div", { key: "pv", style: { color: "
|
|
1996
|
+
!checking && warnings.map((w, i) => react.createElement("div", { key: "w" + i, style: { color: "var(--dsw-alias-state-warn-primary)", fontSize: "12px", marginTop: "4px" } }, "⚠ " + w.message)),
|
|
1997
|
+
!checking && preview && react.createElement("div", { key: "pv", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "2px" } }, "解析结果: " + preview),
|
|
1959
1998
|
]),
|
|
1960
|
-
react.createElement("div", { key: "acts", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--
|
|
1999
|
+
react.createElement("div", { key: "acts", style: { display: "flex", gap: "8px", marginTop: "10px", paddingTop: "8px", borderTop: "1px solid var(--dsw-alias-border-l1)" } }, [
|
|
1961
2000
|
react.createElement("button", {
|
|
1962
|
-
key: "save", style: { ...btn, color: "
|
|
2001
|
+
key: "save", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" },
|
|
1963
2002
|
disabled: busy || checking || !validation?.ok,
|
|
1964
2003
|
onClick: () => void doSave(),
|
|
1965
2004
|
}, saveLabel ?? "保存到工作区"),
|
|
1966
2005
|
react.createElement("button", { key: "cancel", style: btn, disabled: busy, onClick: onClose }, "取消"),
|
|
1967
2006
|
]),
|
|
1968
|
-
react.createElement("div", { key: "use", style: { color: "
|
|
2007
|
+
react.createElement("div", { key: "use", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginTop: "8px" } },
|
|
1969
2008
|
"语法: + 表示 OR,* 表示 AND,优先级 * 高于 +,可用括号。空表达式 = 无条件。"),
|
|
1970
2009
|
]),
|
|
1971
2010
|
]));
|
|
@@ -1988,14 +2027,14 @@ window.__ModuleLoader__.load({
|
|
|
1988
2027
|
react.createElement("strong", { key: "t" }, "精细化添加技能"),
|
|
1989
2028
|
react.createElement("button", { key: "x", style: { ...btn, marginLeft: "auto" }, onClick: onClose }, "✕"),
|
|
1990
2029
|
]),
|
|
1991
|
-
react.createElement("div", { key: "hint", style: { color: "
|
|
2030
|
+
react.createElement("div", { key: "hint", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "11px", marginBottom: "8px" } },
|
|
1992
2031
|
"已排除工作区已有的技能与被禁用的技能"),
|
|
1993
2032
|
react.createElement("input", {
|
|
1994
2033
|
key: "q", style: { ...input, width: "100%", marginBottom: "8px" }, placeholder: "搜索技能…", autoFocus: true,
|
|
1995
2034
|
value: q, onChange: (e) => setQ(e.target.value),
|
|
1996
2035
|
}),
|
|
1997
2036
|
react.createElement("div", { key: "list", style: { flex: 1, overflowY: "auto", minHeight: "100px" } }, [
|
|
1998
|
-
list.length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
2037
|
+
list.length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", padding: "10px 2px" } },
|
|
1999
2038
|
"没有可添加的技能(全部已存在,或被禁用)"),
|
|
2000
2039
|
...list.map((n) => react.createElement("div", { key: n, style: listRow }, [
|
|
2001
2040
|
react.createElement("label", { key: "l", style: { display: "flex", alignItems: "center", gap: "8px", flex: 1, cursor: "pointer" } }, [
|
|
@@ -2007,7 +2046,7 @@ window.__ModuleLoader__.load({
|
|
|
2007
2046
|
]),
|
|
2008
2047
|
react.createElement("div", { key: "f", style: { display: "flex", justifyContent: "flex-end", gap: "8px", marginTop: "10px" } }, [
|
|
2009
2048
|
react.createElement("button", {
|
|
2010
|
-
key: "ok", style: { ...btn, color: "
|
|
2049
|
+
key: "ok", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" }, disabled: busy || picked.size === 0,
|
|
2011
2050
|
onClick: () => void onPick([...picked]),
|
|
2012
2051
|
}, `添加 (${picked.size})`),
|
|
2013
2052
|
react.createElement("button", { key: "c", style: btn, onClick: onClose }, "取消"),
|
|
@@ -2025,12 +2064,12 @@ window.__ModuleLoader__.load({
|
|
|
2025
2064
|
react.createElement("button", { key: "x", style: { ...btn, marginLeft: "auto" }, onClick: onClose }, "✕"),
|
|
2026
2065
|
]),
|
|
2027
2066
|
react.createElement("div", { key: "list", style: { flex: 1, overflowY: "auto", minHeight: "100px" } }, [
|
|
2028
|
-
(disabled ?? []).length === 0 && react.createElement("div", { key: "e", style: { color: "
|
|
2067
|
+
(disabled ?? []).length === 0 && react.createElement("div", { key: "e", style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px" } }, "没有被禁用的技能"),
|
|
2029
2068
|
...(disabled ?? []).map((n) => react.createElement("div", { key: n, style: listRow }, [
|
|
2030
|
-
react.createElement("span", { key: "n", style: { flex: 1, color: "
|
|
2069
|
+
react.createElement("span", { key: "n", style: { flex: 1, color: "var(--dsw-alias-state-error-primary)" } }, n),
|
|
2031
2070
|
react.createElement(RevealButton, { key: "rev", skillName: n, path: pathOf(n), label: "📁" }),
|
|
2032
2071
|
react.createElement("button", {
|
|
2033
|
-
key: "r", style: { ...btn, color: "
|
|
2072
|
+
key: "r", style: { ...btn, color: "var(--dsw-alias-state-success-primary)" }, disabled: busy,
|
|
2034
2073
|
onClick: () => void onRestore(n),
|
|
2035
2074
|
}, "恢复"),
|
|
2036
2075
|
])),
|