feat: BMS 项目初始化(前端+后端)
- 前端 bms-front:基于 RuoYi-Vue3,封装 BasicForm/BasicTable 公共组件,替换 18 个业务页面表格 - 后端 bms-back:基于 RuoYi-Vue,包含 system/quartz/generator 等模块 - 项目标题由若依管理系统改为 BMS
This commit is contained in:
+132
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24" class="card-box">
|
||||
<el-card>
|
||||
<template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">基本信息</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">Redis版本</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">运行模式</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">端口</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">客户端数</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">运行时间(天)</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">使用内存</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">使用CPU</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">内存配置</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">AOF是否开启</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "否" : "是" }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">RDB是否成功</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">Key数量</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">网络入口/出口</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<template #header><PieChart style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">命令统计</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="commandstats" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<template #header><Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存信息</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="usedmemory" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Cache">
|
||||
import { getCache } from '@/api/monitor/cache'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
const cache = ref([])
|
||||
const commandstats = ref(null)
|
||||
const usedmemory = ref(null)
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
function getList() {
|
||||
proxy.$modal.loading("正在加载缓存监控数据,请稍候!")
|
||||
getCache().then(response => {
|
||||
proxy.$modal.closeLoading()
|
||||
cache.value = response.data
|
||||
|
||||
const commandstatsIntance = echarts.init(commandstats.value, "macarons")
|
||||
commandstatsIntance.setOption({
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "命令",
|
||||
type: "pie",
|
||||
roseType: "radius",
|
||||
radius: [15, 95],
|
||||
center: ["50%", "38%"],
|
||||
data: response.data.commandStats,
|
||||
animationEasing: "cubicInOut",
|
||||
animationDuration: 1000
|
||||
}
|
||||
]
|
||||
})
|
||||
const usedmemoryInstance = echarts.init(usedmemory.value, "macarons")
|
||||
usedmemoryInstance.setOption({
|
||||
tooltip: {
|
||||
formatter: "{b} <br/>{a} : " + cache.value.info.used_memory_human
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "峰值",
|
||||
type: "gauge",
|
||||
min: 0,
|
||||
max: 1000,
|
||||
detail: {
|
||||
formatter: cache.value.info.used_memory_human
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: parseFloat(cache.value.info.used_memory_human),
|
||||
name: "内存消耗"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
window.addEventListener("resize", () => {
|
||||
commandstatsIntance.resize()
|
||||
usedmemoryInstance.resize()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getList()
|
||||
</script>
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="8">
|
||||
<el-card style="height: calc(100vh - 125px)">
|
||||
<template #header>
|
||||
<Collection style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存列表</span>
|
||||
<el-button
|
||||
style="float: right; padding: 3px 0"
|
||||
link
|
||||
type="primary"
|
||||
icon="Refresh"
|
||||
@click="refreshCacheNames()"
|
||||
></el-button>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="cacheNames"
|
||||
:height="tableHeight"
|
||||
highlight-current-row
|
||||
@row-click="getCacheKeys"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
label="序号"
|
||||
width="60"
|
||||
type="index"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="缓存名称"
|
||||
align="center"
|
||||
prop="cacheName"
|
||||
:show-overflow-tooltip="true"
|
||||
:formatter="nameFormatter"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="备注"
|
||||
align="center"
|
||||
prop="remark"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="60"
|
||||
align="center"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleClearCacheName(scope.row)"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-card style="height: calc(100vh - 125px)">
|
||||
<template #header>
|
||||
<Key style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">键名列表</span>
|
||||
<el-button
|
||||
style="float: right; padding: 3px 0"
|
||||
link
|
||||
type="primary"
|
||||
icon="Refresh"
|
||||
@click="refreshCacheKeys()"
|
||||
></el-button>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="subLoading"
|
||||
:data="cacheKeys"
|
||||
:height="tableHeight"
|
||||
highlight-current-row
|
||||
@row-click="handleCacheValue"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
label="序号"
|
||||
width="60"
|
||||
type="index"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
label="缓存键名"
|
||||
align="center"
|
||||
:show-overflow-tooltip="true"
|
||||
:formatter="keyFormatter"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="60"
|
||||
align="center"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleClearCacheKey(scope.row)"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-card :bordered="false" style="height: calc(100vh - 125px)">
|
||||
<template #header>
|
||||
<Document style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存内容</span>
|
||||
<el-button
|
||||
style="float: right; padding: 3px 0"
|
||||
link
|
||||
type="primary"
|
||||
icon="Refresh"
|
||||
@click="handleClearCacheAll()"
|
||||
>清理全部</el-button
|
||||
>
|
||||
</template>
|
||||
<el-form :model="cacheForm">
|
||||
<el-row :gutter="32">
|
||||
<el-col :offset="1" :span="22">
|
||||
<el-form-item label="缓存名称:" prop="cacheName">
|
||||
<el-input v-model="cacheForm.cacheName" :readOnly="true" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :offset="1" :span="22">
|
||||
<el-form-item label="缓存键名:" prop="cacheKey">
|
||||
<el-input v-model="cacheForm.cacheKey" :readOnly="true" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :offset="1" :span="22">
|
||||
<el-form-item label="缓存内容:" prop="cacheValue">
|
||||
<el-input
|
||||
v-model="cacheForm.cacheValue"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
:readOnly="true"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="CacheList">
|
||||
import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/monitor/cache"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const cacheNames = ref([])
|
||||
const cacheKeys = ref([])
|
||||
const cacheForm = ref({})
|
||||
const loading = ref(true)
|
||||
const subLoading = ref(false)
|
||||
const nowCacheName = ref("")
|
||||
const tableHeight = ref(window.innerHeight - 200)
|
||||
|
||||
/** 查询缓存名称列表 */
|
||||
function getCacheNames() {
|
||||
loading.value = true
|
||||
listCacheName().then(response => {
|
||||
cacheNames.value = response.data
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
/** 刷新缓存名称列表 */
|
||||
function refreshCacheNames() {
|
||||
getCacheNames()
|
||||
proxy.$modal.msgSuccess("刷新缓存列表成功")
|
||||
}
|
||||
|
||||
/** 清理指定名称缓存 */
|
||||
function handleClearCacheName(row) {
|
||||
clearCacheName(row.cacheName).then(response => {
|
||||
proxy.$modal.msgSuccess("清理缓存名称[" + row.cacheName + "]成功")
|
||||
getCacheKeys()
|
||||
})
|
||||
}
|
||||
|
||||
/** 查询缓存键名列表 */
|
||||
function getCacheKeys(row) {
|
||||
const cacheName = row !== undefined ? row.cacheName : nowCacheName.value
|
||||
if (cacheName === "") {
|
||||
return
|
||||
}
|
||||
subLoading.value = true
|
||||
listCacheKey(cacheName).then(response => {
|
||||
cacheKeys.value = response.data
|
||||
subLoading.value = false
|
||||
nowCacheName.value = cacheName
|
||||
})
|
||||
}
|
||||
|
||||
/** 刷新缓存键名列表 */
|
||||
function refreshCacheKeys() {
|
||||
getCacheKeys()
|
||||
proxy.$modal.msgSuccess("刷新键名列表成功")
|
||||
}
|
||||
|
||||
/** 清理指定键名缓存 */
|
||||
function handleClearCacheKey(cacheKey) {
|
||||
clearCacheKey(cacheKey).then(response => {
|
||||
proxy.$modal.msgSuccess("清理缓存键名[" + cacheKey + "]成功")
|
||||
getCacheKeys()
|
||||
})
|
||||
}
|
||||
|
||||
/** 列表前缀去除 */
|
||||
function nameFormatter(row) {
|
||||
return row.cacheName.replace(":", "")
|
||||
}
|
||||
|
||||
/** 键名前缀去除 */
|
||||
function keyFormatter(cacheKey) {
|
||||
return cacheKey.replace(nowCacheName.value, "")
|
||||
}
|
||||
|
||||
/** 查询缓存内容详细 */
|
||||
function handleCacheValue(cacheKey) {
|
||||
getCacheValue(nowCacheName.value, cacheKey).then(response => {
|
||||
cacheForm.value = response.data
|
||||
})
|
||||
}
|
||||
|
||||
/** 清理全部缓存 */
|
||||
function handleClearCacheAll() {
|
||||
clearCacheAll().then(response => {
|
||||
proxy.$modal.msgSuccess("清理全部缓存成功")
|
||||
})
|
||||
}
|
||||
|
||||
getCacheNames()
|
||||
</script>
|
||||
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<i-frame v-model:src="url"></i-frame>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import iFrame from '@/components/iFrame'
|
||||
|
||||
import { ref } from 'vue'
|
||||
|
||||
const url = ref(import.meta.env.VITE_APP_BASE_API + '/druid/login.html')
|
||||
</script>
|
||||
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<el-dialog :title="type === 'log' ? '调度日志详细' : '任务详细'" v-model="dialogVisible" width="780px" append-to-body>
|
||||
<div class="detail-wrap">
|
||||
<template v-if="type === 'log'">
|
||||
<!-- 基本信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><InfoFilled /></el-icon> 基本信息
|
||||
</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">日志编号</span><span class="detail-value">{{ form.jobLogId }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">执行状态</span>
|
||||
<el-tag v-if="form.status == 0" type="success" size="small">正常</el-tag>
|
||||
<el-tag v-else type="danger" size="small">失败</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">开始时间</span><span class="detail-value">{{ form.startTime }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">结束时间</span><span class="detail-value">{{ form.endTime }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">记录时间</span><span class="detail-value">{{ form.createTime }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="form.status == 0 && form.startTime && form.endTime">
|
||||
<div class="detail-item"><span class="detail-label">执行耗时</span><span class="detail-value">{{ costTime }} 毫秒</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 任务信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Clock /></el-icon> 任务信息
|
||||
</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">任务名称</span><span class="detail-value">{{ form.jobName }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">任务分组</span>
|
||||
<dict-tag :options="sys_job_group" :value="form.jobGroup" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="24">
|
||||
<div class="detail-item"><span class="detail-label">日志信息</span><span class="detail-value">{{ form.jobMessage }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 调用目标 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Operation /></el-icon> 调用目标
|
||||
</div>
|
||||
<div class="code-body">
|
||||
<div class="code-wrap"><pre class="code-pre">{{ form.invokeTarget || '(无)' }}</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 异常信息 -->
|
||||
<div class="detail-card" v-if="form.status == 1">
|
||||
<div class="detail-card-title error-title">
|
||||
<el-icon><Warning /></el-icon> 异常信息
|
||||
</div>
|
||||
<div class="error-body"><div class="error-msg">{{ form.exceptionInfo }}</div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<!-- 任务配置 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Setting /></el-icon> 任务配置
|
||||
</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">任务编号</span><span class="detail-value">{{ form.jobId }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">任务名称</span><span class="detail-value">{{ form.jobName }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">任务分组</span>
|
||||
<dict-tag :options="sys_job_group" :value="form.jobGroup" />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">执行状态</span>
|
||||
<el-tag v-if="form.status == 0" type="success" size="small">正常</el-tag>
|
||||
<el-tag v-else type="info" size="small">暂停</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 调度信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Calendar /></el-icon> 调度信息
|
||||
</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">cron 表达式</span><span class="detail-value mono">{{ form.cronExpression }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">下次执行时间</span><span class="detail-value">{{ parseTime(form.nextValidTime) }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">执行策略</span>
|
||||
<el-tag v-if="form.misfirePolicy == 0" type="info" size="small">默认策略</el-tag>
|
||||
<el-tag v-else-if="form.misfirePolicy == 1" type="warning" size="small">立即执行</el-tag>
|
||||
<el-tag v-else-if="form.misfirePolicy == 2" type="primary" size="small">执行一次</el-tag>
|
||||
<el-tag v-else-if="form.misfirePolicy == 3" type="danger" size="small">放弃执行</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">并发执行</span>
|
||||
<el-tag v-if="form.concurrent == 0" type="success" size="small">允许</el-tag>
|
||||
<el-tag v-else type="danger" size="small">禁止</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 执行方法 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Operation /></el-icon> 执行方法
|
||||
</div>
|
||||
<div class="code-body">
|
||||
<div class="code-wrap"><pre class="code-pre">{{ form.invokeTarget || '(无)' }}</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 元信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title">
|
||||
<el-icon><Document /></el-icon> 元信息
|
||||
</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">创建人</span><span class="detail-value">{{ form.createBy || '-' }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">创建时间</span><span class="detail-value">{{ form.createTime }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">更新人</span><span class="detail-value">{{ form.updateBy || '-' }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">更新时间</span><span class="detail-value">{{ form.updateTime || '-' }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row" v-if="form.remark">
|
||||
<el-col :span="24">
|
||||
<div class="detail-item"><span class="detail-label">备注</span><span class="detail-value">{{ form.remark }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">关 闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup name="JobDetail">
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
row: { type: Object, default: () => ({}) },
|
||||
// 'job' 任务详细 | 'log' 调度日志详细
|
||||
type: { type: String, default: 'job' }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:visible'])
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val)
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { sys_job_group } = useDict('sys_job_group')
|
||||
|
||||
const form = computed(() => props.row || {})
|
||||
|
||||
const costTime = computed(() => {
|
||||
if (!form.value.startTime || !form.value.endTime) return 0
|
||||
return new Date(form.value.endTime).getTime() - new Date(form.value.startTime).getTime()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.detail-label {
|
||||
width: 80px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,361 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
row-key="jobId"
|
||||
>
|
||||
<template #toolbar="{ selection, ids }">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['monitor:job:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="selection.length !== 1"
|
||||
@click="handleUpdate(selection[0])"
|
||||
v-hasPermi="['monitor:job:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="!selection.length"
|
||||
@click="handleDelete(ids)"
|
||||
v-hasPermi="['monitor:job:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['monitor:job:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="Operation"
|
||||
@click="handleJobLog()"
|
||||
v-hasPermi="['monitor:job:query']"
|
||||
>日志</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<template #col-jobName="{ row }">
|
||||
<a class="link-type" style="cursor:pointer" @click="handleView(row)">{{ row.jobName }}</a>
|
||||
</template>
|
||||
|
||||
<template #col-status="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
@change="handleStatusChange(row)"
|
||||
></el-switch>
|
||||
</template>
|
||||
|
||||
<template #col-action="{ row }">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(row)" v-hasPermi="['monitor:job:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(row.jobId)" v-hasPermi="['monitor:job:remove']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="执行一次" placement="top">
|
||||
<el-button link type="primary" icon="CaretRight" @click="handleRun(row)" v-hasPermi="['monitor:job:changeStatus']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="调度日志" placement="top">
|
||||
<el-button link type="primary" icon="Operation" @click="handleJobLog(row)" v-hasPermi="['monitor:job:query']"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</basic-table>
|
||||
|
||||
<!-- 添加或修改定时任务对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="820px" append-to-body>
|
||||
<el-form ref="jobRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务名称" prop="jobName">
|
||||
<el-input v-model="form.jobName" placeholder="请输入任务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务分组" prop="jobGroup">
|
||||
<el-select v-model="form.jobGroup" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="dict in sys_job_group"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="invokeTarget">
|
||||
<template #label>
|
||||
<span>
|
||||
调用方法
|
||||
<el-tooltip placement="top">
|
||||
<template #content>
|
||||
<div>
|
||||
Bean调用示例:ryTask.ryParams('ry')
|
||||
<br />Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')
|
||||
<br />参数说明:支持字符串,布尔类型,长整型,浮点型,整型
|
||||
</div>
|
||||
</template>
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.invokeTarget" placeholder="请输入调用目标字符串" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="cron表达式" prop="cronExpression">
|
||||
<el-input v-model="form.cronExpression" placeholder="请输入cron执行表达式">
|
||||
<template #append>
|
||||
<el-button type="primary" @click="handleShowCron">
|
||||
生成表达式
|
||||
<i class="el-icon-time el-icon--right"></i>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" v-if="form.jobId !== undefined">
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in sys_job_status"
|
||||
:key="dict.value"
|
||||
:value="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行策略" prop="misfirePolicy">
|
||||
<el-radio-group v-model="form.misfirePolicy">
|
||||
<el-radio-button value="1">立即执行</el-radio-button>
|
||||
<el-radio-button value="2">执行一次</el-radio-button>
|
||||
<el-radio-button value="3">放弃执行</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否并发" prop="concurrent">
|
||||
<el-radio-group v-model="form.concurrent">
|
||||
<el-radio-button value="0">允许</el-radio-button>
|
||||
<el-radio-button value="1">禁止</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="Cron表达式生成器" v-model="openCron" append-to-body destroy-on-close>
|
||||
<crontab ref="crontabRef" @hide="openCron=false" @fill="crontabFill" :expression="expression"></crontab>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 任务详细 -->
|
||||
<job-detail v-model:visible="openView" :row="form" type="job" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Job">
|
||||
import Crontab from '@/components/Crontab'
|
||||
import JobDetail from './detail'
|
||||
import { listJob, getJob, delJob, addJob, updateJob, runJob, changeJobStatus } from "@/api/monitor/job"
|
||||
|
||||
const router = useRouter()
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { sys_job_group, sys_job_status } = useDict("sys_job_group", "sys_job_status")
|
||||
|
||||
const tableRef = ref()
|
||||
const open = ref(false)
|
||||
const title = ref("")
|
||||
const openView = ref(false)
|
||||
const openCron = ref(false)
|
||||
const expression = ref("")
|
||||
|
||||
// 搜索项配置
|
||||
const searchColumns = [
|
||||
{ label: "任务名称", prop: "jobName", component: "input", placeholder: "请输入任务名称", width: "200px" },
|
||||
{ label: "任务组名", prop: "jobGroup", component: "select", dict: "sys_job_group", placeholder: "请选择任务组名", width: "200px" },
|
||||
{ label: "任务状态", prop: "status", component: "select", dict: "sys_job_status", placeholder: "请选择任务状态", width: "200px" }
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{ label: "任务编号", prop: "jobId", align: "center", width: 100 },
|
||||
{ label: "任务名称", prop: "jobName", align: "center" },
|
||||
{ label: "任务组名", prop: "jobGroup", align: "center", dict: "sys_job_group" },
|
||||
{ label: "调用目标字符串", prop: "invokeTarget", align: "center" },
|
||||
{ label: "cron执行表达式", prop: "cronExpression", align: "center" },
|
||||
{ label: "状态", prop: "status", align: "center" },
|
||||
{ label: "操作", prop: "action", align: "center", width: 200, showInToolbar: false }
|
||||
]
|
||||
|
||||
// 查询函数
|
||||
function queryList(params) {
|
||||
return listJob(params)
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
rules: {
|
||||
jobName: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
|
||||
invokeTarget: [{ required: true, message: "调用目标字符串不能为空", trigger: "blur" }],
|
||||
cronExpression: [{ required: true, message: "cron执行表达式不能为空", trigger: "change" }]
|
||||
}
|
||||
})
|
||||
|
||||
const { form, rules } = toRefs(data)
|
||||
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
open.value = false
|
||||
reset()
|
||||
}
|
||||
|
||||
/** 表单重置 */
|
||||
function reset() {
|
||||
form.value = {
|
||||
jobId: undefined,
|
||||
jobName: undefined,
|
||||
jobGroup: undefined,
|
||||
invokeTarget: undefined,
|
||||
cronExpression: undefined,
|
||||
misfirePolicy: '1',
|
||||
concurrent: '1',
|
||||
status: "0"
|
||||
}
|
||||
proxy.resetForm("jobRef")
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset()
|
||||
open.value = true
|
||||
title.value = "添加任务"
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
const jobId = row.jobId
|
||||
getJob(jobId).then(response => {
|
||||
form.value = response.data
|
||||
open.value = true
|
||||
title.value = "修改任务"
|
||||
})
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
proxy.$refs["jobRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (form.value.jobId != undefined) {
|
||||
updateJob(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功")
|
||||
open.value = false
|
||||
tableRef.value.refresh()
|
||||
})
|
||||
} else {
|
||||
addJob(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功")
|
||||
open.value = false
|
||||
tableRef.value.refresh()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(jobIds) {
|
||||
proxy.$modal.confirm('是否确认删除定时任务编号为"' + jobIds + '"的数据项?').then(function () {
|
||||
return delJob(jobIds)
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 任务状态修改
|
||||
function handleStatusChange(row) {
|
||||
let text = row.status === "0" ? "启用" : "停用"
|
||||
proxy.$modal.confirm('确认要"' + text + '""' + row.jobName + '"任务吗?').then(function () {
|
||||
return changeJobStatus(row.jobId, row.status)
|
||||
}).then(() => {
|
||||
proxy.$modal.msgSuccess(text + "成功")
|
||||
}).catch(function () {
|
||||
row.status = row.status === "0" ? "1" : "0"
|
||||
})
|
||||
}
|
||||
|
||||
/* 立即执行一次 */
|
||||
function handleRun(row) {
|
||||
proxy.$modal.confirm('确认要立即执行一次"' + row.jobName + '"任务吗?').then(function () {
|
||||
return runJob(row.jobId, row.jobGroup)
|
||||
}).then(() => {
|
||||
proxy.$modal.msgSuccess("执行成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 任务详细信息 */
|
||||
function handleView(row) {
|
||||
getJob(row.jobId).then(response => {
|
||||
form.value = response.data
|
||||
openView.value = true
|
||||
})
|
||||
}
|
||||
|
||||
/** cron表达式按钮操作 */
|
||||
function handleShowCron() {
|
||||
expression.value = form.value.cronExpression
|
||||
openCron.value = true
|
||||
}
|
||||
|
||||
/** 确定后回传值 */
|
||||
function crontabFill(value) {
|
||||
form.value.cronExpression = value
|
||||
}
|
||||
|
||||
/** 任务日志列表查询 */
|
||||
function handleJobLog(row) {
|
||||
const jobId = row?.jobId || 0
|
||||
router.push('/monitor/job-log/index/' + jobId)
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download("monitor/job/export", {
|
||||
...tableRef.value.getQueryParams()
|
||||
}, `job_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
row-key="jobLogId"
|
||||
:auto-load="false"
|
||||
>
|
||||
<template #toolbar="{ selection, ids }">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="!selection.length"
|
||||
@click="handleDelete(ids)"
|
||||
v-hasPermi="['monitor:job:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:job:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['monitor:job:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Close"
|
||||
@click="handleClose"
|
||||
>关闭</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<template #col-action="{ row }">
|
||||
<el-button link type="primary" icon="View" @click="handleView(row)" v-hasPermi="['monitor:job:query']">详细</el-button>
|
||||
</template>
|
||||
</basic-table>
|
||||
|
||||
<!-- 调度日志详细 -->
|
||||
<job-detail v-model:visible="open" :row="form" type="log" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="JobLog">
|
||||
import JobDetail from './detail'
|
||||
import { getJob } from "@/api/monitor/job"
|
||||
import { listJobLog, delJobLog, cleanJobLog } from "@/api/monitor/jobLog"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { sys_common_status, sys_job_group } = useDict("sys_common_status", "sys_job_group")
|
||||
|
||||
const route = useRoute()
|
||||
const tableRef = ref()
|
||||
const open = ref(false)
|
||||
|
||||
const data = reactive({
|
||||
form: {}
|
||||
})
|
||||
const { form } = toRefs(data)
|
||||
|
||||
// 搜索项配置
|
||||
const searchColumns = [
|
||||
{ label: "任务名称", prop: "jobName", component: "input", placeholder: "请输入任务名称", width: "240px" },
|
||||
{ label: "任务组名", prop: "jobGroup", component: "select", dict: "sys_job_group", placeholder: "请选择任务组名", width: "240px" },
|
||||
{ label: "执行状态", prop: "status", component: "select", dict: "sys_common_status", placeholder: "请选择执行状态", width: "240px" },
|
||||
{ label: "执行时间", prop: "dateRange", component: "daterange", width: "308px" }
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{ label: "日志编号", prop: "jobLogId", align: "center", width: 80 },
|
||||
{ label: "任务名称", prop: "jobName", align: "center" },
|
||||
{ label: "任务组名", prop: "jobGroup", align: "center", dict: "sys_job_group" },
|
||||
{ label: "调用目标字符串", prop: "invokeTarget", align: "center" },
|
||||
{ label: "日志信息", prop: "jobMessage", align: "center" },
|
||||
{ label: "执行状态", prop: "status", align: "center", dict: "sys_common_status" },
|
||||
{ label: "执行时间", prop: "createTime", align: "center", width: 180, parseTime: true },
|
||||
{ label: "操作", prop: "action", align: "center", showInToolbar: false }
|
||||
]
|
||||
|
||||
// 查询函数
|
||||
function queryList(params) {
|
||||
const p = proxy.addDateRange({ ...params }, params.dateRange)
|
||||
delete p.dateRange
|
||||
return listJobLog(p)
|
||||
}
|
||||
|
||||
// 返回按钮
|
||||
function handleClose() {
|
||||
const obj = { path: "/monitor/job" }
|
||||
proxy.$tab.closeOpenPage(obj)
|
||||
}
|
||||
|
||||
/** 详细按钮操作 */
|
||||
function handleView(row) {
|
||||
open.value = true
|
||||
form.value = row
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(jobIds) {
|
||||
proxy.$modal.confirm('是否确认删除调度日志编号为"' + jobIds + '"的数据项?').then(function () {
|
||||
return delJobLog(jobIds)
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 清空按钮操作 */
|
||||
function handleClean() {
|
||||
proxy.$modal.confirm("是否确认清空所有调度日志数据项?").then(function () {
|
||||
return cleanJobLog()
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("清空成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download("monitor/jobLog/export", {
|
||||
...tableRef.value.getQueryParams()
|
||||
}, `job_log_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
// 初始化:从路由参数接收 jobId,异步获取任务名称/组名后加载列表
|
||||
onMounted(() => {
|
||||
const jobId = route.params?.jobId || route.query?.jobId
|
||||
if (jobId !== undefined && jobId != 0) {
|
||||
getJob(jobId).then(response => {
|
||||
tableRef.value.setQueryParams({
|
||||
jobName: response.data.jobName,
|
||||
jobGroup: response.data.jobGroup
|
||||
})
|
||||
tableRef.value.reload()
|
||||
})
|
||||
} else {
|
||||
tableRef.value.reload()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
row-key="infoId"
|
||||
:default-sort="defaultSort"
|
||||
:default-params="defaultParams"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<template #toolbar="{ selection, ids }">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="!selection.length"
|
||||
@click="handleDelete(ids)"
|
||||
v-hasPermi="['monitor:logininfor:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:logininfor:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Unlock"
|
||||
:disabled="selection.length !== 1"
|
||||
@click="handleUnlock(selection)"
|
||||
v-hasPermi="['monitor:logininfor:unlock']"
|
||||
>解锁</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['monitor:logininfor:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
</basic-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Logininfor">
|
||||
import { list, delLogininfor, cleanLogininfor, unlockLogininfor } from "@/api/monitor/logininfor"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { sys_common_status } = useDict("sys_common_status")
|
||||
|
||||
const tableRef = ref()
|
||||
|
||||
// 默认排序
|
||||
const defaultSort = { prop: "loginTime", order: "descending" }
|
||||
|
||||
// 默认查询参数(含排序初始值,重置时由 BasicTable 自动恢复)
|
||||
const defaultParams = {
|
||||
orderByColumn: "loginTime",
|
||||
isAsc: "descending"
|
||||
}
|
||||
|
||||
// 搜索项配置
|
||||
const searchColumns = [
|
||||
{ label: "登录地址", prop: "ipaddr", component: "input", placeholder: "请输入登录地址", width: "240px" },
|
||||
{ label: "用户名称", prop: "userName", component: "input", placeholder: "请输入用户名称", width: "240px" },
|
||||
{ label: "状态", prop: "status", component: "select", dict: "sys_common_status", placeholder: "登录状态", width: "240px" },
|
||||
{ label: "登录时间", prop: "dateRange", component: "daterange", width: "308px" }
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{ label: "访问编号", prop: "infoId", align: "center" },
|
||||
{ label: "用户名称", prop: "userName", align: "center", sortable: "custom" },
|
||||
{ label: "地址", prop: "ipaddr", align: "center" },
|
||||
{ label: "登录地点", prop: "loginLocation", align: "center" },
|
||||
{ label: "操作系统", prop: "os", align: "center" },
|
||||
{ label: "浏览器", prop: "browser", align: "center" },
|
||||
{ label: "登录状态", prop: "status", align: "center", dict: "sys_common_status" },
|
||||
{ label: "描述", prop: "msg", align: "center" },
|
||||
{ label: "访问时间", prop: "loginTime", align: "center", width: 180, sortable: "custom", parseTime: true }
|
||||
]
|
||||
|
||||
// 查询函数
|
||||
function queryList(params) {
|
||||
const p = proxy.addDateRange({ ...params }, params.dateRange)
|
||||
delete p.dateRange
|
||||
return list(p)
|
||||
}
|
||||
|
||||
/** 排序触发事件 */
|
||||
function handleSortChange(column) {
|
||||
tableRef.value.setQueryParams({ orderByColumn: column.prop, isAsc: column.order })
|
||||
tableRef.value.reload()
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(infoIds) {
|
||||
proxy.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?').then(function () {
|
||||
return delLogininfor(infoIds)
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 清空按钮操作 */
|
||||
function handleClean() {
|
||||
proxy.$modal.confirm("是否确认清空所有登录日志数据项?").then(function () {
|
||||
return cleanLogininfor()
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("清空成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 解锁按钮操作 */
|
||||
function handleUnlock(selection) {
|
||||
const username = selection.map(item => item.userName)
|
||||
proxy.$modal.confirm('是否确认解锁用户"' + username + '"数据项?').then(function () {
|
||||
return unlockLogininfor(username)
|
||||
}).then(() => {
|
||||
proxy.$modal.msgSuccess("用户" + username + "解锁成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download("monitor/logininfor/export", {
|
||||
...tableRef.value.getQueryParams()
|
||||
}, `logininfor_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
:selection="false"
|
||||
:show-toolbar="false"
|
||||
show-index
|
||||
>
|
||||
<template #col-action="{ row }">
|
||||
<el-button link type="primary" icon="Delete" @click="handleForceLogout(row)" v-hasPermi="['monitor:online:forceLogout']">强退</el-button>
|
||||
</template>
|
||||
</basic-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Online">
|
||||
import { forceLogout, list as initData } from "@/api/monitor/online"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const tableRef = ref()
|
||||
|
||||
// 搜索项配置
|
||||
const searchColumns = [
|
||||
{ label: "登录地址", prop: "ipaddr", component: "input", placeholder: "请输入登录地址", width: "200px" },
|
||||
{ label: "用户名称", prop: "userName", component: "input", placeholder: "请输入用户名称", width: "200px" }
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{ label: "会话编号", prop: "tokenId", align: "center" },
|
||||
{ label: "登录名称", prop: "userName", align: "center" },
|
||||
{ label: "所属部门", prop: "deptName", align: "center" },
|
||||
{ label: "主机", prop: "ipaddr", align: "center" },
|
||||
{ label: "登录地点", prop: "loginLocation", align: "center" },
|
||||
{ label: "操作系统", prop: "os", align: "center" },
|
||||
{ label: "浏览器", prop: "browser", align: "center" },
|
||||
{ label: "登录时间", prop: "loginTime", align: "center", width: 180, parseTime: true },
|
||||
{ label: "操作", prop: "action", align: "center", showInToolbar: false }
|
||||
]
|
||||
|
||||
// 查询函数(在线用户接口返回全量数据,前端分页切片)
|
||||
function queryList(params) {
|
||||
return initData({ ipaddr: params.ipaddr, userName: params.userName }).then(res => {
|
||||
const start = (params.pageNum - 1) * params.pageSize
|
||||
return {
|
||||
rows: res.rows.slice(start, start + params.pageSize),
|
||||
total: res.total
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 强退按钮操作 */
|
||||
function handleForceLogout(row) {
|
||||
proxy.$modal.confirm('是否确认强退名称为"' + row.userName + '"的用户?').then(function () {
|
||||
return forceLogout(row.tokenId)
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<el-dialog title="操作日志详细" v-model="dialogVisible" width="780px" append-to-body @close="$emit('update:visible', false)">
|
||||
<div class="detail-wrap">
|
||||
<!-- 基本信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title"><el-icon><InfoFilled /></el-icon> 基本信息</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">操作模块</span><span class="detail-value">{{ form.title }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">业务类型</span><span class="detail-value">{{ typeLabel }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">操作时间</span><span class="detail-value">{{ form.operTime }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">执行状态</span>
|
||||
<el-tag v-if="form.status === 0" type="success" size="small">正常</el-tag>
|
||||
<el-tag v-else type="danger" size="small">异常</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 操作人员 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title"><el-icon><User /></el-icon> 操作人员</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">操作人员</span><span class="detail-value">{{ form.operName }}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="form.deptName">
|
||||
<div class="detail-item"><span class="detail-label">所属部门</span><span class="detail-value">{{ form.deptName }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="24">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">操作地址</span>
|
||||
<span class="detail-value">{{ form.operIp }} <span class="detail-location">{{ form.operLocation }}</span></span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 请求信息 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title"><el-icon><Sort /></el-icon> 请求信息</div>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="24">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">请求地址</span>
|
||||
<span class="detail-value">
|
||||
<span :class="'method-tag method-' + form.requestMethod">{{ form.requestMethod }}</span>
|
||||
{{ form.operUrl }}
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="24">
|
||||
<div class="detail-item"><span class="detail-label">操作方法</span><span class="detail-value mono">{{ form.method }}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="detail-row">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item"><span class="detail-label">消耗时间</span><span class="detail-value">{{ form.costTime }} 毫秒</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 请求参数 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title"><el-icon><Upload /></el-icon> 请求参数</div>
|
||||
<div class="code-body">
|
||||
<div class="code-wrap">
|
||||
<div class="code-action">
|
||||
<el-button size="small" :icon="CopyDocument" @click="copyText(form.operParam)">复制</el-button>
|
||||
</div>
|
||||
<pre class="code-pre">{{ formatJson(form.operParam) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回参数 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-title"><el-icon><Download /></el-icon> 返回参数</div>
|
||||
<div class="code-body">
|
||||
<div class="code-wrap">
|
||||
<div class="code-action">
|
||||
<el-button size="small" :icon="CopyDocument" @click="copyText(form.jsonResult)">复制</el-button>
|
||||
</div>
|
||||
<pre class="code-pre">{{ formatJson(form.jsonResult) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 异常信息 -->
|
||||
<div class="detail-card" v-if="form.status !== 0">
|
||||
<div class="detail-card-title error-title"><el-icon><Warning /></el-icon> 异常信息</div>
|
||||
<div class="error-body">
|
||||
<div class="error-msg">{{ form.errorMsg }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
row: { type: Object, default: () => ({}) }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:visible'])
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val)
|
||||
})
|
||||
|
||||
|
||||
const { sys_oper_type } = useDict('sys_oper_type')
|
||||
|
||||
const form = computed(() => props.row || {})
|
||||
const typeLabel = computed(() => selectDictLabel(sys_oper_type.value, form.value.businessType) || '-')
|
||||
|
||||
function formatJson(str) {
|
||||
if (!str) return '(无数据)'
|
||||
try { return JSON.stringify(JSON.parse(str), null, 2) } catch { return str }
|
||||
}
|
||||
|
||||
function copyText(str) {
|
||||
const text = formatJson(str)
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).then(() => ElMessage({ message: '已复制', type: 'success', duration: 1500 }))
|
||||
} else {
|
||||
const ta = document.createElement('textarea')
|
||||
ta.value = text
|
||||
document.body.appendChild(ta)
|
||||
ta.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(ta)
|
||||
ElMessage({ message: '已复制', type: 'success', duration: 1500 })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
row-key="operId"
|
||||
:default-sort="defaultSort"
|
||||
:default-params="defaultParams"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<template #toolbar="{ selection, ids }">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="!selection.length"
|
||||
@click="handleDelete(ids)"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['monitor:operlog:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<template #col-action="{ row }">
|
||||
<el-button link type="primary" icon="View" @click="handleDetail(row)" v-hasPermi="['monitor:operlog:query']">详细</el-button>
|
||||
</template>
|
||||
</basic-table>
|
||||
|
||||
<operlog-detail v-model:visible="detailVisible" :row="detailRow" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Operlog">
|
||||
import OperlogDetail from './detail'
|
||||
import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { sys_oper_type, sys_common_status } = useDict("sys_oper_type", "sys_common_status")
|
||||
|
||||
const tableRef = ref()
|
||||
const detailVisible = ref(false)
|
||||
const detailRow = ref({})
|
||||
|
||||
// 默认排序
|
||||
const defaultSort = { prop: "operTime", order: "descending" }
|
||||
|
||||
// 默认查询参数(含排序初始值,重置时由 BasicTable 自动恢复)
|
||||
const defaultParams = {
|
||||
orderByColumn: "operTime",
|
||||
isAsc: "descending"
|
||||
}
|
||||
|
||||
// 搜索项配置
|
||||
const searchColumns = [
|
||||
{ label: "操作地址", prop: "operIp", component: "input", placeholder: "请输入操作地址", width: "240px" },
|
||||
{ label: "系统模块", prop: "title", component: "input", placeholder: "请输入系统模块", width: "240px" },
|
||||
{ label: "操作人员", prop: "operName", component: "input", placeholder: "请输入操作人员", width: "240px" },
|
||||
{ label: "类型", prop: "businessType", component: "select", dict: "sys_oper_type", placeholder: "操作类型", width: "240px" },
|
||||
{ label: "状态", prop: "status", component: "select", dict: "sys_common_status", placeholder: "操作状态", width: "240px" },
|
||||
{ label: "操作时间", prop: "dateRange", component: "daterange", width: "308px" }
|
||||
]
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{ label: "日志编号", prop: "operId", align: "center" },
|
||||
{ label: "系统模块", prop: "title", align: "center" },
|
||||
{ label: "操作类型", prop: "businessType", align: "center", dict: "sys_oper_type" },
|
||||
{ label: "操作人员", prop: "operName", align: "center", width: 110, sortable: "custom" },
|
||||
{ label: "操作地址", prop: "operIp", align: "center", width: 130 },
|
||||
{ label: "操作状态", prop: "status", align: "center", dict: "sys_common_status" },
|
||||
{ label: "操作日期", prop: "operTime", align: "center", width: 180, sortable: "custom", parseTime: true },
|
||||
{ label: "消耗时间", prop: "costTime", align: "center", width: 110, sortable: "custom", formatter: (row, col, val) => val + '毫秒' },
|
||||
{ label: "操作", prop: "action", align: "center", showInToolbar: false }
|
||||
]
|
||||
|
||||
// 查询函数
|
||||
function queryList(params) {
|
||||
const p = proxy.addDateRange({ ...params }, params.dateRange)
|
||||
delete p.dateRange
|
||||
return list(p)
|
||||
}
|
||||
|
||||
/** 排序触发事件 */
|
||||
function handleSortChange(column) {
|
||||
tableRef.value.setQueryParams({ orderByColumn: column.prop, isAsc: column.order })
|
||||
tableRef.value.reload()
|
||||
}
|
||||
|
||||
/** 详细按钮操作 */
|
||||
function handleDetail(row) {
|
||||
detailRow.value = row
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(operIds) {
|
||||
proxy.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?').then(function () {
|
||||
return delOperlog(operIds)
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("删除成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 清空按钮操作 */
|
||||
function handleClean() {
|
||||
proxy.$modal.confirm("是否确认清空所有操作日志数据项?").then(function () {
|
||||
return cleanOperlog()
|
||||
}).then(() => {
|
||||
tableRef.value.refresh()
|
||||
proxy.$modal.msgSuccess("清空成功")
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download("monitor/operlog/export", {
|
||||
...tableRef.value.getQueryParams()
|
||||
}, `config_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<template #header><Cpu style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">CPU</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">属性</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">值</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">核心数</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">用户使用率</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">系统使用率</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">当前空闲率</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<template #header><Tickets style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">属性</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">内存</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">JVM</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">总内存</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">已用内存</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">剩余内存</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">使用率</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="card-box">
|
||||
<el-card>
|
||||
<template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">服务器信息</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">服务器名称</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">操作系统</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">服务器IP</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">系统架构</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="card-box">
|
||||
<el-card>
|
||||
<template #header><CoffeeCup style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">Java虚拟机信息</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%;table-layout:fixed;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">Java名称</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">Java版本</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">启动时间</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">运行时长</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1" class="el-table__cell is-leaf"><div class="cell">安装路径</div></td>
|
||||
<td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1" class="el-table__cell is-leaf"><div class="cell">项目路径</div></td>
|
||||
<td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1" class="el-table__cell is-leaf"><div class="cell">运行参数</div></td>
|
||||
<td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.inputArgs }}</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="card-box">
|
||||
<el-card>
|
||||
<template #header><MessageBox style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">磁盘状态</span></template>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="el-table__cell el-table__cell is-leaf"><div class="cell">盘符路径</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">文件系统</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">盘符类型</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">总大小</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">可用大小</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">已用大小</div></th>
|
||||
<th class="el-table__cell is-leaf"><div class="cell">已用百分比</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="server.sysFiles">
|
||||
<tr v-for="(sysFile, index) in server.sysFiles" :key="index">
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td>
|
||||
<td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getServer } from '@/api/monitor/server'
|
||||
|
||||
const server = ref([])
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
function getList() {
|
||||
proxy.$modal.loading("正在加载服务监控数据,请稍候!")
|
||||
getServer().then(response => {
|
||||
server.value = response.data
|
||||
proxy.$modal.closeLoading()
|
||||
})
|
||||
}
|
||||
|
||||
getList()
|
||||
</script>
|
||||
Reference in New Issue
Block a user