feat: 优化前端组件样式及功能

refactor: 重构定时任务表单布局
fix: 修复用户导入组件按钮顺序
style: 统一对话框按钮顺序
feat: 添加用户头像默认显示
refactor: 移除表格列筛选功能
feat: 添加vue3-cron-plus-picker类型定义
fix: 修正日志处理时间显示格式
style: 优化IntervalTab组件布局
This commit is contained in:
zhangtao
2025-07-26 11:51:04 +08:00
parent 1217a5a4eb
commit e7ebbf5479
28 changed files with 190 additions and 290 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ export interface LogTable {
response_code?: number;
request_payload?: string;
response_json?: string;
process_time?: number;
process_time?: string;
description?: string;
created_at?: string;
updated_at?: string;
+27 -39
View File
@@ -1,43 +1,31 @@
<template>
<div>
<el-row :gutter="16">
<el-col :span="4">
<el-form-item label="秒">
<el-select v-model:value="crontabValueObj.second" placeholder="秒">
<el-option v-for="second in seconds" :key="second" :value="second">{{ second }}</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="分">
<el-select v-model:value="crontabValueObj.min" placeholder="">
<el-option v-for="min in minutes" :key="min" :value="min">{{min}}</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="">
<el-select v-model:value="crontabValueObj.hour" placeholder="时">
<el-option v-for="hour in hours" :key="hour" :value="hour">{{hour}}</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="天">
<el-select v-model:value="crontabValueObj.day" placeholder="天">
<el-option v-for="day in days" :key="day" :value="day">{{day}}</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="周">
<el-select v-model:value="crontabValueObj.week" placeholder="周">
<el-option v-for="week in weeks" :key="week" :value="week">{{week}}</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
<el-form :model="crontabValueObj" ref="formRef" label-width="auto" label-suffix=":" :inline="true" class="flex">
<el-form-item label="秒" prop="second" style="width: 20%">
<el-select v-model:value="crontabValueObj.second" placeholder="秒">
<el-option v-for="second in seconds" :key="second" :value="second">{{ second }}</el-option>
</el-select>
</el-form-item>
<el-form-item label="分" prop="min" style="width: 20%">
<el-select v-model:value="crontabValueObj.min" placeholder="分">
<el-option v-for="min in minutes" :key="min" :value="min">{{min}}</el-option>
</el-select>
</el-form-item>
<el-form-item label="时" prop="hour" style="width: 20%">
<el-select v-model:value="crontabValueObj.hour" placeholder="时">
<el-option v-for="hour in hours" :key="hour" :value="hour">{{hour}}</el-option>
</el-select>
</el-form-item>
<el-form-item label="天" prop="day" style="width: 20%">
<el-select v-model:value="crontabValueObj.day" placeholder="">
<el-option v-for="day in days" :key="day" :value="day">{{day}}</el-option>
</el-select>
</el-form-item>
<el-form-item label="周" prop="week" style="width: 20%">
<el-select v-model:value="crontabValueObj.week" placeholder="周">
<el-option v-for="week in weeks" :key="week" :value="week">{{week}}</el-option>
</el-select>
</el-form-item>
</el-form>
</template>
<script setup>
+1 -1
View File
@@ -18,6 +18,6 @@ export const enum ResultEnum {
/**
* 访问令牌无效或过期
*/
ACCESS_TOKEN_INVALID = 401,
ACCESS_TOKEN_INVALID = 403,
}
@@ -31,7 +31,12 @@
<div class="navbar-actions__item">
<el-dropdown trigger="click">
<div class="user-profile">
<img class="user-profile__avatar" :src="userStore.basicInfo.avatar" />
<template v-if="userStore.basicInfo.avatar">
<el-avatar :src="userStore.basicInfo.avatar" />
</template>
<template v-else>
<el-avatar icon="UserFilled" />
</template>
<span class="user-profile__name">{{ userStore.basicInfo.username }}</span>
</div>
<template #dropdown>
+3
View File
@@ -6,6 +6,7 @@ import { setupStore } from "@/store";
import { setupElIcons } from "./icons";
import { setupPermission } from "./permission";
import { InstallCodeMirror } from "codemirror-editor-vue3";
import ElementPlus from 'element-plus'
export default {
install(app: App<Element>) {
@@ -21,5 +22,7 @@ export default {
setupPermission();
// 注册 CodeMirror
app.use(InstallCodeMirror);
// 注册 ElementPlus
app.use(ElementPlus);
},
};
+3 -2
View File
@@ -26,8 +26,9 @@ export const defaultSettings: AppSettings = {
language: LanguageEnum.ZH_CN,
// 主题颜色 - 修改此值时需同步修改 src/styles/variables.scss
themeColor: "#4080FF",
// 是否显示水印
showWatermark: false,
// 是否显示水印 (修改默认开启水印)
// showWatermark: false,
showWatermark: true,
// 水印内容
watermarkContent: pkg.name,
// 侧边栏配色方案
+1
View File
@@ -85,6 +85,7 @@ declare module 'vue' {
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload']
ElWatermark: typeof import('element-plus/es')['ElWatermark']
Vue3CronPlusPicker: typeof import('vue3-cron-plus-picker')['default']
FileUpload: typeof import('./src/components/Upload/FileUpload.vue')['default']
Frame: typeof import('./src/components/Frame/index.vue')['default']
Fullscreen: typeof import('./src/components/Fullscreen/index.vue')['default']
+20
View File
@@ -0,0 +1,20 @@
declare module "vue3-cron-plus-picker" {
import { DefineComponent } from "vue";
export const Vue3CronPlusPicker: DefineComponent<{}, {}, any>;
export default Vue3CronPlusPicker;
}
declare module "vue3-cron-plus-picker/style.css" {
const content: any;
export default content;
}
declare module "vue3-cron-plus-picker/vue3-cron-plus-picker.js" {
import { DefineComponent } from "vue";
export const Vue3CronPlusPicker: DefineComponent<{}, {}, any>;
export default Vue3CronPlusPicker;
}
+8 -2
View File
@@ -12,9 +12,15 @@
<div class="user-info-header">
<div class="avatar-wrapper">
<el-avatar
v-if="infoFormState.avatar"
:src="infoFormState.avatar"
:size="120"
/>
<el-avatar
v-else
icon="UserFilled"
:size="120"
/>
<el-upload
class="el-upload"
@@ -115,7 +121,7 @@
<span>基本设置</span>
</template>
<div>
<el-form ref="ruleFormRef" :model="infoFormState" :rules="rules" :inline="true" label-suffix=":" label-width="auto" label-position="right">
<el-form ref="ruleFormRef" :model="infoFormState" :rules="rules" :inline="true" label-suffix=":">
<el-form-item label="姓名" name="name">
<el-input v-model:value="infoFormState.name" placeholder="请输入姓名" prefix-icon="User" clearable />
@@ -152,7 +158,7 @@
<span>安全设置</span>
</template>
<div>
<el-form ref="ruleFormRef" :model="passwordFormState" :rules="resetPasswordRules" label-suffix=":" label-width="auto" label-position="right">
<el-form ref="ruleFormRef" :model="passwordFormState" :rules="resetPasswordRules" label-suffix=":">
<el-form-item label="当前密码" name="oldPassword">
<el-input v-model.trim="passwordFormState.oldPassword" :placeholder="t('login.password')" type="password" show-password clearable>
<template #prefix>
+39 -60
View File
@@ -1,4 +1,4 @@
<!-- 公告通知配置 -->
<!-- 定时任务 -->
<template>
<div class="app-container">
<!-- 搜索区域 -->
@@ -232,7 +232,6 @@
<el-dialog
v-model="dialogVisible.visible"
:title="dialogVisible.title"
top="3vh"
@close="handleCloseDialog"
>
<!-- 详情 -->
@@ -303,81 +302,55 @@
</template>
<!-- 新增编辑表单 -->
<template v-else>
<el-form
ref="dataFormRef"
:model="formData"
:rules="rules"
label-suffix=":"
label-width="100px"
>
<el-form-item label="任务名称" prop="name">
<el-input
v-model="formData.name"
placeholder="请输入任务名称"
:maxlength="50"
/>
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-suffix=":" label-width="auto" inline>
<el-form-item label="任务名称" prop="name" style="width: 40%">
<el-input v-model="formData.name" placeholder="请输入任务名称" :maxlength="50"/>
</el-form-item>
<el-form-item label="任务函数" prop="func">
<el-input
v-model="formData.func"
placeholder="请输入任务函数"
:maxlength="50"
/>
<el-form-item label="任务函数" prop="func" style="width: 40%">
<el-input v-model="formData.func" placeholder="请输入任务函数" :maxlength="50"/>
</el-form-item>
<el-form-item label="存储器" prop="jobstore">
<el-select v-model="formData.jobstore" placeholder="请选择存储器">
<el-form-item label="存储器" prop="jobstore" style="width: 40%">
<el-select v-model="formData.jobstore" placeholder="请选择存储器" >
<el-option value="default" label="默认(Memory)" />
<el-option value="sqlalchemy" label="数据库" />
<el-option value="redis" label="Redis存储器" />
</el-select>
</el-form-item>
<el-form-item label="执行器" prop="executor">
<el-form-item label="执行器" prop="executor" style="width: 40%">
<el-select v-model="formData.executor" placeholder="请选择执行器">
<el-option value="default" label="默认" />
<el-option value="processpool" label="进程池" />
</el-select>
</el-form-item>
<el-form-item label="位置参数" prop="args">
<el-input
v-model="formData.args"
placeholder="请输入位置参数"
:maxlength="50"
/>
<el-form-item label="位置参数" prop="args" style="width: 40%">
<el-input v-model="formData.args" placeholder="请输入位置参数" :maxlength="50"/>
</el-form-item>
<el-form-item label="关键字参数" prop="kwargs">
<el-input
v-model="formData.kwargs"
placeholder="请输入关键字参数"
:maxlength="50"
/>
<el-form-item label="关键字参数" prop="kwargs" style="width: 40%">
<el-input v-model="formData.kwargs" placeholder="请输入关键字参数" :maxlength="50"/>
</el-form-item>
<el-form-item label="并发执行" prop="coalesce">
<el-form-item label="并发执行" prop="coalesce" style="width: 40%">
<el-radio-group v-model="formData.coalesce">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="最大实例数" prop="max_instances">
<el-input-number
v-model="formData.max_instances"
controls-position="right"
:min="1"
:max="10"
/>
<el-form-item label="最大实例数" prop="max_instances" style="width: 40%">
<el-input-number v-model="formData.max_instances" controls-position="right" :min="1" :max="10"/>
</el-form-item>
<el-form-item label="触发器" prop="trigger">
<el-form-item label="触发器" prop="trigger" style="width: 40%">
<el-select v-model="formData.trigger" placeholder="请选择触发器">
<el-option value="date" label="指定日期(date)" />
<el-option value="interval" label="间隔触发器(interval)" />
<el-option value="cron" label="cron表达式" />
</el-select>
</el-form-item>
<!-- 运行日期间隔时间或 Cron 表达式 -->
<el-form-item
v-if="formData.trigger === 'date'"
label="运行日期"
prop="trigger_args"
:rules="[{ required: true, message: '请选择运行日期' }]"
style="width: 40%"
>
<el-date-picker
v-model="formData.trigger_args"
@@ -385,13 +358,14 @@
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择运行日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item
v-else-if="formData.trigger === 'interval'"
label="间隔时间"
prop="trigger_args"
:rules="[{ required: true, message: '请输入间隔时间' }]"
style="width: 40%"
>
<el-input
v-model="formData.trigger_args"
@@ -403,7 +377,9 @@
<el-form-item
v-else-if="formData.trigger === 'cron'"
label="Cron表达式"
prop="trigger_args"
:rules="[{ required: true, message: '请输入Cron表达式' }]"
style="width: 40%"
>
<el-input
v-model="formData.trigger_args"
@@ -411,14 +387,15 @@
clearable
readonly
@click="handleShowCron"
>
</el-input>
/>
</el-form-item>
<!-- 开始日期和结束日期 -->
<el-form-item
v-if="formData.trigger && formData.trigger != 'date'"
label="开始日期"
prop="start_date"
:rules="[{ required: false, message: '请选择开始日期' }]"
style="width: 40%"
>
<el-date-picker
v-model="formData.start_date"
@@ -426,13 +403,14 @@
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开始日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item
v-if="formData.trigger && formData.trigger != 'date'"
label="结束日期"
prop="end_date"
:rules="[{ required: false, message: '请选择结束日期' }]"
style="width: 40%"
>
<el-date-picker
v-model="formData.end_date"
@@ -440,11 +418,10 @@
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择结束日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-form-item label="描述" prop="description" style="width: 85%">
<el-input
v-model="formData.description"
:rows="4"
@@ -460,6 +437,7 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button
v-if="dialogVisible.type !== 'detail'"
type="primary"
@@ -469,20 +447,21 @@
<el-button v-else type="primary" @click="handleCloseDialog"
>确定</el-button
>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
<!-- 时间间隔组件 -->
<el-dialog
v-model="openIntervalTab"
title="间隔时间设置"
:width="600"
:destroy-on-close="true"
@ok="handleIntervalConfirm"
>
<el-dialog v-model="openIntervalTab" title="间隔时间设置" :width="700" align-center draggable>
<IntervalTab ref="intervalTabRef" />
<template #footer>
<div class="dialog-footer">
<el-button @click="openIntervalTab = false">取消</el-button>
<el-button type="primary" @click="handleIntervalConfirm">
确认
</el-button>
</div>
</template>
</el-dialog>
<!-- core组件 -->
+1 -1
View File
@@ -170,9 +170,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
+1 -1
View File
@@ -163,9 +163,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
@@ -73,19 +73,7 @@
<el-button type="warning" icon="download" circle @click="handleExport" />
</el-tooltip>
<el-tooltip content="刷新">
<el-button type="primary" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
<el-tooltip content="列表筛选">
<el-dropdown trigger="click">
<el-button type="default" icon="operation" circle />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="column in tableColumns" :key="column.prop" :command="column">
<el-checkbox v-model="column.show">{{ column.label }}</el-checkbox>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="default" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
</div>
</div>
@@ -95,44 +83,44 @@
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column v-if="tableColumns.find(col => col.prop === 'selection')?.show" type="selection" min-width="55" align="center" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'index')?.show" type="index" fixed label="序号" min-width="60">
<el-table-column type="selection" min-width="55" align="center" />
<el-table-column type="index" fixed label="序号" min-width="60">
<template #default="scope">
{{ (queryFormData.page_no - 1) * queryFormData.page_size + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'dict_label')?.show" key="dict_label" label="标签" prop="dict_label" min-width="150" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'status')?.show" key="status" label="状态" prop="status" min-width="100" show-overflow-tooltip>
<el-table-column label="标签" prop="dict_label" min-width="150" show-overflow-tooltip />
<el-table-column label="状态" prop="status" min-width="100" show-overflow-tooltip>
<template #default="scope">
<el-tag :type="scope.row.status === true ? 'success' : 'danger'">
{{ scope.row.status ? "启用" : "停用" }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'dict_type')?.show" key="dict_type" label="类型" prop="dict_type" min-width="180" show-overflow-tooltip>
<el-table-column label="类型" prop="dict_type" min-width="180" show-overflow-tooltip>
<template #default="scope">
<el-tag type="primary">{{ scope.row.dict_type }}</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'dict_value')?.show" key="dict_value" label="值" prop="dict_value" min-width="100" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'css_class')?.show" key="css_class" label="样式属性" prop="css_class" min-width="100" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'list_class')?.show" key="list_class" label="列表类样式" prop="list_class" min-width="100" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'dict_sort')?.show" key="dict_sort" label="排序" prop="dict_sort" min-width="60" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'is_default')?.show" key="is_default" label="是否默认" prop="is_default" min-width="100">
<el-table-column label="值" prop="dict_value" min-width="100" show-overflow-tooltip />
<el-table-column label="样式属性" prop="css_class" min-width="100" show-overflow-tooltip />
<el-table-column label="列表类样式" prop="list_class" min-width="100" show-overflow-tooltip />
<el-table-column label="排序" prop="dict_sort" min-width="60" />
<el-table-column label="是否默认" prop="is_default" min-width="100">
<template #default="scope">
<el-tag v-if="scope.row.is_default" type="success"></el-tag>
<el-tag v-else type="danger"></el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'description')?.show" key="description" label="描述" prop="description" min-width="100" show-overflow-tooltip/>
<el-table-column v-if="tableColumns.find(col => col.prop === 'created_at')?.show" key="created_at" label="创建时间" prop="created_at" min-width="200" sortable />
<el-table-column v-if="tableColumns.find(col => col.prop === 'updated_at')?.show" key="updated_at" label="更新时间" prop="updated_at" min-width="200" sortable />
<el-table-column v-if="tableColumns.find(col => col.prop === 'creator')?.show" label="创建人" prop="creator" min-width="100">
<el-table-column label="描述" prop="description" min-width="100" show-overflow-tooltip/>
<el-table-column label="创建时间" prop="created_at" min-width="200" sortable />
<el-table-column label="更新时间" prop="updated_at" min-width="200" sortable />
<el-table-column label="创建人" prop="creator" min-width="100">
<template #default="scope">
{{ scope.row.creator?.name }}
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'operation')?.show" fixed="right" label="操作" align="center" min-width="200">
<el-table-column fixed="right" label="操作" align="center" min-width="200">
<template #default="scope">
<el-button type="info" size="small" link icon="document" @click="handleOpenDialog('detail', scope.row.id)">详情</el-button>
<el-button type="primary" size="small" link icon="edit" @click="handleOpenDialog('update', scope.row.id)">编辑</el-button>
@@ -219,9 +207,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
@@ -264,26 +252,6 @@ const drawerVisible = ref<boolean>(false);
//
const pageTableData = ref<DictDataTable[]>([]);
//
const tableColumns = ref([
{ prop: 'selection', label: '选择框', show: true },
{ prop: 'index', label: '序号', show: true },
{ prop: 'dict_sort', label: '字典排序', show: true },
{ prop: 'dict_label', label: '字典标签', show: true },
{ prop: 'dict_type', label: '字典类型', show: true },
{ prop: 'dict_value', label: '字典键值', show: true },
{ prop: 'css_class', label: '样式属性', show: false },
{ prop: 'list_class', label: '表格回显属性', show: false },
{ prop: 'is_default', label: '是否默认', show: true },
{ prop: 'status', label: '状态', show: true },
{ prop: 'description', label: '描述', show: true },
{ prop: 'creator', label: '创建人', show: true },
{ prop: 'created_at', label: '创建时间', show: true },
{ prop: 'updated_at', label: '更新时间', show: true },
{ prop: 'operation', label: '操作', show: true }
])
//
const detailFormData = ref<DictDataTable>({});
+1 -1
View File
@@ -185,9 +185,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
+15 -47
View File
@@ -65,19 +65,7 @@
<el-button type="warning" icon="download" circle @click="handleExport" />
</el-tooltip>
<el-tooltip content="刷新">
<el-button type="primary" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
<el-tooltip content="列表筛选">
<el-dropdown trigger="click">
<el-button type="default" icon="operation" circle />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="column in tableColumns" :key="column.prop" :command="column">
<el-checkbox v-model="column.show">{{ column.label }}</el-checkbox>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="default" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
</div>
</div>
@@ -87,46 +75,46 @@
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column v-if="tableColumns.find(col => col.prop === 'selection')?.show" prop='selection' type="selection" min-width="55" align="center" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'index')?.show" type="index" fixed label="序号" min-width="60" >
<el-table-column prop='selection' type="selection" min-width="55" align="center" />
<el-table-column type="index" fixed label="序号" min-width="60" >
<template #default="scope">
{{ (queryFormData.page_no - 1) * queryFormData.page_size + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'type')?.show" label="日志类型" prop="type" min-width="100">
<el-table-column label="日志类型" prop="type" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.type === 1 ? 'success' : 'primary'">
{{ scope.row.type === 1 ? '登录日志' : '操作日志' }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'request_path')?.show" label="请求路径" prop="request_path" min-width="200" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'request_method')?.show" label="请求方法" prop="request_method" min-width="100">
<el-table-column label="请求路径" prop="request_path" min-width="200" show-overflow-tooltip />
<el-table-column label="请求方法" prop="request_method" min-width="100">
<template #default="scope">
<el-tag :type="getMethodType(scope.row.request_method)">
{{ scope.row.request_method }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'response_code')?.show" label="状态码" prop="response_code" min-width="100">
<el-table-column label="状态码" prop="response_code" min-width="100">
<template #default="scope">
<el-tag :type="getStatusCodeType(scope.row.response_code)">
{{ scope.row.response_code }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'request_ip')?.show" label="请求IP" prop="request_ip" min-width="180" show-overflow-tooltip>
<el-table-column label="请求IP" prop="request_ip" min-width="180" show-overflow-tooltip>
<template #default="scope">
<el-text>{{ scope.row.request_ip }}</el-text>
<CopyButton v-if="scope.row.request_ip" :text="scope.row.request_ip" style="margin-left: 2px" />
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'process_time')?.show" label="处理时间" prop="process_time" min-width="120" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'request_browser')?.show" label="浏览器" prop="request_browser" min-width="220" show-overflow-tooltip/>
<el-table-column v-if="tableColumns.find(col => col.prop === 'request_os')?.show" label="系统" prop="request_os" min-width="100" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'description')?.show" label="描述" prop="description" min-width="120" show-overflow-tooltip />
<el-table-column v-if="tableColumns.find(col => col.prop === 'created_at')?.show" label="创建时间" prop="created_at" min-width="200" sortable />
<el-table-column v-if="tableColumns.find(col => col.prop === 'creator')?.show" label="创建人" prop="creator" min-width="120">
<el-table-column label="处理时间" prop="process_time" min-width="120" />
<el-table-column label="浏览器" prop="request_browser" min-width="220" show-overflow-tooltip/>
<el-table-column label="系统" prop="request_os" min-width="100" />
<el-table-column label="描述" prop="description" min-width="120" show-overflow-tooltip />
<el-table-column label="创建时间" prop="created_at" min-width="200" sortable />
<el-table-column label="创建人" prop="creator" min-width="120">
<template #default="scope">
{{ scope.row.creator?.name }}
</template>
@@ -187,8 +175,8 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
<el-button type="primary" @click="handleCloseDialog">确定</el-button>
</div>
</template>
</el-dialog>
@@ -216,26 +204,6 @@ const isExpandable = ref(true);
//
const pageTableData = ref<LogTable[]>([]);
//
const tableColumns = ref([
{ prop: 'selection', label: '选择框', show: true },
{ prop: 'index', label: '序号', show: true },
{ prop: 'type', label: '日志类型', show: true },
{ prop: 'request_path', label: '请求路径', show: true },
{ prop: 'request_method', label: '请求方法', show: true },
{ prop: 'response_code', label: '响应状态码', show: true },
{ prop: 'request_ip', label: '请求IP', show: true },
{ prop: 'process_time', label: '处理时间', show: true },
{ prop: 'request_browser', label: '浏览器', show: true },
{ prop: 'request_os', label: '操作系统', show: true },
{ prop: 'login_location', label: '登录地点', show: true },
{ prop: 'description', label: '描述', show: true },
{ prop: 'creator', label: '创建人', show: true },
{ prop: 'created_at', label: '创建时间', show: true },
{ prop: 'updated_at', label: '更新时间', show: true },
{ prop: 'operation', label: '操作', show: true }
])
//
const formData = ref<LogTable>({});
+3 -9
View File
@@ -221,15 +221,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">
确定
</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">
确定
</el-button>
<el-button @click="handleCloseDialog">
取消
</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
</div>
</template>
</el-dialog>
+1 -1
View File
@@ -176,9 +176,9 @@
<template #footer>
<div class="dialog-footer">
<!-- 详情弹窗不需要确定按钮的提交逻辑 -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button v-if="dialogVisible.type !== 'detail'" type="primary" @click="handleSubmit">确定</el-button>
<el-button v-else type="primary" @click="handleCloseDialog">确定</el-button>
<el-button @click="handleCloseDialog">取消</el-button>
</div>
</template>
</el-dialog>
+1 -2
View File
@@ -196,11 +196,10 @@
</template>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit"> </el-button>
<el-button @click="handleCloseDialog"> </el-button>
<el-button type="primary" @click="handleSubmit"> </el-button>
</div>
</template>
</el-dialog>
@@ -38,7 +38,7 @@ const deptOptions = ref<OptionType[]>([]); // 部门列表
const deptTreeRef = ref<TreeInstance>(); //
const deptName = ref(); //
const emits = defineEmits(["node-click"]);
const emits = defineEmits(["node-click", "update:modelValue"]);
const deptId = useVModel(props, "modelValue", emits);
@@ -30,6 +30,7 @@
<el-button v-if="resultData.length > 0" type="primary" @click="handleShowResult">
错误信息
</el-button>
<el-button @click="handleClose"> </el-button>
<el-button
type="primary"
:disabled="importFormData.files.length === 0"
@@ -37,7 +38,6 @@
>
</el-button>
<el-button @click="handleClose"> </el-button>
</div>
</template>
</el-dialog>
+28 -48
View File
@@ -89,19 +89,7 @@
<el-button type="warning" icon="download" circle @click="handleOperation('export')" />
</el-tooltip>
<el-tooltip content="刷新">
<el-button type="primary" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
<el-tooltip content="列表筛选">
<el-dropdown trigger="click">
<el-button type="default" icon="operation" circle />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="column in tableColumns" :key="column.prop" :command="column">
<el-checkbox v-model="column.show">{{ column.label }}</el-checkbox>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="default" icon="refresh" circle @click="handleRefresh" />
</el-tooltip>
</div>
</div>
@@ -111,34 +99,39 @@
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column v-if="tableColumns.find(col => col.prop === 'selection')?.show" type="selection" min-width="55" align="center" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'index')?.show" type="index" fixed label="序号" align="center" min-width="60" >
<el-table-column type="selection" min-width="55" align="center" />
<el-table-column type="index" fixed label="序号" align="center" min-width="60" >
<template #default="scope">
{{ (queryFormData.page_no - 1) * queryFormData.page_size + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'avatar')?.show" label="头像" prop="avatar" min-width="80" align="center">
<el-table-column label="头像" prop="avatar" min-width="80" align="center">
<template #default="scope">
<el-avatar size="small" :src="scope.row.avatar" />
<template v-if="scope.row.avatar">
<el-avatar size="small" :src="scope.row.avatar" />
</template>
<template v-else>
<el-avatar size="small" icon="UserFilled" />
</template>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'username')?.show" label="账号" prop="username" min-width="100" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'name')?.show" label="用户名" prop="name" min-width="100" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'status')?.show" label="状态" prop="status" min-width="100">
<el-table-column label="账号" prop="username" min-width="100" />
<el-table-column label="用户名" prop="name" min-width="100" />
<el-table-column label="状态" prop="status" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.status === true ? 'success' : 'danger'">
{{ scope.row.status === true ? "启用" : "停用" }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'is_superuser')?.show" label="是否超管" prop="is_superuser" min-width="100">
<el-table-column label="是否超管" prop="is_superuser" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.is_superuser ? 'success' : 'info'">
{{ scope.row.is_superuser ? '是' : '否' }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'gender')?.show" label="性别" min-width="100">
<el-table-column label="性别" prop="gender" min-width="100">
<template #default="scope">
<el-tag v-if="scope.row.gender ==='0'" type="success"></el-tag>
<el-tag v-else-if="scope.row.gender ==='1'" type="warning"></el-tag>
@@ -146,16 +139,16 @@
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'mobile')?.show" label="手机号" prop="mobile" min-width="160" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'email')?.show" label="邮箱" prop="email" min-width="160" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'created_at')?.show" label="创建时间" prop="created_at" min-width="200" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'updated_at')?.show" label="更新时间" prop="updated_at" min-width="200" />
<el-table-column v-if="tableColumns.find(col => col.prop === 'creator')?.show" key="creator" label="创建人" min-width="120">
<el-table-column label="手机号" prop="mobile" min-width="160" />
<el-table-column label="邮箱" prop="email" min-width="160" />
<el-table-column label="创建时间" prop="created_at" min-width="200" />
<el-table-column label="更新时间" prop="updated_at" min-width="200" />
<el-table-column label="创建人" prop="creator" min-width="120">
<template #default="scope">
{{ scope.row.creator?.name }}
</template>
</el-table-column>
<el-table-column v-if="tableColumns.find(col => col.prop === 'operation')?.show" fixed="right" label="操作" align="center" min-width="280">
<el-table-column fixed="right" label="操作" align="center" min-width="280">
<template #default="scope">
<el-button type="warning" icon="RefreshLeft" size="small" link @click="hancleResetPassword(scope.row)">重置密码</el-button>
<el-button type="info" size="small" link icon="document" @click="handleOpenDialog('detail', scope.row.id)">详情</el-button>
@@ -180,7 +173,12 @@
<el-descriptions :column="2" border>
<el-descriptions-item label="编号" :span="2">{{ detailFormData.id }}</el-descriptions-item>
<el-descriptions-item label="头像" :span="2">
<el-avatar :src="detailFormData.avatar" size="small"></el-avatar>
<template v-if="detailFormData.avatar">
<el-avatar :src="detailFormData.avatar" size="small"></el-avatar>
</template>
<template v-else>
<el-avatar icon="UserFilled" size="small"></el-avatar>
</template>
</el-descriptions-item>
<el-descriptions-item label="账号" :span="2">{{ detailFormData.username }}</el-descriptions-item>
<el-descriptions-item label="用户名" :span="2">{{ detailFormData.name }}</el-descriptions-item>
@@ -342,25 +340,6 @@ const pageTableData = ref<UserInfo[]>([]);
//
const detailFormData = ref<UserInfo>({});
//
const tableColumns = ref([
{ prop: 'selection', label: '选择框', show: true },
{ prop: 'index', label: '序号', show: true },
{ prop: 'avatar', label: '头像', show: true },
{ prop: 'username', label: '账号', show: true },
{ prop: 'name', label: '用户名', show: true },
{ prop: 'gender', label: '性别', show: true },
{ prop: 'email', label: '邮箱', show: true },
{ prop: 'mobile', label: '手机号', show: true },
{ prop: 'is_superuser', label: '是否超管', show: true },
{ prop: 'status', label: '状态', show: true },
{ prop: 'description', label: '描述', show: true },
{ prop: 'created_at', label: '创建时间', show: true },
{ prop: 'updated_at', label: '更新时间', show: true },
{ prop: 'creator', label: '创建人', show: true },
{ prop: 'operation', label: '操作', show: true }
])
//
const queryFormData = reactive<UserPageQuery>({
page_no: 1,
@@ -456,6 +435,7 @@ async function handleQuery() {
//
async function handleResetQuery() {
queryFormRef.value.resetFields();
queryFormData.dept_id = undefined;
queryFormData.page_no = 1;
loadingData();
}