upgrade
This commit is contained in:
24
assets/bootstrap/js/jquery.bootstrap.wizard.min.js
vendored
Normal file
24
assets/bootstrap/js/jquery.bootstrap.wizard.min.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
jQuery twitter bootstrap wizard plugin
|
||||
Examples and documentation at: http://github.com/VinceG/twitter-bootstrap-wizard
|
||||
version 1.4.2
|
||||
Requires jQuery v1.3.2 or later
|
||||
Supports Bootstrap 2.2.x, 2.3.x, 3.0
|
||||
Dual licensed under the MIT and GPL licenses:
|
||||
http://www.opensource.org/licenses/mit-license.php
|
||||
http://www.gnu.org/licenses/gpl.html
|
||||
Authors: Vadim Vincent Gabriel (http://vadimg.com), Jason Gill (www.gilluminate.com)
|
||||
*/
|
||||
(function(c){var n=function(d,k){d=c(d);var a=this,h=[],b=c.extend({},c.fn.bootstrapWizard.defaults,k),f=null,e=null;this.rebindClick=function(b,a){b.unbind("click",a).bind("click",a)};this.fixNavigationButtons=function(){f.length||(e.find("a:first").tab("show"),f=e.find('li:has([data-toggle="tab"]):first'));c(b.previousSelector,d).toggleClass("disabled",a.firstIndex()>=a.currentIndex());c(b.nextSelector,d).toggleClass("disabled",a.currentIndex()>=a.navigationLength());c(b.nextSelector,d).toggleClass("d-none",
|
||||
a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);c(b.lastSelector,d).toggleClass("d-none",a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);c(b.finishSelector,d).toggleClass("d-none",a.currentIndex()<a.navigationLength());c(b.backSelector,d).toggleClass("disabled",0==h.length);c(b.backSelector,d).toggleClass("d-none",a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);a.rebindClick(c(b.nextSelector,d),a.next);a.rebindClick(c(b.previousSelector,
|
||||
d),a.previous);a.rebindClick(c(b.lastSelector,d),a.last);a.rebindClick(c(b.firstSelector,d),a.first);a.rebindClick(c(b.finishSelector,d),a.finish);a.rebindClick(c(b.backSelector,d),a.back);if(b.onTabShow&&"function"===typeof b.onTabShow&&!1===b.onTabShow(f,e,a.currentIndex()))return!1};this.next=function(g){if(d.hasClass("last")||b.onNext&&"function"===typeof b.onNext&&!1===b.onNext(f,e,a.nextIndex()))return!1;g=a.currentIndex();var c=a.nextIndex();c>a.navigationLength()||(h.push(g),e.find('li:has([data-toggle="tab"])'+
|
||||
(b.withVisible?":visible":"")+":eq("+c+") a").tab("show"))};this.previous=function(g){if(d.hasClass("first")||b.onPrevious&&"function"===typeof b.onPrevious&&!1===b.onPrevious(f,e,a.previousIndex()))return!1;g=a.currentIndex();var c=a.previousIndex();0>c||(h.push(g),e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")+":eq("+c+") a").tab("show"))};this.first=function(g){if(b.onFirst&&"function"===typeof b.onFirst&&!1===b.onFirst(f,e,a.firstIndex())||d.hasClass("disabled"))return!1;h.push(a.currentIndex());
|
||||
e.find('li:has([data-toggle="tab"]):eq(0) a').tab("show")};this.last=function(g){if(b.onLast&&"function"===typeof b.onLast&&!1===b.onLast(f,e,a.lastIndex())||d.hasClass("disabled"))return!1;h.push(a.currentIndex());e.find('li:has([data-toggle="tab"]):eq('+a.navigationLength()+") a").tab("show")};this.finish=function(g){if(b.onFinish&&"function"===typeof b.onFinish)b.onFinish(f,e,a.lastIndex())};this.back=function(){if(0==h.length)return null;var a=h.pop();if(b.onBack&&"function"===typeof b.onBack&&
|
||||
!1===b.onBack(f,e,a))return h.push(a),!1;d.find('li:has([data-toggle="tab"]):eq('+a+") a").tab("show")};this.currentIndex=function(){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).index(f)};this.firstIndex=function(){return 0};this.lastIndex=function(){return a.navigationLength()};this.getIndex=function(a){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).index(a)};this.nextIndex=function(){var a=this.currentIndex(),c;do a++,c=e.find('li:has([data-toggle="tab"])'+
|
||||
(b.withVisible?":visible":"")+":eq("+a+")");while(c&&c.hasClass("disabled"));return a};this.previousIndex=function(){var a=this.currentIndex(),c;do a--,c=e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")+":eq("+a+")");while(c&&c.hasClass("disabled"));return a};this.navigationLength=function(){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).length-1};this.activeTab=function(){return f};this.nextTab=function(){return e.find('li:has([data-toggle="tab"]):eq('+
|
||||
(a.currentIndex()+1)+")").length?e.find('li:has([data-toggle="tab"]):eq('+(a.currentIndex()+1)+")"):null};this.previousTab=function(){return 0>=a.currentIndex()?null:e.find('li:has([data-toggle="tab"]):eq('+parseInt(a.currentIndex()-1)+")")};this.show=function(b){b=isNaN(b)?d.find('li:has([data-toggle="tab"]) a[href="#'+b+'"]'):d.find('li:has([data-toggle="tab"]):eq('+b+") a");0<b.length&&(h.push(a.currentIndex()),b.tab("show"))};this.disable=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+
|
||||
")").addClass("disabled")};this.enable=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").removeClass("disabled")};this.hide=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").hide()};this.display=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").show()};this.remove=function(a){var b="undefined"!=typeof a[1]?a[1]:!1;a=e.find('li:has([data-toggle="tab"]):eq('+a[0]+")");b&&(b=a.find("a").attr("href"),c(b).remove());a.remove()};var l=function(d){var g=e.find('li:has([data-toggle="tab"])');
|
||||
d=g.index(c(d.currentTarget).parent('li:has([data-toggle="tab"])'));g=c(g[d]);if(b.onTabClick&&"function"===typeof b.onTabClick&&!1===b.onTabClick(f,e,a.currentIndex(),d,g))return!1},m=function(d){d=c(d.target).parent();var g=e.find('li:has([data-toggle="tab"])').index(d);if(d.hasClass("disabled")||b.onTabChange&&"function"===typeof b.onTabChange&&!1===b.onTabChange(f,e,a.currentIndex(),g))return!1;f=d;a.fixNavigationButtons()};this.resetWizard=function(){c('a[data-toggle="tab"]',e).off("click",l);
|
||||
c('a[data-toggle="tab"]',e).off("show show.bs.tab",m);e=d.find("ul:first",d);f=e.find('li:has([data-toggle="tab"]).active',d);c('a[data-toggle="tab"]',e).on("click",l);c('a[data-toggle="tab"]',e).on("show show.bs.tab",m);a.fixNavigationButtons()};e=d.find("ul:first",d);f=e.find('li:has([data-toggle="tab"]).active',d);e.hasClass(b.tabClass)||e.addClass(b.tabClass);if(b.onInit&&"function"===typeof b.onInit)b.onInit(f,e,0);if(b.onShow&&"function"===typeof b.onShow)b.onShow(f,e,a.nextIndex());c('a[data-toggle="tab"]',
|
||||
e).on("click",l);c('a[data-toggle="tab"]',e).on("show show.bs.tab",m)};c.fn.bootstrapWizard=function(d){if("string"==typeof d){var k=Array.prototype.slice.call(arguments,1);1===k.length&&k.toString();return this.data("bootstrapWizard")[d](k)}return this.each(function(a){a=c(this);if(!a.data("bootstrapWizard")){var h=new n(a,d);a.data("bootstrapWizard",h);h.fixNavigationButtons()}})};c.fn.bootstrapWizard.defaults={withVisible:!0,tabClass:"nav nav-pills",nextSelector:".wizard li.next",previousSelector:".wizard li.previous",
|
||||
firstSelector:".wizard li.first",lastSelector:".wizard li.last",finishSelector:".wizard li.finish",backSelector:".wizard li.back",onShow:null,onInit:null,onNext:null,onPrevious:null,onLast:null,onFirst:null,onFinish:null,onBack:null,onTabChange:null,onTabClick:null,onTabShow:null}})(jQuery);
|
||||
33
assets/templates/configinfo/config_code.html
Normal file
33
assets/templates/configinfo/config_code.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!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/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">
|
||||
<header class="card-header">
|
||||
<div class="card-title"> 错误码</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
{{range .}}
|
||||
<p>
|
||||
<code>{{.Code}}</code> {{.Message}}
|
||||
<hr>
|
||||
</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
169
assets/templates/configinfo/config_email.html
Normal file
169
assets/templates/configinfo/config_email.html
Normal file
@@ -0,0 +1,169 @@
|
||||
<!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/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">
|
||||
<header class="card-header">
|
||||
<div class="card-title"> 邮箱告警配置</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<form class="site-form">
|
||||
<div class="form-group">
|
||||
<label>邮箱服务器:</label>
|
||||
<input type="text" class="form-control" id="host" value="{{ .Mail.Host }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>端口:</label>
|
||||
<input type="text" class="form-control" id="port" value="{{ .Mail.Port }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>发件人邮箱</label>
|
||||
<input type="text" class="form-control" id="user" value="{{ .Mail.User }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>发件人密码</label> <small>(发件人邮箱密码或授权码,根据邮箱服务器而定)</small>
|
||||
<input type="password" class="form-control" id="pass" value="{{ .Mail.Pass }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>收件人</label> <small>(添加多个收件人邮箱,用英文,分割)</small>
|
||||
<input type="text" class="form-control" id="to" value="{{ .Mail.To }}"
|
||||
placeholder="请输入收件人邮箱,多个用,分割">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<small>为了验证邮箱配置的准确性,点击保存后会给收件人发送邮件以确保配置可用。</small>
|
||||
</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/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
$('#btnOk').on('click', function () {
|
||||
const host = $("#host").val();
|
||||
if (host === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入邮箱服务器。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const port = $("#port").val();
|
||||
if (port === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入端口。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const user = $("#user").val();
|
||||
if (user === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入发件人邮箱。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const pass = $("#pass").val();
|
||||
if (pass === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入发件人密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const to = $("#to").val();
|
||||
if (to === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入收件人邮箱。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
host: host,
|
||||
port: port,
|
||||
user: user,
|
||||
pass: pass,
|
||||
to: to,
|
||||
};
|
||||
|
||||
|
||||
AjaxForm(
|
||||
"PATCH",
|
||||
"/api/config/email",
|
||||
postData,
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function () {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '配置修改完成',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,45 +0,0 @@
|
||||
<!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/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">
|
||||
<header class="card-header"><div class="card-title"> 配置信息</div></header>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">MySQL</h5>
|
||||
<p>主库信息:{{.MySQL.Write.Addr}},账号:{{.MySQL.Write.User}},数据库:{{.MySQL.Write.Name}}</p>
|
||||
<p>从库信息:{{.MySQL.Read.Addr}},账号:{{.MySQL.Read.User}},数据库:{{.MySQL.Read.Name}}</p>
|
||||
<p>最大连接数:{{ .MySQL.Base.MaxOpenConn }}</p>
|
||||
<p>空闲连接数:{{ .MySQL.Base.MaxIdleConn }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Redis</h5>
|
||||
<p>地址:{{ .Redis.Addr }} </p>
|
||||
<p>最大连接数:{{ .Redis.PoolSize }} </p>
|
||||
<p>空闲连接数:{{ .Redis.MinIdleConns }} </p>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Mail</h5>
|
||||
<p>邮箱服务器:{{ .Mail.Host }} </p>
|
||||
<p>发件人邮箱地址:{{ .Mail.User }} </p>
|
||||
<p>收件人邮箱地址:{{ .Mail.To }} </p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -15,8 +15,6 @@
|
||||
<div class="card">
|
||||
<header class="card-header"><div class="card-title"> <code>gormgen</code> 代码生成工具</div></header>
|
||||
<div class="card-body">
|
||||
<div class="callout callout-warning mb-3">注意:请在 <code>Mac</code> 或 <code>Linux</code> 环境执行。</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="tableSelect">选择数据表,可进行多选:</label>
|
||||
<select multiple="" class="form-control" id="tableSelect" style="height: 260px;">
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
<div class="card">
|
||||
<header class="card-header"><div class="card-title"> <code>handlergen</code> 代码生成工具</div></header>
|
||||
<div class="card-body">
|
||||
<div class="callout callout-warning mb-3">注意:请在 <code>Mac</code> 或 <code>Linux</code> 环境执行。</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="exampleFormControlInput1">handler 名称,例如:<code>user_handler</code></label>
|
||||
<input type="text" class="form-control" id="handlerName" placeholder="请输入 handler 名称">
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
<!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/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="bootstrap/css/bootstrap.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-6">
|
||||
<div class="card">
|
||||
<header class="card-header"><div class="card-title">初始化</div></header>
|
||||
<div class="card-body">
|
||||
<div class="callout callout-warning mb-3">注意:请在 <code>Mac</code> 或 <code>Linux</code> 环境执行。</div>
|
||||
<p>初始化项目所需信息:</p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>user_demo</code> ;</span></p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>authorized</code> ;</span></p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>authorized_api</code> ;</span></p>
|
||||
<p><i class="mdi mdi-checkbox-marked-circle"></i> <span>MySQL 数据表:<code>admin</code> ;</span></p>
|
||||
<p>
|
||||
<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>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<header class="card-header"><div class="card-title">执行结果</div></header>
|
||||
<div class="card-body">
|
||||
<pre id="resultDiv"></pre>
|
||||
</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/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#btnOk").click(function(){
|
||||
|
||||
$("#resultDiv").text("");
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
|
||||
$.post("/init_exec","",function (data) {
|
||||
$("#resultDiv").text(data);
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
if (getQueryString("init")) {
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '初始化完成。',
|
||||
buttons: {
|
||||
okay: {
|
||||
text: '系统首页',
|
||||
action: function () {
|
||||
location.href = "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
function getQueryString(name) {
|
||||
let reg = new RegExp('(?:(?:&|\\?)' + name + '=([^&]*))|(?:/' + name + '/([^/]*))', 'i');
|
||||
let r = window.location.href.match(reg);
|
||||
if (r != null)
|
||||
return decodeURI(r[1] || r[2]);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -34,12 +34,17 @@
|
||||
<nav class="sidebar-main">
|
||||
<ul class="nav-drawer">
|
||||
<li class="nav-item active"> <a class="multitabs" href="/dashboard"><i class="mdi mdi-home"></i> <span>仪表盘</span></a> </li>
|
||||
<li class="nav-item"> <a class="multitabs" href="/configinfo"><i class="mdi mdi-settings-box"></i> <span>配置信息</span></a> </li>
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-settings-box"></i> <span>配置信息</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/config/email">告警邮箱</a> </li>
|
||||
<li> <a class="multitabs" href="/config/code">错误码</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-code-not-equal-variant"></i> <span>代码生成器</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="/init">初始化</a> </li>
|
||||
<li> <a class="multitabs" href="/gormgen">gormgen</a> </li>
|
||||
<li> <a class="multitabs" href="/handlergen">handlergen</a> </li>
|
||||
</ul>
|
||||
|
||||
227
assets/templates/install/install_view.html
Normal file
227
assets/templates/install/install_view.html
Normal file
@@ -0,0 +1,227 @@
|
||||
<!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/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<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-6">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">服务初始化</div>
|
||||
</header>
|
||||
<div class="card-body text-center">
|
||||
<h4 class="card-title">配置 · Redis</h4>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">地址</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="redis_addr" value="{{ .Redis.Addr }}"
|
||||
placeholder="请输入地址,例如:127.0.0.1:6379">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">密码</span>
|
||||
</div>
|
||||
<input type="password" class="form-control" id="redis_pass" value="{{ .Redis.Pass }}"
|
||||
placeholder="请输入密码">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">DB </span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="redis_db" value="{{ .Redis.Db }}"
|
||||
placeholder="请输入 DB ,序号从 0 开始,默认是 0">
|
||||
</div>
|
||||
|
||||
<h4 class="card-title">配置 · MySQL</h4>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">地址</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="mysql_addr" value="{{ .MySQL.Write.Addr }}"
|
||||
placeholder="请输入服务器地址,例如:127.0.0.1:3306">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">用户</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="mysql_user" value="{{ .MySQL.Write.User }}"
|
||||
placeholder="请输入用户名">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">密码</span>
|
||||
</div>
|
||||
<input type="password" class="form-control" id="mysql_pass" value="{{ .MySQL.Write.Pass }}"
|
||||
placeholder="请输入密码">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">DB </span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="mysql_name" value="{{ .MySQL.Write.Name }}"
|
||||
placeholder="请输入数据库名">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<small><i class="mdi mdi-checkbox-marked-circle"></i> 初始化 MySQL 数据表:<code>authorized</code>
|
||||
、<code>authorized_api</code> 、<code>admin</code>;
|
||||
</small>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">执行结果</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<pre id="resultDiv"></pre>
|
||||
</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/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$("#btnOk").click(function () {
|
||||
|
||||
const redis_addr = $("#redis_addr").val();
|
||||
if (redis_addr === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 Redis 服务器地址。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const redis_db = $("#redis_db").val();
|
||||
if (redis_db === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 Redis DB。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const mysql_addr = $("#mysql_addr").val();
|
||||
if (mysql_addr === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 MySQL 服务器地址。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const mysql_user = $("#mysql_user").val();
|
||||
if (mysql_user === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 MySQL 用户名。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const mysql_pass = $("#mysql_pass").val();
|
||||
if (mysql_pass === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 MySQL 密码。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const mysql_name = $("#mysql_name").val();
|
||||
if (mysql_name === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入 MySQL 数据库名。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const postData = {
|
||||
redis_addr: redis_addr,
|
||||
redis_pass: $("#redis_pass").val(),
|
||||
redis_db: redis_db,
|
||||
|
||||
mysql_addr: mysql_addr,
|
||||
mysql_user: mysql_user,
|
||||
mysql_pass: mysql_pass,
|
||||
mysql_name: mysql_name,
|
||||
};
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/install/execute",
|
||||
postData,
|
||||
function () {
|
||||
$("#resultDiv").text("");
|
||||
$(this).hide();
|
||||
$("#btnLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#resultDiv").text(data);
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
$.alert({
|
||||
title: '操作成功',
|
||||
icon: 'mdi mdi-check-decagram',
|
||||
type: 'green',
|
||||
content: '服务初始化成功,<strong style="color: red">请重新启动服务!</strong>',
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
$("#btnLoading").hide();
|
||||
$("#btnOk").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
## 执行命令
|
||||
在根目录下执行脚本:`./scripts/init.sh addr user pass name`;
|
||||
- addr:数据库地址,例如:127.0.0.1:3306
|
||||
- user:账号,例如:root
|
||||
- pass:密码,例如:root
|
||||
- name:数据库名称,例如:go_gin_api
|
||||
|
||||
例如:
|
||||
```
|
||||
./scripts/init.sh 127.0.0.1:3306 root root go_gin_api
|
||||
```
|
||||
@@ -1,113 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/cmd/init/db/mysql"
|
||||
)
|
||||
|
||||
var (
|
||||
dbAddr string
|
||||
dbUser string
|
||||
dbPass string
|
||||
dbName string
|
||||
)
|
||||
|
||||
func init() {
|
||||
addr := flag.String("addr", "", "请输入 db 地址,例如:127.0.0.1:3306\n")
|
||||
user := flag.String("user", "", "请输入 db 用户名\n")
|
||||
pass := flag.String("pass", "", "请输入 db 密码\n")
|
||||
name := flag.String("name", "", "请输入 db 名称\n")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
dbAddr = *addr
|
||||
dbUser = *user
|
||||
dbPass = *pass
|
||||
dbName = strings.ToLower(*name)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 初始化 DB
|
||||
db, err := mysql.New(dbAddr, dbUser, dbPass, dbName)
|
||||
if err != nil {
|
||||
log.Fatal("new db err: ", err.Error())
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := db.DbClose(); err != nil {
|
||||
log.Fatal("db close err: ", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
// 开启事务
|
||||
tx := db.GetDb().Begin()
|
||||
|
||||
// 创建 user_demo 表
|
||||
err = tx.Exec(mysql.CreateUserDemoTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create user_demo table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create user_demo table success")
|
||||
|
||||
// 创建 authorized 表
|
||||
err = tx.Exec(mysql.CreateAuthorizedTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAuthorizedTableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized table data success")
|
||||
|
||||
// 创建 authorized_api 表
|
||||
err = tx.Exec(mysql.CreateAuthorizedAPITableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized_api table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized_api table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAuthorizedAPITableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create authorized_api table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create authorized_api table data success")
|
||||
|
||||
// 创建 admin 表
|
||||
err = tx.Exec(mysql.CreateAdminTableSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create admin table err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create admin table success")
|
||||
|
||||
err = tx.Exec(mysql.CreateAdminTableDataSql()).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
log.Fatal("create admin table data err: ", err.Error())
|
||||
}
|
||||
fmt.Println("create admin table data success")
|
||||
|
||||
// 生成已完成 init 的标识,生成 init_db.lock
|
||||
f, err := os.Create("cmd/init/db/init_db.lock")
|
||||
if err != nil {
|
||||
log.Fatal("create init_db.lock err: ", err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// 完成事务
|
||||
tx.Commit()
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
var _ Repo = (*dbRepo)(nil)
|
||||
|
||||
type Repo interface {
|
||||
i()
|
||||
GetDb() *gorm.DB
|
||||
DbClose() error
|
||||
}
|
||||
|
||||
type dbRepo struct {
|
||||
DbConn *gorm.DB
|
||||
}
|
||||
|
||||
func New(dbAddr, dbUser, dbPass, dbName string) (Repo, error) {
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
|
||||
dbUser,
|
||||
dbPass,
|
||||
dbAddr,
|
||||
dbName,
|
||||
true,
|
||||
"Local")
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true,
|
||||
},
|
||||
//Logger: logger.Default.LogMode(logger.Info), // 日志配置
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("[db connection failed] Database name: %s", dbName))
|
||||
}
|
||||
|
||||
db.Set("gorm:table_options", "CHARSET=utf8mb4")
|
||||
|
||||
return &dbRepo{
|
||||
DbConn: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *dbRepo) i() {}
|
||||
|
||||
func (d *dbRepo) GetDb() *gorm.DB {
|
||||
return d.DbConn
|
||||
}
|
||||
|
||||
func (d *dbRepo) DbClose() error {
|
||||
sqlDB, err := d.DbConn.DB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sqlDB.Close()
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@@ -77,6 +78,13 @@ func init() {
|
||||
if err := viper.Unmarshal(config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
viper.WatchConfig()
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
if err := viper.Unmarshal(config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Get() Config {
|
||||
@@ -95,6 +103,6 @@ func ProjectLogFile() string {
|
||||
return fmt.Sprintf("./logs/%s-access.log", ProjectName())
|
||||
}
|
||||
|
||||
func InitDBLockFile() string {
|
||||
return "cmd/init/db/init_db.lock"
|
||||
func ProjectInstallFile() string {
|
||||
return "INSTALL.lock"
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
[db]
|
||||
host = '127.0.0.1'
|
||||
port = 3306
|
||||
|
||||
|
||||
@@ -1,43 +1,46 @@
|
||||
[mysql]
|
||||
|
||||
[mysql.read] # 从库信息,可读
|
||||
addr = '127.0.0.1:3306' # MySQL 地址:端口
|
||||
user = 'root' # 用户名
|
||||
pass = 'root' # 密码
|
||||
name = 'go_gin_api' # 数据库名称
|
||||
[mysql.write] # 主库信息,可读写
|
||||
addr = '127.0.0.1:3306' # MySQL 地址:端口
|
||||
user = 'root' # 用户名
|
||||
pass = 'root' # 密码
|
||||
name = 'go_gin_api' # 数据库名称
|
||||
[mysql.base] # 基础配置
|
||||
maxOpenConn = 10 # 最大打开的连接数
|
||||
maxIdleConn = 60 # 闲置的连接数
|
||||
connMaxLifeTime = 60 # 最大连接超时(单位:分)
|
||||
|
||||
[redis]
|
||||
addr = '127.0.0.1:6379' # Redis 地址:端口
|
||||
pass = '' # 密码
|
||||
db = 0 # 序号从 0 开始,默认是0,可以不用设置
|
||||
maxRetries = 3 # 命令执行失败时,最多重试多少次,默认为 0 即不重试
|
||||
poolSize = 10 # 连接池最大连接数,默认为 CPU 数 * 10
|
||||
minIdleConns = 5 # 最小空闲连接数
|
||||
|
||||
[mail]
|
||||
host = 'smtp.163.com' # 邮箱服务器,比如 smtp.163.com
|
||||
port = 465 # 端口
|
||||
user = "" # 发件人邮箱
|
||||
pass = "" # 发件人邮箱密码或授权码,根据邮箱服务器而定
|
||||
to = "" # 收件人邮箱,多个可以逗号(,)分割
|
||||
|
||||
[jwt]
|
||||
secret = 'i1ydX9RtHyuJTrw7frcu' # JWT secret
|
||||
expireDuration = 24 # JWT ExpiresAt 过期时间(单位:小时)
|
||||
|
||||
[urlToken]
|
||||
secret = 'i1ydX9RtHyuJTrw7frcu' # URL Token secret
|
||||
expireDuration = 10 # URL Token ExpiresAt 过期时间(单位:分钟)
|
||||
|
||||
[hashids]
|
||||
secret = '6ab6122836cfef95f8db' # hashids secret
|
||||
length = 12 # hashids length
|
||||
length = 12
|
||||
secret = "6ab6122836cfef95f8db"
|
||||
|
||||
[jwt]
|
||||
expireduration = 24
|
||||
secret = "i1ydX9RtHyuJTrw7frcu"
|
||||
|
||||
[mail]
|
||||
host = "smtp.163.com"
|
||||
pass = ""
|
||||
port = 465
|
||||
to = ""
|
||||
user = ""
|
||||
|
||||
[mysql]
|
||||
|
||||
[mysql.base]
|
||||
connmaxlifetime = 60
|
||||
maxidleconn = 60
|
||||
maxopenconn = 10
|
||||
|
||||
[mysql.read]
|
||||
addr = "127.0.0.1:3306"
|
||||
name = "go_gin_api"
|
||||
pass = "root"
|
||||
user = "root"
|
||||
|
||||
[mysql.write]
|
||||
addr = "127.0.0.1:3306"
|
||||
name = "go_gin_api"
|
||||
pass = "root"
|
||||
user = "root"
|
||||
|
||||
[redis]
|
||||
addr = "127.0.0.1:6379"
|
||||
db = "0"
|
||||
maxretries = 3
|
||||
minidleconns = 5
|
||||
pass = ""
|
||||
poolsize = 10
|
||||
|
||||
[urltoken]
|
||||
expireduration = 10
|
||||
secret = "i1ydX9RtHyuJTrw7frcu"
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
[db]
|
||||
host = '127.0.0.1'
|
||||
port = 3306
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
[db]
|
||||
host = '127.0.0.1'
|
||||
port = 3306
|
||||
|
||||
|
||||
|
||||
462
docs/docs.go
462
docs/docs.go
@@ -206,7 +206,7 @@ var doc = `{
|
||||
},
|
||||
"/api/admin/modify_password": {
|
||||
"patch": {
|
||||
"description": "修改个人信息",
|
||||
"description": "修改密码",
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
@@ -216,19 +216,19 @@ var doc = `{
|
||||
"tags": [
|
||||
"API.admin"
|
||||
],
|
||||
"summary": "修改个人信息",
|
||||
"summary": "修改密码",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "昵称",
|
||||
"name": "nickname",
|
||||
"description": "旧密码",
|
||||
"name": "old_password",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "手机号",
|
||||
"name": "mobile",
|
||||
"description": "新密码",
|
||||
"name": "new_password",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
@@ -237,7 +237,7 @@ var doc = `{
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/admin_handler.modifyPersonalInfoResponse"
|
||||
"$ref": "#/definitions/admin_handler.modifyPasswordResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
@@ -695,6 +695,72 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/config/email": {
|
||||
"patch": {
|
||||
"description": "修改邮件配置",
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"API.config"
|
||||
],
|
||||
"summary": "修改邮件配置",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "邮箱服务器",
|
||||
"name": "host",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "端口",
|
||||
"name": "port",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "发件人邮箱",
|
||||
"name": "user",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "发件人密码",
|
||||
"name": "pass",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "收件人邮箱地址,多个用,分割",
|
||||
"name": "to",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/config_handler.emailResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/tool/hashids/decode/{id}": {
|
||||
"get": {
|
||||
"description": "HashIds 解密",
|
||||
@@ -770,300 +836,6 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/get": {
|
||||
"post": {
|
||||
"description": "获取授权信息",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Demo"
|
||||
],
|
||||
"summary": "获取授权信息",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/demo_handler.authResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/demo/trace": {
|
||||
"get": {
|
||||
"description": "Trace 示例",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Demo"
|
||||
],
|
||||
"summary": "Trace 示例",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"job": {
|
||||
"description": "工作",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/create": {
|
||||
"post": {
|
||||
"description": "创建用户",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "创建用户",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求信息",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.createRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.createResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/delete/{id}": {
|
||||
"patch": {
|
||||
"description": "删除用户",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "删除用户",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "用户ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.deleteResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/info/{username}": {
|
||||
"get": {
|
||||
"description": "用户详情",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "用户详情",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "用户名",
|
||||
"name": "username",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.detailResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/update": {
|
||||
"put": {
|
||||
"description": "编辑用户 - 通过用户主键ID更新用户昵称",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "编辑用户 - 通过用户主键ID更新用户昵称",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求信息",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.updateNickNameByIDRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.updateNickNameByIDResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@@ -1390,16 +1162,12 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"demo_handler.authResponse": {
|
||||
"config_handler.emailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorization": {
|
||||
"description": "签名",
|
||||
"email": {
|
||||
"description": "邮箱地址",
|
||||
"type": "string"
|
||||
},
|
||||
"expire_time": {
|
||||
"description": "过期时间",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1420,84 +1188,6 @@ var doc = `{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.createRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mobile": {
|
||||
"description": "手机号",
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
},
|
||||
"user_name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.createResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.deleteResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.detailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"mobile": {
|
||||
"description": "手机号(脱敏)",
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
},
|
||||
"user_name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.updateNickNameByIDRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.updateNickNameByIDResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
},
|
||||
"/api/admin/modify_password": {
|
||||
"patch": {
|
||||
"description": "修改个人信息",
|
||||
"description": "修改密码",
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
@@ -199,19 +199,19 @@
|
||||
"tags": [
|
||||
"API.admin"
|
||||
],
|
||||
"summary": "修改个人信息",
|
||||
"summary": "修改密码",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "昵称",
|
||||
"name": "nickname",
|
||||
"description": "旧密码",
|
||||
"name": "old_password",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "手机号",
|
||||
"name": "mobile",
|
||||
"description": "新密码",
|
||||
"name": "new_password",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
@@ -220,7 +220,7 @@
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/admin_handler.modifyPersonalInfoResponse"
|
||||
"$ref": "#/definitions/admin_handler.modifyPasswordResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
@@ -678,6 +678,72 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/config/email": {
|
||||
"patch": {
|
||||
"description": "修改邮件配置",
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"API.config"
|
||||
],
|
||||
"summary": "修改邮件配置",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "邮箱服务器",
|
||||
"name": "host",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "端口",
|
||||
"name": "port",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "发件人邮箱",
|
||||
"name": "user",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "发件人密码",
|
||||
"name": "pass",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "收件人邮箱地址,多个用,分割",
|
||||
"name": "to",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/config_handler.emailResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/tool/hashids/decode/{id}": {
|
||||
"get": {
|
||||
"description": "HashIds 解密",
|
||||
@@ -753,300 +819,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/get": {
|
||||
"post": {
|
||||
"description": "获取授权信息",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Demo"
|
||||
],
|
||||
"summary": "获取授权信息",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/demo_handler.authResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/demo/trace": {
|
||||
"get": {
|
||||
"description": "Trace 示例",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Demo"
|
||||
],
|
||||
"summary": "Trace 示例",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"job": {
|
||||
"description": "工作",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/create": {
|
||||
"post": {
|
||||
"description": "创建用户",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "创建用户",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求信息",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.createRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.createResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/delete/{id}": {
|
||||
"patch": {
|
||||
"description": "删除用户",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "删除用户",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "用户ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.deleteResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/info/{username}": {
|
||||
"get": {
|
||||
"description": "用户详情",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "用户详情",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "用户名",
|
||||
"name": "username",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.detailResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/update": {
|
||||
"put": {
|
||||
"description": "编辑用户 - 通过用户主键ID更新用户昵称",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "编辑用户 - 通过用户主键ID更新用户昵称",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求信息",
|
||||
"name": "Request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.updateNickNameByIDRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "签名",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user_handler.updateNickNameByIDResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/code.Failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@@ -1373,16 +1145,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"demo_handler.authResponse": {
|
||||
"config_handler.emailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorization": {
|
||||
"description": "签名",
|
||||
"email": {
|
||||
"description": "邮箱地址",
|
||||
"type": "string"
|
||||
},
|
||||
"expire_time": {
|
||||
"description": "过期时间",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1403,84 +1171,6 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.createRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mobile": {
|
||||
"description": "手机号",
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
},
|
||||
"user_name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.createResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.deleteResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.detailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"mobile": {
|
||||
"description": "手机号(脱敏)",
|
||||
"type": "string"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
},
|
||||
"user_name": {
|
||||
"description": "用户名",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.updateNickNameByIDRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"nick_name": {
|
||||
"description": "昵称",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_handler.updateNickNameByIDResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "用户主键ID",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,14 +221,11 @@ definitions:
|
||||
description: 描述信息
|
||||
type: string
|
||||
type: object
|
||||
demo_handler.authResponse:
|
||||
config_handler.emailResponse:
|
||||
properties:
|
||||
authorization:
|
||||
description: 签名
|
||||
email:
|
||||
description: 邮箱地址
|
||||
type: string
|
||||
expire_time:
|
||||
description: 过期时间
|
||||
type: integer
|
||||
type: object
|
||||
tool_handler.hashIdsDecodeResponse:
|
||||
properties:
|
||||
@@ -242,60 +239,6 @@ definitions:
|
||||
description: 加密后的值
|
||||
type: string
|
||||
type: object
|
||||
user_handler.createRequest:
|
||||
properties:
|
||||
mobile:
|
||||
description: 手机号
|
||||
type: string
|
||||
nick_name:
|
||||
description: 昵称
|
||||
type: string
|
||||
user_name:
|
||||
description: 用户名
|
||||
type: string
|
||||
type: object
|
||||
user_handler.createResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
type: object
|
||||
user_handler.deleteResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 用户主键ID
|
||||
type: integer
|
||||
type: object
|
||||
user_handler.detailResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 用户主键ID
|
||||
type: integer
|
||||
mobile:
|
||||
description: 手机号(脱敏)
|
||||
type: string
|
||||
nick_name:
|
||||
description: 昵称
|
||||
type: string
|
||||
user_name:
|
||||
description: 用户名
|
||||
type: string
|
||||
type: object
|
||||
user_handler.updateNickNameByIDRequest:
|
||||
properties:
|
||||
id:
|
||||
description: 用户主键ID
|
||||
type: integer
|
||||
nick_name:
|
||||
description: 昵称
|
||||
type: string
|
||||
type: object
|
||||
user_handler.updateNickNameByIDResponse:
|
||||
properties:
|
||||
id:
|
||||
description: 用户主键ID
|
||||
type: integer
|
||||
type: object
|
||||
host: 127.0.0.1:9999
|
||||
info:
|
||||
contact: {}
|
||||
@@ -451,16 +394,16 @@ paths:
|
||||
patch:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 修改个人信息
|
||||
description: 修改密码
|
||||
parameters:
|
||||
- description: 昵称
|
||||
- description: 旧密码
|
||||
in: formData
|
||||
name: nickname
|
||||
name: old_password
|
||||
required: true
|
||||
type: string
|
||||
- description: 手机号
|
||||
- description: 新密码
|
||||
in: formData
|
||||
name: mobile
|
||||
name: new_password
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
@@ -469,12 +412,12 @@ paths:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/admin_handler.modifyPersonalInfoResponse'
|
||||
$ref: '#/definitions/admin_handler.modifyPasswordResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 修改个人信息
|
||||
summary: 修改密码
|
||||
tags:
|
||||
- API.admin
|
||||
/api/admin/reset_password/{id}:
|
||||
@@ -748,6 +691,51 @@ paths:
|
||||
summary: 删除调用方接口地址
|
||||
tags:
|
||||
- API.authorized
|
||||
/api/config/email:
|
||||
patch:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
description: 修改邮件配置
|
||||
parameters:
|
||||
- description: 邮箱服务器
|
||||
in: formData
|
||||
name: host
|
||||
required: true
|
||||
type: string
|
||||
- description: 端口
|
||||
in: formData
|
||||
name: port
|
||||
required: true
|
||||
type: string
|
||||
- description: 发件人邮箱
|
||||
in: formData
|
||||
name: user
|
||||
required: true
|
||||
type: string
|
||||
- description: 发件人密码
|
||||
in: formData
|
||||
name: pass
|
||||
required: true
|
||||
type: string
|
||||
- description: 收件人邮箱地址,多个用,分割
|
||||
in: formData
|
||||
name: to
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/config_handler.emailResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 修改邮件配置
|
||||
tags:
|
||||
- API.config
|
||||
/api/tool/hashids/decode/{id}:
|
||||
get:
|
||||
consumes:
|
||||
@@ -798,199 +786,4 @@ paths:
|
||||
summary: HashIds 加密
|
||||
tags:
|
||||
- API.tool
|
||||
/auth/get:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取授权信息
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/demo_handler.authResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 获取授权信息
|
||||
tags:
|
||||
- Demo
|
||||
/demo/trace:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Trace 示例
|
||||
parameters:
|
||||
- description: 签名
|
||||
in: header
|
||||
name: Authorization
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
properties:
|
||||
job:
|
||||
description: 工作
|
||||
type: string
|
||||
name:
|
||||
description: 用户名
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: Trace 示例
|
||||
tags:
|
||||
- Demo
|
||||
/user/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建用户
|
||||
parameters:
|
||||
- description: 请求信息
|
||||
in: body
|
||||
name: Request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.createRequest'
|
||||
- description: 签名
|
||||
in: header
|
||||
name: Authorization
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.createResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 创建用户
|
||||
tags:
|
||||
- User
|
||||
/user/delete/{id}:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除用户
|
||||
parameters:
|
||||
- description: 用户ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: 签名
|
||||
in: header
|
||||
name: Authorization
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.deleteResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 删除用户
|
||||
tags:
|
||||
- User
|
||||
/user/info/{username}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 用户详情
|
||||
parameters:
|
||||
- description: 用户名
|
||||
in: path
|
||||
name: username
|
||||
required: true
|
||||
type: string
|
||||
- description: 签名
|
||||
in: header
|
||||
name: Authorization
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.detailResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 用户详情
|
||||
tags:
|
||||
- User
|
||||
/user/update:
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
parameters:
|
||||
- description: 请求信息
|
||||
in: body
|
||||
name: Request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.updateNickNameByIDRequest'
|
||||
- description: 签名
|
||||
in: header
|
||||
name: Authorization
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/user_handler.updateNickNameByIDResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/code.Failure'
|
||||
summary: 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
tags:
|
||||
- User
|
||||
swagger: "2.0"
|
||||
|
||||
1
go.mod
1
go.mod
@@ -8,6 +8,7 @@ require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/dave/dst v0.26.2
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/gin-contrib/pprof v1.2.1
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
|
||||
@@ -41,10 +41,17 @@ const (
|
||||
AdminDeleteError = 20303
|
||||
AdminUpdateError = 20304
|
||||
AdminResetPasswordError = 20305
|
||||
AdminLoginError = 20307
|
||||
AdminLogOutError = 20308
|
||||
AdminModifyPasswordError = 20309
|
||||
AdminModifyPersonalInfoError = 20310
|
||||
AdminLoginError = 20306
|
||||
AdminLogOutError = 20307
|
||||
AdminModifyPasswordError = 20308
|
||||
AdminModifyPersonalInfoError = 20309
|
||||
|
||||
// 配置
|
||||
ConfigEmailError = 20401
|
||||
ConfigSaveError = 20402
|
||||
ConfigRedisConnectError = 20403
|
||||
ConfigMySQLConnectError = 20404
|
||||
ConfigMySQLInstallError = 20405
|
||||
)
|
||||
|
||||
var codeText = map[int]string{
|
||||
@@ -81,6 +88,12 @@ var codeText = map[int]string{
|
||||
AdminLogOutError: "退出失败",
|
||||
AdminModifyPasswordError: "修改密码失败",
|
||||
AdminModifyPersonalInfoError: "修改个人信息失败",
|
||||
|
||||
ConfigEmailError: "修改邮箱配置失败",
|
||||
ConfigSaveError: "写入配置文件失败",
|
||||
ConfigRedisConnectError: "Redis 连接失败",
|
||||
ConfigMySQLConnectError: "MySQL 连接失败",
|
||||
ConfigMySQLInstallError: "MySQL 初始化数据失败",
|
||||
}
|
||||
|
||||
func Text(code int) string {
|
||||
|
||||
98
internal/api/controller/config_handler/func_email.go
Executable file
98
internal/api/controller/config_handler/func_email.go
Executable file
@@ -0,0 +1,98 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/mail"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type emailRequest struct {
|
||||
Host string `form:"host"` // 邮箱服务器
|
||||
Port string `form:"port"` // 端口
|
||||
User string `form:"user"` // 发件人邮箱
|
||||
Pass string `form:"pass"` // 发件人密码
|
||||
To string `form:"to"` // 收件人邮箱地址,多个用,分割
|
||||
}
|
||||
|
||||
type emailResponse struct {
|
||||
Email string `json:"email"` // 邮箱地址
|
||||
}
|
||||
|
||||
// Email 修改邮件配置
|
||||
// @Summary 修改邮件配置
|
||||
// @Description 修改邮件配置
|
||||
// @Tags API.config
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param host formData string true "邮箱服务器"
|
||||
// @Param port formData string true "端口"
|
||||
// @Param user formData string true "发件人邮箱"
|
||||
// @Param pass formData string true "发件人密码"
|
||||
// @Param to formData string true "收件人邮箱地址,多个用,分割"
|
||||
// @Success 200 {object} emailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/config/email [patch]
|
||||
func (h *handler) Email() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(emailRequest)
|
||||
res := new(emailResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
options := &mail.Options{
|
||||
MailHost: req.Host,
|
||||
MailPort: cast.ToInt(req.Port),
|
||||
MailUser: req.User,
|
||||
MailPass: req.Pass,
|
||||
MailTo: req.To,
|
||||
Subject: fmt.Sprintf("%s[%s] 邮箱告警人调整通知。", configs.ProjectName(), env.Active().Value()),
|
||||
Body: fmt.Sprintf("%s[%s] 已添加您为系统告警通知人。", configs.ProjectName(), env.Active().Value()),
|
||||
}
|
||||
if err := mail.Send(options); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigEmailError,
|
||||
"Mail Send error: "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
|
||||
viper.Set("mail.host", req.Host)
|
||||
viper.Set("mail.port", cast.ToInt(req.Port))
|
||||
viper.Set("mail.user", req.User)
|
||||
viper.Set("mail.pass", req.Pass)
|
||||
viper.Set("mail.to", req.To)
|
||||
|
||||
err := viper.WriteConfig()
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigEmailError,
|
||||
code.Text(code.ConfigEmailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Email = req.To
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
34
internal/api/controller/config_handler/handler.go
Normal file
34
internal/api/controller/config_handler/handler.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package config_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()
|
||||
|
||||
// Email 修改邮件配置
|
||||
// @Tags API.config
|
||||
// @Router /api/config/email [patch]
|
||||
Email() 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() {}
|
||||
@@ -1,47 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/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/token"
|
||||
)
|
||||
|
||||
type authResponse struct {
|
||||
Authorization string `json:"authorization"` // 签名
|
||||
ExpireTime int64 `json:"expire_time"` // 过期时间
|
||||
}
|
||||
|
||||
// 获取授权信息
|
||||
// @Summary 获取授权信息
|
||||
// @Description 获取授权信息
|
||||
// @Tags Demo
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} authResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /auth/get [post]
|
||||
func (h *handler) Auth() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
cfg := configs.Get().JWT
|
||||
tokenString, err := token.New(cfg.Secret).JwtSign(1, "xinliangnote", time.Hour*cfg.ExpireDuration)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res := new(authResponse)
|
||||
res.Authorization = tokenString
|
||||
res.ExpireTime = time.Now().Add(time.Hour * cfg.ExpireDuration).Unix()
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (h *handler) Get() core.HandlerFunc {
|
||||
type request struct {
|
||||
Name string `uri:"name"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Name string `json:"name"`
|
||||
Job string `json:"job"`
|
||||
}
|
||||
|
||||
return func(c core.Context) {
|
||||
req := new(request)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "Tom" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.Name != Tom")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(&response{
|
||||
Name: "Tom",
|
||||
Job: "Student",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (h *handler) Post() core.HandlerFunc {
|
||||
type request struct {
|
||||
Name string `form:"name"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Name string `json:"name"`
|
||||
Job string `json:"job"`
|
||||
}
|
||||
|
||||
return func(c core.Context) {
|
||||
req := new(request)
|
||||
if err := c.ShouldBindPostForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "Jack" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.Name != Jack")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(&response{
|
||||
Name: "Jack",
|
||||
Job: "Teacher",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/third_party_request/go_gin_api"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/httpclient"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/p"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type traceResponse []struct {
|
||||
Name string `json:"name"` //用户名
|
||||
Job string `json:"job"` //工作
|
||||
}
|
||||
|
||||
// Trace 示例
|
||||
// @Summary Trace 示例
|
||||
// @Description Trace 示例
|
||||
// @Tags Demo
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} traceResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /demo/trace [get]
|
||||
func (h *handler) Trace() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
// 三方请求信息
|
||||
res1, err := go_gin_api.DemoGet("Tom",
|
||||
httpclient.WithTTL(time.Second*5),
|
||||
httpclient.WithTrace(c.Trace()),
|
||||
httpclient.WithLogger(c.Logger()),
|
||||
httpclient.WithHeader("Authorization", c.GetHeader("Authorization")),
|
||||
httpclient.WithOnFailedRetry(3, time.Second*1, go_gin_api.DemoGetRetryVerify),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("get [demo/get] err", zap.Error(err))
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CallHTTPError,
|
||||
code.Text(code.CallHTTPError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
p.Println("res1.Name", res1.Name, p.WithTrace(c.Trace()))
|
||||
|
||||
// 三方请求信息
|
||||
res2, err := go_gin_api.DemoPost("Jack",
|
||||
httpclient.WithTTL(time.Second*5),
|
||||
httpclient.WithTrace(c.Trace()),
|
||||
httpclient.WithLogger(c.Logger()),
|
||||
httpclient.WithHeader("Authorization", c.GetHeader("Authorization")),
|
||||
httpclient.WithOnFailedRetry(3, time.Second*1, go_gin_api.DemoPostRetryVerify),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("post [demo/post] err", zap.Error(err))
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CallHTTPError,
|
||||
code.Text(code.CallHTTPError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
p.Println("res2.Name",
|
||||
res2.Name,
|
||||
p.WithTrace(c.Trace()),
|
||||
)
|
||||
|
||||
// 执行 SQL 信息
|
||||
h.userService.GetUserByUserName(c, "test_user")
|
||||
|
||||
// 执行 Redis 信息
|
||||
_ = h.cache.Set("name", "tom", time.Minute*10, cache.WithTrace(c.Trace()))
|
||||
val, _ := h.cache.Get("name", cache.WithTrace(c.Trace()))
|
||||
p.Println("redis-name", val, p.WithTrace(c.Trace()))
|
||||
|
||||
// 初始化客户端
|
||||
// client := hello.NewHelloClient(d.grpConn.Conn())
|
||||
// client.SayHello(grpc.ContextWithValueAndTimeout(c, time.Second*3), &hello.HelloRequest{Name: "Hello World"})
|
||||
|
||||
data := &traceResponse{
|
||||
{
|
||||
Name: res1.Name,
|
||||
Job: res1.Job,
|
||||
},
|
||||
{
|
||||
Name: res2.Name,
|
||||
Job: res2.Job,
|
||||
},
|
||||
}
|
||||
c.Payload(data)
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_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/internal/pkg/grpc"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
// 示例:支持 get 请求的方法
|
||||
Get() core.HandlerFunc
|
||||
// 示例:支持 post 请求的方法
|
||||
Post() core.HandlerFunc
|
||||
|
||||
// 获取授权信息
|
||||
// @Tags Demo
|
||||
// @Router /auth/get [post]
|
||||
Auth() core.HandlerFunc
|
||||
|
||||
// Trace 示例
|
||||
// @Tags Demo
|
||||
// @Router /demo/trace [get]
|
||||
Trace() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
grpConn grpc.ClientConn
|
||||
userService user_service.UserService
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
grpConn: grpConn,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,77 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
// @Summary 创建用户
|
||||
// @Description 创建用户
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Request body createRequest true "请求信息"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/create [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindJSON(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.UserName == "" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.UserName = ''")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createUserData := new(user_service.CreateUserInfo)
|
||||
createUserData.Mobile = req.Mobile
|
||||
createUserData.NickName = req.NickName
|
||||
createUserData.UserName = req.UserName
|
||||
|
||||
id, err := h.userService.Create(c, createUserData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserCreateError,
|
||||
code.Text(code.UserCreateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
Id int32 `uri:"id"` // 用户ID
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
// @Summary 删除用户
|
||||
// @Description 删除用户
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "用户ID"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/delete/{id} [patch]
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.userService.Delete(c, req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserUpdateError,
|
||||
code.Text(code.UserUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = req.Id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/ddm"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type detailRequest struct {
|
||||
UserName string `uri:"username"` // 用户名
|
||||
}
|
||||
|
||||
type detailResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile ddm.Mobile `json:"mobile"` // 手机号(脱敏)
|
||||
}
|
||||
|
||||
// 用户详情
|
||||
// @Summary 用户详情
|
||||
// @Description 用户详情
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param username path string true "用户名"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/info/{username} [get]
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(detailRequest)
|
||||
res := new(detailResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.userService.GetUserByUserName(c, req.UserName)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserSearchError,
|
||||
code.Text(code.UserSearchError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = user.Id
|
||||
res.UserName = user.UserName
|
||||
res.NickName = user.NickName
|
||||
res.Mobile = ddm.Mobile(user.Mobile)
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateNickNameByIDRequest struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
}
|
||||
|
||||
type updateNickNameByIDResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
}
|
||||
|
||||
// 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Summary 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Description 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Request body updateNickNameByIDRequest true "请求信息"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} updateNickNameByIDResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/update [put]
|
||||
func (h *handler) UpdateNickNameByID() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateNickNameByIDRequest)
|
||||
res := new(updateNickNameByIDResponse)
|
||||
if err := c.ShouldBindJSON(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.userService.UpdateNickNameByID(c, req.Id, req.NickName)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserUpdateError,
|
||||
code.Text(code.UserUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = req.Id
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_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"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
|
||||
// Create 创建用户
|
||||
// @Tags User
|
||||
// @Router /user/create [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// UpdateNickNameByID 编辑用户 - 通过主键ID更新用户昵称
|
||||
// @Tags User
|
||||
// @Router /user/update [put]
|
||||
UpdateNickNameByID() core.HandlerFunc
|
||||
|
||||
// Delete 删除用户
|
||||
// @Tags User
|
||||
// @Router /user/delete/{id} [patch]
|
||||
Delete() core.HandlerFunc
|
||||
|
||||
// Detail 用户详情
|
||||
// @Tags User
|
||||
// @Router /user/info/{username} [get]
|
||||
Detail() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
userService user_service.UserService
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,15 +0,0 @@
|
||||
package user_demo_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// 用户Demo表
|
||||
//go:generate gormgen -structs UserDemo -input .
|
||||
type UserDemo struct {
|
||||
Id int32 // 主键
|
||||
UserName string // 用户名
|
||||
NickName string // 昵称
|
||||
Mobile string // 手机号
|
||||
IsDeleted int32 // 是否删除 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#### go_gin_api.user_demo
|
||||
用户Demo表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | user_name | 用户名 | varchar(32) | | NO | | |
|
||||
| 3 | nick_name | 昵称 | varchar(100) | | NO | | |
|
||||
| 4 | mobile | 手机号 | varchar(20) | | NO | | |
|
||||
| 5 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 6 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
|
||||
| 7 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
@@ -1,411 +0,0 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package user_demo_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *UserDemo {
|
||||
return new(UserDemo)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *userDemoRepoQueryBuilder {
|
||||
return new(userDemoRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *UserDemo) 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
|
||||
}
|
||||
|
||||
func (t *UserDemo) Delete(db *gorm.DB) (err error) {
|
||||
if err = db.Delete(t).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *UserDemo) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
if err = db.Model(&UserDemo{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type userDemoRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) 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 *userDemoRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&UserDemo{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) First(db *gorm.DB) (*UserDemo, error) {
|
||||
ret := &UserDemo{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) QueryOne(db *gorm.DB) (*UserDemo, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*UserDemo, error) {
|
||||
var ret []*UserDemo
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) Limit(limit int) *userDemoRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) Offset(offset int) *userDemoRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIdIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIdNotIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderById(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserName(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserNameIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserNameNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByUserName(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "user_name "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickName(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickNameIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickNameNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByNickName(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "nick_name "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobile(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobileIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobileNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByMobile(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "mobile "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeletedIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByIsDeleted(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_deleted "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByCreatedAt(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByUpdatedAt(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_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 _ UserService = (*userSer)(nil)
|
||||
|
||||
type UserService interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
|
||||
Create(ctx core.Context, user *CreateUserInfo) (id int32, err error)
|
||||
UpdateNickNameByID(ctx core.Context, id int32, username string) (err error)
|
||||
GetUserByUserName(ctx core.Context, username string) (user *user_demo_repo.UserDemo, err error)
|
||||
Delete(ctx core.Context, id int32) (err error)
|
||||
}
|
||||
|
||||
type userSer struct {
|
||||
db db.Repo
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func NewUserService(db db.Repo, cache cache.Repo) UserService {
|
||||
return &userSer{
|
||||
db: db,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *userSer) i() {}
|
||||
@@ -1,25 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type CreateUserInfo struct {
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
func (u *userSer) Create(ctx core.Context, user *CreateUserInfo) (id int32, err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.UserName = user.UserName
|
||||
model.NickName = user.NickName
|
||||
model.Mobile = user.Mobile
|
||||
|
||||
id, err = model.Create(u.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) Delete(ctx core.Context, id int32) (err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.Id = id
|
||||
err = model.Delete(u.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) GetUserByUserName(ctx core.Context, username string) (user *user_demo_repo.UserDemo, err error) {
|
||||
user, err = user_demo_repo.NewQueryBuilder().
|
||||
WhereUserName(db_repo.EqualPredicate, username).
|
||||
QueryOne(u.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user = user_demo_repo.NewModel()
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) UpdateNickNameByID(ctx core.Context, id int32, nickname string) (err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"nick_name": nickname,
|
||||
}
|
||||
|
||||
err = model.Updates(u.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package resolvers
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/graph/generated"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
@@ -21,17 +20,17 @@ type mutationResolver struct{ *Resolver }
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
type Resolver struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
userService user_service.UserService
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
//userService user_service.UserService
|
||||
}
|
||||
|
||||
func NewRootResolvers(logger *zap.Logger, db db.Repo, cache cache.Repo) generated.Config {
|
||||
c := generated.Config{
|
||||
Resolvers: &Resolver{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
//userService: user_service.NewUserService(db, cache),
|
||||
},
|
||||
}
|
||||
return c
|
||||
|
||||
@@ -24,18 +24,49 @@ type resource struct {
|
||||
middles middleware.Middleware
|
||||
}
|
||||
|
||||
func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) (core.Mux, error) {
|
||||
var openBrowserUri = "http://127.0.0.1:9999"
|
||||
|
||||
_, ok := file.IsExists(configs.InitDBLockFile())
|
||||
if !ok {
|
||||
openBrowserUri = "http://127.0.0.1:9999/init?init=db"
|
||||
}
|
||||
type Server struct {
|
||||
Mux core.Mux
|
||||
Db db.Repo
|
||||
Cache cache.Repo
|
||||
GrpClient grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewHTTPServer(logger *zap.Logger) (*Server, error) {
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger required")
|
||||
}
|
||||
|
||||
r := new(resource)
|
||||
r.logger = logger
|
||||
|
||||
openBrowserUri := "http://127.0.0.1" + configs.ProjectPort()
|
||||
|
||||
_, ok := file.IsExists(configs.ProjectInstallFile())
|
||||
if !ok { // 未安装
|
||||
openBrowserUri += "/install"
|
||||
} else { // 已安装
|
||||
// 初始化 DB
|
||||
dbRepo, err := db.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new db err", zap.Error(err))
|
||||
}
|
||||
r.db = dbRepo
|
||||
|
||||
// 初始化 Cache
|
||||
cacheRepo, err := cache.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new cache err", zap.Error(err))
|
||||
}
|
||||
r.cache = cacheRepo
|
||||
|
||||
// 初始化 gRPC client
|
||||
gRPCRepo, err := grpc.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new grpc err", zap.Error(err))
|
||||
}
|
||||
r.grpConn = gRPCRepo
|
||||
}
|
||||
|
||||
mux, err := core.New(logger,
|
||||
core.WithEnableOpenBrowser(openBrowserUri),
|
||||
core.WithEnableCors(),
|
||||
@@ -48,13 +79,8 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.C
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r := new(resource)
|
||||
r.mux = mux
|
||||
r.logger = logger
|
||||
r.db = db
|
||||
r.cache = cache
|
||||
r.grpConn = grpConn
|
||||
r.middles = middleware.New(logger, cache, db)
|
||||
r.middles = middleware.New(logger, r.cache, r.db)
|
||||
|
||||
// 设置 WEB 路由
|
||||
setWebRouter(r)
|
||||
@@ -65,5 +91,11 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.C
|
||||
// 设置 GraphQL 路由
|
||||
setGraphQLRouter(r)
|
||||
|
||||
return mux, nil
|
||||
s := new(Server)
|
||||
s.Mux = mux
|
||||
s.Db = r.db
|
||||
s.Cache = r.cache
|
||||
s.GrpClient = r.grpConn
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -3,47 +3,17 @@ package router
|
||||
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/demo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/tool_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func setApiRouter(r *resource) {
|
||||
// demo 控制器
|
||||
demoHandler := demo_handler.New(r.logger, r.db, r.cache, r.grpConn)
|
||||
demo := r.mux.Group("/demo", core.WrapAuthHandler(r.middles.Jwt)) // 使用 jwt 验证
|
||||
{
|
||||
// 为了演示 Trace ,增加了一些看起来无意义的调试信息和 SQL 信息。
|
||||
demo.GET("/trace", demoHandler.Trace())
|
||||
|
||||
// 模拟数据
|
||||
demo.GET("get/:name", core.AliasForRecordMetrics("/demo/get"), demoHandler.Get())
|
||||
demo.POST("post", demoHandler.Post())
|
||||
}
|
||||
|
||||
demoNoAuth := r.mux.Group("/auth") // 不使用 jwt 验证
|
||||
{
|
||||
demoNoAuth.POST("/get", demoHandler.Auth())
|
||||
}
|
||||
|
||||
// user 控制器
|
||||
userHandler := user_handler.New(r.logger, r.db, r.cache)
|
||||
user := r.mux.Group("/user", core.WrapAuthHandler(r.middles.Jwt))
|
||||
{
|
||||
user.POST("/create", userHandler.Create())
|
||||
user.PUT("/update", userHandler.UpdateNickNameByID())
|
||||
user.PATCH("/delete/:id", userHandler.Delete())
|
||||
user.GET("/info/:username", core.AliasForRecordMetrics("/user/info"), userHandler.Detail())
|
||||
}
|
||||
|
||||
// authorized
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// admin
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// 登录
|
||||
// login
|
||||
login := r.mux.Group("/login", r.middles.Signature())
|
||||
{
|
||||
login.POST("/web", adminHandler.Login())
|
||||
@@ -52,14 +22,16 @@ func setApiRouter(r *resource) {
|
||||
// api
|
||||
api := r.mux.Group("/api", core.WrapAuthHandler(r.middles.Token), r.middles.Signature())
|
||||
{
|
||||
// authorized
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
api.POST("/authorized", authorizedHandler.Create())
|
||||
api.GET("/authorized", authorizedHandler.List())
|
||||
api.PATCH("/authorized/used", authorizedHandler.UpdateUsed())
|
||||
api.DELETE("/authorized/:id", authorizedHandler.Delete())
|
||||
api.DELETE("/authorized/:id", core.AliasForRecordMetrics("/api/authorized/info"), authorizedHandler.Delete())
|
||||
|
||||
api.POST("/authorized_api", authorizedHandler.CreateAPI())
|
||||
api.GET("/authorized_api", authorizedHandler.ListAPI())
|
||||
api.DELETE("/authorized_api/:id", authorizedHandler.DeleteAPI())
|
||||
api.DELETE("/authorized_api/:id", core.AliasForRecordMetrics("/api/authorized_api/info"), authorizedHandler.DeleteAPI())
|
||||
|
||||
api.POST("/admin", adminHandler.Create())
|
||||
api.GET("/admin", adminHandler.List())
|
||||
@@ -75,5 +47,10 @@ func setApiRouter(r *resource) {
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
api.GET("/tool/hashids/encode/:id", toolHandler.HashIdsEncode())
|
||||
api.GET("/tool/hashids/decode/:id", toolHandler.HashIdsDecode())
|
||||
|
||||
// config
|
||||
configHandler := config_handler.New(r.logger, r.db, r.cache)
|
||||
api.PATCH("/config/email", configHandler.Email())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,38 +3,43 @@ package router
|
||||
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/configinfo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/gencode_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/index_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/install_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/tool_handler"
|
||||
)
|
||||
|
||||
func setWebRouter(r *resource) {
|
||||
|
||||
installHandler := install_handler.New(r.logger)
|
||||
indexHandler := index_handler.New(r.logger, r.db, r.cache)
|
||||
dashboardHandler := dashboard_handler.New(r.logger, r.db, r.cache)
|
||||
genCodeHandler := gencode_handler.New(r.logger, r.db, r.cache)
|
||||
configInfoHandler := configinfo_handler.New(r.logger, r.db, r.cache)
|
||||
configInfoHandler := config_handler.New(r.logger, r.db, r.cache)
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
web := r.mux.Group("", r.middles.DisableLog())
|
||||
{
|
||||
// 首页侧边栏
|
||||
// 首页
|
||||
web.GET("", indexHandler.View())
|
||||
|
||||
// 安装
|
||||
web.GET("/install", installHandler.View())
|
||||
web.POST("/install/execute", installHandler.Execute())
|
||||
web.POST("/install/restart", installHandler.Restart())
|
||||
|
||||
// 仪表盘
|
||||
web.GET("/dashboard", dashboardHandler.View())
|
||||
|
||||
// 配置信息
|
||||
web.GET("/configinfo", configInfoHandler.View())
|
||||
|
||||
// 代码生成
|
||||
web.GET("/init", genCodeHandler.InitView())
|
||||
web.POST("/init_exec", genCodeHandler.InitExecute())
|
||||
web.GET("/config/email", configInfoHandler.EmailView())
|
||||
web.GET("/config/code", configInfoHandler.CodeView())
|
||||
|
||||
// 代码生成工具
|
||||
web.GET("/gormgen", genCodeHandler.GormView())
|
||||
web.POST("/gormgen_exec", genCodeHandler.GormExecute())
|
||||
|
||||
|
||||
56
internal/web/controller/config_handler/func_codeview.go
Normal file
56
internal/web/controller/config_handler/func_codeview.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"log"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"github.com/dave/dst"
|
||||
"github.com/dave/dst/decorator"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func (h *handler) CodeView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
fs := token.NewFileSet()
|
||||
filePath := "./internal/api/code/code.go"
|
||||
parsedFile, err := decorator.ParseFile(fs, filePath, nil, 0)
|
||||
if err != nil {
|
||||
log.Fatalf("parsing package: %s: %s\n", filePath, err)
|
||||
}
|
||||
|
||||
type codes struct {
|
||||
Code int `json:"code"` // 错误码
|
||||
Message string `json:"message"` // 错误码信息
|
||||
}
|
||||
|
||||
var constCodes []codes
|
||||
|
||||
dst.Inspect(parsedFile, func(n dst.Node) bool {
|
||||
decl, ok := n.(*dst.GenDecl)
|
||||
if !ok || decl.Tok != token.CONST {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, spec := range decl.Specs {
|
||||
valueSpec, _ok := spec.(*dst.ValueSpec)
|
||||
if !_ok {
|
||||
continue
|
||||
}
|
||||
|
||||
codeInt := cast.ToInt(valueSpec.Values[0].(*dst.BasicLit).Value)
|
||||
|
||||
constCodes = append(constCodes, codes{
|
||||
Code: codeInt,
|
||||
Message: code.Text(codeInt),
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
c.HTML("config_code", constCodes)
|
||||
}
|
||||
}
|
||||
12
internal/web/controller/config_handler/func_emailview.go
Normal file
12
internal/web/controller/config_handler/func_emailview.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) EmailView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("config_email", configs.Get())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package configinfo_handler
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
@@ -13,7 +13,8 @@ var _ Handler = (*handler)(nil)
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
View() core.HandlerFunc
|
||||
EmailView() core.HandlerFunc
|
||||
CodeView() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
@@ -25,10 +26,12 @@ func (h *handler) GormExecute() core.HandlerFunc {
|
||||
mysqlConf := configs.Get().MySQL.Read
|
||||
shellPath := fmt.Sprintf("./scripts/gormgen.sh %s %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name, req.Tables)
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
@@ -21,10 +22,13 @@ func (h *handler) HandlerExecute() core.HandlerFunc {
|
||||
}
|
||||
|
||||
shellPath := fmt.Sprintf("./scripts/handlergen.sh %s", req.Name)
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package gencode_handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) InitExecute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
mysqlConf := configs.Get().MySQL.Read
|
||||
shellPath := fmt.Sprintf("./scripts/init.sh %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name)
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
c.Payload(stderr.String())
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(string(output))
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package gencode_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) InitView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("gencode_init", nil)
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,6 @@ var _ Handler = (*handler)(nil)
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
InitView() core.HandlerFunc
|
||||
InitExecute() core.HandlerFunc
|
||||
|
||||
HandlerView() core.HandlerFunc
|
||||
HandlerExecute() core.HandlerFunc
|
||||
|
||||
|
||||
204
internal/web/controller/install_handler/func_execute.go
Normal file
204
internal/web/controller/install_handler/func_execute.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"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/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/go-redis/redis/v7"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/viper"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
type initExecuteRequest struct {
|
||||
RedisAddr string `form:"redis_addr"` // 连接地址,例如:127.0.0.1:6379
|
||||
RedisPass string `form:"redis_pass"` // 连接密码
|
||||
RedisDb string `form:"redis_db"` // 连接 db
|
||||
|
||||
MySQLAddr string `form:"mysql_addr"`
|
||||
MySQLUser string `form:"mysql_user"`
|
||||
MySQLPass string `form:"mysql_pass"`
|
||||
MySQLName string `form:"mysql_name"`
|
||||
}
|
||||
|
||||
func (h *handler) Execute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(initExecuteRequest)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString := ""
|
||||
|
||||
cfg := configs.Get()
|
||||
redisClient := redis.NewClient(&redis.Options{
|
||||
Addr: req.RedisAddr,
|
||||
Password: req.RedisPass,
|
||||
DB: cast.ToInt(req.RedisDb),
|
||||
MaxRetries: cfg.Redis.MaxRetries,
|
||||
PoolSize: cfg.Redis.PoolSize,
|
||||
MinIdleConns: cfg.Redis.MinIdleConns,
|
||||
})
|
||||
|
||||
if err := redisClient.Ping().Err(); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigRedisConnectError,
|
||||
code.Text(code.ConfigRedisConnectError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
defer redisClient.Close()
|
||||
|
||||
outPutString += "已检测 Redis 配置可用。\n"
|
||||
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
|
||||
req.MySQLUser,
|
||||
req.MySQLPass,
|
||||
req.MySQLAddr,
|
||||
req.MySQLName,
|
||||
true,
|
||||
"Local")
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true,
|
||||
},
|
||||
//Logger: logger.Default.LogMode(logger.Info), // 日志配置
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLConnectError,
|
||||
code.Text(code.ConfigMySQLConnectError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
db.Set("gorm:table_options", "CHARSET=utf8mb4")
|
||||
|
||||
dbClient, _ := db.DB()
|
||||
defer dbClient.Close()
|
||||
|
||||
outPutString += "已检测 MySQL 配置可用。\n"
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
viper.Set("redis.addr", req.RedisAddr)
|
||||
viper.Set("redis.pass", req.RedisPass)
|
||||
viper.Set("redis.db", req.RedisDb)
|
||||
|
||||
viper.Set("mysql.read.addr", req.MySQLAddr)
|
||||
viper.Set("mysql.read.user", req.MySQLUser)
|
||||
viper.Set("mysql.read.pass", req.MySQLPass)
|
||||
viper.Set("mysql.read.name", req.MySQLName)
|
||||
|
||||
viper.Set("mysql.write.addr", req.MySQLAddr)
|
||||
viper.Set("mysql.write.user", req.MySQLUser)
|
||||
viper.Set("mysql.write.pass", req.MySQLPass)
|
||||
viper.Set("mysql.write.name", req.MySQLName)
|
||||
|
||||
if viper.WriteConfig() != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigSaveError,
|
||||
code.Text(code.ConfigSaveError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += "配置项 Redis、MySQL 配置成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+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.ConfigMySQLInstallError,
|
||||
"MySQL "+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.ConfigMySQLInstallError,
|
||||
"MySQL "+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.ConfigMySQLInstallError,
|
||||
"MySQL "+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.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin 默认数据成功。\n"
|
||||
|
||||
// 生成 install 完成标识
|
||||
f, err := os.Create(configs.ProjectInstallFile())
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"create lock file err: "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
c.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
37
internal/web/controller/install_handler/func_restart.go
Normal file
37
internal/web/controller/install_handler/func_restart.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) Restart() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
shellPath := "./scripts/restart.sh"
|
||||
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
outPutString := ""
|
||||
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
outPutString += stderr.String()
|
||||
c.Payload(outPutString)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += string(output)
|
||||
|
||||
c.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package configinfo_handler
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
@@ -7,6 +7,6 @@ import (
|
||||
|
||||
func (h *handler) View() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("configinfo", configs.Get())
|
||||
c.HTML("install_view", configs.Get())
|
||||
}
|
||||
}
|
||||
29
internal/web/controller/install_handler/handler.go
Normal file
29
internal/web/controller/install_handler/handler.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
View() core.HandlerFunc
|
||||
Execute() core.HandlerFunc
|
||||
Restart() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,4 +1,4 @@
|
||||
package mysql
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `admin` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
@@ -1,4 +1,4 @@
|
||||
package mysql
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `authorized` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
@@ -1,4 +1,4 @@
|
||||
package mysql
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `authorized_api` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
@@ -11,7 +11,7 @@ package mysql
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址';
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址表';
|
||||
|
||||
func CreateAuthorizedAPITableSql() (sql string) {
|
||||
sql = "CREATE TABLE `authorized_api` ("
|
||||
@@ -25,7 +25,7 @@ func CreateAuthorizedAPITableSql() (sql string) {
|
||||
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 += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址表';"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package mysql
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `user_demo` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
71
main.go
71
main.go
@@ -7,9 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/grpc"
|
||||
"github.com/xinliangnote/go-gin-api/internal/router"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/logger"
|
||||
@@ -43,33 +40,15 @@ func main() {
|
||||
}
|
||||
defer loggers.Sync()
|
||||
|
||||
// 初始化 DB
|
||||
dbRepo, err := db.New()
|
||||
if err != nil {
|
||||
loggers.Fatal("new db err", zap.Error(err))
|
||||
}
|
||||
|
||||
// 初始化 Cache
|
||||
cacheRepo, err := cache.New()
|
||||
if err != nil {
|
||||
loggers.Fatal("new cache err", zap.Error(err))
|
||||
}
|
||||
|
||||
// 初始化 gRPC client
|
||||
gRPCRepo, err := grpc.New()
|
||||
if err != nil {
|
||||
loggers.Fatal("new grpc err", zap.Error(err))
|
||||
}
|
||||
|
||||
// 初始化 HTTP 服务
|
||||
mux, err := router.NewHTTPMux(loggers, dbRepo, cacheRepo, gRPCRepo)
|
||||
s, err := router.NewHTTPServer(loggers)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
server := &http.Server{
|
||||
Addr: configs.ProjectPort(),
|
||||
Handler: mux,
|
||||
Handler: s.Mux,
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -94,35 +73,41 @@ func main() {
|
||||
|
||||
// 关闭 db
|
||||
func() {
|
||||
if err := dbRepo.DbWClose(); err != nil {
|
||||
loggers.Error("dbw close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("dbw close success")
|
||||
}
|
||||
if s.Db != nil {
|
||||
if err := s.Db.DbWClose(); err != nil {
|
||||
loggers.Error("dbw close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("dbw close success")
|
||||
}
|
||||
|
||||
if err := dbRepo.DbRClose(); err != nil {
|
||||
loggers.Error("dbr close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("dbr close success")
|
||||
if err := s.Db.DbRClose(); err != nil {
|
||||
loggers.Error("dbr close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("dbr close success")
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭 cache
|
||||
func() {
|
||||
if err := cacheRepo.Close(); err != nil {
|
||||
loggers.Error("cache close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("cache close success")
|
||||
if s.Cache != nil {
|
||||
if err := s.Cache.Close(); err != nil {
|
||||
loggers.Error("cache close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("cache close success")
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭 gRPC client
|
||||
//func() {
|
||||
// if err := gRPCRepo.Conn().Close(); err != nil {
|
||||
// loggers.Error("gRPC client close err", zap.Error(err))
|
||||
// } else {
|
||||
// loggers.Info("gRPC client close success")
|
||||
// }
|
||||
//},
|
||||
func() {
|
||||
if s.GrpClient != nil {
|
||||
if err := s.GrpClient.Conn().Close(); err != nil {
|
||||
loggers.Error("gRPC client close err", zap.Error(err))
|
||||
} else {
|
||||
loggers.Info("gRPC client close success")
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
16
scripts/restart.sh
Executable file
16
scripts/restart.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
shellExit()
|
||||
{
|
||||
if [ $1 -eq 1 ]; then
|
||||
printf "\nfailed!!!\n\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
printf "\nRestart server port:9999 \n\n"
|
||||
|
||||
lsof -i:9999 | grep LISTEN | awk '{print $2}' | xargs kill -s SIGINT && go run ./main.go -env fat
|
||||
shellExit $?
|
||||
|
||||
printf "\nDone.\n\n"
|
||||
Reference in New Issue
Block a user