refactor(developer-config): 移除开发者配置页面相关代码和文档

- 删除应用配置页面及相关组件,重构路由为 /developer/config/[id].vue
- 移除开发者文档页面及其导航与样式实现
- 清理开发者侧功能完善工作日志文件
- 删除全局.gitignore配置文件,清理无用忽略规则
- 优化应用配置页面的参数读取和路由结构,解决刷新404问题
- 解决数据库配置唯一键冲突,调整保存逻辑避免重复插入
- 移除对后端配置加密字段的 secret 标记,修正加密异常问题
This commit is contained in:
2026-04-09 07:35:34 +08:00
parent 3209d92cc5
commit f9e1286ab1
130 changed files with 18656 additions and 22143 deletions

247
app/pages/admin/account.vue Normal file
View File

@@ -0,0 +1,247 @@
<script setup lang="ts">
definePageMeta({ layout: 'admin' })
const { user } = useUser()
// 个人信息数据
const profile = reactive({
username: 'admin',
nickname: '系统管理员',
email: 'admin@company.com',
phone: '138****8888',
department: '信息技术部',
position: '系统管理员',
joinDate: '2024-01-15',
lastLogin: '2026-04-09 07:00',
avatar: '',
})
// 安全设置
const securitySettings = reactive({
emailVerified: true,
phoneVerified: true,
twoFactorEnabled: false,
loginPwdChanged: '2026-03-15',
})
// 修改密码表单
const passwordForm = reactive({
oldPassword: '',
newPassword: '',
confirmPassword: '',
})
const passwordRules = {
newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' }],
confirmPassword: [
{ required: true, message: '请确认新密码', trigger: 'blur' },
{
validator: (_rule: any, value: string) => {
if (value !== passwordForm.newPassword) {
return Promise.reject('两次输入的密码不一致')
}
return Promise.resolve()
},
trigger: 'blur',
},
],
}
// 操作日志
const loginHistory = ref([
{ time: '2026-04-09 07:00:00', ip: '192.168.1.100', device: 'Chrome / Windows 11', location: '广东深圳', status: '成功' },
{ time: '2026-04-08 18:30:00', ip: '192.168.1.100', device: 'Chrome / macOS', location: '广东深圳', status: '成功' },
{ time: '2026-04-08 09:15:00', ip: '192.168.1.101', device: 'Safari / iOS', location: '广东广州', status: '成功' },
{ time: '2026-04-07 16:45:00', ip: '10.0.0.1', device: 'Firefox / Ubuntu', location: '广东深圳', status: '成功' },
{ time: '2026-04-07 08:00:00', ip: '192.168.1.100', device: 'Chrome / Windows 11', location: '广东深圳', status: '成功' },
])
const activeTab = ref('profile')
</script>
<template>
<div class="account-page">
<a-tabs v-model:activeKey="activeTab" class="account-tabs">
<!-- 基本信息 -->
<a-tab-pane key="profile" tab="基本信息">
<a-row :gutter="24">
<a-col :xs="24" :lg="16">
<a-card title="个人信息" class="info-card">
<a-descriptions :column="{ xs: 1, sm: 2 }" bordered>
<a-descriptions-item label="用户名">{{ profile.username }}</a-descriptions-item>
<a-descriptions-item label="昵称">{{ profile.nickname }}</a-descriptions-item>
<a-descriptions-item label="邮箱">
{{ profile.email }}
<a-tag v-if="securitySettings.emailVerified" color="success" size="small">已认证</a-tag>
</a-descriptions-item>
<a-descriptions-item label="手机号">
{{ profile.phone }}
<a-tag v-if="securitySettings.phoneVerified" color="success" size="small">已认证</a-tag>
</a-descriptions-item>
<a-descriptions-item label="部门">{{ profile.department }}</a-descriptions-item>
<a-descriptions-item label="职位">{{ profile.position }}</a-descriptions-item>
<a-descriptions-item label="入职日期">{{ profile.joinDate }}</a-descriptions-item>
<a-descriptions-item label="上次登录">{{ profile.lastLogin }}</a-descriptions-item>
</a-descriptions>
<div class="mt-4">
<a-button type="primary">编辑资料</a-button>
</div>
</a-card>
</a-col>
<a-col :xs="24" :lg="8">
<a-card title="头像设置" class="avatar-card">
<div class="avatar-upload">
<a-avatar :size="100" :src="profile.avatar">
<template #icon><UserOutlined /></template>
</a-avatar>
<div class="mt-4">
<a-button size="small">更换头像</a-button>
<p class="text-xs text-gray-400 mt-2">支持 JPGPNG 格式文件小于 2MB</p>
</div>
</div>
</a-card>
</a-col>
</a-row>
</a-tab-pane>
<!-- 账号安全 -->
<a-tab-pane key="security" tab="账号安全">
<a-row :gutter="24">
<a-col :xs="24" :lg="16">
<!-- 登录密码 -->
<a-card title="登录密码" class="security-card mb-4">
<div class="security-item">
<div class="security-info">
<div class="security-title">登录密码</div>
<div class="security-desc">上次修改于 {{ securitySettings.loginPwdChanged }}</div>
</div>
<a-button>修改密码</a-button>
</div>
</a-card>
<!-- 邮箱绑定 -->
<a-card title="邮箱绑定" class="security-card mb-4">
<div class="security-item">
<div class="security-info">
<div class="security-title">{{ profile.email }}</div>
<div class="security-desc">
<a-tag v-if="securitySettings.emailVerified" color="success" size="small">已验证</a-tag>
<span v-else class="text-orange-500">未验证</span>
</div>
</div>
<a-button type="primary" ghost>更换邮箱</a-button>
</div>
</a-card>
<!-- 手机绑定 -->
<a-card title="手机绑定" class="security-card mb-4">
<div class="security-item">
<div class="security-info">
<div class="security-title">{{ profile.phone }}</div>
<div class="security-desc">
<a-tag v-if="securitySettings.phoneVerified" color="success" size="small">已验证</a-tag>
</div>
</div>
<a-button type="primary" ghost>更换手机</a-button>
</div>
</a-card>
<!-- 两步验证 -->
<a-card title="两步验证" class="security-card">
<div class="security-item">
<div class="security-info">
<div class="security-title">开启两步验证</div>
<div class="security-desc">启用后登录需输入手机验证码提升账号安全</div>
</div>
<a-switch v-model:checked="securitySettings.twoFactorEnabled" />
</div>
</a-card>
</a-col>
</a-row>
</a-tab-pane>
<!-- 登录历史 -->
<a-tab-pane key="history" tab="登录历史">
<a-card title="最近登录记录">
<a-table :dataSource="loginHistory" :pagination="false" rowKey="time" size="small">
<a-table-column title="登录时间" dataIndex="time" width="180" />
<a-table-column title="IP 地址" dataIndex="ip" width="140" />
<a-table-column title="设备" dataIndex="device" />
<a-table-column title="位置" dataIndex="location" width="100" />
<a-table-column title="状态" dataIndex="status" width="80" align="center">
<template #default="{ text }">
<a-tag :color="text === '成功' ? 'success' : 'error'">{{ text }}</a-tag>
</template>
</a-table-column>
</a-table>
</a-card>
</a-tab-pane>
</a-tabs>
</div>
</template>
<style scoped>
.account-page {
max-width: 1200px;
}
.account-tabs :deep(.ant-tabs-nav) {
margin-bottom: 20px;
}
.info-card,
.security-card,
.avatar-card {
border-radius: 8px;
}
.avatar-upload {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
.security-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 0;
}
.security-info {
flex: 1;
}
.security-title {
font-size: 15px;
font-weight: 500;
color: #1f2937;
margin-bottom: 4px;
}
.security-desc {
font-size: 13px;
color: #6b7280;
}
.text-xs {
font-size: 12px;
}
.text-gray-400 {
color: #9ca3af;
}
.text-orange-500 {
color: #f97316;
}
.mt-4 {
margin-top: 16px;
}
.mb-4 {
margin-bottom: 16px;
}
</style>