feat: migrate from Element Plus to Ant Design Vue and update Vite configuration for better dependency management

- Updated Vite configuration to manually chunk Ant Design Vue for improved dependency management.
- Added a comprehensive migration testing checklist for transitioning from Element Plus 2.13.0 to Ant Design Vue 4.x, covering various components and functionalities.
This commit is contained in:
2026-01-03 01:38:38 +08:00
parent 42a1046750
commit 827c9198ae
57 changed files with 5517 additions and 2982 deletions
+217 -116
View File
@@ -16,55 +16,148 @@
<p>您已成功注册账户信息如下</p>
</div>
<div class="info-table">
<div class="info-row">
<div class="info-label">用户名</div>
<div class="info-value">{{ user?.alias || '加载中...' }}</div>
</div>
<div class="info-row">
<div class="info-label">注册时间</div>
<div class="info-value">{{ formatDate(user?.created_at) }}</div>
</div>
<div class="info-row">
<div class="info-label">审批状态</div>
<div class="info-value">
<span class="status-tag warning">待审批</span>
</div>
</div>
</div>
<a-descriptions :column="1" bordered class="mb-6">
<a-descriptions-item label="用户名">
{{ user?.alias || '加载中...' }}
</a-descriptions-item>
<a-descriptions-item label="邮箱">
<template v-if="user?.email">
{{ user.email }}
</template>
<template v-else>
<a-tag color="warning">未设置</a-tag>
</template>
</a-descriptions-item>
<a-descriptions-item label="密码">
<template v-if="user?.has_password">
<a-tag color="success">已设置</a-tag>
</template>
<template v-else>
<a-tag color="warning">未设置</a-tag>
</template>
</a-descriptions-item>
<a-descriptions-item label="注册时间">
{{ formatDate(user?.created_at) }}
</a-descriptions-item>
<a-descriptions-item label="审批状态">
<a-tag color="warning">待审批</a-tag>
</a-descriptions-item>
</a-descriptions>
<div class="alert-box">
<div class="alert-title"> 审批说明</div>
<ul class="tips-list">
<li>管理员将在 <strong>24 小时内</strong> 审核您的注册申请</li>
<li>审核通过后您将可以使用所有功能</li>
<li>如超过 24 小时未审批账户将被自动删除</li>
<li>您可以随时刷新此页面查看最新状态</li>
</ul>
</div>
<a-alert
message="⚠️ 审批说明"
type="info"
:closable="false"
show-icon
class="mb-6"
>
<template #description>
<ul class="tips-list">
<li>管理员将在 <strong>24 小时内</strong> 审核您的注册申请</li>
<li>审核通过后您将可以使用所有功能</li>
<li>如超过 24 小时未审批账户将被自动删除</li>
<li><strong>建议</strong>审批期间可以设置邮箱和密码方便后续使用</li>
<li>您可以随时刷新此页面查看最新状态</li>
</ul>
</template>
</a-alert>
<div class="actions">
<button class="btn btn-primary" @click="checkStatus">
<a-button type="primary" size="large" @click="checkStatus">
<template #icon><ReloadOutlined /></template>
刷新状态
</button>
<button class="btn btn-default" @click="logout">
</a-button>
<a-button size="large" @click="showProfileModal = true">
<template #icon><SettingOutlined /></template>
完善信息
</a-button>
<a-button size="large" @click="logout">
<template #icon><LogoutOutlined /></template>
退出登录
</button>
</a-button>
</div>
</div>
</div>
<!-- 完善信息弹窗 -->
<a-modal
v-model:open="showProfileModal"
title="完善个人信息"
:confirm-loading="profileLoading"
@ok="handleUpdateProfile"
@cancel="resetProfileForm"
width="500px"
>
<a-form :model="profileForm" layout="vertical">
<a-form-item label="邮箱地址(可选)" name="email">
<a-input
v-model:value="profileForm.email"
placeholder="用于接收审批通知"
type="email"
/>
<div class="form-hint">建议设置邮箱方便接收审批结果通知</div>
</a-form-item>
<a-form-item
label="新密码(可选)"
name="new_password"
:help="user?.has_password ? '留空表示不修改密码' : '设置密码后可以使用密码登录'"
>
<a-input-password
v-model:value="profileForm.new_password"
placeholder="至少6位字符"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item
v-if="profileForm.new_password"
label="确认密码"
name="confirm_password"
>
<a-input-password
v-model:value="profileForm.confirm_password"
placeholder="再次输入新密码"
autocomplete="new-password"
/>
</a-form-item>
<a-form-item
v-if="user?.has_password && profileForm.new_password"
label="当前密码"
name="current_password"
>
<a-input-password
v-model:value="profileForm.current_password"
placeholder="修改密码时需要提供当前密码"
autocomplete="current-password"
/>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import { ReloadOutlined, LogoutOutlined, SettingOutlined } from '@ant-design/icons-vue'
import { userAPI } from '@/api'
import { useAuthStore } from '@/stores/auth'
const router = useRouter()
const authStore = useAuthStore()
const user = ref(null)
const showProfileModal = ref(false)
const profileLoading = ref(false)
const profileForm = ref({
email: '',
new_password: '',
confirm_password: '',
current_password: '',
})
const checkStatus = async () => {
try {
@@ -72,14 +165,99 @@ const checkStatus = async () => {
user.value = response
if (response.is_approved) {
alert('恭喜!您的账户已通过审批')
message.success('恭喜!您的账户已通过审批')
router.push('/dashboard')
} else {
alert('仍在等待审批中')
message.info('仍在等待审批中')
}
} catch (error) {
console.error('获取状态失败:', error)
alert('获取状态失败:' + (error.message || '未知错误'))
message.error('获取状态失败:' + (error.message || '未知错误'))
}
}
const loadUserInfo = async () => {
try {
const response = await userAPI.getCurrentUser()
user.value = response
// 初始化表单
profileForm.value.email = response.email || ''
} catch (error) {
console.error('加载用户信息失败:', error)
}
}
const handleUpdateProfile = async () => {
// 验证
if (profileForm.value.new_password && profileForm.value.new_password.length < 6) {
message.error('密码至少需要 6 位字符')
return
}
if (profileForm.value.new_password !== profileForm.value.confirm_password) {
message.error('两次输入的密码不一致')
return
}
if (user.value?.has_password && profileForm.value.new_password && !profileForm.value.current_password) {
message.error('修改密码时需要提供当前密码')
return
}
profileLoading.value = true
try {
const updateData = {}
// 只提交有变化的字段
if (profileForm.value.email !== (user.value?.email || '')) {
updateData.email = profileForm.value.email || null
}
if (profileForm.value.new_password) {
updateData.new_password = profileForm.value.new_password
if (user.value?.has_password) {
updateData.current_password = profileForm.value.current_password
}
}
// 如果没有要更新的字段
if (Object.keys(updateData).length === 0) {
message.info('没有需要更新的信息')
showProfileModal.value = false
return
}
await userAPI.updateProfile(updateData)
message.success('个人信息更新成功')
showProfileModal.value = false
resetProfileForm()
// 重新加载用户信息
await loadUserInfo()
// 如果设置了密码,更新本地存储的用户信息
if (updateData.new_password) {
const currentUser = authStore.user
if (currentUser) {
currentUser.has_password = true
localStorage.setItem('user', JSON.stringify(currentUser))
}
}
} catch (error) {
console.error('更新个人信息失败:', error)
message.error(error.message || '更新失败,请重试')
} finally {
profileLoading.value = false
}
}
const resetProfileForm = () => {
profileForm.value = {
email: user.value?.email || '',
new_password: '',
confirm_password: '',
current_password: '',
}
}
@@ -95,6 +273,7 @@ const formatDate = (dateStr) => {
}
onMounted(() => {
loadUserInfo()
checkStatus()
})
</script>
@@ -160,66 +339,10 @@ onMounted(() => {
margin-bottom: 30px;
}
.info-table {
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
overflow: hidden;
.mb-6 {
margin-bottom: 30px;
}
.info-row {
display: flex;
border-bottom: 1px solid #ddd;
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
flex: 0 0 120px;
padding: 15px 20px;
background: #f5f5f5;
font-weight: bold;
color: #303133;
border-right: 1px solid #ddd;
}
.info-value {
flex: 1;
padding: 15px 20px;
color: #606266;
}
.status-tag {
display: inline-block;
padding: 4px 12px;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
}
.status-tag.warning {
background: #fff3cd;
color: #856404;
border: 1px solid #ffc107;
}
.alert-box {
background: #e7f3ff;
border-left: 4px solid #409eff;
padding: 20px;
margin-bottom: 30px;
border-radius: 4px;
}
.alert-title {
font-weight: bold;
margin-bottom: 10px;
color: #303133;
}
.tips-list {
text-align: left;
padding-left: 20px;
@@ -236,34 +359,12 @@ onMounted(() => {
display: flex;
gap: 15px;
justify-content: center;
flex-wrap: wrap;
}
.btn {
padding: 12px 30px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
}
.btn-primary {
background: #409eff;
color: white;
}
.btn-primary:hover {
background: #66b1ff;
}
.btn-default {
background: #f5f5f5;
color: #606266;
border: 1px solid #dcdfe6;
}
.btn-default:hover {
background: #e8e8e8;
.form-hint {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
</style>