smart-admin-web 10.13.1 → 10.15.0
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 +5 -5
- package/dist/api/index.d.ts +37 -0
- package/dist/api/index.js +35 -14
- package/dist/api/index.js.map +1 -1
- package/dist/api/schema.d.ts +381 -3
- package/dist/assets/icons/ph-subset.json.js +3 -3
- package/dist/assets/smart-logo.svg.js +5 -0
- package/dist/assets/smart-logo.svg.js.map +1 -0
- package/dist/components/SmartLogo.vue.d.ts +3 -0
- package/dist/components/SmartLogo.vue.js +1 -1
- package/dist/components/SmartLogo2.vue.js +22 -64
- package/dist/components/SmartLogo2.vue.js.map +1 -1
- package/dist/composables/useLoginHero.d.ts +2 -0
- package/dist/composables/useLoginHero.js +22 -0
- package/dist/composables/useLoginHero.js.map +1 -0
- package/dist/composables/usePageTitle.js +16 -14
- package/dist/composables/usePageTitle.js.map +1 -1
- package/dist/composables/useSite.d.ts +5 -0
- package/dist/composables/useSite.js +16 -13
- package/dist/composables/useSite.js.map +1 -1
- package/dist/index.js +92 -91
- package/dist/lib/favicon.d.ts +1 -0
- package/dist/lib/favicon.js +12 -0
- package/dist/lib/favicon.js.map +1 -0
- package/dist/lib/loginHero.d.ts +16 -0
- package/dist/lib/loginHero.js +33 -0
- package/dist/lib/loginHero.js.map +1 -0
- package/dist/lib/logoCrop.d.ts +25 -0
- package/dist/lib/logoCrop.js +22 -0
- package/dist/lib/logoCrop.js.map +1 -0
- package/dist/lib/runtime.d.ts +2 -0
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/runtime.js.map +1 -1
- package/dist/lib/securityRules.d.ts +26 -0
- package/dist/lib/securityRules.js +86 -0
- package/dist/lib/securityRules.js.map +1 -0
- package/dist/locales/en-US.d.ts +250 -28
- package/dist/locales/en-US.js +271 -58
- package/dist/locales/en-US.js.map +1 -1
- package/dist/locales/zh-CN.d.ts +250 -28
- package/dist/locales/zh-CN.js +266 -58
- package/dist/locales/zh-CN.js.map +1 -1
- package/dist/router/viewRegistry.js +10 -10
- package/dist/router/viewRegistry.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/utils/oauthBrand.d.ts +34 -9
- package/dist/utils/oauthBrand.js +70 -74
- package/dist/utils/oauthBrand.js.map +1 -1
- package/dist/views/login/components/LoginHeroPanel.vue.d.ts +18 -0
- package/dist/views/login/components/LoginHeroPanel.vue.js +8 -0
- package/dist/views/login/components/LoginHeroPanel.vue.js.map +1 -0
- package/dist/views/login/components/LoginHeroPanel2.vue.js +66 -0
- package/dist/views/login/components/LoginHeroPanel2.vue.js.map +1 -0
- package/dist/views/login/skins/SplitPanel.vue.js +1 -1
- package/dist/views/login/skins/SplitPanel2.vue.js +39 -59
- package/dist/views/login/skins/SplitPanel2.vue.js.map +1 -1
- package/dist/views/system/api-docs/index.vue.js +5 -0
- package/dist/views/system/api-docs/index.vue.js.map +1 -0
- package/dist/views/system/api-docs/index2.vue.js +64 -0
- package/dist/views/system/api-docs/index2.vue.js.map +1 -0
- package/dist/views/system/config/components/AdminMock.vue.js +8 -0
- package/dist/views/system/config/components/AdminMock.vue.js.map +1 -0
- package/dist/views/system/config/components/AdminMock2.vue.js +76 -0
- package/dist/views/system/config/components/AdminMock2.vue.js.map +1 -0
- package/dist/views/system/config/components/AdvancedSection.vue.js +5 -0
- package/dist/views/system/config/components/AdvancedSection.vue.js.map +1 -0
- package/dist/views/system/config/components/AdvancedSection2.vue.js +135 -0
- package/dist/views/system/config/components/AdvancedSection2.vue.js.map +1 -0
- package/dist/views/system/config/components/BrandSection.vue.d.ts +7 -0
- package/dist/views/system/config/components/BrandSection.vue.js +8 -0
- package/dist/views/system/config/components/BrandSection.vue.js.map +1 -0
- package/dist/views/system/config/components/BrandSection2.vue.js +264 -0
- package/dist/views/system/config/components/BrandSection2.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgGroup.vue.d.ts +18 -0
- package/dist/views/system/config/components/CfgGroup.vue.js +8 -0
- package/dist/views/system/config/components/CfgGroup.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgGroup2.vue.js +22 -0
- package/dist/views/system/config/components/CfgGroup2.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgRow.vue.d.ts +26 -0
- package/dist/views/system/config/components/CfgRow.vue.js +9 -0
- package/dist/views/system/config/components/CfgRow.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgRow2.vue.js +53 -0
- package/dist/views/system/config/components/CfgRow2.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgSegment.vue.d.ts +28 -0
- package/dist/views/system/config/components/CfgSegment.vue.js +8 -0
- package/dist/views/system/config/components/CfgSegment.vue.js.map +1 -0
- package/dist/views/system/config/components/CfgSegment2.vue.js +44 -0
- package/dist/views/system/config/components/CfgSegment2.vue.js.map +1 -0
- package/dist/views/system/config/components/ConfigFormModal.vue.js +5 -2
- package/dist/views/system/config/components/ConfigFormModal.vue.js.map +1 -1
- package/dist/views/system/config/components/ConfigFormModal2.vue.js +66 -56
- package/dist/views/system/config/components/ConfigFormModal2.vue.js.map +1 -1
- package/dist/views/system/config/components/JobSection.vue.js +8 -0
- package/dist/views/system/config/components/JobSection.vue.js.map +1 -0
- package/dist/views/system/config/components/JobSection2.vue.js +138 -0
- package/dist/views/system/config/components/JobSection2.vue.js.map +1 -0
- package/dist/views/system/config/components/{GroupExtraConfig.vue.d.ts → LoginMock.vue.d.ts} +3 -4
- package/dist/views/system/config/components/LoginMock.vue.js +8 -0
- package/dist/views/system/config/components/LoginMock.vue.js.map +1 -0
- package/dist/views/system/config/components/LoginMock2.vue.js +121 -0
- package/dist/views/system/config/components/LoginMock2.vue.js.map +1 -0
- package/dist/views/system/config/components/LogoCropper.vue.d.ts +10 -0
- package/dist/views/system/config/components/LogoCropper.vue.js +8 -0
- package/dist/views/system/config/components/LogoCropper.vue.js.map +1 -0
- package/dist/views/system/config/components/LogoCropper2.vue.js +122 -0
- package/dist/views/system/config/components/LogoCropper2.vue.js.map +1 -0
- package/dist/views/system/config/components/LogoEditor.vue.js +8 -0
- package/dist/views/system/config/components/LogoEditor.vue.js.map +1 -0
- package/dist/views/system/config/components/LogoEditor2.vue.js +163 -0
- package/dist/views/system/config/components/LogoEditor2.vue.js.map +1 -0
- package/dist/views/system/config/components/ProviderSheet.vue.d.ts +17 -0
- package/dist/views/system/config/components/ProviderSheet.vue.js +8 -0
- package/dist/views/system/config/components/ProviderSheet.vue.js.map +1 -0
- package/dist/views/system/config/components/ProviderSheet2.vue.js +343 -0
- package/dist/views/system/config/components/ProviderSheet2.vue.js.map +1 -0
- package/dist/views/system/config/components/ScaleToFit.vue.d.ts +17 -0
- package/dist/views/system/config/components/ScaleToFit.vue.js +8 -0
- package/dist/views/system/config/components/ScaleToFit.vue.js.map +1 -0
- package/dist/views/system/config/components/ScaleToFit2.vue.js +41 -0
- package/dist/views/system/config/components/ScaleToFit2.vue.js.map +1 -0
- package/dist/views/system/config/components/SectionLayout.vue.d.ts +28 -0
- package/dist/views/system/config/components/SectionLayout.vue.js +8 -0
- package/dist/views/system/config/components/SectionLayout.vue.js.map +1 -0
- package/dist/views/system/config/components/SectionLayout2.vue.js +45 -0
- package/dist/views/system/config/components/SectionLayout2.vue.js.map +1 -0
- package/dist/views/system/config/components/SecuritySection.vue.js +8 -0
- package/dist/views/system/config/components/SecuritySection.vue.js.map +1 -0
- package/dist/views/system/config/components/SecuritySection2.vue.js +416 -0
- package/dist/views/system/config/components/SecuritySection2.vue.js.map +1 -0
- package/dist/views/system/config/components/SensitiveSection.vue.js +8 -0
- package/dist/views/system/config/components/SensitiveSection.vue.js.map +1 -0
- package/dist/views/system/config/components/SensitiveSection2.vue.js +209 -0
- package/dist/views/system/config/components/SensitiveSection2.vue.js.map +1 -0
- package/dist/views/system/config/components/SigninSection.vue.d.ts +3 -0
- package/dist/views/system/config/components/SigninSection.vue.js +8 -0
- package/dist/views/system/config/components/SigninSection.vue.js.map +1 -0
- package/dist/views/system/config/components/SigninSection2.vue.js +201 -0
- package/dist/views/system/config/components/SigninSection2.vue.js.map +1 -0
- package/dist/views/system/config/components/UploadSection.vue.d.ts +3 -0
- package/dist/views/system/config/components/UploadSection.vue.js +8 -0
- package/dist/views/system/config/components/UploadSection.vue.js.map +1 -0
- package/dist/views/system/config/components/UploadSection2.vue.js +167 -0
- package/dist/views/system/config/components/UploadSection2.vue.js.map +1 -0
- package/dist/views/system/config/draft.d.ts +148 -0
- package/dist/views/system/config/draft.js +170 -0
- package/dist/views/system/config/draft.js.map +1 -0
- package/dist/views/system/config/flash.d.ts +2 -0
- package/dist/views/system/config/flash.js +9 -0
- package/dist/views/system/config/flash.js.map +1 -0
- package/dist/views/system/config/groups.d.ts +35 -7
- package/dist/views/system/config/groups.js +99 -14
- package/dist/views/system/config/groups.js.map +1 -1
- package/dist/views/system/config/index.vue.js +4 -1
- package/dist/views/system/config/index.vue.js.map +1 -1
- package/dist/views/system/config/index2.vue.js +180 -115
- package/dist/views/system/config/index2.vue.js.map +1 -1
- package/dist/views/system/config/providerForm.d.ts +33 -0
- package/dist/views/system/config/providerForm.js +63 -0
- package/dist/views/system/config/providerForm.js.map +1 -0
- package/package.json +4 -4
- package/dist/views/system/config/components/ExternalAuthConfig.vue.js +0 -8
- package/dist/views/system/config/components/ExternalAuthConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/ExternalAuthConfig2.vue.js +0 -218
- package/dist/views/system/config/components/ExternalAuthConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/GroupExtraConfig.vue.js +0 -8
- package/dist/views/system/config/components/GroupExtraConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/GroupExtraConfig2.vue.js +0 -108
- package/dist/views/system/config/components/GroupExtraConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/HighSensConfig.vue.js +0 -5
- package/dist/views/system/config/components/HighSensConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/HighSensConfig2.vue.js +0 -134
- package/dist/views/system/config/components/HighSensConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/JobConfig.vue.js +0 -5
- package/dist/views/system/config/components/JobConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/JobConfig2.vue.js +0 -116
- package/dist/views/system/config/components/JobConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/OtherConfig.vue.js +0 -5
- package/dist/views/system/config/components/OtherConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/OtherConfig2.vue.js +0 -121
- package/dist/views/system/config/components/OtherConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/SecurityConfig.vue.js +0 -8
- package/dist/views/system/config/components/SecurityConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/SecurityConfig2.vue.js +0 -456
- package/dist/views/system/config/components/SecurityConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/SysBaseConfig.vue.js +0 -5
- package/dist/views/system/config/components/SysBaseConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/SysBaseConfig2.vue.js +0 -107
- package/dist/views/system/config/components/SysBaseConfig2.vue.js.map +0 -1
- package/dist/views/system/config/components/UploadConfig.vue.js +0 -5
- package/dist/views/system/config/components/UploadConfig.vue.js.map +0 -1
- package/dist/views/system/config/components/UploadConfig2.vue.js +0 -135
- package/dist/views/system/config/components/UploadConfig2.vue.js.map +0 -1
- /package/dist/views/system/{config/components/ExternalAuthConfig.vue.d.ts → api-docs/index.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{HighSensConfig.vue.d.ts → AdminMock.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{JobConfig.vue.d.ts → AdvancedSection.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{OtherConfig.vue.d.ts → JobSection.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{SecurityConfig.vue.d.ts → LogoEditor.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{SysBaseConfig.vue.d.ts → SecuritySection.vue.d.ts} +0 -0
- /package/dist/views/system/config/components/{UploadConfig.vue.d.ts → SensitiveSection.vue.d.ts} +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { defineComponent as T, computed as v, openBlock as r, createBlock as U, unref as e, withCtx as c, createVNode as u, isRef as w, createElementVNode as s, createElementBlock as d, Fragment as S, renderList as y, toDisplayString as p, withDirectives as z, createTextVNode as h, normalizeClass as O } from "vue";
|
|
2
|
+
import { NSlider as A, NInputNumber as P, NDynamicTags as j } from "naive-ui";
|
|
3
|
+
import { useI18n as $ } from "vue-i18n";
|
|
4
|
+
import F from "../../../../components/AppIcon.vue.js";
|
|
5
|
+
import { UPLOAD_MAX_KEY as C, UPLOAD_EXTS_KEY as g } from "../groups.js";
|
|
6
|
+
import { useConfigDraft as I, useDraftFields as R } from "../draft.js";
|
|
7
|
+
import { vFlash as E } from "../flash.js";
|
|
8
|
+
import V from "./SectionLayout.vue.js";
|
|
9
|
+
import K from "./CfgGroup.vue.js";
|
|
10
|
+
import x from "./CfgRow.vue.js";
|
|
11
|
+
const X = { class: "presets" }, Y = ["onClick"], q = {
|
|
12
|
+
class: "drop",
|
|
13
|
+
"data-testid": "upload-preview"
|
|
14
|
+
}, G = { class: "files" }, W = { class: "fi" }, H = { class: "nm" }, ue = /* @__PURE__ */ T({
|
|
15
|
+
__name: "UploadSection",
|
|
16
|
+
setup(J) {
|
|
17
|
+
const { t: l } = $(), { values: b } = I(), { num: D } = R(), i = D(C, 20);
|
|
18
|
+
function B(a) {
|
|
19
|
+
const t = a.trim().toLowerCase();
|
|
20
|
+
return t.startsWith(".") ? t : "." + t;
|
|
21
|
+
}
|
|
22
|
+
const n = v({
|
|
23
|
+
get: () => (b[g] ?? "").split(",").map((a) => a.trim()).filter(Boolean),
|
|
24
|
+
set: (a) => {
|
|
25
|
+
b[g] = [...new Set(a.map(B).filter((t) => t !== "."))].join(",");
|
|
26
|
+
}
|
|
27
|
+
}), k = {
|
|
28
|
+
images: [".jpg", ".jpeg", ".png", ".gif", ".webp"],
|
|
29
|
+
docs: [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx"],
|
|
30
|
+
archives: [".zip", ".rar", ".7z"]
|
|
31
|
+
};
|
|
32
|
+
function L(a) {
|
|
33
|
+
n.value = [...n.value, ...k[a]];
|
|
34
|
+
}
|
|
35
|
+
const M = [
|
|
36
|
+
{ name: "report.pdf", mb: 3.2 },
|
|
37
|
+
{ name: "photo.png", mb: 1.4 },
|
|
38
|
+
{ name: "demo.mp4", mb: 48 },
|
|
39
|
+
{ name: "setup.exe", mb: 12 }
|
|
40
|
+
], N = v(
|
|
41
|
+
() => M.map((a) => {
|
|
42
|
+
const t = a.name.slice(a.name.lastIndexOf(".")), o = n.value.length ? n.value.includes(t) : void 0, m = a.mb <= i.value, _ = o === !1 ? { ok: !1, text: l("config.upload.fileBadExt", { ext: t }) } : m ? o ? { ok: !0, text: l("config.upload.fileOk") } : { ok: void 0, text: l("config.upload.fileDefault") } : { ok: !1, text: l("config.upload.fileTooBig", { mb: i.value }) };
|
|
43
|
+
return { ...a, ext: t.slice(1).toUpperCase(), status: _ };
|
|
44
|
+
})
|
|
45
|
+
), f = v(
|
|
46
|
+
() => l("config.upload.previewLimit", {
|
|
47
|
+
exts: n.value.length ? n.value.join(" ") : l("config.upload.previewDefault"),
|
|
48
|
+
mb: i.value
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
return (a, t) => (r(), U(V, {
|
|
52
|
+
title: e(l)("config.tab.upload"),
|
|
53
|
+
desc: e(l)("config.upload.desc"),
|
|
54
|
+
"preview-title": e(l)("config.upload.preview"),
|
|
55
|
+
layout: "slim"
|
|
56
|
+
}, {
|
|
57
|
+
preview: c(() => [
|
|
58
|
+
s("div", q, [
|
|
59
|
+
u(F, {
|
|
60
|
+
icon: "ph:cloud-arrow-up",
|
|
61
|
+
size: 30,
|
|
62
|
+
class: "ic"
|
|
63
|
+
}),
|
|
64
|
+
s("b", null, p(e(l)("config.upload.previewDrop")), 1),
|
|
65
|
+
z((r(), d("small", null, [
|
|
66
|
+
h(p(f.value), 1)
|
|
67
|
+
])), [
|
|
68
|
+
[e(E), f.value]
|
|
69
|
+
])
|
|
70
|
+
]),
|
|
71
|
+
z((r(), d("ul", G, [
|
|
72
|
+
(r(!0), d(S, null, y(N.value, (o) => (r(), d("li", {
|
|
73
|
+
key: o.name
|
|
74
|
+
}, [
|
|
75
|
+
s("span", W, p(o.ext), 1),
|
|
76
|
+
s("span", H, [
|
|
77
|
+
h(p(o.name) + " ", 1),
|
|
78
|
+
s("small", null, p(o.mb) + " MB", 1)
|
|
79
|
+
]),
|
|
80
|
+
s("span", {
|
|
81
|
+
class: O(["st", { ok: o.status.ok === !0, no: o.status.ok === !1 }])
|
|
82
|
+
}, p(o.status.text), 3)
|
|
83
|
+
]))), 128))
|
|
84
|
+
])), [
|
|
85
|
+
[e(E), f.value]
|
|
86
|
+
])
|
|
87
|
+
]),
|
|
88
|
+
default: c(() => [
|
|
89
|
+
u(K, {
|
|
90
|
+
title: e(l)("config.upload.groupLimit")
|
|
91
|
+
}, {
|
|
92
|
+
default: c(() => [
|
|
93
|
+
u(x, {
|
|
94
|
+
label: e(l)("config.upload.maxSizeMb"),
|
|
95
|
+
keys: [e(C)]
|
|
96
|
+
}, {
|
|
97
|
+
default: c(() => [
|
|
98
|
+
u(e(A), {
|
|
99
|
+
value: e(i),
|
|
100
|
+
"onUpdate:value": t[0] || (t[0] = (o) => w(i) ? i.value = o : null),
|
|
101
|
+
class: "slider",
|
|
102
|
+
min: 1,
|
|
103
|
+
max: 200,
|
|
104
|
+
tooltip: !1,
|
|
105
|
+
"aria-label": e(l)("config.upload.maxSizeMb")
|
|
106
|
+
}, null, 8, ["value", "aria-label"]),
|
|
107
|
+
u(e(P), {
|
|
108
|
+
value: e(i),
|
|
109
|
+
"onUpdate:value": t[1] || (t[1] = (o) => w(i) ? i.value = o : null),
|
|
110
|
+
class: "num",
|
|
111
|
+
size: "small",
|
|
112
|
+
min: 1,
|
|
113
|
+
"show-button": !1,
|
|
114
|
+
"input-props": { "aria-label": e(l)("config.upload.maxSizeMb") }
|
|
115
|
+
}, null, 8, ["value", "input-props"]),
|
|
116
|
+
t[4] || (t[4] = s("span", { class: "unit" }, "MB", -1))
|
|
117
|
+
]),
|
|
118
|
+
_: 1
|
|
119
|
+
}, 8, ["label", "keys"]),
|
|
120
|
+
u(x, {
|
|
121
|
+
label: e(l)("config.upload.allowedExtensions"),
|
|
122
|
+
hint: e(l)("config.upload.extTip"),
|
|
123
|
+
keys: [e(g)],
|
|
124
|
+
tall: "",
|
|
125
|
+
class: "exts"
|
|
126
|
+
}, {
|
|
127
|
+
default: c(() => [
|
|
128
|
+
u(e(j), {
|
|
129
|
+
value: n.value,
|
|
130
|
+
"onUpdate:value": t[2] || (t[2] = (o) => n.value = o),
|
|
131
|
+
size: "small"
|
|
132
|
+
}, null, 8, ["value"])
|
|
133
|
+
]),
|
|
134
|
+
_: 1
|
|
135
|
+
}, 8, ["label", "hint", "keys"]),
|
|
136
|
+
u(x, {
|
|
137
|
+
label: e(l)("config.upload.quickAdd")
|
|
138
|
+
}, {
|
|
139
|
+
default: c(() => [
|
|
140
|
+
s("span", X, [
|
|
141
|
+
(r(), d(S, null, y(k, (o, m) => s("button", {
|
|
142
|
+
key: m,
|
|
143
|
+
type: "button",
|
|
144
|
+
class: "chip",
|
|
145
|
+
onClick: (_) => L(m)
|
|
146
|
+
}, p(e(l)(`config.upload.preset.${m}`)), 9, Y)), 64)),
|
|
147
|
+
s("button", {
|
|
148
|
+
type: "button",
|
|
149
|
+
class: "chip",
|
|
150
|
+
onClick: t[3] || (t[3] = (o) => n.value = [])
|
|
151
|
+
}, p(e(l)("config.upload.preset.clear")), 1)
|
|
152
|
+
])
|
|
153
|
+
]),
|
|
154
|
+
_: 1
|
|
155
|
+
}, 8, ["label"])
|
|
156
|
+
]),
|
|
157
|
+
_: 1
|
|
158
|
+
}, 8, ["title"])
|
|
159
|
+
]),
|
|
160
|
+
_: 1
|
|
161
|
+
}, 8, ["title", "desc", "preview-title"]));
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
export {
|
|
165
|
+
ue as default
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=UploadSection2.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UploadSection2.vue.js","sources":["../../../../../src/views/system/config/components/UploadSection.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 文件上传:大小上限 + 后缀白名单。后端 FileService 读这两键强制执行,保存即生效。\n// 后缀以逗号分隔落库,输入时补前导点、转小写(与后端 ParseExts 对齐)。\n// 预览是用户看到的上传框,再拿几个示例文件按新规则判一遍,能不能传、为什么不能一目了然。\nimport { computed } from 'vue'\nimport { NDynamicTags, NInputNumber, NSlider } from 'naive-ui'\nimport { useI18n } from 'vue-i18n'\nimport AppIcon from '#/components/AppIcon.vue'\nimport { UPLOAD_EXTS_KEY, UPLOAD_MAX_KEY } from '../groups'\nimport { useConfigDraft, useDraftFields } from '../draft'\nimport { vFlash } from '../flash'\nimport SectionLayout from './SectionLayout.vue'\nimport CfgGroup from './CfgGroup.vue'\nimport CfgRow from './CfgRow.vue'\n\nconst { t } = useI18n()\nconst { values } = useConfigDraft()\nconst { num } = useDraftFields()\nconst maxSizeMb = num(UPLOAD_MAX_KEY, 20)\n\nfunction normalizeExt(v: string): string {\n const s = v.trim().toLowerCase()\n return s.startsWith('.') ? s : '.' + s\n}\nconst exts = computed({\n get: () =>\n (values[UPLOAD_EXTS_KEY] ?? '')\n .split(',')\n .map(e => e.trim())\n .filter(Boolean),\n set: (list: string[]) => {\n values[UPLOAD_EXTS_KEY] = [...new Set(list.map(normalizeExt).filter(e => e !== '.'))].join(',')\n },\n})\n\nconst PRESETS = {\n images: ['.jpg', '.jpeg', '.png', '.gif', '.webp'],\n docs: ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'],\n archives: ['.zip', '.rar', '.7z'],\n} as const\nfunction addPreset(name: keyof typeof PRESETS) {\n exts.value = [...exts.value, ...PRESETS[name]]\n}\n\nconst SAMPLES = [\n { name: 'report.pdf', mb: 3.2 },\n { name: 'photo.png', mb: 1.4 },\n { name: 'demo.mp4', mb: 48 },\n { name: 'setup.exe', mb: 12 },\n]\nconst samples = computed(() =>\n SAMPLES.map(f => {\n const ext = f.name.slice(f.name.lastIndexOf('.'))\n // 白名单留空时格式以服务端默认为准,这里不替它下结论\n const extOk = exts.value.length ? exts.value.includes(ext) : undefined\n const sizeOk = f.mb <= maxSizeMb.value\n const status =\n extOk === false\n ? { ok: false, text: t('config.upload.fileBadExt', { ext }) }\n : !sizeOk\n ? { ok: false, text: t('config.upload.fileTooBig', { mb: maxSizeMb.value }) }\n : extOk\n ? { ok: true, text: t('config.upload.fileOk') }\n : { ok: undefined, text: t('config.upload.fileDefault') }\n return { ...f, ext: ext.slice(1).toUpperCase(), status }\n }),\n)\nconst limitText = computed(() =>\n t('config.upload.previewLimit', {\n exts: exts.value.length ? exts.value.join(' ') : t('config.upload.previewDefault'),\n mb: maxSizeMb.value,\n }),\n)\n</script>\n\n<template>\n <SectionLayout\n :title=\"t('config.tab.upload')\"\n :desc=\"t('config.upload.desc')\"\n :preview-title=\"t('config.upload.preview')\"\n layout=\"slim\"\n >\n <CfgGroup :title=\"t('config.upload.groupLimit')\">\n <CfgRow :label=\"t('config.upload.maxSizeMb')\" :keys=\"[UPLOAD_MAX_KEY]\">\n <n-slider\n v-model:value=\"maxSizeMb\"\n class=\"slider\"\n :min=\"1\"\n :max=\"200\"\n :tooltip=\"false\"\n :aria-label=\"t('config.upload.maxSizeMb')\"\n />\n <n-input-number\n v-model:value=\"maxSizeMb\"\n class=\"num\"\n size=\"small\"\n :min=\"1\"\n :show-button=\"false\"\n :input-props=\"{ 'aria-label': t('config.upload.maxSizeMb') }\"\n />\n <span class=\"unit\">MB</span>\n </CfgRow>\n <CfgRow\n :label=\"t('config.upload.allowedExtensions')\"\n :hint=\"t('config.upload.extTip')\"\n :keys=\"[UPLOAD_EXTS_KEY]\"\n tall\n class=\"exts\"\n >\n <n-dynamic-tags v-model:value=\"exts\" size=\"small\" />\n </CfgRow>\n <CfgRow :label=\"t('config.upload.quickAdd')\">\n <span class=\"presets\">\n <button\n v-for=\"(_, name) in PRESETS\"\n :key=\"name\"\n type=\"button\"\n class=\"chip\"\n @click=\"addPreset(name)\"\n >\n {{ t(`config.upload.preset.${name}`) }}\n </button>\n <button type=\"button\" class=\"chip\" @click=\"exts = []\">\n {{ t('config.upload.preset.clear') }}\n </button>\n </span>\n </CfgRow>\n </CfgGroup>\n\n <template #preview>\n <div class=\"drop\" data-testid=\"upload-preview\">\n <AppIcon icon=\"ph:cloud-arrow-up\" :size=\"30\" class=\"ic\" />\n <b>{{ t('config.upload.previewDrop') }}</b>\n <small v-flash=\"limitText\">{{ limitText }}</small>\n </div>\n <ul v-flash=\"limitText\" class=\"files\">\n <li v-for=\"f in samples\" :key=\"f.name\">\n <span class=\"fi\">{{ f.ext }}</span>\n <span class=\"nm\">\n {{ f.name }}\n <small>{{ f.mb }} MB</small>\n </span>\n <span :class=\"['st', { ok: f.status.ok === true, no: f.status.ok === false }]\">\n {{ f.status.text }}\n </span>\n </li>\n </ul>\n </template>\n </SectionLayout>\n</template>\n\n<style scoped>\n.slider {\n width: 160px;\n}\n.num {\n width: 72px;\n}\n.num :deep(input) {\n text-align: right;\n}\n.unit {\n font-size: var(--font-size-sm);\n color: var(--color-text-secondary);\n}\n.exts :deep(.ctl) {\n flex: 1.4;\n}\n.exts :deep(.n-dynamic-tags) {\n justify-content: flex-end;\n}\n.presets {\n display: inline-flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 5px;\n}\n.chip {\n padding: 2px 9px;\n border: 0;\n border-radius: 6px;\n background: var(--color-fill);\n font: inherit;\n font-size: var(--font-size-sm);\n line-height: 20px;\n color: var(--color-text-secondary);\n cursor: pointer;\n}\n.chip:hover {\n background: var(--color-fill-hover);\n}\n.chip:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: 1px;\n}\n.drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n padding: 24px 16px;\n border: 1.5px dashed var(--color-border-strong);\n border-radius: 14px;\n background: var(--color-bg-container);\n text-align: center;\n}\n.drop .ic {\n color: var(--color-primary);\n}\n.drop b {\n font-weight: 500;\n}\n.drop small {\n padding: 1px 6px;\n border-radius: 6px;\n color: var(--color-text-secondary);\n}\n.files {\n margin: 0;\n padding: 0;\n list-style: none;\n border-radius: 12px;\n background: var(--color-bg-container);\n}\n.files li {\n position: relative;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 9px 14px;\n font-size: var(--font-size-base);\n}\n.files li + li::before {\n content: '';\n position: absolute;\n top: 0;\n left: 50px;\n right: 0;\n border-top: 0.5px solid var(--color-border);\n}\n.fi {\n display: grid;\n flex: none;\n place-items: center;\n width: 26px;\n height: 30px;\n border-radius: 5px;\n background: var(--color-fill);\n font-size: 9px;\n font-weight: 700;\n color: var(--color-text-secondary);\n}\n.nm {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-width: 0;\n}\n.nm small {\n font-size: var(--font-size-sm);\n color: var(--color-text-tertiary);\n}\n.st {\n font-size: var(--font-size-sm);\n color: var(--color-text-tertiary);\n}\n.st.ok {\n color: var(--color-success);\n}\n.st.no {\n color: var(--color-danger);\n}\n</style>\n"],"names":["t","useI18n","values","useConfigDraft","num","useDraftFields","maxSizeMb","UPLOAD_MAX_KEY","normalizeExt","v","s","exts","computed","UPLOAD_EXTS_KEY","e","list","PRESETS","addPreset","name","SAMPLES","samples","f","ext","extOk","sizeOk","status","limitText","_createBlock","SectionLayout","_unref","_createElementVNode","_hoisted_3","_createVNode","AppIcon","_createElementBlock","_withDirectives","_openBlock","_hoisted_4","_Fragment","_renderList","_hoisted_5","_toDisplayString","_hoisted_6","_normalizeClass","CfgGroup","CfgRow","NSlider","$event","NInputNumber","_cache","NDynamicTags","_hoisted_1","_","_hoisted_2"],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { ExternalProviderAdmin } from '../../../api';
|
|
2
|
+
import { ConfigTab, LoginLocale } from './groups';
|
|
3
|
+
export declare const enabledKey: (code: string) => string;
|
|
4
|
+
export declare const linkKey: (code: string) => string;
|
|
5
|
+
export declare const hasLinkSwitch: (code: string) => boolean;
|
|
6
|
+
/** 与原值不同的键(按字符串比较;配置值一律以字符串落库)。 */
|
|
7
|
+
export declare function diffKeys(original: Record<string, string>, values: Record<string, string>): string[];
|
|
8
|
+
/** 保存前的校验结论:error 阻止保存并跳到对应分类,warnings 只提示。 */
|
|
9
|
+
export interface DraftCheck {
|
|
10
|
+
error?: {
|
|
11
|
+
tab: ConfigTab;
|
|
12
|
+
message: string;
|
|
13
|
+
locale?: LoginLocale;
|
|
14
|
+
};
|
|
15
|
+
warnings: {
|
|
16
|
+
locale: LoginLocale;
|
|
17
|
+
message: string;
|
|
18
|
+
}[];
|
|
19
|
+
}
|
|
20
|
+
/** 登录页 Hero 的规则:卖点最多 5 条(阻止);强调词不在主标题里(提示,照常保存)。 */
|
|
21
|
+
export declare function checkDraft(values: Record<string, string>): DraftCheck;
|
|
22
|
+
export declare function createConfigDraft(): {
|
|
23
|
+
original: Record<string, string>;
|
|
24
|
+
values: Record<string, string>;
|
|
25
|
+
providers: import('vue').Ref<{
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
linkByAccount: boolean;
|
|
28
|
+
code: string;
|
|
29
|
+
displayName: string;
|
|
30
|
+
icon?: string | null | undefined;
|
|
31
|
+
}[], ExternalProviderAdmin[] | {
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
linkByAccount: boolean;
|
|
34
|
+
code: string;
|
|
35
|
+
displayName: string;
|
|
36
|
+
icon?: string | null | undefined;
|
|
37
|
+
}[]>;
|
|
38
|
+
catalog: import('vue').Ref<{
|
|
39
|
+
dataProtectionEphemeral: boolean;
|
|
40
|
+
callbackBaseUrlMissing: boolean;
|
|
41
|
+
types: {
|
|
42
|
+
type: string;
|
|
43
|
+
defaultDisplayName: string;
|
|
44
|
+
defaultIcon: null | string;
|
|
45
|
+
allowMultiple: boolean;
|
|
46
|
+
fields: {
|
|
47
|
+
name: string;
|
|
48
|
+
secret: boolean;
|
|
49
|
+
required: boolean;
|
|
50
|
+
default: null | string;
|
|
51
|
+
definesEndpoint: boolean;
|
|
52
|
+
}[];
|
|
53
|
+
}[];
|
|
54
|
+
providers: {
|
|
55
|
+
code: string;
|
|
56
|
+
type: string;
|
|
57
|
+
displayName: string;
|
|
58
|
+
icon: null | string;
|
|
59
|
+
source: string;
|
|
60
|
+
installed: boolean;
|
|
61
|
+
configured: boolean;
|
|
62
|
+
values: {
|
|
63
|
+
[key: string]: string;
|
|
64
|
+
};
|
|
65
|
+
secrets: {
|
|
66
|
+
[key: string]: import('../../..').KernelComponents["schemas"]["ExternalAuthSecretState"];
|
|
67
|
+
};
|
|
68
|
+
callbackUri: string;
|
|
69
|
+
}[];
|
|
70
|
+
callbackUriTemplate: string;
|
|
71
|
+
}, {
|
|
72
|
+
dataProtectionEphemeral: boolean;
|
|
73
|
+
callbackBaseUrlMissing: boolean;
|
|
74
|
+
types: import('../../..').KernelComponents["schemas"]["ExternalAuthTypeView"][];
|
|
75
|
+
providers: import('../../..').KernelComponents["schemas"]["ExternalAuthProviderView"][];
|
|
76
|
+
callbackUriTemplate: string;
|
|
77
|
+
} | {
|
|
78
|
+
dataProtectionEphemeral: boolean;
|
|
79
|
+
callbackBaseUrlMissing: boolean;
|
|
80
|
+
types: {
|
|
81
|
+
type: string;
|
|
82
|
+
defaultDisplayName: string;
|
|
83
|
+
defaultIcon: null | string;
|
|
84
|
+
allowMultiple: boolean;
|
|
85
|
+
fields: {
|
|
86
|
+
name: string;
|
|
87
|
+
secret: boolean;
|
|
88
|
+
required: boolean;
|
|
89
|
+
default: null | string;
|
|
90
|
+
definesEndpoint: boolean;
|
|
91
|
+
}[];
|
|
92
|
+
}[];
|
|
93
|
+
providers: {
|
|
94
|
+
code: string;
|
|
95
|
+
type: string;
|
|
96
|
+
displayName: string;
|
|
97
|
+
icon: null | string;
|
|
98
|
+
source: string;
|
|
99
|
+
installed: boolean;
|
|
100
|
+
configured: boolean;
|
|
101
|
+
values: {
|
|
102
|
+
[key: string]: string;
|
|
103
|
+
};
|
|
104
|
+
secrets: {
|
|
105
|
+
[key: string]: import('../../..').KernelComponents["schemas"]["ExternalAuthSecretState"];
|
|
106
|
+
};
|
|
107
|
+
callbackUri: string;
|
|
108
|
+
}[];
|
|
109
|
+
callbackUriTemplate: string;
|
|
110
|
+
}>;
|
|
111
|
+
providerRows: import('vue').ComputedRef<import('../../../utils/oauthBrand').ConfigProviderRow[]>;
|
|
112
|
+
loading: import('vue').Ref<boolean, boolean>;
|
|
113
|
+
saving: import('vue').Ref<boolean, boolean>;
|
|
114
|
+
pendingLogo: import('vue').Ref<{
|
|
115
|
+
readonly size: number;
|
|
116
|
+
readonly type: string;
|
|
117
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
118
|
+
bytes: () => Promise<Uint8Array<ArrayBuffer>>;
|
|
119
|
+
slice: (start?: number, end?: number, contentType?: string) => Blob;
|
|
120
|
+
stream: () => ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
121
|
+
text: () => Promise<string>;
|
|
122
|
+
} | null, Blob | {
|
|
123
|
+
readonly size: number;
|
|
124
|
+
readonly type: string;
|
|
125
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
126
|
+
bytes: () => Promise<Uint8Array<ArrayBuffer>>;
|
|
127
|
+
slice: (start?: number, end?: number, contentType?: string) => Blob;
|
|
128
|
+
stream: () => ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
129
|
+
text: () => Promise<string>;
|
|
130
|
+
} | null>;
|
|
131
|
+
dirtyKeys: import('vue').ComputedRef<string[]>;
|
|
132
|
+
dirtyTabs: import('vue').ComputedRef<Set<"security" | "brand" | "advanced" | "job" | "sensitive" | "upload" | "signin">>;
|
|
133
|
+
claimedKeys: import('vue').ComputedRef<string[]>;
|
|
134
|
+
load: () => Promise<void>;
|
|
135
|
+
refreshProviders: () => Promise<void>;
|
|
136
|
+
discard: () => void;
|
|
137
|
+
save: () => Promise<void>;
|
|
138
|
+
setPendingLogo: (blob: Blob | null, previewUrl: string) => void;
|
|
139
|
+
};
|
|
140
|
+
export type ConfigDraft = ReturnType<typeof createConfigDraft>;
|
|
141
|
+
export declare function provideConfigDraft(draft: ConfigDraft): void;
|
|
142
|
+
export declare function useConfigDraft(): ConfigDraft;
|
|
143
|
+
/** 字符串 / 数值 / 开关三种双向绑定,模板里直接 v-model。 */
|
|
144
|
+
export declare function useDraftFields(): {
|
|
145
|
+
str: (key: string) => import('vue').WritableComputedRef<string, string>;
|
|
146
|
+
num: (key: string, fallback: number) => import('vue').WritableComputedRef<number, number>;
|
|
147
|
+
bool: (key: string) => import('vue').WritableComputedRef<boolean, boolean>;
|
|
148
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { reactive as L, ref as m, computed as v, provide as B, inject as F } from "vue";
|
|
2
|
+
import { configApi as O, externalAuthApi as p } from "../../../api/index.js";
|
|
3
|
+
import { loadSite as M } from "../../../composables/useSite.js";
|
|
4
|
+
import { splitLoginHeroFeatures as G } from "../../../lib/loginHero.js";
|
|
5
|
+
import { buildConfigProviderRows as I, LINK_BY_ACCOUNT_CODES as x } from "../../../utils/oauthBrand.js";
|
|
6
|
+
import { tabOfKey as Y, STATIC_CLAIMED_KEYS as S, LOGIN_LOCALES as V, LOGO_KEY as y, bumpConfigRevision as $, STRUCTURED_GROUPS as H, heroKeys as W } from "./groups.js";
|
|
7
|
+
const h = (e) => `sys.externalauth.${e}.enabled`, A = (e) => `sys.externalauth.${e}.linkByAccount`, k = (e) => x.includes(e);
|
|
8
|
+
function E(e, t) {
|
|
9
|
+
return Object.keys(t).filter((i) => t[i] !== e[i]);
|
|
10
|
+
}
|
|
11
|
+
function te(e) {
|
|
12
|
+
var i, r;
|
|
13
|
+
const t = [];
|
|
14
|
+
for (const l of V) {
|
|
15
|
+
const f = W(l);
|
|
16
|
+
if (G(e[f.features], Number.MAX_SAFE_INTEGER).length > 5)
|
|
17
|
+
return { error: { tab: "brand", locale: l, message: "config.login.tooManyFeatures" }, warnings: t };
|
|
18
|
+
const a = ((i = e[f.headline]) == null ? void 0 : i.trim()) ?? "", u = ((r = e[f.highlight]) == null ? void 0 : r.trim()) ?? "";
|
|
19
|
+
u && a && !a.includes(u) && t.push({ locale: l, message: "config.login.highlightMissing" });
|
|
20
|
+
}
|
|
21
|
+
return { warnings: t };
|
|
22
|
+
}
|
|
23
|
+
function oe() {
|
|
24
|
+
const e = L({}), t = L({}), i = m([]), r = m({
|
|
25
|
+
dataProtectionEphemeral: !1,
|
|
26
|
+
callbackBaseUrlMissing: !1,
|
|
27
|
+
callbackUriTemplate: "",
|
|
28
|
+
types: [],
|
|
29
|
+
providers: []
|
|
30
|
+
}), l = m(!0), f = m(!1), a = m(null), u = v(() => I(r.value, i.value)), b = v(() => E(e, t)), j = v(() => new Set(b.value.map(Y))), _ = v(() => [
|
|
31
|
+
...S,
|
|
32
|
+
...u.value.flatMap(
|
|
33
|
+
(o) => k(o.code) ? [h(o.code), A(o.code)] : [h(o.code)]
|
|
34
|
+
)
|
|
35
|
+
]);
|
|
36
|
+
function D(o) {
|
|
37
|
+
for (const n of Object.keys(e)) delete e[n];
|
|
38
|
+
for (const n of Object.keys(t)) delete t[n];
|
|
39
|
+
Object.assign(e, o), Object.assign(t, o);
|
|
40
|
+
}
|
|
41
|
+
async function R() {
|
|
42
|
+
l.value = !0;
|
|
43
|
+
try {
|
|
44
|
+
const [o, n, g] = await Promise.all([
|
|
45
|
+
Promise.all(H.map((d) => O.listByGroup(d))),
|
|
46
|
+
p.providersAll(),
|
|
47
|
+
p.catalog()
|
|
48
|
+
]);
|
|
49
|
+
i.value = n, r.value = g;
|
|
50
|
+
const c = new Set(S), s = {};
|
|
51
|
+
for (const d of S) s[d] = "";
|
|
52
|
+
for (const d of o.flat())
|
|
53
|
+
c.has(d.configKey) && (s[d.configKey] = d.configValue ?? "");
|
|
54
|
+
Object.assign(s, C()), D(s);
|
|
55
|
+
} finally {
|
|
56
|
+
l.value = !1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function C() {
|
|
60
|
+
const o = {};
|
|
61
|
+
for (const n of u.value.filter((g) => g.registered))
|
|
62
|
+
o[h(n.code)] = String(n.enabled), k(n.code) && (o[A(n.code)] = String(n.linkByAccount));
|
|
63
|
+
return o;
|
|
64
|
+
}
|
|
65
|
+
async function N() {
|
|
66
|
+
const [o, n] = await Promise.all([
|
|
67
|
+
p.providersAll(),
|
|
68
|
+
p.catalog()
|
|
69
|
+
]);
|
|
70
|
+
i.value = o, r.value = n;
|
|
71
|
+
const g = C();
|
|
72
|
+
for (const [c, s] of Object.entries(g))
|
|
73
|
+
c in e || (e[c] = s, t[c] = s);
|
|
74
|
+
for (const c of u.value.filter((s) => !s.registered))
|
|
75
|
+
for (const s of [h(c.code), A(c.code)])
|
|
76
|
+
delete e[s], delete t[s];
|
|
77
|
+
}
|
|
78
|
+
function P(o, n) {
|
|
79
|
+
w(), a.value = o, t[y] = n;
|
|
80
|
+
}
|
|
81
|
+
function w() {
|
|
82
|
+
var o;
|
|
83
|
+
(o = t[y]) != null && o.startsWith("blob:") && URL.revokeObjectURL(t[y]);
|
|
84
|
+
}
|
|
85
|
+
function T() {
|
|
86
|
+
w(), a.value = null, Object.assign(t, e);
|
|
87
|
+
}
|
|
88
|
+
async function U() {
|
|
89
|
+
f.value = !0;
|
|
90
|
+
try {
|
|
91
|
+
if (a.value) {
|
|
92
|
+
const n = new File([a.value], "logo.png", { type: "image/png" }), g = await O.uploadLogo(n);
|
|
93
|
+
w(), t[y] = g.viewUrl ?? "", a.value = null;
|
|
94
|
+
}
|
|
95
|
+
for (const n of b.value) t[n] = t[n].trim();
|
|
96
|
+
const o = E(e, t).map((n) => ({
|
|
97
|
+
configKey: n,
|
|
98
|
+
configValue: t[n]
|
|
99
|
+
}));
|
|
100
|
+
o.length && await O.saveBatch(o), Object.assign(e, t), $(), await M(!0);
|
|
101
|
+
} finally {
|
|
102
|
+
f.value = !1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
original: e,
|
|
107
|
+
values: t,
|
|
108
|
+
providers: i,
|
|
109
|
+
catalog: r,
|
|
110
|
+
providerRows: u,
|
|
111
|
+
loading: l,
|
|
112
|
+
saving: f,
|
|
113
|
+
pendingLogo: a,
|
|
114
|
+
dirtyKeys: b,
|
|
115
|
+
dirtyTabs: j,
|
|
116
|
+
claimedKeys: _,
|
|
117
|
+
load: R,
|
|
118
|
+
refreshProviders: N,
|
|
119
|
+
discard: T,
|
|
120
|
+
save: U,
|
|
121
|
+
setPendingLogo: P
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const K = Symbol("config-draft");
|
|
125
|
+
function ne(e) {
|
|
126
|
+
B(K, e);
|
|
127
|
+
}
|
|
128
|
+
function X() {
|
|
129
|
+
const e = F(K);
|
|
130
|
+
if (!e) throw new Error("useConfigDraft() 只能在配置中心页面内使用");
|
|
131
|
+
return e;
|
|
132
|
+
}
|
|
133
|
+
function ie() {
|
|
134
|
+
const { values: e } = X();
|
|
135
|
+
return {
|
|
136
|
+
str: (t) => v({
|
|
137
|
+
get: () => e[t] ?? "",
|
|
138
|
+
set: (i) => {
|
|
139
|
+
e[t] = i ?? "";
|
|
140
|
+
}
|
|
141
|
+
}),
|
|
142
|
+
num: (t, i) => v({
|
|
143
|
+
get: () => {
|
|
144
|
+
const r = Number(e[t]);
|
|
145
|
+
return e[t] === "" || e[t] === void 0 || Number.isNaN(r) ? i : r;
|
|
146
|
+
},
|
|
147
|
+
set: (r) => {
|
|
148
|
+
e[t] = String(r ?? i);
|
|
149
|
+
}
|
|
150
|
+
}),
|
|
151
|
+
bool: (t) => v({
|
|
152
|
+
get: () => e[t] === "true",
|
|
153
|
+
set: (i) => {
|
|
154
|
+
e[t] = i ? "true" : "false";
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
te as checkDraft,
|
|
161
|
+
oe as createConfigDraft,
|
|
162
|
+
E as diffKeys,
|
|
163
|
+
h as enabledKey,
|
|
164
|
+
k as hasLinkSwitch,
|
|
165
|
+
A as linkKey,
|
|
166
|
+
ne as provideConfigDraft,
|
|
167
|
+
X as useConfigDraft,
|
|
168
|
+
ie as useDraftFields
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=draft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft.js","sources":["../../../../src/views/system/config/draft.ts"],"sourcesContent":["// 配置中心的页面级草稿:进页面一次载入所有结构化表单的值,各分类只读写这份草稿,\n// 底部保存条统一保存。切换顶部导航不会丢改动;离开页面草稿随组件销毁。\nimport { computed, inject, provide, reactive, ref, type InjectionKey } from 'vue'\nimport {\n configApi,\n externalAuthApi,\n type ExternalAuthCatalog,\n type ExternalProviderAdmin,\n} from '#/api'\nimport { loadSite } from '#/composables/useSite'\nimport { splitLoginHeroFeatures } from '#/lib/loginHero'\nimport { buildConfigProviderRows, LINK_BY_ACCOUNT_CODES } from '#/utils/oauthBrand'\nimport {\n bumpConfigRevision,\n heroKeys,\n LOGIN_LOCALES,\n LOGO_KEY,\n STATIC_CLAIMED_KEYS,\n STRUCTURED_GROUPS,\n tabOfKey,\n type ConfigTab,\n type LoginLocale,\n} from './groups'\n\nexport const enabledKey = (code: string) => `sys.externalauth.${code}.enabled`\nexport const linkKey = (code: string) => `sys.externalauth.${code}.linkByAccount`\nexport const hasLinkSwitch = (code: string) => LINK_BY_ACCOUNT_CODES.includes(code)\n\n/** 与原值不同的键(按字符串比较;配置值一律以字符串落库)。 */\nexport function diffKeys(original: Record<string, string>, values: Record<string, string>) {\n return Object.keys(values).filter(key => values[key] !== original[key])\n}\n\n/** 保存前的校验结论:error 阻止保存并跳到对应分类,warnings 只提示。 */\nexport interface DraftCheck {\n error?: { tab: ConfigTab; message: string; locale?: LoginLocale }\n warnings: { locale: LoginLocale; message: string }[]\n}\n\n/** 登录页 Hero 的规则:卖点最多 5 条(阻止);强调词不在主标题里(提示,照常保存)。 */\nexport function checkDraft(values: Record<string, string>): DraftCheck {\n const warnings: DraftCheck['warnings'] = []\n for (const locale of LOGIN_LOCALES) {\n const keys = heroKeys(locale)\n if (splitLoginHeroFeatures(values[keys.features], Number.MAX_SAFE_INTEGER).length > 5)\n return { error: { tab: 'brand', locale, message: 'config.login.tooManyFeatures' }, warnings }\n const headline = values[keys.headline]?.trim() ?? ''\n const highlight = values[keys.highlight]?.trim() ?? ''\n if (highlight && headline && !headline.includes(highlight))\n warnings.push({ locale, message: 'config.login.highlightMissing' })\n }\n return { warnings }\n}\n\nexport function createConfigDraft() {\n const original = reactive<Record<string, string>>({})\n const values = reactive<Record<string, string>>({})\n const providers = ref<ExternalProviderAdmin[]>([])\n const catalog = ref<ExternalAuthCatalog>({\n dataProtectionEphemeral: false,\n callbackBaseUrlMissing: false,\n callbackUriTemplate: '',\n types: [],\n providers: [],\n })\n const loading = ref(true)\n const saving = ref(false)\n /** 裁剪好、还没上传的 Logo;预览期间 values[LOGO_KEY] 是它的 blob: 地址,保存时才上传 */\n const pendingLogo = ref<Blob | null>(null)\n\n const providerRows = computed(() => buildConfigProviderRows(catalog.value, providers.value))\n const dirtyKeys = computed(() => diffKeys(original, values))\n const dirtyTabs = computed(() => new Set(dirtyKeys.value.map(tabOfKey)))\n /** 结构化表单认领的全部键:「高级」页排除它们。未注册的第三方登录方式也算,它们的开关在卡片上。 */\n const claimedKeys = computed(() => [\n ...STATIC_CLAIMED_KEYS,\n ...providerRows.value.flatMap(p =>\n hasLinkSwitch(p.code) ? [enabledKey(p.code), linkKey(p.code)] : [enabledKey(p.code)],\n ),\n ])\n\n function reset(next: Record<string, string>) {\n for (const key of Object.keys(original)) delete original[key]\n for (const key of Object.keys(values)) delete values[key]\n Object.assign(original, next)\n Object.assign(values, next)\n }\n\n async function load() {\n loading.value = true\n try {\n const [groups, list, cat] = await Promise.all([\n Promise.all(STRUCTURED_GROUPS.map(g => configApi.listByGroup(g))),\n externalAuthApi.providersAll(),\n externalAuthApi.catalog(),\n ])\n providers.value = list\n catalog.value = cat\n const claimed = new Set(STATIC_CLAIMED_KEYS)\n const next: Record<string, string> = {}\n // 库里没有的键按空串起步:表单显示默认值,不动它就不算改动,也不会被写回\n for (const key of STATIC_CLAIMED_KEYS) next[key] = ''\n for (const row of groups.flat())\n if (claimed.has(row.configKey)) next[row.configKey] = row.configValue ?? ''\n // 第三方登录只收已配置的方式:没配好的开关不可打开,永远不写\n Object.assign(next, providerSwitchValues())\n reset(next)\n } finally {\n loading.value = false\n }\n }\n\n /** 已配置的第三方各自的开关值(enabled / linkByAccount)。 */\n function providerSwitchValues() {\n const out: Record<string, string> = {}\n for (const p of providerRows.value.filter(row => row.registered)) {\n out[enabledKey(p.code)] = String(p.enabled)\n if (hasLinkSwitch(p.code)) out[linkKey(p.code)] = String(p.linkByAccount)\n }\n return out\n }\n\n /**\n * 设置面板保存或清除之后重读第三方目录。已在草稿里的开关不动(可能有未保存的改动),\n * 新配好的补进来,被清掉的移出——没有配置的方式,开关没有意义。\n */\n async function refreshProviders() {\n const [list, cat] = await Promise.all([\n externalAuthApi.providersAll(),\n externalAuthApi.catalog(),\n ])\n providers.value = list\n catalog.value = cat\n const fresh = providerSwitchValues()\n for (const [key, value] of Object.entries(fresh)) {\n if (key in original) continue\n original[key] = value\n values[key] = value\n }\n for (const row of providerRows.value.filter(r => !r.registered)) {\n for (const key of [enabledKey(row.code), linkKey(row.code)]) {\n delete original[key]\n delete values[key]\n }\n }\n }\n\n function setPendingLogo(blob: Blob | null, previewUrl: string) {\n revokePreview()\n pendingLogo.value = blob\n values[LOGO_KEY] = previewUrl\n }\n\n function revokePreview() {\n if (values[LOGO_KEY]?.startsWith('blob:')) URL.revokeObjectURL(values[LOGO_KEY])\n }\n\n function discard() {\n revokePreview()\n pendingLogo.value = null\n Object.assign(values, original)\n }\n\n /** 保存全部改动;有待传的 Logo 先上传换成签名直链,再一次批量写库。 */\n async function save() {\n saving.value = true\n try {\n if (pendingLogo.value) {\n const file = new File([pendingLogo.value], 'logo.png', { type: 'image/png' })\n const uploaded = await configApi.uploadLogo(file)\n revokePreview()\n values[LOGO_KEY] = uploaded.viewUrl ?? ''\n // 传完就清掉:后面批量保存失败时重试不会再传一遍\n pendingLogo.value = null\n }\n for (const key of dirtyKeys.value) values[key] = values[key].trim()\n const items = diffKeys(original, values).map(configKey => ({\n configKey,\n configValue: values[configKey],\n }))\n if (items.length) await configApi.saveBatch(items)\n Object.assign(original, values)\n bumpConfigRevision()\n // 即时生效:侧栏、顶栏、登录页、浏览器标签页的品牌随之刷新\n await loadSite(true)\n } finally {\n saving.value = false\n }\n }\n\n return {\n original,\n values,\n providers,\n catalog,\n providerRows,\n loading,\n saving,\n pendingLogo,\n dirtyKeys,\n dirtyTabs,\n claimedKeys,\n load,\n refreshProviders,\n discard,\n save,\n setPendingLogo,\n }\n}\n\nexport type ConfigDraft = ReturnType<typeof createConfigDraft>\n\nconst DRAFT_KEY: InjectionKey<ConfigDraft> = Symbol('config-draft')\n\nexport function provideConfigDraft(draft: ConfigDraft) {\n provide(DRAFT_KEY, draft)\n}\n\nexport function useConfigDraft(): ConfigDraft {\n const draft = inject(DRAFT_KEY)\n if (!draft) throw new Error('useConfigDraft() 只能在配置中心页面内使用')\n return draft\n}\n\n/** 字符串 / 数值 / 开关三种双向绑定,模板里直接 v-model。 */\nexport function useDraftFields() {\n const { values } = useConfigDraft()\n return {\n str: (key: string) =>\n computed({\n get: () => values[key] ?? '',\n set: v => {\n values[key] = v ?? ''\n },\n }),\n num: (key: string, fallback: number) =>\n computed<number>({\n get: () => {\n const n = Number(values[key])\n return values[key] === '' || values[key] === undefined || Number.isNaN(n) ? fallback : n\n },\n set: v => {\n values[key] = String(v ?? fallback)\n },\n }),\n bool: (key: string) =>\n computed<boolean>({\n get: () => values[key] === 'true',\n set: v => {\n values[key] = v ? 'true' : 'false'\n },\n }),\n }\n}\n"],"names":["enabledKey","code","linkKey","hasLinkSwitch","LINK_BY_ACCOUNT_CODES","diffKeys","original","values","key","checkDraft","warnings","locale","LOGIN_LOCALES","keys","heroKeys","splitLoginHeroFeatures","headline","_a","highlight","_b","createConfigDraft","reactive","providers","ref","catalog","loading","saving","pendingLogo","providerRows","computed","buildConfigProviderRows","dirtyKeys","dirtyTabs","tabOfKey","claimedKeys","STATIC_CLAIMED_KEYS","p","reset","next","load","groups","list","cat","STRUCTURED_GROUPS","configApi","g","externalAuthApi","claimed","row","providerSwitchValues","out","refreshProviders","fresh","value","r","setPendingLogo","blob","previewUrl","revokePreview","LOGO_KEY","discard","save","file","uploaded","items","configKey","bumpConfigRevision","loadSite","DRAFT_KEY","provideConfigDraft","draft","provide","useConfigDraft","inject","useDraftFields","v","fallback","n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flash.js","sources":["../../../../src/views/system/config/flash.ts"],"sourcesContent":["// v-flash=\"值\":值一变,元素闪一下橙框(样式 .cfg-flash 在 SectionLayout 的预览区里)。\n// 用在预览里受某项设置影响的部分上,让用户看到\"刚才改的东西落在这里\"。\nimport type { Directive } from 'vue'\n\nexport const vFlash: Directive<HTMLElement, unknown> = {\n updated(el, binding) {\n if (binding.value === binding.oldValue) return\n el.classList.remove('cfg-flash')\n void el.offsetWidth // 重新触发动画\n el.classList.add('cfg-flash')\n },\n}\n"],"names":["vFlash","el","binding"],"mappings":"AAIO,MAAMA,IAA0C;AAAA,EACrD,QAAQC,GAAIC,GAAS;AACnB,IAAIA,EAAQ,UAAUA,EAAQ,aAC9BD,EAAG,UAAU,OAAO,WAAW,GAC1BA,EAAG,aACRA,EAAG,UAAU,IAAI,WAAW;AAAA,EAC9B;AACF;"}
|
|
@@ -1,9 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
export declare const CONFIG_TABS: readonly ["brand", "security", "signin", "sensitive", "upload", "job", "advanced"];
|
|
2
|
+
export type ConfigTab = (typeof CONFIG_TABS)[number];
|
|
3
|
+
/** 顶部导航分组:站点与安全 | 系统,组间留空。 */
|
|
4
|
+
export declare const TAB_GROUPS: readonly (readonly ConfigTab[])[];
|
|
5
|
+
/** 导航图标 */
|
|
6
|
+
export declare const TAB_ICONS: Record<ConfigTab, string>;
|
|
7
|
+
export declare const LOGO_KEY = "sys.site.logo";
|
|
8
|
+
export declare const BRAND_KEYS: readonly ["sys.site.title", "sys.site.logo", "sys.site.copyright", "sys.site.copyrightUrl"];
|
|
9
|
+
export declare const LOGIN_LOCALES: readonly ["zh-CN", "en-US"];
|
|
10
|
+
export type LoginLocale = (typeof LOGIN_LOCALES)[number];
|
|
11
|
+
export declare const heroKeys: (locale: LoginLocale) => {
|
|
12
|
+
headline: string;
|
|
13
|
+
highlight: string;
|
|
14
|
+
features: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const SUBTITLE_KEY = "sys.site.subtitle";
|
|
17
|
+
export declare const SHOW_FEATURES_KEY = "sys.login.hero.showFeatures";
|
|
18
|
+
export declare const LOGIN_KEYS: string[];
|
|
19
|
+
export declare const SECURITY_NUMBERS: Readonly<Record<string, number>>;
|
|
20
|
+
/** 短信验证码登录是一种登录方式,在「登录方式」页,不在安全策略 */
|
|
21
|
+
export declare const SMS_LOGIN_KEY = "sys.security.smsLogin.enabled";
|
|
22
|
+
export declare const SECURITY_SWITCHES: readonly ["sys.security.password.requireUpper", "sys.security.password.requireLower", "sys.security.password.requireDigit", "sys.security.password.requireSpecial", "sys.security.password.forceChangeOnFirstLogin", "sys.security.captcha.enabled", "sys.security.totp.enabled", "sys.security.totp.requireForSuperAdmin", "sys.security.mfa.enabled", "sys.security.rateLimit.enabled"];
|
|
23
|
+
export declare const CAPTCHA_TYPE_KEY = "sys.security.captcha.type";
|
|
24
|
+
export declare const SECURITY_KEYS: string[];
|
|
25
|
+
export declare const UPLOAD_MAX_KEY = "sys.upload.maxSizeMb";
|
|
26
|
+
export declare const UPLOAD_EXTS_KEY = "sys.upload.allowedExtensions";
|
|
27
|
+
export declare const JOB_RETENTION_KEY = "sys.job.logRetentionDays";
|
|
28
|
+
export declare const JOB_ALERT_KEY = "sys.job.alertEmails";
|
|
29
|
+
/** 固定认领的键(第三方登录的键按已注册的方式动态认领,见 draft.ts)。 */
|
|
30
|
+
export declare const STATIC_CLAIMED_KEYS: readonly string[];
|
|
31
|
+
/** 结构化表单从这些分组取值。 */
|
|
32
|
+
export declare const STRUCTURED_GROUPS: readonly ["sys", "login", "security", "upload", "job"];
|
|
33
|
+
/** 键 → 所属分类,用于导航上的"有未保存改动"标记。 */
|
|
34
|
+
export declare function tabOfKey(key: string): ConfigTab;
|
|
35
|
+
/** 配置行增删改的版本号:保存或在「高级」页改了行之后 bump,「高级」表据此重拉。 */
|
|
8
36
|
export declare const configRevision: import('vue').Ref<number, number>;
|
|
9
37
|
export declare function bumpConfigRevision(): void;
|