Skip to content

Commit

Permalink
backup
Browse files Browse the repository at this point in the history
  • Loading branch information
getrebuild committed Dec 22, 2024
1 parent 94cd9bf commit df75ffc
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 30 deletions.
2 changes: 1 addition & 1 deletion @rbv
Submodule @rbv updated from 0695a8 to 2fad20
31 changes: 31 additions & 0 deletions src/main/java/com/rebuild/web/admin/ConfigurationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.integration.QiniuCloud;
import com.rebuild.core.support.integration.SMSender;
import com.rebuild.core.support.setup.DatabaseBackup;
import com.rebuild.core.support.setup.DatafileBackup;
import com.rebuild.utils.CommonsUtils;
import com.rebuild.utils.JSONUtils;
import com.rebuild.utils.RbAssert;
Expand All @@ -46,6 +48,7 @@
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
Expand Down Expand Up @@ -132,6 +135,34 @@ public RespBody postSystems(@RequestBody JSONObject data) {
return RespBody.ok();
}

@PostMapping("systems/backup")
public RespBody postSystemsBackup(HttpServletRequest request) {
RbAssert.isSuperAdmin(getRequestUser(request));
final int type = getIntParameter(request, "type", 3);
final File backups = RebuildConfiguration.getFileOfData("_backups");

String dbFile = null, fileFile = null;
if (type == 1 || type == 3) {
try {
dbFile = "_backups/" + new DatabaseBackup().backup(backups).getName();
} catch (Exception e) {
dbFile = "ERR:" + e.getMessage();
log.error("Executing [DatabaseBackup] fails", e);
}
}
if (type == 2 || type == 3) {
try {
fileFile = "_backups/" + new DatafileBackup().backup(backups).getName();
} catch (Exception e) {
fileFile = "ERR:" + e.getMessage();
log.error("Executing [DataFileBackup] fails", e);
}
}

JSON res = JSONUtils.toJSONObject(new String[]{"db","file"}, new Object[]{dbFile, fileFile});
return RespBody.ok(res);
}

