feature(1.2.7): 新增 WEB 模块 - 后台任务
- 新增数据表:cron_task; - 后台新增后台任务模块,支持(创建、编辑、启用/禁用、列表); - 调整项目初始化,使其支持安装后台任务模块; - 调整服务升级指引,1.2.6 -> 1.2.7;
This commit is contained in:
299
assets/templates/cron_task/cron_task_add.html
Normal file
299
assets/templates/cron_task/cron_task_add.html
Normal file
@@ -0,0 +1,299 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">新增后台任务</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="name">任务名称</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="60" id="name"
|
||||
placeholder="请输入任务名称">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="protocol">选择任务执行方式</label>
|
||||
<select class="form-control" id="protocol">
|
||||
<option value="1">SHELL</option>
|
||||
<option value="2">HTTP</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group http_method">
|
||||
<label for="http_method">选择 HTTP 请求方式</label>
|
||||
<select class="form-control" id="http_method">
|
||||
<option value="0">请选择</option>
|
||||
<option value="1">GET</option>
|
||||
<option value="2">POST</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="spec">任务表达式</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="60" id="spec"
|
||||
placeholder="请输入任务表达式,例如:*/5 * * * *">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="command">命令</label>
|
||||
<textarea class="form-control maxlength" maxlength="250" rows="2" id="command"
|
||||
placeholder="请输入任务表达式,例如:/usr/local/bin/php /data/web/artisan consoleCommand"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="timeout">超时时间(单位:秒)</label>
|
||||
<input type="text" class="form-control" id="timeout"
|
||||
placeholder="请输入超时时间,例如:180">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="retry_times">重试次数</label>
|
||||
<input type="text" class="form-control" id="retry_times"
|
||||
placeholder="请输入重试次数,例如:3">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="retry_interval">重试间隔(单位:秒)</label>
|
||||
<input type="text" class="form-control" id="retry_interval"
|
||||
placeholder="请输入重试间隔,例如:60">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notify_status">执行结束是否通知</label>
|
||||
<select class="form-control" id="notify_status">
|
||||
<option value="1">不通知</option>
|
||||
<option value="2">失败通知</option>
|
||||
<option value="3">结束通知</option>
|
||||
<option value="4">结果关键字匹配通知</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_type">
|
||||
<label for="notify_type">通知方式</label>
|
||||
<select class="form-control" id="notify_type">
|
||||
<option value="0">请选择</option>
|
||||
<option value="1">邮件</option>
|
||||
<option value="2">webhook</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_receiver_email">
|
||||
<label for="notify_receiver_email">通知者邮箱地址(多个用,分割)</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="255" id="notify_receiver_email"
|
||||
placeholder="请输入邮箱地址">
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_keyword">
|
||||
<label for="notify_keyword">匹配关键字(多个用,分割)</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="255" id="notify_keyword"
|
||||
placeholder="请输入匹配关键字">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>状态</label>
|
||||
<div class="clearfix">
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" id="statusOne" value="1" name="is_used"
|
||||
class="custom-control-input"
|
||||
checked="">
|
||||
<label class="custom-control-label" for="statusOne">启用</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" id="statusTwo" value="-1" name="is_used"
|
||||
class="custom-control-input">
|
||||
<label class="custom-control-label" for="statusTwo">禁用</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="remark">备注</label>
|
||||
<textarea class="form-control maxlength" maxlength="100" rows="3" id="remark"
|
||||
placeholder="备注"></textarea>
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$(".maxlength").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$(".http_method").hide();
|
||||
|
||||
$("#protocol").change(function () {
|
||||
if ($(this).val() === "2") {
|
||||
$(".http_method").show();
|
||||
} else {
|
||||
$("#http_method").val(0);
|
||||
$(".http_method").hide();
|
||||
}
|
||||
})
|
||||
|
||||
$(".notify_type").hide();
|
||||
$(".notify_receiver_email").hide();
|
||||
$(".notify_keyword").hide();
|
||||
|
||||
$("#notify_status").change(function () {
|
||||
if ($(this).val() === "1") {
|
||||
$(".notify_type").hide();
|
||||
$("#notify_type").val(0)
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
$(".notify_keyword").hide();
|
||||
$("#notify_keyword").val("");
|
||||
} else if($(this).val() === "2" || $(this).val() === "3") {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").hide();
|
||||
$("#notify_keyword").val("");
|
||||
|
||||
if (("#notify_type").val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
}
|
||||
} else if($(this).val() === "4") {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").show();
|
||||
|
||||
if (("#notify_type").val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#notify_type").change(function (){
|
||||
if ($(this).val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const name = $("#name").val();
|
||||
if (name === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入任务名称。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const spec = $("#spec").val();
|
||||
if (spec === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入任务表达式。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const command = $("#command").val();
|
||||
if (spec === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入命令。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
name: name,
|
||||
spec: spec,
|
||||
command: command,
|
||||
protocol: $("#protocol").val(),
|
||||
http_method: $("#http_method").val(),
|
||||
timeout: $("#timeout").val(),
|
||||
retry_times: $("#retry_times").val(),
|
||||
retry_interval: $("#retry_interval").val(),
|
||||
notify_status: $("#notify_status").val(),
|
||||
notify_type: $("#notify_type").val(),
|
||||
notify_receiver_email: $("#notify_receiver_email").val(),
|
||||
notify_keyword: $("#notify_keyword").val(),
|
||||
is_used: $("input[name='is_used']:checked").val(),
|
||||
remark: $("#remark").val(),
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/cron",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 创建完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.href = "/cron/list";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
349
assets/templates/cron_task/cron_task_edit.html
Normal file
349
assets/templates/cron_task/cron_task_edit.html
Normal file
@@ -0,0 +1,349 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">编辑后台任务</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="name">任务名称</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="60" id="name"
|
||||
placeholder="请输入任务名称">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="protocol">选择任务执行方式</label>
|
||||
<select class="form-control" id="protocol">
|
||||
<option value="1">SHELL</option>
|
||||
<option value="2">HTTP</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group http_method">
|
||||
<label for="http_method">选择 HTTP 请求方式</label>
|
||||
<select class="form-control" id="http_method">
|
||||
<option value="0">请选择</option>
|
||||
<option value="1">GET</option>
|
||||
<option value="2">POST</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="spec">任务表达式</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="60" id="spec"
|
||||
placeholder="请输入任务表达式,例如:*/5 * * * *">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="command">命令</label>
|
||||
<textarea class="form-control maxlength" maxlength="250" rows="2" id="command"
|
||||
placeholder="请输入任务表达式,例如:/usr/local/bin/php /data/web/artisan consoleCommand"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="timeout">超时时间(单位:秒)</label>
|
||||
<input type="text" class="form-control" id="timeout"
|
||||
placeholder="请输入超时时间,例如:180">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="retry_times">重试次数</label>
|
||||
<input type="text" class="form-control" id="retry_times"
|
||||
placeholder="请输入重试次数,例如:3">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="retry_interval">重试间隔(单位:秒)</label>
|
||||
<input type="text" class="form-control" id="retry_interval"
|
||||
placeholder="请输入重试间隔,例如:60">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notify_status">执行结束是否通知</label>
|
||||
<select class="form-control" id="notify_status">
|
||||
<option value="1">不通知</option>
|
||||
<option value="2">失败通知</option>
|
||||
<option value="3">结束通知</option>
|
||||
<option value="4">结果关键字匹配通知</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_type">
|
||||
<label for="notify_type">通知方式</label>
|
||||
<select class="form-control" id="notify_type">
|
||||
<option value="0">请选择</option>
|
||||
<option value="1">邮件</option>
|
||||
<option value="2">webhook</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_receiver_email">
|
||||
<label for="notify_receiver_email">通知者邮箱地址(多个用,分割)</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="255" id="notify_receiver_email"
|
||||
placeholder="请输入邮箱地址">
|
||||
</div>
|
||||
|
||||
<div class="form-group notify_keyword">
|
||||
<label for="notify_keyword">匹配关键字(多个用,分割)</label>
|
||||
<input type="text" class="form-control maxlength" maxlength="255" id="notify_keyword"
|
||||
placeholder="请输入匹配关键字">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>状态</label>
|
||||
<div class="clearfix">
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" id="statusOne" value="1" name="is_used"
|
||||
class="custom-control-input">
|
||||
<label class="custom-control-label" for="statusOne">启用</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input type="radio" id="statusTwo" value="-1" name="is_used"
|
||||
class="custom-control-input">
|
||||
<label class="custom-control-label" for="statusTwo">禁用</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="remark">备注</label>
|
||||
<textarea class="form-control maxlength" maxlength="100" rows="3" id="remark"
|
||||
placeholder="备注"></textarea>
|
||||
</div>
|
||||
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
|
||||
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
|
||||
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
执行中...
|
||||
</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
const hash_id = {{ .HashID }}
|
||||
|
||||
$(".maxlength").maxlength({
|
||||
warningClass: "badge badge-info",
|
||||
limitReachedClass: "badge badge-warning"
|
||||
});
|
||||
|
||||
$("#protocol").change(function () {
|
||||
if ($(this).val() === "2") {
|
||||
$(".http_method").show();
|
||||
} else {
|
||||
$("#http_method").val(0);
|
||||
$(".http_method").hide();
|
||||
}
|
||||
})
|
||||
|
||||
$("#notify_status").change(function () {
|
||||
if ($(this).val() === "1") {
|
||||
$(".notify_type").hide();
|
||||
$("#notify_type").val(0)
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
$(".notify_keyword").hide();
|
||||
$("#notify_keyword").val("");
|
||||
} else if($(this).val() === "2" || $(this).val() === "3") {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").hide();
|
||||
$("#notify_keyword").val("");
|
||||
|
||||
if (("#notify_type").val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
}
|
||||
} else if($(this).val() === "4") {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").show();
|
||||
|
||||
if (("#notify_type").val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
$("#notify_receiver_email").val("");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#notify_type").change(function (){
|
||||
if ($(this).val() === "1") {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
}
|
||||
});
|
||||
|
||||
AjaxForm(
|
||||
"GET",
|
||||
"/api/cron/" + hash_id,
|
||||
"",
|
||||
function () {},
|
||||
function (data) {
|
||||
$("#name").val(data.name);
|
||||
$("#protocol").val(data.protocol);
|
||||
if (data.protocol === 1) {
|
||||
$(".http_method").hide();
|
||||
}
|
||||
|
||||
$("#http_method").val(data.http_method);
|
||||
$("#spec").val(data.spec);
|
||||
$("#command").val(data.command);
|
||||
$("#timeout").val(data.timeout);
|
||||
$("#retry_times").val(data.retry_times);
|
||||
$("#retry_interval").val(data.retry_interval);
|
||||
$("#notify_status").val(data.notify_status);
|
||||
if (data.notify_status === 1) {
|
||||
$(".notify_type").hide();
|
||||
$(".notify_receiver_email").hide();
|
||||
$(".notify_keyword").hide();
|
||||
} else if (data.notify_status === 2 || data.notify_status === 3) {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").hide();
|
||||
|
||||
if (data.notify_type === 1) {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
}
|
||||
} else if (data.notify_status === 4) {
|
||||
$(".notify_type").show();
|
||||
$(".notify_keyword").show();
|
||||
|
||||
if (data.notify_type === 1) {
|
||||
$(".notify_receiver_email").show();
|
||||
} else {
|
||||
$(".notify_receiver_email").hide();
|
||||
}
|
||||
}
|
||||
|
||||
$("#notify_type").val(data.notify_type);
|
||||
$("#notify_receiver_email").val(data.notify_receiver_email);
|
||||
$("#notify_keyword").val(data.notify_keyword);
|
||||
$("input[name='is_used'][value='"+data.is_used+"']").attr("checked", true);
|
||||
$("#remark").val(data.remark);
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const name = $("#name").val();
|
||||
if (name === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入任务名称。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const spec = $("#spec").val();
|
||||
if (spec === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入任务表达式。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const command = $("#command").val();
|
||||
if (spec === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入命令。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
id:hash_id,
|
||||
name: name,
|
||||
spec: spec,
|
||||
command: command,
|
||||
protocol: $("#protocol").val(),
|
||||
http_method: $("#http_method").val(),
|
||||
timeout: $("#timeout").val(),
|
||||
retry_times: $("#retry_times").val(),
|
||||
retry_interval: $("#retry_interval").val(),
|
||||
notify_status: $("#notify_status").val(),
|
||||
notify_type: $("#notify_type").val(),
|
||||
notify_receiver_email: $("#notify_receiver_email").val(),
|
||||
notify_keyword: $("#notify_keyword").val(),
|
||||
is_used: $("input[name='is_used']:checked").val(),
|
||||
remark: $("#remark").val(),
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/cron/" + hash_id,
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 信息修改成功。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.href = "/cron/list";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
284
assets/templates/cron_task/cron_task_list.html
Normal file
284
assets/templates/cron_task/cron_task_list.html
Normal file
@@ -0,0 +1,284 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar d-flex flex-column flex-md-row">
|
||||
<div class="toolbar-btn-action">
|
||||
<a class="btn btn-primary m-r-5" href="/cron/add"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>编号</th>
|
||||
<th>任务名称</th>
|
||||
<th>cron 表达式</th>
|
||||
<th>执行方式</th>
|
||||
<th>超时限制(秒)</th>
|
||||
<th>重试次数</th>
|
||||
<th>重试间隔(秒)</th>
|
||||
<th>通知方式</th>
|
||||
<th>创建人</th>
|
||||
<th>创建日期</th>
|
||||
<th style="text-align: center; ">可用状态</th>
|
||||
<th style="text-align: center; ">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="tbody">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
<ul class="pagination" id="paginationDiv">
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
// 加载列表页数据
|
||||
getPageListData();
|
||||
|
||||
// 提示工具
|
||||
$('[data-toggle="popover"]').popover();
|
||||
|
||||
//$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
function getPageListData(page = 0, page_size = 0) {
|
||||
|
||||
if (parseInt(page) < 1) {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
if (parseInt(page_size) < 1) {
|
||||
page_size = 10;
|
||||
}
|
||||
|
||||
AjaxFormNoAsync(
|
||||
"GET",
|
||||
"/api/cron",
|
||||
{page: page, page_size: page_size},
|
||||
function () {
|
||||
},
|
||||
function (data) {
|
||||
if (data.list.length > 0) {
|
||||
var totalNum = data.pagination.total; //总条数
|
||||
var pageNum = Math.ceil(totalNum / data.pagination.pre_page_count); //分页的总页数
|
||||
|
||||
$("#paginationDiv").pagination({
|
||||
current: data.pagination.current_page,
|
||||
pageCount: pageNum,
|
||||
coping: true,
|
||||
homePage: '首页',
|
||||
endPage: '末页',
|
||||
mode: 'fixed',
|
||||
prevContent: '上一页',
|
||||
nextContent: '下一页',
|
||||
activeCls: 'pageActive',
|
||||
prevCls: 'pagePrev',
|
||||
nextCls: 'pageNext',
|
||||
callback: function (api) {
|
||||
$(".tbody").html("");
|
||||
getPageListData(api.getCurrent());
|
||||
}
|
||||
});
|
||||
|
||||
$.each(data.list, function (index, value) {
|
||||
var showUsedBadge = "";
|
||||
var showProtocolBadge = "";
|
||||
var optionUsedName = "";
|
||||
var notifyBadge = "";
|
||||
|
||||
if (value.is_used === 1) {
|
||||
optionUsedName = '禁用';
|
||||
showUsedBadge = '<span class="badge badge-success">启用</span>';
|
||||
}
|
||||
|
||||
if (value.is_used === -1) {
|
||||
optionUsedName = '启用';
|
||||
showUsedBadge = '<span class="badge badge-danger">禁用</span>';
|
||||
}
|
||||
|
||||
if (value.protocol === 1) {
|
||||
showProtocolBadge = '<span class="badge btn-brown">SHELL</span>';
|
||||
}
|
||||
|
||||
if (value.protocol === 2) {
|
||||
showProtocolBadge = '<span class="badge btn-warning">HTTP</span> ';
|
||||
showProtocolBadge += '<span class="badge btn-secondary">' + value.http_method_text + '</span>';
|
||||
}
|
||||
|
||||
notifyBadge = '<span class="badge btn-cyan">' + value.notify_status_text + '</span>';
|
||||
|
||||
const tr = '<tr>\n' +
|
||||
'<td>' + value.id + '</td>\n' +
|
||||
'<td>' + value.name + '</td>\n' +
|
||||
'<td>' + value.spec + ' <a tabindex="' + value.id + '" role="button" class="badge btn-secondary" data-toggle="popover" data-trigger="focus" title="' + value.spec + '" data-content="' + value.command + '">命令</a></td>\n' +
|
||||
'<td>' + showProtocolBadge + '</td>\n' +
|
||||
'<td>' + value.timeout + '</td>\n' +
|
||||
'<td>' + value.retry_times + '</td>\n' +
|
||||
'<td>' + value.retry_interval + '</td>\n' +
|
||||
'<td>' + notifyBadge + '</td>\n' +
|
||||
'<td>' + value.created_user + '</td>\n' +
|
||||
'<td>' + value.created_at + '</td>\n' +
|
||||
'<td style="text-align: center; ">' + showUsedBadge + '</td>\n' +
|
||||
'<td style="text-align: center; ">\n' +
|
||||
'<div class="btn-group">\n' +
|
||||
' <a class="btn btn-xs btn-default btn-option" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-is-used="' + value.is_used + '"' +
|
||||
' data-toggle="tooltip" data-original-title="' + optionUsedName + '">' + optionUsedName + '</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-edit" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="编辑">编辑</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-log" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="日志">日志</a>\n' +
|
||||
' <a class="btn btn-xs btn-default btn-exec" href="#!" title=""\n' +
|
||||
' data-id="' + value.hashid + '"' +
|
||||
' data-toggle="tooltip" data-original-title="手动执行">手动执行</a>\n' +
|
||||
'</div>\n' +
|
||||
'</td>\n' +
|
||||
'</tr>';
|
||||
|
||||
$(".tbody").append(tr);
|
||||
})
|
||||
} else {
|
||||
// 数据为空
|
||||
const tr = '<tr><td colspan="12" style="text-align: center">暂无数据</td></tr>';
|
||||
$(".tbody").append(tr);
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 启用/禁用
|
||||
$(document).on('click', '.btn-option', function () {
|
||||
const id = $(this).attr('data-id');
|
||||
const isUsed = $(this).attr('data-is-used');
|
||||
|
||||
var tipMessage = "";
|
||||
var wantUsed = 0;
|
||||
if (isUsed === "1") { // 1=当前为启用状态,需要改成禁用
|
||||
tipMessage = "禁用";
|
||||
wantUsed = -1;
|
||||
}
|
||||
if (isUsed === "-1") { // -1=当前为禁用状态,需要改成启用
|
||||
tipMessage = "启用";
|
||||
wantUsed = 1;
|
||||
}
|
||||
|
||||
const patchData = {
|
||||
id: id,
|
||||
used: wantUsed,
|
||||
};
|
||||
|
||||
$.confirm({
|
||||
title: '谨慎操作',
|
||||
content: '确认要 <strong style="color: red">' + tipMessage + '</strong> 吗?',
|
||||
icon: 'mdi mdi-alert',
|
||||
animation: 'scale',
|
||||
closeAnimation: 'zoom',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '确认',
|
||||
keys: ['enter'],
|
||||
btnClass: 'btn-orange',
|
||||
action: function () {
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/cron/used",
|
||||
patchData,
|
||||
function () {
|
||||
},
|
||||
function (data) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '编号:' + data.id + ' 已' + tipMessage + '。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '取消',
|
||||
keys: ['ctrl', 'shift'],
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 编辑
|
||||
$(document).on('click', '.btn-edit', function () {
|
||||
location.href = "/cron/edit/" + $(this).attr('data-id');
|
||||
});
|
||||
|
||||
// 日志
|
||||
$(document).on('click', '.btn-log', function () {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '功能开发中...',
|
||||
});
|
||||
})
|
||||
|
||||
// 手动执行
|
||||
$(document).on('click', '.btn-exec', function () {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '功能开发中...',
|
||||
});
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -108,7 +108,8 @@
|
||||
<code>admin</code>、
|
||||
<code>menu</code>、
|
||||
<code>menu_action</code>、
|
||||
<code>admin_menu</code>;
|
||||
<code>admin_menu</code>、
|
||||
<code>cron_task</code>;
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -83,7 +83,16 @@
|
||||
->
|
||||
<span class="badge badge-pill badge-warning">v1.2.7</span>
|
||||
</p>
|
||||
<p>......</p>
|
||||
|
||||
<p>1、源代码升级:
|
||||
<mark>拉取最新代码,覆盖旧版本代码即可。</mark>
|
||||
</p>
|
||||
<p>2、数据表升级:
|
||||
<mark class="btn btn-xs btn-info upgrade" data-op="table" data-table="cron_task">创建 cron_task 表结构</mark>
|
||||
</p>
|
||||
<p>3、系统管理员->菜单管理,新增侧边栏:后台任务模块,同时添加菜单栏的功能权限。</p>
|
||||
<p>4、系统管理员->管理员,对管理员进行菜单授权。</p>
|
||||
<p>5、退出重新登录,即可以看到自己新增的模块。</p>
|
||||
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ package configs
|
||||
|
||||
const (
|
||||
// ProjectVersion 项目版本
|
||||
ProjectVersion = "v1.2.6"
|
||||
ProjectVersion = "v1.2.7"
|
||||
|
||||
// ProjectName 项目名称
|
||||
ProjectName = "go-gin-api"
|
||||
|
||||
99
internal/api/controller/cron_handler/func_create.go
Executable file
99
internal/api/controller/cron_handler/func_create.go
Executable file
@@ -0,0 +1,99 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
Name string `form:"name" binding:"required"` // 任务名称
|
||||
Spec string `form:"spec" binding:"required"` // crontab 表达式
|
||||
Command string `form:"command" binding:"required"` // 执行命令
|
||||
Protocol int32 `form:"protocol" binding:"required"` // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 `form:"http_method"` // http 请求方式 1:get 2:post
|
||||
Timeout int32 `form:"timeout" binding:"required"` // 超时时间(单位:秒)
|
||||
RetryTimes int32 `form:"retry_times" binding:"required"` // 重试次数
|
||||
RetryInterval int32 `form:"retry_interval" binding:"required"` // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 `form:"notify_status" binding:"required"` // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 `form:"notify_type"` // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string `form:"notify_receiver_email"` // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string `form:"notify_keyword"` // 通知匹配关键字(多个用,分割)
|
||||
Remark string `form:"remark"` // 备注
|
||||
IsUsed int32 `form:"is_used" binding:"required"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Create 创建任务
|
||||
// @Summary 创建任务
|
||||
// @Description 创建任务
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param name formData string true "任务名称"
|
||||
// @Param spec formData string true "crontab 表达式"
|
||||
// @Param command formData string true "执行命令"
|
||||
// @Param protocol formData int true "执行方式 1:shell 2:http"
|
||||
// @Param http_method formData int false "http 请求方式 1:get 2:post"
|
||||
// @Param timeout formData int true "超时时间(单位:秒)"
|
||||
// @Param retry_times formData int true "重试次数"
|
||||
// @Param retry_interval formData int true "重试间隔(单位:秒)"
|
||||
// @Param notify_status formData int true "执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知"
|
||||
// @Param notify_type formData int false "通知类型 1:邮件 2:webhook"
|
||||
// @Param notify_receiver_email formData string false "通知者邮箱地址(多个用,分割)"
|
||||
// @Param notify_keyword formData string false "通知匹配关键字(多个用,分割)"
|
||||
// @Param remark formData string false "备注"
|
||||
// @Param is_used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(cron_service.CreateCronTaskData)
|
||||
createData.Name = req.Name
|
||||
createData.Spec = req.Spec
|
||||
createData.Command = req.Command
|
||||
createData.Protocol = req.Protocol
|
||||
createData.HttpMethod = req.HttpMethod
|
||||
createData.Timeout = req.Timeout
|
||||
createData.RetryTimes = req.RetryTimes
|
||||
createData.RetryInterval = req.RetryInterval
|
||||
createData.NotifyStatus = req.NotifyStatus
|
||||
createData.NotifyType = req.NotifyType
|
||||
createData.NotifyReceiverEmail = req.NotifyReceiverEmail
|
||||
createData.NotifyKeyword = req.NotifyKeyword
|
||||
createData.Remark = req.Remark
|
||||
createData.IsUsed = req.IsUsed
|
||||
|
||||
id, err := h.cronService.Create(ctx, createData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CronCreateError,
|
||||
code.Text(code.CronCreateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
99
internal/api/controller/cron_handler/func_detail.go
Executable file
99
internal/api/controller/cron_handler/func_detail.go
Executable file
@@ -0,0 +1,99 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type detailRequest struct {
|
||||
Id string `uri:"id"` // HashID
|
||||
}
|
||||
|
||||
type detailResponse struct {
|
||||
Name string `json:"name"` // 任务名称
|
||||
Spec string `json:"spec"` // crontab 表达式
|
||||
Command string `json:"command"` // 执行命令
|
||||
Protocol int32 `json:"protocol"` // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 `json:"http_method"` // http 请求方式 1:get 2:post
|
||||
Timeout int32 `json:"timeout"` // 超时时间(单位:秒)
|
||||
RetryTimes int32 `json:"retry_times"` // 重试次数
|
||||
RetryInterval int32 `json:"retry_interval"` // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 `json:"notify_status"` // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 `json:"notify_type"` // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string `json:"notify_receiver_email"` // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string `json:"notify_keyword"` // 通知匹配关键字(多个用,分割)
|
||||
Remark string `json:"remark"` // 备注
|
||||
IsUsed int32 `json:"is_used"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
// Detail 获取单条任务详情
|
||||
// @Summary 获取单条任务详情
|
||||
// @Description 获取单条任务详情
|
||||
// @Tags API.cron
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/:id [get]
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(detailRequest)
|
||||
res := new(detailResponse)
|
||||
if err := ctx.ShouldBindURI(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchOneData := new(cron_service.SearchOneData)
|
||||
searchOneData.Id = cast.ToInt32(ids[0])
|
||||
|
||||
info, err := h.cronService.Detail(ctx, searchOneData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CronDetailError,
|
||||
code.Text(code.CronDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Name = info.Name
|
||||
res.Spec = info.Spec
|
||||
res.Command = info.Command
|
||||
res.Protocol = info.Protocol
|
||||
res.HttpMethod = info.HttpMethod
|
||||
res.Timeout = info.Timeout
|
||||
res.RetryTimes = info.RetryTimes
|
||||
res.RetryInterval = info.RetryInterval
|
||||
res.NotifyStatus = info.NotifyStatus
|
||||
res.NotifyType = info.NotifyType
|
||||
res.NotifyReceiverEmail = info.NotifyReceiverEmail
|
||||
res.NotifyKeyword = info.NotifyKeyword
|
||||
res.Remark = info.Remark
|
||||
res.IsUsed = info.IsUsed
|
||||
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
165
internal/api/controller/cron_handler/func_list.go
Executable file
165
internal/api/controller/cron_handler/func_list.go
Executable file
@@ -0,0 +1,165 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type listRequest struct {
|
||||
Page int `form:"page"` // 第几页
|
||||
PageSize int `form:"page_size"` // 每页显示条数
|
||||
Name string `form:"name"` // 任务名称
|
||||
Protocol int `form:"protocol"` // 执行方式 1:shell 2:http
|
||||
IsUsed int `form:"is_used"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
Id int `json:"id"` // ID
|
||||
HashID string `json:"hashid"` // hashid
|
||||
Name string `json:"name"` // 任务名称
|
||||
Protocol int `json:"protocol"` // 执行方式 1:shell 2:http
|
||||
ProtocolText string `json:"protocol_text"` // 执行方式
|
||||
Spec string `json:"spec"` // crontab 表达式
|
||||
Command string `json:"command"` // 执行命令
|
||||
HttpMethod int `json:"http_method"` // http 请求方式 1:get 2:post
|
||||
HttpMethodText string `json:"http_method_text"` // http 请求方式
|
||||
Timeout int `json:"timeout"` // 超时时间(单位:秒)
|
||||
RetryTimes int `json:"retry_times"` // 重试次数
|
||||
RetryInterval int `json:"retry_interval"` // 重试间隔(单位:秒)
|
||||
NotifyStatus int `json:"notify_status"` // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyStatusText string `json:"notify_status_text"` // 执行结束是否通知
|
||||
IsUsed int `json:"is_used"` // 是否启用 1=启用 2=禁用
|
||||
IsUsedText string `json:"is_used_text"` // 是否启用
|
||||
CreatedAt string `json:"created_at"` // 创建时间
|
||||
CreatedUser string `json:"created_user"` // 创建人
|
||||
UpdatedAt string `json:"updated_at"` // 更新时间
|
||||
UpdatedUser string `json:"updated_user"` // 更新人
|
||||
}
|
||||
|
||||
type listResponse struct {
|
||||
List []listData `json:"list"`
|
||||
Pagination struct {
|
||||
Total int `json:"total"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PrePageCount int `json:"pre_page_count"`
|
||||
} `json:"pagination"`
|
||||
}
|
||||
|
||||
// List 任务列表
|
||||
// @Summary 任务列表
|
||||
// @Description 任务列表
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param name query string false "任务名称"
|
||||
// @Param protocol query int false "执行方式 1:shell 2:http"
|
||||
// @Param is_used query int false "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron [get]
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
page := req.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := req.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(cron_service.SearchData)
|
||||
searchData.Page = req.Page
|
||||
searchData.PageSize = req.PageSize
|
||||
searchData.Name = req.Name
|
||||
searchData.Protocol = cast.ToInt32(req.Protocol)
|
||||
searchData.IsUsed = cast.ToInt32(req.IsUsed)
|
||||
|
||||
resListData, err := h.cronService.PageList(ctx, searchData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CronListError,
|
||||
code.Text(code.CronListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.cronService.PageListCount(ctx, searchData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CronListError,
|
||||
code.Text(code.CronListError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Pagination.Total = cast.ToInt(resCountData)
|
||||
res.Pagination.PrePageCount = pageSize
|
||||
res.Pagination.CurrentPage = page
|
||||
res.List = make([]listData, len(resListData))
|
||||
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
data := listData{
|
||||
Id: cast.ToInt(v.Id),
|
||||
HashID: hashId,
|
||||
Name: v.Name,
|
||||
Protocol: cast.ToInt(v.Protocol),
|
||||
ProtocolText: cron_task_repo.ProtocolText[v.Protocol],
|
||||
Spec: v.Spec,
|
||||
Command: v.Command,
|
||||
HttpMethod: cast.ToInt(v.HttpMethod),
|
||||
HttpMethodText: cron_task_repo.HttpMethodText[v.HttpMethod],
|
||||
Timeout: cast.ToInt(v.Timeout),
|
||||
RetryTimes: cast.ToInt(v.RetryTimes),
|
||||
RetryInterval: cast.ToInt(v.RetryInterval),
|
||||
NotifyStatus: cast.ToInt(v.NotifyStatus),
|
||||
NotifyStatusText: cron_task_repo.NotifyStatusText[v.NotifyStatus],
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
IsUsedText: cron_task_repo.IsUsedText[v.IsUsed],
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
res.List[k] = data
|
||||
}
|
||||
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
111
internal/api/controller/cron_handler/func_modify.go
Executable file
111
internal/api/controller/cron_handler/func_modify.go
Executable file
@@ -0,0 +1,111 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type modifyRequest struct {
|
||||
Id string `form:"id" binding:"required"` // 任务ID
|
||||
Name string `form:"name" binding:"required"` // 任务名称
|
||||
Spec string `form:"spec" binding:"required"` // crontab 表达式
|
||||
Command string `form:"command" binding:"required"` // 执行命令
|
||||
Protocol int32 `form:"protocol" binding:"required"` // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 `form:"http_method"` // http 请求方式 1:get 2:post
|
||||
Timeout int32 `form:"timeout" binding:"required"` // 超时时间(单位:秒)
|
||||
RetryTimes int32 `form:"retry_times" binding:"required"` // 重试次数
|
||||
RetryInterval int32 `form:"retry_interval" binding:"required"` // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 `form:"notify_status" binding:"required"` // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 `form:"notify_type"` // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string `form:"notify_receiver_email"` // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string `form:"notify_keyword"` // 通知匹配关键字(多个用,分割)
|
||||
Remark string `form:"remark"` // 备注
|
||||
IsUsed int32 `form:"is_used" binding:"required"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type modifyResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// Modify 编辑任务
|
||||
// @Summary 编辑任务
|
||||
// @Description 编辑任务
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param name formData string true "任务名称"
|
||||
// @Param spec formData string true "crontab 表达式"
|
||||
// @Param command formData string true "执行命令"
|
||||
// @Param protocol formData int true "执行方式 1:shell 2:http"
|
||||
// @Param http_method formData int false "http 请求方式 1:get 2:post"
|
||||
// @Param timeout formData int true "超时时间(单位:秒)"
|
||||
// @Param retry_times formData int true "重试次数"
|
||||
// @Param retry_interval formData int true "重试间隔(单位:秒)"
|
||||
// @Param notify_status formData int true "执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知"
|
||||
// @Param notify_type formData int false "通知类型 1:邮件 2:webhook"
|
||||
// @Param notify_receiver_email formData string false "通知者邮箱地址(多个用,分割)"
|
||||
// @Param notify_keyword formData string false "通知匹配关键字(多个用,分割)"
|
||||
// @Param remark formData string false "备注"
|
||||
// @Param is_used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} modifyResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/{id} [post]
|
||||
func (h *handler) Modify() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(modifyRequest)
|
||||
res := new(modifyResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
modifyData := new(cron_service.ModifyCronTaskData)
|
||||
modifyData.Name = req.Name
|
||||
modifyData.Spec = req.Spec
|
||||
modifyData.Command = req.Command
|
||||
modifyData.Protocol = req.Protocol
|
||||
modifyData.HttpMethod = req.HttpMethod
|
||||
modifyData.Timeout = req.Timeout
|
||||
modifyData.RetryTimes = req.RetryTimes
|
||||
modifyData.RetryInterval = req.RetryInterval
|
||||
modifyData.NotifyStatus = req.NotifyStatus
|
||||
modifyData.NotifyType = req.NotifyType
|
||||
modifyData.NotifyReceiverEmail = req.NotifyReceiverEmail
|
||||
modifyData.NotifyKeyword = req.NotifyKeyword
|
||||
modifyData.Remark = req.Remark
|
||||
modifyData.IsUsed = req.IsUsed
|
||||
|
||||
if err := h.cronService.Modify(ctx, id, modifyData); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CronUpdateError,
|
||||
code.Text(code.CronUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
70
internal/api/controller/cron_handler/func_updateused.go
Executable file
70
internal/api/controller/cron_handler/func_updateused.go
Executable file
@@ -0,0 +1,70 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
Id string `form:"id"` // 主键ID
|
||||
Used int32 `form:"used"` // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
type updateUsedResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// UpdateUsed 更新任务为启用/禁用
|
||||
// @Summary 更新任务为启用/禁用
|
||||
// @Description 更新任务为启用/禁用
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/used [patch]
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
err = h.cronService.UpdateUsed(ctx, id, req.Used)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminUpdateError,
|
||||
code.Text(code.AdminUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
61
internal/api/controller/cron_handler/handler.go
Normal file
61
internal/api/controller/cron_handler/handler.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// Create 创建任务
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// Modify 编辑任务
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron/{id} [post]
|
||||
Modify() core.HandlerFunc
|
||||
|
||||
// List 任务列表
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron [get]
|
||||
List() core.HandlerFunc
|
||||
|
||||
// UpdateUsed 更新任务为启用/禁用
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron/used [patch]
|
||||
UpdateUsed() core.HandlerFunc
|
||||
|
||||
// Detail 获取单条任务详情
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron/:id [get]
|
||||
Detail() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
hashids hash.Hash
|
||||
cronService cron_service.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
cronService: cron_service.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
937
internal/api/repository/db_repo/cron_task_repo/gen_cron_task.go
Executable file
937
internal/api/repository/db_repo/cron_task_repo/gen_cron_task.go
Executable file
@@ -0,0 +1,937 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package cron_task_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *CronTask {
|
||||
return new(CronTask)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *cronTaskRepoQueryBuilder {
|
||||
return new(cronTaskRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *CronTask) Create(db *gorm.DB) (id int32, err error) {
|
||||
if err = db.Create(t).Error; err != nil {
|
||||
return 0, errors.Wrap(err, "create err")
|
||||
}
|
||||
return t.Id, nil
|
||||
}
|
||||
|
||||
type cronTaskRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
|
||||
ret := db
|
||||
for _, where := range qb.where {
|
||||
ret = ret.Where(where.prefix, where.value)
|
||||
}
|
||||
for _, order := range qb.order {
|
||||
ret = ret.Order(order)
|
||||
}
|
||||
ret = ret.Limit(qb.limit).Offset(qb.offset)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
db = db.Model(&CronTask{})
|
||||
|
||||
for _, where := range qb.where {
|
||||
db.Where(where.prefix, where.value)
|
||||
}
|
||||
|
||||
if err = db.Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
|
||||
for _, where := range qb.where {
|
||||
db = db.Where(where.prefix, where.value)
|
||||
}
|
||||
|
||||
if err = db.Delete(&CronTask{}).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&CronTask{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) First(db *gorm.DB) (*CronTask, error) {
|
||||
ret := &CronTask{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) QueryOne(db *gorm.DB) (*CronTask, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*CronTask, error) {
|
||||
var ret []*CronTask
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) Limit(limit int) *cronTaskRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) Offset(offset int) *cronTaskRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereIdIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereIdNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderById(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereName(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "name", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNameIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "name", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNameNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "name", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByName(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "name "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereSpec(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "spec", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereSpecIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "spec", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereSpecNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "spec", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderBySpec(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "spec "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCommand(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "command", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCommandIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "command", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCommandNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "command", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByCommand(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "command "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereProtocol(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "protocol", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereProtocolIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "protocol", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereProtocolNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "protocol", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByProtocol(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "protocol "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereHttpMethod(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "http_method", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereHttpMethodIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "http_method", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereHttpMethodNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "http_method", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByHttpMethod(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "http_method "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereTimeout(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "timeout", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereTimeoutIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "timeout", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereTimeoutNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "timeout", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByTimeout(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "timeout "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryTimes(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_times", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryTimesIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_times", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryTimesNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_times", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByRetryTimes(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "retry_times "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryInterval(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_interval", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryIntervalIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_interval", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRetryIntervalNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "retry_interval", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByRetryInterval(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "retry_interval "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyStatus(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_status", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyStatusIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_status", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyStatusNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_status", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByNotifyStatus(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "notify_status "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyType(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_type", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyTypeIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_type", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyTypeNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_type", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByNotifyType(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "notify_type "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyReceiverEmail(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_receiver_email", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyReceiverEmailIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_receiver_email", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyReceiverEmailNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_receiver_email", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByNotifyReceiverEmail(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "notify_receiver_email "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyKeyword(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_keyword", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyKeywordIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_keyword", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereNotifyKeywordNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "notify_keyword", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByNotifyKeyword(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "notify_keyword "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRemark(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRemarkIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereRemarkNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "remark", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByRemark(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "remark "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereIsUsed(p db_repo.Predicate, value int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereIsUsedIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereIsUsedNotIn(value []int32) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_used", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByIsUsed(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_used "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByCreatedAt(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedUserIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByCreatedUser(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_user "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByUpdatedAt(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedUser(p db_repo.Predicate, value string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedUserIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) WhereUpdatedUserNotIn(value []string) *cronTaskRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_user", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *cronTaskRepoQueryBuilder) OrderByUpdatedUser(asc bool) *cronTaskRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_user "+order)
|
||||
return qb
|
||||
}
|
||||
27
internal/api/repository/db_repo/cron_task_repo/gen_model.go
Executable file
27
internal/api/repository/db_repo/cron_task_repo/gen_model.go
Executable file
@@ -0,0 +1,27 @@
|
||||
package cron_task_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// CronTask 后台任务表
|
||||
//go:generate gormgen -structs CronTask -input .
|
||||
type CronTask struct {
|
||||
Id int32 // 主键
|
||||
Name string // 任务名称
|
||||
Spec string // crontab 表达式
|
||||
Command string // 执行命令
|
||||
Protocol int32 // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 // http 请求方式 1:get 2:post
|
||||
Timeout int32 // 超时时间(单位:秒)
|
||||
RetryTimes int32 // 重试次数
|
||||
RetryInterval int32 // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string // 通知匹配关键字(多个用,分割)
|
||||
Remark string // 备注
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
CreatedUser string // 创建人
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
UpdatedUser string // 更新人
|
||||
}
|
||||
24
internal/api/repository/db_repo/cron_task_repo/gen_table.md
Executable file
24
internal/api/repository/db_repo/cron_task_repo/gen_table.md
Executable file
@@ -0,0 +1,24 @@
|
||||
#### go_gin_api.cron_task
|
||||
后台任务表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | name | 任务名称 | varchar(64) | MUL | NO | | |
|
||||
| 3 | spec | crontab 表达式 | varchar(64) | | NO | | |
|
||||
| 4 | command | 执行命令 | varchar(255) | | NO | | |
|
||||
| 5 | protocol | 执行方式 1:shell 2:http | tinyint unsigned | | NO | | 1 |
|
||||
| 6 | http_method | http 请求方式 1:get 2:post | tinyint unsigned | | NO | | 1 |
|
||||
| 7 | timeout | 超时时间(单位:秒) | int unsigned | | NO | | 60 |
|
||||
| 8 | retry_times | 重试次数 | tinyint(1) | | NO | | 3 |
|
||||
| 9 | retry_interval | 重试间隔(单位:秒) | int | | NO | | 60 |
|
||||
| 10 | notify_status | 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知 | tinyint unsigned | | NO | | 0 |
|
||||
| 11 | notify_type | 通知类型 1:邮件 2:webhook | tinyint unsigned | | NO | | 1 |
|
||||
| 12 | notify_receiver_email | 通知者邮箱地址(多个用,分割) | varchar(255) | | NO | | |
|
||||
| 13 | notify_keyword | 通知匹配关键字(多个用,分割) | varchar(255) | | NO | | |
|
||||
| 14 | remark | 备注 | varchar(100) | | NO | | |
|
||||
| 15 | is_used | 是否启用 1:是 -1:否 | tinyint(1) | | NO | | 1 |
|
||||
| 16 | created_at | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
||||
| 17 | created_user | 创建人 | varchar(60) | | NO | | |
|
||||
| 18 | updated_at | 更新时间 | timestamp | | NO | DEFAULT_GENERATED on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
| 19 | updated_user | 更新人 | varchar(60) | | NO | | |
|
||||
47
internal/api/repository/db_repo/cron_task_repo/model.go
Normal file
47
internal/api/repository/db_repo/cron_task_repo/model.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package cron_task_repo
|
||||
|
||||
const (
|
||||
ProtocolShell = 1
|
||||
ProtocolHTTP = 2
|
||||
|
||||
HttpMethodGet = 1
|
||||
HttpMethodPost = 2
|
||||
|
||||
NotifyStatusNo = 1
|
||||
NotifyStatusFailed = 2
|
||||
NotifyStatusStopped = 3
|
||||
NotifyStatusKeyword = 4
|
||||
|
||||
NotifyTypeEmail = 1
|
||||
NotifyTypeWebhook = 2
|
||||
|
||||
IsUsedYES = 1
|
||||
IsUsedNo = -1
|
||||
)
|
||||
|
||||
var ProtocolText = map[int32]string{
|
||||
ProtocolShell: "SHELL",
|
||||
ProtocolHTTP: "HTTP",
|
||||
}
|
||||
|
||||
var HttpMethodText = map[int32]string{
|
||||
HttpMethodGet: "GET",
|
||||
HttpMethodPost: "POST",
|
||||
}
|
||||
|
||||
var NotifyStatusText = map[int32]string{
|
||||
NotifyStatusNo: "不通知",
|
||||
NotifyStatusFailed: "失败通知",
|
||||
NotifyStatusStopped: "结束通知",
|
||||
NotifyStatusKeyword: "结果关键字匹配通知",
|
||||
}
|
||||
|
||||
var NotifyTypeText = map[int32]string{
|
||||
NotifyTypeEmail: "邮件",
|
||||
NotifyTypeWebhook: "Webhook",
|
||||
}
|
||||
|
||||
var IsUsedText = map[int32]string{
|
||||
IsUsedYES: "启用",
|
||||
IsUsedNo: "禁用",
|
||||
}
|
||||
35
internal/api/service/cron_service/service.go
Normal file
35
internal/api/service/cron_service/service.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
)
|
||||
|
||||
var _ Service = (*service)(nil)
|
||||
|
||||
type Service interface {
|
||||
i()
|
||||
|
||||
Create(ctx core.Context, createData *CreateCronTaskData) (id int32, err error)
|
||||
Modify(ctx core.Context, id int32, modifyData *ModifyCronTaskData) (err error)
|
||||
PageList(ctx core.Context, searchData *SearchData) (listData []*cron_task_repo.CronTask, err error)
|
||||
PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error)
|
||||
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
|
||||
Detail(ctx core.Context, searchOneData *SearchOneData) (info *cron_task_repo.CronTask, err error)
|
||||
}
|
||||
|
||||
type service struct {
|
||||
db db.Repo
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func New(db db.Repo, cache cache.Repo) Service {
|
||||
return &service{
|
||||
db: db,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) i() {}
|
||||
49
internal/api/service/cron_service/service_create.go
Normal file
49
internal/api/service/cron_service/service_create.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type CreateCronTaskData struct {
|
||||
Name string // 任务名称
|
||||
Spec string // crontab 表达式
|
||||
Command string // 执行命令
|
||||
Protocol int32 // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 // http 请求方式 1:get 2:post
|
||||
Timeout int32 // 超时时间(单位:秒)
|
||||
RetryTimes int32 // 重试次数
|
||||
RetryInterval int32 // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string // 通知匹配关键字(多个用,分割)
|
||||
Remark string // 备注
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
func (s *service) Create(ctx core.Context, createData *CreateCronTaskData) (id int32, err error) {
|
||||
model := cron_task_repo.NewModel()
|
||||
model.Name = createData.Name
|
||||
model.Spec = createData.Spec
|
||||
model.Command = createData.Command
|
||||
model.Protocol = createData.Protocol
|
||||
model.HttpMethod = createData.HttpMethod
|
||||
model.Timeout = createData.Timeout
|
||||
model.RetryTimes = createData.RetryTimes
|
||||
model.RetryInterval = createData.RetryInterval
|
||||
model.NotifyStatus = createData.NotifyStatus
|
||||
model.NotifyType = createData.NotifyType
|
||||
model.NotifyReceiverEmail = createData.NotifyReceiverEmail
|
||||
model.NotifyKeyword = createData.NotifyKeyword
|
||||
model.Remark = createData.Remark
|
||||
model.IsUsed = createData.IsUsed
|
||||
model.CreatedUser = ctx.UserName()
|
||||
|
||||
id, err = model.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
26
internal/api/service/cron_service/service_detail.go
Normal file
26
internal/api/service/cron_service/service_detail.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchOneData struct {
|
||||
Id int32 // 任务ID
|
||||
}
|
||||
|
||||
func (s *service) Detail(ctx core.Context, searchOneData *SearchOneData) (info *cron_task_repo.CronTask, err error) {
|
||||
qb := cron_task_repo.NewQueryBuilder()
|
||||
|
||||
if searchOneData.Id != 0 {
|
||||
qb.WhereId(db_repo.EqualPredicate, searchOneData.Id)
|
||||
}
|
||||
|
||||
info, err = qb.QueryOne(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
53
internal/api/service/cron_service/service_modify.go
Normal file
53
internal/api/service/cron_service/service_modify.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type ModifyCronTaskData struct {
|
||||
Name string // 任务名称
|
||||
Spec string // crontab 表达式
|
||||
Command string // 执行命令
|
||||
Protocol int32 // 执行方式 1:shell 2:http
|
||||
HttpMethod int32 // http 请求方式 1:get 2:post
|
||||
Timeout int32 // 超时时间(单位:秒)
|
||||
RetryTimes int32 // 重试次数
|
||||
RetryInterval int32 // 重试间隔(单位:秒)
|
||||
NotifyStatus int32 // 执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知
|
||||
NotifyType int32 // 通知类型 1:邮件 2:webhook
|
||||
NotifyReceiverEmail string // 通知者邮箱地址(多个用,分割)
|
||||
NotifyKeyword string // 通知匹配关键字(多个用,分割)
|
||||
Remark string // 备注
|
||||
IsUsed int32 // 是否启用 1:是 -1:否
|
||||
}
|
||||
|
||||
func (s *service) Modify(ctx core.Context, id int32, modifyData *ModifyCronTaskData) (err error) {
|
||||
data := map[string]interface{}{
|
||||
"name": modifyData.Name,
|
||||
"spec": modifyData.Spec,
|
||||
"command": modifyData.Command,
|
||||
"protocol": modifyData.Protocol,
|
||||
"http_method": modifyData.HttpMethod,
|
||||
"timeout": modifyData.Timeout,
|
||||
"retry_times": modifyData.RetryTimes,
|
||||
"retry_interval": modifyData.RetryInterval,
|
||||
"notify_status": modifyData.NotifyStatus,
|
||||
"notify_type": modifyData.NotifyType,
|
||||
"notify_receiver_email": modifyData.NotifyReceiverEmail,
|
||||
"notify_keyword": modifyData.NotifyKeyword,
|
||||
"remark": modifyData.Remark,
|
||||
"is_used": modifyData.IsUsed,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
qb := cron_task_repo.NewQueryBuilder()
|
||||
qb.WhereId(db_repo.EqualPredicate, id)
|
||||
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
54
internal/api/service/cron_service/service_pagelist.go
Normal file
54
internal/api/service/cron_service/service_pagelist.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type SearchData struct {
|
||||
Page int // 第几页
|
||||
PageSize int // 每页显示条数
|
||||
Name string // 任务名称
|
||||
Protocol int32 // 执行方式
|
||||
IsUsed int32 // 是否启用
|
||||
}
|
||||
|
||||
func (s *service) PageList(ctx core.Context, searchData *SearchData) (listData []*cron_task_repo.CronTask, err error) {
|
||||
page := searchData.Page
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
pageSize := searchData.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
qb := cron_task_repo.NewQueryBuilder()
|
||||
|
||||
if searchData.Name != "" {
|
||||
qb.WhereName(db_repo.EqualPredicate, searchData.Name)
|
||||
}
|
||||
|
||||
if searchData.Protocol != 0 {
|
||||
qb.WhereProtocol(db_repo.EqualPredicate, searchData.Protocol)
|
||||
}
|
||||
|
||||
if searchData.IsUsed != 0 {
|
||||
qb.WhereIsUsed(db_repo.EqualPredicate, searchData.IsUsed)
|
||||
}
|
||||
|
||||
listData, err = qb.
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
OrderById(false).
|
||||
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
30
internal/api/service/cron_service/service_pagelistcount.go
Normal file
30
internal/api/service/cron_service/service_pagelistcount.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error) {
|
||||
qb := cron_task_repo.NewQueryBuilder()
|
||||
|
||||
if searchData.Name != "" {
|
||||
qb.WhereName(db_repo.EqualPredicate, searchData.Name)
|
||||
}
|
||||
|
||||
if searchData.Protocol != 0 {
|
||||
qb.WhereProtocol(db_repo.EqualPredicate, searchData.Protocol)
|
||||
}
|
||||
|
||||
if searchData.IsUsed != 0 {
|
||||
qb.WhereIsUsed(db_repo.EqualPredicate, searchData.IsUsed)
|
||||
}
|
||||
|
||||
total, err = qb.Count(s.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
23
internal/api/service/cron_service/service_updateused.go
Normal file
23
internal/api/service/cron_service/service_updateused.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package cron_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error) {
|
||||
data := map[string]interface{}{
|
||||
"is_used": used,
|
||||
"updated_user": ctx.UserName(),
|
||||
}
|
||||
|
||||
qb := cron_task_repo.NewQueryBuilder()
|
||||
qb.WhereId(db_repo.EqualPredicate, id)
|
||||
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -60,6 +60,11 @@ const (
|
||||
MenuCreateActionError = 20306
|
||||
MenuListActionError = 20307
|
||||
MenuDeleteActionError = 20308
|
||||
|
||||
CronCreateError = 20401
|
||||
CronUpdateError = 20402
|
||||
CronListError = 20403
|
||||
CronDetailError = 20404
|
||||
)
|
||||
|
||||
func Text(code int) string {
|
||||
|
||||
@@ -52,4 +52,9 @@ var enUSText = map[int]string{
|
||||
MenuCreateActionError: "Failed to create menu action",
|
||||
MenuListActionError: "Failed to get menu action list",
|
||||
MenuDeleteActionError: "Failed to delete menu action",
|
||||
|
||||
CronCreateError: "Failed to create cron",
|
||||
CronUpdateError: "Failed to update menu",
|
||||
CronListError: "Failed to get cron list",
|
||||
CronDetailError: "Failed to get cron detail",
|
||||
}
|
||||
|
||||
@@ -52,4 +52,9 @@ var zhCNText = map[int]string{
|
||||
MenuCreateActionError: "创建菜单栏功能权限失败",
|
||||
MenuListActionError: "获取菜单栏功能权限列表失败",
|
||||
MenuDeleteActionError: "删除菜单栏功能权限失败",
|
||||
|
||||
CronCreateError: "创建后台任务失败",
|
||||
CronUpdateError: "更新后台任务失败",
|
||||
CronListError: "获取定时任务列表失败",
|
||||
CronDetailError: "获取定时任务详情失败",
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/cron_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/menu_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/tool_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
@@ -79,5 +80,13 @@ func setApiRouter(r *resource) {
|
||||
configHandler := config_handler.New(r.logger, r.db, r.cache)
|
||||
api.PATCH("/config/email", configHandler.Email())
|
||||
|
||||
// cron
|
||||
cronHandler := cron_handler.New(r.logger, r.db, r.cache)
|
||||
api.POST("/cron", cronHandler.Create())
|
||||
api.GET("/cron", cronHandler.List())
|
||||
api.GET("/cron/:id", cronHandler.Detail())
|
||||
api.POST("/cron/:id", cronHandler.Modify())
|
||||
api.PATCH("/cron/used", cronHandler.UpdateUsed())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/cron_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/generator_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/index_handler"
|
||||
@@ -23,6 +24,7 @@ func setWebRouter(r *resource) {
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
upgradeHandler := upgrade_handler.New(r.logger, r.db, r.cache)
|
||||
cronTaskHandler := cron_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// 无需记录日志,无需 RBAC 权限验证
|
||||
notRBAC := r.mux.Group("", r.middles.DisableLog())
|
||||
@@ -80,5 +82,9 @@ func setWebRouter(r *resource) {
|
||||
web.GET("/tool/cache", toolHandler.CacheView())
|
||||
web.GET("/tool/data", toolHandler.DataView())
|
||||
|
||||
// 后台任务
|
||||
web.GET("/cron/list", cronTaskHandler.ListView())
|
||||
web.GET("/cron/add", cronTaskHandler.AddView())
|
||||
web.GET("/cron/edit/:id", cronTaskHandler.EditView())
|
||||
}
|
||||
}
|
||||
|
||||
9
internal/web/controller/cron_handler/func_addview.go
Normal file
9
internal/web/controller/cron_handler/func_addview.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package cron_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) AddView() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
ctx.HTML("cron_task_add", nil)
|
||||
}
|
||||
}
|
||||
35
internal/web/controller/cron_handler/func_editview.go
Normal file
35
internal/web/controller/cron_handler/func_editview.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type editViewRequest struct {
|
||||
Id string `uri:"id"` // 主键ID
|
||||
}
|
||||
|
||||
type editViewResponse struct {
|
||||
HashID string `json:"hash_id"` // hashID
|
||||
}
|
||||
|
||||
func (h *handler) EditView() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(editViewRequest)
|
||||
if err := ctx.ShouldBindURI(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
obj := new(editViewResponse)
|
||||
obj.HashID = req.Id
|
||||
ctx.HTML("cron_task_edit", obj)
|
||||
}
|
||||
}
|
||||
9
internal/web/controller/cron_handler/func_listview.go
Normal file
9
internal/web/controller/cron_handler/func_listview.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package cron_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) ListView() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
ctx.HTML("cron_task_list", nil)
|
||||
}
|
||||
}
|
||||
33
internal/web/controller/cron_handler/handler.go
Normal file
33
internal/web/controller/cron_handler/handler.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package cron_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
AddView() core.HandlerFunc
|
||||
EditView() core.HandlerFunc
|
||||
ListView() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -34,10 +34,42 @@ type initExecuteRequest struct {
|
||||
}
|
||||
|
||||
func (h *handler) Execute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
|
||||
installTableList := map[string]map[string]string{
|
||||
"authorized": {
|
||||
"table_sql": mysql_table.CreateAuthorizedTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAuthorizedTableDataSql(),
|
||||
},
|
||||
"authorized_api": {
|
||||
"table_sql": mysql_table.CreateAuthorizedAPITableSql(),
|
||||
"table_data_sql": mysql_table.CreateAuthorizedAPITableDataSql(),
|
||||
},
|
||||
"admin": {
|
||||
"table_sql": mysql_table.CreateAdminTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAdminTableDataSql(),
|
||||
},
|
||||
"admin_menu": {
|
||||
"table_sql": mysql_table.CreateAdminMenuTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAdminMenuTableDataSql(),
|
||||
},
|
||||
"menu": {
|
||||
"table_sql": mysql_table.CreateMenuTableSql(),
|
||||
"table_data_sql": mysql_table.CreateMenuTableDataSql(),
|
||||
},
|
||||
"menu_action": {
|
||||
"table_sql": mysql_table.CreateMenuActionTableSql(),
|
||||
"table_data_sql": mysql_table.CreateMenuActionTableDataSql(),
|
||||
},
|
||||
"cron_task": {
|
||||
"table_sql": mysql_table.CreateCronTaskTableSql(),
|
||||
"table_data_sql": "",
|
||||
},
|
||||
}
|
||||
|
||||
return func(ctx core.Context) {
|
||||
req := new(initExecuteRequest)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
@@ -45,19 +77,20 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// region 验证 version
|
||||
versionStr := runtime.Version()
|
||||
version := cast.ToFloat32(versionStr[2:6])
|
||||
if version < 1.15 {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.GoVersionError,
|
||||
code.Text(code.GoVersionError)),
|
||||
)
|
||||
return
|
||||
}
|
||||
// endregion
|
||||
|
||||
outPutString := ""
|
||||
|
||||
// region 验证 Redis 配置
|
||||
cfg := configs.Get()
|
||||
redisClient := redis.NewClient(&redis.Options{
|
||||
Addr: req.RedisAddr,
|
||||
@@ -69,7 +102,7 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
})
|
||||
|
||||
if err := redisClient.Ping().Err(); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.RedisConnectError,
|
||||
code.Text(code.RedisConnectError)).WithErr(err),
|
||||
@@ -79,8 +112,10 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
|
||||
defer redisClient.Close()
|
||||
|
||||
outPutString += "已检测 Redis 配置可用。\n"
|
||||
outPutString := "已检测 Redis 配置可用。\n"
|
||||
// endregion
|
||||
|
||||
// region 验证 MySQL 配置
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
|
||||
req.MySQLUser,
|
||||
req.MySQLPass,
|
||||
@@ -97,7 +132,7 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLConnectError,
|
||||
code.Text(code.MySQLConnectError)).WithErr(err),
|
||||
@@ -111,7 +146,9 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
defer dbClient.Close()
|
||||
|
||||
outPutString += "已检测 MySQL 配置可用。\n"
|
||||
// endregion
|
||||
|
||||
// region 写入配置文件
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
@@ -133,7 +170,7 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
viper.Set("mysql.write.name", req.MySQLName)
|
||||
|
||||
if viper.WriteConfig() != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.WriteConfigError,
|
||||
code.Text(code.WriteConfigError)).WithErr(err),
|
||||
@@ -143,131 +180,46 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
|
||||
outPutString += "语言包 " + req.Language + " 配置成功。\n"
|
||||
outPutString += "配置项 Redis、MySQL 配置成功。\n"
|
||||
// endregion
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
// region 初始化表结构 + 默认数据
|
||||
for k, v := range installTableList {
|
||||
if v["table_sql"] != "" {
|
||||
// region 初始化表结构
|
||||
if err = db.Exec(v["table_sql"]).Error; err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += "初始化 MySQL 数据表:" + k + " 成功。\n"
|
||||
// endregion
|
||||
|
||||
// region 初始化默认数据
|
||||
if v["table_data_sql"] != "" {
|
||||
if err = db.Exec(v["table_data_sql"]).Error; err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += "初始化 MySQL 数据表:" + k + " 默认数据成功。\n"
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized 成功。\n"
|
||||
// endregion
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedAPITableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized_api 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedAPITableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized_api 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateMenuTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:menu 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateMenuTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:menu 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateMenuActionTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:menu_action 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateMenuActionTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:menu_action 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminMenuTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin_menu 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminMenuTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin_menu 默认数据成功。\n"
|
||||
|
||||
// 生成 install 完成标识
|
||||
// region 生成 install 完成标识
|
||||
f, err := os.Create(configs.ProjectInstallMark)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
@@ -275,7 +227,8 @@ func (h *handler) Execute() core.HandlerFunc {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
// endregion
|
||||
|
||||
c.Payload(outPutString)
|
||||
ctx.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,9 @@ func CreateAdminMenuTableDataSql() (sql string) {
|
||||
sql += "(19, 1, 1, 'init'),"
|
||||
sql += "(20, 1, 3, 'init'),"
|
||||
sql += "(21, 1, 2, 'init'),"
|
||||
sql += "(22, 1, 22, 'init');"
|
||||
sql += "(22, 1, 22, 'init'),"
|
||||
sql += "(23, 1, 23, 'init'),"
|
||||
sql += "(24, 1, 24, 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `cron_task` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`name` varchar(64) NOT NULL DEFAULT '' COMMENT '任务名称',
|
||||
//`spec` varchar(64) NOT NULL DEFAULT '' COMMENT 'crontab 表达式',
|
||||
//`command` varchar(255) NOT NULL DEFAULT '' COMMENT '执行命令',
|
||||
//`protocol` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '执行方式 1:shell 2:http',
|
||||
//`http_method` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT 'http 请求方式 1:get 2:post',
|
||||
//`timeout` int(11) unsigned NOT NULL DEFAULT '60' COMMENT '超时时间(单位:秒)',
|
||||
//`retry_times` tinyint(1) NOT NULL DEFAULT '3' COMMENT '重试次数',
|
||||
//`retry_interval` int(11) NOT NULL DEFAULT '60' COMMENT '重试间隔(单位:秒)',
|
||||
//`notify_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知',
|
||||
//`notify_type` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '通知类型 1:邮件 2:webhook',
|
||||
//`notify_receiver_email` varchar(255) NOT NULL DEFAULT '' COMMENT '通知者邮箱地址(多个用,分割)',
|
||||
//`notify_keyword` varchar(255) NOT NULL DEFAULT '' COMMENT '通知匹配关键字(多个用,分割)',
|
||||
//`remark` varchar(100) NOT NULL DEFAULT '' COMMENT '备注',
|
||||
//`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`),
|
||||
//KEY `idx_name` (`name`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台任务表';
|
||||
|
||||
func CreateCronTaskTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `cron_task` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`name` varchar(64) NOT NULL DEFAULT '' COMMENT '任务名称',"
|
||||
sql += "`spec` varchar(64) NOT NULL DEFAULT '' COMMENT 'crontab 表达式',"
|
||||
sql += "`command` varchar(255) NOT NULL DEFAULT '' COMMENT '执行命令',"
|
||||
sql += "`protocol` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '执行方式 1:shell 2:http',"
|
||||
sql += "`http_method` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT 'http 请求方式 1:get 2:post',"
|
||||
sql += "`timeout` int(11) unsigned NOT NULL DEFAULT '60' COMMENT '超时时间(单位:秒)',"
|
||||
sql += "`retry_times` tinyint(1) NOT NULL DEFAULT '3' COMMENT '重试次数',"
|
||||
sql += "`retry_interval` int(11) NOT NULL DEFAULT '60' COMMENT '重试间隔(单位:秒)',"
|
||||
sql += "`notify_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '执行结束是否通知 1:不通知 2:失败通知 3:结束通知 4:结果关键字匹配通知',"
|
||||
sql += "`notify_type` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '通知类型 1:邮件 2:webhook',"
|
||||
sql += "`notify_receiver_email` varchar(255) NOT NULL DEFAULT '' COMMENT '通知者邮箱地址(多个用,分割)',"
|
||||
sql += "`notify_keyword` varchar(255) NOT NULL DEFAULT '' COMMENT '通知匹配关键字(多个用,分割)',"
|
||||
sql += "`remark` varchar(100) NOT NULL DEFAULT '' COMMENT '备注',"
|
||||
sql += "`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`),"
|
||||
sql += "KEY `idx_name` (`name`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台任务表';"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -40,28 +40,30 @@ func CreateMenuTableSql() (sql string) {
|
||||
|
||||
func CreateMenuTableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `menu` (`id`, `pid`, `name`, `link`, `icon`, `level`, `sort`, `created_user`) VALUES"
|
||||
sql += "(1, 0, '配置信息', '', 'mdi-settings-box', 1, 1, 'init'),"
|
||||
sql += "(2, 1, '告警邮箱', '/config/email', '', 2, 11, 'init'),"
|
||||
sql += "(3, 1, '错误码', '/config/code', '', 2, 12, 'init'),"
|
||||
sql += "(4, 0, '代码生成器', '', 'mdi-code-not-equal-variant', 1, 2, 'init'),"
|
||||
sql += "(5, 4, '生成数据表 CURD', '/generator/gorm', '', 2, 21, 'init'),"
|
||||
sql += "(6, 4, '生成控制器方法', '/generator/handler', '', 2, 22, 'init'),"
|
||||
sql += "(7, 0, '授权调用方', '', 'mdi-playlist-check', 1, 3, 'init'),"
|
||||
sql += "(8, 7, '调用方', '/authorized/list', '', 2, 31, 'init'),"
|
||||
sql += "(9, 7, '使用说明', '/authorized/demo', '', 2, 32, 'init'),"
|
||||
sql += "(10, 0, '系统管理员', '', 'mdi-account', 1, 4, 'init'),"
|
||||
sql += "(11, 10, '管理员', '/admin/list', '', 2, 41, 'init'),"
|
||||
sql += "(12, 10, '菜单管理', '/admin/menu', '', 2, 42, 'init'),"
|
||||
sql += "(13, 0, '查询小助手', '', 'mdi-database-search', 1, 5, 'init'),"
|
||||
sql += "(14, 13, '查询缓存', '/tool/cache', '', 2, 51, 'init'),"
|
||||
sql += "(15, 13, '查询数据', '/tool/data', '', 2, 52, 'init'),"
|
||||
sql += "(16, 0, '实用工具箱', '', 'mdi-tools', 1, 6, 'init'),"
|
||||
sql += "(17, 16, 'Hashids', '/tool/hashids', '', 2, 62, 'init'),"
|
||||
sql += "(18, 16, '调用日志', '/tool/logs', '', 2, 63, 'init'),"
|
||||
sql += "(19, 16, '接口文档', '/swagger/index.html', '', 2, 64, 'init'),"
|
||||
sql += "(20, 16, 'GraphQL', '/graphql', '', 2, 65, 'init'),"
|
||||
sql += "(21, 16, '接口指标', '/metrics', '', 2, 66, 'init'),"
|
||||
sql += "(22, 16, '服务升级', '/upgrade', '', 2, 61, 'init');"
|
||||
sql += "(1, 0, '配置信息', '', 'mdi-settings-box', 1, 10, 'init'),"
|
||||
sql += "(2, 1, '告警邮箱', '/config/email', '', 2, 101, 'init'),"
|
||||
sql += "(3, 1, '错误码', '/config/code', '', 2, 102, 'init'),"
|
||||
sql += "(4, 0, '代码生成器', '', 'mdi-code-not-equal-variant', 1, 20, 'init'),"
|
||||
sql += "(5, 4, '生成数据表 CURD', '/generator/gorm', '', 2, 201, 'init'),"
|
||||
sql += "(6, 4, '生成控制器方法', '/generator/handler', '', 2, 202, 'init'),"
|
||||
sql += "(7, 0, '授权调用方', '', 'mdi-playlist-check', 1, 30, 'init'),"
|
||||
sql += "(8, 7, '调用方', '/authorized/list', '', 2, 301, 'init'),"
|
||||
sql += "(9, 7, '使用说明', '/authorized/demo', '', 2, 302, 'init'),"
|
||||
sql += "(10, 0, '系统管理员', '', 'mdi-account', 1, 50, 'init'),"
|
||||
sql += "(11, 10, '管理员', '/admin/list', '', 2, 501, 'init'),"
|
||||
sql += "(12, 10, '菜单管理', '/admin/menu', '', 2, 502, 'init'),"
|
||||
sql += "(13, 0, '查询小助手', '', 'mdi-database-search', 1, 60, 'init'),"
|
||||
sql += "(14, 13, '查询缓存', '/tool/cache', '', 2, 601, 'init'),"
|
||||
sql += "(15, 13, '查询数据', '/tool/data', '', 2, 602, 'init'),"
|
||||
sql += "(16, 0, '实用工具箱', '', 'mdi-tools', 1, 70, 'init'),"
|
||||
sql += "(17, 16, 'Hashids', '/tool/hashids', '', 2, 702, 'init'),"
|
||||
sql += "(18, 16, '调用日志', '/tool/logs', '', 2, 703, 'init'),"
|
||||
sql += "(19, 16, '接口文档', '/swagger/index.html', '', 2, 704, 'init'),"
|
||||
sql += "(20, 16, 'GraphQL', '/graphql', '', 2, 705, 'init'),"
|
||||
sql += "(21, 16, '接口指标', '/metrics', '', 2, 706, 'init'),"
|
||||
sql += "(22, 16, '服务升级', '/upgrade', '', 2, 701, 'init'),"
|
||||
sql += "(23, 0, '后台任务', '', 'mdi-av-timer', 1, 40, 'init'),"
|
||||
sql += "(24, 23, '任务列表', '/cron/list', '', 2, 401, 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,7 +72,14 @@ func CreateMenuActionTableDataSql() (sql string) {
|
||||
sql += "(36, 12, 'DELETE', '/api/menu_action/*', 'init'),"
|
||||
sql += "(37, 22, 'POST', '/upgrade/execute', 'init'),"
|
||||
sql += "(38, 11, 'PATCH', '/api/admin/offline', 'init'),"
|
||||
sql += "(39, 12, 'PATCH', '/api/menu/sort', 'init');"
|
||||
sql += "(39, 12, 'PATCH', '/api/menu/sort', 'init'),"
|
||||
sql += "(40, 24, 'GET', '/cron/add', 'init'),"
|
||||
sql += "(41, 24, 'GET', '/cron/edit/*', 'init'),"
|
||||
sql += "(42, 24, 'POST', '/api/cron', 'init'),"
|
||||
sql += "(43, 24, 'POST', '/api/cron/*', 'init'),"
|
||||
sql += "(44, 24, 'GET', '/api/cron', 'init'),"
|
||||
sql += "(45, 24, 'GET', '/api/cron/*', 'init'),"
|
||||
sql += "(46, 24, 'PATCH', '/api/cron/used', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/install_handler/mysql_table"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errors"
|
||||
)
|
||||
|
||||
type upgradeExecuteRequest struct {
|
||||
@@ -15,10 +16,47 @@ type upgradeExecuteRequest struct {
|
||||
}
|
||||
|
||||
func (h *handler) UpgradeExecute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
|
||||
upgradeTableList := map[string]map[string]string{
|
||||
"authorized": {
|
||||
"table_sql": mysql_table.CreateAuthorizedTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAuthorizedTableDataSql(),
|
||||
},
|
||||
"authorized_api": {
|
||||
"table_sql": mysql_table.CreateAuthorizedAPITableSql(),
|
||||
"table_data_sql": mysql_table.CreateAuthorizedAPITableDataSql(),
|
||||
},
|
||||
"admin": {
|
||||
"table_sql": mysql_table.CreateAdminTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAdminTableDataSql(),
|
||||
},
|
||||
"admin_menu": {
|
||||
"table_sql": mysql_table.CreateAdminMenuTableSql(),
|
||||
"table_data_sql": mysql_table.CreateAdminMenuTableDataSql(),
|
||||
},
|
||||
"menu": {
|
||||
"table_sql": mysql_table.CreateMenuTableSql(),
|
||||
"table_data_sql": mysql_table.CreateMenuTableDataSql(),
|
||||
},
|
||||
"menu_action": {
|
||||
"table_sql": mysql_table.CreateMenuActionTableSql(),
|
||||
"table_data_sql": mysql_table.CreateMenuActionTableDataSql(),
|
||||
},
|
||||
"cron_task": {
|
||||
"table_sql": mysql_table.CreateCronTaskTableSql(),
|
||||
"table_data_sql": "",
|
||||
},
|
||||
}
|
||||
|
||||
upgradeTableOp := map[string]bool{
|
||||
"table": true,
|
||||
"table_data": true,
|
||||
}
|
||||
|
||||
return func(ctx core.Context) {
|
||||
req := new(upgradeExecuteRequest)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
@@ -29,150 +67,48 @@ func (h *handler) UpgradeExecute() core.HandlerFunc {
|
||||
outPutString := ""
|
||||
db := h.db.GetDbW()
|
||||
|
||||
if req.TableName == "authorized" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateAuthorizedTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if upgradeTableList[req.TableName] == nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)).WithErr(errors.New("数据表不存在")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if !upgradeTableOp[req.Op] {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)).WithErr(errors.New("非法操作")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Op == "table" {
|
||||
if err := db.Exec(upgradeTableList[req.TableName]["table_sql"]).Error; err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:authorized 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "authorized" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateAuthorizedTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
outPutString = "初始化 MySQL 数据表:" + req.TableName + " 成功。"
|
||||
} else if req.Op == "table_data" {
|
||||
if err := db.Exec(upgradeTableList[req.TableName]["table_data_sql"]).Error; err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:authorized 默认数据成功。"
|
||||
|
||||
outPutString = "初始化 MySQL 数据表:" + req.TableName + " 默认数据成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "authorized_api" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateAuthorizedAPITableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:authorized_api 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "authorized_api" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateAuthorizedAPITableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:authorized_api 默认数据成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "admin" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateAdminTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:admin 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "admin" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateAdminTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:admin 默认数据成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "menu" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateMenuTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:menu 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "menu" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateMenuTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:menu 默认数据成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "menu_action" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateMenuActionTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:menu_action 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "menu_action" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateMenuActionTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:menu_action 默认数据成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "admin_menu" && req.Op == "table" {
|
||||
if err := db.Exec(mysql_table.CreateAdminMenuTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:admin_menu 成功。"
|
||||
}
|
||||
|
||||
if req.TableName == "admin_menu" && req.Op == "table_data" {
|
||||
if err := db.Exec(mysql_table.CreateAdminMenuTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.MySQLExecError,
|
||||
code.Text(code.MySQLExecError)+" "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString = "初始化 MySQL 数据表:admin_menu 默认数据成功。"
|
||||
}
|
||||
|
||||
c.Payload(outPutString)
|
||||
ctx.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user