labull-framework 0.1.0 → 0.1.2

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