mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-22 13:05:18 +00:00
fix: 调整前端组件样式和修复后端调度器问题
修复操作列按钮宽度计算问题,调整日志详情页标签宽度 优化任务状态选项标签,从"暂停"改为"停用" 移除后端调度器无用导入,添加job_id到日志记录 添加job_id查询参数到任务日志接口 优化前端应用列表页搜索表单和分页样式 修复Pydantic错误消息处理,去除冗余前缀 添加应用模型的前置处理和验证逻辑
This commit is contained in:
@@ -82,7 +82,7 @@ const getOperationMaxWidth = () => {
|
||||
const buttons = item.querySelectorAll(".el-button");
|
||||
// 获取每行按钮的总宽度
|
||||
totalWidth = Array.from(buttons).reduce((acc, button: any) => {
|
||||
return acc + button.scrollWidth + 22; // 每个按钮的宽度加上预留宽度
|
||||
return acc + button.scrollWidth + 14; // 每个按钮的宽度加上预留宽度
|
||||
}, 0);
|
||||
|
||||
// 获取最大的宽度
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
<el-dialog v-model="dialogVisible.visible" :title="dialogVisible.title" @close="handleCloseDialog">
|
||||
<!-- 详情 -->
|
||||
<template v-if="dialogVisible.type === 'detail'">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions :column="2" border label-width="120px">
|
||||
<el-descriptions-item label="日志ID" :span="2">{{ detailFormData.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称" :span="2">{{ detailFormData.job_name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务组名" :span="2">{{ detailFormData.job_group }}</el-descriptions-item>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
style="width: 167.5px"
|
||||
>
|
||||
<el-option value="true" label="启用" />
|
||||
<el-option value="false" label="暂停" />
|
||||
<el-option value="false" label="停用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 时间范围,收起状态下隐藏 -->
|
||||
@@ -521,7 +521,7 @@
|
||||
max-height="500px"
|
||||
@change="handlechangeCron"
|
||||
@close="openCron = false"
|
||||
></vue3CronPlus>
|
||||
/>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<!-- 开始日期和结束日期 -->
|
||||
|
||||
@@ -2,29 +2,47 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 顶部搜索和操作区域 -->
|
||||
<div class="search-container mb-4">
|
||||
<div class="search-container">
|
||||
<el-form ref="queryFormRef" :model="queryFormData" :inline="true" label-suffix=":">
|
||||
<el-form-item prop="name" label="应用名称">
|
||||
<el-input v-model="queryFormData.name" placeholder="请输入应用名称" clearable style="width: 200px" />
|
||||
<el-input v-model="queryFormData.name" placeholder="请输入应用名称" clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="状态">
|
||||
<el-select v-model="queryFormData.status" placeholder="请选择状态" clearable style="width: 120px">
|
||||
<el-select v-model="queryFormData.status" placeholder="请选择状态" clearable style="width: 170px;">
|
||||
<el-option label="启用" :value="true" />
|
||||
<el-option label="停用" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="creator" label="创建人">
|
||||
<el-input v-model="queryFormData.creator" placeholder="请输入创建人" clearable style="width: 150px" />
|
||||
<el-form-item v-if="isExpand" prop="creator" label="创建人">
|
||||
<UserTableSelect
|
||||
v-model="queryFormData.creator"
|
||||
@confirm-click="handleConfirm"
|
||||
@clear-click="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="search-buttons">
|
||||
<el-button v-hasPerm="['application:myapp:query']" type="primary" icon="search" @click="handleQuery">查询</el-button>
|
||||
<el-button v-hasPerm="['application:myapp:query']" icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||
<!-- 展开/收起 -->
|
||||
<template v-if="isExpandable">
|
||||
<el-link class="ml-3" type="primary" underline="never" @click="isExpand = !isExpand">
|
||||
{{ isExpand ? "收起" : "展开" }}
|
||||
<el-icon>
|
||||
<template v-if="isExpand">
|
||||
<ArrowUp />
|
||||
</template>
|
||||
<template v-else>
|
||||
<ArrowDown />
|
||||
</template>
|
||||
</el-icon>
|
||||
</el-link>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 应用卡片展示区域 -->
|
||||
<el-card shadow="hover" class="app-grid-card">
|
||||
<el-card shadow="hover" class="app-grid-card" >
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>应用市场</span>
|
||||
@@ -35,7 +53,7 @@
|
||||
</template>
|
||||
|
||||
<!-- 应用网格 -->
|
||||
<div v-loading="loading" class="app-grid">
|
||||
<div v-loading="loading" class="app-grid" >
|
||||
<el-card
|
||||
v-for="app in applicationList"
|
||||
:key="app.id"
|
||||
@@ -136,17 +154,14 @@
|
||||
|
||||
<!-- 分页区域 -->
|
||||
<template #footer>
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="queryFormData.page_no"
|
||||
v-model:page-size="queryFormData.page_size"
|
||||
:total="total"
|
||||
:page-sizes="[12, 24, 48]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
<!-- 使用卡片 footer 样式右对齐,无需额外容器 -->
|
||||
<pagination
|
||||
v-model:total="total"
|
||||
v-model:page="queryFormData.page_no"
|
||||
v-model:limit="queryFormData.page_size"
|
||||
:page-sizes="[12, 24, 48]"
|
||||
@pagination="loadApplicationList"
|
||||
/>
|
||||
</template>
|
||||
</el-card>
|
||||
|
||||
@@ -232,6 +247,8 @@ const total = ref(0);
|
||||
const dialogVisible = ref(false);
|
||||
const dialogType = ref<'create' | 'edit'>('create');
|
||||
const currentApp = ref<ApplicationInfo | null>(null);
|
||||
const isExpand = ref(false);
|
||||
const isExpandable = ref(true);
|
||||
|
||||
// 分页查询参数
|
||||
const queryFormData = reactive<ApplicationPageQuery>({
|
||||
@@ -256,7 +273,9 @@ const formData = reactive<ApplicationForm>({
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: "请输入应用名称", trigger: "blur" }],
|
||||
name: [
|
||||
{ required: true, message: "请输入应用名称", trigger: "blur" },
|
||||
{ min: 2, max: 30, message: "长度在 2 到 30 个字符", trigger: "blur" }],
|
||||
access_url: [
|
||||
{ required: true, message: "请输入访问地址", trigger: "blur" },
|
||||
{ type: 'url' as const, message: "请输入正确的URL格式", trigger: "blur" }
|
||||
@@ -298,6 +317,11 @@ async function handleQuery() {
|
||||
await loadApplicationList();
|
||||
}
|
||||
|
||||
// 选择创建人后触发查询
|
||||
function handleConfirm() {
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
async function handleResetQuery() {
|
||||
queryFormRef.value?.resetFields();
|
||||
@@ -305,19 +329,6 @@ async function handleResetQuery() {
|
||||
await loadApplicationList();
|
||||
}
|
||||
|
||||
// 分页大小改变
|
||||
async function handleSizeChange(size: number) {
|
||||
queryFormData.page_size = size;
|
||||
queryFormData.page_no = 1;
|
||||
await loadApplicationList();
|
||||
}
|
||||
|
||||
// 当前页改变
|
||||
async function handleCurrentChange(page: number) {
|
||||
queryFormData.page_no = page;
|
||||
await loadApplicationList();
|
||||
}
|
||||
|
||||
// 创建应用
|
||||
function handleCreateApp() {
|
||||
console.log('handleCreateApp');
|
||||
@@ -465,19 +476,6 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: var(--el-bg-color-page);
|
||||
min-height: calc(100vh - 84px);
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background: var(--el-bg-color);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.app-grid-card {
|
||||
height: calc(100vh - 200px);
|
||||
position: relative;
|
||||
@@ -486,6 +484,8 @@ onMounted(() => {
|
||||
|
||||
:deep(.el-card__footer) {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,14 +493,11 @@ onMounted(() => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 16px;
|
||||
padding: 20px 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -508,13 +505,6 @@ onMounted(() => {
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
min-height: 180px;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.app-card-header-el {
|
||||
@@ -531,14 +521,6 @@ onMounted(() => {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.app-avatar-el {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.app-title-section {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.app-name-el {
|
||||
font-size: 16px;
|
||||
@@ -551,18 +533,7 @@ onMounted(() => {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.app-status-tag {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.app-menu-btn {
|
||||
padding: 4px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.app-card-content {
|
||||
margin: 12px 0;
|
||||
@@ -571,8 +542,6 @@ onMounted(() => {
|
||||
.app-description {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
|
||||
line-height: 1.5;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
@@ -625,7 +594,6 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.app-card-actions {
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
<el-dialog v-model="dialogVisible.visible" :title="dialogVisible.title" @close="handleCloseDialog">
|
||||
<!-- 详情 -->
|
||||
<template v-if="dialogVisible.type === 'detail'">
|
||||
<el-descriptions :column="8" border label-width="140px">
|
||||
<el-descriptions :column="8" border label-width="200px">
|
||||
<el-descriptions-item label="日志类型" :span="2">
|
||||
<el-tag :type="formData.type === 1 ? 'success' : 'primary'">
|
||||
{{ formData.type === 1 ? '登录日志' : '操作日志' }}
|
||||
|
||||
Reference in New Issue
Block a user