refactor: 账号管理功能大体完成,后续优化与细节调整

This commit is contained in:
秋帆
2024-04-21 22:33:48 +08:00
parent 124674c530
commit 875b72b3a0
32 changed files with 1279 additions and 397 deletions

View File

@@ -0,0 +1,99 @@
<template>
<Card>
<template #header> 账号保护 </template>
<template #body>
<div class="mode-item" v-for="item in modeList" :key="item.title">
<div class="mode-item-content">
<div class="icon"><GiSvgIcon :name="item.icon" :size="36" /></div>
<div>
<div style="font-size: 14px; font-weight: 500; line-height: 28px; display: flex; align-items: center">
<span>{{ item.title }}</span>
<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 style="font-size: 12px">{{ item.subtitle }}</div>
</div>
</div>
<div>
<a-button disabled>未开放</a-button>
</div>
</div>
<div>
<div class="content_title">
<div class="icon"><GiSvgIcon name="loginProtect" :size="36" /></div>
<div>
<div style="font-size: 14px; font-weight: 500; line-height: 28px">操作保护</div>
<div style="font-size: 12px">进行敏感操作时需进行二次身份校验</div>
</div>
</div>
<div class="content_Box">
<p>可使用<span class="subTitle">手机号</span>进行二次身份验证</p>
<p>未设置密码有效期</p>
<p>敏感操作二次身份验证后<span class="subTitle">10</span>分钟内不需要再次进行验证</p>
<p class="link_btn">修改规则(未开发)</p>
</div>
</div>
</template>
</Card>
</template>
<script setup lang="ts">
import Card from '../components/Card.vue'
interface ModeItem {
title: string
icon: string
subtitle: string
status: boolean
}
const modeList = ref<ModeItem[]>([])
modeList.value = [
{ title: '登录保护', icon: 'loginProtect', subtitle: '开启登录保护后,账号登录需进行二次身份验证', status: false }
]
</script>
<style scoped lang="scss">
.mode-item {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.mode-item-content {
display: flex;
align-items: center;
.icon {
margin-right: 10px;
}
}
}
.content_title {
display: flex;
align-items: center;
.icon {
margin-right: 10px;
}
}
.content_Box {
border-left: 1px solid #ccc;
margin-left: 40px;
padding-left: 10px;
font-size: 12px;
margin-top: 20px;
& > p {
margin: 10px;
}
}
.link_btn {
cursor: pointer;
color: #007aff;
&:hover {
color: rgba($color: #007aff, $alpha: 0.8);
}
}
.subTitle {
background: var(--color-neutral-2);
padding: 1px 5px;
margin: 0px 5px;
border-radius: 3px;
}
</style>

View File

@@ -0,0 +1,62 @@
<template>
<Card style="height: 100%">
<template #header>基本设置</template>
<template #body>
<div class="mode-item" v-for="item in modeList" :key="item.title">
<div class="mode-item-content">
<div class="icon"><GiSvgIcon :name="item.icon" :size="36" /></div>
<div>
<div style="font-size: 14px; font-weight: 500; line-height: 28px; display: flex; align-items: center">
<span>{{ item.title }}</span>
<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 style="font-size: 12px">{{ item.subtitle }}</div>
</div>
</div>
<div>
<a-button @click="openVerifyModel(item.type)">修改</a-button>
</div>
</div>
</template>
</Card>
<VerifyModel ref="verifyModelRef" />
</template>
<script setup lang="ts">
import Card from '../components/Card.vue'
import VerifyModel from '../components/VerifyModel.vue'
interface ModeItem {
title: string
icon: string
subtitle: string
type: 'phone' | 'email'
status: boolean
}
const modeList = ref<ModeItem[]>([])
modeList.value = [
{ 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') => {
verifyModelRef.value?.open(type)
}
</script>
<style lang="scss" scoped>
.mode-item {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.mode-item-content {
display: flex;
align-items: center;
.icon {
margin-right: 10px;
}
}
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<Card>
<template #header> 密码策略 </template>
<template #body>
<div class="content_title">
<div class="icon"><GiSvgIcon name="password" :size="36" /></div>
<div>
<div style="font-size: 14px; font-weight: 500; line-height: 28px">登录密码</div>
<div style="font-size: 12px">为了您的账号安全建议定期修改密码</div>
</div>
</div>
<div class="content_Box">
<p>
密码至少包含 <span class="subTitle">大写字母</span><span class="subTitle">小写字母</span
><span class="subTitle">数字</span><span class="subTitle">特殊字符</span>3
</p>
<p>限制密码长度至少为<span class="subTitle">8</span></p>
<p>未设置密码有效期</p>
<p>新密码不能与历史前<span class="subTitle">3</span>次密码重复</p>
<p>1小时内密码错误可重试 <span class="subTitle">5</span></p>
<p>超过错误密码重试次数账号将被锁定<span class="subTitle">60</span>分钟</p>
<p class="link_btn">修改规则(未开发)</p>
</div>
</template>
</Card>
</template>
<script setup lang="ts">
import Card from '../components/Card.vue'
</script>
<style scoped lang="scss">
.content_title {
display: flex;
align-items: center;
.icon {
margin-right: 10px;
}
}
.content_Box {
border-left: 1px solid #ccc;
margin-left: 40px;
padding-left: 10px;
font-size: 12px;
margin-top: 20px;
& > p {
margin: 10px;
}
}
.link_btn {
cursor: pointer;
color: #007aff;
&:hover {
color: rgba($color: #007aff, $alpha: 0.8);
}
}
.subTitle {
background: var(--color-neutral-2);
padding: 1px 5px;
margin: 0px 5px;
border-radius: 3px;
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<Card style="height: 100%">
<template #header> 登录会话设置 </template>
<template #body>
<div class="content_title">
<div class="icon"><GiSvgIcon name="loginStatus" :size="36" /></div>
<div>
<div style="font-size: 14px; font-weight: 500; line-height: 28px">登录态保持时间设置</div>
<div style="font-size: 12px">保持登录状态的限制</div>
</div>
</div>
<div class="content_Box">
<p>操作登录会话保持120分钟超时登录会话将失效</p>
<p>登录会话最大保持0天超时登录会话将失效</p>
<p class="link_btn">修改规则(未开发)</p>
</div>
</template>
</Card>
</template>
<script setup lang="ts">
import Card from '../components/Card.vue'
</script>
<style scoped lang="scss">
.content_title {
display: flex;
align-items: center;
.icon {
margin-right: 10px;
}
}
.content_Box {
border-left: 1px solid #ccc;
margin-left: 40px;
padding-left: 10px;
font-size: 12px;
margin-top: 20px;
& > p {
margin: 10px;
}
}
.link_btn {
cursor: pointer;
color: #007aff;
&:hover {
color: rgba($color: #007aff, $alpha: 0.8);
}
}
</style>

View File

@@ -1,10 +1,30 @@
<template>
<div class="page"></div>
<div class="page">
<div class="flex_box">
<div class="flex_item_container">
<BasicsSetting />
</div>
<div class="flex_item_container">
<SessionSetting />
</div>
</div>
<div class="flex_box">
<div class="flex_item_container">
<PasswordPolicy />
</div>
<div class="flex_item_container">
<AccountProtection />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Message } from '@arco-design/web-vue'
import BasicsSetting from './BasicsSetting.vue'
import SessionSetting from './SessionSetting.vue'
import PasswordPolicy from './PasswordPolicy.vue'
import AccountProtection from './AccountProtection.vue'
defineOptions({ name: 'Security' })
const route = useRoute()
@@ -15,5 +35,17 @@ const form = reactive({ name: '' })
.page {
padding: $padding;
background-color: var(--color-bg-1);
.flex_box {
display: flex;
margin-bottom: 20px;
height: 100%;
.flex_item_container {
width: 100%;
height: 100%;
}
& .flex_item_container:first-child {
margin-right: 20px;
}
}
}
</style>