727 lines
29 KiB
Vue
727 lines
29 KiB
Vue
<script>
|
|
import "~/assets/styles/AuthProviders.CgAWouSf.css";
|
|
import { toDisplayString } from "vue";
|
|
import { renderList } from "vue";
|
|
import { onMounted } from "vue";
|
|
import { onUnmounted } from "vue";
|
|
import { normalizeClass } from "vue";
|
|
import { watch } from "vue";
|
|
import { createBlock } from "vue";
|
|
import { ref } from "vue";
|
|
import { withCtx } from "vue";
|
|
import { createCommentVNode } from "vue";
|
|
import { computed } from "vue";
|
|
import { isRef } from "vue";
|
|
import { createElementBlock } from "vue";
|
|
import { Fragment } from "vue";
|
|
import { createElementVNode } from "vue";
|
|
import { createTextVNode } from "vue";
|
|
import { unref } from "vue";
|
|
import { defineComponent } from "vue";
|
|
import { createVNode } from "vue";
|
|
import { openBlock } from "vue";
|
|
import { normalizeStyle } from "vue";
|
|
import { useRoute } from "#app";
|
|
import { useRouter } from "#app";
|
|
import { loginErrorMessage } from "~/lib/auth.js";
|
|
import { useApi } from "~/lib/auth.js";
|
|
import { isValidJwt } from "~/lib/auth.js";
|
|
import { useAuth } from "~/lib/auth.js";
|
|
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.js";
|
|
import button from "primevue/button";
|
|
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
|
import message from "primevue/message";
|
|
import radiobutton from "primevue/radiobutton";
|
|
import { r as wechat_binding_r } from "~/lib/wechat-binding.js";
|
|
import { r as auth_redirect_r } from "~/lib/auth-redirect.js";
|
|
var fe = {
|
|
key: 0,
|
|
class: `auth-providers`,
|
|
"aria-label": `其他登录方式`,
|
|
},
|
|
S = [`id`, `aria-labelledby`],
|
|
pe = {
|
|
key: 0,
|
|
class: `login-qr`,
|
|
},
|
|
me = {
|
|
class: `qr-stage`,
|
|
},
|
|
he = {
|
|
key: 0,
|
|
class: `qr-clients`,
|
|
},
|
|
ge = [`aria-busy`],
|
|
_e = [`src`],
|
|
ve = {
|
|
class: `qr-status`,
|
|
"aria-live": `polite`,
|
|
},
|
|
ye = {
|
|
key: 1,
|
|
class: `qr-tip`,
|
|
},
|
|
be = {
|
|
class: `qr-actions`,
|
|
},
|
|
xe = [
|
|
`id`,
|
|
`aria-selected`,
|
|
`aria-controls`,
|
|
`tabindex`,
|
|
`disabled`,
|
|
`title`,
|
|
`aria-label`,
|
|
`onClick`,
|
|
],
|
|
Se = 5,
|
|
Ce = 300,
|
|
C = Object.assign(
|
|
_plugin_vue_export_helper_t(
|
|
defineComponent({
|
|
__name: `AuthProviders`,
|
|
setup(ee, { expose: b }) {
|
|
let C = useAuth(),
|
|
w = useRoute(),
|
|
T = useRouter(),
|
|
E = useApi(),
|
|
{ load: D, scanLoginEnabled: O, error: we } = useSiteConfig_t(),
|
|
k = ref(!1),
|
|
A = null;
|
|
function j() {
|
|
((k.value = A?.matches ?? !1), k.value || Q());
|
|
}
|
|
let M = computed(() => [
|
|
{
|
|
id: `wechat`,
|
|
label: `微信`,
|
|
enabled: O.value,
|
|
},
|
|
{
|
|
id: `other`,
|
|
label: `其他方式`,
|
|
enabled: !1,
|
|
},
|
|
]),
|
|
N = ref(0),
|
|
P = computed(() => M.value[N.value]),
|
|
F = ref([]);
|
|
function Te(e) {
|
|
let t = M.value.flatMap((e, t) => (e.enabled ? [t] : []));
|
|
if (!t.length) return;
|
|
let n = t.indexOf(N.value),
|
|
r = n;
|
|
if (e.key === `ArrowRight`) r = (n + 1) % t.length;
|
|
else if (e.key === `ArrowLeft`) r = (n + t.length - 1) % t.length;
|
|
else if (e.key === `Home`) r = 0;
|
|
else if (e.key === `End`) r = t.length - 1;
|
|
else return;
|
|
(e.preventDefault(), (N.value = t[r]), F.value[N.value]?.focus());
|
|
}
|
|
let I = ref(null),
|
|
L = ref(!1),
|
|
R = ref(!1),
|
|
z = ref(``),
|
|
B = ref([]),
|
|
V = ref(null),
|
|
H = ref(!1),
|
|
U = ref(0),
|
|
W = null,
|
|
G = null,
|
|
K = 0,
|
|
q = null;
|
|
function J() {
|
|
W !== null && (clearInterval(W), (W = null));
|
|
}
|
|
function Y() {
|
|
(G !== null && (clearInterval(G), (G = null)), (U.value = 0));
|
|
}
|
|
function Ee() {
|
|
(J(), Y(), (W = window.setInterval(De, 2e3)));
|
|
let e = Math.floor(Date.now() / 1e3),
|
|
t = I.value?.expire_time ? I.value.expire_time - e : Ce;
|
|
((U.value = Math.max(1, t - Se)),
|
|
(G = window.setInterval(() => {
|
|
(--U.value, U.value <= 0 && (Y(), X()));
|
|
}, 1e3)));
|
|
}
|
|
async function X() {
|
|
if (!k.value || L.value) return;
|
|
let e = ++K;
|
|
(Z(),
|
|
(z.value = ``),
|
|
(R.value = !1),
|
|
(B.value = []),
|
|
(V.value = null),
|
|
(H.value = !1),
|
|
(L.value = !0));
|
|
try {
|
|
let t = await E.get(`/mp_weixin_notice/qrcode`, void 0, !1, {
|
|
timeoutMs: 15e3,
|
|
});
|
|
if (e !== K) return;
|
|
if (
|
|
typeof t?.img_url != `string` ||
|
|
!t.img_url ||
|
|
typeof t.ticket != `string` ||
|
|
!t.ticket ||
|
|
typeof t.token != `string` ||
|
|
!t.token
|
|
)
|
|
throw Error(`二维码加载失败,请重新获取`);
|
|
((I.value = t), (z.value = ``), Ee());
|
|
} catch (t) {
|
|
if (e !== K) return;
|
|
(J(),
|
|
Y(),
|
|
(z.value = loginErrorMessage(t, `二维码加载失败,请稍后重试`)));
|
|
} finally {
|
|
e === K && (L.value = !1);
|
|
}
|
|
}
|
|
async function De() {
|
|
if (!I.value || q === K) return;
|
|
let e = K,
|
|
t = I.value;
|
|
q = e;
|
|
try {
|
|
let n = await E.get(
|
|
`/mp_weixin_notice/qrcode/status`,
|
|
{
|
|
ticket: t.ticket,
|
|
token: t.token,
|
|
},
|
|
!1,
|
|
{
|
|
timeoutMs: 1e4,
|
|
},
|
|
);
|
|
if (e !== K) return;
|
|
if (!n || typeof n.status != `string`)
|
|
throw Error(`扫码登录状态异常,请重新获取二维码`);
|
|
if (n.status === `Wait`) return;
|
|
if (n.status === `Success`) {
|
|
n.jwt
|
|
? $(n.jwt)
|
|
: (Z(),
|
|
(z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`));
|
|
return;
|
|
}
|
|
if (n.status === `Expired`) {
|
|
(J(),
|
|
Y(),
|
|
(R.value = !0),
|
|
(z.value = `二维码已过期,请刷新后重新扫码`));
|
|
return;
|
|
}
|
|
if (n.status === `SelectClient`) {
|
|
(J(),
|
|
Y(),
|
|
(B.value = Array.isArray(n.client)
|
|
? n.client.filter(
|
|
(e) =>
|
|
e &&
|
|
Number.isSafeInteger(e.id) &&
|
|
e.id > 0 &&
|
|
typeof e.username == `string`,
|
|
)
|
|
: []),
|
|
(V.value = B.value.find((e) => e.status === 1)?.id ?? null),
|
|
V.value ||
|
|
(z.value = `当前微信没有可登录的账号,请使用账号密码登录或联系客服`));
|
|
return;
|
|
}
|
|
if (n.status === `WaitBind`) {
|
|
(Z(),
|
|
wechat_binding_r(t, sessionStorage),
|
|
await T.push({
|
|
path: `/oauth/bind`,
|
|
query: {
|
|
provider: `wechat`,
|
|
redirect: auth_redirect_r(w.query.redirect),
|
|
},
|
|
}));
|
|
return;
|
|
}
|
|
(Z(), (z.value = `扫码登录状态异常,请重新获取二维码`));
|
|
} catch (t) {
|
|
if (e !== K) return;
|
|
(Z(),
|
|
(z.value = loginErrorMessage(
|
|
t,
|
|
`扫码登录验证失败,请刷新二维码后重试`,
|
|
)));
|
|
} finally {
|
|
q === e && (q = null);
|
|
}
|
|
}
|
|
function Z() {
|
|
(J(), Y());
|
|
}
|
|
function Q() {
|
|
(K++,
|
|
Z(),
|
|
(I.value = null),
|
|
(L.value = !1),
|
|
(H.value = !1),
|
|
(R.value = !1),
|
|
(z.value = ``),
|
|
(B.value = []),
|
|
(V.value = null));
|
|
}
|
|
function $(e) {
|
|
if ((Z(), !isValidJwt(e))) {
|
|
z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`;
|
|
return;
|
|
}
|
|
(C.loginWithJwt(e), K++, T.push(auth_redirect_r(w.query.redirect)));
|
|
}
|
|
async function Oe() {
|
|
if (H.value) return;
|
|
if (
|
|
!I.value ||
|
|
!B.value.some((e) => e.id === V.value && e.status === 1)
|
|
) {
|
|
z.value = `请选择一个可登录的账号`;
|
|
return;
|
|
}
|
|
((z.value = ``), (H.value = !0));
|
|
let e = K;
|
|
try {
|
|
let t = await E.post(
|
|
`/mp_weixin_notice/qrcode/select_client_login`,
|
|
{
|
|
ticket: I.value.ticket,
|
|
token: I.value.token,
|
|
client_id: V.value,
|
|
},
|
|
!1,
|
|
{
|
|
timeoutMs: 15e3,
|
|
},
|
|
);
|
|
if (e !== K) return;
|
|
t?.jwt
|
|
? $(t.jwt)
|
|
: (z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`);
|
|
} catch (t) {
|
|
if (e !== K) return;
|
|
z.value = loginErrorMessage(t);
|
|
} finally {
|
|
e === K && (H.value = !1);
|
|
}
|
|
}
|
|
return (
|
|
onMounted(async () => {
|
|
((A = window.matchMedia(`(min-width: 761px)`)),
|
|
j(),
|
|
A.addEventListener(`change`, j),
|
|
await D().catch(() => {}));
|
|
}),
|
|
watch(N, Q),
|
|
onUnmounted(() => {
|
|
(A?.removeEventListener(`change`, j), Q());
|
|
}),
|
|
b({
|
|
resetQr: Q,
|
|
}),
|
|
(n, r) => {
|
|
let a = radiobutton,
|
|
s = button,
|
|
u = message;
|
|
return unref(k)
|
|
? (openBlock(),
|
|
createElementBlock(`aside`, fe, [
|
|
createElementVNode(
|
|
`div`,
|
|
{
|
|
id: `provider-panel-${unref(P).id}`,
|
|
role: `tabpanel`,
|
|
"aria-labelledby": `provider-tab-${unref(P).id}`,
|
|
class: `provider-panel`,
|
|
},
|
|
[
|
|
unref(O)
|
|
? (openBlock(),
|
|
createElementBlock(`div`, pe, [
|
|
createElementVNode(`div`, me, [
|
|
unref(B).length
|
|
? (openBlock(),
|
|
createElementBlock(`div`, he, [
|
|
(r[1] ||= createElementVNode(
|
|
`p`,
|
|
{
|
|
class: `qr-tip`,
|
|
},
|
|
`请选择要登录的账号`,
|
|
-1,
|
|
)),
|
|
(openBlock(!0),
|
|
createElementBlock(
|
|
Fragment,
|
|
null,
|
|
renderList(
|
|
unref(B),
|
|
(t) => (
|
|
openBlock(),
|
|
createElementBlock(
|
|
`label`,
|
|
{
|
|
key: t.id,
|
|
class: normalizeClass([
|
|
`qr-client`,
|
|
{
|
|
disabled: t.status !== 1,
|
|
},
|
|
]),
|
|
},
|
|
[
|
|
createVNode(
|
|
a,
|
|
{
|
|
modelValue: unref(V),
|
|
"onUpdate:modelValue":
|
|
(r[0] ||= (e) =>
|
|
isRef(V)
|
|
? (V.value = e)
|
|
: null),
|
|
"input-id": `qr-client-${t.id}`,
|
|
value: t.id,
|
|
disabled: t.status !== 1,
|
|
},
|
|
null,
|
|
8,
|
|
[
|
|
`modelValue`,
|
|
`input-id`,
|
|
`value`,
|
|
`disabled`,
|
|
],
|
|
),
|
|
createElementVNode(
|
|
`span`,
|
|
null,
|
|
toDisplayString(t.username),
|
|
1,
|
|
),
|
|
],
|
|
2,
|
|
)
|
|
),
|
|
),
|
|
128,
|
|
)),
|
|
createVNode(
|
|
s,
|
|
{
|
|
label: `登录`,
|
|
loading: unref(H),
|
|
disabled: !unref(V) || unref(H),
|
|
class: `qr-client-btn`,
|
|
fluid: ``,
|
|
onClick: Oe,
|
|
},
|
|
null,
|
|
8,
|
|
[`loading`, `disabled`],
|
|
),
|
|
]))
|
|
: (openBlock(),
|
|
createElementBlock(
|
|
`div`,
|
|
{
|
|
key: 1,
|
|
class: normalizeClass([
|
|
`qr-box`,
|
|
{
|
|
"qr-box-idle": !unref(I),
|
|
},
|
|
]),
|
|
"aria-busy": unref(L),
|
|
},
|
|
[
|
|
unref(I) && !unref(R)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`img`,
|
|
{
|
|
key: 0,
|
|
class: normalizeClass([
|
|
`qr-img`,
|
|
{
|
|
"qr-img-dim": unref(L),
|
|
},
|
|
]),
|
|
src: unref(I).img_url,
|
|
alt: `微信扫码登录`,
|
|
},
|
|
null,
|
|
10,
|
|
_e,
|
|
))
|
|
: (openBlock(),
|
|
createBlock(
|
|
s,
|
|
{
|
|
key: 1,
|
|
type: `button`,
|
|
label: unref(R)
|
|
? `刷新二维码`
|
|
: `获取二维码`,
|
|
icon: unref(R)
|
|
? `pi pi-refresh`
|
|
: `pi pi-qrcode`,
|
|
severity: `secondary`,
|
|
text: ``,
|
|
class: `qr-request`,
|
|
loading: unref(L),
|
|
disabled: unref(L),
|
|
onClick: X,
|
|
},
|
|
null,
|
|
8,
|
|
[
|
|
`label`,
|
|
`icon`,
|
|
`loading`,
|
|
`disabled`,
|
|
],
|
|
)),
|
|
],
|
|
10,
|
|
ge,
|
|
)),
|
|
]),
|
|
createElementVNode(`div`, ve, [
|
|
unref(z)
|
|
? (openBlock(),
|
|
createBlock(
|
|
u,
|
|
{
|
|
key: 0,
|
|
severity: `error`,
|
|
closable: !1,
|
|
icon: `pi pi-exclamation-circle`,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
createTextVNode(
|
|
toDisplayString(unref(z)),
|
|
1,
|
|
),
|
|
]),
|
|
_: 1,
|
|
},
|
|
))
|
|
: (openBlock(),
|
|
createElementBlock(
|
|
`p`,
|
|
ye,
|
|
toDisplayString(
|
|
unref(L) && !unref(I)
|
|
? `二维码加载中…`
|
|
: unref(B).length
|
|
? `选择账号后继续登录`
|
|
: `使用微信扫一扫登录`,
|
|
),
|
|
1,
|
|
)),
|
|
]),
|
|
createElementVNode(`div`, be, [
|
|
unref(B).length
|
|
? (openBlock(),
|
|
createBlock(s, {
|
|
key: 0,
|
|
type: `button`,
|
|
label: `返回重新扫码`,
|
|
severity: `secondary`,
|
|
text: ``,
|
|
size: `small`,
|
|
onClick: X,
|
|
}))
|
|
: unref(I) && !unref(R)
|
|
? (openBlock(),
|
|
createBlock(
|
|
s,
|
|
{
|
|
key: 1,
|
|
type: `button`,
|
|
label: `刷新二维码`,
|
|
icon: `pi pi-refresh`,
|
|
severity: `secondary`,
|
|
outlined: ``,
|
|
size: `small`,
|
|
loading: unref(L),
|
|
disabled: unref(L),
|
|
onClick: X,
|
|
},
|
|
null,
|
|
8,
|
|
[`loading`, `disabled`],
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
]),
|
|
]))
|
|
: createCommentVNode(``, !0),
|
|
unref(O)
|
|
? createCommentVNode(``, !0)
|
|
: (openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
{
|
|
key: 1,
|
|
},
|
|
[
|
|
(r[2] ||= createElementVNode(
|
|
`div`,
|
|
{
|
|
class: `provider-qr-placeholder`,
|
|
"aria-hidden": `true`,
|
|
},
|
|
[
|
|
createElementVNode(`i`, {
|
|
class: `pi pi-qrcode`,
|
|
}),
|
|
],
|
|
-1,
|
|
)),
|
|
(r[3] ||= createElementVNode(
|
|
`p`,
|
|
{
|
|
class: `provider-heading`,
|
|
},
|
|
`微信扫码登录`,
|
|
-1,
|
|
)),
|
|
(r[4] ||= createElementVNode(
|
|
`p`,
|
|
{
|
|
class: `provider-description`,
|
|
},
|
|
`扫码登录暂不可用,请使用手机号或邮箱登录`,
|
|
-1,
|
|
)),
|
|
],
|
|
64,
|
|
)),
|
|
unref(we)
|
|
? (openBlock(),
|
|
createBlock(
|
|
u,
|
|
{
|
|
key: 2,
|
|
severity: `warn`,
|
|
closable: !1,
|
|
class: `provider-config-error`,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
(r[5] ||= createTextVNode(
|
|
`登录方式加载失败。`,
|
|
-1,
|
|
)),
|
|
createVNode(
|
|
s,
|
|
{
|
|
type: `button`,
|
|
label: `重试`,
|
|
text: ``,
|
|
size: `small`,
|
|
onClick: unref(D),
|
|
},
|
|
null,
|
|
8,
|
|
[`onClick`],
|
|
),
|
|
]),
|
|
_: 1,
|
|
},
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
],
|
|
8,
|
|
S,
|
|
),
|
|
createElementVNode(
|
|
`div`,
|
|
{
|
|
class: `provider-tabs`,
|
|
role: `tablist`,
|
|
"aria-label": `扫码登录方式`,
|
|
onKeydown: Te,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`span`,
|
|
{
|
|
class: `provider-tab-indicator`,
|
|
style: normalizeStyle({
|
|
transform: `translateX(${unref(N) * 100}%)`,
|
|
}),
|
|
"aria-hidden": `true`,
|
|
},
|
|
null,
|
|
4,
|
|
),
|
|
(openBlock(!0),
|
|
createElementBlock(
|
|
Fragment,
|
|
null,
|
|
renderList(
|
|
unref(M),
|
|
(t, n) => (
|
|
openBlock(),
|
|
createElementBlock(
|
|
`button`,
|
|
{
|
|
id: `provider-tab-${t.id}`,
|
|
key: t.id,
|
|
ref_for: !0,
|
|
ref_key: `providerTabs`,
|
|
ref: F,
|
|
type: `button`,
|
|
role: `tab`,
|
|
"aria-selected": unref(N) === n,
|
|
"aria-controls": t.enabled
|
|
? `provider-panel-${t.id}`
|
|
: void 0,
|
|
tabindex: unref(N) === n ? 0 : -1,
|
|
disabled: !t.enabled,
|
|
title: t.enabled
|
|
? void 0
|
|
: `${t.label}暂未开放`,
|
|
"aria-label": t.enabled
|
|
? `${t.label}登录`
|
|
: `${t.label}暂未开放`,
|
|
class: normalizeClass({
|
|
active: unref(N) === n,
|
|
}),
|
|
onClick: (e) => (N.value = n),
|
|
},
|
|
toDisplayString(t.label),
|
|
11,
|
|
xe,
|
|
)
|
|
),
|
|
),
|
|
128,
|
|
)),
|
|
],
|
|
32,
|
|
),
|
|
]))
|
|
: createCommentVNode(``, !0);
|
|
}
|
|
);
|
|
},
|
|
}),
|
|
[[`__scopeId`, `data-v-9d0ee2f9`]],
|
|
),
|
|
{
|
|
__name: `AuthProviders`,
|
|
},
|
|
);
|
|
export {};
|
|
export default C;
|
|
</script>
|