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

View File

@@ -0,0 +1,301 @@
<template>
<div class="enterprises-page">
<a-card :bordered="false">
<template #title>
<div class="card-title">
<span>企业管理</span>
<a-button type="primary" @click="handleAdd">
<template #icon><PlusOutlined /></template>
新增企业
</a-button>
</div>
</template>
<!-- 筛选栏 -->
<div class="filter-bar">
<a-input-search
v-model:value="searchKeyword"
placeholder="搜索企业名称、联系人..."
style="width: 280px"
allow-clear
@search="handleSearch"
/>
<a-select
v-model:value="filterStatus"
placeholder="状态筛选"
style="width: 140px"
allow-clear
>
<a-select-option value="active">已认证</a-select-option>
<a-select-option value="pending">待审核</a-select-option>
<a-select-option value="suspended">已停用</a-select-option>
</a-select>
<a-range-picker
v-model:value="dateRange"
style="width: 260px"
/>
<a-button @click="resetFilter">重置</a-button>
</div>
<!-- 数据表格 -->
<a-table
:columns="columns"
:data-source="tableData"
:pagination="pagination"
:loading="loading"
row-key="id"
@change="handleTableChange"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<div class="enterprise-cell">
<a-avatar
style="background: linear-gradient(135deg, #667eea, #764ba2); flex-shrink: 0"
:size="36"
>
{{ record.name[0] }}
</a-avatar>
<div>
<p class="name-text">{{ record.name }}</p>
<p class="sub-text">ID: {{ record.id }}</p>
</div>
</div>
</template>
<template v-else-if="column.key === 'status'">
<a-badge
:status="record.status === 'active' ? 'success' : record.status === 'pending' ? 'warning' : 'error'"
:text="statusMap[record.status]"
/>
</template>
<template v-else-if="column.key === 'plan'">
<a-tag :color="planColor[record.plan]">{{ planMap[record.plan] }}</a-tag>
</template>
<template v-else-if="column.key === 'actions'">
<a-space>
<a-button type="link" size="small" @click="handleView(record)">详情</a-button>
<a-button type="link" size="small" @click="handleEdit(record)">编辑</a-button>
<a-dropdown>
<a-button type="link" size="small">更多</a-button>
<template #overlay>
<a-menu>
<a-menu-item key="suspend" @click="handleSuspend(record)">
{{ record.status === 'suspended' ? '启用' : '停用' }}
</a-menu-item>
<a-menu-item key="reset">重置密码</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-card>
<!-- 新增/编辑弹窗 -->
<a-modal
v-model:open="modalVisible"
:title="editingId ? '编辑企业' : '新增企业'"
width="640px"
:confirm-loading="submitting"
@ok="handleSubmit"
@cancel="modalVisible = false"
>
<a-form
ref="formRef"
:model="formState"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 16 }"
>
<a-form-item label="企业名称" name="name" :rules="[{ required: true, message: '请输入企业名称' }]">
<a-input v-model:value="formState.name" placeholder="请输入企业名称" />
</a-form-item>
<a-form-item label="联系人" name="contact" :rules="[{ required: true, message: '请输入联系人' }]">
<a-input v-model:value="formState.contact" placeholder="请输入联系人姓名" />
</a-form-item>
<a-form-item label="联系电话" name="phone">
<a-input v-model:value="formState.phone" placeholder="请输入联系电话" />
</a-form-item>
<a-form-item label="企业邮箱" name="email">
<a-input v-model:value="formState.email" placeholder="请输入企业邮箱" />
</a-form-item>
<a-form-item label="套餐等级" name="plan">
<a-select v-model:value="formState.plan">
<a-select-option value="basic">基础版</a-select-option>
<a-select-option value="standard">标准版</a-select-option>
<a-select-option value="enterprise">企业版</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="状态" name="status">
<a-select v-model:value="formState.status">
<a-select-option value="active">已认证</a-select-option>
<a-select-option value="pending">待审核</a-select-option>
<a-select-option value="suspended">已停用</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="备注" name="remark">
<a-textarea v-model:value="formState.remark" :rows="3" placeholder="选填" />
</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'
import type { TableProps } from 'ant-design-vue'
definePageMeta({ layout: 'admin' })
const searchKeyword = ref('')
const filterStatus = ref<string | undefined>()
const dateRange = ref<[any, any] | null>(null)
const loading = ref(false)
const modalVisible = ref(false)
const editingId = ref<number | null>(null)
const submitting = ref(false)
const formRef = ref()
const formState = reactive({
name: '',
contact: '',
phone: '',
email: '',
plan: 'basic',
status: 'pending',
remark: '',
})
const statusMap: Record<string, string> = {
active: '已认证',
pending: '待审核',
suspended: '已停用',
}
const planMap: Record<string, string> = {
basic: '基础版',
standard: '标准版',
enterprise: '企业版',
}
const planColor: Record<string, string> = {
basic: 'default',
standard: 'blue',
enterprise: 'purple',
}
const columns = [
{ title: '企业信息', key: 'name', width: 260 },
{ title: '联系人', dataIndex: 'contact', key: 'contact', width: 120 },
{ title: '联系电话', dataIndex: 'phone', key: 'phone', width: 140 },
{ title: '套餐', key: 'plan', width: 100 },
{ title: '状态', key: 'status', width: 100 },
{ title: '注册时间', dataIndex: 'createdAt', key: 'createdAt', width: 120 },
{ title: '操作', key: 'actions', width: 200, fixed: 'right' },
]
const tableData = ref([
{ id: 1001, name: '深圳市腾云科技有限公司', contact: '李明', phone: '13800138001', plan: 'enterprise', status: 'pending', createdAt: '2026-04-08' },
{ id: 1002, name: '杭州智联网络技术有限公司', contact: '王芳', phone: '13800138002', plan: 'standard', status: 'active', createdAt: '2026-04-07' },
{ id: 1003, name: '北京华创数据服务有限公司', contact: '张伟', phone: '13800138003', plan: 'enterprise', status: 'active', createdAt: '2026-04-06' },
{ id: 1004, name: '广州云智科技有限公司', contact: '陈静', phone: '13800138004', plan: 'basic', status: 'pending', createdAt: '2026-04-05' },
{ id: 1005, name: '上海数智科技有限公司', contact: '刘强', phone: '13800138005', plan: 'standard', status: 'active', createdAt: '2026-04-04' },
{ id: 1006, name: '成都万物互联有限公司', contact: '赵丽', phone: '13800138006', plan: 'basic', status: 'suspended', createdAt: '2026-04-03' },
{ id: 1007, name: '武汉云帆科技有限公司', contact: '孙磊', phone: '13800138007', plan: 'standard', status: 'active', createdAt: '2026-04-02' },
])
const pagination = reactive({
current: 1,
pageSize: 10,
total: 7,
})
const handleSearch = () => {
message.info('搜索:' + searchKeyword.value)
}
const resetFilter = () => {
searchKeyword.value = ''
filterStatus.value = undefined
dateRange.value = null
}
const handleTableChange: TableProps['onChange'] = (pag) => {
pagination.current = pag.current || 1
pagination.pageSize = pag.pageSize || 10
}
const handleAdd = () => {
editingId.value = null
Object.assign(formState, { name: '', contact: '', phone: '', email: '', plan: 'basic', status: 'pending', remark: '' })
modalVisible.value = true
}
const handleEdit = (record: any) => {
editingId.value = record.id
Object.assign(formState, { ...record })
modalVisible.value = true
}
const handleView = (record: any) => {
message.info('查看企业详情:' + record.name)
}
const handleSuspend = (record: any) => {
const action = record.status === 'suspended' ? '启用' : '停用'
message.success(`${action}成功`)
}
const handleSubmit = async () => {
try {
await formRef.value.validate()
submitting.value = true
await new Promise((r) => setTimeout(r, 800))
message.success(editingId.value ? '编辑成功' : '新增成功')
modalVisible.value = false
submitting.value = false
} catch {
submitting.value = false
}
}
</script>
<style scoped>
.card-title {
display: flex;
align-items: center;
justify-content: space-between;
}
.filter-bar {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
flex-wrap: wrap;
}
.enterprise-cell {
display: flex;
align-items: center;
gap: 10px;
}
.name-text {
font-weight: 500;
color: #111827;
margin: 0;
line-height: 1.4;
}
.sub-text {
font-size: 12px;
color: #9ca3af;
margin: 0;
}
</style>