labull-framework 0.1.1 → 0.1.3

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.
@@ -1,8 +1,8 @@
1
- import { defineComponent as We, ref as w, computed as C, watch as he, nextTick as Et, onMounted as Ze, onActivated as Ct, onBeforeUnmount as Xe, openBlock as h, createElementBlock as b, normalizeStyle as Qe, normalizeClass as J, unref as be, createElementVNode as p, toDisplayString as v, createCommentVNode as x, Fragment as j, renderList as Q, withModifiers as Bt, withDirectives as Tt, vModelText as At, createStaticVNode as Ot, createTextVNode as ue } from "vue";
2
- import { useRoute as et, useRouter as tt } from "vue-router";
3
- import { A as Mt, b as V, c as Me, u as nt } from "./chunk-index-BWpDbB19.js";
4
- import { _ as ot } from "./chunk-_plugin-vue_export-helper-CHgC5LLL.js";
5
- const q = "__mb", st = "call", Pe = "reply", at = "host-ready", it = "height", Pt = "html, body { overflow: hidden !important; }", Rt = `
1
+ import { defineComponent as Je, ref as $, computed as P, watch as ge, nextTick as We, onMounted as st, onBeforeUnmount as at, openBlock as b, createElementBlock as g, normalizeStyle as it, normalizeClass as U, unref as ve, createElementVNode as p, toDisplayString as v, createCommentVNode as E, Fragment as j, renderList as Q, withModifiers as Bt, createBlock as Mt, withDirectives as At, vModelText as Ot, createStaticVNode as Pt, createTextVNode as ce } from "vue";
2
+ import { useRouter as lt } from "vue-router";
3
+ import { A as Rt, b as J, c as Le, u as rt } from "./chunk-index-BWpDbB19.js";
4
+ import { u as jt, o as De, b as ct, _ as ut, d as Nt } from "./chunk-ProductShell.vue_vue_type_style_index_0_scoped_0fb37099_lang-BpRKKThg.js";
5
+ const K = "__mb", dt = "call", Fe = "reply", pt = "host-ready", ft = "height", It = "html, body { overflow: hidden !important; }", Lt = `
6
6
  (function () {
7
7
  var seq = 0, waiting = {}, queue = [], ready = false, last = -1;
8
8
  function call(method, args) {
@@ -10,23 +10,25 @@ const q = "__mb", st = "call", Pe = "reply", at = "host-ready", it = "height", P
10
10
  function run() {
11
11
  var id = ++seq;
12
12
  waiting[id] = { resolve: resolve, reject: reject };
13
- parent.postMessage({ '${q}': '${st}', id: id, method: method, args: args }, '*');
13
+ parent.postMessage({ '${K}': '${dt}', id: id, method: method, args: args }, '*');
14
14
  }
15
15
  if (ready) run(); else queue.push(run);
16
16
  });
17
17
  }
18
18
  window.addEventListener('message', function (event) {
19
19
  var data = event.data, pending;
20
- if (!data || data['${q}'] === undefined) return;
21
- if (data['${q}'] === '${at}') { ready = true; queue.splice(0).forEach(function (run) { run(); }); return; }
22
- if (data['${q}'] !== '${Pe}') return;
20
+ if (!data || data['${K}'] === undefined) return;
21
+ if (data['${K}'] === '${pt}') { ready = true; queue.splice(0).forEach(function (run) { run(); }); return; }
22
+ if (data['${K}'] !== '${Fe}') return;
23
23
  if (!(pending = waiting[data.id])) return;
24
24
  delete waiting[data.id];
25
25
  if (data.ok) pending.resolve(data.value); else pending.reject(new Error(data.error || '调用失败'));
26
26
  });
27
27
  window.magicBlock = {
28
28
  getMe: function () { return call('getMe', []); },
29
- navigateTab: function (path) { return call('navigateTab', [path]); }
29
+ navigateTab: function (path) { return call('navigateTab', [path]); },
30
+ context: function () { return call('context', []); },
31
+ setTabTitle: function (title, icon) { return call('setTabTitle', [title, icon]); }
30
32
  };
