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