@rezti/dsh-rez-suite 0.1.4 → 0.1.5
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/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.d.ts +19 -152
- package/lib/client.js +156 -307
- package/lib/index.js +1 -1
- package/lib/style.css +82 -111
- package/package.json +8 -6
- package/src/client/index.ts +33 -21
- package/src/client/locales.ts +4 -0
- package/src/client/panel/AuditTab.tsx +6 -6
- package/src/client/panel/panel.module.css +89 -118
- package/src/client/settings-card.tsx +68 -0
- package/src/index.ts +4 -4
- package/src/client/mount.tsx +0 -97
- package/src/client/panel/RezPanel.tsx +0 -53
- package/src/client/panel/controller.ts +0 -42
- package/src/client/sidebar-entry.ts +0 -80
package/lib/client.js
CHANGED
|
@@ -4,82 +4,10 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
(function(){var id="dsh-rez-suite-css";if(typeof document==="undefined"||document.getElementById(id))return;var s=document.createElement("style");s.id=id;s.textContent=".WRGRRW_shell {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n display: flex;\n}\n\n.WRGRRW_card {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n}\n\n.WRGRRW_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.WRGRRW_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.WRGRRW_header {\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n\n.WRGRRW_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.WRGRRW_headText {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n.WRGRRW_name {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n.WRGRRW_description {\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.WRGRRW_chevron {\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n transition: transform .16s;\n}\n\n.WRGRRW_chevronOpen {\n transform: rotate(180deg);\n}\n\n.WRGRRW_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px 12px;\n padding-top: 8px;\n}\n\n.WRGRRW_tabBar {\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n flex: none;\n gap: 2px;\n display: flex;\n}\n\n.WRGRRW_tab {\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n border-radius: 6px 6px 0 0;\n padding: 7px 14px;\n font-size: 13px;\n}\n\n.WRGRRW_tab:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.WRGRRW_tab[data-active] {\n color: var(--dsw-alias-label-primary);\n border-bottom-color: var(--dsw-alias-state-business-primary);\n font-weight: 600;\n}\n\n.WRGRRW_tabBody {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n padding: 12px 0 4px;\n display: flex;\n}\n\n.WRGRRW_section {\n border: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-alias-bg-layer-1, var(--dsw-alias-bg-base));\n border-radius: 10px;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n display: flex;\n}\n\n.WRGRRW_sectionTitle {\n color: var(--dsw-alias-label-primary);\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n.WRGRRW_field {\n flex-direction: column;\n align-items: stretch;\n gap: 4px;\n display: flex;\n}\n\n.WRGRRW_label {\n color: var(--dsw-alias-label-secondary);\n font-size: 12.5px;\n}\n\n.WRGRRW_input, .WRGRRW_select {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n outline: none;\n padding: 6px 8px;\n font-size: 13px;\n}\n\n.WRGRRW_checkbox {\n justify-self: start;\n width: 15px;\n height: 15px;\n}\n\n.WRGRRW_toolbar {\n flex-wrap: wrap;\n flex: none;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.WRGRRW_button {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n border-radius: 8px;\n padding: 7px 12px;\n font-size: 13px;\n}\n\n.WRGRRW_button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.WRGRRW_button:disabled {\n opacity: .4;\n cursor: default;\n}\n\n.WRGRRW_primaryButton {\n background: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n.WRGRRW_dangerButton {\n background: var(--dsw-alias-state-danger, #c62828);\n border-color: var(--dsw-alias-state-danger, #c62828);\n color: #fff;\n}\n\n.WRGRRW_qr {\n background: #fff;\n border-radius: 8px;\n width: 200px;\n height: 200px;\n margin: 8px 0;\n display: block;\n}\n\n.WRGRRW_message {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 12.5px;\n line-height: 1.5;\n}\n\n.WRGRRW_error {\n color: var(--dsw-alias-state-danger, #c62828);\n}\n\n.WRGRRW_tableWrap {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n overflow: auto;\n}\n\n.WRGRRW_table {\n border-collapse: collapse;\n width: 100%;\n font-size: 12.5px;\n}\n\n.WRGRRW_table th {\n z-index: 1;\n text-align: left;\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n padding: 8px 10px;\n position: sticky;\n top: 0;\n}\n\n.WRGRRW_table td {\n border-top: 1px solid var(--dsw-alias-border-l1);\n vertical-align: top;\n padding: 8px 10px;\n}\n\n.WRGRRW_badge {\n border-radius: 999px;\n padding: 2px 8px;\n font-size: 11px;\n display: inline-block;\n}\n\n.WRGRRW_badgeOk {\n color: #229a55;\n background: #229a5524;\n}\n\n.WRGRRW_badgeFail {\n color: #c62828;\n background: #c6282824;\n}\n\n.WRGRRW_cards {\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\n gap: 8px;\n display: grid;\n}\n\n.WRGRRW_stat {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n padding: 10px;\n}\n\n.WRGRRW_cardLabel {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.WRGRRW_cardValue {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n}\n";document.head.appendChild(s);})();
|
|
7
8
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
8
|
-
let react_dom_client = require("react-dom/client");
|
|
9
9
|
let react = require("react");
|
|
10
10
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
|
-
//#region src/protocol.ts
|
|
12
|
-
const REZ_API = {
|
|
13
|
-
config: "/api/dsh-rez-suite/config",
|
|
14
|
-
test: "/api/dsh-rez-suite/test",
|
|
15
|
-
status: "/api/dsh-rez-suite/status",
|
|
16
|
-
audit: "/api/dsh-rez-suite/audit",
|
|
17
|
-
auditReset: "/api/dsh-rez-suite/audit/reset",
|
|
18
|
-
weixin: "/api/dsh-rez-suite/weixin",
|
|
19
|
-
weixinVerify: "/api/dsh-rez-suite/weixin/verify"
|
|
20
|
-
};
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/client/api.ts
|
|
23
|
-
/**
|
|
24
|
-
* Browser-side API client for /api/dsh-rez-suite. Plain same-origin fetch.
|
|
25
|
-
*/
|
|
26
|
-
var RezApiError = class extends Error {
|
|
27
|
-
constructor(message) {
|
|
28
|
-
super(message);
|
|
29
|
-
this.name = "RezApiError";
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
async function readJson(response) {
|
|
33
|
-
let body;
|
|
34
|
-
try {
|
|
35
|
-
body = await response.json();
|
|
36
|
-
} catch {
|
|
37
|
-
throw new RezApiError("HTTP " + response.status + ": invalid JSON response");
|
|
38
|
-
}
|
|
39
|
-
if (!response.ok) throw new RezApiError(typeof body === "object" && body !== null && typeof body.error === "string" ? body.error : "HTTP " + response.status);
|
|
40
|
-
return body;
|
|
41
|
-
}
|
|
42
|
-
var RezApi = class {
|
|
43
|
-
async getConfig() {
|
|
44
|
-
return (await readJson(await fetch(REZ_API.config))).config;
|
|
45
|
-
}
|
|
46
|
-
async saveConfig(patch) {
|
|
47
|
-
return (await readJson(await fetch(REZ_API.config, {
|
|
48
|
-
method: "PUT",
|
|
49
|
-
headers: { "content-type": "application/json" },
|
|
50
|
-
body: JSON.stringify(patch)
|
|
51
|
-
}))).config;
|
|
52
|
-
}
|
|
53
|
-
async test() {
|
|
54
|
-
return (await readJson(await fetch(REZ_API.test, { method: "POST" }))).results;
|
|
55
|
-
}
|
|
56
|
-
async status() {
|
|
57
|
-
return readJson(await fetch(REZ_API.status));
|
|
58
|
-
}
|
|
59
|
-
async audit() {
|
|
60
|
-
return (await readJson(await fetch(REZ_API.audit))).audit;
|
|
61
|
-
}
|
|
62
|
-
async resetAudit() {
|
|
63
|
-
await readJson(await fetch(REZ_API.auditReset, { method: "POST" }));
|
|
64
|
-
}
|
|
65
|
-
async weixinStatus() {
|
|
66
|
-
return readJson(await fetch(REZ_API.weixin));
|
|
67
|
-
}
|
|
68
|
-
async weixinLogin() {
|
|
69
|
-
return readJson(await fetch(REZ_API.weixin, { method: "POST" }));
|
|
70
|
-
}
|
|
71
|
-
async weixinVerify(code) {
|
|
72
|
-
return readJson(await fetch(REZ_API.weixinVerify, {
|
|
73
|
-
method: "POST",
|
|
74
|
-
headers: { "content-type": "application/json" },
|
|
75
|
-
body: JSON.stringify({ code })
|
|
76
|
-
}));
|
|
77
|
-
}
|
|
78
|
-
async weixinLogout() {
|
|
79
|
-
return readJson(await fetch(REZ_API.weixin, { method: "DELETE" }));
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
//#endregion
|
|
83
11
|
//#region src/client/locales.ts
|
|
84
12
|
/**
|
|
85
13
|
* dsh-rez-suite surface copy: zh is the key source, en mirrors every key.
|
|
@@ -87,6 +15,8 @@ var RezApi = class {
|
|
|
87
15
|
const zh = {
|
|
88
16
|
"entry.label": "Rez",
|
|
89
17
|
"entry.tooltip": "Rez Suite 配置与审计面板",
|
|
18
|
+
"settings.title": "ReZ-TI",
|
|
19
|
+
"settings.description": "公司 MCP(Odoo / Nextcloud / 企微 / HA)与个人微信扫码通道。",
|
|
90
20
|
"panel.title": "Rez Suite",
|
|
91
21
|
"tab.config": "配置",
|
|
92
22
|
"tab.weixin": "微信",
|
|
@@ -174,6 +104,8 @@ const zh = {
|
|
|
174
104
|
const en = {
|
|
175
105
|
"entry.label": "Rez",
|
|
176
106
|
"entry.tooltip": "Rez Suite configuration and audit panel",
|
|
107
|
+
"settings.title": "ReZ-TI",
|
|
108
|
+
"settings.description": "Company MCP (Odoo / Nextcloud / WeCom / HA) and personal WeChat scan-and-chat.",
|
|
177
109
|
"panel.title": "Rez Suite",
|
|
178
110
|
"tab.config": "Config",
|
|
179
111
|
"tab.weixin": "WeChat",
|
|
@@ -265,6 +197,78 @@ function t(dict, key, values) {
|
|
|
265
197
|
return text;
|
|
266
198
|
}
|
|
267
199
|
//#endregion
|
|
200
|
+
//#region src/protocol.ts
|
|
201
|
+
const REZ_API = {
|
|
202
|
+
config: "/api/dsh-rez-suite/config",
|
|
203
|
+
test: "/api/dsh-rez-suite/test",
|
|
204
|
+
status: "/api/dsh-rez-suite/status",
|
|
205
|
+
audit: "/api/dsh-rez-suite/audit",
|
|
206
|
+
auditReset: "/api/dsh-rez-suite/audit/reset",
|
|
207
|
+
weixin: "/api/dsh-rez-suite/weixin",
|
|
208
|
+
weixinVerify: "/api/dsh-rez-suite/weixin/verify"
|
|
209
|
+
};
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/client/api.ts
|
|
212
|
+
/**
|
|
213
|
+
* Browser-side API client for /api/dsh-rez-suite. Plain same-origin fetch.
|
|
214
|
+
*/
|
|
215
|
+
var RezApiError = class extends Error {
|
|
216
|
+
constructor(message) {
|
|
217
|
+
super(message);
|
|
218
|
+
this.name = "RezApiError";
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
async function readJson(response) {
|
|
222
|
+
let body;
|
|
223
|
+
try {
|
|
224
|
+
body = await response.json();
|
|
225
|
+
} catch {
|
|
226
|
+
throw new RezApiError("HTTP " + response.status + ": invalid JSON response");
|
|
227
|
+
}
|
|
228
|
+
if (!response.ok) throw new RezApiError(typeof body === "object" && body !== null && typeof body.error === "string" ? body.error : "HTTP " + response.status);
|
|
229
|
+
return body;
|
|
230
|
+
}
|
|
231
|
+
var RezApi = class {
|
|
232
|
+
async getConfig() {
|
|
233
|
+
return (await readJson(await fetch(REZ_API.config))).config;
|
|
234
|
+
}
|
|
235
|
+
async saveConfig(patch) {
|
|
236
|
+
return (await readJson(await fetch(REZ_API.config, {
|
|
237
|
+
method: "PUT",
|
|
238
|
+
headers: { "content-type": "application/json" },
|
|
239
|
+
body: JSON.stringify(patch)
|
|
240
|
+
}))).config;
|
|
241
|
+
}
|
|
242
|
+
async test() {
|
|
243
|
+
return (await readJson(await fetch(REZ_API.test, { method: "POST" }))).results;
|
|
244
|
+
}
|
|
245
|
+
async status() {
|
|
246
|
+
return readJson(await fetch(REZ_API.status));
|
|
247
|
+
}
|
|
248
|
+
async audit() {
|
|
249
|
+
return (await readJson(await fetch(REZ_API.audit))).audit;
|
|
250
|
+
}
|
|
251
|
+
async resetAudit() {
|
|
252
|
+
await readJson(await fetch(REZ_API.auditReset, { method: "POST" }));
|
|
253
|
+
}
|
|
254
|
+
async weixinStatus() {
|
|
255
|
+
return readJson(await fetch(REZ_API.weixin));
|
|
256
|
+
}
|
|
257
|
+
async weixinLogin() {
|
|
258
|
+
return readJson(await fetch(REZ_API.weixin, { method: "POST" }));
|
|
259
|
+
}
|
|
260
|
+
async weixinVerify(code) {
|
|
261
|
+
return readJson(await fetch(REZ_API.weixinVerify, {
|
|
262
|
+
method: "POST",
|
|
263
|
+
headers: { "content-type": "application/json" },
|
|
264
|
+
body: JSON.stringify({ code })
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
async weixinLogout() {
|
|
268
|
+
return readJson(await fetch(REZ_API.weixin, { method: "DELETE" }));
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
//#endregion
|
|
268
272
|
//#region src/client/panel/helpers.ts
|
|
269
273
|
/**
|
|
270
274
|
* Shared panel helpers: active-language dictionary pick and error extraction.
|
|
@@ -285,38 +289,39 @@ var panel_module_default = {
|
|
|
285
289
|
"badge": "WRGRRW_badge",
|
|
286
290
|
"badgeFail": "WRGRRW_badgeFail",
|
|
287
291
|
"badgeOk": "WRGRRW_badgeOk",
|
|
292
|
+
"body": "WRGRRW_body",
|
|
288
293
|
"button": "WRGRRW_button",
|
|
289
294
|
"card": "WRGRRW_card",
|
|
290
295
|
"cardLabel": "WRGRRW_cardLabel",
|
|
296
|
+
"cardOpen": "WRGRRW_cardOpen",
|
|
291
297
|
"cards": "WRGRRW_cards",
|
|
292
298
|
"cardValue": "WRGRRW_cardValue",
|
|
293
299
|
"checkbox": "WRGRRW_checkbox",
|
|
300
|
+
"chevron": "WRGRRW_chevron",
|
|
301
|
+
"chevronOpen": "WRGRRW_chevronOpen",
|
|
294
302
|
"dangerButton": "WRGRRW_dangerButton",
|
|
295
|
-
"
|
|
296
|
-
"entryIcon": "WRGRRW_entryIcon",
|
|
297
|
-
"entryLabel": "WRGRRW_entryLabel",
|
|
303
|
+
"description": "WRGRRW_description",
|
|
298
304
|
"error": "WRGRRW_error",
|
|
299
305
|
"field": "WRGRRW_field",
|
|
300
|
-
"
|
|
306
|
+
"header": "WRGRRW_header",
|
|
307
|
+
"headText": "WRGRRW_headText",
|
|
301
308
|
"input": "WRGRRW_input",
|
|
302
309
|
"label": "WRGRRW_label",
|
|
303
310
|
"message": "WRGRRW_message",
|
|
304
|
-
"
|
|
305
|
-
"panelContent": "WRGRRW_panelContent",
|
|
306
|
-
"panelHeader": "WRGRRW_panelHeader",
|
|
307
|
-
"panelTitle": "WRGRRW_panelTitle",
|
|
311
|
+
"name": "WRGRRW_name",
|
|
308
312
|
"primaryButton": "WRGRRW_primaryButton",
|
|
309
313
|
"qr": "WRGRRW_qr",
|
|
310
314
|
"section": "WRGRRW_section",
|
|
311
315
|
"sectionTitle": "WRGRRW_sectionTitle",
|
|
312
316
|
"select": "WRGRRW_select",
|
|
317
|
+
"shell": "WRGRRW_shell",
|
|
318
|
+
"stat": "WRGRRW_stat",
|
|
313
319
|
"tab": "WRGRRW_tab",
|
|
314
320
|
"tabBar": "WRGRRW_tabBar",
|
|
315
321
|
"tabBody": "WRGRRW_tabBody",
|
|
316
322
|
"table": "WRGRRW_table",
|
|
317
323
|
"tableWrap": "WRGRRW_tableWrap",
|
|
318
|
-
"toolbar": "WRGRRW_toolbar"
|
|
319
|
-
"view": "WRGRRW_view"
|
|
324
|
+
"toolbar": "WRGRRW_toolbar"
|
|
320
325
|
};
|
|
321
326
|
//#endregion
|
|
322
327
|
//#region src/client/panel/AuditTab.tsx
|
|
@@ -387,7 +392,7 @@ function AuditTab({ api }) {
|
|
|
387
392
|
className: panel_module_default.cards,
|
|
388
393
|
children: [
|
|
389
394
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
390
|
-
className: panel_module_default.
|
|
395
|
+
className: panel_module_default.stat,
|
|
391
396
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
392
397
|
className: panel_module_default.cardLabel,
|
|
393
398
|
children: tt("audit.totalCalls")
|
|
@@ -397,7 +402,7 @@ function AuditTab({ api }) {
|
|
|
397
402
|
})]
|
|
398
403
|
}),
|
|
399
404
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
400
|
-
className: panel_module_default.
|
|
405
|
+
className: panel_module_default.stat,
|
|
401
406
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
402
407
|
className: panel_module_default.cardLabel,
|
|
403
408
|
children: tt("audit.inputTokens")
|
|
@@ -407,7 +412,7 @@ function AuditTab({ api }) {
|
|
|
407
412
|
})]
|
|
408
413
|
}),
|
|
409
414
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
410
|
-
className: panel_module_default.
|
|
415
|
+
className: panel_module_default.stat,
|
|
411
416
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
412
417
|
className: panel_module_default.cardLabel,
|
|
413
418
|
children: tt("audit.outputTokens")
|
|
@@ -417,7 +422,7 @@ function AuditTab({ api }) {
|
|
|
417
422
|
})]
|
|
418
423
|
}),
|
|
419
424
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
420
|
-
className: panel_module_default.
|
|
425
|
+
className: panel_module_default.stat,
|
|
421
426
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
422
427
|
className: panel_module_default.cardLabel,
|
|
423
428
|
children: tt("audit.totalCost")
|
|
@@ -427,7 +432,7 @@ function AuditTab({ api }) {
|
|
|
427
432
|
})]
|
|
428
433
|
}),
|
|
429
434
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
430
|
-
className: panel_module_default.
|
|
435
|
+
className: panel_module_default.stat,
|
|
431
436
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
432
437
|
className: panel_module_default.cardLabel,
|
|
433
438
|
children: tt("audit.monthCost")
|
|
@@ -437,7 +442,7 @@ function AuditTab({ api }) {
|
|
|
437
442
|
})]
|
|
438
443
|
}),
|
|
439
444
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
440
|
-
className: panel_module_default.
|
|
445
|
+
className: panel_module_default.stat,
|
|
441
446
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
442
447
|
className: panel_module_default.cardLabel,
|
|
443
448
|
children: tt("audit.budget")
|
|
@@ -1090,9 +1095,10 @@ function WeixinTab({ api }) {
|
|
|
1090
1095
|
});
|
|
1091
1096
|
}
|
|
1092
1097
|
//#endregion
|
|
1093
|
-
//#region src/client/
|
|
1098
|
+
//#region src/client/settings-card.tsx
|
|
1094
1099
|
/**
|
|
1095
|
-
*
|
|
1100
|
+
* ReZ settings pages: one accordion card in 设置 → 插件 → 插件配置,
|
|
1101
|
+
* plus a dedicated Plugins tab for the same content.
|
|
1096
1102
|
*/
|
|
1097
1103
|
const TABS = [
|
|
1098
1104
|
{
|
|
@@ -1112,27 +1118,12 @@ const TABS = [
|
|
|
1112
1118
|
label: () => tt("tab.audit")
|
|
1113
1119
|
}
|
|
1114
1120
|
];
|
|
1115
|
-
function
|
|
1121
|
+
function RezSettingsPage() {
|
|
1122
|
+
const api = (0, react.useMemo)(() => new RezApi(), []);
|
|
1116
1123
|
const [activeTab, setActiveTab] = (0, react.useState)("config");
|
|
1117
1124
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1118
|
-
className: panel_module_default.
|
|
1125
|
+
className: panel_module_default.shell,
|
|
1119
1126
|
children: [
|
|
1120
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1121
|
-
className: panel_module_default.panelHeader,
|
|
1122
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1123
|
-
className: panel_module_default.panelTitle,
|
|
1124
|
-
children: tt("panel.title")
|
|
1125
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1126
|
-
type: "button",
|
|
1127
|
-
className: panel_module_default.iconButton,
|
|
1128
|
-
title: tt("common.close"),
|
|
1129
|
-
"aria-label": tt("common.close"),
|
|
1130
|
-
onClick: () => {
|
|
1131
|
-
controller.close();
|
|
1132
|
-
},
|
|
1133
|
-
children: "x"
|
|
1134
|
-
})]
|
|
1135
|
-
}),
|
|
1136
1127
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1137
1128
|
className: panel_module_default.tabBar,
|
|
1138
1129
|
role: "tablist",
|
|
@@ -1148,218 +1139,76 @@ function RezPanel({ controller, api }) {
|
|
|
1148
1139
|
children: tab.label()
|
|
1149
1140
|
}, tab.id))
|
|
1150
1141
|
}),
|
|
1151
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
activeTab === "weixin" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WeixinTab, { api }),
|
|
1156
|
-
activeTab === "status" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusTab, { api }),
|
|
1157
|
-
activeTab === "audit" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AuditTab, { api })
|
|
1158
|
-
]
|
|
1159
|
-
})
|
|
1142
|
+
activeTab === "config" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigTab, { api }),
|
|
1143
|
+
activeTab === "weixin" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WeixinTab, { api }),
|
|
1144
|
+
activeTab === "status" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusTab, { api }),
|
|
1145
|
+
activeTab === "audit" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AuditTab, { api })
|
|
1160
1146
|
]
|
|
1161
1147
|
});
|
|
1162
1148
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
const waitObserver = new MutationObserver(() => {
|
|
1202
|
-
ensure();
|
|
1203
|
-
});
|
|
1204
|
-
waitObserver.observe(document.body, {
|
|
1205
|
-
childList: true,
|
|
1206
|
-
subtree: true
|
|
1207
|
-
});
|
|
1208
|
-
const retryTimer = window.setInterval(() => {
|
|
1209
|
-
ensure();
|
|
1210
|
-
if (container?.isConnected === true) window.clearInterval(retryTimer);
|
|
1211
|
-
}, 250);
|
|
1212
|
-
const applyActive = () => {
|
|
1213
|
-
if (controller.getSnapshot().panelOpen) {
|
|
1214
|
-
for (const attr of OTHER_ACTIVE_ATTRS) document.documentElement.removeAttribute(attr);
|
|
1215
|
-
document.documentElement.setAttribute(ACTIVE_ATTR, "");
|
|
1216
|
-
document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: PANEL_NAME }));
|
|
1217
|
-
} else document.documentElement.removeAttribute(ACTIVE_ATTR);
|
|
1218
|
-
};
|
|
1219
|
-
const onOtherActivate = (event) => {
|
|
1220
|
-
const detail = event.detail;
|
|
1221
|
-
if ((detail === "taskboard" || detail === "ssh") && controller.getSnapshot().panelOpen) controller.close();
|
|
1222
|
-
};
|
|
1223
|
-
const SIDEBAR_ROW_SELECTOR = "[class*=\"sessionRow\"], [class*=\"projectRow\"], [class*=\"searchResultRow\"], [class*=\"searchResultWorkspace\"], [class*=\"newSession\"]";
|
|
1224
|
-
const onClickSidebarRow = (event) => {
|
|
1225
|
-
if (!controller.getSnapshot().panelOpen) return;
|
|
1226
|
-
const target = event.target;
|
|
1227
|
-
if (target === null) return;
|
|
1228
|
-
if (target.closest(SIDEBAR_ROW_SELECTOR) !== null) controller.close();
|
|
1229
|
-
};
|
|
1230
|
-
document.addEventListener("click", onClickSidebarRow, true);
|
|
1231
|
-
document.addEventListener(ACTIVATE_EVENT, onOtherActivate);
|
|
1232
|
-
const unsubscribe = controller.subscribe(applyActive);
|
|
1233
|
-
applyActive();
|
|
1234
|
-
ensure();
|
|
1235
|
-
return () => {
|
|
1236
|
-
window.clearInterval(retryTimer);
|
|
1237
|
-
document.removeEventListener("click", onClickSidebarRow, true);
|
|
1238
|
-
document.removeEventListener(ACTIVATE_EVENT, onOtherActivate);
|
|
1239
|
-
waitObserver.disconnect();
|
|
1240
|
-
unsubscribe();
|
|
1241
|
-
document.documentElement.removeAttribute(ACTIVE_ATTR);
|
|
1242
|
-
root?.unmount();
|
|
1243
|
-
root = void 0;
|
|
1244
|
-
container?.remove();
|
|
1245
|
-
container = void 0;
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
//#endregion
|
|
1249
|
-
//#region src/client/panel/controller.ts
|
|
1250
|
-
var PanelController = class {
|
|
1251
|
-
panelOpen = false;
|
|
1252
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1253
|
-
getSnapshot() {
|
|
1254
|
-
return { panelOpen: this.panelOpen };
|
|
1255
|
-
}
|
|
1256
|
-
subscribe(fn) {
|
|
1257
|
-
this.listeners.add(fn);
|
|
1258
|
-
return () => {
|
|
1259
|
-
this.listeners.delete(fn);
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
open() {
|
|
1263
|
-
if (this.panelOpen) return;
|
|
1264
|
-
this.panelOpen = true;
|
|
1265
|
-
this.notify();
|
|
1266
|
-
}
|
|
1267
|
-
close() {
|
|
1268
|
-
if (!this.panelOpen) return;
|
|
1269
|
-
this.panelOpen = false;
|
|
1270
|
-
this.notify();
|
|
1271
|
-
}
|
|
1272
|
-
toggle() {
|
|
1273
|
-
if (this.panelOpen) this.close();
|
|
1274
|
-
else this.open();
|
|
1275
|
-
}
|
|
1276
|
-
notify() {
|
|
1277
|
-
for (const fn of [...this.listeners]) fn();
|
|
1278
|
-
}
|
|
1279
|
-
};
|
|
1280
|
-
//#endregion
|
|
1281
|
-
//#region src/client/sidebar-entry.ts
|
|
1282
|
-
function sidebarRoot() {
|
|
1283
|
-
const column = document.querySelector("[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]");
|
|
1284
|
-
if (column === null) return void 0;
|
|
1285
|
-
return column.querySelector("[class*=\"logoRow\"]")?.parentElement ?? column.firstElementChild;
|
|
1286
|
-
}
|
|
1287
|
-
function newSessionButton(root) {
|
|
1288
|
-
const nested = root.querySelector("button[class*=\"newSession\"]");
|
|
1289
|
-
if (nested !== null) return nested;
|
|
1290
|
-
for (const child of root.children) if (child.tagName === "BUTTON") return child;
|
|
1291
|
-
}
|
|
1292
|
-
function createEntry(controller) {
|
|
1293
|
-
const entry = document.createElement("button");
|
|
1294
|
-
entry.type = "button";
|
|
1295
|
-
entry.dataset.dshRezEntry = "";
|
|
1296
|
-
entry.className = panel_module_default.entry;
|
|
1297
|
-
entry.setAttribute("aria-label", tt("entry.label"));
|
|
1298
|
-
entry.setAttribute("title", tt("entry.tooltip"));
|
|
1299
|
-
entry.innerHTML = "<span class=\"" + panel_module_default.entryIcon + "\"><svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2.5\" y=\"2.5\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 8l2 2 4-4\"/></svg></span><span class=\"" + panel_module_default.entryLabel + "\">" + tt("entry.label") + "</span>";
|
|
1300
|
-
entry.addEventListener("click", () => {
|
|
1301
|
-
controller.toggle();
|
|
1302
|
-
});
|
|
1303
|
-
return entry;
|
|
1304
|
-
}
|
|
1305
|
-
function placeEntry(root, entry) {
|
|
1306
|
-
const button = newSessionButton(root);
|
|
1307
|
-
if (button === void 0) return false;
|
|
1308
|
-
if (entry.parentElement !== root) {
|
|
1309
|
-
const row = button.closest("[class*=\"logoRow\"]");
|
|
1310
|
-
const base = row !== null && row.parentElement === root ? row : button;
|
|
1311
|
-
const family = Array.from(root.children).filter((el) => el instanceof HTMLElement && el.matches("[data-dsh-taskboard-entry], [data-dsh-ssh-entry], [data-dsh-rez-entry]"));
|
|
1312
|
-
const anchor = family.length > 0 ? family[family.length - 1].nextElementSibling : base.nextElementSibling;
|
|
1313
|
-
root.insertBefore(entry, anchor);
|
|
1314
|
-
}
|
|
1315
|
-
return true;
|
|
1316
|
-
}
|
|
1317
|
-
function mountSidebarEntry(controller) {
|
|
1318
|
-
const entry = createEntry(controller);
|
|
1319
|
-
let root;
|
|
1320
|
-
let placed = false;
|
|
1321
|
-
const place = () => {
|
|
1322
|
-
const next = sidebarRoot();
|
|
1323
|
-
if (next === void 0) return;
|
|
1324
|
-
if (root !== void 0 && root !== next) {
|
|
1325
|
-
if (entry.parentElement === root) entry.remove();
|
|
1326
|
-
placed = false;
|
|
1327
|
-
}
|
|
1328
|
-
root = next;
|
|
1329
|
-
if (!placed) placed = placeEntry(root, entry);
|
|
1330
|
-
};
|
|
1331
|
-
const observer = new MutationObserver(place);
|
|
1332
|
-
observer.observe(document.body, {
|
|
1333
|
-
childList: true,
|
|
1334
|
-
subtree: true
|
|
1149
|
+
function RezPluginCard() {
|
|
1150
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1151
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1152
|
+
className: panel_module_default.card + (open ? " " + panel_module_default.cardOpen : ""),
|
|
1153
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1154
|
+
type: "button",
|
|
1155
|
+
className: panel_module_default.header,
|
|
1156
|
+
onClick: () => {
|
|
1157
|
+
setOpen(!open);
|
|
1158
|
+
},
|
|
1159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1160
|
+
className: panel_module_default.headText,
|
|
1161
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1162
|
+
className: panel_module_default.name,
|
|
1163
|
+
children: tt("settings.title")
|
|
1164
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1165
|
+
className: panel_module_default.description,
|
|
1166
|
+
children: tt("settings.description")
|
|
1167
|
+
})]
|
|
1168
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1169
|
+
className: panel_module_default.chevron + (open ? " " + panel_module_default.chevronOpen : ""),
|
|
1170
|
+
viewBox: "0 0 14 14",
|
|
1171
|
+
width: "14",
|
|
1172
|
+
height: "14",
|
|
1173
|
+
"aria-hidden": "true",
|
|
1174
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1175
|
+
d: "M3 5l4 4 4-4",
|
|
1176
|
+
fill: "none",
|
|
1177
|
+
stroke: "currentColor",
|
|
1178
|
+
strokeWidth: "1.4",
|
|
1179
|
+
strokeLinecap: "round",
|
|
1180
|
+
strokeLinejoin: "round"
|
|
1181
|
+
})
|
|
1182
|
+
})]
|
|
1183
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1184
|
+
className: panel_module_default.body,
|
|
1185
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RezSettingsPage, {})
|
|
1186
|
+
}) : null]
|
|
1335
1187
|
});
|
|
1336
|
-
place();
|
|
1337
|
-
return () => {
|
|
1338
|
-
observer.disconnect();
|
|
1339
|
-
entry.remove();
|
|
1340
|
-
};
|
|
1341
1188
|
}
|
|
1342
1189
|
//#endregion
|
|
1343
1190
|
//#region src/client/index.ts
|
|
1344
1191
|
const NS = "dsh-rez-suite";
|
|
1345
1192
|
const inject = ["slots", "locale"];
|
|
1346
1193
|
function apply(ctx) {
|
|
1194
|
+
const t = ctx.locale.bind(NS);
|
|
1347
1195
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
1348
1196
|
zh,
|
|
1349
1197
|
en
|
|
1350
1198
|
}), "dsh-rez-suite: dictionaries");
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1199
|
+
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
1200
|
+
name: "settings.plugin.item",
|
|
1201
|
+
id: "rez-suite",
|
|
1202
|
+
order: 40,
|
|
1203
|
+
locale: NS
|
|
1204
|
+
}, RezPluginCard));
|
|
1205
|
+
ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({
|
|
1206
|
+
name: "settings.plugins.tab",
|
|
1207
|
+
id: "rez",
|
|
1208
|
+
order: 20,
|
|
1209
|
+
label: () => t("settings.title"),
|
|
1210
|
+
locale: NS
|
|
1211
|
+
}, RezSettingsPage));
|
|
1363
1212
|
}
|
|
1364
1213
|
//#endregion
|
|
1365
1214
|
exports.apply = apply;
|
package/lib/index.js
CHANGED
|
@@ -7558,7 +7558,7 @@ const REZ_GUIDANCE = [
|
|
|
7558
7558
|
"本机已安装 ReZ-TI 套件(一次安装):工作身份由 dsh-rez-sso 提供,MCP 由官方 dsh-mcp-client 接入 Odoo / Nextcloud / 企业微信 / Home Assistant。",
|
|
7559
7559
|
"工具名 mcp__odoo__*、mcp__nextcloud__*、mcp__wechat__*、mcp__homeassistant__*。",
|
|
7560
7560
|
"密钥:REZ_ODOO_TOKEN、REZ_NEXTCLOUD_PASSWORD、REZ_WECHAT_WEBHOOK、REZ_HA_TOKEN。",
|
|
7561
|
-
"个人微信(QClaw/ClawBot):打开
|
|
7561
|
+
"个人微信(QClaw/ClawBot):打开 设置 → 插件 → ReZ-TI → 微信 扫码,然后直接在微信里说话,不必再跑命令、也不要调用微信 MCP 工具。",
|
|
7562
7562
|
"意图用 rez_set_intent(erp/files/chat/home/auto)。审计用 rez_audit。",
|
|
7563
7563
|
"涉及资金、对外发送、设备控制、生产写入时先征得用户批准。"
|
|
7564
7564
|
].join("");
|