Files
console-dev/app/pages/register.vue
T

899 lines
31 KiB
Vue

<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 "~/components/PasswordField.vue";
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: ``,
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,
});
// 仅对已开放且需要验证码的注册方式发送验证码,倒计时与验证码挑战由公共发送器管理。
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 (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: `86`,
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 }))
: 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>