31
33
  function make(prefix) {
32
34
  return new Proxy(function () {}, {
@@ -58,7 +60,7 @@ const q = "__mb", st = "call", Pe = "reply", at = "host-ready", it = "height", P
58
60
  if (height > 0) height += 1;
59
61
  if (height === last) return; /* 一样高就不再发:否则「宿主改高度 → 触发观察 → 又发一次」会转个不停 */
60
62
  last = height;
61
- parent.postMessage({ '${q}': '${it}', height: height }, '*');
63
+ parent.postMessage({ '${K}': '${ft}', height: height }, '*');
62
64
  }
63
65
  function start() {
64
66
  report();
@@ -67,27 +69,27 @@ const q = "__mb", st = "call", Pe = "reply", at = "host-ready", it = "height", P
67
69
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start();
68
70
  setInterval(report, 500);
69
71
  })();
70
- `, jt = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/;
71
- function lt(t) {
72
+ `, Dt = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/;
73
+ function mt(t) {
72
74
  const e = typeof window > "u" ? "http://localhost" : window.location.href;
73
- return new URL(`${Mt}${t}`, e);
75
+ return new URL(`${Rt}${t}`, e);
74
76
  }
75
- const Ke = (() => {
77
+ const Ze = (() => {
76
78
  try {
77
- return lt("").origin;
79
+ return mt("").origin;
78
80
  } catch {
79
81
  return typeof window > "u" ? "" : window.location.origin;
80
82
  }
81
83
  })();
82
- async function Nt(t, e, n) {
83
- if (!jt.test(e)) throw new Error(`路由名不合法:${e}(要写成 类名.方法名,例如 Customer.create)`);
84
- const s = lt(`/bx/${t}/${e}`);
85
- if (s.origin !== Ke) throw new Error(`后端地址必须是本应用的(${Ke}):${s.origin}`);
84
+ async function Ft(t, e, n) {
85
+ if (!Dt.test(e)) throw new Error(`路由名不合法:${e}(要写成 类名.方法名,例如 Customer.create)`);
86
+ const s = mt(`/bx/${t}/${e}`);
87
+ if (s.origin !== Ze) throw new Error(`后端地址必须是本应用的(${Ze}):${s.origin}`);
86
88
  const l = n instanceof Blob ? n : null, r = await fetch(s.toString(), {
87
89
  method: "POST",
88
90
  credentials: "include",
89
91
  // 带上 HttpOnly 会话 cookie;authHeaders('POST') 给 CSRF 头(缺了 403)
90
- headers: l ? { "Content-Type": l.type || "application/octet-stream", ...Me("POST") } : { "Content-Type": "application/json", ...Me("POST") },
92
+ headers: l ? { "Content-Type": l.type || "application/octet-stream", ...Le("POST") } : { "Content-Type": "application/json", ...Le("POST") },
91
93
  body: l ?? JSON.stringify(n ?? {})
92
94
  }), u = await r.text().catch(() => "");
93
95
  if (r.ok) {
@@ -107,7 +109,7 @@ async function Nt(t, e, n) {
107
109
  }
108
110
  throw new Error(c ? `${e} 调用失败:${c.slice(0, 300)}` : `${e} 调用失败(${r.status})`);
109
111
  }
110
- function It(t, e) {
112
+ function zt(t, e) {
111
113
  const n = (u) => {
112
114
  try {
113
115
  t.contentWindow?.postMessage(u, "*");
@@ -116,145 +118,151 @@ function It(t, e) {
116
118
  }
117
119
  };
118
120
  async function s(u, c) {
119
- if (u === "getMe") return await V("/auth/me");
121
+ if (u === "getMe") return await J("/auth/me");
120
122
  if (u === "navigateTab") {
121
123
  const d = typeof c[0] == "string" ? c[0].trim() : "";
122
- if (!d || !e.onNavigateTab) throw new Error(`跳不了 ${d || "(空路径)"}:这个页面没有把宿主接到路由上`);
124
+ if (!d || !e.onNavigateTab) throw new Error(`跳不了 ${d || "(空地址)"}:这个页面没有把宿主接到路由上`);
123
125
  return await e.onNavigateTab(d);
124
126
  }
127
+ if (u === "context") return e.context ? e.context() : {};
128
+ if (u === "setTabTitle") {
129
+ const d = typeof c[0] == "string" ? c[0].trim() : "", f = typeof c[1] == "string" ? c[1].trim() : "";
130
+ if (!d) throw new Error("setTabTitle 要给一个非空的名字");
131
+ return e.onTabTitle?.(d, f || void 0), !0;
132
+ }
125
133
  if (u === "backend") {
126
134
  const d = typeof c[0] == "string" ? c[0].trim() : "", f = c[1];
127
135
  if (!d) throw new Error("后端调用的路由名是空的:要写成 magicBackendApi.类名.方法名(参数)");
128
136
  if (!f || typeof f != "object" || Array.isArray(f)) throw new Error(`magicBackendApi.${d}(params) 的参数要么是一个对象,要么是一个文件(File / Blob)`);
129
- return await Nt(e.uuid, d, f);
137
+ return await Ft(e.uuid, d, f);
130
138
  }
131
- throw new Error(`不认识的方法:${String(u)}(这块桥只有 getMe / navigateTab / backend 三个)`);
139
+ throw new Error(`不认识的方法:${String(u)}(这块桥只有 getMe / navigateTab / context / setTabTitle / backend 五个)`);
132
140
  }
133
141
  const l = (u) => {
134
142
  if (u.source !== t.contentWindow) return;
135
143
  const c = u.data;
136
144
  if (!c) return;
137
- if (c[q] === it) {
145
+ if (c[K] === ft) {
138
146
  const f = typeof c.height == "number" ? c.height : NaN;
139
147
  Number.isFinite(f) && f > 0 && e.onHeight?.(f);
140
148
  return;
141
149
  }
142
- if (c[q] !== st) return;
150
+ if (c[K] !== dt) return;
143
151
  const d = c.id;
144
152
  (async () => {
145
153
  try {
146
- n({ [q]: Pe, id: d, ok: !0, value: await s(String(c.method), c.args ?? []) });
154
+ n({ [K]: Fe, id: d, ok: !0, value: await s(String(c.method), c.args ?? []) });
147
155
  } catch (f) {
148
- n({ [q]: Pe, id: d, ok: !1, error: f instanceof Error ? f.message : String(f) });
156
+ n({ [K]: Fe, id: d, ok: !1, error: f instanceof Error ? f.message : String(f) });
149
157
  }
150
158
  })();
151
159
  };
152
160
  window.addEventListener("message", l);
153
- const r = () => n({ [q]: at });
161
+ const r = () => n({ [K]: pt });
154
162
  return r(), t.addEventListener("load", r), () => {
155
163
  window.removeEventListener("message", l), t.removeEventListener("load", r);
156
164
  };
157
165
  }
158
- const rt = "index.open.html", Lt = "backend_open.py", zt = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
159
- function Ue(t, e) {
160
- if (zt.test(t)) return;
166
+ const bt = "index.open.html", Ht = "backend_open.py", Kt = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
167
+ function Xe(t, e) {
168
+ if (Kt.test(t)) return;
161
169
  const n = (t.split(/[?#]/)[0] ?? "").replace(/^\.\//, "").replace(/^\/+/, "");
162
170
  if (n in e) return n;
163
171
  const s = n.split("/").pop() ?? "";
164
172
  return s ? Object.keys(e).find((l) => (l.split("/").pop() ?? "") === s) : void 0;
165
173
  }
166
- const ct = "\0mb:";
167
- function Dt(t) {
168
- return `${ct}${t}\0`;
174
+ const ht = "\0mb:";
175
+ function qt(t) {
176
+ return `${ht}${t}\0`;
169
177
  }
170
- const Ft = /<script\b([^>]*?)\bsrc\s*=\s*(["'])(.*?)\2([^>]*)>\s*<\/script\s*>/gi, Ht = /<link\b([^>]*?)\bhref\s*=\s*(["'])(.*?)\2([^>]*?)\/?>/gi;
171
- function Kt(t, e) {
172
- const n = [], s = (u) => (n.push(u), Dt(n.length - 1));
173
- return { html: t.replace(Ft, (u, c, d, f, _) => {
174
- const y = Ue(f, e);
175
- return y === void 0 ? u : s(`<script${c}${_}>
176
- ${ut(e[y] ?? "")}
178
+ const Ut = /<script\b([^>]*?)\bsrc\s*=\s*(["'])(.*?)\2([^>]*)>\s*<\/script\s*>/gi, Jt = /<link\b([^>]*?)\bhref\s*=\s*(["'])(.*?)\2([^>]*?)\/?>/gi;
179
+ function Vt(t, e) {
180
+ const n = [], s = (u) => (n.push(u), qt(n.length - 1));
181
+ return { html: t.replace(Ut, (u, c, d, f, w) => {
182
+ const y = Xe(f, e);
183
+ return y === void 0 ? u : s(`<script${c}${w}>
184
+ ${gt(e[y] ?? "")}
177
185
  <\/script>`);
178
- }).replace(Ht, (u, c, d, f, _) => {
179
- if (!/\brel\s*=\s*(?:"|')?stylesheet/i.test(`${c}${_}`)) return u;
180
- const y = Ue(f, e);
186
+ }).replace(Jt, (u, c, d, f, w) => {
187
+ if (!/\brel\s*=\s*(?:"|')?stylesheet/i.test(`${c}${w}`)) return u;
188
+ const y = Xe(f, e);
181
189
  return y === void 0 ? u : s(`<style>
182
190
  ${e[y]}
183
191
  </style>`);
184
192
  }), slots: n };
185
193
  }
186
- function ut(t) {
194
+ function gt(t) {
187
195
  return t.replace(/<\/(script)/gi, "<\\/$1");
188
196
  }
189
- function dt(t, e) {
197
+ function vt(t, e) {
190
198
  const n = /<\/head\s*>/i.exec(t);
191
199
  return n ? `${t.slice(0, n.index)}${e}${t.slice(n.index)}` : `${e}${t}`;
192
200
  }
193
- function Ut(t, e) {
194
- return e ? dt(t, `<script>
195
- ${ut(e)}
201
+ function Gt(t, e) {
202
+ return e ? vt(t, `<script>
203
+ ${gt(e)}
196
204
  <\/script>
197
205
  `) : t;
198
206
  }
199
- function qe(t, e) {
200
- return e ? dt(t, `<style data-magic-block="host">
207
+ function Qe(t, e) {
208
+ return e ? vt(t, `<style data-magic-block="host">
201
209
  ${e}
202
210
  </style>
203
211
  `) : t;
204
212
  }
205
- function qt(t, e = "") {
206
- const n = typeof e == "string" ? e : e.bootstrap ?? "", s = typeof e == "string" ? "" : e.css ?? "", l = typeof e == "string" ? "" : e.themeCss ?? "", r = t[rt];
213
+ function Yt(t, e = "") {
214
+ const n = typeof e == "string" ? e : e.bootstrap ?? "", s = typeof e == "string" ? "" : e.css ?? "", l = typeof e == "string" ? "" : e.themeCss ?? "", r = t[bt];
207
215
  if (r === void 0) return "";
208
- const { html: u, slots: c } = Kt(r, t), d = Ut(qe(qe(u, l), s), n), f = d.split(ct);
216
+ const { html: u, slots: c } = Vt(r, t), d = Gt(Qe(Qe(u, l), s), n), f = d.split(ht);
209
217
  if (f.length === 1) return d;
210
- let _ = f[0] ?? "";
218
+ let w = f[0] ?? "";
211
219
  for (let y = 1; y < f.length; y += 1) {
212
- const S = f[y] ?? "", B = S.indexOf("\0"), L = Number(S.slice(0, B));
213
- _ += (c[L] ?? "") + S.slice(B + 1);
220
+ const _ = f[y] ?? "", N = _.indexOf("\0"), B = Number(_.slice(0, N));
221
+ w += (c[B] ?? "") + _.slice(N + 1);
214
222
  }
215
- return _;
223
+ return w;
216
224
  }
217
- const ge = /* @__PURE__ */ new Map();
218
- let de = null;
219
- const Re = /* @__PURE__ */ new Set();
220
- function Gt(t) {
221
- return Re.add(t), () => {
222
- Re.delete(t);
225
+ const ye = /* @__PURE__ */ new Map();
226
+ let ue = null;
227
+ const ze = /* @__PURE__ */ new Set();
228
+ function Wt(t) {
229
+ return ze.add(t), () => {
230
+ ze.delete(t);
223
231
  };
224
232
  }
225
- function Jt() {
226
- ge.clear(), de = null;
227
- for (const t of Re) t();
233
+ function Zt() {
234
+ ye.clear(), ue = null;
235
+ for (const t of ze) t();
228
236
  }
229
- async function Vt(t) {
237
+ async function Xt(t) {
230
238
  const e = [...new Set(t)].filter(Boolean);
231
- if (e.some((n) => !ge.has(n))) {
232
- de && await de.catch(() => {
239
+ if (e.some((n) => !ye.has(n))) {
240
+ ue && await ue.catch(() => {
233
241
  });
234
- const n = e.filter((s) => !ge.has(s));
235
- n.length > 0 && (de = V(`/magic-blocks/render?ids=${n.map(encodeURIComponent).join(",")}`).then((s) => {
236
- for (const l of s) l?.id && ge.set(l.id, l);
242
+ const n = e.filter((s) => !ye.has(s));
243
+ n.length > 0 && (ue = J(`/magic-blocks/render?ids=${n.map(encodeURIComponent).join(",")}`).then((s) => {
244
+ for (const l of s) l?.id && ye.set(l.id, l);
237
245
  return s;
238
246
  }).catch(() => []).finally(() => {
239
- de = null;
240
- }), await de.catch(() => {
247
+ ue = null;
248
+ }), await ue.catch(() => {
241
249
  }));
242
250
  }
243
- return e.map((n) => ge.get(n)).filter((n) => !!n);
251
+ return e.map((n) => ye.get(n)).filter((n) => !!n);
244
252
  }
245
- const pe = "labull.css", je = "CONTROLS.lock.html";
246
- function Yt(t, e) {
253
+ const de = "labull.css", He = "CONTROLS.lock.html";
254
+ function Qt(t, e) {
247
255
  const n = String(e || "");
248
256
  if (/@font-face|@keyframes/i.test(n)) return !0;
249
257
  const s = String(t || "");
250
258
  return /(^|[\s,>+~])(\.p-|\.pi(?![a-z])|\.pi-|\.labull-|:root|html(?![a-z-])|body(?![a-z-])|\*|:where\()/.test(s) ? !0 : /--(?:sp|surface|primary|text-color|content|highlight|focus-ring|p-)/.test(n);
251
259
  }
252
- function pt(t, e, n) {
260
+ function yt(t, e, n) {
253
261
  for (let s = 0; s < t.length; s += 1) {
254
262
  const l = t[s], r = String(l.cssText || ""), u = String(l.selectorText || "");
255
263
  if (l.cssRules && l.cssRules.length > 0) {
256
264
  const c = [];
257
- if (pt(l.cssRules, c, n), c.length === 0) continue;
265
+ if (yt(l.cssRules, c, n), c.length === 0) continue;
258
266
  const d = r.slice(0, r.indexOf("{")).trim();
259
267
  e.push(`${d} {
260
268
  ${c.map((f) => " " + f).join(`
@@ -262,10 +270,10 @@ ${c.map((f) => " " + f).join(`
262
270
  }`);
263
271
  continue;
264
272
  }
265
- Yt(u, r) && (e.push(r), n.n += 1);
273
+ Qt(u, r) && (e.push(r), n.n += 1);
266
274
  }
267
275
  }
268
- function ft() {
276
+ function _t() {
269
277
  const t = [], e = [], n = { n: 0 };
270
278
  let s = 0;
271
279
  const l = typeof document > "u" ? [] : Array.from(document.styleSheets);
@@ -280,7 +288,7 @@ function ft() {
280
288
  }
281
289
  if (!d || d.length === 0) continue;
282
290
  const f = [];
283
- pt(d, f, n), f.length !== 0 && (s += 1, t.push(`/* ── ${c} ── */`, ...f));
291
+ yt(d, f, n), f.length !== 0 && (s += 1, t.push(`/* ── ${c} ── */`, ...f));
284
292
  }
285
293
  return { css: [
286
294
  "/* 生成物:每次导出都会重写,别手改。",
@@ -291,7 +299,7 @@ function ft() {
291
299
  " *",
292
300
  " * 怎么用(块里):**什么都不用加** —— 宿主会把这一份注入每个块的 iframe(`MagicBlockHost` 的 `theme` prop),",
293
301
  ' * 所以直接写类名就行:`<button class="p-button">` / `<input class="p-inputtext">` / `<span class="p-tag">`。',
294
- " * 这一份放在开发包里是给你**查 / 对照 / 抄**用的(`" + je + "` 里的每一块 markup 都能直接用)。",
302
+ " * 这一份放在开发包里是给你**查 / 对照 / 抄**用的(`" + He + "` 里的每一块 markup 都能直接用)。",
295
303
  " * ⚠️ 别把它当块包文件塞进块里:它 500 KB 上下,而且宿主已经注入了一份(重复只会更慢)。",
296
304
  " * ⚠️ 块里**只有 CSS,没有 JS 组件**:下拉 / 日期 / 弹窗那些要装了 PrimeVue 才有行为,",
297
305
  " * 这里能用的是类名(按钮、输入框、标签、面板、表格、图标)。",
@@ -302,7 +310,7 @@ function ft() {
302
310
  `) + `
303
311
  `, sheets: s, skipped: e, rules: n.n };
304
312
  }
305
- function Wt() {
313
+ function en() {
306
314
  const n = [
307
315
  ["按钮", '<button class="p-button" type="button">主要按钮</button>'],
308
316
  ["次要按钮", '<button class="p-button p-button-outlined" type="button">次要按钮</button>'],
@@ -335,7 +343,7 @@ function Wt() {
335
343
  <head>
336
344
  <meta charset="utf-8">
337
345
  <title>labull 控件清单</title>
338
- <link rel="stylesheet" href="${pe}">
346
+ <link rel="stylesheet" href="${de}">
339
347
  <style>
340
348
  body { margin: 0; padding: 16px; }
341
349
  h1 { margin: 0 0 4px; font-size: 18px; }
@@ -351,10 +359,10 @@ function Wt() {
351
359
  <body>
352
360
  <h1>labull 控件清单</h1>
353
361
  <p class="lead">
354
- 这些类名来自 <code>${pe}</code>(与应用同源同版本)。块里别自己写一套配色 / 按钮:
362
+ 这些类名来自 <code>${de}</code>(与应用同源同版本)。块里别自己写一套配色 / 按钮:
355
363
  把这一行加进 <code>index.open.html</code> 的 <code>&lt;head&gt;</code>,
356
364
  下面每一块 markup 都能直接用:
357
- <code>&lt;link rel="stylesheet" href="${pe}"&gt;</code>
365
+ <code>&lt;link rel="stylesheet" href="${de}"&gt;</code>
358
366
  <br />
359
367
  ⚠️ 这里**只有 CSS,没有 JS 组件**:下拉 / 日期 / 弹窗那些要装了 PrimeVue 才有行为(块里没有构建步骤)。
360
368
  </p>
@@ -363,140 +371,138 @@ ${n}
363
371
  </html>
364
372
  `;
365
373
  }
366
- const ie = /* @__PURE__ */ new Map(), Ne = /* @__PURE__ */ new Set(), Zt = 4e3;
367
- let Ie = "", we = null;
368
- function Ge() {
369
- for (const t of Ne) t();
374
+ const le = /* @__PURE__ */ new Map(), Ke = /* @__PURE__ */ new Set(), tn = 4e3;
375
+ let qe = "", Ee = null;
376
+ function et() {
377
+ for (const t of Ke) t();
370
378
  }
371
- function Xt(t) {
372
- return Ne.add(t), () => {
373
- Ne.delete(t);
379
+ function nn(t) {
380
+ return Ke.add(t), () => {
381
+ Ke.delete(t);
374
382
  };
375
383
  }
376
- function $e() {
377
- return Ie;
384
+ function Pe() {
385
+ return qe;
378
386
  }
379
- function Qt(t, e) {
387
+ function on(t, e) {
380
388
  const n = String(t || "").trim(), s = String(e || "").trim();
381
389
  if (!n || !s) return () => {
382
390
  };
383
- let l = ie.get(n);
384
- return l || (l = /* @__PURE__ */ new Set(), ie.set(n, l)), l.add(s), () => {
385
- const r = ie.get(n);
386
- r && (r.delete(s), r.size === 0 && ie.delete(n));
391
+ let l = le.get(n);
392
+ return l || (l = /* @__PURE__ */ new Set(), le.set(n, l)), l.add(s), () => {
393
+ const r = le.get(n);
394
+ r && (r.delete(s), r.size === 0 && le.delete(n));
387
395
  };
388
396
  }
389
- function Le(t, e) {
390
- const n = ie.get(String(t || ""));
391
- if (!n) return null;
392
- for (const s of n)
393
- if (s !== e) return s;
397
+ function Ue(t, e, n) {
398
+ const s = le.get(String(t || ""));
399
+ if (!s) return null;
400
+ for (const l of s)
401
+ if (l !== e && !(n && !n(l)))
402
+ return l;
394
403
  return null;
395
404
  }
396
- function en(t) {
397
- return [...ie.get(String(t || "")) ?? []];
405
+ function sn(t) {
406
+ return [...le.get(String(t || "")) ?? []];
398
407
  }
399
- function tn(t, e) {
400
- const n = ie.get(String(t || ""));
401
- return !n || n.size === 0 || n.has(e) ? null : Le(t, e);
408
+ function an(t, e, n) {
409
+ const s = le.get(String(t || ""));
410
+ return !s || s.size === 0 || s.has(e) ? null : Ue(t, e, n);
402
411
  }
403
- function mt(t, e = Zt) {
404
- Ie = String(t || ""), we !== null && clearTimeout(we), we = setTimeout(() => {
405
- we = null, Ie = "", Ge();
406
- }, Math.max(1, e)), Ge();
412
+ function kt(t, e = tn) {
413
+ qe = String(t || ""), Ee !== null && clearTimeout(Ee), Ee = setTimeout(() => {
414
+ Ee = null, qe = "", et();
415
+ }, Math.max(1, e)), et();
407
416
  }
408
- const nn = ["data-magic-block", "data-magic-module"], on = ["srcdoc", "title", "scrolling"], sn = { class: "mb__state" }, an = { class: "mb__brief" }, ln = {
417
+ const ln = ["data-magic-block", "data-magic-module"], rn = ["srcdoc", "title"], cn = { class: "mb__state" }, un = { class: "mb__brief" }, dn = {
409
418
  key: 0,
410
419
  class: "mb__reason"
411
- }, rn = {
420
+ }, pn = {
412
421
  key: 1,
413
422
  class: "mb__issues"
414
- }, cn = {
423
+ }, fn = {
415
424
  key: 2,
416
425
  class: "mb__ring",
417
426
  "aria-hidden": "true"
418
- }, un = ["title", "aria-label"], dn = ["title", "aria-label"], pn = ["title", "aria-label"], fn = ["title", "aria-label"], mn = /* @__PURE__ */ We({
427
+ }, mn = ["title", "aria-label"], bn = ["title", "aria-label"], hn = ["title", "aria-label"], gn = ["title", "aria-label"], vn = /* @__PURE__ */ Je({
419
428
  __name: "MagicBlockHost",
420
429
  props: {
421
430
  uuid: {},
422
431
  name: { default: "" },
423
432
  module: { default: "" },
424
- width: {},
425
- height: {},
426
- flexible: { type: Boolean, default: !0 },
427
- fullSize: { type: Boolean, default: !1 },
428
- responsive: { type: Boolean, default: !0 },
429
433
  theme: { type: Boolean, default: !0 }
430
434
  },
431
435
  setup(t) {
432
- const e = t, n = et(), s = tt(), { isStaff: l } = nt(), r = w(null), u = w(null), c = w(null), d = w(!1), f = w(0), _ = w(0);
433
- let y = null, S = null, B = null, L = null, Y = null, A = null;
434
- const T = (m) => typeof m == "number" ? `${m}rem` : m ?? "", U = C(() => e.name.trim() || e.uuid), N = C(() => c.value?.state ?? ""), z = C(() => N.value === "invalid" ? "校验不通过" : N.value === "draft" ? "未开发" : U.value), le = C(() => (c.value?.brief ?? "").trim() || (c.value?.name ?? "").trim() || U.value), G = C(() => (c.value?.reason ?? "").trim()), W = C(() => c.value?.issues ?? []), M = C(() => e.flexible && !e.fullSize && f.value > 0), E = C(() => {
435
- const m = T(e.height);
436
- if (!m || typeof document > "u") return 0;
437
- const k = document.createElement("div");
438
- k.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;height:${m}`, (r.value ?? document.body).appendChild(k);
439
- const I = parseFloat(getComputedStyle(k).height) || 0;
440
- return k.remove(), I;
441
- }), Ee = C(() => Math.max(_.value, f.value, E.value, 1)), H = C(() => {
442
- const m = { "--mb-width": T(e.width) || (e.responsive ? "100%" : "auto"), "--mb-height": T(e.height) || "12rem" };
443
- return e.fullSize ? { ...m, height: `${Ee.value}px`, flexShrink: "0" } : M.value ? { ...m, height: `${f.value}px`, flexGrow: "0" } : m;
444
- }), Z = C(() => {
436
+ const e = t, n = jt(), s = lt(), { isStaff: l } = rt(), r = $(null), u = $(null), c = $(null), d = $(!1), f = $(0), w = $(0);
437
+ let y = null, _ = null, N = null, B = null, V = null, ee = null;
438
+ const M = P(() => e.name.trim() || e.uuid), S = P(() => c.value?.state ?? ""), G = P(() => S.value === "invalid" ? "校验不通过" : S.value === "draft" ? "未开发" : M.value), te = P(() => (c.value?.brief ?? "").trim() || (c.value?.name ?? "").trim() || M.value), I = P(() => (c.value?.reason ?? "").trim()), ne = P(() => c.value?.issues ?? []), Y = P(() => Math.max(w.value, f.value, 1)), oe = P(() => ({ height: `${Y.value}px` })), A = P(() => {
445
439
  const m = {};
446
- for (const [k, I] of Object.entries(c.value?.files ?? {})) k !== Lt && (m[k] = I);
440
+ for (const [k, C] of Object.entries(c.value?.files ?? {})) k !== Ht && (m[k] = C);
447
441
  return m;
448
- }), re = C(() => N.value === "ok" && typeof Z.value[rt] == "string");
449
- let K = null;
450
- function ce() {
442
+ }), T = P(() => S.value === "ok" && typeof A.value[bt] == "string");
443
+ let q = null;
444
+ function D() {
451
445
  if (!e.theme) return "";
452
- if (K !== null || (K = "", typeof document > "u")) return K;
446
+ if (q !== null || (q = "", typeof document > "u")) return q;
453
447
  try {
454
- K = ft().css;
448
+ q = _t().css;
455
449
  } catch {
456
- K = "";
450
+ q = "";
457
451
  }
458
- return K;
452
+ return q;
459
453
  }
460
- const ye = C(() => {
461
- if (!re.value) return "";
462
- const m = { bootstrap: Rt };
463
- e.fullSize && (m.css = Pt);
464
- const k = ce();
465
- return k && (m.themeCss = k), qt(Z.value, m);
454
+ const W = P(() => {
455
+ if (!T.value) return "";
456
+ const m = { bootstrap: Lt, css: It }, k = D();
457
+ return k && (m.themeCss = k), Yt(A.value, m);
466
458
  });
467
- async function Ce(m) {
468
- const k = s.getRoutes().map((I) => I.path);
469
- if (!k.includes(m)) throw new Error(`这个应用里没有页面 ${m}。能跳的页面只有:${k.length > 0 ? k.join(" / ") : "(还没有配路由)"}`);
470
- return await s.push(m), s.currentRoute.value.fullPath || m;
459
+ function ke() {
460
+ return { key: n.key, path: n.path, params: n.params, query: n.query };
471
461
  }
472
- function _e() {
473
- B?.(), B = null;
462
+ async function pe(m) {
463
+ const k = s.resolve(m);
464
+ if (k.matched.length === 0) {
465
+ const C = s.getRoutes().map((z) => z.path);
466
+ throw new Error(`这个应用里没有页面 ${m}。能跳的页面只有:${C.length > 0 ? C.join(" / ") : "(还没有配路由)"}`);
467
+ }
468
+ return De(m) || k.fullPath;
469
+ }
470
+ function re() {
471
+ N?.(), N = null;
474
472
  const m = u.value;
475
- m && (B = It(m, { uuid: e.uuid, onHeight: (k) => {
476
- f.value = k;
477
- }, onNavigateTab: Ce }));
473
+ m && (N = zt(m, {
474
+ uuid: e.uuid,
475
+ onHeight: (k) => {
476
+ f.value = k;
477
+ },
478
+ onNavigateTab: pe,
479
+ context: ke,
480
+ /* 🔴 块给**自己所属那条标签**起名:整页就是一个块时(`MagicBlockPage`),标签栏上那条
481
+ * 默认只有路由的 `meta.title`("订单详情"),而"订单 SO-42"只有块自己知道。 */
482
+ onTabTitle: (k, C) => n.setTitle(k, C)
483
+ }));
478
484
  }
479
485
  async function fe() {
480
- const m = e.uuid, k = await Vt([m]);
481
- m === e.uuid && (c.value = k.find((I) => I.id === m) ?? null);
486
+ const m = e.uuid, k = await Xt([m]);
487
+ m === e.uuid && (c.value = k.find((C) => C.id === m) ?? null);
482
488
  }
483
- function ke() {
489
+ function Ce() {
484
490
  window.dispatchEvent(new CustomEvent("magic-block:open-console", { detail: { uuid: e.uuid } }));
485
491
  }
486
492
  function me(m = !1) {
487
- m && Y?.(), Y = Qt(e.uuid, n.path);
493
+ m && V?.(), V = on(e.uuid, n.key);
488
494
  }
489
- const R = C(() => {
495
+ const we = (m) => !ct(m, s), F = P(() => {
490
496
  if (!l.value) return "";
491
- const m = Le(e.uuid, n.path);
492
- return m ? `管理员:跳到还挂着这个块的页面 ${m}(点一下这一块会亮红框)` : "管理员:这个块只在本页挂着 —— 点一下会亮几秒红框";
497
+ const m = Ue(e.uuid, n.key, we);
498
+ return m ? `管理员:切到还挂着这个块的标签 ${m}(点一下这一块会亮红框)` : "管理员:这个块只在这一条标签里挂着 —— 点一下会亮几秒红框";
493
499
  });
494
- function ee() {
500
+ function se() {
495
501
  if (!l.value) return;
496
- const m = Le(e.uuid, n.path);
497
- mt(e.uuid), m && s.push(m);
502
+ const m = Ue(e.uuid, n.key, we);
503
+ kt(e.uuid), m && De(m);
498
504
  }
499
- function te(m) {
505
+ function Z(m) {
500
506
  let k = m.parentElement;
501
507
  for (; k; ) {
502
508
  if (getComputedStyle(k).overflowY !== "visible" && k.clientHeight > 0) return k;
@@ -504,128 +510,141 @@ const nn = ["data-magic-block", "data-magic-module"], on = ["srcdoc", "title", "
504
510
  }
505
511
  return document.documentElement;
506
512
  }
507
- function ne() {
513
+ function Be() {
508
514
  const m = r.value;
509
515
  if (!m) return 0;
510
- const k = te(m), I = k === document.documentElement ? window.innerHeight : k.clientHeight, se = k === document.documentElement ? window.innerHeight : k.getBoundingClientRect().top + k.clientHeight;
511
- return Math.max(0, Math.floor(Math.max(se - m.getBoundingClientRect().top, I)));
516
+ const k = Z(m), C = getComputedStyle(k), z = parseFloat(C.paddingTop) || 0, $e = parseFloat(C.paddingBottom) || 0, be = parseFloat(C.borderTopWidth) || 0, he = k === document.documentElement, Me = he ? Math.max(0, window.innerHeight - z - $e) : Math.max(0, k.clientHeight - z - $e), Ae = he ? z : k.getBoundingClientRect().top + be + z, xe = he ? window.scrollY || 0 : k.scrollTop, Oe = m.getBoundingClientRect().top - Ae + xe;
517
+ return Math.max(0, Math.floor(Me - Oe));
512
518
  }
513
- function D() {
514
- if (!e.fullSize || !r.value) return;
515
- const m = ne();
516
- m > 0 && Math.abs(m - _.value) > 1 && (_.value = m);
519
+ function ae() {
520
+ if (!n.active.value || !r.value) return;
521
+ const m = Be();
522
+ m > 0 && Math.abs(m - w.value) > 1 && (w.value = m);
517
523
  }
518
- function oe() {
519
- if (!e.fullSize || !r.value) {
520
- S?.disconnect(), S = null, y = null;
521
- return;
522
- }
523
- const m = te(r.value);
524
- y !== m && (y = m, S?.disconnect(), S = null), D(), !(S || typeof ResizeObserver > "u") && (S = new ResizeObserver(() => D()), S.observe(m));
524
+ function H() {
525
+ if (!r.value) return;
526
+ const m = Z(r.value);
527
+ y !== m && (y = m, _?.disconnect(), _ = null), ae(), !(_ || typeof ResizeObserver > "u") && (_ = new ResizeObserver(() => ae()), _.observe(m));
525
528
  }
526
- return he(u, () => _e()), he(ye, () => {
527
- f.value = 0, _.value = 0, oe();
528
- }, { flush: "post" }), he(() => [e.fullSize, e.height, e.uuid], () => {
529
- Et().then(() => oe());
530
- }), he(d, (m) => {
531
- if (!m) return;
532
- const k = r.value;
533
- !k || !k.isConnected || k.offsetParent === null || k.scrollIntoView({ behavior: "smooth", block: "center" });
534
- }), he(() => e.uuid, () => {
535
- f.value = 0, c.value = null, me(!0), d.value = $e() === e.uuid, fe();
536
- }), Ze(() => {
537
- L = Gt(() => void fe()), A = Xt(() => {
538
- d.value = $e() === e.uuid;
539
- }), d.value = $e() === e.uuid, me(), oe(), fe();
540
- }), Ct(() => {
541
- me(!0), d.value = $e() === e.uuid, oe();
542
- }), Xe(() => {
543
- S?.disconnect(), S = null, L?.(), L = null, A?.(), A = null, Y?.(), Y = null, B?.(), B = null;
544
- }), (m, k) => (h(), b("div", {
529
+ return ge(u, () => re()), ge(W, () => {
530
+ f.value = 0, w.value = 0, H();
531
+ }, { flush: "post" }), ge(() => e.uuid, () => {
532
+ We().then(() => H());
533
+ }), ge(() => n.active.value, (m) => {
534
+ m && We().then(() => {
535
+ H();
536
+ const k = r.value;
537
+ !k || !k.isConnected || k.offsetParent === null || d.value && k.scrollIntoView({ behavior: "smooth", block: "center" });
538
+ });
539
+ }), ge(() => e.uuid, () => {
540
+ f.value = 0, c.value = null, me(!0), d.value = Pe() === e.uuid, fe();
541
+ }), st(() => {
542
+ B = Wt(() => void fe()), ee = nn(() => {
543
+ d.value = Pe() === e.uuid;
544
+ }), d.value = Pe() === e.uuid, me(), H(), fe();
545
+ }), at(() => {
546
+ _?.disconnect(), _ = null, B?.(), B = null, ee?.(), ee = null, V?.(), V = null, N?.(), N = null;
547
+ }), (m, k) => (b(), g("div", {
545
548
  ref_key: "el",
546
549
  ref: r,
547
- class: J(["mb", { "mb--responsive": t.responsive, "mb--full": t.fullSize, "mb--admin": be(l), "mb--lit": be(l) && d.value }]),
548
- style: Qe(H.value),
550
+ class: U(["mb", { "mb--admin": ve(l), "mb--lit": ve(l) && d.value }]),
551
+ style: it(oe.value),
549
552
  "data-magic-block": t.uuid,
550
553
  "data-magic-module": t.module
551
554
  }, [
552
- re.value ? (h(), b("iframe", {
555
+ T.value ? (b(), g("iframe", {
553
556
  key: 0,
554
557
  ref_key: "frame",
555
558
  ref: u,
556
559
  class: "mb__frame",
557
- srcdoc: ye.value,
558
- title: U.value,
559
- scrolling: t.fullSize ? "no" : void 0,
560
+ srcdoc: W.value,
561
+ title: M.value,
562
+ scrolling: "no",
560
563
  sandbox: "allow-scripts allow-forms allow-modals allow-popups allow-downloads"
561
- }, null, 8, on)) : (h(), b("div", {
564
+ }, null, 8, rn)) : (b(), g("div", {
562
565
  key: 1,
563
- class: J(["mb__empty", { "mb__empty--off": N.value === "invalid", "mb__empty--draft": N.value === "draft" }]),
564
- onClick: ee
566
+ class: U(["mb__empty", { "mb__empty--off": S.value === "invalid", "mb__empty--draft": S.value === "draft" }]),
567
+ onClick: se
565
568
  }, [
566
- p("p", sn, v(z.value), 1),
567
- p("p", an, v(le.value), 1),
568
- N.value === "invalid" && G.value ? (h(), b("p", ln, v(G.value), 1)) : x("", !0),
569
- N.value === "invalid" && W.value.length > 0 ? (h(), b("ul", rn, [
570
- (h(!0), b(j, null, Q(W.value, (I, se) => (h(), b("li", {
571
- key: se,
569
+ p("p", cn, v(G.value), 1),
570
+ p("p", un, v(te.value), 1),
571
+ S.value === "invalid" && I.value ? (b(), g("p", dn, v(I.value), 1)) : E("", !0),
572
+ S.value === "invalid" && ne.value.length > 0 ? (b(), g("ul", pn, [
573
+ (b(!0), g(j, null, Q(ne.value, (C, z) => (b(), g("li", {
574
+ key: z,
572
575
  class: "mb__issue"
573
- }, v(I.message), 1))), 128))
574
- ])) : x("", !0),
576
+ }, v(C.message), 1))), 128))
577
+ ])) : E("", !0),
575
578
  p("button", {
576
579
  class: "mb__go",
577
580
  type: "button",
578
- onClick: Bt(ke, ["stop"])
581
+ onClick: Bt(Ce, ["stop"])
579
582
  }, "去控制台")
580
583
  ], 2)),
581
- be(l) ? (h(), b("span", cn)) : x("", !0),
582
- be(l) && re.value ? (h(), b(j, { key: 3 }, [
584
+ ve(l) ? (b(), g("span", fn)) : E("", !0),
585
+ ve(l) && T.value ? (b(), g(j, { key: 3 }, [
583
586
  p("button", {
584
587
  class: "mb__grab mb__grab--top",
585
588
  type: "button",
586
- title: R.value,
587
- "aria-label": R.value,
588
- onClick: ee
589
- }, null, 8, un),
589
+ title: F.value,
590
+ "aria-label": F.value,
591
+ onClick: se
592
+ }, null, 8, mn),
590
593
  p("button", {
591
594
  class: "mb__grab mb__grab--right",
592
595
  type: "button",
593
- title: R.value,
594
- "aria-label": R.value,
595
- onClick: ee
596
- }, null, 8, dn),
596
+ title: F.value,
597
+ "aria-label": F.value,
598
+ onClick: se
599
+ }, null, 8, bn),
597
600
  p("button", {
598
601
  class: "mb__grab mb__grab--bottom",
599
602
  type: "button",
600
- title: R.value,
601
- "aria-label": R.value,
602
- onClick: ee
603
- }, null, 8, pn),
603
+ title: F.value,
604
+ "aria-label": F.value,
605
+ onClick: se
606
+ }, null, 8, hn),
604
607
  p("button", {
605
608
  class: "mb__grab mb__grab--left",
606
609
  type: "button",
607
- title: R.value,
608
- "aria-label": R.value,
609
- onClick: ee
610
- }, null, 8, fn)
611
- ], 64)) : x("", !0)
612
- ], 14, nn));
610
+ title: F.value,
611
+ "aria-label": F.value,
612
+ onClick: se
613
+ }, null, 8, gn)
614
+ ], 64)) : E("", !0)
615
+ ], 14, ln));
616
+ }
617
+ }), yn = /* @__PURE__ */ ut(vn, [["__scopeId", "data-v-8e1e849f"]]), ls = /* @__PURE__ */ Je({
618
+ __name: "MagicBlockPage",
619
+ props: {
620
+ uuid: {},
621
+ name: { default: "" },
622
+ module: { default: "" },
623
+ theme: { type: Boolean, default: !0 }
624
+ },
625
+ setup(t) {
626
+ return (e, n) => (b(), Mt(yn, {
627
+ uuid: t.uuid,
628
+ name: t.name,
629
+ module: t.module,
630
+ theme: t.theme
631
+ }, null, 8, ["uuid", "name", "module", "theme"]));
613
632
  }
614
- }), ns = /* @__PURE__ */ ot(mn, [["__scopeId", "data-v-e40128e9"]]), Be = "index.open.html", Te = "magic-block.open.yaml", xe = ["id", "module", "name", "brief"], ze = 40, hn = /^(?![A-Za-z]:)(?!\/)[A-Za-z0-9._\-/]+$/, bn = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, gn = /^[a-z][a-z0-9]*$/, vn = /^[A-Za-z_][A-Za-z0-9_]*$/;
615
- function yn(t) {
616
- return t.length > 0 && t.length <= ze && !/[\u0000-\u001f\u007f]/.test(t);
633
+ }), Re = "index.open.html", je = "magic-block.open.yaml", Te = ["id", "module", "name", "brief"], Ve = 40, _n = /^(?![A-Za-z]:)(?!\/)[A-Za-z0-9._\-/]+$/, kn = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, wn = /^[a-z][a-z0-9]*$/, $n = /^[A-Za-z_][A-Za-z0-9_]*$/;
634
+ function xn(t) {
635
+ return t.length > 0 && t.length <= Ve && !/[\u0000-\u001f\u007f]/.test(t);
617
636
  }
618
- const _n = {
637
+ const En = {
619
638
  id: "块的 uuid,必须与页面里挂载它时写死的那个 uuid 逐字一致",
620
639
  module: "模块名(小写字母与数字,必须以字母开头),例如 home",
621
- name: `可读名:可以用中文,不超过 ${ze} 个字符`,
640
+ name: `可读名:可以用中文,不超过 ${Ve} 个字符`,
622
641
  brief: "一句话说明这个块解决什么问题"
623
642
  };
624
- function Je(t) {
643
+ function tt(t) {
625
644
  const e = Object.keys(t);
626
645
  return e.length > 0 ? `现在包里有:${e.join(" / ")}` : "现在这个包是空的";
627
646
  }
628
- function kn(t) {
647
+ function Tn(t) {
629
648
  let e = "";
630
649
  for (let n = 0; n < t.length; n += 1) {
631
650
  const s = t[n];
@@ -636,7 +655,7 @@ function kn(t) {
636
655
  }
637
656
  return t;
638
657
  }
639
- function wn(t) {
658
+ function Sn(t) {
640
659
  let e = "";
641
660
  for (let n = 0; n < t.length; n += 1) {
642
661
  const s = t[n];
@@ -647,88 +666,88 @@ function wn(t) {
647
666
  }
648
667
  return -1;
649
668
  }
650
- function $n(t) {
669
+ function Cn(t) {
651
670
  return !t || t[0] !== '"' && t[0] !== "'" ? t : t.length >= 2 && t[t.length - 1] === t[0] ? t.slice(1, -1).trim() : t;
652
671
  }
653
- function xn(t) {
672
+ function Bn(t) {
654
673
  const e = [], n = {}, s = {};
655
674
  t.split(/\r?\n/).forEach((l, r) => {
656
- const u = r + 1, c = kn(l).trim();
675
+ const u = r + 1, c = Tn(l).trim();
657
676
  if (!c) return;
658
677
  if (c.startsWith("-")) {
659
678
  e.push(`第 ${u} 行是列表写法(${c}):清单只认「键: 值」,四个键各占一行 —— 例如 name: 客户档案`);
660
679
  return;
661
680
  }
662
- const d = wn(c);
681
+ const d = Sn(c);
663
682
  if (d < 0) {
664
683
  e.push(`第 ${u} 行不是「键: 值」(${c}):清单只认「键: 值」与 # 注释 —— 要么删掉这一行,要么照 name: 客户档案 写`);
665
684
  return;
666
685
  }
667
686
  const f = c.slice(0, d).trim();
668
- if (!vn.test(f)) {
669
- e.push(`第 ${u} 行的键名不合法(${f}):键名只许字母或下划线开头,认得的键只有 ${xe.join(" / ")}`);
687
+ if (!$n.test(f)) {
688
+ e.push(`第 ${u} 行的键名不合法(${f}):键名只许字母或下划线开头,认得的键只有 ${Te.join(" / ")}`);
670
689
  return;
671
690
  }
672
- if (!xe.includes(f)) {
673
- e.push(`第 ${u} 行的键不认识(${f}):清单只有 ${xe.join(" / ")} 这四个键`);
691
+ if (!Te.includes(f)) {
692
+ e.push(`第 ${u} 行的键不认识(${f}):清单只有 ${Te.join(" / ")} 这四个键`);
674
693
  return;
675
694
  }
676
695
  if (f in s) {
677
696
  e.push(`第 ${u} 行重复写了 ${f}(第 ${s[f]} 行已经写过):一个键只许出现一次`);
678
697
  return;
679
698
  }
680
- s[f] = u, n[f] = $n(c.slice(d + 1).trim());
699
+ s[f] = u, n[f] = Cn(c.slice(d + 1).trim());
681
700
  });
682
- for (const l of xe) {
701
+ for (const l of Te) {
683
702
  const r = n[l] ?? "";
684
703
  if (r === "") {
685
- e.push(`清单里缺少 ${l}(或者是空的):${_n[l]}`);
704
+ e.push(`清单里缺少 ${l}(或者是空的):${En[l]}`);
686
705
  continue;
687
706
  }
688
- l === "id" && !bn.test(r) ? e.push(`清单里的 id 不是 uuid:${r} —— 要 8-4-4-4-12 那种十六进制`) : l === "module" && !gn.test(r) ? e.push(
707
+ l === "id" && !kn.test(r) ? e.push(`清单里的 id 不是 uuid:${r} —— 要 8-4-4-4-12 那种十六进制`) : l === "module" && !wn.test(r) ? e.push(
689
708
  `清单里的 module 不合法:${r} —— 它同时是 Django 的 app label,所以只许小写字母与数字、必须以字母开头(不能有横线与下划线),例如 home / orders`
690
- ) : l === "name" && !yn(r) && e.push(`清单里的 name 不合法:${r} —— 不能超过 ${ze} 个字符、不能含控制字符(中文可以)`);
709
+ ) : l === "name" && !xn(r) && e.push(`清单里的 name 不合法:${r} —— 不能超过 ${Ve} 个字符、不能含控制字符(中文可以)`);
691
710
  }
692
711
  return [n, e];
693
712
  }
694
- function Sn(t) {
695
- return hn.test(t) && !t.split("/").includes("..");
713
+ function Mn(t) {
714
+ return _n.test(t) && !t.split("/").includes("..");
696
715
  }
697
- function En(t) {
698
- const e = [], n = t[Be];
699
- n === void 0 ? e.push(`包里缺入口:必须有 ${Be}(${Je(t)})`) : n.trim() || e.push(`${Be} 不能是空文件`);
700
- const s = t[Te];
716
+ function An(t) {
717
+ const e = [], n = t[Re];
718
+ n === void 0 ? e.push(`包里缺入口:必须有 ${Re}(${tt(t)})`) : n.trim() || e.push(`${Re} 不能是空文件`);
719
+ const s = t[je];
701
720
  let l = {};
702
721
  if (s === void 0)
703
- e.push(`包里缺清单:必须有 ${Te}(${Je(t)})`);
722
+ e.push(`包里缺清单:必须有 ${je}(${tt(t)})`);
704
723
  else if (!s.trim())
705
- e.push(`${Te} 不能是空文件`);
724
+ e.push(`${je} 不能是空文件`);
706
725
  else {
707
- const [r, u] = xn(s);
726
+ const [r, u] = Bn(s);
708
727
  l = r, e.push(...u);
709
728
  }
710
729
  for (const r of Object.keys(t))
711
- Sn(r) || e.push(`文件名不合法:${r}(只许字母数字与 . _ - /,且不许 .. 与绝对路径)`);
730
+ Mn(r) || e.push(`文件名不合法:${r}(只许字母数字与 . _ - /,且不许 .. 与绝对路径)`);
712
731
  return { manifest: l, issues: e };
713
732
  }
714
- function Cn(t) {
733
+ function On(t) {
715
734
  const e = [];
716
735
  if (t.length === 0)
717
736
  return e.push("一个块都没勾:请在「读回改动」的结果里勾上要保存的块"), { selected: 0, issues: e };
718
737
  for (const n of t) {
719
738
  const s = n.name?.trim() || "(没有名字的块)";
720
- for (const l of En(n.files ?? {}).issues) e.push(`${s}:${l}`);
739
+ for (const l of An(n.files ?? {}).issues) e.push(`${s}:${l}`);
721
740
  }
722
741
  return { selected: t.length, issues: e };
723
742
  }
724
- const Ve = "pages.lock.ts";
725
- function Bn(t, e) {
743
+ const nt = "pages.lock.ts";
744
+ function Pn(t, e) {
726
745
  const n = String(t || "").split(/[^A-Za-z0-9]+/).filter(Boolean);
727
746
  if (n.length === 0) return `Page${e + 1}`;
728
747
  const s = n.map((l) => l[0].toUpperCase() + l.slice(1)).join("");
729
748
  return /^[0-9]/.test(s) ? `P${s}` : s;
730
749
  }
731
- function Tn(t, e) {
750
+ function Rn(t, e) {
732
751
  if (!e.has(t))
733
752
  return e.add(t), t;
734
753
  let n = 2;
@@ -736,24 +755,31 @@ function Tn(t, e) {
736
755
  const s = `${t}${n}`;
737
756
  return e.add(s), s;
738
757
  }
739
- function An(t) {
758
+ function jn(t) {
740
759
  const e = (t ?? []).filter((r) => r && typeof r.path == "string" && r.path.trim() !== ""), n = /* @__PURE__ */ new Set(), s = [];
741
760
  e.forEach((r, u) => {
742
761
  const c = r.group?.trim() || "(没写 meta.group)";
743
762
  let d = s.find((f) => f.title === c);
744
- d || (d = { title: c, rows: [] }, s.push(d)), d.rows.push({ key: Tn(Bn(r.path, u), n), row: r });
763
+ d || (d = { title: c, rows: [] }, s.push(d)), d.rows.push({ key: Rn(Pn(r.path, u), n), row: r });
745
764
  });
746
765
  const l = [
747
766
  "/* 生成物:**每次导出都会重写**,别手改 —— 改了下次导出就没了。",
748
767
  " *",
749
768
  " * 这个文件回答「块的前端(index.open.html 那一侧)里我能跳哪些页面、能调什么」。",
750
769
  " *",
751
- " * ① 跳页面:`magicBlock.navigateTab(Page.Orders)` —— 值就是路径,直接写字符串也可以。",
752
- " * ② 当前用户:`await magicBlock.getMe()`(认人只认它,**别从请求参数里取**)。",
753
- " * ③ 调这个块自己的后端:`await magicBackendApi.类名.方法名({...})`。",
770
+ " * ① 跳标签:`magicBlock.navigateTab(Page.Orders)` —— 值就是路径,直接写字符串也可以;",
771
+ " * 那个页面已经开着就切过去,没开就新开一条标签(带参数就写全:`/orders/42?orderId=7`)。",
772
+ " * ② 链接参数:`await magicBlock.context()` → `{ key, path, params, query }`",
773
+ " * (`/orders/42?orderId=7` 里是 `params.id` 与 `query.orderId`)。",
774
+ " * ③ 给这条标签起名:`await magicBlock.setTabTitle('订单 SO-42', 'pi pi-file')`",
775
+ " * —— 整页就是一个块时,标签栏上那条默认只有路由的 `meta.title`,具体是哪一单只有块自己知道。",
776
+ " * ④ 当前用户:`await magicBlock.getMe()`(认人只认它,**别从请求参数里取**)。",
777
+ " * ⑤ 调这个块自己的后端:`await magicBackendApi.类名.方法名({...})`。",
754
778
  " * 有哪些路由、每个方法收什么参数,见**这个块文件夹里的 `api.open.d.ts`**(照它的",
755
779
  " * backend_open.py 生成):路由会被自动注册,前端只要按名字调,不必去读一个 .py。",
756
780
  " *",
781
+ ' * 🔴 块**一律占满它所属的那一条标签页**(高度由宿主按"这一页还剩多少地方"给),滚的是标签页那一层,',
782
+ " * 块自己不出滚动条(别写 `html, body { height: 100% }` / `overflow: auto` 跟宿主打架)。",
757
783
  " * 🔴 `Page` 是 **const 对象**而不是 TS 的 `enum`:navigateTab 收的是路径本身,而 enum 的值是数字。",
758
784
  " * 🔴 路由表**只在前端**:后端不知道页面,所以这份名单是前端按自己的 `router.getRoutes()` 算的。",
759
785
  " * 🔴 `Page` 只是给你查路径用的**常量表**:块运行在不透明源的沙箱 iframe 里,那里没有这个对象 ——",
@@ -777,7 +803,7 @@ function An(t) {
777
803
  "export type PagePath = (typeof Page)[keyof typeof Page]",
778
804
  "",
779
805
  "declare global {",
780
- " /** 宿主注入的桥(**运行期就有**):块里能用的东西只有下面这两个成员。 */",
806
+ " /** 宿主注入的桥(**运行期就有**):块里能用的东西只有下面这几个成员。 */",
781
807
  " interface MagicBlockUser {",
782
808
  " id: string",
783
809
  " /** 登录用户名(OIDC 的 sub 落在这一列)。 */",
@@ -793,10 +819,25 @@ function An(t) {
793
819
  " /** 直接权限 + 组权限的 codename(`app_label.codename`)。 */",
794
820
  " permissions: string[]",
795
821
  " }",
822
+ " /** 这一块所属那条标签的链接参数(块自己读不到地址栏:它跑在 srcdoc 沙箱 iframe 里)。 */",
823
+ " interface MagicBlockTab {",
824
+ " /** 标签的身份 = 完整地址(路径 + query)。 */",
825
+ " key: string",
826
+ " /** 路由路径(不带 query)。 */",
827
+ " path: string",
828
+ " /** 路由参数(`/orders/:id` 上的 id)。 */",
829
+ " params: Record<string, string | string[]>",
830
+ " /** 查询串参数(`?orderId=7` 上的 orderId)。 */",
831
+ " query: Record<string, string | string[]>",
832
+ " }",
796
833
  " const magicBlock: {",
797
834
  " getMe(): Promise<MagicBlockUser>",
798
- " /** 跳到某个页面(只认 `Page` 里那些路径;不在路由表里会被拒绝并列出能跳的)。 */",
835
+ " /** 跳页 = **打开那个页面的标签**(已经开着就切过去)。只认 `Page` 里那些路径;不在路由表里会被拒绝并列出能跳的。 */",
799
836
  " navigateTab(path: PagePath | string): Promise<string>",
837
+ " /** 这一块所属那条标签的链接参数(分享出去的链接带的就是这些)。 */",
838
+ " context(): Promise<MagicBlockTab>",
839
+ " /** 给这一块**所属的那条标签**起名 / 换图标(图标不给就沿用原来的)。 */",
840
+ " setTabTitle(title: string, icon?: string): Promise<boolean>",
800
841
  " }",
801
842
  " /** 一条后端路由的调用形状(参数就是请求正文;失败是 rejected Promise,报文是后端的中文原话)。 */",
802
843
  " interface MagicBackendRoute {",
@@ -812,12 +853,12 @@ function An(t) {
812
853
  ), l.join(`
813
854
  `);
814
855
  }
815
- function ht() {
856
+ function wt() {
816
857
  return typeof window < "u" && typeof window.showDirectoryPicker == "function";
817
858
  }
818
- const On = "这个浏览器没法直接写你本机的文件夹(少了 File System Access API):请用 Chrome / Edge,并且从 https 或 http://localhost 打开这个页面(内网 http 会更少 API)。";
819
- async function Ae() {
820
- if (!ht()) throw new Error(On);
859
+ const Nn = "这个浏览器没法直接写你本机的文件夹(少了 File System Access API):请用 Chrome / Edge,并且从 https 或 http://localhost 打开这个页面(内网 http 会更少 API)。";
860
+ async function Ne() {
861
+ if (!wt()) throw new Error(Nn);
821
862
  try {
822
863
  const t = await window.showDirectoryPicker({ mode: "readwrite", id: "labull-magic-block" });
823
864
  return { name: t.name, handle: t };
@@ -829,15 +870,15 @@ async function Ae() {
829
870
  function Se(t) {
830
871
  return (t instanceof Error ? t.message.trim() : String(t)) || "没有说原因";
831
872
  }
832
- function Mn(t) {
873
+ function In(t) {
833
874
  const e = String(t ?? "").split("/");
834
875
  for (const n of e)
835
876
  if (!n || n === "." || n === ".." || n.includes("\\") || /^[A-Za-z]:/.test(n))
836
877
  throw new Error(`路径不合法:${t}(要相对路径,不许 .. / 盘符 / 反斜杠)`);
837
878
  return e;
838
879
  }
839
- const Pn = 8;
840
- function Rn(t) {
880
+ const Ln = 8;
881
+ function Dn(t) {
841
882
  const e = /* @__PURE__ */ new Map();
842
883
  return (n) => {
843
884
  const s = n.join("\0"), l = e.get(s);
@@ -845,40 +886,40 @@ function Rn(t) {
845
886
  let r = Promise.resolve(t);
846
887
  for (let u = 0; u < n.length; u += 1) {
847
888
  const c = n[u], d = n.slice(0, u + 1).join("\0"), f = e.get(d);
848
- r = f ?? r.then((_) => _.getDirectoryHandle(c, { create: !0 })), f || e.set(d, r);
889
+ r = f ?? r.then((w) => w.getDirectoryHandle(c, { create: !0 })), f || e.set(d, r);
849
890
  }
850
891
  return r;
851
892
  };
852
893
  }
853
- async function jn(t, e, n) {
854
- const s = Object.entries(e ?? {}).map(([_, y]) => ({ path: _, parts: Mn(_), body: String(y ?? "") })), l = s.length, r = [], u = Rn(t.handle);
894
+ async function Fn(t, e, n) {
895
+ const s = Object.entries(e ?? {}).map(([w, y]) => ({ path: w, parts: In(w), body: String(y ?? "") })), l = s.length, r = [], u = Dn(t.handle);
855
896
  let c = 0, d = 0;
856
897
  n?.(0, l);
857
898
  const f = async () => {
858
899
  for (; ; ) {
859
- const _ = c;
900
+ const w = c;
860
901
  c += 1;
861
- const y = s[_];
902
+ const y = s[w];
862
903
  if (!y) return;
863
904
  try {
864
- const L = await (await (await u(y.parts.slice(0, -1))).getFileHandle(y.parts[y.parts.length - 1], { create: !0 })).createWritable();
905
+ const B = await (await (await u(y.parts.slice(0, -1))).getFileHandle(y.parts[y.parts.length - 1], { create: !0 })).createWritable();
865
906
  try {
866
- await L.write(y.body);
907
+ await B.write(y.body);
867
908
  } finally {
868
- await L.close();
909
+ await B.close();
869
910
  }
870
911
  d += 1;
871
- } catch (S) {
872
- r.push({ path: y.path, message: Se(S) });
912
+ } catch (_) {
913
+ r.push({ path: y.path, message: Se(_) });
873
914
  }
874
915
  n?.(d + r.length, l);
875
916
  }
876
917
  };
877
- return await Promise.all(Array.from({ length: Math.max(1, Math.min(Pn, l)) }, () => f())), r.sort((_, y) => _.path < y.path ? -1 : _.path > y.path ? 1 : 0), { written: d, failed: r, total: l };
918
+ return await Promise.all(Array.from({ length: Math.max(1, Math.min(Ln, l)) }, () => f())), r.sort((w, y) => w.path < y.path ? -1 : w.path > y.path ? 1 : 0), { written: d, failed: r, total: l };
878
919
  }
879
- async function Nn(t, e) {
920
+ async function zn(t, e) {
880
921
  const n = { items: [], topCount: 0, files: 0, dirs: 0 }, s = async (l, r) => {
881
- for (const u of await ve(l)) {
922
+ for (const u of await _e(l)) {
882
923
  if (u.kind === "file") {
883
924
  n.files += 1;
884
925
  continue;
@@ -886,7 +927,7 @@ async function Nn(t, e) {
886
927
  n.dirs += 1, !(r >= e.maxDepth) && (e.skipDirs.includes(u.name) || await s(u, r + 1));
887
928
  }
888
929
  };
889
- for (const l of await ve(t.handle))
930
+ for (const l of await _e(t.handle))
890
931
  if (n.items.push({ name: l.name, dir: l.kind === "directory" }), l.kind === "file") n.files += 1;
891
932
  else {
892
933
  if (n.dirs += 1, e.skipDirs.includes(l.name) || e.maxDepth <= 0) continue;
@@ -894,45 +935,45 @@ async function Nn(t, e) {
894
935
  }
895
936
  return n.topCount = n.items.length, n;
896
937
  }
897
- async function In(t) {
938
+ async function Hn(t) {
898
939
  const e = [];
899
- for (const s of await ve(t.handle)) e.push(s.name);
940
+ for (const s of await _e(t.handle)) e.push(s.name);
900
941
  let n = 0;
901
942
  for (const s of e)
902
943
  await t.handle.removeEntry(s, { recursive: !0 }), n += 1;
903
944
  return n;
904
945
  }
905
- function Ln(t, e) {
946
+ function Kn(t, e) {
906
947
  if (t.name === e.blocksDir)
907
948
  throw new Error(
908
949
  `你选中的是「${e.blocksDir}」这一层(它就是放代码的那一层):导出会铺成 ${e.blocksDir}/${e.blocksDir}/…。请选它**上面**那一层 —— 也就是开发目录本身。`
909
950
  );
910
951
  }
911
- async function ve(t) {
952
+ async function _e(t) {
912
953
  const e = [];
913
954
  for await (const n of t.values()) e.push(n);
914
955
  return e.sort((n, s) => n.name < s.name ? -1 : n.name > s.name ? 1 : 0), e;
915
956
  }
916
- function zn(t) {
957
+ function qn(t) {
917
958
  return t.charCodeAt(0) === 65279 ? t.slice(1) : t;
918
959
  }
919
- function Dn(t) {
960
+ function Un(t) {
920
961
  const e = t.lastIndexOf(".");
921
962
  return e <= 0 ? "" : t.slice(e).toLowerCase();
922
963
  }
923
- async function bt(t, e, n, s) {
964
+ async function $t(t, e, n, s) {
924
965
  const l = {};
925
- for (const r of await ve(t)) {
966
+ for (const r of await _e(t)) {
926
967
  const u = e ? `${e}/${r.name}` : r.name;
927
968
  if (r.kind === "directory") {
928
969
  if (n.skipDirs.includes(r.name)) continue;
929
970
  const c = r;
930
- for (const [d, f] of Object.entries(await bt(c, u, n, s)))
971
+ for (const [d, f] of Object.entries(await $t(c, u, n, s)))
931
972
  l[`${r.name}/${d}`] = f;
932
973
  continue;
933
974
  }
934
975
  if (!n.platformFiles.includes(r.name)) {
935
- if (!n.textExt.includes(Dn(r.name))) {
976
+ if (!n.textExt.includes(Un(r.name))) {
936
977
  s.failures.push({
937
978
  kind: "file",
938
979
  where: u,
@@ -950,7 +991,7 @@ async function bt(t, e, n, s) {
950
991
  });
951
992
  continue;
952
993
  }
953
- l[r.name] = zn(await c.text());
994
+ l[r.name] = qn(await c.text());
954
995
  } catch (c) {
955
996
  s.failures.push({ kind: "file", where: u, message: `读不了这个文件:${Se(c)}` });
956
997
  }
@@ -958,10 +999,10 @@ async function bt(t, e, n, s) {
958
999
  }
959
1000
  return l;
960
1001
  }
961
- async function gt(t, e, n, s, l) {
962
- const r = await ve(t), u = r.filter((d) => d.kind === "directory"), c = r.filter((d) => d.kind === "file");
1002
+ async function xt(t, e, n, s, l) {
1003
+ const r = await _e(t), u = r.filter((d) => d.kind === "directory"), c = r.filter((d) => d.kind === "file");
963
1004
  if (u.length === 0 || c.some((d) => d.name === s.entry)) {
964
- l.folders.push({ where: e.join("/"), files: await bt(t, e.join("/"), s, l) });
1005
+ l.folders.push({ where: e.join("/"), files: await $t(t, e.join("/"), s, l) });
965
1006
  return;
966
1007
  }
967
1008
  for (const d of c)
@@ -980,385 +1021,393 @@ async function gt(t, e, n, s, l) {
980
1021
  });
981
1022
  continue;
982
1023
  }
983
- await gt(d, [...e, d.name], n + 1, s, l);
1024
+ await xt(d, [...e, d.name], n + 1, s, l);
984
1025
  }
985
1026
  }
986
- function Ye(t) {
1027
+ function ot(t) {
987
1028
  return t >= 1024 * 1024 ? `${(t / 1024 / 1024).toFixed(1)} MB` : `${Math.max(1, Math.round(t / 1024))} KB`;
988
1029
  }
989
- async function Fn(t, e) {
1030
+ async function Jn(t, e) {
990
1031
  const n = { root: t.name, folders: [], failures: [], truncated: !1 };
991
- await gt(t.handle, [], 0, e, n);
1032
+ await xt(t.handle, [], 0, e, n);
992
1033
  const s = n.folders.reduce(
993
1034
  (l, r) => l + Object.values(r.files).reduce((u, c) => u + c.length, 0),
994
1035
  0
995
1036
  );
996
1037
  if (s > e.maxBodyBytes)
997
1038
  throw new Error(
998
- `这个目录读到的正文有 ${Ye(s)},超过一次读回的上限 ${Ye(e.maxBodyBytes)}:请先只留要改的那几个块,或者把大文件挪走。`
1039
+ `这个目录读到的正文有 ${ot(s)},超过一次读回的上限 ${ot(e.maxBodyBytes)}:请先只留要改的那几个块,或者把大文件挪走。`
999
1040
  );
1000
1041
  return n;
1001
1042
  }
1002
- const Hn = {
1043
+ const Vn = {
1003
1044
  key: 0,
1004
1045
  class: "mbc"
1005
- }, Kn = { class: "mbc__head" }, Un = ["disabled"], qn = {
1046
+ }, Gn = { class: "mbc__head" }, Yn = ["disabled"], Wn = {
1006
1047
  key: 0,
1007
1048
  class: "mbc__error"
1008
- }, Gn = {
1049
+ }, Zn = {
1009
1050
  key: 1,
1010
1051
  class: "mbc__notice"
1011
- }, Jn = { class: "mbc__panel" }, Vn = { class: "mbc__title" }, Yn = { class: "mbc__list" }, Wn = ["title", "onClick"], Zn = { class: "mbc__module" }, Xn = { class: "mbc__name" }, Qn = {
1052
+ }, Xn = { class: "mbc__panel" }, Qn = { class: "mbc__title" }, eo = { class: "mbc__list" }, to = ["title", "onClick"], no = { class: "mbc__module" }, oo = { class: "mbc__name" }, so = {
1012
1053
  key: 0,
1013
1054
  class: "mbc__where"
1014
- }, eo = {
1055
+ }, ao = {
1015
1056
  key: 0,
1016
1057
  class: "mbc__detail"
1017
- }, to = {
1058
+ }, io = {
1018
1059
  key: 0,
1019
1060
  class: "mbc__hint"
1020
- }, no = { class: "mbc__meta" }, oo = { class: "mbc__mono" }, so = { class: "mbc__actions" }, ao = ["disabled", "onClick"], io = ["disabled", "onClick"], lo = ["disabled", "onClick"], ro = { class: "mbc__panel" }, co = { class: "mbc__field" }, uo = ["value"], po = ["disabled"], fo = ["disabled"], mo = {
1061
+ }, lo = { class: "mbc__meta" }, ro = { class: "mbc__mono" }, co = { class: "mbc__actions" }, uo = ["disabled", "onClick"], po = ["disabled", "onClick"], fo = ["disabled", "onClick"], mo = { class: "mbc__panel" }, bo = { class: "mbc__field" }, ho = ["value"], go = ["disabled"], vo = ["disabled"], yo = {
1021
1062
  key: 0,
1022
1063
  class: "mbc__hint"
1023
- }, ho = ["aria-valuenow"], bo = {
1064
+ }, _o = ["aria-valuenow"], ko = {
1024
1065
  key: 3,
1025
1066
  class: "mbc__confirm"
1026
- }, go = { class: "mbc__confirm-title" }, vo = { class: "mbc__confirm-body" }, yo = {
1067
+ }, wo = { class: "mbc__confirm-title" }, $o = { class: "mbc__confirm-body" }, xo = {
1027
1068
  key: 0,
1028
1069
  class: "mbc__mono"
1029
- }, _o = { class: "mbc__actions" }, ko = ["disabled"], wo = ["disabled"], $o = ["disabled"], xo = { class: "mbc__panel" }, So = { class: "mbc__field" }, Eo = ["value"], Co = ["disabled"], Bo = ["disabled"], To = {
1070
+ }, Eo = { class: "mbc__actions" }, To = ["disabled"], So = ["disabled"], Co = ["disabled"], Bo = { class: "mbc__panel" }, Mo = { class: "mbc__field" }, Ao = ["value"], Oo = ["disabled"], Po = ["disabled"], Ro = {
1030
1071
  key: 0,
1031
1072
  class: "mbc__hint"
1032
- }, Ao = {
1073
+ }, jo = {
1033
1074
  key: 1,
1034
1075
  class: "mbc__hint"
1035
- }, Oo = {
1076
+ }, No = {
1036
1077
  key: 0,
1037
1078
  class: "mbc__scan"
1038
- }, Mo = { class: "mbc__pick" }, Po = ["disabled", "checked", "onChange"], Ro = { class: "mbc__name" }, jo = { class: "mbc__module" }, No = { class: "mbc__hint" }, Io = { class: "mbc__mono" }, Lo = {
1079
+ }, Io = { class: "mbc__pick" }, Lo = ["disabled", "checked", "onChange"], Do = { class: "mbc__name" }, Fo = { class: "mbc__module" }, zo = { class: "mbc__hint" }, Ho = { class: "mbc__mono" }, Ko = {
1039
1080
  key: 0,
1040
1081
  class: "mbc__problem"
1041
- }, zo = { class: "mbc__hint mbc__mono" }, Do = {
1082
+ }, qo = { class: "mbc__hint mbc__mono" }, Uo = {
1042
1083
  key: 1,
1043
1084
  class: "mbc__hint"
1044
- }, Fo = {
1085
+ }, Jo = {
1045
1086
  key: 2,
1046
1087
  class: "mbc__problem"
1047
- }, Ho = {
1088
+ }, Vo = {
1048
1089
  key: 3,
1049
1090
  class: "mbc__failures"
1050
- }, Ko = { class: "mbc__field mbc__field--end" }, Uo = ["disabled"], qo = {
1091
+ }, Go = { class: "mbc__field mbc__field--end" }, Yo = ["disabled"], Wo = {
1051
1092
  key: 2,
1052
1093
  class: "mbc__panel"
1053
- }, Go = { class: "mbc__title" }, Jo = {
1094
+ }, Zo = { class: "mbc__title" }, Xo = {
1054
1095
  key: 0,
1055
1096
  class: "mbc__failures"
1056
- }, Vo = {
1097
+ }, Qo = {
1057
1098
  key: 1,
1058
1099
  class: "mbc__failures"
1059
- }, Yo = { key: 0 }, Wo = {
1100
+ }, es = { key: 0 }, ts = {
1060
1101
  key: 1,
1061
1102
  class: "mbc__failures mbc__failures--nested"
1062
- }, Oe = 2, Zo = /* @__PURE__ */ We({
1103
+ }, Ie = 2, ns = /* @__PURE__ */ Je({
1063
1104
  __name: "MagicBlockConsole",
1064
1105
  setup(t) {
1065
- const e = { modified: "有改动", unchanged: "没改动", missing: "目录里没有" }, { isStaff: n } = nt(), s = tt(), l = et(), r = w(!1), u = w(""), c = w([]), d = w(""), f = w(""), _ = w(""), y = w(!1), S = w(!1), B = w(!1), L = w(!1), Y = w(!1), A = w(null), T = w(null), U = w(null), N = w(""), z = w(null), le = w({}), G = w([]), W = w([]), M = w(null), E = w({ active: !1, percent: 0, stage: "", failed: !1 }), Ee = C(() => ({
1066
- width: `${Math.max(0, Math.min(100, E.value.percent))}%`,
1067
- background: E.value.failed ? "var(--sp-color-danger)" : "var(--sp-color-primary, var(--primary-color))"
1106
+ const e = { modified: "有改动", unchanged: "没改动", missing: "目录里没有" }, { isStaff: n } = rt(), s = lt(), { active: l } = Nt(), r = (i) => !ct(i, s), u = $(!1), c = $(""), d = $([]), f = $(""), w = $(""), y = $(""), _ = $(!1), N = $(!1), B = $(!1), V = $(!1), ee = $(!1), M = $(null), S = $(null), G = $(null), te = $(""), I = $(null), ne = $({}), Y = $([]), oe = $([]), A = $(null), T = $({ active: !1, percent: 0, stage: "", failed: !1 }), q = P(() => ({
1107
+ width: `${Math.max(0, Math.min(100, T.value.percent))}%`,
1108
+ background: T.value.failed ? "var(--sp-color-danger)" : "var(--sp-color-primary, var(--primary-color))"
1068
1109
  }));
1069
- function H(i, o) {
1070
- E.value = { active: !0, percent: Math.max(E.value.percent, i), stage: o, failed: !1 };
1110
+ function D(i, o) {
1111
+ T.value = { active: !0, percent: Math.max(T.value.percent, i), stage: o, failed: !1 };
1071
1112
  try {
1072
- const a = window.localStorage.getItem("mb:progress") ?? "[]", g = JSON.parse(a);
1073
- g.push({ p: E.value.percent, s: o, t: Math.round(performance.now()) }), window.localStorage.setItem("mb:progress", JSON.stringify(g));
1113
+ const a = window.localStorage.getItem("mb:progress") ?? "[]", h = JSON.parse(a);
1114
+ h.push({ p: T.value.percent, s: o, t: Math.round(performance.now()) }), window.localStorage.setItem("mb:progress", JSON.stringify(h));
1074
1115
  } catch {
1075
1116
  }
1076
1117
  }
1077
- function Z(i, o) {
1078
- H(i ? 100 : E.value.percent, o), E.value = { active: !i, percent: i ? 100 : E.value.percent, stage: o, failed: !i };
1118
+ function W(i, o) {
1119
+ D(i ? 100 : T.value.percent, o), T.value = { active: !i, percent: i ? 100 : T.value.percent, stage: o, failed: !i };
1079
1120
  }
1080
- const re = (i) => (i.disabledReason ?? "").trim(), K = (i) => (i.issues ?? []).map((o) => String(o?.message ?? "")).filter(Boolean), ce = (i) => en(i.id);
1081
- function ye(i) {
1082
- d.value = d.value === i.id ? "" : i.id;
1083
- const o = l?.path ?? "", a = tn(i.id, o);
1084
- mt(i.id);
1085
- const g = i.name || i.id;
1086
- if (a) {
1087
- _.value = `「${g}」不在这一页:正在跳到 ${a}`, s?.push?.(a);
1121
+ const ke = (i) => (i.disabledReason ?? "").trim(), pe = (i) => (i.issues ?? []).map((o) => String(o?.message ?? "")).filter(Boolean), re = (i) => sn(i.id);
1122
+ function fe(i) {
1123
+ f.value = f.value === i.id ? "" : i.id;
1124
+ const o = l.value;
1125
+ kt(i.id);
1126
+ const a = i.name || i.id, h = re(i);
1127
+ if (h.length === 0) {
1128
+ y.value = `「${a}」这次会话里还没在哪条标签上露过面:先打开挂着它的那一页,再点一次`;
1129
+ return;
1130
+ }
1131
+ if (h.includes(o)) {
1132
+ y.value = `「${a}」就在这一条标签上(${h.join(" / ")}):已经把它标红`;
1133
+ return;
1134
+ }
1135
+ const x = an(i.id, o, r);
1136
+ if (x) {
1137
+ y.value = `「${a}」不在这一条标签上:正在切到 ${x} 那条标签`, De(x);
1088
1138
  return;
1089
1139
  }
1090
- const $ = ce(i);
1091
- _.value = $.length === 0 ? `「${g}」这次会话里还没在页面上露过面:先打开挂着它的那一页,再点一次` : `「${g}」就在这一页(${$.join(" / ")}):已经把它标红`;
1140
+ y.value = `「${a}」只挂在带参数的实例标签上(${h.join(" / ")}):不替你挑一单 —— 自己打开要看的那一页再点`;
1092
1141
  }
1093
1142
  function Ce(i) {
1094
- const o = ce(i), a = o.length === 0 ? "点一下:这次会话里它还没在页面上露过面" : `点一下:把「${i.name || i.id}」标红并跳到 ${o.join(" / ")}`, g = re(i);
1095
- return g ? `${g}
1143
+ const o = re(i), a = o.length === 0 ? "点一下:这次会话里它还没在哪条标签上露过面" : `点一下:把「${i.name || i.id}」标红,并在需要时切到挂着它的标签(${o.join(" / ")})`, h = ke(i);
1144
+ return h ? `${h}
1096
1145
  ${a}` : a;
1097
1146
  }
1098
- const _e = C(() => {
1099
- const i = u.value.trim().toLowerCase();
1100
- return i ? c.value.filter((o) => `${o.module} ${o.name} ${o.brief}`.toLowerCase().includes(i)) : c.value;
1101
- }), fe = C(() => (z.value?.blocks ?? []).filter((i) => i.canApply)), ke = C(() => fe.value.filter((i) => le.value[i.id] === !0));
1102
- function me() {
1147
+ const me = P(() => {
1148
+ const i = c.value.trim().toLowerCase();
1149
+ return i ? d.value.filter((o) => `${o.module} ${o.name} ${o.brief}`.toLowerCase().includes(i)) : d.value;
1150
+ }), we = P(() => (I.value?.blocks ?? []).filter((i) => i.canApply)), F = P(() => we.value.filter((i) => ne.value[i.id] === !0));
1151
+ function se() {
1103
1152
  const i = s?.getRoutes?.() ?? [], o = /* @__PURE__ */ new Set(), a = [];
1104
- for (const g of i) {
1105
- const $ = typeof g?.path == "string" ? g.path.trim() : "";
1106
- if (!$ || o.has($) || $.includes(":") || $.includes("*") || g.redirect || !g.components?.default || g.meta?.tab === !1) continue;
1107
- o.add($);
1108
- const F = g.meta?.title ?? g.meta?.sub, O = g.meta?.group;
1153
+ for (const h of i) {
1154
+ const x = typeof h?.path == "string" ? h.path.trim() : "";
1155
+ if (!x || o.has(x) || x.includes(":") || x.includes("*") || h.redirect || !h.components?.default || h.meta?.tab === !1) continue;
1156
+ o.add(x);
1157
+ const L = h.meta?.title ?? h.meta?.sub, O = h.meta?.group;
1109
1158
  a.push({
1110
- path: $,
1111
- title: typeof F == "string" && F.trim() ? F.trim() : $,
1159
+ path: x,
1160
+ title: typeof L == "string" && L.trim() ? L.trim() : x,
1112
1161
  group: typeof O == "string" ? O.trim() : ""
1113
1162
  });
1114
1163
  }
1115
1164
  return a;
1116
1165
  }
1117
- function R(i) {
1166
+ function Z(i) {
1118
1167
  return (i instanceof Error ? i.message.trim() : String(i)) || "请求没有到达后端(网络或登录态的问题),请重试";
1119
1168
  }
1120
- function ee(i) {
1169
+ function Be(i) {
1121
1170
  const o = i?.issues;
1122
1171
  return Array.isArray(o) ? o.map((a) => typeof a == "string" ? a : String(a?.message ?? "")).filter(Boolean) : [];
1123
1172
  }
1124
- async function te(i, o) {
1173
+ async function ae(i, o) {
1125
1174
  const a = JSON.stringify(o);
1126
1175
  try {
1127
- return await V(i, { method: "POST", body: a });
1128
- } catch (g) {
1129
- const $ = R(g), F = await fetch(`http://localhost:3000${i}`, {
1176
+ return await J(i, { method: "POST", body: a });
1177
+ } catch (h) {
1178
+ const x = Z(h), L = await fetch(`http://localhost:3000${i}`, {
1130
1179
  method: "POST",
1131
1180
  credentials: "include",
1132
- headers: { "Content-Type": "application/json", ...Me("POST", !0) },
1181
+ headers: { "Content-Type": "application/json", ...Le("POST", !0) },
1133
1182
  body: a
1134
- }).then((X) => X.json()).catch(() => null), O = ee(F);
1135
- throw O.length === 0 ? new Error($) : new Error(`${String(F?.message ?? $)}
1183
+ }).then((X) => X.json()).catch(() => null), O = Be(L);
1184
+ throw O.length === 0 ? new Error(x) : new Error(`${String(L?.message ?? x)}
1136
1185
  - ${O.join(`
1137
1186
  - `)}`);
1138
1187
  }
1139
1188
  }
1140
- async function ne() {
1189
+ async function H() {
1141
1190
  try {
1142
- const i = await V("/magic-blocks/index");
1143
- c.value = i.blocks ?? [];
1191
+ const i = await J("/magic-blocks/index");
1192
+ d.value = i.blocks ?? [];
1144
1193
  } catch (i) {
1145
- f.value = R(i);
1194
+ w.value = Z(i);
1146
1195
  }
1147
1196
  }
1148
- async function D(i, o) {
1149
- o.value = !0, f.value = "";
1197
+ async function m(i, o) {
1198
+ o.value = !0, w.value = "";
1150
1199
  try {
1151
- await i(), Jt();
1200
+ await i(), Zt();
1152
1201
  } catch (a) {
1153
- f.value = R(a);
1202
+ w.value = Z(a);
1154
1203
  } finally {
1155
1204
  o.value = !1;
1156
1205
  }
1157
1206
  }
1158
- const oe = (i) => D(async () => {
1159
- S.value = !0;
1207
+ const k = (i) => m(async () => {
1208
+ N.value = !0;
1160
1209
  try {
1161
- await V("/magic-blocks/check", { method: "POST", body: JSON.stringify(i ? { blocks: [i] } : {}) }), _.value = i ? "这一块重新体检完了" : "全部块重新体检完了", await ne();
1210
+ await J("/magic-blocks/check", { method: "POST", body: JSON.stringify(i ? { blocks: [i] } : {}) }), y.value = i ? "这一块重新体检完了" : "全部块重新体检完了", await H();
1162
1211
  } finally {
1163
- S.value = !1;
1212
+ N.value = !1;
1164
1213
  }
1165
- }, y), m = (i) => D(async () => {
1166
- const o = await Ae();
1167
- i === "export" ? (A.value = o, T.value || (T.value = o)) : (T.value = o, A.value || (A.value = o)), _.value = i === "export" ? `导出目录:${o.name}${T.value === o ? "(读回目录也填成它了)" : ""}` : `读回目录:${o.name}`;
1168
- }, y);
1169
- async function k() {
1170
- if (U.value) return U.value;
1171
- const i = await V("/magic-blocks/rules");
1172
- return U.value = i.rules, i.rules;
1214
+ }, _), C = (i) => m(async () => {
1215
+ const o = await Ne();
1216
+ i === "export" ? (M.value = o, S.value || (S.value = o)) : (S.value = o, M.value || (M.value = o)), y.value = i === "export" ? `导出目录:${o.name}${S.value === o ? "(读回目录也填成它了)" : ""}` : `读回目录:${o.name}`;
1217
+ }, _);
1218
+ async function z() {
1219
+ if (G.value) return G.value;
1220
+ const i = await J("/magic-blocks/rules");
1221
+ return G.value = i.rules, i.rules;
1173
1222
  }
1174
- const I = () => D(async () => {
1175
- if (!ht()) throw new Error("这个浏览器没法直接写你本机的文件夹:请用 Chrome / Edge,并从 https 或 localhost 打开");
1176
- B.value = !0, _.value = "", N.value = "", f.value = "", E.value = { active: !0, percent: 0, stage: "准备…", failed: !1 };
1223
+ const $e = () => m(async () => {
1224
+ if (!wt()) throw new Error("这个浏览器没法直接写你本机的文件夹:请用 Chrome / Edge,并从 https 或 localhost 打开");
1225
+ B.value = !0, y.value = "", te.value = "", w.value = "", T.value = { active: !0, percent: 0, stage: "准备…", failed: !1 };
1177
1226
  try {
1178
- const i = A.value ?? await Ae();
1179
- A.value = i, T.value || (T.value = i);
1180
- const o = await te("/magic-blocks/export", {});
1181
- U.value = o.rules, Ln(i, o.rules);
1182
- const a = await Nn(i, o.rules);
1227
+ const i = M.value ?? await Ne();
1228
+ M.value = i, S.value || (S.value = i);
1229
+ const o = await ae("/magic-blocks/export", {});
1230
+ G.value = o.rules, Kn(i, o.rules);
1231
+ const a = await zn(i, o.rules);
1183
1232
  if (a.topCount > 0) {
1184
- H(5, "等你确认要不要先清空"), M.value = { target: i, inventory: a };
1233
+ D(5, "等你确认要不要先清空"), A.value = { target: i, inventory: a };
1185
1234
  return;
1186
1235
  }
1187
- await se(i, o, !1);
1236
+ await be(i, o, !1);
1188
1237
  } catch (i) {
1189
- throw Z(!1, "导出失败"), i;
1238
+ throw W(!1, "导出失败"), i;
1190
1239
  } finally {
1191
1240
  B.value = !1;
1192
1241
  }
1193
- }, y);
1194
- async function se(i, o, a) {
1242
+ }, _);
1243
+ async function be(i, o, a) {
1195
1244
  try {
1196
- H(20, "收主题与控件清单…");
1197
- const g = { ...o.files, [Ve]: An(me()) };
1198
- let $ = "";
1199
- await new Promise((P) => {
1200
- setTimeout(P, 0);
1245
+ D(20, "收主题与控件清单…");
1246
+ const h = { ...o.files, [nt]: jn(se()) };
1247
+ let x = "";
1248
+ await new Promise((R) => {
1249
+ setTimeout(R, 0);
1201
1250
  });
1202
1251
  try {
1203
- const P = ft();
1204
- g[pe] = P.css, g[je] = Wt(), $ = P.skipped.length > 0 ? `;⚠️ 有 ${P.skipped.length} 张样式表读不到规则(跨源):${P.skipped.join(" / ")}` : "";
1205
- } catch (P) {
1206
- $ = `;主题 CSS 没收成(${R(P)}):${pe} 没写,其余照旧`;
1252
+ const R = _t();
1253
+ h[de] = R.css, h[He] = en(), x = R.skipped.length > 0 ? `;⚠️ 有 ${R.skipped.length} 张样式表读不到规则(跨源):${R.skipped.join(" / ")}` : "";
1254
+ } catch (R) {
1255
+ x = `;主题 CSS 没收成(${Z(R)}):${de} 没写,其余照旧`;
1207
1256
  }
1208
- let F = "";
1209
- a && (H(35, "清空目录…"), F = `,先清掉了 ${await In(i)} 项`);
1210
- const O = Object.keys(g).length, X = a ? 45 : 30;
1211
- H(X, `写文件 0/${O}…`);
1212
- const ae = await jn(i, g, (P, He) => {
1213
- H(X + Math.round(P / Math.max(1, He) * (95 - X)), `写文件 ${P}/${He}…`);
1257
+ let L = "";
1258
+ a && (D(35, "清空目录…"), L = `,先清掉了 ${await Hn(i)} 项`);
1259
+ const O = Object.keys(h).length, X = a ? 45 : 30;
1260
+ D(X, `写文件 0/${O}…`);
1261
+ const ie = await Fn(i, h, (R, Ye) => {
1262
+ D(X + Math.round(R / Math.max(1, Ye) * (95 - X)), `写文件 ${R}/${Ye}…`);
1214
1263
  });
1215
- H(98, "收尾…");
1216
- const St = ae.failed.length > 0 ? `;⚠️ ${ae.failed.length} 个文件没写成:${ae.failed.slice(0, 3).map((P) => `${P.path}(${P.message})`).join("、")}` + (ae.failed.length > 3 ? ` 等 ${ae.failed.length} 条` : "") : "";
1217
- N.value = `铺到「${i.name}」:${o.blocks} 个块、${ae.written} 个文件(含 ${Ve} / ${pe} / ${je})${F}${St}${$}`, _.value = ae.failed.length > 0 ? "导出完了,但有文件没写成(见下面那句)" : "导出完了:用你自己的编辑器改,改完回这里「读回改动」", Z(!0, "完成");
1218
- } catch (g) {
1219
- throw Z(!1, "导出中途失败(已经铺进去的文件不会自己删掉)"), g;
1264
+ D(98, "收尾…");
1265
+ const Ct = ie.failed.length > 0 ? `;⚠️ ${ie.failed.length} 个文件没写成:${ie.failed.slice(0, 3).map((R) => `${R.path}(${R.message})`).join("、")}` + (ie.failed.length > 3 ? ` 等 ${ie.failed.length} 条` : "") : "";
1266
+ te.value = `铺到「${i.name}」:${o.blocks} 个块、${ie.written} 个文件(含 ${nt} / ${de} / ${He})${L}${Ct}${x}`, y.value = ie.failed.length > 0 ? "导出完了,但有文件没写成(见下面那句)" : "导出完了:用你自己的编辑器改,改完回这里「读回改动」", W(!0, "完成");
1267
+ } catch (h) {
1268
+ throw W(!1, "导出中途失败(已经铺进去的文件不会自己删掉)"), h;
1220
1269
  }
1221
1270
  }
1222
- const vt = () => D(async () => {
1223
- const i = M.value;
1224
- if (M.value = null, !!i) {
1271
+ const he = () => m(async () => {
1272
+ const i = A.value;
1273
+ if (A.value = null, !!i) {
1225
1274
  B.value = !0;
1226
1275
  try {
1227
- H(15, "重新取一份开发包…");
1228
- const o = await te("/magic-blocks/export", {});
1229
- U.value = o.rules, await se(i.target, o, !0);
1276
+ D(15, "重新取一份开发包…");
1277
+ const o = await ae("/magic-blocks/export", {});
1278
+ G.value = o.rules, await be(i.target, o, !0);
1230
1279
  } catch (o) {
1231
- throw Z(!1, "导出失败"), o;
1280
+ throw W(!1, "导出失败"), o;
1232
1281
  } finally {
1233
1282
  B.value = !1;
1234
1283
  }
1235
1284
  }
1236
- }, y), yt = () => D(async () => {
1237
- const i = M.value;
1238
- if (M.value = null, !!i) {
1285
+ }, _), Me = () => m(async () => {
1286
+ const i = A.value;
1287
+ if (A.value = null, !!i) {
1239
1288
  B.value = !0;
1240
1289
  try {
1241
- H(15, "重新取一份开发包…");
1242
- const o = await te("/magic-blocks/export", {});
1243
- U.value = o.rules, await se(i.target, o, !1);
1290
+ D(15, "重新取一份开发包…");
1291
+ const o = await ae("/magic-blocks/export", {});
1292
+ G.value = o.rules, await be(i.target, o, !1);
1244
1293
  } catch (o) {
1245
- throw Z(!1, "导出失败"), o;
1294
+ throw W(!1, "导出失败"), o;
1246
1295
  } finally {
1247
1296
  B.value = !1;
1248
1297
  }
1249
1298
  }
1250
- }, y);
1251
- function _t() {
1252
- M.value = null, E.value = { active: !1, percent: 0, stage: "", failed: !1 }, _.value = "这次没有导出(目录里的东西一个字节都没动)", N.value = "";
1299
+ }, _);
1300
+ function Ae() {
1301
+ A.value = null, T.value = { active: !1, percent: 0, stage: "", failed: !1 }, y.value = "这次没有导出(目录里的东西一个字节都没动)", te.value = "";
1253
1302
  }
1254
- const De = () => D(async () => {
1255
- const i = T.value ?? await Ae();
1256
- T.value = i, A.value || (A.value = i), L.value = !0, _.value = "", G.value = [], W.value = [];
1303
+ const xe = () => m(async () => {
1304
+ const i = S.value ?? await Ne();
1305
+ S.value = i, M.value || (M.value = i), V.value = !0, y.value = "", Y.value = [], oe.value = [];
1257
1306
  try {
1258
- const o = await k().catch((O) => {
1259
- throw new Error(`取不到扫描规则(GET /magic-blocks/rules):${R(O)}`);
1260
- }), a = await Fn(i, o), g = await V("/magic-blocks/read", {
1307
+ const o = await z().catch((O) => {
1308
+ throw new Error(`取不到扫描规则(GET /magic-blocks/rules):${Z(O)}`);
1309
+ }), a = await Jn(i, o), h = await J("/magic-blocks/read", {
1261
1310
  method: "POST",
1262
1311
  body: JSON.stringify({ ...a, includeMissing: !1 })
1263
1312
  });
1264
- z.value = g;
1265
- const $ = {};
1266
- for (const O of g.blocks ?? []) $[O.id] = O.status === "modified" && O.canApply;
1267
- le.value = $;
1268
- const F = (g.blocks ?? []).reduce((O, X) => ({ ...O, [X.status]: (O[X.status] ?? 0) + 1 }), {});
1269
- _.value = `扫到 ${g.folders} 个文件夹、${g.files} 个文件:有改动 ${F.modified ?? 0} / 没改动 ${F.unchanged ?? 0}` + (g.complete ? "" : "(层数到了上限,没走完,可能还有块没扫到)");
1313
+ I.value = h;
1314
+ const x = {};
1315
+ for (const O of h.blocks ?? []) x[O.id] = O.status === "modified" && O.canApply;
1316
+ ne.value = x;
1317
+ const L = (h.blocks ?? []).reduce((O, X) => ({ ...O, [X.status]: (O[X.status] ?? 0) + 1 }), {});
1318
+ y.value = `扫到 ${h.folders} 个文件夹、${h.files} 个文件:有改动 ${L.modified ?? 0} / 没改动 ${L.unchanged ?? 0}` + (h.complete ? "" : "(层数到了上限,没走完,可能还有块没扫到)");
1270
1319
  } finally {
1271
- L.value = !1;
1320
+ V.value = !1;
1272
1321
  }
1273
- }, y), kt = () => D(async () => {
1274
- const i = ke.value, o = Cn(i);
1275
- if (G.value = o.issues, W.value = [], o.issues.length > 0)
1276
- throw _.value = "", new Error(`前端校验没过(${o.issues.length} 条),没有发请求:
1322
+ }, _), Oe = () => m(async () => {
1323
+ const i = F.value, o = On(i);
1324
+ if (Y.value = o.issues, oe.value = [], o.issues.length > 0)
1325
+ throw y.value = "", new Error(`前端校验没过(${o.issues.length} 条),没有发请求:
1277
1326
  - ${o.issues.join(`
1278
1327
  - `)}`);
1279
- Y.value = !0, _.value = "";
1328
+ ee.value = !0, y.value = "";
1280
1329
  try {
1281
- const a = await te("/magic-blocks/import", { updatedBy: "", blocks: i });
1282
- W.value = a.results ?? [], _.value = `保存:成功 ${a.saved} 个、失败 ${a.failed} 个`, await ne();
1283
- const g = _.value;
1284
- await De(), _.value = `${g};已重新读回该目录`;
1330
+ const a = await ae("/magic-blocks/import", { updatedBy: "", blocks: i });
1331
+ oe.value = a.results ?? [], y.value = `保存:成功 ${a.saved} 个、失败 ${a.failed} 个`, await H();
1332
+ const h = y.value;
1333
+ await xe(), y.value = `${h};已重新读回该目录`;
1285
1334
  } finally {
1286
- Y.value = !1;
1335
+ ee.value = !1;
1287
1336
  }
1288
- }, y), wt = (i) => D(async () => {
1289
- await V(`/magic-blocks/${encodeURIComponent(i.id)}/rollback`, { method: "POST" }), _.value = `「${i.name || i.id}」已回滚到上一版`, await ne();
1290
- }, y), $t = (i) => D(async () => {
1291
- window.confirm(`删掉「${i.name || i.id}」?库里这一行(连同它的文件包)会一起没。`) && (await V(`/magic-blocks/${encodeURIComponent(i.id)}`, { method: "DELETE" }), _.value = `「${i.name || i.id}」已删除`, await ne());
1292
- }, y);
1293
- function xt(i, o) {
1337
+ }, _), Et = (i) => m(async () => {
1338
+ await J(`/magic-blocks/${encodeURIComponent(i.id)}/rollback`, { method: "POST" }), y.value = `「${i.name || i.id}」已回滚到上一版`, await H();
1339
+ }, _), Tt = (i) => m(async () => {
1340
+ window.confirm(`删掉「${i.name || i.id}」?库里这一行(连同它的文件包)会一起没。`) && (await J(`/magic-blocks/${encodeURIComponent(i.id)}`, { method: "DELETE" }), y.value = `「${i.name || i.id}」已删除`, await H());
1341
+ }, _);
1342
+ function St(i, o) {
1294
1343
  const a = o.target;
1295
- le.value[i] = a?.checked === !0;
1344
+ ne.value[i] = a?.checked === !0;
1296
1345
  }
1297
- function Fe(i) {
1346
+ function Ge(i) {
1298
1347
  const o = i.detail?.uuid ?? "";
1299
- r.value = !0, d.value = o;
1348
+ u.value = !0, f.value = o;
1300
1349
  }
1301
- return Ze(() => {
1302
- window.addEventListener("magic-block:open-console", Fe), ne(), k().catch(() => {
1350
+ return st(() => {
1351
+ window.addEventListener("magic-block:open-console", Ge), H(), z().catch(() => {
1303
1352
  });
1304
- }), Xe(() => window.removeEventListener("magic-block:open-console", Fe)), (i, o) => be(n) ? (h(), b(j, { key: 0 }, [
1353
+ }), at(() => window.removeEventListener("magic-block:open-console", Ge)), (i, o) => ve(n) ? (b(), g(j, { key: 0 }, [
1305
1354
  p("button", {
1306
1355
  class: "fab",
1307
1356
  type: "button",
1308
1357
  title: "magic block 控制台",
1309
- onClick: o[0] || (o[0] = (a) => r.value = !0)
1358
+ onClick: o[0] || (o[0] = (a) => u.value = !0)
1310
1359
  }, "块"),
1311
- r.value ? (h(), b("aside", Hn, [
1312
- p("header", Kn, [
1360
+ u.value ? (b(), g("aside", Vn, [
1361
+ p("header", Gn, [
1313
1362
  o[12] || (o[12] = p("strong", null, "magic block", -1)),
1314
- Tt(p("input", {
1315
- "onUpdate:modelValue": o[1] || (o[1] = (a) => u.value = a),
1363
+ At(p("input", {
1364
+ "onUpdate:modelValue": o[1] || (o[1] = (a) => c.value = a),
1316
1365
  class: "p-inputtext p-component mbc__grow",
1317
1366
  type: "search",
1318
1367
  placeholder: "筛选 module / 名字"
1319
1368
  }, null, 512), [
1320
- [At, u.value]
1369
+ [Ot, c.value]
1321
1370
  ]),
1322
1371
  p("button", {
1323
1372
  class: "p-button p-button-sm",
1324
1373
  type: "button",
1325
- disabled: y.value,
1326
- onClick: o[2] || (o[2] = (a) => oe())
1327
- }, v(S.value ? "体检中…" : "重新体检全部"), 9, Un),
1374
+ disabled: _.value,
1375
+ onClick: o[2] || (o[2] = (a) => k())
1376
+ }, v(N.value ? "体检中…" : "重新体检全部"), 9, Yn),
1328
1377
  p("button", {
1329
1378
  class: "p-button p-button-sm p-button-text",
1330
1379
  type: "button",
1331
- onClick: o[3] || (o[3] = (a) => r.value = !1)
1380
+ onClick: o[3] || (o[3] = (a) => u.value = !1)
1332
1381
  }, "关闭")
1333
1382
  ]),
1334
- f.value ? (h(), b("p", qn, v(f.value), 1)) : x("", !0),
1335
- _.value ? (h(), b("p", Gn, v(_.value), 1)) : x("", !0),
1336
- p("section", Jn, [
1337
- p("h3", Vn, "库里的块(" + v(_e.value.length) + " / " + v(c.value.length) + ")", 1),
1338
- p("ul", Yn, [
1339
- (h(!0), b(j, null, Q(_e.value, (a) => (h(), b("li", {
1383
+ w.value ? (b(), g("p", Wn, v(w.value), 1)) : E("", !0),
1384
+ y.value ? (b(), g("p", Zn, v(y.value), 1)) : E("", !0),
1385
+ p("section", Xn, [
1386
+ p("h3", Qn, "库里的块(" + v(me.value.length) + " / " + v(d.value.length) + ")", 1),
1387
+ p("ul", eo, [
1388
+ (b(!0), g(j, null, Q(me.value, (a) => (b(), g("li", {
1340
1389
  key: a.id
1341
1390
  }, [
1342
1391
  p("button", {
1343
1392
  type: "button",
1344
- class: J(["mbc__row", { "is-active": a.id === d.value }]),
1393
+ class: U(["mbc__row", { "is-active": a.id === f.value }]),
1345
1394
  title: Ce(a),
1346
- onClick: (g) => ye(a)
1395
+ onClick: (h) => fe(a)
1347
1396
  }, [
1348
- p("span", Zn, v(a.module || "unassigned"), 1),
1349
- p("span", Xn, v(a.name || a.id), 1),
1350
- ce(a).length > 0 ? (h(), b("span", Qn, v(ce(a).join(" / ")), 1)) : x("", !0),
1397
+ p("span", no, v(a.module || "unassigned"), 1),
1398
+ p("span", oo, v(a.name || a.id), 1),
1399
+ re(a).length > 0 ? (b(), g("span", so, v(re(a).join(" / ")), 1)) : E("", !0),
1351
1400
  p("em", {
1352
- class: J({ "is-off": a.enabled === !1 })
1353
- }, v(a.enabled === !1 ? re(a) || "校验失败已停用" : "可用"), 3)
1354
- ], 10, Wn),
1355
- d.value === a.id ? (h(), b("div", eo, [
1356
- (h(!0), b(j, null, Q(K(a).slice(0, Oe), (g, $) => (h(), b("p", {
1357
- key: $,
1401
+ class: U({ "is-off": a.enabled === !1 })
1402
+ }, v(a.enabled === !1 ? ke(a) || "校验失败已停用" : "可用"), 3)
1403
+ ], 10, to),
1404
+ f.value === a.id ? (b(), g("div", ao, [
1405
+ (b(!0), g(j, null, Q(pe(a).slice(0, Ie), (h, x) => (b(), g("p", {
1406
+ key: x,
1358
1407
  class: "mbc__problem"
1359
- }, v(g), 1))), 128)),
1360
- K(a).length > Oe ? (h(), b("p", to, "还有 " + v(K(a).length - Oe) + " 条体检问题,点「体检这一块」看最新结论", 1)) : x("", !0),
1361
- p("dl", no, [
1408
+ }, v(h), 1))), 128)),
1409
+ pe(a).length > Ie ? (b(), g("p", io, "还有 " + v(pe(a).length - Ie) + " 条体检问题,点「体检这一块」看最新结论", 1)) : E("", !0),
1410
+ p("dl", lo, [
1362
1411
  o[13] || (o[13] = p("dt", null, "文件", -1)),
1363
1412
  p("dd", null, v((a.fileNames || []).join(" / ") || "(没有文件)"), 1),
1364
1413
  o[14] || (o[14] = p("dt", null, "更新", -1)),
@@ -1366,224 +1415,224 @@ ${a}` : a;
1366
1415
  o[15] || (o[15] = p("dt", null, "上一版", -1)),
1367
1416
  p("dd", null, v(a.hasPrev ? a.prevUpdatedAt || "有" : "没有"), 1),
1368
1417
  o[16] || (o[16] = p("dt", null, "id", -1)),
1369
- p("dd", oo, v(a.id), 1)
1418
+ p("dd", ro, v(a.id), 1)
1370
1419
  ]),
1371
- p("div", so, [
1420
+ p("div", co, [
1372
1421
  p("button", {
1373
1422
  class: "p-button p-button-sm p-button-outlined",
1374
1423
  type: "button",
1375
- disabled: y.value,
1376
- onClick: (g) => oe(a.id)
1377
- }, "体检这一块", 8, ao),
1424
+ disabled: _.value,
1425
+ onClick: (h) => k(a.id)
1426
+ }, "体检这一块", 8, uo),
1378
1427
  p("button", {
1379
1428
  class: "p-button p-button-sm p-button-outlined",
1380
1429
  type: "button",
1381
- disabled: y.value || !a.hasPrev,
1382
- onClick: (g) => wt(a)
1383
- }, "回滚上一版", 8, io),
1430
+ disabled: _.value || !a.hasPrev,
1431
+ onClick: (h) => Et(a)
1432
+ }, "回滚上一版", 8, po),
1384
1433
  p("button", {
1385
1434
  class: "p-button p-button-sm p-button-text",
1386
1435
  type: "button",
1387
- disabled: y.value,
1388
- onClick: (g) => $t(a)
1389
- }, "删除", 8, lo)
1436
+ disabled: _.value,
1437
+ onClick: (h) => Tt(a)
1438
+ }, "删除", 8, fo)
1390
1439
  ])
1391
- ])) : x("", !0)
1440
+ ])) : E("", !0)
1392
1441
  ]))), 128))
1393
1442
  ])
1394
1443
  ]),
1395
- p("section", ro, [
1444
+ p("section", mo, [
1396
1445
  o[23] || (o[23] = p("h3", { class: "mbc__title" }, "导出去改(用你自己的编辑器)", -1)),
1397
- p("div", co, [
1446
+ p("div", bo, [
1398
1447
  o[17] || (o[17] = p("label", { for: "mbc-dir" }, "导出目录", -1)),
1399
1448
  p("input", {
1400
1449
  id: "mbc-dir",
1401
1450
  class: "p-inputtext p-component mbc__grow mbc__mono",
1402
1451
  type: "text",
1403
1452
  readonly: "",
1404
- value: A.value ? A.value.name : "(还没选:点右边那个按钮选一个文件夹)"
1405
- }, null, 8, uo),
1453
+ value: M.value ? M.value.name : "(还没选:点右边那个按钮选一个文件夹)"
1454
+ }, null, 8, ho),
1406
1455
  p("button", {
1407
1456
  class: "p-button p-button-sm p-button-outlined",
1408
1457
  type: "button",
1409
- disabled: y.value,
1410
- onClick: o[4] || (o[4] = (a) => m("export"))
1411
- }, "选择文件夹", 8, po),
1458
+ disabled: _.value,
1459
+ onClick: o[4] || (o[4] = (a) => C("export"))
1460
+ }, "选择文件夹", 8, go),
1412
1461
  p("button", {
1413
1462
  class: "p-button p-button-sm",
1414
1463
  type: "button",
1415
- disabled: y.value,
1416
- onClick: o[5] || (o[5] = (a) => I())
1417
- }, v(B.value ? "导出中…" : "导出"), 9, fo)
1464
+ disabled: _.value,
1465
+ onClick: o[5] || (o[5] = (a) => $e())
1466
+ }, v(B.value ? "导出中…" : "导出"), 9, vo)
1418
1467
  ]),
1419
- o[24] || (o[24] = Ot('<p class="mbc__hint" data-v-7c262207> 代码会铺在 <span class="mbc__mono" data-v-7c262207>workspace/&lt;可读名&gt;-&lt;块 uuid&gt;/</span>, 顶层另附 <span class="mbc__mono" data-v-7c262207>GUIDE.lock.md</span>(怎么改)、<span class="mbc__mono" data-v-7c262207>pages.lock.ts</span>(Page 枚举)、 <span class="mbc__mono" data-v-7c262207>backend.lock.pyi</span>(能用的库 / ctx / 环境变量 / 模型)、 <span class="mbc__mono" data-v-7c262207>labull.css</span> 与 <span class="mbc__mono" data-v-7c262207>CONTROLS.lock.html</span>(主题与控件清单)—— 那几份都是**生成物**。 </p>', 1)),
1420
- N.value ? (h(), b("p", mo, v(N.value), 1)) : x("", !0),
1421
- E.value.active ? (h(), b("div", {
1468
+ o[24] || (o[24] = Pt('<p class="mbc__hint" data-v-c941d8c8> 代码会铺在 <span class="mbc__mono" data-v-c941d8c8>workspace/&lt;可读名&gt;-&lt;块 uuid&gt;/</span>, 顶层另附 <span class="mbc__mono" data-v-c941d8c8>GUIDE.lock.md</span>(怎么改)、<span class="mbc__mono" data-v-c941d8c8>pages.lock.ts</span>(Page 枚举)、 <span class="mbc__mono" data-v-c941d8c8>backend.lock.pyi</span>(能用的库 / ctx / 环境变量 / 模型)、 <span class="mbc__mono" data-v-c941d8c8>labull.css</span> 与 <span class="mbc__mono" data-v-c941d8c8>CONTROLS.lock.html</span>(主题与控件清单)—— 那几份都是**生成物**。 </p>', 1)),
1469
+ te.value ? (b(), g("p", yo, v(te.value), 1)) : E("", !0),
1470
+ T.value.active ? (b(), g("div", {
1422
1471
  key: 1,
1423
- class: J(["mbc__progress", { "is-failed": E.value.failed }]),
1472
+ class: U(["mbc__progress", { "is-failed": T.value.failed }]),
1424
1473
  role: "progressbar",
1425
- "aria-valuenow": E.value.percent,
1474
+ "aria-valuenow": T.value.percent,
1426
1475
  "aria-valuemin": "0",
1427
1476
  "aria-valuemax": "100"
1428
1477
  }, [
1429
1478
  p("div", {
1430
1479
  class: "mbc__progress-bar",
1431
- style: Qe(Ee.value)
1480
+ style: it(q.value)
1432
1481
  }, null, 4)
1433
- ], 10, ho)) : x("", !0),
1434
- E.value.active ? (h(), b("p", {
1482
+ ], 10, _o)) : E("", !0),
1483
+ T.value.active ? (b(), g("p", {
1435
1484
  key: 2,
1436
- class: J(["mbc__hint", { "mbc__progress-note": E.value.failed }])
1437
- }, v(E.value.failed ? "✗" : "") + " " + v(E.value.percent) + "% · " + v(E.value.stage), 3)) : x("", !0),
1438
- M.value ? (h(), b("div", bo, [
1439
- p("p", go, "「" + v(M.value.target.name) + "」里现在有 " + v(M.value.inventory.dirs) + " 个文件夹 / " + v(M.value.inventory.files) + " 个文件", 1),
1440
- p("p", vo, [
1441
- o[18] || (o[18] = ue(" 接下来会", -1)),
1485
+ class: U(["mbc__hint", { "mbc__progress-note": T.value.failed }])
1486
+ }, v(T.value.failed ? "✗" : "") + " " + v(T.value.percent) + "% · " + v(T.value.stage), 3)) : E("", !0),
1487
+ A.value ? (b(), g("div", ko, [
1488
+ p("p", wo, "「" + v(A.value.target.name) + "」里现在有 " + v(A.value.inventory.dirs) + " 个文件夹 / " + v(A.value.inventory.files) + " 个文件", 1),
1489
+ p("p", $o, [
1490
+ o[18] || (o[18] = ce(" 接下来会", -1)),
1442
1491
  o[19] || (o[19] = p("b", null, "先全部删掉", -1)),
1443
- o[20] || (o[20] = ue("再铺一遍 —— 包括你改过、还没读回库的东西。 清空只动这个目录", -1)),
1492
+ o[20] || (o[20] = ce("再铺一遍 —— 包括你改过、还没读回库的东西。 清空只动这个目录", -1)),
1444
1493
  o[21] || (o[21] = p("b", null, "里面", -1)),
1445
- o[22] || (o[22] = ue("的子项:目录本身、以及它外面的任何东西都不会被碰。 ", -1)),
1446
- M.value.inventory.items.length > 0 ? (h(), b("span", yo, "(" + v(M.value.inventory.items.slice(0, 6).map((a) => a.name).join(" / ")) + v(M.value.inventory.items.length > 6 ? " …" : "") + ")", 1)) : x("", !0)
1494
+ o[22] || (o[22] = ce("的子项:目录本身、以及它外面的任何东西都不会被碰。 ", -1)),
1495
+ A.value.inventory.items.length > 0 ? (b(), g("span", xo, "(" + v(A.value.inventory.items.slice(0, 6).map((a) => a.name).join(" / ")) + v(A.value.inventory.items.length > 6 ? " …" : "") + ")", 1)) : E("", !0)
1447
1496
  ]),
1448
- p("div", _o, [
1497
+ p("div", Eo, [
1449
1498
  p("button", {
1450
1499
  class: "p-button p-button-sm",
1451
1500
  type: "button",
1452
- disabled: y.value,
1453
- onClick: o[6] || (o[6] = (a) => vt())
1454
- }, "清空并导出", 8, ko),
1501
+ disabled: _.value,
1502
+ onClick: o[6] || (o[6] = (a) => he())
1503
+ }, "清空并导出", 8, To),
1455
1504
  p("button", {
1456
1505
  class: "p-button p-button-sm p-button-outlined",
1457
1506
  type: "button",
1458
- disabled: y.value,
1459
- onClick: o[7] || (o[7] = (a) => yt())
1460
- }, "只覆盖", 8, wo),
1507
+ disabled: _.value,
1508
+ onClick: o[7] || (o[7] = (a) => Me())
1509
+ }, "只覆盖", 8, So),
1461
1510
  p("button", {
1462
1511
  class: "p-button p-button-sm p-button-text",
1463
1512
  type: "button",
1464
- disabled: y.value,
1465
- onClick: o[8] || (o[8] = (a) => _t())
1466
- }, "取消", 8, $o)
1513
+ disabled: _.value,
1514
+ onClick: o[8] || (o[8] = (a) => Ae())
1515
+ }, "取消", 8, Co)
1467
1516
  ])
1468
- ])) : x("", !0)
1517
+ ])) : E("", !0)
1469
1518
  ]),
1470
- p("section", xo, [
1519
+ p("section", Bo, [
1471
1520
  o[28] || (o[28] = p("h3", { class: "mbc__title" }, "读回改动", -1)),
1472
- p("div", So, [
1521
+ p("div", Mo, [
1473
1522
  o[25] || (o[25] = p("label", { for: "mbc-read-dir" }, "读回目录", -1)),
1474
1523
  p("input", {
1475
1524
  id: "mbc-read-dir",
1476
1525
  class: "p-inputtext p-component mbc__grow mbc__mono",
1477
1526
  type: "text",
1478
1527
  readonly: "",
1479
- value: T.value ? T.value.name : "(还没选:导出会自动填上,也可以自己选一个)"
1480
- }, null, 8, Eo),
1528
+ value: S.value ? S.value.name : "(还没选:导出会自动填上,也可以自己选一个)"
1529
+ }, null, 8, Ao),
1481
1530
  p("button", {
1482
1531
  class: "p-button p-button-sm p-button-outlined",
1483
1532
  type: "button",
1484
- disabled: y.value,
1485
- onClick: o[9] || (o[9] = (a) => m("read"))
1486
- }, "选择文件夹", 8, Co),
1533
+ disabled: _.value,
1534
+ onClick: o[9] || (o[9] = (a) => C("read"))
1535
+ }, "选择文件夹", 8, Oo),
1487
1536
  p("button", {
1488
1537
  class: "p-button p-button-sm p-button-outlined",
1489
1538
  type: "button",
1490
- disabled: y.value,
1491
- onClick: o[10] || (o[10] = (a) => De())
1492
- }, v(L.value ? "读回中…" : "读回改动"), 9, Bo)
1539
+ disabled: _.value,
1540
+ onClick: o[10] || (o[10] = (a) => xe())
1541
+ }, v(V.value ? "读回中…" : "读回改动"), 9, Po)
1493
1542
  ]),
1494
- T.value && A.value && T.value.name !== A.value.name ? (h(), b("p", To, " 读回的是「" + v(T.value.name) + "」(与导出目录「" + v(A.value.name) + "」不是同一个 —— 想同步就再选一次)。 ", 1)) : (h(), b("p", Ao, "读回目录默认跟着导出目录;要读别的文件夹就点「选择文件夹」单独选一个。")),
1495
- z.value ? (h(), b(j, { key: 2 }, [
1496
- z.value.blocks.length > 0 ? (h(), b("ul", Oo, [
1497
- (h(!0), b(j, null, Q(z.value.blocks, (a) => (h(), b("li", {
1543
+ S.value && M.value && S.value.name !== M.value.name ? (b(), g("p", Ro, " 读回的是「" + v(S.value.name) + "」(与导出目录「" + v(M.value.name) + "」不是同一个 —— 想同步就再选一次)。 ", 1)) : (b(), g("p", jo, "读回目录默认跟着导出目录;要读别的文件夹就点「选择文件夹」单独选一个。")),
1544
+ I.value ? (b(), g(j, { key: 2 }, [
1545
+ I.value.blocks.length > 0 ? (b(), g("ul", No, [
1546
+ (b(!0), g(j, null, Q(I.value.blocks, (a) => (b(), g("li", {
1498
1547
  key: a.id,
1499
1548
  class: "mbc__block"
1500
1549
  }, [
1501
- p("label", Mo, [
1550
+ p("label", Io, [
1502
1551
  p("span", {
1503
- class: J(["p-checkbox p-component", { "p-disabled": !a.canApply }])
1552
+ class: U(["p-checkbox p-component", { "p-disabled": !a.canApply }])
1504
1553
  }, [
1505
1554
  p("input", {
1506
1555
  class: "p-checkbox-input",
1507
1556
  type: "checkbox",
1508
1557
  disabled: !a.canApply,
1509
- checked: le.value[a.id] === !0,
1510
- onChange: (g) => xt(a.id, g)
1511
- }, null, 40, Po),
1558
+ checked: ne.value[a.id] === !0,
1559
+ onChange: (h) => St(a.id, h)
1560
+ }, null, 40, Lo),
1512
1561
  o[26] || (o[26] = p("span", { class: "p-checkbox-box" }, null, -1))
1513
1562
  ], 2),
1514
- p("span", Ro, v(a.name || a.id), 1),
1563
+ p("span", Do, v(a.name || a.id), 1),
1515
1564
  p("span", {
1516
- class: J(["p-tag", a.status === "modified" ? "p-tag-success" : a.status === "missing" ? "p-tag-warning" : ""])
1565
+ class: U(["p-tag", a.status === "modified" ? "p-tag-success" : a.status === "missing" ? "p-tag-warning" : ""])
1517
1566
  }, v(e[a.status]), 3),
1518
- p("span", jo, v(a.module || "—"), 1)
1567
+ p("span", Fo, v(a.module || "—"), 1)
1519
1568
  ]),
1520
- p("p", No, [
1521
- a.status === "missing" ? (h(), b(j, { key: 0 }, [
1522
- ue("目录里没有这一块,勾不上")
1523
- ], 64)) : a.changedFiles.length > 0 ? (h(), b(j, { key: 1 }, [
1524
- o[27] || (o[27] = ue("改了:", -1)),
1525
- p("span", Io, v(a.changedFiles.join(" / ")), 1)
1526
- ], 64)) : (h(), b(j, { key: 2 }, [
1527
- ue("内容与库里一致")
1569
+ p("p", zo, [
1570
+ a.status === "missing" ? (b(), g(j, { key: 0 }, [
1571
+ ce("目录里没有这一块,勾不上")
1572
+ ], 64)) : a.changedFiles.length > 0 ? (b(), g(j, { key: 1 }, [
1573
+ o[27] || (o[27] = ce("改了:", -1)),
1574
+ p("span", Ho, v(a.changedFiles.join(" / ")), 1)
1575
+ ], 64)) : (b(), g(j, { key: 2 }, [
1576
+ ce("内容与库里一致")
1528
1577
  ], 64))
1529
1578
  ]),
1530
- a.blockedWhy ? (h(), b("p", Lo, "不能存:" + v(a.blockedWhy), 1)) : x("", !0),
1531
- p("p", zo, v(a.folder || a.where), 1)
1579
+ a.blockedWhy ? (b(), g("p", Ko, "不能存:" + v(a.blockedWhy), 1)) : E("", !0),
1580
+ p("p", qo, v(a.folder || a.where), 1)
1532
1581
  ]))), 128))
1533
- ])) : (h(), b("p", Do, "这个目录里没有认出任何块。")),
1534
- z.value.unmatched.length > 0 ? (h(), b("p", Fo, "认不出归属的文件夹(" + v(z.value.unmatched.length) + "):" + v(z.value.unmatched.join(" / ")), 1)) : x("", !0),
1535
- z.value.failures.length > 0 ? (h(), b("ul", Ho, [
1536
- (h(!0), b(j, null, Q(z.value.failures, (a, g) => (h(), b("li", { key: g }, v(a.where || a.kind) + ":" + v(a.message), 1))), 128))
1537
- ])) : x("", !0),
1538
- p("div", Ko, [
1582
+ ])) : (b(), g("p", Uo, "这个目录里没有认出任何块。")),
1583
+ I.value.unmatched.length > 0 ? (b(), g("p", Jo, "认不出归属的文件夹(" + v(I.value.unmatched.length) + "):" + v(I.value.unmatched.join(" / ")), 1)) : E("", !0),
1584
+ I.value.failures.length > 0 ? (b(), g("ul", Vo, [
1585
+ (b(!0), g(j, null, Q(I.value.failures, (a, h) => (b(), g("li", { key: h }, v(a.where || a.kind) + ":" + v(a.message), 1))), 128))
1586
+ ])) : E("", !0),
1587
+ p("div", Go, [
1539
1588
  p("button", {
1540
1589
  class: "p-button p-button-sm",
1541
1590
  type: "button",
1542
- disabled: y.value,
1543
- onClick: o[11] || (o[11] = (a) => kt())
1544
- }, v(Y.value ? "保存中…" : `保存选中的块(${ke.value.length})`), 9, Uo)
1591
+ disabled: _.value,
1592
+ onClick: o[11] || (o[11] = (a) => Oe())
1593
+ }, v(ee.value ? "保存中…" : `保存选中的块(${F.value.length})`), 9, Yo)
1545
1594
  ])
1546
- ], 64)) : x("", !0)
1595
+ ], 64)) : E("", !0)
1547
1596
  ]),
1548
- G.value.length > 0 || W.value.length > 0 ? (h(), b("section", qo, [
1549
- p("h3", Go, v(G.value.length > 0 ? "前端校验拦下的问题" : "保存结果"), 1),
1550
- G.value.length > 0 ? (h(), b("ul", Jo, [
1551
- (h(!0), b(j, null, Q(G.value, (a, g) => (h(), b("li", { key: g }, v(a), 1))), 128))
1552
- ])) : (h(), b("ul", Vo, [
1553
- (h(!0), b(j, null, Q(W.value, (a) => (h(), b("li", {
1597
+ Y.value.length > 0 || oe.value.length > 0 ? (b(), g("section", Wo, [
1598
+ p("h3", Zo, v(Y.value.length > 0 ? "前端校验拦下的问题" : "保存结果"), 1),
1599
+ Y.value.length > 0 ? (b(), g("ul", Xo, [
1600
+ (b(!0), g(j, null, Q(Y.value, (a, h) => (b(), g("li", { key: h }, v(a), 1))), 128))
1601
+ ])) : (b(), g("ul", Qo, [
1602
+ (b(!0), g(j, null, Q(oe.value, (a) => (b(), g("li", {
1554
1603
  key: a.id,
1555
- class: J({ "is-ok": a.ok })
1604
+ class: U({ "is-ok": a.ok })
1556
1605
  }, [
1557
1606
  p("strong", null, v(a.name || a.id) + ":" + v(a.ok ? "已保存" : "没保存"), 1),
1558
- !a.ok && a.error ? (h(), b("span", Yo, v(a.error), 1)) : x("", !0),
1559
- !a.ok && (a.issues ?? []).length > 0 ? (h(), b("ul", Wo, [
1560
- (h(!0), b(j, null, Q(a.issues, (g, $) => (h(), b("li", { key: $ }, v(g), 1))), 128))
1561
- ])) : x("", !0)
1607
+ !a.ok && a.error ? (b(), g("span", es, v(a.error), 1)) : E("", !0),
1608
+ !a.ok && (a.issues ?? []).length > 0 ? (b(), g("ul", ts, [
1609
+ (b(!0), g(j, null, Q(a.issues, (h, x) => (b(), g("li", { key: x }, v(h), 1))), 128))
1610
+ ])) : E("", !0)
1562
1611
  ], 2))), 128))
1563
1612
  ]))
1564
- ])) : x("", !0)
1565
- ])) : x("", !0)
1566
- ], 64)) : x("", !0);
1613
+ ])) : E("", !0)
1614
+ ])) : E("", !0)
1615
+ ], 64)) : E("", !0);
1567
1616
  }
1568
- }), os = /* @__PURE__ */ ot(Zo, [["__scopeId", "data-v-7c262207"]]);
1617
+ }), rs = /* @__PURE__ */ ut(ns, [["__scopeId", "data-v-c941d8c8"]]);
1569
1618
  export {
1570
- Mt as API_BASE,
1571
- Lt as BLOCK_BACKEND_FILE,
1572
- rt as BLOCK_ENTRY,
1573
- Te as BLOCK_MANIFEST,
1574
- Rt as CLIENT_SOURCE,
1575
- xe as MANIFEST_KEYS,
1576
- os as MagicBlockConsole,
1577
- ns as MagicBlockHost,
1578
- ze as NAME_MAX,
1579
- qt as buildPreview,
1580
- Cn as checkSelection,
1581
- It as installBridge,
1582
- Vt as loadBlockRender,
1583
- Gt as onBlockRenderRefresh,
1584
- xn as parseManifest,
1585
- Jt as refreshBlockRender,
1586
- Sn as validFileName,
1587
- yn as validName,
1588
- En as validateBlock
1619
+ Rt as API_BASE,
1620
+ Ht as BLOCK_BACKEND_FILE,
1621
+ bt as BLOCK_ENTRY,
1622
+ je as BLOCK_MANIFEST,
1623
+ Lt as CLIENT_SOURCE,
1624
+ Te as MANIFEST_KEYS,
1625
+ rs as MagicBlockConsole,
1626
+ ls as MagicBlockPage,
1627
+ Ve as NAME_MAX,
1628
+ Yt as buildPreview,
1629
+ On as checkSelection,
1630
+ zt as installBridge,
1631
+ Xt as loadBlockRender,
1632
+ Wt as onBlockRenderRefresh,
1633
+ Bn as parseManifest,
1634
+ Zt as refreshBlockRender,
1635
+ Mn as validFileName,
1636
+ xn as validName,
1637
+ An as validateBlock
1589
1638
  };