1. 完成 Job 的新增和修改

2. 优化代码生成器的模板
This commit is contained in:
YunaiV 2021-02-14 19:22:51 +08:00
parent efbd8cad49
commit bc1504d991
23 changed files with 169 additions and 326 deletions

View File

@ -1,7 +1,7 @@
# 开发环境配置 # 开发环境配置
ENV = 'development' ENV = 'development'
# 若依管理系统/开发环境 # 芋道管理系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
# VUE_APP_BASE_API = '/api' # VUE_APP_BASE_API = '/api'

View File

@ -1,5 +1,5 @@
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'
# 若依管理系统/生产环境 # 芋道管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'

View File

@ -3,5 +3,5 @@ NODE_ENV = production
# 测试环境配置 # 测试环境配置
ENV = 'staging' ENV = 'staging'
# 若依管理系统/测试环境 # 芋道管理系统/测试环境
VUE_APP_BASE_API = '/stage-api' VUE_APP_BASE_API = '/stage-api'

View File

@ -1,8 +1,8 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.3.0", "version": "3.3.0",
"description": "若依管理系统", "description": "芋道管理系统",
"author": "若依", "author": "芋道",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",

View File

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询定时任务调度列表 // 查询定时任务调度列表
export function listJob(query) { export function listJob(query) {
return request({ return request({
url: '/monitor/job/list', url: '/infra/job/page',
method: 'get', method: 'get',
params: query params: query
}) })
@ -12,7 +12,7 @@ export function listJob(query) {
// 查询定时任务调度详细 // 查询定时任务调度详细
export function getJob(jobId) { export function getJob(jobId) {
return request({ return request({
url: '/monitor/job/' + jobId, url: '/infra/job/get?id=' + jobId,
method: 'get' method: 'get'
}) })
} }
@ -20,7 +20,7 @@ export function getJob(jobId) {
// 新增定时任务调度 // 新增定时任务调度
export function addJob(data) { export function addJob(data) {
return request({ return request({
url: '/monitor/job', url: '/infra/job/create',
method: 'post', method: 'post',
data: data data: data
}) })
@ -29,7 +29,7 @@ export function addJob(data) {
// 修改定时任务调度 // 修改定时任务调度
export function updateJob(data) { export function updateJob(data) {
return request({ return request({
url: '/monitor/job', url: '/infra/job/update',
method: 'put', method: 'put',
data: data data: data
}) })
@ -38,7 +38,7 @@ export function updateJob(data) {
// 删除定时任务调度 // 删除定时任务调度
export function delJob(jobId) { export function delJob(jobId) {
return request({ return request({
url: '/monitor/job/' + jobId, url: '/infra/job/delete?id=' + jobId,
method: 'delete' method: 'delete'
}) })
} }
@ -46,7 +46,7 @@ export function delJob(jobId) {
// 导出定时任务调度 // 导出定时任务调度
export function exportJob(query) { export function exportJob(query) {
return request({ return request({
url: '/monitor/job/export', url: '/infra/job/export',
method: 'get', method: 'get',
params: query params: query
}) })

View File

@ -35,7 +35,7 @@ export default {
}, },
data() { data() {
return { return {
title: '若依管理系统', title: '芋道管理系统',
logo: logoImg logo: logoImg
} }
} }

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
title: '若依管理系统', title: '芋道管理系统',
/** /**
* 侧边栏主题 深色主题theme-dark浅色主题theme-light * 侧边栏主题 深色主题theme-dark浅色主题theme-light

View File

@ -17,6 +17,7 @@ export const DICT_TYPE = {
SYS_CONFIG_TYPE: 'sys_config_type', SYS_CONFIG_TYPE: 'sys_config_type',
INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type', INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type',
INF_JOB_STATUS: 'inf_job_status',
TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type',
} }

View File

@ -39,9 +39,9 @@
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :sm="24" :lg="12" style="padding-left: 20px"> <el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>若依后台管理框架</h2> <h2>芋道后台管理框架</h2>
<p> <p>
一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适自己的于是利用空闲休息时间开始自己写一套后台系统如此有了若依管理系统她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA等等当然您也可以对她进行深度定制以做出更强系统所有前端后台代码封装过后十分精简易上手出错概率低同时支持移动客户端访问系统会陆续更新一些实用功能 一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适自己的于是利用空闲休息时间开始自己写一套后台系统如此有了芋道管理系统她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA等等当然您也可以对她进行深度定制以做出更强系统所有前端后台代码封装过后十分精简易上手出错概率低同时支持移动客户端访问系统会陆续更新一些实用功能
</p> </p>
<p> <p>
<b>当前版本:</b> <span>v{{ version }}</span> <b>当前版本:</b> <span>v{{ version }}</span>
@ -127,14 +127,14 @@
<p> <p>
<i class="el-icon-chat-dot-round"></i> 微信<a <i class="el-icon-chat-dot-round"></i> 微信<a
href="javascript:;" href="javascript:;"
>/ *</a >/ *</a
> >
</p> </p>
<p> <p>
<i class="el-icon-money"></i> 支付宝<a <i class="el-icon-money"></i> 支付宝<a
href="javascript:;" href="javascript:;"
class="支付宝信息" class="支付宝信息"
>/ *</a >/ *</a
> >
</p> </p>
</div> </div>
@ -460,7 +460,7 @@
</el-collapse-item> </el-collapse-item>
<el-collapse-item title="v1.0.0 - 2019-10-08"> <el-collapse-item title="v1.0.0 - 2019-10-08">
<ol> <ol>
<li>若依前后端分离系统正式发布</li> <li>芋道前后端分离系统正式发布</li>
</ol> </ol>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="login"> <div class="login">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">若依后台管理系统</h3> <h3 class="title">芋道后台管理系统</h3>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号"> <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />

View File

@ -1,35 +1,18 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="任务名称" prop="jobName"> <el-form-item label="任务名称" prop="name">
<el-input <el-input v-model="queryParams.name" placeholder="请输入任务名称" clearable size="small" @keyup.enter.native="handleQuery"/>
v-model="queryParams.jobName"
placeholder="请输入任务名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="任务组名" prop="jobGroup">
<el-select v-model="queryParams.jobGroup" placeholder="请选择任务组名" clearable size="small">
<el-option
v-for="dict in jobGroupOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="任务状态" prop="status"> <el-form-item label="任务状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable size="small"> <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable size="small">
<el-option <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INF_JOB_STATUS)"
v-for="dict in statusOptions" :key="dict.value" :label="dict.label" :value="dict.value"/>
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="处理器的名字" prop="handlerName">
<el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable size="small" @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -38,171 +21,69 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
type="primary" v-hasPermi="['monitor:job:add']">新增</el-button>
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['monitor:job:add']"
>新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
type="success" v-hasPermi="['monitor:job:export']">导出</el-button>
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['monitor:job:edit']"
>修改</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog"
type="danger" v-hasPermi="['monitor:job:query']">日志</el-button>
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['monitor:job:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['monitor:job:export']"
>导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
icon="el-icon-s-operation"
size="mini"
@click="handleJobLog"
v-hasPermi="['monitor:job:query']"
>日志</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="jobList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="jobList">
<el-table-column type="selection" width="55" align="center" /> <el-table-column label="任务编号" align="center" prop="id" />
<el-table-column label="任务编号" align="center" prop="jobId" /> <el-table-column label="任务名称" align="center" prop="name" />
<el-table-column label="任务名称" align="center" prop="jobName" :show-overflow-tooltip="true" /> <el-table-column label="任务状态" align="center" prop="status">
<el-table-column label="任务组名" align="center" prop="jobGroup" :formatter="jobGroupFormat" />
<el-table-column label="调用目标字符串" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
<el-table-column label="cron执行表达式" align="center" prop="cronExpression" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <span>{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, scope.row.status) }}</span>
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
</template> </template>
</el-table-column> </el-table-column>>
<el-table-column label="处理器的名字" align="center" prop="handlerName" />
<el-table-column label="处理器的参数" align="center" prop="handlerParam" />
<el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
v-hasPermi="['monitor:job:query']">详细</el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click="handleUpdate(scope.row)"
v-hasPermi="['monitor:job:query']">修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-caret-right" icon="el-icon-caret-right"
@click="handleRun(scope.row)" @click="handleRun(scope.row)"
v-hasPermi="['monitor:job:changeStatus']" v-hasPermi="['monitor:job:changeStatus']"
>执行一次</el-button> >执行一次</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
v-hasPermi="['monitor:job:query']"
>详细</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页组件 -->
<pagination <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
v-show="total>0" @pagination="getList"/>
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改定时任务对话框 --> <!-- 添加或修改定时任务对话框 -->
<el-dialog :title="title" :visible.sync="open" width="700px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row> <el-form-item label="任务名称" prop="name">
<el-col :span="12"> <el-input v-model="form.name" placeholder="请输入任务名称" />
<el-form-item label="任务名称" prop="jobName"> </el-form-item>
<el-input v-model="form.jobName" placeholder="请输入任务名称" /> <el-form-item label="处理器的名字" prop="handlerName">
</el-form-item> <el-input v-model="form.handlerName" placeholder="请输入处理器的名字" v-bind:readonly="form.id !== undefined" />
</el-col> </el-form-item>
<el-col :span="12"> <el-form-item label="处理器的参数" prop="handlerParam">
<el-form-item label="任务分组" prop="jobGroup"> <el-input v-model="form.handlerParam" placeholder="请输入处理器的参数" />
<el-select v-model="form.jobGroup" placeholder="请选择"> </el-form-item>
<el-option <el-form-item label="CRON 表达式" prop="cronExpression">
v-for="dict in jobGroupOptions" <el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式" />
:key="dict.dictValue" </el-form-item>
:label="dict.dictLabel" <el-form-item label="监控超时时间" prop="monitorTimeout">
:value="dict.dictValue" <el-input v-model="form.monitorTimeout" placeholder="请输入监控超时时间,单位:毫秒" />
></el-option> </el-form-item>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item prop="invokeTarget">
<span slot="label">
调用方法
<el-tooltip placement="top">
<div slot="content">
Bean调用示例ryTask.ryParams('ry')
<br />Class类调用示例com.ruoyi.quartz.task.RyTask.ryParams('ry')
<br />参数说明支持字符串布尔类型长整型浮点型整型
</div>
<i class="el-icon-question"></i>
</el-tooltip>
</span>
<el-input v-model="form.invokeTarget" placeholder="请输入调用目标字符串" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="cron表达式" prop="cronExpression">
<el-input v-model="form.cronExpression" placeholder="请输入cron执行表达式" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否并发" prop="concurrent">
<el-radio-group v-model="form.concurrent" size="small">
<el-radio-button label="0">允许</el-radio-button>
<el-radio-button label="1">禁止</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="错误策略" prop="misfirePolicy">
<el-radio-group v-model="form.misfirePolicy" size="small">
<el-radio-button label="1">立即执行</el-radio-button>
<el-radio-button label="2">执行一次</el-radio-button>
<el-radio-button label="3">放弃执行</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{dict.dictLabel}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" @click="submitForm"> </el-button>
@ -212,44 +93,20 @@
<!-- 任务日志详细 --> <!-- 任务日志详细 -->
<el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body> <el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body>
<el-form ref="form" :model="form" label-width="120px" size="mini"> <el-form ref="form" :model="form" label-width="200px" size="mini">
<el-row> <el-row>
<el-col :span="12">
<el-form-item label="任务编号:">{{ form.jobId }}</el-form-item>
<el-form-item label="任务名称:">{{ form.jobName }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="任务分组:">{{ jobGroupFormat(form) }}</el-form-item>
<el-form-item label="创建时间:">{{ form.createTime }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="cron表达式">{{ form.cronExpression }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下次执行时间:">{{ parseTime(form.nextValidTime) }}</el-form-item>
</el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="调用目标方法:">{{ form.invokeTarget }}</el-form-item> <el-form-item label="任务编号:">{{ form.id }}</el-form-item>
</el-col> <el-form-item label="任务名称:">{{ form.name }}</el-form-item>
<el-col :span="12"> <el-form-item label="任务名称:">{{ getDictDataLabel(DICT_TYPE.INF_JOB_STATUS, form.status) }}</el-form-item>
<el-form-item label="任务状态:"> <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
<div v-if="form.status == 0">正常</div> <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
<div v-else-if="form.status == 1">失败</div> <el-form-item label="cron表达式">{{ form.cronExpression }}</el-form-item>
</el-form-item> <el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeBeginTime) }}</el-form-item>
</el-col> <el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeEndTime) }}</el-form-item>
<el-col :span="12"> <el-form-item label="上一次触发时间:">{{ parseTime(form.firePrevTime) }}</el-form-item>
<el-form-item label="是否并发:"> <el-form-item label="下一次触发时间:">{{ parseTime(form.fireNextTime) }}</el-form-item>
<div v-if="form.concurrent == 0">允许</div> <el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item>
<div v-else-if="form.concurrent == 1">禁止</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="执行策略:">
<div v-if="form.misfirePolicy == 0">默认策略</div>
<div v-else-if="form.misfirePolicy == 1">立即执行</div>
<div v-else-if="form.misfirePolicy == 2">执行一次</div>
<div v-else-if="form.misfirePolicy == 3">放弃执行</div>
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
@ -257,6 +114,7 @@
<el-button @click="openView = false"> </el-button> <el-button @click="openView = false"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
@ -269,12 +127,6 @@ export default {
return { return {
// //
loading: true, loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
// //
showSearch: true, showSearch: true,
// //
@ -287,83 +139,59 @@ export default {
open: false, open: false,
// //
openView: false, openView: false,
//
jobGroupOptions: [],
// //
statusOptions: [], statusOptions: [],
// //
queryParams: { queryParams: {
pageNum: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
jobName: undefined, name: undefined,
jobGroup: undefined, status: undefined,
status: undefined handlerName: undefined
}, },
// //
form: {}, form: {},
// //
rules: { rules: {
jobName: [ name: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
{ required: true, message: "任务名称不能为空", trigger: "blur" } handlerName: [{ required: true, message: "处理器的名字不能为空", trigger: "blur" }],
], cronExpression: [{ required: true, message: "CRON 表达式不能为空", trigger: "blur" }],
invokeTarget: [
{ required: true, message: "调用目标字符串不能为空", trigger: "blur" }
],
cronExpression: [
{ required: true, message: "cron执行表达式不能为空", trigger: "blur" }
]
} }
}; };
}, },
created() { created() {
this.getList(); this.getList();
this.getDicts("sys_job_group").then(response => {
this.jobGroupOptions = response.data;
});
this.getDicts("sys_job_status").then(response => {
this.statusOptions = response.data;
});
}, },
methods: { methods: {
/** 查询定时任务列表 */ /** 查询定时任务列表 */
getList() { getList() {
this.loading = true; this.loading = true;
listJob(this.queryParams).then(response => { listJob(this.queryParams).then(response => {
this.jobList = response.rows; this.jobList = response.data.list;
this.total = response.total; this.total = response.data.total;
this.loading = false; this.loading = false;
}); });
}, },
// /** 取消按钮 */
jobGroupFormat(row, column) {
return this.selectDictLabel(this.jobGroupOptions, row.jobGroup);
},
//
statusFormat(row, column) {
return this.selectDictLabel(this.statusOptions, row.status);
},
//
cancel() { cancel() {
this.open = false; this.open = false;
this.reset(); this.reset();
}, },
// /** 表单重置 */
reset() { reset() {
this.form = { this.form = {
jobId: undefined, id: undefined,
jobName: undefined, name: undefined,
jobGroup: undefined, handlerName: undefined,
invokeTarget: undefined, handlerParam: undefined,
cronExpression: undefined, cronExpression: undefined,
misfirePolicy: 1, monitorTimeout: undefined,
concurrent: 1,
status: "0"
}; };
this.resetForm("form"); this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNo = 1;
this.getList(); this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
@ -371,21 +199,15 @@ export default {
this.resetForm("queryForm"); this.resetForm("queryForm");
this.handleQuery(); this.handleQuery();
}, },
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.jobId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
// //
handleStatusChange(row) { handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用"; let text = row.status === "0" ? "启用" : "停用";
this.$confirm('确认要"' + text + '""' + row.jobName + '"任务吗?', "警告", { this.$confirm('确认要"' + text + '""' + row.name + '"任务吗?', "警告", {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(function() { }).then(function() {
return changeJobStatus(row.jobId, row.status); return changeJobStatus(row.id, row.status);
}).then(() => { }).then(() => {
this.msgSuccess(text + "成功"); this.msgSuccess(text + "成功");
}).catch(function() { }).catch(function() {
@ -394,19 +216,19 @@ export default {
}, },
/* 立即执行一次 */ /* 立即执行一次 */
handleRun(row) { handleRun(row) {
this.$confirm('确认要立即执行一次"' + row.jobName + '"任务吗?', "警告", { this.$confirm('确认要立即执行一次"' + row.name + '"任务吗?', "警告", {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(function() { }).then(function() {
return runJob(row.jobId, row.jobGroup); return runJob(row.id, row.jobGroup);
}).then(() => { }).then(() => {
this.msgSuccess("执行成功"); this.msgSuccess("执行成功");
}) })
}, },
/** 任务详细信息 */ /** 任务详细信息 */
handleView(row) { handleView(row) {
getJob(row.jobId).then(response => { getJob(row.id).then(response => {
this.form = response.data; this.form = response.data;
this.openView = true; this.openView = true;
}); });
@ -424,8 +246,8 @@ export default {
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset();
const jobId = row.jobId || this.ids; const id = row.id;
getJob(jobId).then(response => { getJob(id).then(response => {
this.form = response.data; this.form = response.data;
this.open = true; this.open = true;
this.title = "修改任务"; this.title = "修改任务";
@ -435,7 +257,7 @@ export default {
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.jobId != undefined) { if (this.form.id !== undefined) {
updateJob(this.form).then(response => { updateJob(this.form).then(response => {
this.msgSuccess("修改成功"); this.msgSuccess("修改成功");
this.open = false; this.open = false;
@ -453,13 +275,13 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const jobIds = row.jobId || this.ids; const ids = row.id || this.ids;
this.$confirm('是否确认删除定时任务编号为"' + jobIds + '"的数据项?', "警告", { this.$confirm('是否确认删除定时任务编号为"' + ids + '"的数据项?', "警告", {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(function() { }).then(function() {
return delJob(jobIds); return delJob(ids);
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");

View File

@ -212,7 +212,7 @@ export default {
/** 关闭按钮 */ /** 关闭按钮 */
close() { close() {
this.$store.dispatch("tagsView/delView", this.$route); this.$store.dispatch("tagsView/delView", this.$route);
this.$router.push({ path: "/tool/gen", query: { t: Date.now()}}) this.$router.push({ path: "/tool/codegen", query: { t: Date.now()}})
} }
}, },
mounted() { mounted() {

View File

@ -59,7 +59,7 @@
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="160"> <el-table-column label="更新时间" align="center" prop="createTime" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime) }}</span> <span>{{ parseTime(scope.row.updateTime) }}</span>
</template> </template>

View File

@ -6,7 +6,7 @@ function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
const name = defaultSettings.title || '若依管理系统' // 标题 const name = defaultSettings.title || '芋道管理系统' // 标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80 // 端口

View File

@ -89,7 +89,7 @@ public class InfJobController {
@PreAuthorize("@ss.hasPermission('infra:job:export')") @PreAuthorize("@ss.hasPermission('infra:job:export')")
@OperateLog(type = EXPORT) @OperateLog(type = EXPORT)
public void exportJobExcel(@Valid InfJobExportReqVO exportReqVO, public void exportJobExcel(@Valid InfJobExportReqVO exportReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
List<InfJobDO> list = jobService.getJobList(exportReqVO); List<InfJobDO> list = jobService.getJobList(exportReqVO);
// 导出 Excel // 导出 Excel
List<InfJobExcelVO> datas = InfJobConvert.INSTANCE.convertList02(list); List<InfJobExcelVO> datas = InfJobConvert.INSTANCE.convertList02(list);

View File

@ -2,12 +2,8 @@ package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/** /**
* 定时任务 Base VO提供给添加修改详细的子 VO 使用 * 定时任务 Base VO提供给添加修改详细的子 VO 使用
@ -20,14 +16,6 @@ public class InfJobBaseVO {
@NotNull(message = "任务名称不能为空") @NotNull(message = "任务名称不能为空")
private String name; private String name;
@ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 InfJobStatusEnum 枚举")
@NotNull(message = "任务状态不能为空")
private Integer status;
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "处理器的参数", example = "yudao") @ApiModelProperty(value = "处理器的参数", example = "yudao")
private String handlerParam; private String handlerParam;
@ -35,22 +23,6 @@ public class InfJobBaseVO {
@NotNull(message = "CRON 表达式不能为空") @NotNull(message = "CRON 表达式不能为空")
private String cronExpression; private String cronExpression;
@ApiModelProperty(value = "最后一次执行的开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date executeBeginTime;
@ApiModelProperty(value = "最后一次执行的结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date executeEndTime;
@ApiModelProperty(value = "上一次触发时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date firePrevTime;
@ApiModelProperty(value = "下一次触发时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date fireNextTime;
@ApiModelProperty(value = "监控超时时间", example = "1000") @ApiModelProperty(value = "监控超时时间", example = "1000")
private Integer monitorTimeout; private Integer monitorTimeout;

View File

@ -1,14 +1,21 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.job; package cn.iocoder.dashboard.modules.infra.controller.job.vo.job;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("定时任务创建 Request VO") @ApiModel("定时任务创建 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class InfJobCreateReqVO extends InfJobBaseVO { public class InfJobCreateReqVO extends InfJobBaseVO {
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
} }

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date; import java.util.Date;
@ApiModel("定时任务 Response VO") @ApiModel("定时任务 Response VO")
@ -17,6 +18,25 @@ public class InfJobRespVO extends InfJobBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024") @ApiModelProperty(value = "任务编号", required = true, example = "1024")
private Long id; private Long id;
@ApiModelProperty(value = "任务状态", required = true, example = "1")
private Integer status;
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "最后一次执行的开始时间")
private Date executeBeginTime;
@ApiModelProperty(value = "最后一次执行的结束时间")
private Date executeEndTime;
@ApiModelProperty(value = "上一次触发时间")
private Date firePrevTime;
@ApiModelProperty(value = "下一次触发时间")
private Date fireNextTime;
@ApiModelProperty(value = "创建时间", required = true) @ApiModelProperty(value = "创建时间", required = true)
private Date createTime; private Date createTime;

View File

@ -80,10 +80,10 @@ public class InfJobDO extends BaseDO {
// ========== 监控相关字段 ========== // ========== 监控相关字段 ==========
/** /**
* 监控超时时间单位毫秒 * 监控超时时间单位毫秒
* 为空时表示不监控
* *
* 注意这里的超时的目的不是进行任务的取消而是告警任务的执行时间过长 * 注意这里的超时的目的不是进行任务的取消而是告警任务的执行时间过长
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Integer monitorTimeout; private Integer monitorTimeout;
// TODO misfirePolicy // TODO misfirePolicy

View File

@ -35,6 +35,9 @@ public class InfJobServiceImpl implements InfJobService {
public Long createJob(InfJobCreateReqVO createReqVO) { public Long createJob(InfJobCreateReqVO createReqVO) {
// 插入 // 插入
InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
if (job.getMonitorTimeout() == null) {
job.setMonitorTimeout(0);
}
jobMapper.insert(job); jobMapper.insert(job);
// 返回 // 返回
return job.getId(); return job.getId();
@ -46,6 +49,9 @@ public class InfJobServiceImpl implements InfJobService {
this.validateJobExists(updateReqVO.getId()); this.validateJobExists(updateReqVO.getId());
// 更新 // 更新
InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO); InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO);
if (updateObj.getMonitorTimeout() == null) {
updateObj.setMonitorTimeout(0);
}
jobMapper.updateById(updateObj); jobMapper.updateById(updateObj);
} }

View File

@ -5,6 +5,11 @@ import cn.iocoder.dashboard.framework.quartz.core.handler.JobHandler;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* 用户 Session 超时 Job
*
* @author 芋道源码
*/
@Component @Component
@Slf4j @Slf4j
public class SysUserSessionTimeoutJob implements JobHandler { public class SysUserSessionTimeoutJob implements JobHandler {

View File

@ -6,7 +6,7 @@ import io.swagger.annotations.*;
import javax.validation.constraints.*; import javax.validation.constraints.*;
## 处理 Date 字段的引入 ## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult})##通用操作 #if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult}
&& ${column.javaType} == "Date")## 时间类型 && ${column.javaType} == "Date")## 时间类型
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;

View File

@ -218,11 +218,13 @@ export default {
// 是否显示弹出层 // 是否显示弹出层
open: false, open: false,
#foreach ($column in $columns)## 时间范围 #foreach ($column in $columns)## 时间范围
#if ($column.listOperation)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN") #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
dateRange${AttrName}: [], dateRange${AttrName}: [],
#end #end
#end #end
#end
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNo: 1, pageNo: 1,
@ -256,11 +258,13 @@ export default {
// 处理查询参数 // 处理查询参数
let params = {...this.queryParams}; let params = {...this.queryParams};
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.listOperation)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN") #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}'); this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}');
#end #end
#end #end
#end
// 执行查询 // 执行查询
get${simpleClassName}Page(params).then(response => { get${simpleClassName}Page(params).then(response => {
this.list = response.data.list; this.list = response.data.list;
@ -277,12 +281,14 @@ export default {
reset() { reset() {
this.form = { this.form = {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [], $column.javaField: [],
#else #else
$column.javaField: undefined, $column.javaField: undefined,
#end #end
#end #end
#end
}; };
this.resetForm("form"); this.resetForm("form");
}, },
@ -294,11 +300,13 @@ export default {
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.listOperation)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN") #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.dateRange${AttrName} = []; this.dateRange${AttrName} = [];
#end #end
#end #end
#end
this.resetForm("queryForm"); this.resetForm("queryForm");
this.handleQuery(); this.handleQuery();
}, },
@ -372,11 +380,13 @@ export default {
params.pageNo = undefined; params.pageNo = undefined;
params.pageSize = undefined; params.pageSize = undefined;
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.listOperation)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN") #if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}'); this.addBeginAndEndTime(params, this.dateRange${AttrName}, '${column.javaField}');
#end #end
#end #end
#end
// 执行导出 // 执行导出
this.$confirm('是否确认导出所有${table.classComment}数据项?', "警告", { this.$confirm('是否确认导出所有${table.classComment}数据项?', "警告", {
confirmButtonText: "确定", confirmButtonText: "确定",