feat: 任务日志

This commit is contained in:
WANGFAN\wangf 2025-04-13 15:07:54 +08:00
parent 05f099a5a8
commit a1cc230f76
20 changed files with 249 additions and 228 deletions

View File

@ -9,9 +9,18 @@ export const getOnlineuserAPI = () => {
};
// 获取定时任务
export const getCronJobAPI = () => {
export const getCrontabAPI = () => {
return axios({
url: "/mock/monitor/getCronJob",
url: "/mock/monitor/getCrontab",
method: "get"
});
};
// 获取定时任务日志
export const getCrontabLogsAPI = (params: any) => {
return axios({
url: "/mock/monitor/getCrontabLogs",
method: "get",
params
});
};

View File

@ -92,7 +92,8 @@ export default {
["hide-menu"]: "hide-menu",
["system-monitor"]: "system monitor",
["onlineuser"]: "online user",
["cron-job"]: "cron job",
["crontab"]: "crontab",
["crontab-logs"]: "crontab logs",
["i18n"]: "i18n",
["amap"]: "amap",
["permission"]: "permission",

View File

@ -92,7 +92,8 @@ export default {
["hide-menu"]: "隐藏菜单",
["system-monitor"]: "系统监控",
["onlineuser"]: "在线用户",
["cron-job"]: "定时任务",
["crontab"]: "定时任务",
["crontab-logs"]: "任务日志",
["i18n"]: "国际化",
["amap"]: "高德地图",
["permission"]: "权限测试",

View File

@ -23,6 +23,10 @@ let { refreshPage, isTabs, watermark, watermarkStyle, watermarkRotate, watermark
const routerStore = useRoutesConfigStore();
const { cacheRoutes } = storeToRefs(routerStore);
// setInterval(() => {
// console.log("", cacheRoutes.value);
// }, 2000);
//
const watermarkConfig = computed(() => {
return {

View File

@ -25,16 +25,15 @@ export const onlineuser = [
];
// 定时任务
export const cronJob = [
export const crontab = [
{
id: 1,
jobId: "9e1f42c8-b127-449b-b0a4-d53c60b79e75", // 任务编号
name: "cron任务5秒执行一次", // 任务名称
cron: "0/5 * * * * * ", // cron-执行规则
every: null, // 间隔时间秒-执行规则
service: "taskDemoService.test()", // 执行服务
startDate: "2024-06-30 11:28:35", // 开始时间
nextRunTime: "2025-04-13 11:20:50", // 下次执行时间
startDate: "2025-03-30 11:28:35", // 开始时间
nextRunTime: "2025-03-13 11:20:50", // 下次执行时间
taskType: 0, // 任务类型 0 cron 1 指定时间(秒)
misfirePolicy: 1, // 执行策略 1 循环 2 执行一次
remark: "这是定时任务", // 备注
@ -46,13 +45,12 @@ export const cronJob = [
},
{
id: 2,
jobId: "9e1f42c8-b127-449b-b0a4-d53c60b79e76",
name: "每秒执行一次",
cron: null,
every: 1000,
every: 1,
service: "taskDemoService.test(1,2)",
startDate: "2024-06-30 11:28:35",
nextRunTime: "2025-04-13 11:20:50",
startDate: "2025-03-30 11:28:35",
nextRunTime: "2025-03-13 11:20:50",
taskType: 1,
misfirePolicy: 1,
remark: "这是定时任务",
@ -63,3 +61,26 @@ export const cronJob = [
updateTime: null
}
];
// 任务日志
export const crontabLogs = [
{
id: 1,
taskId: 1,
taskName: "cron任务5秒执行一次",
status: 1,
remark: "",
createTime: "2025-03-30 11:28:35",
executionTime: "2025-03-30 11:28:35"
},
{
id: 2,
taskId: 2,
taskName: "每秒执行一次",
status: 0,
remark:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ', `_isUTC` = false, `_pf` = '[object Object]', `_locale` = '[object Object]', `_' at line 1",
createTime: "2025-03-30 11:28:35",
executionTime: "2025-03-30 11:28:35"
}
];

View File

@ -167,7 +167,7 @@ export const dictData = [
name: "状态",
code: "status",
status: 1,
description: "想要统一状态字段可以用这个",
description: "状态字段可以用这个",
createTime: "2024-07-01 10:00:00",
list: [
{ id: "021", name: "禁用", value: 0, status: 1 },
@ -189,6 +189,18 @@ export const dictData = [
{ id: "035", name: "普通职员", value: 5, status: 1 },
{ id: "036", name: "其它", value: 999, status: 1 }
]
},
{
id: "04",
name: "任务状态",
code: "taskStatus",
status: 1,
description: "任务状态字段可以用它",
createTime: "2024-07-01 10:00:00",
list: [
{ id: "041", name: "失败", value: 0, status: 1 },
{ id: "042", name: "成功", value: 1, status: 1 }
]
}
];

View File

@ -359,126 +359,6 @@ export const systemMenu = [
},
children: null
},
{
id: "050204",
parentId: "0502",
path: "/multilevel/third-4",
name: "third-4",
component: "multilevel/third/third-4",
meta: {
title: "third-4",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 4,
type: 2
},
children: null
},
{
id: "050205",
parentId: "0502",
path: "/multilevel/third-5",
name: "third-5",
component: "multilevel/third/third-5",
meta: {
title: "third-5",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 5,
type: 2
},
children: null
},
{
id: "050206",
parentId: "0502",
path: "/multilevel/third-6",
name: "third-6",
component: "multilevel/third/third-6",
meta: {
title: "third-6",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 6,
type: 2
},
children: null
},
{
id: "050207",
parentId: "0502",
path: "/multilevel/third-7",
name: "third-7",
component: "multilevel/third/third-7",
meta: {
title: "third-7",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 7,
type: 2
},
children: null
},
{
id: "050208",
parentId: "0502",
path: "/multilevel/third-8",
name: "third-8",
component: "multilevel/third/third-8",
meta: {
title: "third-8",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 8,
type: 2
},
children: null
},
{
id: "050209",
parentId: "0502",
path: "/multilevel/third-9",
name: "third-9",
component: "multilevel/third/third-9",
meta: {
title: "third-9",
link: "",
hide: false,
keepAlive: true,
affix: false,
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 9,
type: 2
},
children: null
},
{
id: "06",
parentId: "0",
@ -1427,11 +1307,11 @@ export const systemMenu = [
{
id: "1402",
parentId: "14",
path: "/monitor/cron-job",
name: "cron-job",
component: "monitor/cron-job/index",
path: "/monitor/crontab",
name: "crontab",
component: "monitor/crontab/index",
meta: {
title: "cron-job",
title: "crontab",
hide: false,
keepAlive: true,
disable: false,
@ -1445,6 +1325,27 @@ export const systemMenu = [
},
children: null
},
{
id: "1403",
parentId: "14",
path: "/monitor/crontab-logs",
name: "crontab-logs",
component: "monitor/crontab-logs/index",
meta: {
title: "crontab-logs",
hide: false,
keepAlive: true,
disable: false,
affix: false,
link: "",
iframe: false,
roles: ["admin"],
icon: "icon-menu",
sort: 3,
type: 2
},
children: null
},
{
id: "15",
parentId: "0",

View File

@ -1,10 +1,10 @@
import type { MockMethod } from "vite-plugin-mock";
import { resultSuccess } from "../_utils";
import { onlineuser, cronJob } from "../_data/monitor_data";
import { onlineuser, crontab, crontabLogs } from "../_data/monitor_data";
/**
* post请求body,get请求query
* /mock/monitor/getOnlineuser 线
* /mock/monitor/getCronJob
* /mock/monitor/getCrontab
*/
export default [
{
@ -16,11 +16,21 @@ export default [
}
},
{
url: "/mock/monitor/getCronJob",
url: "/mock/monitor/getCrontab",
method: "get",
timeout: 300,
response: () => {
return resultSuccess(cronJob);
return resultSuccess(crontab);
}
},
{
url: "/mock/monitor/getCrontabLogs",
method: "get",
timeout: 300,
response: ({ query }: any) => {
console.log("请求参数", query);
return resultSuccess(crontabLogs);
}
}
] as MockMethod[];

View File

@ -0,0 +1,121 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<a-space wrap>
<a-input v-model="form.name" placeholder="请输入任务名称" allow-clear />
<a-select placeholder="执行状态" v-model="form.status" style="width: 120px" allow-clear>
<a-option v-for="item in openState" :key="item.value" :value="item.value">{{ item.name }}</a-option>
</a-select>
<a-range-picker v-model="form.datetimeRange" show-time format="YYYY-MM-DD HH:mm" allow-clear />
<a-button type="primary" @click="search">
<template #icon><icon-search /></template>
<span>查询</span>
</a-button>
<a-button @click="reset">
<template #icon><icon-refresh /></template>
<span>重置</span>
</a-button>
</a-space>
<a-table
row-key="id"
:data="list"
:bordered="{ cell: true }"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="pagination"
>
<template #columns>
<a-table-column title="序号" :width="64">
<template #cell="cell">{{ cell.rowIndex + 1 }}</template>
</a-table-column>
<a-table-column title="任务名称" data-index="taskName" ellipsis tooltip></a-table-column>
<a-table-column title="执行状态" data-index="status" align="center" :width="100">
<template #cell="{ record }">
<a-tag bordered size="small" color="arcoblue" v-if="record.status === 1">成功</a-tag>
<a-tag bordered size="small" color="red" v-else>失败</a-tag>
</template>
</a-table-column>
<a-table-column title="备注" data-index="remark" ellipsis tooltip>
<template #cell="{ record }">
{{ record.remark || "无" }}
</template>
</a-table-column>
<a-table-column title="预设时间" data-index="createTime"></a-table-column>
<a-table-column title="执行时间" data-index="executionTime"></a-table-column>
<a-table-column title="操作" :width="100" align="center" :fixed="'right'">
<template #cell="{ record }">
<a-space>
<a-button type="primary" status="success" size="mini" @click="onDetail(record)">
<template #icon><icon-file /></template>
<span>详情</span>
</a-button>
</a-space>
</template>
</a-table-column>
</template>
</a-table>
</div>
</div>
</template>
<script setup lang="ts">
import { getCrontabLogsAPI } from "@/api/modules/monitor/index";
let route = useRoute();
const openState = ref(dictFilter("taskStatus"));
const form = ref({
jobId: null,
name: "",
status: null,
datetimeRange: []
});
const search = () => {
getCrontabLogs();
};
const reset = () => {
form.value = {
jobId: null,
name: "",
status: null,
datetimeRange: []
};
getCrontabLogs();
};
const onDetail = (record: any) => {
console.log("详情", record);
};
//
const loading = ref(false);
const pagination = ref({
pageSize: 10,
showPageSize: true
});
const list = ref([]);
const getCrontabLogs = async () => {
try {
loading.value = true;
let res = await getCrontabLogsAPI(form.value);
list.value = res.data;
} finally {
loading.value = false;
}
};
onMounted(() => {
if (route.query.id) {
form.value.jobId = route.query.id;
form.value.name = route.query.name;
}
getCrontabLogs();
});
</script>
<style lang="scss" scoped>
.text-right-gap {
margin-right: $margin;
}
</style>

View File

@ -6,6 +6,7 @@
<a-select placeholder="任务状态" v-model="form.status" style="width: 120px" allow-clear>
<a-option v-for="item in openState" :key="item.value" :value="item.value">{{ item.name }}</a-option>
</a-select>
<a-range-picker v-model="form.createTime" show-time format="YYYY-MM-DD HH:mm" allow-clear />
<a-button type="primary" @click="search">
<template #icon><icon-search /></template>
<span>查询</span>
@ -45,7 +46,7 @@
<span v-else>间隔时间: {{ record.every }} </span>
</template>
</a-table-column>
<a-table-column title="状态" data-index="status" :width="80">
<a-table-column title="状态" align="center" data-index="status" :width="80">
<template #cell="{ record }">
<a-tag bordered size="small" color="arcoblue" v-if="record.status === 1">启用</a-tag>
<a-tag bordered size="small" color="red" v-else>禁用</a-tag>
@ -56,7 +57,7 @@
<a-table-column title="操作" :width="250" align="center" :fixed="'right'">
<template #cell="{ record }">
<a-space>
<a-button type="primary" status="success" size="mini">
<a-button type="primary" status="success" size="mini" @click="onLogs(record)">
<template #icon><icon-file /></template>
<span>日志</span>
</a-button>
@ -64,7 +65,7 @@
<template #icon><icon-edit /></template>
<span>修改</span>
</a-button>
<a-popconfirm type="warning" content="确定删除吗?" @ok="onLogout(record)">
<a-popconfirm type="warning" content="确定删除吗?">
<a-button type="primary" status="danger" size="mini">
<template #icon><icon-delete /></template>
<span>删除</span>
@ -139,8 +140,9 @@
</template>
<script setup lang="ts">
import { getCronJobAPI } from "@/api/modules/monitor/index";
import { getCrontabAPI } from "@/api/modules/monitor/index";
import { deepClone } from "@/utils";
const router = useRouter();
const openState = ref(dictFilter("status"));
const misfirePolicyOption = ref([
{ name: "循环", value: 1 },
@ -153,18 +155,20 @@ const taskTypeOption = ref([
const form = ref({
loginLocation: "",
userName: "",
status: null
status: null,
createTime: []
});
const search = () => {
getCronJob();
getCrontab();
};
const reset = () => {
form.value = {
loginLocation: "",
userName: "",
status: null
status: null,
createTime: []
};
getCronJob();
getCrontab();
};
//
@ -199,9 +203,8 @@ const onAdd = () => {
const handleOk = async () => {
let state = await formRef.value.validate();
if (state) return (open.value = true); //
console.log("模拟提交", addFrom.value);
arcoMessage("success", "模拟提交成功");
getCronJob();
getCrontab();
};
//
const afterClose = () => {
@ -229,10 +232,14 @@ const onUpdate = (row: any) => {
open.value = true;
};
const onLogout = (row: any) => {
console.log("退出", row);
arcoMessage("success", "模拟删除成功");
getCronJob();
const onLogs = (row: any) => {
router.push({
path: "/monitor/crontab-logs",
query: {
id: row.id,
name: row.name
}
});
};
//
@ -242,17 +249,17 @@ const pagination = ref({
showPageSize: true
});
const list = ref([]);
const getCronJob = async () => {
const getCrontab = async () => {
try {
loading.value = true;
let res = await getCronJobAPI();
let res = await getCrontabAPI();
list.value = res.data;
} finally {
loading.value = false;
}
};
getCronJob();
getCrontab();
</script>
<style lang="scss" scoped>

View File

@ -32,7 +32,7 @@
<a-table-column title="部门名称" data-index="deptName" ellipsis tooltip></a-table-column>
<a-table-column title="IP地址" data-index="ipaddr" ellipsis tooltip></a-table-column>
<a-table-column title="登录地址" data-index="loginLocation" ellipsis tooltip></a-table-column>
<a-table-column title="状态" data-index="status" :width="80">
<a-table-column title="状态" data-index="status" align="center" :width="80">
<template #cell="{ record }">
<a-space>
<a-badge status="success" text="在线" v-if="record.status == 1" />

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-04</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-05</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-06</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-07</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-08</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -1,11 +0,0 @@
<template>
<div class="snow-page">
<div class="snow-inner">
<div>三级-菜单-09</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>

View File

@ -60,7 +60,7 @@
</a-table-column>
<a-table-column title="用户名称" data-index="userName"></a-table-column>
<a-table-column title="昵称" data-index="nickName"></a-table-column>
<a-table-column title="性别" data-index="sex">
<a-table-column title="性别" data-index="sex" align="center">
<template #cell="{ record }">
<a-tag bordered size="small" color="arcoblue" v-if="record.sex == 1"></a-tag>
<a-tag bordered size="small" color="red" v-else-if="record.sex == 0"></a-tag>

View File

@ -43,7 +43,7 @@
{{ record.name }}
</template>
</a-table-column>
<a-table-column title="排序" data-index="sort" :width="100"></a-table-column>
<a-table-column title="排序" data-index="sort" :width="100" align="center"></a-table-column>
<a-table-column title="启用状态" align="center">
<template #cell="{ record }">
<a-space>

View File

@ -49,7 +49,7 @@
</a-table-column>
<a-table-column title="角色名称" data-index="name"></a-table-column>
<a-table-column title="角色标识" data-index="code"></a-table-column>
<a-table-column title="排序" data-index="sort" :width="100"></a-table-column>
<a-table-column title="排序" data-index="sort" :width="100" align="center"></a-table-column>
<a-table-column title="状态" :width="100" align="center">
<template #cell="{ record }">
<a-tag bordered size="small" color="arcoblue" v-if="record.status === 1">启用</a-tag>