labull-framework 0.1.10 → 0.1.12

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