first commit

This commit is contained in:
cieanyau committed 2026-11-06 00:04:38 +08:00
commit db5762abd4
687 files changed
+171307

No files matched your search

+726
View File
@@ -0,0 +1,726 @@
<script>
import "~/assets/styles/AuthProviders.CgAWouSf.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onUnmounted } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { useRoute } from "#app";
import { useRouter } from "#app";
import { loginErrorMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import { isValidJwt } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import radiobutton from "primevue/radiobutton";
import { r as wechat_binding_r } from "~/lib/wechat-binding.js";
import { r as auth_redirect_r } from "~/lib/auth-redirect.js";
var fe = {
key: 0,
class: `auth-providers`,
"aria-label": `其他登录方式`,
},
S = [`id`, `aria-labelledby`],
pe = {
key: 0,
class: `login-qr`,
},
me = {
class: `qr-stage`,
},
he = {
key: 0,
class: `qr-clients`,
},
ge = [`aria-busy`],
_e = [`src`],
ve = {
class: `qr-status`,
"aria-live": `polite`,
},
ye = {
key: 1,
class: `qr-tip`,
},
be = {
class: `qr-actions`,
},
xe = [
`id`,
`aria-selected`,
`aria-controls`,
`tabindex`,
`disabled`,
`title`,
`aria-label`,
`onClick`,
],
Se = 5,
Ce = 300,
C = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `AuthProviders`,
setup(ee, { expose: b }) {
let C = useAuth(),
w = useRoute(),
T = useRouter(),
E = useApi(),
{ load: D, scanLoginEnabled: O, error: we } = useSiteConfig_t(),
k = ref(!1),
A = null;
function j() {
((k.value = A?.matches ?? !1), k.value || Q());
}
let M = computed(() => [
{
id: `wechat`,
label: `微信`,
enabled: O.value,
},
{
id: `other`,
label: `其他方式`,
enabled: !1,
},
]),
N = ref(0),
P = computed(() => M.value[N.value]),
F = ref([]);
function Te(e) {
let t = M.value.flatMap((e, t) => (e.enabled ? [t] : []));
if (!t.length) return;
let n = t.indexOf(N.value),
r = n;
if (e.key === `ArrowRight`) r = (n + 1) % t.length;
else if (e.key === `ArrowLeft`) r = (n + t.length - 1) % t.length;
else if (e.key === `Home`) r = 0;
else if (e.key === `End`) r = t.length - 1;
else return;
(e.preventDefault(), (N.value = t[r]), F.value[N.value]?.focus());
}
let I = ref(null),
L = ref(!1),
R = ref(!1),
z = ref(``),
B = ref([]),
V = ref(null),
H = ref(!1),
U = ref(0),
W = null,
G = null,
K = 0,
q = null;
function J() {
W !== null && (clearInterval(W), (W = null));
}
function Y() {
(G !== null && (clearInterval(G), (G = null)), (U.value = 0));
}
function Ee() {
(J(), Y(), (W = window.setInterval(De, 2e3)));
let e = Math.floor(Date.now() / 1e3),
t = I.value?.expire_time ? I.value.expire_time - e : Ce;
((U.value = Math.max(1, t - Se)),
(G = window.setInterval(() => {
(--U.value, U.value <= 0 && (Y(), X()));
}, 1e3)));
}
async function X() {
if (!k.value || L.value) return;
let e = ++K;
(Z(),
(z.value = ``),
(R.value = !1),
(B.value = []),
(V.value = null),
(H.value = !1),
(L.value = !0));
try {
let t = await E.get(`/mp_weixin_notice/qrcode`, void 0, !1, {
timeoutMs: 15e3,
});
if (e !== K) return;
if (
typeof t?.img_url != `string` ||
!t.img_url ||
typeof t.ticket != `string` ||
!t.ticket ||
typeof t.token != `string` ||
!t.token
)
throw Error(`二维码加载失败,请重新获取`);
((I.value = t), (z.value = ``), Ee());
} catch (t) {
if (e !== K) return;
(J(),
Y(),
(z.value = loginErrorMessage(t, `二维码加载失败,请稍后重试`)));
} finally {
e === K && (L.value = !1);
}
}
async function De() {
if (!I.value || q === K) return;
let e = K,
t = I.value;
q = e;
try {
let n = await E.get(
`/mp_weixin_notice/qrcode/status`,
{
ticket: t.ticket,
token: t.token,
},
!1,
{
timeoutMs: 1e4,
},
);
if (e !== K) return;
if (!n || typeof n.status != `string`)
throw Error(`扫码登录状态异常,请重新获取二维码`);
if (n.status === `Wait`) return;
if (n.status === `Success`) {
n.jwt
? $(n.jwt)
: (Z(),
(z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`));
return;
}
if (n.status === `Expired`) {
(J(),
Y(),
(R.value = !0),
(z.value = `二维码已过期,请刷新后重新扫码`));
return;
}
if (n.status === `SelectClient`) {
(J(),
Y(),
(B.value = Array.isArray(n.client)
? n.client.filter(
(e) =>
e &&
Number.isSafeInteger(e.id) &&
e.id > 0 &&
typeof e.username == `string`,
)
: []),
(V.value = B.value.find((e) => e.status === 1)?.id ?? null),
V.value ||
(z.value = `当前微信没有可登录的账号,请使用账号密码登录或联系客服`));
return;
}
if (n.status === `WaitBind`) {
(Z(),
wechat_binding_r(t, sessionStorage),
await T.push({
path: `/oauth/bind`,
query: {
provider: `wechat`,
redirect: auth_redirect_r(w.query.redirect),
},
}));
return;
}
(Z(), (z.value = `扫码登录状态异常,请重新获取二维码`));
} catch (t) {
if (e !== K) return;
(Z(),
(z.value = loginErrorMessage(
t,
`扫码登录验证失败,请刷新二维码后重试`,
)));
} finally {
q === e && (q = null);
}
}
function Z() {
(J(), Y());
}
function Q() {
(K++,
Z(),
(I.value = null),
(L.value = !1),
(H.value = !1),
(R.value = !1),
(z.value = ``),
(B.value = []),
(V.value = null));
}
function $(e) {
if ((Z(), !isValidJwt(e))) {
z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`;
return;
}
(C.loginWithJwt(e), K++, T.push(auth_redirect_r(w.query.redirect)));
}
async function Oe() {
if (H.value) return;
if (
!I.value ||
!B.value.some((e) => e.id === V.value && e.status === 1)
) {
z.value = `请选择一个可登录的账号`;
return;
}
((z.value = ``), (H.value = !0));
let e = K;
try {
let t = await E.post(
`/mp_weixin_notice/qrcode/select_client_login`,
{
ticket: I.value.ticket,
token: I.value.token,
client_id: V.value,
},
!1,
{
timeoutMs: 15e3,
},
);
if (e !== K) return;
t?.jwt
? $(t.jwt)
: (z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`);
} catch (t) {
if (e !== K) return;
z.value = loginErrorMessage(t);
} finally {
e === K && (H.value = !1);
}
}
return (
onMounted(async () => {
((A = window.matchMedia(`(min-width: 761px)`)),
j(),
A.addEventListener(`change`, j),
await D().catch(() => {}));
}),
watch(N, Q),
onUnmounted(() => {
(A?.removeEventListener(`change`, j), Q());
}),
b({
resetQr: Q,
}),
(n, r) => {
let a = radiobutton,
s = button,
u = message;
return unref(k)
? (openBlock(),
createElementBlock(`aside`, fe, [
createElementVNode(
`div`,
{
id: `provider-panel-${unref(P).id}`,
role: `tabpanel`,
"aria-labelledby": `provider-tab-${unref(P).id}`,
class: `provider-panel`,
},
[
unref(O)
? (openBlock(),
createElementBlock(`div`, pe, [
createElementVNode(`div`, me, [
unref(B).length
? (openBlock(),
createElementBlock(`div`, he, [
(r[1] ||= createElementVNode(
`p`,
{
class: `qr-tip`,
},
`请选择要登录的账号`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(B),
(t) => (
openBlock(),
createElementBlock(
`label`,
{
key: t.id,
class: normalizeClass([
`qr-client`,
{
disabled: t.status !== 1,
},
]),
},
[
createVNode(
a,
{
modelValue: unref(V),
"onUpdate:modelValue":
(r[0] ||= (e) =>
isRef(V)
? (V.value = e)
: null),
"input-id": `qr-client-${t.id}`,
value: t.id,
disabled: t.status !== 1,
},
null,
8,
[
`modelValue`,
`input-id`,
`value`,
`disabled`,
],
),
createElementVNode(
`span`,
null,
toDisplayString(t.username),
1,
),
],
2,
)
),
),
128,
)),
createVNode(
s,
{
label: `登录`,
loading: unref(H),
disabled: !unref(V) || unref(H),
class: `qr-client-btn`,
fluid: ``,
onClick: Oe,
},
null,
8,
[`loading`, `disabled`],
),
]))
: (openBlock(),
createElementBlock(
`div`,
{
key: 1,
class: normalizeClass([
`qr-box`,
{
"qr-box-idle": !unref(I),
},
]),
"aria-busy": unref(L),
},
[
unref(I) && !unref(R)
? (openBlock(),
createElementBlock(
`img`,
{
key: 0,
class: normalizeClass([
`qr-img`,
{
"qr-img-dim": unref(L),
},
]),
src: unref(I).img_url,
alt: `微信扫码登录`,
},
null,
10,
_e,
))
: (openBlock(),
createBlock(
s,
{
key: 1,
type: `button`,
label: unref(R)
? `刷新二维码`
: `获取二维码`,
icon: unref(R)
? `pi pi-refresh`
: `pi pi-qrcode`,
severity: `secondary`,
text: ``,
class: `qr-request`,
loading: unref(L),
disabled: unref(L),
onClick: X,
},
null,
8,
[
`label`,
`icon`,
`loading`,
`disabled`,
],
)),
],
10,
ge,
)),
]),
createElementVNode(`div`, ve, [
unref(z)
? (openBlock(),
createBlock(
u,
{
key: 0,
severity: `error`,
closable: !1,
icon: `pi pi-exclamation-circle`,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(z)),
1,
),
]),
_: 1,
},
))
: (openBlock(),
createElementBlock(
`p`,
ye,
toDisplayString(
unref(L) && !unref(I)
? `二维码加载中…`
: unref(B).length
? `选择账号后继续登录`
: `使用微信扫一扫登录`,
),
1,
)),
]),
createElementVNode(`div`, be, [
unref(B).length
? (openBlock(),
createBlock(s, {
key: 0,
type: `button`,
label: `返回重新扫码`,
severity: `secondary`,
text: ``,
size: `small`,
onClick: X,
}))
: unref(I) && !unref(R)
? (openBlock(),
createBlock(
s,
{
key: 1,
type: `button`,
label: `刷新二维码`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
size: `small`,
loading: unref(L),
disabled: unref(L),
onClick: X,
},
null,
8,
[`loading`, `disabled`],
))
: createCommentVNode(``, !0),
]),
]))
: createCommentVNode(``, !0),
unref(O)
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
(r[2] ||= createElementVNode(
`div`,
{
class: `provider-qr-placeholder`,
"aria-hidden": `true`,
},
[
createElementVNode(`i`, {
class: `pi pi-qrcode`,
}),
],
-1,
)),
(r[3] ||= createElementVNode(
`p`,
{
class: `provider-heading`,
},
`微信扫码登录`,
-1,
)),
(r[4] ||= createElementVNode(
`p`,
{
class: `provider-description`,
},
`扫码登录暂不可用,请使用手机号或邮箱登录`,
-1,
)),
],
64,
)),
unref(we)
? (openBlock(),
createBlock(
u,
{
key: 2,
severity: `warn`,
closable: !1,
class: `provider-config-error`,
},
{
default: withCtx(() => [
(r[5] ||= createTextVNode(
`登录方式加载失败。`,
-1,
)),
createVNode(
s,
{
type: `button`,
label: `重试`,
text: ``,
size: `small`,
onClick: unref(D),
},
null,
8,
[`onClick`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
],
8,
S,
),
createElementVNode(
`div`,
{
class: `provider-tabs`,
role: `tablist`,
"aria-label": `扫码登录方式`,
onKeydown: Te,
},
[
createElementVNode(
`span`,
{
class: `provider-tab-indicator`,
style: normalizeStyle({
transform: `translateX(${unref(N) * 100}%)`,
}),
"aria-hidden": `true`,
},
null,
4,
),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(M),
(t, n) => (
openBlock(),
createElementBlock(
`button`,
{
id: `provider-tab-${t.id}`,
key: t.id,
ref_for: !0,
ref_key: `providerTabs`,
ref: F,
type: `button`,
role: `tab`,
"aria-selected": unref(N) === n,
"aria-controls": t.enabled
? `provider-panel-${t.id}`
: void 0,
tabindex: unref(N) === n ? 0 : -1,
disabled: !t.enabled,
title: t.enabled
? void 0
: `${t.label}暂未开放`,
"aria-label": t.enabled
? `${t.label}登录`
: `${t.label}暂未开放`,
class: normalizeClass({
active: unref(N) === n,
}),
onClick: (e) => (N.value = n),
},
toDisplayString(t.label),
11,
xe,
)
),
),
128,
)),
],
32,
),
]))
: createCommentVNode(``, !0);
}
);
},
}),
[[`__scopeId`, `data-v-9d0ee2f9`]],
),
{
__name: `AuthProviders`,
},
);
export {};
export default C;
</script>
+433
View File
@@ -0,0 +1,433 @@
<script>
import "~/assets/styles/BackendNavEntry.Bx6IPica.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useRoute } from "#app";
import { NuxtLink } from "#components";
import { Icon } from "#components";
import { c as backend_menu_c } from "~/lib/backend-menu.js";
import { n as backend_menu_n } from "~/lib/backend-menu.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var T = {
key: 0,
class: `nav-group`,
},
E = [`aria-expanded`],
D = {
class: `nav-label`,
},
O = [`inert`, `aria-hidden`],
k = {
class: `sub-nav-clip`,
},
A = {
class: `sub-nav-items`,
},
j = [`href`, `aria-current`, `onClick`],
M = {
class: `nav-label`,
},
N = [`href`],
P = {
class: `nav-label`,
},
F = [`title`],
I = {
class: `nav-label`,
},
L = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `BackendNavEntry`,
props: {
entry: {},
siblings: {},
nested: {
type: Boolean,
},
},
setup(m) {
let w = m,
R = useRoute(),
z = `configured-nav-${useId()}`,
B = ref(null);
function V(e) {
let t = e
.filter((e) => e.to)
.map((e) => ({
to: e.to,
}));
return e.some(
(e) =>
(e.to && backend_menu_c(e.to, R, t)) ||
(e.children && V(e.children)),
);
}
let H = computed(() => V(w.entry.children ?? [])),
U = computed(() => B.value ?? H.value),
W = computed(
() =>
!!w.entry.to &&
backend_menu_c(
w.entry.to,
R,
(w.siblings ?? [])
.filter((e) => e.to)
.map((e) => ({
to: e.to,
})),
),
),
G = ref(!1),
K;
function q(e, t) {
if (!w.entry.confirm) {
t && (e.preventDefault(), t());
return;
}
(e.preventDefault(),
(K =
t ??
(() =>
window.open(w.entry.href, `_blank`, `noopener,noreferrer`))),
(G.value = !0));
}
function J() {
G.value = !1;
let e = K;
((K = void 0), e?.());
}
return (n, a) => {
let c = Icon,
_ = L,
b = NuxtLink,
w = button,
R = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
m.entry.children?.length
? (openBlock(),
createElementBlock(`div`, T, [
createElementVNode(
`button`,
{
type: `button`,
class: normalizeClass([
`nav-item`,
{
active: unref(H),
},
]),
"aria-expanded": unref(U),
"aria-controls": z,
onClick: (a[0] ||= (e) => (B.value = !unref(U))),
},
[
createVNode(
c,
{
name: unref(backend_menu_n)(m.entry),
class: `nav-icon`,
},
null,
8,
[`name`],
),
createElementVNode(
`span`,
D,
toDisplayString(m.entry.label),
1,
),
createElementVNode(
`i`,
{
class: normalizeClass([
`pi pi-angle-down nav-arrow`,
{
open: unref(U),
},
]),
"aria-hidden": `true`,
},
null,
2,
),
],
10,
E,
),
createElementVNode(
`div`,
{
id: z,
class: normalizeClass([
`sub-nav`,
{
open: unref(U),
},
]),
inert: !unref(U),
"aria-hidden": !unref(U),
},
[
createElementVNode(`div`, k, [
createElementVNode(`div`, A, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
m.entry.children,
(e) => (
openBlock(),
createBlock(
_,
{
key: e.key,
entry: e,
siblings: m.entry.children,
nested: ``,
},
null,
8,
[`entry`, `siblings`],
)
),
),
128,
)),
]),
]),
],
10,
O,
),
]))
: m.entry.to
? (openBlock(),
createBlock(
b,
{
key: 1,
to: m.entry.to,
custom: ``,
},
{
default: withCtx(({ href: t, navigate: n }) => [
createElementVNode(
`a`,
{
href: t || void 0,
class: normalizeClass([
m.nested ? `sub-item` : `nav-item`,
{
active: unref(W),
},
]),
"aria-current": unref(W) ? `page` : void 0,
onClick: (e) => q(e, n),
},
[
m.nested
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
c,
{
key: 0,
name: unref(backend_menu_n)(m.entry),
class: `nav-icon`,
},
null,
8,
[`name`],
)),
createElementVNode(
`span`,
M,
toDisplayString(m.entry.label),
1,
),
],
10,
j,
),
]),
_: 1,
},
8,
[`to`],
))
: m.entry.href
? (openBlock(),
createElementBlock(
`a`,
{
key: 2,
href: m.entry.href,
class: normalizeClass(
m.nested
? `sub-item configured-external`
: `nav-item`,
),
target: `_blank`,
rel: `noopener noreferrer`,
onClick: (a[1] ||= (e) => q(e)),
},
[
m.nested
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
c,
{
key: 0,
name: unref(backend_menu_n)(m.entry),
class: `nav-icon`,
},
null,
8,
[`name`],
)),
createElementVNode(
`span`,
P,
toDisplayString(m.entry.label),
1,
),
(a[4] ||= createElementVNode(
`i`,
{
class: `pi pi-external-link external-icon`,
"aria-hidden": `true`,
},
null,
-1,
)),
],
10,
N,
))
: (openBlock(),
createElementBlock(
`button`,
{
key: 3,
type: `button`,
class: normalizeClass([
m.nested ? `sub-item` : `nav-item`,
`nav-unavailable`,
]),
disabled: ``,
title: m.entry.disabledReason,
},
[
m.nested
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
c,
{
key: 0,
name: unref(backend_menu_n)(m.entry),
class: `nav-icon`,
},
null,
8,
[`name`],
)),
createElementVNode(
`span`,
I,
toDisplayString(m.entry.label),
1,
),
(a[5] ||= createElementVNode(
`small`,
null,
`暂未开放`,
-1,
)),
],
10,
F,
)),
createVNode(
R,
{
visible: unref(G),
"onUpdate:visible": (a[3] ||= (e) =>
isRef(G) ? (G.value = e) : null),
header: `打开链接`,
modal: ``,
draggable: !1,
style: {
width: `420px`,
},
},
{
footer: withCtx(() => [
createVNode(w, {
label: `取消`,
severity: `secondary`,
outlined: ``,
onClick: (a[2] ||= (e) => (G.value = !1)),
}),
createVNode(w, {
label: `确认打开`,
onClick: J,
}),
]),
default: withCtx(() => [
createElementVNode(
`p`,
null,
`确认打开「` +
toDisplayString(m.entry.label) +
`」?`,
1,
),
]),
_: 1,
},
8,
[`visible`],
),
],
64,
)
);
};
},
}),
[[`__scopeId`, `data-v-b0009398`]],
),
{
__name: `BackendNavEntry`,
},
);
export {};
export default L;
</script>
+153
View File
@@ -0,0 +1,153 @@
<script>
import "~/assets/styles/BackendNavEntry.Bx6IPica.css";
import "~/assets/styles/BackendNavigation.CEj4LnzI.css";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { renderSlot } from "vue";
import { createBlock } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import { t as navigation_state_t } from "~/lib/navigation-state.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import BackendNavEntry from "~/components/BackendNavEntry.vue";
var y = {
key: 1,
class: `nav-placeholder`,
role: `status`,
"aria-label": `正在加载导航`,
},
b = {
key: 2,
class: `nav-load-error`,
role: `status`,
},
x = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `BackendNavigation`,
emits: [`loaded`],
setup(u, { emit: _ }) {
let x = _,
S = useApi(),
C = navigation_state_t(useAuth(), S),
{ entries: w, loading: T, error: E, loaded: D } = C,
O = !0;
onBeforeUnmount(() => {
O = !1;
});
async function k() {
(await C.load(!!E.value),
O && D.value && x(`loaded`, w.value, C.authoritative.value));
}
return (
onMounted(k),
(t, n) => {
let u = BackendNavEntry,
p = button;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
unref(D)
? renderSlot(
t.$slots,
`default`,
{},
() => [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(w),
(e) => (
openBlock(),
createBlock(
u,
{
key: e.key,
entry: e,
siblings: unref(w),
},
null,
8,
[`entry`, `siblings`],
)
),
),
128,
)),
],
!0,
0,
)
: unref(E)
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, y, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(10, (e) =>
createElementVNode(`span`, {
key: e,
}),
),
64,
)),
])),
unref(E)
? (openBlock(),
createElementBlock(`div`, b, [
(n[0] ||= createElementVNode(
`span`,
null,
`导航加载失败`,
-1,
)),
createVNode(
p,
{
label: `重试`,
size: `small`,
text: ``,
severity: `secondary`,
disabled: unref(T),
onClick: k,
},
null,
8,
[`disabled`],
),
]))
: createCommentVNode(``, !0),
],
64,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-02b58e93`]],
),
{
__name: `BackendNavigation`,
},
);
export {};
export default x;
</script>
+177
View File
@@ -0,0 +1,177 @@
<script>
import "~/assets/styles/BuildUpdateNotice.CuqdqvlF.css";
import { reloadNuxtApp as y } from "#app";
import { useNuxtApp } from "#app";
import { toDisplayString } from "vue";
import { onBeforeUnmount } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var b = {
key: 0,
class: `build-notice`,
role: `status`,
"aria-live": `polite`,
},
x = {
class: `build-actions`,
},
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `BuildUpdateNotice`,
setup(d) {
let m = useNuxtApp(),
h = ref(!1),
v = ref(!1),
S = ref(!1),
C = ref(!1),
w = ``,
T = m.hook(`app:manifest:update`, (e) => {
(e?.id && e.id === w) || ((w = e?.id || ``), (h.value = !0));
}),
E = m.hook(`app:chunkError`, () => {
((C.value = !0), (h.value = !0));
});
onBeforeUnmount(() => {
(T(), E());
});
function D() {
h.value = !1;
}
function O() {
v.value = !0;
}
function k() {
!S.value &&
v.value &&
((S.value = !0),
y({
force: !0,
persistState: !1,
}));
}
return (e, n) => {
let r = button,
d = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
unref(h)
? (openBlock(),
createElementBlock(`aside`, b, [
createElementVNode(`div`, null, [
createElementVNode(
`strong`,
null,
toDisplayString(
unref(C) ? `页面资源需要更新` : `发现新版本`,
),
1,
),
(n[2] ||= createElementVNode(
`p`,
null,
`请完成并保存当前操作后刷新页面。`,
-1,
)),
]),
createElementVNode(`div`, x, [
createVNode(r, {
label: `稍后`,
text: ``,
severity: `secondary`,
onClick: D,
}),
createVNode(r, {
label: `刷新页面`,
size: `small`,
onClick: O,
}),
]),
]))
: createCommentVNode(``, !0),
createVNode(
d,
{
visible: unref(v),
"onUpdate:visible": (n[1] ||= (e) =>
isRef(v) ? (v.value = e) : null),
header: `刷新页面`,
modal: ``,
closable: !unref(S),
draggable: !1,
style: {
width: `460px`,
maxWidth: `94vw`,
},
},
{
footer: withCtx(() => [
createVNode(
r,
{
label: `继续当前操作`,
severity: `secondary`,
disabled: unref(S),
onClick: (n[0] ||= (e) => (v.value = !1)),
},
null,
8,
[`disabled`],
),
createVNode(
r,
{
label: `确认刷新`,
loading: unref(S),
onClick: k,
},
null,
8,
[`loading`],
),
]),
default: withCtx(() => [
(n[3] ||= createElementVNode(
`p`,
null,
`刷新会清空尚未提交的表单。请确认支付、身份验证等操作已结束,且需要保留的信息已经保存。`,
-1,
)),
]),
_: 1,
},
8,
[`visible`, `closable`],
),
],
64,
)
);
};
},
}),
[[`__scopeId`, `data-v-fc2ba853`]],
),
{
__name: `BuildUpdateNotice`,
},
);
export { y as n };
export default S;
</script>
+230
View File
@@ -0,0 +1,230 @@
<script>
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
import { toDisplayString } from "vue";
import { useId } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { createBlock } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import GeetestField from "~/components/GeetestField.vue";
import inputtext from "primevue/inputtext";
var _ = {
class: `field`,
},
v = [`for`],
y = {
class: `row`,
},
b = [`disabled`],
x = [`src`],
S = {
key: 1,
class: `pi pi-spin pi-spinner`,
},
C = {
key: 2,
class: `retry`,
},
w = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `CaptchaField`,
props: mergeModels(
{
img: {},
loading: {
type: Boolean,
},
label: {},
provider: {},
captchaId: {},
disabled: {
type: Boolean,
},
},
{
modelValue: {
default: ``,
},
modelModifiers: {},
},
),
emits: mergeModels(
[`refresh`, `verified`, `invalid`],
[`update:modelValue`],
),
setup(n, { emit: u }) {
let m = u,
w = useModel(n, `modelValue`),
T = useId();
return (t, r) => {
let u = GeetestField,
E = button,
D = inputtext;
return (
openBlock(),
createElementBlock(`div`, _, [
n.provider === `geetest`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
!n.loading && n.captchaId
? (openBlock(),
createBlock(
u,
{
key: 0,
"captcha-id": n.captchaId,
disabled: n.disabled,
onVerified: (r[0] ||= (e) => m(`verified`, e)),
onInvalid: (r[1] ||= (e) => m(`invalid`)),
},
null,
8,
[`captcha-id`, `disabled`],
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
(r[5] ||= createElementVNode(
`span`,
null,
`人机验证`,
-1,
)),
createVNode(
E,
{
type: `button`,
severity: `secondary`,
outlined: ``,
label: n.loading
? `验证码加载中…`
: `重新加载验证码`,
disabled: n.loading || n.disabled,
onClick: (r[2] ||= (e) => m(`refresh`)),
fluid: ``,
},
null,
8,
[`label`, `disabled`],
),
],
64,
)),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`label`,
{
for: unref(T),
},
toDisplayString(n.label || `图形验证码`),
9,
v,
),
createElementVNode(`div`, y, [
createVNode(
D,
{
id: unref(T),
modelValue: w.value,
"onUpdate:modelValue": (r[3] ||= (e) =>
(w.value = e)),
placeholder: `请输入图中字符`,
disabled: n.disabled || n.loading,
autocomplete: `off`,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
createElementVNode(
`button`,
{
type: `button`,
class: `img`,
disabled: n.loading || n.disabled,
title: `点击刷新`,
"aria-label": `刷新图形验证码`,
onClick: (r[4] ||= (e) => m(`refresh`)),
},
[
n.img
? (openBlock(),
createElementBlock(
`img`,
{
key: 0,
src: n.img,
alt: `图形验证码`,
},
null,
8,
x,
))
: n.loading
? (openBlock(), createElementBlock(`i`, S))
: (openBlock(),
createElementBlock(`span`, C, [
...(r[6] ||= [
createElementVNode(
`i`,
{
class: `pi pi-refresh`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(` 点击加载`, -1),
]),
])),
],
8,
b,
),
]),
],
64,
)),
])
);
};
},
}),
[[`__scopeId`, `data-v-5ba6618f`]],
),
{
__name: `CaptchaField`,
},
);
export {};
export default w;
</script>
+87
View File
@@ -0,0 +1,87 @@
<script setup>
import { computed, onMounted, onBeforeUnmount, ref } from "vue";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { LineChart } from "echarts/charts";
import {
GridComponent,
TooltipComponent,
LegendComponent,
} from "echarts/components";
import VChart from "vue-echarts";
import { t as useTheme } from "~/lib/useTheme.js";
import "~/assets/styles/ChartBox.CYP_mhat.css";
use([
CanvasRenderer,
LineChart,
GridComponent,
TooltipComponent,
LegendComponent,
]);
const props = defineProps({
option: { type: Object, required: true },
height: { default: 140 },
loading: Boolean,
});
const theme = useTheme();
const container = ref(null);
const visible = ref(false);
let observer;
onMounted(() => {
observer = new ResizeObserver(([entry]) => {
if (entry?.contentRect.width > 0 && entry.contentRect.height > 0)
visible.value = true;
});
if (container.value) observer.observe(container.value);
});
onBeforeUnmount(() => observer?.disconnect());
const themedOption = computed(() => {
const dark = theme.isDark.value;
const color = dark ? "#a1a1aa" : "#94a3b8";
const grid = dark ? "rgba(255,255,255,.08)" : "rgba(0,0,0,.06)";
const axis = {
axisLine: { lineStyle: { color: grid } },
axisLabel: { color, fontSize: 11 },
};
const apply = (value, y = false) => ({
...axis,
...value,
...(y ? { splitLine: { lineStyle: { color: grid } } } : {}),
});
return {
textStyle: { color },
...props.option,
xAxis: Array.isArray(props.option.xAxis)
? props.option.xAxis.map((value) => apply(value))
: apply(props.option.xAxis),
yAxis: Array.isArray(props.option.yAxis)
? props.option.yAxis.map((value) => apply(value, true))
: apply(props.option.yAxis, true),
};
});
</script>
<template>
<div ref="container" class="chart-box" :style="{ height: `${height}px` }">
<VChart
v-if="visible"
:option="themedOption"
:loading="loading"
autoresize
class="chart"
/>
</div>
</template>
<style scoped>
.chart-box {
width: 100%;
min-width: 0;
overflow: hidden;
}
.chart {
width: 100%;
height: 100%;
}
</style>
+449
View File
@@ -0,0 +1,449 @@
<script>
import "~/assets/styles/ClientLevelDialog.DcYabp-W.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as product_name_n } from "~/lib/product-name.js";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import column from "primevue/column";
var E = {
key: 0,
class: `lvl-state`,
},
D = {
key: 1,
class: `lvl-state`,
},
O = {
class: `lvl-grid`,
},
k = {
class: `lvl-item`,
},
A = {
class: `lvl-item`,
},
j = {
class: `lvl-value`,
},
M = {
class: `lvl-item`,
},
N = {
class: `lvl-value`,
},
P = {
class: `lvl-item`,
},
F = {
class: `lvl-value`,
},
I = {
class: `lvl-grid`,
},
L = {
class: `lvl-item`,
},
R = {
key: 4,
class: `lvl-state`,
},
z = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ClientLevelDialog`,
props: mergeModels(
{
accountLevel: {},
},
{
modelValue: {
type: Boolean,
default: !1,
},
modelModifiers: {},
},
),
emits: [`update:modelValue`],
setup(n) {
let h = useModel(n, `modelValue`),
x = useApi(),
z = ref(null),
B = ref(!1),
V = ref(``),
H = computed(() => z.value?.levels ?? []),
U = computed(() => {
let e = {};
for (let t of H.value)
for (let n of t.discount_list ?? []) {
if (!n.product_name) continue;
let r = e[n.product_name] ?? (e[n.product_name] = {});
r[`level_${t.id}`] = n.discount_percent;
}
return Object.entries(e).map(([e, t]) => ({
product_name: e,
...t,
}));
});
function W(e, t) {
let n = e[`level_${t}`];
return n == null || n === `` ? `--` : `${n}%`;
}
function G(e) {
return `¥${Number(e ?? 0).toFixed(2)}`;
}
async function K() {
((B.value = !0), (V.value = ``));
try {
z.value = await x.get(`/client_level`);
} catch (e) {
V.value = e instanceof Error ? e.message : `等级信息加载失败`;
} finally {
B.value = !1;
}
}
return (
watch(h, (e) => {
e && K();
}),
(r, i) => {
let o = column,
l = datatable,
y = dialog;
return (
openBlock(),
createBlock(
y,
{
visible: h.value,
"onUpdate:visible": (i[0] ||= (e) => (h.value = e)),
header: `等级策略`,
modal: ``,
style: {
width: `min(720px, calc(100vw - 28px))`,
},
},
{
default: withCtx(() => [
unref(B)
? (openBlock(), createElementBlock(`div`, E, `加载中…`))
: unref(V)
? (openBlock(),
createElementBlock(
`div`,
D,
toDisplayString(unref(V)),
1,
))
: unref(z) && unref(z).level_id > 0
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(`div`, O, [
createElementVNode(`div`, k, [
(i[1] ||= createElementVNode(
`span`,
{
class: `lvl-label`,
},
`我的等级`,
-1,
)),
createElementVNode(
`span`,
{
class: `lvl-value`,
style: normalizeStyle({
color:
unref(z).background_color ||
void 0,
}),
},
toDisplayString(
unref(z).level_name || `普通会员`,
),
5,
),
]),
createElementVNode(`div`, A, [
(i[2] ||= createElementVNode(
`span`,
{
class: `lvl-label`,
},
`等级有效期`,
-1,
)),
createElementVNode(
`span`,
j,
toDisplayString(
unref(z).cycle_end_time
? (`formatTime` in r
? r.formatTime
: unref(dict_r))(
unref(z).cycle_end_time,
)
: `长期有效`,
),
1,
),
]),
createElementVNode(`div`, M, [
(i[3] ||= createElementVNode(
`span`,
{
class: `lvl-label`,
},
`当前周期消费`,
-1,
)),
createElementVNode(
`span`,
N,
toDisplayString(
G(unref(z).cycle_consume_amount),
),
1,
),
]),
createElementVNode(`div`, P, [
(i[4] ||= createElementVNode(
`span`,
{
class: `lvl-label`,
},
`距下一等级`,
-1,
)),
createElementVNode(
`span`,
F,
toDisplayString(
unref(z).next_level_name
? `${unref(z).next_level_name} 还需 ${G(unref(z).next_level_need_amount)}`
: `已是最高等级`,
),
1,
),
]),
]),
(i[6] ||= createElementVNode(
`p`,
{
class: `lvl-desc`,
},
`等级折扣由系统在结算时自动应用;部分优惠码不可与等级折扣叠加,以下单页的实际价格为准。`,
-1,
)),
unref(U).length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
(i[5] ||= createElementVNode(
`h4`,
{
class: `lvl-section`,
},
`等级折扣`,
-1,
)),
createVNode(
l,
{
value: unref(U),
size: `small`,
scrollable: ``,
scrollHeight: `400px`,
},
{
default: withCtx(() => [
createVNode(
o,
{
field: `product_name`,
header: `商品`,
frozen: ``,
style: {
"min-width": `150px`,
},
},
{
body: withCtx(
({ data: t }) => [
createTextVNode(
toDisplayString(
unref(
product_name_n,
)(t.product_name),
),
1,
),
],
),
_: 1,
},
),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(H),
(t) => (
openBlock(),
createBlock(
o,
{
key: t.id,
style: {
"min-width": `100px`,
},
},
{
header: withCtx(
() => [
createElementVNode(
`span`,
{
style:
normalizeStyle(
{
color:
t.background_color ||
void 0,
},
),
},
toDisplayString(
t.name,
),
5,
),
],
),
body: withCtx(
({ data: n }) => [
createTextVNode(
toDisplayString(
W(n, t.id),
),
1,
),
],
),
_: 2,
},
1024,
)
),
),
128,
)),
]),
_: 1,
},
8,
[`value`],
),
],
64,
))
: createCommentVNode(``, !0),
],
64,
))
: n.accountLevel
? (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
createElementVNode(`div`, I, [
createElementVNode(`div`, L, [
(i[7] ||= createElementVNode(
`span`,
{
class: `lvl-label`,
},
`我的等级`,
-1,
)),
createElementVNode(
`span`,
{
class: `lvl-value`,
style: normalizeStyle({
color:
n.accountLevel
.background_color || void 0,
}),
},
toDisplayString(n.accountLevel.name),
5,
),
]),
]),
(i[8] ||= createElementVNode(
`p`,
{
class: `lvl-desc`,
},
`该等级没有公开的升级策略(下一等级与折扣范围由平台设置);下单时折扣会自动应用到价格。`,
-1,
)),
],
64,
))
: (openBlock(),
createElementBlock(`div`, R, `暂无等级信息`)),
]),
_: 1,
},
8,
[`visible`],
)
);
}
);
},
}),
[[`__scopeId`, `data-v-7c5ffb84`]],
),
{
__name: `ClientLevelDialog`,
},
);
export {};
export default z;
</script>
+69
View File
@@ -0,0 +1,69 @@
<script>
import "~/assets/styles/ConsoleLegalFooter.DAYWmXIB.css";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var i = {},
a = {
class: `console-legal-footer`,
"aria-label": `网站备案信息`,
};
function o(r, i) {
return (
openBlock(),
createElementBlock(`footer`, a, [
...(i[0] ||= [
createElementVNode(
`div`,
{
class: `legal-footer-inner`,
},
[
createElementVNode(
`span`,
null,
`运营主体:厦门破碎工坊网络科技有限公司`,
),
createElementVNode(
`a`,
{
href: `https://beian.miit.gov.cn/`,
target: `_blank`,
rel: `noopener noreferrer`,
},
`ICP备案:闽ICP备2023023682号-1`,
),
createElementVNode(
`a`,
{
href: `https://beian.mps.gov.cn/#/query/webSearch?code=35020602002951`,
target: `_blank`,
rel: `noopener noreferrer`,
},
`公网安备:闽公网安备35020602002951号`,
),
createElementVNode(
`span`,
null,
`ISP/CDN/IDC电信增值许可:B1-20242576`,
),
],
-1,
),
]),
])
);
}
var s = Object.assign(
_plugin_vue_export_helper_t(i, [
[`render`, o],
[`__scopeId`, `data-v-81b185f4`],
]),
{
__name: `ConsoleLegalFooter`,
},
);
export {};
export default s;
</script>
+372
View File
@@ -0,0 +1,372 @@
<script>
import "~/assets/styles/GeetestField.DiieTibK.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var p = `https://static.geetest.com/v4/gt4.js`,
m = 1e4,
h = 8e3,
g = null;
function _() {
let e = window.initGeetest4;
return typeof e == `function` ? e : void 0;
}
function v() {
if (typeof window > `u` || typeof document > `u`)
return Promise.reject(Error(`请在浏览器中完成人机验证`));
let e = _();
return e
? Promise.resolve(e)
: g ||
((g = new Promise((e, t) => {
let n = document.createElement(`script`),
r = !1,
i = (i) => {
if (r) return;
((r = !0),
window.clearTimeout(a),
(n.onload = null),
(n.onerror = null));
let o = _();
i || !o
? (n.remove(), t(i ?? Error(`验证组件加载异常,请重试`)))
: e(o);
},
a = window.setTimeout(
() => i(Error(`验证组件加载超时,请重试`)),
m,
);
((n.src = p),
(n.async = !0),
(n.onload = () => i()),
(n.onerror = () => i(Error(`验证组件加载失败,请检查网络后重试`))),
document.head.appendChild(n));
}).catch((e) => {
throw ((g = null), e);
})),
g);
}
function y(e) {
if (!e || typeof e != `object` || Array.isArray(e)) return null;
let t = e,
n = [`lot_number`, `captcha_output`, `pass_token`, `gen_time`];
return n.some((e) => typeof t[e] != `string` || !t[e].trim())
? null
: Object.fromEntries(n.map((e) => [e, t[e]]));
}
function b(e) {
if (!e || typeof e != `object`) return !1;
let t = e;
return [
`onReady`,
`onSuccess`,
`onClose`,
`onError`,
`onBoxShow`,
`getValidate`,
`showCaptcha`,
`destroy`,
].every((e) => typeof t[e] == `function`);
}
function x(e, t) {
let n = !1,
r = !1,
i = !1,
a = null,
o,
s,
c = new WeakSet(),
l = (e) => {
if (!e || typeof e != `object` || c.has(e)) return;
c.add(e);
let t = e.destroy;
if (typeof t == `function`)
try {
t.call(e);
} catch {}
},
u = () => {
(window.clearTimeout(o), window.clearTimeout(s), (o = s = void 0));
},
d = () => {
n || ((n = !0), (r = i = !1), u(), l(a), (a = null));
},
f = (e) => {
n || (d(), t.onError(Error(e)));
};
return (
e.trim()
? v()
.then((c) => {
if (!n) {
o = window.setTimeout(() => f(`验证组件初始化超时,请重试`), m);
try {
c(
{
captchaId: e,
product: `bind`,
language: `zho`,
},
(e) => {
if (n) {
l(e);
return;
}
if (a) {
e !== a && l(e);
return;
}
if ((window.clearTimeout(o), !b(e))) {
(l(e), f(`验证组件初始化异常,请重试`));
return;
}
((a = e),
(o = window.setTimeout(
() => f(`验证组件准备超时,请重试`),
m,
)),
e.onSuccess(() => {
if (n || !r || !i) return;
let a = null;
try {
a = y(e.getValidate());
} catch {}
if (!a) {
f(`验证结果无效,请重新验证`);
return;
}
(d(), t.onSuccess(a));
}),
e.onClose(() => {
!n && i && (d(), t.onClose());
}),
e.onError(() => f(`人机验证异常,请重试`)),
e.onBoxShow(() => {
!n && i && (window.clearTimeout(s), (s = void 0));
}),
e.onReady(() => {
n ||
r ||
(window.clearTimeout(o),
(o = void 0),
(r = !0),
t.onReady());
}));
},
);
} catch {
f(`验证组件初始化失败,请重试`);
}
}
})
.catch((e) =>
f(e instanceof Error ? e.message : `验证组件加载失败,请重试`),
)
: Promise.resolve().then(() => f(`人机验证尚未配置,请联系管理员`)),
{
show() {
if (!(n || i)) {
if (!r || !a) {
f(`验证组件尚未就绪,请重试`);
return;
}
((i = !0),
(s = window.setTimeout(
() =>
f(`验证面板未能显示,请检查网络或联系管理员确认极验域名配置`),
h,
)));
try {
a.showCaptcha();
} catch {
f(`验证面板打开失败,请重试`);
}
}
},
destroy: d,
}
);
}
var S = {
class: `geetest-field`,
},
C = [`disabled`, `aria-busy`, `aria-label`],
w = {
key: 0,
class: `pi pi-spin pi-spinner`,
"aria-hidden": `true`,
},
T = {
key: 1,
class: `pi pi-check-circle`,
"aria-hidden": `true`,
},
E = {
key: 2,
class: `pi pi-exclamation-circle`,
"aria-hidden": `true`,
},
D = {
key: 3,
class: `pi pi-shield`,
"aria-hidden": `true`,
},
O = [`role`],
k = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `GeetestField`,
props: {
captchaId: {},
disabled: {
type: Boolean,
},
},
emits: [`verified`, `invalid`],
setup(u, { emit: f }) {
let p = u,
m = f,
h = ref(`loading`),
g = ref(``),
_ = null,
v = 0,
y = !1,
b = computed(() =>
h.value === `loading`
? `正在加载验证…`
: h.value === `verifying`
? `请完成安全验证…`
: h.value === `verified`
? `验证通过,点击重新验证`
: h.value === `error`
? `重新加载验证`
: `点击完成验证`,
),
k = computed(
() => h.value === `loading` || h.value === `verifying`,
);
function A() {
(v++, _?.destroy(), (_ = null));
}
function j(e = !1) {
if ((A(), m(`invalid`), (g.value = ``), !y || p.disabled)) {
h.value = `idle`;
return;
}
h.value = `loading`;
let t = v,
n = () => y && !p.disabled && t === v;
_ = x(p.captchaId, {
onReady() {
n() && ((h.value = `ready`), e && M());
},
onSuccess(e) {
n() && ((_ = null), (h.value = `verified`), m(`verified`, e));
},
onClose() {
n() &&
((_ = null),
(h.value = `idle`),
(g.value = `已取消验证,请重试`),
m(`invalid`));
},
onError(e) {
n() &&
((_ = null),
(h.value = `error`),
(g.value = e.message),
m(`invalid`));
},
});
}
function M() {
if (!(p.disabled || k.value)) {
if (!_) {
j(!0);
return;
}
((g.value = ``), m(`invalid`), (h.value = `verifying`), _.show());
}
}
return (
watch(
() => [p.captchaId, p.disabled],
([e], [t]) => {
y && (e !== t || h.value !== `verified`) && j();
},
{
flush: `sync`,
},
),
onMounted(() => {
((y = !0), j());
}),
onBeforeUnmount(() => {
((y = !1), A());
}),
(t, r) => (
openBlock(),
createElementBlock(`div`, S, [
createElementVNode(
`button`,
{
type: `button`,
class: normalizeClass([
`geetest-trigger`,
{
verified: unref(h) === `verified`,
"has-error": !!unref(g),
},
]),
disabled: u.disabled || unref(k),
"aria-busy": unref(k),
"aria-label": unref(g) || unref(b),
onClick: M,
},
[
unref(k)
? (openBlock(), createElementBlock(`i`, w))
: unref(h) === `verified`
? (openBlock(), createElementBlock(`i`, T))
: unref(g)
? (openBlock(), createElementBlock(`i`, E))
: (openBlock(), createElementBlock(`i`, D)),
createElementVNode(
`span`,
{
role: unref(g) ? `alert` : `status`,
"aria-live": `polite`,
"aria-atomic": `true`,
},
toDisplayString(unref(g) || unref(b)),
9,
O,
),
],
10,
C,
),
])
)
);
},
}),
[[`__scopeId`, `data-v-4cd14cdc`]],
),
{
__name: `GeetestField`,
},
);
export {};
export default k;
</script>
+162
View File
@@ -0,0 +1,162 @@
<script>
import "~/assets/styles/GenericOAuthProviders.Bv8oNwXP.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { t as oauth_t } from "~/lib/oauth.js";
import { t as useOAuth_t } from "~/lib/useOAuth.js";
var x = {
key: 0,
class: `oauth-providers`,
},
S = {
key: 0,
class: `oauth-buttons`,
},
C = [`src`],
w = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `GenericOAuthProviders`,
setup(f) {
let _ = useSiteConfig_t(),
w = computed(() => oauth_t(_.config.value?.oauth)),
{ busy: T, error: E, start: D } = useOAuth_t(),
O = ref(!1);
return (
onMounted(() => {
_.load();
try {
O.value =
sessionStorage.getItem(`console-oauth-pending`) === `1`;
} catch {}
}),
(n, i) => {
let s = button,
f = message,
h = NuxtLink;
return unref(w).length || unref(O)
? (openBlock(),
createElementBlock(`div`, x, [
unref(w).length
? (openBlock(),
createElementBlock(`div`, S, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(w),
(t) => (
openBlock(),
createBlock(
s,
{
key: t.name,
severity: `secondary`,
outlined: ``,
disabled: unref(T),
onClick: (e) => unref(D)(t.name),
},
{
default: withCtx(() => [
t.image
? (openBlock(),
createElementBlock(
`img`,
{
key: 0,
src: t.image,
alt: ``,
referrerpolicy: `no-referrer`,
},
null,
8,
C,
))
: createCommentVNode(``, !0),
createTextVNode(
toDisplayString(t.title) + `登录`,
1,
),
]),
_: 2,
},
1032,
[`disabled`, `onClick`],
)
),
),
128,
)),
]))
: createCommentVNode(``, !0),
unref(E)
? (openBlock(),
createBlock(
f,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(E)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(O)
? (openBlock(),
createBlock(
h,
{
key: 2,
to: `/oauth/callback`,
},
{
default: withCtx(() => [
...(i[0] ||= [
createTextVNode(
`已完成第三方授权?继续登录`,
-1,
),
]),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]))
: createCommentVNode(``, !0);
}
);
},
}),
[[`__scopeId`, `data-v-45e5a5aa`]],
),
{
__name: `GenericOAuthProviders`,
},
);
export {};
export default w;
</script>
+403
View File
@@ -0,0 +1,403 @@
<script>
import "~/assets/styles/GlobalSearch.BQqObidy.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onUnmounted } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { withDirectives } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { vModelText } from "vue";
import { withModifiers } from "vue";
import { withKeys } from "vue";
import { useRouter } from "#app";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as product_name_n } from "~/lib/product-name.js";
var w = {
class: `gs-input`,
},
T = [`id`, `aria-controls`],
E = [`aria-busy`],
D = {
key: 0,
class: `gs-state`,
role: `status`,
},
O = {
key: 1,
class: `gs-state gs-error`,
role: `alert`,
},
k = {
key: 0,
class: `gs-group`,
},
A = [`onClick`],
j = {
class: `gs-item-name`,
},
ee = {
class: `gs-item-sub`,
},
te = {
key: 1,
class: `gs-group`,
},
ne = [`onClick`],
M = {
class: `gs-item-name`,
},
N = {
class: `gs-item-sub`,
},
P = {
key: 2,
class: `gs-state`,
role: `status`,
},
F = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `GlobalSearch`,
setup(h) {
let S = useApi(),
F = useRouter(),
I = ref(``),
L = ref(!1),
R = ref(!1),
z = ref(``),
B = ref(null),
V = ref(null),
H = ref(null),
U = `global-search-${useId()}`,
W = null,
G = 0,
K = !1;
function q() {
(W !== null && clearTimeout(W),
(W = null),
(G += 1),
(R.value = !1));
}
function J(e = !1) {
(q(), e && H.value?.focus(), (L.value = !1));
}
async function Y() {
if ((q(), K)) return;
let e = G,
t = I.value.trim();
if (((z.value = ``), (B.value = null), !t)) {
L.value = !1;
return;
}
((R.value = !0), (L.value = !0));
try {
let n = await S.get(`/global_search`, {
keywords: t,
});
if (e !== G || K) return;
B.value = n;
} catch (t) {
if (e !== G || K) return;
((B.value = null),
(z.value =
t instanceof Error ? t.message : `搜索失败,请重试`));
} finally {
e === G && !K && (R.value = !1);
}
}
function X() {
(J(),
(B.value = null),
(z.value = ``),
I.value.trim() && (W = setTimeout(Y, 300)));
}
let Z = computed(() => B.value?.hosts ?? []),
Q = computed(() => B.value?.products ?? []),
re = computed(
() =>
!R.value &&
B.value != null &&
!Z.value.length &&
!Q.value.length,
);
function ie(e) {
(J(),
(I.value = ``),
(B.value = null),
F.push(`/servers/server?id=${e}`));
}
function ae(e) {
(J(), (I.value = ``), (B.value = null), F.push(`/products/${e}`));
}
function $(e) {
V.value && !V.value.contains(e.target) && J();
}
return (
onMounted(() => document.addEventListener(`click`, $)),
onUnmounted(() => {
((K = !0), document.removeEventListener(`click`, $), q());
}),
(n, r) => (
openBlock(),
createElementBlock(
`div`,
{
ref_key: `box`,
ref: V,
class: `gs`,
onKeydown: (r[2] ||= withKeys(
withModifiers((e) => J(!0), [`stop`, `prevent`]),
[`esc`],
)),
},
[
createElementVNode(`span`, w, [
(r[3] ||= createElementVNode(
`i`,
{
class: `pi pi-search`,
"aria-hidden": `true`,
},
null,
-1,
)),
withDirectives(
createElementVNode(
`input`,
{
id: `${U}-input`,
name: `keywords`,
ref_key: `input`,
ref: H,
"onUpdate:modelValue": (r[0] ||= (e) =>
isRef(I) ? (I.value = e) : null),
type: `search`,
"aria-label": `搜索产品标识或商品名`,
"aria-controls": unref(L) ? U : void 0,
autocomplete: `off`,
placeholder: `搜索产品标识 / 商品名`,
onInput: X,
onKeyup: withKeys(Y, [`enter`]),
onFocus: (r[1] ||= (e) =>
unref(I).trim() &&
(unref(B) || unref(z)) &&
(L.value = !0)),
},
null,
40,
T,
),
[[vModelText, unref(I)]],
),
]),
unref(L)
? (openBlock(),
createElementBlock(
`div`,
{
key: 0,
id: U,
class: `gs-panel`,
role: `region`,
"aria-label": `搜索结果`,
"aria-busy": unref(R),
},
[
unref(R)
? (openBlock(),
createElementBlock(`div`, D, [
...(r[4] ||= [
createElementVNode(
`i`,
{
class: `pi pi-spin pi-spinner`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(` 搜索中…`, -1),
]),
]))
: unref(z)
? (openBlock(),
createElementBlock(`div`, O, [
createElementVNode(
`span`,
null,
toDisplayString(unref(z)),
1,
),
createElementVNode(
`button`,
{
type: `button`,
class: `gs-retry`,
onClick: Y,
},
`重试搜索`,
),
]))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
unref(Z).length
? (openBlock(),
createElementBlock(`div`, k, [
(r[5] ||= createElementVNode(
`div`,
{
class: `gs-group-title`,
},
`产品`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(Z),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.id,
type: `button`,
class: `gs-item`,
onClick: (e) => ie(t.id),
},
[
createElementVNode(
`span`,
j,
toDisplayString(
unref(product_name_n)(
t.product_name,
),
),
1,
),
createElementVNode(
`span`,
ee,
`#` +
toDisplayString(t.id) +
` · ` +
toDisplayString(t.name),
1,
),
],
8,
A,
)
),
),
128,
)),
]))
: createCommentVNode(``, !0),
unref(Q).length
? (openBlock(),
createElementBlock(`div`, te, [
(r[6] ||= createElementVNode(
`div`,
{
class: `gs-group-title`,
},
`商品`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(Q),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.id,
type: `button`,
class: `gs-item`,
onClick: (e) => ae(t.id),
},
[
createElementVNode(
`span`,
M,
toDisplayString(
unref(product_name_n)(
t.name,
),
),
1,
),
createElementVNode(
`span`,
N,
`#` +
toDisplayString(t.id),
1,
),
],
8,
ne,
)
),
),
128,
)),
]))
: createCommentVNode(``, !0),
unref(re)
? (openBlock(),
createElementBlock(
`div`,
P,
`没有匹配的结果`,
))
: createCommentVNode(``, !0),
],
64,
)),
],
8,
E,
))
: createCommentVNode(``, !0),
],
544,
)
)
);
},
}),
[[`__scopeId`, `data-v-bc4d898a`]],
),
{
__name: `GlobalSearch`,
},
);
export {};
export default F;
</script>
File diff suppressed because it is too large. Load diff
+56
View File
@@ -0,0 +1,56 @@
<script>
import { toDisplayString } from "vue";
import { normalizeClass } from "vue";
import { renderSlot } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
var c = {
class: `list-empty`,
},
l = {
class: `list-empty-title`,
},
u = {
key: 0,
class: `list-empty-desc`,
},
d = Object.assign(
defineComponent({
__name: `ListEmpty`,
props: {
icon: {},
title: {},
description: {},
},
setup(o) {
return (d, f) => (
openBlock(),
createElementBlock(`div`, c, [
createElementVNode(
`i`,
{
class: normalizeClass(o.icon || `pi pi-inbox`),
},
null,
2,
),
createElementVNode(`div`, l, toDisplayString(o.title), 1),
o.description
? (openBlock(),
createElementBlock(`p`, u, toDisplayString(o.description), 1))
: createCommentVNode(``, !0),
renderSlot(d.$slots, `default`),
])
);
},
}),
{
__name: `ListEmpty`,
},
);
export {};
export default d;
</script>
+74
View File
@@ -0,0 +1,74 @@
<script>
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
var l = {
class: `list-segments`,
role: `group`,
},
u = [`aria-pressed`, `onClick`],
d = Object.assign(
defineComponent({
__name: `ListSegments`,
props: mergeModels(
{
options: {},
},
{
modelValue: {},
modelModifiers: {},
},
),
emits: [`update:modelValue`],
setup(r) {
let s = useModel(r, `modelValue`);
return (i, d) => (
openBlock(),
createElementBlock(`div`, l, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
r.options,
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.value,
type: `button`,
class: normalizeClass([
`list-seg`,
{
active: s.value === t.value,
},
]),
"aria-pressed": s.value === t.value,
onClick: (e) => (s.value = t.value),
},
toDisplayString(t.label),
11,
u,
)
),
),
128,
)),
])
);
},
}),
{
__name: `ListSegments`,
},
);
export {};
export default d;
</script>
File diff suppressed because it is too large. Load diff
+379
View File
@@ -0,0 +1,379 @@
<script>
import "~/assets/styles/NotificationPreferences.DcH8Noxd.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { reactive } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import toggleswitch from "primevue/toggleswitch";
var x = [`aria-labelledby`],
S = {
class: `preferences-heading`,
},
C = [`id`],
w = [`id`],
T = [`aria-busy`],
E = {
class: `preference-row`,
},
D = {
class: `preference-copy`,
},
O = [`for`],
k = [`id`],
A = {
class: `preference-row`,
},
j = {
class: `preference-copy`,
},
M = [`for`],
N = [`id`],
P = {
key: 2,
class: `preferences-status`,
role: `status`,
},
F = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `NotificationPreferences`,
setup(p) {
let v = useApi(),
F = useId(),
I = reactive({
email_enabled: !1,
sms_enabled: !1,
email_available: !1,
sms_available: !1,
}),
L = ref(!1),
R = ref(!1),
z = ref(!1),
B = ref(``),
V = ref(``),
H = ref(``),
U = 0,
W = !1;
function G(e) {
let t = [
`email_enabled`,
`sms_enabled`,
`email_available`,
`sms_available`,
];
if (!e || t.some((t) => typeof e[t] != `boolean`))
throw Error(`提醒设置响应异常,请重试`);
for (let n of t) I[n] = e[n];
}
async function K() {
if (W || R.value || z.value) return;
let e = ++U;
((R.value = !0), (B.value = ``));
try {
let t = await v.get(`/account/notification-preferences`);
if (W || e !== U) return;
(G(t), (L.value = !0));
} catch (t) {
if (W || e !== U) return;
((B.value =
t instanceof Error ? t.message : `提醒设置加载失败,请重试`),
(L.value = !1));
} finally {
!W && e === U && (R.value = !1);
}
}
async function q(e, t) {
let n = e === `email_enabled` ? I.email_available : I.sms_available;
if (
W ||
!L.value ||
R.value ||
z.value ||
typeof t != `boolean` ||
I[e] === t ||
(t && !n)
)
return;
let r = ++U,
i = I[e];
((I[e] = t), (z.value = !0), (V.value = ``), (H.value = ``));
try {
let n = await v.put(`/account/notification-preferences`, {
[e]: t,
});
if (W || r !== U) return;
(G(n), (H.value = `提醒设置已保存`));
} catch (t) {
if (W || r !== U) return;
((I[e] = i),
(V.value =
t instanceof Error ? t.message : `保存失败,请重试`));
} finally {
!W && r === U && (z.value = !1);
}
}
return (
onMounted(K),
onBeforeUnmount(() => {
((W = !0), U++);
}),
(t, n) => {
let r = button,
a = message,
c = toggleswitch;
return (
openBlock(),
createElementBlock(
`section`,
{
class: `notification-preferences`,
"aria-labelledby": `${unref(F)}-title`,
},
[
createElementVNode(`div`, S, [
createElementVNode(`div`, null, [
createElementVNode(
`h3`,
{
id: `${unref(F)}-title`,
},
`提醒设置`,
8,
C,
),
createElementVNode(
`p`,
{
id: `${unref(F)}-description`,
},
`关闭后不接收普通提醒,站内消息和验证码不受影响。`,
8,
w,
),
]),
unref(B)
? (openBlock(),
createBlock(
r,
{
key: 0,
label: `重新加载`,
icon: `pi pi-refresh`,
size: `small`,
severity: `secondary`,
outlined: ``,
loading: unref(R),
onClick: K,
},
null,
8,
[`loading`],
))
: createCommentVNode(``, !0),
]),
unref(B)
? (openBlock(),
createBlock(
a,
{
key: 0,
severity: `error`,
closable: !1,
class: `preferences-message`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(B)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(V)
? (openBlock(),
createBlock(
a,
{
key: 1,
severity: `error`,
closable: !1,
class: `preferences-message`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(V)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createElementVNode(
`div`,
{
class: `preference-rows`,
"aria-busy": unref(R) || unref(z),
},
[
createElementVNode(`div`, E, [
createElementVNode(`div`, D, [
createElementVNode(
`label`,
{
for: `${unref(F)}-email`,
class: `preference-label`,
},
`邮箱提醒`,
8,
O,
),
unref(L) && !unref(I).email_available
? (openBlock(),
createElementBlock(
`small`,
{
key: 0,
id: `${unref(F)}-email-hint`,
class: `preference-hint`,
},
`当前不可用,请检查绑定信息或联系管理员`,
8,
k,
))
: createCommentVNode(``, !0),
]),
createVNode(
c,
{
"input-id": `${unref(F)}-email`,
modelValue: unref(I).email_enabled,
disabled:
!unref(L) ||
unref(R) ||
unref(z) ||
(!unref(I).email_available &&
!unref(I).email_enabled),
"aria-label": `邮箱提醒`,
pt: {
input: {
"aria-describedby":
unref(L) && !unref(I).email_available
? `${unref(F)}-description ${unref(F)}-email-hint`
: `${unref(F)}-description`,
},
},
"onUpdate:modelValue": (n[0] ||= (e) =>
q(`email_enabled`, e)),
},
null,
8,
[`input-id`, `modelValue`, `disabled`, `pt`],
),
]),
createElementVNode(`div`, A, [
createElementVNode(`div`, j, [
createElementVNode(
`label`,
{
for: `${unref(F)}-sms`,
class: `preference-label`,
},
`短信提醒`,
8,
M,
),
unref(L) && !unref(I).sms_available
? (openBlock(),
createElementBlock(
`small`,
{
key: 0,
id: `${unref(F)}-sms-hint`,
class: `preference-hint`,
},
`当前不可用,请检查绑定信息或联系管理员`,
8,
N,
))
: createCommentVNode(``, !0),
]),
createVNode(
c,
{
"input-id": `${unref(F)}-sms`,
modelValue: unref(I).sms_enabled,
disabled:
!unref(L) ||
unref(R) ||
unref(z) ||
(!unref(I).sms_available &&
!unref(I).sms_enabled),
"aria-label": `短信提醒`,
pt: {
input: {
"aria-describedby":
unref(L) && !unref(I).sms_available
? `${unref(F)}-description ${unref(F)}-sms-hint`
: `${unref(F)}-description`,
},
},
"onUpdate:modelValue": (n[1] ||= (e) =>
q(`sms_enabled`, e)),
},
null,
8,
[`input-id`, `modelValue`, `disabled`, `pt`],
),
]),
],
8,
T,
),
unref(R) || unref(z) || unref(H)
? (openBlock(),
createElementBlock(
`p`,
P,
toDisplayString(
unref(R)
? `正在加载提醒设置…`
: unref(z)
? `正在保存…`
: unref(H),
),
1,
))
: createCommentVNode(``, !0),
],
8,
x,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-f4132ec8`]],
),
{
__name: `NotificationPreferences`,
},
);
export {};
export default F;
</script>
+36
View File
@@ -0,0 +1,36 @@
<script>
import { onMounted } from "vue";
import { renderSlot } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
var s = Object.assign(
defineComponent({
__name: `OperatePasswordGate`,
setup(a) {
let { config: s, load: c } = useSiteConfig_t(),
l = computed(
() =>
Array.isArray(s.value?.home_enforce_safe_method) &&
s.value.home_enforce_safe_method.includes(`operate_password`),
);
return (
onMounted(() => {
c();
}),
(e, r) =>
unref(l)
? renderSlot(e.$slots, `default`, {}, void 0, void 0, 0)
: createCommentVNode(``, !0)
);
},
}),
{
__name: `OperatePasswordGate`,
},
);
export {};
export default s;
</script>
+52
View File
@@ -0,0 +1,52 @@
<script>
import { onMounted } from "vue";
import { renderSlot } from "vue";
import { watch } from "vue";
import { defineComponent } from "vue";
import { useToast } from "primevue/usetoast";
var a = Object.assign(
defineComponent({
__name: `OperationNotice`,
props: {
message: {},
severity: {
default: `success`,
},
details: {
default: () => [],
},
},
setup(r) {
let a = r,
o = useToast();
function s() {
a.message.trim() &&
o.add({
group: `operations`,
severity: a.severity,
summary: a.message,
detail: [...a.details],
life: a.details.length
? void 0
: a.severity === `success`
? 4e3
: 8e3,
closable: !0,
});
}
return (
onMounted(s),
watch(() => [a.message, a.severity], s, {
flush: `post`,
}),
(e, n) => renderSlot(e.$slots, `default`)
);
},
}),
{
__name: `OperationNotice`,
},
);
export {};
export default a;
</script>
+123
View File
@@ -0,0 +1,123 @@
<script>
import "~/assets/styles/OperationToasts.DfA_b8om.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { useAuth } from "~/lib/auth.js";
import toast from "primevue/toast";
import { useToast } from "primevue/usetoast";
var h = {
class: `operation-toast-copy`,
},
g = {
key: 0,
class: `operation-toast-results`,
},
_ = Object.assign(
defineComponent({
__name: `OperationToasts`,
setup(u) {
let _ = useToast(),
v = useAuth();
watch(
() => v.token,
() => _.removeGroup(`operations`),
);
let y = {
success: `pi-check-circle`,
error: `pi-times-circle`,
warn: `pi-exclamation-triangle`,
info: `pi-info-circle`,
};
return (r, u) => {
let f = toast;
return (
openBlock(),
createBlock(
f,
{
group: `operations`,
position: `top-right`,
class: `operation-toasts`,
"base-z-index": 2e3,
limit: 3,
},
{
message: withCtx(({ message: r }) => [
createElementVNode(
`i`,
{
class: normalizeClass([
`pi operation-toast-icon`,
[y[r.severity || `info`], `notice-${r.severity}`],
]),
"aria-hidden": `true`,
},
null,
2,
),
createElementVNode(`div`, h, [
createElementVNode(
`div`,
null,
toDisplayString(r.summary),
1,
),
r.detail?.length
? (openBlock(),
createElementBlock(`details`, g, [
(u[0] ||= createElementVNode(
`summary`,
null,
`查看处理结果`,
-1,
)),
createElementVNode(`ul`, null, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
r.detail,
(t, n) => (
openBlock(),
createElementBlock(
`li`,
{
key: n,
},
toDisplayString(t),
1,
)
),
),
128,
)),
]),
]))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
)
);
};
},
}),
{
__name: `OperationToasts`,
},
);
export {};
export default _;
</script>
+124
View File
@@ -0,0 +1,124 @@
<script>
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { Icon } from "#components";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as modules_n } from "~/lib/modules.js";
var f = [`src`, `width`, `height`],
p = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `OsIcon`,
props: {
url: {},
name: {},
icon: {},
size: {
default: 24,
},
},
setup(o) {
let u = o,
p = ref([]);
watch(
() => [u.url, u.name, u.icon],
() => {
p.value = [];
},
{
flush: `sync`,
},
);
function m(e) {
let t = String(e ?? ``).trim();
if (!t || /[\u0000-\u0020\u007f\\]/.test(t)) return ``;
if (/^\/(?!\/)/.test(t)) return t;
try {
let e = new URL(t.startsWith(`//`) ? `https:${t}` : t);
return /^(https?:)$/.test(e.protocol) &&
!e.username &&
!e.password
? t
: ``;
} catch {
return ``;
}
}
let h = computed(() =>
modules_n(m(u.icon) ? `` : u.icon, void 0, u.name),
),
g = computed(
() =>
[m(u.url), m(u.icon), h.value].find(
(e) => e && !p.value.includes(e),
) || ``,
),
_ = computed(() =>
h.value.endsWith(`/Windows.svg`)
? `lucide:monitor`
: /(?:FreeBSD|ESXi|XenServer)\.svg$/.test(h.value)
? `lucide:hard-drive`
: `lucide:terminal`,
);
function v(e) {
let t = e.target?.getAttribute(`src`);
t && t === g.value && p.value.push(t);
}
return (e, n) => {
let r = Icon;
return unref(g)
? (openBlock(),
createElementBlock(
`img`,
{
key: unref(g),
src: unref(g),
width: o.size,
height: o.size,
alt: ``,
"aria-hidden": `true`,
class: `os-icon`,
loading: `lazy`,
onError: v,
},
null,
40,
f,
))
: (openBlock(),
createBlock(
r,
{
key: 1,
name: unref(_),
"aria-hidden": `true`,
class: `os-icon-fallback`,
style: normalizeStyle({
width: `${o.size * 0.8}px`,
height: `${o.size * 0.8}px`,
}),
},
null,
8,
[`name`, `style`],
));
};
},
}),
[[`__scopeId`, `data-v-01907ce4`]],
),
{
__name: `OsIcon`,
},
);
export {};
export default p;
</script>
+49
View File
@@ -0,0 +1,49 @@
<script>
import "~/assets/styles/PageInfoNotice._16xRFrB.css";
import { renderSlot } from "vue";
import { createBlock } from "vue";
import { withCtx } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
var o = {};
function s(i, o) {
let s = message;
return (
openBlock(),
createBlock(
s,
{
severity: `info`,
closable: !1,
icon: `pi pi-info-circle`,
class: `page-info-notice`,
role: `note`,
"aria-live": `off`,
pt: {
icon: {
"aria-hidden": `true`,
},
},
},
{
default: withCtx(() => [
renderSlot(i.$slots, `default`, {}, void 0, !0),
]),
_: 3,
},
)
);
}
var c = Object.assign(
_plugin_vue_export_helper_t(o, [
[`render`, s],
[`__scopeId`, `data-v-8f81f268`],
]),
{
__name: `PageInfoNotice`,
},
);
export {};
export default c;
</script>
+100
View File
@@ -0,0 +1,100 @@
<script>
import "~/assets/styles/PageSteps.B5K7G9zF.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var d = {
class: `steps`,
},
f = {
class: `step-dot`,
},
p = {
key: 0,
class: `pi pi-check`,
},
m = {
class: `step-label`,
},
h = {
key: 0,
class: `step-line`,
},
g = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `PageSteps`,
props: {
steps: {},
current: {},
},
setup(c) {
return (u, g) => (
openBlock(),
createElementBlock(`ol`, d, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
c.steps,
(t, u) => (
openBlock(),
createElementBlock(
`li`,
{
key: u,
class: normalizeClass([
`step`,
{
done: u + 1 < c.current,
active: u + 1 === c.current,
},
]),
},
[
createElementVNode(`span`, f, [
u + 1 < c.current
? (openBlock(), createElementBlock(`i`, p))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[createTextVNode(toDisplayString(u + 1), 1)],
64,
)),
]),
createElementVNode(`span`, m, toDisplayString(t), 1),
u < c.steps.length - 1
? (openBlock(), createElementBlock(`span`, h))
: createCommentVNode(``, !0),
],
2,
)
),
),
128,
)),
])
);
},
}),
[[`__scopeId`, `data-v-a16c5dea`]],
),
{
__name: `PageSteps`,
},
);
export {};
export default g;
</script>
File diff suppressed because it is too large. Load diff
+173
View File
@@ -0,0 +1,173 @@
<script>
import "~/assets/styles/PhoneCodeField.CwyHXfML.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var m = {
class: `phone-code-field`,
},
h = [`for`],
g = {
class: `phone-code-input`,
},
_ = [`id`, `value`, `list`, `disabled`],
v = [`id`],
y = [`value`],
b = {
key: 0,
role: `status`,
},
x = {
key: 1,
role: `status`,
},
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `PhoneCodeField`,
props: {
modelValue: {},
disabled: {
type: Boolean,
},
},
emits: [`update:modelValue`],
setup(u, { emit: p }) {
let S = u,
C = p,
w = useId(),
T = useApi(),
E = ref([]),
D = ref(!1),
O = ref(``),
k = !1;
onBeforeUnmount(() => {
k = !0;
});
async function A() {
if (!(D.value || E.value.length)) {
((D.value = !0), (O.value = ``));
try {
let e = await T.get(`/country`, void 0, !1);
if (k) return;
E.value = (e.list || [])
.filter((e) => /^[1-9]\d{0,3}$/.test(String(e.phone_code)))
.map((e) => ({
phone_code: String(e.phone_code),
name: e.name_zh || e.name || ``,
}));
} catch {
k || (O.value = `地区列表暂不可用,可直接填写国际区号`);
} finally {
k || (D.value = !1);
}
}
}
return (n, r) => (
openBlock(),
createElementBlock(`div`, m, [
createElementVNode(
`label`,
{
for: `${unref(w)}-phone-code`,
},
`国际区号`,
8,
h,
),
createElementVNode(`div`, g, [
(r[1] ||= createElementVNode(
`span`,
{
"aria-hidden": `true`,
},
`+`,
-1,
)),
createElementVNode(
`input`,
{
id: `${unref(w)}-phone-code`,
value: S.modelValue,
list: `${unref(w)}-countries`,
inputmode: `numeric`,
autocomplete: `tel-country-code`,
maxlength: `4`,
disabled: u.disabled,
onFocus: A,
onInput: (r[0] ||= (e) =>
C(
`update:modelValue`,
e.target.value.replace(/^\+/, ``).trim(),
)),
},
null,
40,
_,
),
]),
createElementVNode(
`datalist`,
{
id: `${unref(w)}-countries`,
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(E),
(t, n) => (
openBlock(),
createElementBlock(
`option`,
{
key: `${t.phone_code}-${n}`,
value: t.phone_code,
},
toDisplayString(t.name) +
` +` +
toDisplayString(t.phone_code),
9,
y,
)
),
),
128,
)),
],
8,
v,
),
unref(D)
? (openBlock(), createElementBlock(`small`, b, `正在加载地区…`))
: createCommentVNode(``, !0),
unref(O)
? (openBlock(),
createElementBlock(`small`, x, toDisplayString(unref(O)), 1))
: createCommentVNode(``, !0),
])
);
},
}),
[[`__scopeId`, `data-v-24cb0489`]],
),
{
__name: `PhoneCodeField`,
},
);
export {};
export default S;
</script>
+91
View File
@@ -0,0 +1,91 @@
<script>
import "~/assets/styles/ProductCategoryNotice.CwaR3eXN.css";
import { normalizeClass } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as sanitize_n } from "~/lib/sanitize.js";
var u = {
key: 0,
class: `category-notice`,
"aria-label": `分类订购提示`,
"aria-live": `polite`,
"aria-atomic": `true`,
},
d = [`innerHTML`],
f = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ProductCategoryNotice`,
props: {
description: {},
},
setup(o) {
let c = o,
f = computed(() => {
let e = typeof c.description == `string` ? c.description : ``;
for (let t = 0; t < 2; t++) {
let t = new DOMParser().parseFromString(e, `text/html`);
if (t.body.childElementCount || t.head.childElementCount) break;
let n = t.body.textContent ?? e;
if (n === e) break;
e = n;
}
let t = sanitize_n(e),
n = new DOMParser().parseFromString(t, `text/html`);
return {
html:
n.body.textContent
?.replace(/[\u200b-\u200d\ufeff]/g, ``)
.trim() || n.body.querySelector(`img[src]`)
? t
: ``,
plain: n.body.childElementCount === 0,
};
});
return (n, o) =>
unref(f).html
? (openBlock(),
createElementBlock(`aside`, u, [
(o[0] ||= createElementVNode(
`i`,
{
class: `pi pi-info-circle category-notice-icon`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(
`div`,
{
class: normalizeClass([
`category-notice-content`,
{
"category-notice-plain": unref(f).plain,
},
]),
innerHTML: unref(f).html,
},
null,
10,
d,
),
]))
: createCommentVNode(``, !0);
},
}),
[[`__scopeId`, `data-v-faa6a7a3`]],
),
{
__name: `ProductCategoryNotice`,
},
);
export {};
export default f;
</script>
@@ -0,0 +1,454 @@
<script>
import "~/assets/styles/ProductConfigurationSummary.BqZns1LB.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { t as product_name_t } from "~/lib/product-name.js";
import { a as storage_capacity_a } from "~/lib/storage-capacity.js";
import { t as storage_capacity_t } from "~/lib/storage-capacity.js";
import { t as product_order_module_t } from "~/lib/product-order-module.js";
var y = {
timeoutMs: 5e3,
},
b = new Set([`remf_finance`, `remf_finance_dcim`, `remf_finance_common`]);
function x(e) {
return typeof e == `string` || typeof e == `number` ? String(e).trim() : ``;
}
function S(e) {
let t = x(e);
if (!/^\d+(?:\.\d+)?$/.test(t)) return;
let n = Number(t);
return Number.isFinite(n) && n > 0 ? n : void 0;
}
function C(e) {
let t = e.trim().replace(/\s+/g, ``).toLowerCase();
if (/^(cpu|处理器|cpu核心|cpu核数|核心数)$/.test(t)) return `cpu`;
if (/^(内存|运行内存|memory|ram)$/.test(t)) return `memory`;
if (/^(系统盘|系统磁盘)$/.test(t)) return `system`;
if (/^(数据盘|数据磁盘)$/.test(t)) return `data`;
if (/^(磁盘|硬盘|存储|disk)$/.test(t)) return `disk`;
if (
/^(?:(?:上行|下行|上联|下联|入站|出站|流入|流出|峰值|突发|共享|独享|网络|公网))*带宽(?:上限)?$/.test(
t,
)
)
return `bandwidth`;
if (/^(流量|流量额度|月流量|每月流量|流量包|traffic)$/.test(t))
return `traffic`;
}
function w(e) {
let t = e.match(/^(\d+(?:\.\d+)?)\s*(?:c\s*v?cpu|核|核心|v?cpu|cores?|c)?$/i);
return t && S(t[1])
? `${Number(t[1])}核`
: e.length <= 42 &&
/^(?:\d+\s*[x×*]\s*)?(?:Intel|AMD|Xeon|EPYC|E[3579]-|Ryzen)/i.test(e) &&
/^[\w\s.*×()+-]+$/.test(e)
? e.replace(/\s+/g, ` `)
: ``;
}
function T(e) {
let t = e.match(
/^(?:(\d+)\s*[x×*]\s*)?(\d+(?:\.\d+)?)\s*(TB|GB|MB|T|G|M)(?:\s*(SSD|HDD|NVMe|SAS|SATA|DDR[345](?:\s+ECC)?|ECC))?$/i,
);
if (!t || !S(t[2]) || (t[1] !== void 0 && !S(t[1]))) return ``;
let n = t[3].toUpperCase().replace(/^([TGM])$/, `$1B`);
return `${t[1] ? `${Number(t[1])}×` : ``}${Number(t[2])}${n}${t[4] ? ` ${t[4]}` : ``}`;
}
function E(e, t) {
let n = e
.replace(/\s+/g, ``)
.match(
/^((?:(?:突发|峰值|共享|独享|上行|下行|入站|出站|流入|流出|带宽))*)(\d+(?:\.\d+)?)(Mbps|Gbps|Kbps|M|G)((?:(?:突发|峰值|共享|独享|带宽))*)$/i,
);
if (!n || !S(n[2])) return ``;
let r = `${t}${n[1]}${n[4]}`,
i = /共享/.test(r) ? `共享` : /独享/.test(r) ? `独享` : ``,
a = /峰值/.test(r) ? `峰值` : /突发/.test(r) ? `突发` : ``,
o = /^g/i.test(n[3]) ? `Gbps` : /^k/i.test(n[3]) ? `Kbps` : `Mbps`;
return `${i}${a}${Number(n[2])}${o}`;
}
function D(e) {
let t = ``,
n = ``,
r = ``,
i = [],
a = [];
for (let o of e) {
let e = C(o.label);
if (e === `cpu` && !t) t = w(o.value);
else if (e === `memory` && !n) n = T(o.value);
else if (
e === `traffic` &&
!r &&
/^\d+(?:\.\d+)?\s*[TGM]B?$/i.test(o.value)
)
r = T(o.value);
else if (e === `disk` || e === `system` || e === `data`) {
let t = storage_capacity_t(o.value),
n =
t && t.size > 0
? `${t.size}${t.unit}${t.type ? ` ${t.type}` : ``}`
: T(o.value);
n &&
i.push(
`${n}${e === `system` ? `系统盘` : e === `data` ? `数据盘` : `磁盘`}`,
);
} else if (e === `bandwidth`) {
let e = E(o.value, o.label),
t = /上行|上联|出站|流出/.test(o.label)
? `上行`
: /下行|下联|入站|流入/.test(o.label)
? `下行`
: ``;
e &&
a.push({
direction: t,
value: e,
});
}
}
let o = [...new Set(a.map((e) => e.value))],
s =
o.length === 1
? o[0]
: [...new Set(a.map((e) => `${e.direction}${e.value}`))].join(` / `);
return [t, n, [...new Set(i)].join(`+`), s, r ? `${r}流量` : ``].filter(
(e) => !!e,
);
}
function O(e) {
if (e.kind !== `quantity`) return e.choices[0]?.label ?? ``;
let t =
e.unit ||
(C(e.label) === `system` || C(e.label) === `data` || C(e.label) === `disk`
? `GB`
: C(e.label) === `bandwidth`
? `Mbps`
: ``);
return `${e.min}${t}`;
}
function k(e) {
return (
e &&
(e.type === `step` || e.type === `total`
? (e.min_value ?? e.value)
: e.value)
);
}
function A(e, t, n = ``) {
return {
label: e,
value: S(t) === void 0 ? `` : `${Number(t)}${n}`,
};
}
async function j(e, t) {
if (!product_name_t(t.name)) return [];
let n = (t, n) => e.get(t, n, !1, y);
try {
let r = await product_order_module_t(
{
get: n,
},
t,
);
if (b.has(r)) {
let n = await e.getRaw(`/product/${t.id}/${r}/order_page`, void 0, y),
i = storage_capacity_a(n);
return i.linkDefinitions?.length ||
i.options.some((e) => e.kind === `cascade`)
? []
: D(
i.options.flatMap((e) =>
!C(e.label) || e.kind === `boolean` || e.kind === `os`
? []
: [
{
label: e.label,
value: O(e),
},
],
),
);
}
if (r === `idcsmart_common`) {
let e = await n(`/idcsmart_common/product/${t.id}/configoption`);
return e.advanced_rules?.length
? []
: D(
(e.configoptions ?? []).flatMap((e) =>
e.is_show !== 1 ||
!C(e.option_name) ||
![
`select`,
`multi_select`,
`quantity`,
`quantity_range`,
].includes(e.option_type)
? []
: [
{
label: e.option_name,
value:
e.option_type === `quantity` ||
e.option_type === `quantity_range`
? `${e.qty_min ?? 1}${e.unit ?? ``}`
: (e.subs?.[0]?.option_name ?? ``),
},
],
),
);
}
if (r === `mf_cloud`) {
let e = await n(`/product/${t.id}/mf_cloud/order_page`, {
id: t.id,
billing_cycle: `recurring_prepayment`,
}),
r = e.config,
i = e.system_disk?.[0],
a =
Number(r?.disk_range_limit_switch) === 1 && S(r?.disk_range_limit)
? Number(r.disk_range_limit)
: 1,
o = (e.system_disk ?? [])
.filter(
(e) =>
(e.other_config?.disk_type ?? ``) ===
(i?.other_config?.disk_type ?? ``),
)
.flatMap((e) => {
let t = S(k(e));
if (t === void 0) return [];
if (e.type !== `step` && e.type !== `total`) return [t];
let n = Math.ceil(t / a) * a,
r = Number(e.max_value ?? e.min_value ?? e.value);
return n <= Math.floor(r / a) * a ? [n] : [];
}),
s = [
A(`CPU`, e.cpu?.[0]?.value),
A(`内存`, k(e.memory?.[0]), r?.memory_unit || `GB`),
A(`系统盘`, o.length ? Math.min(...o) : void 0, `GB`),
];
Number(r?.free_disk_switch) === 1 &&
s.push(A(`数据盘`, r.free_disk_size, `GB`));
let c = e.data_center?.[0]?.city?.[0]?.area?.[0]?.line?.[0];
if (c?.id) {
let e = await n(`/product/${t.id}/mf_cloud/line/${c.id}`);
if (e.bill_type === `bw`) s.push(A(`带宽`, k(e.bw?.[0]), `Mbps`));
else if (e.bill_type === `flow`) {
let t = e.flow?.[0];
s.push(A(`流量`, t?.value, `GB`));
let n = t?.bw?.[0] ?? t?.other_config;
n &&
s.push(
A(`上行带宽`, n.out_bw, `Mbps`),
A(`下行带宽`, n.in_bw, `Mbps`),
);
}
}
return D(s);
}
if (r === `mf_dcim` || r === `remf_dcim`) {
let e = await n(`/product/${t.id}/${r}/order_page`);
if (e.config_limit?.length || e.limit_rule?.length) return [];
let i = e.model_config?.[0];
if (!i) return [];
let a = [
{
label: `CPU`,
value: x(i.cpu),
},
{
label: `内存`,
value: x(i.memory),
},
{
label: `磁盘`,
value: x(i.disk),
},
],
o = e.data_center
?.flatMap((e) => e.city ?? [])
.flatMap((e) => e.area ?? [])
.flatMap((e) => e.line ?? [])[0];
if (o?.id) {
let e = await n(`/product/${t.id}/${r}/line/${o.id}`);
e.bill_type === `bw`
? a.push(A(`带宽`, k(e.bw?.[0]), `Mbps`))
: e.bill_type === `flow` && a.push(A(`流量`, k(e.flow?.[0]), `GB`));
}
return D(a);
}
if (r === `kky_ecs`) {
let e = await n(`/product/${t.id}/kky_ecs/order_page`, {
id: t.id,
}),
r = e.package_list?.find(
(e) => Number(e.is_sell_out) !== 1 && S(e.cpu_num) && S(e.memory),
);
if (!r) return [];
let i = e.system_disk_config?.[String(r.id)],
a =
i &&
Number.isFinite(Number(i.min)) &&
Number.isFinite(Number(i.max)) &&
Math.max(Number(i.min), Number(i.max)) > 0,
o = [
A(`CPU`, r.cpu_num),
A(`内存`, r.memory, `GB`),
A(
`系统盘`,
a ? Math.max(0, Math.min(Number(i.min), Number(i.max))) : void 0,
`GB`,
),
],
s = e.network_list?.find(
(t) => e.bill_method_list?.[String(r.id)]?.[String(t.id)]?.length,
),
c = s
? e.bill_method_list?.[String(r.id)]?.[String(s.id)]?.[0]
: void 0;
return (c && o.push(A(`带宽`, c.config?.min, `Mbps`)), D(o));
}
} catch {}
return [];
}
var M = {
key: 0,
class: `product-configuration-summary`,
"aria-label": `默认配置`,
},
N = {
key: 0,
class: `summary-separator`,
"aria-hidden": `true`,
},
P = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ProductConfigurationSummary`,
props: {
product: {},
summary: {},
},
setup(d) {
let m = d,
g = useApi(),
_ = ref([]),
v = computed(() => {
let e = (e) => /(?:[KMG]bps|流量)$/i.test(e);
return [_.value.filter((t) => !e(t)), _.value.filter(e)].filter(
(e) => e.length,
);
}),
y = 0;
return (
watch(
() => [
m.product.id,
m.product.name,
m.product.module,
m.product.res_module,
m.summary,
],
async () => {
let e = ++y;
if (((_.value = []), product_name_t(m.product.name))) {
if (m.summary !== void 0) {
_.value = m.summary;
return;
}
try {
let t = await j(g, m.product);
e === y && (_.value = t);
} catch {}
}
},
{
immediate: !0,
},
),
onBeforeUnmount(() => {
y++;
}),
(n, r) =>
unref(product_name_t)(d.product.name) && unref(_).length
? (openBlock(),
createElementBlock(`p`, M, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(v),
(n, r) => (
openBlock(),
createElementBlock(
`span`,
{
key: r,
class: `summary-line`,
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
n,
(t, n) => (
openBlock(),
createElementBlock(
Fragment,
{
key: n,
},
[
n
? (openBlock(),
createElementBlock(`span`, N, `·`))
: createCommentVNode(``, !0),
createElementVNode(
`span`,
null,
toDisplayString(t),
1,
),
],
64,
)
),
),
128,
)),
],
)
),
),
128,
)),
]))
: createCommentVNode(``, !0)
);
},
}),
[[`__scopeId`, `data-v-cb8d72e4`]],
),
{
__name: `ProductConfigurationSummary`,
},
);
export { j as n };
export default P;
</script>
+592
View File
@@ -0,0 +1,592 @@
<script>
import "~/assets/styles/ProductDescription.Ctb7jDuO.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as product_name_n } from "~/lib/product-name.js";
import { n as sanitize_n } from "~/lib/sanitize.js";
var v = {
配置: `pi-sliders-h`,
规格: `pi-sliders-h`,
套餐: `pi-sliders-h`,
线路: `pi-sitemap`,
网络线路: `pi-sitemap`,
网络: `pi-sitemap`,
回程: `pi-sitemap`,
去程: `pi-sitemap`,
电信: `pi-sitemap`,
联通: `pi-sitemap`,
移动: `pi-sitemap`,
网络类型: `pi-sitemap`,
线路类型: `pi-sitemap`,
稳定性: `pi-shield`,
可用性: `pi-shield`,
SLA: `pi-shield`,
防御能力: `pi-shield`,
硬防: `pi-shield`,
处理器: `pi-microchip`,
CPU: `pi-microchip`,
内存: `pi-server`,
存储: `pi-server`,
硬盘: `pi-server`,
系统盘: `pi-server`,
数据盘: `pi-server`,
带宽: `pi-sitemap`,
流量: `pi-sitemap`,
IP: `pi-sitemap`,
IP地址: `pi-sitemap`,
防御: `pi-shield`,
数据中心: `pi-server`,
机房: `pi-server`,
地域: `pi-server`,
系统: `pi-server`,
操作系统: `pi-server`,
镜像: `pi-server`,
区域: `pi-server`,
适用场景: `pi-info-circle`,
适用业务: `pi-info-circle`,
说明: `pi-info-circle`,
备注: `pi-info-circle`,
交付: `pi-server`,
开通: `pi-server`,
备份: `pi-server`,
使用须知: `pi-info-circle`,
计费方式: `pi-clock`,
购买周期: `pi-clock`,
付款周期: `pi-clock`,
},
y = RegExp(`^(${Object.keys(v).join(`|`)})\\s*[::]\\s*(.*)$`),
b = new Set([`p`, `div`, `br`, `span`, `b`, `strong`]),
x = new Set([
`p`,
`div`,
`h1`,
`h2`,
`h3`,
`h4`,
`h5`,
`h6`,
`hr`,
`blockquote`,
`pre`,
`ul`,
`ol`,
`li`,
`dl`,
`dt`,
`dd`,
`table`,
`thead`,
`tbody`,
`tfoot`,
`tr`,
`caption`,
`figure`,
`figcaption`,
]);
function S(e) {
return /<\/?[a-z][^>]*>|<!doctype\b[^>]*>|<!--/i.test(e);
}
function C(e) {
let t = e;
for (
let e = 0;
e < 2 && !S(t) && /&(?:[a-z]+|#\d+|#x[\da-f]+);/i.test(t);
e++
) {
let e = t.replace(
/&(?:[a-z]+|#\d+|#x[\da-f]+);/gi,
(e) =>
new DOMParser().parseFromString(e, `text/html`).body.textContent ?? e,
);
if (e === t) break;
t = e;
}
return t;
}
function w(e, t, n = ``) {
let r = ``;
function i() {
r &&
!r.endsWith(`
`) &&
(r += `
`);
}
function a(e) {
if ((e === t && (r += n), e.nodeType === 3)) {
r += e.textContent ?? ``;
return;
}
if (e.nodeType !== 1) return;
let o = e,
s = o.localName;
if (s === `br`) {
r += `
`;
return;
}
(x.has(s) && i(),
s === `img` &&
o.hasAttribute(`src`) &&
(r += o.getAttribute(`alt`) ?? ``));
for (let t of Array.from(e.childNodes)) a(t);
((s === `td` || s === `th`) && (r += ` `), x.has(s) && i());
}
for (let t of Array.from(e.childNodes)) a(t);
return r
.replace(
/\r\n?/g,
`
`,
)
.replace(/\u00a0/g, ` `)
.replace(/[\u200b\ufeff]/g, ``)
.split(
`
`,
)
.map((e) => e.trim())
.join(
`
`,
)
.trim();
}
function T(e, t) {
for (let n of Array.from(e.querySelectorAll(`*`))) {
let r = n.localName;
if (!b.has(r) || n.attributes.length) return !1;
if (r !== `b` && r !== `strong`) continue;
let i = (n.textContent ?? ``).trim().replace(/\s*[::]$/, ``);
if (!Object.hasOwn(v, i)) return !1;
let a = ``;
for (; t.includes(a);) a += ``;
let o = w(e, n, a),
s = o.indexOf(a),
c =
o
.slice(0, s)
.split(
`
`,
)
.pop() ?? ``,
l =
o.slice(s + a.length).split(`
`)[0] ?? ``;
if (c.trim() || !y.test(l)) return !1;
}
return !0;
}
function E(e) {
if (typeof e != `string` || !e.trim())
return {
html: ``,
text: ``,
blocks: [],
rich: !1,
empty: !0,
};
let t = C(e),
n = S(t)
? t
: t.replace(/&/g, `&amp;`).replace(/</g, `&lt;`).replace(/>/g, `&gt;`),
r = sanitize_n(n),
i = new DOMParser().parseFromString(r, `text/html`).body,
a = w(i);
if (!a && !i.querySelector(`img[src]`))
return {
html: r,
text: a,
blocks: [],
rich: !1,
empty: !0,
};
if (!T(i, a))
return {
html: r,
text: a,
blocks: [],
rich: !0,
empty: !1,
};
let o = [],
s = [];
function c() {
let e = s
.join(
`
`,
)
.trim();
(e &&
o.push({
kind: `text`,
text: e,
}),
(s = []));
}
for (let e of a.split(`
`)) {
let t = e.match(y);
if (!t) {
s.push(e);
continue;
}
c();
let n = t[1];
o.push({
kind: `field`,
label: n,
value: t[2] ?? ``,
icon: v[n],
});
}
return (
c(),
{
html: r,
text: a,
blocks: o,
rich: !1,
empty: !1,
}
);
}
var D = [`aria-label`],
O = {
key: 0,
class: `description-header`,
},
k = [`id`],
A = {
key: 1,
class: `description-paragraph`,
},
j = {
key: 1,
class: `description-paragraph description-preview`,
},
M = [`innerHTML`],
N = [`aria-expanded`, `aria-controls`, `aria-label`],
P = {
key: 1,
class: `product-description description-empty`,
},
F = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ProductDescription`,
props: {
description: {},
compact: {
type: Boolean,
default: !1,
},
heading: {},
productName: {},
},
setup(p) {
let h = p,
_ = computed(() => E(h.description)),
v = ref(!1),
y = useId();
watch(
() => h.description,
() => {
v.value = !1;
},
);
function b(e, t) {
let n = Array.from(e);
return n.length > t ? `${n.slice(0, t).join(``)}…` : e;
}
let x = computed(
() =>
h.compact &&
!_.value.empty &&
(_.value.rich ||
_.value.blocks.length > 3 ||
_.value.blocks.some(
(e) =>
Array.from(e.kind === `field` ? e.value : e.text).length >
100,
)),
),
S = computed(() =>
!h.compact || v.value
? _.value.blocks
: _.value.blocks.slice(0, 3).map((e) =>
e.kind === `field`
? {
...e,
value: b(e.value, 100),
}
: {
...e,
text: b(e.text, 100),
},
),
),
C = computed(() => b(_.value.text.replace(/\s+/g, ` `), 160)),
w = computed(
() =>
`${v.value ? `收起` : `展开`}${h.productName ? ` ${product_name_n(h.productName)} 的` : ``}产品介绍`,
),
T = {
featured: [`配置`, `规格`, `套餐`],
network: [
`线路`,
`网络线路`,
`网络`,
`回程`,
`去程`,
`电信`,
`联通`,
`移动`,
`网络类型`,
`线路类型`,
`带宽`,
`流量`,
`IP`,
`IP地址`,
],
notes: [`说明`, `备注`, `适用场景`, `适用业务`, `使用须知`],
security: [`稳定性`, `可用性`, `SLA`, `防御能力`, `硬防`, `防御`],
hardware: [
`处理器`,
`CPU`,
`内存`,
`存储`,
`硬盘`,
`系统盘`,
`数据盘`,
],
resources: [
`数据中心`,
`机房`,
`地域`,
`系统`,
`操作系统`,
`镜像`,
`区域`,
`交付`,
`开通`,
`备份`,
],
billing: [`计费方式`, `购买周期`, `付款周期`],
};
function F(e) {
return (
Object.entries(T).find(([, t]) => t.includes(e))?.[0] || `default`
);
}
return (n, i) =>
unref(_).empty
? p.compact
? (openBlock(),
createElementBlock(
`p`,
P,
`进入配置页查看可选规格与购买时长。`,
))
: createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`section`,
{
key: 0,
class: normalizeClass([
`product-description`,
{
"description-compact": p.compact,
"description-panel": p.heading,
},
]),
"aria-label":
p.heading ||
`${unref(product_name_n)(p.productName)}产品介绍`,
},
[
p.heading
? (openBlock(),
createElementBlock(`header`, O, [
createElementVNode(
`h2`,
null,
toDisplayString(p.heading),
1,
),
]))
: createCommentVNode(``, !0),
createElementVNode(
`div`,
{
id: unref(y),
class: `description-content`,
},
[
unref(_).rich
? p.compact && !unref(v)
? (openBlock(),
createElementBlock(
`p`,
j,
toDisplayString(unref(C) || `查看图文介绍`),
1,
))
: (openBlock(),
createElementBlock(
`div`,
{
key: 2,
class: `description-rich`,
innerHTML: unref(_).html,
},
null,
8,
M,
))
: (openBlock(!0),
createElementBlock(
Fragment,
{
key: 0,
},
renderList(
unref(S),
(t, n) => (
openBlock(),
createElementBlock(
Fragment,
{
key: n,
},
[
t.kind === `field`
? (openBlock(),
createElementBlock(
`dl`,
{
key: 0,
class: normalizeClass([
`description-field`,
[
`description-field--${F(t.label)}`,
],
]),
},
[
createElementVNode(`dt`, null, [
createElementVNode(
`i`,
{
class: normalizeClass([
`pi`,
t.icon,
]),
"aria-hidden": `true`,
},
null,
2,
),
createElementVNode(
`span`,
null,
toDisplayString(t.label),
1,
),
]),
createElementVNode(
`dd`,
null,
toDisplayString(t.value),
1,
),
],
2,
))
: (openBlock(),
createElementBlock(
`p`,
A,
toDisplayString(t.text),
1,
)),
],
64,
)
),
),
128,
)),
],
8,
k,
),
unref(x)
? (openBlock(),
createElementBlock(
`button`,
{
key: 1,
type: `button`,
class: `description-toggle`,
"aria-expanded": unref(v),
"aria-controls": unref(y),
"aria-label": unref(w),
onClick: (i[0] ||= (e) => (v.value = !unref(v))),
},
[
createTextVNode(
toDisplayString(
unref(v) ? `收起介绍` : `展开完整介绍`,
),
1,
),
createElementVNode(
`i`,
{
class: normalizeClass([
`pi`,
unref(v) ? `pi-angle-up` : `pi-angle-down`,
]),
"aria-hidden": `true`,
},
null,
2,
),
],
8,
N,
))
: createCommentVNode(``, !0),
],
10,
D,
));
},
}),
[[`__scopeId`, `data-v-8a6cfb44`]],
),
{
__name: `ProductDescription`,
},
);
export {};
export default F;
</script>
+77
View File
@@ -0,0 +1,77 @@
<script>
import "~/assets/styles/ProductGroupLabel.B1kWpFA-.css";
import { toDisplayString } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
function l(e) {
let t = typeof e == `string` ? e.trim() : ``,
n = t.indexOf(`-N`);
if (n < 0)
return {
name: t,
badge: ``,
};
let r = t.slice(0, n).trim(),
i = t.slice(n + 2).trim();
return r && i
? {
name: r,
badge: i,
}
: {
name: t,
badge: ``,
};
}
var u = {
class: `product-group-label`,
},
d = {
class: `product-group-name`,
},
f = {
key: 0,
class: `product-group-badge`,
},
p = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ProductGroupLabel`,
props: {
name: {},
},
setup(o) {
let c = o,
p = computed(() => l(c.name));
return (n, o) => (
openBlock(),
createElementBlock(`span`, u, [
createElementVNode(`span`, d, toDisplayString(unref(p).name), 1),
unref(p).badge
? (openBlock(),
createElementBlock(
`span`,
f,
toDisplayString(unref(p).badge),
1,
))
: createCommentVNode(``, !0),
])
);
},
}),
[[`__scopeId`, `data-v-6806c62d`]],
),
{
__name: `ProductGroupLabel`,
},
);
export { l as n };
export default p;
</script>
+253
View File
@@ -0,0 +1,253 @@
<script>
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/RechargeDialog.DpsMly4r.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputnumber from "primevue/inputnumber";
import PaymentDialog from "~/components/PaymentDialog.vue";
var E = {
class: `step`,
},
D = [`for`],
O = {
class: `recharge-options`,
},
k = [`disabled`, `aria-pressed`, `onClick`],
A = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `RechargeDialog`,
props: {
modelValue: {
type: Boolean,
default: !1,
},
modelModifiers: {},
},
emits: mergeModels([`success`], [`update:modelValue`]),
setup(i, { emit: g }) {
let S = useModel(i, `modelValue`),
A = g,
j = useApi(),
M = useId(),
N = ref(null),
P = ref(!1),
F = ref(``),
I = ref(!1),
L = ref(null),
R = ref(``);
async function z() {
if (!P.value) {
if (((F.value = ``), !N.value || N.value <= 0)) {
F.value = `请输入充值金额`;
return;
}
P.value = !0;
try {
let e = await j.post(`/recharge`, {
amount: N.value,
});
((L.value = e.id),
(R.value = Number(N.value).toFixed(2)),
(N.value = null),
(S.value = !1),
(I.value = !0));
} catch (e) {
F.value = e instanceof Error ? e.message : `创建充值订单失败`;
} finally {
P.value = !1;
}
}
}
function B() {
A(`success`);
}
return (n, i) => {
let a = inputnumber,
s = message,
g = button,
y = dialog,
A = PaymentDialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
y,
{
visible: S.value,
"onUpdate:visible": (i[2] ||= (e) => (S.value = e)),
header: `充值`,
modal: ``,
draggable: !1,
style: {
width: `min(640px, calc(100vw - 28px))`,
},
},
{
footer: withCtx(() => [
createVNode(g, {
label: `取消`,
icon: `pi pi-times`,
severity: `secondary`,
outlined: ``,
onClick: (i[1] ||= (e) => (S.value = !1)),
}),
createVNode(
g,
{
label: `充值`,
icon: `pi pi-check`,
loading: unref(P),
onClick: z,
},
null,
8,
[`loading`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, E, [
createElementVNode(
`label`,
{
for: `${unref(M)}-amount`,
class: `field-label`,
},
`充值金额`,
8,
D,
),
createElementVNode(`div`, O, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList([30, 50, 100, 200, 400, 800], (t) =>
createElementVNode(
`button`,
{
key: t,
type: `button`,
disabled: unref(P),
"aria-pressed": unref(N) === t,
class: normalizeClass([
`recharge-option`,
{
active: unref(N) === t,
},
]),
onClick: (e) => (N.value = t),
},
`¥ ` + toDisplayString(t),
11,
k,
),
),
64,
)),
createVNode(
a,
{
"input-id": `${unref(M)}-amount`,
modelValue: unref(N),
"onUpdate:modelValue": (i[0] ||= (e) =>
isRef(N) ? (N.value = e) : null),
disabled: unref(P),
"aria-label": `自定义充值金额`,
class: `custom-amount`,
mode: `currency`,
currency: `CNY`,
locale: `zh-CN`,
min: 0,
minFractionDigits: 2,
maxFractionDigits: 2,
placeholder: `请输入充值金额`,
fluid: ``,
},
null,
8,
[`input-id`, `modelValue`, `disabled`],
),
]),
unref(F)
? (openBlock(),
createBlock(
s,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(F)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`],
),
createVNode(
A,
{
modelValue: unref(I),
"onUpdate:modelValue": (i[3] ||= (e) =>
isRef(I) ? (I.value = e) : null),
"order-id": unref(L),
amount: unref(R),
onSuccess: B,
},
null,
8,
[`modelValue`, `order-id`, `amount`],
),
],
64,
)
);
};
},
}),
[[`__scopeId`, `data-v-c038cb91`]],
),
{
__name: `RechargeDialog`,
},
);
export {};
export default A;
</script>
+248
View File
@@ -0,0 +1,248 @@
<script>
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
import { renderList } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { withModifiers } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { n as sanitize_n } from "~/lib/sanitize.js";
var g = [`aria-label`],
_ = [`title`, `aria-label`, `disabled`, `onClick`],
v = [
`id`,
`aria-label`,
`aria-disabled`,
`contenteditable`,
`data-placeholder`,
],
y = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `RichTextEditor`,
props: mergeModels(
{
id: {},
label: {
default: `正文`,
},
placeholder: {
default: `输入内容`,
},
disabled: {
type: Boolean,
},
minHeight: {
default: 240,
},
},
{
modelValue: {
default: ``,
},
modelModifiers: {},
},
),
emits: [`update:modelValue`],
setup(r) {
let u = r,
m = useModel(r, `modelValue`),
y = ref(null),
b = null,
x = [
{
name: `加粗`,
command: `bold`,
icon: `pi pi-bold`,
},
{
name: `斜体`,
command: `italic`,
icon: `pi pi-italic`,
},
{
name: `下划线`,
command: `underline`,
icon: `pi pi-underline`,
},
{
name: `有序列表`,
command: `insertOrderedList`,
icon: `pi pi-list`,
},
{
name: `无序列表`,
command: `insertUnorderedList`,
icon: `pi pi-list-check`,
},
{
name: `左对齐`,
command: `justifyLeft`,
icon: `pi pi-align-left`,
},
{
name: `居中对齐`,
command: `justifyCenter`,
icon: `pi pi-align-center`,
},
{
name: `右对齐`,
command: `justifyRight`,
icon: `pi pi-align-right`,
},
];
function S() {
let e = window.getSelection();
e?.rangeCount &&
y.value?.contains(e.anchorNode) &&
(b = e.getRangeAt(0).cloneRange());
}
function C() {
y.value &&
((m.value = y.value.innerText.trim()
? sanitize_n(y.value.innerHTML)
: ``),
S());
}
function w(e) {
if (!u.disabled && y.value) {
if (
(y.value.focus(),
b && y.value.contains(b.commonAncestorContainer))
) {
let e = window.getSelection();
(e?.removeAllRanges(), e?.addRange(b));
}
(document.execCommand(e, !1), C());
}
}
function T(e) {
(e.preventDefault(),
!u.disabled &&
(document.execCommand(
`insertText`,
!1,
e.clipboardData?.getData(`text/plain`) || ``,
),
C()));
}
return (
onMounted(() => {
y.value && (y.value.innerHTML = sanitize_n(m.value));
}),
watch(m, (e) => {
y.value &&
sanitize_n(y.value.innerHTML) !== e &&
(y.value.innerHTML = sanitize_n(e));
}),
(t, i) => (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`rich-editor`,
{
disabled: r.disabled,
},
]),
},
[
createElementVNode(
`div`,
{
class: `editor-toolbar`,
role: `toolbar`,
"aria-label": `${r.label}格式`,
},
[
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(x, (e) =>
createElementVNode(
`button`,
{
key: e.command,
type: `button`,
title: e.name,
"aria-label": e.name,
disabled: r.disabled,
onMousedown: (i[0] ||= withModifiers(() => {}, [
`prevent`,
])),
onClick: (t) => w(e.command),
},
[
createElementVNode(
`i`,
{
class: normalizeClass(e.icon),
"aria-hidden": `true`,
},
null,
2,
),
],
40,
_,
),
),
64,
)),
],
8,
g,
),
createElementVNode(
`div`,
{
id: r.id,
ref_key: `editor`,
ref: y,
class: `editor-content`,
role: `textbox`,
"aria-label": r.label,
"aria-multiline": `true`,
"aria-disabled": r.disabled,
contenteditable: !r.disabled,
"data-placeholder": r.placeholder,
style: normalizeStyle({
minHeight: `${r.minHeight}px`,
}),
onInput: C,
onKeyup: S,
onMouseup: S,
onBlur: S,
onPaste: T,
},
null,
44,
v,
),
],
2,
)
)
);
},
}),
[[`__scopeId`, `data-v-858a2ddd`]],
),
{
__name: `RichTextEditor`,
},
);
export {};
export default y;
</script>
+128
View File
@@ -0,0 +1,128 @@
<script>
import "~/assets/styles/RingProgress.CVwR7il5.css";
import { toDisplayString } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var u = [`width`, `height`, `viewBox`],
d = [`cx`, `cy`, `r`],
f = [`cx`, `cy`, `r`, `stroke-dasharray`, `stroke-dashoffset`, `transform`],
p = {
class: `ring-text`,
},
m = {
class: `ring-value`,
},
h = {
key: 0,
class: `ring-label`,
},
g = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `RingProgress`,
props: {
value: {},
label: {},
size: {
default: 112,
},
},
setup(o) {
let l = o,
g = computed(() => l.size / 2 - 8),
_ = computed(() => 2 * Math.PI * g.value),
v = computed(
() => _.value * (1 - Math.min(100, Math.max(0, l.value)) / 100),
);
return (n, l) => (
openBlock(),
createElementBlock(
`div`,
{
class: `ring`,
style: normalizeStyle({
width: `${o.size}px`,
height: `${o.size}px`,
}),
},
[
(openBlock(),
createElementBlock(
`svg`,
{
width: o.size,
height: o.size,
viewBox: `0 0 ${o.size} ${o.size}`,
},
[
createElementVNode(
`circle`,
{
cx: o.size / 2,
cy: o.size / 2,
r: unref(g),
fill: `none`,
stroke: `var(--p-content-border-color, #e2e8f0)`,
"stroke-width": 6,
},
null,
8,
d,
),
createElementVNode(
`circle`,
{
cx: o.size / 2,
cy: o.size / 2,
r: unref(g),
fill: `none`,
stroke: `#0ea5e9`,
"stroke-width": 6,
"stroke-linecap": `round`,
"stroke-dasharray": unref(_),
"stroke-dashoffset": unref(v),
transform: `rotate(-90 ${o.size / 2} ${o.size / 2})`,
class: `ring-bar`,
},
null,
8,
f,
),
],
8,
u,
)),
createElementVNode(`div`, p, [
createElementVNode(
`div`,
m,
toDisplayString(Math.round(o.value)) + `%`,
1,
),
o.label
? (openBlock(),
createElementBlock(`div`, h, toDisplayString(o.label), 1))
: createCommentVNode(``, !0),
]),
],
4,
)
);
},
}),
[[`__scopeId`, `data-v-bff6718d`]],
),
{
__name: `RingProgress`,
},
);
export {};
export default g;
</script>
@@ -0,0 +1,635 @@
<script>
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
import "~/assets/styles/SecurityVerificationDialog.skYFo4v7.css";
import { i as rolldown_runtime_i } from "~/lib/rolldown-runtime.js";
import { toDisplayString } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { loadModule } from "~/utils/load-module.js";
import { securityMethods } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import CaptchaField from "~/components/CaptchaField.vue";
import select from "primevue/select";
import { t as interval_t } from "~/lib/interval.js";
import { t as useCaptcha_t } from "~/lib/useCaptcha.js";
var w = {
class: `security-verify`,
},
oe = {
key: 1,
class: `tip`,
},
T = [`src`],
se = {
for: `security-value`,
},
ce = {
class: `verify-input`,
},
le = {
key: 1,
class: `error`,
},
ue = {
key: 4,
role: `alert`,
class: `error`,
},
de = {
key: 5,
role: `alert`,
class: `error`,
},
fe = {
class: `actions`,
},
E = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `SecurityVerificationDialog`,
props: {
visible: {
type: Boolean,
},
challenge: {},
busy: {
type: Boolean,
default: !1,
},
requestError: {
default: ``,
},
context: {
default: void 0,
},
},
emits: [`update:visible`, `verified`, `cancel`],
setup(m, { emit: b }) {
let E = m,
D = b,
O = useApi(),
k = ref(``),
A = ref(``),
j = ref(``),
M = ref(``),
N = ref(!1),
P = ref(0),
F = ref(!1),
I = ref(``),
L = 0,
R = !1,
z,
B,
V = useCaptcha_t(`security_verify`),
{
needed: pe,
provider: me,
captchaId: he,
img: ge,
value: H,
loading: _e,
error: U,
} = V,
W = computed(() =>
securityMethods(E.challenge).map((e) => ({
...e,
disabled:
e.value === `certification` && E.context?.scene !== `login`,
displayLabel:
e.label +
(e.value === `certification` && E.context?.scene !== `login`
? `(暂未开放)`
: ``),
})),
),
G = computed(() => W.value.find((e) => e.value === k.value)),
K = computed(() => E.busy || N.value || F.value);
function ve() {
(clearInterval(z), clearTimeout(B), (z = void 0), (B = void 0));
}
function q() {
(L++,
ve(),
(A.value = ``),
(M.value = ``),
(P.value = 0),
(N.value = !1),
(F.value = !1),
(j.value = ``),
(I.value = ``),
V.invalidate());
}
(watch(
() => [E.visible, E.challenge],
() => {
(q(),
E.visible &&
((k.value = W.value.find((e) => !e.disabled)?.value || ``),
(k.value === `phone_code` || k.value === `email_code`) &&
V.needed.value &&
V.load()));
},
{
immediate: !0,
},
),
watch(k, () => {
(q(),
E.visible &&
(k.value === `phone_code` || k.value === `email_code`) &&
V.needed.value &&
V.load());
}),
onBeforeUnmount(() => {
((R = !0), q());
}));
let J = (e) => !R && E.visible && e === L,
Y = computed(
() => k.value === `email_code` || k.value === `phone_code`,
);
async function ye() {
if (K.value || P.value || !Y.value || !G.value || !E.visible)
return;
let e =
E.context?.scene === `login`
? `exception_login`
: E.context?.action;
if (!e) {
M.value = `验证场景缺失,请重新发起操作`;
return;
}
if (((M.value = V.validationError()), M.value)) return;
let t = L,
n = G.value,
r = n.account || E.context?.account || ``;
if (E.context?.scene === `login` && !r) {
M.value = `验证账户信息缺失,请重新登录`;
return;
}
N.value = !0;
try {
if (
(await O.post(
n.value === `email_code` ? `/email/code` : `/phone/code`,
{
action: e,
...(n.value === `email_code`
? {
email: r,
}
: {
phone: r,
phone_code:
n.phone_code || E.context?.phoneCode || `86`,
}),
captcha: V.value.value.trim(),
token: V.token.value,
security_verify_token:
n.security_verify_token || E.context?.token || ``,
},
),
!J(t))
)
return;
((P.value = 60),
(z = interval_t(() => {
--P.value <= 0 && (clearInterval(z), (z = void 0));
}, 1e3)),
V.needed.value && V.load());
} catch (e) {
J(t) &&
((M.value = e instanceof Error ? e.message : `验证码发送失败`),
await V.handleError(e));
} finally {
J(t) && (N.value = !1);
}
}
function X() {
return {
security_verify_method: k.value,
security_verify_value:
k.value === `operate_password` ? A.value : A.value.trim(),
...(j.value
? {
certify_id: j.value,
}
: {}),
security_verify_token:
G.value?.security_verify_token || E.context?.token || ``,
};
}
function Z() {
return {
account: G.value?.account || E.context?.account || ``,
phone_code: G.value?.phone_code || E.context?.phoneCode || `86`,
security_verify_token:
G.value?.security_verify_token || E.context?.token || ``,
};
}
async function Q(e) {
if (J(e) && j.value) {
try {
let t = await O.get(
`/login/exception/certification/status`,
{
...Z(),
certify_id: j.value,
},
!1,
);
if (!J(e)) return;
if (Number(t.verify_status) === 1) {
(clearTimeout(B), D(`verified`, X()));
return;
}
M.value = ``;
} catch (t) {
J(e) &&
(M.value =
t instanceof Error
? t.message
: `暂时无法查询验证结果,正在重试`);
}
J(e) && (B = setTimeout(() => void Q(e), 2e3));
}
}
async function be() {
if (
K.value ||
G.value?.disabled ||
k.value !== `certification` ||
E.context?.scene !== `login`
)
return;
let t = ++L;
(clearTimeout(B), (F.value = !0), (M.value = ``));
try {
let n = await O.post(
`/login/exception/certification/create`,
Z(),
!1,
);
if (!J(t)) return;
if (
!n.certify_id ||
!n.certify_url ||
!/^https:\/\//i.test(n.certify_url)
)
throw Error(`认证二维码响应无效,请重试`);
let { toDataURL: r } = await loadModule(
async () => {
let { toDataURL: t } =
await import("qrcode/lib/browser.js").then((t) =>
rolldown_runtime_i(t.default, 1),
);
return {
toDataURL: t,
};
},
[],
import.meta.url,
),
i = await r(n.certify_url, {
width: 240,
margin: 2,
});
if (!J(t)) return;
((j.value = String(n.certify_id)), (I.value = i), Q(t));
} catch (e) {
J(t) &&
(M.value =
e instanceof Error ? e.message : `认证二维码加载失败`);
} finally {
J(t) && (F.value = !1);
}
}
function xe() {
if (
!K.value &&
E.visible &&
G.value &&
!G.value.disabled &&
k.value !== `certification`
) {
if (((M.value = ``), !A.value.trim())) {
M.value = `请输入验证信息`;
return;
}
D(`verified`, X());
}
}
function $() {
E.busy || (q(), D(`cancel`), D(`update:visible`, !1));
}
return (e, n) => {
let r = select,
a = message,
c = button,
_ = inputtext,
v = CaptchaField,
y = dialog;
return (
openBlock(),
createBlock(
y,
{
visible: m.visible,
header: `安全验证`,
modal: ``,
closable: !m.busy,
"close-on-escape": !m.busy,
style: {
width: `min(430px, calc(100vw - 28px))`,
},
"onUpdate:visible": (n[3] ||= (e) => !e && $()),
},
{
default: withCtx(() => [
createElementVNode(`div`, w, [
(n[5] ||= createElementVNode(
`label`,
{
for: `security-method`,
},
`验证方式`,
-1,
)),
createVNode(
r,
{
"input-id": `security-method`,
modelValue: unref(k),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(k) ? (k.value = e) : null),
options: unref(W),
"option-label": `displayLabel`,
"option-value": `value`,
"option-disabled": `disabled`,
disabled: unref(K),
},
null,
8,
[`modelValue`, `options`, `disabled`],
),
unref(k)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
a,
{
key: 0,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
...(n[4] ||= [
createTextVNode(
`当前没有已开放的验证方式,请联系客服。`,
-1,
),
]),
]),
_: 1,
},
)),
unref(G)?.tip
? (openBlock(),
createElementBlock(
`p`,
oe,
toDisplayString(unref(G).tip),
1,
))
: createCommentVNode(``, !0),
unref(k) === `certification`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
unref(I)
? (openBlock(),
createElementBlock(
`img`,
{
key: 0,
src: unref(I),
alt: `安全验证二维码`,
class: `security-qr`,
},
null,
8,
T,
))
: createCommentVNode(``, !0),
createVNode(
c,
{
label: unref(I) ? `刷新二维码` : `获取二维码`,
loading: unref(F),
disabled: unref(K),
onClick: be,
},
null,
8,
[`label`, `loading`, `disabled`],
),
],
64,
))
: unref(k)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
createElementVNode(
`label`,
se,
toDisplayString(
unref(Y) ? `验证码` : `操作密码`,
),
1,
),
createElementVNode(`div`, ce, [
createVNode(
_,
{
id: `security-value`,
modelValue: unref(A),
"onUpdate:modelValue": (n[1] ||= (e) =>
isRef(A) ? (A.value = e) : null),
type: unref(Y) ? `text` : `password`,
autocomplete: unref(Y)
? `one-time-code`
: `off`,
disabled: unref(K),
},
null,
8,
[
`modelValue`,
`type`,
`autocomplete`,
`disabled`,
],
),
unref(Y)
? (openBlock(),
createBlock(
c,
{
key: 0,
label: unref(P)
? `${unref(P)}s`
: `发送验证码`,
severity: `secondary`,
outlined: ``,
disabled: unref(K) || unref(P) > 0,
onClick: ye,
},
null,
8,
[`label`, `disabled`],
))
: createCommentVNode(``, !0),
]),
unref(Y) && unref(pe)
? (openBlock(),
createBlock(
v,
{
key: 0,
modelValue: unref(H),
"onUpdate:modelValue": (n[2] ||= (e) =>
isRef(H) ? (H.value = e) : null),
img: unref(ge),
provider: unref(me),
"captcha-id": unref(he),
loading: unref(_e),
disabled: unref(K),
onVerified: unref(V).complete,
onInvalid: unref(V).invalidate,
onRefresh: unref(V).load,
},
null,
8,
[
`modelValue`,
`img`,
`provider`,
`captcha-id`,
`loading`,
`disabled`,
`onVerified`,
`onInvalid`,
`onRefresh`,
],
))
: createCommentVNode(``, !0),
unref(Y) && unref(U)
? (openBlock(),
createElementBlock(
`small`,
le,
toDisplayString(unref(U)),
1,
))
: createCommentVNode(``, !0),
],
64,
))
: createCommentVNode(``, !0),
unref(M)
? (openBlock(),
createElementBlock(
`small`,
ue,
toDisplayString(unref(M)),
1,
))
: m.requestError
? (openBlock(),
createElementBlock(
`small`,
de,
toDisplayString(m.requestError),
1,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, fe, [
createVNode(
c,
{
label: `取消`,
severity: `secondary`,
text: ``,
disabled: m.busy,
onClick: $,
},
null,
8,
[`disabled`],
),
unref(k) && unref(k) !== `certification`
? (openBlock(),
createBlock(
c,
{
key: 0,
label: `验证`,
loading: m.busy,
disabled: unref(K),
onClick: xe,
},
null,
8,
[`loading`, `disabled`],
))
: createCommentVNode(``, !0),
]),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
)
);
};
},
}),
[[`__scopeId`, `data-v-ff4061ec`]],
),
{
__name: `SecurityVerificationDialog`,
},
);
export {};
export default E;
</script>
+166
View File
@@ -0,0 +1,166 @@
<script>
import "~/assets/styles/SensitiveValue.BSZlaRHT.css";
import { toDisplayString } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { useRoute } from "#app";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
function p(e) {
return /[**•●]/u.test(e ?? ``);
}
function m(e) {
return !!e?.trim() && !p(e);
}
function h(e, t, n) {
let r = Array.from(e);
return r.length <= t + n
? `*`.repeat(Math.max(r.length, 1))
: `${r.slice(0, t).join(``)}****${n ? r.slice(-n).join(``) : ``}`;
}
function g(e, t) {
if (!e?.trim()) return ``;
if (p(e)) return e;
let n = e.trim(),
r = Array.from(n);
switch (t) {
case `phone`:
return r.length >= 8
? h(n, 3, 4)
: r.length >= 5
? h(n, 2, 2)
: h(n, +(r.length > 1), 0);
case `email`: {
let e = n.split(`@`);
if (e.length !== 2 || !e[0] || !e[1] || /\s/u.test(n)) return h(n, 1, 1);
let t = Array.from(e[0]),
r =
t.length > 2
? t.slice(0, 2).join(``)
: t.length > 1
? (t[0] ?? ``)
: ``;
return `${r}${`*`.repeat(Math.max(2, t.length - Array.from(r).length))}@${e[1]}`;
}
case `name`:
return r.length > 1 ? `${r[0]}**` : `*`;
case `text`:
return h(n, 2, 2);
case `identity`:
return r.length > 7 ? h(n, 3, 4) : h(n, +(r.length > 1), 0);
}
}
var _ = {
class: `sensitive-value`,
},
v = {
class: `sensitive-value-text`,
},
y = [`aria-label`, `aria-pressed`],
b = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `SensitiveValue`,
props: {
value: {
default: ``,
},
kind: {
default: `text`,
},
label: {
default: `敏感信息`,
},
prefix: {
default: ``,
},
placeholder: {
default: `—`,
},
empty: {},
resetKey: {
default: void 0,
},
},
setup(l) {
let f = l,
p = useRoute(),
h = ref(!1),
b = computed(() => m(f.value)),
x = computed(() => g(f.value, f.kind)),
S = computed(() => {
if (!x.value) return f.empty ?? f.placeholder;
let e = h.value && b.value ? f.value : x.value;
return f.prefix ? `${f.prefix} ${e}` : e;
});
return (
watch(
[
() => f.value,
() => f.kind,
() => f.prefix,
() => f.resetKey,
() => p.fullPath,
],
() => {
h.value = !1;
},
{
flush: `sync`,
},
),
(n, r) => (
openBlock(),
createElementBlock(`span`, _, [
createElementVNode(`span`, v, toDisplayString(unref(S)), 1),
unref(b)
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
type: `button`,
class: `sensitive-value-toggle`,
"aria-label": `${unref(h) ? `隐藏` : `显示完整`}${l.label}`,
"aria-pressed": unref(h),
onClick: (r[0] ||= (e) => (h.value = !unref(h))),
},
[
createElementVNode(
`i`,
{
class: normalizeClass([
`pi`,
unref(h) ? `pi-eye-slash` : `pi-eye`,
]),
"aria-hidden": `true`,
},
null,
2,
),
],
8,
y,
))
: createCommentVNode(``, !0),
])
)
);
},
}),
[[`__scopeId`, `data-v-07008ebf`]],
),
{
__name: `SensitiveValue`,
},
);
export {};
export default b;
</script>
+457
View File
@@ -0,0 +1,457 @@
<script>
import "~/assets/styles/TicketAttachments.DtbJGLkE.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { t as ticketAttachments_t } from "~/lib/ticketAttachments.js";
var S = {
key: 1,
class: `message-attachments`,
"aria-label": `消息附件`,
},
C = [`aria-label`, `onClick`],
w = {
class: `thumbnail`,
},
T = [`src`, `alt`, `onError`],
E = {
key: 1,
class: `pi pi-image`,
"aria-hidden": `true`,
},
D = {
class: `image-caption`,
},
O = {
class: `attachment-name`,
},
k = {
key: 1,
class: `file-attachment`,
},
A = [`href`, `download`, `aria-label`],
j = {
key: 2,
class: `attachment-unavailable`,
},
M = {
key: 0,
class: `preview-status`,
role: `status`,
},
N = {
key: 1,
class: `preview-error`,
role: `alert`,
},
P = [`aria-busy`],
F = [`src`, `alt`],
I = {
class: `preview-actions`,
},
L = [`href`, `download`],
R = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `TicketAttachments`,
props: {
files: {},
},
setup(p) {
let y = ref(null),
R = ref(!1),
z = ref(!1),
B = ref(!1),
V = ref(!1),
H = ref({}),
U = null,
W = ref({}),
G = ref(``);
async function K(e) {
if (
!(e.href || !e.storageName || W.value[e.name]) &&
(!U && typeof useApi == `function` && (U = useApi()), U)
) {
((W.value[e.name] = !0), (G.value = ``));
try {
await U.download(
`/ticket/download`,
{
name: e.storageName,
},
e.name,
{
method: `POST`,
},
);
} catch (e) {
G.value =
e instanceof Error ? e.message : `附件下载失败,请重试`;
} finally {
W.value[e.name] = !1;
}
}
}
function q(e) {
ticketAttachments_t(e) &&
((y.value = e),
(z.value = !0),
(B.value = !1),
(V.value = !1),
(R.value = !0));
}
function J() {
((z.value = !1), (B.value = !0));
}
return (i, g) => {
let U = message,
Y = button,
X = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
unref(G)
? (openBlock(),
createBlock(
U,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(G)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
p.files.length
? (openBlock(),
createElementBlock(`ul`, S, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
p.files,
(t, n) => (
openBlock(),
createElementBlock(
`li`,
{
key: `${n}-${t.href || t.name}`,
},
[
unref(ticketAttachments_t)(t)
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
type: `button`,
class: `image-attachment`,
"aria-label": `预览图片 ${t.name}`,
onClick: (e) => q(t),
},
[
createElementVNode(`span`, w, [
t.href && !unref(H)[t.href]
? (openBlock(),
createElementBlock(
`img`,
{
key: 0,
src: t.href,
alt: t.name,
loading: `lazy`,
referrerpolicy: `no-referrer`,
onError: (e) =>
(unref(H)[t.href] = !0),
},
null,
40,
T,
))
: (openBlock(),
createElementBlock(`i`, E)),
]),
createElementVNode(`span`, D, [
createElementVNode(
`span`,
O,
toDisplayString(t.name),
1,
),
(g[4] ||= createElementVNode(
`span`,
{
class: `image-hint`,
},
`点击查看大图`,
-1,
)),
]),
],
8,
C,
))
: (openBlock(),
createElementBlock(`span`, k, [
(g[6] ||= createElementVNode(
`i`,
{
class: `pi pi-paperclip`,
"aria-hidden": `true`,
},
null,
-1,
)),
t.href
? (openBlock(),
createElementBlock(
`a`,
{
key: 0,
href: t.href,
download: t.name,
target: `_blank`,
rel: `noopener noreferrer`,
"aria-label": `下载附件 ${t.name}`,
},
[
createTextVNode(
toDisplayString(t.name) + ` `,
1,
),
(g[5] ||= createElementVNode(
`i`,
{
class: `pi pi-download`,
"aria-hidden": `true`,
},
null,
-1,
)),
],
8,
A,
))
: t.storageName
? (openBlock(),
createBlock(
Y,
{
key: 1,
label: t.name,
icon: `pi pi-download`,
text: ``,
size: `small`,
loading: unref(W)[t.name],
disabled: unref(W)[t.name],
onClick: (e) => K(t),
},
null,
8,
[
`label`,
`loading`,
`disabled`,
`onClick`,
],
))
: (openBlock(),
createElementBlock(
`span`,
j,
toDisplayString(t.name),
1,
)),
])),
],
)
),
),
128,
)),
]))
: createCommentVNode(``, !0),
createVNode(
X,
{
visible: unref(R),
"onUpdate:visible": (g[3] ||= (e) =>
isRef(R) ? (R.value = e) : null),
header: unref(y)?.name || `图片预览`,
modal: ``,
"dismissable-mask": ``,
draggable: !1,
style: {
width: `min(1100px, calc(100vw - 32px))`,
},
},
{
footer: withCtx(() => [
createElementVNode(`div`, I, [
unref(B)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
Y,
{
key: 0,
label: unref(V) ? `适应窗口` : `原始尺寸`,
icon: unref(V)
? `pi pi-window-minimize`
: `pi pi-search-plus`,
severity: `secondary`,
outlined: ``,
disabled: unref(z),
"aria-pressed": unref(V),
onClick: (g[1] ||= (e) =>
(V.value = !unref(V))),
},
null,
8,
[`label`, `icon`, `disabled`, `aria-pressed`],
)),
unref(y)?.href
? (openBlock(),
createElementBlock(
`a`,
{
key: 1,
class: `download-image`,
href: unref(y).href,
download: unref(y).name,
target: `_blank`,
rel: `noopener noreferrer`,
},
[
...(g[7] ||= [
createElementVNode(
`i`,
{
class: `pi pi-download`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`下载原图 `, -1),
]),
],
8,
L,
))
: createCommentVNode(``, !0),
createVNode(Y, {
label: `关闭`,
severity: `secondary`,
text: ``,
onClick: (g[2] ||= (e) => (R.value = !1)),
}),
]),
]),
default: withCtx(() => [
unref(y)?.href
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
unref(z)
? (openBlock(),
createElementBlock(`p`, M, `正在加载图片…`))
: createCommentVNode(``, !0),
unref(B)
? (openBlock(),
createElementBlock(
`p`,
N,
`图片加载失败,链接可能已过期。请刷新工单后重试,或下载原图查看。`,
))
: (openBlock(),
createElementBlock(
`div`,
{
key: 2,
class: normalizeClass([
`image-preview`,
{
"original-size": unref(V),
},
]),
"aria-busy": unref(z),
},
[
(openBlock(),
createElementBlock(
`img`,
{
key: unref(y).href,
src: unref(y).href,
alt: unref(y).name,
referrerpolicy: `no-referrer`,
onLoad: (g[0] ||= (e) =>
(z.value = !1)),
onError: J,
},
null,
40,
F,
)),
],
10,
P,
)),
],
64,
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `header`],
),
],
64,
)
);
};
},
}),
[[`__scopeId`, `data-v-77cd676b`]],
),
{
__name: `TicketAttachments`,
},
);
export {};
export default R;
</script>
+119
View File
@@ -0,0 +1,119 @@
<script>
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import message from "primevue/message";
import { n as sanitize_n } from "~/lib/sanitize.js";
var _ = [`innerHTML`],
v = Object.assign(
defineComponent({
__name: `TicketNotice`,
setup(u) {
let v = useApi(),
y = ref(``),
b = ref(``),
x = ref(!1),
S = !1;
async function C() {
if (!x.value) {
((x.value = !0), (b.value = ``));
try {
let e = await v.get(`/ticket/config`);
if (S) return;
y.value =
Number(e.ticket_notice_open) === 1
? sanitize_n(e.ticket_notice_description || ``)
: ``;
} catch (e) {
S ||
(b.value =
e instanceof Error ? e.message : `工单通知说明加载失败`);
} finally {
S || (x.value = !1);
}
}
}
return (
onMounted(C),
onBeforeUnmount(() => {
S = !0;
}),
(t, n) => {
let i = message,
u = button;
return unref(y)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createElementVNode(
`div`,
{
innerHTML: unref(y),
},
null,
8,
_,
),
]),
_: 1,
},
))
: unref(b)
? (openBlock(),
createBlock(
i,
{
key: 1,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(b)) + ` `, 1),
createVNode(
u,
{
label: `重试通知说明`,
text: ``,
loading: unref(x),
onClick: C,
},
null,
8,
[`loading`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0);
}
);
},
}),
{
__name: `TicketNotice`,
},
);
export {};
export default v;
</script>
+191
View File
@@ -0,0 +1,191 @@
<script>
import "~/assets/styles/UploadField.BbTCTv6C.css";
import { toDisplayString } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var m = {
class: `field`,
},
h = {
key: 0,
},
g = {
class: `row`,
},
_ = [`accept`, `disabled`],
v = {
key: 0,
class: `state`,
},
y = {
class: `state ok`,
},
b = {
key: 2,
class: `state`,
},
x = {
key: 1,
class: `err`,
},
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `UploadField`,
props: mergeModels(
{
label: {},
hint: {},
accept: {},
},
{
modelValue: {
default: ``,
},
modelModifiers: {},
},
),
emits: mergeModels([`uploaded`], [`update:modelValue`]),
setup(t, { emit: u }) {
let p = useModel(t, `modelValue`),
S = u,
C = useApi(),
w = ref(!1),
T = ref(``),
E = ref(``);
async function D(e) {
let t = e.target,
n = t.files?.[0];
if (n) {
((w.value = !0), (T.value = ``));
try {
let e = await C.upload(n);
((p.value = e.save_name), (E.value = n.name), S(`uploaded`, e));
} catch (e) {
T.value = e instanceof Error ? e.message : `上传失败`;
} finally {
((w.value = !1), (t.value = ``));
}
}
}
function O() {
((p.value = ``), (E.value = ``));
}
return (n, r) => (
openBlock(),
createElementBlock(`div`, m, [
t.label
? (openBlock(),
createElementBlock(`label`, h, toDisplayString(t.label), 1))
: createCommentVNode(``, !0),
createElementVNode(`div`, g, [
createElementVNode(
`input`,
{
type: `file`,
accept: t.accept,
disabled: unref(w),
onChange: D,
},
null,
40,
_,
),
unref(w)
? (openBlock(),
createElementBlock(`span`, v, [
...(r[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-spin pi-spinner`,
},
null,
-1,
),
createTextVNode(` 上传中…`, -1),
]),
]))
: p.value
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(`span`, y, [
(r[1] ||= createElementVNode(
`i`,
{
class: `pi pi-check-circle`,
},
null,
-1,
)),
createTextVNode(
` ` + toDisplayString(unref(E) || `已上传`),
1,
),
]),
createElementVNode(
`button`,
{
type: `button`,
class: `rm`,
onClick: O,
},
[
...(r[2] ||= [
createElementVNode(
`i`,
{
class: `pi pi-times`,
},
null,
-1,
),
]),
],
),
],
64,
))
: t.hint
? (openBlock(),
createElementBlock(
`span`,
b,
toDisplayString(t.hint),
1,
))
: createCommentVNode(``, !0),
]),
unref(T)
? (openBlock(),
createElementBlock(`span`, x, toDisplayString(unref(T)), 1))
: createCommentVNode(``, !0),
])
);
},
}),
[[`__scopeId`, `data-v-8267b59f`]],
),
{
__name: `UploadField`,
},
);
export {};
export default S;
</script>
+296
View File
@@ -0,0 +1,296 @@
<script>
import "~/assets/styles/WechatConnection.DI5ko1xy.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import tag from "primevue/tag";
import skeleton from "primevue/skeleton";
import toggleswitch from "primevue/toggleswitch";
var w = {
key: 0,
class: `wechat-connection`,
"aria-label": `微信公众号`,
},
T = {
key: 1,
class: `connection-list wechat-loading`,
role: `status`,
"aria-label": `正在读取微信关联信息`,
},
E = {
class: `connection-list`,
},
D = {
class: `connection-provider`,
},
O = {
class: `connection-provider-main`,
},
k = {
key: 0,
class: `connection-provider`,
},
A = {
key: 0,
class: `account-management-note wechat-binding-help`,
},
j = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `WechatConnection`,
setup(p) {
let y = useApi(),
j = useSiteConfig_t(),
M = ref(null),
N = ref(``),
P = ref(!1),
F = ref(!1),
I = !0,
L = 0;
async function R() {
if (!j.scanLoginEnabled.value || !I) return;
let e = ++L;
((F.value = !0), (N.value = ``));
try {
let t = await y.get(`/mp_weixin_notice/client`);
if (!I || e !== L) return;
if (
![0, 1].includes(Number(t.is_subscribe)) ||
![0, 1].includes(Number(t.accept_push))
)
throw Error(`微信关联状态无效,请重试`);
M.value = {
is_subscribe: Number(t.is_subscribe),
accept_push: Number(t.accept_push),
};
} catch (t) {
I &&
e === L &&
(N.value =
t instanceof Error ? t.message : `微信关联信息加载失败`);
} finally {
I && e === L && (F.value = !1);
}
}
async function z() {
if (!(!I || P.value || F.value || M.value?.is_subscribe !== 1)) {
((P.value = !0), (N.value = ``));
try {
(await y.put(`/mp_weixin_notice/accept_push`, {
status: M.value.accept_push === 1 ? 0 : 1,
}),
I && (await R()));
} catch (e) {
I &&
(N.value =
e instanceof Error ? e.message : `推送设置保存失败`);
} finally {
I && (P.value = !1);
}
}
}
return (
watch(j.scanLoginEnabled, () => {
j.scanLoginEnabled.value ? R() : (L++, (M.value = null));
}),
onMounted(async () => {
(await j.load(), await R());
}),
onBeforeUnmount(() => {
((I = !1), L++);
}),
(t, n) => {
let r = button,
a = message,
p = skeleton,
g = tag,
_ = toggleswitch;
return unref(j).scanLoginEnabled.value
? (openBlock(),
createElementBlock(`section`, w, [
(n[2] ||= createElementVNode(
`h3`,
{
class: `connection-section-title`,
},
`微信公众号`,
-1,
)),
unref(N)
? (openBlock(),
createBlock(
a,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(N)) + ` `,
1,
),
createVNode(
r,
{
label: `重试`,
size: `small`,
text: ``,
severity: `secondary`,
disabled: unref(P),
onClick: R,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(F)
? (openBlock(),
createElementBlock(`div`, T, [
createVNode(p, {
width: `40%`,
height: `20px`,
}),
createVNode(p, {
width: `65%`,
height: `16px`,
}),
]))
: unref(M)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(`div`, E, [
createElementVNode(`div`, D, [
createElementVNode(`div`, O, [
(n[0] ||= createElementVNode(
`strong`,
null,
`关联状态`,
-1,
)),
createElementVNode(
`p`,
null,
toDisplayString(
unref(M).is_subscribe === 1
? `已关注并关联`
: `尚未关注或关联`,
),
1,
),
]),
createVNode(
g,
{
value:
unref(M).is_subscribe === 1
? `已关联`
: `未关联`,
severity:
unref(M).is_subscribe === 1
? `success`
: `secondary`,
},
null,
8,
[`value`, `severity`],
),
]),
unref(M).is_subscribe === 1
? (openBlock(),
createElementBlock(`div`, k, [
(n[1] ||= createElementVNode(
`div`,
{
class: `connection-provider-main`,
},
[
createElementVNode(`strong`, null, [
createElementVNode(
`label`,
{
for: `wechat-notifications`,
},
`接收微信通知`,
),
]),
createElementVNode(
`p`,
null,
`通过公众号接收账户和服务通知`,
),
],
-1,
)),
createVNode(
_,
{
"input-id": `wechat-notifications`,
"model-value":
unref(M).accept_push === 1,
disabled: unref(P) || unref(F),
"onUpdate:modelValue": z,
},
null,
8,
[`model-value`, `disabled`],
),
]))
: createCommentVNode(``, !0),
]),
unref(M).is_subscribe === 1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
A,
`使用微信扫码登录,并验证已注册的手机号或邮箱完成关联。`,
)),
],
64,
))
: createCommentVNode(``, !0),
]))
: createCommentVNode(``, !0);
}
);
},
}),
[[`__scopeId`, `data-v-4c933481`]],
),
{
__name: `WechatConnection`,
},
);
export {};
export default j;
</script>
+965
View File
@@ -0,0 +1,965 @@
<script>
import "~/assets/styles/WithdrawDialog.ks0wdKEK.css";
import { toDisplayString } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { reactive } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import textarea from "primevue/textarea";
import skeleton from "primevue/skeleton";
function C(e) {
return (
Array.isArray(e?.method) &&
e.method.some(
(e) =>
!!e &&
typeof e == `object` &&
Number.isInteger(e.id) &&
Number(e.id) >= 0 &&
typeof e.name == `string`,
)
);
}
function w(e, t = ``) {
return t === `recommend`
? C(e)
: e?.status === 1 || e?.status === `1` || e?.status === !0;
}
function T(e) {
if (typeof e != `string` && typeof e != `number`) return null;
let t = String(e).trim();
if (!/^\d+(?:\.\d{1,2})?$/.test(t)) return null;
let [n = `0`, r = ``] = t.split(`.`),
i = Number(n) * 100 + Number(r.padEnd(2, `0`));
return Number.isSafeInteger(i) ? i : null;
}
function E(e, t) {
let n = String(t ?? ``).trim();
if (!/^\d+(?:\.\d{1,6})?$/.test(n) || Number(n) > 100) return null;
let [r = `0`, i = ``] = n.split(`.`),
a = 10n ** BigInt(i.length),
o = BigInt(r) * a + BigInt(i || `0`);
return Number((BigInt(e) * o) / (100n * a));
}
var ce = {
key: 0,
class: `sk`,
},
le = {
key: 1,
class: `form`,
},
ue = {
key: 2,
class: `form`,
},
de = {
class: `notice`,
},
fe = {
key: 0,
},
pe = {
key: 1,
},
me = {
key: 2,
},
he = {
key: 3,
},
ge = {
class: `field`,
},
_e = [`id`],
ve = {
class: `field`,
},
D = [`for`],
O = {
key: 0,
class: `hint`,
},
k = {
key: 1,
class: `hint`,
},
A = {
class: `field`,
},
j = [`for`],
M = {
class: `field`,
},
N = [`for`],
P = [`for`],
F = {
class: `field`,
},
ye = [`for`],
be = {
class: `calc`,
},
xe = {
class: `calc-row`,
},
Se = {
class: `calc-row`,
},
Ce = {
class: `calc-row total`,
},
I = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `WithdrawDialog`,
props: mergeModels(
{
source: {
default: ``,
},
available: {
default: null,
},
title: {
default: ``,
},
},
{
modelValue: {
type: Boolean,
default: !1,
},
modelModifiers: {},
},
),
emits: mergeModels([`success`], [`update:modelValue`]),
setup(r, { emit: _ }) {
let x = useModel(r, `modelValue`),
C = _,
I = r,
L = useApi(),
R = useAuth(),
z = useId(),
we = {
day: `天`,
week: `周`,
month: `月`,
},
B = ref(null),
V = ref(!1),
H = ref(!1),
U = ref(``),
W = 0,
G = !0,
K = reactive({
method_id: null,
amount: null,
name: ``,
account: ``,
card_number: ``,
notes: ``,
}),
q = computed(() => {
let e = B.value,
t = T(K.amount);
return !e || t === null || t <= 0
? 0
: e.withdraw_fee_type === `fixed`
? (T(e.withdraw_fee || 0) ?? 0)
: Math.max(
E(t, e.percent || 0) ?? 0,
T(e.percent_min || 0) ?? 0,
);
}),
Te = computed(() => q.value / 100),
Ee = computed(
() => Math.max(0, (T(K.amount) ?? 0) - q.value) / 100,
),
J = computed(() =>
B.value?.method.find((e) => e.id === K.method_id),
),
Y = computed(
() => !!J.value && J.value.id !== 0 && !J.value.no_account,
),
X = computed(() => !!J.value && /银行卡/.test(J.value.name)),
Z = computed(() =>
Number(B.value?.max) > 0 ? Number(B.value?.max) : void 0,
),
Q = (e) => w(e, I.source ? `recommend` : ``);
function De() {
Object.assign(K, {
method_id: null,
amount: null,
name: ``,
account: ``,
card_number: ``,
notes: ``,
});
}
async function $() {
if (!G || !x.value || V.value) return;
let e = ++W,
t = I.source;
((V.value = !0), (B.value = null), (U.value = ``));
try {
let n = await L.get(
`/withdraw/rule/credit`,
t
? {
scene: `recommend`,
}
: void 0,
);
if (!G || e !== W) return;
if (!n || !Array.isArray(n.method))
throw Error(`提现设置不完整,请重新加载`);
let r = {
...n,
method: n.method.filter(
(e) =>
!!e &&
Number.isInteger(e.id) &&
e.id >= 0 &&
typeof e.name == `string`,
),
};
if (t && r.method.length) {
let t = await L.get(`/recommend/config`);
if (!G || e !== W) return;
if (
T(t?.config?.withdraw_min) === null ||
E(100, t?.config?.withdraw_handling_fee) === null
)
throw Error(`奖励提现规则不完整,请重新加载`);
r = {
...r,
min: String(t.config.withdraw_min),
max: ``,
cycle: ``,
cycle_limit: 0,
withdraw_fee_type: `percent`,
withdraw_fee: ``,
percent: String(t.config.withdraw_handling_fee),
percent_min: `0`,
};
}
if (Q(r)) {
let e = T(r.min || 0) !== null && T(r.max || 0) !== null,
t =
r.withdraw_fee_type === `fixed`
? T(r.withdraw_fee || 0) !== null
: r.withdraw_fee_type === `percent` &&
E(100, r.percent || 0) !== null &&
T(r.percent_min || 0) !== null;
if (!e || !t) throw Error(`提现设置不完整,请重新加载`);
}
((B.value = r),
(K.method_id = r.method[0]?.id ?? null),
(K.amount = Number(r.min || 0) || null),
!r.method.length &&
Q(r) &&
(U.value = `暂无可用的提现方式,请联系客服`));
} catch (t) {
G &&
e === W &&
(U.value = t instanceof Error ? t.message : `加载提现设置失败`);
} finally {
G && e === W && (V.value = !1);
}
}
async function Oe() {
if (!G || !x.value || H.value || V.value || !Q(B.value)) return;
let e = B.value;
if (!e) return;
if (((U.value = ``), !J.value)) {
U.value = `请选择有效的提现方式`;
return;
}
let t = T(K.amount);
if (t === null || t <= 0) {
U.value = `请输入大于 0 且最多两位小数的提现金额`;
return;
}
let n = T(e.min || 0),
r = T(e.max || 0);
if (n === null || r === null) {
U.value = `提现金额限制异常,请重新加载提现设置`;
return;
}
if (t < n) {
U.value = `提现金额不能低于 ¥${e.min}`;
return;
}
if (r > 0 && t > r) {
U.value = `提现金额不能高于 ¥${e.max}`;
return;
}
let i = T(I.source ? I.available : R.overview?.credit);
if (i === null) {
U.value = `可提现金额暂不可用,请刷新页面后重试`;
return;
}
if (t > i) {
U.value = I.source
? `提现金额不能超过可提现奖励`
: `提现金额不能超过可用余额`;
return;
}
if (
Y.value &&
!(X.value ? K.card_number.trim() : K.account.trim())
) {
U.value = X.value ? `请填写银行卡号` : `请填写收款账号`;
return;
}
if (q.value > t) {
U.value = `提现金额不能低于手续费`;
return;
}
let a = W,
o = I.source;
H.value = !0;
try {
let n = {
method_id: K.method_id,
amount: t / 100,
name: Y.value ? K.name.trim() : ``,
account: Y.value && !X.value ? K.account.trim() : ``,
card_number: Y.value && X.value ? K.card_number.trim() : ``,
notes: K.notes.trim(),
};
(o && ((n.source = o), (n.fee = Number(e.percent))),
await L.post(o ? `/recommend/withdraw` : `/withdraw`, n),
G &&
o === I.source &&
(a === W && (x.value = !1), C(`success`)));
} catch (e) {
G &&
a === W &&
(U.value = e instanceof Error ? e.message : `提交失败`);
} finally {
G && (H.value = !1);
}
}
return (
watch(
[x, () => I.source],
([e]) => {
(W++,
(B.value = null),
(V.value = !1),
(U.value = ``),
De(),
e && $());
},
{
immediate: !0,
flush: `sync`,
},
),
onBeforeUnmount(() => {
((G = !1), W++);
}),
(t, n) => {
let r = skeleton,
i = message,
a = button,
s = select,
u = inputnumber,
d = inputtext,
_ = textarea,
b = dialog;
return (
openBlock(),
createBlock(
b,
{
visible: x.value,
"onUpdate:visible": (n[7] ||= (e) => (x.value = e)),
header: I.title || `提现`,
modal: ``,
draggable: !1,
closable: !unref(H),
"close-on-escape": !unref(H),
style: {
width: `min(720px, calc(100vw - 28px))`,
},
},
{
footer: withCtx(() => [
createVNode(
a,
{
label: `取消`,
icon: `pi pi-times`,
severity: `secondary`,
outlined: ``,
disabled: unref(H),
onClick: (n[6] ||= (e) => (x.value = !1)),
},
null,
8,
[`disabled`],
),
createVNode(
a,
{
label: `确认`,
icon: `pi pi-check`,
loading: unref(H),
disabled:
unref(V) ||
unref(H) ||
!Q(unref(B)) ||
!unref(B)?.method.length,
onClick: Oe,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
unref(V)
? (openBlock(),
createElementBlock(`div`, ce, [
createVNode(r, {
height: `180px`,
}),
]))
: !unref(B) && unref(U)
? (openBlock(),
createElementBlock(`div`, le, [
createVNode(
i,
{
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(U)),
1,
),
]),
_: 1,
},
),
createVNode(a, {
label: `重新加载提现设置`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
onClick: $,
}),
]))
: unref(B)
? (openBlock(),
createElementBlock(`div`, ue, [
Q(unref(B))
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
i,
{
key: 0,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
...(n[8] ||= [
createTextVNode(
` 提现功能当前已关闭,如有需要请联系客服。 `,
-1,
),
]),
]),
_: 1,
},
)),
createElementVNode(`section`, de, [
(n[10] ||= createElementVNode(
`div`,
{
class: `notice-title`,
},
[
createElementVNode(`i`, {
class: `pi pi-info-circle`,
}),
createTextVNode(` 提现说明`),
],
-1,
)),
createElementVNode(`ul`, null, [
I.source
? (openBlock(),
createElementBlock(
`li`,
fe,
`提现申请需审核;审核通过后,提现到余额将计入账户余额,其他方式由管理员安排汇款。`,
))
: unref(B).process === `artificial`
? (openBlock(),
createElementBlock(
`li`,
pe,
` 提现申请经人工审核通过后按所选方式处理,处理进度可在提现记录查看。 `,
))
: (openBlock(),
createElementBlock(
`li`,
me,
`提现申请按所选方式处理,处理进度可在提现记录查看。`,
)),
createElementVNode(
`li`,
null,
` 手续费:` +
toDisplayString(
unref(B).withdraw_fee_type === `fixed`
? `每笔 ¥${unref(B).withdraw_fee}`
: `按 ${unref(B).percent}% 收取,最低 ¥${unref(B).percent_min}`,
) +
`。 `,
1,
),
createElementVNode(`li`, null, [
createTextVNode(
` 起提 ¥` +
toDisplayString(unref(B).min),
1,
),
unref(Z)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`,单笔上限 ¥` +
toDisplayString(unref(B).max),
1,
),
],
64,
))
: createCommentVNode(``, !0),
Number(unref(B).cycle_limit) > 0
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createTextVNode(
` ,每` +
toDisplayString(
we[unref(B).cycle] ||
unref(B).cycle,
) +
`最多 ` +
toDisplayString(
unref(B).cycle_limit,
) +
` 次`,
1,
),
],
64,
))
: createCommentVNode(``, !0),
(n[9] ||= createTextVNode(`。 `, -1)),
]),
I.source
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`li`,
he,
`已开票的充值需先申请发票作废或冲红,方可提现。`,
)),
]),
]),
createElementVNode(`div`, ge, [
createElementVNode(
`span`,
{
id: `${unref(z)}-method-label`,
class: `field-label`,
},
`提现方式`,
8,
_e,
),
createVNode(
s,
{
"input-id": `${unref(z)}-method`,
"aria-labelledby": `${unref(z)}-method-label`,
modelValue: unref(K).method_id,
"onUpdate:modelValue": (n[0] ||= (e) =>
(unref(K).method_id = e)),
options: unref(B).method,
optionLabel: `name`,
optionValue: `id`,
placeholder: `请选择提现方式`,
disabled: unref(H) || !Q(unref(B)),
fluid: ``,
},
null,
8,
[
`input-id`,
`aria-labelledby`,
`modelValue`,
`options`,
`disabled`,
],
),
]),
createElementVNode(`div`, ve, [
createElementVNode(
`label`,
{
for: `${unref(z)}-amount`,
},
`提现金额`,
8,
D,
),
createVNode(
u,
{
"input-id": `${unref(z)}-amount`,
modelValue: unref(K).amount,
"onUpdate:modelValue": (n[1] ||= (e) =>
(unref(K).amount = e)),
mode: `currency`,
currency: `CNY`,
locale: `zh-CN`,
min: Number(unref(B).min),
max: unref(Z),
disabled: unref(H) || !Q(unref(B)),
minFractionDigits: 2,
maxFractionDigits: 2,
fluid: ``,
},
null,
8,
[
`input-id`,
`modelValue`,
`min`,
`max`,
`disabled`,
],
),
I.source
? (openBlock(),
createElementBlock(
`span`,
O,
`可提现奖励 ¥` +
toDisplayString(
Number(I.available ?? 0).toFixed(2),
),
1,
))
: (openBlock(),
createElementBlock(
`span`,
k,
`可用余额 ¥` +
toDisplayString(
unref(R).overview?.credit ?? `0.00`,
),
1,
)),
]),
unref(Y)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(`div`, A, [
createElementVNode(
`label`,
{
for: `${unref(z)}-name`,
},
`收款人姓名`,
8,
j,
),
createVNode(
d,
{
id: `${unref(z)}-name`,
modelValue: unref(K).name,
"onUpdate:modelValue": (n[2] ||= (
e,
) => (unref(K).name = e)),
placeholder: `与账号实名一致`,
autocomplete: `name`,
disabled:
unref(H) || !Q(unref(B)),
maxlength: 20,
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
]),
createElementVNode(`div`, M, [
unref(X)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(
`label`,
{
for: `${unref(z)}-card-number`,
},
`银行卡号`,
8,
N,
),
createVNode(
d,
{
id: `${unref(z)}-card-number`,
modelValue:
unref(K).card_number,
"onUpdate:modelValue":
(n[3] ||= (e) =>
(unref(
K,
).card_number = e)),
placeholder: `请输入银行卡号`,
disabled:
unref(H) ||
!Q(unref(B)),
maxlength: 100,
fluid: ``,
},
null,
8,
[
`id`,
`modelValue`,
`disabled`,
],
),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`label`,
{
for: `${unref(z)}-account`,
},
`收款账号`,
8,
P,
),
createVNode(
d,
{
id: `${unref(z)}-account`,
modelValue:
unref(K).account,
"onUpdate:modelValue":
(n[4] ||= (e) =>
(unref(K).account =
e)),
placeholder: `请输入收款账号`,
disabled:
unref(H) ||
!Q(unref(B)),
maxlength: 100,
fluid: ``,
},
null,
8,
[
`id`,
`modelValue`,
`disabled`,
],
),
],
64,
)),
]),
],
64,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, F, [
createElementVNode(
`label`,
{
for: `${unref(z)}-notes`,
},
`备注`,
8,
ye,
),
createVNode(
_,
{
id: `${unref(z)}-notes`,
modelValue: unref(K).notes,
"onUpdate:modelValue": (n[5] ||= (e) =>
(unref(K).notes = e)),
rows: `2`,
placeholder: `选填`,
disabled: unref(H) || !Q(unref(B)),
maxlength: 1e3,
autoResize: ``,
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
]),
createElementVNode(`div`, be, [
createElementVNode(`div`, xe, [
(n[11] ||= createElementVNode(
`span`,
null,
`提现金额`,
-1,
)),
createElementVNode(
`b`,
null,
`¥` +
toDisplayString(
Number(unref(K).amount ?? 0).toFixed(
2,
),
),
1,
),
]),
createElementVNode(`div`, Se, [
(n[12] ||= createElementVNode(
`span`,
null,
`手续费`,
-1,
)),
createElementVNode(
`b`,
null,
`-¥` +
toDisplayString(unref(Te).toFixed(2)),
1,
),
]),
createElementVNode(`div`, Ce, [
(n[13] ||= createElementVNode(
`span`,
null,
`预计到账`,
-1,
)),
createElementVNode(
`b`,
null,
`¥` +
toDisplayString(unref(Ee).toFixed(2)),
1,
),
]),
]),
unref(U)
? (openBlock(),
createBlock(
i,
{
key: 2,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(U)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `header`, `closable`, `close-on-escape`],
)
);
}
);
},
}),
[[`__scopeId`, `data-v-e4be3b52`]],
),
{
__name: `WithdrawDialog`,
},
);
export { w as n };
export default I;
</script>
@@ -0,0 +1,449 @@
<script>
import "~/assets/styles/ProductGroupLabel.B1kWpFA-.css";
import "~/assets/styles/CloudProductPicker.CAm9rmUl.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { createBlock } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { n as product_name_n } from "~/lib/product-name.js";
import paginator from "primevue/paginator";
import skeleton from "primevue/skeleton";
import ProductGroupLabel from "~/components/ProductGroupLabel.vue";
var C = {
class: `cloud-product-picker`,
},
w = [`aria-labelledby`],
T = [`id`],
E = {
class: `zone-options`,
role: `group`,
"aria-label": `产品专区`,
},
D = [`aria-pressed`, `disabled`, `onClick`],
O = {
key: 2,
class: `catalog-empty`,
},
k = [`aria-labelledby`],
A = [`id`],
j = {
key: 2,
class: `catalog-empty`,
},
M = {
key: 3,
class: `product-options`,
role: `group`,
"aria-label": `选择云服务器产品`,
},
N = [`aria-pressed`, `disabled`, `onClick`],
P = {
key: 0,
},
F = {
key: 1,
},
I = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `CloudProductPicker`,
props: {
groups: {},
activeGroup: {},
products: {},
selectedId: {},
loading: {
type: Boolean,
},
productLoading: {
type: Boolean,
},
error: {},
errorSource: {},
total: {},
page: {},
disabled: {
type: Boolean,
},
soldOut: {
type: Function,
},
stockLabel: {
type: Function,
},
},
emits: [
`choose-group`,
`choose-product`,
`retry-groups`,
`retry-products`,
`paginate`,
],
setup(f, { emit: _ }) {
let I = _,
L = useId();
return (n, _) => {
let R = skeleton,
z = button,
B = message,
V = ProductGroupLabel,
H = NuxtLink,
U = paginator;
return (
openBlock(),
createElementBlock(`div`, C, [
createElementVNode(
`section`,
{
class: `selection-section`,
"aria-labelledby": `${unref(L)}-lines-title`,
},
[
createElementVNode(
`h3`,
{
id: `${unref(L)}-lines-title`,
},
`选择线路`,
8,
T,
),
f.loading
? (openBlock(),
createBlock(R, {
key: 0,
height: `110px`,
}))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
f.error && f.errorSource === `groups`
? (openBlock(),
createBlock(
B,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(f.error),
1,
),
createVNode(
z,
{
label: `重新加载线路`,
severity: `secondary`,
text: ``,
disabled: f.disabled,
onClick: (_[0] ||= (e) =>
I(`retry-groups`)),
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: f.groups.length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
(_[3] ||= createElementVNode(
`div`,
{
class: `selection-label`,
},
`产品专区`,
-1,
)),
createElementVNode(`div`, E, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
f.groups,
(e) => (
openBlock(),
createElementBlock(
`button`,
{
key: e.id,
type: `button`,
class: normalizeClass([
`zone-option`,
{
active:
f.activeGroup === e.id,
},
]),
"aria-pressed":
f.activeGroup === e.id,
disabled: f.disabled,
onClick: (t) =>
I(`choose-group`, e.id),
},
[
createVNode(
V,
{
name: e.name,
},
null,
8,
[`name`],
),
],
10,
D,
)
),
),
128,
)),
]),
],
64,
))
: (openBlock(),
createElementBlock(`div`, O, [
(_[5] ||= createElementVNode(
`i`,
{
class: `pi pi-box`,
"aria-hidden": `true`,
},
null,
-1,
)),
(_[6] ||= createElementVNode(
`p`,
null,
`暂未提供可选的云服务器线路`,
-1,
)),
createVNode(
H,
{
to: `/products`,
},
{
default: withCtx(() => [
...(_[4] ||= [
createTextVNode(`浏览产品`, -1),
]),
]),
_: 1,
},
),
])),
],
64,
)),
],
8,
w,
),
f.groups.length
? (openBlock(),
createElementBlock(
`section`,
{
key: 0,
class: `selection-section`,
"aria-labelledby": `${unref(L)}-products-title`,
},
[
createElementVNode(
`h3`,
{
id: `${unref(L)}-products-title`,
class: `products-title`,
},
`产品`,
8,
A,
),
f.productLoading && !f.products.length
? (openBlock(),
createBlock(R, {
key: 0,
height: `110px`,
}))
: f.error && f.errorSource === `products`
? (openBlock(),
createBlock(
B,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(f.error),
1,
),
createVNode(
z,
{
label: `重新加载商品`,
severity: `secondary`,
text: ``,
disabled: f.disabled,
onClick: (_[1] ||= (e) =>
I(`retry-products`)),
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: !f.products.length && !f.error
? (openBlock(),
createElementBlock(`div`, j, [
...(_[7] ||= [
createElementVNode(
`p`,
null,
`该专区暂无可售产品`,
-1,
),
]),
]))
: (openBlock(),
createElementBlock(`div`, M, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
f.products,
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.id,
type: `button`,
class: normalizeClass([
`product-option`,
{
active: f.selectedId === t.id,
},
]),
"aria-pressed":
f.selectedId === t.id,
disabled:
f.disabled || f.soldOut(t),
onClick: (e) =>
I(`choose-product`, t.id),
},
[
createElementVNode(
`strong`,
null,
toDisplayString(
unref(product_name_n)(t.name),
),
1,
),
f.soldOut(t)
? (openBlock(),
createElementBlock(
`span`,
P,
toDisplayString(
f.stockLabel(t),
),
1,
))
: (openBlock(),
createElementBlock(
`span`,
F,
toDisplayString(
f.selectedId === t.id
? `当前配置`
: `查看可选配置`,
),
1,
)),
],
10,
N,
)
),
),
128,
)),
])),
f.total > 24
? (openBlock(),
createBlock(
U,
{
key: 4,
first: (f.page - 1) * 24,
rows: 24,
totalRecords: f.total,
disabled: f.disabled,
onPage: (_[2] ||= (e) => I(`paginate`, e)),
},
null,
8,
[`first`, `totalRecords`, `disabled`],
))
: createCommentVNode(``, !0),
],
8,
k,
))
: createCommentVNode(``, !0),
])
);
};
},
}),
[[`__scopeId`, `data-v-a438862d`]],
),
{
__name: `CloudProductPicker`,
},
);
export {};
export default I;
</script>
File diff suppressed because it is too large. Load diff
+305
View File
@@ -0,0 +1,305 @@
<script>
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
import { nextTick } from "vue";
import { normalizeClass } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { withDirectives } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputnumber from "primevue/inputnumber";
import tooltip from "primevue/tooltip";
var p = {
class: `bandwidth-field`,
},
m = {
class: `bandwidth-label`,
},
h = [`aria-label`],
g = [`aria-valuetext`, `disabled`, `value`, `min`, `max`],
_ = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ConfigBandwidth`,
props: {
modelValue: {},
options: {},
disabled: {
type: Boolean,
},
},
emits: [`update:modelValue`, `change`],
setup(s, { emit: u }) {
let _ = s,
v = u,
y = computed(() =>
_.options
.map((e) => {
let t = e.type === `step` || e.type === `total`,
n = Number(t ? (e.min_value ?? e.value) : e.value),
r = Number(
t ? (e.max_value ?? e.min_value ?? e.value) : e.value,
),
i = Number(e.step),
a = Number.isFinite(i) && i > 0 ? i : 1;
return {
min: n,
max: Number(
(n + Math.floor((r - n) / a + 1e-7) * a).toFixed(8),
),
step: a,
};
})
.filter(
(e) =>
Number.isFinite(e.min) &&
Number.isFinite(e.max) &&
e.max >= e.min,
),
),
b = computed(() =>
y.value.length ? Math.min(...y.value.map((e) => e.min)) : 0,
),
x = computed(() =>
y.value.length ? Math.max(...y.value.map((e) => e.max)) : 0,
),
S = computed(() => b.value === x.value),
C = computed(() =>
_.modelValue == null ||
_.modelValue === `` ||
!Number.isFinite(Number(_.modelValue))
? null
: Number(_.modelValue),
),
w = computed(() =>
y.value.length
? S.value
? `当前线路带宽固定为 ${b.value} Mbps。`
: `设置服务器的带宽上限,可输入数值或拖动滑块。可选范围 ${b.value}–${x.value} Mbps,数值会自动匹配可用档位。`
: `当前线路暂无可用带宽。`,
);
function T(e) {
let t = b.value,
n = 1 / 0;
for (let r of y.value) {
let i = Number(
Math.min(
r.max,
Math.max(
r.min,
r.min + Math.round((e - r.min) / r.step) * r.step,
),
).toFixed(8),
),
a = Math.abs(i - e);
a < n && ((t = i), (n = a));
}
return t;
}
let E = !1;
function D(e, t = !0) {
if (
_.disabled ||
S.value ||
e === null ||
!Number.isFinite(e) ||
!y.value.length
)
return;
let n = T(e);
C.value !== n &&
(v(`update:modelValue`, n), t ? v(`change`) : (E = !0));
}
function O(e) {
let t = e.target;
_.disabled ||
S.value ||
(D(Number(t.value), !1), (t.value = String(T(Number(t.value)))));
}
function k() {
(E && !_.disabled && !S.value && v(`change`), (E = !1));
}
function A(e) {
if (_.disabled || S.value) return;
if (e.key === `Home` || e.key === `End`) {
(e.preventDefault(), D(e.key === `Home` ? b.value : x.value));
return;
}
let t = [`ArrowRight`, `ArrowUp`, `PageUp`].includes(e.key)
? 1
: [`ArrowLeft`, `ArrowDown`, `PageDown`].includes(e.key)
? -1
: 0;
if (!t) return;
e.preventDefault();
let n = C.value ?? b.value,
r = y.value.flatMap((e) => {
let r =
t > 0
? Math.max(
e.min,
e.min +
(Math.floor((n - e.min) / e.step + 1e-7) + 1) *
e.step,
)
: Math.min(
e.max,
e.min +
(Math.ceil((n - e.min) / e.step - 1e-7) - 1) * e.step,
);
return r >= e.min && r <= e.max ? [r] : [];
});
r.length && D(t > 0 ? Math.min(...r) : Math.max(...r));
}
async function j(t) {
(await Promise.resolve(), await nextTick());
let n = t.originalEvent.target;
((n.value = C.value === null ? `` : String(C.value)),
C.value === null
? n.removeAttribute(`aria-valuenow`)
: n.setAttribute(`aria-valuenow`, String(C.value)));
}
function M(e) {
if (e.key === `ArrowUp` || e.key === `ArrowDown`)
return (
e.stopPropagation(),
A(e),
j({
originalEvent: e,
})
);
if (e.key === `Enter`)
return new Promise((t) => {
setTimeout(() => {
j({
originalEvent: e,
}).then(t);
}, 0);
});
}
return (e, n) => {
let u = inputnumber,
_ = tooltip;
return (
openBlock(),
createElementBlock(`div`, p, [
createElementVNode(`div`, m, [
(n[1] ||= createElementVNode(`span`, null, `带宽上限`, -1)),
withDirectives(
(openBlock(),
createElementBlock(
`button`,
{
class: `bandwidth-help`,
type: `button`,
"aria-label": unref(w),
},
[
...(n[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-question-circle`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
],
8,
h,
)),
[
[
_,
{
value: unref(w),
autoHide: !1,
},
void 0,
{
top: !0,
},
],
],
),
]),
createElementVNode(
`div`,
{
class: normalizeClass([
`bandwidth-capacity`,
{
"is-disabled": s.disabled,
},
]),
onKeydownCapture: M,
},
[
createVNode(
u,
{
"aria-label": `带宽上限`,
disabled: s.disabled || unref(S),
"model-value": unref(C),
min: unref(b),
max: unref(x),
"use-grouping": !1,
"onUpdate:modelValue": D,
onBlur: j,
},
null,
8,
[`disabled`, `model-value`, `min`, `max`],
),
(n[2] ||= createElementVNode(
`span`,
{
class: `bandwidth-unit`,
"aria-hidden": `true`,
},
`Mbps`,
-1,
)),
],
34,
),
createElementVNode(
`input`,
{
class: `bandwidth-slider`,
type: `range`,
"aria-label": `带宽上限滑块`,
"aria-valuetext": `${unref(C) ?? unref(b)} Mbps`,
disabled: s.disabled || unref(S),
value: unref(C) ?? unref(b),
min: unref(b),
max: unref(x),
step: `any`,
onInput: O,
onChange: k,
onKeydown: A,
},
null,
40,
g,
),
])
);
};
},
}),
[[`__scopeId`, `data-v-45a9c613`]],
),
{
__name: `ConfigBandwidth`,
},
);
export {};
export default _;
</script>
+657
View File
@@ -0,0 +1,657 @@
<script>
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { renderSlot } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useRoute } from "#app";
import { navigateTo } from "#app";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import button from "primevue/button";
import message from "primevue/message";
import PromoCodeField from "~/components/config/PromoCodeField.vue";
import { t as purchase_limit_state_t } from "~/lib/purchase-limit-state.js";
var O = {
class: `config-summary-wrap`,
},
k = {
class: `config-summary`,
},
ee = {
class: `buy-bar`,
},
te = [`aria-busy`],
ne = {
key: 0,
class: `price-value`,
},
A = {
key: 1,
class: `price-pending`,
},
j = {
key: 0,
class: `pi pi-spin pi-spinner`,
"aria-hidden": `true`,
},
M = {
key: 2,
class: `level-hint`,
},
N = {
key: 1,
class: `cart-confirmation`,
role: `status`,
},
P = {
class: `cart-confirmation-message`,
},
F = {
key: 2,
class: `quote-status`,
},
I = {
key: 3,
class: `quote-status`,
role: `status`,
},
L = {
class: `buy-actions`,
},
R = {
key: 6,
class: `quote-status`,
role: `status`,
},
z = [`href`],
B = {
class: `config-mobile-label`,
},
V = Object.assign(
defineComponent({
__name: `ConfigCheckout`,
props: {
productId: {},
quantity: {},
editPosition: {},
summary: {},
price: {},
quoteReady: {
type: Boolean,
},
priceLoading: {
type: Boolean,
},
canSubmit: {
type: Boolean,
},
activeAction: {
default: null,
},
disabled: {
type: Boolean,
default: !1,
},
promoCode: {
default: ``,
},
promoDiscount: {
default: 0,
},
levelDiscount: {
default: 0,
},
error: {
default: ``,
},
actionError: {
default: ``,
},
cartTip: {
default: ``,
},
showCart: {
type: Boolean,
default: !0,
},
showPromo: {
type: Boolean,
default: !0,
},
editing: {
type: Boolean,
default: !1,
},
loginRedirect: {},
},
emits: [`update:promoCode`, `recalc`, `retry`, `cart`, `buy`],
setup(g, { emit: V }) {
let H = g,
U = V,
W = `configuration-${useId()}`,
G = useAuth(),
K = useRoute(),
q = computed(() => H.disabled || H.activeAction !== null),
J = purchase_limit_state_t((e) =>
useApi().post(`/purchase_limit/check`, e, !1, {
timeoutMs: 15e3,
}),
),
Y = computed(() => H.productId !== void 0 && G.isLoggedIn),
X = computed(() => Y.value && (!J.checked.value || !J.allowed.value)),
Z;
function Q() {
if (!Y.value) {
J.reset();
return;
}
let e = {
product_id: Number(H.productId),
qty: H.quantity ?? 1,
};
return J.check(
H.editPosition === void 0
? {
mode: `single`,
...e,
}
: {
mode: `cart_update`,
...e,
position: H.editPosition,
},
);
}
(onMounted(() => {
Z = watch(
() => [
G.token,
G.isLoggedIn,
H.productId,
H.quantity,
H.editPosition,
],
Q,
{
immediate: !0,
flush: `sync`,
},
);
}),
onBeforeUnmount(() => {
(Z?.(), J.reset());
}));
function $(e) {
if (H.canSubmit && H.quoteReady && !H.priceLoading && !q.value) {
if (!G.isLoggedIn)
return navigateTo({
path: `/login`,
query: {
redirect: H.loginRedirect || K.fullPath,
},
});
X.value ||
(e === `cart` ? H.showCart && U(`cart`) : H.editing || U(`buy`));
}
}
return (n, r) => {
let i = PromoCodeField,
o = NuxtLink,
u = message,
y = button;
return (
openBlock(),
createElementBlock(`div`, O, [
(r[13] ||= createElementVNode(
`h2`,
{
class: `config-column-title`,
},
`所选配置`,
-1,
)),
createElementVNode(
`aside`,
{
id: W,
class: `panel config-checkout`,
"aria-label": `订单确认`,
},
[
(r[10] ||= createElementVNode(
`h3`,
{
class: `section-title`,
},
`配置详情`,
-1,
)),
createElementVNode(`dl`, k, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
g.summary,
(t, n) => (
openBlock(),
createElementBlock(
`div`,
{
key: `${t.label}-${n}`,
class: `config-summary-row`,
},
[
createElementVNode(
`dt`,
null,
toDisplayString(t.label),
1,
),
createElementVNode(
`dd`,
null,
toDisplayString(t.value),
1,
),
],
)
),
),
128,
)),
renderSlot(n.$slots, `summary`),
]),
n.$slots.default
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
(r[5] ||= createElementVNode(
`div`,
{
class: `checkout-divider`,
},
null,
-1,
)),
renderSlot(n.$slots, `default`),
],
64,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ee, [
createElementVNode(
`div`,
{
class: `price-area`,
"aria-live": `polite`,
"aria-busy": g.priceLoading,
},
[
(r[6] ||= createElementVNode(
`span`,
{
class: `price-label`,
},
`配置费用`,
-1,
)),
g.quoteReady
? (openBlock(),
createElementBlock(
`span`,
ne,
`¥ ` + toDisplayString(g.price),
1,
))
: (openBlock(),
createElementBlock(`span`, A, [
g.priceLoading
? (openBlock(), createElementBlock(`i`, j))
: createCommentVNode(``, !0),
createTextVNode(
` ` +
toDisplayString(
g.priceLoading ? `正在计算…` : `待确认`,
),
1,
),
])),
g.quoteReady && g.levelDiscount > 0
? (openBlock(),
createElementBlock(
`span`,
M,
`已享会员折扣 -¥` +
toDisplayString(g.levelDiscount.toFixed(2)),
1,
))
: createCommentVNode(``, !0),
],
8,
te,
),
g.showPromo
? (openBlock(),
createBlock(
i,
{
key: 0,
"model-value": g.promoCode,
discount: g.quoteReady ? g.promoDiscount : 0,
loading: g.priceLoading,
disabled: unref(q),
"onUpdate:modelValue": (r[0] ||= (e) =>
U(`update:promoCode`, e)),
onRecalc: (r[1] ||= (e) => U(`recalc`)),
},
null,
8,
[`model-value`, `discount`, `loading`, `disabled`],
))
: createCommentVNode(``, !0),
g.cartTip
? (openBlock(),
createElementBlock(`div`, N, [
createElementVNode(`span`, P, [
(r[7] ||= createElementVNode(
`i`,
{
class: `pi pi-check-circle`,
"aria-hidden": `true`,
},
null,
-1,
)),
createTextVNode(toDisplayString(g.cartTip), 1),
]),
createVNode(
o,
{
to: `/cart`,
class: `cart-confirmation-link`,
},
{
default: withCtx(() => [
...(r[8] ||= [
createTextVNode(`查看购物车`, -1),
createElementVNode(
`i`,
{
class: `pi pi-arrow-right`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]))
: createCommentVNode(``, !0),
renderSlot(n.$slots, `agreement`),
unref(G).isLoggedIn
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
F,
`登录后可加入购物车或购买,登录完成后返回当前产品页面。`,
)),
unref(J).pending.value
? (openBlock(),
createElementBlock(`p`, I, `正在检查购买限制…`))
: createCommentVNode(``, !0),
unref(J).message.value
? (openBlock(),
createBlock(
u,
{
key: 4,
severity: `warn`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(J).message.value),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(J).message.value
? (openBlock(),
createBlock(
y,
{
key: 5,
label: `重新检查购买限制`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
outlined: ``,
disabled: unref(q) || unref(J).pending.value,
onClick: Q,
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
createElementVNode(`div`, L, [
g.showCart
? (openBlock(),
createBlock(
y,
{
key: 0,
label: g.editing ? `保存配置` : `加入购物车`,
icon: g.editing
? `pi pi-check`
: `pi pi-shopping-cart`,
severity: `secondary`,
outlined: ``,
loading: g.activeAction === `cart`,
disabled:
!g.canSubmit ||
!g.quoteReady ||
g.priceLoading ||
unref(q) ||
unref(X),
onClick: (r[2] ||= (e) => $(`cart`)),
},
null,
8,
[`label`, `icon`, `loading`, `disabled`],
))
: createCommentVNode(``, !0),
g.editing && !unref(q)
? (openBlock(),
createBlock(
o,
{
key: 1,
to: `/cart`,
class: `cart-confirmation-link`,
},
{
default: withCtx(() => [
...(r[9] ||= [createTextVNode(`取消`, -1)]),
]),
_: 1,
},
))
: g.editing
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
y,
{
key: 2,
label: `立即购买`,
loading: g.activeAction === `buy`,
disabled:
!g.canSubmit ||
!g.quoteReady ||
g.priceLoading ||
unref(q) ||
unref(X),
onClick: (r[3] ||= (e) => $(`buy`)),
},
null,
8,
[`loading`, `disabled`],
)),
]),
!g.quoteReady && !g.priceLoading
? (openBlock(),
createElementBlock(`div`, R, [
createElementVNode(
`p`,
null,
toDisplayString(
g.error
? `报价未能完成,请重试后再提交。`
: `请选择完整配置并计算报价后继续。`,
),
1,
),
createVNode(
y,
{
label: g.error ? `重新获取报价` : `计算报价`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
outlined: ``,
disabled: unref(q),
onClick: (r[4] ||= (e) => U(`retry`)),
},
null,
8,
[`label`, `disabled`],
),
]))
: createCommentVNode(``, !0),
g.error
? (openBlock(),
createBlock(
u,
{
key: 7,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(g.error), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
g.actionError
? (openBlock(),
createBlock(
u,
{
key: 8,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(g.actionError),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
],
),
createElementVNode(
`a`,
{
href: `#${W}`,
class: `config-mobile-total`,
},
[
createElementVNode(`span`, null, [
(r[11] ||= createTextVNode(`配置费用`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
g.quoteReady
? `¥ ${g.price}`
: g.priceLoading
? `正在计算…`
: `待确认`,
),
1,
),
]),
createElementVNode(`span`, B, [
createTextVNode(
toDisplayString(
g.editing ? `查看配置与保存` : `查看配置与购买`,
),
1,
),
(r[12] ||= createElementVNode(
`i`,
{
class: `pi pi-angle-up`,
"aria-hidden": `true`,
},
null,
-1,
)),
]),
],
8,
z,
),
])
);
};
},
}),
{
__name: `ConfigCheckout`,
},
);
export {};
export default V;
</script>
+140
View File
@@ -0,0 +1,140 @@
<script>
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { createBlock } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import OsIcon from "~/components/OsIcon.vue";
var d = [`aria-label`],
f = [`aria-pressed`, `disabled`, `onClick`],
p = {
key: 1,
},
m = Object.assign(
defineComponent({
__name: `ConfigChoiceGrid`,
props: {
modelValue: {},
options: {},
disabled: {
type: Boolean,
},
compact: {
type: Boolean,
},
images: {
type: Boolean,
},
label: {},
},
emits: [`update:modelValue`, `change`],
setup(c, { emit: m }) {
let h = c,
g = m;
function _(e) {
h.disabled ||
h.modelValue === e ||
(g(`update:modelValue`, e), g(`change`));
}
return (m, h) => {
let g = OsIcon;
return (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`config-choices`,
{
compact: c.compact && !c.images,
"image-groups": c.images,
},
]),
role: `group`,
"aria-label": c.label,
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
c.options,
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.value,
type: `button`,
class: normalizeClass([
c.images ? `image-group` : `config-choice`,
{
active: c.modelValue === t.value,
},
]),
"aria-pressed": c.modelValue === t.value,
disabled: c.disabled,
onClick: (e) => _(t.value),
},
[
c.images
? (openBlock(),
createBlock(
g,
{
key: 0,
name: t.label,
url: t.iconUrl,
icon: t.icon,
size: 36,
},
null,
8,
[`name`, `url`, `icon`],
))
: createCommentVNode(``, !0),
createElementVNode(
`span`,
null,
toDisplayString(t.label),
1,
),
t.description
? (openBlock(),
createElementBlock(
`small`,
p,
toDisplayString(t.description),
1,
))
: createCommentVNode(``, !0),
],
10,
f,
)
),
),
128,
)),
],
10,
d,
)
);
};
},
}),
{
__name: `ConfigChoiceGrid`,
},
);
export {};
export default m;
</script>
+66
View File
@@ -0,0 +1,66 @@
<script>
import "~/assets/styles/ConfigDiskAdd.C92e9ZuF.css";
import { toDisplayString } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var s = [`disabled`],
c = {
key: 0,
},
l = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ConfigDiskAdd`,
props: {
disabled: {
type: Boolean,
},
hint: {},
},
emits: [`add`],
setup(i) {
return (o, l) => (
openBlock(),
createElementBlock(
`button`,
{
class: `storage-add`,
type: `button`,
disabled: i.disabled,
onClick: (l[0] ||= (e) => o.$emit(`add`)),
},
[
(l[1] ||= createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
)),
(l[2] ||= createElementVNode(`span`, null, `添加数据盘`, -1)),
i.hint
? (openBlock(),
createElementBlock(`small`, c, toDisplayString(i.hint), 1))
: createCommentVNode(``, !0),
],
8,
s,
)
);
},
}),
[[`__scopeId`, `data-v-68361f8e`]],
),
{
__name: `ConfigDiskAdd`,
},
);
export {};
export default l;
</script>
+346
View File
@@ -0,0 +1,346 @@
<script>
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
import { nextTick } from "vue";
import { toDisplayString } from "vue";
import { renderSlot } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputnumber from "primevue/inputnumber";
var m = {
class: `storage-field`,
},
h = {
key: 0,
class: `storage-label`,
},
g = [`aria-label`],
_ = {
class: `storage-card-header`,
},
v = [`disabled`, `aria-label`],
y = {
class: `storage-unit`,
"aria-hidden": `true`,
},
b = [`aria-label`, `aria-valuetext`, `disabled`, `value`, `min`, `max`],
x = {
key: 0,
class: `storage-description`,
},
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ConfigDiskCard`,
props: {
label: {},
hideLabel: {
type: Boolean,
},
title: {},
modelValue: {},
options: {
default: () => [],
},
unit: {
default: `GB`,
},
description: {},
disabled: {
type: Boolean,
},
removable: {
type: Boolean,
},
},
emits: [`update:modelValue`, `change`, `remove`],
setup(l, { emit: f }) {
let S = l,
C = f,
w = computed(() =>
S.options
.map((e) => {
let t = e.type === `step` || e.type === `total`,
n = Number(t ? (e.min_value ?? e.value) : e.value),
r = Number(
t ? (e.max_value ?? e.min_value ?? e.value) : e.value,
),
i = Number(e.step) > 0 ? Number(e.step) : 1;
return {
min: n,
max: n + Math.floor((r - n) / i + 1e-7) * i,
step: i,
};
})
.filter(
(e) =>
Number.isFinite(e.min) &&
Number.isFinite(e.max) &&
e.max >= e.min,
),
),
T = computed(() => Math.min(...w.value.map((e) => e.min))),
E = computed(() => Math.max(...w.value.map((e) => e.max))),
D = computed(() => T.value === E.value),
O = computed(() => Number(S.modelValue) || 0),
k = computed(() =>
D.value
? `容量 ${T.value} ${S.unit}`
: `容量 ${T.value}–${E.value} ${S.unit}`,
);
function A(e) {
let t = T.value,
n = 1 / 0;
for (let r of w.value) {
let i = Number(
Math.min(
r.max,
Math.max(
r.min,
r.min + Math.round((e - r.min) / r.step) * r.step,
),
).toFixed(8),
),
a = Math.abs(i - e);
a < n && ((t = i), (n = a));
}
return t;
}
function j(e, t = !0) {
if (
S.disabled ||
D.value ||
e === null ||
!Number.isFinite(e) ||
!w.value.length
)
return;
let n = A(e);
Number(S.modelValue) !== n &&
(C(`update:modelValue`, n), t && C(`change`));
}
function M(e) {
let t = e.target,
n = Number(t.value);
(j(n, !1), (t.value = String(A(n))));
}
function N() {
!S.disabled && !D.value && C(`change`);
}
function P(e) {
let t = [`ArrowRight`, `ArrowUp`].includes(e.key)
? 1
: [`ArrowLeft`, `ArrowDown`].includes(e.key)
? -1
: 0;
if (!t || S.disabled || D.value) return;
e.preventDefault();
let n = O.value,
r = w.value.flatMap((e) => {
let r =
t > 0
? Math.max(
e.min,
e.min +
(Math.floor((n - e.min) / e.step + 1e-7) + 1) *
e.step,
)
: Math.min(
e.max,
e.min +
(Math.ceil((n - e.min) / e.step - 1e-7) - 1) * e.step,
);
return r >= e.min && r <= e.max ? [r] : [];
});
r.length && j(t > 0 ? Math.min(...r) : Math.max(...r));
}
function F() {
!S.disabled && S.removable && C(`remove`);
}
async function I(t) {
(await Promise.resolve(), await nextTick());
let n = t.originalEvent.target;
((n.value = String(O.value)),
n.setAttribute(`aria-valuenow`, String(O.value)));
}
function L(e) {
e.key === `ArrowUp` || e.key === `ArrowDown`
? (e.stopPropagation(),
P(e),
I({
originalEvent: e,
}))
: e.key === `Enter` &&
I({
originalEvent: e,
});
}
return (e, i) => {
let f = inputnumber;
return (
openBlock(),
createElementBlock(`div`, m, [
l.hideLabel
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, h, toDisplayString(l.label), 1)),
createElementVNode(
`div`,
{
class: `storage-card`,
role: `group`,
"aria-label": l.label,
},
[
createElementVNode(`div`, _, [
createElementVNode(
`strong`,
null,
toDisplayString(l.title || `标准存储`),
1,
),
l.removable
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
class: `storage-remove`,
type: `button`,
disabled: l.disabled,
"aria-label": `删除${l.label}`,
onClick: F,
},
[
...(i[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-trash`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
],
8,
v,
))
: createCommentVNode(``, !0),
]),
renderSlot(e.$slots, `type`, {}, void 0, !0),
renderSlot(
e.$slots,
`default`,
{},
() => [
unref(w).length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(
`div`,
{
class: `storage-capacity`,
onKeydownCapture: L,
},
[
createVNode(
f,
{
"aria-label": l.label,
disabled: l.disabled || unref(D),
"model-value": unref(O),
min: unref(T),
max: unref(E),
"use-grouping": !1,
"onUpdate:modelValue": j,
onBlur: I,
},
null,
8,
[
`aria-label`,
`disabled`,
`model-value`,
`min`,
`max`,
],
),
createElementVNode(
`span`,
y,
toDisplayString(l.unit),
1,
),
],
32,
),
createElementVNode(
`input`,
{
class: `storage-slider`,
type: `range`,
"aria-label": `${l.label}容量滑块`,
"aria-valuetext": `${unref(O)} ${l.unit}`,
disabled: l.disabled || unref(D),
value: unref(O),
min: unref(T),
max: unref(E),
step: `any`,
onInput: M,
onChange: N,
onKeydown: P,
},
null,
40,
b,
),
],
64,
))
: createCommentVNode(``, !0),
],
!0,
),
l.description || unref(w).length
? (openBlock(),
createElementBlock(
`p`,
x,
toDisplayString(l.description || unref(k)),
1,
))
: createCommentVNode(``, !0),
renderSlot(e.$slots, `extra`, {}, void 0, !0),
],
8,
g,
),
renderSlot(e.$slots, `hint`, {}, void 0, !0),
])
);
};
},
}),
[[`__scopeId`, `data-v-83c644c5`]],
),
{
__name: `ConfigDiskCard`,
},
);
export {};
export default S;
</script>
@@ -0,0 +1,197 @@
<script>
import { renderList } from "vue";
import { renderSlot } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import skeleton from "primevue/skeleton";
var l = [`aria-busy`, `aria-label`],
u = {
class: `config-layout`,
},
d = {
class: `config-options`,
},
f = {
class: `section-title`,
},
p = {
class: `config-loading-fields`,
},
m = {
class: `config-choices`,
},
h = {
class: `config-summary-wrap`,
"aria-hidden": `true`,
},
g = {
class: `panel config-checkout config-loading-summary`,
},
_ = Object.assign(
defineComponent({
__name: `ConfigLoadingShell`,
props: {
busy: {
type: Boolean,
default: !0,
},
},
setup(a) {
return (_, v) => {
let y = skeleton;
return (
openBlock(),
createElementBlock(
`div`,
{
class: `config-page config-loading-shell`,
"aria-busy": a.busy,
"aria-label": a.busy ? `正在加载产品配置` : `产品配置`,
},
[
createElementVNode(`div`, u, [
createElementVNode(`div`, d, [
renderSlot(_.$slots, `catalog`),
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(3, (t) =>
createElementVNode(
`section`,
{
key: t,
class: `panel`,
"aria-hidden": `true`,
},
[
createElementVNode(`h2`, f, [
createVNode(y, {
width: `6rem`,
height: `1.429rem`,
}),
]),
createElementVNode(`div`, p, [
createVNode(y, {
width: `4rem`,
height: `1.429rem`,
}),
createElementVNode(`div`, m, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(4, (e) =>
createVNode(y, {
key: e,
height: `60px`,
}),
),
64,
)),
]),
createVNode(y, {
width: `4rem`,
height: `1.429rem`,
}),
createVNode(y, {
width: `70%`,
height: `36px`,
}),
]),
],
),
),
64,
)),
]),
createElementVNode(`div`, h, [
(v[3] ||= createElementVNode(
`h2`,
{
class: `config-column-title`,
},
`所选配置`,
-1,
)),
createElementVNode(`aside`, g, [
(v[0] ||= createElementVNode(
`h3`,
{
class: `section-title`,
},
`配置详情`,
-1,
)),
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(6, (e) =>
createVNode(y, {
key: e,
height: `1.429rem`,
}),
),
64,
)),
(v[1] ||= createElementVNode(
`div`,
{
class: `checkout-divider`,
},
null,
-1,
)),
createVNode(y, {
height: `36px`,
}),
createVNode(y, {
height: `36px`,
}),
(v[2] ||= createElementVNode(
`div`,
{
class: `checkout-divider`,
},
null,
-1,
)),
createVNode(y, {
width: `5rem`,
height: `1.714rem`,
}),
createVNode(y, {
height: `2.275rem`,
}),
createVNode(y, {
height: `100px`,
}),
createVNode(y, {
height: `36px`,
}),
createVNode(y, {
height: `36px`,
}),
]),
]),
]),
],
8,
l,
)
);
};
},
}),
{
__name: `ConfigLoadingShell`,
},
);
export {};
export default _;
</script>
@@ -0,0 +1,233 @@
<script>
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import "~/assets/styles/ConfigResourceOption.Dj4VopnA.css";
import { toDisplayString } from "vue";
import { createBlock } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import ConfigChoiceGrid from "~/components/config/ConfigChoiceGrid.vue";
var h = {
key: 1,
class: `resource-range`,
},
g = {
key: 1,
class: `hint`,
},
_ = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ConfigResourceOption`,
props: {
modelValue: {},
options: {},
label: {},
unit: {},
disabled: {
type: Boolean,
},
},
emits: [`update:modelValue`, `change`],
setup(c, { emit: d }) {
let _ = c,
v = d,
y = computed(() =>
_.options
.map((e, t) => {
let n = e.type === `step` || e.type === `total`,
r = Number(n ? (e.min_value ?? e.value) : e.value),
i = Number(
n ? (e.max_value ?? e.min_value ?? e.value) : e.value,
);
return {
value: t,
min: r,
max: i,
step: Number(e.step) > 0 ? Number(e.step) : 1,
label: e.desc || `${r}${i > r ? `–${i}` : ``} ${_.unit}`,
};
})
.filter(
(e) =>
Number.isFinite(e.min) &&
Number.isFinite(e.max) &&
e.max >= e.min,
),
),
b = computed(() => y.value.some((e) => e.max > e.min)),
x = computed(
() =>
y.value.find((e) => {
let t =
_.modelValue === null ||
_.modelValue === void 0 ||
_.modelValue === ``
? NaN
: Number(_.modelValue);
return (
t >= e.min &&
t <= e.max &&
Math.abs(
(t - e.min) / e.step - Math.round((t - e.min) / e.step),
) < 1e-7
);
}) ?? y.value[0],
),
S = computed(() =>
_.modelValue === null ||
_.modelValue === void 0 ||
_.modelValue === ``
? null
: Number(_.modelValue),
);
function C(e) {
if (_.disabled || e === null || !Number.isFinite(e) || !x.value)
return;
let { min: t, max: n, step: r } = x.value,
i = t + Math.floor((n - t) / r + 1e-7) * r,
a = Number(
Math.min(
i,
Math.max(t, t + Math.round((e - t) / r) * r),
).toFixed(8),
);
Number(_.modelValue) !== a &&
(v(`update:modelValue`, a), v(`change`));
}
function w(e) {
if (_.disabled) return;
let t = y.value.find((t) => t.value === e);
if (!t) return;
let n = S.value;
(x.value === t &&
n !== null &&
n >= t.min &&
n <= t.max &&
Math.abs(
(n - t.min) / t.step - Math.round((n - t.min) / t.step),
) < 1e-7) ||
(v(`update:modelValue`, t.min), v(`change`));
}
return (r, d) => {
let _ = ConfigChoiceGrid,
v = select,
T = inputnumber;
return unref(b)
? (openBlock(),
createElementBlock(`div`, h, [
unref(y).length > 1
? (openBlock(),
createBlock(
v,
{
key: 0,
"aria-label": `${c.label}范围`,
disabled: c.disabled,
"model-value": unref(x)?.value,
options: unref(y),
"option-label": `label`,
"option-value": `value`,
"onUpdate:modelValue": w,
},
null,
8,
[`aria-label`, `disabled`, `model-value`, `options`],
))
: createCommentVNode(``, !0),
createVNode(
T,
{
"aria-label": c.label,
disabled: c.disabled || unref(x)?.min === unref(x)?.max,
"model-value": unref(S),
min: unref(x)?.min,
max: unref(x)?.max,
step: unref(x)?.step,
suffix: ` ${c.unit}`,
"show-buttons": ``,
"button-layout": `horizontal`,
"onUpdate:modelValue": C,
},
null,
8,
[
`aria-label`,
`disabled`,
`model-value`,
`min`,
`max`,
`step`,
`suffix`,
],
),
unref(x)
? (openBlock(),
createElementBlock(`small`, g, [
createTextVNode(
toDisplayString(unref(x).min) +
`–` +
toDisplayString(unref(x).max) +
` ` +
toDisplayString(c.unit),
1,
),
unref(x).max > unref(x).min
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`,步长 ` +
toDisplayString(unref(x).step) +
` ` +
toDisplayString(c.unit),
1,
),
],
64,
))
: createCommentVNode(``, !0),
]))
: createCommentVNode(``, !0),
]))
: (openBlock(),
createBlock(
_,
{
key: 0,
label: c.label,
disabled: c.disabled,
"model-value": unref(x)?.value,
options: unref(y),
compact: ``,
"onUpdate:modelValue": w,
},
null,
8,
[`label`, `disabled`, `model-value`, `options`],
));
};
},
}),
[[`__scopeId`, `data-v-5a04c843`]],
),
{
__name: `ConfigResourceOption`,
},
);
export {};
export default _;
</script>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,268 @@
<script>
import "~/assets/styles/ProductCustomFields.B2QMnPil.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { createBlock } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputtext from "primevue/inputtext";
import select from "primevue/select";
import checkbox from "primevue/checkbox";
import textarea from "primevue/textarea";
var _ = {
key: 0,
class: `panel product-custom-fields`,
},
v = [`for`],
y = {
key: 0,
},
b = {
key: 4,
class: `field-note`,
},
x = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ProductCustomFields`,
props: {
fields: {},
modelValue: {},
disabled: {
type: Boolean,
},
},
emits: [`update:modelValue`],
setup(u, { emit: f }) {
let x = u,
S = f,
C = computed(() => x.fields.filter((e) => e.kind !== `explain`));
function w(e, t) {
S(`update:modelValue`, {
...x.modelValue,
[e]: t == null ? `` : String(t),
});
}
return (i, f) => {
let x = textarea,
S = select,
T = checkbox,
E = inputtext;
return u.fields.length
? (openBlock(),
createElementBlock(`section`, _, [
(f[0] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`订购信息`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
u.fields.filter((e) => e.kind === `explain`),
(t) => (
openBlock(),
createElementBlock(
`p`,
{
key: `explain-${t.id}`,
class: `field-note`,
},
toDisplayString(t.explain || t.description),
1,
)
),
),
128,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(C),
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.id,
class: `form-row`,
},
[
createElementVNode(
`label`,
{
for: `product-field-${t.id}`,
},
[
createTextVNode(toDisplayString(t.label), 1),
t.required
? (openBlock(),
createElementBlock(`span`, y, ` *`))
: createCommentVNode(``, !0),
],
8,
v,
),
t.kind === `textarea`
? (openBlock(),
createBlock(
x,
{
key: 0,
id: `product-field-${t.id}`,
"model-value": u.modelValue[t.id],
"aria-label": t.label,
required: t.required,
disabled: u.disabled,
rows: `3`,
class: `grow`,
"onUpdate:modelValue": (e) => w(t.id, e),
},
null,
8,
[
`id`,
`model-value`,
`aria-label`,
`required`,
`disabled`,
`onUpdate:modelValue`,
],
))
: t.kind === `select`
? (openBlock(),
createBlock(
S,
{
key: 1,
"input-id": `product-field-${t.id}`,
"model-value": u.modelValue[t.id],
"aria-label": t.label,
required: t.required,
options: t.options,
"option-label": `label`,
"option-value": `value`,
disabled: u.disabled,
class: `grow`,
"onUpdate:modelValue": (e) => w(t.id, e),
},
null,
8,
[
`input-id`,
`model-value`,
`aria-label`,
`required`,
`options`,
`disabled`,
`onUpdate:modelValue`,
],
))
: t.kind === `boolean`
? (openBlock(),
createBlock(
T,
{
key: 2,
"input-id": `product-field-${t.id}`,
"model-value":
u.modelValue[t.id] === `1`,
"aria-label": t.label,
required: t.required,
binary: ``,
disabled: u.disabled,
"onUpdate:modelValue": (e) =>
w(t.id, e ? `1` : ``),
},
null,
8,
[
`input-id`,
`model-value`,
`aria-label`,
`required`,
`disabled`,
`onUpdate:modelValue`,
],
))
: (openBlock(),
createBlock(
E,
{
key: 3,
id: `product-field-${t.id}`,
"model-value": u.modelValue[t.id],
"aria-label": t.label,
required: t.required,
type:
t.kind === `password`
? `password`
: t.kind === `link`
? `url`
: `text`,
disabled: u.disabled,
autocomplete:
t.kind === `password`
? `new-password`
: `off`,
class: `grow`,
"onUpdate:modelValue": (e) =>
w(t.id, e),
},
null,
8,
[
`id`,
`model-value`,
`aria-label`,
`required`,
`type`,
`disabled`,
`autocomplete`,
`onUpdate:modelValue`,
],
)),
t.description
? (openBlock(),
createElementBlock(
`small`,
b,
toDisplayString(t.description),
1,
))
: createCommentVNode(``, !0),
],
)
),
),
128,
)),
]))
: createCommentVNode(``, !0);
};
},
}),
[[`__scopeId`, `data-v-9d2a6f70`]],
),
{
__name: `ProductCustomFields`,
},
);
export {};
export default x;
</script>
+193
View File
@@ -0,0 +1,193 @@
<script>
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
import { toDisplayString } from "vue";
import { normalizeClass } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { withKeys } from "vue";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputtext from "primevue/inputtext";
var y = [`open`],
b = {
class: `promo-body`,
},
x = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `PromoCodeField`,
props: mergeModels(
{
discount: {},
loading: {
type: Boolean,
},
disabled: {
type: Boolean,
},
},
{
modelValue: {
default: ``,
},
modelModifiers: {},
},
),
emits: mergeModels([`recalc`], [`update:modelValue`]),
setup(n, { emit: f }) {
let _ = useModel(n, `modelValue`),
x = n,
S = f,
C = ref(``),
w = ref(!1),
T = ref(`idle`);
function E() {
if (x.disabled || x.loading) return;
let e = C.value.trim();
e &&
((w.value = !0), (T.value = `idle`), (_.value = e), S(`recalc`));
}
function D() {
x.disabled ||
x.loading ||
((C.value = ``),
(_.value = ``),
(T.value = `idle`),
(w.value = !1),
S(`recalc`));
}
return (
watch(
() => x.loading,
(e, t) => {
t &&
!e &&
w.value &&
((w.value = !1),
(T.value = (x.discount ?? 0) > 0 ? `ok` : `fail`));
},
),
watch(_, (e) => {
!e && !w.value && ((C.value = ``), (T.value = `idle`));
}),
(r, i) => {
let o = inputtext,
f = button;
return (
openBlock(),
createElementBlock(
`details`,
{
class: `promo`,
open: !!_.value,
},
[
(i[1] ||= createElementVNode(
`summary`,
null,
`我有优惠码,立即使用`,
-1,
)),
createElementVNode(`div`, b, [
createVNode(
o,
{
modelValue: unref(C),
"onUpdate:modelValue": (i[0] ||= (e) =>
isRef(C) ? (C.value = e) : null),
"aria-label": `优惠码`,
placeholder: `选填,输入后点「使用」`,
disabled: n.disabled,
class: `promo-input`,
onKeyup: withKeys(E, [`enter`]),
},
null,
8,
[`modelValue`, `disabled`],
),
createVNode(
f,
{
label: `使用`,
size: `small`,
severity: `secondary`,
outlined: ``,
disabled: n.disabled || !unref(C).trim(),
loading: unref(w),
onClick: E,
},
null,
8,
[`disabled`, `loading`],
),
_.value
? (openBlock(),
createBlock(
f,
{
key: 0,
label: `取消`,
size: `small`,
severity: `secondary`,
text: ``,
disabled: n.disabled,
onClick: D,
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
]),
unref(T) === `idle`
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
{
key: 0,
class: normalizeClass([
`promo-tip`,
{
ok: unref(T) === `ok`,
fail: unref(T) === `fail`,
},
]),
role: `status`,
},
toDisplayString(
unref(T) === `ok`
? `优惠码已生效,已优惠 ¥${(n.discount ?? 0).toFixed(2)}`
: `该优惠码不可用`,
),
3,
)),
],
8,
y,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-a17e621a`]],
),
{
__name: `PromoCodeField`,
},
);
export {};
export default x;
</script>
+295
View File
@@ -0,0 +1,295 @@
<script>
import "~/assets/styles/ChartBox.CYP_mhat.css";
import "~/assets/styles/HomeConsumeTrend.DfrmEdD9.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { t as useTheme_t } from "~/lib/useTheme.js";
import ChartBox from "~/components/ChartBox.vue";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
var x = {
class: `home-card`,
},
S = {
class: `home-card-head`,
},
C = {
class: `home-mini-stats`,
},
w = {
class: `home-mini-stat`,
},
T = {
class: `home-mini-value`,
},
E = {
class: `home-mini-stat`,
},
D = {
class: `home-mini-value`,
},
O = {
class: `home-mini-stat`,
},
k = {
class: `home-mini-value`,
},
A = {
class: `chart-wrap`,
},
j = {
key: 0,
},
M = 6,
N = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeConsumeTrend`,
setup(u) {
let g = useApi(),
N = useAuth(),
P = useTheme_t(),
F = ref([]),
I = ref(!0),
L = ref(``);
function R(e) {
let t = new Date();
return Array.from(
{
length: e,
},
(n, r) => {
let i = new Date(
t.getFullYear(),
t.getMonth() - (e - 1 - r),
1,
);
return {
key: `${i.getFullYear()}-${i.getMonth() + 1}`,
label: `${i.getMonth() + 1}月`,
};
},
);
}
onMounted(async () => {
try {
let e = await g.get(`/transaction`, {
page: 1,
limit: 200,
}),
t = R(M),
n = new Map(t.map((e) => [e.key, 0]));
for (let t of e.list ?? []) {
let e = new Date((t.create_time || 0) * 1e3),
r = `${e.getFullYear()}-${e.getMonth() + 1}`;
n.has(r) && n.set(r, (n.get(r) ?? 0) + Number(t.amount || 0));
}
F.value = t.map((e) => ({
label: e.label,
amount: Math.round((n.get(e.key) ?? 0) * 100) / 100,
}));
} catch (e) {
L.value = e instanceof Error ? e.message : `消费记录加载失败`;
} finally {
I.value = !1;
}
});
let z = computed(() => (P.isDark.value ? `#618dff` : `#0052d9`)),
B = computed(() => ({
grid: {
left: 4,
right: 8,
top: 16,
bottom: 0,
outerBoundsMode: `same`,
outerBoundsContain: `axisLabel`,
},
tooltip: {
trigger: `axis`,
valueFormatter: (e) => `¥${Number(e ?? 0).toFixed(2)}`,
},
xAxis: {
type: `category`,
boundaryGap: !1,
data: F.value.map((e) => e.label),
},
yAxis: {
type: `value`,
axisLabel: {
formatter: `¥{value}`,
},
},
series: [
{
type: `line`,
smooth: !0,
symbol: `circle`,
symbolSize: 6,
data: F.value.map((e) => e.amount),
itemStyle: {
color: z.value,
},
lineStyle: {
color: z.value,
width: 2,
},
areaStyle: {
color: z.value,
opacity: 0.1,
},
},
],
}));
return (t, r) => {
let a = NuxtLink,
u = skeleton,
m = ListEmpty,
h = ChartBox;
return (
openBlock(),
createElementBlock(`div`, x, [
createElementVNode(`div`, S, [
(r[1] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
[
createElementVNode(`i`, {
class: `pi pi-chart-line`,
}),
createTextVNode(`消费趋势`),
],
-1,
)),
createVNode(
a,
{
to: `/finance`,
class: `home-card-more`,
},
{
default: withCtx(() => [
...(r[0] ||= [createTextVNode(`消费记录 ›`, -1)]),
]),
_: 1,
},
),
]),
createElementVNode(`div`, C, [
createElementVNode(`div`, w, [
(r[2] ||= createElementVNode(
`span`,
{
class: `home-mini-label`,
},
`本月消费`,
-1,
)),
createElementVNode(
`span`,
T,
`¥` +
toDisplayString(
unref(N).overview?.this_month_consume ?? `--`,
),
1,
),
]),
createElementVNode(`div`, E, [
(r[3] ||= createElementVNode(
`span`,
{
class: `home-mini-label`,
},
`累计消费`,
-1,
)),
createElementVNode(
`span`,
D,
`¥` + toDisplayString(unref(N).overview?.consume ?? `--`),
1,
),
]),
createElementVNode(`div`, O, [
(r[4] ||= createElementVNode(
`span`,
{
class: `home-mini-label`,
},
`未付订单`,
-1,
)),
createElementVNode(
`span`,
k,
toDisplayString(unref(N).overview?.unpaid_order ?? `--`),
1,
),
]),
]),
createElementVNode(`div`, A, [
unref(I)
? (openBlock(),
createElementBlock(`div`, j, [
createVNode(u, {
height: `150px`,
}),
]))
: unref(L)
? (openBlock(),
createBlock(
m,
{
key: 1,
icon: `pi pi-exclamation-circle`,
title: `消费趋势加载失败`,
description: unref(L),
},
null,
8,
[`description`],
))
: (openBlock(),
createBlock(
h,
{
key: 2,
option: unref(B),
height: 150,
},
null,
8,
[`option`],
)),
]),
])
);
};
},
}),
[[`__scopeId`, `data-v-90c11ad2`]],
),
{
__name: `HomeConsumeTrend`,
},
);
export {};
export default N;
</script>
+268
View File
@@ -0,0 +1,268 @@
<script>
import "~/assets/styles/HomeExpiringPanel.Ckflw2Hv.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { r as dict_r } from "~/lib/dict.js";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
var b = {
class: `home-card`,
},
x = {
key: 0,
class: `home-list`,
},
S = {
key: 3,
class: `home-list`,
},
C = {
class: `home-row-main`,
},
w = {
class: `home-row-title col-mono`,
},
T = {
class: `home-row-sub`,
},
E = {
class: `due-badge`,
},
D = 7,
O = 5,
k = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeExpiringPanel`,
setup(d) {
let g = useApi(),
k = ref([]),
A = ref(!0),
j = ref(``);
onMounted(async () => {
try {
let e = Math.floor(Date.now() / 1e3),
t = e + D * 86400,
n = [],
r = 1,
i = 0;
for (; n.length < O;) {
let a = await g.get(`/host`, {
page: r,
limit: 100,
orderby: `due_time`,
sort: `asc`,
start_time: e,
end_time: t,
}),
o = a.list ?? [];
if (
(n.push(
...o.filter(
(e) =>
Number(e.due_time) > Date.now() / 1e3 &&
Number(e.due_time) <= t,
),
),
(i += o.length),
!o.length ||
(a.count === void 0
? o.length < 100
: i >= Number(a.count)))
)
break;
r++;
}
k.value = n
.filter((e) => Number(e.due_time) > Date.now() / 1e3)
.sort((e, t) => Number(e.due_time) - Number(t.due_time))
.slice(0, O);
} catch (e) {
j.value = e instanceof Error ? e.message : `到期实例加载失败`;
} finally {
A.value = !1;
}
});
function M(e) {
return e ? Math.ceil((e * 1e3 - Date.now()) / 864e5) : 0;
}
return (n, i) => {
let d = skeleton,
h = ListEmpty,
g = NuxtLink;
return (
openBlock(),
createElementBlock(`div`, b, [
createElementVNode(
`div`,
{
class: `home-card-head`,
},
[
(i[0] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
[
createElementVNode(`i`, {
class: `pi pi-clock`,
}),
createTextVNode(`到期提醒`),
],
-1,
)),
createElementVNode(
`span`,
{
class: `home-card-more`,
},
toDisplayString(D) + ` 天内`,
),
],
),
unref(A)
? (openBlock(),
createElementBlock(`div`, x, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(2, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `home-row-skeleton`,
},
[
createVNode(d, {
height: `14px`,
width: `50%`,
}),
createVNode(d, {
height: `12px`,
width: `30%`,
style: {
"margin-top": `8px`,
},
}),
],
),
),
64,
)),
]))
: unref(j)
? (openBlock(),
createBlock(
h,
{
key: 1,
icon: `pi pi-exclamation-circle`,
title: `加载失败`,
description: unref(j),
},
null,
8,
[`description`],
))
: unref(k).length
? (openBlock(),
createElementBlock(`div`, S, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(k),
(t) => (
openBlock(),
createBlock(
g,
{
key: t.id,
to: `/servers/server?id=${t.id}`,
class: `home-row`,
},
{
default: withCtx(() => [
createElementVNode(`div`, C, [
createElementVNode(
`div`,
w,
toDisplayString(t.name),
1,
),
createElementVNode(
`div`,
T,
`到期 ` +
toDisplayString(
(`formatTime` in n
? n.formatTime
: unref(dict_r))(t.due_time),
),
1,
),
]),
createElementVNode(
`span`,
E,
toDisplayString(M(t.due_time)) +
` 天后 `,
1,
),
]),
_: 2,
},
1032,
[`to`],
)
),
),
128,
)),
]))
: (openBlock(),
createBlock(
h,
{
key: 2,
icon: `pi pi-check-circle`,
title: `暂无即将到期的实例`,
description: `${D} 天内有实例到期时会在这里提醒你`,
},
null,
8,
[`description`],
)),
])
);
};
},
}),
[[`__scopeId`, `data-v-9017f053`]],
),
{
__name: `HomeExpiringPanel`,
},
);
export {};
export default k;
</script>
+440
View File
@@ -0,0 +1,440 @@
<script>
import "~/assets/styles/HomeNoticePanel.e5-qgzAs.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { n as dict_n } from "~/lib/dict.js";
import { r as dict_r } from "~/lib/dict.js";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
import { n as sanitize_n } from "~/lib/sanitize.js";
var O = [`aria-busy`],
k = {
class: `home-card-head`,
},
A = {
key: 1,
class: `home-list`,
},
j = [`inert`, `aria-disabled`],
M = [`onClick`],
N = {
class: `home-row-title notice-title`,
},
P = {
class: `home-row-sub`,
},
F = {
class: `home-card-foot`,
},
I = {
key: 0,
},
L = {
key: 2,
class: `detail`,
},
R = {
class: `detail-time`,
},
z = [`innerHTML`],
B = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeNoticePanel`,
setup(m) {
let x = useApi(),
B = ref([]),
V = ref(!0),
H = ref(!1),
U = ref(``),
W = !1,
G = 0,
K = ref(!1),
q = ref(null),
J = ref(!1),
Y = ref(``),
X = ref(null),
Z = 0;
async function Q() {
if (W) return;
let e = ++G;
((W = !0), (V.value = !0), (U.value = ``));
try {
let t = await x.get(`/announcement`, {
page: 1,
limit: 5,
});
if (e !== G) return;
((B.value = t.list ?? []), (H.value = !0));
} catch (t) {
if (e !== G) return;
U.value = t instanceof Error ? t.message : `公告加载失败`;
} finally {
e === G && ((V.value = !1), (W = !1));
}
}
(onMounted(Q),
onBeforeUnmount(() => {
(G++, Z++);
}));
async function $(e) {
let t = ++Z;
((K.value = !0),
(J.value = !0),
(X.value = e),
(Y.value = ``),
(q.value = null));
try {
let n = await x.get(`/announcement/${e.id}`);
if (t !== Z) return;
if (!n.announcement) throw Error(`公告不存在或已删除`);
q.value = n.announcement;
} catch (e) {
t === Z &&
(Y.value =
e instanceof Error ? e.message : `正文加载失败,请重试`);
} finally {
t === Z && (J.value = !1);
}
}
return (n, r) => {
let a = NuxtLink,
m = button,
v = message,
x = skeleton,
W = ListEmpty,
G = dialog;
return (
openBlock(),
createElementBlock(
`div`,
{
class: `home-card`,
"aria-busy": unref(V),
},
[
createElementVNode(`div`, k, [
(r[4] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
`公告板`,
-1,
)),
createVNode(
a,
{
to: `/notices`,
class: `home-card-more`,
"aria-label": `全部公告`,
},
{
default: withCtx(() => [
...(r[3] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
unref(U) && unref(H)
? (openBlock(),
createBlock(
v,
{
key: 0,
severity: `error`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(U)), 1),
createVNode(
m,
{
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
text: ``,
disabled: unref(V),
onClick: Q,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(V) && !unref(H)
? (openBlock(),
createElementBlock(`div`, A, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(5, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `home-row-skeleton`,
},
[
createVNode(x, {
height: `14px`,
width: `70%`,
}),
],
),
),
64,
)),
]))
: unref(U) && !unref(H)
? (openBlock(),
createBlock(
W,
{
key: 2,
icon: `pi pi-exclamation-circle`,
title: `公告加载失败`,
description: unref(U),
},
{
default: withCtx(() => [
createVNode(m, {
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
onClick: Q,
}),
]),
_: 1,
},
8,
[`description`],
))
: unref(B).length
? (openBlock(),
createElementBlock(
`div`,
{
key: 4,
class: `home-list`,
inert: unref(U) ? !0 : void 0,
"aria-disabled": !!unref(U),
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(B),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.id,
type: `button`,
class: `home-row notice-row`,
onClick: (e) => $(t),
},
[
createElementVNode(
`span`,
N,
toDisplayString(t.title),
1,
),
createElementVNode(
`span`,
P,
toDisplayString(
(`formatDate` in n
? n.formatDate
: unref(dict_n))(t.create_time),
),
1,
),
],
8,
M,
)
),
),
128,
)),
],
8,
j,
))
: (openBlock(),
createBlock(W, {
key: 3,
icon: `pi pi-megaphone`,
title: `暂无公告`,
description: `平台公告与通知会显示在这里`,
})),
createElementVNode(`div`, F, [
createVNode(
a,
{
to: `/notices`,
class: `home-button secondary`,
},
{
default: withCtx(() => [
...(r[5] ||= [createTextVNode(`查看全部`, -1)]),
]),
_: 1,
},
),
]),
createVNode(
G,
{
visible: unref(K),
"onUpdate:visible": (r[2] ||= (e) =>
isRef(K) ? (K.value = e) : null),
header: unref(X)?.title || `公告详情`,
modal: ``,
draggable: !1,
style: {
width: `640px`,
},
},
{
footer: withCtx(() => [
unref(Y) && unref(X)
? (openBlock(),
createBlock(m, {
key: 0,
label: `重新加载正文`,
icon: `pi pi-refresh`,
severity: `secondary`,
onClick: (r[0] ||= (e) => $(unref(X))),
}))
: createCommentVNode(``, !0),
createVNode(m, {
label: `关闭`,
severity: `secondary`,
text: ``,
onClick: (r[1] ||= (e) => (K.value = !1)),
}),
]),
default: withCtx(() => [
unref(J)
? (openBlock(),
createElementBlock(`div`, I, [
createVNode(x, {
height: `120px`,
}),
]))
: unref(Y)
? (openBlock(),
createBlock(
v,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(Y)),
1,
),
]),
_: 1,
},
))
: unref(q)
? (openBlock(),
createElementBlock(`div`, L, [
createElementVNode(
`div`,
R,
toDisplayString(
(`formatTime` in n
? n.formatTime
: unref(dict_r))(unref(q).create_time),
),
1,
),
createElementVNode(
`div`,
{
class: `detail-content`,
innerHTML: (`sanitizeHtml` in n
? n.sanitizeHtml
: unref(sanitize_n))(
unref(q).content || ``,
),
},
null,
8,
z,
),
]))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `header`],
),
],
8,
O,
)
);
};
},
}),
[[`__scopeId`, `data-v-a93c47c1`]],
),
{
__name: `HomeNoticePanel`,
},
);
export {};
export default B;
</script>
+427
View File
@@ -0,0 +1,427 @@
<script>
import "~/assets/styles/HomeReferralPanel.DsgN33ME.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { Icon } from "#components";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import skeleton from "primevue/skeleton";
var x = [`aria-busy`],
S = {
class: `home-card-head`,
},
C = {
id: `home-referral-title`,
class: `home-card-title`,
},
w = {
key: 0,
class: `referral-body referral-loading`,
role: `status`,
"aria-label": `正在加载推介数据`,
},
T = {
class: `referral-placeholders`,
},
E = {
key: 1,
class: `referral-body referral-empty`,
role: `status`,
},
D = {
key: 2,
class: `referral-body`,
},
O = {
class: `referral-overview`,
},
k = {
class: `referral-balance`,
},
A = {
key: 0,
},
j = {
key: 0,
class: `referral-invitees`,
},
M = {
class: `referral-stats`,
},
N = {
key: 0,
},
P = {
class: `referral-footer`,
},
F = {
key: 3,
class: `referral-body referral-empty`,
},
I = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeReferralPanel`,
setup(f) {
let y = useApi(),
I = ref(null),
L = ref(!0),
R = ref(``),
z = !1,
B = computed(() => !!I.value?.url),
V = computed(() => I.value?.permission === 1),
H = computed(() => I.value?.relation_mode === `permanent`),
U = computed(() => [
{
label: `待结算`,
value: I.value?.pending_amount,
},
{
label: `已生效`,
value: I.value?.active_amount,
},
{
label: `已提现`,
value: I.value?.withdrawn_amount,
},
]);
function W(e, t = !0) {
if (
(typeof e != `number` && typeof e != `string`) ||
String(e).trim() === ``
)
return `—`;
let n = Number(e);
return !Number.isFinite(n) ||
(!t && (!Number.isInteger(n) || n < 0))
? `—`
: n.toLocaleString(`zh-CN`, {
minimumFractionDigits: t ? 2 : 0,
maximumFractionDigits: t ? 2 : 0,
});
}
async function G() {
if (!z) {
((z = !0), (L.value = !0), (R.value = ``));
try {
let e = (
await y.get(`/recommend/promoter`, void 0, !1, {
timeoutMs: 1e4,
})
)?.promoter;
if (!e || (!e.url && e.permission !== 0 && e.permission !== 1))
throw Error(`暂时无法获取推介数据,请重试。`);
I.value = e;
} catch (e) {
((I.value = null),
(R.value =
e instanceof Error
? e.message
: `暂时无法获取推介数据,请重试。`));
} finally {
((L.value = !1), (z = !1));
}
}
}
return (
onMounted(G),
(n, r) => {
let o = Icon,
f = NuxtLink,
g = skeleton,
y = button;
return (
openBlock(),
createElementBlock(
`section`,
{
class: `home-card home-referral`,
"aria-labelledby": `home-referral-title`,
"aria-busy": unref(L),
},
[
createElementVNode(`div`, S, [
createElementVNode(`h2`, C, [
createVNode(o, {
name: `lucide:gift`,
"aria-hidden": `true`,
}),
(r[0] ||= createTextVNode(`推介计划`, -1)),
]),
createVNode(
f,
{
to: `/recommend`,
class: `home-card-more`,
"aria-label": `查看推介计划`,
},
{
default: withCtx(() => [
...(r[1] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
unref(L)
? (openBlock(),
createElementBlock(`div`, w, [
createVNode(g, {
width: `6rem`,
height: `14px`,
}),
createVNode(g, {
width: `11rem`,
height: `36px`,
}),
createElementVNode(`div`, T, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(3, (e) =>
createVNode(g, {
key: e,
height: `48px`,
}),
),
64,
)),
]),
]))
: unref(R)
? (openBlock(),
createElementBlock(`div`, E, [
(r[2] ||= createElementVNode(
`h3`,
null,
`推介数据加载失败`,
-1,
)),
createElementVNode(
`p`,
null,
toDisplayString(unref(R)),
1,
),
createVNode(y, {
label: `重试`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
size: `small`,
onClick: G,
}),
]))
: unref(B)
? (openBlock(),
createElementBlock(`div`, D, [
createElementVNode(`dl`, O, [
createElementVNode(`div`, k, [
(r[3] ||= createElementVNode(
`dt`,
null,
`可提现奖励`,
-1,
)),
createElementVNode(`dd`, null, [
W(unref(I)?.withdrawable_amount) === `—`
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`small`, A, `¥`)),
createTextVNode(
toDisplayString(
W(unref(I)?.withdrawable_amount),
),
1,
),
]),
]),
unref(H)
? (openBlock(),
createElementBlock(`div`, j, [
(r[5] ||= createElementVNode(
`dt`,
null,
`邀请人数`,
-1,
)),
createElementVNode(`dd`, null, [
createTextVNode(
toDisplayString(
W(unref(I)?.invitee_count, !1),
),
1,
),
(r[4] ||= createElementVNode(
`small`,
null,
`人`,
-1,
)),
]),
]))
: createCommentVNode(``, !0),
]),
createElementVNode(`dl`, M, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(U),
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.label,
class: `referral-stat`,
},
[
createElementVNode(
`dt`,
null,
toDisplayString(t.label),
1,
),
createElementVNode(`dd`, null, [
W(t.value) === `—`
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`small`,
N,
`¥`,
)),
createTextVNode(
toDisplayString(W(t.value)),
1,
),
]),
],
)
),
),
128,
)),
]),
createElementVNode(`div`, P, [
(r[7] ||= createElementVNode(
`p`,
null,
`查看邀请记录与奖励结算进度`,
-1,
)),
createVNode(
f,
{
to: `/recommend`,
class: `referral-details`,
},
{
default: withCtx(() => [
...(r[6] ||= [
createTextVNode(`查看推介明细`, -1),
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
]))
: (openBlock(),
createElementBlock(`div`, F, [
createElementVNode(
`h3`,
null,
toDisplayString(
unref(V)
? `尚未开通推介计划`
: `暂未开放推介申请`,
),
1,
),
createElementVNode(
`p`,
null,
toDisplayString(
unref(V)
? `开通后获取专属链接,邀请好友。你的邀请人数与推介奖励将在这里展示。`
: `目前暂不接受新的推介申请,可前往推介计划查看详情。`,
),
1,
),
createVNode(
f,
{
to: `/recommend`,
class: `home-button`,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
unref(V)
? `了解并开通`
: `查看推介计划`,
),
1,
),
]),
_: 1,
},
),
])),
],
8,
x,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-8690c3a5`]],
),
{
__name: `HomeReferralPanel`,
},
);
export {};
export default I;
</script>
+491
View File
@@ -0,0 +1,491 @@
<script>
import "~/assets/styles/HomeServerPanel.Do7AgMDx.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onUnmounted } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { n as product_name_n } from "~/lib/product-name.js";
import { c as dict_c } from "~/lib/dict.js";
import { l as dict_l } from "~/lib/dict.js";
import { r as dict_r } from "~/lib/dict.js";
import paginator from "primevue/paginator";
import ListEmpty from "~/components/ListEmpty.vue";
import { t as modules_t } from "~/lib/modules.js";
import tag from "primevue/tag";
import skeleton from "primevue/skeleton";
import { t as server_page_t } from "~/lib/server-page.js";
var ne = [`aria-busy`],
j = {
class: `home-card-head server-head`,
},
M = {
class: `home-tabs`,
role: `group`,
"aria-label": `服务器类型`,
},
N = [`aria-pressed`, `onClick`],
P = {
key: 0,
class: `server-cols`,
},
F = {
key: 2,
class: `home-list`,
},
I = [`inert`, `aria-disabled`],
L = {
class: `home-row-main`,
},
R = {
class: `home-row-title`,
},
z = {
class: `home-row-sub`,
},
B = {
class: `home-row-side server-due`,
},
V = [`inert`, `aria-disabled`],
H = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeServerPanel`,
setup(h) {
let x = useApi(),
H = [
{
label: `云服务器`,
modules: modules_t.cloud,
to: `/cloud-servers`,
},
{
label: `物理服务器`,
modules: modules_t.dcim,
to: `/dedicated-servers`,
},
],
U = H.map((e) => server_page_t(x, e.modules)),
W = ref(0),
G = ref([]),
K = ref(!0),
q = ref(!1),
J = ref(``),
Y = ref(1),
X = ref(0),
Z = 0,
Q = ``;
async function $() {
let e = ++Z,
t = JSON.stringify([W.value, Y.value]);
(t !== Q && ((G.value = []), (X.value = 0), (q.value = !1)),
(K.value = !0),
(J.value = ``));
try {
let n = await U[W.value]({
module: H[W.value].modules.join(`,`),
page: Y.value,
limit: 5,
});
if (e !== Z) return;
((G.value = n.list ?? []),
(X.value = n.count ?? G.value.length),
(Q = t),
(q.value = !0));
} catch (t) {
if (e !== Z) return;
J.value = t instanceof Error ? t.message : `服务器加载失败`;
} finally {
e === Z && (K.value = !1);
}
}
function re(e) {
if (!(K.value || J.value)) return ((Y.value = e.page + 1), $());
}
return (
watch(W, () => {
((Y.value = 1), $());
}),
onMounted($),
onUnmounted(() => {
Z += 1;
}),
(n, r) => {
let a = NuxtLink,
s = button,
h = message,
y = skeleton,
x = ListEmpty,
D = tag,
A = paginator;
return (
openBlock(),
createElementBlock(
`div`,
{
class: `home-card`,
"aria-busy": unref(K),
},
[
createElementVNode(`div`, j, [
(r[1] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
`服务器`,
-1,
)),
createVNode(
a,
{
to: H[unref(W)].to,
class: `home-card-more`,
"aria-label": `查看全部${H[unref(W)].label}`,
},
{
default: withCtx(() => [
...(r[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
},
null,
-1,
),
]),
]),
_: 1,
},
8,
[`to`, `aria-label`],
),
]),
createElementVNode(`div`, M, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(H, (t, n) =>
createElementVNode(
`button`,
{
key: t.label,
type: `button`,
class: normalizeClass([
`home-tab`,
{
active: unref(W) === n,
},
]),
"aria-pressed": unref(W) === n,
onClick: (e) => (W.value = n),
},
toDisplayString(t.label),
11,
N,
),
),
64,
)),
]),
unref(G).length || unref(K)
? (openBlock(),
createElementBlock(`div`, P, [
...(r[2] ||= [
createElementVNode(`span`, null, `名称`, -1),
createElementVNode(`span`, null, `到期时间`, -1),
createElementVNode(`span`, null, `计费状态`, -1),
]),
]))
: createCommentVNode(``, !0),
unref(J) && unref(q)
? (openBlock(),
createBlock(
h,
{
key: 1,
severity: `error`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(J)), 1),
createVNode(
s,
{
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
text: ``,
disabled: unref(K),
onClick: $,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(K) && !unref(q)
? (openBlock(),
createElementBlock(`div`, F, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(5, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `home-row-skeleton`,
},
[
createVNode(y, {
height: `14px`,
width: `45%`,
}),
createVNode(y, {
height: `12px`,
width: `30%`,
style: {
"margin-top": `8px`,
},
}),
],
),
),
64,
)),
]))
: unref(J) && !unref(q)
? (openBlock(),
createBlock(
x,
{
key: 3,
icon: `pi pi-exclamation-circle`,
title: `服务器加载失败`,
description: unref(J),
},
{
default: withCtx(() => [
createVNode(s, {
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
onClick: $,
}),
]),
_: 1,
},
8,
[`description`],
))
: unref(G).length
? (openBlock(),
createElementBlock(
`div`,
{
key: 5,
class: `home-list`,
inert: unref(J) ? !0 : void 0,
"aria-disabled": !!unref(J),
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(G),
(t) => (
openBlock(),
createBlock(
a,
{
key: t.id,
to: `/servers/server?id=${t.id}`,
class: `home-row`,
},
{
default: withCtx(() => [
createElementVNode(`div`, L, [
createElementVNode(
`div`,
R,
toDisplayString(
unref(product_name_n)(
t.product_name,
) || t.name,
),
1,
),
createElementVNode(
`div`,
z,
` #` +
toDisplayString(t.id) +
` / ` +
toDisplayString(t.name),
1,
),
]),
createElementVNode(
`span`,
B,
toDisplayString(
(`formatTime` in n
? n.formatTime
: unref(dict_r))(t.due_time),
),
1,
),
createVNode(
D,
{
value: (`statusLabel` in n
? n.statusLabel
: unref(dict_c))(t.status),
severity: (`statusSeverity` in n
? n.statusSeverity
: unref(dict_l))(t.status),
},
null,
8,
[`value`, `severity`],
),
]),
_: 2,
},
1032,
[`to`],
)
),
),
128,
)),
],
8,
I,
))
: (openBlock(),
createBlock(
x,
{
key: 4,
icon: `pi pi-server`,
title: `还没有${H[unref(W)].label}`,
description: `选购后实例会显示在这里`,
},
{
default: withCtx(() => [
createVNode(
a,
{
to: `/products`,
class: `home-button`,
},
{
default: withCtx(() => [
...(r[3] ||= [
createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`订购产品`, -1),
]),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`title`],
)),
unref(G).length || (unref(K) && !unref(q))
? (openBlock(),
createElementBlock(
`div`,
{
key: 6,
class: `server-pagination`,
inert: unref(K) || unref(J) ? !0 : void 0,
"aria-disabled": unref(K) || !!unref(J),
},
[
unref(K) && !unref(q)
? (openBlock(),
createBlock(y, {
key: 0,
height: `40px`,
}))
: (openBlock(),
createBlock(
A,
{
key: 1,
rows: 5,
"total-records": unref(X),
first: (unref(Y) - 1) * 5,
onPage: re,
},
null,
8,
[`total-records`, `first`],
)),
],
8,
V,
))
: createCommentVNode(``, !0),
],
8,
ne,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-7ce76df7`]],
),
{
__name: `HomeServerPanel`,
},
);
export {};
export default H;
</script>
+394
View File
@@ -0,0 +1,394 @@
<script>
import "~/assets/styles/HomeTicketPanel.LxPesukM.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { n as dict_n } from "~/lib/dict.js";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
var T = [`aria-busy`],
E = {
class: `home-card-head`,
},
D = {
key: 1,
class: `home-list`,
},
O = [`inert`, `aria-disabled`],
k = {
class: `home-row-main`,
},
A = {
class: `home-row-title`,
},
j = {
class: `home-row-sub`,
},
M = {
key: 5,
class: `home-card-foot`,
},
N = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeTicketPanel`,
setup(p) {
let b = useApi(),
N = ref([]),
P = ref(!0),
F = ref(!1),
I = ref(``),
L = 0;
async function R() {
let e = ++L;
((P.value = !0), (I.value = ``));
try {
let t = await b.get(`/ticket`, {
page: 1,
limit: 5,
});
if (e !== L) return;
((N.value = t.list ?? []), (F.value = !0));
} catch (t) {
if (e !== L) return;
I.value = t instanceof Error ? t.message : `工单加载失败`;
} finally {
e === L && (P.value = !1);
}
}
return (
onMounted(R),
onBeforeUnmount(() => {
L++;
}),
(n, r) => {
let a = NuxtLink,
p = button,
v = message,
b = skeleton,
L = ListEmpty;
return (
openBlock(),
createElementBlock(
`div`,
{
class: `home-card`,
"aria-busy": unref(P),
},
[
createElementVNode(`div`, E, [
(r[1] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
`工单处理`,
-1,
)),
createVNode(
a,
{
to: `/tickets`,
class: `home-card-more`,
"aria-label": `全部工单`,
},
{
default: withCtx(() => [
...(r[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
unref(I) && unref(F)
? (openBlock(),
createBlock(
v,
{
key: 0,
severity: `error`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
createVNode(
p,
{
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
text: ``,
disabled: unref(P),
onClick: R,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(P) && !unref(F)
? (openBlock(),
createElementBlock(`div`, D, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(5, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `home-row-skeleton`,
},
[
createVNode(b, {
height: `14px`,
width: `55%`,
}),
createVNode(b, {
height: `12px`,
width: `35%`,
style: {
"margin-top": `8px`,
},
}),
],
),
),
64,
)),
]))
: unref(I) && !unref(F)
? (openBlock(),
createBlock(
L,
{
key: 2,
icon: `pi pi-exclamation-circle`,
title: `工单加载失败`,
description: unref(I),
},
{
default: withCtx(() => [
createVNode(p, {
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
onClick: R,
}),
]),
_: 1,
},
8,
[`description`],
))
: unref(N).length
? (openBlock(),
createElementBlock(
`div`,
{
key: 4,
class: `home-list`,
inert: unref(I) ? !0 : void 0,
"aria-disabled": !!unref(I),
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(N),
(t) => (
openBlock(),
createBlock(
a,
{
key: t.id,
to: `/tickets/${t.id}`,
class: `home-row`,
},
{
default: withCtx(() => [
createElementVNode(`div`, k, [
createElementVNode(
`div`,
A,
toDisplayString(t.title),
1,
),
createElementVNode(
`div`,
j,
toDisplayString(
(`formatDate` in n
? n.formatDate
: unref(dict_n))(
t.last_reply_time ||
t.post_time,
),
),
1,
),
]),
createElementVNode(
`span`,
{
class: `ticket-status`,
style: normalizeStyle({
background:
t.color ||
`var(--p-text-muted-color)`,
}),
},
toDisplayString(t.status),
5,
),
]),
_: 2,
},
1032,
[`to`],
)
),
),
128,
)),
],
8,
O,
))
: (openBlock(),
createBlock(
L,
{
key: 3,
icon: `pi pi-inbox`,
title: `暂无工单`,
description: `有问题随时提交工单,我们会尽快处理`,
},
{
default: withCtx(() => [
createVNode(
a,
{
to: `/tickets/create`,
class: `home-button`,
},
{
default: withCtx(() => [
...(r[2] ||= [
createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`创建工单`, -1),
]),
]),
_: 1,
},
),
]),
_: 1,
},
)),
unref(N).length || (unref(P) && !unref(F))
? (openBlock(),
createElementBlock(`div`, M, [
createVNode(
a,
{
to: `/tickets`,
class: `home-button secondary`,
},
{
default: withCtx(() => [
...(r[3] ||= [createTextVNode(`查看全部`, -1)]),
]),
_: 1,
},
),
createVNode(
a,
{
to: `/tickets/create`,
class: `home-button`,
},
{
default: withCtx(() => [
...(r[4] ||= [
createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`创建工单`, -1),
]),
]),
_: 1,
},
),
]))
: createCommentVNode(``, !0),
],
8,
T,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-bacdfa58`]],
),
{
__name: `HomeTicketPanel`,
},
);
export {};
export default N;
</script>
+197
View File
@@ -0,0 +1,197 @@
<script>
import "~/assets/styles/HomeTicketStat.C4kzybrY.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
var x = {
class: `home-card`,
},
S = {
class: `home-card-head`,
},
C = {
key: 0,
class: `home-card-body`,
},
w = {
key: 3,
class: `stat-grid`,
},
T = {
class: `stat-num`,
},
E = {
class: `stat-name`,
},
D = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeTicketStat`,
setup(f) {
let v = useApi(),
D = ref([]),
O = ref({}),
k = ref(!0),
A = ref(``);
onMounted(async () => {
try {
let [e, t] = await Promise.all([
v.get(`/ticket/status`),
v.get(`/ticket/statistic`),
]);
((D.value = e.list ?? []), (O.value = t ?? {}));
} catch (e) {
A.value = e instanceof Error ? e.message : `工单统计加载失败`;
} finally {
k.value = !1;
}
});
let j = computed(() =>
D.value
.filter((e) => O.value[e.id] !== void 0)
.map((e) => ({
...e,
count: O.value[e.id] ?? 0,
})),
);
return (n, i) => {
let o = NuxtLink,
f = skeleton,
_ = ListEmpty;
return (
openBlock(),
createElementBlock(`div`, x, [
createElementVNode(`div`, S, [
(i[1] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
[
createElementVNode(`i`, {
class: `pi pi-chart-bar`,
}),
createTextVNode(`工单状态`),
],
-1,
)),
createVNode(
o,
{
to: `/tickets`,
class: `home-card-more`,
},
{
default: withCtx(() => [
...(i[0] ||= [createTextVNode(`全部 ›`, -1)]),
]),
_: 1,
},
),
]),
unref(k)
? (openBlock(),
createElementBlock(`div`, C, [
createVNode(f, {
height: `56px`,
}),
]))
: unref(A)
? (openBlock(),
createBlock(
_,
{
key: 1,
icon: `pi pi-exclamation-circle`,
title: `统计加载失败`,
description: unref(A),
},
null,
8,
[`description`],
))
: unref(j).length
? (openBlock(),
createElementBlock(`div`, w, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(j),
(t) => (
openBlock(),
createBlock(
o,
{
key: t.id,
to: `/tickets?status=${t.id}`,
class: `stat-chip`,
style: normalizeStyle({
borderLeftColor: t.color,
}),
},
{
default: withCtx(() => [
createElementVNode(
`span`,
T,
toDisplayString(t.count),
1,
),
createElementVNode(
`span`,
E,
toDisplayString(t.name),
1,
),
]),
_: 2,
},
1032,
[`to`, `style`],
)
),
),
128,
)),
]))
: (openBlock(),
createBlock(_, {
key: 2,
icon: `pi pi-inbox`,
title: `暂无工单`,
description: `提交工单后可在这里跟踪进度`,
})),
])
);
};
},
}),
[[`__scopeId`, `data-v-6971a1b9`]],
),
{
__name: `HomeTicketStat`,
},
);
export {};
export default D;
</script>
+206
View File
@@ -0,0 +1,206 @@
<script>
import "~/assets/styles/WithdrawDialog.ks0wdKEK.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/RechargeDialog.DpsMly4r.css";
import "~/assets/styles/HomeWalletCard.C5SHzGlJ.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useAuth } from "~/lib/auth.js";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import skeleton from "primevue/skeleton";
import RechargeDialog from "~/components/RechargeDialog.vue";
import WithdrawDialog from "~/components/WithdrawDialog.vue";
import { t as useWithdrawAvailability_t } from "~/lib/useWithdrawAvailability.js";
var C = {
class: `home-card`,
},
w = {
class: `home-card-head`,
},
T = {
class: `home-card-body wallet-body`,
},
E = {
class: `balance-value`,
},
D = {
key: 0,
},
O = {
key: 1,
},
k = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeWalletCard`,
setup(d) {
let v = useAuth(),
{ rechargeClosed: k, load: A } = useSiteConfig_t(),
{ enabled: j, load: M } = useWithdrawAvailability_t(),
N = ref(!1),
P = ref(!1);
onMounted(() => {
(A().catch(() => {}), M());
});
async function F() {
await v.refreshOverview().catch(() => {});
}
return (t, i) => {
let d = NuxtLink,
h = skeleton,
g = button,
S = RechargeDialog,
A = WithdrawDialog;
return (
openBlock(),
createElementBlock(`div`, C, [
createElementVNode(`div`, w, [
(i[5] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
`钱包`,
-1,
)),
createVNode(
d,
{
to: `/finance`,
class: `home-card-more`,
"aria-label": `钱包明细`,
},
{
default: withCtx(() => [
...(i[4] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
createElementVNode(`div`, T, [
(i[6] ||= createElementVNode(
`div`,
{
class: `balance-label`,
},
`可用余额`,
-1,
)),
createElementVNode(`div`, E, [
unref(v).overview
? (openBlock(),
createElementBlock(
`span`,
O,
`¥` + toDisplayString(unref(v).overview.credit),
1,
))
: (openBlock(),
createElementBlock(`span`, D, [
createVNode(h, {
width: `90px`,
height: `28px`,
}),
])),
]),
createElementVNode(
`div`,
{
class: normalizeClass([
`wallet-actions`,
{
"wallet-actions-single": !unref(j),
},
]),
},
[
unref(j)
? (openBlock(),
createBlock(g, {
key: 0,
label: `提现`,
severity: `secondary`,
outlined: ``,
onClick: (i[0] ||= (e) => (P.value = !0)),
}))
: createCommentVNode(``, !0),
createVNode(
g,
{
label: `充值`,
icon: `pi pi-plus`,
disabled: unref(k),
title: unref(k) ? `站点已关闭充值` : void 0,
onClick: (i[1] ||= (e) => (N.value = !0)),
},
null,
8,
[`disabled`, `title`],
),
],
2,
),
]),
createVNode(
S,
{
modelValue: unref(N),
"onUpdate:modelValue": (i[2] ||= (e) =>
isRef(N) ? (N.value = e) : null),
onSuccess: F,
},
null,
8,
[`modelValue`],
),
createVNode(
A,
{
modelValue: unref(P),
"onUpdate:modelValue": (i[3] ||= (e) =>
isRef(P) ? (P.value = e) : null),
onSuccess: F,
},
null,
8,
[`modelValue`],
),
])
);
};
},
}),
[[`__scopeId`, `data-v-0dbd1f86`]],
),
{
__name: `HomeWalletCard`,
},
);
export {};
export default k;
</script>
+36
View File
@@ -0,0 +1,36 @@
<script>
import "~/assets/styles/RoxyMascot.CDqPSf2d.css";
import { createStaticVNode } from "vue";
import { createElementBlock } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var i = {},
a = {
class: `roxy-mascot`,
"aria-hidden": `true`,
};
function o(r, i) {
return (
openBlock(),
createElementBlock(`div`, a, [
...(i[0] ||= [
createStaticVNode(
`<div class="roxy-shadow" data-v-65169a82></div><div class="roxy-staff" data-v-65169a82><span class="staff-ring" data-v-65169a82><i data-v-65169a82></i></span></div><div class="roxy-leg leg-back" data-v-65169a82><i data-v-65169a82></i></div><div class="roxy-leg leg-front" data-v-65169a82><i data-v-65169a82></i></div><div class="roxy-body" data-v-65169a82><span class="cape-fold" data-v-65169a82></span><span class="cape-hem" data-v-65169a82></span></div><div class="roxy-sleeve sleeve-left" data-v-65169a82></div><div class="roxy-sleeve sleeve-right" data-v-65169a82></div><div class="roxy-head" data-v-65169a82><div class="hair-back" data-v-65169a82></div><div class="roxy-ear ear-left" data-v-65169a82></div><div class="roxy-ear ear-right" data-v-65169a82></div><div class="roxy-face" data-v-65169a82><span class="roxy-brow brow-left" data-v-65169a82></span><span class="roxy-brow brow-right" data-v-65169a82></span><span class="roxy-eye eye-left" data-v-65169a82><i data-v-65169a82></i></span><span class="roxy-eye eye-right" data-v-65169a82><i data-v-65169a82></i></span><span class="roxy-cheek cheek-left" data-v-65169a82></span><span class="roxy-cheek cheek-right" data-v-65169a82></span><span class="roxy-nose" data-v-65169a82></span><span class="roxy-mouth" data-v-65169a82></span></div><div class="roxy-fringe fringe-left" data-v-65169a82></div><div class="roxy-fringe fringe-middle" data-v-65169a82></div><div class="roxy-fringe fringe-right" data-v-65169a82></div><div class="roxy-braid braid-left" data-v-65169a82><i data-v-65169a82></i><i data-v-65169a82></i><i data-v-65169a82></i><i data-v-65169a82></i><span class="hair-tie" data-v-65169a82></span></div><div class="roxy-braid braid-right" data-v-65169a82><i data-v-65169a82></i><i data-v-65169a82></i><i data-v-65169a82></i><i data-v-65169a82></i><span class="hair-tie" data-v-65169a82></span></div><div class="roxy-hat" data-v-65169a82><div class="hat-cone" data-v-65169a82><span class="hat-seam" data-v-65169a82></span></div><div class="hat-band" data-v-65169a82></div><div class="hat-brim" data-v-65169a82></div><span class="hat-buckle" data-v-65169a82></span></div></div><div class="roxy-hand hand-left" data-v-65169a82><i data-v-65169a82></i></div><div class="roxy-hand hand-right" data-v-65169a82><i data-v-65169a82></i></div>`,
10,
),
]),
])
);
}
var s = Object.assign(
_plugin_vue_export_helper_t(i, [
[`render`, o],
[`__scopeId`, `data-v-65169a82`],
]),
{
__name: `RoxyMascot`,
},
);
export {};
export default s;
</script>
@@ -0,0 +1,172 @@
<script>
import "~/assets/styles/CloudAccessExtras.CnBJlFAZ.css";
import { toDisplayString } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
var y = {
key: 0,
class: `cloud-extras`,
},
b = {
class: `info-table`,
},
x = {
key: 0,
class: `kv`,
},
S = {
class: `action-cell`,
},
C = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `CloudAccessExtras`,
props: {
hostId: {},
module: {},
imageName: {},
config: {},
},
emits: [`refresh`],
setup(f) {
let _ = f,
C = useApi(),
w = computed(() => [`mf_cloud`, `remf_cloud`].includes(_.module)),
T = computed(() => /windows/i.test(_.imageName)),
E = ref(!1),
D = ref(``),
O = 0,
k = !1;
async function A() {
if (!w.value || !T.value || E.value || k) return;
let e = O;
((E.value = !0), (D.value = ``));
try {
let t = await C.get(`/${_.module}/${_.hostId}/download_rdp`);
if (k || e !== O) return;
if (typeof t.content != `string` || !t.content.trim())
throw Error(`远程桌面文件内容为空`);
let n = URL.createObjectURL(
new Blob([t.content], {
type: `application/x-rdp`,
}),
),
r = document.createElement(`a`);
((r.href = n),
(r.download = String(
t.name || `instance-${_.hostId}.rdp`,
).replace(/[\\/\0]/g, `_`)),
r.click(),
setTimeout(() => URL.revokeObjectURL(n), 1e3));
} catch (t) {
!k &&
e === O &&
(D.value = t instanceof Error ? t.message : `RDP 文件下载失败`);
} finally {
e === O && (E.value = !1);
}
}
return (
watch([() => _.hostId, () => _.module, () => _.imageName], () => {
(O++, (E.value = !1), (D.value = ``));
}),
onBeforeUnmount(() => {
((k = !0), O++);
}),
(t, n) => {
let i = button,
s = message;
return unref(w) && unref(T)
? (openBlock(),
createElementBlock(`section`, y, [
(n[2] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`远程桌面连接`,
-1,
)),
createElementVNode(`div`, b, [
unref(T)
? (openBlock(),
createElementBlock(`div`, x, [
(n[1] ||= createElementVNode(
`span`,
null,
`远程桌面`,
-1,
)),
createElementVNode(`div`, S, [
createVNode(
i,
{
label: `下载远程桌面连接文件`,
icon: `pi pi-download`,
loading: unref(E),
onClick: A,
},
null,
8,
[`loading`],
),
(n[0] ||= createElementVNode(
`p`,
{
class: `action-desc`,
},
`下载连接文件后,使用远程桌面客户端连接您的实例。`,
-1,
)),
]),
]))
: createCommentVNode(``, !0),
]),
unref(D)
? (openBlock(),
createBlock(
s,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(D)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]))
: createCommentVNode(``, !0);
}
);
},
}),
[[`__scopeId`, `data-v-94e7f654`]],
),
{
__name: `CloudAccessExtras`,
},
);
export {};
export default C;
</script>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+838
View File
@@ -0,0 +1,838 @@
<script>
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
import "~/assets/styles/InstanceSmsCode.CsITfIEU.css";
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/DcimActions.Da2op5wy.css";
import { toDisplayString } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import { n as product_name_n } from "~/lib/product-name.js";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import checkbox from "primevue/checkbox";
import OperationNotice from "~/components/OperationNotice.vue";
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
import { t as os_name_t } from "~/lib/os-name.js";
import ImagePurchaseDialog from "~/components/instance/ImagePurchaseDialog.vue";
import InstanceSmsCode from "~/components/instance/InstanceSmsCode.vue";
import { t as remote_console_t } from "~/lib/remote-console.js";
var fe = {
class: `action-form`,
},
pe = {
class: `target`,
},
me = [`id`],
he = {
key: 1,
class: `muted`,
},
ge = {
class: `form-grid`,
},
_e = [`for`],
ve = [`id`],
ye = [`for`],
be = [`id`],
xe = [`for`],
Se = {
key: 6,
class: `ack`,
},
Ce = [`for`],
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimActions`,
props: {
hostId: {},
productId: {},
host: {},
module: {},
detail: {},
},
emits: [`refresh`],
setup(h, { expose: y, emit: S }) {
let C = h,
w = S,
T = useApi(),
E = useId(),
D = ref(null),
O = ref(``),
k = ref(!1),
A = ref(``),
j = ref(!1),
M = ref(``),
N = ref(``),
P = ref(``),
F = ref(!1),
I = ref(2),
L = ref(null),
R = ref([]),
we = (e) => os_name_t(e.name),
z = ref(!1),
B = ref(``),
V = ref(22),
H = ref(1),
U = ref(``),
W = ref(null),
G = 0,
K = !1,
q = {
on: `开机`,
off: `关机`,
reboot: `重启`,
vnc: `打开 VNC 控制台`,
"vnc/restart": `重启 VNC`,
"vnc/start": `启动 VNC`,
reset_password: `重置密码`,
reinstall: `重装系统`,
rescue: `进入救援模式`,
"rescue/exit": `退出救援模式`,
},
J = computed(() => D.value === `reinstall`),
Y = computed(
() => D.value === `reinstall` || D.value === `reset_password`,
),
X = computed(() =>
D.value === `reinstall`
? Number(C.detail.info.value?.config?.reinstall_sms_verify) ===
1
: D.value === `reset_password` &&
Number(
C.detail.info.value?.config?.reset_password_sms_verify,
) === 1,
),
Z = computed(
() => C.host.status === `Active` && C.detail.canControl.value,
),
Te = computed(() =>
D.value === `reinstall`
? `重装会覆盖所选分区并删除其中的数据。请先完成备份,再确认继续。`
: D.value === `off`
? `关机后,该实例上的服务将停止运行。`
: [`reboot`, `rescue`, `rescue/exit`].includes(D.value || ``)
? `此操作会中断当前连接,实例上的服务可能暂时不可用。`
: D.value === `reset_password`
? `密码修改后,请使用新密码连接服务器。部分系统可能需要重启后生效。`
: `请确认目标实例后继续。`,
);
function Ee(e) {
return e === `rescue` || e === `rescue/exit`
? !!C.detail.remote?.value && !C.detail.remoteLoading?.value
: !0;
}
function Q() {
return (
!K &&
Z.value &&
O.value === `${C.module}:${C.hostId}` &&
String(C.host.id) === C.hostId
);
}
function De() {
k.value ||
(G++,
(D.value = null),
(N.value = ``),
(P.value = ``),
(A.value = ``),
(W.value = null));
}
async function $(e) {
if (!Z.value || k.value || K || !(e in q) || !Ee(e)) return;
if (e === `vnc`) {
remote_console_t(C.hostId, C.module);
return;
}
let t = ++G;
if (
((O.value = `${C.module}:${C.hostId}`),
(D.value = e),
(A.value = ``),
(M.value = ``),
(N.value = ``),
(P.value = ``),
(F.value = !1),
(U.value = ``),
(L.value = null),
(R.value = []),
(B.value = ``),
(z.value = !1),
e === `reinstall`)
) {
z.value = !0;
try {
let e = await T.get(
`/product/${C.productId}/${C.module}/image`,
);
if (t !== G || !Q()) return;
R.value = (e.list || []).flatMap((e) => e.image || []);
} catch (e) {
t === G &&
Q() &&
(B.value =
e instanceof Error ? e.message : `系统镜像加载失败`);
} finally {
t === G && (z.value = !1);
}
}
}
async function Oe() {
if (!D.value || k.value || !Q() || !Ee(D.value)) return;
let e = D.value,
t = G,
n = C.hostId,
r = C.module;
if (((A.value = ``), (j.value = !1), X.value && !U.value.trim())) {
A.value = `请输入账户手机验证码`;
return;
}
if (Y.value && N.value.length < 8) {
A.value = `请设置至少 8 位的新密码`;
return;
}
if (
e === `reinstall` &&
(!L.value || !R.value.some((e) => e.id === L.value))
) {
A.value = `请选择操作系统`;
return;
}
if (
e === `reinstall` &&
(!Number.isInteger(V.value) || V.value < 1 || V.value > 65535)
) {
A.value = `请输入 1 到 65535 之间的端口`;
return;
}
if (J.value && !F.value) {
A.value = `请确认已备份数据并了解重装影响`;
return;
}
let i = () => t === G && Q(),
a = {};
([`mf_dcim`, `remf_dcim`].includes(r) &&
P.value &&
(a.client_operate_password = P.value),
Y.value && (a.password = N.value),
X.value && (a.code = U.value.trim()),
e === `rescue` && (a.type = I.value),
e === `reinstall` &&
Object.assign(a, {
image_id: L.value,
port: V.value,
part_type: H.value,
}),
(k.value = !0));
try {
if (e === `reinstall`) {
let e = L.value,
t = await T.get(`/${r}/${n}/image/check`, {
image_id: e,
});
if (!i()) return;
if (
t.price === null ||
t.price === void 0 ||
String(t.price).trim() === `` ||
!Number.isFinite(Number(t.price)) ||
Number(t.price) < 0
)
throw Error(`镜像费用信息无效,请重试`);
if (Number(t.price) > 0) {
((W.value = {
module: r,
hostId: n,
imageId: Number(e),
price: Number(t.price).toFixed(2),
description: t.description,
}),
(F.value = !1));
return;
}
}
if ((await T.post(`/${r}/${n}/${e}`, a), !i())) return;
((M.value = `${q[e]}指令已提交,请等待实例状态更新。`),
(D.value = null),
(N.value = ``),
(P.value = ``),
w(`refresh`));
} catch (t) {
i() &&
((j.value = !0),
(A.value = t instanceof Error ? t.message : `${q[e]}失败`));
} finally {
t === G && (k.value = !1);
}
}
return (
watch(
[() => C.hostId, () => C.module, () => C.host.status],
() => {
(G++,
(D.value = null),
(k.value = !1),
(N.value = ``),
(P.value = ``),
(W.value = null));
},
{
flush: `sync`,
},
),
watch(
L,
() => {
W.value = null;
},
{
flush: `sync`,
},
),
onBeforeUnmount(() => {
((K = !0), G++);
}),
y({
request: $,
busy: k,
}),
(t, n) => {
let r = ImagePurchaseDialog,
a = OperationNotice,
c = message,
v = InstanceSmsCode,
y = select,
b = button,
x = inputnumber,
S = inputtext,
C = OperatePasswordGate,
w = checkbox,
T = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
r,
{
modelValue: unref(W),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(W) ? (W.value = e) : null),
onAuthorized: (n[1] ||= (e) =>
(M.value = `镜像已授权,请确认备份后重新提交重装`)),
},
null,
8,
[`modelValue`],
),
unref(M)
? (openBlock(),
createBlock(
a,
{
key: 0,
message: unref(M),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
unref(A) && unref(j)
? (openBlock(),
createBlock(
a,
{
key: 1,
severity: `error`,
message: unref(A),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
createVNode(
T,
{
visible: !!unref(D),
header: unref(D) ? q[unref(D)] : ``,
modal: ``,
style: {
width: `520px`,
},
draggable: !1,
closable: !unref(k),
"close-on-escape": !unref(k),
"onUpdate:visible": (n[11] ||= (e) => {
e || De();
}),
},
{
footer: withCtx(() => [
createVNode(
b,
{
label: `取消`,
outlined: ``,
severity: `secondary`,
disabled: unref(k),
onClick: De,
},
null,
8,
[`disabled`],
),
createVNode(
b,
{
label: `确认${unref(D) ? q[unref(D)] : ``}`,
severity:
unref(D) === `vnc` || unref(D) === `on`
? `primary`
: `danger`,
loading: unref(k),
disabled: unref(k) || unref(z) || !unref(Z),
onClick: Oe,
},
null,
8,
[`label`, `severity`, `loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, fe, [
createElementVNode(`p`, pe, [
(n[12] ||= createTextVNode(`目标实例:`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
h.host.name ||
unref(product_name_n)(h.host.product_name),
),
1,
),
createTextVNode(
`(#` + toDisplayString(h.hostId) + `)`,
1,
),
]),
createVNode(
c,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(Te)),
1,
),
]),
_: 1,
},
),
unref(A) && !unref(j)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(A)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(X)
? (openBlock(),
createBlock(
v,
{
key: 1,
modelValue: unref(U),
"onUpdate:modelValue": (n[2] ||= (e) =>
isRef(U) ? (U.value = e) : null),
disabled: unref(k),
},
null,
8,
[`modelValue`, `disabled`],
))
: createCommentVNode(``, !0),
unref(D) === `reinstall`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(
`span`,
{
id: `${unref(E)}-image-label`,
},
`操作系统`,
8,
me,
),
createVNode(
y,
{
modelValue: unref(L),
"onUpdate:modelValue": (n[3] ||= (e) =>
isRef(L) ? (L.value = e) : null),
"input-id": `${unref(E)}-image`,
"aria-labelledby": `${unref(E)}-image-label`,
options: unref(R),
"option-label": we,
"option-value": `id`,
placeholder: `请选择操作系统`,
loading: unref(z),
disabled: unref(k) || unref(z),
fluid: ``,
},
null,
8,
[
`modelValue`,
`input-id`,
`aria-labelledby`,
`options`,
`loading`,
`disabled`,
],
),
unref(B)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(B)),
1,
),
createVNode(b, {
label: `重试`,
text: ``,
onClick: (n[4] ||= (e) =>
$(`reinstall`)),
}),
]),
_: 1,
},
))
: !unref(z) && !unref(R).length
? (openBlock(),
createElementBlock(
`p`,
he,
`此商品暂无可用系统镜像。`,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ge, [
createElementVNode(`div`, null, [
createElementVNode(
`label`,
{
for: `${unref(E)}-port`,
},
`连接端口`,
8,
_e,
),
createVNode(
x,
{
modelValue: unref(V),
"onUpdate:modelValue": (n[5] ||= (
e,
) =>
isRef(V) ? (V.value = e) : null),
"input-id": `${unref(E)}-port`,
min: 1,
max: 65535,
"use-grouping": !1,
disabled: unref(k),
fluid: ``,
},
null,
8,
[
`modelValue`,
`input-id`,
`disabled`,
],
),
]),
createElementVNode(`div`, null, [
createElementVNode(
`span`,
{
id: `${unref(E)}-partition-label`,
},
`分区方式`,
8,
ve,
),
createVNode(
y,
{
modelValue: unref(H),
"onUpdate:modelValue": (n[6] ||= (
e,
) =>
isRef(H) ? (H.value = e) : null),
"aria-labelledby": `${unref(E)}-partition-label`,
options: [
{
label: `仅格式化第一分区`,
value: 1,
},
{
label: `格式化全盘`,
value: 0,
},
],
"option-label": `label`,
"option-value": `value`,
disabled: unref(k),
fluid: ``,
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`disabled`,
],
),
]),
]),
],
64,
))
: createCommentVNode(``, !0),
unref(Y)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
createElementVNode(
`label`,
{
for: `${unref(E)}-password`,
},
`新密码`,
8,
ye,
),
createVNode(
S,
{
id: `${unref(E)}-password`,
modelValue: unref(N),
"onUpdate:modelValue": (n[7] ||= (e) =>
isRef(N) ? (N.value = e) : null),
type: `password`,
autocomplete: `new-password`,
disabled: unref(k),
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
],
64,
))
: createCommentVNode(``, !0),
unref(D) === `rescue`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 4,
},
[
createElementVNode(
`span`,
{
id: `${unref(E)}-rescue-label`,
},
`救援系统`,
8,
be,
),
createVNode(
y,
{
modelValue: unref(I),
"onUpdate:modelValue": (n[8] ||= (e) =>
isRef(I) ? (I.value = e) : null),
"aria-labelledby": `${unref(E)}-rescue-label`,
options: [
{
label: `Linux`,
value: 2,
},
{
label: `Windows`,
value: 1,
},
],
"option-label": `label`,
"option-value": `value`,
disabled: unref(k),
fluid: ``,
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`disabled`,
],
),
],
64,
))
: createCommentVNode(``, !0),
[`mf_dcim`, `remf_dcim`].includes(h.module)
? (openBlock(),
createBlock(
C,
{
key: 5,
},
{
default: withCtx(() => [
createElementVNode(
`label`,
{
for: `${unref(E)}-operate`,
},
`操作密码(如已设置)`,
8,
xe,
),
createVNode(
S,
{
id: `${unref(E)}-operate`,
modelValue: unref(P),
"onUpdate:modelValue": (n[9] ||= (
e,
) =>
isRef(P) ? (P.value = e) : null),
type: `password`,
autocomplete: `off`,
disabled: unref(k),
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(J)
? (openBlock(),
createElementBlock(`div`, Se, [
createVNode(
w,
{
modelValue: unref(F),
"onUpdate:modelValue": (n[10] ||= (e) =>
isRef(F) ? (F.value = e) : null),
"input-id": `${unref(E)}-ack`,
binary: ``,
disabled: unref(k),
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
createElementVNode(
`label`,
{
for: `${unref(E)}-ack`,
},
`我已备份数据,了解所选分区的数据将被清除`,
8,
Ce,
),
]))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `header`, `closable`, `close-on-escape`],
),
],
64,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-a1044895`]],
),
{
__name: `DcimActions`,
},
);
export {};
export default S;
</script>
+989
View File
@@ -0,0 +1,989 @@
<script>
import "~/assets/styles/InstanceRenewDialog.BHDAL6d3.css";
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
import "~/assets/styles/SecurityVerificationDialog.skYFo4v7.css";
import "~/assets/styles/DcimBilling.QV7PUjnH.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { navigateTo } from "#app";
import { NuxtLink } from "#components";
import { sanitizeMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import { assertSecurityComplete } from "~/lib/auth.js";
import { securityChallenge } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { c as dict_c } from "~/lib/dict.js";
import { l as dict_l } from "~/lib/dict.js";
import { r as dict_r } from "~/lib/dict.js";
import select from "primevue/select";
import OperationNotice from "~/components/OperationNotice.vue";
import textarea from "primevue/textarea";
import tag from "primevue/tag";
import SecurityVerificationDialog from "~/components/SecurityVerificationDialog.vue";
import InstanceRenewDialog from "~/components/instance/InstanceRenewDialog.vue";
var he = {
class: `billing`,
},
ge = {
class: `rows`,
},
_e = {
key: 1,
},
ve = {
key: 0,
},
ye = {
key: 0,
},
be = {
key: 1,
},
xe = {
class: `order-row`,
},
Se = {
key: 1,
},
Ce = {
class: `muted`,
},
we = {
class: `form`,
},
Te = {
key: 1,
},
Ee = [`id`],
De = [`for`],
Oe = [`id`],
ke = {
key: 3,
},
C = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimBilling`,
props: {
hostId: {},
host: {},
},
emits: [`refresh`],
setup(g, { emit: S }) {
let C = g,
w = S,
T = useApi(),
E = ref(``),
D = useId(),
O = ref(!1),
k = ref(null),
A = ref(``),
j = ref(``),
M = ref(``),
N = ref(``),
P = ref(!1),
F = ref(!1),
I = ref(null),
L = ref(`Expire`),
R = ref(null),
z = ref(``),
B = ref(!1),
V = ref({}),
H = ref(null),
U = ref(null),
W = ref(null),
Ae = {
Pending: `待审核`,
Suspending: `待停用`,
Suspend: `停用中`,
Suspended: `已停用`,
Refund: `已退款`,
Reject: `已驳回`,
Cancelled: `已取消`,
},
je = computed(
() =>
!C.host.renew_forbidden &&
![`Deleted`, `Unpaid`, `Cancelled`, `Failed`].includes(
C.host.status,
),
),
G = computed(
() =>
!F.value &&
!j.value &&
Number(U.value?.allow_refund) === 1 &&
(!W.value || [`Reject`, `Cancelled`].includes(W.value.status)),
),
K = computed(
() =>
!F.value &&
!j.value &&
[`Pending`, `Suspending`, `Suspend`].includes(
W.value?.status || ``,
),
),
q = 0,
J = 0,
Y = !1,
X = (e, t) =>
!Y && e === C.hostId && String(C.host.id) === e && t === J;
async function Z() {
let e = ++q,
t = C.hostId;
((F.value = !0),
(k.value = null),
(U.value = null),
(W.value = null),
(A.value = ``),
(j.value = ``));
let n = await Promise.allSettled([
T.get(`/host/${t}/renew/auto`),
T.get(`/refund`, {
host_id: t,
}),
T.get(`/refund/host/${t}/refund`),
]);
if (Y || e !== q || t !== C.hostId) return;
let [r, i, a] = n;
(r.status === `fulfilled` &&
[0, 1].includes(Number(r.value?.status))
? (k.value = Number(r.value.status))
: (A.value =
r.status === `rejected` && r.reason instanceof Error
? r.reason.message
: `自动续费状态不可用`),
i.status === `fulfilled`
? (U.value = i.value)
: (j.value =
i.reason instanceof Error
? i.reason.message
: `停用信息暂不可用`),
a.status === `fulfilled` && a.value && `refund` in a.value
? (W.value = a.value.refund)
: (j.value =
a.status === `rejected` && a.reason instanceof Error
? a.reason.message
: `停用记录暂不可用`),
(F.value = !1));
}
function Q(e) {
P.value ||
F.value ||
B.value ||
String(C.host.id) !== C.hostId ||
(e === `auto` && k.value === null) ||
(e === `refund` && !G.value) ||
(e === `cancel` && !K.value) ||
((I.value = e),
(M.value = ``),
(E.value = ``),
(N.value = ``),
(L.value = `Expire`),
(z.value = ``),
(R.value = null),
(H.value = null));
}
function $() {
!P.value &&
!B.value &&
((I.value = null), (M.value = ``), (H.value = null));
}
async function Me() {
if (
P.value ||
B.value ||
!I.value ||
Y ||
String(C.host.id) !== C.hostId
)
return;
let e = I.value,
t = C.hostId,
n = J,
r = () => X(t, n);
if (
((M.value = ``),
(E.value = ``),
(e === `auto` && k.value === null) ||
(e === `refund` && !G.value) ||
(e === `cancel` && !K.value))
)
return;
if (
e === `refund` &&
(U.value?.reason_custom ? !z.value.trim() : !R.value)
) {
M.value = `请填写或选择停用原因`;
return;
}
let i = {
host_id: Number(t),
type: L.value,
suspend_reason: U.value?.reason_custom
? z.value.trim()
: [R.value],
};
P.value = !0;
try {
if (e === `auto`) {
let e = k.value === 1 ? 0 : 1;
(await T.put(`/host/${t}/renew/auto`, {
status: e,
}),
r() && (k.value = e));
} else if (e === `cancel`)
await T.put(`/refund/${W.value.id}/cancel`);
else {
let e = await T.post(`/refund`, i);
if (!r()) return;
assertSecurityComplete(e);
}
if (!r()) return;
((I.value = null),
(N.value =
e === `auto`
? `自动续费设置已更新`
: e === `cancel`
? `停用申请已取消`
: `停用申请已提交`),
e !== `auto` && (await Z()));
} catch (t) {
if (!r()) return;
let n = e === `refund` ? securityChallenge(t) : null;
n
? ((H.value = i), (V.value = n), (B.value = !0))
: (E.value =
t instanceof Error ? t.message : `操作失败,请重试`);
} finally {
r() && (P.value = !1);
}
}
async function Ne(e) {
let t = H.value,
n = C.hostId,
r = J;
if (
t &&
!P.value &&
B.value &&
Number(n) === t.host_id &&
X(n, r)
) {
((P.value = !0), (E.value = ``));
try {
let i = await T.post(`/refund`, {
...t,
...e,
});
if (!X(n, r)) return;
(assertSecurityComplete(i),
(H.value = null),
(B.value = !1),
(I.value = null),
(N.value = `停用申请已提交`),
await Z(),
X(n, r) && w(`refresh`));
} catch (e) {
if (!X(n, r)) return;
let t = securityChallenge(e);
t
? ((V.value = t), (E.value = `安全验证尚未完成,请重试`))
: (E.value =
e instanceof Error ? e.message : `操作失败,请重试`);
} finally {
X(n, r) && (P.value = !1);
}
}
}
return (
watch(
() => C.hostId,
() => {
(J++,
(I.value = null),
(P.value = !1),
(O.value = !1),
(H.value = null),
(B.value = !1),
(V.value = {}),
(E.value = ``),
(N.value = ``),
Z());
},
{
flush: `sync`,
},
),
onMounted(Z),
onBeforeUnmount(() => {
((Y = !0), q++, J++, (H.value = null), (B.value = !1));
}),
(t, n) => {
let r = OperationNotice,
i = tag,
o = button,
l = NuxtLink,
y = InstanceRenewDialog,
b = message,
x = select,
S = textarea,
C = dialog,
T = SecurityVerificationDialog;
return (
openBlock(),
createElementBlock(`div`, he, [
createVNode(
r,
{
message: unref(E),
severity: `error`,
},
null,
8,
[`message`],
),
createVNode(
r,
{
message: unref(N),
severity: `success`,
},
null,
8,
[`message`],
),
(n[24] ||= createElementVNode(`h3`, null, `计费信息`, -1)),
createElementVNode(`dl`, ge, [
createElementVNode(`div`, null, [
(n[12] ||= createElementVNode(
`dt`,
null,
`计费方式`,
-1,
)),
createElementVNode(
`dd`,
null,
toDisplayString(
g.host.billing_cycle_name ||
g.host.billing_cycle ||
`—`,
),
1,
),
]),
createElementVNode(`div`, null, [
(n[13] ||= createElementVNode(`dt`, null, `状态`, -1)),
createElementVNode(`dd`, null, [
createVNode(
i,
{
value: (`statusLabel` in t
? t.statusLabel
: unref(dict_c))(g.host.status),
severity: (`statusSeverity` in t
? t.statusSeverity
: unref(dict_l))(g.host.status),
},
null,
8,
[`value`, `severity`],
),
]),
]),
createElementVNode(`div`, null, [
(n[14] ||= createElementVNode(
`dt`,
null,
`自动续费`,
-1,
)),
createElementVNode(`dd`, null, [
createElementVNode(
`span`,
null,
toDisplayString(
unref(F)
? `加载中…`
: unref(k) === null
? `状态不可用`
: unref(k)
? `已开启`
: `已关闭`,
),
1,
),
unref(k) === null
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
o,
{
key: 0,
label: unref(k) ? `关闭` : `开启`,
text: ``,
size: `small`,
disabled: unref(P) || unref(F),
onClick: (n[0] ||= (e) => Q(`auto`)),
},
null,
8,
[`label`, `disabled`],
)),
unref(A)
? (openBlock(),
createElementBlock(
`small`,
_e,
toDisplayString(unref(A)),
1,
))
: createCommentVNode(``, !0),
]),
]),
createElementVNode(`div`, null, [
(n[15] ||= createElementVNode(
`dt`,
null,
`续费金额`,
-1,
)),
createElementVNode(`dd`, null, [
createTextVNode(
`¥` + toDisplayString(g.host.renew_amount),
1,
),
createVNode(
o,
{
label: `续费`,
size: `small`,
text: ``,
disabled: !unref(je),
onClick: (n[1] ||= (e) => (O.value = !0)),
},
null,
8,
[`disabled`],
),
]),
]),
createElementVNode(`div`, null, [
(n[16] ||= createElementVNode(
`dt`,
null,
`开通时间`,
-1,
)),
createElementVNode(
`dd`,
null,
toDisplayString(
(`formatTime` in t ? t.formatTime : unref(dict_r))(
g.host.active_time,
),
),
1,
),
]),
createElementVNode(`div`, null, [
(n[17] ||= createElementVNode(
`dt`,
null,
`到期时间`,
-1,
)),
createElementVNode(
`dd`,
null,
toDisplayString(
(`formatTime` in t ? t.formatTime : unref(dict_r))(
g.host.due_time,
),
),
1,
),
]),
createElementVNode(`div`, null, [
(n[18] ||= createElementVNode(
`dt`,
null,
`停用 / 退款`,
-1,
)),
createElementVNode(`dd`, null, [
unref(F)
? (openBlock(),
createElementBlock(`span`, ve, `加载中…`))
: unref(j)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`span`,
null,
toDisplayString(unref(j)),
1,
),
createVNode(o, {
label: `重试`,
text: ``,
size: `small`,
onClick: Z,
}),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
unref(W)
? (openBlock(),
createElementBlock(`span`, ye, [
createTextVNode(
toDisplayString(
Ae[unref(W).status] ||
unref(W).status,
),
1,
),
unref(W).reject_reason
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
` · ` +
toDisplayString(
unref(sanitizeMessage)(
unref(W).reject_reason,
),
),
1,
),
],
64,
))
: createCommentVNode(``, !0),
]))
: unref(G)
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`span`,
be,
`当前实例不支持申请停用 / 退款`,
)),
unref(G)
? (openBlock(),
createBlock(o, {
key: 2,
label: `申请停用`,
text: ``,
severity: `danger`,
size: `small`,
onClick: (n[2] ||= (e) => Q(`refund`)),
}))
: createCommentVNode(``, !0),
unref(K)
? (openBlock(),
createBlock(o, {
key: 3,
label: `取消申请`,
text: ``,
size: `small`,
onClick: (n[3] ||= (e) => Q(`cancel`)),
}))
: createCommentVNode(``, !0),
],
64,
)),
]),
]),
]),
(n[25] ||= createElementVNode(`h3`, null, `关联订单`, -1)),
createElementVNode(`div`, xe, [
(n[19] ||= createElementVNode(
`span`,
null,
`开通订单`,
-1,
)),
g.host.order_id
? (openBlock(),
createBlock(
l,
{
key: 0,
to: `/orders/${g.host.order_id}`,
},
{
default: withCtx(() => [
createTextVNode(
`#` + toDisplayString(g.host.order_id),
1,
),
]),
_: 1,
},
8,
[`to`],
))
: (openBlock(),
createElementBlock(`span`, Se, `暂无关联订单`)),
]),
createElementVNode(`p`, Ce, [
(n[21] ||= createTextVNode(`续费及变更订单可前往`, -1)),
createVNode(
l,
{
to: `/orders`,
},
{
default: withCtx(() => [
...(n[20] ||= [createTextVNode(`订单管理`, -1)]),
]),
_: 1,
},
),
(n[22] ||= createTextVNode(`查看。`, -1)),
]),
createVNode(
y,
{
modelValue: unref(O),
"onUpdate:modelValue": (n[4] ||= (e) =>
isRef(O) ? (O.value = e) : null),
"host-id": g.hostId,
onPaid: (n[5] ||= (e) => {
(w(`refresh`),
(`navigateTo` in t
? t.navigateTo
: unref(navigateTo))(`/orders`));
}),
},
null,
8,
[`modelValue`, `host-id`],
),
createVNode(
C,
{
visible: !!unref(I),
header:
unref(I) === `auto`
? `确认自动续费设置`
: unref(I) === `refund`
? `确认申请停用`
: `确认取消申请`,
modal: ``,
style: {
width: `500px`,
},
closable: !unref(P) && !unref(B),
"close-on-escape": !unref(P) && !unref(B),
"onUpdate:visible": (n[9] ||= (e) => {
e || $();
}),
},
{
footer: withCtx(() => [
createVNode(
o,
{
label: `取消`,
outlined: ``,
severity: `secondary`,
disabled: unref(P) || unref(B),
onClick: $,
},
null,
8,
[`disabled`],
),
createVNode(
o,
{
label: `确认`,
severity:
unref(I) === `refund` ? `danger` : `primary`,
loading: unref(P),
disabled: unref(P) || unref(B),
onClick: Me,
},
null,
8,
[`severity`, `loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, we, [
createElementVNode(
`p`,
null,
`实例「` +
toDisplayString(g.host.name) +
`」(#` +
toDisplayString(g.hostId) +
`)`,
1,
),
unref(M)
? (openBlock(),
createBlock(
b,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(M)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(I) === `auto`
? (openBlock(),
createElementBlock(
`p`,
Te,
`确认` +
toDisplayString(unref(k) ? `关闭` : `开启`) +
`自动续费?开启后将按平台规则扣取余额续费。`,
1,
))
: unref(I) === `refund`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createVNode(
b,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
...(n[23] ||= [
createTextVNode(
`停用后服务将不可用,请提前备份数据。退款金额以审核结果为准。`,
-1,
),
]),
]),
_: 1,
},
),
createElementVNode(
`span`,
{
id: `${unref(D)}-type-label`,
},
`停用时间`,
8,
Ee,
),
createVNode(
x,
{
modelValue: unref(L),
"onUpdate:modelValue": (n[6] ||= (e) =>
isRef(L) ? (L.value = e) : null),
"aria-labelledby": `${unref(D)}-type-label`,
options: [
{
label: `到期停用`,
value: `Expire`,
},
{
label: `立即停用`,
value: `Immediate`,
},
],
"option-label": `label`,
"option-value": `value`,
disabled: unref(P) || unref(B),
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`disabled`,
],
),
unref(U)?.reason_custom
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(
`label`,
{
for: `${unref(D)}-reason`,
},
`停用原因`,
8,
De,
),
createVNode(
S,
{
id: `${unref(D)}-reason`,
modelValue: unref(z),
"onUpdate:modelValue": (n[7] ||=
(e) =>
isRef(z)
? (z.value = e)
: null),
disabled: unref(P) || unref(B),
rows: `3`,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`span`,
{
id: `${unref(D)}-reason-label`,
},
`停用原因`,
8,
Oe,
),
createVNode(
x,
{
modelValue: unref(R),
"onUpdate:modelValue": (n[8] ||=
(e) =>
isRef(R)
? (R.value = e)
: null),
"aria-labelledby": `${unref(D)}-reason-label`,
options:
unref(U)?.reasons || [],
"option-label": `content`,
"option-value": `id`,
disabled: unref(P) || unref(B),
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`options`,
`disabled`,
],
),
],
64,
)),
],
64,
))
: (openBlock(),
createElementBlock(
`p`,
ke,
`确认取消尚未处理的停用申请?`,
)),
]),
]),
_: 1,
},
8,
[`visible`, `header`, `closable`, `close-on-escape`],
),
createVNode(
T,
{
visible: unref(B),
"onUpdate:visible": (n[10] ||= (e) =>
isRef(B) ? (B.value = e) : null),
challenge: unref(V),
busy: unref(P),
"request-error": unref(E),
context: {
scene: `account`,
action: `host_refund`,
},
onVerified: Ne,
onCancel: (n[11] ||= (e) => (H.value = null)),
},
null,
8,
[`visible`, `challenge`, `busy`, `request-error`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-9a8e05c2`]],
),
{
__name: `DcimBilling`,
},
);
export {};
export default C;
</script>
+636
View File
@@ -0,0 +1,636 @@
<script>
import "~/assets/styles/DcimDefence.BYaQccXZ.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { navigateTo } from "#app";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import select from "primevue/select";
import OperationNotice from "~/components/OperationNotice.vue";
import skeleton from "primevue/skeleton";
var T = {
class: `defence`,
},
E = {
class: `head`,
},
D = [`id`],
O = {
class: `rows`,
},
k = {
key: 0,
class: `config-error`,
},
A = {
key: 1,
class: `muted`,
},
j = {
class: `form`,
},
re = [`id`],
ie = {
key: 0,
},
ae = {
key: 1,
class: `muted`,
},
M = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimDefence`,
props: {
hostId: {},
module: {},
ip: {},
additionalIp: {},
peak: {},
active: {
type: Boolean,
},
upgradeAllowed: {
type: Boolean,
default: !0,
},
},
setup(g) {
let x = g,
M = useApi(),
N = ref(``),
P = useId(),
F = ref(x.ip),
I = computed(() => [
...new Set(
[x.ip, ...(x.additionalIp || ``).split(/[,;]/)]
.map((e) => e.trim())
.filter(Boolean),
),
]),
L = ref([]),
R = ref(``),
z = ref(!1),
B = ref(``),
V = ref(!1),
H = ref(!1),
U = ref(``),
W = ref(!1),
G = ref(``),
K = ref(null),
q = 0,
J = 0,
Y = !1,
X = computed(() =>
L.value.filter((e) => String(e.value) !== String(R.value)),
);
async function Z() {
let e = ++q,
t = F.value,
n = x.hostId;
if (
((L.value = []),
(R.value = ``),
(B.value = ``),
(z.value = !0),
!t || x.upgradeAllowed === !1)
) {
z.value = !1;
return;
}
try {
let r = await M.get(`/${x.module}/${n}/upgrade_defence_config`, {
ip: t,
});
if (Y || e !== q || t !== F.value || n !== x.hostId) return;
((L.value = Array.isArray(r.defence) ? r.defence : []),
(R.value = r.current_defence ?? ``));
} catch (t) {
!Y &&
e === q &&
(B.value = t instanceof Error ? t.message : `防御配置暂不可用`);
} finally {
!Y && e === q && (z.value = !1);
}
}
function oe() {
x.upgradeAllowed !== !1 &&
x.active &&
!H.value &&
!z.value &&
X.value.length &&
(J++,
(U.value = ``),
(K.value = null),
(G.value = ``),
(V.value = !0));
}
function Q() {
H.value || ((V.value = !1), J++, (W.value = !1), (K.value = null));
}
async function $() {
if (x.upgradeAllowed === !1) return;
let e = ++J,
t = U.value,
n = F.value,
r = x.hostId;
if (((K.value = null), (G.value = ``), (W.value = !0), !t)) {
W.value = !1;
return;
}
try {
let i = await M.get(`/${x.module}/${r}/upgrade_defence/price`, {
ip: n,
peak_defence: t,
});
if (
Y ||
e !== J ||
t !== U.value ||
n !== F.value ||
r !== x.hostId
)
return;
if (
i.price == null ||
!Number.isFinite(Number(i.price)) ||
Number(i.price) < 0
)
throw Error(`防御报价无效,请重试`);
K.value = i;
} catch (t) {
!Y &&
e === J &&
(G.value = t instanceof Error ? t.message : `获取防御报价失败`);
} finally {
!Y && e === J && (W.value = !1);
}
}
async function se() {
if (
x.upgradeAllowed === !1 ||
H.value ||
!x.active ||
!V.value ||
!K.value ||
W.value ||
!X.value.some((e) => String(e.value) === String(U.value))
)
return;
let e = J,
t = x.hostId,
n = F.value;
((H.value = !0), (G.value = ``), (N.value = ``));
try {
let r = await M.post(`/${x.module}/${t}/upgrade_defence/order`, {
ip: n,
peak_defence: U.value,
});
if (Y || e !== J || t !== x.hostId || n !== F.value) return;
if (!r.id)
throw Error(`订单编号未返回,请在订单管理中检查后再试`);
((V.value = !1), await navigateTo(`/orders/${r.id}`));
} catch (t) {
!Y &&
e === J &&
(N.value = t instanceof Error ? t.message : `创建防御订单失败`);
} finally {
!Y && e === J && (H.value = !1);
}
}
return (
watch(F, () => {
(Q(), Z());
}),
watch([() => x.hostId, () => x.module], () => {
(q++, J++, (H.value = !1), (V.value = !1), (F.value = x.ip), Z());
}),
onMounted(Z),
onBeforeUnmount(() => {
((Y = !0), q++, J++);
}),
(t, n) => {
let r = OperationNotice,
i = message,
o = select,
l = button,
y = skeleton,
b = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
r,
{
message: unref(N),
severity: `error`,
},
null,
8,
[`message`],
),
createElementVNode(`div`, T, [
createVNode(
i,
{
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
(n[3] ||= createTextVNode(`当前实例可查看`, -1)),
g.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[createTextVNode(`和调整`)],
64,
)),
(n[4] ||= createTextVNode(
`平台提供的防御配置,暂未提供攻击事件与黑洞记录查询。`,
-1,
)),
]),
_: 1,
},
),
createElementVNode(`div`, E, [
(n[5] ||= createElementVNode(
`h3`,
null,
`DDoS 防护`,
-1,
)),
createElementVNode(
`span`,
{
id: `${unref(P)}-ip-label`,
},
`IP 地址`,
8,
D,
),
createVNode(
o,
{
modelValue: unref(F),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(F) ? (F.value = e) : null),
options: unref(I),
"aria-labelledby": `${unref(P)}-ip-label`,
disabled: unref(H),
},
null,
8,
[
`modelValue`,
`options`,
`aria-labelledby`,
`disabled`,
],
),
createVNode(
l,
{
label: `刷新`,
text: ``,
icon: `pi pi-refresh`,
loading: unref(z),
onClick: Z,
},
null,
8,
[`loading`],
),
]),
createElementVNode(`dl`, O, [
createElementVNode(`div`, null, [
(n[6] ||= createElementVNode(
`dt`,
null,
`防御峰值`,
-1,
)),
createElementVNode(`dd`, null, [
createTextVNode(
toDisplayString(
unref(R) || g.peak != null
? `${unref(R) || g.peak} Gbps`
: `未提供`,
),
1,
),
g.upgradeAllowed !== !1 && unref(X).length
? (openBlock(),
createBlock(
l,
{
key: 0,
label: `调整防御`,
text: ``,
size: `small`,
disabled: !g.active || unref(H),
onClick: oe,
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
]),
]),
]),
unref(B)
? (openBlock(),
createElementBlock(`div`, k, [
createElementVNode(
`span`,
null,
toDisplayString(unref(B)),
1,
),
createVNode(l, {
label: `重试`,
text: ``,
size: `small`,
onClick: Z,
}),
]))
: g.upgradeAllowed !== !1 &&
!unref(z) &&
!unref(X).length
? (openBlock(),
createElementBlock(
`p`,
A,
`此 IP 暂无可选的防御调整配置。`,
))
: createCommentVNode(``, !0),
(n[7] ||= createElementVNode(`h3`, null, `攻击记录`, -1)),
(n[8] ||= createElementVNode(
`p`,
{
class: `unavailable`,
},
`攻击记录暂不可用`,
-1,
)),
(n[9] ||= createElementVNode(`h3`, null, `黑洞记录`, -1)),
(n[10] ||= createElementVNode(
`p`,
{
class: `unavailable`,
},
`黑洞记录暂不可用`,
-1,
)),
]),
g.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
b,
{
key: 0,
visible: unref(V),
header: `确认调整防御`,
modal: ``,
style: {
width: `480px`,
},
closable: !unref(H),
"close-on-escape": !unref(H),
"onUpdate:visible": (n[2] ||= (e) => {
e || Q();
}),
},
{
footer: withCtx(() => [
createVNode(
l,
{
label: `取消`,
severity: `secondary`,
outlined: ``,
disabled: unref(H),
onClick: Q,
},
null,
8,
[`disabled`],
),
createVNode(
l,
{
label: `确认并创建订单`,
loading: unref(H),
disabled:
unref(H) ||
!unref(K) ||
unref(W) ||
!g.active,
onClick: se,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, j, [
createElementVNode(
`p`,
null,
`实例 #` +
toDisplayString(g.hostId) +
` · ` +
toDisplayString(unref(F)),
1,
),
createElementVNode(
`span`,
{
id: `${unref(P)}-peak-label`,
},
`防御配置`,
8,
re,
),
createVNode(
o,
{
modelValue: unref(U),
"onUpdate:modelValue": (n[1] ||= (e) =>
isRef(U) ? (U.value = e) : null),
options: unref(X),
"option-label": `desc`,
"option-value": `value`,
"aria-labelledby": `${unref(P)}-peak-label`,
disabled: unref(H),
placeholder: `选择防御配置`,
onChange: $,
},
null,
8,
[
`modelValue`,
`options`,
`aria-labelledby`,
`disabled`,
],
),
unref(W)
? (openBlock(),
createBlock(y, {
key: 0,
height: `60px`,
}))
: unref(K)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(`p`, null, [
(n[11] ||= createTextVNode(
`本次费用:`,
-1,
)),
createElementVNode(
`strong`,
null,
`¥` +
toDisplayString(unref(K).price),
1,
),
]),
unref(K).renew_price_difference ==
null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
ie,
`续费差价:¥` +
toDisplayString(
unref(K)
.renew_price_difference,
),
1,
)),
unref(K).description
? (openBlock(),
createElementBlock(
`p`,
ae,
toDisplayString(
unref(K).description,
),
1,
))
: createCommentVNode(``, !0),
],
64,
))
: createCommentVNode(``, !0),
unref(G)
? (openBlock(),
createBlock(
i,
{
key: 2,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(G)),
1,
),
!unref(H) && !unref(K)
? (openBlock(),
createBlock(l, {
key: 0,
label: `重试报价`,
text: ``,
size: `small`,
onClick: $,
}))
: createCommentVNode(``, !0),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
i,
{
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(n[12] ||= [
createTextVNode(
`确认后将创建调整订单,请核对费用后完成付款。`,
-1,
),
]),
]),
_: 1,
},
),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
)),
],
64,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-2f38c55b`]],
),
{
__name: `DcimDefence`,
},
);
export {};
export default M;
</script>
+356
View File
@@ -0,0 +1,356 @@
<script>
import "~/assets/styles/DcimDomains.BT2s5hGW.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { sanitizeMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import paginator from "primevue/paginator";
import column from "primevue/column";
import tag from "primevue/tag";
var E = {
class: `domains`,
},
D = {
class: `toolbar`,
},
O = {
class: `empty`,
},
k = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimDomains`,
props: {
hostId: {},
},
setup(f) {
let y = f,
k = useApi(),
A = ref(null),
j = ref(``),
M = ref(!1),
N = ref([]),
P = ref(0),
F = ref(0),
I = 0,
L = !1;
async function R() {
let e = ++I,
t = y.hostId;
((M.value = !0), (j.value = ``), (N.value = []));
try {
let n = await k.get(`/domain_whitelist/host`);
if (L || e !== I || t !== y.hostId) return;
A.value = (n.list || []).some((e) => String(e.id) === t);
let r = await k.get(`/domain_whitelist/record`, {
host_id: t,
page: P.value + 1,
limit: 10,
});
if (L || e !== I || t !== y.hostId) return;
((N.value = r.list || []), (F.value = Number(r.count || 0)));
} catch (t) {
!L &&
e === I &&
(j.value =
t instanceof Error ? t.message : `域名白名单加载失败`);
} finally {
!L && e === I && (M.value = !1);
}
}
return (
watch(
() => y.hostId,
() => {
((A.value = null), (P.value = 0), R());
},
),
onMounted(R),
onBeforeUnmount(() => {
((L = !0), I++);
}),
(t, n) => {
let r = message,
a = NuxtLink,
_ = button,
y = column,
k = tag,
I = datatable,
L = paginator;
return (
openBlock(),
createElementBlock(`div`, E, [
createVNode(
r,
{
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(n[1] ||= [
createTextVNode(
`域名白名单用于为当前实例提交域名访问申请,审核结果以平台记录为准。`,
-1,
),
]),
]),
_: 1,
},
),
createElementVNode(`div`, D, [
(n[3] ||= createElementVNode(`h3`, null, `域名白名单`, -1)),
unref(A)
? (openBlock(),
createBlock(
a,
{
key: 0,
class: `p-button p-button-sm`,
to: {
path: `/security/domain-whitelist`,
query: {
host_id: f.hostId,
},
},
},
{
default: withCtx(() => [
...(n[2] ||= [
createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`管理 / 添加域名`, -1),
]),
]),
_: 1,
},
8,
[`to`],
))
: createCommentVNode(``, !0),
createVNode(
_,
{
label: `刷新`,
icon: `pi pi-refresh`,
severity: `secondary`,
text: ``,
size: `small`,
loading: unref(M),
onClick: R,
},
null,
8,
[`loading`],
),
]),
unref(j)
? (openBlock(),
createBlock(
r,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(j)), 1),
]),
_: 1,
},
))
: unref(A) === !1
? (openBlock(),
createBlock(
r,
{
key: 1,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(n[4] ||= [
createTextVNode(
`此实例尚未配置可用的域名白名单入口,暂不能提交新域名。`,
-1,
),
]),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
I,
{
value: unref(N),
loading: unref(M),
"data-key": `id`,
scrollable: ``,
},
{
empty: withCtx(() => [
createElementVNode(
`div`,
O,
toDisplayString(
unref(j) ? `记录暂不可用` : `暂无域名记录`,
),
1,
),
]),
default: withCtx(() => [
createVNode(
y,
{
header: `域名`,
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(t.domains?.join(`、`) || `—`),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `状态`,
},
{
body: withCtx(({ data: e }) => [
createVNode(
k,
{
value:
e.status === 1
? `已通过`
: e.status === -1
? `已驳回`
: `处理中`,
severity:
e.status === 1
? `success`
: e.status === -1
? `danger`
: `warn`,
},
null,
8,
[`value`, `severity`],
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `驳回原因`,
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(
unref(sanitizeMessage)(t.reject_reason) ||
`—`,
),
1,
),
]),
_: 1,
},
),
createVNode(y, {
field: `remark`,
header: `备注`,
}),
createVNode(
y,
{
header: `创建时间`,
},
{
body: withCtx(({ data: n }) => [
createTextVNode(
toDisplayString(
(`formatTime` in t
? t.formatTime
: unref(dict_r))(n.create_time),
),
1,
),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`],
),
unref(F) > 10
? (openBlock(),
createBlock(
L,
{
key: 2,
rows: 10,
first: unref(P) * 10,
"total-records": unref(F),
onPage: (n[0] ||= (e) => {
((P.value = e.page), R());
}),
},
null,
8,
[`first`, `total-records`],
))
: createCommentVNode(``, !0),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-6c2c5ee1`]],
),
{
__name: `DcimDomains`,
},
);
export {};
export default k;
</script>
File diff suppressed because it is too large. Load diff
+343
View File
@@ -0,0 +1,343 @@
<script>
import "~/assets/styles/DcimMonitor.CiStTCbZ.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { defineAsyncComponent } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { loadModule } from "~/utils/load-module.js";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import skeleton from "primevue/skeleton";
import selectbutton from "primevue/selectbutton";
var T = defineAsyncComponent(() =>
loadModule(
() => import("~/components/ChartBox.vue").then((e) => e.default || e),
[],
import.meta.url,
),
),
E = {
class: `monitor-panel`,
},
D = {
key: 0,
class: `monitor-head`,
},
O = {
class: `legend`,
},
k = [`aria-busy`],
A = {
key: 1,
role: `alert`,
class: `monitor-error`,
},
j = {
key: 3,
class: `empty`,
},
M = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimMonitor`,
props: {
hostId: {},
module: {},
compact: {
type: Boolean,
default: !1,
},
},
setup(a) {
let h = a,
y = useApi(),
S = ref(3600),
M = [
{
label: `1 小时`,
value: 3600,
},
{
label: `24 小时`,
value: 86400,
},
{
label: `7 天`,
value: 604800,
},
{
label: `1 个月`,
value: 2592e3,
},
{
label: `1 年`,
value: 31536e3,
},
],
N = ref(!1),
P = ref(``),
F = ref([]),
I = ref(``),
L = 0,
R = !1,
z = ``;
async function B() {
let e = ++L,
t = h.hostId,
n = h.module,
r = `${n}:${t}:${S.value}`;
(r !== z && ((F.value = []), (I.value = ``)),
(z = r),
(N.value = !0),
(P.value = ``));
try {
let r = await y.get(`/${n}/${t}/chart`, {
start_time: Math.floor(Date.now() / 1e3) - S.value,
});
if (R || e !== L || t !== h.hostId || n !== h.module) return;
((F.value = (Array.isArray(r.list) ? r.list : []).filter((e) =>
Number.isFinite(Number(e.time)),
)),
(I.value = typeof r.unit == `string` ? r.unit : ``));
} catch (t) {
!R &&
e === L &&
(P.value = t instanceof Error ? t.message : `带宽监控加载失败`);
} finally {
!R && e === L && (N.value = !1);
}
}
function V(e) {
return e != null && e !== `` && Number.isFinite(Number(e))
? Number(e)
: null;
}
let H = computed(() =>
F.value.some((e) => V(e.in_bw) !== null || V(e.out_bw) !== null),
),
U = computed(() => ({
color: [`#1687d9`, `#29b6d8`],
tooltip: {
trigger: `axis`,
},
grid: {
left: 8,
right: 8,
top: h.compact ? 10 : 30,
bottom: 8,
outerBoundsMode: `same`,
outerBoundsContain: `axisLabel`,
},
xAxis: {
type: `category`,
boundaryGap: !1,
data: F.value.map((e) =>
new Date(Number(e.time) * 1e3).toLocaleTimeString(`zh-CN`, {
hour: `2-digit`,
minute: `2-digit`,
}),
),
},
yAxis: {
type: `value`,
name: I.value,
min: 0,
splitNumber: h.compact ? 2 : 5,
},
series: [`in_bw`, `out_bw`].map((e, t) => ({
name: t ? `出站` : `入站`,
type: `line`,
showSymbol: !0,
symbol: `circle`,
symbolSize: h.compact ? 3 : 4,
smooth: 0.25,
lineStyle: {
width: 1.5,
},
areaStyle: {
opacity: 0.14,
},
connectNulls: !1,
data: F.value.map((t) => V(t[e])),
})),
}));
return (
watch([() => h.hostId, () => h.module, S], B),
onMounted(B),
onBeforeUnmount(() => {
((R = !0), L++);
}),
(t, r) => {
let i = selectbutton,
s = skeleton,
l = button,
h = T;
return (
openBlock(),
createElementBlock(
`section`,
{
class: normalizeClass([
`monitor`,
{
compact: a.compact,
},
]),
},
[
a.compact
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
i,
{
key: 0,
modelValue: unref(S),
"onUpdate:modelValue": (r[0] ||= (e) =>
isRef(S) ? (S.value = e) : null),
class: `range`,
options: M,
"option-label": `label`,
"option-value": `value`,
"allow-empty": !1,
"aria-label": `监控时间范围`,
},
null,
8,
[`modelValue`],
)),
createElementVNode(`div`, E, [
a.compact
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, D, [
...(r[1] ||= [
createElementVNode(`h3`, null, `网络带宽`, -1),
]),
])),
createElementVNode(`div`, O, [
(r[2] ||= createElementVNode(
`span`,
null,
[
createElementVNode(`i`, {
class: `incoming`,
}),
createTextVNode(`入站`),
],
-1,
)),
(r[3] ||= createElementVNode(
`span`,
null,
[
createElementVNode(`i`, {
class: `outgoing`,
}),
createTextVNode(`出站`),
],
-1,
)),
createElementVNode(
`small`,
null,
toDisplayString(unref(I) || `单位未返回`),
1,
),
]),
createElementVNode(
`div`,
{
class: `chart-viewport`,
style: normalizeStyle({
"--chart-height": a.compact ? `126px` : `320px`,
}),
"aria-busy": unref(N),
},
[
unref(N) && !unref(H)
? (openBlock(),
createBlock(
s,
{
key: 0,
height: a.compact ? `126px` : `320px`,
},
null,
8,
[`height`],
))
: unref(P)
? (openBlock(),
createElementBlock(`div`, A, [
createElementVNode(
`span`,
null,
toDisplayString(unref(P)),
1,
),
createVNode(l, {
label: `重试`,
text: ``,
size: `small`,
onClick: B,
}),
]))
: unref(H)
? (openBlock(),
createBlock(
h,
{
key: 2,
option: unref(U),
height: a.compact ? 126 : 320,
loading: unref(N),
},
null,
8,
[`option`, `height`, `loading`],
))
: (openBlock(),
createElementBlock(
`p`,
j,
`所选时段暂无带宽采样`,
)),
],
12,
k,
),
]),
],
2,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-eb47944f`]],
),
{
__name: `DcimMonitor`,
},
);
export {};
export default M;
</script>
@@ -0,0 +1,163 @@
<script>
import "~/assets/styles/DcimReinstallStatus.CuXeXmZ3.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
var m = {
class: `task-status`,
},
h = {
key: 0,
role: `status`,
},
g = [`aria-label`, `title`],
_ = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimReinstallStatus`,
props: {
hostId: {},
module: {},
refreshVersion: {},
},
setup(c) {
let p = c,
_ = useApi(),
v = ref(!1),
y = ref(``),
b = ref(!1),
x = ref(!1),
S = 0,
C = !1,
w = 0,
T;
function E() {
T = setTimeout(() => {
if (!C) {
if (
document.visibilityState !== `visible` ||
document.querySelector(`.p-dialog-mask`)
) {
E();
return;
}
D(!1);
}
}, 1e4);
}
async function D(e = !0) {
if (v.value || C) return;
(clearTimeout(T), e && (w = 0));
let t = ++S;
((v.value = !0), (y.value = ``));
try {
let e = await _.get(`/${p.module}/${p.hostId}/reinstall_status`);
if (C || t !== S) return;
if (
!Array.isArray(e) ||
e.some(
(e) =>
!e ||
e.task_type === null ||
e.task_type === void 0 ||
!Number.isInteger(Number(e.task_type)),
)
)
throw Error(`重装任务状态响应无效`);
((x.value = e.some((e) => Number(e.task_type) === 0)),
(b.value = !0),
x.value && ++w < 60 && E());
} catch (e) {
!C &&
t === S &&
(y.value =
e instanceof Error ? e.message : `重装任务状态加载失败`);
} finally {
t === S && (v.value = !1);
}
}
return (
watch(
[() => p.hostId, () => p.module, () => p.refreshVersion],
() => {
(S++, clearTimeout(T), (v.value = !1), (b.value = !1), D());
},
),
onMounted(D),
onBeforeUnmount(() => {
((C = !0), S++, clearTimeout(T));
}),
(t, n) => {
let r = button;
return (
openBlock(),
createElementBlock(`div`, m, [
unref(b) && !unref(y)
? (openBlock(),
createElementBlock(
`span`,
h,
toDisplayString(
unref(x)
? `系统正在重装,请等待任务结束`
: `当前未检测到进行中的重装任务`,
),
1,
))
: createCommentVNode(``, !0),
unref(y)
? (openBlock(),
createElementBlock(
`span`,
{
key: 1,
class: `task-error`,
role: `alert`,
"aria-label": `重装任务状态加载失败:${unref(y)}`,
title: unref(y),
},
`重装状态加载失败,可点刷新重试`,
8,
g,
))
: createCommentVNode(``, !0),
createVNode(
r,
{
label: `刷新重装状态`,
icon: `pi pi-refresh`,
text: ``,
size: `small`,
loading: unref(v),
onClick: (n[0] ||= (e) => D()),
},
null,
8,
[`loading`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-d99d9473`]],
),
{
__name: `DcimReinstallStatus`,
},
);
export {};
export default _;
</script>
+613
View File
@@ -0,0 +1,613 @@
<script>
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
import "~/assets/styles/DcimUpgrade.DaLApYFa.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { reactive } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import ConfigBandwidth from "~/components/config/ConfigBandwidth.vue";
var T = {
key: 0,
class: `dcim-upgrade`,
},
E = {
key: 1,
},
te = {
key: 2,
},
D = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimUpgrade`,
props: {
hostId: {},
productId: {},
module: {},
current: {},
upgradeAllowed: {
type: Boolean,
},
},
emits: [`pay`],
setup(h, { expose: b, emit: D }) {
let O = h,
k = D,
A = useApi(),
j = ref(null),
M = computed(() => O.current.model_config ?? {}),
N = [`memory`, `disk`, `gpu`],
P = {
memory: `内存`,
disk: `硬盘`,
gpu: `显卡`,
},
F = reactive({
bw: 0,
flow: 0,
ip_num: 0,
peak_defence: 0,
optional_memory: {},
optional_disk: {},
optional_gpu: {},
}),
I = ref(!1),
L = ref(!1),
R = ref(!1),
z = ref(``),
B = ref(``),
V = ref(``),
H = 0,
U = 0,
W = !1,
G = ``,
K = ``,
q = computed(() => JSON.stringify([O.hostId, O.module, F])),
J = computed(() => q.value !== K),
ne = (e = []) =>
e
.filter(
(e) => e.value !== `` && Number.isFinite(Number(e.value)),
)
.map((e) => ({
value: Number(e.value),
label: String(e.value_show || e.desc || e.value),
})),
re = (e = []) =>
e.some((e) => e.min_value !== void 0 && e.max_value !== void 0),
Y = computed(() =>
[
...(j.value?.bill_type === `flow`
? [
{
key: `flow`,
label: `流量配额`,
options: j.value.flow ?? [],
},
]
: []),
{
key: `ip_num`,
label: `IPv4 数量`,
options: j.value?.ip ?? [],
},
{
key: `peak_defence`,
label: `防御峰值`,
options: j.value?.defence ?? [],
},
].filter((e) => e.options.length),
);
function ie(e, t) {
return (
Number.isFinite(e) &&
t.some((t) => {
if (
t.min_value === void 0 ||
t.max_value === void 0 ||
t.type === `radio`
)
return Number(t.value) === e;
let n = Number(t.step ?? 1);
return (
n > 0 &&
e >= Number(t.min_value) &&
e <= Number(t.max_value) &&
Math.abs(
(e - Number(t.min_value)) / n -
Math.round((e - Number(t.min_value)) / n),
) < 1e-7
);
})
);
}
let X = (e) => M.value[`optional_${e}`] ?? [];
function Z() {
(H++, (B.value = ``), (V.value = ``), (G = ``), (L.value = !1));
}
function ae() {
for (let e of [`bw`, `flow`, `ip_num`, `peak_defence`])
F[e] = Number(O.current[e] ?? 0);
for (let e of N) {
let t = O.current[`optional_${e}`];
F[`optional_${e}`] =
t && typeof t == `object` && !Array.isArray(t)
? Object.fromEntries(
Object.entries(t).map(([e, t]) => [e, Number(t)]),
)
: {};
}
((K = q.value), Z());
}
async function Q() {
if (O.upgradeAllowed === !1 || W) return;
let e = ++U;
(ae(), (I.value = !0), (z.value = ``), (j.value = null));
try {
let t = Number(O.current.line?.id);
if (!Number.isSafeInteger(t) || t <= 0)
throw Error(`实例线路信息无效,请刷新后重试`);
let n = await A.get(
`/product/${O.productId}/${O.module}/line/${t}`,
);
!W && e === U && (j.value = n);
} catch (t) {
!W &&
e === U &&
(z.value = t instanceof Error ? t.message : `升级配置加载失败`);
} finally {
e === U && (I.value = !1);
}
}
function oe() {
for (let e of N) {
let t = F[`optional_${e}`],
n = O.current[`optional_${e}`] ?? {},
r = new Set([
...X(e).map((e) => String(e.id)),
...Object.keys(n),
]);
if (
Object.entries(t).some(
([e, t]) => !r.has(e) || !Number.isSafeInteger(t) || t < 0,
)
)
throw Error(`${P[e]}数量无效`);
let i =
Object.values(t).reduce((e, t) => e + t, 0) -
Object.values(n).reduce((e, t) => e + Number(t), 0),
a = M.value[`max_${e}_num`];
if (a !== void 0 && i > Number(a))
throw Error(`${P[e]}数量超过剩余槽位`);
}
if (!j.value) throw Error(`请先加载有效的升级配置`);
let e = [
...Y.value,
...(j.value.bill_type === `bw`
? [
{
key: `bw`,
label: `带宽`,
options: j.value.bw ?? [],
},
]
: []),
];
for (let t of e)
if (
F[t.key] !== Number(O.current[t.key] ?? 0) &&
!ie(F[t.key], t.options)
)
throw Error(`请选择有效的${t.label}档位`);
}
async function $() {
if (O.upgradeAllowed === !1 || R.value || W || !J.value) return;
((z.value = ``), Z());
try {
oe();
} catch (e) {
z.value = e.message;
return;
}
let e = ++H,
t = q.value,
n = JSON.parse(JSON.stringify(F)),
r = {
bw: n.bw,
flow: n.flow,
ip_num: n.ip_num,
peak_defence: n.peak_defence,
};
for (let e of N)
for (let [t, i] of Object.entries(n[`optional_${e}`]))
r[`optional_${e}[${t}]`] = i;
L.value = !0;
try {
let n = await A.get(`/${O.module}/${O.hostId}/common_config`, r);
if (W || e !== H || t !== q.value) return;
if (
n.price === null ||
n.price === void 0 ||
String(n.price).trim() === `` ||
!Number.isFinite(Number(n.price))
)
throw Error(`升级报价无效,请重试`);
((B.value = String(n.price)),
(V.value = n.description ?? ``),
(G = t));
} catch (t) {
!W &&
e === H &&
(z.value = t instanceof Error ? t.message : `升级询价失败`);
} finally {
e === H && (L.value = !1);
}
}
async function se() {
if (
O.upgradeAllowed === !1 ||
R.value ||
L.value ||
!J.value ||
!B.value ||
G !== q.value ||
W
)
return;
let e = q.value,
t = B.value,
n = JSON.parse(JSON.stringify(F));
((R.value = !0), (z.value = ``));
try {
let r = await A.post(
`/${O.module}/${O.hostId}/common_config/order`,
n,
);
if (W || e !== q.value) return;
if (!/^[1-9]\d*$/.test(String(r.id)))
throw Error(`升级订单无效,请重试`);
(Z(),
k(`pay`, {
order_id: r.id,
amount: t,
}));
} catch (t) {
!W &&
e === q.value &&
(z.value = t instanceof Error ? t.message : `升级订单创建失败`);
} finally {
W || (R.value = !1);
}
}
return (
watch(F, Z, {
deep: !0,
flush: `sync`,
}),
watch(
[
() => O.hostId,
() => O.module,
() => O.current,
() => O.upgradeAllowed,
],
() => {
(U++, Z(), Q());
},
{
flush: `sync`,
},
),
onMounted(Q),
onBeforeUnmount(() => {
((W = !0), H++, U++);
}),
b({
busy: R,
}),
(n, r) => {
let i = message,
o = button,
l = ConfigBandwidth,
u = inputnumber,
v = select;
return h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, T, [
unref(z)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(z)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(j)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
o,
{
key: 1,
label: `加载升级配置`,
text: ``,
loading: unref(I),
onClick: Q,
},
null,
8,
[`loading`],
)),
unref(j)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
unref(j).bill_type === `bw` && unref(j).bw?.length
? (openBlock(),
createBlock(
l,
{
key: 0,
modelValue: unref(F).bw,
"onUpdate:modelValue": (r[0] ||= (e) =>
(unref(F).bw = e)),
options: unref(j).bw,
disabled: unref(R),
onChange: $,
},
null,
8,
[`modelValue`, `options`, `disabled`],
))
: createCommentVNode(``, !0),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(Y),
(t) => (
openBlock(),
createElementBlock(
`label`,
{
key: t.key,
},
[
createTextVNode(
toDisplayString(t.label),
1,
),
re(t.options)
? (openBlock(),
createBlock(
u,
{
key: 0,
modelValue: unref(F)[t.key],
"onUpdate:modelValue": (e) =>
(unref(F)[t.key] = e),
min: 0,
disabled: unref(R),
"use-grouping": !1,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`disabled`,
],
))
: (openBlock(),
createBlock(
v,
{
key: 1,
modelValue: unref(F)[t.key],
"onUpdate:modelValue": (e) =>
(unref(F)[t.key] = e),
options: ne(t.options),
"option-label": `label`,
"option-value": `value`,
disabled: unref(R),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`options`,
`disabled`,
],
)),
],
)
),
),
128,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
N.filter((e) => X(e).length),
(n) => (
openBlock(),
createElementBlock(
`fieldset`,
{
key: n,
},
[
createElementVNode(
`legend`,
null,
toDisplayString(P[n]) + `配置`,
1,
),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
X(n),
(t) => (
openBlock(),
createElementBlock(
`label`,
{
key: t.id,
},
[
createTextVNode(
toDisplayString(t.value),
1,
),
createVNode(
u,
{
modelValue:
unref(F)[`optional_${n}`][
String(t.id)
],
"onUpdate:modelValue": (
e,
) =>
(unref(F)[
`optional_${n}`
][String(t.id)] = e),
min: 0,
max:
Number(
unref(M)[
`max_${n}_num`
] ?? 99,
) +
Number(
h.current[
`optional_${n}`
]?.[String(t.id)] ?? 0,
),
disabled: unref(R),
"use-grouping": !1,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`max`,
`disabled`,
],
),
],
)
),
),
128,
)),
],
)
),
),
128,
)),
createVNode(
o,
{
label: `计算变更费用`,
outlined: ``,
loading: unref(L),
disabled: unref(R) || !unref(J),
onClick: $,
},
null,
8,
[`loading`, `disabled`],
),
unref(B) === ``
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
E,
`变更费用:¥` + toDisplayString(unref(B)),
1,
)),
unref(V)
? (openBlock(),
createElementBlock(
`p`,
te,
toDisplayString(unref(V)),
1,
))
: createCommentVNode(``, !0),
createVNode(
o,
{
label: `确认生成升级订单`,
loading: unref(R),
disabled:
unref(B) === `` || unref(L) || !unref(J),
onClick: se,
},
null,
8,
[`loading`, `disabled`],
),
],
64,
))
: createCommentVNode(``, !0),
]));
}
);
},
}),
[[`__scopeId`, `data-v-790898bc`]],
),
{
__name: `DcimUpgrade`,
},
);
export {};
export default D;
</script>
+681
View File
@@ -0,0 +1,681 @@
<script>
import "~/assets/styles/FlowPacketPanel.-RJSx13z.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { r as dict_r } from "~/lib/dict.js";
import OperationNotice from "~/components/OperationNotice.vue";
import tag from "primevue/tag";
import { n as complete_list_n } from "~/lib/complete-list.js";
var oe = {
key: 1,
class: `block`,
},
se = {
class: `info-table`,
},
C = {
key: 0,
class: `kv`,
},
w = {
class: `kv`,
},
T = {
class: `action-cell`,
},
E = {
key: 0,
class: `pk-empty`,
role: `status`,
},
ce = {
key: 2,
class: `pk-empty`,
},
le = {
key: 1,
class: `kv`,
},
ue = {
class: `pk-list`,
},
de = {
class: `pk-name`,
},
fe = {
class: `col-mono`,
},
D = {
class: `pk-expire`,
},
O = {
key: 0,
class: `pk-empty`,
role: `status`,
},
k = {
key: 2,
class: `pk-empty`,
},
A = {
key: 3,
class: `pk-grid`,
},
j = {
class: `pk-card-name`,
},
M = {
class: `pk-card-cap`,
},
N = {
class: `pk-card-price`,
},
P = {
class: `pk-card-tags`,
},
F = {
key: 1,
class: `pk-card-note`,
},
I = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `FlowPacketPanel`,
props: {
hostId: {},
flow: {},
module: {
default: `mf_cloud`,
},
mode: {
default: `panel`,
},
},
emits: [`pay`],
setup(_, { emit: S }) {
let I = _,
L = S,
R = useApi(),
z = ref([]),
B = ref([]),
V = ref(!1),
H = ref(``),
U = ref(``),
W = computed(() => {
let e = I.flow?.flow_packet?.leave_size;
if (![`mf_cloud`, `remf_cloud`].includes(I.module) || e == null)
return null;
let t = Number(e);
return Number.isFinite(t) && t >= 0 ? t : null;
});
function G(e) {
let t = Number(e ?? 0);
return t
? t >= 1024
? `${(t / 1024).toFixed(2)} TB`
: `${t} GB`
: `0`;
}
let K = 0,
q = 0,
J = !1;
async function Y() {
if (J || !I.hostId) return;
let e = ++K,
t = I.hostId,
n = I.module,
r = () => !J && e === K && t === I.hostId && n === I.module;
((V.value = !0),
(H.value = ``),
(U.value = ``),
(z.value = []),
(B.value = []));
try {
await Promise.all([
(async () => {
try {
let e = await R.get(`/host/${t}/flow_packet`, {
page: 1,
limit: 100,
});
r() && (z.value = e.list ?? []);
} catch (e) {
r() &&
(H.value =
e instanceof Error
? e.message
: `流量包加载失败,请重试`);
}
})(),
[`mf_cloud`, `remf_cloud`].includes(n) && I.mode === `panel`
? (async () => {
try {
let e = await complete_list_n(
(e, r) =>
R.get(`/${n}/${t}/traffic_package`, {
page: e,
limit: r,
}),
r,
);
r() && (B.value = e);
} catch (e) {
r() &&
(U.value =
e instanceof Error
? e.message
: `已购流量包加载失败,请重试`);
}
})()
: Promise.resolve(),
]);
} finally {
r() && (V.value = !1);
}
}
let X = ref(!1),
Z = ref(null),
Q = ref(``);
async function $() {
((Q.value = ``), (X.value = !0), await Y());
}
async function pe(e) {
if (
J ||
Z.value !== null ||
V.value ||
H.value ||
!I.hostId ||
!z.value.some((t) => t.id === e.id) ||
e.billing_mode !== 0 ||
e.monthly_purchase_limit_reached === 1
)
return;
let t = ++q,
n = I.hostId,
r = I.module,
i = () => !J && t === q && n === I.hostId && r === I.module;
((Q.value = ``), (Z.value = e.id));
try {
let t = await R.post(`/host/${n}/flow_packet_order`, {
id: n,
flow_packet_id: e.id,
});
if (!i()) return;
if (!/^[1-9]\d*$/.test(String(t.id)))
throw Error(`流量包订单无效,请重试`);
((X.value = !1),
L(`pay`, {
order_id: t.id,
amount: e.price,
}));
} catch (e) {
i() &&
(Q.value =
e instanceof Error ? e.message : `下单失败,请稍后重试`);
} finally {
i() && (Z.value = null);
}
}
return (
onMounted(() => {
if (I.mode === `panel`) return Y();
}),
watch(
() => [I.hostId, I.module],
() => {
if (
(K++,
q++,
(z.value = []),
(B.value = []),
(H.value = ``),
(U.value = ``),
(Q.value = ``),
(V.value = !1),
(Z.value = null),
(X.value = !1),
I.mode === `panel`)
)
return Y();
},
),
onBeforeUnmount(() => {
((J = !0), K++, q++);
}),
(n, i) => {
let a = OperationNotice,
s = button,
u = message,
b = tag,
S = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
a,
{
message: unref(Q),
severity: `error`,
},
null,
8,
[`message`],
),
_.mode === `button`
? (openBlock(),
createBlock(s, {
key: 0,
label: `购买流量包`,
icon: `pi pi-plus`,
fluid: ``,
onClick: $,
}))
: (openBlock(),
createElementBlock(`section`, oe, [
(i[4] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`流量包`,
-1,
)),
(i[5] ||= createElementVNode(
`p`,
{
class: `block-desc`,
},
` 购买流量包可补充当前实例的可用流量,容量和有效期以套餐为准。 `,
-1,
)),
createElementVNode(`div`, se, [
unref(W) === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, C, [
(i[1] ||= createElementVNode(
`span`,
null,
`流量包剩余`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(G(unref(W))),
1,
),
])),
createElementVNode(`div`, w, [
(i[2] ||= createElementVNode(
`span`,
null,
`流量包购买`,
-1,
)),
createElementVNode(`div`, T, [
unref(V)
? (openBlock(),
createElementBlock(`p`, E, `流量包加载中…`))
: unref(H)
? (openBlock(),
createBlock(
u,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(H)) + ` `,
1,
),
createVNode(s, {
label: `重试`,
size: `small`,
severity: `secondary`,
text: ``,
onClick: Y,
}),
]),
_: 1,
},
))
: unref(z).length
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
ce,
`该实例暂无可购流量包`,
)),
unref(z).length
? (openBlock(),
createBlock(s, {
key: 3,
label: `购买流量包`,
icon: `pi pi-plus`,
size: `small`,
severity: `secondary`,
outlined: ``,
onClick: $,
}))
: createCommentVNode(``, !0),
]),
]),
unref(B).length || unref(U)
? (openBlock(),
createElementBlock(`div`, le, [
(i[3] ||= createElementVNode(
`span`,
null,
`已购流量包`,
-1,
)),
createElementVNode(`div`, ue, [
unref(U)
? (openBlock(),
createBlock(
u,
{
key: 0,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(U)) + ` `,
1,
),
createVNode(s, {
label: `重试`,
size: `small`,
severity: `secondary`,
text: ``,
onClick: Y,
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(B),
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.id,
class: `pk-row`,
},
[
createElementVNode(
`span`,
de,
toDisplayString(t.name),
1,
),
createElementVNode(`span`, fe, [
createTextVNode(
toDisplayString(G(t.size)),
1,
),
t.used
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`(已用 ` +
toDisplayString(
G(t.used),
) +
`)`,
1,
),
],
64,
))
: createCommentVNode(``, !0),
]),
createElementVNode(
`span`,
D,
toDisplayString(
t.expire_time
? `${(`formatTime` in n ? n.formatTime : unref(dict_r))(t.expire_time)} 到期`
: `不限时`,
),
1,
),
],
)
),
),
128,
)),
]),
]))
: createCommentVNode(``, !0),
]),
])),
createVNode(
S,
{
visible: unref(X),
"onUpdate:visible": (i[0] ||= (e) =>
isRef(X) ? (X.value = e) : null),
header: `购买流量包`,
modal: ``,
style: {
width: `600px`,
maxWidth: `calc(100vw - 32px)`,
},
closable: unref(Z) === null,
"close-on-escape": unref(Z) === null,
},
{
default: withCtx(() => [
unref(V)
? (openBlock(),
createElementBlock(`div`, O, `流量包加载中…`))
: unref(H)
? (openBlock(),
createBlock(
u,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(H)) + ` `,
1,
),
createVNode(s, {
label: `重试`,
size: `small`,
severity: `secondary`,
text: ``,
onClick: Y,
}),
]),
_: 1,
},
))
: unref(z).length
? (openBlock(),
createElementBlock(`div`, A, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(z),
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.id,
class: normalizeClass([
`pk-card`,
{
"pk-card-disabled":
t.billing_mode !== 0 ||
t.monthly_purchase_limit_reached ===
1,
},
]),
},
[
createElementVNode(
`div`,
j,
toDisplayString(t.name),
1,
),
createElementVNode(
`div`,
M,
toDisplayString(t.capacity) +
` GB`,
1,
),
createElementVNode(
`div`,
N,
`¥` + toDisplayString(t.price),
1,
),
createElementVNode(`div`, P, [
t.long_term_valid === 1
? (openBlock(),
createBlock(b, {
key: 0,
value: `长期有效`,
severity: `success`,
}))
: createCommentVNode(``, !0),
t.monthly_purchase_limit
? (openBlock(),
createBlock(
b,
{
key: 1,
value: `本月还可购 ${t.monthly_purchase_left ?? 0} 份`,
severity: `secondary`,
},
null,
8,
[`value`],
))
: createCommentVNode(``, !0),
]),
t.billing_mode === 0
? (openBlock(),
createBlock(
s,
{
key: 0,
label: `购买`,
size: `small`,
loading:
unref(Z) === t.id,
disabled:
unref(Z) !== null ||
t.monthly_purchase_limit_reached ===
1,
onClick: (e) => pe(t),
},
null,
8,
[
`loading`,
`disabled`,
`onClick`,
],
))
: (openBlock(),
createElementBlock(
`span`,
F,
`按 GB 计费,请联系客服购买`,
)),
],
2,
)
),
),
128,
)),
]))
: (openBlock(),
createElementBlock(
`div`,
k,
`该实例暂无可购流量包`,
)),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
],
64,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-ca0029df`]],
),
{
__name: `FlowPacketPanel`,
},
);
export {};
export default I;
</script>
@@ -0,0 +1,275 @@
<script>
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
import { toDisplayString } from "vue";
import { onBeforeUnmount } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import message from "primevue/message";
import PaymentDialog from "~/components/PaymentDialog.vue";
var C = {
key: 0,
},
w = Object.assign(
defineComponent({
__name: `ImagePurchaseDialog`,
props: {
modelValue: {
default: null,
},
modelModifiers: {},
},
emits: mergeModels([`authorized`], [`update:modelValue`]),
setup(n, { emit: h }) {
let w = useModel(n, `modelValue`),
T = h,
E = useApi(),
D = ref(!1),
O = ref(``),
k = ref(!1),
A = ref(null),
j = new Map(),
M = 0,
N = !1,
P = (e) => `${e.module}:${e.hostId}:${e.imageId}`;
function F(e) {
if (
(typeof e != `string` && typeof e != `number`) ||
String(e).trim() === `` ||
!Number.isFinite(Number(e)) ||
Number(e) < 0
)
throw Error(`镜像费用信息无效,请重试`);
return Number(e).toFixed(2);
}
async function I() {
let e = w.value;
if (!e || D.value || N) return;
let t = M,
n = () => !N && M === t && w.value === e;
((D.value = !0), (O.value = ``));
try {
let t = await E.get(`/${e.module}/${e.hostId}/image/check`, {
image_id: e.imageId,
});
if (!n()) return;
let r = F(t.price);
if (Number(r) === 0) {
((w.value = null), T(`authorized`));
return;
}
if (r !== F(e.price)) {
((w.value = {
...e,
price: r,
}),
(O.value = `镜像费用已更新,请确认最新金额`));
return;
}
let i = j.get(P(e));
if (!i) {
let t = await E.post(`/${e.module}/${e.hostId}/image/order`, {
image_id: e.imageId,
});
if (!/^[1-9]\d*$/.test(String(t.id)))
throw Error(`镜像购买订单无效,请重试`);
((i = t.id), j.set(P(e), i));
}
if (!n()) return;
((A.value = i), (k.value = !0));
} catch (e) {
n() &&
(O.value = e instanceof Error ? e.message : `创建镜像订单失败`);
} finally {
t === M && (D.value = !1);
}
}
async function L() {
let e = w.value;
if (!e || N) return;
let t = M;
((D.value = !0), (O.value = ``), (k.value = !1));
try {
let n = await E.get(`/${e.module}/${e.hostId}/image/check`, {
image_id: e.imageId,
});
if (t !== M || N) return;
if (Number(F(n.price)) !== 0)
throw Error(`镜像授权尚未生效,请稍后重新检查`);
(j.delete(P(e)), (w.value = null), T(`authorized`));
} catch (e) {
t === M &&
(O.value = e instanceof Error ? e.message : `镜像授权校验失败`);
} finally {
t === M && (D.value = !1);
}
}
return (
watch(
w,
() => {
(M++,
(D.value = !1),
(k.value = !1),
(O.value = ``),
(A.value = null));
},
{
flush: `sync`,
},
),
onBeforeUnmount(() => {
((N = !0), M++);
}),
(t, n) => {
let r = message,
i = button,
o = dialog,
h = PaymentDialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
o,
{
visible: !!w.value && !unref(k),
header: `购买系统镜像`,
modal: ``,
closable: !unref(D),
"close-on-escape": !unref(D),
style: {
width: `480px`,
},
"onUpdate:visible": (n[1] ||= (e) => {
!e && !unref(D) && (w.value = null);
}),
},
{
footer: withCtx(() => [
createVNode(
i,
{
label: `取消`,
outlined: ``,
severity: `secondary`,
disabled: unref(D),
onClick: (n[0] ||= (e) => (w.value = null)),
},
null,
8,
[`disabled`],
),
createVNode(
i,
{
label: `确认购买 / 继续支付`,
loading: unref(D),
onClick: I,
},
null,
8,
[`loading`],
),
]),
default: withCtx(() => [
createElementVNode(`p`, null, [
createTextVNode(
`实例 #` +
toDisplayString(w.value?.hostId) +
` 所选镜像需要购买,费用为 `,
1,
),
createElementVNode(
`strong`,
null,
`¥` + toDisplayString(w.value?.price),
1,
),
(n[3] ||= createTextVNode(`。`, -1)),
]),
w.value?.description
? (openBlock(),
createElementBlock(
`p`,
C,
toDisplayString(w.value.description),
1,
))
: createCommentVNode(``, !0),
(n[4] ||= createElementVNode(
`p`,
null,
`支付并确认授权后,请再次确认重装。支付不会自动清除服务器数据。`,
-1,
)),
unref(O)
? (openBlock(),
createBlock(
r,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(O)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
createVNode(
h,
{
modelValue: unref(k),
"onUpdate:modelValue": (n[2] ||= (e) =>
isRef(k) ? (k.value = e) : null),
"order-id": unref(A),
amount: w.value?.price ?? ``,
onSuccess: L,
},
null,
8,
[`modelValue`, `order-id`, `amount`],
),
],
64,
)
);
}
);
},
}),
{
__name: `ImagePurchaseDialog`,
},
);
export {};
export default w;
</script>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,166 @@
<script>
import "~/assets/styles/InstanceLoadingShell.CwfiUwdU.css";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import skeleton from "primevue/skeleton";
var u = {
class: `shell-tabs`,
"aria-hidden": `true`,
},
d = {
class: `shell-grid`,
"aria-hidden": `true`,
},
f = {
class: `shell-card`,
},
p = {
class: `shell-card shell-secondary`,
},
m = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceLoadingShell`,
props: {
dcim: {
type: Boolean,
default: !1,
},
},
setup(a) {
return (c, m) => {
let h = skeleton;
return (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`instance-loading-shell`,
{
dcim: a.dcim,
},
]),
role: `status`,
"aria-label": `正在加载实例管理信息`,
"aria-busy": `true`,
},
[
createElementVNode(`div`, u, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList([32, 32, 64, 32, 80, 80, 32], (e, t) =>
createElementVNode(
`span`,
{
key: t,
},
[
createVNode(
h,
{
width: `${e}px`,
height: `24px`,
},
null,
8,
[`width`],
),
],
),
),
64,
)),
]),
createElementVNode(`div`, d, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(3, (t) =>
createElementVNode(
`div`,
{
key: t,
class: `shell-column`,
},
[
createElementVNode(`div`, f, [
createVNode(h, {
width: `64px`,
height: `24px`,
}),
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(5, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `shell-row`,
},
[
createVNode(h, {
width: `28%`,
height: `24px`,
}),
createVNode(h, {
width: `45%`,
height: `24px`,
}),
],
),
),
64,
)),
createVNode(h, {
height: `40px`,
class: `shell-button`,
}),
]),
createElementVNode(`div`, p, [
createVNode(h, {
width: `64px`,
height: `24px`,
}),
createVNode(h, {
height: `126px`,
}),
createVNode(h, {
width: `70%`,
height: `24px`,
}),
]),
],
),
),
64,
)),
]),
],
2,
)
);
};
},
}),
[[`__scopeId`, `data-v-f12d9300`]],
),
{
__name: `InstanceLoadingShell`,
},
);
export {};
export default m;
</script>
+882
View File
@@ -0,0 +1,882 @@
<script>
import "~/assets/styles/InstanceTraffic.CyyEAXl3.css";
import "~/assets/styles/RingProgress.CVwR7il5.css";
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import "~/assets/styles/InstanceOverview.C9ExpxMB.css";
import "~/assets/styles/InstanceMonitorSkeleton.C0FT51jJ.css";
import "~/assets/styles/InstanceLoadingShell.CwfiUwdU.css";
import "~/assets/styles/FlowPacketPanel.-RJSx13z.css";
import "~/assets/styles/InstanceServiceInfo.BftSVIeW.css";
import "~/assets/styles/InstanceManage.apzbBV1c.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { Suspense } from "vue";
import { defineAsyncComponent } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { loadModule } from "~/utils/load-module.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import InstanceServiceInfo from "~/components/instance/InstanceServiceInfo.vue";
import InstanceLoadingShell from "~/components/instance/InstanceLoadingShell.vue";
import InstanceMonitorSkeleton from "~/components/instance/InstanceMonitorSkeleton.vue";
import tabs from "primevue/tabs";
import tabpanels from "primevue/tabpanels";
import tabpanel from "primevue/tabpanel";
import tablist from "primevue/tablist";
import tab from "primevue/tab";
import InstanceOverview from "~/components/instance/InstanceOverview.vue";
var oe = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceMonitor.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
D = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceAccess.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
O = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceDisks.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
k = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceNetwork.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
A = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/MfCloudBackupPanel.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
j = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceBilling.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
M = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/mfcloud/MfCloudLogs.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
N = {
class: `instance-manage`,
},
P = {
key: 1,
class: `bs-wrap`,
},
F = {
class: `bs-block`,
},
I = {
class: `bs-block`,
},
L = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceManage`,
props: mergeModels(
{
hostId: {},
productId: {},
productState: {},
host: {},
module: {},
detail: {},
},
{
tab: {
default: `overview`,
},
tabModifiers: {},
},
),
emits: mergeModels([`refresh`, `pay`], [`update:tab`]),
setup(n, { emit: o }) {
let _ = n,
b = o,
S = ref(null),
L = 0,
{
info: R,
powerDesc: z,
loading: B,
error: V,
caps: H,
disksLoading: U,
disksError: W,
disksLoaded: G,
refreshDisks: K,
} = _.detail,
q = computed(() => _.host.status === `Active`),
J = useModel(n, `tab`),
Y = computed(() => [
{
value: `overview`,
label: `概要`,
},
{
value: `monitor`,
label: `监控`,
},
{
value: `access`,
label: `访问控制`,
},
...(H.value.disk === !1
? []
: [
{
value: `disk`,
label: `硬盘`,
},
]),
{
value: `network`,
label: `网络与安全`,
},
...(H.value.snapshot
? [
{
value: `backup`,
label: `备份与快照`,
},
]
: []),
{
value: `billing`,
label: `计费`,
},
...(H.value.log
? [
{
value: `log`,
label: `日志`,
},
]
: []),
]);
function se(e) {
J.value = Y.value.some((t) => t.value === e) ? e : `overview`;
}
function ce(e) {
q.value &&
(e !== `rescue` || H.value.rescue) &&
(e !== `reinstall` || H.value.reinstall) &&
((J.value = `access`),
(S.value = {
kind: e,
id: ++L,
}));
}
function le() {
S.value = null;
}
watch(
[Y, J],
([e, t]) => {
e.some((e) => e.value === t) || (J.value = `overview`);
},
{
immediate: !0,
},
);
let X = (e) => `实例尚未开通,${e}`;
return (r, i) => {
let o = button,
c = message,
d = InstanceServiceInfo,
_ = InstanceLoadingShell,
L = tab,
ue = tablist,
de = InstanceOverview,
Z = tabpanel,
fe = oe,
pe = InstanceMonitorSkeleton,
me = D,
he = O,
ge = k,
Q = A,
$ = j,
_e = M,
ve = tabpanels,
ye = tabs;
return (
openBlock(),
createElementBlock(`div`, N, [
unref(V) && unref(R)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(V)), 1),
createVNode(
o,
{
label: `重试`,
text: ``,
size: `small`,
loading: unref(B),
onClick: (i[0] ||= (e) => n.detail.load()),
},
null,
8,
[`loading`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
!unref(q) || (!unref(R) && unref(V))
? (openBlock(),
createBlock(
d,
{
key: 1,
host: n.host,
module: n.module,
info: unref(R),
onPay: (i[1] ||= (e) => b(`pay`, e)),
},
null,
8,
[`host`, `module`, `info`],
))
: !unref(R) && !unref(V)
? (openBlock(),
createBlock(_, {
key: 2,
}))
: createCommentVNode(``, !0),
unref(V) && !unref(R) && unref(q)
? (openBlock(),
createBlock(
c,
{
key: 3,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(V)), 1),
createVNode(o, {
label: `重试`,
text: ``,
onClick: (i[2] ||= (e) => n.detail.load()),
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(q) && unref(R)
? (openBlock(),
createBlock(
ye,
{
key: 4,
value: J.value,
"onUpdate:value": (i[11] ||= (e) => (J.value = e)),
lazy: ``,
},
{
default: withCtx(() => [
createVNode(ue, null, {
default: withCtx(() => [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(Y),
(t) => (
openBlock(),
createBlock(
L,
{
key: t.value,
value: t.value,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(t.label),
1,
),
]),
_: 2,
},
1032,
[`value`],
)
),
),
128,
)),
]),
_: 1,
}),
createVNode(ve, null, {
default: withCtx(() => [
createVNode(
Z,
{
value: `overview`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createBlock(
de,
{
key: 1,
"product-state": n.productState,
info: unref(R),
host: n.host,
"host-id": n.hostId,
module: n.module,
caps: unref(H),
"power-desc": unref(z),
"disks-loading": unref(U),
"disks-error": unref(W),
"disks-loaded": unref(G),
onPay: (i[3] ||= (e) =>
b(`pay`, e)),
onGoTab: se,
onAccessAction: ce,
onRefreshDisks: unref(K),
},
null,
8,
[
`product-state`,
`info`,
`host`,
`host-id`,
`module`,
`caps`,
`power-desc`,
`disks-loading`,
`disks-error`,
`disks-loaded`,
`onRefreshDisks`,
],
))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
X(`以下数据将在开通后可用。`),
),
1,
),
]),
_: 1,
},
)),
]),
_: 1,
},
),
createVNode(
Z,
{
value: `monitor`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createBlock(
Suspense,
{
key: 1,
},
{
fallback: withCtx(() => [
createVNode(pe),
]),
default: withCtx(() => [
createVNode(
fe,
{
"host-id": n.hostId,
module: n.module,
},
null,
8,
[`host-id`, `module`],
),
]),
_: 1,
},
))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
X(`暂无监控数据。`),
),
1,
),
]),
_: 1,
},
)),
]),
_: 1,
},
),
createVNode(
Z,
{
value: `access`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createBlock(
me,
{
key: 1,
info: unref(R),
"host-id": n.hostId,
"product-id": n.productId,
module: n.module,
caps: unref(H),
detail: n.detail,
"pending-action": unref(S),
onRefresh: (i[4] ||= (e) =>
b(`refresh`)),
onActionConsumed: le,
},
null,
8,
[
`info`,
`host-id`,
`product-id`,
`module`,
`caps`,
`detail`,
`pending-action`,
],
))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
X(`暂不能进行访问相关操作。`),
),
1,
),
]),
_: 1,
},
)),
]),
_: 1,
},
),
unref(H).disk === !1
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
Z,
{
key: 0,
value: `disk`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createBlock(
he,
{
key: 1,
disks: unref(R).disks,
"host-id": n.hostId,
"product-id": n.productId,
module: n.module,
"upgrade-allowed":
unref(H).upgrade,
loading: unref(U),
error: unref(W),
loaded: unref(G),
onPay: (i[5] ||= (e) =>
b(`pay`, e)),
onRefresh: unref(K),
},
null,
8,
[
`disks`,
`host-id`,
`product-id`,
`module`,
`upgrade-allowed`,
`loading`,
`error`,
`loaded`,
`onRefresh`,
],
))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
X(`暂不能管理硬盘。`),
),
1,
),
]),
_: 1,
},
)),
]),
_: 1,
},
)),
createVNode(
Z,
{
value: `network`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createBlock(
ge,
{
key: 1,
info: unref(R),
"host-id": n.hostId,
"product-id": n.productId,
module: n.module,
caps: unref(H),
onPay: (i[6] ||= (e) =>
b(`pay`, e)),
onRefresh: (i[7] ||= (e) =>
b(`refresh`)),
},
null,
8,
[
`info`,
`host-id`,
`product-id`,
`module`,
`caps`,
],
))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
X(`暂无网络信息。`),
),
1,
),
]),
_: 1,
},
)),
]),
_: 1,
},
),
unref(H).snapshot
? (openBlock(),
createBlock(
Z,
{
key: 1,
value: `backup`,
},
{
default: withCtx(() => [
unref(q)
? (openBlock(),
createElementBlock(`div`, P, [
createElementVNode(`section`, F, [
createVNode(
Q,
{
"product-id": n.productId,
"upgrade-allowed":
unref(H).upgrade,
module: n.module,
"host-id": n.hostId,
kind: `snapshot`,
limit: Number(
unref(R).raw.snap_num ??
0,
),
onPay: (i[8] ||= (e) =>
b(`pay`, e)),
},
null,
8,
[
`product-id`,
`upgrade-allowed`,
`module`,
`host-id`,
`limit`,
],
),
]),
createElementVNode(`section`, I, [
createVNode(
Q,
{
"product-id": n.productId,
"upgrade-allowed":
unref(H).upgrade,
module: n.module,
"host-id": n.hostId,
kind: `backup`,
limit: Number(
unref(R).raw.backup_num ??
0,
),
"backup-mode": String(
unref(R).raw
.backup_mode ?? ``,
),
onPay: (i[9] ||= (e) =>
b(`pay`, e)),
},
null,
8,
[
`product-id`,
`upgrade-allowed`,
`module`,
`host-id`,
`limit`,
`backup-mode`,
],
),
]),
]))
: (openBlock(),
createBlock(
c,
{
key: 0,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(i[12] ||= [
createTextVNode(
`实例尚未开通,暂不能管理备份与快照。`,
-1,
),
]),
]),
_: 1,
},
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
Z,
{
value: `billing`,
},
{
default: withCtx(() => [
createVNode(
$,
{
"product-state": n.productState,
"upgrade-allowed": unref(H).upgrade,
host: n.host,
info: unref(R),
"host-id": n.hostId,
module: n.module,
disks: unref(R).disks,
provisioned: unref(q),
onPay: (i[10] ||= (e) => b(`pay`, e)),
},
null,
8,
[
`product-state`,
`upgrade-allowed`,
`host`,
`info`,
`host-id`,
`module`,
`disks`,
`provisioned`,
],
),
]),
_: 1,
},
),
unref(H).log
? (openBlock(),
createBlock(
Z,
{
key: 2,
value: `log`,
},
{
default: withCtx(() => [
J.value === `log`
? (openBlock(),
createBlock(
_e,
{
key: 0,
"host-id": n.hostId,
module: n.module,
},
null,
8,
[`host-id`, `module`],
))
: createCommentVNode(``, !0),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
}),
]),
_: 1,
},
8,
[`value`],
))
: createCommentVNode(``, !0),
])
);
};
},
}),
[[`__scopeId`, `data-v-627058ac`]],
),
{
__name: `InstanceManage`,
},
);
export {};
export default L;
</script>
+757
View File
@@ -0,0 +1,757 @@
<script>
import "~/assets/styles/InstanceMonitor.B0X15iQt.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { defineAsyncComponent } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { loadModule } from "~/utils/load-module.js";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import { t as useTheme_t } from "~/lib/useTheme.js";
import message from "primevue/message";
import ListSegments from "~/components/ListSegments.vue";
import skeleton from "primevue/skeleton";
import { n as finance_resource_chart_n } from "~/lib/finance-resource-chart.js";
import { t as finance_resource_chart_t } from "~/lib/finance-resource-chart.js";
var O = defineAsyncComponent(() =>
loadModule(
() => import("~/components/ChartBox.vue").then((e) => e.default || e),
[],
import.meta.url,
),
),
k = {
class: `mon`,
},
A = {
class: `range-row`,
},
j = {
class: `hint`,
},
M = {
key: 1,
class: `charts`,
},
N = {
class: `chart-title`,
},
P = {
class: `chart-viewport`,
},
F = {
key: 2,
class: `charts`,
},
I = {
class: `chart-title`,
},
L = {
key: 0,
class: `chart-unit`,
},
R = {
class: `chart-viewport`,
},
z = {
key: 0,
class: `chart-error`,
},
B = {
key: 2,
class: `chart-empty`,
},
V = {
class: `refresh-row`,
},
H = `#f59e0b`,
U = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceMonitor`,
props: {
hostId: {},
module: {},
},
setup(a) {
let g = a,
y = useApi(),
S = useTheme_t(),
U = computed(() => (S.isDark.value ? `#38bdf8` : `#0ea5e9`)),
W = ref([]),
G = ref(!1),
K = ref(``),
q = 0,
J = !1,
Y = ``,
X = [
{
label: `1小时`,
value: 3600,
},
{
label: `24小时`,
value: 86400,
},
{
label: `7天`,
value: 604800,
},
{
label: `1个月`,
value: 2592e3,
},
{
label: `1年`,
value: 31536e3,
},
],
Z = ref(86400),
Q = (e) => {
let t = new Date(e * 1e3);
return `${String(t.getHours()).padStart(2, `0`)}:${String(t.getMinutes()).padStart(2, `0`)}`;
};
async function te(e, t, n = `mf_cloud`) {
let r = [
{
type: `cpu`,
title: `CPU 使用率`,
max: 100,
pick: [
{
name: `CPU`,
fn: (e) => e.value,
color: U.value,
unit: `%`,
},
],
},
{
type: `memory`,
title: `内存使用率`,
max: 100,
pick: [
{
name: `内存`,
fn: (e) =>
e.total
? (Number(e.used ?? 0) / Number(e.total)) * 100
: void 0,
color: U.value,
unit: `%`,
},
],
},
{
type: `bw`,
title: `带宽(入 / 出)`,
pick: [
{
name: `入`,
fn: (e) => e.in_bw,
color: U.value,
},
{
name: `出`,
fn: (e) => e.out_bw,
color: H,
},
],
scale: `bits`,
},
{
type: `disk_io`,
title: `硬盘 IO(读 / 写)`,
pick: [
{
name: `读`,
fn: (e) => e.read_bytes,
color: U.value,
unit: `B/s`,
},
{
name: `写`,
fn: (e) => e.write_bytes,
color: H,
unit: `B/s`,
},
],
},
];
function i(e) {
let t = e > 0 ? Math.max(0, Math.floor(Math.log2(e) / 10)) : 0,
n = [`bps`, `Kbps`, `Mbps`, `Gbps`, `Tbps`];
return {
divisor: 1024 ** t,
unit: n[Math.min(t, n.length - 1)],
};
}
let a = n === `jy_dcim` ? r.filter((e) => e.type === `bw`) : r,
o = await Promise.allSettled(
a.map((r) =>
y.get(`/${n}/${e}/chart`, {
type: r.type,
start_time: t,
}),
),
);
return a.map((e, t) => {
let n = o[t];
if (n.status === `rejected`)
return {
key: e.type,
title: e.title,
labels: [],
series: [],
error:
n.reason instanceof Error
? n.reason.message
: `监控数据加载失败,请重试`,
};
let r = n.value.list ?? [],
a = e.pick.map((e) =>
r.map((t) => {
let n = e.fn(t);
return n === void 0 || Number.isNaN(n) ? null : Number(n);
}),
),
s =
e.scale === `bits`
? i(Math.max(0, ...a.flat().filter((e) => e !== null)))
: null;
return {
key: e.type,
title: e.title,
max: e.max,
labels: r.map((e) => Q(e.time)),
series: e.pick.map((e, t) => ({
name: e.name,
unit: s ? s.unit : e.unit,
color: e.color,
data: a[t].map((e) =>
e === null
? null
: Number((e / (s?.divisor ?? 1)).toFixed(2)),
),
})),
};
});
}
async function ne(e, t, n) {
let r = [
{
type: `cpu`,
title: `CPU 使用率`,
max: 100,
},
{
type: `memory`,
title: `内存使用率`,
max: 100,
},
{
type: `flow`,
title: `带宽(进 / 出)`,
},
{
type: `disk`,
title: `硬盘 IO(读 / 写)`,
},
],
i = await Promise.allSettled(
r.map((r) =>
y.get(`/remf_finance/${e}/chart`, {
type: r.type,
start: t,
end: n,
}),
),
);
return r.map((e, t) => {
let n = i[t];
if (n.status === `rejected`)
return {
key: e.type,
title: e.title,
labels: [],
series: [],
error:
n.reason instanceof Error
? n.reason.message
: `监控数据加载失败,请重试`,
};
let r = n.value ?? {};
if (e.type === `cpu` || e.type === `memory`) {
let t = finance_resource_chart_n(r, e.type);
return {
key: e.type,
title: e.title,
max: 100,
labels: t.labels,
series: [
{
name: e.type === `cpu` ? `CPU` : `内存`,
unit: `%`,
color: U.value,
data: t.data,
},
],
};
}
let a = (r.list?.[0] ?? []).map((e) =>
String(e.time ?? ``).slice(11, 16),
),
o = (r.list ?? []).map((e, t) => ({
name: String(r.label?.[t] ?? `系列 ${t + 1}`).replace(
/\(.*\)$/,
``,
),
unit: r.unit,
color: t === 0 ? U.value : H,
data: e.map((e) => finance_resource_chart_t(e.value)),
}));
return {
key: e.type,
title: e.title,
max: e.max,
labels: a,
series: o,
};
});
}
async function re(e) {
let t = await y.get(`/kky_ecs/monitor/${e}`),
n = (t.sample_info ?? []).map((e) =>
String(e.timestamp ?? ``).slice(11, 16),
),
r = (e, t, r, i, a, o = 1) => ({
key: e,
title: t,
labels: n,
series: (r ?? []).map((e, t) => ({
name: e.title,
unit: a,
color: i[t % i.length],
data: (e.value ?? []).map((e) =>
typeof e == `number` ? Number((e / o).toFixed(2)) : null,
),
})),
});
return [
r(`cpu`, `CPU 使用率`, t.cpu, [U.value], `%`),
r(`memory`, `内存`, t.memory, [U.value, H], `KB`),
r(`bandwidth`, `带宽`, t.bandwidth, [U.value, H], `Mbps`, 1e3),
r(`disk`, `硬盘 IO`, t.disk, [U.value, H], `KB/s`),
];
}
async function $() {
if (J) return;
let e = ++q,
t = g.hostId,
n = g.module,
r = Z.value,
i = `${n}:${t}:${n === `kky_ecs` ? `` : r}`,
a = () =>
!J &&
e === q &&
t === g.hostId &&
n === g.module &&
(n === `kky_ecs` || r === Z.value);
((G.value = !0), (K.value = ``), Y !== i && (W.value = []));
try {
let e = Date.now(),
o =
n === `mf_cloud` ||
n === `remf_cloud` ||
n === `jy_cloud` ||
n === `jy_dcim`
? await te(t, Math.floor(e / 1e3) - r, n)
: n === `remf_finance`
? await ne(t, e - r * 1e3, e)
: await re(t);
a() && ((W.value = o), (Y = i));
} catch (e) {
if (!a()) return;
((K.value = e instanceof Error ? e.message : `加载监控数据失败`),
(W.value = []));
} finally {
a() && (G.value = !1);
}
}
function ie(e) {
if (g.module === `kky_ecs` || e === void 0) return;
let t = Number(e);
if (X.some((e) => e.value === t)) return ((Z.value = t), $());
}
let ae = (e) => e.series.some((e) => e.data.some((e) => e !== null));
function oe(e) {
let t = S.isDark.value ? `#a1a1aa` : `#94a3b8`,
n = S.isDark.value ? `rgba(255,255,255,.08)` : `rgba(0,0,0,.06)`;
return {
grid: {
left: 6,
right: 10,
top: 26,
bottom: 4,
outerBoundsMode: `same`,
outerBoundsContain: `axisLabel`,
},
tooltip: {
trigger: `axis`,
},
legend:
e.series.length > 1
? {
top: 0,
right: 0,
itemWidth: 10,
itemHeight: 2,
textStyle: {
fontSize: 11,
},
}
: void 0,
xAxis: {
type: `category`,
data: e.labels,
boundaryGap: !1,
axisTick: {
show: !1,
},
axisLine: {
lineStyle: {
color: n,
},
},
axisLabel: {
color: t,
fontSize: 11,
},
},
yAxis: {
type: `value`,
max: e.max,
axisLine: {
show: !1,
},
axisTick: {
show: !1,
},
axisLabel: {
color: t,
fontSize: 11,
formatter: e.series.every((e) => e.unit === `%`)
? (e) => `${e}%`
: void 0,
},
splitLine: {
lineStyle: {
color: n,
},
},
},
series: e.series.map((t) => ({
name: t.name,
type: `line`,
smooth: !0,
showSymbol: !1,
connectNulls: !1,
areaStyle:
e.series.length === 1
? {
opacity: 0.12,
}
: void 0,
lineStyle: {
width: 1.6,
color: t.color,
},
itemStyle: {
color: t.color,
},
data: t.data,
tooltip: {
valueFormatter: (e) =>
e == null
? `暂无数据`
: t.unit === `%`
? `${e}%`
: t.unit
? `${e} ${t.unit}`
: String(e),
},
})),
};
}
return (
onMounted($),
watch(() => [g.hostId, g.module], $),
onBeforeUnmount(() => {
((J = !0), (q += 1));
}),
(n, r) => {
let i = ListSegments,
s = button,
u = message,
g = skeleton,
y = O;
return (
openBlock(),
createElementBlock(`div`, k, [
createElementVNode(`div`, A, [
a.module === `kky_ecs`
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
i,
{
key: 0,
"aria-label": `监控时间范围`,
"model-value": unref(Z),
options: X,
"onUpdate:modelValue": ie,
},
null,
8,
[`model-value`],
)),
createElementVNode(`span`, j, [
a.module === `kky_ecs`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createTextVNode(
`数据由平台采集,可查询的时间范围固定。`,
),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`数据由平台采集,实例未运行时可能为空。`,
),
],
64,
)),
]),
]),
unref(K)
? (openBlock(),
createBlock(
u,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(K)) + ` `, 1),
createVNode(
s,
{
label: `重试`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(G),
onClick: $,
},
null,
8,
[`loading`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(G) && !unref(W).length
? (openBlock(),
createElementBlock(`div`, M, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(4, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `chart-card`,
},
[
createElementVNode(`div`, N, [
createVNode(g, {
width: `35%`,
height: `24px`,
}),
]),
createElementVNode(`div`, P, [
createVNode(g, {
height: `280px`,
}),
]),
],
),
),
64,
)),
]))
: (openBlock(),
createElementBlock(`div`, F, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(W),
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.key,
class: `chart-card`,
},
[
createElementVNode(`div`, I, [
createTextVNode(
toDisplayString(t.title),
1,
),
t.series[0]?.unit
? (openBlock(),
createElementBlock(
`span`,
L,
`(` +
toDisplayString(t.series[0].unit) +
`)`,
1,
))
: createCommentVNode(``, !0),
]),
createElementVNode(`div`, R, [
t.error
? (openBlock(),
createElementBlock(`div`, z, [
createVNode(
u,
{
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(t.error) +
` `,
1,
),
createVNode(
s,
{
label: `重试`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(G),
onClick: $,
},
null,
8,
[`loading`],
),
]),
_: 2,
},
1024,
),
]))
: ae(t)
? (openBlock(),
createBlock(
y,
{
key: 1,
option: oe(t),
height: 280,
loading: unref(G),
},
null,
8,
[`option`, `loading`],
))
: (openBlock(),
createElementBlock(
`p`,
B,
`暂无监控数据`,
)),
]),
],
)
),
),
128,
)),
])),
createElementVNode(`div`, V, [
createVNode(
s,
{
label: `刷新`,
icon: `pi pi-refresh`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(G),
onClick: $,
},
null,
8,
[`loading`],
),
]),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-6a900feb`]],
),
{
__name: `InstanceMonitor`,
},
);
export {};
export default U;
</script>
@@ -0,0 +1,147 @@
<script>
import "~/assets/styles/InstanceMonitorSkeleton.C0FT51jJ.css";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { createCommentVNode } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import skeleton from "primevue/skeleton";
var d = {
class: `range-placeholder`,
"aria-hidden": `true`,
},
f = {
key: 0,
class: `hint-placeholder`,
},
p = {
class: `title-placeholder`,
},
m = {
key: 0,
class: `legend-placeholder`,
},
h = {
key: 0,
class: `refresh-placeholder`,
"aria-hidden": `true`,
},
g = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceMonitorSkeleton`,
props: {
dcim: {
type: Boolean,
default: !1,
},
},
setup(o) {
return (l, g) => {
let _ = skeleton;
return (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`monitor-skeleton`,
{
dcim: o.dcim,
},
]),
role: `status`,
"aria-label": `正在加载监控`,
"aria-busy": `true`,
},
[
createElementVNode(`div`, d, [
createVNode(_, {
width: `340px`,
height: `40px`,
}),
o.dcim
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`span`,
f,
`数据由平台采集,实例未运行时可能为空。`,
)),
]),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
o.dcim ? 1 : 4,
(e) => (
openBlock(),
createElementBlock(
`div`,
{
key: e,
class: `chart-placeholder`,
"aria-hidden": `true`,
},
[
createElementVNode(`div`, p, [
createVNode(_, {
width: `120px`,
height: `24px`,
}),
]),
o.dcim
? (openBlock(),
createElementBlock(`div`, m, [
createVNode(_, {
width: `180px`,
height: `21px`,
}),
]))
: createCommentVNode(``, !0),
createVNode(
_,
{
height: o.dcim ? `320px` : `280px`,
},
null,
8,
[`height`],
),
],
)
),
),
128,
)),
o.dcim
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, h, [
createVNode(_, {
width: `70px`,
height: `35px`,
}),
])),
],
2,
)
);
};
},
}),
[[`__scopeId`, `data-v-5a1fd568`]],
),
{
__name: `InstanceMonitorSkeleton`,
},
);
export {};
export default g;
</script>
+926
View File
@@ -0,0 +1,926 @@
<script>
import "~/assets/styles/MfCloudDefence.B2vl5Yip.css";
import "~/assets/styles/MfCloudVpc.CpOEbuWs.css";
import "~/assets/styles/MfCloudIps.jhFnuvcs.css";
import "~/assets/styles/InstanceTraffic.CyyEAXl3.css";
import "~/assets/styles/FlowPacketPanel.-RJSx13z.css";
import "~/assets/styles/InstanceNetwork.CyucZaZp.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import OperationNotice from "~/components/OperationNotice.vue";
import { n as configuration_display_n } from "~/lib/configuration-display.js";
import { i as cloud_instance_management_i } from "~/lib/cloud-instance-management.js";
import FlowPacketPanel from "~/components/instance/FlowPacketPanel.vue";
import InstanceTraffic from "~/components/instance/InstanceTraffic.vue";
import MfCloudIps from "~/components/mfcloud/MfCloudIps.vue";
import MfCloudVpc from "~/components/mfcloud/MfCloudVpc.vue";
import MfCloudDefence from "~/components/mfcloud/MfCloudDefence.vue";
var ce = {
class: `nw`,
},
le = {
class: `block`,
},
ue = {
class: `block-desc`,
},
de = {
class: `info-table`,
},
fe = {
class: `kv`,
},
pe = {
class: `kv`,
},
me = {
key: 0,
class: `kv`,
},
he = {
class: `kv`,
},
ge = {
class: `kv`,
},
_e = {
key: 0,
class: `block-desc`,
},
ve = {
class: `block`,
},
ye = {
key: 1,
class: `info-table`,
},
be = {
class: `col-mono`,
},
xe = {
key: 0,
class: `kv`,
},
Se = {
class: `col-mono`,
},
Ce = {
key: 1,
class: `kv`,
},
we = {
class: `action-cell`,
},
Te = {
key: 0,
class: `sub`,
},
Ee = {
key: 2,
class: `kv`,
},
De = {
key: 1,
class: `block`,
},
Oe = {
class: `block`,
},
ke = {
class: `info-table`,
},
Ae = {
key: 0,
class: `kv`,
},
S = {
class: `kv`,
},
C = {
class: `action-cell`,
},
je = {
key: 3,
class: `block`,
},
Me = {
class: `info-table`,
},
Ne = {
class: `kv`,
},
Pe = {
key: 0,
},
Fe = {
key: 1,
},
Ie = {
key: 2,
},
Le = {
class: `kv`,
},
w = {
class: `action-cell`,
},
Re = {
key: 4,
class: `block`,
role: `status`,
},
ze = {
class: `block-desc`,
},
T = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceNetwork`,
props: {
info: {},
hostId: {},
productId: {},
module: {},
caps: {},
},
emits: [`pay`, `refresh`],
setup(h, { emit: y }) {
let T = h,
E = y,
D = useApi(),
O = computed(() => configuration_display_n(T.module, T.info.raw)),
k = computed(() => cloud_instance_management_i(T.module)),
A = ref([]),
Be = computed(() => [...new Set([...T.info.ips, ...A.value])]);
watch(
() => [T.hostId, T.module],
() => {
A.value = [];
},
);
let j = ref(!1),
M = ref(``),
N = ref(``),
P = ref(!1),
F = ref(``),
I = computed(() =>
String(T.info.raw.intranet_ip || F.value || ``).trim(),
),
L = computed(
() =>
T.module === `kky_ecs` &&
!I.value &&
T.caps.upgrade !== !1 &&
[`on`, `off`].includes(T.info.powerStatus) &&
!P.value,
),
R = 0,
z = !1;
function B() {
(++R,
(j.value = !1),
(P.value = !1),
(F.value = ``),
(M.value = ``),
(N.value = ``));
}
async function Ve() {
if (z || j.value || !L.value) return;
let e = T.hostId,
t = ++R,
n = () =>
!z && t === R && T.hostId === e && T.module === `kky_ecs`;
((j.value = !0), (M.value = ``), (N.value = ``));
try {
let t = await D.post(`/kky_ecs/upgrade/${e}/add_intranet_ip`);
if (!n()) return;
((F.value = String(t?.intranet_ip || ``).trim()),
(P.value = !0),
(N.value = F.value
? `内网 IP 已添加`
: `内网 IP 分配请求已提交,请稍后刷新查看`),
F.value && E(`refresh`));
} catch (e) {
n() &&
(M.value =
e instanceof Error
? e.message
: `添加内网 IP 失败,请稍后重试`);
} finally {
n() && (j.value = !1);
}
}
watch(() => [T.hostId, T.module], B, {
flush: `sync`,
});
let V = computed(() =>
[`mf_cloud`, `remf_cloud`, `remf_finance`].includes(T.module),
),
H = ref(null),
U = ref(!1),
W = ref(!1),
G = ref(`loading`),
K = ref(null),
q = ref(``),
J = ref(``);
function He(e) {
return e.status === 1
? `已通过`
: e.status === -1
? `已驳回`
: e.need_review
? `等待人工审核`
: `处理中`;
}
let Y = 0,
X = 0;
function Ue(e) {
return (
typeof e == `object` &&
!!e &&
`status` in e &&
Number(e.status) === 400 &&
`message` in e &&
String(e.message).includes(`该商品暂不支持域名过白`)
);
}
async function Z(e) {
let t = ++X,
n = () => t === X && T.hostId === e;
((G.value = `loading`),
(K.value = null),
(q.value = ``),
(J.value = ``));
try {
if (
(await D.get(`/domain_whitelist/form`, {
host_id: e,
}),
!n())
)
return;
G.value = `supported`;
} catch (e) {
if (!n()) return;
if (Ue(e)) {
G.value = `unsupported`;
return;
}
((G.value = `error`),
(q.value =
e instanceof Error
? e.message
: `暂时无法确认域名白名单状态,请重试`));
return;
}
try {
let t = await D.get(`/domain_whitelist/record`, {
host_id: e,
page: 1,
limit: 1,
});
n() && (K.value = t.list?.[0] ?? null);
} catch (e) {
n() &&
(J.value =
e instanceof Error
? e.message
: `读取白名单记录失败,请重试`);
}
}
function Q() {
Z(T.hostId);
}
async function $() {
let e = ++Y,
t = T.hostId;
if (
((H.value = null),
(U.value = !1),
(W.value =
T.caps.traffic !== !1 &&
[`mf_cloud`, `remf_cloud`].includes(T.module)),
T.caps.traffic !== !1 &&
(T.module === `mf_cloud` || T.module === `remf_cloud`))
)
try {
let n = await D.get(`/${T.module}/${t}/flow`);
e === Y && (H.value = n);
} catch {
e === Y && (U.value = !0);
} finally {
e === Y && (W.value = !1);
}
e === Y && (await Z(t));
}
return (
onMounted($),
watch(() => [T.hostId, T.module], $),
onBeforeUnmount(() => {
(Y++, X++, (z = !0), B());
}),
(n, r) => {
let i = MfCloudIps,
o = button,
l = OperationNotice,
v = MfCloudVpc,
y = MfCloudDefence,
b = InstanceTraffic,
x = FlowPacketPanel,
T = NuxtLink;
return (
openBlock(),
createElementBlock(`div`, ce, [
createElementVNode(`section`, le, [
(r[11] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`公共网络`,
-1,
)),
createElementVNode(`p`, ue, [
(r[5] ||= createTextVNode(
` 任何人都可以通过公共网络地址访问您的服务器。`,
-1,
)),
h.caps.upgrade === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`若您需要调整带宽上限或流量配额,请前往「计费」进行升降级。`,
),
],
64,
)),
]),
createElementVNode(`div`, de, [
createElementVNode(`div`, fe, [
(r[6] ||= createElementVNode(`span`, null, `区域`, -1)),
createElementVNode(
`b`,
null,
toDisplayString(unref(O).region || `—`),
1,
),
]),
createElementVNode(`div`, pe, [
(r[7] ||= createElementVNode(`span`, null, `线路`, -1)),
createElementVNode(
`b`,
null,
toDisplayString(unref(O).line || `—`),
1,
),
]),
unref(O).networkType
? (openBlock(),
createElementBlock(`div`, me, [
(r[8] ||= createElementVNode(
`span`,
null,
`网络类型`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(unref(O).networkType),
1,
),
]))
: createCommentVNode(``, !0),
createElementVNode(`div`, he, [
(r[9] ||= createElementVNode(
`span`,
null,
`带宽上限`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
h.info.bw > 0 ? `${h.info.bw} Mbps` : `不限制`,
),
1,
),
]),
createElementVNode(`div`, ge, [
(r[10] ||= createElementVNode(
`span`,
null,
`防护峰值`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
h.info.protect > 0 ? `${h.info.protect} Gbps` : `—`,
),
1,
),
]),
]),
h.info.protect > 0
? (openBlock(),
createElementBlock(`p`, _e, `在防御峰值内提供保护。`))
: createCommentVNode(``, !0),
]),
createElementVNode(`section`, ve, [
(r[16] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`IP 地址`,
-1,
)),
unref(k)
? (openBlock(),
createBlock(
i,
{
key: 0,
"host-id": h.hostId,
module: h.module,
"upgrade-allowed": h.caps.upgrade,
onAddresses: (r[0] ||= (e) => (A.value = e)),
onPay: (r[1] ||= (e) => E(`pay`, e)),
},
null,
8,
[`host-id`, `module`, `upgrade-allowed`],
))
: (openBlock(),
createElementBlock(`div`, ye, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
h.info.ips,
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t,
class: `kv`,
},
[
(r[12] ||= createElementVNode(
`span`,
null,
`IPv4 地址`,
-1,
)),
createElementVNode(
`b`,
be,
toDisplayString(t),
1,
),
],
)
),
),
128,
)),
unref(I)
? (openBlock(),
createElementBlock(`div`, xe, [
(r[13] ||= createElementVNode(
`span`,
null,
`内网地址`,
-1,
)),
createElementVNode(
`b`,
Se,
toDisplayString(unref(I)),
1,
),
]))
: h.module === `kky_ecs` && h.caps.upgrade !== !1
? (openBlock(),
createElementBlock(`div`, Ce, [
(r[14] ||= createElementVNode(
`span`,
null,
`内网地址`,
-1,
)),
createElementVNode(`div`, we, [
createVNode(
o,
{
label: `添加内网 IP`,
icon: `pi pi-plus`,
size: `small`,
severity: `secondary`,
outlined: ``,
loading: unref(j),
disabled: unref(j) || !unref(L),
onClick: Ve,
},
null,
8,
[`loading`, `disabled`],
),
!unref(L) && !unref(j) && !unref(P)
? (openBlock(),
createElementBlock(
`span`,
Te,
`实例正常开机或关机时可添加`,
))
: createCommentVNode(``, !0),
]),
]))
: createCommentVNode(``, !0),
h.info.ips.length
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, Ee, [
...(r[15] ||= [
createElementVNode(
`span`,
null,
`IPv4 地址`,
-1,
),
createElementVNode(
`b`,
null,
`暂无 IP 地址`,
-1,
),
]),
])),
])),
createVNode(
l,
{
message: unref(M),
severity: `error`,
},
null,
8,
[`message`],
),
createVNode(
l,
{
message: unref(N),
severity: `success`,
},
null,
8,
[`message`],
),
]),
unref(k)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createVNode(
v,
{
"host-id": h.hostId,
"product-id": h.productId,
module: h.module,
"network-type": String(
h.info.raw.network_type ?? ``,
),
"data-center-id":
Number(h.info.raw.data_center?.id) || void 0,
active: [`on`, `off`].includes(
h.info.powerStatus,
),
onRefresh: (r[2] ||= (e) => E(`refresh`)),
},
null,
8,
[
`host-id`,
`product-id`,
`module`,
`network-type`,
`data-center-id`,
`active`,
],
),
createVNode(
y,
{
"host-id": h.hostId,
module: h.module,
ips: unref(Be),
active: [`on`, `off`].includes(
h.info.powerStatus,
),
"upgrade-allowed": h.caps.upgrade,
onPay: (r[3] ||= (e) => E(`pay`, e)),
},
null,
8,
[
`host-id`,
`module`,
`ips`,
`active`,
`upgrade-allowed`,
],
),
],
64,
))
: createCommentVNode(``, !0),
h.caps.traffic === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`section`, De, [
(r[17] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`网络流量`,
-1,
)),
createVNode(
b,
{
layout: `table`,
module: h.module,
"host-id": h.hostId,
raw: h.info.raw,
flow: unref(H),
loading: unref(W),
failed: unref(U),
},
null,
8,
[
`module`,
`host-id`,
`raw`,
`flow`,
`loading`,
`failed`,
],
),
])),
unref(V)
? (openBlock(),
createBlock(
x,
{
key: 2,
"host-id": h.hostId,
module: h.module,
flow: unref(H),
onPay: (r[4] ||= (e) => E(`pay`, e)),
},
null,
8,
[`host-id`, `module`, `flow`],
))
: createCommentVNode(``, !0),
createElementVNode(`section`, Oe, [
(r[20] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`安全组`,
-1,
)),
(r[21] ||= createElementVNode(
`p`,
{
class: `block-desc`,
},
` 安全组是一种虚拟防火墙,用于控制实例级别的入站和出站网络流量。 请确保所选安全组已放通 22 端口(Linux SSH 登录)、3389 端口(Windows 远程登录),否则无法远程登录。 `,
-1,
)),
createElementVNode(`div`, ke, [
unref(V)
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, Ae, [
(r[18] ||= createElementVNode(
`span`,
null,
`当前安全组`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
h.info.securityGroupName || `未加入安全组`,
),
1,
),
])),
createElementVNode(`div`, S, [
(r[19] ||= createElementVNode(
`span`,
null,
`安全组管理`,
-1,
)),
createElementVNode(`div`, C, [
createVNode(
T,
{
to: `/security/groups`,
},
{
default: withCtx(() => [
createVNode(o, {
label: `前往安全组管理`,
size: `small`,
severity: `secondary`,
outlined: ``,
icon: `pi pi-shield`,
}),
]),
_: 1,
},
),
]),
]),
]),
]),
unref(G) === `supported`
? (openBlock(),
createElementBlock(`section`, je, [
(r[24] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`域名白名单`,
-1,
)),
(r[25] ||= createElementVNode(
`p`,
{
class: `block-desc`,
},
` 使用中国大陆机房提供 HTTP/HTTPS 服务前需要先完成域名过白。白名单仅需提交一级域名,通过后所有子域名均可使用。 `,
-1,
)),
createElementVNode(`div`, Me, [
createElementVNode(`div`, Ne, [
(r[22] ||= createElementVNode(
`span`,
null,
`最近提交`,
-1,
)),
unref(J)
? (openBlock(),
createElementBlock(
`b`,
Pe,
`读取失败:` + toDisplayString(unref(J)),
1,
))
: unref(K)
? (openBlock(),
createElementBlock(
`b`,
Fe,
toDisplayString(
unref(K).domains.join(`、`),
) +
` · ` +
toDisplayString(He(unref(K))),
1,
))
: (openBlock(),
createElementBlock(`b`, Ie, `暂无记录`)),
]),
createElementVNode(`div`, Le, [
(r[23] ||= createElementVNode(
`span`,
null,
`白名单管理`,
-1,
)),
createElementVNode(`div`, w, [
createVNode(
T,
{
to: `/security/domains?host_id=${h.hostId}`,
},
{
default: withCtx(() => [
createVNode(o, {
label: `前往域名白名单`,
size: `small`,
severity: `secondary`,
outlined: ``,
icon: `pi pi-shield`,
}),
]),
_: 1,
},
8,
[`to`],
),
unref(J)
? (openBlock(),
createBlock(o, {
key: 0,
label: `重试读取`,
size: `small`,
severity: `secondary`,
text: ``,
icon: `pi pi-refresh`,
onClick: Q,
}))
: createCommentVNode(``, !0),
]),
]),
]),
]))
: unref(G) === `error`
? (openBlock(),
createElementBlock(`section`, Re, [
(r[26] ||= createElementVNode(
`h4`,
{
class: `block-title`,
},
`域名白名单`,
-1,
)),
createElementVNode(
`p`,
ze,
toDisplayString(unref(q)),
1,
),
createVNode(o, {
label: `重试`,
size: `small`,
severity: `secondary`,
outlined: ``,
icon: `pi pi-refresh`,
onClick: Q,
}),
]))
: createCommentVNode(``, !0),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-aa906366`]],
),
{
__name: `InstanceNetwork`,
},
);
export {};
export default T;
</script>
@@ -0,0 +1,797 @@
<script>
import "~/assets/styles/InstanceOnDemand.okGWwgIJ.css";
import { toDisplayString } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { r as dict_r } from "~/lib/dict.js";
import select from "primevue/select";
import checkbox from "primevue/checkbox";
import skeleton from "primevue/skeleton";
import datepicker from "primevue/datepicker";
var oe = {
class: `on-demand`,
},
se = {
key: 2,
},
ce = {
class: `actions`,
},
le = {
key: 3,
},
x = {
key: 4,
},
S = {
key: 6,
},
ue = {
key: 1,
},
de = {
key: 0,
},
fe = {
class: `confirmation`,
},
C = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceOnDemand`,
props: {
host: {},
hostId: {},
},
emits: [`refresh`, `pay`],
setup(m, { emit: b }) {
let C = m,
w = b,
T = useApi(),
E = computed(() => C.host.billing_cycle === `on_demand`),
D = computed(() => Number(C.host.change_billing_cycle_id) > 0),
O = computed(() => {
if (D.value) return `已设置到期转换计划。`;
if (!E.value && C.host.billing_cycle !== `recurring_prepayment`)
return `当前计费方式不支持到期转为按需计费。`;
let e = E.value
? C.host.product_on_demand?.on_demand_to_duration
: C.host.product_on_demand?.duration_to_on_demand;
return e == null
? `计费转换能力信息未返回,请刷新实例详情。`
: Number(e) === 1
? E.value && Number(C.host.auto_release_time) > 0
? `请先取消自动释放计划,再转为包年包月。`
: (E.value ? [`Active`, `Grace`] : [`Active`]).includes(
C.host.status,
)
? ``
: `当前实例状态不支持计费转换。`
: E.value
? `当前商品未开启按需转包年包月。`
: `当前商品未开启包年包月转按需计费。`;
}),
k = computed(() => {
if (!E.value) return `自动释放设置仅支持按需计费实例。`;
let e = C.host.product_on_demand?.client_auto_delete;
return e == null
? `自动释放能力信息未返回,请刷新实例详情。`
: Number(e) === 1
? C.host.status === `Active`
? ``
: `当前实例状态不支持修改自动释放时间。`
: `当前商品未开启自动释放设置。`;
}),
A = computed(() => !O.value),
j = computed(() => !k.value),
pe = computed(
() =>
(E.value
? C.host.product_on_demand?.on_demand_to_duration
: C.host.product_on_demand?.duration_to_on_demand) == null ||
(E.value &&
C.host.product_on_demand?.client_auto_delete == null),
),
M = computed(
() =>
`/host/${C.hostId}/${E.value ? `on_demand_to_recurring_prepayment` : `recurring_prepayment_to_on_demand`}`,
),
N = ref(!1),
P = ref(!1),
F = ref(!1),
I = ref(``),
L = ref(``),
R = ref([]),
z = ref(null),
B = ref(null),
V = ref(!1),
H = ref(null),
U = ref(!1),
W = ref(!1),
G = 0,
K = !1,
q = () =>
`${C.hostId}:${C.host.billing_cycle}:${C.host.change_billing_cycle_id}:${A.value}:${j.value}`,
J = (e) =>
e != null &&
String(e).trim() !== `` &&
Number.isFinite(Number(e)) &&
Number(e) >= 0,
Y = ``,
X = computed(() => R.value.find((e) => e.id === z.value)),
Z = computed(
() =>
!P.value &&
!F.value &&
A.value &&
Y === q() &&
(E.value ? !!X.value : !!B.value),
);
function Q() {
(G++,
(Y = ``),
(N.value = V.value = W.value = !1),
(P.value = !1),
(R.value = []),
(B.value = null),
(I.value = ``),
(L.value = ``));
}
(watch(q, Q, {
flush: `sync`,
}),
onBeforeUnmount(() => {
((K = !0), Q());
}));
async function $() {
if (!A.value || F.value) return;
((N.value = !0),
(P.value = !0),
(I.value = ``),
(Y = ``),
(R.value = []),
(B.value = null),
(z.value = null));
let e = ++G,
t = q();
try {
let n = await T.get(M.value);
if (K || e !== G || !N.value || t !== q()) return;
if (E.value) {
if (
!Array.isArray(n?.duration) ||
!n.duration.length ||
n.duration.some(
(e) =>
!Number.isSafeInteger(Number(e.id)) ||
Number(e.id) <= 0 ||
!J(e.price),
)
)
throw Error(`未获得可用周期报价,请重试`);
((R.value = n.duration), (z.value = n.duration[0].id));
} else {
if (
!J(n.on_demand_price) ||
(n.keep_time_price != null && !J(n.keep_time_price))
)
throw Error(`按需价格响应无效,请重试`);
B.value = {
...n,
on_demand_price: n.on_demand_price,
};
}
Y = t;
} catch (t) {
e === G &&
!K &&
(I.value = t instanceof Error ? t.message : `计费报价加载失败`);
} finally {
e === G && !K && (P.value = !1);
}
}
async function me() {
if (!Z.value) return;
((F.value = !0), (I.value = ``));
let e = G,
t = E.value,
n = M.value;
try {
let r = await T.post(
n,
t
? {
duration_id: z.value,
}
: void 0,
);
if (K || G !== e) return;
if (t) {
if (
!Number.isSafeInteger(Number(r?.id)) ||
Number(r.id) <= 0 ||
!J(r.amount)
)
throw Error(`转换订单响应无效,请到订单列表核对`);
w(`pay`, {
order_id: r.id,
amount: r.amount,
});
} else L.value = `已申请到期转为按需计费`;
((N.value = !1), (Y = ``), w(`refresh`));
} catch (t) {
e === G &&
!K &&
(I.value = t instanceof Error ? t.message : `转换申请失败`);
} finally {
F.value = !1;
}
}
async function he() {
if (!D.value || F.value || !W.value) return;
((F.value = !0), (I.value = ``));
let e = G;
try {
if (
(await T.del(
`/host/${C.hostId}/recurring_prepayment_to_on_demand`,
),
K || e !== G)
)
return;
((W.value = !1), (L.value = `已取消到期转换计划`), w(`refresh`));
} catch (t) {
!K &&
e === G &&
(I.value = t instanceof Error ? t.message : `取消转换失败`);
} finally {
F.value = !1;
}
}
function ge() {
j.value &&
!F.value &&
((H.value =
Number(C.host.auto_release_time) > 0
? new Date(Number(C.host.auto_release_time) * 1e3)
: null),
(U.value = !1),
(I.value = ``),
(V.value = !0));
}
async function _e() {
if (!j.value || F.value || !V.value || !U.value) return;
let e = H.value ? Math.floor(H.value.getTime() / 1e3) : 0;
if (
H.value &&
(!Number.isSafeInteger(e) || e <= Date.now() / 1e3)
) {
I.value = `请选择将来的释放时间`;
return;
}
((F.value = !0), (I.value = ``));
let t = G;
try {
if (
(await T.put(`/host/${C.hostId}/auto_release_time`, {
auto_release_time: e,
}),
K || t !== G)
)
return;
((V.value = !1),
(L.value = e ? `自动释放时间已保存` : `已取消自动释放`),
w(`refresh`));
} catch (e) {
!K &&
t === G &&
(I.value = e instanceof Error ? e.message : `保存自动释放失败`);
} finally {
F.value = !1;
}
}
return (t, n) => {
let i = message,
s = button,
_ = skeleton,
b = select,
C = dialog,
T = datepicker,
M = checkbox;
return (
openBlock(),
createElementBlock(`section`, oe, [
(n[12] ||= createElementVNode(
`h4`,
null,
`计费转换与自动释放`,
-1,
)),
unref(L)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `success`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(L)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(I)
? (openBlock(),
createBlock(
i,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(D)
? (openBlock(),
createElementBlock(
`p`,
se,
`已申请到期转为按需计费,取消转换计划后才可续费或升降级。`,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ce, [
createVNode(
s,
{
label: unref(E) ? `转为包年包月` : `到期转为按需计费`,
disabled: !unref(A) || unref(F),
outlined: ``,
onClick: $,
},
null,
8,
[`label`, `disabled`],
),
unref(D)
? (openBlock(),
createBlock(
s,
{
key: 0,
label: `取消转换计划`,
disabled: unref(F),
outlined: ``,
onClick: (n[0] ||= (e) => (W.value = !0)),
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
createVNode(
s,
{
label: `设置自动释放`,
disabled: !unref(j) || unref(F),
outlined: ``,
onClick: ge,
},
null,
8,
[`disabled`],
),
]),
unref(O) && !unref(D)
? (openBlock(),
createElementBlock(
`small`,
le,
toDisplayString(unref(O)),
1,
))
: createCommentVNode(``, !0),
unref(k)
? (openBlock(),
createElementBlock(
`small`,
x,
toDisplayString(unref(k)),
1,
))
: createCommentVNode(``, !0),
unref(pe)
? (openBlock(),
createBlock(
s,
{
key: 5,
label: `刷新实例详情`,
text: ``,
size: `small`,
disabled: unref(F),
onClick: (n[1] ||= (e) => w(`refresh`)),
},
null,
8,
[`disabled`],
))
: createCommentVNode(``, !0),
m.host.auto_release_time
? (openBlock(),
createElementBlock(
`p`,
S,
`当前自动释放时间:` +
toDisplayString(
(`formatTime` in t ? t.formatTime : unref(dict_r))(
m.host.auto_release_time,
),
),
1,
))
: createCommentVNode(``, !0),
createVNode(
C,
{
visible: unref(N),
"onUpdate:visible": (n[3] ||= (e) =>
isRef(N) ? (N.value = e) : null),
header: `确认计费转换`,
modal: ``,
closable: !unref(F),
"close-on-escape": !unref(F),
style: {
width: `min(460px, calc(100vw - 28px))`,
},
},
{
footer: withCtx(() => [
createVNode(
s,
{
label: `重新报价`,
text: ``,
disabled: unref(F) || unref(P),
onClick: $,
},
null,
8,
[`disabled`],
),
createVNode(
s,
{
label: `确认转换`,
loading: unref(F),
disabled: !unref(Z),
onClick: me,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
unref(P)
? (openBlock(),
createBlock(_, {
key: 0,
height: `90px`,
}))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
unref(E)
? (openBlock(),
createBlock(
b,
{
key: 0,
modelValue: unref(z),
"onUpdate:modelValue": (n[2] ||= (e) =>
isRef(z) ? (z.value = e) : null),
options: unref(R),
"option-label": `name_show`,
"option-value": `id`,
disabled: unref(F),
placeholder: `选择计费周期`,
},
null,
8,
[`modelValue`, `options`, `disabled`],
))
: createCommentVNode(``, !0),
unref(E) && unref(X)
? (openBlock(),
createElementBlock(
`p`,
ue,
`转换费用:¥` +
toDisplayString(unref(X).price),
1,
))
: createCommentVNode(``, !0),
!unref(E) && unref(B)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(
`p`,
null,
`到期后按需出账:¥` +
toDisplayString(
unref(B).on_demand_price,
) +
` / ` +
toDisplayString(
unref(B).billing_cycle_name,
),
1,
),
unref(B).keep_time_price
? (openBlock(),
createElementBlock(
`p`,
de,
`保留期价格:¥` +
toDisplayString(
unref(B).keep_time_price,
),
1,
))
: createCommentVNode(``, !0),
],
64,
))
: createCommentVNode(``, !0),
],
64,
)),
unref(I)
? (openBlock(),
createBlock(
i,
{
key: 2,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
createVNode(
C,
{
visible: unref(W),
"onUpdate:visible": (n[4] ||= (e) =>
isRef(W) ? (W.value = e) : null),
header: `取消转换计划`,
modal: ``,
closable: !unref(F),
style: {
width: `min(420px, calc(100vw - 28px))`,
},
},
{
footer: withCtx(() => [
createVNode(
s,
{
label: `确认取消计划`,
loading: unref(F),
onClick: he,
},
null,
8,
[`loading`],
),
]),
default: withCtx(() => [
(n[9] ||= createElementVNode(
`p`,
null,
`取消后将保留当前计费方式。`,
-1,
)),
unref(I)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `error`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `closable`],
),
createVNode(
C,
{
visible: unref(V),
"onUpdate:visible": (n[8] ||= (e) =>
isRef(V) ? (V.value = e) : null),
header: `自动释放设置`,
modal: ``,
closable: !unref(F),
"close-on-escape": !unref(F),
style: {
width: `min(460px, calc(100vw - 28px))`,
},
},
{
footer: withCtx(() => [
createVNode(
s,
{
label: `取消自动释放`,
text: ``,
disabled: unref(F),
onClick: (n[7] ||= (e) => (H.value = null)),
},
null,
8,
[`disabled`],
),
createVNode(
s,
{
label: `保存设置`,
loading: unref(F),
disabled: !unref(U),
onClick: _e,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createVNode(
i,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
...(n[10] ||= [
createTextVNode(
`达到设定时间后,实例将自动释放,数据无法恢复。请提前备份。`,
-1,
),
]),
]),
_: 1,
},
),
createVNode(
T,
{
modelValue: unref(H),
"onUpdate:modelValue": (n[5] ||= (e) =>
isRef(H) ? (H.value = e) : null),
"show-time": ``,
"hour-format": `24`,
"date-format": `yy-mm-dd`,
disabled: unref(F),
placeholder: `选择释放时间,留空取消计划`,
fluid: ``,
},
null,
8,
[`modelValue`, `disabled`],
),
createElementVNode(`label`, fe, [
createVNode(
M,
{
modelValue: unref(U),
"onUpdate:modelValue": (n[6] ||= (e) =>
isRef(U) ? (U.value = e) : null),
binary: ``,
disabled: unref(F),
},
null,
8,
[`modelValue`, `disabled`],
),
(n[11] ||= createTextVNode(
`我已确认释放时间及数据影响`,
-1,
)),
]),
unref(I)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `error`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
])
);
};
},
}),
[[`__scopeId`, `data-v-2710106c`]],
),
{
__name: `InstanceOnDemand`,
},
);
export {};
export default C;
</script>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,640 @@
<script>
import "~/assets/styles/InstanceRenewDialog.BHDAL6d3.css";
import { toDisplayString } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { withKeys } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import select from "primevue/select";
import OperationNotice from "~/components/OperationNotice.vue";
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
import password from "primevue/password";
import skeleton from "primevue/skeleton";
import { n as renewal_quote_n } from "~/lib/renewal-quote.js";
import { r as renewal_quote_r } from "~/lib/renewal-quote.js";
import { t as renewal_quote_t } from "~/lib/renewal-quote.js";
var ue = {
key: 0,
class: `rd`,
},
de = {
key: 1,
class: `rd`,
},
fe = {
class: `rd-row`,
},
pe = [`id`],
me = {
key: 0,
class: `rd-hint`,
},
he = {
class: `rd-row`,
},
ge = [`id`],
_e = [`for`],
ve = [`aria-labelledby`],
ye = {
class: `rd-code`,
},
T = {
key: 3,
class: `rd-promo rd-grow`,
},
E = {
class: `rd-row`,
},
D = [`for`],
O = {
class: `rd-quote`,
},
k = {
key: 0,
class: `rd-quote-row`,
},
A = {
class: `rd-discount`,
},
j = {
class: `rd-quote-row`,
},
M = {
class: `rd-price`,
},
N = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceRenewDialog`,
props: mergeModels(
{
hostId: {},
},
{
modelValue: {
type: Boolean,
default: !1,
},
modelModifiers: {},
},
),
emits: mergeModels([`paid`], [`update:modelValue`]),
setup(r, { emit: _ }) {
let x = useModel(r, `modelValue`),
N = r,
P = _,
F = useApi(),
I = ref(``),
L = useId(),
R = ref(!1),
z = ref(!1),
B = ref([]),
V = ref(``),
H = ref(``),
U = ref([]),
W = ref(``),
G = ref(``),
K = 0,
q = ref(``),
J = computed(
() => B.value.find((e) => e.billing_cycle === V.value) ?? null,
),
Y = () => JSON.stringify([N.hostId, U.value]),
X = computed(
() =>
x.value &&
!R.value &&
!z.value &&
!!V.value &&
!!J.value &&
q.value === Y(),
),
be = computed(() => J.value?.price ?? ``),
Z = computed(() => Number(J.value?.client_level_discount ?? 0));
async function Q() {
let e = ++K,
t = N.hostId,
n = Y(),
r = () => e === K && x.value && t === N.hostId && n === Y();
((R.value = !0), (H.value = ``), (q.value = ``), (B.value = []));
try {
let e = {};
U.value.length && (e[`customfield[promo_code]`] = U.value);
let i = await renewal_quote_t(
() => F.get(`/host/${t}/renew`, e),
r,
);
return r()
? ((B.value = renewal_quote_r(i.host)),
B.value.some((e) => e.billing_cycle === V.value) ||
(V.value =
B.value.find((e) => e.is_current_cycle === 1)
?.billing_cycle ??
B.value[0]?.billing_cycle ??
``),
(q.value = n),
!0)
: !1;
} catch (e) {
return (r() && (H.value = renewal_quote_n(e)), !1);
} finally {
e === K && (R.value = !1);
}
}
(watch(
x,
(e) => {
if (!e) {
(K++, (R.value = !1), (q.value = ``));
return;
}
((V.value = ``),
(U.value = []),
(W.value = ``),
(G.value = ``),
Q());
},
{
immediate: !0,
},
),
watch(
() => N.hostId,
() => {
x.value &&
((V.value = ``), (U.value = []), (W.value = ``), Q());
},
),
onBeforeUnmount(() => {
(K++, (R.value = !1));
}));
async function $() {
let e = W.value.trim();
if (!e || R.value || z.value) return;
let t = U.value.slice();
if (((U.value = [e]), !(await Q()))) {
let n = H.value;
U.value.length === 1 &&
U.value[0] === e &&
((U.value = t),
await Q(),
n && (H.value = `优惠码报价失败,已恢复原报价:${n}`));
return;
}
if (Number(J.value?.manual_promo_code_success ?? 0) !== 1) {
((U.value = t), await Q(), (H.value = `该优惠码不可用`));
return;
}
W.value = ``;
}
async function xe() {
R.value || z.value || ((U.value = []), await Q());
}
async function Se() {
if (X.value) {
((z.value = !0), (H.value = ``), (I.value = ``));
try {
let e = {
billing_cycle: V.value,
};
(U.value.length &&
(e.customfield = {
promo_code: U.value,
}),
G.value && (e.client_operate_password = G.value),
await F.post(`/host/${N.hostId}/renew`, e),
(x.value = !1),
P(`paid`));
} catch (e) {
I.value = e instanceof Error ? e.message : `续费失败`;
} finally {
z.value = !1;
}
}
}
return (t, n) => {
let r = OperationNotice,
i = skeleton,
a = select,
s = button,
u = inputtext,
_ = password,
b = OperatePasswordGate,
C = message,
w = dialog;
return (
openBlock(),
createElementBlock(
Fragment,
null,
[
createVNode(
r,
{
message: unref(I),
severity: `error`,
},
null,
8,
[`message`],
),
createVNode(
w,
{
visible: x.value,
"onUpdate:visible": (n[4] ||= (e) => (x.value = e)),
header: `续费`,
modal: ``,
draggable: !1,
style: {
width: `460px`,
maxWidth: `calc(100vw - 32px)`,
},
},
{
footer: withCtx(() => [
createVNode(s, {
label: `取消`,
severity: `secondary`,
text: ``,
onClick: (n[3] ||= (e) => (x.value = !1)),
}),
createVNode(
s,
{
label: `提交续费`,
loading: unref(z),
disabled: !unref(X),
onClick: Se,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
unref(R)
? (openBlock(),
createElementBlock(`div`, ue, [
createVNode(i, {
height: `120px`,
}),
]))
: unref(B).length
? (openBlock(),
createElementBlock(`div`, de, [
createElementVNode(`div`, fe, [
createElementVNode(
`span`,
{
id: `${unref(L)}-cycle-label`,
class: `rd-label`,
},
`续费周期`,
8,
pe,
),
createVNode(
a,
{
"input-id": `${unref(L)}-cycle`,
"aria-labelledby": `${unref(L)}-cycle-label`,
modelValue: unref(V),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(V) ? (V.value = e) : null),
options: unref(B),
optionLabel: `name_show`,
optionValue: `billing_cycle`,
placeholder: `选择续费周期`,
class: `rd-grow`,
disabled: unref(R) || unref(z),
},
null,
8,
[
`input-id`,
`aria-labelledby`,
`modelValue`,
`options`,
`disabled`,
],
),
]),
unref(B).length === 1
? (openBlock(),
createElementBlock(
`p`,
me,
`该产品当前仅支持此续费周期。`,
))
: createCommentVNode(``, !0),
createElementVNode(`div`, he, [
unref(U).length
? (openBlock(),
createElementBlock(
`span`,
{
key: 0,
id: `${unref(L)}-promo-label`,
class: `rd-label`,
},
`优惠码`,
8,
ge,
))
: (openBlock(),
createElementBlock(
`label`,
{
key: 1,
for: `${unref(L)}-promo`,
},
`优惠码`,
8,
_e,
)),
unref(U).length
? (openBlock(),
createElementBlock(
`div`,
{
key: 2,
class: `rd-promo rd-grow`,
role: `group`,
"aria-labelledby": `${unref(L)}-promo-label`,
},
[
createElementVNode(
`span`,
ye,
toDisplayString(unref(U)[0]),
1,
),
createVNode(
s,
{
label: `取消`,
size: `small`,
severity: `secondary`,
text: ``,
disabled: unref(R) || unref(z),
onClick: xe,
},
null,
8,
[`disabled`],
),
],
8,
ve,
))
: (openBlock(),
createElementBlock(`div`, T, [
createVNode(
u,
{
id: `${unref(L)}-promo`,
modelValue: unref(W),
"onUpdate:modelValue": (n[1] ||= (
e,
) =>
isRef(W) ? (W.value = e) : null),
placeholder: `选填`,
class: `rd-grow`,
disabled: unref(R) || unref(z),
onKeyup: withKeys($, [`enter`]),
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
createVNode(
s,
{
label: `使用`,
size: `small`,
severity: `secondary`,
outlined: ``,
disabled:
!unref(W).trim() ||
unref(R) ||
unref(z),
onClick: $,
},
null,
8,
[`disabled`],
),
])),
]),
createVNode(b, null, {
default: withCtx(() => [
createElementVNode(`div`, E, [
createElementVNode(
`label`,
{
for: `${unref(L)}-operate-password`,
},
`操作密码`,
8,
D,
),
createVNode(
_,
{
modelValue: unref(G),
"onUpdate:modelValue": (n[2] ||= (
e,
) =>
isRef(G) ? (G.value = e) : null),
"input-id": `${unref(L)}-operate-password`,
feedback: !1,
"toggle-mask": ``,
class: `rd-grow`,
placeholder: `账户已设置时填写`,
disabled: unref(z),
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
]),
]),
_: 1,
}),
createElementVNode(`div`, O, [
unref(Z) > 0
? (openBlock(),
createElementBlock(`div`, k, [
(n[5] ||= createElementVNode(
`span`,
null,
`会员折扣`,
-1,
)),
createElementVNode(
`span`,
A,
`-¥` +
toDisplayString(
unref(Z).toFixed(2),
),
1,
),
]))
: createCommentVNode(``, !0),
createElementVNode(`div`, j, [
(n[6] ||= createElementVNode(
`span`,
null,
`应付金额`,
-1,
)),
createElementVNode(
`span`,
M,
`¥` + toDisplayString(unref(be)),
1,
),
]),
]),
unref(H)
? (openBlock(),
createBlock(
C,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(H)),
1,
),
createVNode(
s,
{
label: `重新获取价格`,
size: `small`,
severity: `secondary`,
text: ``,
disabled: unref(z),
onClick: Q,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
(n[7] ||= createElementVNode(
`p`,
{
class: `rd-hint`,
},
`续费订单创建后需前往订单页完成支付。`,
-1,
)),
]))
: unref(H)
? (openBlock(),
createBlock(
C,
{
key: 3,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(H)),
1,
),
createVNode(
s,
{
label: `重新获取价格`,
size: `small`,
severity: `secondary`,
text: ``,
disabled: unref(z),
onClick: Q,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: (openBlock(),
createBlock(
C,
{
key: 2,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(n[8] ||= [
createTextVNode(
`当前产品暂不可续费。`,
-1,
),
]),
]),
_: 1,
},
)),
]),
_: 1,
},
8,
[`visible`],
),
],
64,
)
);
};
},
}),
[[`__scopeId`, `data-v-01429388`]],
),
{
__name: `InstanceRenewDialog`,
},
);
export {};
export default N;
</script>
@@ -0,0 +1,435 @@
<script>
import "~/assets/styles/FlowPacketPanel.-RJSx13z.css";
import "~/assets/styles/InstanceServiceInfo.BftSVIeW.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { normalizeClass } from "vue";
import { watch } from "vue";
import { defineAsyncComponent } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { navigateTo } from "#app";
import { loadModule } from "~/utils/load-module.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { r as dict_r } from "~/lib/dict.js";
import { n as instance_status_n } from "~/lib/instance-status.js";
import { t as instance_status_t } from "~/lib/instance-status.js";
import tag from "primevue/tag";
import { c as instance_data_c } from "~/lib/instance-data.js";
import { i as instance_data_i } from "~/lib/instance-data.js";
import { l as instance_data_l } from "~/lib/instance-data.js";
import { n as configuration_display_n } from "~/lib/configuration-display.js";
import FlowPacketPanel from "~/components/instance/FlowPacketPanel.vue";
var N = defineAsyncComponent(() =>
loadModule(
() =>
import("~/components/instance/InstanceRenewDialog.vue").then(
(e) => e.default || e,
),
[],
import.meta.url,
),
),
P = {
class: `service-info`,
"aria-label": `实例信息`,
},
F = {
class: `service-heading`,
},
I = {
key: 2,
class: `traffic-recovery`,
},
L = {
key: 3,
class: `traffic-recovery`,
},
R = {
class: `service-rows`,
},
z = [`aria-label`],
B = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceServiceInfo`,
props: {
host: {},
module: {},
info: {},
},
emits: [`pay`],
setup(i, { emit: g }) {
let b = i,
S = g,
B = computed(() =>
instance_status_t(
b.info?.powerStatus ?? b.info?.power_status,
b.host.status,
),
),
V = computed(() =>
instance_status_n(
b.host,
b.info?.powerStatus ?? b.info?.power_status,
),
),
H = computed(
() =>
b.host.status === `Suspended` &&
b.host.suspend_type === `overdue`,
),
U = computed(() =>
Number(b.host.renew_forbidden) === 1
? `该实例已禁止续费,请联系支持`
: Number(b.host.change_billing_cycle_id) > 0
? `请先取消到期转换计划后再续费`
: [`onetime`, `on_demand`].includes(
b.host.billing_cycle || ``,
)
? `该计费方式不支持续费,请联系支持`
: ``,
),
W = ref(!1);
function G() {
H.value && !U.value && (W.value = !0);
}
watch([() => b.host.id, () => H.value, () => U.value], () => {
W.value = !1;
});
let K = ref(!1),
q = computed(() => {
let e = b.info ?? {},
t = instance_data_l(e.raw ?? e),
n = instance_data_l(b.host.addition),
r = instance_data_l(e.image ?? t.image),
i = instance_data_l(t.model_config),
a = e.ip || b.host.ip || b.host.dedicate_ip || b.host.assign_ip,
o = configuration_display_n(b.module || ``, t, b.host),
s = String(e.password || n.password || ``);
return [
[`实例编号`, `#${b.host.id}`],
[`实例名称`, b.host.name || `—`],
[`配置摘要`, b.host.base_info || `—`],
[`区域`, o.region || `—`],
[`线路`, o.line || `—`],
[
`IP 地址`,
a || (b.host.status === `Pending` ? `待分配` : `未提供`),
],
[
`CPU`,
e.cpu
? `${e.cpu} ${b.module === `jy_dcim` ? `颗 CPU` : `核`}`
: i.cpu || `未提供`,
],
[`内存`, e.memory ? `${e.memory} GB` : i.memory || `未提供`],
[
`磁盘`,
instance_data_i(e.disks)
.map((e) => `${e.name} ${e.size} GB`)
.join(` / `) ||
i.disk ||
`未提供`,
],
[
`带宽`,
t.bw_show ||
(e.bw || t.bw || t.bandwidth
? `${e.bw || t.bw || t.bandwidth} Mbps`
: `未提供`),
],
[
`操作系统`,
r.name || b.host.image_name || n.image_name || `未提供`,
],
[`用户名`, e.username || n.username || `未提供`],
[
`连接端口`,
String(instance_data_c(e.port ?? n.port) || `未提供`),
],
[`密码`, s ? (K.value ? s : `••••••••`) : `未提供`],
[`计费周期`, b.host.billing_cycle_name || `—`],
[
`续费金额`,
b.host.renew_amount == null ? `—` : `¥${b.host.renew_amount}`,
],
[
`开通时间`,
b.host.active_time
? dict_r(b.host.active_time)
: b.host.status === `Pending` || b.host.status === `Unpaid`
? `尚未开通`
: `未提供`,
],
[`到期时间`, dict_r(b.host.due_time)],
];
}),
J = computed(() => {
let e = instance_data_l(b.info?.raw ?? b.info);
return instance_data_i(e.config_options ?? e.configoptions)
.map((e) => ({
label: String(e.option_name ?? e.name ?? ``),
value: String(e.sub_name ?? e.value ?? ``),
}))
.filter((e) => e.label && e.value);
});
return (r, o) => {
let l = tag,
g = message,
b = button,
w = FlowPacketPanel,
T = N;
return (
openBlock(),
createElementBlock(`section`, P, [
createElementVNode(`div`, F, [
(o[4] ||= createElementVNode(`h3`, null, `实例信息`, -1)),
createVNode(
l,
{
value: unref(B).label,
severity: unref(B).severity,
},
null,
8,
[`value`, `severity`],
),
]),
unref(V)
? (openBlock(),
createBlock(
g,
{
key: 0,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
`暂停原因:` + toDisplayString(unref(V)),
1,
),
]),
_: 1,
},
))
: i.host.status === `Pending`
? (openBlock(),
createBlock(
g,
{
key: 1,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(o[5] ||= [
createTextVNode(
`实例开通中,IP 和连接信息将在开通完成后显示。`,
-1,
),
]),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(H)
? (openBlock(),
createElementBlock(`div`, I, [
createElementVNode(
`p`,
null,
toDisplayString(
unref(U) ||
`可选择续费周期并完成付款。付款后由平台处理恢复,请稍后刷新查看实例状态。`,
),
1,
),
createElementVNode(`div`, null, [
createVNode(
b,
{
label: `立即续费`,
disabled: !!unref(U),
onClick: G,
},
null,
8,
[`disabled`],
),
]),
]))
: createCommentVNode(``, !0),
i.host.status === `Suspended` &&
i.host.suspend_type === `overtraffic`
? (openBlock(),
createElementBlock(`div`, L, [
(o[6] ||= createElementVNode(
`p`,
null,
`可购买流量包补充可用流量。付款后由平台处理恢复,请稍后刷新查看实例状态。`,
-1,
)),
createVNode(
w,
{
"host-id": String(i.host.id),
module: i.module,
flow: null,
mode: `button`,
onPay: (o[0] ||= (e) => S(`pay`, e)),
},
null,
8,
[`host-id`, `module`],
),
]))
: createCommentVNode(``, !0),
createElementVNode(`dl`, R, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(q),
([t, r]) => (
openBlock(),
createElementBlock(
`div`,
{
key: t,
},
[
createElementVNode(
`dt`,
null,
toDisplayString(t),
1,
),
createElementVNode(`dd`, null, [
createTextVNode(toDisplayString(r), 1),
t === `密码` && r !== `未提供`
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
type: `button`,
class: `password-toggle`,
"aria-label": unref(K)
? `隐藏密码`
: `显示密码`,
onClick: (o[1] ||= (e) =>
(K.value = !unref(K))),
},
[
createElementVNode(
`i`,
{
class: normalizeClass([
`pi`,
unref(K)
? `pi-eye-slash`
: `pi-eye`,
]),
},
null,
2,
),
],
8,
z,
))
: createCommentVNode(``, !0),
]),
],
)
),
),
128,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(J),
(t, n) => (
openBlock(),
createElementBlock(
`div`,
{
key: `config-${n}`,
},
[
createElementVNode(
`dt`,
null,
toDisplayString(t.label),
1,
),
createElementVNode(
`dd`,
null,
toDisplayString(t.value),
1,
),
],
)
),
),
128,
)),
]),
unref(W)
? (openBlock(),
createBlock(
T,
{
key: 4,
modelValue: unref(W),
"onUpdate:modelValue": (o[2] ||= (e) =>
isRef(W) ? (W.value = e) : null),
"host-id": String(i.host.id),
onPaid: (o[3] ||= (e) =>
(`navigateTo` in r
? r.navigateTo
: unref(navigateTo))(`/orders`)),
},
null,
8,
[`modelValue`, `host-id`],
))
: createCommentVNode(``, !0),
])
);
};
},
}),
[[`__scopeId`, `data-v-0ff5d554`]],
),
{
__name: `InstanceServiceInfo`,
},
);
export {};
export default B;
</script>
+223
View File
@@ -0,0 +1,223 @@
<script>
import "~/assets/styles/GeetestField.DiieTibK.css";
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
import "~/assets/styles/InstanceSmsCode.CsITfIEU.css";
import { toDisplayString } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { mergeModels } from "vue";
import { useModel } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import CaptchaField from "~/components/CaptchaField.vue";
import { t as interval_t } from "~/lib/interval.js";
import { t as useCaptcha_t } from "~/lib/useCaptcha.js";
var T = {
class: `instance-code`,
},
E = [`for`],
D = {
class: `code-row`,
},
O = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceSmsCode`,
props: mergeModels(
{
disabled: {
type: Boolean,
},
},
{
modelValue: {
default: ``,
},
modelModifiers: {},
},
),
emits: [`update:modelValue`],
setup(r) {
let m = r,
y = useModel(r, `modelValue`),
O = useApi(),
k = useCaptcha_t(`verify`),
{
needed: A,
provider: j,
captchaId: M,
img: N,
value: P,
loading: F,
error: I,
} = k,
L = useId(),
R = ref(!1),
z = ref(``),
B = ref(0),
V,
H = !1;
async function U() {
if (
!(m.disabled || R.value || B.value || H) &&
((z.value = k.validationError()), !z.value)
) {
R.value = !0;
try {
if (
(await O.post(`/phone/code`, {
action: `verify`,
captcha: k.value.value.trim(),
token: k.token.value,
}),
H)
)
return;
(k.invalidate(),
(B.value = 60),
(V = interval_t(() => {
--B.value <= 0 && (clearInterval(V), (V = void 0));
}, 1e3)),
k.needed.value && k.load());
} catch (e) {
H ||
((z.value =
e instanceof Error ? e.message : `验证码发送失败`),
await k.handleError(e));
} finally {
H || (R.value = !1);
}
}
}
return (
onBeforeUnmount(() => {
((H = !0), clearInterval(V), k.invalidate(), (y.value = ``));
}),
(t, n) => {
let i = inputtext,
o = button,
m = CaptchaField,
_ = message;
return (
openBlock(),
createElementBlock(`div`, T, [
createElementVNode(
`label`,
{
for: `${unref(L)}-code`,
},
`账户手机验证码`,
8,
E,
),
createElementVNode(`div`, D, [
createVNode(
i,
{
id: `${unref(L)}-code`,
modelValue: y.value,
"onUpdate:modelValue": (n[0] ||= (e) => (y.value = e)),
autocomplete: `one-time-code`,
disabled: r.disabled,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
createVNode(
o,
{
label: unref(B) ? `${unref(B)}s 后重试` : `发送验证码`,
outlined: ``,
loading: unref(R),
disabled: r.disabled || unref(B) > 0,
onClick: U,
},
null,
8,
[`label`, `loading`, `disabled`],
),
]),
unref(A)
? (openBlock(),
createBlock(
m,
{
key: 0,
modelValue: unref(P),
"onUpdate:modelValue": (n[1] ||= (e) =>
isRef(P) ? (P.value = e) : null),
img: unref(N),
provider: unref(j),
"captcha-id": unref(M),
loading: unref(F),
disabled: r.disabled || unref(R),
onVerified: unref(k).complete,
onInvalid: unref(k).invalidate,
onRefresh: unref(k).load,
},
null,
8,
[
`modelValue`,
`img`,
`provider`,
`captcha-id`,
`loading`,
`disabled`,
`onVerified`,
`onInvalid`,
`onRefresh`,
],
))
: createCommentVNode(``, !0),
unref(z) || unref(I)
? (openBlock(),
createBlock(
_,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(z) || unref(I)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-741dd729`]],
),
{
__name: `InstanceSmsCode`,
},
);
export {};
export default O;
</script>
@@ -0,0 +1,45 @@
<script>
import { createBlock } from "vue";
import { computed } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { openBlock } from "vue";
import { t as instance_status_t } from "~/lib/instance-status.js";
import tag from "primevue/tag";
var s = Object.assign(
defineComponent({
__name: `InstanceStatusTag`,
props: {
state: {},
power: {},
lifecycle: {},
},
setup(r) {
let s = r,
c = computed(() => s.state ?? instance_status_t(s.power, s.lifecycle));
return (t, r) => {
let a = tag;
return (
openBlock(),
createBlock(
a,
{
class: `instance-product-status`,
value: unref(c).label,
severity: unref(c).severity,
},
null,
8,
[`value`, `severity`],
)
);
};
},
}),
{
__name: `InstanceStatusTag`,
},
);
export {};
export default s;
</script>
+641
View File
@@ -0,0 +1,641 @@
<script>
import "~/assets/styles/InstanceTraffic.CyyEAXl3.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { d as instance_data_d } from "~/lib/instance-data.js";
import { n as instance_data_n } from "~/lib/instance-data.js";
import progressbar from "primevue/progressbar";
var w = [`aria-busy`],
T = {
key: 0,
class: `traffic-progress`,
},
E = {
class: `traffic-row`,
},
D = {
class: `traffic-row`,
},
O = {
class: `traffic-row`,
},
k = {
class: `traffic-row`,
},
A = {
key: 1,
class: `traffic-row`,
},
j = {
key: 2,
class: `traffic-row`,
},
M = {
key: 3,
class: `traffic-row`,
},
N = {
key: 4,
class: `traffic-actions`,
},
P = {
key: 5,
class: `traffic-note`,
role: `status`,
},
F = {
key: 6,
class: `traffic-error`,
},
I = {
key: 1,
class: `traffic-note`,
role: `status`,
},
L = {
key: 2,
class: `traffic-error`,
},
R = {
key: 0,
class: `traffic-progress`,
},
z = {
class: `traffic-row`,
},
B = {
class: `traffic-row`,
},
V = {
class: `traffic-row`,
},
H = {
key: 1,
class: `traffic-row`,
},
U = {
key: 2,
class: `traffic-row`,
},
W = {
key: 3,
class: `traffic-note`,
},
G = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `InstanceTraffic`,
props: {
module: {},
hostId: {},
raw: {},
flow: {},
loading: {
type: Boolean,
},
failed: {
type: Boolean,
},
layout: {},
},
setup(m) {
let y = m,
G = useApi(),
K = ref(null),
q = ref(!1),
J = ref(``),
Y = computed(() =>
instance_data_d(
y.module,
y.raw,
y.module === `kky_ecs` ? K.value : y.flow,
),
),
X = 0,
Z = !1;
async function Q() {
if (Z) return;
let e = ++X,
t = y.hostId,
n = y.module,
r = () => !Z && e === X && t === y.hostId && n === y.module;
if (
((K.value = null),
(J.value = ``),
(q.value = !1),
n === `kky_ecs` && t)
) {
q.value = !0;
try {
let e = await G.get(`/kky_ecs/${t}/traffic`);
r() &&
((K.value = e),
e.usage_status === `unavailable` &&
(J.value =
e.usage_error || `流量统计暂不可用,请稍后重试`));
} catch (e) {
r() &&
(J.value =
e instanceof Error ? e.message : `流量数据获取失败`);
} finally {
r() && (q.value = !1);
}
}
}
return (
onMounted(Q),
watch(() => [y.hostId, y.module, y.raw], Q, {
flush: `sync`,
}),
onBeforeUnmount(() => {
((Z = !0), X++);
}),
(t, r) => {
let i = progressbar,
a = button,
c = message;
return (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`traffic-summary`,
{
"traffic-table": m.layout === `table`,
},
]),
"aria-busy": m.module === `kky_ecs` ? unref(q) : m.loading,
},
[
m.module === `kky_ecs`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
unref(Y).quota && unref(Y).quota.percent !== null
? (openBlock(),
createElementBlock(`div`, T, [
createVNode(
i,
{
value: unref(Y).quota.percent,
showValue: !1,
"aria-label": `当前流量包使用进度`,
style: {
height: `6px`,
},
},
null,
8,
[`value`],
),
]))
: createCommentVNode(``, !0),
createElementVNode(`div`, E, [
(r[0] ||= createElementVNode(
`span`,
null,
`已用流量`,
-1,
)),
createElementVNode(`b`, null, [
createTextVNode(
toDisplayString(
unref(Y).quota
? unref(instance_data_n)(
unref(Y).quota.used,
)
: `—`,
),
1,
),
unref(Y).quota &&
unref(Y).quota.percent !== null
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`(` +
toDisplayString(
unref(Y).quota.percent.toFixed(1),
) +
`%)`,
1,
),
],
64,
))
: createCommentVNode(``, !0),
]),
]),
createElementVNode(`div`, D, [
(r[1] ||= createElementVNode(
`span`,
null,
`总流量`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).quota
? unref(instance_data_n)(
unref(Y).quota.total,
)
: unref(Y).quotaLoaded
? unref(Y).metered
? unref(Y).monthlyQuota
? `暂无有效流量包`
: `无固定额度`
: `不限量`
: `—`,
),
1,
),
]),
createElementVNode(`div`, O, [
(r[2] ||= createElementVNode(
`span`,
null,
`剩余流量`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).quota
? unref(instance_data_n)(
unref(Y).quota.remaining,
)
: unref(Y).quotaLoaded
? unref(Y).metered
? `无可抵扣流量`
: `不限量`
: `—`,
),
1,
),
]),
createElementVNode(`div`, k, [
(r[3] ||= createElementVNode(
`span`,
null,
`网络计费`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).metered
? `按流量计费 · 按小时结算`
: `按带宽计费`,
),
1,
),
]),
unref(Y).metered
? (openBlock(),
createElementBlock(`div`, A, [
(r[4] ||= createElementVNode(
`span`,
null,
`超额流量单价`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).unitPrice === null
? `—`
: `¥${unref(Y).unitPrice.toFixed(2)} / GB`,
),
1,
),
]))
: createCommentVNode(``, !0),
unref(Y).metered && unref(Y).monthlyQuota !== null
? (openBlock(),
createElementBlock(`div`, j, [
(r[5] ||= createElementVNode(
`span`,
null,
`每月赠送额度`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(instance_data_n)(
unref(Y).monthlyQuota,
),
),
1,
),
]))
: createCommentVNode(``, !0),
!unref(Y).quota &&
unref(Y).packageRemaining !== null
? (openBlock(),
createElementBlock(`div`, M, [
(r[6] ||= createElementVNode(
`span`,
null,
`流量包剩余`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(instance_data_n)(
unref(Y).packageRemaining,
),
),
1,
),
]))
: createCommentVNode(``, !0),
m.hostId && !unref(J)
? (openBlock(),
createElementBlock(`div`, N, [
createVNode(
a,
{
label: `刷新流量数据`,
icon: `pi pi-refresh`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(q),
onClick: Q,
},
null,
8,
[`loading`],
),
]))
: createCommentVNode(``, !0),
unref(q)
? (openBlock(),
createElementBlock(`p`, P, `正在加载流量数据…`))
: unref(J)
? (openBlock(),
createElementBlock(`div`, F, [
createVNode(
c,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(J)),
1,
),
]),
_: 1,
},
),
createVNode(a, {
label: `重试`,
size: `small`,
severity: `secondary`,
outlined: ``,
onClick: Q,
}),
]))
: createCommentVNode(``, !0),
],
64,
))
: m.loading
? (openBlock(),
createElementBlock(`p`, I, `正在加载流量数据…`))
: m.failed
? (openBlock(),
createElementBlock(`div`, L, [
createVNode(
c,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
...(r[7] ||= [
createTextVNode(
`流量数据获取失败,请刷新后重试。`,
-1,
),
]),
]),
_: 1,
},
),
]))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
unref(Y).percent === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, R, [
createVNode(
i,
{
value: unref(Y).percent,
showValue: !1,
style: {
height: `6px`,
},
},
null,
8,
[`value`],
),
])),
createElementVNode(`div`, z, [
(r[8] ||= createElementVNode(
`span`,
null,
`已用流量`,
-1,
)),
createElementVNode(`b`, null, [
createTextVNode(
toDisplayString(
unref(instance_data_n)(unref(Y).used),
),
1,
),
unref(Y).percent === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`(` +
toDisplayString(
unref(Y).percent.toFixed(1),
) +
`%)`,
1,
),
],
64,
)),
]),
]),
createElementVNode(`div`, B, [
(r[9] ||= createElementVNode(
`span`,
null,
`总流量`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).unlimited
? `不限量`
: unref(instance_data_n)(
unref(Y).total,
),
),
1,
),
]),
createElementVNode(`div`, V, [
(r[10] ||= createElementVNode(
`span`,
null,
`剩余流量`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(Y).unlimited
? `不限量`
: unref(instance_data_n)(
unref(Y).remaining,
),
),
1,
),
]),
unref(Y).packageRemaining === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, H, [
(r[11] ||= createElementVNode(
`span`,
null,
`流量包剩余`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(
unref(instance_data_n)(
unref(Y).packageRemaining,
),
),
1,
),
])),
unref(Y).reset
? (openBlock(),
createElementBlock(`div`, U, [
(r[12] ||= createElementVNode(
`span`,
null,
`重置时间`,
-1,
)),
createElementVNode(
`b`,
null,
toDisplayString(unref(Y).reset),
1,
),
]))
: createCommentVNode(``, !0),
unref(Y).used === null
? (openBlock(),
createElementBlock(
`p`,
W,
toDisplayString(
unref(Y).metered
? `按流量计费,当前用量暂未返回。`
: `当前用量暂未返回。`,
),
1,
))
: createCommentVNode(``, !0),
],
64,
)),
],
10,
w,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-484c7b21`]],
),
{
__name: `InstanceTraffic`,
},
);
export {};
export default G;
</script>
@@ -0,0 +1,870 @@
<script>
import "~/assets/styles/LegacyDcimActions.DcIrQby6.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import { n as product_name_n } from "~/lib/product-name.js";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import checkbox from "primevue/checkbox";
import OperationNotice from "~/components/OperationNotice.vue";
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
import { t as os_name_t } from "~/lib/os-name.js";
import { t as remote_console_t } from "~/lib/remote-console.js";
var de = {
class: `legacy-actions`,
},
fe = {
class: `action-buttons`,
},
pe = {
class: `action-form`,
},
me = {
class: `target`,
},
he = [`for`],
ge = {
key: 0,
class: `muted`,
},
_e = [`for`],
ve = [`for`],
ye = [`for`],
be = {
key: 0,
class: `muted`,
},
xe = [`for`],
Se = [`for`],
Ce = {
key: 4,
class: `ack`,
},
we = [`for`],
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `LegacyDcimActions`,
props: {
hostId: {},
host: {},
data: {},
disabled: {
type: Boolean,
},
},
emits: [`refresh`],
setup(g, { expose: b, emit: S }) {
let C = g,
Te = S,
Ee = useApi(),
w = useId(),
T = (e) =>
e && typeof e == `object` && !Array.isArray(e) ? e : null,
E = (e) =>
e === !0 || e === 1 || e === `1` || e === `on` || e === `true`,
D = (e) =>
e === !1 || e === 0 || e === `0` || e === `off` || e === `false`,
O = {
vnc: `打开 VNC 控制台`,
reset_password: `重置密码`,
reinstall: `重装系统`,
rescue: `进入救援模式`,
cancel_task: `取消当前任务`,
reset_bmc: `重置 BMC`,
},
k = {
vnc: `novnc`,
reset_password: `crack_pass`,
reinstall: `reinstall`,
rescue: `rescue`,
cancel_task: `rescue`,
reset_bmc: `reset_bmc`,
},
A = computed(() => T(C.data)),
j = computed(() => T(A.value?.dcim)),
De = ref(C.hostId),
M = computed(
() =>
!C.disabled &&
/^[1-9]\d*$/.test(C.hostId) &&
String(C.host.id) === C.hostId &&
De.value === C.hostId &&
C.host.status === `Active` &&
!!A.value &&
!!j.value,
);
function Oe(e) {
let t = A.value?.module_button,
n = Array.isArray(t) ? t : [t];
for (let t of n) {
let n = T(t);
if (!n) continue;
let r =
`func` in n
? [n]
: [n.console, n.control].flatMap((e) =>
Array.isArray(e) ? e : [],
);
for (let t of r) {
let n = T(t);
if (
!(
!n ||
(n.type && n.type !== "default") ||
![e, k[e]].includes(String(n.func))
) &&
(E(n.disabled) || D(n.enabled) || D(n.enable))
)
return !0;
}
}
return !1;
}
function N(e) {
if (!Object.hasOwn(O, e) || !j.value || Oe(e)) return !1;
let t = j.value.auth,
n = T(t);
return e === `reset_bmc`
? !!n && E(n.reset_bmc)
: D(t) || (n && (D(n[k[e]]) || D(n[e])))
? !1
: E(t) || !!(n && E(n[k[e]]));
}
let ke = computed(() => Object.keys(O).filter(N)),
P = computed(() => {
let e = [
...(Array.isArray(A.value?.cloud_os_group)
? A.value.cloud_os_group
: []),
...(Array.isArray(j.value?.os_group) ? j.value.os_group : []),
],
t = Array.isArray(A.value?.cloud_os) ? A.value.cloud_os : [],
n = Array.isArray(j.value?.os) ? j.value.os : [],
r = [];
for (let i of t.length ? t : n) {
let t = T(i);
if (
!t ||
!Number.isSafeInteger(Number(t.id)) ||
Number(t.id) <= 0 ||
typeof t.name != `string` ||
!t.name.trim()
)
continue;
let n = t.group ?? t.group_id,
a = e.map(T).find((e) => e && String(e.id) === String(n)),
o = typeof a?.name == `string` ? a.name : ``;
r.some((e) => e.id === Number(t.id)) ||
r.push({
id: Number(t.id),
name: t.name,
group: o,
windows:
Number(t.ostype) === 1 ||
/windows/i.test(t.name + ` ` + o),
});
}
return r;
}),
Ae = (e) => os_name_t(e.name),
F = ref(null),
I = ref(``),
L = ref(!1),
R = ref(``),
z = ref(``),
B = ref(null),
V = ref(22),
H = ref(0),
U = ref(2),
W = ref(!1),
G = ref(``),
K = ref(!1),
q = ref(``),
J = computed(() => P.value.find((e) => e.id === B.value)),
Y = computed(
() => F.value === `reset_password` || F.value === `reinstall`,
),
je = computed(() =>
F.value === `reinstall`
? J.value?.windows && H.value === 1
? `重装将格式化第一分区并删除其中的数据。请先完成备份,再确认继续。`
: `重装将格式化全盘并删除数据。请先完成备份,再确认继续。`
: F.value === `rescue`
? `进入救援模式可能中断当前连接和服务,请确认可以暂时停止业务。`
: F.value === `cancel_task`
? `取消当前重装或救援任务可能使系统暂时不可用,请确认后继续。`
: F.value === `reset_bmc`
? `重置 BMC 会暂时中断带外管理连接,请确认后继续。`
: `重置后请使用新密码连接服务器。部分系统可能需要重启后生效。`,
),
Me = computed(() => {
let e = T(T(A.value?.host_data)?.password_rule),
t = T(e?.rule);
if (!t) return ``;
let n = [],
r = Number(t.len_num);
Number.isSafeInteger(r) && r > 0 && r <= 128 && n.push(`${r} 位`);
for (let [e, r] of [
[`upper`, `大写字母`],
[`lower`, `小写字母`],
[`num`, `数字`],
[`special`, `特殊字符`],
])
e && r && E(t[e]) && n.push(r);
return n.length
? `服务器密码要求:${n.join(`、`)},具体规则由服务器校验。`
: ``;
}),
X = 0,
Z = !1,
Q = null;
function Ne(e) {
return (
!Z && M.value && N(e) && I.value === C.hostId && Q === C.data
);
}
function $() {
(X++,
(F.value = null),
(I.value = ``),
(Q = null),
(L.value = !1),
(R.value = ``),
(z.value = ``),
(G.value = ``),
(q.value = ``),
(K.value = !1));
}
function Pe() {
L.value || $();
}
function Fe(e) {
if (!Z && !L.value && M.value && N(e)) {
if (e === `vnc`) {
remote_console_t(C.hostId, `remf_finance_dcim`);
return;
}
(X++,
(I.value = C.hostId),
(Q = C.data),
(F.value = e),
(R.value = ``),
(z.value = ``),
(G.value = ``),
(q.value = ``),
(K.value = !1),
(B.value = null),
(V.value = 22),
(H.value = 0),
(U.value = 2),
(W.value = !1));
}
}
async function Ie() {
let e = F.value;
if (!e || e === `vnc` || L.value || !Ne(e)) return;
if (
((G.value = ``),
(K.value = !1),
Y.value && (!R.value.trim() || R.value.includes(`\0`)))
) {
G.value = `请输入有效的新密码`;
return;
}
if (e === `reinstall`) {
if (!J.value) {
G.value = `请选择可用的操作系统`;
return;
}
if (
!Number.isInteger(V.value) ||
Number(V.value) < 1 ||
Number(V.value) > 65535
) {
G.value = `请输入 1 到 65535 之间的端口`;
return;
}
if (![0, 1].includes(H.value)) {
G.value = `请选择有效的分区方式`;
return;
}
if (!W.value) {
G.value = `请确认已备份数据并了解重装影响`;
return;
}
}
if (e === `rescue` && ![1, 2].includes(U.value)) {
G.value = `请选择救援系统`;
return;
}
let t = X,
n = C.hostId,
r = {
client_operate_password: z.value,
};
(Y.value && (r.password = R.value),
e === `rescue` && (r.type = U.value),
e === `reinstall` &&
Object.assign(r, {
os: B.value,
port: V.value,
part_type: J.value?.windows ? H.value : 0,
}));
let i = () => t === X && Ne(e);
L.value = !0;
try {
if ((await Ee.post(`/remf_finance_dcim/${n}/${e}`, r), !i()))
return;
((q.value = `${O[e]}指令已提交,请等待实例状态更新。`),
(F.value = null),
(R.value = ``),
(z.value = ``),
Te(`refresh`));
} catch (t) {
i() &&
((K.value = !0),
(G.value =
t instanceof Error ? t.message : `${O[e]}失败,请重试`));
} finally {
t === X && (L.value = !1);
}
}
return (
watch(
[
() => C.hostId,
() => C.host.id,
() => C.host.status,
() => C.host.module,
() => C.data,
() => C.disabled,
],
$,
{
flush: `sync`,
},
),
watch(
() => C.data,
() => {
De.value = C.hostId;
},
{
flush: `sync`,
},
),
watch(B, () => {
((V.value = J.value?.windows ? 3389 : 22), (H.value = 0));
}),
onBeforeUnmount(() => {
((Z = !0), $());
}),
b({
request: Fe,
busy: L,
}),
(n, r) => {
let i = button,
o = OperationNotice,
l = message,
y = select,
b = inputnumber,
x = inputtext,
ue = OperatePasswordGate,
S = checkbox,
C = dialog;
return (
openBlock(),
createElementBlock(`div`, de, [
createElementVNode(`div`, fe, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(ke),
(e) => (
openBlock(),
createBlock(
i,
{
key: e,
label: O[e],
icon:
e === `vnc`
? `pi pi-desktop`
: e === `reset_password`
? `pi pi-key`
: `pi pi-wrench`,
outlined: ``,
size: `small`,
disabled: !unref(M) || unref(L),
onClick: (t) => Fe(e),
},
null,
8,
[`label`, `icon`, `disabled`, `onClick`],
)
),
),
128,
)),
]),
unref(q)
? (openBlock(),
createBlock(
o,
{
key: 0,
message: unref(q),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
unref(G) && unref(K)
? (openBlock(),
createBlock(
o,
{
key: 1,
severity: `error`,
message: unref(G),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
createVNode(
C,
{
visible: !!unref(F),
header: unref(F) ? O[unref(F)] : ``,
modal: ``,
style: {
width: `540px`,
maxWidth: `calc(100vw - 24px)`,
},
draggable: !1,
closable: !unref(L),
"close-on-escape": !unref(L),
"onUpdate:visible": (r[7] ||= (e) => {
e || Pe();
}),
},
{
footer: withCtx(() => [
createVNode(
i,
{
label: `取消`,
outlined: ``,
severity: `secondary`,
disabled: unref(L),
onClick: Pe,
},
null,
8,
[`disabled`],
),
createVNode(
i,
{
label: `确认${unref(F) ? O[unref(F)] : ``}`,
severity: `danger`,
loading: unref(L),
disabled:
unref(L) ||
!unref(M) ||
!unref(F) ||
!N(unref(F)),
onClick: Ie,
},
null,
8,
[`label`, `loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, pe, [
createElementVNode(`p`, me, [
(r[8] ||= createTextVNode(`目标实例:`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
g.host.name ||
unref(product_name_n)(g.host.product_name),
),
1,
),
createTextVNode(
`(#` + toDisplayString(g.hostId) + `)`,
1,
),
]),
createVNode(
l,
{
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(je)), 1),
]),
_: 1,
},
),
unref(G) && !unref(K)
? (openBlock(),
createBlock(
l,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(G)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(F) === `reinstall`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`label`,
{
for: `${unref(w)}-image`,
},
`操作系统`,
8,
he,
),
createVNode(
y,
{
modelValue: unref(B),
"onUpdate:modelValue": (r[0] ||= (e) =>
isRef(B) ? (B.value = e) : null),
"input-id": `${unref(w)}-image`,
options: unref(P),
"option-label": Ae,
"option-value": `id`,
placeholder: `请选择操作系统`,
disabled: unref(L),
fluid: ``,
},
null,
8,
[
`modelValue`,
`input-id`,
`options`,
`disabled`,
],
),
unref(P).length
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
ge,
`此实例暂无可用系统镜像,请刷新详情后重试。`,
)),
createElementVNode(
`label`,
{
for: `${unref(w)}-port`,
},
`连接端口`,
8,
_e,
),
createVNode(
b,
{
modelValue: unref(V),
"onUpdate:modelValue": (r[1] ||= (e) =>
isRef(V) ? (V.value = e) : null),
"input-id": `${unref(w)}-port`,
min: 1,
max: 65535,
"use-grouping": !1,
disabled: unref(L),
fluid: ``,
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
unref(J)?.windows
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`label`,
{
for: `${unref(w)}-partition`,
},
`分区方式`,
8,
ve,
),
createVNode(
y,
{
modelValue: unref(H),
"onUpdate:modelValue": (r[2] ||= (
e,
) =>
isRef(H)
? (H.value = e)
: null),
"input-id": `${unref(w)}-partition`,
options: [
{
label: `格式化全盘`,
value: 0,
},
{
label: `仅格式化第一分区`,
value: 1,
},
],
"option-label": `label`,
"option-value": `value`,
disabled: unref(L),
fluid: ``,
},
null,
8,
[
`modelValue`,
`input-id`,
`disabled`,
],
),
],
64,
))
: createCommentVNode(``, !0),
],
64,
))
: createCommentVNode(``, !0),
unref(Y)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(
`label`,
{
for: `${unref(w)}-password`,
},
`新密码`,
8,
ye,
),
createVNode(
x,
{
id: `${unref(w)}-password`,
modelValue: unref(R),
"onUpdate:modelValue": (r[3] ||= (e) =>
isRef(R) ? (R.value = e) : null),
type: `password`,
autocomplete: `new-password`,
disabled: unref(L),
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
unref(Me)
? (openBlock(),
createElementBlock(
`p`,
be,
toDisplayString(unref(Me)),
1,
))
: createCommentVNode(``, !0),
],
64,
))
: createCommentVNode(``, !0),
unref(F) === `rescue`
? (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
createElementVNode(
`label`,
{
for: `${unref(w)}-rescue`,
},
`救援系统`,
8,
xe,
),
createVNode(
y,
{
modelValue: unref(U),
"onUpdate:modelValue": (r[4] ||= (e) =>
isRef(U) ? (U.value = e) : null),
"input-id": `${unref(w)}-rescue`,
options: [
{
label: `Linux`,
value: 2,
},
{
label: `Windows`,
value: 1,
},
],
"option-label": `label`,
"option-value": `value`,
disabled: unref(L),
fluid: ``,
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
],
64,
))
: createCommentVNode(``, !0),
createVNode(ue, null, {
default: withCtx(() => [
createElementVNode(
`label`,
{
for: `${unref(w)}-operate`,
},
`操作密码(如已设置)`,
8,
Se,
),
createVNode(
x,
{
id: `${unref(w)}-operate`,
modelValue: unref(z),
"onUpdate:modelValue": (r[5] ||= (e) =>
isRef(z) ? (z.value = e) : null),
type: `password`,
autocomplete: `off`,
disabled: unref(L),
fluid: ``,
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
]),
_: 1,
}),
unref(F) === `reinstall`
? (openBlock(),
createElementBlock(`div`, Ce, [
createVNode(
S,
{
modelValue: unref(W),
"onUpdate:modelValue": (r[6] ||= (e) =>
isRef(W) ? (W.value = e) : null),
"input-id": `${unref(w)}-ack`,
binary: ``,
disabled: unref(L),
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
createElementVNode(
`label`,
{
for: `${unref(w)}-ack`,
},
`我已备份数据,了解所选分区的数据将被清除`,
8,
we,
),
]))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `header`, `closable`, `close-on-escape`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-e3236d5c`]],
),
{
__name: `LegacyDcimActions`,
},
);
export {};
export default S;
</script>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,340 @@
<script>
import "~/assets/styles/LegacyProductUpgrade.dzWGwGgY.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import select from "primevue/select";
var C = {
key: 0,
class: `product-upgrade`,
},
w = {
key: 2,
},
T = {
key: 0,
},
E = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `LegacyProductUpgrade`,
props: {
hostId: {},
module: {
default: `remf_finance`,
},
upgradeAllowed: {
type: Boolean,
default: !0,
},
},
emits: [`pay`],
setup(h, { expose: b, emit: E }) {
let D = h,
O = E,
k = useApi(),
A = ref([]),
j = ref(null),
M = ref(``),
N = ref(!1),
P = ref(!1),
F = ref(!1),
I = ref(``),
L = ref(``),
R = computed(() => A.value.find((e) => e.pid === j.value)),
z = computed(() =>
JSON.stringify([D.hostId, D.module, j.value, M.value]),
),
B = 0,
V = 0,
H = !1,
U = ``;
function W() {
(B++, (L.value = ``), (U = ``), (P.value = !1), (I.value = ``));
}
async function G() {
if (D.upgradeAllowed === !1 || H) return;
let e = ++V;
((N.value = !0), (I.value = ``), W());
try {
let t = await k.get(`/${D.module}/${D.hostId}/upgrade_product`);
if (H || e !== V) return;
if (!Array.isArray(t.host))
throw Error(`可升级商品列表无效,请重试`);
((A.value = t.host.filter(
(e) =>
/^[1-9]\d*$/.test(String(e.pid)) && Array.isArray(e.cycle),
)),
(j.value = null),
(M.value = ``));
} catch (t) {
!H &&
e === V &&
(I.value = t instanceof Error ? t.message : `升级商品加载失败`);
} finally {
e === V && (N.value = !1);
}
}
async function K() {
if (
D.upgradeAllowed === !1 ||
F.value ||
!R.value?.cycle.some((e) => e.billingcycle === M.value)
)
return;
let e = ++B,
t = z.value;
((P.value = !0), (L.value = ``), (I.value = ``), (U = ``));
try {
let n = await k.post(
`/${D.module}/${D.hostId}/sync_upgrade_product_price`,
{
product_id: j.value,
cycle: M.value,
},
);
if (H || e !== B || t !== z.value) return;
if (
n.price === null ||
n.price === void 0 ||
String(n.price).trim() === `` ||
!Number.isFinite(Number(n.price))
)
throw Error(`升级报价无效,请重试`);
((L.value = String(n.price)), (U = t));
} catch (t) {
!H &&
e === B &&
(I.value = t instanceof Error ? t.message : `升级询价失败`);
} finally {
e === B && (P.value = !1);
}
}
async function q() {
if (
D.upgradeAllowed === !1 ||
F.value ||
P.value ||
!L.value ||
U !== z.value ||
H
)
return;
let e = z.value,
t = L.value,
n = {
product_id: j.value,
cycle: M.value,
};
((F.value = !0), (I.value = ``));
try {
let r = await k.post(
`/${D.module}/${D.hostId}/upgrade_product`,
n,
);
if (H || e !== z.value) return;
if (!/^[1-9]\d*$/.test(String(r.id)))
throw Error(`升级订单无效,请重试`);
(W(),
O(`pay`, {
order_id: r.id,
amount: t,
}));
} catch (t) {
!H &&
e === z.value &&
(I.value = t instanceof Error ? t.message : `升级订单创建失败`);
} finally {
H || (F.value = !1);
}
}
return (
watch(
j,
() => {
((M.value = ``), W());
},
{
flush: `sync`,
},
),
watch(M, W, {
flush: `sync`,
}),
watch(
[() => D.hostId, () => D.module, () => D.upgradeAllowed],
() => {
(W(), (A.value = []), (j.value = null), G());
},
{
flush: `sync`,
},
),
onMounted(G),
onBeforeUnmount(() => {
((H = !0), B++, V++);
}),
b({
busy: F,
}),
(t, n) => {
let r = message,
a = button,
c = select;
return h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`section`, C, [
(n[2] ||= createElementVNode(`h4`, null, `变更商品`, -1)),
unref(I)
? (openBlock(),
createBlock(
r,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(A).length
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
a,
{
key: 1,
label: unref(N)
? `正在加载可升级商品`
: `刷新可升级商品`,
text: ``,
loading: unref(N),
onClick: G,
},
null,
8,
[`label`, `loading`],
)),
!unref(N) && !unref(I) && !unref(A).length
? (openBlock(),
createElementBlock(`p`, w, `当前暂无可升级商品。`))
: createCommentVNode(``, !0),
unref(A).length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 3,
},
[
createVNode(
c,
{
modelValue: unref(j),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(j) ? (j.value = e) : null),
"aria-label": `升级目标商品`,
options: unref(A),
"option-label": `host`,
"option-value": `pid`,
placeholder: `选择目标商品`,
disabled: unref(F),
},
null,
8,
[`modelValue`, `options`, `disabled`],
),
createVNode(
c,
{
modelValue: unref(M),
"onUpdate:modelValue": (n[1] ||= (e) =>
isRef(M) ? (M.value = e) : null),
"aria-label": `升级计费周期`,
options: unref(R)?.cycle ?? [],
"option-label": `billingcycle_zh`,
"option-value": `billingcycle`,
placeholder: `选择计费周期`,
disabled: unref(F) || !unref(R),
},
null,
8,
[`modelValue`, `options`, `disabled`],
),
createVNode(
a,
{
label: `计算变更费用`,
outlined: ``,
loading: unref(P),
disabled: unref(F) || !unref(M),
onClick: K,
},
null,
8,
[`loading`, `disabled`],
),
unref(L) === ``
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
T,
`变更费用:¥` + toDisplayString(unref(L)),
1,
)),
createVNode(
a,
{
label: `确认生成升级订单`,
loading: unref(F),
disabled: unref(L) === `` || unref(P),
onClick: q,
},
null,
8,
[`loading`, `disabled`],
),
],
64,
))
: createCommentVNode(``, !0),
]));
}
);
},
}),
[[`__scopeId`, `data-v-3bd25322`]],
),
{
__name: `LegacyProductUpgrade`,
},
);
export {};
export default E;
</script>
+641
View File
@@ -0,0 +1,641 @@
<script>
import "~/assets/styles/RemfUpgrade.4stQ5ASH.css";
import { nextTick } from "vue";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import select from "primevue/select";
import inputnumber from "primevue/inputnumber";
import OperationNotice from "~/components/OperationNotice.vue";
import { t as configuration_display_t } from "~/lib/configuration-display.js";
var se = {
key: 0,
class: `upg`,
},
ce = {
key: 0,
class: `upg-state`,
},
le = {
key: 1,
class: `upg-state`,
},
x = {
class: `info-table`,
},
S = [`id`, `for`],
C = {
class: `config-field`,
},
w = {
key: 3,
class: `upg-unsupported`,
},
T = {
class: `kv`,
},
ue = {
class: `upg-price`,
"aria-live": `polite`,
},
de = {
key: 0,
class: `upg-loading`,
},
fe = {
key: 1,
},
pe = {
key: 2,
class: `upg-idle`,
},
me = {
key: 3,
},
he = {
class: `kv`,
},
ge = {
class: `action-cell`,
},
_e = {
key: 0,
class: `upg-note`,
},
E = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `RemfUpgrade`,
props: {
hostId: {},
module: {
default: `remf_finance`,
},
upgradeAllowed: {
type: Boolean,
default: !0,
},
},
emits: [`pay`],
setup(h, { expose: v, emit: E }) {
let D = h,
O = computed(() => D.module || `remf_finance`),
ve = E,
k = useApi(),
A = ref(``),
j = useId(),
M = [4, 7, 9, 11, 14, 15, 16, 17, 18, 19],
N = [1, 2, 3, 6, 8, 10, 13],
P = ref([]),
F = ref({}),
I = ref(!1),
L = ref(``),
R = ref(``),
z = ref(``),
B = ref(!1),
V = ref(!1),
H = ref(!1),
U = !1,
W,
G = 0,
K = !1,
q = 0,
J = ``,
Y = computed(() => JSON.stringify([D.hostId, O.value, F.value]));
function X(e) {
return e.option_type === 5 && e.sub && !Array.isArray(e.sub)
? Object.entries(e.sub).flatMap(([e, t]) =>
(t.child ?? []).map((t) => ({
...t,
option_name: `${e} / ${t.version || t.option_name || t.id}`,
})),
)
: e.option_type === 12 && Array.isArray(e.sub)
? e.sub.flatMap((e) =>
(e.area ?? []).map((t) => ({
id: t.id,
option_name: [e.option_name, t.area_zh || t.area]
.filter(Boolean)
.join(` / `),
})),
)
: Array.isArray(e.sub)
? e.sub
: [];
}
let Z = (e) =>
M.includes(e.option_type) ||
N.includes(e.option_type) ||
([5, 12].includes(e.option_type) && X(e).length > 0),
Q = computed(() =>
P.value
.filter((e) => !Z(e))
.map((e) =>
configuration_display_t(e.option_name, e.option_type),
),
);
async function $() {
if (D.upgradeAllowed === !1) return;
let t = ++q;
((I.value = !0), (L.value = ``));
try {
let n = await k.get(`/${O.value}/${D.hostId}/upgrade_config`);
if (K || t !== q) return;
P.value = n.host ?? [];
let r = {};
for (let e of P.value)
Z(e) &&
(r[String(e.id)] = M.includes(e.option_type)
? Number(e.qty ?? e.qty_minimum ?? 1)
: Number(e.subid ?? X(e)[0]?.id ?? 0));
((U = !0),
(F.value = r),
await nextTick(),
(U = !1),
(H.value = !1));
} catch (e) {
!K &&
t === q &&
(L.value =
e instanceof Error ? e.message : `加载升降级配置失败`);
} finally {
t === q && (I.value = !1);
}
}
function ye() {
D.upgradeAllowed === !1 ||
U ||
((H.value = !0),
G++,
(J = ``),
(B.value = !1),
clearTimeout(W),
(z.value = ``),
(L.value = ``),
(W = setTimeout(be, 400)));
}
async function be() {
if (
D.upgradeAllowed === !1 ||
!P.value.length ||
!Object.keys(F.value).length
)
return;
for (let e of P.value.filter(Z)) {
let t = F.value[String(e.id)];
if (!(
Number.isFinite(t) &&
(M.includes(e.option_type)
? Number(t) >= Number(e.qty_minimum ?? 0) &&
Number(t) <= Number(e.qty_maximum ?? 1 / 0)
: (e.option_type === 3 && t === 0) ||
X(e).some((e) => e.id === t))
)) {
L.value = `请检查${configuration_display_t(e.option_name, e.option_type)}的配置`;
return;
}
}
let e = ++G,
t = Y.value,
n = {
...F.value,
};
((B.value = !0), (L.value = ``));
try {
let r = await k.post(
`/${O.value}/${D.hostId}/sync_upgrade_config_price`,
{
id: D.hostId,
configoption: n,
},
);
if (K || e !== G || t !== Y.value) return;
if (
r?.price === null ||
r?.price === void 0 ||
String(r.price).trim() === `` ||
!Number.isFinite(Number(r.price))
)
throw Error(`升级报价无效,请重试`);
((z.value = String(r.price)), (J = t));
} catch (n) {
if (K || e !== G || t !== Y.value) return;
((z.value = ``),
(L.value = n instanceof Error ? n.message : `询价失败`));
} finally {
e === G && (B.value = !1);
}
}
async function xe() {
if (
D.upgradeAllowed === !1 ||
!z.value ||
V.value ||
B.value ||
K ||
J !== Y.value
)
return;
let e = Y.value,
t = {
...F.value,
},
n = z.value;
((V.value = !0), (L.value = ``), (A.value = ``), (R.value = ``));
try {
let r = await k.post(`/${O.value}/${D.hostId}/upgrade_config`, {
configoption: t,
buy: !1,
});
if (K || e !== Y.value) return;
if (!/^[1-9]\d*$/.test(String(r.id)))
throw Error(`升级订单无效,请重试`);
((J = ``),
(z.value = ``),
ve(`pay`, {
order_id: r.id,
amount: n,
}));
} catch (e) {
A.value = e instanceof Error ? e.message : `提交失败`;
} finally {
V.value = !1;
}
}
return (
watch(F, ye, {
deep: !0,
flush: `sync`,
}),
watch(
[() => D.hostId, O, () => D.upgradeAllowed],
() => {
(G++,
q++,
clearTimeout(W),
(J = ``),
(z.value = ``),
(P.value = []),
$());
},
{
flush: `sync`,
},
),
onMounted($),
onBeforeUnmount(() => {
((K = !0), G++, q++, clearTimeout(W));
}),
v({
busy: V,
}),
(e, r) => {
let i = OperationNotice,
a = inputnumber,
o = select,
c = button,
u = message;
return h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, se, [
createVNode(
i,
{
message: unref(A),
severity: `error`,
},
null,
8,
[`message`],
),
unref(I)
? (openBlock(), createElementBlock(`div`, ce, `加载中…`))
: unref(P).length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(`div`, x, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(P),
(e) => (
openBlock(),
createElementBlock(
`div`,
{
key: e.id,
class: `kv`,
},
[
createElementVNode(
`label`,
{
id: `${unref(j)}-option-${e.id}-label`,
for: Z(e)
? `${unref(j)}-option-${e.id}`
: void 0,
},
toDisplayString(
unref(configuration_display_t)(
e.option_name,
e.option_type,
),
),
9,
S,
),
createElementVNode(`div`, C, [
M.includes(e.option_type)
? (openBlock(),
createBlock(
a,
{
key: 0,
"input-id": `${unref(j)}-option-${e.id}`,
modelValue:
unref(F)[String(e.id)],
"onUpdate:modelValue": (
t,
) =>
(unref(F)[String(e.id)] =
t),
min: Number(
e.qty_minimum ?? 1,
),
max: Number(
e.qty_maximum ?? 99,
),
disabled: unref(V),
showButtons: ``,
buttonLayout: `horizontal`,
suffix: e.unit
? ` ${e.unit}`
: ``,
},
null,
8,
[
`input-id`,
`modelValue`,
`onUpdate:modelValue`,
`min`,
`max`,
`disabled`,
`suffix`,
],
))
: e.option_type === 1 ||
e.option_type === 3
? (openBlock(),
createBlock(
o,
{
key: 1,
"input-id": `${unref(j)}-option-${e.id}`,
"aria-labelledby": `${unref(j)}-option-${e.id}-label`,
modelValue:
unref(F)[String(e.id)],
"onUpdate:modelValue": (
t,
) =>
(unref(F)[
String(e.id)
] = t),
options:
e.option_type === 3
? [
{
id: 0,
option_name: `不启用`,
},
...X(e),
]
: X(e),
disabled: unref(V),
optionLabel: `option_name`,
optionValue: `id`,
},
null,
8,
[
`input-id`,
`aria-labelledby`,
`modelValue`,
`onUpdate:modelValue`,
`options`,
`disabled`,
],
))
: Z(e)
? (openBlock(),
createBlock(
o,
{
key: 2,
"input-id": `${unref(j)}-option-${e.id}`,
"aria-labelledby": `${unref(j)}-option-${e.id}-label`,
modelValue:
unref(F)[
String(e.id)
],
"onUpdate:modelValue": (
t,
) =>
(unref(F)[
String(e.id)
] = t),
options: X(e),
disabled: unref(V),
optionLabel: `option_name`,
optionValue: `id`,
},
null,
8,
[
`input-id`,
`aria-labelledby`,
`modelValue`,
`onUpdate:modelValue`,
`options`,
`disabled`,
],
))
: (openBlock(),
createElementBlock(
`span`,
w,
`该配置项暂不支持在线调整,请联系客服`,
)),
]),
],
)
),
),
128,
)),
createElementVNode(`div`, T, [
(r[1] ||= createElementVNode(
`span`,
null,
`升级费用`,
-1,
)),
createElementVNode(`div`, ue, [
unref(B)
? (openBlock(),
createElementBlock(`b`, de, [
...(r[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-spin pi-spinner`,
},
null,
-1,
),
]),
]))
: unref(z) === ``
? unref(H)
? (openBlock(),
createElementBlock(`b`, me, `—`))
: (openBlock(),
createElementBlock(
`b`,
pe,
`调整配置后显示`,
))
: (openBlock(),
createElementBlock(
`b`,
fe,
`¥` + toDisplayString(unref(z)),
1,
)),
]),
]),
createElementVNode(`div`, he, [
(r[2] ||= createElementVNode(
`span`,
null,
`操作`,
-1,
)),
createElementVNode(`div`, ge, [
createVNode(
c,
{
label: `提交升级`,
loading: unref(V),
disabled: !unref(z),
onClick: xe,
},
null,
8,
[`loading`, `disabled`],
),
]),
]),
]),
unref(Q).length && unref(P).length
? (openBlock(),
createElementBlock(
`div`,
_e,
` 以下配置项需联系客服调整:` +
toDisplayString(unref(Q).join(`、`)),
1,
))
: createCommentVNode(``, !0),
unref(L)
? (openBlock(),
createBlock(
u,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(L)),
1,
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
i,
{
message: unref(R),
severity: `success`,
},
null,
8,
[`message`],
),
(r[3] ||= createElementVNode(
`p`,
{
class: `upg-desc`,
},
`提交后生成升级订单,支付完成后生效;费用按剩余周期折算。`,
-1,
)),
],
64,
))
: (openBlock(),
createElementBlock(
`div`,
le,
toDisplayString(
unref(L) || `该实例暂无可调整的配置项`,
),
1,
)),
]));
}
);
},
}),
[[`__scopeId`, `data-v-7efd9d4d`]],
),
{
__name: `RemfUpgrade`,
},
);
export {};
export default E;
</script>
+923
View File
@@ -0,0 +1,923 @@
<script>
import "~/assets/styles/RemoteConsole.DLmX5UZu.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { withModifiers } from "vue";
import { loadModule } from "~/utils/load-module.js";
import { useAuth } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputtext from "primevue/inputtext";
var T = /^[a-f0-9]{64}$/;
function E(e, n) {
let r = useAuth(),
o = ref(`idle`),
c = ref(``),
l = ref(!0),
u = ref([]),
d = 0,
f = !1,
p = null,
m = null,
h = null,
g = null,
_ = [];
function v() {
(m !== null && clearTimeout(m), (m = null));
}
async function y(e, t) {
if (T.test(e))
try {
await fetch(`/remote-console/sessions/${e}`, {
method: `DELETE`,
headers: {
Authorization: `Bearer ${t}`,
},
credentials: `same-origin`,
cache: `no-store`,
keepalive: !0,
});
} catch {}
}
function S() {
if ((d++, p?.abort(), (p = null), v(), g)) {
for (let [e, t] of _) g.removeEventListener(e, t);
try {
g.disconnect();
} catch {}
g = null;
}
if (((_ = []), (u.value = []), h)) {
let e = h;
((h = null), y(e.id, e.token));
}
}
function C() {
(S(), (c.value = ``), (o.value = `disconnected`));
}
function w(e) {
(S(), (c.value = e), (o.value = `error`));
}
function E(e) {
(v(),
(m = setTimeout(() => {
e === d && !f && w(`连接超时,请重新连接。`);
}, 45e3)));
}
function D(e, t) {
if (t === 401) return `登录已失效,请重新登录后打开控制台。`;
if (t === 403) return `暂时无法访问此实例的控制台,请核对账号后重试。`;
let n = e && typeof e == `object` && `error` in e ? e.error : null;
return typeof n == `string` &&
/^[\u3400-\u9fff\s,。!?、:()…0-9-]{1,100}$/u.test(n)
? n
: `控制台暂时无法连接,请稍后重试。`;
}
async function O() {
if ((S(), (c.value = ``), f || !n.visible() || !e.value)) {
o.value = `idle`;
return;
}
let t = localStorage.getItem(`jwt`);
if (!t || r.token !== t) {
((o.value = `error`), (c.value = `请重新登录后打开控制台。`));
return;
}
let i = String(n.hostId()),
a = n.module(),
s = e.value;
if (!/^\d+$/.test(i) || Number(i) < 1 || !a) {
((o.value = `error`), (c.value = `实例信息尚未就绪,请重新打开控制台。`));
return;
}
let m = d,
x = () =>
m === d &&
!f &&
n.visible() &&
e.value === s &&
String(n.hostId()) === i &&
n.module() === a &&
r.token === t &&
localStorage.getItem(`jwt`) === t;
((o.value = `creating`), (p = new AbortController()));
let C = p.signal;
E(m);
try {
let e = await fetch(`/remote-console/sessions`, {
method: `POST`,
credentials: `same-origin`,
cache: `no-store`,
signal: C,
headers: {
Authorization: `Bearer ${t}`,
"Content-Type": `application/json`,
},
body: JSON.stringify({
hostId: i,
module: a,
...(n.operatePassword()
? {
client_operate_password: n.operatePassword(),
}
: {}),
}),
}),
r = await e.json().catch(() => null),
d =
typeof r?.sessionId == `string` && T.test(r.sessionId)
? r.sessionId
: ``;
if (!x()) {
d && y(d, t);
return;
}
if (!e.ok) {
(d && y(d, t), w(D(r, e.status)));
return;
}
if (
(d &&
(h = {
id: d,
token: t,
}),
!d || r?.websocketPath !== `/remote-console/sessions/${d}/socket`)
) {
w(`控制台连接信息无效,请重新连接。`);
return;
}
let { default: f } = await loadModule(
async () => {
let { default: e } = await import("@novnc/novnc");
return {
default: e,
};
},
[],
import.meta.url,
);
if (!x()) return;
o.value = `connecting`;
let p = new f(
s,
`${window.location.protocol === `https:` ? `wss:` : `ws:`}//${window.location.host}${r.websocketPath}`,
{
...(typeof r.credentials?.password == `string`
? {
credentials: {
password: r.credentials.password,
},
}
: {}),
},
);
((g = p), (p.scaleViewport = l.value), (p.resizeSession = !1));
let m = (e, t) => {
(p.addEventListener(e, t), _.push([e, t]));
};
(m(`connect`, () => {
x() && (v(), (u.value = []), (o.value = `connected`));
}),
m(`disconnect`, () => {
if (!x()) return;
let e = o.value === `connected`;
(S(),
(o.value = e ? `disconnected` : `error`),
(c.value = e ? `` : `连接未能建立,请重新连接。`));
}),
m(`credentialsrequired`, (e) => {
if (!x()) return;
v();
let t = e.detail?.types;
if (
((u.value = Array.isArray(t)
? t.filter((e) => [`username`, `password`, `target`].includes(e))
: [`password`]),
!u.value.length)
) {
w(`此控制台暂不支持当前验证方式,请联系支持。`);
return;
}
o.value = `credentials`;
}),
m(`securityfailure`, () => {
x() && w(`控制台验证失败,请重新连接。`);
}));
} catch {
x() && w(`控制台暂时无法连接,请稍后重试。`);
}
}
function k(e) {
if (!g || o.value !== `credentials` || u.value.some((t) => !e[t]))
return !1;
try {
return (
g.sendCredentials(e),
(o.value = `connecting`),
(u.value = []),
E(d),
!0
);
} catch {
return (w(`控制台验证失败,请重新连接。`), !1);
}
}
function A() {
if (o.value === `connected` && g)
try {
(g.sendCtrlAltDel(), g.focus());
} catch {
w(`连接已中断,请重新连接。`);
}
}
(watch(l, (e) => {
g && (g.scaleViewport = e);
}),
watch(
[n.visible, n.hostId, n.module, e],
() => {
n.visible() && e.value
? O()
: (S(), (o.value = `idle`), (c.value = ``));
},
{
flush: `post`,
immediate: !0,
},
),
watch(
() => r.token,
() => {
(S(), (o.value = `idle`), n.visible() && n.close());
},
{
flush: `sync`,
},
));
function j(e) {
(e.key === `jwt` || e.key === null) &&
n.visible() &&
(S(), (o.value = `idle`), n.close());
}
return (
onMounted(() => window.addEventListener(`storage`, j)),
onBeforeUnmount(() => {
((f = !0), S(), window.removeEventListener(`storage`, j));
}),
{
state: o,
error: c,
fit: l,
credentialTypes: u,
connect: O,
disconnect: C,
submitCredentials: k,
sendCtrlAltDel: A,
}
);
}
var D = [`aria-labelledby`],
O = {
class: `console-header`,
},
k = {
class: `console-heading`,
},
A = [`id`],
j = {
class: `host-id`,
},
M = {
key: 0,
class: `console-target`,
},
ee = {
class: `console-toolbar`,
role: `toolbar`,
"aria-label": `远程控制台操作`,
},
te = {
class: `toolbar-group`,
},
ne = {
class: `toolbar-group`,
},
re = {
key: 0,
class: `toolbar-message`,
role: `status`,
},
ie = [`aria-busy`],
ae = [`aria-label`],
oe = {
key: 0,
class: `console-overlay`,
},
se = [`for`],
ce = [`for`],
N = [`for`],
P = {
key: 3,
class: `credential-error`,
role: `alert`,
},
F = {
key: 1,
class: `connection-message`,
role: `status`,
"aria-live": `polite`,
},
I = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `RemoteConsole`,
props: {
visible: {
type: Boolean,
},
hostId: {},
module: {},
hostName: {},
operatePassword: {},
},
emits: [`update:visible`],
setup(g, { emit: b }) {
let x = g,
C = b,
T = useId(),
I = ref(null),
L = ref(null),
R = ref(!1),
z = ref(``),
B = ref(``),
V = ref(``),
H = ref(``),
U = ref(``),
{
state: W,
error: le,
fit: G,
credentialTypes: K,
connect: q,
disconnect: J,
submitCredentials: ue,
sendCtrlAltDel: de,
} = E(I, {
visible: () => x.visible,
hostId: () => x.hostId,
module: () => x.module,
operatePassword: () => x.operatePassword,
close: () => C(`update:visible`, !1),
}),
Y = computed(
() => W.value === `creating` || W.value === `connecting`,
),
X = computed(
() =>
({
idle: `准备连接`,
creating: `正在建立会话`,
connecting: `正在连接`,
credentials: `等待验证`,
connected: `已连接`,
disconnected: `已断开`,
error: `连接失败`,
})[W.value],
),
Z = computed(() => x.hostName?.trim() || `服务器实例`);
function Q() {
((z.value = ``), (B.value = ``), (V.value = ``), (H.value = ``));
}
watch([W, () => x.visible], Q);
function fe() {
((H.value = ``),
ue({
password: z.value,
username: B.value,
target: V.value,
})
? Q()
: W.value === `credentials` &&
(H.value = `请填写所需的验证信息。`));
}
function pe() {
(J(), Q(), C(`update:visible`, !1));
}
async function me() {
U.value = ``;
try {
document.fullscreenElement === L.value
? await document.exitFullscreen()
: L.value?.requestFullscreen
? await L.value.requestFullscreen()
: (U.value = `当前浏览器不支持全屏,可使用浏览器缩放调整显示。`);
} catch {
U.value = `未能进入全屏,请重试。`;
}
}
function $() {
R.value = !!L.value && document.fullscreenElement === L.value;
}
return (
onMounted(() => document.addEventListener(`fullscreenchange`, $)),
onBeforeUnmount(() =>
document.removeEventListener(`fullscreenchange`, $),
),
(t, n) => {
let i = button,
a = inputtext;
return g.visible
? (openBlock(),
createElementBlock(
`section`,
{
key: 0,
ref_key: `surface`,
ref: L,
class: normalizeClass([
`remote-console`,
{
"is-fullscreen": unref(R),
},
]),
"aria-labelledby": `${unref(T)}-title`,
},
[
createElementVNode(`header`, O, [
(n[7] ||= createElementVNode(
`span`,
{
class: `console-mark`,
"aria-hidden": `true`,
},
[
createElementVNode(`i`, {
class: `pi pi-desktop`,
}),
],
-1,
)),
createElementVNode(`div`, k, [
(n[5] ||= createElementVNode(
`p`,
{
class: `console-brand`,
},
`破碎工坊云`,
-1,
)),
createElementVNode(
`h1`,
{
id: `${unref(T)}-title`,
},
[
(n[4] ||= createTextVNode(`远程控制台`, -1)),
createElementVNode(
`span`,
j,
`#` + toDisplayString(g.hostId),
1,
),
],
8,
A,
),
g.hostName
? (openBlock(),
createElementBlock(
`p`,
M,
toDisplayString(unref(Z)),
1,
))
: createCommentVNode(``, !0),
]),
createElementVNode(
`span`,
{
class: normalizeClass([
`connection-state`,
`state-${unref(W)}`,
]),
role: `status`,
"aria-live": `polite`,
},
[
(n[6] ||= createElementVNode(
`span`,
{
class: `state-dot`,
"aria-hidden": `true`,
},
null,
-1,
)),
createTextVNode(toDisplayString(unref(X)), 1),
],
2,
),
createVNode(i, {
icon: `pi pi-times`,
"aria-label": `关闭远程控制台`,
text: ``,
severity: `secondary`,
rounded: ``,
onClick: pe,
}),
]),
createElementVNode(`div`, ee, [
createElementVNode(`div`, te, [
createVNode(
i,
{
label: `适应窗口`,
icon: `pi pi-expand`,
outlined: !unref(G),
severity: unref(G) ? `primary` : `secondary`,
size: `small`,
"aria-pressed": unref(G),
onClick: (n[0] ||= (e) => (G.value = !unref(G))),
},
null,
8,
[`outlined`, `severity`, `aria-pressed`],
),
createVNode(
i,
{
label: unref(R) ? `退出全屏` : `全屏`,
icon: unref(R)
? `pi pi-window-minimize`
: `pi pi-window-maximize`,
outlined: ``,
severity: `secondary`,
size: `small`,
onClick: me,
},
null,
8,
[`label`, `icon`],
),
createVNode(
i,
{
label: `Ctrl + Alt + Del`,
outlined: ``,
severity: `secondary`,
size: `small`,
disabled: unref(W) !== `connected`,
onClick: unref(de),
},
null,
8,
[`disabled`, `onClick`],
),
]),
createElementVNode(`div`, ne, [
createVNode(
i,
{
label: `重新连接`,
icon: `pi pi-refresh`,
outlined: ``,
severity: `secondary`,
size: `small`,
disabled: unref(Y),
onClick: unref(q),
},
null,
8,
[`disabled`, `onClick`],
),
createVNode(
i,
{
label: `断开`,
icon: `pi pi-power-off`,
text: ``,
severity: `secondary`,
size: `small`,
disabled:
unref(W) === `idle` ||
unref(W) === `disconnected` ||
unref(W) === `error`,
onClick: unref(J),
},
null,
8,
[`disabled`, `onClick`],
),
]),
]),
unref(U)
? (openBlock(),
createElementBlock(
`p`,
re,
toDisplayString(unref(U)),
1,
))
: createCommentVNode(``, !0),
createElementVNode(
`div`,
{
class: `console-display`,
"aria-busy": unref(Y),
},
[
createElementVNode(
`div`,
{
ref_key: `screen`,
ref: I,
class: `console-screen`,
"aria-label": `${unref(Z)} 的远程屏幕`,
},
null,
8,
ae,
),
unref(W) === `connected`
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, oe, [
unref(W) === `credentials`
? (openBlock(),
createElementBlock(
`form`,
{
key: 0,
class: `credential-form`,
onSubmit: withModifiers(fe, [
`prevent`,
]),
},
[
(n[8] ||= createElementVNode(
`i`,
{
class: `pi pi-lock state-icon`,
"aria-hidden": `true`,
},
null,
-1,
)),
(n[9] ||= createElementVNode(
`h3`,
null,
`验证控制台连接`,
-1,
)),
(n[10] ||= createElementVNode(
`p`,
null,
`请输入此控制台要求的连接凭据。`,
-1,
)),
unref(K).includes(`username`)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(
`label`,
{
for: `${unref(T)}-username`,
},
`用户名`,
8,
se,
),
createVNode(
a,
{
id: `${unref(T)}-username`,
modelValue: unref(B),
"onUpdate:modelValue":
(n[1] ||= (e) =>
isRef(B)
? (B.value = e)
: null),
autocomplete: `off`,
fluid: ``,
},
null,
8,
[`id`, `modelValue`],
),
],
64,
))
: createCommentVNode(``, !0),
unref(K).includes(`target`)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(
`label`,
{
for: `${unref(T)}-target`,
},
`目标`,
8,
ce,
),
createVNode(
a,
{
id: `${unref(T)}-target`,
modelValue: unref(V),
"onUpdate:modelValue":
(n[2] ||= (e) =>
isRef(V)
? (V.value = e)
: null),
autocomplete: `off`,
fluid: ``,
},
null,
8,
[`id`, `modelValue`],
),
],
64,
))
: createCommentVNode(``, !0),
unref(K).includes(`password`)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
createElementVNode(
`label`,
{
for: `${unref(T)}-password`,
},
`控制台密码`,
8,
N,
),
createVNode(
a,
{
id: `${unref(T)}-password`,
modelValue: unref(z),
"onUpdate:modelValue":
(n[3] ||= (e) =>
isRef(z)
? (z.value = e)
: null),
type: `password`,
autocomplete: `off`,
fluid: ``,
},
null,
8,
[`id`, `modelValue`],
),
],
64,
))
: createCommentVNode(``, !0),
unref(H)
? (openBlock(),
createElementBlock(
`p`,
P,
toDisplayString(unref(H)),
1,
))
: createCommentVNode(``, !0),
createVNode(i, {
type: `submit`,
label: `连接`,
fluid: ``,
}),
],
32,
))
: (openBlock(),
createElementBlock(`div`, F, [
createElementVNode(
`i`,
{
class: normalizeClass([
unref(Y)
? `pi pi-spinner pi-spin`
: unref(W) === `error`
? `pi pi-exclamation-circle`
: `pi pi-desktop`,
`state-icon`,
]),
"aria-hidden": `true`,
},
null,
2,
),
createElementVNode(
`h3`,
null,
toDisplayString(unref(X)),
1,
),
createElementVNode(
`p`,
null,
toDisplayString(
unref(le) ||
(unref(Y)
? `连接启动可能需要一些时间,请稍候。`
: unref(W) === `disconnected`
? `远程会话已结束,实例继续运行。`
: `正在准备您的远程屏幕。`),
),
1,
),
unref(W) === `error` ||
unref(W) === `disconnected`
? (openBlock(),
createBlock(
i,
{
key: 0,
label: `重新连接`,
icon: `pi pi-refresh`,
onClick: unref(q),
},
null,
8,
[`onClick`],
))
: createCommentVNode(``, !0),
])),
])),
],
8,
ie,
),
(n[11] ||= createElementVNode(
`footer`,
{
class: `console-footer`,
},
[
createElementVNode(
`span`,
null,
`点击远程屏幕后使用键盘与鼠标操作。`,
),
createElementVNode(
`span`,
null,
`关闭控制台不会关闭实例`,
),
],
-1,
)),
],
10,
D,
))
: createCommentVNode(``, !0);
}
);
},
}),
[[`__scopeId`, `data-v-e696489e`]],
),
{
__name: `RemoteConsole`,
},
);
export {};
export default I;
</script>
File diff suppressed because it is too large. Load diff
+511
View File
@@ -0,0 +1,511 @@
<script>
import "~/assets/styles/MfCloudDefence.B2vl5Yip.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import select from "primevue/select";
import { n as cloud_instance_management_n } from "~/lib/cloud-instance-management.js";
import { s as cloud_instance_management_s } from "~/lib/cloud-instance-management.js";
import { t as cloud_instance_management_t } from "~/lib/cloud-instance-management.js";
var E = {
class: `defence network-section`,
},
D = {
class: `network-head`,
},
O = {
class: `network-actions`,
},
te = {
key: 0,
},
ne = {
key: 1,
class: `muted`,
},
re = {
key: 2,
class: `muted`,
},
ie = {
key: 3,
class: `muted`,
},
ae = {
key: 4,
class: `muted`,
},
oe = {
class: `form`,
},
se = {
key: 0,
},
k = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `MfCloudDefence`,
props: {
hostId: {},
module: {},
ips: {},
active: {
type: Boolean,
},
upgradeAllowed: {
type: Boolean,
},
},
emits: [`pay`],
setup(h, { emit: b }) {
let k = h,
ce = b,
A = useApi(),
le = useId(),
j = ref(k.ips[0] ?? ``),
M = ref(``),
N = ref(``),
P = ref([]),
F = ref(!1),
I = ref(!1),
L = ref(``),
R = ref(``),
z = ref(!1),
B = ref(!1),
V = ref(``),
H = ref(``),
U = computed(() =>
JSON.stringify([
k.hostId,
k.module,
j.value,
M.value,
z.value,
k.upgradeAllowed,
]),
),
W = ref(``),
G = computed(() =>
P.value.filter((e) => String(e.value) !== String(N.value)),
),
K = computed(
() =>
!!W.value &&
W.value === U.value &&
!B.value &&
!I.value &&
k.upgradeAllowed &&
k.active &&
G.value.some((e) => String(e.value) === String(M.value)),
),
q = 0,
J = 0,
Y = 0,
X = !1;
function Z() {
(J++,
(W.value = ``),
(V.value = ``),
(H.value = ``),
(B.value = !1));
}
watch(U, Z, {
flush: `sync`,
});
async function Q() {
let e = ++q,
t = j.value,
n = k.hostId,
r = k.module;
if (
((P.value = []),
(L.value = ``),
(F.value = !0),
(N.value = ``),
Z(),
!t)
) {
F.value = !1;
return;
}
try {
let i = await A.get(`/${r}/${n}/upgrade_defence_config`, {
ip: t,
});
if (X || e !== q) return;
let a = cloud_instance_management_n(i);
((P.value = a.options), (N.value = a.current));
} catch (t) {
!X &&
e === q &&
(L.value = t instanceof Error ? t.message : `加载防御配置失败`);
} finally {
!X && e === q && (F.value = !1);
}
}
function ue() {
k.upgradeAllowed &&
k.active &&
!I.value &&
!F.value &&
G.value.length &&
((M.value = ``), (R.value = ``), (z.value = !0));
}
async function $() {
if (
(Z(),
!z.value ||
!k.upgradeAllowed ||
!G.value.some((e) => String(e.value) === String(M.value)))
)
return;
let e = ++J,
t = U.value;
((B.value = !0), (R.value = ``));
try {
let n = await A.get(
`/${k.module}/${k.hostId}/upgrade_defence/price`,
{
ip: j.value,
peak_defence: M.value,
},
);
if (X || e !== J || t !== U.value) return;
((V.value = cloud_instance_management_t(n.price)),
(H.value = String(n.renew_price_difference ?? ``)),
(W.value = t));
} catch (t) {
!X &&
e === J &&
(R.value = t instanceof Error ? t.message : `报价失败`);
} finally {
!X && e === J && (B.value = !1);
}
}
async function de() {
if (!K.value || X) return;
let e = U.value,
t = V.value,
n = ++Y;
((I.value = !0), (R.value = ``));
try {
let n = await A.post(
`/${k.module}/${k.hostId}/upgrade_defence/order`,
{
ip: j.value,
peak_defence: M.value,
},
);
if (X || e !== U.value) return;
let r = cloud_instance_management_s(n.id);
((z.value = !1),
ce(`pay`, {
order_id: r,
amount:
n.amount == null
? t
: cloud_instance_management_t(n.amount),
}));
} catch (t) {
!X &&
e === U.value &&
(R.value = t instanceof Error ? t.message : `创建订单失败`);
} finally {
!X && n === Y && (I.value = !1);
}
}
return (
watch(j, () => {
((z.value = !1), Q());
}),
watch(
() => [k.hostId, k.module, k.ips.join(`,`)],
() => {
(Y++,
(z.value = !1),
(I.value = !1),
(j.value = k.ips.includes(j.value)
? j.value
: (k.ips[0] ?? ``)),
Q());
},
),
onMounted(Q),
onBeforeUnmount(() => {
((X = !0), q++, Z());
}),
(t, n) => {
let r = select,
i = button,
o = message,
l = dialog;
return (
openBlock(),
createElementBlock(`section`, E, [
createElementVNode(`div`, D, [
(n[4] ||= createElementVNode(`h4`, null, `每 IP 防御`, -1)),
createElementVNode(`div`, O, [
createVNode(
r,
{
class: `defence-ip`,
modelValue: unref(j),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(j) ? (j.value = e) : null),
options: h.ips,
"input-id": `${unref(le)}-ip`,
"aria-label": `防御 IP`,
disabled: unref(I) || !h.ips.length,
},
null,
8,
[`modelValue`, `options`, `input-id`, `disabled`],
),
createVNode(
i,
{
label: `刷新`,
text: ``,
size: `small`,
loading: unref(F),
disabled: unref(I),
onClick: Q,
},
null,
8,
[`loading`, `disabled`],
),
createVNode(
i,
{
label: `调整防御`,
size: `small`,
disabled:
!h.upgradeAllowed ||
!h.active ||
unref(I) ||
unref(F) ||
!unref(G).length,
onClick: ue,
},
null,
8,
[`disabled`],
),
]),
]),
unref(N) === ``
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
te,
`当前防御:` + toDisplayString(unref(N)) + ` Gbps`,
1,
)),
h.ips.length
? !unref(F) && !unref(L) && !unref(P).length
? (openBlock(),
createElementBlock(`p`, re, `当前 IP 未开放防御调整。`))
: !unref(F) && !unref(L) && !unref(G).length
? (openBlock(),
createElementBlock(
`p`,
ie,
`当前 IP 没有其他可选防御档位。`,
))
: createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
ne,
`暂无可调整防御的 IP 地址。`,
)),
h.upgradeAllowed
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`p`, ae, `当前实例不允许升降级。`)),
unref(L)
? (openBlock(),
createBlock(
o,
{
key: 5,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(L)), 1),
createVNode(i, {
label: `重试`,
text: ``,
size: `small`,
onClick: Q,
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
l,
{
visible: unref(z),
"onUpdate:visible": (n[3] ||= (e) =>
isRef(z) ? (z.value = e) : null),
header: `调整 IP 防御`,
modal: ``,
closable: !unref(I),
"close-on-escape": !unref(I),
},
{
footer: withCtx(() => [
createVNode(
i,
{
label: `取消`,
text: ``,
severity: `secondary`,
disabled: unref(I),
onClick: (n[2] ||= (e) => (z.value = !1)),
},
null,
8,
[`disabled`],
),
createVNode(
i,
{
label: `创建订单`,
loading: unref(I),
disabled: !unref(K),
onClick: de,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, oe, [
createElementVNode(
`p`,
null,
toDisplayString(unref(j)),
1,
),
createVNode(
r,
{
modelValue: unref(M),
"onUpdate:modelValue": (n[1] ||= (e) =>
isRef(M) ? (M.value = e) : null),
options: unref(G),
"option-label": `desc`,
"option-value": `value`,
"aria-label": `目标防御峰值`,
disabled: unref(I),
onChange: $,
},
null,
8,
[`modelValue`, `options`, `disabled`],
),
createElementVNode(
`p`,
null,
`本次费用:` +
toDisplayString(
unref(B)
? `正在计算…`
: unref(V) === ``
? `待确认`
: `¥${unref(V)}`,
),
1,
),
unref(H) === ``
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
se,
`续费差价:¥` + toDisplayString(unref(H)),
1,
)),
unref(R)
? (openBlock(),
createBlock(
o,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(R)),
1,
),
createVNode(
i,
{
label: `重新报价`,
text: ``,
size: `small`,
disabled: unref(I),
onClick: $,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-b0c2bd86`]],
),
{
__name: `MfCloudDefence`,
},
);
export {};
export default k;
</script>
+726
View File
@@ -0,0 +1,726 @@
<script>
import "~/assets/styles/MfCloudIps.jhFnuvcs.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { reactive } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import datatable from "primevue/datatable";
import inputnumber from "primevue/inputnumber";
import column from "primevue/column";
import OperationNotice from "~/components/OperationNotice.vue";
import { i as cloud_instance_management_i } from "~/lib/cloud-instance-management.js";
import { s as cloud_instance_management_s } from "~/lib/cloud-instance-management.js";
import { t as cloud_instance_management_t } from "~/lib/cloud-instance-management.js";
var ce = {
class: `ips`,
},
C = {
class: `ips-head network-head`,
},
w = {
class: `ips-title`,
},
T = {
key: 0,
class: `count`,
},
E = {
class: `network-actions`,
},
le = {
class: `col-mono`,
},
ue = {
class: `col-mono`,
},
de = {
class: `col-mono`,
},
fe = {
class: `ipv6-group`,
},
pe = {
class: `ips-title ipv6-title`,
},
me = {
key: 0,
class: `count`,
},
he = {
class: `col-mono`,
},
ge = {
class: `dlg`,
},
_e = {
class: `form-row`,
},
ve = {
class: `form-row`,
},
ye = {
class: `quote`,
},
be = {
class: `quote-value`,
},
D = {
key: 0,
class: `pi pi-spin pi-spinner`,
},
O = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `MfCloudIps`,
props: {
hostId: {},
module: {
default: `mf_cloud`,
},
upgradeAllowed: {
type: Boolean,
default: !0,
},
},
emits: [`pay`, `addresses`],
setup(h, { emit: b }) {
let O = h,
k = b,
A = useApi(),
j = ref(``),
M = ref([]),
N = ref([]),
P = ref(!1),
F = ref(``),
I = ref(``),
L = 0,
R = 0,
z = 0,
B = !1;
async function V() {
let e = ++L,
t = `/${O.module}/${O.hostId}`;
((P.value = !0), (F.value = ``), (I.value = ``));
async function n(n) {
let r = [],
i = 1;
for (;;) {
let a = await A.get(`${t}/${n}`, {
page: i,
limit: 100,
});
if (B || e !== L) return null;
if (!Array.isArray(a.list)) throw Error(`地址列表无效,请重试`);
if (
(r.push(...a.list),
a.count === void 0
? a.list.length < 100
: r.length >= Number(a.count))
)
return r;
if (!a.list.length) throw Error(`地址列表不完整,请重试`);
i++;
}
}
(await Promise.allSettled([
n(`ip`)
.then((e) => {
e &&
((M.value = e),
k(`addresses`, e.map((e) => e.ip).filter(Boolean)));
})
.catch((t) => {
!B &&
e === L &&
(F.value =
t instanceof Error ? t.message : `IPv4 加载失败`);
}),
...(cloud_instance_management_i(O.module)
? [
n(`ipv6`)
.then((e) => {
e && (N.value = e);
})
.catch((t) => {
!B &&
e === L &&
(I.value =
t instanceof Error ? t.message : `IPv6 加载失败`);
}),
]
: []),
]),
!B && e === L && (P.value = !1));
}
let H = ref(!1),
U = ref(!1),
W = ref(``),
G = reactive({
ip_num: 1,
ipv6_num: 0,
}),
K = ref(``),
q = ref(!1),
J = ref(``),
Y = computed(() =>
JSON.stringify([
O.hostId,
O.module,
O.upgradeAllowed,
H.value,
G,
]),
),
X = computed(
() =>
Number.isInteger(G.ip_num) &&
G.ip_num >= 0 &&
Number.isInteger(G.ipv6_num) &&
G.ipv6_num >= 0 &&
G.ip_num + G.ipv6_num > 0,
),
Z = computed(
() =>
O.upgradeAllowed !== !1 &&
H.value &&
X.value &&
!!J.value &&
J.value === Y.value &&
!q.value &&
!U.value,
);
function Q() {
(R++, (K.value = ``), (J.value = ``), (q.value = !1));
}
watch(Y, Q, {
flush: `sync`,
});
async function xe() {
O.upgradeAllowed !== !1 &&
!U.value &&
cloud_instance_management_i(O.module) &&
((G.ip_num = 1),
(G.ipv6_num = 0),
(W.value = ``),
(H.value = !0),
await $());
}
async function $() {
if ((Q(), O.upgradeAllowed === !1 || !H.value || !X.value)) return;
let e = ++R,
t = Y.value;
((q.value = !0), (W.value = ``));
try {
let n = await A.get(`/${O.module}/${O.hostId}/ip_num`, {
ip_num: G.ip_num,
ipv6_num: G.ipv6_num,
});
if (B || e !== R || t !== Y.value) return;
((K.value = cloud_instance_management_t(n.price)), (J.value = t));
} catch (t) {
!B &&
e === R &&
(W.value = t instanceof Error ? t.message : `询价失败`);
} finally {
!B && e === R && (q.value = !1);
}
}
async function Se() {
if (!Z.value || B) return;
let e = Y.value,
t = K.value,
n = ++z;
((U.value = !0), (W.value = ``), (j.value = ``));
try {
let n = await A.post(`/${O.module}/${O.hostId}/ip_num/order`, {
ip_num: G.ip_num,
ipv6_num: G.ipv6_num,
});
if (B || e !== Y.value) return;
let r = cloud_instance_management_s(n.id);
((H.value = !1),
k(`pay`, {
order_id: r,
amount: t,
}));
} catch (t) {
!B &&
e === Y.value &&
(W.value = t instanceof Error ? t.message : `下单失败`);
} finally {
!B && n === z && (U.value = !1);
}
}
return (
onMounted(V),
watch(
() => [O.hostId, O.module],
() => {
(z++,
(H.value = !1),
(U.value = !1),
(M.value = []),
(N.value = []),
V());
},
),
onBeforeUnmount(() => {
((B = !0), L++, Q());
}),
(t, n) => {
let r = OperationNotice,
a = button,
c = message,
l = column,
v = datatable,
b = inputnumber,
x = dialog;
return (
openBlock(),
createElementBlock(`div`, ce, [
createVNode(
r,
{
message: unref(j),
severity: `error`,
},
null,
8,
[`message`],
),
createElementVNode(`div`, C, [
createElementVNode(`div`, w, [
(n[4] ||= createTextVNode(`IP 列表`, -1)),
unref(M).length
? (openBlock(),
createElementBlock(
`span`,
T,
`(` + toDisplayString(unref(M).length) + `)`,
1,
))
: createCommentVNode(``, !0),
]),
createElementVNode(`div`, E, [
h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(a, {
key: 0,
label: `购买附加 IP`,
icon: `pi pi-plus`,
size: `small`,
onClick: xe,
})),
createVNode(
a,
{
label: `刷新地址`,
icon: `pi pi-refresh`,
size: `small`,
text: ``,
loading: unref(P),
onClick: V,
},
null,
8,
[`loading`],
),
]),
]),
unref(F)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(F)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
v,
{
class: `network-table ipv4-table`,
value: unref(M),
loading: unref(P),
size: `small`,
scrollable: ``,
},
{
empty: withCtx(() => [
...(n[5] ||= [
createElementVNode(
`div`,
{
class: `empty`,
},
`暂无 IP 信息`,
-1,
),
]),
]),
default: withCtx(() => [
createVNode(
l,
{
field: `ip`,
header: `IP 地址`,
style: {
width: `40%`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
le,
toDisplayString(t.ip),
1,
),
]),
_: 1,
},
),
createVNode(
l,
{
field: `subnet_mask`,
header: `子网掩码`,
style: {
width: `30%`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
ue,
toDisplayString(t.subnet_mask || `—`),
1,
),
]),
_: 1,
},
),
createVNode(
l,
{
field: `gateway`,
header: `网关`,
style: {
width: `30%`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
de,
toDisplayString(t.gateway || `—`),
1,
),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`],
),
createElementVNode(`div`, fe, [
createElementVNode(`div`, pe, [
(n[6] ||= createTextVNode(`IPv6 地址`, -1)),
unref(N).length
? (openBlock(),
createElementBlock(
`span`,
me,
`(` + toDisplayString(unref(N).length) + `)`,
1,
))
: createCommentVNode(``, !0),
]),
unref(I)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(I)), 1),
createVNode(a, {
label: `重试`,
text: ``,
size: `small`,
onClick: V,
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
v,
{
class: `network-table ipv6-table`,
"show-headers": !1,
value: unref(N),
loading: unref(P),
size: `small`,
scrollable: ``,
},
{
empty: withCtx(() => [
...(n[7] ||= [
createElementVNode(
`div`,
{
class: `empty`,
},
`暂无 IPv6 地址`,
-1,
),
]),
]),
default: withCtx(() => [
createVNode(
l,
{
field: `ipv6`,
header: `IPv6 地址`,
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
he,
toDisplayString(t.ipv6),
1,
),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`],
),
]),
h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
x,
{
key: 1,
visible: unref(H),
"onUpdate:visible": (n[3] ||= (e) =>
isRef(H) ? (H.value = e) : null),
header: `购买附加 IP`,
modal: ``,
style: {
width: `420px`,
},
draggable: !1,
closable: !unref(U),
"close-on-escape": !unref(U),
},
{
footer: withCtx(() => [
createVNode(
a,
{
label: `取消`,
severity: `secondary`,
text: ``,
disabled: unref(U),
onClick: (n[2] ||= (e) => (H.value = !1)),
},
null,
8,
[`disabled`],
),
createVNode(
a,
{
label: `提交订单`,
loading: unref(U),
disabled: !unref(Z),
onClick: Se,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, ge, [
createElementVNode(`div`, _e, [
(n[8] ||= createElementVNode(
`label`,
null,
`IPv4 数量`,
-1,
)),
createVNode(
b,
{
modelValue: unref(G).ip_num,
"onUpdate:modelValue": [
(n[0] ||= (e) => (unref(G).ip_num = e)),
$,
],
min: 0,
disabled: unref(U),
showButtons: ``,
buttonLayout: `horizontal`,
},
null,
8,
[`modelValue`, `disabled`],
),
]),
createElementVNode(`div`, ve, [
(n[9] ||= createElementVNode(
`label`,
null,
`IPv6 数量`,
-1,
)),
createVNode(
b,
{
modelValue: unref(G).ipv6_num,
"onUpdate:modelValue": [
(n[1] ||= (e) => (unref(G).ipv6_num = e)),
$,
],
min: 0,
disabled: unref(U),
showButtons: ``,
buttonLayout: `horizontal`,
},
null,
8,
[`modelValue`, `disabled`],
),
]),
createElementVNode(`div`, ye, [
(n[10] ||= createElementVNode(
`span`,
null,
`应付金额`,
-1,
)),
createElementVNode(`span`, be, [
unref(q)
? (openBlock(), createElementBlock(`i`, D))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createTextVNode(
toDisplayString(
unref(K) ? `¥${unref(K)}` : `—`,
),
1,
),
],
64,
)),
]),
]),
unref(W)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(W)),
1,
),
createVNode(
a,
{
label: `重新报价`,
text: ``,
size: `small`,
disabled: unref(U),
onClick: $,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
)),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-9ba8a1b3`]],
),
{
__name: `MfCloudIps`,
},
);
export {};
export default O;
</script>
+406
View File
@@ -0,0 +1,406 @@
<script>
import "~/assets/styles/MfCloudLogs.MTqtLGjA.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { watch } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { withModifiers } from "vue";
import { operationMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import iconfield from "primevue/iconfield";
import inputicon from "primevue/inputicon";
import column from "primevue/column";
import ListEmpty from "~/components/ListEmpty.vue";
import { i as instance_data_i } from "~/lib/instance-data.js";
import { l as instance_data_l } from "~/lib/instance-data.js";
import { o as instance_data_o } from "~/lib/instance-data.js";
var N = {
class: `logs`,
},
ee = {
class: `logs-heading`,
},
P = {
class: `log-time`,
},
F = {
class: `log-content`,
},
I = {
key: 2,
class: `logs-foot`,
},
L = {
key: 0,
},
R = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `MfCloudLogs`,
props: {
hostId: {},
module: {
default: `mf_cloud`,
},
},
setup(m) {
let x = m,
R = useApi(),
z = ref(``),
B = ref(``),
V = ref([]),
H = ref(null),
U = ref(1),
W = ref(10),
G = ref(!1),
K = ref(``),
q = 0,
J = computed(() =>
H.value === null
? V.value.length === W.value
: U.value * W.value < H.value,
);
async function Y() {
let e = ++q;
((G.value = !0), (K.value = ``));
try {
let t = await R.get(
`/${x.module}/${x.hostId}/log`,
{
page: U.value,
limit: W.value,
keywords: B.value,
},
!0,
);
if (e !== q) return;
let n = instance_data_l(t);
V.value = instance_data_i(
Array.isArray(t) ? t : (n.list ?? n.logs ?? n.log),
).map(instance_data_o);
let r = Number(n.count ?? n.total);
H.value =
Number.isFinite(r) &&
r >= (U.value - 1) * W.value + V.value.length &&
r < 1e8
? r
: null;
} catch (t) {
if (e !== q) return;
((K.value = t instanceof Error ? t.message : `日志加载失败`),
(V.value = []),
(H.value = null));
} finally {
e === q && (G.value = !1);
}
}
function X() {
return ((U.value = 1), Y());
}
function Z() {
((B.value = z.value.trim()), X());
}
function Q() {
((z.value = ``), (B.value = ``), X());
}
function $(e) {
G.value ||
(e > 0 && !J.value) ||
((U.value = Math.max(1, U.value + e)), Y());
}
return (
watch(
() => [x.hostId, x.module],
() => {
((z.value = ``), (B.value = ``), (V.value = []), X());
},
),
onMounted(Y),
onBeforeUnmount(() => {
q++;
}),
(t, n) => {
let r = button,
a = inputicon,
c = inputtext,
m = iconfield,
y = message,
x = ListEmpty,
A = column,
j = datatable;
return (
openBlock(),
createElementBlock(`section`, N, [
createElementVNode(`div`, ee, [
(n[3] ||= createElementVNode(
`div`,
null,
[
createElementVNode(`h4`, null, `操作日志`),
createElementVNode(
`p`,
null,
`查看实例操作记录与执行时间。`,
),
],
-1,
)),
createVNode(
r,
{
label: `刷新`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
loading: unref(G),
onClick: Y,
},
null,
8,
[`loading`],
),
]),
createElementVNode(
`form`,
{
class: `logs-toolbar`,
onSubmit: withModifiers(Z, [`prevent`]),
},
[
createVNode(m, null, {
default: withCtx(() => [
createVNode(a, {
class: `pi pi-search`,
}),
createVNode(
c,
{
modelValue: unref(z),
"onUpdate:modelValue": (n[0] ||= (e) =>
isRef(z) ? (z.value = e) : null),
placeholder: `搜索操作内容`,
"aria-label": `搜索操作日志`,
},
null,
8,
[`modelValue`],
),
]),
_: 1,
}),
createVNode(
r,
{
type: `submit`,
label: `搜索`,
disabled: unref(G),
},
null,
8,
[`disabled`],
),
unref(B)
? (openBlock(),
createBlock(r, {
key: 0,
label: `清除筛选`,
severity: `secondary`,
text: ``,
onClick: Q,
}))
: createCommentVNode(``, !0),
],
32,
),
unref(K)
? (openBlock(),
createBlock(
y,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(K)), 1),
createVNode(r, {
label: `重试`,
severity: `secondary`,
text: ``,
onClick: Y,
}),
]),
_: 1,
},
))
: (openBlock(),
createBlock(
j,
{
key: 1,
value: unref(V),
loading: unref(G),
dataKey: `id`,
size: `small`,
scrollable: ``,
class: `logs-table`,
},
{
empty: withCtx(() => [
createVNode(
x,
{
icon: `pi pi-history`,
title: unref(G)
? `正在加载操作日志`
: unref(B)
? `未找到匹配的日志`
: `暂无操作日志`,
description: unref(B)
? `更换关键词或清除筛选后重试`
: `实例产生操作记录后会显示在这里`,
},
null,
8,
[`title`, `description`],
),
]),
default: withCtx(() => [
createVNode(
A,
{
header: `时间`,
style: {
"min-width": `180px`,
width: `22%`,
},
},
{
body: withCtx(({ data: n }) => [
createElementVNode(
`span`,
P,
toDisplayString(
n.create_time
? (`formatTime` in t
? t.formatTime
: unref(dict_r))(n.create_time)
: `—`,
),
1,
),
]),
_: 1,
},
),
createVNode(
A,
{
header: `操作内容`,
style: {
"min-width": `280px`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
F,
toDisplayString(
unref(operationMessage)(t.description),
),
1,
),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`],
)),
unref(U) > 1 || unref(V).length
? (openBlock(),
createElementBlock(`div`, I, [
unref(H) === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`span`,
L,
`共 ` + toDisplayString(unref(H)) + ` 条`,
1,
)),
createVNode(
r,
{
icon: `pi pi-angle-left`,
severity: `secondary`,
outlined: ``,
"aria-label": `上一页`,
disabled: unref(G) || unref(U) <= 1,
onClick: (n[1] ||= (e) => $(-1)),
},
null,
8,
[`disabled`],
),
createElementVNode(
`span`,
null,
`第 ` + toDisplayString(unref(U)) + ` 页`,
1,
),
createVNode(
r,
{
icon: `pi pi-angle-right`,
severity: `secondary`,
outlined: ``,
"aria-label": `下一页`,
disabled: unref(G) || !unref(J),
onClick: (n[2] ||= (e) => $(1)),
},
null,
8,
[`disabled`],
),
]))
: createCommentVNode(``, !0),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-c4521240`]],
),
{
__name: `MfCloudLogs`,
},
);
export {};
export default R;
</script>
Loaded 100 of 687 files, more files were not shown because too many files have changed in this diff. Show more