Commit c8d517e5 by yuwei

2.0.0项目初始化

parent 05a43fad
......@@ -17,4 +17,6 @@ import lombok.EqualsAndHashCode;
public class QrtzJobLogQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String jobId;
}
......@@ -9,6 +9,7 @@ import cn.datax.service.quartz.api.vo.QrtzJobVo;
import cn.datax.service.quartz.api.query.QrtzJobQuery;
import cn.datax.service.quartz.mapstruct.QrtzJobMapper;
import cn.datax.service.quartz.service.QrtzJobService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -71,6 +72,7 @@ public class QrtzJobController extends BaseController {
@GetMapping("/page")
public R getQrtzJobPage(QrtzJobQuery qrtzJobQuery) {
QueryWrapper<QrtzJobEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StrUtil.isNotBlank(qrtzJobQuery.getJobName()), "job_name", qrtzJobQuery.getJobName());
IPage<QrtzJobEntity> page = qrtzJobService.page(new Page<>(qrtzJobQuery.getPageNum(), qrtzJobQuery.getPageSize()), queryWrapper);
List<QrtzJobVo> collect = page.getRecords().stream().map(qrtzJobMapper::toVO).collect(Collectors.toList());
JsonPage<QrtzJobVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
......
......@@ -9,6 +9,7 @@ import cn.datax.service.quartz.api.vo.QrtzJobLogVo;
import cn.datax.service.quartz.api.query.QrtzJobLogQuery;
import cn.datax.service.quartz.mapstruct.QrtzJobLogMapper;
import cn.datax.service.quartz.service.QrtzJobLogService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -71,6 +72,7 @@ public class QrtzJobLogController extends BaseController {
@GetMapping("/page")
public R getQrtzJobLogPage(QrtzJobLogQuery qrtzJobLogQuery) {
QueryWrapper<QrtzJobLogEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(qrtzJobLogQuery.getJobId()), "job_id", qrtzJobLogQuery.getJobId());
IPage<QrtzJobLogEntity> page = qrtzJobLogService.page(new Page<>(qrtzJobLogQuery.getPageNum(), qrtzJobLogQuery.getPageSize()), queryWrapper);
List<QrtzJobLogVo> collect = page.getRecords().stream().map(qrtzJobLogMapper::toVO).collect(Collectors.toList());
JsonPage<QrtzJobLogVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
......@@ -118,4 +120,12 @@ public class QrtzJobLogController extends BaseController {
qrtzJobLogService.deleteQrtzJobLogById(id);
return R.ok();
}
@ApiOperation(value = "批量删除", notes = "根据url的ids来批量删除对象")
@ApiImplicitParam(name = "ids", value = "ID集合", required = true, dataType = "List", paramType = "path")
@DeleteMapping("/batch/{ids}")
public R deleteQrtzJobLogBatch(@PathVariable List<String> ids) {
qrtzJobLogService.deleteQrtzJobLogBatch(ids);
return R.ok();
}
}
......@@ -4,6 +4,8 @@ import cn.datax.service.quartz.api.entity.QrtzJobLogEntity;
import cn.datax.service.quartz.api.dto.QrtzJobLogDto;
import cn.datax.common.base.BaseService;
import java.util.List;
/**
* <p>
* 定时任务日志信息表 服务类
......@@ -21,4 +23,6 @@ public interface QrtzJobLogService extends BaseService<QrtzJobLogEntity> {
QrtzJobLogEntity getQrtzJobLogById(String id);
void deleteQrtzJobLogById(String id);
void deleteQrtzJobLogBatch(List<String> ids);
}
......@@ -11,6 +11,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 定时任务日志信息表 服务实现类
......@@ -54,4 +56,10 @@ public class QrtzJobLogServiceImpl extends BaseServiceImpl<QrtzJobLogDao, QrtzJo
public void deleteQrtzJobLogById(String id) {
qrtzJobLogDao.deleteById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteQrtzJobLogBatch(List<String> ids) {
qrtzJobLogDao.deleteBatchIds(ids);
}
}
......@@ -14,4 +14,14 @@ public class LogQuery extends BaseQueryParams {
* 日志标题
*/
private String title;
/**
* 所属模块
*/
private String module;
/**
* 用户名称
*/
private String userName;
}
......@@ -63,6 +63,8 @@ public class LogController extends BaseController {
public R getLogPage(LogQuery logQuery) {
QueryWrapper<LogEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StrUtil.isNotBlank(logQuery.getTitle()), "title", logQuery.getTitle());
queryWrapper.like(StrUtil.isNotBlank(logQuery.getModule()), "module", logQuery.getModule());
queryWrapper.like(StrUtil.isNotBlank(logQuery.getUserName()), "user_name", logQuery.getUserName());
IPage<LogEntity> page = logService.page(new Page<>(logQuery.getPageNum(), logQuery.getPageSize()), queryWrapper);
List<LogVo> collect = page.getRecords().stream().map(logMapper::toVO).collect(Collectors.toList());
JsonPage<LogVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
......
import request from '@/utils/request'
export function pageLog (data) {
return request({
url: '/system/login/logs/page',
method: 'get',
params: data
})
}
export function getLog (id) {
return request({
url: '/system/login/logs/' + id,
method: 'get'
})
}
export function delLog (id) {
return request({
url: '/system/login/logs/' + id,
method: 'delete'
})
}
export function delLogs (ids) {
return request({
url: '/system/login/logs/batch/' + ids,
method: 'delete'
})
}
import request from '@/utils/request'
export function pageLog (data) {
return request({
url: '/system/logs/page',
method: 'get',
params: data
})
}
export function getLog (id) {
return request({
url: '/system/logs/' + id,
method: 'get'
})
}
export function delLog (id) {
return request({
url: '/system/logs/' + id,
method: 'delete'
})
}
export function delLogs (ids) {
return request({
url: '/system/logs/batch/' + ids,
method: 'delete'
})
}
import request from '@/utils/request'
export function pageJob (data) {
return request({
url: '/quartz/jobs/page',
method: 'get',
params: data
})
}
export function getJob (id) {
return request({
url: '/quartz/jobs/' + id,
method: 'get'
})
}
export function delJob (id) {
return request({
url: '/quartz/jobs/' + id,
method: 'delete'
})
}
export function addJob (data) {
return request({
url: '/quartz/jobs',
method: 'post',
data: data
})
}
export function updateJob (data) {
return request({
url: '/quartz/jobs/' + data.id,
method: 'put',
data: data
})
}
export function pauseJob (id) {
return request({
url: '/quartz/jobs/pause/' + id,
method: 'post'
})
}
export function resumeJob (id) {
return request({
url: '/quartz/jobs/resume/' + id,
method: 'post'
})
}
export function runJob (id) {
return request({
url: '/quartz/jobs/run/' + id,
method: 'post'
})
}
import request from '@/utils/request'
export function pageLog (data) {
return request({
url: '/quartz/logs/page',
method: 'get',
params: data
})
}
export function getLog (id) {
return request({
url: '/quartz/logs/' + id,
method: 'get'
})
}
export function delLog (id) {
return request({
url: '/quartz/logs/' + id,
method: 'delete'
})
}
export function delLogs (ids) {
return request({
url: '/quartz/logs/batch/' + ids,
method: 'delete'
})
}
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="登录用户" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="操作系统" prop="opOs">
<el-input v-model="form.opOs" />
</el-form-item>
<el-form-item label="浏览器类型" prop="opBrowser">
<el-input v-model="form.opBrowser" />
</el-form-item>
<el-form-item label="登录IP地址" prop="opIp">
<el-input v-model="form.opIp" />
</el-form-item>
<el-form-item label="登录时间" prop="opDate">
<el-input v-model="form.opDate" />
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { getLog } from '@/api/monitor/loginlog'
export default {
name: 'LoginLogDetail',
props: {
data: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
title: '登录日志详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 表单参数
form: {}
}
},
created () {
console.log('id:' + this.data.id)
this.getLog(this.data.id)
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getLog: function (id) {
getLog(id).then(response => {
if (response.success) {
this.form = response.data
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<el-form :model="queryParams" ref="queryForm" :inline="true">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
type="info"
icon="el-icon-view"
size="mini"
:disabled="single"
@click="handleDetail"
v-hasPerm="['monitor:loginlog:detail']"
>详情</el-button>
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleBatchDelete"
v-hasPerm="['monitor:loginlog:remove']"
>删除</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="logList"
@selection-change="handleSelectionChange"
border
tooltip-effect="dark"
:size="tableSize"
:max-height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:prop="item.prop"
:label="item.label"
:key="index"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
v-hasPerm="['monitor:loginlog:detail']"
>详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPerm="['monitor:loginlog:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
></el-pagination>
</el-card>
</div>
</template>
<script>
import { pageLog, delLog, delLogs } from '@/api/monitor/loginlog'
export default {
name: 'LoginLogList',
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
tableHeight: document.body.offsetHeight - 230 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 表格头
tableColumns: [
{ prop: 'userName', label: '登录用户', show: true },
{ prop: 'opOs', label: '操作系统', show: true },
{ prop: 'opBrowser', label: '浏览器类型', show: true },
{ prop: 'opIp', label: '登录IP地址', show: true },
{ prop: 'opDate', label: '登录时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 日志表格数据
logList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
userName: ''
}
}
},
created () {
this.getList()
this.initCols()
},
methods: {
/** 查询日志列表 */
getList () {
this.loading = true
pageLog(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.logList = data.data
this.total = data.total
}
})
},
initCols () {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange (val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand (command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery () {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery () {
this.$refs['queryForm'].resetFields()
this.handleQuery()
},
/** 刷新列表 */
handleRefresh () {
this.getList()
},
/** 多选框选中数据 */
handleSelectionChange (selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 详情按钮操作 */
handleDetail (row) {
this.showOptions.data.id = row.id || this.ids[0]
this.showOptions.showList = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete (row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delLog(row.id)
}).then(() => {
this.$message.success('删除成功')
this.getList()
}).catch(() => {
})
},
/** 批量删除按钮操作 */
handleBatchDelete () {
if (!this.ids.length) {
this.$message({
message: '请先选择需要操作的数据',
type: 'warning'
})
}
this.$message.warning('不支持批量删除')
},
handleSizeChange (val) {
console.log(`每页 ${val} 条`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange (val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
</style>
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<log-list v-if="options.showList" @showCard="showCard"></log-list>
</transition>
<transition name="el-zoom-in-bottom">
<log-detail v-if="options.showDetail" :data="options.data" @showCard="showCard"></log-detail>
</transition>
</div>
</template>
<script>
import LogList from './LogList'
import LogDetail from './LogDetail'
export default {
name: 'LoginLog',
components: { LogList, LogDetail },
data () {
return {
options: {
data: {},
showList: true,
showDetail: false
}
}
},
methods: {
showCard (data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="所属模块" prop="module">
<el-input v-model="form.module" />
</el-form-item>
<el-form-item label="日志标题" prop="title">
<el-input v-model="form.title" />
</el-form-item>
<el-form-item label="用户名称" prop="userName">
<el-input v-model="form.userName" />
</el-form-item>
<el-form-item label="请求IP" prop="remoteAddr">
<el-input v-model="form.remoteAddr" />
</el-form-item>
<el-form-item label="请求URI" prop="requestUri">
<el-input v-model="form.requestUri" />
</el-form-item>
<el-form-item label="方法类名" prop="className">
<el-input v-model="form.className" />
</el-form-item>
<el-form-item label="方法名称" prop="methodName">
<el-input v-model="form.methodName" />
</el-form-item>
<el-form-item label="请求参数" prop="params">
<el-input v-model="form.params" />
</el-form-item>
<el-form-item label="请求耗时" prop="time">
<el-input v-model="form.time" />
</el-form-item>
<el-form-item label="浏览器名称" prop="browser">
<el-input v-model="form.browser" />
</el-form-item>
<el-form-item label="操作系统" prop="os">
<el-input v-model="form.os" />
</el-form-item>
<el-form-item label="错误类型" prop="exCode">
<el-input v-model="form.exCode" />
</el-form-item>
<el-form-item label="错误信息" prop="exMsg">
<el-input v-model="form.exMsg" />
</el-form-item>
<el-form-item label="操作时间" prop="createTime">
<el-input v-model="form.createTime" />
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { getLog } from '@/api/monitor/operlog'
export default {
name: 'OperLogDetail',
props: {
data: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
title: '操作日志详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 表单参数
form: {}
}
},
created () {
console.log('id:' + this.data.id)
this.getLog(this.data.id)
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getLog: function (id) {
getLog(id).then(response => {
if (response.success) {
this.form = response.data
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<el-form :model="queryParams" ref="queryForm" :inline="true">
<el-form-item label="模块名称" prop="module">
<el-input
v-model="queryParams.module"
placeholder="请输入模块名称"
clearable
size="small"
/>
</el-form-item>
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
size="small"
/>
</el-form-item>
<el-form-item label="日志标题" prop="title">
<el-input
v-model="queryParams.title"
placeholder="请输入日志标题"
clearable
size="small"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
type="info"
icon="el-icon-view"
size="mini"
:disabled="single"
@click="handleDetail"
v-hasPerm="['monitor:operlog:detail']"
>详情</el-button>
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleBatchDelete"
v-hasPerm="['monitor:operlog:remove']"
>删除</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="logList"
@selection-change="handleSelectionChange"
border
tooltip-effect="dark"
:size="tableSize"
:max-height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:prop="item.prop"
:label="item.label"
:key="index"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
v-hasPerm="['monitor:operlog:detail']"
>详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPerm="['monitor:operlog:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
></el-pagination>
</el-card>
</div>
</template>
<script>
import { pageLog, delLog, delLogs } from '@/api/monitor/operlog'
export default {
name: 'OperLogList',
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
tableHeight: document.body.offsetHeight - 230 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 表格头
tableColumns: [
{ prop: 'module', label: '所属模块', show: true },
{ prop: 'title', label: '日志标题', show: true },
{ prop: 'userName', label: '用户名称', show: true },
{ prop: 'os', label: '操作系统', show: true },
{ prop: 'browser', label: '浏览器名称', show: true },
{ prop: 'remoteAddr', label: '请求IP', show: true },
{ prop: 'time', label: '请求耗时', show: true },
{ prop: 'createTime', label: '操作时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 日志表格数据
logList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
userName: ''
}
}
},
created () {
this.getList()
this.initCols()
},
methods: {
/** 查询日志列表 */
getList () {
this.loading = true
pageLog(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.logList = data.data
this.total = data.total
}
})
},
initCols () {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange (val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand (command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery () {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery () {
this.$refs['queryForm'].resetFields()
this.handleQuery()
},
/** 刷新列表 */
handleRefresh () {
this.getList()
},
/** 多选框选中数据 */
handleSelectionChange (selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 详情按钮操作 */
handleDetail (row) {
this.showOptions.data.id = row.id || this.ids[0]
this.showOptions.showList = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete (row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delLog(row.id)
}).then(() => {
this.$message.success('删除成功')
this.getList()
}).catch(() => {
})
},
/** 批量删除按钮操作 */
handleBatchDelete () {
if (!this.ids.length) {
this.$message({
message: '请先选择需要操作的数据',
type: 'warning'
})
}
this.$message.warning('不支持批量删除')
},
handleSizeChange (val) {
console.log(`每页 ${val} 条`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange (val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
</style>
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<log-list v-if="options.showList" @showCard="showCard"></log-list>
</transition>
<transition name="el-zoom-in-bottom">
<log-detail v-if="options.showDetail" :data="options.data" @showCard="showCard"></log-detail>
</transition>
</div>
</template>
<script>
import LogList from './LogList'
import LogDetail from './LogDetail'
export default {
name: 'OperLog',
components: { LogList, LogDetail },
data () {
return {
options: {
data: {},
showList: true,
showDetail: false
}
}
},
methods: {
showCard (data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-plus" round @click="submitForm" :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled">{{loadingOptions.loadingText}}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="任务名称" prop="jobName">
<el-input v-model="form.jobName" placeholder="请输入任务名称" />
</el-form-item>
<el-form-item label="Spring Bean名称" prop="beanName">
<el-input v-model="form.beanName" placeholder="请输入Spring Bean名称" />
</el-form-item>
<el-form-item label="方法名称" prop="methodName">
<el-input v-model="form.methodName" placeholder="请输入方法名称" />
</el-form-item>
<el-form-item label="方法参数" prop="methodParams">
<el-input v-model="form.methodParams" placeholder="请输入方法参数" />
</el-form-item>
<el-form-item label="cron表达式" prop="cronExpression">
<el-input v-model="form.cronExpression" placeholder="请输入cron表达式" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { addJob } from '@/api/scheduler/job'
export default {
name: 'JobAdd',
props: {
data: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
title: '任务新增',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showLogList: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {
status: '1'
},
// 表单校验
rules: {
jobName: [
{ required: true, message: '任务名称不能为空', trigger: 'blur' }
],
beanName: [
{ required: true, message: 'Spring Bean名称不能为空', trigger: 'blur' }
],
methodName: [
{ required: true, message: '方法名称不能为空', trigger: 'blur' }
],
cronExpression: [
{ required: true, message: 'cron表达式不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: []
}
},
created () {
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 提交按钮 */
submitForm: function () {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
addJob(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="任务名称" prop="jobName">
<el-input v-model="form.jobName" placeholder="请输入任务名称" />
</el-form-item>
<el-form-item label="Spring Bean名称" prop="beanName">
<el-input v-model="form.beanName" placeholder="请输入Spring Bean名称" />
</el-form-item>
<el-form-item label="方法名称" prop="methodName">
<el-input v-model="form.methodName" placeholder="请输入方法名称" />
</el-form-item>
<el-form-item label="方法参数" prop="methodParams">
<el-input v-model="form.methodParams" placeholder="请输入方法参数" />
</el-form-item>
<el-form-item label="cron表达式" prop="cronExpression">
<el-input v-model="form.cronExpression" placeholder="请输入cron表达式" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { getJob } from '@/api/scheduler/job'
export default {
name: 'JobDetail',
props: {
data: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
title: '任务详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showLogList: false
},
// 表单参数
form: {},
// 状态数据字典
statusOptions: []
}
},
created () {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getJob(this.data.id)
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getJob: function (id) {
getJob(id).then(response => {
if (response.success) {
this.form = response.data
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-plus" round @click="submitForm" :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled">{{loadingOptions.loadingText}}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="任务名称" prop="jobName">
<el-input v-model="form.jobName" placeholder="请输入任务名称" />
</el-form-item>
<el-form-item label="Spring Bean名称" prop="beanName">
<el-input v-model="form.beanName" placeholder="请输入Spring Bean名称" />
</el-form-item>
<el-form-item label="方法名称" prop="methodName">
<el-input v-model="form.methodName" placeholder="请输入方法名称" />
</el-form-item>
<el-form-item label="方法参数" prop="methodParams">
<el-input v-model="form.methodParams" placeholder="请输入方法参数" />
</el-form-item>
<el-form-item label="cron表达式" prop="cronExpression">
<el-input v-model="form.cronExpression" placeholder="请输入cron表达式" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { getJob, updateJob } from '@/api/scheduler/job'
export default {
name: 'JobEdit',
props: {
data: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
title: '任务编辑',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showLogList: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {},
// 表单校验
rules: {
jobName: [
{ required: true, message: '任务名称不能为空', trigger: 'blur' }
],
beanName: [
{ required: true, message: 'Spring Bean名称不能为空', trigger: 'blur' }
],
methodName: [
{ required: true, message: '方法名称不能为空', trigger: 'blur' }
],
cronExpression: [
{ required: true, message: 'cron表达式不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: []
}
},
created () {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getJob(this.data.id)
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getJob: function (id) {
getJob(id).then(response => {
if (response.success) {
this.form = response.data
}
})
},
/** 提交按钮 */
submitForm: function () {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
updateJob(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<job-list v-if="options.showList" @showCard="showCard"></job-list>
</transition>
<transition name="el-zoom-in-top">
<job-add v-if="options.showAdd" :data="options.data" @showCard="showCard"></job-add>
</transition>
<transition name="el-zoom-in-top">
<job-edit v-if="options.showEdit" :data="options.data" @showCard="showCard"></job-edit>
</transition>
<transition name="el-zoom-in-bottom">
<job-detail v-if="options.showDetail" :data="options.data" @showCard="showCard"></job-detail>
</transition>
<transition name="el-zoom-in-center">
<job-log-list v-if="options.showLogList" :data="options.data" @showCard="showCard"></job-log-list>
</transition>
</div>
</template>
<script>
import JobList from './JobList'
import JobAdd from './JobAdd'
import JobEdit from './JobEdit'
import JobDetail from './JobDetail'
import JobLogList from './log/JobLogList'
export default {
name: 'Job',
components: { JobList, JobAdd, JobEdit, JobDetail, JobLogList },
data () {
return {
options: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showLogList: false
}
}
},
methods: {
showCard (data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div>
<el-card class="box-card" shadow="always" :body-style="{ height: bodyHeight }" style="overflow-y: auto;">
<el-form :model="queryParams" ref="queryForm" :inline="true">
<el-form-item label="参数名称" prop="configName">
<el-input
v-model="queryParams.configName"
placeholder="请输入参数名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回主表</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleBatchDelete"
v-hasPerm="['scheduler:log:remove']"
>删除</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="logList"
@selection-change="handleSelectionChange"
border
tooltip-effect="dark"
:size="tableSize"
:max-height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:prop="item.prop"
:label="item.label"
:key="index"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPerm="['scheduler:log:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
></el-pagination>
</el-card>
</div>
</template>
<script>
import { pageLog, delLog } from '@/api/scheduler/log'
export default {
name: 'LogList',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data () {
return {
bodyHeight: document.body.offsetHeight - 130 + 'px',
tableHeight: document.body.offsetHeight - 230 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showLogList: false
},
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 表格头
tableColumns: [
{ prop: 'msg', label: '信息记录', show: true },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'createTime', label: '创建时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 日志表格数据
logList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
configName: ''
}
}
},
created () {
console.log('data:' + JSON.stringify(this.data))
this.queryParams.jobId = this.data.jobId
this.getList()
this.initCols()
},
methods: {
showCard () {
this.$emit('showCard', this.showOptions)
},
/** 查询参数列表 */
getList () {
this.loading = true
pageLog(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.logList = data.data
this.total = data.total
}
})
},
initCols () {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange (val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand (command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery () {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery () {
this.$refs['queryForm'].resetFields()
this.handleQuery()
},
/** 刷新列表 */
handleRefresh () {
this.getList()
},
/** 多选框选中数据 */
handleSelectionChange (selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 删除按钮操作 */
handleDelete (row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delLog(row.id)
}).then(() => {
this.$message.success('删除成功')
this.getList()
}).catch(() => {
})
},
/** 批量删除按钮操作 */
handleBatchDelete () {
if (!this.ids.length) {
this.$message({
message: '请先选择需要操作的数据',
type: 'warning'
})
}
this.$message.warning('不支持批量删除')
},
handleSizeChange (val) {
console.log(`每页 ${val} 条`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange (val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
statusFormatter (row, column, cellValue, index) {
let status = row.status
if (status === '0') {
return <el-tag type="warning">失败</el-tag>
} else {
return <el-tag type="success">成功</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
</style>
......@@ -32,10 +32,10 @@ import DictList from './DictList'
import DictAdd from './DictAdd'
import DictEdit from './DictEdit'
import DictDetail from './DictDetail'
import DictItemList from './DictItemList'
import DictItemAdd from './DictItemAdd'
import DictItemEdit from './DictItemEdit'
import DictItemDetail from './DictItemDetail'
import DictItemList from './item/DictItemList'
import DictItemAdd from './item/DictItemAdd'
import DictItemEdit from './item/DictItemEdit'
import DictItemDetail from './item/DictItemDetail'
export default {
name: 'Dict',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment