Files
console-dev/app/pages/security/domains/index.vue
T
2026-11-06 00:04:38 +08:00

1161 lines
42 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
import "~/assets/styles/domains.GiD6NSti.css";
definePageMeta({
alias: [`/security/domain-whitelist`],
});
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 { useRoute } from "#app";
import { NuxtLink } from "#components";
import { sanitizeMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import { n as product_name_n } from "~/lib/product-name.js";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import 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";
import textarea from "primevue/textarea";
import tag from "primevue/tag";
import { t as composables_t } from "~/lib/composables-2.js";
var ve = {
class: `list-page`,
},
ye = {
class: `list-head`,
},
be = {
class: `list-head-actions`,
},
xe = {
class: `list-toolbar`,
},
Se = {
class: `list-toolbar-right`,
},
Ce = {
class: `list-table`,
},
we = {
class: `col-mono`,
},
Te = {
class: `sub`,
},
Ee = {
key: 0,
},
De = {
key: 1,
},
Oe = {
key: 6,
class: `list-foot`,
},
ke = {
class: `form`,
},
Ae = {
class: `field`,
},
je = {
key: 0,
class: `req`,
},
Me = {
key: 3,
class: `tip`,
},
Ne = {
key: 1,
class: `tip`,
},
Pe = {
key: 2,
class: `tip`,
},
Fe = {
class: `confirm-text`,
},
b = _plugin_vue_export_helper_t(
defineComponent({
__name: `index`,
setup(h) {
composables_t({
alias: `/security/domain-whitelist`,
});
let y = useApi(),
b = useRoute(),
x = ref(Number(b.query.host_id) || null),
S = ref(null),
{
list: Ie,
total: C,
loading: w,
error: T,
page: E,
limit: D,
onPage: Le,
reload: O,
} = useListPage_t(`/domain_whitelist/record`, {
limit: 10,
params: () => ({
host_id: x.value ?? ``,
status: S.value ?? ``,
}),
}),
k = computed(() => x.value !== null || S.value !== null);
function Re() {
((x.value = null), (S.value = null), O());
}
let A = ref([]),
j = ref(!0),
M = ref(``),
N = ref(``),
P = ref(!1),
F = ref(!1),
I = !1,
L = 0,
R = 0;
onBeforeUnmount(() => {
((I = !0), L++, R++, Y++);
});
let ze = computed(() => [
{
label: `全部主机`,
value: null,
},
...A.value.map((e) => ({
label: `${e.name}(${product_name_n(e.product_name)})`,
value: e.id,
})),
]),
Be = [
{
label: `全部状态`,
value: null,
},
{
label: `待处理`,
value: 0,
},
{
label: `已通过`,
value: 1,
},
{
label: `已驳回`,
value: -1,
},
];
async function Ve() {
let e = ++L;
((P.value = !0), (M.value = ``));
try {
let t = await y.get(`/domain_whitelist/host`);
if (I || e !== L) return;
if (!Array.isArray(t?.list)) throw Error(`可用主机响应无效`);
A.value = t.list;
} catch (t) {
if (I || e !== L) return;
((A.value = []),
(M.value = t instanceof Error ? t.message : `可用主机加载失败`));
} finally {
!I && e === L && (P.value = !1);
}
}
async function He() {
let e = ++R;
((F.value = !0), (N.value = ``));
try {
let t = await y.get(`/certification/info`);
if (I || e !== R) return;
if (![!0, !1, 1, 0, `1`, `0`].includes(t?.is_certification))
throw Error(`实名状态响应无效`);
j.value =
t.is_certification === !0 || Number(t.is_certification) === 1;
} catch (t) {
if (I || e !== R) return;
N.value = t instanceof Error ? t.message : `实名状态加载失败`;
} finally {
!I && e === R && (F.value = !1);
}
}
function Ue(e) {
return e.status === 1
? `已通过`
: e.status === -1
? `已驳回`
: e.need_review
? `等待人工审核`
: `处理中`;
}
function We(e) {
return e.status === 1
? `success`
: e.status === -1
? `danger`
: e.need_review
? `warn`
: `info`;
}
let z = ref(``),
Ge = ref(`success`);
function B(e, t = `success`) {
((z.value = e), (Ge.value = t));
}
let V = ref(!1),
H = ref(null),
U = ref(null),
W = ref(!1),
G = ref({}),
K = ref(``),
q = ref(!1),
J = ref(null),
Y = 0;
function X(e) {
if (!q.value)
return (
(V.value = !0),
(K.value = ``),
(H.value = e ?? x.value ?? null),
Ke()
);
}
async function Ke() {
let e = ++Y,
t = H.value;
if (
((W.value = !!t),
(K.value = ``),
(U.value = null),
(J.value = null),
(G.value = {}),
t)
)
try {
let n = await y.get(`/domain_whitelist/form`, {
host_id: t,
});
if (e !== Y || t !== H.value) return;
((U.value = n), (J.value = t));
let r = {};
for (let e of n.fields ?? []) r[e.name] = ``;
G.value = r;
} catch (n) {
if (e !== Y || t !== H.value) return;
K.value =
n instanceof Error ? n.message : `该主机暂不支持域名过白`;
} finally {
e === Y && (W.value = !1);
}
}
async function qe() {
if (!(
q.value ||
W.value ||
P.value ||
F.value ||
M.value ||
N.value ||
!U.value ||
!H.value ||
J.value !== H.value ||
!j.value
)) {
K.value = ``;
for (let e of U.value.fields ?? [])
if (e.required && !String(G.value[e.name] ?? ``).trim()) {
K.value = `请填写${e.title}`;
return;
}
q.value = !0;
try {
let e = await y.post(`/domain_whitelist/record`, {
host_id: H.value,
...G.value,
});
((V.value = !1),
B(e.pending ? `已提交,等待人工审核` : `提交成功`),
O());
} catch (e) {
K.value = e instanceof Error ? e.message : `提交失败`;
} finally {
q.value = !1;
}
}
}
let Z = ref(!1),
Q = ref(null),
$ = ref(!1);
function Je(e) {
((Q.value = e), (Z.value = !0));
}
async function Ye() {
if (!Q.value || $.value || !Q.value.can_remove) return;
let e = Q.value;
$.value = !0;
try {
(await y.del(`/domain_whitelist/record/${e.id}`),
(Z.value = !1),
B(`已撤销`),
O());
} catch (e) {
((Z.value = !1),
B(e instanceof Error ? e.message : `撤销失败`, `error`));
} finally {
$.value = !1;
}
}
return (
onMounted(async () => {
(He(), await Ve(), x.value && X(x.value));
}),
(n, r) => {
let a = NuxtLink,
c = message,
h = button,
v = select,
ne = ListEmpty,
y = column,
me = tag,
_e = datatable,
b = paginator,
I = textarea,
L = inputtext,
R = dialog;
return (
openBlock(),
createElementBlock(`div`, ve, [
createVNode(
c,
{
severity: `info`,
closable: !1,
class: `domain-notice`,
},
{
default: withCtx(() => [
(r[16] ||= createElementVNode(
`strong`,
null,
`注意事项`,
-1,
)),
createElementVNode(`p`, null, [
(r[10] ||= createTextVNode(
`1. 在中国大陆机房提供 HTTP/HTTPS 服务前,请先完成域名备案并添加白名单。`,
-1,
)),
(r[11] ||= createElementVNode(`br`, null, null, -1)),
(r[12] ||= createTextVNode(
`2. 关联产品逾期或删除后,请及时核对域名白名单状态。`,
-1,
)),
(r[13] ||= createElementVNode(`br`, null, null, -1)),
(r[14] ||= createTextVNode(
`3. 如需了解域名备案,可前往`,
-1,
)),
createVNode(
a,
{
to: `/help`,
},
{
default: withCtx(() => [
...(r[9] ||= [createTextVNode(`帮助中心`, -1)]),
]),
_: 1,
},
),
(r[15] ||= createTextVNode(`。`, -1)),
]),
]),
_: 1,
},
),
createElementVNode(`div`, ye, [
(r[17] ||= createElementVNode(`h2`, null, `域名白名单`, -1)),
createElementVNode(`div`, be, [
createVNode(
h,
{
label: `添加域名白名单`,
icon: `pi pi-plus`,
disabled:
!unref(j) ||
unref(A).length === 0 ||
unref(P) ||
unref(F) ||
!!unref(M) ||
!!unref(N),
onClick: (r[0] ||= (e) => X()),
},
null,
8,
[`disabled`],
),
]),
]),
unref(M)
? (openBlock(),
createBlock(
c,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(M)) + ` `, 1),
createVNode(h, {
label: `重试可用主机`,
text: ``,
onClick: Ve,
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(N)
? (openBlock(),
createBlock(
c,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(N)) + ` `, 1),
createVNode(h, {
label: `重试实名状态`,
text: ``,
onClick: He,
}),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
!unref(N) && !unref(F) && !unref(j)
? (openBlock(),
createBlock(
c,
{
key: 2,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
(r[19] ||= createTextVNode(
` 提交域名过白前请先完成实名认证,前往`,
-1,
)),
createVNode(
a,
{
to: `/account/realname`,
class: `cert-link`,
},
{
default: withCtx(() => [
...(r[18] ||= [
createTextVNode(`实名认证`, -1),
]),
]),
_: 1,
},
),
(r[20] ||= createTextVNode(`。 `, -1)),
]),
_: 1,
},
))
: !unref(M) && !unref(P) && unref(A).length === 0
? (openBlock(),
createBlock(
c,
{
key: 3,
severity: `info`,
closable: !1,
},
{
default: withCtx(() => [
...(r[21] ||= [
createTextVNode(
` 暂无可提交过白的主机(仅支持已开通对应机房过白服务的产品)。 `,
-1,
),
]),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createElementVNode(`div`, xe, [
createElementVNode(`div`, Se, [
createVNode(
v,
{
modelValue: unref(x),
"onUpdate:modelValue": (r[1] ||= (e) =>
isRef(x) ? (x.value = e) : null),
class: `list-select`,
options: unref(ze),
optionLabel: `label`,
optionValue: `value`,
onChange: unref(O),
},
null,
8,
[`modelValue`, `options`, `onChange`],
),
createVNode(
v,
{
modelValue: unref(S),
"onUpdate:modelValue": (r[2] ||= (e) =>
isRef(S) ? (S.value = e) : null),
class: `list-select`,
options: Be,
optionLabel: `label`,
optionValue: `value`,
onChange: unref(O),
},
null,
8,
[`modelValue`, `onChange`],
),
unref(k)
? (openBlock(),
createBlock(h, {
key: 0,
label: `清除筛选`,
icon: `pi pi-filter-slash`,
severity: `secondary`,
text: ``,
size: `small`,
onClick: Re,
}))
: createCommentVNode(``, !0),
]),
]),
unref(z)
? (openBlock(),
createBlock(
c,
{
key: 4,
severity: unref(Ge),
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(z)), 1),
]),
_: 1,
},
8,
[`severity`],
))
: createCommentVNode(``, !0),
createElementVNode(`div`, Ce, [
createVNode(
_e,
{
value: unref(Ie),
loading: unref(w),
lazy: ``,
rows: unref(D),
totalRecords: unref(C),
first: (unref(E) - 1) * unref(D),
dataKey: `id`,
},
{
empty: withCtx(() => [
createVNode(
ne,
{
icon: `pi pi-shield`,
title: unref(w) ? `加载中…` : `还没有过白记录`,
description: unref(k)
? `换个筛选条件试试`
: `在中国大陆机房提供网站服务前,需要先把域名加入机房白名单`,
},
{
default: withCtx(() => [
!unref(k) && unref(j) && unref(A).length
? (openBlock(),
createBlock(h, {
key: 0,
label: `添加域名白名单`,
icon: `pi pi-plus`,
size: `small`,
onClick: (r[3] ||= (e) => X()),
}))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`title`, `description`],
),
]),
default: withCtx(() => [
createVNode(
y,
{
header: `ID`,
style: {
width: `70px`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
we,
`#` + toDisplayString(t.id),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `主机`,
style: {
"min-width": `170px`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`div`,
null,
toDisplayString(t.host_name || `—`),
1,
),
createElementVNode(
`div`,
Te,
`#` +
toDisplayString(t.host_id) +
` · ` +
toDisplayString(
unref(product_name_n)(t.product_name) ||
`—`,
),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `域名`,
style: {
"min-width": `190px`,
},
},
{
body: withCtx(({ data: n }) => [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
n.domains,
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t,
class: `col-mono`,
},
toDisplayString(t),
1,
)
),
),
128,
)),
n.domains?.length
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`span`, Ee, `—`)),
]),
_: 1,
},
),
createVNode(
y,
{
header: `状态`,
style: {
width: `120px`,
},
},
{
body: withCtx(({ data: e }) => [
createVNode(
me,
{
value: Ue(e),
severity: We(e),
},
null,
8,
[`value`, `severity`],
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `驳回原因`,
style: {
"min-width": `160px`,
},
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(
unref(sanitizeMessage)(t.reject_reason) ||
`—`,
),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `备注`,
style: {
"min-width": `120px`,
},
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(t.remark || `—`),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `提交时间`,
style: {
"min-width": `160px`,
},
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(
(`formatTime` in n
? n.formatTime
: unref(dict_r))(t.create_time),
),
1,
),
]),
_: 1,
},
),
createVNode(
y,
{
header: `操作`,
style: {
width: `90px`,
},
},
{
body: withCtx(({ data: e }) => [
e.can_remove
? (openBlock(),
createBlock(
h,
{
key: 0,
label: `撤销`,
size: `small`,
severity: `danger`,
text: ``,
onClick: (t) => Je(e),
},
null,
8,
[`onClick`],
))
: (openBlock(),
createElementBlock(`span`, De, `—`)),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`, `rows`, `totalRecords`, `first`],
),
]),
unref(T)
? (openBlock(),
createBlock(
c,
{
key: 5,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(T)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(C) > 0
? (openBlock(),
createElementBlock(`div`, Oe, [
(r[22] ||= createElementVNode(
`div`,
{
class: `list-bulk`,
},
null,
-1,
)),
createVNode(
b,
{
rows: unref(D),
totalRecords: unref(C),
first: (unref(E) - 1) * unref(D),
rowsPerPageOptions: [10, 20, 50],
onPage: unref(Le),
},
null,
8,
[`rows`, `totalRecords`, `first`, `onPage`],
),
]))
: createCommentVNode(``, !0),
createVNode(
R,
{
visible: unref(V),
"onUpdate:visible": (r[6] ||= (e) =>
isRef(V) ? (V.value = e) : null),
header: `添加域名白名单`,
modal: ``,
style: {
width: `640px`,
},
},
{
footer: withCtx(() => [
createVNode(h, {
label: `取消`,
severity: `secondary`,
text: ``,
onClick: (r[5] ||= (e) => (V.value = !1)),
}),
createVNode(
h,
{
label: `提交`,
loading: unref(q),
disabled:
unref(W) ||
!unref(U) ||
unref(J) !== unref(H) ||
!unref(j),
onClick: qe,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, ke, [
createElementVNode(`div`, Ae, [
(r[23] ||= createElementVNode(
`label`,
null,
`主机`,
-1,
)),
createVNode(
v,
{
modelValue: unref(H),
"onUpdate:modelValue": (r[4] ||= (e) =>
isRef(H) ? (H.value = e) : null),
disabled: unref(q),
loading: unref(W),
options: unref(A),
optionLabel: `name`,
optionValue: `id`,
placeholder: `选择主机`,
filter: ``,
onChange: Ke,
},
null,
8,
[`modelValue`, `disabled`, `loading`, `options`],
),
]),
unref(U)
? (openBlock(!0),
createElementBlock(
Fragment,
{
key: 0,
},
renderList(
unref(U).fields,
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.name,
class: `field`,
},
[
createElementVNode(`label`, null, [
createTextVNode(
toDisplayString(t.title),
1,
),
t.required
? (openBlock(),
createElementBlock(`span`, je, `*`))
: createCommentVNode(``, !0),
]),
t.type === `select`
? (openBlock(),
createBlock(
v,
{
key: 0,
modelValue: unref(G)[t.name],
"onUpdate:modelValue": (e) =>
(unref(G)[t.name] = e),
options: t.options || [],
optionLabel: `label`,
optionValue: `value`,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`options`,
],
))
: t.type === `textarea`
? (openBlock(),
createBlock(
I,
{
key: 1,
modelValue: unref(G)[t.name],
"onUpdate:modelValue": (e) =>
(unref(G)[t.name] = e),
rows: 3,
autoResize: ``,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
],
))
: (openBlock(),
createBlock(
L,
{
key: 2,
modelValue: unref(G)[t.name],
"onUpdate:modelValue": (e) =>
(unref(G)[t.name] = e),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
],
)),
t.tip
? (openBlock(),
createElementBlock(
`div`,
Me,
toDisplayString(t.tip),
1,
))
: createCommentVNode(``, !0),
],
)
),
),
128,
))
: createCommentVNode(``, !0),
unref(U)?.ips?.length
? (openBlock(),
createElementBlock(
`div`,
Ne,
` 将为主机 IP ` +
toDisplayString(unref(U).ips.join(`、`)) +
` 提交过白。 `,
1,
))
: createCommentVNode(``, !0),
unref(U)?.need_review
? (openBlock(),
createElementBlock(
`div`,
Pe,
` 该机房需要人工审核:提交后由客服处理,处理进度会更新在列表里。 `,
))
: createCommentVNode(``, !0),
unref(K)
? (openBlock(),
createBlock(
c,
{
key: 3,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(K)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`],
),
createVNode(
R,
{
visible: unref(Z),
"onUpdate:visible": (r[8] ||= (e) =>
isRef(Z) ? (Z.value = e) : null),
header: `撤销过白`,
modal: ``,
style: {
width: `420px`,
},
},
{
footer: withCtx(() => [
createVNode(h, {
label: `取消`,
severity: `secondary`,
text: ``,
onClick: (r[7] ||= (e) => (Z.value = !1)),
}),
createVNode(
h,
{
label: `确认撤销`,
severity: `danger`,
loading: unref($),
onClick: Ye,
},
null,
8,
[`loading`],
),
]),
default: withCtx(() => [
createElementVNode(
`p`,
Fe,
` 确认撤销域名 ` +
toDisplayString(unref(Q)?.domains?.join(`、`)) +
` 的白名单?撤销后该域名将无法通过此机房访问。 `,
1,
),
]),
_: 1,
},
8,
[`visible`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-0a28aca5`]],
);
export {};
export default b;
</script>