optim db backup 、config mail permission

This commit is contained in:
bwcx_jzy 2022-01-24 22:16:25 +08:00
parent f66bb60242
commit 237a405393
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
15 changed files with 102 additions and 41 deletions

View File

@ -1,12 +1,14 @@
# 🚀 版本日志
# 2.8.7 (2022-01-24)
# 2.8.8
### 🐣 新增功能
### 🐞 解决BUG、优化功能
1. 优化定时任务检查逻辑,避免不能正常关闭定时任务
1. 【server】优化定时任务检查逻辑,避免不能正常关闭定时任务
2. 【server】数据库备份新增修改人字段可以表示备份人和还原操作人
3. 【server】邮箱配置权限修改为超级管理员
------

View File

@ -20,7 +20,7 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.jpom.controller.system;
package io.jpom.controller.monitor;
import cn.hutool.core.util.StrUtil;
import cn.jiangzeyin.common.JsonMessage;
@ -33,8 +33,8 @@ import io.jpom.plugin.*;
import io.jpom.service.system.SystemParametersServer;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
@ -62,7 +62,7 @@ public class SystemMailConfigController extends BaseServerController {
* @return json
* @author Hotstrip
*/
@RequestMapping(value = "mail-config-data", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = "mail-config-data", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public String mailConfigData() {
MailAccountModel item = systemParametersServer.getConfig(MailAccountModel.ID, MailAccountModel.class);
@ -72,8 +72,9 @@ public class SystemMailConfigController extends BaseServerController {
return JsonMessage.getString(200, "success", item);
}
@RequestMapping(value = "mailConfig_save.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping(value = "mailConfig_save.json", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
@SystemPermission(superUser = true)
public String listData(MailAccountModel mailAccountModel) {
Assert.notNull(mailAccountModel, "请填写信息,并检查是否填写合法");
Assert.hasText(mailAccountModel.getHost(), "请填写host");

View File

@ -22,7 +22,7 @@
*/
package io.jpom.model.data;
import io.jpom.model.BaseDbModel;
import io.jpom.model.BaseUserModifyDbModel;
import io.jpom.service.h2db.TableName;
/**
@ -31,7 +31,7 @@ import io.jpom.service.h2db.TableName;
* Backup info with H2 database
*/
@TableName(value = "BACKUP_INFO", name = "数据备份")
public class BackupInfoModel extends BaseDbModel {
public class BackupInfoModel extends BaseUserModifyDbModel {
/**
* 备份名称

View File

@ -30,3 +30,5 @@ ALTER TABLE BACKUP_INFO
ADD IF NOT EXISTS baleTimeStamp BIGINT comment '打包时间';
ALTER TABLE BACKUP_INFO
ADD IF NOT EXISTS version varchar(255) comment '服务版本';
ALTER TABLE BACKUP_INFO
ADD IF NOT EXISTS modifyUser VARCHAR(50) comment '操作人';

View File

@ -62,8 +62,10 @@
<a-tooltip title="我在这里" :visible="showOptVisible[record.id]">
<a-space>
<a-button v-if="record.unLockType" type="primary" @click="unlock(record)">解锁节点</a-button>
<a-button v-else class="jpom-node-manage-btn" type="primary" @click="handleNode(record)" :disabled="record.openStatus !== 1"><a-icon type="apartment" />节点管理</a-button>
<a-tooltip v-else title="如果按钮不可用则表示当前节点已经关闭啦,需要去编辑中启用">
<a-button class="jpom-node-manage-btn" type="primary" @click="handleNode(record)" :disabled="record.openStatus !== 1"><a-icon type="apartment" />节点管理</a-button>
</a-tooltip>
<a-tooltip title="需要到编辑中去为一个节点绑定一个 ssh信息才能启用该功能">
<a-button type="primary" @click="handleTerminal(record)" :disabled="!record.sshId"><a-icon type="code" />终端</a-button>
</a-tooltip>

View File

@ -17,13 +17,24 @@
<div ref="filter" class="filter">
<!-- <a-tag color="#2db7f5">项目目录: {{ absPath }}</a-tag>-->
<a-space>
<a-button type="primary" :disabled="!Object.keys(this.tempNode).length" @click="handleUpload">批量上传文件</a-button>
<a-button type="primary" :disabled="!Object.keys(this.tempNode).length" @click="handleZipUpload">上传文件自动解压</a-button>
<a-button type="primary" @click="openRemoteUpload">远程上传</a-button>
<a-button type="primary" @click="loadFileList">刷新表格</a-button>
<a-button type="danger" @click="clearFile">清空目录</a-button>
<a-tooltip title="上传文件">
<a-button type="primary" :disabled="!Object.keys(this.tempNode).length" @click="handleUpload"><a-icon type="upload" /></a-button>
</a-tooltip>
<a-tooltip title="上传压缩包并自动解压">
<a-button type="primary" :disabled="!Object.keys(this.tempNode).length" @click="handleZipUpload"><a-icon type="upload" /><a-icon type="file-zip" /></a-button>
</a-tooltip>
<a-tooltip title="通过 URL 下载远程文件到项目文件夹,需要到节点系统配置->白名单配置中配置允许的 HOST 白名单">
<a-button type="primary" @click="openRemoteUpload"><a-icon type="cloud-download" /></a-button>
</a-tooltip>
<a-tooltip title="刷新文件表格">
<a-button type="primary" @click="loadFileList"><a-icon type="reload" /></a-button>
</a-tooltip>
<a-tooltip title="清空当前目录文件">
<a-button type="danger" @click="clearFile"><a-icon type="delete" /></a-button>
</a-tooltip>
<a-tag color="#2db7f5" v-if="uploadPath">当前目录: {{ uploadPath || "" }}</a-tag>
<div>文件名栏支持右键菜单</div>
</a-space>
</div>
<a-table :data-source="fileList" :loading="loading" :columns="columns" :pagination="false" bordered :rowKey="(record, index) => index">
@ -45,10 +56,20 @@
</a-tooltip>
<template slot="operation" slot-scope="text, record">
<a-space>
<a-tooltip v-if="!record.isDirectory" title="需要到 节点管理中的系统管理的白名单配置中配置允许编辑的文件后缀">
<a-button type="primary" :disabled="!record.textFileEdit" @click="handleEditFile(record)">编辑</a-button>
</a-tooltip>
<a-button v-if="!record.isDirectory" type="primary" @click="handleDownload(record)">下载</a-button>
<template v-if="record.isDirectory">
<a-tooltip title="目录不能编辑">
<a-button type="primary" :disabled="true">编辑</a-button>
</a-tooltip>
<a-tooltip title="还不能下载目录">
<a-button type="primary" :disabled="true">下载</a-button>
</a-tooltip>
</template>
<template v-else>
<a-tooltip title="需要到 节点管理中的系统管理的白名单配置中配置允许编辑的文件后缀">
<a-button type="primary" :disabled="!record.textFileEdit" @click="handleEditFile(record)">编辑</a-button>
</a-tooltip>
<a-button type="primary" @click="handleDownload(record)">下载</a-button>
</template>
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
</a-space>
</template>
@ -171,7 +192,7 @@ export default {
{ title: "文件类型", dataIndex: "isDirectory", width: 100, ellipsis: true, scopedSlots: { customRender: "isDirectory" } },
{ title: "文件大小", dataIndex: "fileSize", width: 120, ellipsis: true, scopedSlots: { customRender: "fileSize" } },
{ title: "修改时间", dataIndex: "modifyTime", width: 180, ellipsis: true },
{ title: "操作", dataIndex: "operation", width: 260, scopedSlots: { customRender: "operation" } },
{ title: "操作", dataIndex: "operation", width: 240, align: "center", scopedSlots: { customRender: "operation" } },
],
rules: {
url: [{ required: true, message: "远程下载Url不为空", trigger: "change" }],

View File

@ -6,6 +6,7 @@
<a-select-option v-for="(nodeName, key) in nodeMap" :key="key">{{ nodeName }}</a-select-option>
</a-select>
<a-input v-model="listQuery['%name%']" placeholder="名称" allowClear class="search-input-item" />
<a-input v-model="listQuery['%autoExecCron%']" placeholder="定时执行" class="search-input-item" />
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
<a-button :loading="loading" type="primary" @click="loadData">搜索</a-button>
</a-tooltip>
@ -123,7 +124,7 @@ export default {
{ title: "名称", dataIndex: "name", ellipsis: true, scopedSlots: { customRender: "name" } },
{ title: "节点名称", dataIndex: "nodeId", ellipsis: true, scopedSlots: { customRender: "nodeId" } },
{ title: "定时执行", dataIndex: "autoExecCron", ellipsis: true, scopedSlots: { customRender: "autoExecCron" } },
{ title: "修改时间", dataIndex: "modifyTimeMillis", width: 170, ellipsis: true, scopedSlots: { customRender: "modifyTimeMillis" } },
{ title: "修改时间", dataIndex: "modifyTimeMillis", width: 170, sorter: true, ellipsis: true, scopedSlots: { customRender: "modifyTimeMillis" } },
{ title: "修改人", dataIndex: "modifyUser", ellipsis: true, scopedSlots: { customRender: "modifyUser" }, width: 120 },
{ title: "最后操作人", dataIndex: "lastRunUser", ellipsis: true, scopedSlots: { customRender: "lastRunUser" } },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 260 },

View File

@ -155,7 +155,7 @@ export default {
{
title: "创建时间",
dataIndex: "createTimeMillis",
sorter: true,
ellipsis: true,
customRender: (text) => {
return parseTime(text);

View File

@ -3,6 +3,8 @@
<div ref="filter" class="filter">
<a-space>
<a-input v-model="listQuery['%name%']" placeholder="名称" allowClear class="search-input-item" />
<a-input v-model="listQuery['%description%']" placeholder="描述" class="search-input-item" />
<a-input v-model="listQuery['%autoExecCron%']" placeholder="定时执行" class="search-input-item" />
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
<a-button :loading="loading" type="primary" @click="loadData">搜索</a-button>
</a-tooltip>

View File

@ -74,10 +74,10 @@ export default {
logVisible: false,
columns: [
{ title: "名称", dataIndex: "scriptName", ellipsis: true, scopedSlots: { customRender: "scriptName" } },
{ title: "执行时间", dataIndex: "createTimeMillis", ellipsis: true, scopedSlots: { customRender: "createTimeMillis" } },
{ title: "执行时间", dataIndex: "createTimeMillis", sorter: true, ellipsis: true, scopedSlots: { customRender: "createTimeMillis" } },
{ title: "触发类型", dataIndex: "triggerExecType", width: 100, ellipsis: true, scopedSlots: { customRender: "triggerExecTypeMap" } },
{ title: "执行人", dataIndex: "modifyUser", ellipsis: true, scopedSlots: { customRender: "modifyUser" } },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 220 },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 200 },
],
};
},

View File

@ -78,7 +78,7 @@ export default {
{
title: "执行时间",
dataIndex: "createTimeMillis",
sorter: true,
ellipsis: true,
customRender: (text) => {
return parseTime(text);
@ -88,6 +88,7 @@ export default {
{
title: "结束时间",
dataIndex: "modifyTimeMillis",
sorter: true,
ellipsis: true,
customRender: (text) => {
return parseTime(text);

View File

@ -4,6 +4,7 @@
<a-space>
<a-input v-model="listQuery['%name%']" placeholder="搜索命令" class="search-input-item" />
<a-input v-model="listQuery['%desc%']" placeholder="描述" class="search-input-item" />
<a-input v-model="listQuery['%autoExecCron%']" placeholder="定时执行" class="search-input-item" />
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
<a-button type="primary" :loading="loading" @click="getCommandData">搜索</a-button>
</a-tooltip>
@ -175,17 +176,27 @@ export default {
columns: [
{ title: "命令名称", dataIndex: "name", ellipsis: true, scopedSlots: { customRender: "name" } },
{ title: "命令描述", dataIndex: "desc", ellipsis: true, scopedSlots: { customRender: "desc" } },
{ title: "定时执行", dataIndex: "autoExecCron", ellipsis: true, scopedSlots: { customRender: "autoExecCron" } },
{
title: "创建时间",
dataIndex: "createTimeMillis",
ellipsis: true,
sorter: true,
customRender: (text) => {
return parseTime(text);
},
width: 170,
},
{
title: "修改时间",
dataIndex: "modifyTimeMillis",
width: 170,
ellipsis: true,
sorter: true,
customRender: (text) => {
return parseTime(text);
},
},
{
title: "最后操作人",
dataIndex: "modifyUser",
@ -193,7 +204,7 @@ export default {
ellipsis: true,
scopedSlots: { customRender: "modifyUser" },
},
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 300 },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 250 },
],
};
},

View File

@ -22,7 +22,9 @@
<template slot="backupType" slot-scope="text" placement="topleft" :title="text">
<span>{{ backupTypeMap[text] }}</span>
</template>
<a-tooltip slot="baleTimeStamp" slot-scope="text" placement="topLeft" :title="`${parseTime(text)}`"> {{ parseTime(text) }} </a-tooltip>
<template slot="baleTimeStamp" slot-scope="text, reocrd">
<a-tooltip placement="topLeft" :title="`${parseTime(text)}`"> {{ parseTime(text) }} {{ reocrd.version }} </a-tooltip>
</template>
<a-tooltip slot="status" slot-scope="text, reocrd" placement="topLeft" :title="`${backupStatusMap[text]} 点击复制文件路径`">
<div
v-clipboard:copy="reocrd.filePath"
@ -131,17 +133,17 @@ export default {
title: "打包时间",
width: 170,
dataIndex: "baleTimeStamp",
ellipsis: true,
// ellipsis: true,
sorter: true,
scopedSlots: { customRender: "baleTimeStamp" },
},
{
title: "版本",
dataIndex: "version",
width: 100,
// ellipsis: true,
scopedSlots: { customRender: "version" },
},
// {
// title: "",
// dataIndex: "version",
// width: 100,
// // ellipsis: true,
// scopedSlots: { customRender: "version" },
// },
{ title: "备份类型", dataIndex: "backupType", width: 100, ellipsis: true, scopedSlots: { customRender: "backupType" } },
{
title: "文件大小",
@ -158,6 +160,7 @@ export default {
// ellipsis: true,
// scopedSlots: { customRender: "filePath" },
// },
{ title: "修改人", dataIndex: "modifyUser", ellipsis: true, scopedSlots: { customRender: "modifyUser" }, width: 120 },
{
title: "备份时间",
dataIndex: "createTimeMillis",

View File

@ -130,6 +130,17 @@ export default {
columns: [
{ title: "名称", dataIndex: "name", ellipsis: true, scopedSlots: { customRender: "name" } },
{ title: "描述", dataIndex: "description", ellipsis: true, scopedSlots: { customRender: "description" } },
{ title: "修改人", dataIndex: "modifyUser", ellipsis: true, scopedSlots: { customRender: "modifyUser" }, width: 120 },
{
title: "创建时间",
dataIndex: "createTimeMillis",
sorter: true,
ellipsis: true,
customRender: (text) => {
return parseTime(text);
},
width: 170,
},
{
title: "修改时间",
dataIndex: "modifyTimeMillis",
@ -143,7 +154,7 @@ export default {
sorter: true,
width: 180,
},
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: "300px" },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 250 },
],
envVarColumns: [
{ title: "名称", dataIndex: "name", ellipsis: true, scopedSlots: { customRender: "name" } },

View File

@ -30,8 +30,12 @@
<a-switch size="small" checked-children="" un-checked-children="" :checked="record.systemUser == 1" />
</template>
<a-tooltip slot="id" slot-scope="text" :title="text">
<span>{{ text }}</span></a-tooltip
>
<span>{{ text }}</span>
</a-tooltip>
<a-tooltip slot="email" slot-scope="text" :title="text">
<span>{{ text }}</span>
</a-tooltip>
</a-table>
<!-- 编辑区 -->
<a-modal v-model="editUserVisible" width="800px" title="编辑用户" @ok="handleEditUserOk" :maskClosable="false">
@ -155,7 +159,7 @@ export default {
{ title: "ID", dataIndex: "id", ellipsis: true, width: 150, scopedSlots: { customRender: "id" } },
{ title: "昵称", dataIndex: "name", ellipsis: true },
{ title: "管理员", dataIndex: "systemUser", ellipsis: true, width: 90, scopedSlots: { customRender: "systemUser" } },
{ title: "邮箱", dataIndex: "email", ellipsis: true, width: 150 },
{ title: "邮箱", dataIndex: "email", ellipsis: true, width: 150, scopedSlots: { customRender: "email" } },
{ title: "创建人", dataIndex: "parent", ellipsis: true, width: 150 },
{
title: "修改时间",
@ -165,7 +169,7 @@ export default {
customRender: (text) => {
return parseTime(text);
},
width: 150,
width: 170,
},
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 260 },
],