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