feat: 添加平台管理、计算模块适配器及前端页面更新

- 新增 platform API 端点和存储
- 新增 llama_factory 适配器
- 新增前端 compute、guide、system 等视图页面
- 新增 echarts 插件和 mock 数据
- 更新 Docker 配置、后端配置及文档
- 更新前端路由、API、侧边栏等组件

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
wuyongtao
2026-07-21 09:23:43 +08:00
parent 2c1e08a271
commit a67ca2c19c
43 changed files with 3632 additions and 814 deletions

View File

@@ -0,0 +1,12 @@
<template>
<section class="simple-page">
<h1>无权访问</h1>
<p>当前账号没有访问该页面的权限请联系管理员调整角色或页面权限</p>
</section>
</template>
<style scoped>
.simple-page {
padding: 24px;
}
</style>

View File

@@ -0,0 +1,94 @@
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { createUser } from '@/api/modules/system'
import type { CreateUserPayload, PermissionCode } from '@/types'
const router = useRouter()
const submitting = ref(false)
const form = reactive<CreateUserPayload>({
username: '',
display_name: '',
password: 'platform123',
role: 'viewer',
status: 'active',
permissions: ['dashboard'],
})
const permissionOptions: PermissionCode[] = [
'dashboard',
'fine-tune',
'model-eval',
'model-inference',
'model-manage',
'dataset',
'data-process',
'data-convert',
'compute',
'hardware',
'logs',
'user-settings',
]
async function submit() {
submitting.value = true
try {
await createUser(form)
ElMessage.success('用户已创建')
router.push('/user-settings')
} finally {
submitting.value = false
}
}
</script>
<template>
<section class="user-create">
<h1>创建用户</h1>
<el-form :model="form" label-width="110px" class="user-form">
<el-form-item label="账号">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="显示名称">
<el-input v-model="form.display_name" />
</el-form-item>
<el-form-item label="初始密码">
<el-input v-model="form.password" type="password" show-password />
</el-form-item>
<el-form-item label="角色">
<el-select v-model="form.role">
<el-option label="管理员" value="admin" />
<el-option label="操作员" value="operator" />
<el-option label="观察员" value="viewer" />
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio value="active">启用</el-radio>
<el-radio value="disabled">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="页面权限">
<el-checkbox-group v-model="form.permissions">
<el-checkbox v-for="item in permissionOptions" :key="item" :value="item">{{ item }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item>
<el-button @click="router.back()">返回</el-button>
<el-button type="primary" :loading="submitting" @click="submit">保存</el-button>
</el-form-item>
</el-form>
</section>
</template>
<style scoped>
.user-create {
padding: 24px;
}
.user-form {
max-width: 760px;
}
</style>

View File

@@ -0,0 +1,12 @@
<template>
<section class="simple-page">
<h1>权限设置</h1>
<p>第一版已支持账号页面权限读取与保存精细化项目/模型/数据集权限将在后续版本补齐</p>
</section>
</template>
<style scoped>
.simple-page {
padding: 24px;
}
</style>

View File

@@ -0,0 +1,65 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { getUsers } from '@/api/modules/system'
import type { SystemUser } from '@/types'
const loading = ref(false)
const users = ref<SystemUser[]>([])
async function loadUsers() {
loading.value = true
try {
users.value = await getUsers()
} finally {
loading.value = false
}
}
onMounted(loadUsers)
</script>
<template>
<section class="user-settings" v-loading="loading">
<header class="page-header">
<div>
<h1>用户设置</h1>
<p>管理平台账号角色状态和页面权限</p>
</div>
<el-button type="primary" @click="$router.push('/user-settings/create')">创建用户</el-button>
</header>
<el-table :data="users">
<el-table-column prop="username" label="账号" min-width="140" />
<el-table-column prop="display_name" label="显示名称" min-width="160" />
<el-table-column prop="role" label="角色" width="120" />
<el-table-column prop="status" label="状态" width="120" />
<el-table-column label="权限数" width="120">
<template #default="{ row }">{{ row.permissions?.length || 0 }}</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" min-width="180" />
</el-table>
</section>
</template>
<style scoped>
.user-settings {
padding: 24px;
}
.page-header {
display: flex;
justify-content: space-between;
gap: 16px;
margin-bottom: 18px;
}
.page-header h1 {
margin: 0;
font-size: 24px;
}
.page-header p {
margin: 8px 0 0;
color: #64748b;
}
</style>