dsh-novel-writer 5.2.0 → 5.5.0
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 +823 -278
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -24,166 +24,700 @@ window.__ModuleLoader__.load({
|
|
|
24
24
|
let react = require("react");
|
|
25
25
|
let react_dom_client = require("react-dom/client");
|
|
26
26
|
|
|
27
|
+
// ---- 官方原语适配层(v5.5.0)----
|
|
28
|
+
// 第三方插件(@linxin666/dsh-client-ui-market 等 6 个)同样直接 require 官方 primitives,
|
|
29
|
+
// 且都未声明 dsh.client.external —— 该包属客户端基线模块;这里仍包 try/catch,取不到即回退。
|
|
30
|
+
/* ===== B:官方原语适配层(v5.5.0 · @deepseek-ai/dsh-client-ui-primitives → 自绘回退) =====
|
|
31
|
+
* 插入位置:client.js 的 factory 内、`let react = require("react");` 之后(任意组件定义之前)。
|
|
32
|
+
* 用法(本块最后一行已给出):
|
|
33
|
+
* * 对外只有 NW_UI:{ available, Button, Switch, SegmentedControl, Modal, RiskConfirmation,
|
|
34
|
+
* Tag, Tooltip, DisclosureRow }
|
|
35
|
+
*
|
|
36
|
+
* 设计约束(宿主启动安全第一):
|
|
37
|
+
* 1. require 官方包只在 try/catch 内;取不到模块 / 缺某个组件 / 官方组件渲染抛错 → 逐控件回退;
|
|
38
|
+
* 本层在任何情况下都不向上抛,也不写 console(用 NW_UI.available 自检即可)。
|
|
39
|
+
* 2. 回退实现复用既有 nw* 类名,外观全部由 CSS 承担:本块没有任何内联 style、没有任何颜色字面量。
|
|
40
|
+
* 3. 不硬编码任何文案:文案由调用方传入,缺失时给空串等安全默认值。
|
|
41
|
+
* 4. 回退分支与官方分支的 props 映射共用同一套归一化函数,保证两条路径语义一致。
|
|
42
|
+
*/
|
|
43
|
+
function createNovelWriterUI(react, require) {
|
|
44
|
+
var NOOP = function () {};
|
|
45
|
+
var canCreate = !!react && typeof react.createElement === "function";
|
|
46
|
+
var h = canCreate
|
|
47
|
+
? function () { return react.createElement.apply(react, arguments); }
|
|
48
|
+
: function () { return null; };
|
|
49
|
+
|
|
50
|
+
/* ---------- 归一化小工具(只做类型兜底,不产生文案) ---------- */
|
|
51
|
+
function text(value) { return typeof value === "string" ? value : ""; }
|
|
52
|
+
function optionalText(value) { return typeof value === "string" && value !== "" ? value : void 0; }
|
|
53
|
+
function callback(value) { return typeof value === "function" ? value : null; }
|
|
54
|
+
function isOn(value) { return value === true; }
|
|
55
|
+
function classNameOf(base, extra) { return optionalText(extra) === void 0 ? base : base + " " + extra; }
|
|
56
|
+
function isElement(node) {
|
|
57
|
+
if (!node || typeof node !== "object") return false;
|
|
58
|
+
if (typeof react.isValidElement === "function") return react.isValidElement(node) === true;
|
|
59
|
+
return node.$$typeof !== void 0 && node.$$typeof !== null;
|
|
60
|
+
}
|
|
61
|
+
// 元素锚点:官方 Tooltip 用 cloneElement 注入 ref/handler,children 必须是单个元素
|
|
62
|
+
function anchorOf(children) {
|
|
63
|
+
return isElement(children) ? children : h("span", null, children);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* ---------- 官方模块加载(唯一的 require,全程 try/catch) ---------- */
|
|
67
|
+
// 包名与第三方插件(@linxin666/dsh-client-ui-preset-center 等)用的是同一个,属客户端基线包。
|
|
68
|
+
// 调用按完整包名字面量书写(不抽成变量):契约与审计工具都按这一行字面匹配"必须包在 try 内"。
|
|
69
|
+
var primitives = null;
|
|
70
|
+
try {
|
|
71
|
+
if (typeof require === "function") primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
72
|
+
} catch (err) {
|
|
73
|
+
primitives = null; // 模块不在客户端基线里 / 解析失败 → 全部走回退
|
|
74
|
+
}
|
|
75
|
+
if (!primitives || (typeof primitives !== "object" && typeof primitives !== "function")) primitives = null;
|
|
76
|
+
|
|
77
|
+
function typeTag(value) {
|
|
78
|
+
if (!value || typeof value !== "object") return "";
|
|
79
|
+
try { return String(value.$$typeof); } catch (err) { return ""; }
|
|
80
|
+
}
|
|
81
|
+
// 可渲染的组件类型:函数组件/类组件,或 React.memo / forwardRef / lazy 包装对象
|
|
82
|
+
function isComponentType(value) {
|
|
83
|
+
if (typeof value === "function") return true;
|
|
84
|
+
var tag = typeTag(value);
|
|
85
|
+
return tag.indexOf("react.memo") >= 0 || tag.indexOf("react.forward_ref") >= 0 || tag.indexOf("react.lazy") >= 0;
|
|
86
|
+
}
|
|
87
|
+
// 取"可直接调用"的内层函数:memo/forwardRef 拆包(保住"官方组件抛错也能被 try/catch 兜住");
|
|
88
|
+
// 类组件不能当函数调用(返回 null,改走 createElement,由 React 渲染)。
|
|
89
|
+
function invocable(value, depth) {
|
|
90
|
+
if (typeof value === "function") {
|
|
91
|
+
if (value.prototype && value.prototype.isReactComponent) return null;
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
if (!value || typeof value !== "object" || depth > 3) return null;
|
|
95
|
+
var tag = typeTag(value);
|
|
96
|
+
if (tag.indexOf("react.memo") >= 0) return invocable(value.type, depth + 1);
|
|
97
|
+
if (tag.indexOf("react.forward_ref") >= 0) {
|
|
98
|
+
var render = value.render;
|
|
99
|
+
if (typeof render !== "function") return null;
|
|
100
|
+
return function (props) { return render(props, null); };
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
function pick(name) {
|
|
105
|
+
if (primitives === null) return null;
|
|
106
|
+
try {
|
|
107
|
+
var value = primitives[name];
|
|
108
|
+
if (isComponentType(value)) return value;
|
|
109
|
+
var inner = primitives["default"]; // ESM/CJS 互操作兜底
|
|
110
|
+
if (inner && typeof inner === "object" && isComponentType(inner[name])) return inner[name];
|
|
111
|
+
} catch (err) { /* 访问器抛错 → 视为该组件缺失 */ }
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var NAMES = ["Button", "Switch", "SegmentedControl", "Modal", "RiskConfirmation", "Tag", "Tooltip", "DisclosureRow"];
|
|
116
|
+
var official = {};
|
|
117
|
+
var resolved = 0;
|
|
118
|
+
for (var n = 0; n < NAMES.length; n += 1) {
|
|
119
|
+
official[NAMES[n]] = pick(NAMES[n]);
|
|
120
|
+
if (official[NAMES[n]] !== null) resolved += 1;
|
|
121
|
+
}
|
|
122
|
+
// available:8 个官方原语是否**全部**拿到(模块解析层面;个别组件运行时抛错仍会逐次回退,不会翻转它)
|
|
123
|
+
var available = resolved === NAMES.length;
|
|
124
|
+
|
|
125
|
+
/* ---------- 统一的"官方优先,抛错即回退"包装 ---------- */
|
|
126
|
+
// prepare(props) 在每次渲染恰好调用一次(分段控件/折叠行的 hook 都在这里,保证 hook 数量稳定);
|
|
127
|
+
// mapProps(props, ctx) 给出官方 props;回退实现拿到同一份 ctx。
|
|
128
|
+
function adapt(name, fallback, prepare, mapProps) {
|
|
129
|
+
var component = official[name];
|
|
130
|
+
if (component === null || !canCreate) return fallback;
|
|
131
|
+
var call = null;
|
|
132
|
+
try { call = invocable(component, 0); } catch (err) { call = null; }
|
|
133
|
+
return function Adapted(props) {
|
|
134
|
+
var input = props || {};
|
|
135
|
+
var context = null;
|
|
136
|
+
try { context = prepare === null ? null : prepare(input); } catch (err) { context = null; }
|
|
137
|
+
var mapped = null;
|
|
138
|
+
try { mapped = mapProps(input, context); } catch (err) { mapped = null; }
|
|
139
|
+
if (mapped !== null) {
|
|
140
|
+
try {
|
|
141
|
+
var node = call !== null ? call(mapped) : h(component, mapped);
|
|
142
|
+
if (node !== void 0) return node; // null 是合法节点(例如 open:false 的弹窗),只有 undefined 才当失败
|
|
143
|
+
} catch (err2) { /* 官方组件抛错 → 落到下面的回退实现 */ }
|
|
144
|
+
}
|
|
145
|
+
return fallback(input, context);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* ---------- 回退实现(只复用既有 nw* 类名;样式全在 CSS) ---------- */
|
|
150
|
+
|
|
151
|
+
// --- Button ---
|
|
152
|
+
var BUTTON_VARIANTS = { primary: 1, ghost: 1, outline: 1, toolbar: 1 };
|
|
153
|
+
var BUTTON_CLASS = {
|
|
154
|
+
primary: "nwBtn nwBtnPrimary",
|
|
155
|
+
ghost: "nwBtn nwBtnGhost",
|
|
156
|
+
outline: "nwBtn",
|
|
157
|
+
toolbar: "nwBtn nwBtnGhost"
|
|
158
|
+
};
|
|
159
|
+
function buttonVariant(value) {
|
|
160
|
+
var variant = text(value);
|
|
161
|
+
return BUTTON_VARIANTS[variant] === 1 ? variant : "ghost"; // 与官方默认 variant 对齐
|
|
162
|
+
}
|
|
163
|
+
function mapButton(props) {
|
|
164
|
+
return {
|
|
165
|
+
variant: buttonVariant(props.variant),
|
|
166
|
+
size: props.size === "sm" ? "sm" : "md",
|
|
167
|
+
disabled: isOn(props.disabled),
|
|
168
|
+
title: optionalText(props.title),
|
|
169
|
+
onClick: callback(props.onClick) || void 0,
|
|
170
|
+
className: optionalText(props.className),
|
|
171
|
+
children: props.children
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function fallbackButton(props) {
|
|
175
|
+
return h("button", {
|
|
176
|
+
type: "button",
|
|
177
|
+
className: classNameOf(BUTTON_CLASS[buttonVariant(props.variant)], props.className),
|
|
178
|
+
disabled: isOn(props.disabled),
|
|
179
|
+
title: optionalText(props.title),
|
|
180
|
+
onClick: callback(props.onClick) || void 0
|
|
181
|
+
}, props.children);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// --- Switch ---
|
|
185
|
+
function mapSwitch(props) {
|
|
186
|
+
return {
|
|
187
|
+
checked: isOn(props.checked),
|
|
188
|
+
onChange: callback(props.onChange) || NOOP,
|
|
189
|
+
label: text(props.label), // 官方必填:缺失兜底成空串(不硬编码文案)
|
|
190
|
+
disabled: isOn(props.disabled),
|
|
191
|
+
title: optionalText(props.title),
|
|
192
|
+
className: optionalText(props.className)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function fallbackSwitch(props) {
|
|
196
|
+
var checked = isOn(props.checked);
|
|
197
|
+
return h("button", {
|
|
198
|
+
type: "button",
|
|
199
|
+
role: "switch",
|
|
200
|
+
"aria-checked": checked ? "true" : "false",
|
|
201
|
+
"aria-label": optionalText(props.label),
|
|
202
|
+
disabled: isOn(props.disabled),
|
|
203
|
+
title: optionalText(props.title),
|
|
204
|
+
className: classNameOf("nwSwitch" + (checked ? " nwSwitchOn" : ""), props.className),
|
|
205
|
+
onClick: function () {
|
|
206
|
+
var onChange = callback(props.onChange);
|
|
207
|
+
if (onChange !== null) onChange(!checked);
|
|
208
|
+
}
|
|
209
|
+
}, h("span", { className: "nwSwitchKnob" }));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// --- SegmentedControl(官方必填 id,适配层自己生成稳定 id) ---
|
|
213
|
+
var useIdHook = typeof react.useId === "function" ? react.useId : null;
|
|
214
|
+
var useRefHook = typeof react.useRef === "function" ? react.useRef : null;
|
|
215
|
+
var controlSeq = 0;
|
|
216
|
+
function normalizeOptions(options) {
|
|
217
|
+
var list = [];
|
|
218
|
+
var source = Array.isArray(options) ? options : [];
|
|
219
|
+
for (var i = 0; i < source.length; i += 1) {
|
|
220
|
+
var option = source[i];
|
|
221
|
+
if (!option || typeof option !== "object") continue;
|
|
222
|
+
var value = text(option.value);
|
|
223
|
+
if (value === "") continue;
|
|
224
|
+
list.push({
|
|
225
|
+
value: value,
|
|
226
|
+
label: text(option.label) || value,
|
|
227
|
+
disabled: isOn(option.disabled),
|
|
228
|
+
title: optionalText(option.title)
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return list;
|
|
232
|
+
}
|
|
233
|
+
function prepareSegments(props) {
|
|
234
|
+
// 无论调用方是否自带 id,都先按固定分支取一次自动 id:hook 数量每帧恒定
|
|
235
|
+
var auto;
|
|
236
|
+
if (useIdHook !== null) auto = "nw-seg-" + String(useIdHook()).replace(/[^A-Za-z0-9_-]/g, "");
|
|
237
|
+
else if (useRefHook !== null) {
|
|
238
|
+
var box = useRefHook(null);
|
|
239
|
+
if (box === null || typeof box !== "object") box = { current: null };
|
|
240
|
+
if (box.current === null) {
|
|
241
|
+
controlSeq += 1;
|
|
242
|
+
box.current = "nw-seg-" + controlSeq;
|
|
243
|
+
}
|
|
244
|
+
auto = box.current;
|
|
245
|
+
} else {
|
|
246
|
+
auto = "nw-seg-fallback";
|
|
247
|
+
}
|
|
248
|
+
return { id: optionalText(props.id) || auto, options: normalizeOptions(props.options) }; // 自带 id(可选)优先
|
|
249
|
+
}
|
|
250
|
+
function mapSegments(props, context) {
|
|
251
|
+
return {
|
|
252
|
+
id: context !== null && context !== void 0 ? context.id : text(props.id),
|
|
253
|
+
value: text(props.value),
|
|
254
|
+
options: context !== null && context !== void 0 ? context.options : normalizeOptions(props.options),
|
|
255
|
+
onChange: callback(props.onChange) || NOOP,
|
|
256
|
+
label: text(props.label), // 官方必填
|
|
257
|
+
disabled: isOn(props.disabled),
|
|
258
|
+
className: optionalText(props.className)
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function fallbackSegments(props, context) {
|
|
262
|
+
var value = text(props.value);
|
|
263
|
+
var disabled = isOn(props.disabled);
|
|
264
|
+
var onChange = callback(props.onChange);
|
|
265
|
+
var options = context !== null && context !== void 0 ? context.options : normalizeOptions(props.options);
|
|
266
|
+
var tabs = [];
|
|
267
|
+
for (var i = 0; i < options.length; i += 1) {
|
|
268
|
+
var option = options[i];
|
|
269
|
+
var active = option.value === value;
|
|
270
|
+
tabs.push(h("button", {
|
|
271
|
+
key: option.value,
|
|
272
|
+
type: "button",
|
|
273
|
+
role: "tab",
|
|
274
|
+
"aria-selected": active ? "true" : "false",
|
|
275
|
+
disabled: disabled || option.disabled === true,
|
|
276
|
+
title: option.title,
|
|
277
|
+
className: "nwSegBtn" + (active ? " nwSegBtnOn" : ""),
|
|
278
|
+
onClick: (function (next, isActive) {
|
|
279
|
+
return function () { if (!isActive && onChange !== null) onChange(next); };
|
|
280
|
+
})(option.value, active)
|
|
281
|
+
}, option.label));
|
|
282
|
+
}
|
|
283
|
+
return h("div", {
|
|
284
|
+
className: classNameOf("nwSeg", props.className),
|
|
285
|
+
role: "tablist",
|
|
286
|
+
"aria-label": optionalText(props.label)
|
|
287
|
+
}, tabs);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// --- Modal ---
|
|
291
|
+
function mapModal(props) {
|
|
292
|
+
return {
|
|
293
|
+
open: isOn(props.open),
|
|
294
|
+
onClose: callback(props.onClose) || NOOP, // 官方必填
|
|
295
|
+
title: text(props.title), // 官方必填
|
|
296
|
+
closeLabel: text(props.closeLabel), // 官方必填:缺失即空串(不硬编码文案)
|
|
297
|
+
description: optionalText(props.description),
|
|
298
|
+
children: props.children,
|
|
299
|
+
footer: props.footer
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function fallbackModal(props) {
|
|
303
|
+
if (!isOn(props.open)) return null;
|
|
304
|
+
var title = text(props.title);
|
|
305
|
+
var description = optionalText(props.description);
|
|
306
|
+
var children = props.children === void 0 || props.children === null ? null : h("div", null, props.children);
|
|
307
|
+
return h("div", { className: "nwModal", role: "presentation" },
|
|
308
|
+
h("div", { className: "nwModalBox", role: "dialog", "aria-modal": "true", "aria-label": title },
|
|
309
|
+
title === "" ? null : h("div", { className: "nwModalTitle" }, title),
|
|
310
|
+
description === void 0 ? null : h("div", { className: "nwModalText" }, description),
|
|
311
|
+
children,
|
|
312
|
+
props.footer === void 0 || props.footer === null ? null : h("div", { className: "nwModalBtns" }, props.footer)
|
|
313
|
+
));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// --- RiskConfirmation ---
|
|
317
|
+
function riskLabels(props) {
|
|
318
|
+
var cancelLabel = text(props.cancelLabel);
|
|
319
|
+
return {
|
|
320
|
+
cancelLabel: cancelLabel,
|
|
321
|
+
// 官方多一个必填 closeLabel(弹窗右上角 × 的无障碍名);
|
|
322
|
+
// 调用方没给就借用 cancelLabel,仍然不产生硬编码文案
|
|
323
|
+
closeLabel: text(props.closeLabel) || cancelLabel
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function mapRisk(props) {
|
|
327
|
+
var labels = riskLabels(props);
|
|
328
|
+
return {
|
|
329
|
+
open: isOn(props.open),
|
|
330
|
+
title: text(props.title),
|
|
331
|
+
description: text(props.description),
|
|
332
|
+
acknowledgeLabel: text(props.acknowledgeLabel),
|
|
333
|
+
cancelLabel: labels.cancelLabel,
|
|
334
|
+
closeLabel: labels.closeLabel,
|
|
335
|
+
confirmLabel: text(props.confirmLabel),
|
|
336
|
+
acknowledged: isOn(props.acknowledged),
|
|
337
|
+
disabled: isOn(props.disabled),
|
|
338
|
+
onAcknowledgedChange: callback(props.onAcknowledgedChange) || NOOP,
|
|
339
|
+
onCancel: callback(props.onCancel) || NOOP,
|
|
340
|
+
onConfirm: callback(props.onConfirm) || NOOP
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function fallbackRisk(props) {
|
|
344
|
+
var labels = riskLabels(props);
|
|
345
|
+
var acknowledged = isOn(props.acknowledged);
|
|
346
|
+
var disabled = isOn(props.disabled);
|
|
347
|
+
var onAck = callback(props.onAcknowledgedChange);
|
|
348
|
+
var onCancel = callback(props.onCancel);
|
|
349
|
+
var onConfirm = callback(props.onConfirm);
|
|
350
|
+
return fallbackModal({
|
|
351
|
+
open: props.open,
|
|
352
|
+
title: props.title,
|
|
353
|
+
description: props.description,
|
|
354
|
+
children: h("label", { className: "nwModalText" },
|
|
355
|
+
h("input", {
|
|
356
|
+
type: "checkbox",
|
|
357
|
+
checked: acknowledged,
|
|
358
|
+
disabled: disabled,
|
|
359
|
+
// 没有回调时给 readOnly,避免 React 对"受控字段无 onChange"报 console.error
|
|
360
|
+
readOnly: onAck === null,
|
|
361
|
+
onChange: onAck === null ? void 0 : function (event) {
|
|
362
|
+
onAck(!!(event && event.target && event.target.checked === true));
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
h("span", null, text(props.acknowledgeLabel))),
|
|
366
|
+
footer: h("div", { className: "nwModalBtns" },
|
|
367
|
+
h("button", {
|
|
368
|
+
type: "button",
|
|
369
|
+
className: "nwBtn nwBtnGhost",
|
|
370
|
+
onClick: onCancel === null ? void 0 : onCancel
|
|
371
|
+
}, labels.cancelLabel),
|
|
372
|
+
h("button", {
|
|
373
|
+
type: "button",
|
|
374
|
+
className: "nwBtn nwBtnDanger",
|
|
375
|
+
disabled: disabled || !acknowledged,
|
|
376
|
+
onClick: onConfirm === null ? void 0 : onConfirm
|
|
377
|
+
}, text(props.confirmLabel)))
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// --- Tag ---
|
|
382
|
+
var TAG_TONES = { outline: 1, solid: 1, neutral: 1, quiet: 1, success: 1, info: 1, warning: 1, danger: 1 };
|
|
383
|
+
function tagTone(value) {
|
|
384
|
+
var tone = text(value);
|
|
385
|
+
return TAG_TONES[tone] === 1 ? tone : "outline"; // 与官方默认 tone 对齐
|
|
386
|
+
}
|
|
387
|
+
function mapTag(props) {
|
|
388
|
+
return { tone: tagTone(props.tone), className: optionalText(props.className), children: props.children };
|
|
389
|
+
}
|
|
390
|
+
function fallbackTag(props) {
|
|
391
|
+
// 既有 nw* 只有"开/关"两种胶囊:成功态映射到 nwBadgeOn,其余中性 tone 共用 nwBadge
|
|
392
|
+
var tone = tagTone(props.tone);
|
|
393
|
+
return h("span", { className: classNameOf(tone === "success" ? "nwBadge nwBadgeOn" : "nwBadge", props.className) }, props.children);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// --- Tooltip ---
|
|
397
|
+
function mapTooltip(props) {
|
|
398
|
+
var label = props.label;
|
|
399
|
+
if (typeof label !== "function") label = text(label); // 官方的 label 可以是 () => string
|
|
400
|
+
return { label: label, children: anchorOf(props.children) };
|
|
401
|
+
}
|
|
402
|
+
function fallbackTooltip(props) {
|
|
403
|
+
var label = "";
|
|
404
|
+
try {
|
|
405
|
+
label = typeof props.label === "function" ? text(props.label()) : text(props.label);
|
|
406
|
+
} catch (err) { label = ""; }
|
|
407
|
+
var anchor = anchorOf(props.children);
|
|
408
|
+
if (label === "" || anchor === null || typeof react.cloneElement !== "function") return anchor;
|
|
409
|
+
try {
|
|
410
|
+
return react.cloneElement(anchor, { title: label }); // 回退用原生 title 气泡
|
|
411
|
+
} catch (err) { return anchor; }
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// --- DisclosureRow(官方是受控组件,回退实现自己持有展开态) ---
|
|
415
|
+
var useStateHook = typeof react.useState === "function" ? react.useState : null;
|
|
416
|
+
function prepareDisclosure(props) {
|
|
417
|
+
if (useStateHook === null) return { open: isOn(props.defaultOpen), toggle: NOOP };
|
|
418
|
+
var pair = useStateHook(isOn(props.defaultOpen));
|
|
419
|
+
var setter = callback(pair === null || pair === void 0 ? null : pair[1]);
|
|
420
|
+
return {
|
|
421
|
+
open: pair !== null && pair !== void 0 && pair[0] === true,
|
|
422
|
+
toggle: function () {
|
|
423
|
+
if (setter !== null) setter(function (value) { return value !== true; });
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function mapDisclosure(props, context) {
|
|
428
|
+
var open = isOn(props.defaultOpen);
|
|
429
|
+
var toggle = NOOP;
|
|
430
|
+
if (context !== null && context !== void 0) { open = context.open === true; toggle = context.toggle; }
|
|
431
|
+
return {
|
|
432
|
+
icon: null, // 官方必填 icon:给 null,官方自带的 chevron 足以表达展开态
|
|
433
|
+
title: text(props.title),
|
|
434
|
+
open: open,
|
|
435
|
+
expandable: true,
|
|
436
|
+
onToggle: toggle,
|
|
437
|
+
expandOnRowClick: true,
|
|
438
|
+
children: props.children,
|
|
439
|
+
className: optionalText(props.className)
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function fallbackDisclosure(props, context) {
|
|
443
|
+
var open = isOn(props.defaultOpen);
|
|
444
|
+
var toggle = NOOP;
|
|
445
|
+
if (context !== null && context !== void 0) { open = context.open === true; toggle = context.toggle; }
|
|
446
|
+
return h("div", { className: classNameOf("nwToolGroup", props.className) },
|
|
447
|
+
h("div", { className: "nwToolGroupHead" },
|
|
448
|
+
h("button", {
|
|
449
|
+
type: "button",
|
|
450
|
+
className: "nwToolGroupHeadBtn",
|
|
451
|
+
"aria-expanded": open ? "true" : "false",
|
|
452
|
+
onClick: toggle
|
|
453
|
+
},
|
|
454
|
+
h("span", { className: "nwToolGroupHeadText" },
|
|
455
|
+
h("span", { className: "nwToolGroupName" }, text(props.title))),
|
|
456
|
+
h("span", { className: "nwToolGroupArrow" }, open ? "\u25be" : "\u25b8")
|
|
457
|
+
)
|
|
458
|
+
),
|
|
459
|
+
open ? h("div", { className: "nwToolGroupBody" }, props.children) : null);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/* ---------- 冻结 API ---------- */
|
|
463
|
+
return {
|
|
464
|
+
available: available,
|
|
465
|
+
Button: adapt("Button", fallbackButton, null, mapButton),
|
|
466
|
+
Switch: adapt("Switch", fallbackSwitch, null, mapSwitch),
|
|
467
|
+
SegmentedControl: adapt("SegmentedControl", fallbackSegments, prepareSegments, mapSegments),
|
|
468
|
+
Modal: adapt("Modal", fallbackModal, null, mapModal),
|
|
469
|
+
RiskConfirmation: adapt("RiskConfirmation", fallbackRisk, null, mapRisk),
|
|
470
|
+
Tag: adapt("Tag", fallbackTag, null, mapTag),
|
|
471
|
+
Tooltip: adapt("Tooltip", fallbackTooltip, null, mapTooltip),
|
|
472
|
+
DisclosureRow: adapt("DisclosureRow", fallbackDisclosure, prepareDisclosure, mapDisclosure)
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
var NW_UI = createNovelWriterUI(react, require);
|
|
477
|
+
|
|
27
478
|
// ---- 样式 ----
|
|
28
479
|
var css = `
|
|
29
480
|
|
|
481
|
+
|
|
482
|
+
|
|
30
483
|
/* ===== 杂项 ===== */
|
|
31
484
|
/* v4.3.0:删掉永不匹配的 [data-pane=…](宿主全树 0 命中,真实列名是 CSS-module 的 …_sidebarCol / …_centerCol) */
|
|
32
485
|
[class*=centerCol]{position:relative}
|
|
33
|
-
[data-dsh-novel-writer-view]{position:absolute;inset:0;z-index:60;background:var(--dsw-alias-bg-base
|
|
486
|
+
[data-dsh-novel-writer-view]{position:absolute;inset:0;z-index:60;background:var(--dsw-alias-bg-base);display:none;overflow:auto}
|
|
34
487
|
html[data-dsh-novel-writer-active]:not([data-dsh-ssh-active]):not([data-dsh-taskboard-active]) [data-dsh-novel-writer-view]{display:block}
|
|
35
488
|
html[data-dsh-novel-writer-active]:not([data-dsh-ssh-active]):not([data-dsh-taskboard-active]) [class*=centerCol]>:not([data-dsh-novel-writer-view]){display:none!important}
|
|
36
489
|
/* v4.3.0:宿主折叠标记挂在 frame 上(<div class="…_frame" data-sidebar-collapsed>),并不存在 data-dsh-frame 属性 */
|
|
37
490
|
[data-sidebar-collapsed] .nwEntry{justify-content:center;width:100%;padding:0}
|
|
38
491
|
[data-sidebar-collapsed] .nwEntryLabel{display:none}
|
|
39
|
-
.nwSectionTitle{display:flex;align-items:center;gap:6px;font-weight:700;font-size:13px;margin-top:
|
|
40
|
-
.nwNavEntry{display:flex;align-items:center;
|
|
41
|
-
.nwNavEntry:hover{
|
|
492
|
+
.nwSectionTitle{display:inline-flex;align-items:center;gap:6px;font-weight:700;font-size:13px;line-height:19px;letter-spacing:.02em;color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 8%,var(--dsw-alias-bg-layer-1));border:0.5px solid color-mix(in srgb,var(--dsw-alias-state-business-primary) 16%,var(--dsw-alias-bg-layer-1));border-radius:999px;corner-shape:round;padding:3px 12px;margin-top:10px}.nwTolVer{font-size:10px;line-height:14px;color:var(--dsw-alias-label-tertiary);margin:-2px 0 2px;letter-spacing:.03em}.nwTolCard{border-radius:var(--dsw-radius-xl);border:0.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-2);padding:4px 14px 8px;margin:8px 0 4px}.nwTolRow{display:flex;align-items:center;gap:10px;padding:9px 2px}.nwTolRow+.nwTolRow{border-top:1px dashed var(--dsw-alias-border-l2)}.nwTolName{flex:1;min-width:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary);font-weight:500;display:flex;align-items:center;gap:8px;white-space:nowrap}.nwTolIcon{font-size:15px;line-height:22px;opacity:.9;flex-shrink:0}.nwTolField{width:66px;flex-shrink:0;display:flex;flex-direction:column;align-items:stretch;gap:3px}.nwTolInput{width:100%;height:30px;padding:0 4px;box-sizing:border-box;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);font-size:13px;line-height:20px;text-align:center;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);transition:border-color .18s,box-shadow .18s,background .18s;-moz-appearance:textfield}.nwTolInput::-webkit-outer-spin-button,.nwTolInput::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.nwTolInput:hover{border-color:var(--dsw-alias-border-l3)}.nwTolInput:focus{outline:none;border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 3px var(--dsw-focus-ring-color);background:var(--dsw-alias-bg-layer-1)}.nwTolInput::placeholder{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.nwTolCaption{font-size:10px;line-height:14px;color:var(--dsw-alias-label-tertiary);text-align:center}.nwTolSep{width:14px;flex-shrink:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);text-align:center}.nwTolPct{width:14px;flex-shrink:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary);text-align:left}.nwTolBtns{display:flex;gap:12px;margin-top:16px}.nwBtn.nwBtnPrimary{background:var(--dsw-alias-state-business-primary);border:none;color:var(--dsw-alias-label-primary-foreground);font-weight:600;font-size:13px;line-height:20px;padding:9px 20px;border-radius:var(--dsw-radius-sm);cursor:pointer;box-shadow:var(--dsw-elevation-soft);transition:transform .15s,box-shadow .15s,opacity .15s,filter .15s;font-family:inherit}.nwBtnPrimary:hover{transform:translateY(-1px);box-shadow:var(--dsw-elevation-panel);filter:brightness(1.12)}.nwBtnPrimary:active{transform:translateY(0);box-shadow:var(--dsw-elevation-soft)}.nwBtn.nwBtnDone{background:linear-gradient(135deg,var(--dsw-alias-state-success-primary),var(--dsw-alias-state-success-primary));box-shadow:var(--dsw-elevation-soft);font-family:inherit}.nwBtn.nwBtnGhost{background:transparent;border:0.5px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;padding:9px 18px;border-radius:var(--dsw-radius-sm);cursor:pointer;transition:background .15s,border-color .15s,transform .15s;font-family:inherit}.nwBtnGhost:hover{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l3);transform:translateY(-1px)}.nwUpdateBar{display:block;margin:4px 0 8px;padding:7px 10px;border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary);font-size:12px;line-height:18px;text-decoration:none;border:1px solid var(--dsw-alias-state-success-primary);cursor:pointer}.nwUpdateBar:hover{background:var(--dsw-alias-interactive-bg-hover)}.nwUpdateStale{display:block;margin:4px 0 8px;padding:7px 10px;border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5;border:0.5px solid var(--dsw-alias-border-l2)}
|
|
493
|
+
.nwNavEntry{display:flex;align-items:center;gap:10px;width:100%;box-sizing:border-box;padding:9px 12px;margin:4px 0;border:0;border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft);cursor:pointer;text-align:left;color:inherit;font:inherit;transition:box-shadow .2s var(--nw-ease),transform .18s var(--nw-ease)}
|
|
494
|
+
.nwNavEntry:hover{box-shadow:var(--dsw-elevation-panel);transform:translateY(-1px);font-family:inherit}
|
|
42
495
|
.nwNavEntryText{flex:1;min-width:0;padding-right:8px}
|
|
43
|
-
.nwNavEntryTitle{font-size:13px;font-weight:600}
|
|
44
|
-
.nwNavEntryHint{font-size:11px;color:var(--dsw-alias-label-tertiary);margin-top:2px}
|
|
496
|
+
.nwNavEntryTitle{font-size:13px;line-height:20px;font-weight:600}
|
|
497
|
+
.nwNavEntryHint{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary);margin-top:2px}
|
|
45
498
|
.nwNavEntryRight{display:flex;align-items:center;gap:6px;flex:none}
|
|
46
499
|
.nwNavEntryRight .nwBadge{white-space:nowrap;flex:none}
|
|
47
|
-
.nwNavEntryArrow{font-size:18px;color:var(--dsw-alias-label-tertiary);flex:none}
|
|
48
|
-
.nwBackBtn{
|
|
49
|
-
.nwModelBtn{font-size:11px;padding:2px 6px;margin-top:4px;border:
|
|
500
|
+
.nwNavEntryArrow{font-size:18px;line-height:26px;color:var(--dsw-alias-label-tertiary);flex:none}
|
|
501
|
+
.nwBackBtn{display:flex;width:fit-content;align-items:center;justify-content:center;gap:6px;height:30px;padding:0 14px;margin:2px 0 6px;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;cursor:pointer;font-family:inherit;transition:background .16s var(--nw-ease),color .16s var(--nw-ease),box-shadow .2s var(--nw-ease)}
|
|
502
|
+
.nwModelBtn{font-size:11px;line-height:16px;padding:2px 6px;margin-top:4px;border:0.5px solid var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary);border-radius:var(--dsw-radius-sm);background:transparent;cursor:pointer;font-family:inherit}
|
|
50
503
|
.nwToolRight{display:flex;flex-direction:column;align-items:flex-end;gap:4px}
|
|
51
504
|
|
|
52
505
|
/* ===== 导航/入口 ===== */
|
|
53
|
-
.nwEntry{width:100%;height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:
|
|
54
|
-
.nwEntry:hover{background:var(--dsw-specific-sidebar-nav-item-hover);color:var(--dsw-alias-label-primary)}
|
|
506
|
+
.nwEntry{width:100%;height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:var(--dsw-radius-md);align-items:center;gap:8px;padding:0 12px;font-size:13px;line-height:20px;display:flex;font-family:inherit}
|
|
507
|
+
.nwEntry:hover{background:var(--dsw-specific-sidebar-nav-item-hover);color:var(--dsw-alias-label-primary);font-family:inherit}
|
|
55
508
|
.nwEntry[data-active]{background:var(--dsw-specific-sidebar-nav-item-active);color:var(--dsw-alias-label-primary);font-weight:600}
|
|
56
|
-
.nwEntryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex;width:16px;font-size:13px}
|
|
509
|
+
.nwEntryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex;width:16px;font-size:13px;line-height:20px}
|
|
57
510
|
.nwEntryLabel{text-overflow:ellipsis;overflow:hidden}
|
|
58
|
-
.nwPanel{max-width:560px;margin:0 auto;padding:28px 24px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);display:flex;flex-direction:column;gap:10px}
|
|
511
|
+
.nwPanel{--nw-ease:cubic-bezier(.16,1,.3,1);scrollbar-gutter:stable;width:100%;max-width:560px;margin:0 auto;padding:28px 24px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);display:flex;flex-direction:column;gap:10px}
|
|
59
512
|
.nwPanelHeader{display:flex;align-items:center;gap:10px}
|
|
60
|
-
.nwPanelTitle{font-size:16px;font-weight:700;flex:1;min-width:0}
|
|
61
|
-
.nwClose{appearance:none;font:inherit;cursor:pointer;border:
|
|
62
|
-
.nwRefresh{appearance:none;font:inherit;cursor:pointer;border:
|
|
63
|
-
.nwRefresh:hover{background:var(--dsw-alias-bg-
|
|
513
|
+
.nwPanelTitle{font-size:16px;line-height:24px;font-weight:700;letter-spacing:-.02em;flex:1;min-width:0}
|
|
514
|
+
.nwClose{appearance:none;font:inherit;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);width:30px;height:30px;padding:0;font-size:15px;line-height:1;transition:background .16s var(--nw-ease),color .16s var(--nw-ease),box-shadow .2s var(--nw-ease)}
|
|
515
|
+
.nwRefresh{appearance:none;font:inherit;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);height:30px;padding:0 12px;font-size:12px;line-height:18px;transition:background .16s var(--nw-ease),color .16s var(--nw-ease),box-shadow .2s var(--nw-ease)}
|
|
516
|
+
.nwRefresh:hover,.nwClose:hover,.nwBackBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font-family:inherit}
|
|
64
517
|
.nwDesc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.6;margin:0}
|
|
65
518
|
.nwRefreshSpin{animation:nwspin 1s linear infinite}
|
|
66
519
|
|
|
67
520
|
/* ===== 横幅与开关 ===== */
|
|
68
|
-
.nwBanner{display:flex;align-items:center;gap:10px;border-radius:
|
|
69
|
-
.nwBannerOn{background:
|
|
70
|
-
.nwBannerOff{background:
|
|
521
|
+
.nwBanner{display:flex;align-items:center;gap:10px;border-radius:var(--dsw-radius-lg);padding:14px 16px;font-size:15px;line-height:22px;font-weight:700;border:0.5px solid}
|
|
522
|
+
.nwBannerOn{background:var(--dsw-alias-state-success-tertiary);border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}
|
|
523
|
+
.nwBannerOff{background:var(--dsw-alias-state-danger-tertiary);border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-error)}
|
|
71
524
|
.nwBannerIcon{flex:none;font-size:18px;line-height:1}
|
|
72
|
-
.nwBannerSub{font-size:12px;font-weight:500;opacity:.9;margin-left:6px}
|
|
73
|
-
.nwRow{display:flex;align-items:center;gap:
|
|
74
|
-
.
|
|
75
|
-
.
|
|
525
|
+
.nwBannerSub{font-size:12px;line-height:18px;font-weight:500;opacity:.9;margin-left:6px}
|
|
526
|
+
.nwRow{display:flex;align-items:center;gap:14px;border:0;background:var(--dsw-alias-bg-layer-1);border-radius:var(--dsw-radius-lg);padding:14px 16px;box-shadow:var(--dsw-elevation-soft);transition:box-shadow .2s var(--nw-ease),transform .18s var(--nw-ease)}
|
|
527
|
+
.nwRow:hover{box-shadow:var(--dsw-elevation-panel);transform:translateY(-1px)}
|
|
528
|
+
.nwRowOn{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-elevation-panel)}
|
|
529
|
+
.nwRowOff{background:var(--dsw-alias-bg-layer-1)}
|
|
76
530
|
.nwRowText{flex:1;min-width:0}
|
|
77
531
|
.nwRowLabel{font-size:13px;font-weight:600;line-height:1.5}
|
|
78
532
|
.nwRowHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;margin-top:2px}
|
|
79
533
|
.nwSwitchWrap{flex:none;display:flex;align-items:center;gap:8px}
|
|
80
|
-
.nwSwitch{appearance:none;flex:none;width:56px;height:30px;border-radius:999px;border:
|
|
81
|
-
.nwSwitch:hover{
|
|
82
|
-
.nwSwitch:focus-visible{outline:2px solid
|
|
83
|
-
.nwSwitchOn{background
|
|
84
|
-
.nwSwitchOn:hover{
|
|
85
|
-
.nwSwitchKnob{position:absolute;top:
|
|
86
|
-
.nwSwitchOn .nwSwitchKnob{left:
|
|
534
|
+
.nwSwitch{appearance:none;flex:none;width:56px;height:30px;box-sizing:border-box;border-radius:999px;border:0;background:var(--dsw-alias-bg-layer-4);cursor:pointer;position:relative;padding:0;transition:background .18s,border-color .18s;corner-shape:round}
|
|
535
|
+
.nwSwitch:hover{border-color:var(--dsw-alias-border-l4)}
|
|
536
|
+
.nwSwitch:focus-visible{outline:2px solid var(--dsw-focus-ring-color);outline-offset:2px}
|
|
537
|
+
.nwSwitchOn{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}
|
|
538
|
+
.nwSwitchOn:hover{border-color:var(--dsw-alias-state-business-primary)}
|
|
539
|
+
.nwSwitchKnob{position:absolute;top:4px;left:4px;width:22px;height:22px;border-radius:50%;background:var(--dsw-alias-switch-thumb);box-shadow:var(--dsw-elevation-soft);transition:left .18s;corner-shape:round}
|
|
540
|
+
.nwSwitchOn .nwSwitchKnob{left:30px}
|
|
87
541
|
.nwSwitch:disabled{opacity:.5;cursor:default;box-shadow:none}
|
|
88
|
-
.nwSwitchSmall{appearance:none;flex:none;width:40px;height:22px;border-radius:999px;border:
|
|
89
|
-
.nwSwitchSmallOn{background
|
|
90
|
-
.nwSwitchSmallKnob{position:absolute;top:
|
|
91
|
-
.nwSwitchSmallOn .nwSwitchSmallKnob{left:
|
|
92
|
-
.nwSeg{display:flex;gap:
|
|
93
|
-
.nwSegBtn{appearance:none;border:
|
|
94
|
-
.nwSegBtn:hover{border-color
|
|
95
|
-
.nwSegBtnOn{background
|
|
96
|
-
.nwSegBtn:disabled{opacity:.6;cursor:default}
|
|
542
|
+
.nwSwitchSmall{appearance:none;flex:none;width:40px;height:22px;box-sizing:border-box;border-radius:999px;border:0;background:var(--dsw-alias-bg-layer-4);cursor:pointer;position:relative;padding:0;transition:background .16s,border-color .16s;corner-shape:round}
|
|
543
|
+
.nwSwitchSmallOn{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary)}
|
|
544
|
+
.nwSwitchSmallKnob{position:absolute;top:4px;left:4px;width:14px;height:14px;border-radius:50%;background:var(--dsw-alias-switch-thumb);transition:left .16s;corner-shape:round}
|
|
545
|
+
.nwSwitchSmallOn .nwSwitchSmallKnob{left:22px}
|
|
546
|
+
.nwSeg{display:flex;gap:3px;flex:none;background:var(--dsw-alias-bg-layer-2);border-radius:var(--dsw-radius-md);padding:3px}
|
|
547
|
+
.nwSegBtn{appearance:none;border:0.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px;padding:5px 10px;border-radius:var(--dsw-radius-sm);cursor:pointer;transition:background .16s,border-color .16s,color .16s;font-family:inherit}
|
|
548
|
+
.nwSegBtn:hover{border-color:var(--dsw-alias-border-l3);font-family:inherit}
|
|
549
|
+
.nwSegBtnOn{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary-foreground);font-weight:600}
|
|
550
|
+
.nwSegBtn:disabled{opacity:.6;cursor:default;font-family:inherit}
|
|
97
551
|
|
|
98
552
|
/* ===== 徽章 ===== */
|
|
99
|
-
.nwBadge{flex:none;border-radius:999px;padding:3px 10px;font-size:12px;font-weight:700;white-space:nowrap;letter-spacing:.5px}
|
|
100
|
-
.nwBadgeOn{background
|
|
101
|
-
.nwBadgeOff{background
|
|
553
|
+
.nwBadge{flex:none;border-radius:999px;padding:3px 10px;font-size:12px;line-height:18px;font-weight:700;white-space:nowrap;letter-spacing:.5px;corner-shape:round}
|
|
554
|
+
.nwBadgeOn{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-business-primary)}
|
|
555
|
+
.nwBadgeOff{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-tertiary)}
|
|
102
556
|
|
|
103
557
|
/* ===== 动画与杂项 ===== */
|
|
104
558
|
@keyframes nwspin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
|
|
105
|
-
@keyframes nwflash{0%{background:
|
|
559
|
+
@keyframes nwflash{0%{background:var(--dsw-alias-state-success-tertiary)}100%{background:transparent}}
|
|
106
560
|
/* v4.3.0:错误提示的红色闪烁(旧版错误分支恒不可达,见 PanelView msg 类名) */
|
|
107
|
-
@keyframes nwflashErr{0%{background:
|
|
561
|
+
@keyframes nwflashErr{0%{background:var(--dsw-alias-state-error-secondary)}100%{background:transparent}}
|
|
108
562
|
|
|
109
563
|
/* ===== 路径/按钮/状态 ===== */
|
|
110
|
-
.nwPlotOk{color
|
|
564
|
+
.nwPlotOk{color:var(--dsw-alias-state-success-primary)}
|
|
111
565
|
.nwFlash{animation:nwflash 1.2s ease}
|
|
112
566
|
.nwFlashErr{animation:nwflashErr 1.2s ease}
|
|
113
|
-
.nwBtnDanger{background
|
|
114
|
-
.nwPlotBox{margin-top:6px;padding:6px 8px;background:
|
|
567
|
+
.nwBtn.nwBtnDanger{background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary-foreground);border-color:var(--dsw-alias-state-error-primary);font-family:inherit}
|
|
568
|
+
.nwPlotBox{margin-top:6px;padding:6px 8px;background:var(--dsw-alias-bg-layer-2);border-radius:var(--dsw-radius-sm)}
|
|
115
569
|
.nwPlotPath{font-size:11px;line-height:1.5;color:var(--dsw-alias-label-secondary);word-break:break-all}
|
|
116
570
|
.nwBtnGroup{display:flex;gap:6px;margin-top:6px}
|
|
117
|
-
.nwBtn{font-size:11px;line-height:1;padding:5px 10px;border-radius:
|
|
118
|
-
.nwBtn:hover{background:var(--dsw-alias-bg-layer-2)}
|
|
119
|
-
.nwBtn:disabled{opacity:.45;cursor:not-allowed}
|
|
571
|
+
.nwBtn{font-size:11px;line-height:1;padding:5px 10px;border-radius:var(--dsw-radius-sm);border:0.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;font-family:inherit;transition:background .16s var(--nw-ease),box-shadow .2s var(--nw-ease),transform .18s var(--nw-ease)}
|
|
572
|
+
.nwBtn:hover{background:var(--dsw-alias-bg-layer-2);font-family:inherit}
|
|
573
|
+
.nwBtn:disabled{opacity:.45;cursor:not-allowed;font-family:inherit}
|
|
120
574
|
.nwPlotMsg{font-size:11px;line-height:1.5;color:var(--dsw-alias-label-secondary);margin-top:4px;word-break:break-all}
|
|
121
|
-
.nwPlotErr{color
|
|
575
|
+
.nwPlotErr{color:var(--dsw-alias-label-error)}
|
|
122
576
|
.nwStatus{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;word-break:break-all}
|
|
123
|
-
.nwFoot{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.6;border-top:
|
|
124
|
-
.nwGroupState{width:16px;height:16px;border-radius:
|
|
125
|
-
.nwGroupStateOn{border-color
|
|
126
|
-
.nwGroupStatePartial{border-color
|
|
127
|
-
.nwGroupStateOff{border-color
|
|
128
|
-
.nwGroupStateCheck{color
|
|
129
|
-
.nwGroupStateCheckPartial{width:10px;height:10px;border-radius:
|
|
577
|
+
.nwFoot{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.6;border-top:0.5px solid var(--dsw-alias-border-l2);padding-top:10px;margin-top:4px}
|
|
578
|
+
.nwGroupState{width:16px;height:16px;border-radius:var(--dsw-radius-xs);border:0.5px solid var(--dsw-alias-border-l3);display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;background:var(--dsw-alias-bg-layer-1);box-sizing:border-box}
|
|
579
|
+
.nwGroupStateOn{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-primary)}
|
|
580
|
+
.nwGroupStatePartial{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-layer-1)}
|
|
581
|
+
.nwGroupStateOff{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-layer-1)}
|
|
582
|
+
.nwGroupStateCheck{color:var(--dsw-alias-label-primary-foreground);font-size:11px;font-weight:700;line-height:1}
|
|
583
|
+
.nwGroupStateCheckPartial{width:10px;height:10px;border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-state-business-primary);color:transparent}
|
|
130
584
|
|
|
131
585
|
/* ===== 非净化模式 ===== */
|
|
132
|
-
.nwToolRowRaw{
|
|
133
|
-
.nwToolLabelRaw{color
|
|
134
|
-
.nwRawDanger{color
|
|
135
|
-
.nwRawOn{font-size:11px;color
|
|
586
|
+
.nwToolRow.nwToolRowRaw{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 5%,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-elevation-panel)}
|
|
587
|
+
.nwToolLabelRaw{color:var(--dsw-alias-label-error);font-weight:700}
|
|
588
|
+
.nwRawDanger{color:var(--dsw-alias-label-error)!important;font-weight:600}
|
|
589
|
+
.nwRawOn{font-size:11px;line-height:16px;color:var(--dsw-alias-label-error);margin-top:2px;font-weight:600}
|
|
136
590
|
|
|
137
591
|
/* ===== 确认框(v5.2.0:面板内卡片,不再用全屏遮罩)===== */
|
|
138
|
-
/*
|
|
592
|
+
/* 旧版用写死的半透明黑遮罩、上一版换成宿主 mask token + backdrop-blur —— 两者都是"整屏遮罩",
|
|
139
593
|
会把整个应用(侧栏、会话、面板)糊成一片均匀的灰,用户直观感受就是"背景突变了"。
|
|
140
594
|
但这两个确认框(先确认开启 / 再输入承诺文字)本来就是 PanelView 正文的一部分:
|
|
141
595
|
它们出现时已经替换掉正常正文,所以**完全不需要遮罩**——做成一枚居中卡片即可,
|
|
142
596
|
背景一点不变,也不会盖住侧栏与会话。 */
|
|
143
597
|
.nwModal{display:block;margin:18px auto 0;width:100%;max-width:460px}
|
|
144
|
-
.nwModalBox{background:var(--dsw-alias-bg-layer-2
|
|
598
|
+
.nwModalBox{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border-radius:var(--dsw-radius-panel);padding:18px 20px;box-shadow:var(--dsw-elevation-prominent)}
|
|
145
599
|
.nwModalTitle{font-size:15px;font-weight:600;line-height:1.5;margin-bottom:8px}
|
|
146
600
|
.nwModalText{font-size:13px;line-height:1.7;color:var(--dsw-alias-label-secondary);white-space:pre-line;margin-bottom:14px}
|
|
147
|
-
.nwModalInput{width:100%;box-sizing:border-box;padding:9px 11px;font:inherit;font-size:13px;border:
|
|
148
|
-
.nwModalInput:focus{outline:none;border-color:var(--dsw-alias-
|
|
601
|
+
.nwModalInput{width:100%;box-sizing:border-box;padding:9px 11px;font:inherit;font-size:13px;line-height:20px;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);margin-bottom:14px}
|
|
602
|
+
.nwModalInput:focus{outline:none;border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 3px var(--dsw-focus-ring-color)}
|
|
149
603
|
.nwModalBtns{display:flex;gap:10px;justify-content:flex-end}
|
|
150
604
|
/* 卡片里的按钮:给足点击面积,并与卡片底色拉开层次 */
|
|
151
|
-
.nwModalBtns .nwBtn{min-width:88px;height:34px;padding:0 14px;font-size:13px;border-radius:
|
|
152
|
-
.nwModalBtns .nwBtn:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-3
|
|
153
|
-
.nwModalBtns .nwBtnDanger{background:var(--dsw-alias-state-error-primary
|
|
605
|
+
.nwModalBtns .nwBtn{min-width:88px;height:34px;padding:0 14px;font-size:13px;line-height:20px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1)}
|
|
606
|
+
.nwModalBtns .nwBtn:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-3))}
|
|
607
|
+
.nwModalBtns .nwBtn.nwBtnDanger{background:var(--dsw-alias-state-error-primary);border-color:transparent;color:var(--dsw-alias-label-primary-foreground)}
|
|
154
608
|
.nwModalBtns .nwBtnDanger:hover{filter:brightness(1.05)}
|
|
155
609
|
/* 入场:卡片轻微上浮即可,不再有整屏淡入(并尊重系统「减少动态效果」设置) */
|
|
156
610
|
@keyframes nwModalBoxIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
|
|
157
611
|
@media (prefers-reduced-motion: no-preference){
|
|
158
|
-
.nwModalBox{animation:nwModalBoxIn .18s ease-out}
|
|
159
|
-
}
|
|
612
|
+
.nwModalBox{animation:nwModalBoxIn .18s ease-out}}
|
|
160
613
|
|
|
161
614
|
/* ===== 工具行/开关/说明 ===== */
|
|
162
|
-
.nwToolItem{width:100%;margin-bottom:
|
|
615
|
+
.nwToolItem{width:100%;margin-bottom:6px}
|
|
163
616
|
.nwToolItem .nwPlotBox{width:100%;box-sizing:border-box}
|
|
164
|
-
.nwToolsHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:
|
|
165
|
-
.nwToolRow{display:flex;align-items:center;gap:10px;border:
|
|
166
|
-
.
|
|
617
|
+
.nwToolsHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:6px 0 14px}
|
|
618
|
+
.nwToolRow{display:flex;align-items:center;gap:10px;border:0;background:var(--dsw-alias-bg-layer-1);border-radius:var(--dsw-radius-md);padding:10px 14px;box-shadow:var(--dsw-elevation-soft);transition:box-shadow .2s var(--nw-ease),transform .18s var(--nw-ease)}
|
|
619
|
+
.nwToolRow:hover{box-shadow:var(--dsw-elevation-panel);transform:translateY(-1px)}
|
|
620
|
+
.nwToolRow+.nwToolRow{margin-top:10px}
|
|
621
|
+
.nwRow+.nwToolRow,.nwToolRow+.nwRow{margin-top:10px}
|
|
622
|
+
.nwToolRow+.nwPlotBox{margin-top:10px}
|
|
623
|
+
.nwToolRowOn{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-elevation-panel)}
|
|
167
624
|
.nwToolLabel{flex:1;min-width:0;font-size:12px;line-height:1.4;color:var(--dsw-alias-label-primary)}
|
|
168
625
|
.nwToolDesc{font-size:11px;line-height:1.45;color:var(--dsw-alias-label-tertiary);margin-top:2px}
|
|
169
626
|
|
|
170
627
|
/* ===== 工具组 ===== */
|
|
171
|
-
.nwToolGroup{border:
|
|
172
|
-
.
|
|
173
|
-
.
|
|
174
|
-
.
|
|
628
|
+
.nwToolGroup{border:0;border-radius:var(--dsw-radius-md);margin-bottom:8px;overflow:hidden;background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}
|
|
629
|
+
.nwToolGroupBody .nwToolRow{box-shadow:none;background:transparent;transform:none}
|
|
630
|
+
.nwToolGroupBody .nwToolRowOn{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,var(--dsw-alias-bg-layer-1))}
|
|
631
|
+
.nwToolGroupBody .nwToolRow:hover{box-shadow:none;transform:none}
|
|
632
|
+
.nwToolGroupHead{display:flex;align-items:center;gap:6px;width:100%;padding:9px 12px;background:var(--dsw-alias-bg-layer-2);border:none;cursor:default;font-size:13px;line-height:20px;text-align:left;color:inherit;font-family:inherit}
|
|
633
|
+
.nwToolGroupHead:hover{background:var(--dsw-alias-bg-layer-3);font-family:inherit}
|
|
634
|
+
.nwToolGroupIcon{font-size:15px;line-height:22px}
|
|
175
635
|
.nwToolGroupName{font-weight:600}
|
|
176
|
-
.nwToolGroupBadge{margin-left:auto;font-size:11px;color
|
|
177
|
-
.nwToolGroupArrow{font-size:12px;opacity:.6}
|
|
636
|
+
.nwToolGroupBadge{margin-left:auto;font-size:11px;line-height:16px;color:var(--dsw-alias-label-error);background:var(--dsw-alias-state-error-secondary);border-radius:var(--dsw-radius-md);padding:1px 7px}
|
|
637
|
+
.nwToolGroupArrow{font-size:12px;line-height:18px;opacity:.6}
|
|
178
638
|
.nwToolGroupBody{padding:4px 8px 8px}
|
|
179
639
|
.nwToolGroupToggle{flex:none;width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:0}
|
|
180
|
-
.nwToolGroupHeadBtn{flex:1;display:flex;align-items:center;gap:8px;background:none;border:none;cursor:pointer;padding:0;text-align:left;color:inherit;font-size:13px}
|
|
640
|
+
.nwToolGroupHeadBtn{flex:1;display:flex;align-items:center;gap:8px;background:none;border:none;cursor:pointer;padding:0;text-align:left;color:inherit;font-size:13px;line-height:20px}
|
|
181
641
|
.nwToolGroupHeadText{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
182
642
|
.nwToolGroupDescInline{font-size:11px;line-height:1.4;color:var(--dsw-alias-label-tertiary);font-weight:400;white-space:normal}
|
|
183
643
|
|
|
184
644
|
/* ===== v5.2.0:官方主栏全局面板 ===== */
|
|
185
645
|
/* 主栏页面:栅格、滚动容器与选中态都由宿主 layout 负责,这里只管内容排版 */
|
|
186
|
-
.nwPanelMain{max-width:760px;margin:0 auto;padding:28px 24px 48px;gap:10px;box-sizing:border-box;height:100%;overflow:auto}
|
|
646
|
+
.nwPanelMain{width:100%;max-width:760px;margin:0 auto;padding:28px 24px 48px;gap:10px;box-sizing:border-box;height:100%;overflow:auto;scrollbar-gutter:stable}
|
|
647
|
+
|
|
648
|
+
/* ===== v5.5.0:官方语义类(内联样式收编 + 官方设置卡片材质)===== */
|
|
649
|
+
.nwBoxed{background:var(--dsw-alias-bg-layer-1);border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);padding:8px 12px}
|
|
650
|
+
.nwSubCard{background:var(--dsw-alias-bg-layer-1);border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-lg);padding:10px 12px}
|
|
651
|
+
.nwChip{height:24px;padding:0 10px;border-radius:var(--dsw-radius-sm);border:0.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;cursor:pointer;font-family:inherit;transition:background .16s var(--nw-ease),box-shadow .2s var(--nw-ease)}
|
|
652
|
+
.nwChip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font-family:inherit}
|
|
653
|
+
.nwTextInput{height:32px;box-sizing:border-box;padding:0 12px;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;font-family:inherit}
|
|
654
|
+
.nwTextArea{box-sizing:border-box;min-height:56px;padding:10px 12px;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;font-family:inherit}
|
|
655
|
+
.nwSelect{height:32px;padding:0 10px;border:0.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;font-family:inherit}
|
|
656
|
+
.nwNote{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary)}
|
|
657
|
+
.nwMuted{font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary)}
|
|
658
|
+
.nwSignOk{color:var(--dsw-alias-state-success-primary)}
|
|
659
|
+
.nwSignBad{color:var(--dsw-alias-label-error)}
|
|
660
|
+
.nwGutter{font-size:13px;line-height:18px;color:var(--dsw-alias-label-tertiary);text-align:center}
|
|
661
|
+
.nwDashedNote{margin-top:10px;padding:10px 12px;border:1px dashed var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1)}
|
|
662
|
+
.nwDividerRow{border-bottom:0.5px solid var(--dsw-alias-border-l2)}
|
|
663
|
+
.nwSettingsCard{border-radius:var(--dsw-radius-xl);border:0.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-2);padding:14px 16px}
|
|
664
|
+
.nwSettingsCardTitle{font-size:14px;line-height:22px;font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
665
|
+
.nwReportPre{font-size:12px;line-height:20px;color:var(--dsw-alias-label-secondary)}
|
|
666
|
+
.nwGroupName{font-size:12px;line-height:18px;font-weight:600;color:var(--dsw-alias-label-secondary)}
|
|
667
|
+
.nwFileRow{display:flex;align-items:center;gap:8px;width:100%;box-sizing:border-box;padding:7px 10px;cursor:pointer;font-family:inherit}
|
|
668
|
+
.nwFileLabel{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary)}
|
|
669
|
+
.nwStatRow{display:flex;align-items:center;gap:8px;font-size:11px;line-height:16px}
|
|
670
|
+
.nwStatName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary)}
|
|
671
|
+
.nwChevron{font-size:13px;line-height:18px}
|
|
672
|
+
.nwFieldLabel{display:flex;align-items:center;gap:6px;font-size:13px;line-height:20px;font-weight:500;color:var(--dsw-alias-label-primary)}
|
|
673
|
+
.nwWarnBanner{border-radius:var(--dsw-radius-sm);border:1px solid var(--dsw-alias-state-warn-primary);background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-label);font-size:11px;line-height:16px}
|
|
674
|
+
.nwNoteAccent{color:var(--dsw-alias-state-business-primary)}
|
|
675
|
+
.nwNoteWarn{color:var(--dsw-alias-state-warn-label)}
|
|
676
|
+
.nwNoteOk{color:var(--dsw-alias-state-success-primary)}
|
|
677
|
+
.nwNoteDim{color:var(--dsw-alias-label-dimmed)}
|
|
678
|
+
.nwAccentStrong{font-size:13px;line-height:20px;font-weight:600;color:var(--dsw-alias-state-business-primary)}
|
|
679
|
+
.nwTolSign{width:12px;flex:none;text-align:center;font-size:14px;line-height:20px;font-weight:600}
|
|
680
|
+
.nwTolSign.nwSignOk{color:var(--dsw-alias-state-success-primary)}
|
|
681
|
+
.nwTolSign.nwSignBad{color:var(--dsw-alias-label-error)}
|
|
682
|
+
.nwInputErr{border-color:var(--dsw-alias-state-error-primary);box-shadow:0 0 0 3px var(--dsw-alias-interactive-bg-hover-danger)}
|
|
683
|
+
.nwCreationInput{width:100%;box-sizing:border-box;resize:vertical}
|
|
684
|
+
.nwPlotBoxEmpty{color:var(--dsw-alias-label-tertiary)}
|
|
685
|
+
|
|
686
|
+
.nwToolGroupHeadOpen{color:var(--dsw-alias-label-primary)}
|
|
687
|
+
.nwTextInput:focus-visible,.nwTextArea:focus-visible,.nwSelect:focus-visible,.nwTolInput:focus-visible,.nwModalInput:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
|
|
688
|
+
|
|
689
|
+
/* ===== v5.5.0:内联样式收编层(总负责人所有,拼在 A 的 CSS 之后)===== */
|
|
690
|
+
/* 这些类承接原先写在 React 内联 style 里的**外观**(色值/圆角/字号/描边),
|
|
691
|
+
使外观全部由 CSS + 官方语义 token 掌握:深浅主题自动跟随,不再有硬编码色值。
|
|
692
|
+
只放 A 的清单里没有的类;A 已提供 nwBoxed / nwSubCard / nwChip / nwTextInput /
|
|
693
|
+
nwTextArea / nwSelect / nwNote / nwMuted / nwSignOk / nwSignBad / nwGutter /
|
|
694
|
+
nwDashedNote / nwDividerRow 的外观,这里不重复定义。 */
|
|
695
|
+
/* 阈值行里的 +/- 记号:几何由这里给,颜色由 A 的 nwSignOk / nwSignBad 给 */
|
|
696
|
+
/* 新建书名输入框的错误态:由 JS 加类(替代原先 ev.target.style 写死色值) */
|
|
697
|
+
/* 输入类控件的键盘焦点:官方 focus.css 的全局兜底之外,再显式声明一次 */
|
|
698
|
+
/* 设置页「插件卡」:官方设置卡片材质(R20 + 0.5px 发丝描边 + 卡片底色别名) */
|
|
699
|
+
|
|
700
|
+
/* ===== 方案 B(官网式重构):hero 头部 / 分区 kicker / 图标卡 / 状态 pill ===== */
|
|
701
|
+
.nwHero{display:flex;flex-direction:column;gap:6px;border-radius:var(--dsw-radius-xl);padding:18px 18px 16px;border:0.5px solid var(--dsw-alias-border-l4);background-color:var(--dsw-alias-bg-layer-2);background-image:radial-gradient(340px 120px at top center,color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,var(--dsw-alias-bg-layer-2)) 0%,var(--dsw-alias-bg-layer-2) 72%);box-shadow:none}
|
|
702
|
+
.nwHero .nwBanner{background:transparent;border-color:transparent;padding:2px 0;box-shadow:none;letter-spacing:-.01em}
|
|
703
|
+
.nwHero .nwBannerOn,.nwHero .nwBannerOff{background:transparent;border-color:transparent}
|
|
704
|
+
.nwHeroDesc{font-size:12.5px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
705
|
+
.nwSection{display:flex;flex-direction:column;gap:12px;margin-top:16px}
|
|
706
|
+
.nwKickerRow{display:flex;align-items:center;gap:10px}
|
|
707
|
+
.nwKicker{display:inline-flex;align-items:center;gap:6px;padding:3px 12px;border-radius:999px;corner-shape:round;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 8%,var(--dsw-alias-bg-layer-1));border:0.5px solid color-mix(in srgb,var(--dsw-alias-state-business-primary) 16%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-business-primary);font-size:12px;line-height:17px;font-weight:700;letter-spacing:.04em;flex:none}
|
|
708
|
+
.nwKickerRule{flex:1;min-width:0;height:1px;background:var(--dsw-alias-border-l2)}
|
|
709
|
+
.nwIconSlot{flex:none;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:var(--dsw-radius-md);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 8%,var(--dsw-alias-bg-layer-1));border:0.5px solid color-mix(in srgb,var(--dsw-alias-state-business-primary) 16%,var(--dsw-alias-bg-layer-1))}
|
|
710
|
+
.nwIconGlyph{font-size:15px;line-height:20px;color:var(--dsw-alias-state-business-primary)}
|
|
711
|
+
.nwPillRow{display:flex;flex-wrap:wrap;gap:8px}
|
|
712
|
+
.nwPill{display:inline-flex;align-items:baseline;gap:8px;padding:7px 16px;border-radius:999px;corner-shape:round;background:var(--dsw-alias-bg-layer-2);transition:background .16s var(--nw-ease)}
|
|
713
|
+
.nwPillKey{font-size:12.5px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
714
|
+
.nwPillVal{font-size:13px;line-height:18px;font-weight:650;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}
|
|
715
|
+
/* 微交互总门:减少动态效果时关掉 hover 抬升与过渡(模态入场动画原本就在 no-preference 门内) */
|
|
716
|
+
@media (prefers-reduced-motion: reduce){
|
|
717
|
+
.nwRow,.nwNavEntry,.nwToolRow,.nwBtn,.nwChip,.nwPill,.nwSwitch,.nwSwitchKnob,.nwSegBtn{transition:none!important}
|
|
718
|
+
.nwRow:hover,.nwNavEntry:hover,.nwToolRow:hover,.nwBtnPrimary:hover,.nwBtnGhost:hover{transform:none!important}
|
|
719
|
+
.nwBtnPrimary:hover{filter:none!important}
|
|
720
|
+
}
|
|
187
721
|
`;
|
|
188
722
|
// v3.0.0-UI3:已存在旧 style 标签也覆盖内容——否则插件脚本重复执行时新 CSS 永不注入(UI 停留在旧版)
|
|
189
723
|
if (typeof document !== "undefined") {
|
|
@@ -209,6 +743,10 @@ var css = `
|
|
|
209
743
|
"panel.autoAnalyze": "分析作品时自动使用",
|
|
210
744
|
"panel.autoAnalyzeHint": "开启后,AI 在分析作品时会主动附带句式分析;关闭则仅在用户明确要求时使用。",
|
|
211
745
|
"panel.spMode": "系统提示词",
|
|
746
|
+
"panel.secSwitch": "开关",
|
|
747
|
+
"panel.secPrompt": "提示词",
|
|
748
|
+
"panel.secStatus": "状态",
|
|
749
|
+
"panel.heroDesc": "18 个工具 · 6 维文笔基线 · 全本地推理,正文不外传",
|
|
212
750
|
"panel.spModeHint": "控制插件往系统提示词里注入多少内容:关闭=完全不注入;精简=一句话(推荐);完整=完整工作流说明。改完下一轮对话生效。",
|
|
213
751
|
"sp.off": "关闭",
|
|
214
752
|
"sp.brief": "精简",
|
|
@@ -425,6 +963,10 @@ var css = `
|
|
|
425
963
|
"panel.autoAnalyze": "Auto-use when analyzing works",
|
|
426
964
|
"panel.autoAnalyzeHint": "When on, the AI proactively includes sentence analysis; otherwise only on explicit request.",
|
|
427
965
|
"panel.spMode": "System prompt",
|
|
966
|
+
"panel.secSwitch": "Switch",
|
|
967
|
+
"panel.secPrompt": "Prompts",
|
|
968
|
+
"panel.secStatus": "Status",
|
|
969
|
+
"panel.heroDesc": "18 tools · 6-dimension style baseline · fully local — text never leaves your machine",
|
|
428
970
|
"panel.spModeHint": "How much the plugin injects into the system prompt: Off = nothing; Brief = one line (recommended); Full = the complete workflow. Applies from the next turn.",
|
|
429
971
|
"sp.off": "Off",
|
|
430
972
|
"sp.brief": "Brief",
|
|
@@ -1049,19 +1591,19 @@ var css = `
|
|
|
1049
1591
|
// v4.3.0:同上,删掉永不匹配的 [data-pane="conversation"](真实标记是 …_centerCol)
|
|
1050
1592
|
return document.querySelector('[class*="centerCol"]') ?? void 0;
|
|
1051
1593
|
}
|
|
1594
|
+
/**
|
|
1595
|
+
* v5.5.0:开关交给官方 primitives(Switch 36×20,关闭态滑块读 --dsw-alias-switch-thumb),
|
|
1596
|
+
* 取不到官方包时由 NW_UI 内部回退到同一套 token 样式的本地实现(见「官方原语适配层」)。
|
|
1597
|
+
* 保留这个局部名字,6 个调用点无需改动;label 是无障碍名称,由调用点传入。
|
|
1598
|
+
*/
|
|
1052
1599
|
function Switch(props) {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
className: "nwSwitch" + (props.checked ? " nwSwitchOn" : ""),
|
|
1061
|
-
onClick: function () { props.onChange(!props.checked); }
|
|
1062
|
-
},
|
|
1063
|
-
react.createElement("span", { className: "nwSwitchKnob" })
|
|
1064
|
-
);
|
|
1600
|
+
// 必须用 createElement 变成子组件:官方 Switch 内部用 hook,直接调用会把 hook 混进本组件的 hook 链
|
|
1601
|
+
return react.createElement(NW_UI.Switch, {
|
|
1602
|
+
checked: props.checked,
|
|
1603
|
+
disabled: props.disabled,
|
|
1604
|
+
onChange: props.onChange,
|
|
1605
|
+
label: props.label || ""
|
|
1606
|
+
});
|
|
1065
1607
|
}
|
|
1066
1608
|
function PanelView(props) {
|
|
1067
1609
|
// v3.7.0 高1:isEn 声明在视图作用域(此前只在 rawSetPromise 内部,基线视图引用 ReferenceError 必崩)
|
|
@@ -1085,6 +1627,7 @@ var css = `
|
|
|
1085
1627
|
var loadingHint = state.loading ? el("div", { className: "nwStatus" }, "⟳ " + t("panel.loading")) : null;
|
|
1086
1628
|
var entry = function (title, hint, count, viewName) {
|
|
1087
1629
|
return el("button", { type: "button", className: "nwNavEntry", onClick: function () { props.controller.openView(viewName); } },
|
|
1630
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, viewName === "features" ? "⚙" : viewName === "tools" ? "🛠" : viewName === "creation" ? "📖" : viewName === "baseline" ? "🎯" : "▸")),
|
|
1088
1631
|
el("div", { className: "nwNavEntryText" },
|
|
1089
1632
|
el("div", { className: "nwNavEntryTitle" }, title),
|
|
1090
1633
|
el("div", { className: "nwNavEntryHint" }, hint)
|
|
@@ -1108,15 +1651,14 @@ var css = `
|
|
|
1108
1651
|
};
|
|
1109
1652
|
var switchRow = function (name, fOn, onToggle, extra) {
|
|
1110
1653
|
return el("div", { className: "nwToolRow" + (fOn ? " nwToolRowOn" : ""), key: name },
|
|
1654
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, name === "emotionCaveat" ? "💧" : name === "emotionComplexity" ? "🎭" : name === "genreTheme" ? "🏷" : name === "webnovelVibe" ? "📡" : name === "semanticEmbedding" ? "🧠" : name === "semanticSearch" ? "🔎" : name === "semanticStyle" ? "🖌" : name === "semanticImplicit" ? "👁" : "⚙")),
|
|
1111
1655
|
el("div", { className: "nwToolLabel" },
|
|
1112
1656
|
el("div", null, t("feature." + name)),
|
|
1113
1657
|
el("div", { className: "nwToolDesc" }, t("feature." + name + ".desc")),
|
|
1114
1658
|
extra || null
|
|
1115
1659
|
),
|
|
1116
|
-
el(
|
|
1117
|
-
|
|
1118
|
-
el("span", { className: "nwSwitchSmallKnob" })
|
|
1119
|
-
)
|
|
1660
|
+
el(Switch, { checked: fOn, disabled: state.loading, label: String(t("feature." + name)),
|
|
1661
|
+
onChange: function () { onToggle(name, !fOn); } })
|
|
1120
1662
|
);
|
|
1121
1663
|
};
|
|
1122
1664
|
function formatSize(bytes) {
|
|
@@ -1205,14 +1747,13 @@ var TOOL_GROUPS = [
|
|
|
1205
1747
|
else if (name === "novel_sentence_analysis") pathExtra = pathBox(t("dir.analysis"), dirs.analysisDir || "", "analysis-dir");
|
|
1206
1748
|
return el("div", { key: name, className: "nwToolItem" },
|
|
1207
1749
|
el("div", { className: "nwToolRow" + (checked ? " nwToolRowOn" : "") },
|
|
1750
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "🧩")),
|
|
1208
1751
|
el("div", { className: "nwToolLabel" },
|
|
1209
1752
|
el("div", null, String(t("tool." + name)).replace(/\s+novel_\w+$/, "")),
|
|
1210
1753
|
el("div", { className: "nwToolDesc" }, desc)
|
|
1211
1754
|
),
|
|
1212
|
-
el(
|
|
1213
|
-
|
|
1214
|
-
el("span", { className: "nwSwitchSmallKnob" })
|
|
1215
|
-
)
|
|
1755
|
+
el(Switch, { checked: checked, disabled: state.loading, label: String(t("tool." + name)).replace(/\s+novel_\w+$/, ""),
|
|
1756
|
+
onChange: function () { props.toggle({ tools: (function (patch) { patch[name] = !checked; return patch; })({}) }); } })
|
|
1216
1757
|
),
|
|
1217
1758
|
pathExtra || null
|
|
1218
1759
|
);
|
|
@@ -1343,34 +1884,34 @@ var TOOL_GROUPS = [
|
|
|
1343
1884
|
el("div", { className: "nwSectionTitle" }, "🎯 " + t("panel.baselineTitle")),
|
|
1344
1885
|
el("div", { className: "nwToolsHint" }, t("baseline.desc")),
|
|
1345
1886
|
el("div", { className: "nwTolVer" }, "v3.0.0-UI3"),
|
|
1346
|
-
el("div", { className: "nwTolCard"
|
|
1887
|
+
el("div", { className: "nwTolCard" },
|
|
1347
1888
|
NW_METRICS.map(function (item) {
|
|
1348
1889
|
var mk2 = item[0];
|
|
1349
1890
|
var d = draft[mk2] || DEFAULT_TOL;
|
|
1350
1891
|
return el("div", { className: "nwTolRow", key: mk2, style: { display: "flex", alignItems: "center", gap: "10px", padding: "9px 2px" } },
|
|
1351
|
-
el("div", { className: "nwTolName"
|
|
1892
|
+
el("div", { className: "nwTolName" }, el("span", { className: "nwTolIcon" }, item[2]), isEn ? (item[3] || item[1]) : item[1]),
|
|
1352
1893
|
el("div", { className: "nwTolField", style: { width: "74px", flexShrink: "0", display: "flex", flexDirection: "column", gap: "3px" } },
|
|
1353
1894
|
el("div", { style: { display: "flex", alignItems: "center", gap: "4px" } },
|
|
1354
|
-
el("span", { className: "nwTolSign"
|
|
1355
|
-
el("input", { type: "number", className: "nwTolInput", placeholder: t("tol.recommend"), value: d.low, min: 0, max: 99, disabled: state.loading,
|
|
1895
|
+
el("span", { className: "nwTolSign" }, "−"),
|
|
1896
|
+
el("input", { type: "number", className: "nwTolInput", placeholder: t("tol.recommend"), value: d.low, min: 0, max: 99, disabled: state.loading, onChange: function (ev) { setDraft(mk2, "low", ev.target.value); } })
|
|
1356
1897
|
),
|
|
1357
|
-
el("span", { className: "nwTolCaption"
|
|
1898
|
+
el("span", { className: "nwTolCaption" }, t("baseline.low"))
|
|
1358
1899
|
),
|
|
1359
|
-
el("span", { className: "nwTolSep"
|
|
1900
|
+
el("span", { className: "nwTolSep" }, "~"),
|
|
1360
1901
|
el("div", { className: "nwTolField", style: { width: "74px", flexShrink: "0", display: "flex", flexDirection: "column", gap: "3px" } },
|
|
1361
1902
|
el("div", { style: { display: "flex", alignItems: "center", gap: "4px" } },
|
|
1362
|
-
el("span", { className: "nwTolSign"
|
|
1363
|
-
el("input", { type: "number", className: "nwTolInput", placeholder: t("tol.recommend"), value: d.high, min: 0, max: 99, disabled: state.loading,
|
|
1903
|
+
el("span", { className: "nwTolSign" }, "+"),
|
|
1904
|
+
el("input", { type: "number", className: "nwTolInput", placeholder: t("tol.recommend"), value: d.high, min: 0, max: 99, disabled: state.loading, onChange: function (ev) { setDraft(mk2, "high", ev.target.value); } })
|
|
1364
1905
|
),
|
|
1365
|
-
el("span", { className: "nwTolCaption"
|
|
1906
|
+
el("span", { className: "nwTolCaption" }, t("baseline.high"))
|
|
1366
1907
|
),
|
|
1367
|
-
el("span", { className: "nwTolPct"
|
|
1908
|
+
el("span", { className: "nwTolPct" }, "%")
|
|
1368
1909
|
);
|
|
1369
1910
|
})
|
|
1370
1911
|
),
|
|
1371
1912
|
el("div", { className: "nwTolBtns", style: { display: "flex", gap: "12px", marginTop: "16px" } },
|
|
1372
|
-
el("button", { type: "button", className: "nwBtn nwBtnPrimary" + (state.baselineSaved ? " nwBtnDone" : ""), disabled: state.loading, onClick: saveTol
|
|
1373
|
-
el("button", { type: "button", className: "nwBtn nwBtnGhost", disabled: state.loading, onClick: resetTol
|
|
1913
|
+
el("button", { type: "button", className: "nwBtn nwBtnPrimary" + (state.baselineSaved ? " nwBtnDone" : ""), disabled: state.loading, onClick: saveTol }, state.baselineSaved ? "✓ " + t("baseline.saved") : "💾 " + t("baseline.save")),
|
|
1914
|
+
el("button", { type: "button", className: "nwBtn nwBtnGhost", disabled: state.loading, onClick: resetTol }, "↺ " + t("baseline.reset"))
|
|
1374
1915
|
)
|
|
1375
1916
|
);
|
|
1376
1917
|
} else if (view === "reports") {
|
|
@@ -1399,18 +1940,18 @@ var TOOL_GROUPS = [
|
|
|
1399
1940
|
el("div", { className: "nwToolsHint" }, t("reports.hint")),
|
|
1400
1941
|
state.reportContent ?
|
|
1401
1942
|
el("div", null,
|
|
1402
|
-
el("button", { type: "button",
|
|
1403
|
-
el("pre", {
|
|
1943
|
+
el("button", { type: "button", className: "nwChip", style: { margin: "6px 0" }, onClick: function () { props.controller.set({ reportContent: null }); } }, "‹ " + t("reports.back")),
|
|
1944
|
+
el("pre", { className: "nwBoxed nwReportPre", style: { margin: "4px 0 0", whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: "70vh", overflow: "auto" } }, state.reportContent)
|
|
1404
1945
|
)
|
|
1405
1946
|
: el("div", { style: { display: "flex", flexDirection: "column", gap: "8px" } },
|
|
1406
|
-
reportsLoading ? el("div", {
|
|
1947
|
+
reportsLoading ? el("div", { className: "nwMuted", style: { padding: "10px 0" } }, t("reports.loading2")) : totalFiles === 0 ? el("div", { className: "nwMuted", style: { padding: "10px 0" } }, t("reports.empty")) : null,
|
|
1407
1948
|
groups.map(function (g) {
|
|
1408
1949
|
return el("div", { key: g.name },
|
|
1409
|
-
el("div", {
|
|
1950
|
+
el("div", { className: "nwGroupName", style: { margin: "6px 0 4px" } }, g.name + "(" + (g.files || []).length + ")"),
|
|
1410
1951
|
(g.files || []).map(function (f) {
|
|
1411
|
-
return el("button", { key: f.file, type: "button",
|
|
1412
|
-
el("span", {
|
|
1413
|
-
el("span", {
|
|
1952
|
+
return el("button", { key: f.file, type: "button", className: "nwBoxed nwFileRow", style: { marginBottom: "4px", textAlign: "left" }, onClick: function () { openReport(f.file); } },
|
|
1953
|
+
el("span", { className: "nwFileLabel", }, f.label),
|
|
1954
|
+
el("span", { className: "nwNote", }, (f.time || "").slice(0, 16).replace("T", " "))
|
|
1414
1955
|
);
|
|
1415
1956
|
})
|
|
1416
1957
|
);
|
|
@@ -1470,7 +2011,7 @@ var TOOL_GROUPS = [
|
|
|
1470
2011
|
}
|
|
1471
2012
|
if (!nb) {
|
|
1472
2013
|
var elInp = document.getElementById("nwNewBookInput");
|
|
1473
|
-
if (elInp) { elInp.focus(); elInp.
|
|
2014
|
+
if (elInp) { elInp.focus(); elInp.classList.add("nwInputErr"); }
|
|
1474
2015
|
props.controller.set({ revealMsg: t("creation.needName"), revealErr: true }, { silent: true });
|
|
1475
2016
|
return;
|
|
1476
2017
|
}
|
|
@@ -1481,15 +2022,15 @@ var TOOL_GROUPS = [
|
|
|
1481
2022
|
};
|
|
1482
2023
|
function bookRow(name, profile, isDefault, hasProfile) {
|
|
1483
2024
|
var filled = filledCount(profile);
|
|
1484
|
-
return el("div", { key: "bk-" + name,
|
|
2025
|
+
return el("div", { key: "bk-" + name, className: "nwBoxed nwFileRow", style: { gap: "10px", padding: "10px 12px" } },
|
|
1485
2026
|
el("div", { style: { flex: "1", minWidth: "0" } },
|
|
1486
|
-
el("div", {
|
|
1487
|
-
el("div", {
|
|
1488
|
-
isDefault ? el("div", {
|
|
2027
|
+
el("div", { className: "nwRowLabel", }, isDefault ? "🌐 " + t("creation.default") : "📕 " + name),
|
|
2028
|
+
el("div", { className: "nwNote" + (filled > 0 ? " nwNoteAccent" : ""), style: { marginTop: "2px" } }, summaryOf(profile)),
|
|
2029
|
+
isDefault ? el("div", { className: "nwNote", style: { marginTop: "1px" } }, t("creation.defaultHint")) : null
|
|
1489
2030
|
),
|
|
1490
|
-
el("button", { type: "button", onClick: function () { props.controller.set({ creationBook: name, creationDraft: null, creationDirty: false }, { silent: true }); props.controller.openView("creation-form"); } }, t("creation.edit")),
|
|
2031
|
+
el("button", { type: "button", className: "nwChip", onClick: function () { props.controller.set({ creationBook: name, creationDraft: null, creationDirty: false }, { silent: true }); props.controller.openView("creation-form"); } }, t("creation.edit")),
|
|
1491
2032
|
// v4.0.0 修正:书库里的书若没有设定条目,不渲染"删除"(此前点了空操作却提示"已删除")
|
|
1492
|
-
(isDefault || !hasProfile) ? null : el("button", { type: "button", onClick: function () { var patch = {}; patch[name] = null; props.toggle({ creationProfiles: patch }); props.controller.set({ revealMsg: t("creation.deleted"), revealErr: false }, { silent: true }); } }, t("creation.delete"))
|
|
2033
|
+
(isDefault || !hasProfile) ? null : el("button", { type: "button", className: "nwChip", onClick: function () { var patch = {}; patch[name] = null; props.toggle({ creationProfiles: patch }); props.controller.set({ revealMsg: t("creation.deleted"), revealErr: false }, { silent: true }); } }, t("creation.delete"))
|
|
1493
2034
|
);
|
|
1494
2035
|
}
|
|
1495
2036
|
body = el("div", null,
|
|
@@ -1498,8 +2039,8 @@ var TOOL_GROUPS = [
|
|
|
1498
2039
|
el("div", { className: "nwToolsHint" }, t("creation.desc2")),
|
|
1499
2040
|
// 新建设定
|
|
1500
2041
|
el("div", { style: { display: "flex", gap: "8px", marginTop: "8px", marginBottom: "10px" } },
|
|
1501
|
-
el("input", { id: "nwNewBookInput", type: "text", value: newBookName, placeholder: t("creation.newPlaceholder"), style: { flex: "1", height: "34px"
|
|
1502
|
-
el("button", { type: "button", style: { height: "34px", padding: "0 16px"
|
|
2042
|
+
el("input", { id: "nwNewBookInput", type: "text", value: newBookName, placeholder: t("creation.newPlaceholder"), className: "nwTextInput", style: { flex: "1", height: "34px" }, onInput: function (ev) { props.controller.set({ creationNewBook: ev.target.value }, { silent: true }); }, onKeyDown: function (ev) { if (ev.key === "Enter") { ev.preventDefault(); createNewBook(); } } }),
|
|
2043
|
+
el("button", { type: "button", className: "nwBtn nwBtnPrimary", style: { height: "34px", padding: "0 16px" }, onClick: createNewBook }, t("creation.new"))
|
|
1503
2044
|
),
|
|
1504
2045
|
el("div", { style: { display: "flex", flexDirection: "column", gap: "8px" } },
|
|
1505
2046
|
bookRow("", cpGlobal, true),
|
|
@@ -1572,21 +2113,21 @@ var TOOL_GROUPS = [
|
|
|
1572
2113
|
el("div", { className: "nwSectionTitle" }, "🎨 " + (curBook ? curBook : t("creation.default")) + " · " + t("creation.formTitle")),
|
|
1573
2114
|
// 快速切换
|
|
1574
2115
|
el("div", { style: { display: "flex", alignItems: "center", gap: "8px", margin: "4px 0 10px" } },
|
|
1575
|
-
el("span", {
|
|
1576
|
-
el("select", {
|
|
2116
|
+
el("span", { className: "nwMuted", }, t("creation.bookFor")),
|
|
2117
|
+
el("select", { className: "nwSelect", value: curBook, onChange: function (ev) { switchBook(ev.target.value); } }, switchOpts)
|
|
1577
2118
|
),
|
|
1578
2119
|
el("div", { style: { display: "flex", flexDirection: "column", gap: "10px" } },
|
|
1579
2120
|
CREATION_FIELDS.map(function (item) {
|
|
1580
2121
|
var cf4 = item[0];
|
|
1581
2122
|
return el("div", { key: cf4, style: { display: "flex", flexDirection: "column", gap: "4px" } },
|
|
1582
|
-
el("div", {
|
|
1583
|
-
el("textarea", { className: "nwCreationInput", value: formDraft[cf4] || "", rows: 2, placeholder: item[3], style: { width: "100%",
|
|
2123
|
+
el("div", { className: "nwFieldLabel", }, item[1] + " " + item[2]),
|
|
2124
|
+
el("textarea", { className: "nwCreationInput nwTextArea", value: formDraft[cf4] || "", rows: 2, placeholder: item[3], style: { width: "100%", resize: "vertical" }, onInput: function (ev) { setFormDraft(cf4, ev.target.value); } })
|
|
1584
2125
|
);
|
|
1585
2126
|
})
|
|
1586
2127
|
),
|
|
1587
2128
|
el("div", { style: { display: "flex", gap: "12px", marginTop: "14px" } },
|
|
1588
|
-
el("button", { type: "button", className: "nwBtn", style: {
|
|
1589
|
-
el("button", { type: "button", className: "nwBtn", style: {
|
|
2129
|
+
el("button", { type: "button", className: "nwBtn", style: { padding: "9px 20px" }, onClick: saveForm }, "💾 " + t("creation.save")),
|
|
2130
|
+
el("button", { type: "button", className: "nwBtn", style: { padding: "9px 18px" }, onClick: clearForm }, "↺ " + t("creation.clear"))
|
|
1590
2131
|
)
|
|
1591
2132
|
);
|
|
1592
2133
|
} } else {
|
|
@@ -1615,7 +2156,7 @@ var TOOL_GROUPS = [
|
|
|
1615
2156
|
}
|
|
1616
2157
|
body = el("div", null,
|
|
1617
2158
|
// v3.5.0 #37:保存失败/宿主不可达提示条
|
|
1618
|
-
(state.saveFailed || state.hostOk === false) ? el("div", { key: "saveBanner", style: { padding: "7px 10px", marginBottom: "8px"
|
|
2159
|
+
(state.saveFailed || state.hostOk === false) ? el("div", { key: "saveBanner", className: "nwWarnBanner", style: { padding: "7px 10px", marginBottom: "8px" } }, state.hostOk === false ? t("panel.localOnly") : t("panel.saveFailed")) : null,
|
|
1619
2160
|
// v2.6.5:更新提示条(有新版才显示,点击跳 GitHub Release)
|
|
1620
2161
|
// v4.3.0:ok === false 时不显示该条——避免用"上次检查到的版本"冒充本次结果
|
|
1621
2162
|
updateCheck && !updateFailed && updateCheck.updateAvailable && updateCheck.releaseUrl
|
|
@@ -1627,124 +2168,151 @@ var TOOL_GROUPS = [
|
|
|
1627
2168
|
updateFailed
|
|
1628
2169
|
? el("div", { key: "updateStale", className: "nwUpdateStale" }, updateFailedText)
|
|
1629
2170
|
: null,
|
|
1630
|
-
el("div", { className: "
|
|
1631
|
-
el("div", { className: "
|
|
1632
|
-
el("div", { className: "
|
|
1633
|
-
el("div", { className: "
|
|
2171
|
+
el("div", { className: "nwSection" },
|
|
2172
|
+
el("div", { className: "nwKickerRow" },
|
|
2173
|
+
el("div", { className: "nwKicker" }, t("panel.secSwitch")),
|
|
2174
|
+
el("div", { className: "nwKickerRule" })
|
|
1634
2175
|
),
|
|
1635
|
-
el("div", { className: "
|
|
1636
|
-
el(
|
|
1637
|
-
el("
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
2176
|
+
el("div", { className: "nwRow " + (state.enabled ? "nwRowOn" : "nwRowOff") },
|
|
2177
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "🎚")),
|
|
2178
|
+
el("div", { className: "nwRowText" },
|
|
2179
|
+
el("div", { className: "nwRowLabel" }, t("panel.enabled")),
|
|
2180
|
+
el("div", { className: "nwRowHint" }, t("panel.enabledHint"))
|
|
2181
|
+
),
|
|
2182
|
+
el("div", { className: "nwSwitchWrap" },
|
|
2183
|
+
el(Switch, { checked: state.enabled, disabled: state.loading, label: t("panel.enabled"), onChange: function (value) { props.toggle({ enabled: value }); } }),
|
|
2184
|
+
el("span", { className: "nwBadge " + (state.enabled ? "nwBadgeOn" : "nwBadgeOff") }, state.enabled ? t("badge.on") : t("badge.off"))
|
|
2185
|
+
)
|
|
2186
|
+
),
|
|
2187
|
+
el("div", { className: "nwRow " + (state.autoAnalyze ? "nwRowOn" : "nwRowOff") },
|
|
2188
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "📊")),
|
|
2189
|
+
el("div", { className: "nwRowText" },
|
|
2190
|
+
el("div", { className: "nwRowLabel" }, t("panel.autoAnalyze")),
|
|
2191
|
+
el("div", { className: "nwRowHint" }, t("panel.autoAnalyzeHint"))
|
|
2192
|
+
),
|
|
2193
|
+
el("div", { className: "nwSwitchWrap" },
|
|
2194
|
+
el(Switch, { checked: state.autoAnalyze, disabled: state.loading, label: t("panel.autoAnalyze"), onChange: function (value) { props.toggle({ autoAnalyze: value }); } }),
|
|
2195
|
+
el("span", { className: "nwBadge " + (state.autoAnalyze ? "nwBadgeOn" : "nwBadgeOff") }, state.autoAnalyze ? t("badge.on") : t("badge.off"))
|
|
2196
|
+
)
|
|
2197
|
+
),
|
|
2198
|
+
// v5.0.0:精简工作流——全局开关,与相邻开关同一套 switch/badge 组件。
|
|
2199
|
+
// B2 重排:由「提示词档位 / 提示词场景」两行之下移入「开关」分区——与「提示词场景」行的区别:它不受"仅完整档生效"限制(不给 disabled 逻辑),任何时候都可切换;
|
|
2200
|
+
// 打开(true)= 提示词换"按需调用"最简档,关闭(false,默认)= 维持 5.0.0 的自检/收尾/复测清单。
|
|
2201
|
+
el("div", { className: "nwRow " + (state.leanWorkflow ? "nwRowOn" : "nwRowOff") },
|
|
2202
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "⚡")),
|
|
2203
|
+
el("div", { className: "nwRowText" },
|
|
2204
|
+
el("div", { className: "nwRowLabel" }, t("panel.leanWorkflow")),
|
|
2205
|
+
el("div", { className: "nwRowHint" }, t("panel.leanWorkflowHint"))
|
|
2206
|
+
),
|
|
2207
|
+
el("div", { className: "nwSwitchWrap" },
|
|
2208
|
+
el(Switch, { checked: state.leanWorkflow === true, disabled: state.loading, label: t("panel.leanWorkflow"), onChange: function (value) { props.toggle({ leanWorkflow: value }); } }),
|
|
2209
|
+
el("span", { className: "nwBadge " + (state.leanWorkflow ? "nwBadgeOn" : "nwBadgeOff") }, state.leanWorkflow ? t("badge.on") : t("badge.off"))
|
|
2210
|
+
)
|
|
1644
2211
|
),
|
|
1645
|
-
el("div", { className: "nwSwitchWrap" },
|
|
1646
|
-
el(Switch, { checked: state.autoAnalyze, disabled: state.loading, onChange: function (value) { props.toggle({ autoAnalyze: value }); } }),
|
|
1647
|
-
el("span", { className: "nwBadge " + (state.autoAnalyze ? "nwBadgeOn" : "nwBadgeOff") }, state.autoAnalyze ? t("badge.on") : t("badge.off"))
|
|
1648
|
-
)
|
|
1649
2212
|
),
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
el("div", { className: "
|
|
1654
|
-
el("div", { className: "nwRowHint" }, t("panel.spModeHint"))
|
|
2213
|
+
el("div", { className: "nwSection" },
|
|
2214
|
+
el("div", { className: "nwKickerRow" },
|
|
2215
|
+
el("div", { className: "nwKicker" }, t("panel.secPrompt")),
|
|
2216
|
+
el("div", { className: "nwKickerRule" })
|
|
1655
2217
|
),
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
2218
|
+
// v4.0.0:系统提示词注入档位(关闭 / 精简 / 完整)——三档分段按钮,沿用 dsh-unrestricted 的开关思路
|
|
2219
|
+
el("div", { className: "nwRow " + (state.systemPromptMode !== "off" ? "nwRowOn" : "nwRowOff") },
|
|
2220
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "📝")),
|
|
2221
|
+
el("div", { className: "nwRowText" },
|
|
2222
|
+
el("div", { className: "nwRowLabel" }, t("panel.spMode")),
|
|
2223
|
+
el("div", { className: "nwRowHint" }, t("panel.spModeHint"))
|
|
2224
|
+
),
|
|
2225
|
+
el(NW_UI.SegmentedControl, {
|
|
2226
|
+
label: t("panel.spMode"),
|
|
2227
|
+
value: state.systemPromptMode,
|
|
2228
|
+
disabled: state.loading,
|
|
2229
|
+
options: ["off", "brief", "full"].map(function (m) { return { value: m, label: t("sp." + m) }; }),
|
|
2230
|
+
onChange: function (m) { if (state.systemPromptMode !== m) props.toggle({ systemPromptMode: m }); }
|
|
1660
2231
|
})
|
|
1661
|
-
)
|
|
1662
|
-
),
|
|
1663
|
-
// v5.0.0:提示词场景——与上面的档位正交:档位决定"注入多少",场景决定"注入什么"。
|
|
1664
|
-
// v5.1.1 修正:**不再因为档位非 full 就把按钮 disabled**——用户反馈"场景里点不了其他选项",
|
|
1665
|
-
// 因为默认档位是 off/精简,五个按钮全灰且没有任何解释,等于把"选场景"锁死在一个看不见的前提后面。
|
|
1666
|
-
// 现在按钮始终可点(只受 loading 限制),档位非 full 时改用行内提示说明"已保存但暂不注入"。
|
|
1667
|
-
// 场景枚举必须与 lib/prompts.js 的 PROMPT_SCENES 保持一致(客户端是独立 bundle,不能 import)。
|
|
1668
|
-
el("div", { className: "nwRow " + (state.systemPromptMode === "full" ? "nwRowOn" : "nwRowOff") },
|
|
1669
|
-
el("div", { className: "nwRowText" },
|
|
1670
|
-
el("div", { className: "nwRowLabel" }, t("panel.spScene")),
|
|
1671
|
-
el("div", { className: "nwRowHint" }, t("panel.spSceneHint") + (state.systemPromptMode === "full" ? "" : " " + t("panel.spSceneInactive")))
|
|
1672
2232
|
),
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2233
|
+
// v5.0.0:提示词场景——与上面的档位正交:档位决定"注入多少",场景决定"注入什么"。
|
|
2234
|
+
// v5.1.1 修正:**不再因为档位非 full 就把按钮 disabled**——用户反馈"场景里点不了其他选项",
|
|
2235
|
+
// 因为默认档位是 off/精简,五个按钮全灰且没有任何解释,等于把"选场景"锁死在一个看不见的前提后面。
|
|
2236
|
+
// 现在按钮始终可点(只受 loading 限制),档位非 full 时改用行内提示说明"已保存但暂不注入"。
|
|
2237
|
+
// 场景枚举必须与 lib/prompts.js 的 PROMPT_SCENES 保持一致(客户端是独立 bundle,不能 import)。
|
|
2238
|
+
el("div", { className: "nwRow " + (state.systemPromptMode === "full" ? "nwRowOn" : "nwRowOff") },
|
|
2239
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "🎛")),
|
|
2240
|
+
el("div", { className: "nwRowText" },
|
|
2241
|
+
el("div", { className: "nwRowLabel" }, t("panel.spScene")),
|
|
2242
|
+
el("div", { className: "nwRowHint" }, t("panel.spSceneHint") + (state.systemPromptMode === "full" ? "" : " " + t("panel.spSceneInactive")))
|
|
2243
|
+
),
|
|
2244
|
+
el(NW_UI.SegmentedControl, {
|
|
2245
|
+
label: t("panel.spScene"),
|
|
2246
|
+
value: state.promptScene || "general",
|
|
2247
|
+
disabled: state.loading,
|
|
2248
|
+
options: ["general", "writing", "revising", "auditing", "setup"].map(function (s) { return { value: s, label: t("sc." + s) }; }),
|
|
2249
|
+
onChange: function (s) { if ((state.promptScene || "general") !== s) props.toggle({ promptScene: s }); }
|
|
1678
2250
|
})
|
|
1679
|
-
)
|
|
1680
|
-
),
|
|
1681
|
-
// v5.0.0:精简工作流——全局开关,紧挨「提示词档位 / 提示词场景」两行之下、与相邻开关同一套 switch/badge 组件。
|
|
1682
|
-
// 与上一条「提示词场景」的区别:它不受"仅完整档生效"限制(不给 disabled 逻辑),任何时候都可切换;
|
|
1683
|
-
// 打开(true)= 提示词换"按需调用"最简档,关闭(false,默认)= 维持 5.0.0 的自检/收尾/复测清单。
|
|
1684
|
-
el("div", { className: "nwRow " + (state.leanWorkflow ? "nwRowOn" : "nwRowOff") },
|
|
1685
|
-
el("div", { className: "nwRowText" },
|
|
1686
|
-
el("div", { className: "nwRowLabel" }, t("panel.leanWorkflow")),
|
|
1687
|
-
el("div", { className: "nwRowHint" }, t("panel.leanWorkflowHint"))
|
|
1688
2251
|
),
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
el("
|
|
1692
|
-
|
|
2252
|
+
(function () {
|
|
2253
|
+
var rawOn = f.rawWriting === true;
|
|
2254
|
+
return el("div", { className: "nwToolRow" + (rawOn ? " nwToolRowOn" : " nwToolRowRaw"), key: "rawWriting" },
|
|
2255
|
+
el("div", { className: "nwIconSlot" }, el("span", { className: "nwIconGlyph" }, "⚠️")),
|
|
2256
|
+
el("div", { className: "nwToolLabel" },
|
|
2257
|
+
el("div", { className: "nwToolLabelRaw" }, "🔞 " + t("feature.rawWriting")),
|
|
2258
|
+
el("div", { className: "nwToolDesc nwRawDanger" }, t("raw.danger")),
|
|
2259
|
+
rawOn ? el("div", { className: "nwRawOn" }, t("raw.on")) : null
|
|
2260
|
+
),
|
|
2261
|
+
el(Switch, { checked: rawOn, disabled: state.loading, label: "🔞 " + t("feature.rawWriting"),
|
|
2262
|
+
onChange: function () { props.controller.rawToggle(!rawOn); } })
|
|
2263
|
+
);
|
|
2264
|
+
})(),
|
|
1693
2265
|
),
|
|
1694
|
-
(
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
el("div", { className: "
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
2266
|
+
el("div", { className: "nwSection" },
|
|
2267
|
+
el("div", { className: "nwKickerRow" },
|
|
2268
|
+
el("div", { className: "nwKicker" }, t("panel.secStatus")),
|
|
2269
|
+
el("div", { className: "nwKickerRule" })
|
|
2270
|
+
),
|
|
2271
|
+
entry(t("panel.featuresTitle"), t("panel.featuresHint"), onFeatures, "features"),
|
|
2272
|
+
entry(t("panel.toolsTitle"), t("panel.toolsHint"), onTools, "tools"),
|
|
2273
|
+
// v3.2.0:原创模式(设定库)移到主面板
|
|
2274
|
+
entry(t("panel.creationTitle"), t("panel.creationHint"), null, "creation"),
|
|
2275
|
+
// v3.0.0:风格基线(六维 ±% 容差带)
|
|
2276
|
+
entry(t("panel.baselineTitle"), t("panel.baselineHint"), null, "baseline"),
|
|
2277
|
+
// v3.7.0:功能开关(情感深度/风格检测/语义增强)在二级「功能开关」页维护——主页不重复展示
|
|
2278
|
+
// v2.6.0:数据目录占用 + 语义引擎状态(一目了然)
|
|
2279
|
+
el("div", { className: "nwPillRow" },
|
|
2280
|
+
el("div", { className: "nwPill" },
|
|
2281
|
+
el("span", { className: "nwPillKey" }, t("dir.size")),
|
|
2282
|
+
el("span", { className: "nwPillVal" }, formatSize(state.dataDirSize))
|
|
1701
2283
|
),
|
|
1702
|
-
el("
|
|
1703
|
-
|
|
1704
|
-
el("span", { className: "
|
|
2284
|
+
el("div", { className: "nwPill" },
|
|
2285
|
+
el("span", { className: "nwPillKey" }, t("model.engine")),
|
|
2286
|
+
el("span", { className: "nwPillVal" }, engineStatusText(state.embeddingStatus, t))
|
|
1705
2287
|
)
|
|
1706
|
-
)
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
entry(t("panel.creationTitle"), t("panel.creationHint"), null, "creation"),
|
|
1712
|
-
// v3.0.0:风格基线(六维 ±% 容差带)
|
|
1713
|
-
entry(t("panel.baselineTitle"), t("panel.baselineHint"), null, "baseline"),
|
|
1714
|
-
// v3.7.0:功能开关(情感深度/风格检测/语义增强)在二级「功能开关」页维护——主页不重复展示
|
|
1715
|
-
// v2.6.0:数据目录占用 + 语义引擎状态(一目了然)
|
|
1716
|
-
el("div", { className: "nwRow nwRowOff" },
|
|
1717
|
-
el("div", { className: "nwRowText" },
|
|
1718
|
-
el("div", { className: "nwRowLabel" }, t("dir.size")),
|
|
1719
|
-
el("div", { className: "nwRowHint" }, formatSize(state.dataDirSize) + " · " + engineStatusText(state.embeddingStatus, t))
|
|
1720
|
-
)
|
|
2288
|
+
),
|
|
2289
|
+
pathBox(t("dir.data"), dirs.dataDir || state.dataDir || "", "data-dir"),
|
|
2290
|
+
// v4.3.0:state.file / dirs.stateFile 此前写了 4 处却从不读取——宿主 reveal 支持 state-file
|
|
2291
|
+
//(lib/core.js allowedTargets 含 "state-file"),这里补一行路径卡把它用起来
|
|
2292
|
+
pathBox(t("dir.stateFile"), dirs.stateFile || state.file || "", "state-file"),
|
|
1721
2293
|
),
|
|
1722
|
-
pathBox(t("dir.data"), dirs.dataDir || state.dataDir || "", "data-dir"),
|
|
1723
|
-
// v4.3.0:state.file / dirs.stateFile 此前写了 4 处却从不读取——宿主 reveal 支持 state-file
|
|
1724
|
-
//(lib/core.js allowedTargets 含 "state-file"),这里补一行路径卡把它用起来
|
|
1725
|
-
pathBox(t("dir.stateFile"), dirs.stateFile || state.file || "", "state-file"),
|
|
1726
2294
|
// v3.2.0:书库统计(写作打卡);null=未就绪不渲染,[]=真空提示
|
|
1727
|
-
el("div", { key: "statsCard", style: { marginTop: "10px", padding: "10px 12px"
|
|
1728
|
-
el("div", {
|
|
2295
|
+
el("div", { key: "statsCard", className: "nwBoxed", style: { marginTop: "10px", padding: "10px 12px" } },
|
|
2296
|
+
el("div", { className: "nwGroupName", style: { marginBottom: "6px" } }, "📚 " + t("stats.title")),
|
|
1729
2297
|
el("div", { style: { display: "flex", flexDirection: "column", gap: "5px" } },
|
|
1730
2298
|
state.booksStats === null
|
|
1731
|
-
? el("div", {
|
|
2299
|
+
? el("div", { className: "nwNote nwNoteWarn", }, t("stats.pending"))
|
|
1732
2300
|
: (state.booksStats || []).length === 0
|
|
1733
|
-
? el("div", {
|
|
2301
|
+
? el("div", { className: "nwNote", }, t("stats.empty"))
|
|
1734
2302
|
: (state.booksStats || []).slice(0, 6).map(function (bs) {
|
|
1735
2303
|
var charsText = fmtChars(bs.chars);
|
|
1736
|
-
return el("div", { key: bs.name,
|
|
1737
|
-
el("span", {
|
|
1738
|
-
el("span", {
|
|
2304
|
+
return el("div", { key: bs.name, className: "nwStatRow" },
|
|
2305
|
+
el("span", { className: "nwStatRow", }, "📕 " + bs.name),
|
|
2306
|
+
el("span", { className: "nwStatName", }, bs.chapters + " " + t("stats.chapters") + " · " + charsText + t("stats.chars")),
|
|
1739
2307
|
bs.recent7Chars > 0
|
|
1740
|
-
? el("span", {
|
|
1741
|
-
: el("span", {
|
|
2308
|
+
? el("span", { className: "nwNote nwNoteOk", }, "🔥 " + fmtChars(bs.recent7Chars) + " " + t("stats.week"))
|
|
2309
|
+
: el("span", { className: "nwNote nwNoteDim", }, t("stats.idle"))
|
|
1742
2310
|
);
|
|
1743
2311
|
})
|
|
1744
2312
|
)
|
|
1745
2313
|
),
|
|
1746
2314
|
// v3.2.0:报告历史入口
|
|
1747
|
-
el("button", { key: "reportsEntry", type: "button",
|
|
2315
|
+
el("button", { key: "reportsEntry", type: "button", className: "nwBoxed nwFileRow", style: { marginTop: "8px", padding: "9px 12px", textAlign: "left" }, onClick: function () {
|
|
1748
2316
|
props.controller.set({ reportsGroups: null, reportContent: null }, { silent: true });
|
|
1749
2317
|
// v4.3.0:超时 + 错误透传(reports.readFailDetail 已被具体错误取代,该词条随之删除)
|
|
1750
2318
|
fetchWithTimeout("/api/dsh-novel-writer/reports", { headers: { accept: "application/json" } }).then(function (r2) {
|
|
@@ -1760,12 +2328,12 @@ var TOOL_GROUPS = [
|
|
|
1760
2328
|
});
|
|
1761
2329
|
props.controller.openView("reports");
|
|
1762
2330
|
} },
|
|
1763
|
-
el("span", {
|
|
1764
|
-
el("span", {
|
|
1765
|
-
el("span", {
|
|
2331
|
+
el("span", { className: "nwRowLabel", style: { flex: "1" } }, "📊 " + t("reports.title")),
|
|
2332
|
+
el("span", { className: "nwNote", }, t("reports.hint")),
|
|
2333
|
+
el("span", { className: "nwNote nwChevron", }, "›")
|
|
1766
2334
|
),
|
|
1767
2335
|
// v3.2.0:体验演示
|
|
1768
|
-
el("div", { key: "demoCard",
|
|
2336
|
+
el("div", { key: "demoCard", className: "nwDashedNote", style: { marginTop: "10px" } },
|
|
1769
2337
|
el("button", { type: "button", disabled: state.demoLoading, style: { display: "flex", alignItems: "center", gap: "8px", width: "100%", background: "transparent", border: "none", padding: 0, cursor: state.demoLoading ? "default" : "pointer", textAlign: "left" }, onClick: function () {
|
|
1770
2338
|
if (state.demoLoading) return;
|
|
1771
2339
|
props.controller.set({ demoLoading: true }, { silent: true });
|
|
@@ -1783,10 +2351,10 @@ var TOOL_GROUPS = [
|
|
|
1783
2351
|
props.controller.set({ demoLoading: false }, { silent: true });
|
|
1784
2352
|
});
|
|
1785
2353
|
} },
|
|
1786
|
-
el("span", {
|
|
1787
|
-
el("span", {
|
|
2354
|
+
el("span", { className: "nwAccentStrong", }, state.demoLoading ? t("demo.loading") : t("demo.run")),
|
|
2355
|
+
el("span", { className: "nwNote", }, t("demo.hint"))
|
|
1788
2356
|
),
|
|
1789
|
-
state.demoReport ? el("pre", {
|
|
2357
|
+
state.demoReport ? el("pre", { className: "nwBoxed nwReportPre", style: { margin: "8px 0 0", maxHeight: "260px", overflow: "auto" } }, state.demoReport) : null
|
|
1790
2358
|
)
|
|
1791
2359
|
);
|
|
1792
2360
|
}
|
|
@@ -1823,9 +2391,12 @@ var TOOL_GROUPS = [
|
|
|
1823
2391
|
// v5.2.0:作为官方右栏 tab 时不画关闭按钮——关闭由宿主 tab chip 提供
|
|
1824
2392
|
typeof props.onClose === "function" ? el("button", { type: "button", className: "nwClose", "aria-label": t("panel.close"), onClick: props.onClose }, "×") : null
|
|
1825
2393
|
),
|
|
1826
|
-
el("div", { className: "
|
|
1827
|
-
el("
|
|
1828
|
-
|
|
2394
|
+
el("div", { className: "nwHero" },
|
|
2395
|
+
el("div", { className: "nwBanner " + (on ? "nwBannerOn" : "nwBannerOff") },
|
|
2396
|
+
el("span", { className: "nwBannerIcon" }, on ? "✔" : "✘"),
|
|
2397
|
+
el("span", null, on ? t("banner.on") : t("banner.off"))
|
|
2398
|
+
),
|
|
2399
|
+
el("div", { className: "nwHeroDesc" }, t("panel.heroDesc")),
|
|
1829
2400
|
),
|
|
1830
2401
|
loadingHint,
|
|
1831
2402
|
msg,
|
|
@@ -1844,43 +2415,17 @@ var TOOL_GROUPS = [
|
|
|
1844
2415
|
var statusKey = state.enabled ? (state.autoAnalyze ? "card.status" : "card.statusAutoOff") : "card.statusOff";
|
|
1845
2416
|
return react.createElement(
|
|
1846
2417
|
"div",
|
|
1847
|
-
{
|
|
1848
|
-
react.createElement("div", {
|
|
1849
|
-
react.createElement("div", {
|
|
2418
|
+
{ className: "nwSettingsCard" },
|
|
2419
|
+
react.createElement("div", { className: "nwSettingsCardTitle" }, t("card.title")),
|
|
2420
|
+
react.createElement("div", { className: "nwMuted", style: { margin: "4px 0 8px" } }, t("card.desc")),
|
|
1850
2421
|
react.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, marginTop: 4 } },
|
|
1851
|
-
react.createElement(
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
fontSize: 12, fontWeight: 700, lineHeight: 1,
|
|
1857
|
-
padding: "4px 10px", borderRadius: 999,
|
|
1858
|
-
background: state.enabled ? "rgba(34,197,94,.14)" : "rgba(239,68,68,.10)",
|
|
1859
|
-
color: state.enabled ? "#15803d" : "#b91c1c",
|
|
1860
|
-
border: "1px solid " + (state.enabled ? "#22c55e" : "#ef4444")
|
|
1861
|
-
}
|
|
1862
|
-
},
|
|
1863
|
-
react.createElement("span", null, state.enabled ? "●" : "○"),
|
|
1864
|
-
react.createElement("span", null, t(statusKey))
|
|
1865
|
-
),
|
|
1866
|
-
react.createElement(
|
|
1867
|
-
"button",
|
|
1868
|
-
{
|
|
1869
|
-
type: "button",
|
|
1870
|
-
style: {
|
|
1871
|
-
appearance: "none", font: "inherit", cursor: "pointer",
|
|
1872
|
-
border: "1px solid var(--dsw-alias-border-l2, #d1d5db)", borderRadius: 8,
|
|
1873
|
-
background: "var(--dsw-alias-bg-layer-3, #fff)", color: "inherit",
|
|
1874
|
-
padding: "5px 12px", fontSize: 12
|
|
1875
|
-
},
|
|
1876
|
-
onClick: function () {
|
|
1877
|
-
if (typeof props.onOpenPanel === "function") props.onOpenPanel();
|
|
1878
|
-
}
|
|
1879
|
-
},
|
|
1880
|
-
t("card.open")
|
|
1881
|
-
)
|
|
2422
|
+
react.createElement(NW_UI.Tag, { tone: state.enabled ? "success" : "danger" }, t(statusKey)),
|
|
2423
|
+
react.createElement(NW_UI.Button, {
|
|
2424
|
+
variant: "outline", size: "sm",
|
|
2425
|
+
onClick: function () { if (typeof props.onOpenPanel === "function") props.onOpenPanel(); }
|
|
2426
|
+
}, t("card.open"))
|
|
1882
2427
|
),
|
|
1883
|
-
react.createElement("div", {
|
|
2428
|
+
react.createElement("div", { className: "nwMuted", style: { marginTop: 8 } }, t("card.hint"))
|
|
1884
2429
|
);
|
|
1885
2430
|
}
|
|
1886
2431
|
function mountPanel(controller, toggle) {
|