414 lines
14 KiB
Vue
414 lines
14 KiB
Vue
<script>
|
|
/**
|
|
* 第三方账号关联管理:从账户资料整理 OAuth 绑定状态,通过公共 OAuth 流程发起关联,并确认后解除绑定。
|
|
*/
|
|
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;
|
|
});
|
|
// 读取 /account 的 OAuth 关联列表;组件卸载后的响应不再更新界面。
|
|
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),
|
|
// 列表、绑定入口与解绑确认共用上方互斥状态;外部授权流程由公共 OAuth 控制器处理。
|
|
(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>
|