refactor: 优化账号管理
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
@@ -1,5 +0,0 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00033 1.16666C10.222 1.16666 12.8337 3.77833 12.8337 6.99999C12.8337 10.2217 10.222 12.8333 7.00033 12.8333C3.77867 12.8333 1.16699 10.2217 1.16699 6.99999C1.16699 3.77833 3.77867 1.16666 7.00033 1.16666Z" fill="#00B42A"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.14096 5.01194L9.47611 5.29316C9.66128 5.44838 9.68542 5.72433 9.53011 5.90943C9.53008 5.90946 9.53006 5.90949 9.52994 5.90944L6.60396 9.39457C6.44853 9.57951 6.17264 9.60361 5.9875 9.44842L5.31721 8.88598L8.52451 5.06578C8.67993 4.88084 8.95583 4.85674 9.14096 5.01194Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.19314 7.32433L4.48668 6.99832C4.64581 6.82159 4.91696 6.80433 5.09721 6.95947L7.15505 8.73065L6.59516 9.40433C6.44073 9.59016 6.16489 9.6156 5.97906 9.46117C5.97677 9.45926 5.9745 9.45733 5.97225 9.45538L4.23181 7.94776C4.04918 7.78956 4.02938 7.51326 4.18758 7.33063C4.18941 7.32851 4.19126 7.32641 4.19314 7.32433Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 437 B |
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
@@ -1,5 +0,0 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.01" x="0.333333" y="0.333333" width="13.3333" height="13.3333" stroke="#F0F0F0" stroke-width="0.666667"/>
|
||||
<path d="M6.99995 13.4159C3.45612 13.4159 0.583282 10.543 0.583282 6.99919C0.583282 3.45536 3.45612 0.58252 6.99995 0.58252C10.5438 0.58252 13.4166 3.45536 13.4166 6.99919C13.4166 10.543 10.5438 13.4159 6.99995 13.4159Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.99995 13.4159C3.45612 13.4159 0.583282 10.543 0.583282 6.99919C0.583282 3.45536 3.45612 0.58252 6.99995 0.58252C10.5438 0.58252 13.4166 3.45536 13.4166 6.99919C13.4166 10.543 10.5438 13.4159 6.99995 13.4159ZM6.1833 10.1492C6.1833 9.69815 6.54893 9.33252 6.99996 9.33252C7.45099 9.33252 7.81663 9.69815 7.81663 10.1492C7.81663 10.6002 7.45099 10.9659 6.99996 10.9659C6.54893 10.9659 6.1833 10.6002 6.1833 10.1492ZM6.21963 3.68084C6.1833 3.75214 6.1833 3.84548 6.1833 4.03217V7.92384C6.1833 8.11052 6.1833 8.20386 6.21963 8.27517C6.25158 8.33789 6.30258 8.38888 6.3653 8.42084C6.4366 8.45717 6.52994 8.45717 6.71663 8.45717H7.2833C7.46998 8.45717 7.56332 8.45717 7.63463 8.42084C7.69735 8.38888 7.74834 8.33789 7.7803 8.27517C7.81663 8.20386 7.81663 8.11052 7.81663 7.92384V4.03217C7.81663 3.84548 7.81663 3.75214 7.7803 3.68084C7.74834 3.61812 7.69735 3.56712 7.63463 3.53517C7.56332 3.49884 7.46998 3.49884 7.2833 3.49884H6.71663C6.52994 3.49884 6.4366 3.49884 6.3653 3.53517C6.30258 3.56712 6.25158 3.61812 6.21963 3.68084Z" fill="#FF8B07"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -21,19 +21,4 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.arco-icon.success {
|
||||
color: rgb(var(--success-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.arco-icon.warning {
|
||||
color: rgb(var(--warning-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.arco-icon.danger {
|
||||
color: rgb(var(--danger-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -50,9 +50,12 @@
|
||||
<icon-down />
|
||||
</a-row>
|
||||
<template #content>
|
||||
<a-doption @click="toUser">
|
||||
<a-doption @click="router.push('/setting/profile')">
|
||||
<span>账号管理</span>
|
||||
</a-doption>
|
||||
<a-doption @click="router.push('/setting/security')">
|
||||
<span>安全设置</span>
|
||||
</a-doption>
|
||||
<a-divider :margin="0" />
|
||||
<a-doption @click="logout">
|
||||
<span>退出登录</span>
|
||||
@@ -80,11 +83,6 @@ const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const SettingDrawerRef = ref<InstanceType<typeof SettingDrawer>>()
|
||||
|
||||
// 跳转基本信息
|
||||
const toUser = () => {
|
||||
router.push('/setting/profile')
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logout = () => {
|
||||
Modal.warning({
|
||||
|
||||
@@ -70,19 +70,13 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||
path: '/setting/profile',
|
||||
component: () => import('@/views/setting/profile/index.vue'),
|
||||
name: 'Profile',
|
||||
meta: { title: '基本信息', hidden: false }
|
||||
meta: { title: '账号管理', hidden: false, showInTabs: false }
|
||||
},
|
||||
{
|
||||
path: '/setting/security',
|
||||
component: () => import('@/views/setting/security/index.vue'),
|
||||
name: 'Security',
|
||||
meta: { title: '安全设置', hidden: false }
|
||||
},
|
||||
{
|
||||
path: '/setting/notice',
|
||||
component: () => import('@/views/setting/notice/index.vue'),
|
||||
name: 'Notification',
|
||||
meta: { title: '消息中心', hidden: false }
|
||||
meta: { title: '安全设置', hidden: false, showInTabs: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -56,3 +56,16 @@ body {
|
||||
.arco-checkbox-label {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: rgb(var(--success-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
.warning {
|
||||
color: rgb(var(--warning-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
.danger {
|
||||
color: rgb(var(--danger-6));
|
||||
margin-right: 4px;
|
||||
}
|
||||
@@ -261,6 +261,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 渐变卡片
|
||||
.gradient-card {
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-neutral-3);
|
||||
& > .arco-card-header {
|
||||
border: none;
|
||||
background: linear-gradient(180deg, rgba(232, 244, 255, 0.5), hsla(0, 0%, 100%, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// 通用描述
|
||||
.general-description {
|
||||
position: relative;
|
||||
@@ -277,21 +287,3 @@
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-table-cell {
|
||||
.circle {
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: rgb(var(--blue-6));
|
||||
vertical-align: middle;
|
||||
&.pass {
|
||||
background-color: rgb(var(--green-6));
|
||||
}
|
||||
&.fail {
|
||||
background-color: rgb(var(--red-6));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,6 @@
|
||||
<template>
|
||||
<div class="setting" :class="{ 'setting--h5': !isDesktop }">
|
||||
<div class="setting__tabs">
|
||||
<a-tabs hide-content size="medium" :active-key="selectedKeys" @change="(key) => toPage(String(key))">
|
||||
<a-tab-pane v-for="item in list" :key="item.path" :title="item.name"> </a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
|
||||
<div class="setting__main">
|
||||
<div class="setting__main__menu">
|
||||
<a-menu :selected-keys="selectedKeys">
|
||||
<a-menu-item v-for="item in list" :key="item.path" @click="toPage(item.path)">
|
||||
<span>{{ item.name }}</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</div>
|
||||
<div class="setting__main__content">
|
||||
<ParentView></ParentView>
|
||||
</div>
|
||||
@@ -26,29 +13,7 @@ import { useDevice } from '@/hooks'
|
||||
|
||||
defineOptions({ name: 'Setting' })
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { isDesktop } = useDevice()
|
||||
|
||||
const selectedKeys = ref('')
|
||||
watch(
|
||||
() => route.path,
|
||||
(newPath) => {
|
||||
selectedKeys.value = newPath
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const list = [
|
||||
{ name: '基本信息', value: 1, path: '/setting/profile' },
|
||||
{ name: '安全设置', value: 2, path: '/setting/security' },
|
||||
{ name: '消息中心', value: 3, path: '/setting/notice' }
|
||||
]
|
||||
|
||||
const toPage = (path: string) => {
|
||||
router.push({ path: path })
|
||||
selectedKeys.value = path
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -58,20 +23,11 @@ const toPage = (path: string) => {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&__tabs {
|
||||
display: none;
|
||||
background-color: var(--color-bg-1);
|
||||
}
|
||||
|
||||
&__main {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
&__menu {
|
||||
width: 200px;
|
||||
margin-top: $margin;
|
||||
margin-left: $margin;
|
||||
}
|
||||
&__content {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
@@ -85,15 +41,5 @@ const toPage = (path: string) => {
|
||||
|
||||
.setting--h5 {
|
||||
flex-direction: column;
|
||||
.setting__tabs {
|
||||
display: block;
|
||||
}
|
||||
.setting__main__menu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-menu-vertical .arco-menu-inner) {
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<div class="page"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
|
||||
defineOptions({ name: 'Notification' })
|
||||
|
||||
const route = useRoute()
|
||||
const form = reactive({ name: '' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
padding: $padding;
|
||||
background-color: var(--color-bg-1);
|
||||
}
|
||||
</style>
|
||||
@@ -1,65 +1,49 @@
|
||||
<template>
|
||||
<Card style="height: 600px">
|
||||
<template #header> 主账号信息 </template>
|
||||
<template #body>
|
||||
<div class="body">
|
||||
<section>
|
||||
<div class="avatar">
|
||||
<img :src="userStore.avatar" alt="avatar" />
|
||||
</div>
|
||||
<div class="name">
|
||||
<span style="margin-right: 10px">{{ userInfo.nickname }}</span>
|
||||
<icon-edit :size="16" class="btn" @click="onEditNickName" />
|
||||
</div>
|
||||
<div class="id">
|
||||
<GiSvgIcon name="id" :size="16" />
|
||||
<span style="margin-left: 10px">{{ userInfo.id }}</span>
|
||||
</div>
|
||||
</section>
|
||||
<footer>
|
||||
<div class="footer_item">
|
||||
<div>
|
||||
<span style="margin-right: 10px">安全手机</span>
|
||||
<span>{{ userInfo.phone }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span
|
||||
><GiSvgIcon :name="userInfo.email ? 'success' : 'warning'" :size="14" /><span
|
||||
style="margin-left: 5px; font-size: 12px"
|
||||
>{{ userInfo.phone ? '已绑定' : '未绑定' }}</span
|
||||
></span
|
||||
>
|
||||
<a-divider direction="vertical" />
|
||||
<icon-edit :size="16" class="btn" @click="openVerifyModel('phone')" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer_item">
|
||||
<div>
|
||||
<span style="margin-right: 10px">安全邮箱</span>
|
||||
<span>{{ userInfo.email }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span
|
||||
><GiSvgIcon :name="userInfo.email ? 'success' : 'warning'" :size="14" /><span
|
||||
style="margin-left: 5px; font-size: 12px"
|
||||
>{{ userInfo.email ? '已绑定' : '未绑定' }}</span
|
||||
></span
|
||||
>
|
||||
<a-divider direction="vertical" />
|
||||
<icon-edit :size="16" class="btn" @click="openVerifyModel('email')" />
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="footer">注册于 {{ userInfo.registrationDate }}</div>
|
||||
</template>
|
||||
</Card>
|
||||
<a-card title="基本信息" bordered class="gradient-card">
|
||||
<div class="body">
|
||||
<section>
|
||||
<div class="avatar">
|
||||
<img :src="userStore.avatar" alt="avatar" />
|
||||
</div>
|
||||
<div class="name">
|
||||
<span style="margin-right: 10px">{{ userInfo.nickname }}</span>
|
||||
<icon-edit :size="16" class="btn" @click="onEditNickName" />
|
||||
</div>
|
||||
<div class="id">
|
||||
<GiSvgIcon name="id" :size="16" />
|
||||
<span>{{ userInfo.id }}</span>
|
||||
</div>
|
||||
</section>
|
||||
<footer>
|
||||
<a-descriptions column="4" size="large">
|
||||
<a-descriptions-item label="性别" :span="4">
|
||||
{{ userInfo.nickname }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="4">
|
||||
<template #label> <icon-phone /><span style="margin-left: 5px">手机</span></template>
|
||||
{{ userInfo.phone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="4">
|
||||
<template #label> <icon-email /><span style="margin-left: 5px">邮箱</span></template>
|
||||
{{ userInfo.email }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="4">
|
||||
<template #label> <icon-mind-mapping /><span style="margin-left: 5px">部门</span></template>
|
||||
{{ userInfo.nickname }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="4">
|
||||
<template #label> <icon-user-group /><span style="margin-left: 5px">角色</span></template>
|
||||
{{ userInfo.nickname }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="footer">注册于 {{ userInfo.registrationDate }}</div>
|
||||
</a-card>
|
||||
<VerifyModel ref="verifyModelRef" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from '../components/Card.vue'
|
||||
import { updateUserBaseInfo } from '@/apis'
|
||||
import VerifyModel from '../components/VerifyModel.vue'
|
||||
import { useUserStore } from '@/stores'
|
||||
@@ -73,20 +57,23 @@ const openVerifyModel = (type: 'phone' | 'email') => {
|
||||
verifyModelRef.value?.open(type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 28px 10px 20px 10px;
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
& > section {
|
||||
flex: 1;
|
||||
flex: 1 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 32px 0 50px;
|
||||
.avatar > img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
@@ -96,18 +83,30 @@ const openVerifyModel = (type: 'phone' | 'email') => {
|
||||
font-size: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.id {
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
padding: 0 6px;
|
||||
color: var(--color-text-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > footer .footer_item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 15px 28px;
|
||||
margin: 0 -16px;
|
||||
padding-top: 16px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
border-top: 1px solid var(--color-neutral-2);
|
||||
border-top: 1px solid var(--color-border-2);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,54 +1,55 @@
|
||||
<template>
|
||||
<Card>
|
||||
<template #header> 登录方式 </template>
|
||||
<template #body>
|
||||
<div class="mode-list">
|
||||
<div v-for="item in modeList" :key="item.title" class="mode-item">
|
||||
<div class="mode-item-box">
|
||||
<div class="mode-item-icon">
|
||||
<GiSvgIcon :name="item.icon" :size="50" />
|
||||
</div>
|
||||
<div class="mode-item-content">
|
||||
<div class="mode-item-title">
|
||||
<div>{{ item.title }}</div>
|
||||
<div style="margin-left: 10px">
|
||||
<GiSvgIcon :name="item.status ? 'success' : 'warning'" :size="14" /><span
|
||||
style="margin-left: 5px; font-size: 12px"
|
||||
>{{ item.status ? '已绑定' : '未绑定' }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mode-item-subtitle">{{ item.subtitle }}</div>
|
||||
</div>
|
||||
<a-card title="登录方式" bordered class="gradient-card">
|
||||
<div class="mode-list">
|
||||
<div v-for="item in modeList" :key="item.title" class="mode-item">
|
||||
<div class="mode-item-box">
|
||||
<div class="mode-item-box__icon">
|
||||
<GiSvgIcon :name="item.icon" :size="48" />
|
||||
</div>
|
||||
<div class="model-item-btn">
|
||||
<a-button @click="openVerifyModel(item.type, item.status)" v-if="item.jumpMode == 'modal'">{{
|
||||
item.status ? '修改' : '绑定'
|
||||
}}</a-button>
|
||||
<a-button @click="onBinding(item.type, item.status)" v-else-if="item.jumpMode == 'link'">{{
|
||||
item.status ? '解绑' : '绑定'
|
||||
}}</a-button>
|
||||
<div class="mode-item-box__content">
|
||||
<div class="title">
|
||||
<div>{{ item.title }}</div>
|
||||
<div style="margin-left: 10px">
|
||||
<icon-check-circle-fill v-if="item.status" :size="14" class="success" />
|
||||
<icon-exclamation-circle-fill v-else :size="14" class="warning" />
|
||||
<span style="font-size: 12px" :class="item.status ? 'success' : 'warning'">{{
|
||||
item.status ? '已绑定' : '未绑定'
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mode-item-box__subtitle">{{ item.subtitle }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-button
|
||||
v-if="item.jumpMode == 'modal'"
|
||||
class="btn"
|
||||
:type="item.status ? 'secondary' : 'primary'"
|
||||
@click="openVerifyModel(item.type, item.status)"
|
||||
>
|
||||
{{ item.status ? '修改' : '绑定' }}
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else-if="item.jumpMode == 'link'"
|
||||
class="btn"
|
||||
:type="item.status ? 'secondary' : 'primary'"
|
||||
@click="onBinding(item.type, item.status)"
|
||||
>
|
||||
{{ item.status ? '解绑' : '绑定' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
</a-card>
|
||||
<VerifyModel ref="verifyModelRef" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/stores'
|
||||
import Card from '../components/Card.vue'
|
||||
import VerifyModel from '../components/VerifyModel.vue'
|
||||
import { socialAuth, getSocialAccount, unbindSocialAccount } from '@/apis'
|
||||
interface ModeItem {
|
||||
title: string
|
||||
icon: string
|
||||
subtitle: string
|
||||
type: 'phone' | 'email' | 'gitee' | 'github'
|
||||
jumpMode: 'link' | 'modal'
|
||||
status: boolean
|
||||
}
|
||||
import type { ModeItem } from './type'
|
||||
import { useUserStore } from '@/stores'
|
||||
import VerifyModel from '../components/VerifyModel.vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const userInfo = computed(() => userStore.userInfo)
|
||||
const verifyModelRef = ref<InstanceType<typeof VerifyModel>>()
|
||||
@@ -56,36 +57,37 @@ const openVerifyModel = (type: 'phone' | 'email') => {
|
||||
verifyModelRef.value?.open(type)
|
||||
}
|
||||
const socialList = ref<any>([])
|
||||
|
||||
const modeList = ref<ModeItem[]>([])
|
||||
modeList.value = [
|
||||
{
|
||||
title: '绑定手机号',
|
||||
icon: 'Tel',
|
||||
subtitle: `${userInfo.value.phone || '绑定后'},可通过手机验证码快捷登录`,
|
||||
title: '绑定手机',
|
||||
icon: userInfo.value.phone ? 'tel' : 'tel-unbind',
|
||||
subtitle: `${userInfo.value.phone || '绑定后'},可通过手机验证码快捷登录`,
|
||||
type: 'phone',
|
||||
jumpMode: 'modal',
|
||||
status: userInfo.value.phone ? true : false
|
||||
status: !!userInfo.value.phone
|
||||
},
|
||||
{
|
||||
title: '绑定邮箱',
|
||||
icon: 'Mail',
|
||||
subtitle: `${userInfo.value.email || '绑定后'},可通过邮箱验证码进行登录`,
|
||||
icon: userInfo.value.email ? 'mail' : 'mail-unbind',
|
||||
subtitle: `${userInfo.value.email || '绑定后'},可通过邮箱验证码进行登录`,
|
||||
type: 'email',
|
||||
jumpMode: 'modal',
|
||||
status: userInfo.value.email ? true : false
|
||||
status: !!userInfo.value.email
|
||||
},
|
||||
{
|
||||
title: '绑定Gitee',
|
||||
title: '绑定 Gitee',
|
||||
icon: 'gitee',
|
||||
subtitle: '绑定后,可通过Gitee进行登录',
|
||||
subtitle: '绑定后,可通过 Gitee 进行登录',
|
||||
jumpMode: 'link',
|
||||
type: 'gitee',
|
||||
status: socialList.value.some((el) => el == 'gitee')
|
||||
},
|
||||
{
|
||||
title: '绑定GitHub',
|
||||
title: '绑定 GitHub',
|
||||
icon: 'github',
|
||||
subtitle: '绑定后,可通过github进行登录',
|
||||
subtitle: '绑定后,可通过 GitHub 进行登录',
|
||||
type: 'github',
|
||||
jumpMode: 'link',
|
||||
status: socialList.value.some((el) => el == 'github')
|
||||
@@ -96,9 +98,7 @@ const initData = () => {
|
||||
socialList.value = res.data.map((el) => el.source)
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
const onBinding = (type: string, status: boolean) => {
|
||||
if (!status) {
|
||||
socialAuth(type).then((res) => {
|
||||
@@ -112,6 +112,10 @@ const onBinding = (type: string, status: boolean) => {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -119,21 +123,29 @@ const onBinding = (type: string, status: boolean) => {
|
||||
.mode-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
.mode-item-box {
|
||||
&-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.mode-item-icon {
|
||||
&__icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mode-item-content > div {
|
||||
line-height: 26px;
|
||||
}
|
||||
.mode-item-content .mode-item-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&__content {
|
||||
div {
|
||||
line-height: 26px;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
height: 28px;
|
||||
margin-left: 10px;
|
||||
width: 56px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,40 +1,25 @@
|
||||
<template>
|
||||
<div class="user">
|
||||
<div class="user__info">
|
||||
<a-row justify="space-between">
|
||||
<a-col :span="7" style="padding-right: 20px">
|
||||
<LeftBox />
|
||||
</a-col>
|
||||
<a-col :span="17">
|
||||
<RightBox />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<div class="gi_page">
|
||||
<a-row wrap :gutter="16">
|
||||
<a-col :xs="24" :sm="24" :md="10" :lg="10" :xl="7" :xxl="7">
|
||||
<LeftBox />
|
||||
</a-col>
|
||||
<a-col :xs="24" :sm="24" :md="14" :lg="14" :xl="17" :xxl="17">
|
||||
<RightBox />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { useUserStore } from '@/stores'
|
||||
import RightBox from './RightBox.vue'
|
||||
import LeftBox from './LeftBox.vue'
|
||||
defineOptions({ name: 'Profile' })
|
||||
import RightBox from './RightBox.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const userStore = useUserStore()
|
||||
defineOptions({ name: 'Profile' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user {
|
||||
// background-color: var(--color-bg-1);
|
||||
&__alert {
|
||||
padding: $padding;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
&__info {
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
// display: flex;
|
||||
}
|
||||
.gi_page {
|
||||
background-color: var(--color-bg-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
8
src/views/setting/profile/type.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface ModeItem {
|
||||
title: string
|
||||
icon: string
|
||||
subtitle: string
|
||||
type: 'phone' | 'email' | 'gitee' | 'github'
|
||||
jumpMode: 'link' | 'modal'
|
||||
status: boolean
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<div class="content_title">
|
||||
<div class="icon"><GiSvgIcon name="loginProtect" :size="36" /></div>
|
||||
<div class="icon"><GiSvgIcon name="login-protect" :size="36" /></div>
|
||||
<div>
|
||||
<div style="font-size: 14px; font-weight: 500; line-height: 28px">操作保护</div>
|
||||
<div style="font-size: 12px">进行敏感操作时需进行二次身份校验</div>
|
||||
@@ -50,7 +50,7 @@ interface ModeItem {
|
||||
}
|
||||
const modeList = ref<ModeItem[]>([])
|
||||
modeList.value = [
|
||||
{ title: '登录保护', icon: 'loginProtect', subtitle: '开启登录保护后,账号登录需进行二次身份验证', status: false }
|
||||
{ title: '登录保护', icon: 'login-protect', subtitle: '开启登录保护后,账号登录需进行二次身份验证', status: false }
|
||||
]
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -38,8 +38,8 @@ interface ModeItem {
|
||||
}
|
||||
const modeList = ref<ModeItem[]>([])
|
||||
modeList.value = [
|
||||
{ title: '绑定手机号', icon: 'Tel', subtitle: '+86******88888可通过手机验证码快捷登录', type: 'phone', status: true },
|
||||
{ title: '绑定邮箱', icon: 'Mail', subtitle: '邮箱可用于身份验证、密码找回、通知接收', type: 'email', status: true }
|
||||
{ title: '绑定手机号', icon: 'tel', subtitle: '+86******88888可通过手机验证码快捷登录', type: 'phone', status: true },
|
||||
{ title: '绑定邮箱', icon: 'mail', subtitle: '邮箱可用于身份验证、密码找回、通知接收', type: 'email', status: true }
|
||||
]
|
||||
const verifyModelRef = ref<InstanceType<typeof VerifyModel>>()
|
||||
const openVerifyModel = (type: 'phone' | 'email') => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<template #header> 登录会话设置 </template>
|
||||
<template #body>
|
||||
<div class="content_title">
|
||||
<div class="icon"><GiSvgIcon name="loginStatus" :size="36" /></div>
|
||||
<div class="icon"><GiSvgIcon name="login-status" :size="36" /></div>
|
||||
<div>
|
||||
<div style="font-size: 14px; font-weight: 500; line-height: 28px">登录态保持时间设置</div>
|
||||
<div style="font-size: 12px">保持登录状态的限制</div>
|
||||
|
||||