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

328
app/pages/admin/members.vue Normal file
View File

@@ -0,0 +1,328 @@
<template>
<div class="members-page">
<a-card :bordered="false">
<template #title>成员管理</template>
<!-- Tab 切换 -->
<a-tabs v-model:activeKey="activeTab">
<a-tab-pane key="users" tab="用户列表">
<!-- 筛选栏 -->
<div class="filter-bar">
<a-input-search
v-model:value="searchKeyword"
placeholder="搜索用户名、邮箱、手机号..."
style="width: 300px"
allow-clear
@search="handleSearch"
/>
<a-select v-model:value="filterRole" placeholder="角色筛选" style="width: 140px" allow-clear>
<a-select-option value="super_admin">超级管理员</a-select-option>
<a-select-option value="admin">企业管理员</a-select-option>
<a-select-option value="member">普通成员</a-select-option>
<a-select-option value="developer">开发者</a-select-option>
</a-select>
<a-select v-model:value="filterStatus" placeholder="状态筛选" style="width: 140px" allow-clear>
<a-select-option value="active">正常</a-select-option>
<a-select-option value="disabled">已禁用</a-select-option>
</a-select>
<a-button @click="resetFilter">重置</a-button>
</div>
<a-table
:columns="userColumns"
:data-source="userData"
:pagination="pagination"
row-key="id"
:scroll="{ x: 1100 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'user'">
<div class="user-cell">
<a-avatar :src="record.avatar" :size="36">
{{ record.name[0] }}
</a-avatar>
<div>
<p class="name-text">{{ record.name }}</p>
<p class="sub-text">{{ record.email }}</p>
</div>
</div>
</template>
<template v-else-if="column.key === 'role'">
<a-tag :color="roleColor[record.role]">{{ roleMap[record.role] }}</a-tag>
</template>
<template v-else-if="column.key === 'enterprise'">
{{ record.enterprise || '-' }}
</template>
<template v-else-if="column.key === 'status'">
<a-badge :status="record.status === 'active' ? 'success' : 'error'" :text="record.status === 'active' ? '正常' : '已禁用'" />
</template>
<template v-else-if="column.key === 'actions'">
<a-space>
<a-button type="link" size="small" @click="handleViewUser(record)">详情</a-button>
<a-button type="link" size="small" @click="handleEditUser(record)">编辑</a-button>
<a-dropdown>
<a-button type="link" size="small">更多</a-button>
<template #overlay>
<a-menu>
<a-menu-item key="role">调整角色</a-menu-item>
<a-menu-item key="disable">{{ record.status === 'active' ? '禁用账户' : '启用账户' }}</a-menu-item>
<a-menu-divider />
<a-menu-item key="delete" style="color: #ff4d4f">删除</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space>
</template>
</template>
</a-table>
</a-tab-pane>
<a-tab-pane key="roles" tab="角色权限">
<div class="roles-section">
<div class="roles-header">
<a-button type="primary" @click="roleModalVisible = true">
<template #icon><PlusOutlined /></template>
新增角色
</a-button>
</div>
<a-row :gutter="[16, 16]">
<a-col :xs="24" :md="12" :xl="8" v-for="role in roles" :key="role.key">
<a-card class="role-card" :bordered="false">
<div class="role-card-header">
<a-tag :color="role.color">{{ role.count }} </a-tag>
<span class="role-name">{{ role.label }}</span>
</div>
<p class="role-desc">{{ role.desc }}</p>
<div class="role-permissions">
<a-tag v-for="p in role.permissions" :key="p" size="small">{{ p }}</a-tag>
</div>
<div class="role-actions">
<a-button type="link" size="small" @click="handleEditRole(role)">编辑</a-button>
<a-button type="link" size="small" danger>删除</a-button>
</div>
</a-card>
</a-col>
</a-row>
</div>
</a-tab-pane>
</a-tabs>
</a-card>
<!-- 用户编辑弹窗 -->
<a-modal
v-model:open="userModalVisible"
title="编辑用户"
width="540px"
@ok="saveUser"
@cancel="userModalVisible = false"
>
<a-form :model="userForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
<a-form-item label="用户名">
<a-input v-model:value="userForm.name" />
</a-form-item>
<a-form-item label="手机号">
<a-input v-model:value="userForm.phone" />
</a-form-item>
<a-form-item label="邮箱">
<a-input v-model:value="userForm.email" />
</a-form-item>
<a-form-item label="角色">
<a-select v-model:value="userForm.role">
<a-select-option value="super_admin">超级管理员</a-select-option>
<a-select-option value="admin">企业管理员</a-select-option>
<a-select-option value="member">普通成员</a-select-option>
<a-select-option value="developer">开发者</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="状态">
<a-select v-model:value="userForm.status">
<a-select-option value="active">正常</a-select-option>
<a-select-option value="disabled">已禁用</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-modal>
<!-- 角色编辑弹窗 -->
<a-modal
v-model:open="roleModalVisible"
title="新增角色"
width="540px"
@ok="saveRole"
@cancel="roleModalVisible = false"
>
<a-form :model="roleForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
<a-form-item label="角色名称" :rules="[{ required: true, message: '请输入角色名称' }]">
<a-input v-model:value="roleForm.label" placeholder="如:财务管理员" />
</a-form-item>
<a-form-item label="角色描述">
<a-textarea v-model:value="roleForm.desc" :rows="2" />
</a-form-item>
<a-form-item label="权限配置">
<a-checkbox-group v-model:value="roleForm.permissions">
<a-row>
<a-col :span="12" v-for="perm in allPermissions" :key="perm.key">
<a-checkbox :value="perm.key">{{ perm.label }}</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
definePageMeta({ layout: 'admin' })
const activeTab = ref('users')
const searchKeyword = ref('')
const filterRole = ref<string | undefined>()
const filterStatus = ref<string | undefined>()
const userModalVisible = ref(false)
const roleModalVisible = ref(false)
const userForm = reactive({ id: null as number | null, name: '', phone: '', email: '', role: 'member', status: 'active' })
const roleForm = reactive({ label: '', desc: '', permissions: [] as string[] })
const roleMap: Record<string, string> = {
super_admin: '超级管理员',
admin: '企业管理员',
member: '普通成员',
developer: '开发者',
}
const roleColor: Record<string, string> = {
super_admin: 'red',
admin: 'purple',
member: 'blue',
developer: 'green',
}
const userColumns = [
{ title: '用户', key: 'user', width: 240 },
{ title: '手机号', dataIndex: 'phone', key: 'phone', width: 130 },
{ title: '角色', key: 'role', width: 110 },
{ title: '所属企业', key: 'enterprise', width: 160 },
{ title: '注册时间', dataIndex: 'createdAt', key: 'createdAt', width: 120 },
{ title: '最后登录', dataIndex: 'lastLogin', key: 'lastLogin', width: 140 },
{ title: '状态', key: 'status', width: 90 },
{ title: '操作', key: 'actions', width: 180, fixed: 'right' },
]
const userData = ref([
{ id: 1, name: '李明', email: 'liming@example.com', phone: '138****8001', role: 'super_admin', enterprise: '平台', status: 'active', createdAt: '2025-01-01', lastLogin: '2026-04-08 10:23' },
{ id: 2, name: '王芳', email: 'wangfang@example.com', phone: '138****8002', role: 'admin', enterprise: '腾云科技', status: 'active', createdAt: '2025-03-15', lastLogin: '2026-04-08 09:15' },
{ id: 3, name: '张伟', email: 'zhangwei@example.com', phone: '138****8003', role: 'member', enterprise: '腾云科技', status: 'active', createdAt: '2025-06-20', lastLogin: '2026-04-07 18:30' },
{ id: 4, name: '陈静', email: 'chenjing@example.com', phone: '138****8004', role: 'developer', enterprise: '华创数据', status: 'active', createdAt: '2025-09-10', lastLogin: '2026-04-08 11:00' },
{ id: 5, name: '刘强', email: 'liuqiang@example.com', phone: '138****8005', role: 'member', enterprise: '华创数据', status: 'disabled', createdAt: '2025-11-05', lastLogin: '2026-03-01 14:00' },
])
const pagination = reactive({ current: 1, pageSize: 10, total: 5 })
const roles = [
{ key: 'super_admin', label: '超级管理员', desc: '平台最高权限,可管理所有模块', count: 1, color: 'red', permissions: ['全部权限'] },
{ key: 'admin', label: '企业管理员', desc: '管理本企业内的用户、配置、账单', count: 12, color: 'purple', permissions: ['用户管理', '账单查看', '应用管理'] },
{ key: 'member', label: '普通成员', desc: '使用平台基础功能,无管理权限', count: 845, color: 'blue', permissions: ['功能使用'] },
{ key: 'developer', label: '开发者', desc: '拥有开发者权限,可创建和管理应用', count: 342, color: 'green', permissions: ['API调用', '插件开发', '模板发布'] },
]
const allPermissions = [
{ key: 'user_manage', label: '用户管理' },
{ key: 'app_manage', label: '应用管理' },
{ key: 'finance_view', label: '账单查看' },
{ key: 'finance_pay', label: '充值缴费' },
{ key: 'developer_api', label: 'API 调用' },
{ key: 'developer_plugin', label: '插件开发' },
{ key: 'setting_base', label: '基础配置' },
{ key: 'setting_advance', label: '高级配置' },
]
const handleSearch = () => message.info('搜索:' + searchKeyword.value)
const resetFilter = () => { searchKeyword.value = ''; filterRole.value = undefined; filterStatus.value = undefined }
const handleViewUser = (u: any) => message.info('查看用户:' + u.name)
const handleEditUser = (u: any) => { Object.assign(userForm, u); userModalVisible.value = true }
const handleEditRole = (r: any) => { Object.assign(roleForm, r); roleModalVisible.value = true }
const saveUser = () => { userModalVisible.value = false; message.success('保存成功') }
const saveRole = () => { roleModalVisible.value = false; message.success('保存成功') }
</script>
<style scoped>
.filter-bar {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
flex-wrap: wrap;
}
.user-cell {
display: flex;
align-items: center;
gap: 10px;
}
.name-text {
font-weight: 500;
color: #111827;
margin: 0;
}
.sub-text {
font-size: 12px;
color: #9ca3af;
margin: 0;
}
.roles-section {
padding-top: 4px;
}
.roles-header {
margin-bottom: 16px;
}
.role-card {
border-radius: 10px;
transition: box-shadow 0.2s;
}
.role-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.role-card-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.role-name {
font-weight: 600;
font-size: 15px;
color: #111827;
}
.role-desc {
font-size: 13px;
color: #6b7280;
margin: 0 0 10px;
}
.role-permissions {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-bottom: 10px;
}
.role-actions {
display: flex;
gap: 4px;
}
</style>