first commit
This commit is contained in:
commit
db5762abd4
687 files changed
+171307
No files matched your search
@@ -0,0 +1,927 @@
|
||||
<script>
|
||||
import "~/assets/styles/api-keys.Bq3Csr53.css";
|
||||
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 { 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 { withModifiers } from "vue";
|
||||
import { useHead } from "#app";
|
||||
import { onBeforeRouteLeave } from "vue-router";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import datatable from "primevue/datatable";
|
||||
import paginator from "primevue/paginator";
|
||||
import checkbox from "primevue/checkbox";
|
||||
import column from "primevue/column";
|
||||
import textarea from "primevue/textarea";
|
||||
function D() {
|
||||
let e = useApi(),
|
||||
t = ref([]),
|
||||
r = ref(0),
|
||||
a = ref(1),
|
||||
o = ref(!1),
|
||||
s = ref(!1),
|
||||
l = ref(!1),
|
||||
u = ref(!1),
|
||||
d = ref(``),
|
||||
f = ref(``),
|
||||
p = ref(``),
|
||||
m = ref(null),
|
||||
h = ref(null),
|
||||
g = reactive({
|
||||
enabled: !1,
|
||||
ip: ``,
|
||||
}),
|
||||
_ = ref(null),
|
||||
v = !0,
|
||||
y = 0,
|
||||
b = () => {
|
||||
m.value = null;
|
||||
};
|
||||
onBeforeUnmount(() => {
|
||||
((v = !1), y++, b());
|
||||
});
|
||||
async function x() {
|
||||
if (!v) return;
|
||||
let n = ++y;
|
||||
((o.value = !0), (d.value = ``), (u.value = !1));
|
||||
try {
|
||||
let i = await e.get(`/api`, {
|
||||
page: a.value,
|
||||
limit: 20,
|
||||
orderby: `id`,
|
||||
sort: `desc`,
|
||||
});
|
||||
if (!v || n !== y) return;
|
||||
if (!Array.isArray(i?.list)) throw Error(`密钥列表响应异常,请重试`);
|
||||
((t.value = i.list),
|
||||
(r.value = Number(i.count) || 0),
|
||||
(u.value = Number(i.create_api) === 1),
|
||||
(l.value = !0));
|
||||
} catch (e) {
|
||||
v &&
|
||||
n === y &&
|
||||
((d.value = e instanceof Error ? e.message : `加载失败`),
|
||||
(l.value = !1));
|
||||
} finally {
|
||||
v && n === y && (o.value = !1);
|
||||
}
|
||||
}
|
||||
async function C() {
|
||||
if (!(!v || s.value || m.value)) {
|
||||
if (((d.value = ``), (f.value = ``), !l.value || o.value)) {
|
||||
d.value = `权限尚未加载,请刷新列表`;
|
||||
return;
|
||||
}
|
||||
if (!u.value) {
|
||||
d.value = `当前账户暂未开放 API 密钥创建`;
|
||||
return;
|
||||
}
|
||||
if (!p.value.trim()) {
|
||||
d.value = `请填写密钥名称`;
|
||||
return;
|
||||
}
|
||||
s.value = !0;
|
||||
try {
|
||||
let t = await e.post(`/api`, {
|
||||
name: p.value.trim(),
|
||||
});
|
||||
if (!v) return;
|
||||
if (!t?.private_key || !t?.token)
|
||||
throw Error(
|
||||
`服务端未返回完整密钥,请刷新列表核实创建结果,避免重复创建`,
|
||||
);
|
||||
((m.value = t),
|
||||
(p.value = ``),
|
||||
(f.value = `密钥已创建,请立即保存私钥。关闭后无法再次查看。`),
|
||||
(a.value = 1),
|
||||
await x());
|
||||
} catch (e) {
|
||||
v &&
|
||||
(d.value = `${e instanceof Error ? e.message : `创建失败`}。请先刷新列表核实结果,再决定是否重试。`);
|
||||
} finally {
|
||||
v && (s.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
function w(e) {
|
||||
s.value ||
|
||||
((d.value = ``),
|
||||
(f.value = ``),
|
||||
(h.value = e.id),
|
||||
(g.enabled = Number(e.status) === 1),
|
||||
(g.ip = e.ip || ``));
|
||||
}
|
||||
async function T() {
|
||||
if (!v || s.value || !h.value) return;
|
||||
if (((d.value = ``), (f.value = ``), g.enabled && !g.ip.trim())) {
|
||||
d.value = `开启白名单时请填写 IP 地址`;
|
||||
return;
|
||||
}
|
||||
let t = h.value;
|
||||
s.value = !0;
|
||||
try {
|
||||
if (
|
||||
(await e.put(`/api/${t}/white_list`, {
|
||||
status: +!!g.enabled,
|
||||
ip: g.ip.trim(),
|
||||
}),
|
||||
!v)
|
||||
)
|
||||
return;
|
||||
((h.value = null), (f.value = `白名单设置已保存`), await x());
|
||||
} catch (e) {
|
||||
v && (d.value = e instanceof Error ? e.message : `保存失败`);
|
||||
} finally {
|
||||
v && (s.value = !1);
|
||||
}
|
||||
}
|
||||
async function E() {
|
||||
if (v && !s.value && _.value?.id) {
|
||||
((d.value = ``), (f.value = ``), (s.value = !0));
|
||||
try {
|
||||
if ((await e.del(`/api/${_.value.id}`), !v)) return;
|
||||
((_.value = null),
|
||||
(f.value = `密钥已删除`),
|
||||
t.value.length === 1 && a.value > 1 && a.value--,
|
||||
await x());
|
||||
} catch (e) {
|
||||
v && (d.value = e instanceof Error ? e.message : `删除失败`);
|
||||
} finally {
|
||||
v && (s.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
rows: t,
|
||||
count: r,
|
||||
page: a,
|
||||
limit: 20,
|
||||
loading: o,
|
||||
busy: s,
|
||||
loaded: l,
|
||||
createAllowed: u,
|
||||
error: d,
|
||||
success: f,
|
||||
name: p,
|
||||
secret: m,
|
||||
clearSecret: b,
|
||||
whitelistId: h,
|
||||
whitelist: g,
|
||||
deleteTarget: _,
|
||||
load: x,
|
||||
create: C,
|
||||
editWhitelist: w,
|
||||
saveWhitelist: T,
|
||||
remove: E,
|
||||
};
|
||||
}
|
||||
var O = {
|
||||
class: `api-page account-management-page`,
|
||||
},
|
||||
k = {
|
||||
class: `account-management-head`,
|
||||
},
|
||||
A = {
|
||||
class: `account-management-actions`,
|
||||
},
|
||||
j = {
|
||||
class: `create-key-field`,
|
||||
},
|
||||
oe = {
|
||||
key: 2,
|
||||
class: `muted`,
|
||||
},
|
||||
se = {
|
||||
class: `list-table`,
|
||||
},
|
||||
ce = {
|
||||
class: `token`,
|
||||
},
|
||||
le = {
|
||||
class: `row-actions`,
|
||||
},
|
||||
ue = {
|
||||
class: `token`,
|
||||
},
|
||||
de = {
|
||||
key: 0,
|
||||
},
|
||||
M = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `api-keys`,
|
||||
setup(n) {
|
||||
useHead({
|
||||
title: `API 密钥`,
|
||||
});
|
||||
let {
|
||||
rows: c,
|
||||
count: h,
|
||||
page: S,
|
||||
limit: T,
|
||||
loading: M,
|
||||
busy: N,
|
||||
loaded: P,
|
||||
createAllowed: F,
|
||||
error: I,
|
||||
success: L,
|
||||
name: R,
|
||||
secret: z,
|
||||
clearSecret: B,
|
||||
whitelistId: V,
|
||||
whitelist: H,
|
||||
deleteTarget: U,
|
||||
load: W,
|
||||
create: G,
|
||||
editWhitelist: fe,
|
||||
saveWhitelist: K,
|
||||
remove: pe,
|
||||
} = D(),
|
||||
q = ref(!1),
|
||||
J = ref(``),
|
||||
me = computed(() => !!z.value),
|
||||
Y = computed({
|
||||
get: () => V.value !== null,
|
||||
set: (e) => {
|
||||
!e && !N.value && (V.value = null);
|
||||
},
|
||||
}),
|
||||
X = computed({
|
||||
get: () => !!U.value,
|
||||
set: (e) => {
|
||||
!e && !N.value && (U.value = null);
|
||||
},
|
||||
});
|
||||
async function he() {
|
||||
if (z.value) {
|
||||
J.value = ``;
|
||||
try {
|
||||
(await navigator.clipboard.writeText(z.value.private_key),
|
||||
(q.value = !0));
|
||||
} catch {
|
||||
J.value = `复制失败,请手动选择并复制私钥`;
|
||||
}
|
||||
}
|
||||
}
|
||||
function Z() {
|
||||
(B(), (q.value = !1), (J.value = ``));
|
||||
}
|
||||
function ge(e) {
|
||||
((S.value = e.page + 1), W());
|
||||
}
|
||||
let _e = (e) => (e ? new Date(e * 1e3).toLocaleString(`zh-CN`) : `—`);
|
||||
return (
|
||||
onMounted(W),
|
||||
onBeforeRouteLeave(
|
||||
() =>
|
||||
!z.value ||
|
||||
window.confirm(
|
||||
`私钥仅显示一次,请确认已保存后离开。离开后将无法再次查看。`,
|
||||
),
|
||||
),
|
||||
(t, n) => {
|
||||
let i = NuxtLink,
|
||||
s = button,
|
||||
y = message,
|
||||
b = inputtext,
|
||||
D = column,
|
||||
B = datatable,
|
||||
V = paginator,
|
||||
Q = textarea,
|
||||
$ = dialog,
|
||||
ve = checkbox;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`section`, O, [
|
||||
createElementVNode(`header`, k, [
|
||||
createElementVNode(`div`, null, [
|
||||
(n[10] ||= createElementVNode(`h2`, null, `API 密钥`, -1)),
|
||||
createElementVNode(`p`, null, [
|
||||
(n[9] ||= createTextVNode(
|
||||
`管理程序访问凭证及 IP 白名单。`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: `/logbook?type=api`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[8] ||= [
|
||||
createTextVNode(`查看 API 日志`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, A, [
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: `/account`,
|
||||
class: `account-management-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[11] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-angle-left`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`账户设置`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `刷新`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
loading: unref(M),
|
||||
disabled: unref(N),
|
||||
onClick: unref(W),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`, `onClick`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(I)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(I)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(L)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 1,
|
||||
severity: `success`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(L)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
class: `create-key`,
|
||||
onSubmit: (n[1] ||= withModifiers(
|
||||
(...e) => unref(G) && unref(G)(...e),
|
||||
[`prevent`],
|
||||
)),
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, j, [
|
||||
(n[12] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `api-name`,
|
||||
},
|
||||
`密钥名称`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
b,
|
||||
{
|
||||
id: `api-name`,
|
||||
modelValue: unref(R),
|
||||
"onUpdate:modelValue": (n[0] ||= (e) =>
|
||||
isRef(R) ? (R.value = e) : null),
|
||||
maxlength: `100`,
|
||||
placeholder: `例如:自动化管理`,
|
||||
disabled: unref(N) || !unref(F),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
]),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `创建密钥`,
|
||||
loading: unref(N),
|
||||
disabled:
|
||||
!unref(P) || !unref(F) || unref(M) || !!unref(z),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
],
|
||||
32,
|
||||
),
|
||||
unref(P) && !unref(F)
|
||||
? (openBlock(),
|
||||
createElementBlock(`p`, oe, `当前账户暂未开放创建密钥。`))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, se, [
|
||||
createVNode(
|
||||
B,
|
||||
{
|
||||
value: unref(c),
|
||||
loading: unref(M),
|
||||
"data-key": `id`,
|
||||
scrollable: ``,
|
||||
},
|
||||
{
|
||||
empty: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
unref(P)
|
||||
? `暂无 API 密钥`
|
||||
: `尚未加载密钥,请刷新重试`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createVNode(D, {
|
||||
field: `name`,
|
||||
header: `名称`,
|
||||
}),
|
||||
createVNode(
|
||||
D,
|
||||
{
|
||||
field: `token`,
|
||||
header: `Token`,
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createElementVNode(
|
||||
`code`,
|
||||
ce,
|
||||
toDisplayString(t.token),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
D,
|
||||
{
|
||||
header: `创建时间`,
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(_e(t.create_time)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
D,
|
||||
{
|
||||
header: `IP 白名单`,
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
Number(t.status) === 1 ? t.ip : `未开启`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
D,
|
||||
{
|
||||
header: `操作`,
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: e }) => [
|
||||
createElementVNode(`div`, le, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `白名单`,
|
||||
text: ``,
|
||||
disabled: unref(N),
|
||||
onClick: (t) => unref(fe)(e),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`, `onClick`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `删除`,
|
||||
severity: `danger`,
|
||||
text: ``,
|
||||
disabled: unref(N),
|
||||
onClick: (t) => (U.value = e),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`, `onClick`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`value`, `loading`],
|
||||
),
|
||||
]),
|
||||
unref(h) > unref(T)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
V,
|
||||
{
|
||||
key: 3,
|
||||
first: (unref(S) - 1) * unref(T),
|
||||
rows: unref(T),
|
||||
"total-records": unref(h),
|
||||
onPage: ge,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`first`, `rows`, `total-records`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
$,
|
||||
{
|
||||
visible: unref(me),
|
||||
header: `保存新私钥`,
|
||||
modal: ``,
|
||||
closable: !1,
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `600px`,
|
||||
maxWidth: `94vw`,
|
||||
},
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: unref(q) ? `已复制` : `复制私钥`,
|
||||
severity: `secondary`,
|
||||
onClick: he,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`],
|
||||
),
|
||||
createVNode(s, {
|
||||
label: `已安全保存,关闭`,
|
||||
onClick: Z,
|
||||
}),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
(n[16] ||= createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`私钥仅显示一次。请保存到安全位置后关闭此窗口。`,
|
||||
-1,
|
||||
)),
|
||||
unref(z)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 0,
|
||||
},
|
||||
[
|
||||
createElementVNode(`p`, null, [
|
||||
(n[13] ||= createElementVNode(
|
||||
`strong`,
|
||||
null,
|
||||
`Token:`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`code`,
|
||||
ue,
|
||||
toDisplayString(unref(z).token),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
unref(z).api_url
|
||||
? (openBlock(),
|
||||
createElementBlock(`p`, de, [
|
||||
(n[14] ||= createElementVNode(
|
||||
`strong`,
|
||||
null,
|
||||
`API 地址:`,
|
||||
-1,
|
||||
)),
|
||||
createTextVNode(
|
||||
toDisplayString(unref(z).api_url),
|
||||
1,
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
(n[15] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `private-key`,
|
||||
},
|
||||
`私钥`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
Q,
|
||||
{
|
||||
id: `private-key`,
|
||||
"model-value": unref(z).private_key,
|
||||
readonly: ``,
|
||||
rows: `8`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`model-value`],
|
||||
),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(J)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(J)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`],
|
||||
),
|
||||
createVNode(
|
||||
$,
|
||||
{
|
||||
visible: unref(Y),
|
||||
"onUpdate:visible": (n[5] ||= (e) =>
|
||||
isRef(Y) ? (Y.value = e) : null),
|
||||
header: `API 白名单`,
|
||||
modal: ``,
|
||||
closable: !unref(N),
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `480px`,
|
||||
maxWidth: `94vw`,
|
||||
},
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
class: `whitelist-form`,
|
||||
onSubmit: (n[4] ||= withModifiers(
|
||||
(...e) => unref(K) && unref(K)(...e),
|
||||
[`prevent`],
|
||||
)),
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, null, [
|
||||
createVNode(
|
||||
ve,
|
||||
{
|
||||
modelValue: unref(H).enabled,
|
||||
"onUpdate:modelValue": (n[2] ||= (e) =>
|
||||
(unref(H).enabled = e)),
|
||||
"input-id": `api-whitelist-on`,
|
||||
binary: ``,
|
||||
disabled: unref(N),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
(n[17] ||= createTextVNode()),
|
||||
(n[18] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `api-whitelist-on`,
|
||||
},
|
||||
`启用 IP 白名单`,
|
||||
-1,
|
||||
)),
|
||||
]),
|
||||
(n[19] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `api-whitelist-ip`,
|
||||
},
|
||||
`允许访问的 IP 地址`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
Q,
|
||||
{
|
||||
id: `api-whitelist-ip`,
|
||||
modelValue: unref(H).ip,
|
||||
"onUpdate:modelValue": (n[3] ||= (e) =>
|
||||
(unref(H).ip = e)),
|
||||
disabled: unref(N) || !unref(H).enabled,
|
||||
rows: `4`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
unref(I)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(I)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `保存`,
|
||||
loading: unref(N),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
],
|
||||
32,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `closable`],
|
||||
),
|
||||
createVNode(
|
||||
$,
|
||||
{
|
||||
visible: unref(X),
|
||||
"onUpdate:visible": (n[7] ||= (e) =>
|
||||
isRef(X) ? (X.value = e) : null),
|
||||
header: `删除 API 密钥`,
|
||||
modal: ``,
|
||||
closable: !unref(N),
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `450px`,
|
||||
maxWidth: `94vw`,
|
||||
},
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `取消`,
|
||||
severity: `secondary`,
|
||||
disabled: unref(N),
|
||||
onClick: (n[6] ||= (e) => (U.value = null)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `确认删除`,
|
||||
severity: `danger`,
|
||||
loading: unref(N),
|
||||
onClick: unref(pe),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `onClick`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`确认删除「` +
|
||||
toDisplayString(unref(U)?.name) +
|
||||
`」?使用此密钥的程序将立即失去访问权限。`,
|
||||
1,
|
||||
),
|
||||
unref(I)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(I)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `closable`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-76e29360`]],
|
||||
);
|
||||
export {};
|
||||
export default M;
|
||||
</script>
|
||||
@@ -0,0 +1,407 @@
|
||||
<script>
|
||||
import "~/assets/styles/WechatConnection.DI5ko1xy.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 { 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 { NuxtLink } from "#components";
|
||||
import { useApi } from "~/lib/auth.js";
|
||||
import dialog from "primevue/dialog";
|
||||
import button from "primevue/button";
|
||||
import message from "primevue/message";
|
||||
import { t as oauth_t } from "~/lib/oauth.js";
|
||||
import { t as useOAuth_t } from "~/lib/useOAuth.js";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import WechatConnection from "~/components/WechatConnection.vue";
|
||||
var D = {
|
||||
class: `account-management-page`,
|
||||
},
|
||||
O = {
|
||||
class: `account-management-head`,
|
||||
},
|
||||
k = {
|
||||
class: `account-management-actions`,
|
||||
},
|
||||
A = {
|
||||
"aria-label": `其他登录方式`,
|
||||
},
|
||||
j = {
|
||||
key: 0,
|
||||
class: `connection-list`,
|
||||
},
|
||||
M = {
|
||||
key: 1,
|
||||
class: `account-management-note`,
|
||||
},
|
||||
N = {
|
||||
key: 2,
|
||||
class: `connection-list`,
|
||||
},
|
||||
P = [`src`],
|
||||
F = {
|
||||
class: `connection-provider-main`,
|
||||
},
|
||||
I = defineComponent({
|
||||
__name: `connections`,
|
||||
setup(h) {
|
||||
let I = useApi(),
|
||||
L = ref([]),
|
||||
R = ref(!1),
|
||||
z = ref(``),
|
||||
B = ref(``),
|
||||
V = ref(!1),
|
||||
H = ref(!1),
|
||||
U = ref(null),
|
||||
{ busy: W, error: G, start: K } = useOAuth_t(),
|
||||
q = computed({
|
||||
get: () => !!U.value,
|
||||
set: (e) => {
|
||||
!e && !H.value && (U.value = null);
|
||||
},
|
||||
}),
|
||||
J = !0;
|
||||
onBeforeUnmount(() => {
|
||||
J = !1;
|
||||
});
|
||||
async function Y() {
|
||||
if (!R.value) {
|
||||
((R.value = !0), (z.value = ``));
|
||||
try {
|
||||
let e = await I.get(`/account`);
|
||||
if (!J) return;
|
||||
((L.value = oauth_t(e.account?.oauth)), (V.value = !0));
|
||||
} catch (e) {
|
||||
J && (z.value = e instanceof Error ? e.message : `加载失败`);
|
||||
} finally {
|
||||
J && (R.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
async function X() {
|
||||
if (U.value?.linked && !H.value && !W.value && J) {
|
||||
((H.value = !0), (z.value = ``), (B.value = ``));
|
||||
try {
|
||||
if (
|
||||
(await I.post(
|
||||
`/oauth/unbind/${encodeURIComponent(U.value.name)}`,
|
||||
),
|
||||
!J)
|
||||
)
|
||||
return;
|
||||
((U.value = null), (B.value = `已取消关联`), await Y());
|
||||
} catch (e) {
|
||||
J && (z.value = e instanceof Error ? e.message : `取消关联失败`);
|
||||
} finally {
|
||||
J && (H.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(Y),
|
||||
(n, r) => {
|
||||
let a = NuxtLink,
|
||||
c = button,
|
||||
h = message,
|
||||
y = WechatConnection,
|
||||
C = skeleton,
|
||||
w = dialog;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, D, [
|
||||
createElementVNode(`header`, O, [
|
||||
(r[3] ||= createElementVNode(
|
||||
`div`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`h2`, null, `关联账号`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`管理第三方登录方式与微信通知。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, k, [
|
||||
createVNode(
|
||||
a,
|
||||
{
|
||||
to: `/account`,
|
||||
class: `account-management-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(r[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-angle-left`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`账户设置`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
label: `刷新`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
loading: unref(R),
|
||||
disabled: unref(H) || unref(W),
|
||||
onClick: Y,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(z) || unref(G)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(z) || unref(G)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 1,
|
||||
severity: `success`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(B)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(y),
|
||||
createElementVNode(`section`, A, [
|
||||
(r[4] ||= createElementVNode(
|
||||
`h3`,
|
||||
{
|
||||
class: `connection-section-title`,
|
||||
},
|
||||
`其他登录方式`,
|
||||
-1,
|
||||
)),
|
||||
unref(R) && !unref(V)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createVNode(C, {
|
||||
height: `60px`,
|
||||
}),
|
||||
]))
|
||||
: unref(V) && !unref(L).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`p`, M, `暂无其他第三方登录方式。`))
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, N, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(L),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: t.name,
|
||||
class: `connection-provider`,
|
||||
},
|
||||
[
|
||||
t.image
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`img`,
|
||||
{
|
||||
key: 0,
|
||||
src: t.image,
|
||||
alt: ``,
|
||||
referrerpolicy: `no-referrer`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
P,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, F, [
|
||||
createElementVNode(
|
||||
`strong`,
|
||||
null,
|
||||
toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
toDisplayString(
|
||||
t.linked ? `已关联` : `未关联`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
t.linked
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
c,
|
||||
{
|
||||
key: 1,
|
||||
label: `取消关联`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
disabled:
|
||||
unref(H) || unref(W) || unref(R),
|
||||
onClick: (e) => (U.value = t),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`, `onClick`],
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
c,
|
||||
{
|
||||
key: 2,
|
||||
label: `关联账号`,
|
||||
disabled:
|
||||
unref(H) || unref(W) || unref(R),
|
||||
onClick: (e) => unref(K)(t.name),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`, `onClick`],
|
||||
)),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
])),
|
||||
]),
|
||||
createVNode(
|
||||
w,
|
||||
{
|
||||
visible: unref(q),
|
||||
"onUpdate:visible": (r[1] ||= (e) =>
|
||||
isRef(q) ? (q.value = e) : null),
|
||||
header: `取消关联`,
|
||||
modal: ``,
|
||||
closable: !unref(H),
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `450px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
label: `保留关联`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
disabled: unref(H),
|
||||
onClick: (r[0] ||= (e) => (U.value = null)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
label: `确认取消关联`,
|
||||
severity: `danger`,
|
||||
loading: unref(H),
|
||||
onClick: X,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`确认取消与 ` +
|
||||
toDisplayString(unref(U)?.title) +
|
||||
` 的关联?之后将无法使用该方式登录。请先确认手机号或邮箱登录可用。`,
|
||||
1,
|
||||
),
|
||||
unref(z)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(z)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `closable`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default I;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import "~/assets/styles/UploadField.BbTCTv6C.css";
|
||||
import "~/assets/styles/PageSteps.B5K7G9zF.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/realname.BpRCvfXO.css";
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import index from "~/pages/account/realname/index.vue";
|
||||
var i = defineComponent({
|
||||
__name: `company`,
|
||||
setup(t) {
|
||||
return (t, i) => (
|
||||
openBlock(),
|
||||
createBlock(index, {
|
||||
"initial-type": `company`,
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import "~/assets/styles/UploadField.BbTCTv6C.css";
|
||||
import "~/assets/styles/PageSteps.B5K7G9zF.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/realname.BpRCvfXO.css";
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import index from "~/pages/account/realname/index.vue";
|
||||
var i = defineComponent({
|
||||
__name: `personal`,
|
||||
setup(t) {
|
||||
return (t, i) => (
|
||||
openBlock(),
|
||||
createBlock(index, {
|
||||
"initial-type": `person`,
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/_id_.gjoJy9S8.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import _id_ from "~/pages/orders/[id].vue";
|
||||
var a = defineComponent({
|
||||
__name: `[id]`,
|
||||
setup(t) {
|
||||
return (
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
}),
|
||||
(t, r) => (openBlock(), createBlock(_id_))
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default a;
|
||||
</script>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script>
|
||||
definePageMeta({
|
||||
redirect: {
|
||||
redirect: (e) => ({
|
||||
path: `/finance`,
|
||||
query: {
|
||||
...e.query,
|
||||
tab: `bills`,
|
||||
},
|
||||
hash: e.hash,
|
||||
}),
|
||||
}.redirect,
|
||||
});
|
||||
import { createElementBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var i = defineComponent({
|
||||
__name: `index`,
|
||||
setup(t) {
|
||||
return (
|
||||
composables_t({
|
||||
redirect: (e) => ({
|
||||
path: `/finance`,
|
||||
query: {
|
||||
...e.query,
|
||||
tab: `bills`,
|
||||
},
|
||||
hash: e.hash,
|
||||
}),
|
||||
}),
|
||||
(t, r) => (openBlock(), createElementBlock(`div`))
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,92 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||||
import "~/assets/styles/HostList.B3U15sJm.css";
|
||||
import { createBlock } from "vue";
|
||||
import { withCtx } from "vue";
|
||||
import { computed } 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 { NuxtLink } from "#components";
|
||||
import button from "primevue/button";
|
||||
import message from "primevue/message";
|
||||
import { t as modules_t } from "~/lib/modules.js";
|
||||
import HostList from "~/components/HostList.vue";
|
||||
var m = defineComponent({
|
||||
__name: `index`,
|
||||
setup(a) {
|
||||
let m = useRoute(),
|
||||
h = computed(() =>
|
||||
/^\d+$/.test(String(m.query.m ?? ``)) &&
|
||||
Number.isSafeInteger(Number(m.query.m)) &&
|
||||
Number(m.query.m) > 0
|
||||
? Number(m.query.m)
|
||||
: void 0,
|
||||
);
|
||||
return (n, a) => {
|
||||
let c = message,
|
||||
g = button,
|
||||
_ = NuxtLink,
|
||||
v = HostList;
|
||||
return unref(m).query.m !== void 0 && !unref(h)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
c,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[0] ||= [createTextVNode(`服务器导航参数无效`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: unref(h) ?? `default`,
|
||||
"menu-id": unref(h),
|
||||
modules: (`SERVER_MODULE_GROUPS` in n
|
||||
? n.SERVER_MODULE_GROUPS
|
||||
: unref(modules_t)
|
||||
).cloud,
|
||||
title: `云服务器`,
|
||||
description: `管理你的云服务器实例`,
|
||||
},
|
||||
{
|
||||
actions: withCtx(() => [
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
to: `/products`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(g, {
|
||||
label: `订购云服务器`,
|
||||
icon: `pi pi-plus`,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`menu-id`, `modules`],
|
||||
));
|
||||
};
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default m;
|
||||
</script>
|
||||
@@ -0,0 +1,92 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||||
import "~/assets/styles/HostList.B3U15sJm.css";
|
||||
import { createBlock } from "vue";
|
||||
import { withCtx } from "vue";
|
||||
import { computed } 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 { NuxtLink } from "#components";
|
||||
import button from "primevue/button";
|
||||
import message from "primevue/message";
|
||||
import { t as modules_t } from "~/lib/modules.js";
|
||||
import HostList from "~/components/HostList.vue";
|
||||
var m = defineComponent({
|
||||
__name: `index`,
|
||||
setup(a) {
|
||||
let m = useRoute(),
|
||||
h = computed(() =>
|
||||
/^\d+$/.test(String(m.query.m ?? ``)) &&
|
||||
Number.isSafeInteger(Number(m.query.m)) &&
|
||||
Number(m.query.m) > 0
|
||||
? Number(m.query.m)
|
||||
: void 0,
|
||||
);
|
||||
return (n, a) => {
|
||||
let c = message,
|
||||
g = button,
|
||||
_ = NuxtLink,
|
||||
v = HostList;
|
||||
return unref(m).query.m !== void 0 && !unref(h)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
c,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[0] ||= [createTextVNode(`服务器导航参数无效`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: unref(h) ?? `default`,
|
||||
"menu-id": unref(h),
|
||||
modules: (`SERVER_MODULE_GROUPS` in n
|
||||
? n.SERVER_MODULE_GROUPS
|
||||
: unref(modules_t)
|
||||
).dcim,
|
||||
title: `物理服务器`,
|
||||
description: `管理你的物理服务器(裸金属)`,
|
||||
},
|
||||
{
|
||||
actions: withCtx(() => [
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
to: `/products`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(g, {
|
||||
label: `订购物理服务器`,
|
||||
icon: `pi pi-plus`,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`menu-id`, `modules`],
|
||||
));
|
||||
};
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default m;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,520 @@
|
||||
<script>
|
||||
import "~/assets/styles/PhoneCodeField.CwyHXfML.css";
|
||||
import "~/assets/styles/GeetestField.DiieTibK.css";
|
||||
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
|
||||
definePageMeta({
|
||||
layout: `blank`,
|
||||
alias: [`/forgot_password`],
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { normalizeClass } from "vue";
|
||||
import { createBlock } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { withCtx } from "vue";
|
||||
import { createCommentVNode } from "vue";
|
||||
import { reactive } 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 { useRoute } from "#app";
|
||||
import { useRouter } from "#app";
|
||||
import { useHead } from "#app";
|
||||
import { NuxtLink } from "#components";
|
||||
import { useApi } from "~/lib/auth.js";
|
||||
import button from "primevue/button";
|
||||
import message from "primevue/message";
|
||||
import { n as auth_redirect_n } from "~/lib/auth-redirect.js";
|
||||
import { t as auth_redirect_t } from "~/lib/auth-redirect.js";
|
||||
import inputtext from "primevue/inputtext";
|
||||
import CaptchaField from "~/components/CaptchaField.vue";
|
||||
import password from "primevue/password";
|
||||
import PhoneCodeField from "~/components/PhoneCodeField.vue";
|
||||
import { t as useCaptcha_t } from "~/lib/useCaptcha.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as useVerifyCode_t } from "~/lib/useVerifyCode.js";
|
||||
var D = {
|
||||
class: `auth-card login-card`,
|
||||
},
|
||||
O = {
|
||||
class: `field`,
|
||||
},
|
||||
k = {
|
||||
class: `seg`,
|
||||
role: `group`,
|
||||
"aria-labelledby": `recovery-method-label`,
|
||||
},
|
||||
A = [`aria-pressed`, `disabled`],
|
||||
j = [`aria-pressed`, `disabled`],
|
||||
M = {
|
||||
class: `field`,
|
||||
},
|
||||
N = {
|
||||
for: `account`,
|
||||
},
|
||||
P = {
|
||||
class: `field`,
|
||||
},
|
||||
F = {
|
||||
class: `code-row`,
|
||||
},
|
||||
I = {
|
||||
class: `field`,
|
||||
},
|
||||
L = {
|
||||
class: `field`,
|
||||
},
|
||||
R = {
|
||||
class: `login-links center`,
|
||||
},
|
||||
z = defineComponent({
|
||||
__name: `forgot-password`,
|
||||
setup(f) {
|
||||
(useHead({
|
||||
title: `找回密码 - 破碎工坊网络`,
|
||||
}),
|
||||
composables_t({
|
||||
layout: `blank`,
|
||||
alias: `/forgot_password`,
|
||||
}));
|
||||
let z = useApi(),
|
||||
B = useRouter(),
|
||||
V = useRoute(),
|
||||
H = ref(`phone`),
|
||||
U = reactive({
|
||||
account: ``,
|
||||
code: ``,
|
||||
password: ``,
|
||||
re_password: ``,
|
||||
phone_code: `86`,
|
||||
}),
|
||||
W = ref(``),
|
||||
G = ref(!1),
|
||||
K = useCaptcha_t(`password_reset`),
|
||||
{
|
||||
needed: q,
|
||||
provider: J,
|
||||
captchaId: Y,
|
||||
complete: ae,
|
||||
invalidate: oe,
|
||||
img: se,
|
||||
value: X,
|
||||
loading: ce,
|
||||
error: Z,
|
||||
load: le,
|
||||
handleError: ue,
|
||||
} = K,
|
||||
{
|
||||
sending: Q,
|
||||
countdown: $,
|
||||
send: de,
|
||||
} = useVerifyCode_t({
|
||||
action: `password_reset`,
|
||||
captcha: K,
|
||||
error: W,
|
||||
phoneCode: () => U.phone_code,
|
||||
});
|
||||
function fe() {
|
||||
if (G.value) return;
|
||||
let e = U.account.trim();
|
||||
return de(
|
||||
H.value,
|
||||
e,
|
||||
H.value === `email` ? `请输入邮箱` : `请输入手机号`,
|
||||
);
|
||||
}
|
||||
async function pe() {
|
||||
if (G.value || Q.value) return;
|
||||
W.value = ``;
|
||||
let e = U.account.trim();
|
||||
if (!e)
|
||||
return (W.value =
|
||||
H.value === `email` ? `请输入邮箱` : `请输入手机号`);
|
||||
if (H.value === `phone` && !/^[1-9]\d{0,3}$/.test(U.phone_code))
|
||||
return (W.value = `请输入有效的国际电话区号`);
|
||||
if (!U.code.trim()) return (W.value = `请输入验证码`);
|
||||
if (!U.password) return (W.value = `请输入新密码`);
|
||||
if (U.password !== U.re_password)
|
||||
return (W.value = `两次输入的密码不一致`);
|
||||
G.value = !0;
|
||||
try {
|
||||
(await z.post(`/account/password_reset`, {
|
||||
type: H.value,
|
||||
account: e,
|
||||
phone_code: U.phone_code,
|
||||
code: U.code.trim(),
|
||||
password: U.password,
|
||||
re_password: U.re_password,
|
||||
}),
|
||||
await B.push({
|
||||
path: `/login`,
|
||||
query: {
|
||||
reset: `1`,
|
||||
...auth_redirect_n(V.query.redirect),
|
||||
},
|
||||
}));
|
||||
} catch (e) {
|
||||
((W.value = e instanceof Error ? e.message : `重置失败`),
|
||||
await ue(e));
|
||||
} finally {
|
||||
G.value = !1;
|
||||
}
|
||||
}
|
||||
return (r, o) => {
|
||||
let f = PhoneCodeField,
|
||||
h = inputtext,
|
||||
g = button,
|
||||
_ = CaptchaField,
|
||||
y = password,
|
||||
b = message,
|
||||
T = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, D, [
|
||||
(o[13] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `login-brand`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`h1`, null, `找回密码`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`通过注册手机号或邮箱验证身份,设置新密码。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
class: `login-form`,
|
||||
onSubmit: withModifiers(pe, [`prevent`]),
|
||||
},
|
||||
[
|
||||
unref(H) === `phone`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
f,
|
||||
{
|
||||
key: 0,
|
||||
modelValue: unref(U).phone_code,
|
||||
"onUpdate:modelValue": (o[0] ||= (e) =>
|
||||
(unref(U).phone_code = e)),
|
||||
disabled: unref(G) || unref(Q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, O, [
|
||||
(o[8] ||= createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
id: `recovery-method-label`,
|
||||
class: `method-label`,
|
||||
},
|
||||
`找回方式`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, k, [
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(H) === `phone`,
|
||||
}),
|
||||
"aria-pressed": unref(H) === `phone`,
|
||||
disabled: unref(G) || unref(Q),
|
||||
onClick: (o[1] ||= (e) => (H.value = `phone`)),
|
||||
},
|
||||
` 手机号 `,
|
||||
10,
|
||||
A,
|
||||
),
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(H) === `email`,
|
||||
}),
|
||||
"aria-pressed": unref(H) === `email`,
|
||||
disabled: unref(G) || unref(Q),
|
||||
onClick: (o[2] ||= (e) => (H.value = `email`)),
|
||||
},
|
||||
` 邮箱 `,
|
||||
10,
|
||||
j,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, M, [
|
||||
createElementVNode(
|
||||
`label`,
|
||||
N,
|
||||
toDisplayString(unref(H) === `email` ? `邮箱` : `手机号`),
|
||||
1,
|
||||
),
|
||||
createVNode(
|
||||
h,
|
||||
{
|
||||
id: `account`,
|
||||
modelValue: unref(U).account,
|
||||
"onUpdate:modelValue": (o[3] ||= (e) =>
|
||||
(unref(U).account = e)),
|
||||
placeholder:
|
||||
unref(H) === `email`
|
||||
? `请输入注册邮箱`
|
||||
: `请输入注册手机号`,
|
||||
autocomplete: `username`,
|
||||
disabled: unref(G) || unref(Q),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `placeholder`, `disabled`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, P, [
|
||||
(o[9] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `code`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`验证码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, F, [
|
||||
createVNode(
|
||||
h,
|
||||
{
|
||||
id: `code`,
|
||||
modelValue: unref(U).code,
|
||||
"onUpdate:modelValue": (o[4] ||= (e) =>
|
||||
(unref(U).code = e)),
|
||||
placeholder: `请输入验证码`,
|
||||
autocomplete: `one-time-code`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
type: `button`,
|
||||
label: unref($) > 0 ? `${unref($)}s` : `获取验证码`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
loading: unref(Q),
|
||||
disabled: unref($) > 0 || unref(G),
|
||||
onClick: fe,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`, `loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(q)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
_,
|
||||
{
|
||||
key: 1,
|
||||
modelValue: unref(X),
|
||||
"onUpdate:modelValue": (o[5] ||= (e) =>
|
||||
isRef(X) ? (X.value = e) : null),
|
||||
img: unref(se),
|
||||
provider: unref(J),
|
||||
"captcha-id": unref(Y),
|
||||
disabled: unref(G) || unref(Q),
|
||||
onVerified: unref(ae),
|
||||
onInvalid: unref(oe),
|
||||
loading: unref(ce),
|
||||
onRefresh: unref(le),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`modelValue`,
|
||||
`img`,
|
||||
`provider`,
|
||||
`captcha-id`,
|
||||
`disabled`,
|
||||
`onVerified`,
|
||||
`onInvalid`,
|
||||
`loading`,
|
||||
`onRefresh`,
|
||||
],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, I, [
|
||||
(o[10] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `password`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`新密码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
"input-id": `password`,
|
||||
modelValue: unref(U).password,
|
||||
"onUpdate:modelValue": (o[6] ||= (e) =>
|
||||
(unref(U).password = e)),
|
||||
placeholder: `输入新密码`,
|
||||
feedback: !1,
|
||||
toggleMask: ``,
|
||||
autocomplete: `new-password`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, L, [
|
||||
(o[11] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `re-password`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`确认新密码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
"input-id": `re-password`,
|
||||
modelValue: unref(U).re_password,
|
||||
"onUpdate:modelValue": (o[7] ||= (e) =>
|
||||
(unref(U).re_password = e)),
|
||||
placeholder: `再次输入新密码`,
|
||||
feedback: !1,
|
||||
toggleMask: ``,
|
||||
autocomplete: `new-password`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
unref(W)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: 2,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(W)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(Z)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: 3,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(Z)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `重置密码`,
|
||||
loading: unref(G),
|
||||
class: `login-btn`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
createElementVNode(`div`, R, [
|
||||
createVNode(
|
||||
T,
|
||||
{
|
||||
to: unref(auth_redirect_t)(
|
||||
`/login`,
|
||||
unref(V).query.redirect,
|
||||
),
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(o[12] ||= [
|
||||
createTextVNode(`想起密码了?返回登录`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
]),
|
||||
],
|
||||
32,
|
||||
),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default z;
|
||||
</script>
|
||||
@@ -0,0 +1,741 @@
|
||||
<script>
|
||||
import "~/assets/styles/help.BSOB30LE.css";
|
||||
definePageMeta({
|
||||
scrollToTop: !0,
|
||||
alias: [`/help/article`],
|
||||
});
|
||||
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 { useRoute } from "#app";
|
||||
import { navigateTo } from "#app";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import iconfield from "primevue/iconfield";
|
||||
import inputicon from "primevue/inputicon";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import { t as sanitize_t } from "~/lib/sanitize.js";
|
||||
import { n as ticketAttachments_n } from "~/lib/ticketAttachments.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as content_route_t } from "~/lib/content-route.js";
|
||||
var me = {
|
||||
class: `help-page`,
|
||||
},
|
||||
he = {
|
||||
key: 0,
|
||||
class: `page-head`,
|
||||
},
|
||||
ge = {
|
||||
class: `help-body`,
|
||||
},
|
||||
_e = {
|
||||
class: `help-nav`,
|
||||
"aria-label": `帮助目录`,
|
||||
},
|
||||
ve = {
|
||||
class: `nav-heading`,
|
||||
},
|
||||
ye = {
|
||||
key: 0,
|
||||
},
|
||||
be = {
|
||||
key: 0,
|
||||
class: `nav-sk`,
|
||||
},
|
||||
C = {
|
||||
key: 1,
|
||||
class: `nav-groups`,
|
||||
"aria-label": `帮助文章`,
|
||||
},
|
||||
w = {
|
||||
class: `nav-group-title`,
|
||||
},
|
||||
T = {
|
||||
key: 0,
|
||||
class: `nav-empty`,
|
||||
},
|
||||
E = [`aria-busy`],
|
||||
D = {
|
||||
key: 0,
|
||||
class: `content-sk`,
|
||||
},
|
||||
O = {
|
||||
key: 1,
|
||||
class: `content-error`,
|
||||
},
|
||||
k = {
|
||||
key: 2,
|
||||
},
|
||||
A = {
|
||||
class: `article-category`,
|
||||
},
|
||||
j = {
|
||||
class: `content-title`,
|
||||
},
|
||||
M = [`innerHTML`],
|
||||
N = {
|
||||
key: 0,
|
||||
class: `article-attachments`,
|
||||
"aria-label": `文章附件`,
|
||||
},
|
||||
xe = [`href`],
|
||||
P = {
|
||||
class: `article-footer`,
|
||||
},
|
||||
F = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `help`,
|
||||
props: {
|
||||
embedded: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(h) {
|
||||
composables_t({
|
||||
scrollToTop: !0,
|
||||
alias: `/help/article`,
|
||||
});
|
||||
let x = h,
|
||||
F = useRoute(),
|
||||
I = useApi(),
|
||||
L = ref([]),
|
||||
R = ref(!0),
|
||||
z = ref(``),
|
||||
B = ref(``),
|
||||
V = ref(``),
|
||||
H = computed(() =>
|
||||
L.value.reduce((e, t) => e + (t.helps?.length ?? 0), 0),
|
||||
),
|
||||
U = computed(() => {
|
||||
let e = V.value.trim().toLocaleLowerCase();
|
||||
return L.value
|
||||
.map((t) => ({
|
||||
...t,
|
||||
helps: (t.helps ?? []).filter(
|
||||
(n) =>
|
||||
!e ||
|
||||
t.name.toLocaleLowerCase().includes(e) ||
|
||||
n.title.toLocaleLowerCase().includes(e),
|
||||
),
|
||||
}))
|
||||
.filter((e) => e.helps.length > 0);
|
||||
}),
|
||||
W = ref(null),
|
||||
G = computed(() =>
|
||||
ticketAttachments_n(W.value?.attachment).filter((e) => e.href),
|
||||
),
|
||||
K = ref(!1),
|
||||
q = ref(null),
|
||||
J = 0,
|
||||
Y = 0,
|
||||
X = !1,
|
||||
Se = computed(
|
||||
() =>
|
||||
L.value.find((e) => e.helps?.some((e) => e.id === q.value))
|
||||
?.name ?? ``,
|
||||
);
|
||||
function Ce(e) {
|
||||
return x?.embedded
|
||||
? `/resources?section=help&id=${e}`
|
||||
: `/help/article?id=${e}`;
|
||||
}
|
||||
async function Z() {
|
||||
if (X) return;
|
||||
let e = F.query.id !== void 0 || F.path === `/help/article`,
|
||||
t = content_route_t(F.query.id);
|
||||
if (e && !t) {
|
||||
(J++,
|
||||
(q.value = null),
|
||||
(W.value = null),
|
||||
(K.value = !1),
|
||||
(z.value = `帮助文档编号无效,请从目录重新选择`));
|
||||
return;
|
||||
}
|
||||
let n = t ?? L.value.flatMap((e) => e.helps ?? [])[0]?.id;
|
||||
n
|
||||
? await $(n)
|
||||
: (J++,
|
||||
(q.value = null),
|
||||
(W.value = null),
|
||||
(K.value = !1),
|
||||
(z.value = ``));
|
||||
}
|
||||
async function Q() {
|
||||
let e = ++Y;
|
||||
((R.value = !0), (B.value = ``));
|
||||
try {
|
||||
let t = await I.get(`/help`);
|
||||
if (X || e !== Y) return;
|
||||
L.value = t.list ?? [];
|
||||
} catch (t) {
|
||||
if (X || e !== Y) return;
|
||||
B.value = t instanceof Error ? t.message : `目录加载失败`;
|
||||
} finally {
|
||||
!X && e === Y && (R.value = !1);
|
||||
}
|
||||
!X && e === Y && (await Z());
|
||||
}
|
||||
async function $(e) {
|
||||
let t = ++J;
|
||||
((q.value = e), (K.value = !0), (W.value = null), (z.value = ``));
|
||||
try {
|
||||
let n = await I.get(`/help/${e}`);
|
||||
if (X || t !== J) return;
|
||||
if (!n.help) throw Error(`帮助文档不存在或已删除`);
|
||||
W.value = n.help;
|
||||
} catch (e) {
|
||||
!X &&
|
||||
t === J &&
|
||||
(z.value = e instanceof Error ? e.message : `加载失败`);
|
||||
} finally {
|
||||
!X && t === J && (K.value = !1);
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(Q),
|
||||
watch(
|
||||
() => F.query.id,
|
||||
() => {
|
||||
R.value || Z();
|
||||
},
|
||||
),
|
||||
onBeforeUnmount(() => {
|
||||
((X = !0), J++, Y++);
|
||||
}),
|
||||
(n, r) => {
|
||||
let i = button,
|
||||
o = inputicon,
|
||||
l = inputtext,
|
||||
h = iconfield,
|
||||
v = skeleton,
|
||||
b = NuxtLink,
|
||||
x = message,
|
||||
S = ListEmpty;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, me, [
|
||||
n.$props.embedded
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, he, [
|
||||
(r[6] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `page-heading`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`h2`, null, `帮助中心`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`查找产品使用指南与常见问题解答`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(i, {
|
||||
label: `创建工单`,
|
||||
icon: `pi pi-plus`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: (r[0] ||= (e) =>
|
||||
(`navigateTo` in n
|
||||
? n.navigateTo
|
||||
: unref(navigateTo))(`/tickets/create`)),
|
||||
}),
|
||||
])),
|
||||
createElementVNode(`div`, ge, [
|
||||
createElementVNode(`aside`, _e, [
|
||||
createElementVNode(`div`, ve, [
|
||||
(r[7] ||= createElementVNode(`h3`, null, `帮助目录`, -1)),
|
||||
unref(R)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
ye,
|
||||
toDisplayString(unref(H)) + ` 篇`,
|
||||
1,
|
||||
)),
|
||||
]),
|
||||
createVNode(
|
||||
h,
|
||||
{
|
||||
class: `help-search`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(o, {
|
||||
class: `pi pi-search`,
|
||||
}),
|
||||
createVNode(
|
||||
l,
|
||||
{
|
||||
modelValue: unref(V),
|
||||
"onUpdate:modelValue": (r[1] ||= (e) =>
|
||||
isRef(V) ? (V.value = e) : null),
|
||||
placeholder: `搜索文章或分类`,
|
||||
"aria-label": `搜索帮助文章或分类`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
unref(R)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, be, [
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(6, (e) =>
|
||||
createVNode(v, {
|
||||
key: e,
|
||||
height: `20px`,
|
||||
}),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createElementBlock(`nav`, C, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(U),
|
||||
(n) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: n.id,
|
||||
class: `nav-group`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, w, [
|
||||
createTextVNode(
|
||||
toDisplayString(n.name),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(n.helps.length),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
n.helps,
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: t.id,
|
||||
to: Ce(t.id),
|
||||
class: normalizeClass([
|
||||
`nav-item`,
|
||||
{
|
||||
active: unref(q) === t.id,
|
||||
},
|
||||
]),
|
||||
"aria-current":
|
||||
unref(q) === t.id
|
||||
? `page`
|
||||
: void 0,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
(r[8] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-file`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`, `class`, `aria-current`],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
unref(U).length
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, T, [
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(V).trim()
|
||||
? `没有找到匹配的文章`
|
||||
: `暂无帮助内容`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
unref(V).trim()
|
||||
? (openBlock(),
|
||||
createBlock(i, {
|
||||
key: 0,
|
||||
label: `清除搜索`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: (r[2] ||= (e) => (V.value = ``)),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
])),
|
||||
])),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
x,
|
||||
{
|
||||
key: 2,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(B)), 1),
|
||||
createVNode(i, {
|
||||
label: `重试目录`,
|
||||
text: ``,
|
||||
onClick: Q,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
(r[9] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `support-note`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`i`, {
|
||||
class: `pi pi-question-circle`,
|
||||
"aria-hidden": `true`,
|
||||
}),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`仍有疑问?创建工单,联系我们协助处理。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
]),
|
||||
createElementVNode(
|
||||
`section`,
|
||||
{
|
||||
class: `help-content`,
|
||||
"aria-label": `帮助文章正文`,
|
||||
"aria-busy": unref(K),
|
||||
},
|
||||
[
|
||||
unref(K) || unref(R)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, D, [
|
||||
createVNode(v, {
|
||||
width: `60%`,
|
||||
height: `28px`,
|
||||
}),
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(5, (e) =>
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
key: e,
|
||||
width: e === 5 ? `70%` : `100%`,
|
||||
height: `18px`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`width`],
|
||||
),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
]))
|
||||
: unref(z)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, O, [
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
icon: `pi pi-exclamation-circle`,
|
||||
title: `帮助内容暂时无法显示`,
|
||||
description: unref(z),
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
unref(q)
|
||||
? (openBlock(),
|
||||
createBlock(i, {
|
||||
key: 0,
|
||||
label: `重新加载文章`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: (r[3] ||= (e) =>
|
||||
$(unref(q))),
|
||||
}))
|
||||
: (openBlock(),
|
||||
createBlock(i, {
|
||||
key: 1,
|
||||
label: `重新加载帮助目录`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: Q,
|
||||
})),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`description`],
|
||||
),
|
||||
]))
|
||||
: unref(W)
|
||||
? (openBlock(),
|
||||
createElementBlock(`article`, k, [
|
||||
createElementVNode(`div`, A, [
|
||||
(r[10] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-book`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(unref(Se) || `帮助文档`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(
|
||||
`h3`,
|
||||
j,
|
||||
toDisplayString(unref(W).title),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `content-html`,
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
(`decodeEntities` in n
|
||||
? n.decodeEntities
|
||||
: unref(sanitize_t))(
|
||||
unref(W).content || ``,
|
||||
),
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
M,
|
||||
),
|
||||
unref(G).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`section`, N, [
|
||||
(r[13] ||= createElementVNode(
|
||||
`h4`,
|
||||
null,
|
||||
`相关附件`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`ul`, null, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(G),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`li`,
|
||||
{
|
||||
key: t.href || t.name,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`a`,
|
||||
{
|
||||
href: t.href,
|
||||
target: `_blank`,
|
||||
rel: `noopener noreferrer`,
|
||||
},
|
||||
[
|
||||
(r[11] ||=
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-file`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
(r[12] ||=
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-download`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
],
|
||||
8,
|
||||
xe,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`footer`, P, [
|
||||
(r[14] ||= createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`没有解决你的问题?`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(i, {
|
||||
label: `创建工单`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: (r[4] ||= (e) =>
|
||||
(`navigateTo` in n
|
||||
? n.navigateTo
|
||||
: unref(navigateTo))(
|
||||
`/tickets/create`,
|
||||
)),
|
||||
}),
|
||||
]),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
S,
|
||||
{
|
||||
key: 3,
|
||||
icon: `pi pi-book`,
|
||||
title: unref(H)
|
||||
? `选择一篇帮助文档`
|
||||
: `帮助文档正在准备中`,
|
||||
description: unref(H)
|
||||
? `从左侧目录选择文章,查看详细操作指引。`
|
||||
: `如需协助,可以创建工单联系我们。`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
unref(H)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(i, {
|
||||
key: 0,
|
||||
label: `创建工单`,
|
||||
icon: `pi pi-plus`,
|
||||
onClick: (r[5] ||= (e) =>
|
||||
(`navigateTo` in n
|
||||
? n.navigateTo
|
||||
: unref(navigateTo))(
|
||||
`/tickets/create`,
|
||||
)),
|
||||
})),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`title`, `description`],
|
||||
)),
|
||||
],
|
||||
8,
|
||||
E,
|
||||
),
|
||||
]),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-2e1fbf8d`]],
|
||||
);
|
||||
export {};
|
||||
export default F;
|
||||
</script>
|
||||
@@ -0,0 +1,105 @@
|
||||
<script setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from "vue";
|
||||
import { useHead, useRouter } from "#app";
|
||||
import { NuxtLink } from "#components";
|
||||
import Button from "primevue/button";
|
||||
import Message from "primevue/message";
|
||||
import { useAuth } from "~/lib/auth.js";
|
||||
|
||||
definePageMeta({ layout: "blank" });
|
||||
useHead({
|
||||
title: "正在进入会员中心",
|
||||
meta: [{ name: "referrer", content: "no-referrer" }],
|
||||
});
|
||||
|
||||
const auth = useAuth();
|
||||
const router = useRouter();
|
||||
const isVerifying = ref(false);
|
||||
const verificationError = ref("");
|
||||
let disposed = false;
|
||||
|
||||
async function verifyAndEnterConsole() {
|
||||
if (isVerifying.value) return;
|
||||
isVerifying.value = true;
|
||||
verificationError.value = "";
|
||||
try {
|
||||
// The route guard owns credential extraction; this page never reads it from the URL.
|
||||
await auth.verifyLegacyLogin();
|
||||
if (!disposed) await router.replace("/");
|
||||
} catch (error) {
|
||||
if (!disposed) {
|
||||
verificationError.value =
|
||||
error instanceof Error ? error.message : "登录验证失败,请稍后重试。";
|
||||
}
|
||||
} finally {
|
||||
if (!disposed) isVerifying.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(verifyAndEnterConsole);
|
||||
onBeforeUnmount(() => {
|
||||
disposed = true;
|
||||
auth.cancelLegacyLogin();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section
|
||||
class="auth-card legacy-login"
|
||||
:aria-busy="isVerifying"
|
||||
aria-labelledby="legacy-login-title"
|
||||
>
|
||||
<span class="legacy-login-icon" aria-hidden="true">
|
||||
<i :class="isVerifying ? 'pi pi-spin pi-spinner' : 'pi pi-user'" />
|
||||
</span>
|
||||
<h1 id="legacy-login-title">
|
||||
{{ verificationError ? "暂时无法进入会员中心" : "正在进入会员中心" }}
|
||||
</h1>
|
||||
<Message v-if="verificationError" severity="error" :closable="false">
|
||||
{{ verificationError }}
|
||||
</Message>
|
||||
<p v-else role="status">正在验证登录身份,请稍候…</p>
|
||||
<div v-if="verificationError" class="legacy-login-actions">
|
||||
<Button
|
||||
label="重新验证"
|
||||
icon="pi pi-refresh"
|
||||
:loading="isVerifying"
|
||||
@click="verifyAndEnterConsole"
|
||||
/>
|
||||
<NuxtLink to="/login" class="legacy-login-link">使用账号登录</NuxtLink>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.legacy-login {
|
||||
text-align: center;
|
||||
}
|
||||
.legacy-login-icon {
|
||||
background: color-mix(in srgb, var(--p-primary-color) 10%, transparent);
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
color: var(--p-primary-color);
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.75em;
|
||||
display: inline-flex;
|
||||
}
|
||||
.legacy-login p {
|
||||
color: var(--p-text-muted-color);
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.legacy-login-actions {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
}
|
||||
.legacy-login-link {
|
||||
color: var(--p-primary-color);
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,675 @@
|
||||
<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 "~/assets/styles/HomeTicketPanel.LxPesukM.css";
|
||||
import "~/assets/styles/HomeServerPanel.Do7AgMDx.css";
|
||||
import "~/assets/styles/HomeReferralPanel.DsgN33ME.css";
|
||||
import "~/assets/styles/HomeNoticePanel.e5-qgzAs.css";
|
||||
import "~/assets/styles/HomeExpiringPanel.Ckflw2Hv.css";
|
||||
import "~/assets/styles/SensitiveValue.BSZlaRHT.css";
|
||||
import "~/assets/styles/pages.DytekQXu.css";
|
||||
import { toDisplayString } from "vue";
|
||||
import { renderList } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { normalizeClass } from "vue";
|
||||
import { onBeforeUnmount } 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 { NuxtLink } from "#components";
|
||||
import { useApi } from "~/lib/auth.js";
|
||||
import { useAuth } 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 message from "primevue/message";
|
||||
import { t as interval_t } from "~/lib/interval.js";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import SensitiveValue from "~/components/SensitiveValue.vue";
|
||||
import HomeExpiringPanel from "~/components/home/HomeExpiringPanel.vue";
|
||||
import HomeNoticePanel from "~/components/home/HomeNoticePanel.vue";
|
||||
import HomeReferralPanel from "~/components/home/HomeReferralPanel.vue";
|
||||
import HomeServerPanel from "~/components/home/HomeServerPanel.vue";
|
||||
import HomeTicketPanel from "~/components/home/HomeTicketPanel.vue";
|
||||
import HomeWalletCard from "~/components/home/HomeWalletCard.vue";
|
||||
function S(e) {
|
||||
let t = e.getHours();
|
||||
return t < 5 || t >= 22
|
||||
? {
|
||||
title: `夜深了`,
|
||||
message: `忙碌之余,也记得早点休息。愿今晚的工作顺利收尾。`,
|
||||
icon: `lucide:moon-star`,
|
||||
}
|
||||
: t < 11
|
||||
? {
|
||||
title: `早上好`,
|
||||
message: `新的一天开始了,愿今天的每一份计划都顺利。`,
|
||||
icon: `lucide:sunrise`,
|
||||
}
|
||||
: t < 14
|
||||
? {
|
||||
title: `中午好`,
|
||||
message: `忙碌了半天,记得好好吃饭,给自己一点休息时间。`,
|
||||
icon: `lucide:sun`,
|
||||
}
|
||||
: t < 18
|
||||
? {
|
||||
title: `下午好`,
|
||||
message: `喝杯水,舒展一下,愿接下来的工作从容又顺利。`,
|
||||
icon: `lucide:sun`,
|
||||
}
|
||||
: {
|
||||
title: `晚上好`,
|
||||
message: `辛苦一天了,愿你有个轻松的晚上。`,
|
||||
icon: `lucide:sunset`,
|
||||
};
|
||||
}
|
||||
function C(e) {
|
||||
let t = e?.previous_login,
|
||||
n = Number(t?.time),
|
||||
r = new Date(n * 1e3);
|
||||
if (!Number.isFinite(n) || n <= 0 || !Number.isFinite(r.getTime()))
|
||||
return {
|
||||
available: !1,
|
||||
time: `暂无历史记录`,
|
||||
ip: `—`,
|
||||
};
|
||||
let i = (e) => String(e).padStart(2, `0`);
|
||||
return {
|
||||
available: !0,
|
||||
time: `${r.getFullYear()}-${i(r.getMonth() + 1)}-${i(r.getDate())} ${i(r.getHours())}:${i(r.getMinutes())}`,
|
||||
ip: typeof t?.ip == `string` && t.ip.trim() ? t.ip.trim() : `未记录`,
|
||||
};
|
||||
}
|
||||
var w = {
|
||||
class: `home-page`,
|
||||
},
|
||||
T = {
|
||||
class: `home-grid`,
|
||||
},
|
||||
E = {
|
||||
class: `home-card welcome-card home-welcome`,
|
||||
"aria-labelledby": `welcome-title`,
|
||||
},
|
||||
D = {
|
||||
class: `home-card-head welcome-head`,
|
||||
},
|
||||
O = {
|
||||
class: `welcome-greeting`,
|
||||
},
|
||||
k = {
|
||||
class: `welcome-heading`,
|
||||
},
|
||||
A = {
|
||||
class: `welcome-icon`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
j = {
|
||||
id: `welcome-title`,
|
||||
class: `home-card-title welcome-title`,
|
||||
},
|
||||
M = [`aria-label`],
|
||||
N = {
|
||||
key: 1,
|
||||
class: `copy-id-placeholder`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
P = {
|
||||
class: `welcome-message`,
|
||||
},
|
||||
F = {
|
||||
class: `welcome-meta`,
|
||||
},
|
||||
I = {
|
||||
class: `welcome-login`,
|
||||
},
|
||||
L = {
|
||||
key: 1,
|
||||
},
|
||||
R = {
|
||||
class: `welcome-login`,
|
||||
},
|
||||
z = {
|
||||
key: 1,
|
||||
},
|
||||
de = {
|
||||
class: `home-card-body welcome-body`,
|
||||
},
|
||||
B = {
|
||||
key: 1,
|
||||
class: `tiles`,
|
||||
},
|
||||
V = {
|
||||
key: 2,
|
||||
class: `tiles`,
|
||||
},
|
||||
H = {
|
||||
class: `tile-label`,
|
||||
},
|
||||
fe = {
|
||||
class: `tile-value`,
|
||||
},
|
||||
pe = {
|
||||
key: 2,
|
||||
class: `tile-text`,
|
||||
},
|
||||
U = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `index`,
|
||||
setup(m) {
|
||||
let b = useAuth(),
|
||||
U = useApi(),
|
||||
W = ref(!1),
|
||||
G = ref(new Date()),
|
||||
K = computed(() => S(G.value)),
|
||||
q = computed(() => C(b.overview)),
|
||||
J;
|
||||
function Y() {
|
||||
G.value = new Date();
|
||||
}
|
||||
async function me() {
|
||||
if (b.overview)
|
||||
try {
|
||||
(await navigator.clipboard.writeText(String(b.overview.id)),
|
||||
(W.value = !0));
|
||||
} catch {
|
||||
W.value = !1;
|
||||
}
|
||||
}
|
||||
let X = ref(null),
|
||||
Z = ref(!0),
|
||||
Q = ref(``);
|
||||
function $() {
|
||||
((Q.value = ``),
|
||||
b.fetchOverview().catch((e) => {
|
||||
e?.status !== 401 &&
|
||||
(Q.value = e instanceof Error ? e.message : `账户信息加载失败`);
|
||||
}));
|
||||
}
|
||||
(onMounted(() => {
|
||||
(Y(),
|
||||
(J = interval_t(Y, 6e4)),
|
||||
document.addEventListener(`visibilitychange`, Y),
|
||||
$(),
|
||||
U.get(`/certification/info`)
|
||||
.then((e) => {
|
||||
X.value = e;
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
Z.value = !1;
|
||||
}));
|
||||
}),
|
||||
onBeforeUnmount(() => {
|
||||
(clearInterval(J),
|
||||
document.removeEventListener(`visibilitychange`, Y));
|
||||
}));
|
||||
let he = computed(() => {
|
||||
let e = b.overview;
|
||||
if (!e) return [];
|
||||
let t = [
|
||||
e.phone
|
||||
? {
|
||||
label: `手机号`,
|
||||
value: e.phone,
|
||||
kind: `phone`,
|
||||
prefix: `+${e.phone_code || 86}`,
|
||||
}
|
||||
: {
|
||||
label: `手机号`,
|
||||
value: `未绑定`,
|
||||
action: `绑定手机`,
|
||||
to: `/account?tab=phone`,
|
||||
},
|
||||
];
|
||||
t.push(
|
||||
e.email
|
||||
? {
|
||||
label: `邮箱`,
|
||||
value: e.email,
|
||||
kind: `email`,
|
||||
}
|
||||
: {
|
||||
label: `邮箱`,
|
||||
value: `未绑定`,
|
||||
action: `绑定邮箱`,
|
||||
to: `/account`,
|
||||
},
|
||||
);
|
||||
let n = X.value;
|
||||
return (
|
||||
n
|
||||
? (t.push(
|
||||
n.certification_open === 0
|
||||
? {
|
||||
label: `实名认证`,
|
||||
value: `暂未开放`,
|
||||
}
|
||||
: n.is_certification
|
||||
? {
|
||||
label: `实名认证`,
|
||||
value: n.person?.card_name || `已认证`,
|
||||
kind: n.person?.card_name ? `name` : void 0,
|
||||
}
|
||||
: n.person?.status
|
||||
? {
|
||||
label: `实名认证`,
|
||||
value: `审核中`,
|
||||
}
|
||||
: {
|
||||
label: `实名认证`,
|
||||
value: `未认证`,
|
||||
action: `去认证`,
|
||||
to: `/account/realname`,
|
||||
},
|
||||
),
|
||||
n.certification_company_open === 1
|
||||
? t.push(
|
||||
n.company?.status
|
||||
? {
|
||||
label: `组织机构认证`,
|
||||
value: n.company?.company || `已认证`,
|
||||
kind: n.company?.company ? `text` : void 0,
|
||||
}
|
||||
: {
|
||||
label: `组织机构认证`,
|
||||
value: `未认证`,
|
||||
action: `去认证`,
|
||||
to: `/account/realname`,
|
||||
},
|
||||
)
|
||||
: t.push({
|
||||
label: `组织机构认证`,
|
||||
value: `暂未开放`,
|
||||
}))
|
||||
: t.push(
|
||||
{
|
||||
label: `实名认证`,
|
||||
value: `暂不可用`,
|
||||
loading: Z.value,
|
||||
},
|
||||
{
|
||||
label: `组织机构认证`,
|
||||
value: `暂不可用`,
|
||||
loading: Z.value,
|
||||
},
|
||||
),
|
||||
t
|
||||
);
|
||||
});
|
||||
return (n, i) => {
|
||||
let o = Icon,
|
||||
c = skeleton,
|
||||
m = NuxtLink,
|
||||
v = button,
|
||||
y = message,
|
||||
x = SensitiveValue,
|
||||
S = HomeWalletCard,
|
||||
C = HomeTicketPanel,
|
||||
U = HomeServerPanel,
|
||||
G = HomeExpiringPanel,
|
||||
J = HomeNoticePanel,
|
||||
Y = HomeReferralPanel;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, w, [
|
||||
createElementVNode(`div`, T, [
|
||||
createElementVNode(`section`, E, [
|
||||
createElementVNode(`div`, D, [
|
||||
createElementVNode(`div`, O, [
|
||||
createElementVNode(`div`, k, [
|
||||
createElementVNode(`span`, A, [
|
||||
unref(K).icon === `lucide:moon-star`
|
||||
? (openBlock(),
|
||||
createBlock(o, {
|
||||
key: 0,
|
||||
name: `lucide:moon-star`,
|
||||
}))
|
||||
: unref(K).icon === `lucide:sunrise`
|
||||
? (openBlock(),
|
||||
createBlock(o, {
|
||||
key: 1,
|
||||
name: `lucide:sunrise`,
|
||||
}))
|
||||
: unref(K).icon === `lucide:sunset`
|
||||
? (openBlock(),
|
||||
createBlock(o, {
|
||||
key: 2,
|
||||
name: `lucide:sunset`,
|
||||
}))
|
||||
: (openBlock(),
|
||||
createBlock(o, {
|
||||
key: 3,
|
||||
name: `lucide:sun`,
|
||||
})),
|
||||
]),
|
||||
createElementVNode(`h1`, j, [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(K).title) +
|
||||
`,` +
|
||||
toDisplayString(
|
||||
unref(b).overview?.username || `会员`,
|
||||
) +
|
||||
` `,
|
||||
1,
|
||||
),
|
||||
unref(b).overview
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`button`,
|
||||
{
|
||||
key: 0,
|
||||
type: `button`,
|
||||
class: `copy-id`,
|
||||
"aria-label": unref(W)
|
||||
? `用户 ID 已复制`
|
||||
: `复制用户 ID`,
|
||||
onClick: me,
|
||||
},
|
||||
[
|
||||
createTextVNode(
|
||||
` #` +
|
||||
toDisplayString(unref(b).overview.id),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: normalizeClass(
|
||||
unref(W) ? `pi pi-check` : `pi pi-copy`,
|
||||
),
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
],
|
||||
8,
|
||||
M,
|
||||
))
|
||||
: (openBlock(), createElementBlock(`span`, N)),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
P,
|
||||
toDisplayString(unref(K).message),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`dl`, F, [
|
||||
createElementVNode(`div`, I, [
|
||||
createElementVNode(`dt`, null, [
|
||||
createVNode(o, {
|
||||
name: `lucide:clock-3`,
|
||||
"aria-hidden": `true`,
|
||||
}),
|
||||
(i[0] ||= createTextVNode(`上次登录`, -1)),
|
||||
]),
|
||||
createElementVNode(`dd`, null, [
|
||||
!unref(b).overview && !unref(Q)
|
||||
? (openBlock(),
|
||||
createBlock(c, {
|
||||
key: 0,
|
||||
height: `18px`,
|
||||
width: `138px`,
|
||||
}))
|
||||
: (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
L,
|
||||
toDisplayString(unref(q).time),
|
||||
1,
|
||||
)),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, R, [
|
||||
createElementVNode(`dt`, null, [
|
||||
createVNode(o, {
|
||||
name: `lucide:map-pin`,
|
||||
"aria-hidden": `true`,
|
||||
}),
|
||||
(i[1] ||= createTextVNode(`IP 地址`, -1)),
|
||||
]),
|
||||
createElementVNode(`dd`, null, [
|
||||
!unref(b).overview && !unref(Q)
|
||||
? (openBlock(),
|
||||
createBlock(c, {
|
||||
key: 0,
|
||||
height: `18px`,
|
||||
width: `108px`,
|
||||
}))
|
||||
: (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
z,
|
||||
toDisplayString(unref(q).ip),
|
||||
1,
|
||||
)),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
createVNode(
|
||||
m,
|
||||
{
|
||||
to: `/account`,
|
||||
class: `home-card-more welcome-settings`,
|
||||
"aria-label": `账户设置`,
|
||||
title: `账户设置`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(i[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-cog`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, de, [
|
||||
unref(Q)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(Q)), 1),
|
||||
createVNode(v, {
|
||||
label: `重试`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: $,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(b).overview
|
||||
? (openBlock(),
|
||||
createElementBlock(`dl`, V, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(he),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: t.label,
|
||||
class: `tile`,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`dt`,
|
||||
H,
|
||||
toDisplayString(t.label),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`dd`, fe, [
|
||||
t.loading
|
||||
? (openBlock(),
|
||||
createBlock(c, {
|
||||
key: 0,
|
||||
width: `64px`,
|
||||
height: `22px`,
|
||||
}))
|
||||
: t.kind
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
x,
|
||||
{
|
||||
key: 1,
|
||||
value: t.value,
|
||||
kind: t.kind,
|
||||
prefix: t.prefix,
|
||||
label: t.label,
|
||||
"reset-key":
|
||||
unref(b).overview?.id,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`value`,
|
||||
`kind`,
|
||||
`prefix`,
|
||||
`label`,
|
||||
`reset-key`,
|
||||
],
|
||||
))
|
||||
: t.action
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
m,
|
||||
{
|
||||
key: 3,
|
||||
to: t.to,
|
||||
class: `tile-action`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
t.action,
|
||||
) + ` `,
|
||||
1,
|
||||
),
|
||||
(i[3] ||=
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-angle-right`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`],
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
pe,
|
||||
toDisplayString(t.value),
|
||||
1,
|
||||
)),
|
||||
]),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, B, [
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(4, (e) =>
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
key: e,
|
||||
class: `tile`,
|
||||
},
|
||||
[
|
||||
createVNode(c, {
|
||||
height: `14px`,
|
||||
width: `50%`,
|
||||
}),
|
||||
createVNode(c, {
|
||||
height: `14px`,
|
||||
width: `75%`,
|
||||
style: {
|
||||
"margin-top": `10px`,
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
])),
|
||||
]),
|
||||
]),
|
||||
createVNode(S, {
|
||||
class: `home-wallet`,
|
||||
}),
|
||||
createVNode(C, {
|
||||
class: `home-tickets`,
|
||||
}),
|
||||
createVNode(U, {
|
||||
class: `home-servers`,
|
||||
}),
|
||||
createVNode(G, {
|
||||
class: `home-expiring`,
|
||||
}),
|
||||
createVNode(J, {
|
||||
class: `home-notices`,
|
||||
}),
|
||||
createVNode(Y),
|
||||
]),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-b43b228e`]],
|
||||
);
|
||||
export {};
|
||||
export default U;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,623 @@
|
||||
<script>
|
||||
import "~/assets/styles/invoice.B6sYFYlb.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
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 { 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 { useRoute } from "#app";
|
||||
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 { n as dict_n } from "~/lib/dict.js";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var T = {
|
||||
class: `invoice-detail-page`,
|
||||
},
|
||||
E = {
|
||||
key: 1,
|
||||
class: `invoice-error`,
|
||||
},
|
||||
D = {
|
||||
key: 2,
|
||||
class: `invoice-paper`,
|
||||
},
|
||||
O = {
|
||||
class: `invoice-number`,
|
||||
},
|
||||
k = {
|
||||
key: 0,
|
||||
},
|
||||
A = {
|
||||
key: 1,
|
||||
},
|
||||
j = {
|
||||
key: 2,
|
||||
},
|
||||
M = {
|
||||
key: 3,
|
||||
},
|
||||
N = {
|
||||
key: 4,
|
||||
},
|
||||
P = {
|
||||
class: `invoice-total`,
|
||||
},
|
||||
F = {
|
||||
class: `invoice-actions`,
|
||||
},
|
||||
I = [`href`],
|
||||
L = {
|
||||
key: 2,
|
||||
class: `invoice-file-hint`,
|
||||
},
|
||||
R = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `invoice`,
|
||||
setup(f) {
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let b = useRoute(),
|
||||
R = useApi(),
|
||||
z = ref(null),
|
||||
B = ref(!0),
|
||||
V = ref(``),
|
||||
H = ref(!1),
|
||||
U = ref(``),
|
||||
W = {
|
||||
pending: `待审核`,
|
||||
unpaid: `待支付`,
|
||||
wait_create: `待开具`,
|
||||
creating: `开具中`,
|
||||
create_fail: `开具失败`,
|
||||
approved: `已审核`,
|
||||
reject: `已驳回`,
|
||||
rejected: `已驳回`,
|
||||
issued: `已开具`,
|
||||
wait_send: `待寄出`,
|
||||
sent: `已寄出`,
|
||||
cancel: `已取消`,
|
||||
flushed: `已冲红`,
|
||||
},
|
||||
G = computed(() => z.value?.invoice_project === `历史已开票登记`),
|
||||
K = computed(() =>
|
||||
G.value
|
||||
? `历史已开票登记`
|
||||
: W[String(z.value?.status || ``).toLowerCase()] ||
|
||||
String(z.value?.status || `—`),
|
||||
);
|
||||
function q(e) {
|
||||
return typeof e != `string` || /[\u0000-\u0020\\]/.test(e)
|
||||
? ``
|
||||
: /^https?:\/\//i.test(e) || /^\/(?!\/)/.test(e)
|
||||
? e
|
||||
: ``;
|
||||
}
|
||||
function J(...e) {
|
||||
for (let t of e) {
|
||||
let e = z.value?.[t];
|
||||
if (e != null && String(e) !== ``) return e;
|
||||
}
|
||||
return ``;
|
||||
}
|
||||
async function Y(e) {
|
||||
if (!(G.value || q(z.value?.invoice_url))) {
|
||||
((H.value = !0), (U.value = ``));
|
||||
try {
|
||||
let t = await R.get(`/invoice/${e}/invoice_filename`),
|
||||
n = t.data && typeof t.data == `object` ? t.data : t,
|
||||
r = q(n.url ?? n.invoice_url);
|
||||
if (r && z.value)
|
||||
z.value = {
|
||||
...z.value,
|
||||
invoice_url: r,
|
||||
};
|
||||
else throw Error(`正式发票文件尚未提供`);
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `获取发票下载地址失败`;
|
||||
} finally {
|
||||
H.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function X() {
|
||||
((B.value = !0), (V.value = ``));
|
||||
try {
|
||||
let e = String(b.query.id || ``);
|
||||
if (!/^\d+$/.test(e)) throw Error(`请选择要查看的发票`);
|
||||
let t = await R.get(`/invoice/${e}`),
|
||||
n = t.invoice && typeof t.invoice == `object` ? t.invoice : t;
|
||||
if (!n.id && !n.title && !n.invoice_project)
|
||||
throw Error(`发票不存在或暂不可用`);
|
||||
((z.value = n), G.value || Y(String(n.id || e)));
|
||||
} catch (e) {
|
||||
V.value = e instanceof Error ? e.message : `加载发票失败`;
|
||||
} finally {
|
||||
B.value = !1;
|
||||
}
|
||||
}
|
||||
let Z = computed(() => q(z.value?.invoice_url));
|
||||
return (
|
||||
onMounted(X),
|
||||
(t, i) => {
|
||||
let s = message,
|
||||
f = skeleton,
|
||||
h = button,
|
||||
v = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, T, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
severity: `info`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(i[1] ||= [
|
||||
createTextVNode(
|
||||
`发票内容以开票机构出具的正式文件为准,请下载后查看完整票面信息。`,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(f, {
|
||||
key: 0,
|
||||
height: `480px`,
|
||||
}))
|
||||
: unref(V)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, E, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(V)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(h, {
|
||||
label: `重新加载`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: X,
|
||||
}),
|
||||
]))
|
||||
: unref(z)
|
||||
? (openBlock(),
|
||||
createElementBlock(`article`, D, [
|
||||
(i[16] ||= createElementVNode(
|
||||
`h1`,
|
||||
null,
|
||||
`发票详情`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
O,
|
||||
`发票 ID:` +
|
||||
toDisplayString(unref(z).id || unref(b).query.id),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`dl`, null, [
|
||||
createElementVNode(`div`, null, [
|
||||
(i[2] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`发票抬头`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(unref(z).title || `—`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, null, [
|
||||
(i[3] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`开票项目`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(z).invoice_project || `—`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, null, [
|
||||
(i[4] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`收件地址`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(z).email || unref(z).address || `—`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, null, [
|
||||
(i[5] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`申请日期`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(z).create_time
|
||||
? (`formatDate` in t
|
||||
? t.formatDate
|
||||
: unref(dict_n))(
|
||||
Number(unref(z).create_time),
|
||||
)
|
||||
: `—`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, null, [
|
||||
(i[6] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`格式`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(unref(z).invoice_format || `—`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, null, [
|
||||
(i[7] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`状态`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(unref(K)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
J(`tax_price`, `tax_amount`) === ``
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, k, [
|
||||
(i[8] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`税费`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
`¥` +
|
||||
toDisplayString(
|
||||
J(`tax_price`, `tax_amount`),
|
||||
),
|
||||
1,
|
||||
),
|
||||
])),
|
||||
J(`parcel_price`, `shipping_fee`, `express_fee`) ===
|
||||
``
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, A, [
|
||||
(i[9] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`快递费`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
`¥` +
|
||||
toDisplayString(
|
||||
J(
|
||||
`parcel_price`,
|
||||
`shipping_fee`,
|
||||
`express_fee`,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
])),
|
||||
J(
|
||||
`express_company`,
|
||||
`logistics_company`,
|
||||
`parcel_name`,
|
||||
) === ``
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
(i[10] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`物流公司`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(
|
||||
J(
|
||||
`express_company`,
|
||||
`logistics_company`,
|
||||
`parcel_name`,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
])),
|
||||
J(
|
||||
`express_number`,
|
||||
`tracking_number`,
|
||||
`parcel_number`,
|
||||
) === ``
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, M, [
|
||||
(i[11] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`物流单号`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
toDisplayString(
|
||||
J(
|
||||
`express_number`,
|
||||
`tracking_number`,
|
||||
`parcel_number`,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
])),
|
||||
J(`invoice_order_id`, `fee_order_id`) === ``
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, N, [
|
||||
(i[12] ||= createElementVNode(
|
||||
`dt`,
|
||||
null,
|
||||
`费用订单`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`dd`,
|
||||
null,
|
||||
`#` +
|
||||
toDisplayString(
|
||||
J(`invoice_order_id`, `fee_order_id`),
|
||||
),
|
||||
1,
|
||||
),
|
||||
])),
|
||||
]),
|
||||
createElementVNode(`div`, P, [
|
||||
(i[13] ||= createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`价税合计`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`strong`,
|
||||
null,
|
||||
`¥` + toDisplayString(unref(z).price ?? `—`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
unref(z).reject_reason
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
s,
|
||||
{
|
||||
key: 0,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
unref(sanitizeMessage)(
|
||||
unref(z).reject_reason,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, F, [
|
||||
createVNode(
|
||||
h,
|
||||
{
|
||||
"as-child": ``,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
},
|
||||
{
|
||||
default: withCtx((e) => [
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
to: `/invoices`,
|
||||
class: normalizeClass(e.class),
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(i[14] ||= [
|
||||
createTextVNode(`返回发票列表`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`class`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
unref(Z)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 0,
|
||||
"as-child": ``,
|
||||
},
|
||||
{
|
||||
default: withCtx((e) => [
|
||||
createElementVNode(
|
||||
`a`,
|
||||
{
|
||||
href: unref(Z),
|
||||
class: normalizeClass(e.class),
|
||||
target: `_blank`,
|
||||
rel: `noopener noreferrer`,
|
||||
},
|
||||
[
|
||||
...(i[15] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-download`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(` 下载发票`, -1),
|
||||
]),
|
||||
],
|
||||
10,
|
||||
I,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(G)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 1,
|
||||
label: `获取发票文件`,
|
||||
icon: `pi pi-download`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
loading: unref(H),
|
||||
disabled: unref(H),
|
||||
onClick: (i[0] ||= (e) =>
|
||||
Y(
|
||||
String(
|
||||
unref(z).id ||
|
||||
unref(b).query.id ||
|
||||
``,
|
||||
),
|
||||
)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
)),
|
||||
]),
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
s,
|
||||
{
|
||||
key: 1,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(U)) +
|
||||
`。可稍后重试获取。`,
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: !unref(Z) && !unref(G)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`p`,
|
||||
L,
|
||||
`正式发票文件尚未提供,可在交付后查看或下载。`,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-3b8f6704`]],
|
||||
);
|
||||
export {};
|
||||
export default R;
|
||||
</script>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import "~/assets/styles/PageInfoNotice._16xRFrB.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/invoices.t1P1GXOx.css";
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import index from "~/pages/invoices/index.vue";
|
||||
var i = defineComponent({
|
||||
__name: `request`,
|
||||
setup(t) {
|
||||
return (t, i) => (openBlock(), createBlock(index));
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,393 @@
|
||||
<script>
|
||||
import "~/assets/styles/logbook.Y7gm684m.css";
|
||||
import { toDisplayString } 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 { withKeys } from "vue";
|
||||
import { useRoute } from "#app";
|
||||
import { operationMessage } 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 paginator from "primevue/paginator";
|
||||
import select from "primevue/select";
|
||||
import column from "primevue/column";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import { t as useListPage_t } from "~/lib/useListPage.js";
|
||||
var k = {
|
||||
class: `list-page`,
|
||||
},
|
||||
A = {
|
||||
class: `list-toolbar`,
|
||||
},
|
||||
j = {
|
||||
class: `list-toolbar-right`,
|
||||
},
|
||||
M = {
|
||||
class: `list-table`,
|
||||
},
|
||||
N = {
|
||||
class: `col-mono`,
|
||||
},
|
||||
P = {
|
||||
key: 1,
|
||||
class: `list-foot`,
|
||||
},
|
||||
F = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `index`,
|
||||
setup(f) {
|
||||
let y = ref(``),
|
||||
F = ref(``),
|
||||
I = useRoute(),
|
||||
L = ref(I.query.type === `api` ? `api` : `system`),
|
||||
R = ref(`id`),
|
||||
z = ref(`desc`),
|
||||
{
|
||||
list: B,
|
||||
total: V,
|
||||
loading: H,
|
||||
error: U,
|
||||
page: W,
|
||||
limit: G,
|
||||
onPage: K,
|
||||
reload: q,
|
||||
} = useListPage_t(`/log`, {
|
||||
limit: 20,
|
||||
params: () => ({
|
||||
keywords: F.value,
|
||||
type: L.value,
|
||||
orderby: R.value,
|
||||
sort: z.value,
|
||||
}),
|
||||
});
|
||||
watch(
|
||||
() => I.query.type,
|
||||
(e) => {
|
||||
let t = e === `api` ? `api` : `system`;
|
||||
L.value !== t && ((L.value = t), q());
|
||||
},
|
||||
);
|
||||
let J = computed(() => !!F.value || L.value !== `system`);
|
||||
function Y() {
|
||||
((F.value = y.value.trim()), q());
|
||||
}
|
||||
function X() {
|
||||
((y.value = ``),
|
||||
(F.value = ``),
|
||||
(L.value = `system`),
|
||||
(R.value = `id`),
|
||||
(z.value = `desc`),
|
||||
q());
|
||||
}
|
||||
return (t, r) => {
|
||||
let o = select,
|
||||
f = inputtext,
|
||||
g = button,
|
||||
O = ListEmpty,
|
||||
F = column,
|
||||
I = datatable,
|
||||
Z = message,
|
||||
Q = paginator;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, k, [
|
||||
(r[5] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `list-head`,
|
||||
},
|
||||
[createElementVNode(`h2`, null, `操作日志`)],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, A, [
|
||||
createElementVNode(`div`, j, [
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(L),
|
||||
"onUpdate:modelValue": (r[0] ||= (e) =>
|
||||
isRef(L) ? (L.value = e) : null),
|
||||
options: [
|
||||
{
|
||||
label: `系统日志`,
|
||||
value: `system`,
|
||||
},
|
||||
{
|
||||
label: `API 日志`,
|
||||
value: `api`,
|
||||
},
|
||||
],
|
||||
"option-label": `label`,
|
||||
"option-value": `value`,
|
||||
"aria-label": `日志类型`,
|
||||
onChange: unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `onChange`],
|
||||
),
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(R),
|
||||
"onUpdate:modelValue": (r[1] ||= (e) =>
|
||||
isRef(R) ? (R.value = e) : null),
|
||||
options: [
|
||||
{
|
||||
label: `记录 ID`,
|
||||
value: `id`,
|
||||
},
|
||||
{
|
||||
label: `创建时间`,
|
||||
value: `create_time`,
|
||||
},
|
||||
{
|
||||
label: `操作内容`,
|
||||
value: `description`,
|
||||
},
|
||||
{
|
||||
label: `IP`,
|
||||
value: `ip`,
|
||||
},
|
||||
],
|
||||
"option-label": `label`,
|
||||
"option-value": `value`,
|
||||
"aria-label": `日志排序字段`,
|
||||
onChange: unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `onChange`],
|
||||
),
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(z),
|
||||
"onUpdate:modelValue": (r[2] ||= (e) =>
|
||||
isRef(z) ? (z.value = e) : null),
|
||||
options: [
|
||||
{
|
||||
label: `降序`,
|
||||
value: `desc`,
|
||||
},
|
||||
{
|
||||
label: `升序`,
|
||||
value: `asc`,
|
||||
},
|
||||
],
|
||||
"option-label": `label`,
|
||||
"option-value": `value`,
|
||||
"aria-label": `日志排序方向`,
|
||||
onChange: unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `onChange`],
|
||||
),
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
modelValue: unref(y),
|
||||
"onUpdate:modelValue": (r[3] ||= (e) =>
|
||||
isRef(y) ? (y.value = e) : null),
|
||||
class: `list-search`,
|
||||
placeholder: `输入关键字`,
|
||||
onKeyup: withKeys(Y, [`enter`]),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(g, {
|
||||
label: `清除筛选`,
|
||||
icon: `pi pi-filter-slash`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
size: `small`,
|
||||
onClick: X,
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, M, [
|
||||
createVNode(
|
||||
I,
|
||||
{
|
||||
value: unref(B),
|
||||
loading: unref(H),
|
||||
lazy: ``,
|
||||
rows: unref(G),
|
||||
totalRecords: unref(V),
|
||||
first: (unref(W) - 1) * unref(G),
|
||||
dataKey: `id`,
|
||||
},
|
||||
{
|
||||
empty: withCtx(() => [
|
||||
createVNode(
|
||||
O,
|
||||
{
|
||||
icon: `pi pi-history`,
|
||||
title: unref(H) ? `加载中…` : `暂无日志`,
|
||||
description: unref(J)
|
||||
? `换个关键字试试`
|
||||
: `账户操作与登录记录会显示在这里`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`title`, `description`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createVNode(
|
||||
F,
|
||||
{
|
||||
header: `创建时间`,
|
||||
style: {
|
||||
width: `180px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: n }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
(`formatTime` in t
|
||||
? t.formatTime
|
||||
: unref(dict_r))(n.create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
F,
|
||||
{
|
||||
field: `id`,
|
||||
header: `ID`,
|
||||
style: {
|
||||
width: `120px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(`#` + toDisplayString(t.id), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
F,
|
||||
{
|
||||
header: `操作内容`,
|
||||
style: {
|
||||
"min-width": `320px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
unref(operationMessage)(t.description),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
F,
|
||||
{
|
||||
header: `IP`,
|
||||
style: {
|
||||
width: `200px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
N,
|
||||
toDisplayString(t.ip || `—`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`value`, `loading`, `rows`, `totalRecords`, `first`],
|
||||
),
|
||||
]),
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
Z,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(U)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(V) > 0
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, P, [
|
||||
(r[4] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `list-bulk`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
Q,
|
||||
{
|
||||
rows: unref(G),
|
||||
totalRecords: unref(V),
|
||||
first: (unref(W) - 1) * unref(G),
|
||||
rowsPerPageOptions: [20, 50, 100],
|
||||
onPage: unref(K),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`rows`, `totalRecords`, `first`, `onPage`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-0e32233b`]],
|
||||
);
|
||||
export {};
|
||||
export default F;
|
||||
</script>
|
||||
@@ -0,0 +1,568 @@
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
watch,
|
||||
} from "vue";
|
||||
import { useHead, useRoute, useRouter } from "#app";
|
||||
import { NuxtLink } from "#components";
|
||||
import Button from "primevue/button";
|
||||
import InputText from "primevue/inputtext";
|
||||
import Message from "primevue/message";
|
||||
import Password from "primevue/password";
|
||||
import AuthProviders from "~/components/AuthProviders.vue";
|
||||
import CaptchaField from "~/components/CaptchaField.vue";
|
||||
import GenericOAuthProviders from "~/components/GenericOAuthProviders.vue";
|
||||
import SecurityVerificationDialog from "~/components/SecurityVerificationDialog.vue";
|
||||
import { loginErrorMessage, securityChallenge, useAuth } from "~/lib/auth.js";
|
||||
import { r as safeRedirect, t as withRedirect } from "~/lib/auth-redirect.js";
|
||||
import { t as useCaptcha } from "~/lib/useCaptcha.js";
|
||||
import { t as useSiteConfig } from "~/lib/useSiteConfig.js";
|
||||
import { t as useVerifyCode } from "~/lib/useVerifyCode.js";
|
||||
import "~/assets/styles/SecurityVerificationDialog.skYFo4v7.css";
|
||||
import "~/assets/styles/GenericOAuthProviders.Bv8oNwXP.css";
|
||||
import "~/assets/styles/GeetestField.DiieTibK.css";
|
||||
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
|
||||
import "~/assets/styles/AuthProviders.CgAWouSf.css";
|
||||
import "~/assets/styles/login.Clyo2_3T.css";
|
||||
|
||||
definePageMeta({ layout: "blank" });
|
||||
useHead({ title: "登录 - 破碎工坊网络" });
|
||||
|
||||
const auth = useAuth();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const site = useSiteConfig();
|
||||
const { config, error: configError } = site;
|
||||
const form = reactive({ account: "", password: "", code: "" });
|
||||
const loginMode = ref("password");
|
||||
const phoneCode = ref("86");
|
||||
const errorMessage = ref("");
|
||||
const submitting = ref(false);
|
||||
const authProviders = ref(null);
|
||||
const securityDialogVisible = ref(false);
|
||||
const challenge = ref({});
|
||||
const pendingCredentials = ref(null);
|
||||
const pendingVerification = ref(null);
|
||||
let attemptVersion = 0;
|
||||
|
||||
const phonePasswordEnabled = computed(
|
||||
() =>
|
||||
config.value?.login_phone_password === undefined ||
|
||||
site.on(config.value.login_phone_password),
|
||||
);
|
||||
const emailPasswordEnabled = computed(
|
||||
() =>
|
||||
config.value?.login_email_password === undefined ||
|
||||
site.on(config.value.login_email_password),
|
||||
);
|
||||
const passwordLoginEnabled = computed(
|
||||
() => phonePasswordEnabled.value || emailPasswordEnabled.value,
|
||||
);
|
||||
const codeLoginEnabled = computed(() =>
|
||||
site.on(config.value?.login_phone_verify),
|
||||
);
|
||||
const registrationEnabled = computed(
|
||||
() =>
|
||||
config.value?.register_phone === undefined ||
|
||||
config.value?.register_email === undefined ||
|
||||
site.on(config.value.register_phone) ||
|
||||
site.on(config.value.register_email),
|
||||
);
|
||||
const isPhoneAccount = computed(
|
||||
() => loginMode.value === "code" || !form.account.includes("@"),
|
||||
);
|
||||
const formLocked = computed(
|
||||
() =>
|
||||
submitting.value ||
|
||||
securityDialogVisible.value ||
|
||||
!!pendingVerification.value,
|
||||
);
|
||||
const securityContext = computed(() => ({
|
||||
scene: "login",
|
||||
account: pendingCredentials.value?.account,
|
||||
phoneCode: pendingCredentials.value?.phoneCode,
|
||||
}));
|
||||
const passwordWasReset = computed(() => route.query.reset === "1");
|
||||
const registrationSucceeded = computed(() => route.query.registered === "1");
|
||||
|
||||
const captcha = useCaptcha("login");
|
||||
const {
|
||||
needed: captchaNeeded,
|
||||
provider: captchaProvider,
|
||||
captchaId,
|
||||
img: captchaImage,
|
||||
token: captchaToken,
|
||||
value: captchaValue,
|
||||
loading: captchaLoading,
|
||||
configLoading: captchaConfigLoading,
|
||||
error: captchaError,
|
||||
load: loadCaptcha,
|
||||
complete: completeCaptcha,
|
||||
invalidate: invalidateCaptcha,
|
||||
} = captcha;
|
||||
const {
|
||||
sending: sendingCode,
|
||||
countdown: codeCountdown,
|
||||
send: sendCode,
|
||||
} = useVerifyCode({
|
||||
action: "login",
|
||||
captcha,
|
||||
error: errorMessage,
|
||||
phoneCode: () => phoneCode.value,
|
||||
});
|
||||
const fieldsDisabled = computed(() => formLocked.value || sendingCode.value);
|
||||
const captchaBusy = computed(
|
||||
() => captchaConfigLoading.value || captchaLoading.value,
|
||||
);
|
||||
|
||||
onMounted(() => site.load());
|
||||
watch(
|
||||
config,
|
||||
(settings) => {
|
||||
if (formLocked.value || sendingCode.value) return;
|
||||
if (
|
||||
codeLoginEnabled.value &&
|
||||
(settings?.first_login_method === "code" || !passwordLoginEnabled.value)
|
||||
) {
|
||||
loginMode.value = "code";
|
||||
} else if (!codeLoginEnabled.value) {
|
||||
loginMode.value = "password";
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
watch([() => form.account, loginMode], () => {
|
||||
form.code = "";
|
||||
errorMessage.value = "";
|
||||
});
|
||||
|
||||
function setLoginMode(mode) {
|
||||
if (
|
||||
fieldsDisabled.value ||
|
||||
!(mode === "code" ? codeLoginEnabled.value : passwordLoginEnabled.value)
|
||||
)
|
||||
return;
|
||||
loginMode.value = mode;
|
||||
}
|
||||
|
||||
function sendLoginCode() {
|
||||
if (loginMode.value !== "code" || fieldsDisabled.value) return;
|
||||
if (!config.value) {
|
||||
errorMessage.value = "登录设置暂不可用,请重新加载";
|
||||
return;
|
||||
}
|
||||
if (!codeLoginEnabled.value) {
|
||||
errorMessage.value = "当前登录方式未开放,请选择其他方式";
|
||||
return;
|
||||
}
|
||||
const account = form.account.trim();
|
||||
if (account.includes("@")) {
|
||||
errorMessage.value = "请输入手机号";
|
||||
return;
|
||||
}
|
||||
return sendCode("phone", account, "请输入手机号");
|
||||
}
|
||||
|
||||
function cancelLogin() {
|
||||
attemptVersion += 1;
|
||||
securityDialogVisible.value = false;
|
||||
pendingCredentials.value = null;
|
||||
pendingVerification.value = null;
|
||||
submitting.value = false;
|
||||
errorMessage.value = "";
|
||||
}
|
||||
onBeforeUnmount(cancelLogin);
|
||||
|
||||
async function attemptLogin(credentials, verification) {
|
||||
const methodEnabled =
|
||||
credentials.type === "code"
|
||||
? codeLoginEnabled.value
|
||||
: credentials.account.includes("@")
|
||||
? emailPasswordEnabled.value
|
||||
: phonePasswordEnabled.value;
|
||||
if (!config.value || !methodEnabled) {
|
||||
cancelLogin();
|
||||
errorMessage.value = config.value
|
||||
? "当前登录方式未开放,请选择其他方式"
|
||||
: "登录设置暂不可用,请重新加载";
|
||||
return;
|
||||
}
|
||||
|
||||
const version = attemptVersion;
|
||||
submitting.value = true;
|
||||
errorMessage.value = "";
|
||||
try {
|
||||
await auth.login(
|
||||
credentials.account,
|
||||
credentials.password,
|
||||
credentials.captcha,
|
||||
credentials.token,
|
||||
credentials.type,
|
||||
credentials.code,
|
||||
credentials.phoneCode,
|
||||
verification,
|
||||
);
|
||||
if (version !== attemptVersion) return;
|
||||
authProviders.value?.resetQr();
|
||||
securityDialogVisible.value = false;
|
||||
pendingCredentials.value = null;
|
||||
pendingVerification.value = null;
|
||||
await router.push(safeRedirect(route.query.redirect));
|
||||
} catch (error) {
|
||||
if (version !== attemptVersion) return;
|
||||
const nextChallenge = securityChallenge(error);
|
||||
if (nextChallenge) {
|
||||
pendingCredentials.value = credentials;
|
||||
pendingVerification.value = null;
|
||||
challenge.value = nextChallenge;
|
||||
securityDialogVisible.value = true;
|
||||
} else {
|
||||
errorMessage.value = loginErrorMessage(error);
|
||||
const captchaRequired = await captcha.handleError(error);
|
||||
if (version !== attemptVersion) return;
|
||||
if (
|
||||
captchaRequired &&
|
||||
verification?.security_verify_method === "certification"
|
||||
) {
|
||||
pendingCredentials.value = credentials;
|
||||
pendingVerification.value = { ...verification };
|
||||
securityDialogVisible.value = false;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (version === attemptVersion) submitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSecurityVerification(verification) {
|
||||
const credentials = pendingCredentials.value;
|
||||
if (!credentials || submitting.value || pendingVerification.value) return;
|
||||
if (
|
||||
verification.security_verify_method === "certification" &&
|
||||
credentials.type === "password" &&
|
||||
captchaNeeded.value
|
||||
) {
|
||||
// Certification returns to this form for a fresh CAPTCHA before continuing the same login.
|
||||
pendingVerification.value = { ...verification };
|
||||
securityDialogVisible.value = false;
|
||||
errorMessage.value = "";
|
||||
invalidateCaptcha();
|
||||
await loadCaptcha();
|
||||
return;
|
||||
}
|
||||
await attemptLogin(credentials, verification);
|
||||
}
|
||||
|
||||
async function submitLogin() {
|
||||
if (submitting.value || sendingCode.value || securityDialogVisible.value)
|
||||
return;
|
||||
errorMessage.value = "";
|
||||
if (pendingVerification.value && pendingCredentials.value) {
|
||||
const validationError = captcha.validationError();
|
||||
if (validationError) {
|
||||
errorMessage.value = validationError;
|
||||
return;
|
||||
}
|
||||
await attemptLogin(
|
||||
{
|
||||
...pendingCredentials.value,
|
||||
captcha: captchaValue.value.trim(),
|
||||
token: captchaToken.value,
|
||||
},
|
||||
pendingVerification.value,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!form.account.trim()) {
|
||||
errorMessage.value = "请输入手机号或邮箱";
|
||||
return;
|
||||
}
|
||||
if (!config.value) {
|
||||
errorMessage.value = "登录设置暂不可用,请重新加载";
|
||||
return;
|
||||
}
|
||||
if (
|
||||
(loginMode.value === "code" && !codeLoginEnabled.value) ||
|
||||
(loginMode.value === "password" &&
|
||||
!(isPhoneAccount.value
|
||||
? phonePasswordEnabled.value
|
||||
: emailPasswordEnabled.value))
|
||||
) {
|
||||
errorMessage.value = "当前登录方式未开放,请选择其他方式";
|
||||
return;
|
||||
}
|
||||
if (isPhoneAccount.value && !/^[1-9]\d{0,3}$/.test(phoneCode.value)) {
|
||||
errorMessage.value = "请输入有效的国际电话区号";
|
||||
return;
|
||||
}
|
||||
if (loginMode.value === "code" && form.account.includes("@")) {
|
||||
errorMessage.value = "请输入手机号";
|
||||
return;
|
||||
}
|
||||
if (loginMode.value === "code" && !form.code.trim()) {
|
||||
errorMessage.value = "请输入验证码";
|
||||
return;
|
||||
}
|
||||
if (loginMode.value === "password" && !form.password) {
|
||||
errorMessage.value = "请输入密码";
|
||||
return;
|
||||
}
|
||||
const validationError =
|
||||
loginMode.value === "password" ? captcha.validationError() : "";
|
||||
if (validationError) {
|
||||
errorMessage.value = validationError;
|
||||
return;
|
||||
}
|
||||
attemptVersion += 1;
|
||||
await attemptLogin({
|
||||
account: form.account.trim(),
|
||||
password: loginMode.value === "password" ? form.password : "",
|
||||
captcha: captchaValue.value.trim(),
|
||||
token: captchaToken.value,
|
||||
type: loginMode.value,
|
||||
code: form.code.trim(),
|
||||
phoneCode: isPhoneAccount.value ? phoneCode.value : "",
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="auth-shell">
|
||||
<div class="auth-card login-card">
|
||||
<div class="login-main">
|
||||
<div class="login-brand"><h1>欢迎回来</h1></div>
|
||||
<form class="login-form" @submit.prevent="submitLogin">
|
||||
<div class="seg" role="group" aria-label="登录方式">
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: loginMode === 'password' }"
|
||||
:aria-pressed="loginMode === 'password'"
|
||||
:disabled="!passwordLoginEnabled || fieldsDisabled"
|
||||
@click="setLoginMode('password')"
|
||||
>
|
||||
密码登录
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:class="{ active: loginMode === 'code' }"
|
||||
:aria-pressed="loginMode === 'code'"
|
||||
:disabled="!codeLoginEnabled || fieldsDisabled"
|
||||
@click="setLoginMode('code')"
|
||||
>
|
||||
验证码登录
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Message
|
||||
v-if="passwordWasReset && !errorMessage"
|
||||
severity="success"
|
||||
:closable="false"
|
||||
icon="pi pi-check-circle"
|
||||
>密码已重置,请使用新密码登录</Message
|
||||
>
|
||||
<Message
|
||||
v-if="registrationSucceeded && !errorMessage"
|
||||
severity="success"
|
||||
:closable="false"
|
||||
>注册成功,请登录</Message
|
||||
>
|
||||
<Message v-if="configError" severity="error" :closable="false">
|
||||
{{ configError }}
|
||||
<Button label="重新加载" text @click="site.load" />
|
||||
</Message>
|
||||
<Message
|
||||
v-else-if="!passwordLoginEnabled && !codeLoginEnabled"
|
||||
severity="info"
|
||||
:closable="false"
|
||||
>账号登录暂未开放,请使用已开放的其他登录方式</Message
|
||||
>
|
||||
<Message v-if="pendingVerification" severity="info" :closable="false"
|
||||
>实名认证已通过,请完成新的人机验证后继续登录。</Message
|
||||
>
|
||||
|
||||
<div class="field">
|
||||
<label for="account">账号</label>
|
||||
<InputText
|
||||
id="account"
|
||||
v-model="form.account"
|
||||
:placeholder="
|
||||
loginMode === 'code' ? '输入手机号' : '输入手机号/邮箱'
|
||||
"
|
||||
autocomplete="username"
|
||||
:invalid="!!errorMessage"
|
||||
:aria-describedby="errorMessage ? 'login-error' : undefined"
|
||||
:disabled="fieldsDisabled"
|
||||
fluid
|
||||
/>
|
||||
</div>
|
||||
<div v-if="loginMode === 'code'" class="field">
|
||||
<label for="login-code">验证码</label>
|
||||
<!-- Retain the deployed scoped selectors without changing the shared stylesheet. -->
|
||||
<div class="code-row" data-v-7896f676>
|
||||
<InputText
|
||||
id="login-code"
|
||||
v-model="form.code"
|
||||
autocomplete="one-time-code"
|
||||
placeholder="请输入验证码"
|
||||
:disabled="fieldsDisabled"
|
||||
fluid
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
:label="codeCountdown > 0 ? `${codeCountdown}s` : '获取验证码'"
|
||||
:loading="sendingCode"
|
||||
:disabled="
|
||||
codeCountdown > 0 ||
|
||||
fieldsDisabled ||
|
||||
!codeLoginEnabled ||
|
||||
captchaBusy
|
||||
"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="sendLoginCode"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loginMode === 'password'" class="field">
|
||||
<div class="field-label-row">
|
||||
<label for="password">密码</label>
|
||||
<NuxtLink
|
||||
:to="withRedirect('/forgot-password', route.query.redirect)"
|
||||
class="field-link"
|
||||
>忘记密码?</NuxtLink
|
||||
>
|
||||
</div>
|
||||
<Password
|
||||
input-id="password"
|
||||
v-model="form.password"
|
||||
placeholder="请输入密码"
|
||||
:feedback="false"
|
||||
toggle-mask
|
||||
autocomplete="current-password"
|
||||
:invalid="!!errorMessage"
|
||||
:input-props="{
|
||||
'aria-describedby': errorMessage ? 'login-error' : undefined,
|
||||
}"
|
||||
:disabled="fieldsDisabled"
|
||||
fluid
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="login-captcha" data-v-7896f676 :aria-busy="captchaBusy">
|
||||
<button
|
||||
v-if="captchaBusy || captchaError"
|
||||
type="button"
|
||||
class="captcha-placeholder"
|
||||
data-v-7896f676
|
||||
:class="{ 'has-error': !!captchaError }"
|
||||
:disabled="
|
||||
captchaBusy ||
|
||||
submitting ||
|
||||
sendingCode ||
|
||||
securityDialogVisible ||
|
||||
!captchaNeeded
|
||||
"
|
||||
:aria-label="captchaError || '正在加载验证…'"
|
||||
@click="loadCaptcha"
|
||||
>
|
||||
<i
|
||||
:class="
|
||||
captchaError
|
||||
? 'pi pi-exclamation-circle'
|
||||
: 'pi pi-spin pi-spinner'
|
||||
"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span
|
||||
:role="captchaError ? 'alert' : 'status'"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>{{ captchaError || "正在加载验证…" }}</span
|
||||
>
|
||||
</button>
|
||||
<CaptchaField
|
||||
v-else-if="captchaNeeded"
|
||||
v-model="captchaValue"
|
||||
:img="captchaImage"
|
||||
:provider="captchaProvider"
|
||||
:captcha-id="captchaId"
|
||||
:disabled="submitting || sendingCode || securityDialogVisible"
|
||||
@verified="completeCaptcha"
|
||||
@invalid="invalidateCaptcha"
|
||||
@refresh="loadCaptcha"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Message
|
||||
v-if="errorMessage"
|
||||
id="login-error"
|
||||
severity="error"
|
||||
:closable="false"
|
||||
icon="pi pi-exclamation-circle"
|
||||
class="login-error"
|
||||
>{{ errorMessage }}</Message
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
:label="
|
||||
submitting
|
||||
? '正在登录…'
|
||||
: pendingVerification
|
||||
? '继续登录'
|
||||
: '登录'
|
||||
"
|
||||
:loading="submitting"
|
||||
:disabled="
|
||||
submitting ||
|
||||
sendingCode ||
|
||||
securityDialogVisible ||
|
||||
captchaBusy ||
|
||||
!config ||
|
||||
(!passwordLoginEnabled && !codeLoginEnabled)
|
||||
"
|
||||
class="login-btn"
|
||||
fluid
|
||||
/>
|
||||
<Button
|
||||
v-if="pendingVerification"
|
||||
label="取消本次登录"
|
||||
type="button"
|
||||
severity="secondary"
|
||||
text
|
||||
:disabled="submitting"
|
||||
@click="cancelLogin"
|
||||
/>
|
||||
<Button
|
||||
v-if="registrationEnabled"
|
||||
v-slot="{ class: buttonClass, a11yAttrs }"
|
||||
as-child
|
||||
severity="secondary"
|
||||
fluid
|
||||
>
|
||||
<NuxtLink
|
||||
:to="withRedirect('/register', route.query.redirect)"
|
||||
:class="[buttonClass, 'register-btn']"
|
||||
v-bind="a11yAttrs"
|
||||
><span class="p-button-label">注册账号</span></NuxtLink
|
||||
>
|
||||
</Button>
|
||||
<SecurityVerificationDialog
|
||||
v-model:visible="securityDialogVisible"
|
||||
:challenge="challenge"
|
||||
:context="securityContext"
|
||||
:busy="submitting"
|
||||
:request-error="errorMessage"
|
||||
@verified="confirmSecurityVerification"
|
||||
@cancel="cancelLogin"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<AuthProviders ref="authProviders" />
|
||||
<GenericOAuthProviders />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,904 @@
|
||||
<script>
|
||||
import "~/assets/styles/NotificationPreferences.DcH8Noxd.css";
|
||||
import "~/assets/styles/messages.asRdYcVu.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
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 { 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 { useRoute } 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 inputtext from "primevue/inputtext";
|
||||
import { r as dict_r } from "~/lib/dict.js";
|
||||
import datatable from "primevue/datatable";
|
||||
import paginator from "primevue/paginator";
|
||||
import iconfield from "primevue/iconfield";
|
||||
import inputicon from "primevue/inputicon";
|
||||
import select from "primevue/select";
|
||||
import column from "primevue/column";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import { t as useListPage_t } from "~/lib/useListPage.js";
|
||||
import tag from "primevue/tag";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import NotificationPreferences from "~/components/NotificationPreferences.vue";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import { t as useMailbox_t } from "~/lib/useMailbox.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var ge = {
|
||||
class: `list-page`,
|
||||
},
|
||||
_e = {
|
||||
class: `list-head`,
|
||||
},
|
||||
ve = {
|
||||
class: `list-head-actions`,
|
||||
},
|
||||
ye = {
|
||||
class: `message-panel`,
|
||||
},
|
||||
be = {
|
||||
class: `list-toolbar`,
|
||||
},
|
||||
xe = {
|
||||
class: `selection-toolbar`,
|
||||
},
|
||||
Se = {
|
||||
class: `selection-summary`,
|
||||
},
|
||||
Ce = {
|
||||
class: `bulk-actions`,
|
||||
},
|
||||
we = {
|
||||
key: 1,
|
||||
class: `message-error`,
|
||||
},
|
||||
Te = {
|
||||
key: 2,
|
||||
class: `list-table`,
|
||||
},
|
||||
Ee = [`onClick`],
|
||||
De = {
|
||||
key: 0,
|
||||
class: `mail-dot`,
|
||||
},
|
||||
Oe = {
|
||||
key: 3,
|
||||
class: `list-foot`,
|
||||
},
|
||||
ke = {
|
||||
key: 0,
|
||||
class: `detail-state`,
|
||||
},
|
||||
w = {
|
||||
key: 1,
|
||||
class: `detail-state`,
|
||||
},
|
||||
Ae = {
|
||||
class: `detail-meta`,
|
||||
},
|
||||
je = [`innerHTML`],
|
||||
Me = {
|
||||
class: `detail-nav`,
|
||||
},
|
||||
Ne = {
|
||||
class: `confirm-text`,
|
||||
},
|
||||
T = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `index`,
|
||||
setup(p) {
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let y = useApi(),
|
||||
T = useRoute(),
|
||||
{ types: E, refresh: D } = useMailbox_t(),
|
||||
O = ref(null),
|
||||
k = ref(``),
|
||||
A = ref(``),
|
||||
j = ref(``),
|
||||
{
|
||||
list: M,
|
||||
total: N,
|
||||
loading: P,
|
||||
error: F,
|
||||
page: I,
|
||||
limit: L,
|
||||
onPage: Pe,
|
||||
reload: R,
|
||||
} = useListPage_t(`/client_care/mail/list`, {
|
||||
limit: 10,
|
||||
params: () => ({
|
||||
orderby: `id`,
|
||||
sort: `desc`,
|
||||
read: O.value ?? ``,
|
||||
type: k.value,
|
||||
keywords: j.value,
|
||||
}),
|
||||
}),
|
||||
z = ref([]),
|
||||
B = ref(!1),
|
||||
V = computed(() => O.value !== null || !!k.value || !!j.value),
|
||||
Fe = [
|
||||
{
|
||||
label: `全部消息`,
|
||||
value: null,
|
||||
},
|
||||
{
|
||||
label: `未读`,
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: `已读`,
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
Ie = computed(() => [
|
||||
{
|
||||
label: `全部类型`,
|
||||
value: ``,
|
||||
},
|
||||
...E.value.map((e) => ({
|
||||
label: e.name_lang || e.name,
|
||||
value: e.name,
|
||||
})),
|
||||
]);
|
||||
function H(e) {
|
||||
return E.value.find((t) => t.name === e)?.name_lang || e || `—`;
|
||||
}
|
||||
function Le() {
|
||||
((j.value = A.value.trim()), R());
|
||||
}
|
||||
function Re() {
|
||||
((A.value = ``),
|
||||
(j.value = ``),
|
||||
(O.value = null),
|
||||
(k.value = ``),
|
||||
R());
|
||||
}
|
||||
async function ze(e) {
|
||||
if (!(!e.length || B.value || G.value)) {
|
||||
((B.value = !0), (U.value = ``));
|
||||
try {
|
||||
(await y.put(`/client_care/mail/read`, {
|
||||
id: e,
|
||||
}),
|
||||
(z.value = []),
|
||||
await R(),
|
||||
await D());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `操作失败`;
|
||||
} finally {
|
||||
B.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function Be() {
|
||||
if (!(B.value || G.value)) {
|
||||
((B.value = !0), (U.value = ``));
|
||||
try {
|
||||
(await y.put(`/client_care/mail/read`, {
|
||||
all: 1,
|
||||
}),
|
||||
(z.value = []),
|
||||
await R(),
|
||||
await D());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `操作失败`;
|
||||
} finally {
|
||||
B.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
let U = ref(``),
|
||||
W = ref(!1),
|
||||
G = ref(!1);
|
||||
function Ve() {
|
||||
!z.value.length ||
|
||||
B.value ||
|
||||
G.value ||
|
||||
((U.value = ``), (W.value = !0));
|
||||
}
|
||||
async function He() {
|
||||
if (!z.value.length || G.value || B.value) return;
|
||||
let e = z.value.map((e) => e.id);
|
||||
((G.value = !0), (U.value = ``));
|
||||
try {
|
||||
(await y.del(`/client_care/mail`, {
|
||||
id: e,
|
||||
}),
|
||||
(W.value = !1),
|
||||
(z.value = []),
|
||||
await R(),
|
||||
await D());
|
||||
} catch (e) {
|
||||
((W.value = !1),
|
||||
(U.value = e instanceof Error ? e.message : `删除失败`));
|
||||
} finally {
|
||||
G.value = !1;
|
||||
}
|
||||
}
|
||||
let K = ref(!1),
|
||||
q = ref(null),
|
||||
J = ref(!1),
|
||||
Y = ref(``),
|
||||
X = ref(null),
|
||||
Z = 0;
|
||||
async function Q(e) {
|
||||
let t = ++Z;
|
||||
((X.value = e),
|
||||
(K.value = !0),
|
||||
(J.value = !0),
|
||||
(Y.value = ``),
|
||||
(q.value = null));
|
||||
try {
|
||||
let n = await y.get(`/client_care/mail/${e}`);
|
||||
if (t !== Z) return;
|
||||
if (!n?.mail?.id) {
|
||||
Y.value = `消息不存在或已删除`;
|
||||
return;
|
||||
}
|
||||
((q.value = n.mail), (J.value = !1));
|
||||
let r = M.value.find((t) => t.id === e);
|
||||
if (!r || r.read === 0)
|
||||
try {
|
||||
(await y.put(`/client_care/mail/read`, {
|
||||
id: [e],
|
||||
}),
|
||||
r && (r.read = 1),
|
||||
await D());
|
||||
} catch {}
|
||||
} catch (e) {
|
||||
t === Z && (Y.value = e instanceof Error ? e.message : `加载失败`);
|
||||
} finally {
|
||||
t === Z && (J.value = !1);
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(async () => {
|
||||
await D();
|
||||
let e = Number(T.query.id);
|
||||
e && Q(e);
|
||||
}),
|
||||
(t, i) => {
|
||||
let s = button,
|
||||
p = NotificationPreferences,
|
||||
_ = inputicon,
|
||||
v = inputtext,
|
||||
y = iconfield,
|
||||
x = select,
|
||||
S = message,
|
||||
C = column,
|
||||
T = ListEmpty,
|
||||
E = datatable,
|
||||
D = paginator,
|
||||
j = skeleton,
|
||||
Z = tag,
|
||||
$ = dialog;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, ge, [
|
||||
createElementVNode(`div`, _e, [
|
||||
(i[12] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `page-heading`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`h2`, null, `消息`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`查看产品、订单与账户的重要通知`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, ve, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `全部已读`,
|
||||
icon: `pi pi-check`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
disabled: !unref(N) || unref(P) || unref(G),
|
||||
loading: unref(B),
|
||||
onClick: Be,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`, `loading`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createVNode(p),
|
||||
createElementVNode(`section`, ye, [
|
||||
createElementVNode(`div`, be, [
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
class: `list-toolbar-right`,
|
||||
onSubmit: withModifiers(Le, [`prevent`]),
|
||||
},
|
||||
[
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
class: `search-field`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(_, {
|
||||
class: `pi pi-search`,
|
||||
}),
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
modelValue: unref(A),
|
||||
"onUpdate:modelValue": (i[0] ||= (e) =>
|
||||
isRef(A) ? (A.value = e) : null),
|
||||
class: `list-search`,
|
||||
placeholder: `搜索消息标题`,
|
||||
"aria-label": `搜索消息标题`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
x,
|
||||
{
|
||||
modelValue: unref(O),
|
||||
"onUpdate:modelValue": (i[1] ||= (e) =>
|
||||
isRef(O) ? (O.value = e) : null),
|
||||
class: `list-select`,
|
||||
options: Fe,
|
||||
optionLabel: `label`,
|
||||
optionValue: `value`,
|
||||
"aria-label": `阅读状态`,
|
||||
onChange: unref(R),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `onChange`],
|
||||
),
|
||||
createVNode(
|
||||
x,
|
||||
{
|
||||
modelValue: unref(k),
|
||||
"onUpdate:modelValue": (i[2] ||= (e) =>
|
||||
isRef(k) ? (k.value = e) : null),
|
||||
class: `list-select`,
|
||||
options: unref(Ie),
|
||||
optionLabel: `label`,
|
||||
optionValue: `value`,
|
||||
"aria-label": `消息类型`,
|
||||
onChange: unref(R),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`, `onChange`],
|
||||
),
|
||||
createVNode(s, {
|
||||
type: `submit`,
|
||||
label: `搜索`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
}),
|
||||
unref(V)
|
||||
? (openBlock(),
|
||||
createBlock(s, {
|
||||
key: 0,
|
||||
label: `清除筛选`,
|
||||
icon: `pi pi-filter-slash`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: Re,
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
],
|
||||
32,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, xe, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
Se,
|
||||
toDisplayString(
|
||||
unref(z).length
|
||||
? `已选择 ${unref(z).length} 条消息`
|
||||
: `共 ${unref(N)} 条消息`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`div`, Ce, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `标记已读`,
|
||||
icon: `pi pi-envelope-open`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
disabled: !unref(z).length || unref(B) || unref(G),
|
||||
onClick: (i[3] ||= (e) =>
|
||||
ze(unref(z).map((e) => e.id))),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `删除`,
|
||||
icon: `pi pi-trash`,
|
||||
size: `small`,
|
||||
severity: `danger`,
|
||||
text: ``,
|
||||
disabled: !unref(z).length || unref(B) || unref(G),
|
||||
onClick: Ve,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
S,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(U)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(F)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, we, [
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(F)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `重新加载消息`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: unref(R),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`onClick`],
|
||||
),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, Te, [
|
||||
createVNode(
|
||||
E,
|
||||
{
|
||||
selection: unref(z),
|
||||
"onUpdate:selection": (i[4] ||= (e) =>
|
||||
isRef(z) ? (z.value = e) : null),
|
||||
value: unref(M),
|
||||
loading: unref(P),
|
||||
lazy: ``,
|
||||
scrollable: ``,
|
||||
rows: unref(L),
|
||||
totalRecords: unref(N),
|
||||
first: (unref(I) - 1) * unref(L),
|
||||
dataKey: `id`,
|
||||
},
|
||||
{
|
||||
empty: withCtx(() => [
|
||||
createVNode(
|
||||
T,
|
||||
{
|
||||
icon: `pi pi-envelope`,
|
||||
title: unref(P)
|
||||
? `加载中…`
|
||||
: unref(V)
|
||||
? `没有符合条件的消息`
|
||||
: `还没有消息`,
|
||||
description: unref(V)
|
||||
? `换个筛选条件试试`
|
||||
: `订单、产品、财务等重要通知会出现在这里`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`title`, `description`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createVNode(C, {
|
||||
selectionMode: `multiple`,
|
||||
style: {
|
||||
width: `3rem`,
|
||||
},
|
||||
}),
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
header: `标题`,
|
||||
style: {
|
||||
"min-width": `260px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass([
|
||||
`mail-title`,
|
||||
{
|
||||
unread: t.read === 0,
|
||||
},
|
||||
]),
|
||||
onClick: (e) => Q(t.id),
|
||||
},
|
||||
[
|
||||
t.read === 0
|
||||
? (openBlock(),
|
||||
createElementBlock(`span`, De))
|
||||
: createCommentVNode(``, !0),
|
||||
createTextVNode(
|
||||
` ` + toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
],
|
||||
10,
|
||||
Ee,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
header: `类型`,
|
||||
style: {
|
||||
width: `150px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(H(t.type)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
header: `接收时间`,
|
||||
style: {
|
||||
"min-width": `160px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: n }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
(`formatTime` in t
|
||||
? t.formatTime
|
||||
: unref(dict_r))(n.create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[
|
||||
`selection`,
|
||||
`value`,
|
||||
`loading`,
|
||||
`rows`,
|
||||
`totalRecords`,
|
||||
`first`,
|
||||
],
|
||||
),
|
||||
])),
|
||||
unref(N) > 0
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, Oe, [
|
||||
(i[13] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `list-bulk`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
D,
|
||||
{
|
||||
rows: unref(L),
|
||||
totalRecords: unref(N),
|
||||
first: (unref(I) - 1) * unref(L),
|
||||
rowsPerPageOptions: [10, 20, 50],
|
||||
onPage: unref(Pe),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`rows`, `totalRecords`, `first`, `onPage`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
createVNode(
|
||||
$,
|
||||
{
|
||||
visible: unref(K),
|
||||
"onUpdate:visible": (i[9] ||= (e) =>
|
||||
isRef(K) ? (K.value = e) : null),
|
||||
header: unref(q)?.title || `消息详情`,
|
||||
modal: ``,
|
||||
style: {
|
||||
width: `680px`,
|
||||
},
|
||||
draggable: !1,
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
createElementVNode(`div`, Me, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `上一条`,
|
||||
icon: `pi pi-angle-left`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
disabled: !unref(q)?.prev?.id,
|
||||
onClick: (i[6] ||= (e) =>
|
||||
unref(q)?.prev?.id && Q(unref(q).prev.id)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `下一条`,
|
||||
icon: `pi pi-angle-right`,
|
||||
iconPos: `right`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
disabled: !unref(q)?.next?.id,
|
||||
onClick: (i[7] ||= (e) =>
|
||||
unref(q)?.next?.id && Q(unref(q).next.id)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
]),
|
||||
createVNode(s, {
|
||||
label: `关闭`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: (i[8] ||= (e) => (K.value = !1)),
|
||||
}),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
unref(J)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, ke, [
|
||||
createVNode(j, {
|
||||
height: `18px`,
|
||||
width: `45%`,
|
||||
}),
|
||||
createVNode(j, {
|
||||
height: `150px`,
|
||||
}),
|
||||
]))
|
||||
: unref(Y)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, w, [
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(Y)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(s, {
|
||||
label: `重新加载消息`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: (i[5] ||= (e) =>
|
||||
unref(X) && Q(unref(X))),
|
||||
}),
|
||||
]))
|
||||
: unref(q)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 2,
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, Ae, [
|
||||
createVNode(
|
||||
Z,
|
||||
{
|
||||
value: H(unref(q).type),
|
||||
severity: `secondary`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`value`],
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(
|
||||
(`formatTime` in t
|
||||
? t.formatTime
|
||||
: unref(dict_r))(
|
||||
unref(q).create_time,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `detail-body`,
|
||||
innerHTML: (`sanitizeHtml` in t
|
||||
? t.sanitizeHtml
|
||||
: unref(sanitize_n))(unref(q).content),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
je,
|
||||
),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `header`],
|
||||
),
|
||||
createVNode(
|
||||
$,
|
||||
{
|
||||
visible: unref(W),
|
||||
"onUpdate:visible": (i[11] ||= (e) =>
|
||||
isRef(W) ? (W.value = e) : null),
|
||||
header: `删除消息`,
|
||||
modal: ``,
|
||||
closable: !unref(G),
|
||||
closeOnEscape: !unref(G),
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `420px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `取消`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
disabled: unref(G),
|
||||
onClick: (i[10] ||= (e) => (W.value = !1)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`disabled`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
label: `确认删除`,
|
||||
severity: `danger`,
|
||||
loading: unref(G),
|
||||
onClick: He,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createElementVNode(
|
||||
`p`,
|
||||
Ne,
|
||||
`确认删除选中的 ` +
|
||||
toDisplayString(unref(z).length) +
|
||||
` 条消息?删除后不可恢复。`,
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `closable`, `closeOnEscape`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-e9dbafec`]],
|
||||
);
|
||||
export {};
|
||||
export default T;
|
||||
</script>
|
||||
@@ -0,0 +1,576 @@
|
||||
<script>
|
||||
import "~/assets/styles/news.CbIzdrjt.css";
|
||||
definePageMeta({
|
||||
scrollToTop: !0,
|
||||
alias: [`/news/article`],
|
||||
});
|
||||
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 { 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 { useRoute } from "#app";
|
||||
import { useRouter } from "#app";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import { r as dict_r } from "~/lib/dict.js";
|
||||
import paginator from "primevue/paginator";
|
||||
import ListSegments from "~/components/ListSegments.vue";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import { t as useListPage_t } from "~/lib/useListPage.js";
|
||||
import tag from "primevue/tag";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import { t as sanitize_t } from "~/lib/sanitize.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as content_route_t } from "~/lib/content-route.js";
|
||||
var fe = {
|
||||
class: `list-page`,
|
||||
},
|
||||
pe = {
|
||||
key: 0,
|
||||
class: `list-head`,
|
||||
},
|
||||
me = {
|
||||
class: `list-toolbar`,
|
||||
},
|
||||
he = {
|
||||
class: `list-toolbar-right`,
|
||||
},
|
||||
ge = {
|
||||
class: `list-search`,
|
||||
},
|
||||
_e = {
|
||||
key: 2,
|
||||
class: `news-list`,
|
||||
},
|
||||
ve = {
|
||||
key: 3,
|
||||
class: `news-list`,
|
||||
},
|
||||
ye = [`src`],
|
||||
be = {
|
||||
class: `news-main`,
|
||||
},
|
||||
D = {
|
||||
class: `news-title`,
|
||||
},
|
||||
O = {
|
||||
class: `news-excerpt`,
|
||||
},
|
||||
k = {
|
||||
class: `news-meta`,
|
||||
},
|
||||
A = {
|
||||
key: 5,
|
||||
class: `list-foot`,
|
||||
},
|
||||
j = {
|
||||
key: 0,
|
||||
},
|
||||
M = {
|
||||
key: 2,
|
||||
class: `news-detail`,
|
||||
},
|
||||
N = {
|
||||
class: `news-detail-time`,
|
||||
},
|
||||
xe = [`innerHTML`],
|
||||
P = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `news`,
|
||||
props: {
|
||||
embedded: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(h) {
|
||||
composables_t({
|
||||
scrollToTop: !0,
|
||||
alias: `/news/article`,
|
||||
});
|
||||
let x = h,
|
||||
P = useRoute(),
|
||||
Se = useRouter(),
|
||||
F = useApi(),
|
||||
I = ref([]),
|
||||
L = ref(``),
|
||||
R = ref(``),
|
||||
{
|
||||
list: z,
|
||||
total: B,
|
||||
loading: Ce,
|
||||
error: V,
|
||||
page: we,
|
||||
limit: H,
|
||||
onPage: Te,
|
||||
reload: U,
|
||||
} = useListPage_t(`/news`, {
|
||||
limit: 10,
|
||||
params: () => ({
|
||||
addon_idcsmart_news_type_id: L.value,
|
||||
keywords: R.value,
|
||||
}),
|
||||
});
|
||||
async function Ee() {
|
||||
try {
|
||||
let e = await F.get(`/news/type`);
|
||||
I.value = e.list ?? [];
|
||||
} catch {
|
||||
I.value = [];
|
||||
}
|
||||
}
|
||||
function De(e) {
|
||||
((L.value = e === `` || e === void 0 ? `` : Number(e)), U());
|
||||
}
|
||||
function Oe(e) {
|
||||
return sanitize_t(e || ``)
|
||||
.replace(/<[^>]*>/g, ``)
|
||||
.replace(/<[^>]*$/, ``)
|
||||
.replace(/&(?:#(?:x[\da-f]*|\d*)|[a-z]+)(?=(?:…|\.{3})?\s*$)/gi, ``)
|
||||
.replace(/ /g, ` `)
|
||||
.replace(/\s+/g, ` `)
|
||||
.trim();
|
||||
}
|
||||
let W = ref(!1),
|
||||
G = ref(!1),
|
||||
K = ref(null),
|
||||
q = ref(``),
|
||||
J = ref(null),
|
||||
Y = 0,
|
||||
X = !1;
|
||||
function ke(e) {
|
||||
return x?.embedded
|
||||
? `/resources?section=news&id=${e}`
|
||||
: `/news/article?id=${e}`;
|
||||
}
|
||||
async function Z() {
|
||||
if (X) return;
|
||||
let e = P.query.id !== void 0 || P.path === `/news/article`,
|
||||
t = content_route_t(P.query.id);
|
||||
if (!e || !t) {
|
||||
(Y++,
|
||||
(W.value = e),
|
||||
(G.value = !1),
|
||||
(K.value = null),
|
||||
(J.value = null),
|
||||
(q.value = e ? `新闻编号无效,请从列表重新选择` : ``));
|
||||
return;
|
||||
}
|
||||
await $({
|
||||
id: t,
|
||||
title: `新闻详情`,
|
||||
create_time: 0,
|
||||
});
|
||||
}
|
||||
function Q() {
|
||||
if (
|
||||
((W.value = !1),
|
||||
Y++,
|
||||
(G.value = !1),
|
||||
P.query.id !== void 0 || P.path === `/news/article`)
|
||||
) {
|
||||
let e = {
|
||||
...P.query,
|
||||
};
|
||||
(delete e.id,
|
||||
Se.replace({
|
||||
path: x?.embedded ? `/resources` : `/news`,
|
||||
query: e,
|
||||
}));
|
||||
}
|
||||
}
|
||||
async function $(e) {
|
||||
let t = ++Y;
|
||||
((W.value = !0),
|
||||
(G.value = !0),
|
||||
(J.value = e),
|
||||
(q.value = ``),
|
||||
(K.value = null));
|
||||
try {
|
||||
let n = await F.get(`/news/${e.id}`);
|
||||
if (X || t !== Y) return;
|
||||
if (!n.news) throw Error(`新闻不存在或已删除`);
|
||||
K.value = n.news;
|
||||
} catch (e) {
|
||||
!X &&
|
||||
t === Y &&
|
||||
(q.value =
|
||||
e instanceof Error ? e.message : `正文加载失败,请重试`);
|
||||
} finally {
|
||||
!X && t === Y && (G.value = !1);
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(async () => {
|
||||
await Promise.all([Ee(), Z()]);
|
||||
}),
|
||||
watch(
|
||||
() => P.query.id,
|
||||
() => {
|
||||
Z();
|
||||
},
|
||||
),
|
||||
onBeforeUnmount(() => {
|
||||
((X = !0), Y++);
|
||||
}),
|
||||
(n, r) => {
|
||||
let i = ListSegments,
|
||||
o = inputtext,
|
||||
h = button,
|
||||
v = message,
|
||||
y = skeleton,
|
||||
b = tag,
|
||||
x = NuxtLink,
|
||||
C = ListEmpty,
|
||||
T = paginator,
|
||||
E = dialog;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, fe, [
|
||||
n.$props.embedded
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, pe, [
|
||||
...(r[3] ||= [
|
||||
createElementVNode(`h2`, null, `新闻中心`, -1),
|
||||
]),
|
||||
])),
|
||||
createElementVNode(`div`, me, [
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
options: [
|
||||
{
|
||||
label: `全部`,
|
||||
value: ``,
|
||||
},
|
||||
...unref(I).map((e) => ({
|
||||
label: `${e.name}(${e.news_num})`,
|
||||
value: e.id,
|
||||
})),
|
||||
],
|
||||
"model-value": unref(L),
|
||||
"onUpdate:modelValue": De,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`options`, `model-value`],
|
||||
),
|
||||
createElementVNode(`div`, he, [
|
||||
createElementVNode(`span`, ge, [
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(R),
|
||||
"onUpdate:modelValue": (r[0] ||= (e) =>
|
||||
isRef(R) ? (R.value = e) : null),
|
||||
placeholder: `搜索标题`,
|
||||
onKeyup: withKeys(unref(U), [`enter`]),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `onKeyup`],
|
||||
),
|
||||
]),
|
||||
createVNode(
|
||||
h,
|
||||
{
|
||||
label: `查询`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: unref(U),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`onClick`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(V)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(V)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(Ce) && !unref(z).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, _e, [
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(4, (e) =>
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
key: e,
|
||||
class: `news-card`,
|
||||
},
|
||||
[
|
||||
createVNode(y, {
|
||||
height: `72px`,
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
]))
|
||||
: unref(z).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, ve, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(z),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createBlock(
|
||||
x,
|
||||
{
|
||||
key: t.id,
|
||||
to: ke(t.id),
|
||||
class: `news-card`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
t.img
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`img`,
|
||||
{
|
||||
key: 0,
|
||||
src: t.img,
|
||||
class: `news-img`,
|
||||
alt: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
ye,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, be, [
|
||||
createElementVNode(
|
||||
`div`,
|
||||
D,
|
||||
toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
O,
|
||||
toDisplayString(Oe(t.excerpt)),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`div`, k, [
|
||||
t.type
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: 0,
|
||||
value: t.type,
|
||||
severity: `secondary`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`value`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(t.create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createBlock(C, {
|
||||
key: 4,
|
||||
icon: `pi pi-megaphone`,
|
||||
title: `暂无新闻`,
|
||||
description: `站点发布的新闻与公告会显示在这里`,
|
||||
})),
|
||||
unref(B) > 0
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, A, [
|
||||
(r[4] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `list-bulk`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
T,
|
||||
{
|
||||
rows: unref(H),
|
||||
totalRecords: unref(B),
|
||||
first: (unref(we) - 1) * unref(H),
|
||||
rowsPerPageOptions: [10, 20, 50],
|
||||
onPage: unref(Te),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`rows`, `totalRecords`, `first`, `onPage`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
E,
|
||||
{
|
||||
visible: unref(W),
|
||||
header: unref(K)?.title || unref(J)?.title || `新闻详情`,
|
||||
modal: ``,
|
||||
draggable: !1,
|
||||
style: {
|
||||
width: `760px`,
|
||||
},
|
||||
"onUpdate:visible": (r[2] ||= (e) => {
|
||||
e || Q();
|
||||
}),
|
||||
},
|
||||
{
|
||||
footer: withCtx(() => [
|
||||
unref(q) && unref(J)
|
||||
? (openBlock(),
|
||||
createBlock(h, {
|
||||
key: 0,
|
||||
label: `重新加载正文`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
onClick: (r[1] ||= (e) => $(unref(J))),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(h, {
|
||||
label: `关闭`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: Q,
|
||||
}),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
unref(G)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createVNode(y, {
|
||||
height: `220px`,
|
||||
}),
|
||||
]))
|
||||
: unref(q)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(q)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(K)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, M, [
|
||||
createElementVNode(
|
||||
`div`,
|
||||
N,
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(unref(K).create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `news-detail-html`,
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
(`decodeEntities` in n
|
||||
? n.decodeEntities
|
||||
: unref(sanitize_t))(
|
||||
unref(K).content || ``,
|
||||
),
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
xe,
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`visible`, `header`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-0f61b69d`]],
|
||||
);
|
||||
export {};
|
||||
export default P;
|
||||
</script>
|
||||
@@ -0,0 +1,543 @@
|
||||
<script>
|
||||
import "~/assets/styles/notices.BXNGOj-Q.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
alias: [`/notices/notice`],
|
||||
});
|
||||
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 { 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 { useRoute } from "#app";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import { r as dict_r } from "~/lib/dict.js";
|
||||
import paginator from "primevue/paginator";
|
||||
import select from "primevue/select";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as content_route_t } from "~/lib/content-route.js";
|
||||
var ue = {
|
||||
key: 0,
|
||||
class: `list-page notices-page`,
|
||||
},
|
||||
w = {
|
||||
class: `list-toolbar`,
|
||||
},
|
||||
de = {
|
||||
key: 1,
|
||||
class: `notice-list`,
|
||||
},
|
||||
fe = {
|
||||
key: 2,
|
||||
class: `notice-list`,
|
||||
},
|
||||
T = {
|
||||
class: `notice-title`,
|
||||
},
|
||||
pe = {
|
||||
class: `notice-time`,
|
||||
},
|
||||
me = {
|
||||
key: 1,
|
||||
class: `notice-article`,
|
||||
},
|
||||
he = {
|
||||
key: 0,
|
||||
},
|
||||
ge = {
|
||||
class: `detail-time`,
|
||||
},
|
||||
E = [`innerHTML`],
|
||||
D = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `index`,
|
||||
props: {
|
||||
embedded: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(h) {
|
||||
let b = h,
|
||||
D = useApi(),
|
||||
O = useRoute();
|
||||
composables_t({
|
||||
alias: `/notices/notice`,
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let k = ref([]),
|
||||
A = ref(0),
|
||||
j = ref(!0),
|
||||
M = ref(``),
|
||||
N = ref(1),
|
||||
P = ref(10),
|
||||
F = ref(``),
|
||||
I = ref(``),
|
||||
L = ref(`desc`),
|
||||
R = ref(null),
|
||||
z = ref([]),
|
||||
B = ref(``),
|
||||
V = 0,
|
||||
H = !1;
|
||||
async function U() {
|
||||
B.value = ``;
|
||||
try {
|
||||
let e = await D.get(`/announcement/type`);
|
||||
H || (z.value = e.list || []);
|
||||
} catch (e) {
|
||||
H ||
|
||||
(B.value = e instanceof Error ? e.message : `公告分类加载失败`);
|
||||
}
|
||||
}
|
||||
function W() {
|
||||
((I.value = F.value.trim()), (N.value = 1), Z());
|
||||
}
|
||||
let G = ref(!1),
|
||||
K = ref(null),
|
||||
q = ref(!1),
|
||||
J = ref(``),
|
||||
Y = ref(null),
|
||||
X = 0;
|
||||
async function Z() {
|
||||
let e = ++V;
|
||||
((j.value = !0), (M.value = ``));
|
||||
try {
|
||||
let t = await D.get(`/announcement`, {
|
||||
page: N.value,
|
||||
limit: P.value,
|
||||
keywords: I.value,
|
||||
addon_idcsmart_announcement_type_id: R.value ?? void 0,
|
||||
orderby: `id`,
|
||||
sort: L.value,
|
||||
});
|
||||
if (H || e !== V) return;
|
||||
((k.value = t.list), (A.value = t.count));
|
||||
} catch (t) {
|
||||
if (H || e !== V) return;
|
||||
((M.value = t instanceof Error ? t.message : `加载公告失败`),
|
||||
(k.value = []),
|
||||
(A.value = 0));
|
||||
} finally {
|
||||
!H && e === V && (j.value = !1);
|
||||
}
|
||||
}
|
||||
async function Q(e) {
|
||||
let t = ++X;
|
||||
((G.value = !0),
|
||||
(q.value = !0),
|
||||
(Y.value = e),
|
||||
(J.value = ``),
|
||||
(K.value = null));
|
||||
try {
|
||||
let n = await D.get(`/announcement/${e.id}`);
|
||||
if (t !== X) return;
|
||||
if (!n.announcement) throw Error(`公告不存在或已删除`);
|
||||
K.value = n.announcement;
|
||||
} catch (e) {
|
||||
t === X &&
|
||||
(J.value =
|
||||
e instanceof Error ? e.message : `正文加载失败,请重试`);
|
||||
} finally {
|
||||
t === X && (q.value = !1);
|
||||
}
|
||||
}
|
||||
function _e(e) {
|
||||
((N.value = e.page + 1), (P.value = e.rows), Z());
|
||||
}
|
||||
async function $() {
|
||||
if (H) return;
|
||||
let e = O.query.id !== void 0 || O.path === `/notices/notice`,
|
||||
t = content_route_t(O.query.id);
|
||||
if (!e || !t) {
|
||||
(X++,
|
||||
(G.value = e),
|
||||
(q.value = !1),
|
||||
(K.value = null),
|
||||
(Y.value = null),
|
||||
(J.value = e ? `公告编号无效,请从列表重新选择` : ``));
|
||||
return;
|
||||
}
|
||||
await Q(
|
||||
k.value.find((e) => e.id === t) ?? {
|
||||
id: t,
|
||||
title: `公告详情`,
|
||||
create_time: 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
return (
|
||||
onMounted(async () => {
|
||||
(U(), await Promise.all([Z(), $()]));
|
||||
}),
|
||||
watch(() => O.query.id, $),
|
||||
onBeforeUnmount(() => {
|
||||
((H = !0), (X += 1), V++);
|
||||
}),
|
||||
(n, r) => {
|
||||
let i = inputtext,
|
||||
o = select,
|
||||
h = button,
|
||||
v = message,
|
||||
y = skeleton,
|
||||
S = NuxtLink,
|
||||
C = ListEmpty,
|
||||
D = paginator;
|
||||
return unref(G)
|
||||
? (openBlock(),
|
||||
createElementBlock(`article`, me, [
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
to: b.embedded
|
||||
? `/resources?section=notices`
|
||||
: `/notices`,
|
||||
class: `article-back`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(r[5] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-arrow-left`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(` 返回公告`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
createElementVNode(
|
||||
`h1`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(K)?.title || unref(Y)?.title || `公告详情`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
unref(q)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, he, [
|
||||
createVNode(y, {
|
||||
height: `180px`,
|
||||
}),
|
||||
]))
|
||||
: unref(J)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(J)), 1),
|
||||
unref(Y)
|
||||
? (openBlock(),
|
||||
createBlock(h, {
|
||||
key: 0,
|
||||
label: `重新加载正文`,
|
||||
text: ``,
|
||||
onClick: (r[3] ||= (e) => Q(unref(Y))),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(K)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 2,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`p`,
|
||||
ge,
|
||||
`发布时间 ` +
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(unref(K).create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `detail-content`,
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
unref(K).content || ``,
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
E,
|
||||
),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, ue, [
|
||||
(r[4] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `notice-heading`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`h2`, null, `公告`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`我们会在这里发布重要公告与服务信息,帮助您及时了解平台动态。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, w, [
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
modelValue: unref(F),
|
||||
"onUpdate:modelValue": (r[0] ||= (e) =>
|
||||
isRef(F) ? (F.value = e) : null),
|
||||
placeholder: `搜索公告标题`,
|
||||
"aria-label": `搜索公告标题`,
|
||||
onKeyup: withKeys(W, [`enter`]),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(R),
|
||||
"onUpdate:modelValue": (r[1] ||= (e) =>
|
||||
isRef(R) ? (R.value = e) : null),
|
||||
options: [
|
||||
{
|
||||
id: null,
|
||||
name: `全部分类`,
|
||||
},
|
||||
...unref(z),
|
||||
],
|
||||
"option-label": `name`,
|
||||
"option-value": `id`,
|
||||
"aria-label": `公告分类`,
|
||||
onChange: W,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`],
|
||||
),
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
modelValue: unref(L),
|
||||
"onUpdate:modelValue": (r[2] ||= (e) =>
|
||||
isRef(L) ? (L.value = e) : null),
|
||||
options: [
|
||||
{
|
||||
label: `最新优先`,
|
||||
value: `desc`,
|
||||
},
|
||||
{
|
||||
label: `最早优先`,
|
||||
value: `asc`,
|
||||
},
|
||||
],
|
||||
"option-label": `label`,
|
||||
"option-value": `value`,
|
||||
"aria-label": `公告排序`,
|
||||
onChange: W,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(h, {
|
||||
label: `搜索`,
|
||||
text: ``,
|
||||
onClick: W,
|
||||
}),
|
||||
]),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 0,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(B)) + ` `, 1),
|
||||
createVNode(h, {
|
||||
label: `重试分类`,
|
||||
text: ``,
|
||||
onClick: U,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(j) && !unref(k).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, de, [
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(5, (e) =>
|
||||
createVNode(y, {
|
||||
key: e,
|
||||
height: `48px`,
|
||||
}),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
]))
|
||||
: unref(k).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, fe, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(k),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createBlock(
|
||||
S,
|
||||
{
|
||||
key: t.id,
|
||||
to: b.embedded
|
||||
? `/resources?section=notices&id=${t.id}`
|
||||
: `/notices/notice?id=${t.id}`,
|
||||
class: `notice-item`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
T,
|
||||
toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
pe,
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(t.create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: unref(M)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 3,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(M)) + ` `,
|
||||
1,
|
||||
),
|
||||
createVNode(h, {
|
||||
label: `重试`,
|
||||
text: ``,
|
||||
onClick: Z,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(C, {
|
||||
key: 4,
|
||||
icon: `pi pi-megaphone`,
|
||||
title: `暂无公告`,
|
||||
description: `平台公告与通知会显示在这里`,
|
||||
})),
|
||||
unref(A) > 0
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
D,
|
||||
{
|
||||
key: 5,
|
||||
rows: unref(P),
|
||||
totalRecords: unref(A),
|
||||
first: (unref(N) - 1) * unref(P),
|
||||
rowsPerPageOptions: [10, 20, 50],
|
||||
onPage: _e,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`rows`, `totalRecords`, `first`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]));
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-4ba0157b`]],
|
||||
);
|
||||
export {};
|
||||
export default D;
|
||||
</script>
|
||||
@@ -0,0 +1,614 @@
|
||||
<script>
|
||||
import "~/assets/styles/PhoneCodeField.CwyHXfML.css";
|
||||
import "~/assets/styles/GeetestField.DiieTibK.css";
|
||||
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
|
||||
import "~/assets/styles/bind.CFZQE2UH.css";
|
||||
definePageMeta({
|
||||
layout: `blank`,
|
||||
});
|
||||
import { useRuntimeConfig } from "#app";
|
||||
import { toDisplayString } 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 { 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 { useRoute } from "#app";
|
||||
import { navigateTo } from "#app";
|
||||
import { useHead } from "#app";
|
||||
import { NuxtLink } from "#components";
|
||||
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 { n as wechat_binding_n } from "~/lib/wechat-binding.js";
|
||||
import { t as wechat_binding_t } from "~/lib/wechat-binding.js";
|
||||
import { r as auth_redirect_r } from "~/lib/auth-redirect.js";
|
||||
import inputtext from "primevue/inputtext";
|
||||
import CaptchaField from "~/components/CaptchaField.vue";
|
||||
import checkbox from "primevue/checkbox";
|
||||
import { n as oauth_n } from "~/lib/oauth.js";
|
||||
import PhoneCodeField from "~/components/PhoneCodeField.vue";
|
||||
import { t as useCaptcha_t } from "~/lib/useCaptcha.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as useVerifyCode_t } from "~/lib/useVerifyCode.js";
|
||||
var ve = {
|
||||
class: `auth-card bind-card`,
|
||||
},
|
||||
ye = {
|
||||
key: 1,
|
||||
class: `session-status`,
|
||||
},
|
||||
be = [`disabled`],
|
||||
xe = {
|
||||
class: `seg`,
|
||||
},
|
||||
Se = [`aria-pressed`],
|
||||
Ce = [`aria-pressed`],
|
||||
we = {
|
||||
class: `field`,
|
||||
},
|
||||
w = {
|
||||
for: `bind-account`,
|
||||
},
|
||||
T = {
|
||||
class: `input-row`,
|
||||
},
|
||||
E = {
|
||||
class: `field`,
|
||||
},
|
||||
D = {
|
||||
class: `input-row`,
|
||||
},
|
||||
O = {
|
||||
class: `agreement`,
|
||||
},
|
||||
k = {
|
||||
for: `bind-agreement`,
|
||||
},
|
||||
Te = [`href`],
|
||||
Ee = {
|
||||
key: 1,
|
||||
},
|
||||
De = [`href`],
|
||||
Oe = {
|
||||
key: 3,
|
||||
},
|
||||
A = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `bind`,
|
||||
setup(g) {
|
||||
(composables_t({
|
||||
layout: `blank`,
|
||||
}),
|
||||
useHead({
|
||||
title: `绑定账号 - 破碎工坊网络`,
|
||||
}));
|
||||
let S = useApi(),
|
||||
A = useAuth(),
|
||||
j = useSiteConfig_t(),
|
||||
M = useRoute(),
|
||||
N = M.query.provider === `wechat`,
|
||||
P = N ? wechat_binding_n(sessionStorage) : null,
|
||||
F = auth_redirect_r(M.query.redirect),
|
||||
I = ref(`phone`),
|
||||
L = ref(``),
|
||||
R = ref(`86`),
|
||||
z = ref(``),
|
||||
B = ref(!1),
|
||||
V = ref(!1),
|
||||
H = ref(``),
|
||||
U = ref(!1),
|
||||
W = ref(!1),
|
||||
G = !0;
|
||||
onBeforeUnmount(() => {
|
||||
G = !1;
|
||||
});
|
||||
async function K() {
|
||||
if (!W.value && G) {
|
||||
((W.value = !0), (U.value = !1), (H.value = ``));
|
||||
try {
|
||||
if (N) {
|
||||
if (!P) throw Error(`扫码会话已过期,请返回登录重新扫码`);
|
||||
let e = await S.get(`/mp_weixin_notice/qrcode/status`, {
|
||||
ticket: P.ticket,
|
||||
token: P.token,
|
||||
});
|
||||
if (!G) return;
|
||||
if (e.status === `Success` && isValidJwt(e.jwt)) {
|
||||
(wechat_binding_t(sessionStorage),
|
||||
A.loginWithJwt(e.jwt),
|
||||
await navigateTo(F));
|
||||
return;
|
||||
}
|
||||
if (e.status !== `WaitBind`)
|
||||
throw Error(`扫码会话已失效,请返回登录重新扫码`);
|
||||
U.value = !0;
|
||||
return;
|
||||
}
|
||||
let t = await S.get(`/oauth/token`);
|
||||
if (!G) return;
|
||||
let n = oauth_n(
|
||||
t,
|
||||
window.location.origin,
|
||||
new URL(
|
||||
String(
|
||||
useRuntimeConfig().public.apiBase || window.location.origin,
|
||||
),
|
||||
window.location.origin,
|
||||
).origin,
|
||||
);
|
||||
if (n.kind === `login`) {
|
||||
(A.loginWithJwt(n.jwt), await navigateTo(`/`));
|
||||
return;
|
||||
}
|
||||
if (n.kind !== `bind`)
|
||||
throw Error(`授权会话已过期,请返回登录并重新授权`);
|
||||
U.value = !0;
|
||||
} catch (e) {
|
||||
G &&
|
||||
(H.value = e instanceof Error ? e.message : `验证授权会话失败`);
|
||||
} finally {
|
||||
G && (W.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
let q = useCaptcha_t(`oauth`),
|
||||
{
|
||||
sending: J,
|
||||
countdown: Y,
|
||||
send: ke,
|
||||
} = useVerifyCode_t({
|
||||
action: `oauth`,
|
||||
captcha: q,
|
||||
error: H,
|
||||
phoneCode: () => R.value,
|
||||
}),
|
||||
{
|
||||
needed: Ae,
|
||||
provider: je,
|
||||
captchaId: Me,
|
||||
complete: Ne,
|
||||
invalidate: X,
|
||||
value: Z,
|
||||
img: Pe,
|
||||
loading: Fe,
|
||||
error: Q,
|
||||
load: Ie,
|
||||
} = q,
|
||||
$ = computed(() => {
|
||||
let e = j.config.value,
|
||||
t = (e) =>
|
||||
typeof e == `string` && /^https?:\/\//i.test(e) ? e : ``;
|
||||
return {
|
||||
service: t(e?.terms_service_url),
|
||||
privacy: t(e?.terms_privacy_url),
|
||||
};
|
||||
});
|
||||
watch(I, () => {
|
||||
((L.value = ``), (z.value = ``), (H.value = ``));
|
||||
});
|
||||
async function Le() {
|
||||
if (!V.value && G) {
|
||||
if (((H.value = ``), !U.value)) {
|
||||
H.value = `请先验证授权会话;会话失效时请返回登录重新授权`;
|
||||
return;
|
||||
}
|
||||
if (!L.value.trim() || !z.value.trim()) {
|
||||
H.value = `请填写账号和验证码`;
|
||||
return;
|
||||
}
|
||||
if (!B.value) {
|
||||
H.value = `请先阅读并同意服务协议和隐私协议`;
|
||||
return;
|
||||
}
|
||||
if (I.value === `phone` && !/^[1-9]\d{0,3}$/.test(R.value)) {
|
||||
H.value = `请输入有效的国际电话区号`;
|
||||
return;
|
||||
}
|
||||
V.value = !0;
|
||||
try {
|
||||
let e = q.validationError?.();
|
||||
if (e) throw Error(e);
|
||||
let t = await S.post(
|
||||
N
|
||||
? `/mp_weixin_notice/qrcode/bind_client`
|
||||
: `/oauth/client/bind`,
|
||||
{
|
||||
type: I.value,
|
||||
account: L.value.trim(),
|
||||
phone_code: R.value,
|
||||
code: z.value.trim(),
|
||||
...(N && P
|
||||
? {
|
||||
ticket: P.ticket,
|
||||
token: P.token,
|
||||
captcha: q.value.value,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
);
|
||||
if (!G) return;
|
||||
if (!isValidJwt(t?.jwt))
|
||||
throw Error(`绑定会话已失效,请返回登录后重新发起第三方授权`);
|
||||
(N && wechat_binding_t(sessionStorage),
|
||||
A.loginWithJwt(t.jwt),
|
||||
await navigateTo(F));
|
||||
} catch (e) {
|
||||
G &&
|
||||
((H.value =
|
||||
e instanceof Error ? e.message : `绑定失败,请重试`),
|
||||
await q.handleError?.(e));
|
||||
} finally {
|
||||
G && (V.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(() => {
|
||||
(j.load(), K());
|
||||
}),
|
||||
(e, n) => {
|
||||
let i = message,
|
||||
a = button,
|
||||
s = NuxtLink,
|
||||
u = PhoneCodeField,
|
||||
g = inputtext,
|
||||
y = CaptchaField,
|
||||
b = checkbox;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`section`, ve, [
|
||||
(n[13] ||= createElementVNode(`h1`, null, `绑定账号`, -1)),
|
||||
(n[14] ||= createElementVNode(
|
||||
`p`,
|
||||
{
|
||||
class: `bind-intro`,
|
||||
},
|
||||
`请使用已注册的手机号或邮箱接收验证码,完成与第三方账号的绑定。`,
|
||||
-1,
|
||||
)),
|
||||
unref(H)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
i,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(H)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(U)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, ye, [
|
||||
createVNode(
|
||||
a,
|
||||
{
|
||||
label: `验证授权会话`,
|
||||
loading: unref(W),
|
||||
onClick: K,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
to: `/login`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[8] ||= [createTextVNode(`返回登录`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
])),
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`form`,
|
||||
{
|
||||
key: 2,
|
||||
class: `bind-form`,
|
||||
onSubmit: withModifiers(Le, [`prevent`]),
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`fieldset`,
|
||||
{
|
||||
disabled: unref(V),
|
||||
},
|
||||
[
|
||||
(n[9] ||= createElementVNode(
|
||||
`legend`,
|
||||
null,
|
||||
`验证方式`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, xe, [
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(I) === `email`,
|
||||
}),
|
||||
"aria-pressed": unref(I) === `email`,
|
||||
onClick: (n[0] ||= (e) =>
|
||||
(I.value = `email`)),
|
||||
},
|
||||
` 邮箱 `,
|
||||
10,
|
||||
Se,
|
||||
),
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(I) === `phone`,
|
||||
}),
|
||||
"aria-pressed": unref(I) === `phone`,
|
||||
onClick: (n[1] ||= (e) =>
|
||||
(I.value = `phone`)),
|
||||
},
|
||||
` 手机号 `,
|
||||
10,
|
||||
Ce,
|
||||
),
|
||||
]),
|
||||
],
|
||||
8,
|
||||
be,
|
||||
),
|
||||
createElementVNode(`div`, we, [
|
||||
createElementVNode(
|
||||
`label`,
|
||||
w,
|
||||
toDisplayString(
|
||||
unref(I) === `phone` ? `手机号` : `邮箱`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(`div`, T, [
|
||||
unref(I) === `phone`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
u,
|
||||
{
|
||||
key: 0,
|
||||
modelValue: unref(R),
|
||||
"onUpdate:modelValue": (n[2] ||= (e) =>
|
||||
isRef(R) ? (R.value = e) : null),
|
||||
disabled: unref(V) || unref(J),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
id: `bind-account`,
|
||||
modelValue: unref(L),
|
||||
"onUpdate:modelValue": (n[3] ||= (e) =>
|
||||
isRef(L) ? (L.value = e) : null),
|
||||
type: unref(I) === `email` ? `email` : `tel`,
|
||||
placeholder:
|
||||
unref(I) === `phone`
|
||||
? `输入手机号`
|
||||
: `输入邮箱`,
|
||||
autocomplete: `username`,
|
||||
disabled: unref(V),
|
||||
required: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `type`, `placeholder`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, E, [
|
||||
(n[10] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `bind-code`,
|
||||
},
|
||||
`验证码`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, D, [
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
id: `bind-code`,
|
||||
modelValue: unref(z),
|
||||
"onUpdate:modelValue": (n[4] ||= (e) =>
|
||||
isRef(z) ? (z.value = e) : null),
|
||||
placeholder: `输入验证码`,
|
||||
autocomplete: `one-time-code`,
|
||||
disabled: unref(V),
|
||||
required: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
createVNode(
|
||||
a,
|
||||
{
|
||||
label: unref(Y) ? `${unref(Y)}s` : `获取验证码`,
|
||||
loading: unref(J),
|
||||
disabled:
|
||||
unref(V) || !unref(L).trim() || unref(Y) > 0,
|
||||
onClick: (n[5] ||= (e) =>
|
||||
unref(ke)(
|
||||
unref(I),
|
||||
unref(L).trim(),
|
||||
`请输入账号`,
|
||||
)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`, `loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(Ae)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
modelValue: unref(Z),
|
||||
"onUpdate:modelValue": (n[6] ||= (e) =>
|
||||
isRef(Z) ? (Z.value = e) : null),
|
||||
img: unref(Pe),
|
||||
provider: unref(je),
|
||||
"captcha-id": unref(Me),
|
||||
disabled: unref(V) || unref(J),
|
||||
onVerified: unref(Ne),
|
||||
onInvalid: unref(X),
|
||||
loading: unref(Fe),
|
||||
onRefresh: unref(Ie),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`modelValue`,
|
||||
`img`,
|
||||
`provider`,
|
||||
`captcha-id`,
|
||||
`disabled`,
|
||||
`onVerified`,
|
||||
`onInvalid`,
|
||||
`loading`,
|
||||
`onRefresh`,
|
||||
],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(Q)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
i,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(Q)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, O, [
|
||||
createVNode(
|
||||
b,
|
||||
{
|
||||
modelValue: unref(B),
|
||||
"onUpdate:modelValue": (n[7] ||= (e) =>
|
||||
isRef(B) ? (B.value = e) : null),
|
||||
"input-id": `bind-agreement`,
|
||||
binary: ``,
|
||||
disabled: unref(V),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
createElementVNode(`label`, k, [
|
||||
(n[11] ||= createTextVNode(`阅读并同意 `, -1)),
|
||||
unref($).service
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`a`,
|
||||
{
|
||||
key: 0,
|
||||
href: unref($).service,
|
||||
target: `_blank`,
|
||||
rel: `noopener noreferrer`,
|
||||
},
|
||||
`《服务协议》`,
|
||||
8,
|
||||
Te,
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(`span`, Ee, `《服务协议》`)),
|
||||
(n[12] ||= createTextVNode(` 和 `, -1)),
|
||||
unref($).privacy
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`a`,
|
||||
{
|
||||
key: 2,
|
||||
href: unref($).privacy,
|
||||
target: `_blank`,
|
||||
rel: `noopener noreferrer`,
|
||||
},
|
||||
`《隐私协议》`,
|
||||
8,
|
||||
De,
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(`span`, Oe, `《隐私协议》`)),
|
||||
]),
|
||||
]),
|
||||
createVNode(
|
||||
a,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `确认绑定`,
|
||||
loading: unref(V),
|
||||
disabled:
|
||||
!unref(B) || !unref(L).trim() || !unref(z).trim(),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
],
|
||||
32,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-146faed1`]],
|
||||
);
|
||||
export {};
|
||||
export default A;
|
||||
</script>
|
||||
@@ -0,0 +1,149 @@
|
||||
<script>
|
||||
definePageMeta({
|
||||
layout: `blank`,
|
||||
});
|
||||
import { useRuntimeConfig } from "#app";
|
||||
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 { 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 { navigateTo } from "#app";
|
||||
import { useHead } 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 { n as oauth_n } from "~/lib/oauth.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var w = {
|
||||
class: `auth-card`,
|
||||
},
|
||||
T = defineComponent({
|
||||
__name: `callback`,
|
||||
setup(f) {
|
||||
(composables_t({
|
||||
layout: `blank`,
|
||||
}),
|
||||
useHead({
|
||||
title: `恢复第三方登录`,
|
||||
}));
|
||||
let T = useApi(),
|
||||
E = useAuth(),
|
||||
D = ref(!1),
|
||||
O = ref(``),
|
||||
k = !0;
|
||||
onBeforeUnmount(() => {
|
||||
k = !1;
|
||||
});
|
||||
async function A() {
|
||||
if (k && !D.value) {
|
||||
((D.value = !0), (O.value = ``));
|
||||
try {
|
||||
let t = await T.get(`/oauth/token`);
|
||||
if (!k) return;
|
||||
let n = oauth_n(
|
||||
t,
|
||||
window.location.origin,
|
||||
new URL(
|
||||
String(
|
||||
useRuntimeConfig().public.apiBase || window.location.origin,
|
||||
),
|
||||
window.location.origin,
|
||||
).origin,
|
||||
);
|
||||
if (n.kind === `login`) {
|
||||
E.loginWithJwt(n.jwt);
|
||||
try {
|
||||
sessionStorage.removeItem(`console-oauth-pending`);
|
||||
} catch {}
|
||||
await navigateTo(`/`);
|
||||
} else if (n.kind === `bind`) {
|
||||
if (new URL(n.url).pathname === `/oauth/callback`)
|
||||
throw Error(`授权返回地址异常,请重新发起授权`);
|
||||
window.location.replace(n.url);
|
||||
} else throw Error(`授权会话已过期,请返回登录并重新授权`);
|
||||
} catch (e) {
|
||||
k && (O.value = e instanceof Error ? e.message : `恢复登录失败`);
|
||||
} finally {
|
||||
k && (D.value = !1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(A),
|
||||
(e, n) => {
|
||||
let r = message,
|
||||
a = button,
|
||||
f = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`section`, w, [
|
||||
(n[1] ||= createElementVNode(`h1`, null, `恢复第三方登录`, -1)),
|
||||
(n[2] ||= createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`正在验证授权会话。`,
|
||||
-1,
|
||||
)),
|
||||
unref(O)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
r,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(O)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
a,
|
||||
{
|
||||
label: `重新验证`,
|
||||
loading: unref(D),
|
||||
onClick: A,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
createElementVNode(`p`, null, [
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
to: `/login`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[0] ||= [createTextVNode(`返回登录`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default T;
|
||||
</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,25 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/_id_.gjoJy9S8.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import _id_ from "~/pages/orders/[id].vue";
|
||||
var a = defineComponent({
|
||||
__name: `index`,
|
||||
setup(t) {
|
||||
return (
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
}),
|
||||
(t, r) => (openBlock(), createBlock(_id_))
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default a;
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/_id_.gjoJy9S8.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import _id_ from "~/pages/orders/[id].vue";
|
||||
var a = defineComponent({
|
||||
__name: `paid`,
|
||||
setup(t) {
|
||||
return (
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
}),
|
||||
(t, r) => (openBlock(), createBlock(_id_))
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default a;
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script>
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/_id_.gjoJy9S8.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import _id_ from "~/pages/orders/[id].vue";
|
||||
var a = defineComponent({
|
||||
__name: `pay`,
|
||||
setup(t) {
|
||||
return (
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
}),
|
||||
(t, r) => (openBlock(), createBlock(_id_))
|
||||
);
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default a;
|
||||
</script>
|
||||
@@ -0,0 +1,460 @@
|
||||
<script>
|
||||
import "~/assets/styles/MfDcimConfig.BhC_eZ0V.css";
|
||||
import "~/assets/styles/MfCloudConfig.DbgUu8qr.css";
|
||||
import "~/assets/styles/KkyEcsConfig.BFaAwQPZ.css";
|
||||
import "~/assets/styles/ConfigResourceOption.Dj4VopnA.css";
|
||||
import "~/assets/styles/ConfigDiskAdd.C92e9ZuF.css";
|
||||
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
|
||||
import "~/assets/styles/JyCloudConfig.kGfttaHi.css";
|
||||
import "~/assets/styles/FinanceConfig.CLwX1CC8.css";
|
||||
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
|
||||
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
|
||||
import "~/assets/styles/ProductCustomFields.B2QMnPil.css";
|
||||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||||
import "~/assets/styles/CommonConfig.Cfik-oMe.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/_id_.CSXsMADH.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { onScopeDispose } 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 { useRoute } from "#app";
|
||||
import { useRouter } from "#app";
|
||||
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 PaymentDialog from "~/components/PaymentDialog.vue";
|
||||
import { t as product_order_module_t } from "~/lib/product-order-module.js";
|
||||
import ConfigLoadingShell from "~/components/config/ConfigLoadingShell.vue";
|
||||
import { n as cart_edit_n } from "~/lib/cart-edit.js";
|
||||
import CommonConfig from "~/components/config/CommonConfig.vue";
|
||||
import FinanceConfig from "~/components/config/FinanceConfig.vue";
|
||||
import JyCloudConfig from "~/components/config/JyCloudConfig.vue";
|
||||
import KkyEcsConfig from "~/components/config/KkyEcsConfig.vue";
|
||||
import MfCloudConfig from "~/components/config/MfCloudConfig.vue";
|
||||
import { r as order_image_continuation_r } from "~/lib/order-image-continuation.js";
|
||||
import MfDcimConfig from "~/components/config/MfDcimConfig.vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as product_description_data_t } from "~/lib/product-description-data.js";
|
||||
var j = {
|
||||
class: `page product-order-page`,
|
||||
},
|
||||
M = {
|
||||
class: `product-head`,
|
||||
},
|
||||
N = {
|
||||
class: `product-links`,
|
||||
"aria-label": `订购导航`,
|
||||
},
|
||||
P = {
|
||||
key: 1,
|
||||
class: `panel config-load-error`,
|
||||
},
|
||||
F = {
|
||||
key: 6,
|
||||
class: `panel`,
|
||||
},
|
||||
I = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `[id]`,
|
||||
setup(f) {
|
||||
let b = useRoute(),
|
||||
I = useRouter(),
|
||||
L = useApi(),
|
||||
R = String(b.params.id ?? b.query.id ?? b.query.product_id ?? ``),
|
||||
z = order_image_continuation_r(b.query.order_image),
|
||||
B = b.fullPath;
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
function V() {
|
||||
let e = {},
|
||||
t = b.query.g ?? b.query.first_group_id,
|
||||
n = b.query.sg ?? b.query.second_group_id;
|
||||
return (
|
||||
typeof t == `string` && /^[1-9]\d*$/.test(t) && (e.g = t),
|
||||
typeof n == `string` && /^[1-9]\d*$/.test(n) && (e.sg = n),
|
||||
{
|
||||
path: `/products`,
|
||||
query: e,
|
||||
}
|
||||
);
|
||||
}
|
||||
let H = ref(null),
|
||||
U = ref(null),
|
||||
W = ref(!0),
|
||||
G = ref(``),
|
||||
K = computed(() => {
|
||||
let e = b.query.edit_position;
|
||||
if (typeof e != `string` || !/^\d+$/.test(e)) return null;
|
||||
let t = Number(e);
|
||||
return Number.isInteger(t) && t >= 0 ? t : null;
|
||||
}),
|
||||
q = computed(() => {
|
||||
if (K.value !== null && U.value)
|
||||
return {
|
||||
position: K.value,
|
||||
item: U.value,
|
||||
};
|
||||
}),
|
||||
J = ref(!1),
|
||||
Y = ref(null),
|
||||
X = ref(``),
|
||||
Z = 0;
|
||||
onScopeDispose(() => {
|
||||
Z++;
|
||||
});
|
||||
async function Q() {
|
||||
let e = ++Z;
|
||||
((W.value = !0), (G.value = ``), (H.value = null), (U.value = null));
|
||||
try {
|
||||
if (!/^[1-9]\d*$/.test(R)) throw Error(`商品编号无效`);
|
||||
let t = await L.get(`/product/${R}`);
|
||||
if (e !== Z) return;
|
||||
let n = t?.product ?? t;
|
||||
if (
|
||||
!n ||
|
||||
typeof n != `object` ||
|
||||
!n.id ||
|
||||
Number(n.id) !== Number(R)
|
||||
)
|
||||
throw Error(`商品不存在或已下架`);
|
||||
let r = n;
|
||||
if (r.order_allowed === !1)
|
||||
throw Error(r.order_block_reason || `该产品已停止订购`);
|
||||
if (K.value !== null) {
|
||||
let t = (await L.get(`/cart`))?.list?.[K.value];
|
||||
if (!t || Number(t.product_id) !== Number(R))
|
||||
throw Error(`购物车商品已变化,请返回购物车重新编辑`);
|
||||
if (e !== Z) return;
|
||||
U.value = cart_edit_n(t);
|
||||
}
|
||||
let i = await product_order_module_t(L, r);
|
||||
if (e !== Z) return;
|
||||
((H.value = {
|
||||
...r,
|
||||
module: i,
|
||||
}),
|
||||
product_description_data_t(L, r).then((t) => {
|
||||
e === Z && H.value && (H.value.description = t);
|
||||
}));
|
||||
} catch (t) {
|
||||
e === Z &&
|
||||
(G.value = t instanceof Error ? t.message : `加载商品失败`);
|
||||
} finally {
|
||||
e === Z && (W.value = !1);
|
||||
}
|
||||
}
|
||||
function $(e) {
|
||||
((Y.value = e.order_id), (X.value = e.amount), (J.value = !0));
|
||||
}
|
||||
function se() {
|
||||
I.push(`/orders`);
|
||||
}
|
||||
return (
|
||||
onMounted(Q),
|
||||
(t, n) => {
|
||||
let i = NuxtLink,
|
||||
o = ConfigLoadingShell,
|
||||
f = message,
|
||||
h = button,
|
||||
g = MfCloudConfig,
|
||||
v = MfDcimConfig,
|
||||
b = CommonConfig,
|
||||
C = FinanceConfig,
|
||||
T = KkyEcsConfig,
|
||||
O = PaymentDialog;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createElementVNode(`header`, M, [
|
||||
createElementVNode(`div`, null, [
|
||||
createElementVNode(
|
||||
`h1`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(product_name_n)(unref(H)?.name) || `配置产品`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(q)
|
||||
? `编辑购物车商品配置,保存后返回购物车结算。`
|
||||
: `选择所需资源,确认配置与费用后购买。`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`nav`, N, [
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: V(),
|
||||
class: `back`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[1] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-angle-left`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`返回产品列表`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: `/cart`,
|
||||
class: `cart-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-shopping-cart`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`购物车`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(W)
|
||||
? (openBlock(),
|
||||
createBlock(o, {
|
||||
key: 0,
|
||||
}))
|
||||
: unref(G) && !unref(H)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, P, [
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(G)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(h, {
|
||||
label: `重新加载商品`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: Q,
|
||||
}),
|
||||
]))
|
||||
: unref(H)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 2,
|
||||
},
|
||||
[
|
||||
unref(H).module === `mf_cloud` ||
|
||||
unref(H).module === `remf_cloud`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
g,
|
||||
{
|
||||
key: 0,
|
||||
"product-id": unref(R),
|
||||
module: unref(H).module,
|
||||
"initial-image-id": unref(z),
|
||||
"continuation-path": unref(B),
|
||||
"initial-product": unref(H),
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`product-id`,
|
||||
`module`,
|
||||
`initial-image-id`,
|
||||
`continuation-path`,
|
||||
`initial-product`,
|
||||
`edit`,
|
||||
],
|
||||
))
|
||||
: unref(H).module === `mf_dcim` ||
|
||||
unref(H).module === `remf_dcim`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
"product-id": unref(R),
|
||||
module: unref(H).module,
|
||||
"initial-product": unref(H),
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`product-id`,
|
||||
`module`,
|
||||
`initial-product`,
|
||||
`edit`,
|
||||
],
|
||||
))
|
||||
: unref(H).module === `jy_cloud` ||
|
||||
unref(H).module === `jy_dcim`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
JyCloudConfig,
|
||||
{
|
||||
key: 2,
|
||||
"product-id": unref(R),
|
||||
module: unref(H).module,
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`product-id`, `module`, `edit`],
|
||||
))
|
||||
: unref(H).module === `idcsmart_common`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: 3,
|
||||
"product-id": unref(R),
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`product-id`, `edit`],
|
||||
))
|
||||
: [
|
||||
`remf_finance`,
|
||||
`remf_finance_dcim`,
|
||||
`remf_finance_common`,
|
||||
].includes(unref(H).module || ``)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
C,
|
||||
{
|
||||
key: 4,
|
||||
"product-id": unref(R),
|
||||
module: unref(H).module,
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`product-id`, `module`, `edit`],
|
||||
))
|
||||
: unref(H).module === `kky_ecs`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
T,
|
||||
{
|
||||
key: 5,
|
||||
"product-id": unref(R),
|
||||
edit: unref(q),
|
||||
onSettled: $,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`product-id`, `edit`],
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(`div`, F, [
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[3] ||= [
|
||||
createTextVNode(
|
||||
` 该商品暂不支持在线配置,请联系客服下单。 `,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
])),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
O,
|
||||
{
|
||||
modelValue: unref(J),
|
||||
"onUpdate:modelValue": (n[0] ||= (e) =>
|
||||
isRef(J) ? (J.value = e) : null),
|
||||
"order-id": unref(Y),
|
||||
amount: unref(X),
|
||||
onSuccess: se,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `order-id`, `amount`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-49461ec8`]],
|
||||
);
|
||||
export {};
|
||||
export default I;
|
||||
</script>
|
||||
@@ -0,0 +1,494 @@
|
||||
<script>
|
||||
import "~/assets/styles/MfCloudConfig.DbgUu8qr.css";
|
||||
import "~/assets/styles/KkyEcsConfig.BFaAwQPZ.css";
|
||||
import "~/assets/styles/ConfigResourceOption.Dj4VopnA.css";
|
||||
import "~/assets/styles/ConfigDiskAdd.C92e9ZuF.css";
|
||||
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
|
||||
import "~/assets/styles/JyCloudConfig.kGfttaHi.css";
|
||||
import "~/assets/styles/FinanceConfig.CLwX1CC8.css";
|
||||
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
|
||||
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
|
||||
import "~/assets/styles/ProductCustomFields.B2QMnPil.css";
|
||||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||||
import "~/assets/styles/CommonConfig.Cfik-oMe.css";
|
||||
import "~/assets/styles/CloudProductPicker.CAm9rmUl.css";
|
||||
import "~/assets/styles/ProductGroupLabel.B1kWpFA-.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/cloud-server.CcwlOXJ0.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
alias: [`/products/cvm`],
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { resolveDynamicComponent } from "vue";
|
||||
import { onScopeDispose } from "vue";
|
||||
import { createBlock } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { withCtx } from "vue";
|
||||
import { createCommentVNode } from "vue";
|
||||
import { mergeProps } from "vue";
|
||||
import { computed } from "vue";
|
||||
import { isRef } from "vue";
|
||||
import { createElementBlock } from "vue";
|
||||
import { toHandlers } 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 { useRouter } from "#app";
|
||||
import { useHead } from "#app";
|
||||
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 PaymentDialog from "~/components/PaymentDialog.vue";
|
||||
import { t as product_order_module_t } from "~/lib/product-order-module.js";
|
||||
import { n as ProductGroupLabel_n } from "~/components/ProductGroupLabel.vue";
|
||||
import CloudProductPicker from "~/components/config/CloudProductPicker.vue";
|
||||
import ConfigLoadingShell from "~/components/config/ConfigLoadingShell.vue";
|
||||
import CommonConfig from "~/components/config/CommonConfig.vue";
|
||||
import FinanceConfig from "~/components/config/FinanceConfig.vue";
|
||||
import JyCloudConfig from "~/components/config/JyCloudConfig.vue";
|
||||
import KkyEcsConfig from "~/components/config/KkyEcsConfig.vue";
|
||||
import MfCloudConfig from "~/components/config/MfCloudConfig.vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as product_description_data_t } from "~/lib/product-description-data.js";
|
||||
var ge = {
|
||||
class: `cloud-order-page`,
|
||||
},
|
||||
_e = {
|
||||
key: 0,
|
||||
class: `product-switch-status`,
|
||||
role: `status`,
|
||||
},
|
||||
S = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `cloud-server`,
|
||||
setup(m) {
|
||||
let y = new Set([
|
||||
`云服务器`,
|
||||
`轻量云服务器`,
|
||||
`国内云服务器`,
|
||||
`香港云服务器`,
|
||||
`弹性云服务器`,
|
||||
]);
|
||||
(composables_t({
|
||||
alias: `/products/cvm`,
|
||||
key: (e) => e.fullPath,
|
||||
}),
|
||||
useHead({
|
||||
title: `创建云服务器实例 - 破碎工坊网络`,
|
||||
}));
|
||||
let S = useApi(),
|
||||
C = useRoute(),
|
||||
ve = useRouter(),
|
||||
w = ref([]),
|
||||
T = ref(null),
|
||||
E = ref([]),
|
||||
D = ref(null),
|
||||
O = ref(null),
|
||||
k = ref(!0),
|
||||
A = ref(!1),
|
||||
j = ref(!1),
|
||||
M = ref(``),
|
||||
N = ref(`groups`),
|
||||
P = ref(``),
|
||||
F = ref(0),
|
||||
ye = computed(() => j.value || !!P.value || O.value !== D.value?.id),
|
||||
I = ref(0),
|
||||
L = ref(1),
|
||||
R = 0,
|
||||
z = 0;
|
||||
onScopeDispose(() => {
|
||||
(R++, z++);
|
||||
});
|
||||
let be = {
|
||||
mf_cloud: MfCloudConfig,
|
||||
remf_cloud: MfCloudConfig,
|
||||
jy_cloud: JyCloudConfig,
|
||||
jy_dcim: JyCloudConfig,
|
||||
kky_ecs: KkyEcsConfig,
|
||||
idcsmart_common: CommonConfig,
|
||||
remf_finance: FinanceConfig,
|
||||
},
|
||||
B = computed(() => be[D.value?.module ?? ``]),
|
||||
V = computed(() =>
|
||||
D.value?.module === `mf_cloud` || D.value?.module === `remf_cloud`
|
||||
? D.value.module
|
||||
: void 0,
|
||||
),
|
||||
H = computed(() =>
|
||||
D.value?.module === `jy_cloud` || D.value?.module === `jy_dcim`
|
||||
? D.value.module
|
||||
: void 0,
|
||||
),
|
||||
U = (e) => Number(e.stock_control) === 1 && !(Number(e.qty) > 0),
|
||||
W = (e) =>
|
||||
e.qty == null || !Number.isFinite(Number(e.qty))
|
||||
? `库存待确认`
|
||||
: `暂时缺货`,
|
||||
G = (e) =>
|
||||
Number(e.hidden ?? 0) !== 1 &&
|
||||
(e.product_group_id_second == null ||
|
||||
Number(e.product_group_id_second) === T.value);
|
||||
async function K(e) {
|
||||
let t = E.value.find((t) => t.id === e);
|
||||
if (
|
||||
!t ||
|
||||
!G(t) ||
|
||||
U(t) ||
|
||||
(O.value === e && (j.value || (D.value?.id === e && !P.value)))
|
||||
)
|
||||
return;
|
||||
let n = ++z;
|
||||
((O.value = e), (P.value = ``), (j.value = !0));
|
||||
try {
|
||||
let r = await S.get(`/product/${e}`);
|
||||
if (n !== z) return;
|
||||
let i = r?.product ?? r;
|
||||
if (!i?.id || Number(i.id) !== e) throw Error(`商品不存在或已下架`);
|
||||
let a = {
|
||||
...t,
|
||||
...i,
|
||||
};
|
||||
if (
|
||||
(typeof i.description != `string` &&
|
||||
typeof t.description == `string` &&
|
||||
(a.description = t.description),
|
||||
!G(a))
|
||||
)
|
||||
throw Error(`商品不存在或已下架`);
|
||||
if (U(a)) throw Error(`当前商品${W(a)},请稍后重试`);
|
||||
let o = await product_order_module_t(S, a);
|
||||
if (n !== z) return;
|
||||
(F.value++,
|
||||
(D.value = {
|
||||
...a,
|
||||
module: o,
|
||||
}),
|
||||
product_description_data_t(S, a).then((e) => {
|
||||
n === z && D.value && (D.value.description = e);
|
||||
}));
|
||||
} catch (e) {
|
||||
n === z &&
|
||||
(P.value = e instanceof Error ? e.message : `商品配置加载失败`);
|
||||
} finally {
|
||||
n === z && (j.value = !1);
|
||||
}
|
||||
}
|
||||
async function q() {
|
||||
let e = ++R;
|
||||
(z++,
|
||||
(E.value = []),
|
||||
(D.value = null),
|
||||
(O.value = null),
|
||||
(j.value = !1),
|
||||
(P.value = ``),
|
||||
(I.value = 0),
|
||||
(M.value = ``),
|
||||
(N.value = `products`),
|
||||
(A.value = !0));
|
||||
try {
|
||||
if (!T.value || !w.value.some((e) => e.id === T.value)) return;
|
||||
let t = await S.get(`/product`, {
|
||||
id: T.value,
|
||||
page: L.value,
|
||||
limit: 24,
|
||||
});
|
||||
if (e !== R) return;
|
||||
((E.value = (t.list ?? []).filter(G)),
|
||||
(I.value = Number(t.count) || 0),
|
||||
(A.value = !1));
|
||||
let n = Number(C.query.id ?? C.query.product_id),
|
||||
r =
|
||||
E.value.find((e) => e.id === n && !U(e)) ??
|
||||
E.value.find((e) => !U(e));
|
||||
r && (await K(r.id));
|
||||
} catch (t) {
|
||||
e === R &&
|
||||
(M.value = t instanceof Error ? t.message : `产品加载失败`);
|
||||
} finally {
|
||||
e === R && (A.value = !1);
|
||||
}
|
||||
}
|
||||
async function J() {
|
||||
let e = ++R;
|
||||
(z++,
|
||||
(k.value = !0),
|
||||
(M.value = ``),
|
||||
(N.value = `groups`),
|
||||
(P.value = ``),
|
||||
(w.value = []),
|
||||
(T.value = null),
|
||||
(E.value = []),
|
||||
(D.value = null),
|
||||
(O.value = null),
|
||||
(I.value = 0),
|
||||
(L.value = 1),
|
||||
(j.value = !1),
|
||||
(A.value = !1));
|
||||
try {
|
||||
let [t, n] = await Promise.all([
|
||||
S.get(`/product/group/first`),
|
||||
S.get(`/product/group/second`),
|
||||
]);
|
||||
if (e !== R) return;
|
||||
let r = new Set(
|
||||
(t.list ?? [])
|
||||
.filter((e) => y.has(ProductGroupLabel_n(e.name).name))
|
||||
.map((e) => Number(e.id)),
|
||||
);
|
||||
((w.value = (n.list ?? []).filter((e) =>
|
||||
r.has(Number(e.parent_id)),
|
||||
)),
|
||||
(T.value = w.value[0]?.id ?? null),
|
||||
(k.value = !1),
|
||||
await q());
|
||||
} catch (t) {
|
||||
e === R &&
|
||||
(M.value = t instanceof Error ? t.message : `线路加载失败`);
|
||||
} finally {
|
||||
e === R && (k.value = !1);
|
||||
}
|
||||
}
|
||||
function xe(e) {
|
||||
T.value !== e &&
|
||||
w.value.some((t) => t.id === e) &&
|
||||
((T.value = e), (L.value = 1), q());
|
||||
}
|
||||
function Se(e) {
|
||||
((L.value = e.page + 1), q());
|
||||
}
|
||||
let Y = ref(!1),
|
||||
X = ref(null),
|
||||
Z = ref(``);
|
||||
function Ce(e) {
|
||||
((X.value = e.order_id), (Z.value = e.amount), (Y.value = !0));
|
||||
}
|
||||
function we() {
|
||||
((Y.value = !1),
|
||||
X.value && ve.push(`/orders/order/paid?id=${X.value}`));
|
||||
}
|
||||
let Q = computed(() => ({
|
||||
groups: w.value,
|
||||
activeGroup: T.value,
|
||||
products: E.value,
|
||||
selectedId: O.value,
|
||||
loading: k.value,
|
||||
productLoading: A.value,
|
||||
error: M.value,
|
||||
errorSource: N.value,
|
||||
total: I.value,
|
||||
page: L.value,
|
||||
soldOut: U,
|
||||
stockLabel: W,
|
||||
})),
|
||||
$ = {
|
||||
"choose-group": xe,
|
||||
"choose-product": K,
|
||||
"retry-groups": J,
|
||||
"retry-products": q,
|
||||
paginate: Se,
|
||||
};
|
||||
return (
|
||||
onMounted(J),
|
||||
(t, r) => {
|
||||
let a = CloudProductPicker,
|
||||
l = button,
|
||||
m = message,
|
||||
_ = ConfigLoadingShell,
|
||||
v = PaymentDialog;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, ge, [
|
||||
(r[4] ||= createElementVNode(
|
||||
`h2`,
|
||||
null,
|
||||
`创建云服务器实例`,
|
||||
-1,
|
||||
)),
|
||||
unref(D) && unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
resolveDynamicComponent(unref(B)),
|
||||
mergeProps(
|
||||
{
|
||||
key: `${unref(D).id}-${unref(F)}`,
|
||||
"product-id": unref(D).id,
|
||||
"identity-locked": unref(ye),
|
||||
},
|
||||
unref(V)
|
||||
? {
|
||||
module: unref(V),
|
||||
initialProduct: unref(D),
|
||||
}
|
||||
: unref(H)
|
||||
? {
|
||||
module: unref(H),
|
||||
}
|
||||
: {},
|
||||
{
|
||||
onSettled: Ce,
|
||||
},
|
||||
),
|
||||
{
|
||||
catalog: withCtx(({ disabled: t }) => [
|
||||
createVNode(
|
||||
a,
|
||||
mergeProps(
|
||||
unref(Q),
|
||||
{
|
||||
disabled: t,
|
||||
},
|
||||
toHandlers($),
|
||||
),
|
||||
null,
|
||||
16,
|
||||
[`disabled`],
|
||||
),
|
||||
unref(j)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`p`,
|
||||
_e,
|
||||
`正在加载所选商品,原配置暂不可操作。`,
|
||||
))
|
||||
: unref(P)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
m,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(P)),
|
||||
1,
|
||||
),
|
||||
unref(O)
|
||||
? (openBlock(),
|
||||
createBlock(l, {
|
||||
key: 0,
|
||||
label: `重新加载配置`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: (r[0] ||= (e) =>
|
||||
K(unref(O))),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
16,
|
||||
[`product-id`, `identity-locked`],
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
_,
|
||||
{
|
||||
key: 1,
|
||||
busy: unref(k) || unref(A) || unref(j),
|
||||
},
|
||||
{
|
||||
catalog: withCtx(() => [
|
||||
createVNode(
|
||||
a,
|
||||
mergeProps(unref(Q), toHandlers($)),
|
||||
null,
|
||||
16,
|
||||
),
|
||||
unref(P)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
m,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(P)),
|
||||
1,
|
||||
),
|
||||
unref(O)
|
||||
? (openBlock(),
|
||||
createBlock(l, {
|
||||
key: 0,
|
||||
label: `重新加载配置`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: (r[1] ||= (e) =>
|
||||
K(unref(O))),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(D)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
m,
|
||||
{
|
||||
key: 1,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(r[3] ||= [
|
||||
createTextVNode(
|
||||
`当前商品暂不支持在线配置,请通过工单咨询。`,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`busy`],
|
||||
)),
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
modelValue: unref(Y),
|
||||
"onUpdate:modelValue": (r[2] ||= (e) =>
|
||||
isRef(Y) ? (Y.value = e) : null),
|
||||
"order-id": unref(X),
|
||||
amount: unref(Z),
|
||||
onSuccess: we,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `order-id`, `amount`],
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-ef3931f0`]],
|
||||
);
|
||||
export {};
|
||||
export default S;
|
||||
</script>
|
||||
@@ -0,0 +1,255 @@
|
||||
<script>
|
||||
import "~/assets/styles/dedicated-server.CiJfMYtk.css";
|
||||
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
|
||||
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
|
||||
import "~/assets/styles/ProductCustomFields.B2QMnPil.css";
|
||||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||||
import "~/assets/styles/MfDcimConfig.BhC_eZ0V.css";
|
||||
import "~/assets/styles/PaymentDialog.BNFKQF1U.css";
|
||||
import "~/assets/styles/customize.Cc123Awf.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { onScopeDispose } 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 { useRoute } from "#app";
|
||||
import { useRouter } from "#app";
|
||||
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 PaymentDialog from "~/components/PaymentDialog.vue";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { t as product_order_module_t } from "~/lib/product-order-module.js";
|
||||
import MfDcimConfig from "~/components/config/MfDcimConfig.vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as product_description_data_t } from "~/lib/product-description-data.js";
|
||||
import index from "~/pages/products/dedicated-server/index.vue";
|
||||
var A = {
|
||||
key: 1,
|
||||
class: `dedicated-customize`,
|
||||
},
|
||||
j = {
|
||||
class: `product-links`,
|
||||
},
|
||||
M = {
|
||||
key: 0,
|
||||
class: `panel`,
|
||||
},
|
||||
N = {
|
||||
key: 1,
|
||||
class: `panel config-load-error`,
|
||||
},
|
||||
P = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `customize`,
|
||||
setup(p) {
|
||||
let x = useRoute(),
|
||||
P = useRouter(),
|
||||
F = useApi(),
|
||||
I = computed(() => String(x.query.id ?? x.query.product_id ?? ``));
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let L = ref(null),
|
||||
R = ref(!0),
|
||||
z = ref(``),
|
||||
B = ref(!1),
|
||||
V = ref(null),
|
||||
H = ref(``),
|
||||
U = 0;
|
||||
onScopeDispose(() => {
|
||||
U++;
|
||||
});
|
||||
async function W() {
|
||||
let e = ++U,
|
||||
t = I.value;
|
||||
((R.value = !0), (z.value = ``), (L.value = null));
|
||||
try {
|
||||
if (!/^[1-9]\d*$/.test(t)) throw Error(`商品编号无效`);
|
||||
let n = await F.get(`/product/${t}`);
|
||||
if (e !== U) return;
|
||||
let r = n?.product ?? n;
|
||||
if (!r || Number(r.id) !== Number(t) || r.hidden === 1)
|
||||
throw Error(`商品不存在或已下架`);
|
||||
let i = r,
|
||||
a = await product_order_module_t(F, i);
|
||||
if (a !== `mf_dcim` && a !== `remf_dcim`)
|
||||
throw Error(`该商品不支持物理服务器定制,请返回列表重新选择`);
|
||||
((L.value = {
|
||||
...i,
|
||||
module: a,
|
||||
}),
|
||||
product_description_data_t(F, L.value).then((t) => {
|
||||
e === U && L.value && (L.value.description = t);
|
||||
}));
|
||||
} catch (t) {
|
||||
e === U &&
|
||||
(z.value = t instanceof Error ? t.message : `加载商品失败`);
|
||||
} finally {
|
||||
e === U && (R.value = !1);
|
||||
}
|
||||
}
|
||||
function G(e) {
|
||||
((V.value = e.order_id), (H.value = e.amount), (B.value = !0));
|
||||
}
|
||||
return (
|
||||
onMounted(() => {
|
||||
I.value ? W() : (R.value = !1);
|
||||
}),
|
||||
(t, n) => {
|
||||
let i = NuxtLink,
|
||||
s = skeleton,
|
||||
p = message,
|
||||
g = button,
|
||||
_ = MfDcimConfig,
|
||||
y = PaymentDialog;
|
||||
return unref(I)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, A, [
|
||||
createElementVNode(`header`, null, [
|
||||
(n[4] ||= createElementVNode(
|
||||
`h1`,
|
||||
null,
|
||||
`定制物理服务器`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, j, [
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: `/products/dedicated-server`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-angle-left`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`返回物理服务器列表`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
i,
|
||||
{
|
||||
to: `/cart`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[3] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-shopping-cart`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(`购物车`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(R)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, M, [
|
||||
createVNode(s, {
|
||||
height: `360px`,
|
||||
}),
|
||||
]))
|
||||
: unref(z)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, N, [
|
||||
createVNode(
|
||||
p,
|
||||
{
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(z)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(g, {
|
||||
label: `重新加载商品`,
|
||||
icon: `pi pi-refresh`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
onClick: W,
|
||||
}),
|
||||
]))
|
||||
: unref(L)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
_,
|
||||
{
|
||||
key: 2,
|
||||
"product-id": unref(I),
|
||||
module: unref(L).module,
|
||||
"initial-product": unref(L),
|
||||
onSettled: G,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`product-id`, `module`, `initial-product`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
modelValue: unref(B),
|
||||
"onUpdate:modelValue": (n[0] ||= (e) =>
|
||||
isRef(B) ? (B.value = e) : null),
|
||||
"order-id": unref(V),
|
||||
amount: unref(H),
|
||||
onSuccess: (n[1] ||= (e) => unref(P).push(`/orders`)),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `order-id`, `amount`],
|
||||
),
|
||||
]))
|
||||
: (openBlock(),
|
||||
createBlock(index, {
|
||||
key: 0,
|
||||
}));
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-5618b27d`]],
|
||||
);
|
||||
export {};
|
||||
export default P;
|
||||
</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,907 @@
|
||||
<script>
|
||||
import "~/assets/styles/PhoneCodeField.CwyHXfML.css";
|
||||
import "~/assets/styles/GeetestField.DiieTibK.css";
|
||||
import "~/assets/styles/CaptchaField.BSN3ZbsD.css";
|
||||
definePageMeta({
|
||||
layout: `blank`,
|
||||
alias: [`/signup`],
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { renderList } 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 { 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 { withModifiers } from "vue";
|
||||
import { useRoute } from "#app";
|
||||
import { useRouter } from "#app";
|
||||
import { useHead } from "#app";
|
||||
import { NuxtLink } from "#components";
|
||||
import { useApi } from "~/lib/auth.js";
|
||||
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
|
||||
import button from "primevue/button";
|
||||
import message from "primevue/message";
|
||||
import { n as auth_redirect_n } from "~/lib/auth-redirect.js";
|
||||
import { t as auth_redirect_t } from "~/lib/auth-redirect.js";
|
||||
import inputtext from "primevue/inputtext";
|
||||
import CaptchaField from "~/components/CaptchaField.vue";
|
||||
import select from "primevue/select";
|
||||
import checkbox from "primevue/checkbox";
|
||||
import password from "primevue/password";
|
||||
import textarea from "primevue/textarea";
|
||||
import PhoneCodeField from "~/components/PhoneCodeField.vue";
|
||||
import { i as product_fields_i } from "~/lib/product-fields.js";
|
||||
import { t as useCaptcha_t } from "~/lib/useCaptcha.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
import { t as useVerifyCode_t } from "~/lib/useVerifyCode.js";
|
||||
var w = (e) => e === !0 || e === 1 || e === `1`,
|
||||
T = (e) => (typeof e == `string` || typeof e == `number` ? String(e) : ``);
|
||||
function _e(e) {
|
||||
if (e == null)
|
||||
return {
|
||||
fields: [],
|
||||
error: ``,
|
||||
};
|
||||
if (!Array.isArray(e))
|
||||
return {
|
||||
fields: [],
|
||||
error: `注册资料配置暂不可用,请联系客服`,
|
||||
};
|
||||
let t = [];
|
||||
for (let n of e) {
|
||||
if (!n || typeof n != `object` || Array.isArray(n))
|
||||
return {
|
||||
fields: t,
|
||||
error: `注册资料配置暂不可用,请联系客服`,
|
||||
};
|
||||
let e = n;
|
||||
if (e.show_register !== void 0 && !w(e.show_register)) continue;
|
||||
let r = T(e.field ?? e.key ?? e.id ?? e.name),
|
||||
i = T(e.title ?? e.label ?? e.field_name ?? e.name) || `注册资料`,
|
||||
a = {
|
||||
string: `text`,
|
||||
text: `text`,
|
||||
password: `password`,
|
||||
textarea: `textarea`,
|
||||
select: `select`,
|
||||
dropdown: `select`,
|
||||
checkbox: `boolean`,
|
||||
tickbox: `boolean`,
|
||||
explain: `explain`,
|
||||
link: `link`,
|
||||
}[T(e.type ?? e.field_type) || `text`];
|
||||
if (
|
||||
!r ||
|
||||
[`__proto__`, `prototype`, `constructor`].includes(r) ||
|
||||
!a ||
|
||||
t.some((e) => e.id === r)
|
||||
)
|
||||
return {
|
||||
fields: t,
|
||||
error: `${i}的配置暂不受支持,请联系客服`,
|
||||
};
|
||||
let o = e.options ?? e.field_option,
|
||||
s = Array.isArray(o)
|
||||
? o.map((e) => {
|
||||
if (e && typeof e == `object`) {
|
||||
let t = e;
|
||||
return {
|
||||
value: T(t.value ?? t.id),
|
||||
label: T(t.label ?? t.name ?? t.value),
|
||||
};
|
||||
}
|
||||
return {
|
||||
value: T(e),
|
||||
label: T(e),
|
||||
};
|
||||
})
|
||||
: o && typeof o == `object`
|
||||
? Object.entries(o).map(([e, t]) => ({
|
||||
value: e,
|
||||
label: T(t),
|
||||
}))
|
||||
: T(o)
|
||||
.split(/[,\n]/)
|
||||
.map((e) => ({
|
||||
value: e.trim(),
|
||||
label: e.trim(),
|
||||
}))
|
||||
.filter((e) => e.value);
|
||||
t.push({
|
||||
id: r,
|
||||
label: i,
|
||||
kind: a,
|
||||
required: w(e.required ?? e.is_required),
|
||||
options: s,
|
||||
pattern: T(e.regexpr ?? e.pattern) || void 0,
|
||||
description: T(e.description ?? e.tip),
|
||||
explain: T(e.explain_content),
|
||||
});
|
||||
}
|
||||
return {
|
||||
fields: t,
|
||||
error: ``,
|
||||
};
|
||||
}
|
||||
var ve = {
|
||||
class: `auth-card login-card`,
|
||||
},
|
||||
ye = {
|
||||
class: `login-brand`,
|
||||
},
|
||||
be = {
|
||||
class: `seg`,
|
||||
role: `group`,
|
||||
"aria-label": `注册方式`,
|
||||
},
|
||||
xe = [`aria-pressed`, `disabled`],
|
||||
E = [`aria-pressed`, `disabled`],
|
||||
D = {
|
||||
class: `field`,
|
||||
},
|
||||
O = {
|
||||
for: `account`,
|
||||
},
|
||||
k = [`for`],
|
||||
A = {
|
||||
key: 0,
|
||||
class: `req`,
|
||||
},
|
||||
j = {
|
||||
key: 0,
|
||||
},
|
||||
M = {
|
||||
key: 5,
|
||||
},
|
||||
Se = {
|
||||
key: 4,
|
||||
class: `field`,
|
||||
},
|
||||
Ce = {
|
||||
class: `code-row`,
|
||||
},
|
||||
we = {
|
||||
class: `field`,
|
||||
},
|
||||
Te = {
|
||||
class: `field`,
|
||||
},
|
||||
Ee = {
|
||||
class: `field`,
|
||||
},
|
||||
De = {
|
||||
class: `login-links center`,
|
||||
},
|
||||
N = defineComponent({
|
||||
__name: `register`,
|
||||
setup(m) {
|
||||
(useHead({
|
||||
title: `注册账号 - 破碎工坊网络`,
|
||||
}),
|
||||
composables_t({
|
||||
layout: `blank`,
|
||||
alias: `/signup`,
|
||||
}));
|
||||
let w = useApi(),
|
||||
T = useRouter(),
|
||||
N = useRoute(),
|
||||
P = ref(`phone`),
|
||||
F = reactive({
|
||||
account: ``,
|
||||
code: ``,
|
||||
username: ``,
|
||||
password: ``,
|
||||
re_password: ``,
|
||||
phone_code: `86`,
|
||||
customfield: {},
|
||||
}),
|
||||
I = ref(``),
|
||||
L = ref(!1),
|
||||
R = useCaptcha_t(`register`),
|
||||
{
|
||||
needed: Oe,
|
||||
provider: ke,
|
||||
captchaId: Ae,
|
||||
complete: je,
|
||||
invalidate: Me,
|
||||
img: Ne,
|
||||
value: z,
|
||||
loading: Pe,
|
||||
error: B,
|
||||
load: Fe,
|
||||
handleError: Ie,
|
||||
} = R,
|
||||
{
|
||||
siteName: Le,
|
||||
config: V,
|
||||
error: H,
|
||||
load: U,
|
||||
on: W,
|
||||
} = useSiteConfig_t(),
|
||||
G = computed(() => ({
|
||||
phone:
|
||||
V.value?.register_phone === void 0 || W(V.value?.register_phone),
|
||||
email:
|
||||
V.value?.register_email === void 0 || W(V.value?.register_email),
|
||||
})),
|
||||
K = computed(() =>
|
||||
P.value === `phone`
|
||||
? V.value?.code_client_phone_register === void 0 ||
|
||||
W(V.value?.code_client_phone_register)
|
||||
: V.value?.code_client_email_register === void 0 ||
|
||||
W(V.value?.code_client_email_register),
|
||||
),
|
||||
q = computed(() => _e(V.value?.custom_fields)),
|
||||
J = computed(() => q.value.fields),
|
||||
Y = computed(() => !!V.value && (G.value.phone || G.value.email));
|
||||
async function X() {
|
||||
(await U(), !G.value.phone && G.value.email && (P.value = `email`));
|
||||
}
|
||||
onMounted(X);
|
||||
let {
|
||||
sending: Z,
|
||||
countdown: Q,
|
||||
send: Re,
|
||||
} = useVerifyCode_t({
|
||||
action: `register`,
|
||||
captcha: R,
|
||||
error: I,
|
||||
phoneCode: () => F.phone_code,
|
||||
});
|
||||
function ze() {
|
||||
if (!Y.value || !G.value[P.value] || !K.value || L.value) return;
|
||||
let e = F.account.trim();
|
||||
return Re(
|
||||
P.value,
|
||||
e,
|
||||
P.value === `email` ? `请输入邮箱` : `请输入手机号`,
|
||||
);
|
||||
}
|
||||
function $(e) {
|
||||
!G.value[e] || L.value || Z.value || ((P.value = e), (F.code = ``));
|
||||
}
|
||||
async function Be() {
|
||||
if (L.value || Z.value) return;
|
||||
if (((I.value = ``), !V.value))
|
||||
return (I.value = `请先重新加载注册设置`);
|
||||
if (!G.value[P.value]) return (I.value = `当前注册方式未开放`);
|
||||
if (q.value.error) return (I.value = q.value.error);
|
||||
let e = F.account.trim();
|
||||
if (!e)
|
||||
return (I.value =
|
||||
P.value === `email` ? `请输入邮箱` : `请输入手机号`);
|
||||
if (P.value === `phone` && !/^[1-9]\d{0,3}$/.test(F.phone_code))
|
||||
return (I.value = `请输入有效的国际电话区号`);
|
||||
if (K.value && !F.code.trim()) return (I.value = `请输入验证码`);
|
||||
if (!F.password) return (I.value = `请输入密码`);
|
||||
if (F.password !== F.re_password)
|
||||
return (I.value = `两次输入的密码不一致`);
|
||||
try {
|
||||
product_fields_i(J.value, F.customfield);
|
||||
} catch (e) {
|
||||
I.value = e instanceof Error ? e.message : `请检查注册资料`;
|
||||
return;
|
||||
}
|
||||
L.value = !0;
|
||||
try {
|
||||
(await w.post(`/register`, {
|
||||
type: P.value,
|
||||
account: e,
|
||||
phone_code: F.phone_code,
|
||||
code: K.value ? F.code.trim() : ``,
|
||||
username: F.username.trim(),
|
||||
password: F.password,
|
||||
re_password: F.re_password,
|
||||
customfield: Object.fromEntries(
|
||||
J.value
|
||||
.filter((e) => e.kind !== `explain`)
|
||||
.map((e) => [e.id, F.customfield[e.id] || ``]),
|
||||
),
|
||||
}),
|
||||
await T.push({
|
||||
path: `/login`,
|
||||
query: {
|
||||
registered: `1`,
|
||||
...auth_redirect_n(N.query.redirect),
|
||||
},
|
||||
}));
|
||||
} catch (e) {
|
||||
((I.value = e instanceof Error ? e.message : `注册失败`),
|
||||
await Ie(e));
|
||||
} finally {
|
||||
L.value = !1;
|
||||
}
|
||||
}
|
||||
return (n, a) => {
|
||||
let c = button,
|
||||
l = message,
|
||||
m = PhoneCodeField,
|
||||
_ = inputtext,
|
||||
v = textarea,
|
||||
y = select,
|
||||
b = checkbox,
|
||||
x = CaptchaField,
|
||||
S = password,
|
||||
C = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, ve, [
|
||||
createElementVNode(`div`, ye, [
|
||||
(a[9] ||= createElementVNode(`h1`, null, `创建账户`, -1)),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`只需几分钟,即可开始使用` +
|
||||
toDisplayString(unref(Le)) +
|
||||
`服务。`,
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
class: `login-form`,
|
||||
onSubmit: withModifiers(Be, [`prevent`]),
|
||||
},
|
||||
[
|
||||
unref(H)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
l,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(H)) + ` `, 1),
|
||||
createVNode(c, {
|
||||
label: `重新加载`,
|
||||
text: ``,
|
||||
onClick: X,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(V) && !unref(Y)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
l,
|
||||
{
|
||||
key: 1,
|
||||
severity: `info`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[10] ||= [
|
||||
createTextVNode(`本站暂未开放新用户注册`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(q).error
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
l,
|
||||
{
|
||||
key: 2,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(q).error), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, be, [
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(P) === `email`,
|
||||
}),
|
||||
"aria-pressed": unref(P) === `email`,
|
||||
onClick: (a[0] ||= (e) => $(`email`)),
|
||||
disabled: !unref(G).email || unref(L) || unref(Z),
|
||||
},
|
||||
` 邮箱 `,
|
||||
10,
|
||||
xe,
|
||||
),
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: normalizeClass({
|
||||
active: unref(P) === `phone`,
|
||||
}),
|
||||
"aria-pressed": unref(P) === `phone`,
|
||||
onClick: (a[1] ||= (e) => $(`phone`)),
|
||||
disabled: !unref(G).phone || unref(L) || unref(Z),
|
||||
},
|
||||
` 手机号 `,
|
||||
10,
|
||||
E,
|
||||
),
|
||||
]),
|
||||
unref(P) === `phone`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
m,
|
||||
{
|
||||
key: 3,
|
||||
modelValue: unref(F).phone_code,
|
||||
"onUpdate:modelValue": (a[2] ||= (e) =>
|
||||
(unref(F).phone_code = e)),
|
||||
disabled: unref(L) || unref(Z),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, D, [
|
||||
createElementVNode(
|
||||
`label`,
|
||||
O,
|
||||
toDisplayString(unref(P) === `email` ? `邮箱` : `手机号`),
|
||||
1,
|
||||
),
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
id: `account`,
|
||||
modelValue: unref(F).account,
|
||||
"onUpdate:modelValue": (a[3] ||= (e) =>
|
||||
(unref(F).account = e)),
|
||||
placeholder:
|
||||
unref(P) === `email` ? `请输入邮箱` : `请输入手机号`,
|
||||
autocomplete: `username`,
|
||||
disabled: unref(L) || unref(Z),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `placeholder`, `disabled`],
|
||||
),
|
||||
]),
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(J),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: t.id,
|
||||
class: `field`,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `custom-${t.id}`,
|
||||
},
|
||||
[
|
||||
createTextVNode(
|
||||
toDisplayString(t.label || t.id) + ` `,
|
||||
1,
|
||||
),
|
||||
t.required
|
||||
? (openBlock(),
|
||||
createElementBlock(`span`, A, `*`))
|
||||
: createCommentVNode(``, !0),
|
||||
],
|
||||
8,
|
||||
k,
|
||||
),
|
||||
t.kind === `explain`
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`p`,
|
||||
j,
|
||||
toDisplayString(t.explain || t.description),
|
||||
1,
|
||||
))
|
||||
: t.kind === `textarea`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
id: `custom-${t.id}`,
|
||||
modelValue: unref(F).customfield[t.id],
|
||||
"onUpdate:modelValue": (e) =>
|
||||
(unref(F).customfield[t.id] = e),
|
||||
disabled: unref(L),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`id`,
|
||||
`modelValue`,
|
||||
`onUpdate:modelValue`,
|
||||
`disabled`,
|
||||
],
|
||||
))
|
||||
: t.kind === `select`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 2,
|
||||
"input-id": `custom-${t.id}`,
|
||||
modelValue: unref(F).customfield[t.id],
|
||||
"onUpdate:modelValue": (e) =>
|
||||
(unref(F).customfield[t.id] = e),
|
||||
options: t.options,
|
||||
"option-label": `label`,
|
||||
"option-value": `value`,
|
||||
disabled: unref(L),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`input-id`,
|
||||
`modelValue`,
|
||||
`onUpdate:modelValue`,
|
||||
`options`,
|
||||
`disabled`,
|
||||
],
|
||||
))
|
||||
: t.kind === `boolean`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
b,
|
||||
{
|
||||
key: 3,
|
||||
"input-id": `custom-${t.id}`,
|
||||
modelValue: unref(F).customfield[t.id],
|
||||
"onUpdate:modelValue": (e) =>
|
||||
(unref(F).customfield[t.id] = e),
|
||||
binary: ``,
|
||||
"true-value": `1`,
|
||||
"false-value": ``,
|
||||
disabled: unref(L),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`input-id`,
|
||||
`modelValue`,
|
||||
`onUpdate:modelValue`,
|
||||
`disabled`,
|
||||
],
|
||||
))
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
_,
|
||||
{
|
||||
key: 4,
|
||||
id: `custom-${t.id}`,
|
||||
modelValue: unref(F).customfield[t.id],
|
||||
"onUpdate:modelValue": (e) =>
|
||||
(unref(F).customfield[t.id] = e),
|
||||
type:
|
||||
t.kind === `password`
|
||||
? `password`
|
||||
: `text`,
|
||||
disabled: unref(L),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`id`,
|
||||
`modelValue`,
|
||||
`onUpdate:modelValue`,
|
||||
`type`,
|
||||
`disabled`,
|
||||
],
|
||||
)),
|
||||
t.description && t.kind !== `explain`
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`small`,
|
||||
M,
|
||||
toDisplayString(t.description),
|
||||
1,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
unref(K)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, Se, [
|
||||
(a[11] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `code`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`验证码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, Ce, [
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
id: `code`,
|
||||
modelValue: unref(F).code,
|
||||
"onUpdate:modelValue": (a[4] ||= (e) =>
|
||||
(unref(F).code = e)),
|
||||
placeholder: `请输入验证码`,
|
||||
autocomplete: `one-time-code`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
type: `button`,
|
||||
label: unref(Q) > 0 ? `${unref(Q)}s` : `获取验证码`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
loading: unref(Z),
|
||||
disabled:
|
||||
unref(Q) > 0 ||
|
||||
unref(L) ||
|
||||
!unref(Y) ||
|
||||
!unref(G)[unref(P)],
|
||||
onClick: ze,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`, `loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(Oe) && unref(K)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
x,
|
||||
{
|
||||
key: 5,
|
||||
modelValue: unref(z),
|
||||
"onUpdate:modelValue": (a[5] ||= (e) =>
|
||||
isRef(z) ? (z.value = e) : null),
|
||||
img: unref(Ne),
|
||||
provider: unref(ke),
|
||||
"captcha-id": unref(Ae),
|
||||
disabled: unref(L) || unref(Z),
|
||||
onVerified: unref(je),
|
||||
onInvalid: unref(Me),
|
||||
loading: unref(Pe),
|
||||
onRefresh: unref(Fe),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`modelValue`,
|
||||
`img`,
|
||||
`provider`,
|
||||
`captcha-id`,
|
||||
`disabled`,
|
||||
`onVerified`,
|
||||
`onInvalid`,
|
||||
`loading`,
|
||||
`onRefresh`,
|
||||
],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, we, [
|
||||
(a[12] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `username`,
|
||||
},
|
||||
`姓名`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
id: `username`,
|
||||
modelValue: unref(F).username,
|
||||
"onUpdate:modelValue": (a[6] ||= (e) =>
|
||||
(unref(F).username = e)),
|
||||
placeholder: `选填`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, Te, [
|
||||
(a[13] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `password`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`密码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
"input-id": `password`,
|
||||
modelValue: unref(F).password,
|
||||
"onUpdate:modelValue": (a[7] ||= (e) =>
|
||||
(unref(F).password = e)),
|
||||
feedback: !1,
|
||||
toggleMask: ``,
|
||||
autocomplete: `new-password`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, Ee, [
|
||||
(a[14] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `re-password`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`确认密码 `),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `req`,
|
||||
},
|
||||
`*`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
"input-id": `re-password`,
|
||||
modelValue: unref(F).re_password,
|
||||
"onUpdate:modelValue": (a[8] ||= (e) =>
|
||||
(unref(F).re_password = e)),
|
||||
feedback: !1,
|
||||
toggleMask: ``,
|
||||
autocomplete: `new-password`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
unref(I)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
l,
|
||||
{
|
||||
key: 6,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(I)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
l,
|
||||
{
|
||||
key: 7,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(B)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `创建账户`,
|
||||
loading: unref(L),
|
||||
disabled: !unref(Y) || !!unref(q).error || unref(Z),
|
||||
class: `login-btn`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
createElementVNode(`div`, De, [
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
to: unref(auth_redirect_t)(
|
||||
`/login`,
|
||||
unref(N).query.redirect,
|
||||
),
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[15] ||= [
|
||||
createTextVNode(`已有账号?返回登录`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
]),
|
||||
],
|
||||
32,
|
||||
),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default N;
|
||||
</script>
|
||||
@@ -0,0 +1,427 @@
|
||||
<script>
|
||||
import "~/assets/styles/RemoteConsole.DLmX5UZu.css";
|
||||
import "~/assets/styles/remote-console.zcxaOxxS.css";
|
||||
definePageMeta({
|
||||
layout: !1,
|
||||
});
|
||||
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 { withModifiers } from "vue";
|
||||
import { useRoute } from "#app";
|
||||
import { useHead } from "#app";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
|
||||
import RemoteConsole from "~/components/instance/RemoteConsole.vue";
|
||||
import { logoUrl } from "~/utils/brand.js";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var O = {
|
||||
class: `standalone-console`,
|
||||
},
|
||||
k = {
|
||||
class: `console-page-header`,
|
||||
},
|
||||
A = {
|
||||
key: 0,
|
||||
class: `console-page-host`,
|
||||
},
|
||||
j = {
|
||||
class: `console-page-content`,
|
||||
},
|
||||
M = {
|
||||
key: 0,
|
||||
class: `console-intro`,
|
||||
"aria-labelledby": `console-invalid-title`,
|
||||
},
|
||||
N = {
|
||||
key: 1,
|
||||
class: `console-intro`,
|
||||
"aria-labelledby": `console-closed-title`,
|
||||
},
|
||||
P = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `remote-console`,
|
||||
setup(m) {
|
||||
(composables_t({
|
||||
layout: !1,
|
||||
}),
|
||||
useHead({
|
||||
title: `远程控制台 - 破碎工坊云`,
|
||||
}));
|
||||
let S = useRoute(),
|
||||
P = ref(!0),
|
||||
F = ref(``),
|
||||
I = ref(!1),
|
||||
L = computed(() =>
|
||||
/^\d+$/.test(String(S.query.hostId || ``))
|
||||
? String(S.query.hostId)
|
||||
: ``,
|
||||
),
|
||||
R = new Set([
|
||||
`kky_ecs`,
|
||||
`mf_cloud`,
|
||||
`remf_cloud`,
|
||||
`mf_dcim`,
|
||||
`remf_dcim`,
|
||||
`remf_finance`,
|
||||
`remf_finance_dcim`,
|
||||
`remf_finance_common`,
|
||||
`idcsmart_common`,
|
||||
]),
|
||||
z = computed(() =>
|
||||
R.has(String(S.query.module)) ? String(S.query.module) : ``,
|
||||
),
|
||||
B = computed(() =>
|
||||
L.value
|
||||
? {
|
||||
path: `/servers/server`,
|
||||
query: {
|
||||
id: L.value,
|
||||
},
|
||||
}
|
||||
: {
|
||||
path: `/cloud-servers`,
|
||||
},
|
||||
),
|
||||
V = computed(() => z.value === `mf_dcim` && !I.value);
|
||||
function H() {
|
||||
((I.value = !0), (P.value = !0));
|
||||
}
|
||||
function U() {
|
||||
((F.value = ``), (I.value = !1), (P.value = !0));
|
||||
}
|
||||
return (
|
||||
watch(P, (e) => {
|
||||
e || ((F.value = ``), (I.value = !1));
|
||||
}),
|
||||
watch([L, z], () => {
|
||||
((F.value = ``), (I.value = !1), (P.value = !0));
|
||||
}),
|
||||
onBeforeUnmount(() => {
|
||||
F.value = ``;
|
||||
}),
|
||||
(t, n) => {
|
||||
let i = RemoteConsole,
|
||||
s = NuxtLink,
|
||||
m = button,
|
||||
v = inputtext,
|
||||
y = OperatePasswordGate;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`main`, O, [
|
||||
unref(L) && unref(z) && unref(P) && !unref(V)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
i,
|
||||
{
|
||||
key: 0,
|
||||
visible: unref(P),
|
||||
"onUpdate:visible": (n[0] ||= (e) =>
|
||||
isRef(P) ? (P.value = e) : null),
|
||||
"host-id": unref(L),
|
||||
module: unref(z),
|
||||
"operate-password": unref(F),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`visible`, `host-id`, `module`, `operate-password`],
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 1,
|
||||
},
|
||||
[
|
||||
createElementVNode(`header`, k, [
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
to: unref(B),
|
||||
class: `console-page-brand`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[2] ||= [
|
||||
createElementVNode(
|
||||
`img`,
|
||||
{
|
||||
src: logoUrl,
|
||||
alt: `破碎工坊云`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
unref(L)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
A,
|
||||
`实例 #` + toDisplayString(unref(L)),
|
||||
1,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
createElementVNode(`div`, j, [
|
||||
!unref(L) || !unref(z)
|
||||
? (openBlock(),
|
||||
createElementBlock(`section`, M, [
|
||||
(n[4] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-link intro-icon`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(n[5] ||= createElementVNode(
|
||||
`h1`,
|
||||
{
|
||||
id: `console-invalid-title`,
|
||||
},
|
||||
`控制台链接已失效`,
|
||||
-1,
|
||||
)),
|
||||
(n[6] ||= createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`请从实例详情页重新打开远程控制台。`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
to: `/cloud-servers`,
|
||||
class: `console-return`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[3] ||= [
|
||||
createTextVNode(`返回云服务器`, -1),
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-arrow-right`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]))
|
||||
: unref(P)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`form`,
|
||||
{
|
||||
key: 2,
|
||||
class: `console-intro console-operation`,
|
||||
"aria-labelledby": `console-operation-title`,
|
||||
onSubmit: withModifiers(H, [`prevent`]),
|
||||
},
|
||||
[
|
||||
(n[14] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-desktop intro-icon`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(n[15] ||= createElementVNode(
|
||||
`h1`,
|
||||
{
|
||||
id: `console-operation-title`,
|
||||
},
|
||||
`连接远程控制台`,
|
||||
-1,
|
||||
)),
|
||||
(n[16] ||= createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`在此标签页中查看和操作实例屏幕。`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(y, null, {
|
||||
default: withCtx(() => [
|
||||
(n[11] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `console-operation-password`,
|
||||
},
|
||||
[
|
||||
createTextVNode(`操作密码`),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`选填`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
id: `console-operation-password`,
|
||||
modelValue: unref(F),
|
||||
"onUpdate:modelValue": (n[1] ||= (
|
||||
e,
|
||||
) =>
|
||||
isRef(F) ? (F.value = e) : null),
|
||||
type: `password`,
|
||||
autocomplete: `off`,
|
||||
fluid: ``,
|
||||
"aria-describedby": `console-operation-help`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
(n[12] ||= createElementVNode(
|
||||
`p`,
|
||||
{
|
||||
id: `console-operation-help`,
|
||||
class: `operation-help`,
|
||||
},
|
||||
`若此实例开启了操作验证,请填写操作密码。`,
|
||||
-1,
|
||||
)),
|
||||
]),
|
||||
_: 1,
|
||||
}),
|
||||
createVNode(m, {
|
||||
type: `submit`,
|
||||
label: `连接控制台`,
|
||||
icon: `pi pi-arrow-right`,
|
||||
fluid: ``,
|
||||
}),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
to: unref(B),
|
||||
class: `console-return`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[13] ||= [
|
||||
createTextVNode(`返回实例详情`, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
],
|
||||
32,
|
||||
))
|
||||
: (openBlock(),
|
||||
createElementBlock(`section`, N, [
|
||||
(n[8] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-desktop intro-icon`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(n[9] ||= createElementVNode(
|
||||
`h1`,
|
||||
{
|
||||
id: `console-closed-title`,
|
||||
},
|
||||
`远程控制台已关闭`,
|
||||
-1,
|
||||
)),
|
||||
(n[10] ||= createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`远程会话已结束,实例继续运行。您可以关闭此标签页,或重新打开控制台。`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(m, {
|
||||
label: `重新打开控制台`,
|
||||
icon: `pi pi-refresh`,
|
||||
onClick: U,
|
||||
}),
|
||||
createVNode(
|
||||
s,
|
||||
{
|
||||
to: unref(B),
|
||||
class: `console-return`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(n[7] ||= [
|
||||
createTextVNode(`返回实例详情`, -1),
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-arrow-right`,
|
||||
"aria-hidden": `true`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`to`],
|
||||
),
|
||||
])),
|
||||
]),
|
||||
(n[17] ||= createElementVNode(
|
||||
`footer`,
|
||||
{
|
||||
class: `console-page-footer`,
|
||||
},
|
||||
`关闭控制台不会关闭实例`,
|
||||
-1,
|
||||
)),
|
||||
],
|
||||
64,
|
||||
)),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-5f7e2625`]],
|
||||
);
|
||||
export {};
|
||||
export default P;
|
||||
</script>
|
||||
@@ -0,0 +1,263 @@
|
||||
<script>
|
||||
import "~/assets/styles/notices.BXNGOj-Q.css";
|
||||
import "~/assets/styles/news.CbIzdrjt.css";
|
||||
import "~/assets/styles/help.BSOB30LE.css";
|
||||
import "~/assets/styles/resources._aUrMsvM.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 { 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 { useRouter } from "#app";
|
||||
import { navigateTo } from "#app";
|
||||
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 skeleton from "primevue/skeleton";
|
||||
import { n as content_route_n } from "~/lib/content-route.js";
|
||||
import { r as content_route_r } from "~/lib/content-route.js";
|
||||
import help from "~/pages/help.vue";
|
||||
import news from "~/pages/news.vue";
|
||||
import index from "~/pages/notices/index.vue";
|
||||
var j = {
|
||||
class: `resources-page`,
|
||||
},
|
||||
M = {
|
||||
class: `page-head`,
|
||||
},
|
||||
N = {
|
||||
class: `resource-tabs`,
|
||||
role: `tablist`,
|
||||
"aria-label": `资源分类`,
|
||||
},
|
||||
P = [
|
||||
`id`,
|
||||
`aria-selected`,
|
||||
`aria-controls`,
|
||||
`tabindex`,
|
||||
`onClick`,
|
||||
`onKeydown`,
|
||||
],
|
||||
F = [`id`, `aria-labelledby`],
|
||||
I = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `resources`,
|
||||
setup(h) {
|
||||
let C = useRoute(),
|
||||
I = useRouter(),
|
||||
L = useApi(),
|
||||
R = ref(null),
|
||||
z = ref(``),
|
||||
B = ref(!1),
|
||||
V = [
|
||||
{
|
||||
value: `help`,
|
||||
label: `帮助文档`,
|
||||
},
|
||||
{
|
||||
value: `news`,
|
||||
label: `新闻资讯`,
|
||||
},
|
||||
{
|
||||
value: `notices`,
|
||||
label: `平台公告`,
|
||||
},
|
||||
],
|
||||
H = 0;
|
||||
async function U() {
|
||||
let e = ++H;
|
||||
((z.value = ``), (R.value = null), (B.value = !0));
|
||||
try {
|
||||
if (C.query.section !== void 0)
|
||||
R.value = content_route_r(C.query.section);
|
||||
else if (C.query.plugin !== void 0) {
|
||||
let t = await L.get(`/plugin`);
|
||||
if (e !== H) return;
|
||||
R.value = content_route_n(C.query.plugin, t.list ?? []);
|
||||
} else R.value = `help`;
|
||||
R.value || (z.value = `资源入口无效或插件未启用,请重新选择分类`);
|
||||
} catch (t) {
|
||||
e === H &&
|
||||
(z.value = t instanceof Error ? t.message : `资源分类加载失败`);
|
||||
} finally {
|
||||
e === H && (B.value = !1);
|
||||
}
|
||||
}
|
||||
function W(e) {
|
||||
((R.value = e),
|
||||
I.push({
|
||||
path: `/resources`,
|
||||
query: {
|
||||
section: e,
|
||||
},
|
||||
}));
|
||||
}
|
||||
(onMounted(U),
|
||||
watch(() => [C.query.section, C.query.plugin], U),
|
||||
onBeforeUnmount(() => {
|
||||
H++;
|
||||
}));
|
||||
function G(e, t) {
|
||||
let n = t;
|
||||
if (e.key === `ArrowRight`) n = (t + 1) % V.length;
|
||||
else if (e.key === `ArrowLeft`) n = (t + V.length - 1) % V.length;
|
||||
else if (e.key === `Home`) n = 0;
|
||||
else if (e.key === `End`) n = V.length - 1;
|
||||
else return;
|
||||
(e.preventDefault(),
|
||||
W(V[n].value),
|
||||
document.getElementById(`resource-tab-${V[n].value}`)?.focus());
|
||||
}
|
||||
return (n, i) => {
|
||||
let a = button,
|
||||
s = skeleton,
|
||||
h = message;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createElementVNode(`div`, M, [
|
||||
(i[1] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `page-heading`,
|
||||
},
|
||||
[
|
||||
createElementVNode(`h2`, null, `资源中心`),
|
||||
createElementVNode(`p`, null, `查找帮助文档与站点资讯`),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
unref(R) === `help`
|
||||
? (openBlock(),
|
||||
createBlock(a, {
|
||||
key: 0,
|
||||
label: `创建工单`,
|
||||
icon: `pi pi-plus`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: (i[0] ||= (e) =>
|
||||
(`navigateTo` in n ? n.navigateTo : unref(navigateTo))(
|
||||
`/tickets/create`,
|
||||
)),
|
||||
}))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
createElementVNode(`div`, N, [
|
||||
(openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(V, (t, n) =>
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
id: `resource-tab-${t.value}`,
|
||||
key: t.value,
|
||||
type: `button`,
|
||||
role: `tab`,
|
||||
class: normalizeClass([
|
||||
`resource-tab`,
|
||||
{
|
||||
active: unref(R) === t.value,
|
||||
},
|
||||
]),
|
||||
"aria-selected": unref(R) === t.value,
|
||||
"aria-controls": `resource-panel-${t.value}`,
|
||||
tabindex: unref(R) === t.value ? 0 : -1,
|
||||
onClick: (e) => W(t.value),
|
||||
onKeydown: (e) => G(e, n),
|
||||
},
|
||||
toDisplayString(t.label),
|
||||
43,
|
||||
P,
|
||||
),
|
||||
),
|
||||
64,
|
||||
)),
|
||||
]),
|
||||
unref(B)
|
||||
? (openBlock(),
|
||||
createBlock(s, {
|
||||
key: 0,
|
||||
height: `120px`,
|
||||
}))
|
||||
: unref(z)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
h,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(z)), 1),
|
||||
createVNode(a, {
|
||||
label: `重试`,
|
||||
text: ``,
|
||||
onClick: U,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(R)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: 2,
|
||||
id: `resource-panel-${unref(R)}`,
|
||||
role: `tabpanel`,
|
||||
"aria-labelledby": `resource-tab-${unref(R)}`,
|
||||
class: `resource-content`,
|
||||
},
|
||||
[
|
||||
unref(R) === `help`
|
||||
? (openBlock(),
|
||||
createBlock(help, {
|
||||
key: 0,
|
||||
embedded: ``,
|
||||
}))
|
||||
: unref(R) === `news`
|
||||
? (openBlock(),
|
||||
createBlock(news, {
|
||||
key: 1,
|
||||
embedded: ``,
|
||||
}))
|
||||
: (openBlock(),
|
||||
createBlock(index, {
|
||||
key: 2,
|
||||
embedded: ``,
|
||||
})),
|
||||
],
|
||||
8,
|
||||
F,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-7390ef3e`]],
|
||||
);
|
||||
export {};
|
||||
export default I;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,413 @@
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
useId,
|
||||
} from "vue";
|
||||
import Button from "primevue/button";
|
||||
import Column from "primevue/column";
|
||||
import DataTable from "primevue/datatable";
|
||||
import Dialog from "primevue/dialog";
|
||||
import InputText from "primevue/inputtext";
|
||||
import Message from "primevue/message";
|
||||
import Paginator from "primevue/paginator";
|
||||
import Textarea from "primevue/textarea";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import { useApi } from "~/lib/auth.js";
|
||||
import { n as loadCompleteList } from "~/lib/complete-list.js";
|
||||
import "~/assets/styles/ssh-keys.WWTOf2zG.css";
|
||||
|
||||
const api = useApi();
|
||||
const fieldId = useId();
|
||||
const draftSearch = ref("");
|
||||
const appliedSearch = ref("");
|
||||
const rows = ref([]);
|
||||
const totalRows = ref(0);
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const listLoading = ref(true);
|
||||
const searchLoading = ref(false);
|
||||
const listError = ref("");
|
||||
const actionError = ref("");
|
||||
const editorVisible = ref(false);
|
||||
const saving = ref(false);
|
||||
const editingKey = ref(null);
|
||||
const keyForm = reactive({ name: "", public_key: "" });
|
||||
const copiedKeyId = ref(null);
|
||||
let copyResetTimer;
|
||||
let requestGeneration = 0;
|
||||
let disposed = false;
|
||||
|
||||
const firstRecord = computed(() => (currentPage.value - 1) * pageSize.value);
|
||||
const visibleRows = computed(() =>
|
||||
appliedSearch.value
|
||||
? rows.value.slice(firstRecord.value, firstRecord.value + pageSize.value)
|
||||
: rows.value,
|
||||
);
|
||||
|
||||
function isCurrentLoad(generation) {
|
||||
return !disposed && generation === requestGeneration;
|
||||
}
|
||||
|
||||
function clampPage() {
|
||||
const lastPage = Math.max(1, Math.ceil(totalRows.value / pageSize.value));
|
||||
const nextPage = Math.max(1, Math.min(currentPage.value, lastPage));
|
||||
if (nextPage === currentPage.value) return false;
|
||||
currentPage.value = nextPage;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function loadKeys() {
|
||||
if (disposed) return;
|
||||
if (appliedSearch.value) return loadSearchResults();
|
||||
const generation = ++requestGeneration;
|
||||
searchLoading.value = false;
|
||||
listLoading.value = true;
|
||||
listError.value = "";
|
||||
try {
|
||||
const result = await api.get("/ssh_key", {
|
||||
page: currentPage.value,
|
||||
limit: pageSize.value,
|
||||
});
|
||||
if (!isCurrentLoad(generation)) return;
|
||||
totalRows.value = result.count;
|
||||
if (clampPage()) {
|
||||
await loadKeys();
|
||||
return;
|
||||
}
|
||||
rows.value = result.list;
|
||||
} catch (error) {
|
||||
if (!isCurrentLoad(generation)) return;
|
||||
listError.value =
|
||||
error instanceof Error ? error.message : "加载密钥列表失败";
|
||||
rows.value = [];
|
||||
totalRows.value = 0;
|
||||
} finally {
|
||||
if (isCurrentLoad(generation)) listLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSearchResults() {
|
||||
const query = appliedSearch.value;
|
||||
const generation = ++requestGeneration;
|
||||
const isCurrent = () => isCurrentLoad(generation);
|
||||
listLoading.value = true;
|
||||
searchLoading.value = true;
|
||||
listError.value = "";
|
||||
try {
|
||||
// Search owns the complete result set; only visibleRows applies local pagination.
|
||||
const completeRows = await loadCompleteList(
|
||||
(page, limit) => api.get("/ssh_key", { page, limit }),
|
||||
isCurrent,
|
||||
);
|
||||
if (!isCurrent()) return;
|
||||
rows.value = completeRows.filter((row) =>
|
||||
(row.id + " " + row.name + " " + row.public_key)
|
||||
.toLowerCase()
|
||||
.includes(query),
|
||||
);
|
||||
totalRows.value = rows.value.length;
|
||||
clampPage();
|
||||
} catch (error) {
|
||||
if (!isCurrent()) return;
|
||||
listError.value = error instanceof Error ? error.message : "搜索密钥失败";
|
||||
rows.value = [];
|
||||
totalRows.value = 0;
|
||||
} finally {
|
||||
if (isCurrent()) {
|
||||
searchLoading.value = false;
|
||||
listLoading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function submitSearch() {
|
||||
appliedSearch.value = draftSearch.value.trim().toLowerCase();
|
||||
currentPage.value = 1;
|
||||
await loadKeys();
|
||||
}
|
||||
|
||||
async function clearSearch() {
|
||||
draftSearch.value = "";
|
||||
appliedSearch.value = "";
|
||||
currentPage.value = 1;
|
||||
await loadKeys();
|
||||
}
|
||||
|
||||
function changePage(event) {
|
||||
currentPage.value = event.rows === pageSize.value ? event.page + 1 : 1;
|
||||
pageSize.value = event.rows;
|
||||
if (appliedSearch.value) clampPage();
|
||||
else void loadKeys();
|
||||
}
|
||||
|
||||
function openCreateDialog() {
|
||||
editingKey.value = null;
|
||||
keyForm.name = "";
|
||||
keyForm.public_key = "";
|
||||
actionError.value = "";
|
||||
editorVisible.value = true;
|
||||
}
|
||||
|
||||
function openEditDialog(key) {
|
||||
editingKey.value = key;
|
||||
keyForm.name = key.name;
|
||||
keyForm.public_key = key.public_key;
|
||||
actionError.value = "";
|
||||
editorVisible.value = true;
|
||||
}
|
||||
|
||||
async function saveKey() {
|
||||
if (saving.value || disposed) return;
|
||||
actionError.value = "";
|
||||
if (!keyForm.name.trim()) {
|
||||
actionError.value = "请输入密钥名称";
|
||||
return;
|
||||
}
|
||||
if ([...keyForm.name.trim()].length > 10) {
|
||||
actionError.value = "密钥名称最多 10 个字符";
|
||||
return;
|
||||
}
|
||||
if (!keyForm.public_key.trim()) {
|
||||
actionError.value = "请输入公钥内容";
|
||||
return;
|
||||
}
|
||||
saving.value = true;
|
||||
try {
|
||||
if (editingKey.value) {
|
||||
await api.put("/ssh_key/" + editingKey.value.id, {
|
||||
id: editingKey.value.id,
|
||||
...keyForm,
|
||||
});
|
||||
} else {
|
||||
await api.post("/ssh_key", { ...keyForm });
|
||||
}
|
||||
if (disposed) return;
|
||||
editorVisible.value = false;
|
||||
await loadKeys();
|
||||
} catch (error) {
|
||||
if (!disposed)
|
||||
actionError.value = error instanceof Error ? error.message : "保存失败";
|
||||
} finally {
|
||||
if (!disposed) saving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteKey(key) {
|
||||
if (disposed) return;
|
||||
try {
|
||||
await api.del("/ssh_key/" + key.id);
|
||||
await loadKeys();
|
||||
} catch (error) {
|
||||
if (!disposed)
|
||||
actionError.value = error instanceof Error ? error.message : "删除失败";
|
||||
}
|
||||
}
|
||||
|
||||
async function copyPublicKey(key) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(key.public_key);
|
||||
if (disposed) return;
|
||||
clearTimeout(copyResetTimer);
|
||||
copiedKeyId.value = key.id;
|
||||
copyResetTimer = setTimeout(() => (copiedKeyId.value = null), 2000);
|
||||
} catch {
|
||||
// Clipboard access can be unavailable; the public key remains selectable.
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadKeys);
|
||||
onBeforeUnmount(() => {
|
||||
disposed = true;
|
||||
requestGeneration++;
|
||||
clearTimeout(copyResetTimer);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Keep the imported page styles scoped, including the teleported editor. -->
|
||||
<div class="list-page" data-v-31489433>
|
||||
<div class="list-head" data-v-31489433>
|
||||
<h2 data-v-31489433>SSH 密钥</h2>
|
||||
<div class="list-head-actions" data-v-31489433>
|
||||
<Button label="添加密钥" icon="pi pi-plus" @click="openCreateDialog" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Message v-if="listError" severity="error" :closable="false">
|
||||
{{ listError }}
|
||||
<Button label="重试" text @click="loadKeys" />
|
||||
</Message>
|
||||
<Message
|
||||
v-if="actionError && !editorVisible"
|
||||
severity="error"
|
||||
:closable="false"
|
||||
>
|
||||
{{ actionError }}
|
||||
</Message>
|
||||
|
||||
<div class="list-toolbar" data-v-31489433>
|
||||
<InputText
|
||||
v-model="draftSearch"
|
||||
class="list-search"
|
||||
placeholder="输入关键字"
|
||||
aria-label="搜索 SSH 密钥"
|
||||
data-v-31489433
|
||||
@keyup.enter="submitSearch"
|
||||
/>
|
||||
<Button
|
||||
label="搜索"
|
||||
icon="pi pi-search"
|
||||
severity="secondary"
|
||||
outlined
|
||||
:loading="searchLoading"
|
||||
@click="submitSearch"
|
||||
/>
|
||||
<Button
|
||||
label="清除筛选"
|
||||
icon="pi pi-filter-slash"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="clearSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="list-table" data-v-31489433>
|
||||
<DataTable
|
||||
:value="visibleRows"
|
||||
:loading="listLoading"
|
||||
lazy
|
||||
:rows="pageSize"
|
||||
:total-records="totalRows"
|
||||
:first="firstRecord"
|
||||
data-key="id"
|
||||
>
|
||||
<template #empty>
|
||||
<ListEmpty
|
||||
icon="pi pi-key"
|
||||
title="还没有 SSH 密钥"
|
||||
description="添加公钥后可在开通云服务器时选用"
|
||||
/>
|
||||
</template>
|
||||
<Column field="id" header="ID" style="width: 120px">
|
||||
<template #body="{ data }">#{{ data.id }}</template>
|
||||
</Column>
|
||||
<Column header="名称" style="width: 180px; min-width: 140px">
|
||||
<template #body="{ data }">{{ data.name }}</template>
|
||||
</Column>
|
||||
<Column header="公钥">
|
||||
<template #body="{ data }">
|
||||
<span class="key-text" data-v-31489433>{{ data.public_key }}</span>
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="指纹" style="width: 220px">
|
||||
<template #body="{ data }">
|
||||
<span class="fingerprint" data-v-31489433>{{
|
||||
data.finger_print || "--"
|
||||
}}</span>
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="操作" style="width: 200px">
|
||||
<template #body="{ data }">
|
||||
<div class="row-actions" data-v-31489433>
|
||||
<Button
|
||||
:label="copiedKeyId === data.id ? '已复制' : '复制'"
|
||||
size="small"
|
||||
severity="secondary"
|
||||
outlined
|
||||
@click="copyPublicKey(data)"
|
||||
/>
|
||||
<Button
|
||||
label="编辑"
|
||||
size="small"
|
||||
severity="secondary"
|
||||
text
|
||||
@click="openEditDialog(data)"
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-trash"
|
||||
aria-label="删除密钥"
|
||||
size="small"
|
||||
severity="danger"
|
||||
text
|
||||
@click="deleteKey(data)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
<div v-if="totalRows > 0" class="list-foot" data-v-31489433>
|
||||
<div class="list-bulk" data-v-31489433 />
|
||||
<Paginator
|
||||
:rows="pageSize"
|
||||
:total-records="totalRows"
|
||||
:first="firstRecord"
|
||||
:rows-per-page-options="[10, 20, 50]"
|
||||
@page="changePage"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
v-model:visible="editorVisible"
|
||||
:header="editingKey ? '编辑密钥' : '添加密钥'"
|
||||
modal
|
||||
:draggable="false"
|
||||
style="width: 448px"
|
||||
>
|
||||
<div class="form" data-v-31489433>
|
||||
<div class="field" data-v-31489433>
|
||||
<label :for="fieldId + '-name'" data-v-31489433>
|
||||
名称 <span class="req" data-v-31489433>*</span>
|
||||
</label>
|
||||
<InputText
|
||||
:id="fieldId + '-name'"
|
||||
v-model="keyForm.name"
|
||||
:aria-describedby="fieldId + '-name-hint'"
|
||||
aria-required="true"
|
||||
placeholder="便于识别的名称"
|
||||
maxlength="10"
|
||||
fluid
|
||||
/>
|
||||
<span :id="fieldId + '-name-hint'" class="hint" data-v-31489433>
|
||||
最多 10 个字符
|
||||
</span>
|
||||
</div>
|
||||
<div class="field" data-v-31489433>
|
||||
<label :for="fieldId + '-public-key'" data-v-31489433>
|
||||
公钥内容 <span class="req" data-v-31489433>*</span>
|
||||
</label>
|
||||
<Textarea
|
||||
:id="fieldId + '-public-key'"
|
||||
v-model="keyForm.public_key"
|
||||
:aria-describedby="fieldId + '-key-hint'"
|
||||
aria-required="true"
|
||||
rows="8"
|
||||
placeholder="输入公钥"
|
||||
auto-resize
|
||||
fluid
|
||||
/>
|
||||
<span :id="fieldId + '-key-hint'" class="hint" data-v-31489433>
|
||||
粘贴 ~/.ssh/id_rsa.pub 等公钥文件内容
|
||||
</span>
|
||||
</div>
|
||||
<Message v-if="actionError" severity="error" :closable="false">
|
||||
{{ actionError }}
|
||||
</Message>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button
|
||||
label="取消"
|
||||
severity="secondary"
|
||||
text
|
||||
@click="editorVisible = false"
|
||||
/>
|
||||
<Button label="保存" :loading="saving" @click="saveKey" />
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,778 @@
|
||||
<script>
|
||||
import "~/assets/styles/TicketAttachments.DtbJGLkE.css";
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/_id_.C-0--Lx-.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { renderList } 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 { 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 { 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 { r as dict_r } from "~/lib/dict.js";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import RichTextEditor from "~/components/RichTextEditor.vue";
|
||||
import { n as ticketAttachments_n } from "~/lib/ticketAttachments.js";
|
||||
import TicketAttachments from "~/components/TicketAttachments.vue";
|
||||
import TicketNotice from "~/components/TicketNotice.vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var le = {
|
||||
class: `page`,
|
||||
},
|
||||
ue = {
|
||||
class: `page-head`,
|
||||
},
|
||||
de = {
|
||||
key: 0,
|
||||
class: `panel`,
|
||||
},
|
||||
fe = {
|
||||
class: `panel head-panel`,
|
||||
},
|
||||
pe = {
|
||||
class: `ticket-head`,
|
||||
},
|
||||
me = {
|
||||
class: `ticket-title`,
|
||||
},
|
||||
he = {
|
||||
class: `ticket-num`,
|
||||
},
|
||||
ge = {
|
||||
class: `ticket-meta`,
|
||||
},
|
||||
w = {
|
||||
class: `panel thread-panel`,
|
||||
},
|
||||
T = {
|
||||
class: `thread`,
|
||||
},
|
||||
E = {
|
||||
class: `message-head`,
|
||||
},
|
||||
D = {
|
||||
class: `sender`,
|
||||
},
|
||||
O = {
|
||||
key: 0,
|
||||
class: `badge`,
|
||||
},
|
||||
k = {
|
||||
class: `time`,
|
||||
},
|
||||
A = [`innerHTML`],
|
||||
j = {
|
||||
key: 0,
|
||||
class: `message-quote`,
|
||||
},
|
||||
M = [`innerHTML`],
|
||||
N = {
|
||||
class: `reply-box`,
|
||||
},
|
||||
P = {
|
||||
key: 0,
|
||||
class: `reply-quote`,
|
||||
role: `status`,
|
||||
},
|
||||
F = [`innerHTML`],
|
||||
I = {
|
||||
class: `reply-attachments`,
|
||||
},
|
||||
L = {
|
||||
class: `reply-upload`,
|
||||
for: `reply-files`,
|
||||
},
|
||||
_e = [`disabled`],
|
||||
R = {
|
||||
key: 0,
|
||||
class: `muted`,
|
||||
},
|
||||
ve = {
|
||||
key: 1,
|
||||
class: `reply-file-list`,
|
||||
},
|
||||
ye = {
|
||||
class: `reply-actions`,
|
||||
},
|
||||
be = {
|
||||
class: `buttons`,
|
||||
},
|
||||
z = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `[id]`,
|
||||
setup(m) {
|
||||
let y = useRoute(),
|
||||
z = useApi(),
|
||||
B = String(y.params.id ?? y.query.id ?? ``);
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let V = ref(null),
|
||||
H = ref(!0),
|
||||
U = ref(``),
|
||||
W = ref(``),
|
||||
G = ref(!1),
|
||||
K = ref(!1),
|
||||
q = ref([]),
|
||||
J = ref(!1),
|
||||
Y = ref(0);
|
||||
async function X() {
|
||||
try {
|
||||
let e = await z.get(`/ticket/${B}`);
|
||||
if (!e.ticket || !e.ticket.id) {
|
||||
U.value = `工单不存在或已删除`;
|
||||
return;
|
||||
}
|
||||
V.value = e.ticket;
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `加载失败`;
|
||||
} finally {
|
||||
H.value = !1;
|
||||
}
|
||||
}
|
||||
let Z = computed(() => {
|
||||
let e = V.value;
|
||||
return e
|
||||
? [
|
||||
{
|
||||
id: 0,
|
||||
content: e.content,
|
||||
attachment: e.attachment || [],
|
||||
create_time: e.create_time,
|
||||
type: `Client`,
|
||||
client_name: e.username,
|
||||
admin_name: ``,
|
||||
client_id: e.client_id,
|
||||
quote_reply_id: 0,
|
||||
quote_info: null,
|
||||
},
|
||||
...(e.replies || []).filter((e) => e.id !== 0),
|
||||
]
|
||||
.sort((e, t) => e.create_time - t.create_time)
|
||||
.map((e) => ({
|
||||
...e,
|
||||
files: ticketAttachments_n(e.attachment),
|
||||
}))
|
||||
: [];
|
||||
});
|
||||
function Q(e) {
|
||||
return e.type === `Admin`
|
||||
? e.admin_name || `客服`
|
||||
: e.client_name || `我`;
|
||||
}
|
||||
let $ = computed(() => Z.value.find((e) => e.id === Y.value));
|
||||
async function xe(e) {
|
||||
if (J.value || G.value || V.value?.status === `已关闭`) return;
|
||||
let t = e.target,
|
||||
n = Array.from(t.files ?? []);
|
||||
if (n.length) {
|
||||
((J.value = !0), (U.value = ``));
|
||||
try {
|
||||
for (let e of n) {
|
||||
let t = await z.upload(e);
|
||||
if (!t?.save_name)
|
||||
throw Error(`附件「${e.name}」上传失败,请重新选择文件`);
|
||||
q.value.push({
|
||||
save_name: t.save_name,
|
||||
name: e.name,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `附件上传失败`;
|
||||
} finally {
|
||||
((J.value = !1), (t.value = ``));
|
||||
}
|
||||
}
|
||||
}
|
||||
function Se(e) {
|
||||
G.value || q.value.splice(e, 1);
|
||||
}
|
||||
function Ce(e) {
|
||||
e.id > 0 && V.value?.status !== `已关闭` && (Y.value = e.id);
|
||||
}
|
||||
function we(e) {
|
||||
return Number(e.quote_info?.is_deleted) === 1
|
||||
? `该回复已删除`
|
||||
: e.quote_info?.content ||
|
||||
Z.value.find((t) => t.id === e.quote_reply_id)?.content ||
|
||||
`原回复 #${e.quote_reply_id}(内容暂不可用)`;
|
||||
}
|
||||
function Te(e) {
|
||||
let t = e.quote_info,
|
||||
n = Z.value.find((t) => t.id === e.quote_reply_id);
|
||||
return (
|
||||
t?.sender_name ||
|
||||
t?.admin_name ||
|
||||
t?.client_name ||
|
||||
(n ? Q(n) : `回复 #${e.quote_reply_id}`)
|
||||
);
|
||||
}
|
||||
function Ee(e) {
|
||||
return Number(e.quote_info?.is_deleted) === 1
|
||||
? []
|
||||
: ticketAttachments_n(
|
||||
e.quote_info?.attachment ||
|
||||
Z.value.find((t) => t.id === e.quote_reply_id)?.attachment ||
|
||||
[],
|
||||
);
|
||||
}
|
||||
async function De() {
|
||||
if (!(
|
||||
G.value ||
|
||||
!W.value.trim() ||
|
||||
J.value ||
|
||||
V.value?.status === `已关闭`
|
||||
)) {
|
||||
G.value = !0;
|
||||
try {
|
||||
(await z.post(`/ticket/${B}/reply`, {
|
||||
content: W.value.trim(),
|
||||
attachment: q.value.map((e) => e.save_name),
|
||||
quote_reply_id: Y.value,
|
||||
}),
|
||||
(W.value = ``),
|
||||
(q.value = []),
|
||||
(Y.value = 0),
|
||||
await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `回复失败`;
|
||||
} finally {
|
||||
G.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function Oe() {
|
||||
K.value = !0;
|
||||
try {
|
||||
(await z.put(`/ticket/${B}/urge`), await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `催单失败`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
async function ke() {
|
||||
K.value = !0;
|
||||
try {
|
||||
(await z.put(`/ticket/${B}/close`), await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `关闭失败`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(X),
|
||||
(n, a) => {
|
||||
let c = TicketNotice,
|
||||
m = NuxtLink,
|
||||
_ = skeleton,
|
||||
v = message,
|
||||
y = button,
|
||||
S = TicketAttachments,
|
||||
C = RichTextEditor;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, le, [
|
||||
createVNode(c),
|
||||
createElementVNode(`div`, ue, [
|
||||
createVNode(
|
||||
m,
|
||||
{
|
||||
to: `/tickets`,
|
||||
class: `back`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-arrow-left`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(` 返回工单列表 `, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
unref(H)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, de, [
|
||||
createVNode(_, {
|
||||
height: `220px`,
|
||||
}),
|
||||
]))
|
||||
: unref(U) && !unref(V)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(U)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(V)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 2,
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, fe, [
|
||||
createElementVNode(`div`, pe, [
|
||||
createElementVNode(`div`, me, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
he,
|
||||
`#` + toDisplayString(unref(V).ticket_num),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`h2`,
|
||||
null,
|
||||
toDisplayString(unref(V).title),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
unref(V).status === `已关闭`
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
label: `关闭工单`,
|
||||
severity: `danger`,
|
||||
outlined: ``,
|
||||
size: `small`,
|
||||
loading: unref(K),
|
||||
onClick: ke,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `status-tag`,
|
||||
style: normalizeStyle({
|
||||
color: `var(--p-text-color)`,
|
||||
borderColor: unref(V).color,
|
||||
}),
|
||||
},
|
||||
toDisplayString(unref(V).status),
|
||||
5,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, ge, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`提交时间:` +
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(unref(V).create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, w, [
|
||||
createElementVNode(`div`, T, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(Z),
|
||||
(t, a) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: `${t.id}-${a}`,
|
||||
class: normalizeClass([
|
||||
`message`,
|
||||
{
|
||||
admin: t.type === `Admin`,
|
||||
},
|
||||
]),
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, E, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: normalizeClass([
|
||||
`sender-avatar`,
|
||||
{
|
||||
staff: t.type === `Admin`,
|
||||
},
|
||||
]),
|
||||
},
|
||||
toDisplayString(Q(t).slice(0, 1)),
|
||||
3,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
D,
|
||||
toDisplayString(Q(t)),
|
||||
1,
|
||||
),
|
||||
t.type === `Admin`
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
O,
|
||||
`客服`,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
k,
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(
|
||||
t.create_time,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `message-body`,
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(t.content),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
A,
|
||||
),
|
||||
t.quote_reply_id
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`引用 ` +
|
||||
toDisplayString(Te(t)) +
|
||||
`:`,
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
innerHTML:
|
||||
(`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
we(t),
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
M,
|
||||
),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
files: Ee(t),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`files`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
files: t.files,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`files`],
|
||||
),
|
||||
t.id > 0 &&
|
||||
unref(V).status !== `已关闭`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 1,
|
||||
label: `引用`,
|
||||
icon: `pi pi-reply`,
|
||||
text: ``,
|
||||
size: `small`,
|
||||
class: `quote-button`,
|
||||
onClick: (e) => Ce(t),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`onClick`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
],
|
||||
2,
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]),
|
||||
createElementVNode(`div`, N, [
|
||||
unref($)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, P, [
|
||||
createElementVNode(`div`, null, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`引用 ` +
|
||||
toDisplayString(Q(unref($))) +
|
||||
`:`,
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
unref($).content,
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
F,
|
||||
),
|
||||
]),
|
||||
createVNode(y, {
|
||||
icon: `pi pi-times`,
|
||||
text: ``,
|
||||
rounded: ``,
|
||||
size: `small`,
|
||||
"aria-label": `取消引用`,
|
||||
onClick: (a[0] ||= (e) =>
|
||||
(Y.value = 0)),
|
||||
}),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
modelValue: unref(W),
|
||||
"onUpdate:modelValue": (a[1] ||= (e) =>
|
||||
isRef(W) ? (W.value = e) : null),
|
||||
label: `回复内容`,
|
||||
"min-height": 140,
|
||||
placeholder: `输入回复内容…`,
|
||||
disabled: unref(V).status === `已关闭`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
createElementVNode(`div`, I, [
|
||||
createElementVNode(`label`, L, [
|
||||
(a[3] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-paperclip`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(a[4] ||= createTextVNode(`添加附件`, -1)),
|
||||
createElementVNode(
|
||||
`input`,
|
||||
{
|
||||
id: `reply-files`,
|
||||
type: `file`,
|
||||
multiple: ``,
|
||||
disabled:
|
||||
unref(G) ||
|
||||
unref(J) ||
|
||||
unref(V).status === `已关闭`,
|
||||
onChange: xe,
|
||||
},
|
||||
null,
|
||||
40,
|
||||
_e,
|
||||
),
|
||||
]),
|
||||
unref(J)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
R,
|
||||
`正在上传…`,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(q).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`ul`, ve, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(q),
|
||||
(t, n) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`li`,
|
||||
{
|
||||
key: t.save_name,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
icon: `pi pi-times`,
|
||||
text: ``,
|
||||
rounded: ``,
|
||||
size: `small`,
|
||||
"aria-label": `移除附件 ${t.name}`,
|
||||
disabled: unref(G),
|
||||
onClick: (e) => Se(n),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`aria-label`,
|
||||
`disabled`,
|
||||
`onClick`,
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
createElementVNode(`div`, ye, [
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
class: `inline-error`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(U)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, be, [
|
||||
unref(V).status === `已关闭`
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
label: `催单`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
size: `small`,
|
||||
loading: unref(K),
|
||||
onClick: Oe,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
label: `提交回复`,
|
||||
loading: unref(G),
|
||||
disabled:
|
||||
unref(V).status === `已关闭` ||
|
||||
!unref(W).trim() ||
|
||||
unref(J),
|
||||
onClick: De,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-3743a20f`]],
|
||||
);
|
||||
export {};
|
||||
export default z;
|
||||
</script>
|
||||
@@ -0,0 +1,675 @@
|
||||
<script>
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/create.gX6gpD00.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 { 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 { withModifiers } from "vue";
|
||||
import { useRouter } from "#app";
|
||||
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 radiobutton from "primevue/radiobutton";
|
||||
import inputtext from "primevue/inputtext";
|
||||
import { n as product_name_n } from "~/lib/product-name.js";
|
||||
import select from "primevue/select";
|
||||
import RichTextEditor from "~/components/RichTextEditor.vue";
|
||||
import TicketNotice from "~/components/TicketNotice.vue";
|
||||
import chip from "primevue/chip";
|
||||
import multiselect from "primevue/multiselect";
|
||||
var le = {
|
||||
class: `ticket-create`,
|
||||
},
|
||||
ue = {
|
||||
class: `ticket-section`,
|
||||
},
|
||||
de = {
|
||||
class: `section-fields`,
|
||||
},
|
||||
fe = {
|
||||
key: 0,
|
||||
role: `status`,
|
||||
},
|
||||
C = {
|
||||
class: `type-options`,
|
||||
},
|
||||
w = {
|
||||
class: `field`,
|
||||
},
|
||||
T = {
|
||||
key: 2,
|
||||
class: `field`,
|
||||
},
|
||||
E = {
|
||||
class: `field`,
|
||||
},
|
||||
D = {
|
||||
class: `host-opt`,
|
||||
},
|
||||
O = {
|
||||
class: `host-opt-meta`,
|
||||
},
|
||||
k = {
|
||||
class: `ticket-section`,
|
||||
},
|
||||
A = {
|
||||
class: `section-fields`,
|
||||
},
|
||||
j = {
|
||||
class: `field`,
|
||||
},
|
||||
M = {
|
||||
class: `field`,
|
||||
},
|
||||
N = {
|
||||
class: `upload-drop`,
|
||||
for: `files`,
|
||||
},
|
||||
P = [`disabled`],
|
||||
F = {
|
||||
key: 0,
|
||||
class: `files`,
|
||||
},
|
||||
I = {
|
||||
class: `fname`,
|
||||
},
|
||||
L = [`aria-label`, `disabled`, `onClick`],
|
||||
R = {
|
||||
class: `actions`,
|
||||
},
|
||||
z = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `create`,
|
||||
setup(m) {
|
||||
let b = useApi(),
|
||||
z = useRouter(),
|
||||
B = ref([]),
|
||||
V = ref([]),
|
||||
H = ref([]),
|
||||
U = reactive({
|
||||
title: ``,
|
||||
ticket_type_id: null,
|
||||
admin_role_id: null,
|
||||
host_ids: [],
|
||||
content: ``,
|
||||
}),
|
||||
W = ref(!1),
|
||||
G = ref(``),
|
||||
K = ref(!1),
|
||||
q = ref(!1);
|
||||
function J(e) {
|
||||
return e.dedicate_ip || e.assign_ip || ``;
|
||||
}
|
||||
function pe(e) {
|
||||
return [`#${e.id}`, e.name, J(e)].filter(Boolean).join(` / `);
|
||||
}
|
||||
let Y = computed(() => new Map(H.value.map((e) => [e.id, e])));
|
||||
function me(e) {
|
||||
let t = Y.value.get(e);
|
||||
return t
|
||||
? `${product_name_n(t.product_name) || t.name} (#${t.id})`
|
||||
: `#${e}`;
|
||||
}
|
||||
let X = ref([]),
|
||||
Z = ref(!1);
|
||||
async function he(e) {
|
||||
if (Z.value || W.value) return;
|
||||
let t = e.target,
|
||||
n = Array.from(t.files ?? []);
|
||||
if (n.length) {
|
||||
((Z.value = !0), (G.value = ``));
|
||||
try {
|
||||
for (let e of n) {
|
||||
let t = await b.upload(e);
|
||||
if (!t?.save_name)
|
||||
throw Error(`附件「${e.name}」上传失败,请重新选择文件`);
|
||||
X.value.push({
|
||||
save_name: t.save_name,
|
||||
name: e.name,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
G.value = e instanceof Error ? e.message : `上传失败`;
|
||||
} finally {
|
||||
((Z.value = !1), (t.value = ``));
|
||||
}
|
||||
}
|
||||
}
|
||||
function ge(e) {
|
||||
W.value || X.value.splice(e, 1);
|
||||
}
|
||||
async function Q() {
|
||||
if (!K.value) {
|
||||
((K.value = !0), (q.value = !1), (G.value = ``));
|
||||
try {
|
||||
let [e, t] = await Promise.all([
|
||||
b.get(`/ticket/type`),
|
||||
b.get(`/ticket/department`),
|
||||
]);
|
||||
((B.value = e.list ?? []), (V.value = t.list ?? []));
|
||||
try {
|
||||
let e = [],
|
||||
t = 1,
|
||||
n = 0;
|
||||
do {
|
||||
let r = await b.get(`/host`, {
|
||||
page: t,
|
||||
limit: 200,
|
||||
});
|
||||
(e.push(...(r.list ?? [])),
|
||||
(n = Number(r.count ?? e.length)),
|
||||
(t += 1));
|
||||
} while (e.length < n && t <= 100);
|
||||
H.value = e;
|
||||
} catch {
|
||||
H.value = [];
|
||||
}
|
||||
((U.ticket_type_id = B.value[0]?.id ?? null),
|
||||
(U.admin_role_id = V.value[0]?.id ?? null),
|
||||
(q.value = !0));
|
||||
} catch (e) {
|
||||
G.value =
|
||||
e instanceof Error ? e.message : `加载工单选项失败,请重试`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function $() {
|
||||
if (!(W.value || Z.value || K.value || !q.value)) {
|
||||
if (((G.value = ``), !U.title.trim())) {
|
||||
G.value = `请输入工单标题`;
|
||||
return;
|
||||
}
|
||||
if (!U.content.trim()) {
|
||||
G.value = `请输入工单内容`;
|
||||
return;
|
||||
}
|
||||
W.value = !0;
|
||||
try {
|
||||
let e = await b.post(`/ticket`, {
|
||||
title: U.title.trim(),
|
||||
content: U.content.trim(),
|
||||
ticket_type_id: U.ticket_type_id,
|
||||
admin_role_id: U.admin_role_id,
|
||||
host_ids: U.host_ids,
|
||||
attachment: X.value.map((e) => e.save_name),
|
||||
});
|
||||
z.push(`/tickets/${e.id}`);
|
||||
} catch (e) {
|
||||
G.value = e instanceof Error ? e.message : `提交失败`;
|
||||
} finally {
|
||||
W.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(Q),
|
||||
(n, i) => {
|
||||
let s = TicketNotice,
|
||||
c = button,
|
||||
m = radiobutton,
|
||||
_ = inputtext,
|
||||
y = select,
|
||||
b = chip,
|
||||
z = multiselect,
|
||||
J = RichTextEditor,
|
||||
Y = message,
|
||||
_e = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, le, [
|
||||
createVNode(s),
|
||||
(i[18] ||= createElementVNode(`h2`, null, `创建工单`, -1)),
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
onSubmit: withModifiers($, [`prevent`]),
|
||||
},
|
||||
[
|
||||
createElementVNode(`section`, ue, [
|
||||
(i[9] ||= createElementVNode(
|
||||
`aside`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`h3`, null, `基本信息`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`请提供一些基本信息,这有助于我们快速定位您的问题并将其转交给正确的团队处理。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, de, [
|
||||
unref(K)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, fe, `正在加载工单选项…`))
|
||||
: unref(q)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(c, {
|
||||
key: 1,
|
||||
label: `重新加载工单选项`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: Q,
|
||||
})),
|
||||
createElementVNode(`fieldset`, C, [
|
||||
(i[5] ||= createElementVNode(
|
||||
`legend`,
|
||||
null,
|
||||
`工单类型`,
|
||||
-1,
|
||||
)),
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(B),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`label`,
|
||||
{
|
||||
key: t.id,
|
||||
},
|
||||
[
|
||||
createVNode(
|
||||
m,
|
||||
{
|
||||
modelValue: unref(U).ticket_type_id,
|
||||
"onUpdate:modelValue": (i[0] ||= (e) =>
|
||||
(unref(U).ticket_type_id = e)),
|
||||
"input-id": `ticket-type-${t.id}`,
|
||||
value: t.id,
|
||||
disabled: !unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`modelValue`,
|
||||
`input-id`,
|
||||
`value`,
|
||||
`disabled`,
|
||||
],
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]),
|
||||
createElementVNode(`div`, w, [
|
||||
(i[6] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `title`,
|
||||
},
|
||||
`工单标题`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
id: `title`,
|
||||
modelValue: unref(U).title,
|
||||
"onUpdate:modelValue": (i[1] ||= (e) =>
|
||||
(unref(U).title = e)),
|
||||
placeholder: `输入工单标题`,
|
||||
maxlength: `100`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
unref(V).length > 1
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, T, [
|
||||
(i[7] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `department`,
|
||||
},
|
||||
`服务部门`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
"input-id": `department`,
|
||||
modelValue: unref(U).admin_role_id,
|
||||
"onUpdate:modelValue": (i[2] ||= (e) =>
|
||||
(unref(U).admin_role_id = e)),
|
||||
options: unref(V),
|
||||
optionLabel: `name`,
|
||||
optionValue: `id`,
|
||||
disabled: !unref(q),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`, `disabled`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, E, [
|
||||
(i[8] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `ticket-hosts`,
|
||||
},
|
||||
`关联产品`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
z,
|
||||
{
|
||||
"input-id": `ticket-hosts`,
|
||||
modelValue: unref(U).host_ids,
|
||||
"onUpdate:modelValue": (i[3] ||= (e) =>
|
||||
(unref(U).host_ids = e)),
|
||||
options: unref(H),
|
||||
optionLabel: `name`,
|
||||
optionValue: `id`,
|
||||
filter: ``,
|
||||
filterFields: [
|
||||
`product_name`,
|
||||
`name`,
|
||||
`dedicate_ip`,
|
||||
`assign_ip`,
|
||||
`id`,
|
||||
],
|
||||
filterPlaceholder: `输入关键字`,
|
||||
placeholder: `选择关联产品`,
|
||||
display: `chip`,
|
||||
fluid: ``,
|
||||
},
|
||||
{
|
||||
option: withCtx(({ option: t }) => [
|
||||
createElementVNode(`div`, D, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(product_name_n)(t.product_name) ||
|
||||
t.name,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
O,
|
||||
toDisplayString(pe(t)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
chip: withCtx(
|
||||
({ value: e, removeCallback: t }) => [
|
||||
createVNode(
|
||||
b,
|
||||
{
|
||||
label: me(e),
|
||||
removable: ``,
|
||||
onRemove: (n) => t(n, e),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`, `onRemove`],
|
||||
),
|
||||
],
|
||||
),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`modelValue`, `options`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`section`, k, [
|
||||
(i[17] ||= createElementVNode(
|
||||
`aside`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`h3`, null, `详细信息`),
|
||||
createElementVNode(`p`, null, [
|
||||
createTextVNode(
|
||||
`请尽可能详细地描述您的问题,包括您已经尝试过的解决方案。`,
|
||||
),
|
||||
createElementVNode(`br`),
|
||||
createTextVNode(
|
||||
`如果您有相关的文件或图片,请上传它们,这将有助于我们更快地诊断问题并为您提供解决方案。`,
|
||||
),
|
||||
]),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, A, [
|
||||
createElementVNode(`div`, j, [
|
||||
(i[10] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `content`,
|
||||
},
|
||||
`工单内容`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
J,
|
||||
{
|
||||
id: `content`,
|
||||
modelValue: unref(U).content,
|
||||
"onUpdate:modelValue": (i[4] ||= (e) =>
|
||||
(unref(U).content = e)),
|
||||
label: `工单内容`,
|
||||
placeholder: `请描述问题、复现步骤和报错信息`,
|
||||
disabled: unref(W),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, M, [
|
||||
(i[15] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `files`,
|
||||
},
|
||||
`附件`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`label`, N, [
|
||||
(i[11] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-upload`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(i[12] ||= createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`b`, null, `点击此处`),
|
||||
createTextVNode(`上传相关文件`),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`small`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(Z)
|
||||
? `正在上传,请稍候…`
|
||||
: `支持多选;上传完成后再提交工单`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`input`,
|
||||
{
|
||||
id: `files`,
|
||||
type: `file`,
|
||||
multiple: ``,
|
||||
disabled: unref(Z) || unref(W),
|
||||
onChange: he,
|
||||
},
|
||||
null,
|
||||
40,
|
||||
P,
|
||||
),
|
||||
]),
|
||||
unref(X).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`ul`, F, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(X),
|
||||
(t, n) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`li`,
|
||||
{
|
||||
key: t.save_name,
|
||||
},
|
||||
[
|
||||
(i[14] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-paperclip`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
I,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: `rm`,
|
||||
"aria-label": `移除附件 ${t.name}`,
|
||||
disabled: unref(W),
|
||||
onClick: (e) => ge(n),
|
||||
},
|
||||
[
|
||||
...(i[13] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-times`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
],
|
||||
8,
|
||||
L,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
unref(G)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
Y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(G)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, R, [
|
||||
createVNode(
|
||||
_e,
|
||||
{
|
||||
to: `/tickets`,
|
||||
class: `cancel-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(i[16] ||= [createTextVNode(`取消`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `创建工单`,
|
||||
loading: unref(W),
|
||||
disabled: unref(Z) || unref(K) || !unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
32,
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-710c7c49`]],
|
||||
);
|
||||
export {};
|
||||
export default z;
|
||||
</script>
|
||||
@@ -0,0 +1,623 @@
|
||||
<script>
|
||||
import "~/assets/styles/tickets.Dz8JrDhQ.css";
|
||||
import { toDisplayString } 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 { 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 { withKeys } from "vue";
|
||||
import { useRoute } from "#app";
|
||||
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 inputtext from "primevue/inputtext";
|
||||
import { r as dict_r } from "~/lib/dict.js";
|
||||
import datatable from "primevue/datatable";
|
||||
import paginator from "primevue/paginator";
|
||||
import select from "primevue/select";
|
||||
import column from "primevue/column";
|
||||
import ListEmpty from "~/components/ListEmpty.vue";
|
||||
import { t as useListPage_t } from "~/lib/useListPage.js";
|
||||
var ie = {
|
||||
class: `list-page`,
|
||||
},
|
||||
D = {
|
||||
class: `list-head`,
|
||||
},
|
||||
O = {
|
||||
class: `list-head-actions`,
|
||||
},
|
||||
ae = {
|
||||
class: `list-toolbar`,
|
||||
},
|
||||
oe = {
|
||||
class: `list-toolbar-right`,
|
||||
},
|
||||
k = {
|
||||
class: `list-table`,
|
||||
},
|
||||
A = {
|
||||
key: 3,
|
||||
class: `list-foot`,
|
||||
},
|
||||
j = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `index`,
|
||||
setup(f) {
|
||||
let v = useApi(),
|
||||
j = useRoute(),
|
||||
M = ref([]),
|
||||
N = ref([]),
|
||||
P = ref({}),
|
||||
F = ref(``),
|
||||
I = ref(!1),
|
||||
L = ref(``),
|
||||
R = ref(!1),
|
||||
z = ref(``),
|
||||
B = ref(``),
|
||||
V = Number(j.query.status),
|
||||
H = ref(V > 0 ? V : null),
|
||||
U = ref(null),
|
||||
{
|
||||
list: W,
|
||||
total: G,
|
||||
loading: K,
|
||||
error: q,
|
||||
page: J,
|
||||
limit: Y,
|
||||
onPage: se,
|
||||
reload: X,
|
||||
} = useListPage_t(`/ticket`, {
|
||||
limit: 10,
|
||||
params: () => ({
|
||||
keywords: B.value,
|
||||
status: H.value ? [H.value] : [],
|
||||
ticket_type_id: U.value ?? ``,
|
||||
}),
|
||||
});
|
||||
async function Z() {
|
||||
if (!I.value) {
|
||||
((I.value = !0), (F.value = ``));
|
||||
try {
|
||||
let [e, t] = await Promise.allSettled([
|
||||
v.get(`/ticket/status`),
|
||||
v.get(`/ticket/type`),
|
||||
]);
|
||||
(e.status === `fulfilled` && (M.value = e.value.list ?? []),
|
||||
t.status === `fulfilled` && (N.value = t.value.list ?? []));
|
||||
let n = [e, t].flatMap((e, t) =>
|
||||
e.status === `rejected`
|
||||
? [
|
||||
`${t === 0 ? `工单状态` : `工单类型`}加载失败:${e.reason instanceof Error ? e.reason.message : `请稍后重试`}`,
|
||||
]
|
||||
: [],
|
||||
);
|
||||
F.value = n.join(`;`);
|
||||
} finally {
|
||||
I.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function Q() {
|
||||
if (!R.value) {
|
||||
((R.value = !0), (L.value = ``));
|
||||
try {
|
||||
P.value = await v.get(`/ticket/statistic`);
|
||||
} catch (e) {
|
||||
L.value = e instanceof Error ? e.message : `工单统计加载失败`;
|
||||
} finally {
|
||||
R.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
computed(() =>
|
||||
M.value
|
||||
.filter((e) => P.value[e.id] !== void 0)
|
||||
.map((e) => ({
|
||||
...e,
|
||||
count: P.value[e.id] ?? 0,
|
||||
})),
|
||||
);
|
||||
let ce = computed(() => [
|
||||
{
|
||||
label: `全部状态`,
|
||||
value: null,
|
||||
},
|
||||
...M.value.map((e) => ({
|
||||
label: e.name,
|
||||
value: e.id,
|
||||
})),
|
||||
]),
|
||||
le = computed(() => [
|
||||
{
|
||||
label: `全部类型`,
|
||||
value: null,
|
||||
},
|
||||
...N.value.map((e) => ({
|
||||
label: e.name,
|
||||
value: e.id,
|
||||
})),
|
||||
]),
|
||||
$ = computed(() => !!B.value || !!H.value || !!U.value);
|
||||
function ue() {
|
||||
((B.value = z.value.trim()), X());
|
||||
}
|
||||
function de() {
|
||||
((z.value = ``),
|
||||
(B.value = ``),
|
||||
(H.value = null),
|
||||
(U.value = null),
|
||||
X());
|
||||
}
|
||||
return (
|
||||
onMounted(() => {
|
||||
(Z(), Q());
|
||||
}),
|
||||
(t, r) => {
|
||||
let o = message,
|
||||
f = button,
|
||||
g = NuxtLink,
|
||||
_ = inputtext,
|
||||
v = select,
|
||||
E = ListEmpty,
|
||||
j = column,
|
||||
M = datatable,
|
||||
N = paginator;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, ie, [
|
||||
createVNode(
|
||||
o,
|
||||
{
|
||||
severity: `info`,
|
||||
closable: !1,
|
||||
class: `support-notice`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(r[3] ||= [
|
||||
createElementVNode(
|
||||
`div`,
|
||||
null,
|
||||
[
|
||||
createTextVNode(
|
||||
`尊敬的客户您好:为了更好地为您服务,请详细描述您遇到的问题,并提供相关截图或报错信息。`,
|
||||
),
|
||||
createElementVNode(`br`),
|
||||
createTextVNode(
|
||||
`请勿在工单中发送账户密码等敏感信息。我们会尽快为您处理。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createElementVNode(`div`, D, [
|
||||
(r[4] ||= createElementVNode(`h2`, null, `工单`, -1)),
|
||||
createElementVNode(`div`, O, [
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
to: `/tickets/create`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(f, {
|
||||
label: `创建工单`,
|
||||
icon: `pi pi-plus`,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
]),
|
||||
unref(L)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
o,
|
||||
{
|
||||
key: 0,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
` 工单统计暂不可用:` +
|
||||
toDisplayString(unref(L)) +
|
||||
` `,
|
||||
1,
|
||||
),
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
label: `重试统计`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
loading: unref(R),
|
||||
onClick: Q,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(F)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
o,
|
||||
{
|
||||
key: 1,
|
||||
severity: `warn`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(F)) + ` `, 1),
|
||||
createVNode(
|
||||
f,
|
||||
{
|
||||
label: `重试筛选选项`,
|
||||
size: `small`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
loading: unref(I),
|
||||
onClick: Z,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, ae, [
|
||||
createElementVNode(`div`, oe, [
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
modelValue: unref(z),
|
||||
"onUpdate:modelValue": (r[0] ||= (e) =>
|
||||
isRef(z) ? (z.value = e) : null),
|
||||
class: `list-search`,
|
||||
placeholder: `输入关键字`,
|
||||
onKeyup: withKeys(ue, [`enter`]),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
modelValue: unref(U),
|
||||
"onUpdate:modelValue": (r[1] ||= (e) =>
|
||||
isRef(U) ? (U.value = e) : null),
|
||||
class: `list-select`,
|
||||
options: unref(le),
|
||||
optionLabel: `label`,
|
||||
optionValue: `value`,
|
||||
onChange: unref(X),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`, `onChange`],
|
||||
),
|
||||
createVNode(
|
||||
v,
|
||||
{
|
||||
modelValue: unref(H),
|
||||
"onUpdate:modelValue": (r[2] ||= (e) =>
|
||||
isRef(H) ? (H.value = e) : null),
|
||||
class: `list-select`,
|
||||
options: unref(ce),
|
||||
optionLabel: `label`,
|
||||
optionValue: `value`,
|
||||
onChange: unref(X),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`, `onChange`],
|
||||
),
|
||||
createVNode(f, {
|
||||
label: `清除筛选`,
|
||||
icon: `pi pi-filter-slash`,
|
||||
severity: `secondary`,
|
||||
text: ``,
|
||||
size: `small`,
|
||||
onClick: de,
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, k, [
|
||||
createVNode(
|
||||
M,
|
||||
{
|
||||
value: unref(W),
|
||||
loading: unref(K),
|
||||
lazy: ``,
|
||||
rows: unref(Y),
|
||||
totalRecords: unref(G),
|
||||
first: (unref(J) - 1) * unref(Y),
|
||||
dataKey: `id`,
|
||||
},
|
||||
{
|
||||
empty: withCtx(() => [
|
||||
createVNode(
|
||||
E,
|
||||
{
|
||||
icon: `pi pi-comments`,
|
||||
title: unref(K) ? `加载中…` : `还没有工单`,
|
||||
description: unref($)
|
||||
? `换个筛选条件试试`
|
||||
: `遇到问题可以提交工单联系我们`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
unref($)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
g,
|
||||
{
|
||||
key: 0,
|
||||
to: `/tickets/create`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createVNode(f, {
|
||||
label: `创建工单`,
|
||||
icon: `pi pi-plus`,
|
||||
size: `small`,
|
||||
}),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
)),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`title`, `description`],
|
||||
),
|
||||
]),
|
||||
default: withCtx(() => [
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `ID`,
|
||||
style: {
|
||||
width: `120px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
to: `/tickets/${t.id}`,
|
||||
class: `col-id`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
`#` + toDisplayString(t.ticket_num),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `标题`,
|
||||
style: {
|
||||
"min-width": `220px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createVNode(
|
||||
g,
|
||||
{
|
||||
to: `/tickets/${t.id}`,
|
||||
class: `title-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(t.title),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[`to`],
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `工单类型`,
|
||||
style: {
|
||||
width: `130px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(t.name || `—`),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `提交时间`,
|
||||
style: {
|
||||
"min-width": `160px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: n }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
(`formatTime` in t
|
||||
? t.formatTime
|
||||
: unref(dict_r))(n.post_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `最近回复`,
|
||||
style: {
|
||||
"min-width": `160px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: n }) => [
|
||||
createTextVNode(
|
||||
toDisplayString(
|
||||
n.last_reply_time
|
||||
? (`formatTime` in t
|
||||
? t.formatTime
|
||||
: unref(dict_r))(n.last_reply_time)
|
||||
: `—`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
j,
|
||||
{
|
||||
header: `状态`,
|
||||
style: {
|
||||
width: `110px`,
|
||||
},
|
||||
},
|
||||
{
|
||||
body: withCtx(({ data: t }) => [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `status-tag`,
|
||||
style: normalizeStyle({
|
||||
color: `var(--p-text-color)`,
|
||||
borderColor: t.color,
|
||||
}),
|
||||
},
|
||||
toDisplayString(t.status),
|
||||
5,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`value`, `loading`, `rows`, `totalRecords`, `first`],
|
||||
),
|
||||
]),
|
||||
unref(q)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
o,
|
||||
{
|
||||
key: 2,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(q)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(G) > 0
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, A, [
|
||||
(r[5] ||= createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `list-bulk`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
N,
|
||||
{
|
||||
rows: unref(Y),
|
||||
totalRecords: unref(G),
|
||||
first: (unref(J) - 1) * unref(Y),
|
||||
rowsPerPageOptions: [10, 20, 50],
|
||||
onPage: unref(se),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`rows`, `totalRecords`, `first`, `onPage`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-1ff3e04d`]],
|
||||
);
|
||||
export {};
|
||||
export default j;
|
||||
</script>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import "~/assets/styles/TicketAttachments.DtbJGLkE.css";
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/_id_.C-0--Lx-.css";
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import _id_ from "~/pages/tickets/[id].vue";
|
||||
var i = defineComponent({
|
||||
__name: `ticket`,
|
||||
setup(t) {
|
||||
return (t, i) => (openBlock(), createBlock(_id_));
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user