feat(app): 初始化项目配置和页面结构
- 添加 .dockerignore 和 .env.example 配置文件 - 添加 .gitignore 忽略规则配置 - 创建服务端代理API路由(_file、_modules、_server) - 集成 Ant Design Vue 组件库并配置SSR样式提取 - 定义API响应类型封装 - 创建基础布局组件(blank、console) - 实现应用中心页面和组件(AppsCenter) - 添加文章列表测试页面 - 配置控制台导航菜单结构 - 实现控制台头部组件 - 创建联系页面表单
This commit is contained in:
134
app/pages/console/account/security.vue
Normal file
134
app/pages/console/account/security.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<a-page-header title="账号安全" sub-title="密码、登录设备与安全设置">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button danger @click="logout">退出登录</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-page-header>
|
||||
|
||||
<a-row :gutter="[16, 16]">
|
||||
<a-col :xs="24" :lg="12">
|
||||
<a-card :bordered="false" class="card" title="修改密码">
|
||||
<a-form ref="formRef" layout="vertical" :model="form" :rules="rules">
|
||||
<a-form-item label="原密码" name="oldPassword">
|
||||
<a-input-password v-model:value="form.oldPassword" placeholder="请输入原密码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="新密码" name="password">
|
||||
<a-input-password v-model:value="form.password" placeholder="请输入新密码(至少 6 位)" />
|
||||
</a-form-item>
|
||||
<a-form-item label="确认新密码" name="password2">
|
||||
<a-input-password v-model:value="form.password2" placeholder="再次输入新密码" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<div class="mt-2 flex justify-end gap-2">
|
||||
<a-button @click="resetForm" :disabled="pending">重置</a-button>
|
||||
<a-button type="primary" :loading="pending" @click="submit">保存</a-button>
|
||||
</div>
|
||||
|
||||
<a-alert
|
||||
class="mt-4"
|
||||
show-icon
|
||||
type="info"
|
||||
message="修改密码后建议重新登录,以确保所有会话状态一致。"
|
||||
/>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :xs="24" :lg="12">
|
||||
<a-card :bordered="false" class="card" title="安全建议">
|
||||
<a-list size="small" bordered :data-source="tips">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>{{ item }}</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { message, type FormInstance } from 'ant-design-vue'
|
||||
import { updatePassword } from '@/api/layout'
|
||||
import { removeToken } from '@/utils/token-util'
|
||||
import { clearAuthz } from '@/utils/permission'
|
||||
|
||||
definePageMeta({ layout: 'console' })
|
||||
|
||||
const pending = ref(false)
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const form = reactive<{ oldPassword: string; password: string; password2: string }>({
|
||||
oldPassword: '',
|
||||
password: '',
|
||||
password2: ''
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
oldPassword: [{ required: true, type: 'string', message: '请输入原密码' }],
|
||||
password: [
|
||||
{ required: true, type: 'string', message: '请输入新密码' },
|
||||
{ min: 6, type: 'string', message: '新密码至少 6 位', trigger: 'blur' }
|
||||
],
|
||||
password2: [{ required: true, type: 'string', message: '请再次输入新密码' }]
|
||||
})
|
||||
|
||||
const tips = [
|
||||
'定期修改密码,避免与其他平台重复使用。',
|
||||
'优先使用更长的随机密码。',
|
||||
'不要将账号/密码分享给他人。',
|
||||
'如怀疑账号被盗用,请立即修改密码并退出登录。'
|
||||
]
|
||||
|
||||
function resetForm() {
|
||||
form.oldPassword = ''
|
||||
form.password = ''
|
||||
form.password2 = ''
|
||||
formRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
if (form.password !== form.password2) {
|
||||
message.error('两次输入的新密码不一致')
|
||||
return
|
||||
}
|
||||
|
||||
pending.value = true
|
||||
try {
|
||||
await updatePassword({ oldPassword: form.oldPassword, password: form.password })
|
||||
message.success('密码修改成功')
|
||||
resetForm()
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : '密码修改失败')
|
||||
} finally {
|
||||
pending.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
removeToken()
|
||||
try {
|
||||
localStorage.removeItem('TenantId')
|
||||
localStorage.removeItem('UserId')
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
clearAuthz()
|
||||
navigateTo('/login')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user