@GetMapping("integration/storage")
public ModelAndView pageIntegrationStorage() {
ModelAndView mv = createModelAndView("/admin/integration/storage-qiniu");
Expand Down
10 changes: 9 additions & 1 deletion src/main/resources/i18n/lang.zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3335,5 +3335,13 @@
"飞书侧配置":"飞书侧配置",
"已有记录":"已有记录",
"存在同名字段,是否继续添加?":"存在同名字段,是否继续添加?",
"安装系统模版将清空您现有系统的所有数据,包括系统配置、业务实体、数据等。安装前强烈建议您做好系统备份。":"安装系统模版将清空您现有系统的所有数据,包括系统配置、业务实体、数据等。安装前强烈建议您做好系统备份。"
"安装系统模版将清空您现有系统的所有数据,包括系统配置、业务实体、数据等。安装前强烈建议您做好系统备份。":"安装系统模版将清空您现有系统的所有数据,包括系统配置、业务实体、数据等。安装前强烈建议您做好系统备份。",
"请勿在业务高峰时段执行备份":"请勿在业务高峰时段执行备份",
"无需提交":"无需提交",
"数据目录文件":"数据目录文件",
"开始备份":"开始备份",
"立即备份":"立即备份",
"数据库":"数据库",
"未备份":"未备份",
"选择要备份哪些数据":"选择要备份哪些数据"
}
11 changes: 9 additions & 2 deletions src/main/resources/web/admin/integration/dingtalk.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
<th:block th:replace="~{/_include/header}" />
<meta name="page-help" content="https://getrebuild.com/docs/admin/integration-dingtalk" />
<title>[[${bundle.L('钉钉')}]]</title>
<style>
.J_syncUsers {
position: absolute;
margin-top: -6px;
margin-left: 6px;
}
</style>
</head>
<body>
<div class="rb-wrapper rb-fixed-sidebar rb-collapsible-sidebar rb-collapsible-sidebar-hide-logo rb-color-header" th:classappend="${sideCollapsedClazz}">
Expand Down Expand Up @@ -70,8 +77,8 @@ <h5>[[${bundle.L('数据同步')}]]</h5>
<tr>
<td width="40%">[[${bundle.L('自动同步部门用户')}]]</td>
<td data-id="DingtalkSyncUsers" th:data-value="${DingtalkSyncUsers}">
<span class="mr-1">[[${DingtalkSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers up-1" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
<span>[[${DingtalkSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
</td>
</tr>
<tr>
Expand Down
11 changes: 9 additions & 2 deletions src/main/resources/web/admin/integration/feishu.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
<th:block th:replace="~{/_include/header}" />
<meta name="page-help" content="https://getrebuild.com/docs/admin/integration-dingtalk" />
<title>[[${bundle.L('飞书')}]]</title>
<style>
.J_syncUsers {
position: absolute;
margin-top: -6px;
margin-left: 6px;
}
</style>
</head>
<body>
<div class="rb-wrapper rb-fixed-sidebar rb-collapsible-sidebar rb-collapsible-sidebar-hide-logo rb-color-header" th:classappend="${sideCollapsedClazz}">
Expand Down Expand Up @@ -65,8 +72,8 @@ <h5>[[${bundle.L('数据同步')}]]</h5>
<tr>
<td width="40%">[[${bundle.L('自动同步部门用户')}]]</td>
<td data-id="FeishuSyncUsers" th:data-value="${FeishuSyncUsers}">
<span class="mr-1">[[${FeishuSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers up-1" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
<span>[[${FeishuSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
</td>
</tr>
<tr>
Expand Down
11 changes: 9 additions & 2 deletions src/main/resources/web/admin/integration/wxwork.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
<th:block th:replace="~{/_include/header}" />
<meta name="page-help" content="https://getrebuild.com/docs/admin/integration-wxwork" />
<title>[[${bundle.L('企业微信')}]]</title>
<style>
.J_syncUsers {
position: absolute;
margin-top: -6px;
margin-left: 6px;
}
</style>
</head>
<body>
<div class="rb-wrapper rb-fixed-sidebar rb-collapsible-sidebar rb-collapsible-sidebar-hide-logo rb-color-header" th:classappend="${sideCollapsedClazz}">
Expand Down Expand Up @@ -70,8 +77,8 @@ <h5>[[${bundle.L('数据同步')}]]</h5>
<tr>
<td width="40%">[[${bundle.L('自动同步部门用户')}]]</td>
<td data-id="WxworkSyncUsers" th:data-value="${WxworkSyncUsers}">
<span class="mr-1">[[${WxworkSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers up-1" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
<span>[[${WxworkSyncUsers ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_syncUsers" type="button"><i class="icon zmdi zmdi-refresh up-1"></i> [[${bundle.L('立即同步')}]]</button>
</td>
</tr>
<tr>
Expand Down
25 changes: 16 additions & 9 deletions src/main/resources/web/admin/system-cfg.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@
padding: 10px 15px;
display: none;
}
td.td-MobileAppPath .J_MobileAppPath-del {
display: none;
.J_backDb,
button.J_MobileAppPath,
button.J_MobileAppPath-del {
position: absolute;
margin-top: -6px;
margin-left: 6px;
}
td.td-MobileAppPath:hover .J_MobileAppPath-del {
display: inline-block;
button.J_MobileAppPath + button.J_MobileAppPath-del {
margin-left: 70px;
}
</style>
</head>
Expand Down Expand Up @@ -242,7 +246,8 @@ <h5>[[${bundle.L('数据安全')}]]</h5>
<tr>
<td width="40%">[[${bundle.L('数据自动备份')}]]</td>
<td data-id="DBBackupsEnable" th:data-value="${DBBackupsEnable}" th:data-form-text="${bundle.L('每日 0 点备份到数据目录,请预留足够磁盘空间')}">
[[${DBBackupsEnable ? bundle.L('是') : bundle.L('否')}]]
<span>[[${DBBackupsEnable ? bundle.L('是') : bundle.L('否')}]]</span>
<button class="btn btn-light btn-sm J_backDb" type="button"><i class="icon mdi mdi-database-clock-outline"></i> [[${bundle.L('立即备份')}]]</button>
</td>
</tr>
<tr>
Expand Down Expand Up @@ -291,10 +296,12 @@ <h5>[[${bundle.L('其他')}]]</h5>
<tr>
<td>[[${bundle.L('APP 安装包')}]] <sup class="rbv"></sup></td>
<td class="td-MobileAppPath">
<a class="J_MobileAppPath hide-empty mr-1 link" target="_blank" href="../h5app-download">[[${MobileAppPath}]]</a>
<input type="file" class="hide J_MobileAppPath" accept=".apk" />
<button class="btn btn-light btn-sm J_MobileAppPath" type="button"><i class="icon zmdi zmdi-upload"></i> [[${bundle.L('上传')}]]<span></span></button>
<button class="btn btn-light w-auto btn-sm J_MobileAppPath-del hide" type="button" th:title="${bundle.L('删除')}"><i class="icon zmdi zmdi-delete"></i></button>
<a>[[${MobileAppPath ?:bundle.L('无')}]]</a>
<button class="btn btn-light btn-sm J_MobileAppPath" type="button"><i class="icon mdi mdi-upload"></i> [[${bundle.L('上传')}]]<span></span></button>
<button class="btn btn-light btn-sm J_MobileAppPath-del w-auto hide" type="button" th:title="${bundle.L('删除')}"><i class="icon mdi mdi-delete"></i></button>
<div class="hide">
<input type="file" class="hide J_MobileAppPath" accept=".apk" />
</div>
</td>
</tr>
</tbody>
Expand Down
74 changes: 61 additions & 13 deletions src/main/resources/web/assets/js/admin/system-cfg.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ $(document).ready(() => {
})
}
})

$('.J_backDb').on('click', () => renderRbcomp(<DlgBackup />))
})

useEditComp = function (name) {
Expand Down Expand Up @@ -285,13 +287,15 @@ class DlgMM extends RbAlert {

$(document).ready(() => {
if (rb.commercial < 1) {
$('button.J_MobileAppPath').attr('disabled', true)
$('.td-MobileAppPath button').remove()
return
}

const renderMobileAppPath = function (key) {
const file = $fileCutName(key)
$('a.J_MobileAppPath').text(file)
$('.td-MobileAppPath>a').text($fileCutName(key)).attr({
href: '../h5app-download',
target: '_blank',
})
$('button.J_MobileAppPath-del').removeClass('hide')
}

Expand All @@ -316,22 +320,66 @@ $(document).ready(() => {
)
$('button.J_MobileAppPath').on('click', () => $input[0].click())

const $del = $('button.J_MobileAppPath-del').on('click', () => {
$('button.J_MobileAppPath-del').on('click', () => {
RbAlert.create($L('确认删除 APP 安装包?'), {
onConfirm: function () {
this.hide()
$.post(location.href, JSON.stringify({ MobileAppPath: '' }), (res) => {
if (res.error_code === 0) {
$('a.J_MobileAppPath').removeAttr('href').text('')
$del.addClass('hide')
} else {
RbHighbar.error(res.error_msg)
}
$.post(location.href, JSON.stringify({ MobileAppPath: '' }), () => {
location.reload()
})
},
})
})

const key = $('a.J_MobileAppPath').text()
if (key) renderMobileAppPath(key)
const apk = $('.td-MobileAppPath>a').text()
if (apk && apk.length > 20) renderMobileAppPath(apk)
})

class DlgBackup extends RbAlert {
state = { ...this.props }

renderContent() {
return (
<form className="rbalert-form-sm">
<div className="form-group mb-0">
<label className="text-bold">{$L('选择要备份哪些数据')}</label>
<div ref={(c) => (this._$bkType = c)}>
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline">
<input className="custom-control-input" type="checkbox" defaultChecked />
<span className="custom-control-label">{$L('数据库')}</span>
</label>
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline">
<input className="custom-control-input" type="checkbox" defaultChecked />
<span className="custom-control-label">{$L('数据目录文件')}</span>
</label>
</div>
</div>
<div className="form-group mb-1">
<div className="text-warning mb-1" ref={(c) => (this._$tips = c)}>
<i className="mdi-alert-outline mdi" /> {$L('请勿在业务高峰时段执行备份')}
</div>
<button type="button" className="btn btn-space btn-primary" onClick={this.confirm} disabled={this.state.disable}>
{$L('开始备份')}
</button>
</div>
</form>
)
}

confirm = () => {
let type = ($(this._$bkType).find('input:eq(0)').prop('checked') ? 1 : 0) + ($(this._$bkType).find('input:eq(1)').prop('checked') ? 2 : 0)
if (type === 0) return

this.disabled(true, true)
$.post(`systems/backup?type=${type}`, (res) => {
if (res.error_code === 0) {
const data = res.data || {}
const tips = [$L('数据库'), ' <code>', data.db || $L('未备份'), '</code><br>', $L('数据目录文件'), ' <code>', data.file || $L('未备份'), '</code>']
$(this._$tips).html(tips.join(''))
} else {
RbHighbar.error(res.error_msg)
}
this.disabled(false, false)
})
}
}

0 comments on commit df75ffc

Please sign in to comment.