This commit is contained in:
新亮
2021-05-09 21:43:23 +08:00
parent 8fbcb5d717
commit ec3c9f0ccf
83 changed files with 3971 additions and 284 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
1. 支持 [gorm](https://gorm.io/gorm) 数据库组件
1. 支持 [go-redis](https://github.com/go-redis/redis/v7) 组件
1. 支持 RESTful API 返回值规范
1. 支持 gormgen、handlergen 代码生成工具
1. 支持 生成数据表 CURD、控制器方法 等代码生成
1. 支持 web 界面,使用的 [Light Year Admin 模板](https://gitee.com/yinqi/Light-Year-Admin-Using-Iframe)
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

+1 -1
View File
@@ -3,7 +3,7 @@ document.write('<script type="text/javascript" src="../../bootstrap/js/authoriza
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/hmac-sha256.js"></script>');
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/enc-base64.min.js"></script>');
document.write('<script type="text/javascript" src="../../bootstrap/js/jquery.cookie.min.js"></script>');
document.write('<div style="display:none"><script type="text/javascript">document.write(unescape("%3Cspan id=\'cnzz_stat_icon_1279911342\'%3E%3C/span%3E%3Cscript src=\'https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26\' type=\'text/javascript\'%3E%3C/script%3E"));</script></div>');
function GenerateAuthorization(path, method, params) {
let key = "admin";
+8
View File
@@ -131,6 +131,9 @@
' <a class="btn btn-xs btn-default btn-resetPassword" href="#!" title=""\n' +
' data-id="' + value.hashid + '"' +
' data-toggle="tooltip" data-original-title="重置密码">重置密码</a>\n' +
' <a class="btn btn-xs btn-default btn-menu" href="#!" title=""\n' +
' data-id="' + value.hashid + '"' +
' data-toggle="tooltip" data-original-title="菜单授权">菜单授权</a>\n' +
' <a class="btn btn-xs btn-default btn-confirm" href="#!" title=""\n' +
' data-id="' + value.hashid + '"' +
' data-toggle="tooltip" data-original-title="删除">删除</a>\n' +
@@ -272,6 +275,11 @@
});
});
// 菜单授权
$(document).on('click', '.btn-menu', function () {
location.href = "/admin/action/" + $(this).attr('data-id');
});
// 删除
$(document).on('click', '.btn-confirm', function () {
const id = $(this).attr('data-id');
+1 -1
View File
@@ -115,7 +115,7 @@
AjaxForm(
"POST",
"/login/web",
"/api/login",
postData,
function () {
},
+213
View File
@@ -0,0 +1,213 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="card-title">配置菜单
<small id="adminName"></small>
</div>
</div>
<div class="card-body">
<form action="#!" method="post" id="form">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="check-all">
<label class="custom-control-label" for="check-all">全选/取消全选</label>
</div>
</th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
</div>
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
执行中...
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
<script type="text/javascript">
$(document).ready(function () {
const hash_id = {{ .HashID }}
AjaxForm(
"GET",
"/api/admin/menu/" + hash_id,
'',
function () {
},
function (data) {
$("#adminName").html("(管理员:" + data.username + "");
if (data.list.length > 0) {
let newArr = [];
data.list.forEach(function (v) {
if (v.pid === 0) {
v.children = [];
newArr.push(v)
}
});
data.list.forEach(function (v) {
newArr.forEach(function (item) {
if (v.pid === item.id) {
item.children.push(v)
}
})
});
$.each(newArr, function (index, value) {
let checked = "";
if (value.is_have == 1) {
checked = "checked";
}
let tr = '<tr><td><div class="custom-control custom-checkbox custom-parent">';
tr += '<input type="checkbox" ' + checked + ' class="custom-control-input checkbox-parent" id="' + value.id + '" value="' + value.id + '">';
tr += '<label class="custom-control-label" for="' + value.id + '">' + value.name + '</label>';
tr += '</div></td></tr>';
tr += '<tr><td class="p-l-40">';
value.children.forEach(function (item) {
let itemChecked = "";
if (item.is_have == 1) {
itemChecked = "checked";
}
tr += '<div class="custom-control custom-checkbox custom-control-inline">';
tr += '<input type="checkbox" ' + itemChecked + ' class="custom-control-input checkbox-child c-' + item.pid + '" id="' + item.id + '" value="' + item.id + '">';
tr += '<label class="custom-control-label" for="' + item.id + '">' + item.name + '</label>';
tr += '</div>';
});
tr += '</td></tr>';
$(".tbody").append(tr);
});
}
},
function (response) {
AjaxError(response);
}
);
$(document).on('click', '.checkbox-parent', function () {
const id = $(this).attr('id');
if ($(this).prop('checked') === true) {
$(this).prop('checked', true);
$('.c-' + id).prop('checked', true);
} else {
$(this).prop('checked', false);
$('.c-' + id).prop('checked', false);
}
});
$(document).on('click', '.checkbox-child', function () {
if ($(this).prop('checked') === true) {
$(this).prop('checked', true);
} else {
$(this).prop('checked', false);
}
});
$(document).on('click', '#check-all', function () {
if ($(this).prop('checked') === true) {
$('.checkbox-parent').prop('checked', true);
$('.checkbox-child').prop('checked', true);
} else {
$('.checkbox-parent').prop('checked', false);
$('.checkbox-child').prop('checked', false);
}
});
$('#btnOk').on('click', function () {
let vals = [];
$.each($('.tbody').find('input:checkbox:checked'), function () {
vals.push($(this).val());
});
if (vals.length === 0) {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请至少选择 1 个功能权限。',
});
return false;
}
AjaxForm(
"POST",
"/api/admin/menu",
{id: hash_id, actions: vals.join(',')},
function () {
$(this).hide();
$("#btnLoading").show();
},
function () {
$("#btnLoading").hide();
$("#btnOk").show();
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: $("#adminName").html() + ' 菜单授权完成。',
buttons: {
okay: {
text: '关闭',
action: function () {
location.href = "/admin/list";
}
}
}
});
},
function (response) {
$("#btnLoading").hide();
$("#btnOk").show();
AjaxError(response);
}
);
});
})
</script>
</body>
</html>
@@ -58,7 +58,7 @@
<div class="col-lg-6">
<div class="card">
<header class="card-header">
<div class="card-title">已授权接口</div>
<div class="card-title">已授权接口<small id="businessKey"></small></div>
</header>
<div class="card-body apis">
@@ -96,6 +96,7 @@
},
function (data) {
$("#businessKey").html("(授权方:" + data.business_key + "");
if (data.list.length > 0) {
var badgeMethodClass = "";
@@ -210,5 +210,6 @@ console.log({authorization: key + " " + digest, date: datetime});
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/main.min.js"></script>
<script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279911342'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26' type='text/javascript'%3E%3C/script%3E"));</script>
</body>
</html>
+3 -1
View File
@@ -42,6 +42,8 @@
</div>
</div>
<div style="display:none">
<script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279911342'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26' type='text/javascript'%3E%3C/script%3E"));</script>
</div>
</body>
</html>
@@ -14,7 +14,7 @@
<div class="col-lg-12">
<div class="card">
<header class="card-header">
<div class="card-title"> 邮箱告警配置</div>
<div class="card-title">邮箱告警配置</div>
</header>
<div class="card-body">
<form class="site-form">
@@ -119,7 +119,7 @@
return false;
}
const postData = {
const patchData = {
host: host,
port: port,
user: user,
@@ -131,7 +131,7 @@
AjaxForm(
"PATCH",
"/api/config/email",
postData,
patchData,
function () {
$(this).hide();
$("#btnLoading").show();
+33 -11
View File
@@ -3,8 +3,8 @@
<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">
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
</head>
<body>
@@ -12,6 +12,19 @@
<div class="row">
<div class="col-md-6 col-lg-4">
<div class="card border-secondary">
<header class="card-header">
<div class="card-title">项目信息</div>
</header>
<div class="card-body">
<p>操作系统:{{ .GoOS }} <span class="badge badge-brown"> {{ .GoArch }} </span> <span class="badge badge-info"> {{ .GoVersion }} </span></p>
<p>项目地址:{{ .ProjectPath }}</p>
<p>项目域名:{{ .Host }} <span class="badge badge-secondary"> {{ .Env }} </span></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="card border-secondary">
<header class="card-header">
@@ -66,21 +79,30 @@
<div class="col-md-6 col-lg-4">
<div class="card border-secondary">
<header class="card-header">
<div class="card-title">项目信息</div>
<div class="card-title">开源信息</div>
</header>
<div class="card-body">
<p>操作系统:{{ .GoOS }} <span class="badge badge-brown"> {{ .GoArch }} </span></p>
<p>项目地址:{{ .ProjectPath }}</p>
<p>项目域名:{{ .Host }} <span class="badge badge-secondary"> {{ .Env }} </span></p>
<p>GOPATH{{ .GoPath }}</p>
<p>Version{{ .GoVersion }}</p>
<p>Goroutine{{ .Goroutine }}</p>
<p>GitHub 地址:<a target="_blank" href="https://github.com/xinliangnote/go-gin-api">xinliangnote/go-gin-api</a></p>
<p>GitHub Stars<a href="https://github.com/xinliangnote/go-gin-api/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/xinliangnote/go-gin-api?style=flat-square"></a></p>
<p>GitHub Forks<a href="https://github.com/xinliangnote/go-gin-api/network"><img alt="GitHub forks" src="https://img.shields.io/github/forks/xinliangnote/go-gin-api?style=flat-square"></a></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="card border-secondary">
<header class="card-header">
<div class="card-title">欢迎交流</div>
</header>
<div class="card-body text-center">
<p style="height: 105px;">
<img style="height: 100px;" src="../../bootstrap/images/qr-code.png"/>
</p>
</div>
</div>
</div>
</div>
</div>
@@ -3,9 +3,9 @@
<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/style.min.css" rel="stylesheet">
<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/style.min.css" rel="stylesheet">
</head>
<body>
@@ -13,7 +13,7 @@
<div class="row">
<div class="col-lg-6">
<div class="card">
<header class="card-header"><div class="card-title"> <code>gormgen</code> 代码生成工具</div></header>
<header class="card-header"><div class="card-title"> 生成数据表 CURD </div></header>
<div class="card-body">
<div class="form-group">
<label for="tableSelect">选择数据表,可进行多选:</label>
@@ -48,9 +48,9 @@
</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/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(){
@@ -75,7 +75,7 @@
tables.push(options.eq(i).val()); // 将所有的值赋给数组
}
$.post("/gormgen_exec",{tables:tables.join(',')},function (data) {
$.post("/generator/gorm/execute",{tables:tables.join(',')},function (data) {
$("#resultDiv").text(data);
$("#btnLoading").hide();
$("#btnOk").show();
@@ -84,5 +84,8 @@
})
})
</script>
<div style="display:none">
<script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279911342'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26' type='text/javascript'%3E%3C/script%3E"));</script>
</div>
</body>
</html>
@@ -3,9 +3,9 @@
<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/style.min.css" rel="stylesheet">
<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/style.min.css" rel="stylesheet">
</head>
<body>
@@ -13,7 +13,7 @@
<div class="row">
<div class="col-lg-6">
<div class="card">
<header class="card-header"><div class="card-title"> <code>handlergen</code> 代码生成工具</div></header>
<header class="card-header"><div class="card-title"> 生成控制器方法 </div></header>
<div class="card-body">
<div class="form-group">
<label for="exampleFormControlInput1">handler 名称,例如:<code>user_handler</code></label>
@@ -44,9 +44,9 @@
</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/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(){
@@ -65,7 +65,7 @@
$(this).hide();
$("#btnLoading").show();
$.post("/handlergen_exec",{name:handlerName},function (data) {
$.post("/generator/handler/execute",{name:handlerName},function (data) {
$("#resultDiv").text(data);
$("#btnLoading").hide();
$("#btnOk").show();
@@ -74,5 +74,8 @@
})
})
</script>
<div style="display:none">
<script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279911342'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26' type='text/javascript'%3E%3C/script%3E"));</script>
</div>
</body>
</html>
+3 -2
View File
@@ -45,8 +45,8 @@
<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="/gormgen">gormgen</a> </li>
<li> <a class="multitabs" href="/handlergen">handlergen</a> </li>
<li> <a class="multitabs" href="/generator/gorm">生成数据表 CURD</a> </li>
<li> <a class="multitabs" href="/generator/handler">生成控制器方法</a> </li>
</ul>
</li>
@@ -77,6 +77,7 @@
<li class="nav-item nav-item-has-subnav">
<a href="javascript:void(0)"><i class="mdi mdi-tools"></i> <span>实用工具箱</span></a>
<ul class="nav nav-subnav">
<li> <a class="multitabs" href="/upgrade">服务升级</a> </li>
<li> <a class="multitabs" href="/tool/hashids">Hashids</a> </li>
<li> <a class="multitabs" href="/tool/logs">调用日志</a> </li>
<li> <a target="_blank" href="/swagger/index.html">接口文档</a> </li>
+17 -5
View File
@@ -1,8 +1,14 @@
<!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"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<title>服务初始化</title>
<link rel="shortcut icon" type="image/x-icon" href="../../bootstrap/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<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">
@@ -18,7 +24,7 @@
<div class="card-title">服务初始化</div>
</header>
<div class="card-body text-center">
<h4 class="card-title">检测环境</h4>
<h4 class="card-title">检测 · 环境</h4>
<div class="input-group mb-3">
<p class="text-left">所需版本: Go Version <code>go1.15+</code>,目前版本:<code>{{.GoVersion}}</code></p>
@@ -85,8 +91,14 @@
</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><code>menu</code>
<small>
<i class="mdi mdi-checkbox-marked-circle"></i>
初始化 MySQL 数据表:<code>authorized</code>
<code>authorized_api</code>
<code>admin</code>
<code>menu</code>
<code>menu_action</code>
<code>admin_menu</code>
</small>
</div>
+123
View File
@@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<title>服务升级</title>
<link rel="shortcut icon" type="image/x-icon" href="../../bootstrap/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<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-12">
<div class="card">
<header class="card-header">
<div class="card-title">服务升级</div>
</header>
<div class="card-body">
<p class="h6">发现 GitHub 仓库更新了新代码,如何进行服务升级?</p>
<p>1、源代码升级:
<mark>拉取最新代码,覆盖旧版本代码即可。</mark>
</p>
<p>2、数据表升级:</p>
{{range $key, $value := .List}}
<p style="margin-left: 24px;">
<i class="mdi mdi-checkbox-marked-circle"></i> MySQL 数据表:{{$value.TableName}}
{{if eq $value.IsHave 1}} <font class="text-success">已存在</font>
{{else}} <font class="text-danger">不存在</font>
{{end}}
<button class="btn btn-xs btn-info upgrade" data-op="table"
data-table="{{$value.TableName}}">创建表结构
</button>
<button class="btn btn-xs btn-cyan upgrade" data-op="table_data"
data-table="{{$value.TableName}}">初始化数据
</button>
</p>
{{end}}
</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 () {
$(document).on('click', '.upgrade', function () {
const op = $(this).attr('data-op');
const table = $(this).attr('data-table');
let tipMsg;
if (op === "table") {
tipMsg = '请先确保数据表不存在,确定要创建表结构吗?';
}
if (op === "table_data") {
tipMsg = '请先确保表中数据不存在,确定要初始化表数据吗?';
}
$.confirm({
title: '谨慎操作',
content: tipMsg,
icon: 'mdi mdi-alert',
animation: 'scale',
closeAnimation: 'zoom',
buttons: {
okay: {
text: '确认',
keys: ['enter'],
btnClass: 'btn-orange',
action: function () {
AjaxForm(
"POST",
'/upgrade/execute',
{table_name: table, op: op},
function () {
},
function (data) {
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: data,
buttons: {
okay: {
text: '关闭',
action: function () {
location.reload();
}
}
}
});
},
function (response) {
AjaxError(response);
}
);
}
},
cancel: {
text: '取消',
keys: ['ctrl', 'shift'],
}
}
});
});
});
</script>
</body>
</html>
+261
View File
@@ -0,0 +1,261 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="../../bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-6">
<div class="card">
<div class="card-header">
<div class="card-title">功能权限</div>
</div>
<div class="card-body">
<div class="alert alert-warning" role="alert">
接口地址支持通配符(*),其中 * 表示 1 级,** 表示 n 级。
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="request_method">选择请求方式</label>
</div>
<select class="custom-select" id="request_method">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
<option value="PATCH">PATCH</option>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">输入接口地址</span>
</div>
<input type="text" class="form-control" maxlength="60" id="request_api"
placeholder="接口地址">
</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">已配置功能权限
<small id="menuName"></small>
</div>
</header>
<div class="card-body apis">
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
<script type="text/javascript">
$(document).ready(function () {
const hash_id = {{ .HashID }}
$("input#request_api").maxlength({
warningClass: "badge badge-info",
limitReachedClass: "badge badge-warning"
});
// 加载列表页数据
getListData();
function getListData() {
AjaxForm(
"GET",
"/api/menu_action",
{id: hash_id},
function () {
},
function (data) {
$("#menuName").html("(菜单栏:" + data.menu_name + "");
if (data.list.length > 0) {
var badgeMethodClass = "";
$.each(data.list, function (index, value) {
if (value.method === "GET") {
badgeMethodClass = "badge-primary";
} else if (value.method === "POST") {
badgeMethodClass = "badge-success";
} else if (value.method === "DELETE") {
badgeMethodClass = "badge-danger";
} else if (value.method === "PUT") {
badgeMethodClass = "badge-yellow";
} else if (value.method === "PATCH") {
badgeMethodClass = "badge-cyan";
} else {
badgeMethodClass = "badge-dark";
}
const p = '<p>\n' +
'<a href="#!" data-id="' + value.hash_id + '" data-api="' + value.api + '" class="del">' +
'<span class="badge badge-dark"><i class="mdi mdi-window-close"></i></span>\n' +
'</a>\n' +
'<span class="badge ' + badgeMethodClass + '">' + value.method + '</span>\n' + value.api
;
$(".apis").append(p);
})
} else {
// 数据为空
const p = '<p>暂无功能权限</p>';
$(".apis").append(p);
}
},
function (response) {
AjaxError(response);
}
);
}
$('#btnOk').on('click', function () {
const requestMethod = $("#request_method").val();
const requestApi = $("#request_api").val();
if (requestMethod === "") {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请选择请求方式。',
});
return false;
}
if (requestApi === "") {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请输入请求地址。',
});
return false;
}
const postData = {
method: requestMethod,
api: requestApi,
id: hash_id,
};
AjaxForm(
"POST",
"/api/menu_action",
postData,
function () {
$(this).hide();
$("#btnLoading").show();
},
function () {
$("#btnLoading").hide();
$("#btnOk").show();
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: '接口:' + requestApi + ' 配置完成。',
buttons: {
okay: {
text: '关闭',
action: function () {
location.reload();
}
}
}
});
},
function (response) {
$("#btnLoading").hide();
$("#btnOk").show();
AjaxError(response);
}
);
});
$(document).on('click', '.del', function () {
const id = $(this).attr('data-id');
const api = $(this).attr('data-api');
$.confirm({
title: '谨慎操作',
content: '确认要 <strong style="color: red">取消配置</strong> 吗?',
icon: 'mdi mdi-alert',
animation: 'scale',
closeAnimation: 'zoom',
buttons: {
okay: {
text: '确认',
keys: ['enter'],
btnClass: 'btn-orange',
action: function () {
AjaxForm(
"DELETE",
'/api/menu_action/' + id,
"",
function () {
},
function () {
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: '接口:' + api + ' 已取消配置。',
buttons: {
okay: {
text: '关闭',
action: function () {
location.reload();
}
}
}
});
},
function (response) {
AjaxError(response);
}
);
}
},
cancel: {
text: '取消',
keys: ['ctrl', 'shift'],
}
}
});
})
})
</script>
</body>
</html>
+32 -13
View File
@@ -123,15 +123,11 @@
dataType: 'jsonp',
//toolbar: '#toolbar2',
columns: [
{
field: 'id',
title: '编号'
},
{
field: 'name',
title: '名称',
formatter: function (value, row, index) {
return row.name + '<i class="mdi ' + row.icon + '"></i>';
return '<i class="mdi ' + row.icon + '"></i>' + row.name ;
}
},
{
@@ -165,6 +161,19 @@
},
'click .role-edit': function (e, value, row, index) {
update(row.hashid);
},
'click .role-action': function (e, value, row, index) {
if (row.link !== '') {
location.href = "/admin/menu_action/" + row.hashid;
} else {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '当前菜单无需设置功能权限。',
});
return false;
}
}
},
formatter: operateFormatter
@@ -177,7 +186,7 @@
onResetView: function (menuData) {
$treeTable.treegrid({
initialState: 'collapsed', // 所有节点都折叠
treeColumn: 1,
treeColumn: 0,
//expanderExpandedClass: 'mdi mdi-folder-open', // 可自定义图标样式
//expanderCollapsedClass: 'mdi mdi-folder',
});
@@ -193,6 +202,7 @@
return [
'<a type="button" class="role-add btn btn-xs btn-default m-r-5" title="编辑" data-toggle="tooltip"><i class="mdi mdi-plus"></i></a>',
'<a type="button" class="role-edit btn btn-xs btn-default m-r-5" title="修改" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>',
'<a type="button" class="role-action btn btn-xs btn-default m-r-5" title="功能权限" data-toggle="tooltip"><i class="mdi mdi-playlist-plus"></i></a>',
'<a type="button" class="role-delete btn btn-xs btn-default" title="删除" data-toggle="tooltip"><i class="mdi mdi-delete"></i></a>'
].join('');
}
@@ -224,12 +234,12 @@
"",
function () {
},
function (data) {
function () {
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: '编号:' + data.id + ' 已删除。',
content: '已删除成功。',
buttons: {
okay: {
text: '关闭',
@@ -266,11 +276,20 @@
function () {
},
function (data) {
$('#level').selectpicker('val', data.id);
$("#level").selectpicker('refresh');
$("#level").attr("disabled", "");
if (op === 'add') {
$('#level').selectpicker('val', data.id);
$("#level").selectpicker('refresh');
$("#level").attr("disabled", "");
}
if (op === 'update') {
if (data.pid === 0) {
data.pid = -1
}
$('#level').selectpicker('val', data.pid);
$("#level").selectpicker('refresh');
$("#level").attr("disabled", "");
$("#id").val(id);
$("#name").val(data.name);
$("#icon").val(data.icon);
@@ -308,12 +327,12 @@
{id: hashid, used: is_used},
function () {
},
function (data) {
function () {
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: '编号:' + data.id + ' 已' + is_used_msg + '。',
content: '已' + is_used_msg + '成功。',
buttons: {
okay: {
text: '关闭',
+1 -1
View File
@@ -48,7 +48,7 @@
<div class="col-lg-6">
<div class="card">
<header class="card-header">
<div class="card-title">执行结果</div>
<div class="card-title">查询结果</div>
</header>
<div class="card-body">
<pre id="resultDiv" style="white-space: pre-wrap;word-wrap: break-word;"></pre>
+3
View File
@@ -100,5 +100,8 @@
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
<div style="display:none">
<script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279911342'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26' type='text/javascript'%3E%3C/script%3E"));</script>
</div>
</body>
</html>
+24 -14
View File
@@ -44,20 +44,6 @@ func (t *{{.StructName}}) Create(db *gorm.DB) (id int32, err error) {
return t.Id, nil
}
func (t *{{.StructName}}) Delete(db *gorm.DB) (err error) {
if err = db.Delete(t).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (t *{{.StructName}}) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
if err = db.Model(&{{.StructName}}{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
type {{.QueryBuilderName}} struct {
order []string
where []struct {
@@ -80,6 +66,30 @@ func (qb *{{.QueryBuilderName}}) buildQuery(db *gorm.DB) *gorm.DB {
return ret
}
func (qb *{{.QueryBuilderName}}) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&{{.StructName}}{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *{{.QueryBuilderName}}) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&{{.StructName}}{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *{{.QueryBuilderName}}) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&{{.StructName}}{}).Count(&c)
+320 -14
View File
@@ -32,7 +32,7 @@ var doc = `{
"get": {
"description": "管理员列表",
"consumes": [
"application/json"
"multipart/form-data"
],
"produces": [
"application/json"
@@ -220,9 +220,9 @@ var doc = `{
}
}
},
"/api/admin/modify_password": {
"patch": {
"description": "修改密码",
"/api/admin/menu": {
"post": {
"description": "提交菜单授权",
"consumes": [
"multipart/form-data"
],
@@ -232,19 +232,19 @@ var doc = `{
"tags": [
"API.admin"
],
"summary": "修改密码",
"summary": "提交菜单授权",
"parameters": [
{
"type": "string",
"description": "旧密码",
"name": "old_password",
"description": "Hashid",
"name": "id",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "新密码",
"name": "new_password",
"description": "功能权限ID,多个用,分割",
"name": "actions",
"in": "formData",
"required": true
}
@@ -253,7 +253,90 @@ var doc = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.modifyPasswordResponse"
"$ref": "#/definitions/admin_handler.createResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/admin/menu/:id": {
"get": {
"description": "菜单授权列表",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"API.admin"
],
"summary": "菜单授权列表",
"parameters": [
{
"type": "string",
"description": "hashId",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.listAdminMenuResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/admin/modify_password": {
"patch": {
"description": "修改个人信息",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.admin"
],
"summary": "修改个人信息",
"parameters": [
{
"type": "string",
"description": "昵称",
"name": "nickname",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "手机号",
"name": "mobile",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.modifyPersonalInfoResponse"
}
},
"400": {
@@ -590,7 +673,7 @@ var doc = `{
"get": {
"description": "调用方接口地址列表",
"consumes": [
"application/json"
"multipart/form-data"
],
"produces": [
"application/json"
@@ -602,9 +685,10 @@ var doc = `{
"parameters": [
{
"type": "string",
"description": "调用方key",
"name": "business_key",
"in": "query"
"description": "hashID",
"name": "id",
"in": "query",
"required": true
}
],
"responses": {
@@ -963,6 +1047,132 @@ var doc = `{
}
}
},
"/api/menu_action": {
"get": {
"description": "功能权限列表",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "功能权限列表",
"parameters": [
{
"type": "string",
"description": "hashID",
"name": "id",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.listActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
},
"post": {
"description": "创建功能权限",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "创建功能权限",
"parameters": [
{
"type": "string",
"description": "HashID",
"name": "id",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "请求方法",
"name": "method",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "请求地址",
"name": "api",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.createActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/menu_action/{id}": {
"delete": {
"description": "删除功能权限",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "删除功能权限",
"parameters": [
{
"type": "string",
"description": "hashId",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.deleteActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/tool/cache/clear": {
"patch": {
"description": "清空缓存",
@@ -1271,6 +1481,20 @@ var doc = `{
}
}
},
"admin_handler.listAdminMenuResponse": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/admin_service.ListMenuData"
}
},
"username": {
"type": "string"
}
}
},
"admin_handler.listData": {
"type": "object",
"properties": {
@@ -1395,6 +1619,27 @@ var doc = `{
}
}
},
"admin_service.ListMenuData": {
"type": "object",
"properties": {
"id": {
"description": "ID",
"type": "integer"
},
"is_have": {
"description": "是否已拥有权限",
"type": "integer"
},
"name": {
"description": "菜单名称",
"type": "string"
},
"pid": {
"description": "父类ID",
"type": "integer"
}
}
},
"authorized_handler.createAPIResponse": {
"type": "object",
"properties": {
@@ -1455,6 +1700,10 @@ var doc = `{
"authorized_handler.listAPIResponse": {
"type": "object",
"properties": {
"business_key": {
"description": "调用方key",
"type": "string"
},
"list": {
"type": "array",
"items": {
@@ -1568,6 +1817,15 @@ var doc = `{
}
}
},
"menu_handler.createActionResponse": {
"type": "object",
"properties": {
"id": {
"description": "主键ID",
"type": "integer"
}
}
},
"menu_handler.createRequest": {
"type": "object",
"properties": {
@@ -1606,6 +1864,15 @@ var doc = `{
}
}
},
"menu_handler.deleteActionResponse": {
"type": "object",
"properties": {
"id": {
"description": "主键ID",
"type": "integer"
}
}
},
"menu_handler.deleteResponse": {
"type": "object",
"properties": {
@@ -1633,6 +1900,45 @@ var doc = `{
"name": {
"description": "菜单名称",
"type": "string"
},
"pid": {
"description": "父类ID",
"type": "integer"
}
}
},
"menu_handler.listActionData": {
"type": "object",
"properties": {
"api": {
"description": "调用方对接人",
"type": "string"
},
"hash_id": {
"description": "hashID",
"type": "string"
},
"menu_id": {
"description": "菜单栏ID",
"type": "integer"
},
"method": {
"description": "调用方secret",
"type": "string"
}
}
},
"menu_handler.listActionResponse": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/menu_handler.listActionData"
}
},
"menu_name": {
"type": "string"
}
}
},
+320 -14
View File
@@ -15,7 +15,7 @@
"get": {
"description": "管理员列表",
"consumes": [
"application/json"
"multipart/form-data"
],
"produces": [
"application/json"
@@ -203,9 +203,9 @@
}
}
},
"/api/admin/modify_password": {
"patch": {
"description": "修改密码",
"/api/admin/menu": {
"post": {
"description": "提交菜单授权",
"consumes": [
"multipart/form-data"
],
@@ -215,19 +215,19 @@
"tags": [
"API.admin"
],
"summary": "修改密码",
"summary": "提交菜单授权",
"parameters": [
{
"type": "string",
"description": "旧密码",
"name": "old_password",
"description": "Hashid",
"name": "id",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "新密码",
"name": "new_password",
"description": "功能权限ID,多个用,分割",
"name": "actions",
"in": "formData",
"required": true
}
@@ -236,7 +236,90 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.modifyPasswordResponse"
"$ref": "#/definitions/admin_handler.createResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/admin/menu/:id": {
"get": {
"description": "菜单授权列表",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"API.admin"
],
"summary": "菜单授权列表",
"parameters": [
{
"type": "string",
"description": "hashId",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.listAdminMenuResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/admin/modify_password": {
"patch": {
"description": "修改个人信息",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.admin"
],
"summary": "修改个人信息",
"parameters": [
{
"type": "string",
"description": "昵称",
"name": "nickname",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "手机号",
"name": "mobile",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/admin_handler.modifyPersonalInfoResponse"
}
},
"400": {
@@ -573,7 +656,7 @@
"get": {
"description": "调用方接口地址列表",
"consumes": [
"application/json"
"multipart/form-data"
],
"produces": [
"application/json"
@@ -585,9 +668,10 @@
"parameters": [
{
"type": "string",
"description": "调用方key",
"name": "business_key",
"in": "query"
"description": "hashID",
"name": "id",
"in": "query",
"required": true
}
],
"responses": {
@@ -946,6 +1030,132 @@
}
}
},
"/api/menu_action": {
"get": {
"description": "功能权限列表",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "功能权限列表",
"parameters": [
{
"type": "string",
"description": "hashID",
"name": "id",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.listActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
},
"post": {
"description": "创建功能权限",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "创建功能权限",
"parameters": [
{
"type": "string",
"description": "HashID",
"name": "id",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "请求方法",
"name": "method",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "请求地址",
"name": "api",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.createActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/menu_action/{id}": {
"delete": {
"description": "删除功能权限",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"API.menu"
],
"summary": "删除功能权限",
"parameters": [
{
"type": "string",
"description": "hashId",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/menu_handler.deleteActionResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/code.Failure"
}
}
}
}
},
"/api/tool/cache/clear": {
"patch": {
"description": "清空缓存",
@@ -1254,6 +1464,20 @@
}
}
},
"admin_handler.listAdminMenuResponse": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/admin_service.ListMenuData"
}
},
"username": {
"type": "string"
}
}
},
"admin_handler.listData": {
"type": "object",
"properties": {
@@ -1378,6 +1602,27 @@
}
}
},
"admin_service.ListMenuData": {
"type": "object",
"properties": {
"id": {
"description": "ID",
"type": "integer"
},
"is_have": {
"description": "是否已拥有权限",
"type": "integer"
},
"name": {
"description": "菜单名称",
"type": "string"
},
"pid": {
"description": "父类ID",
"type": "integer"
}
}
},
"authorized_handler.createAPIResponse": {
"type": "object",
"properties": {
@@ -1438,6 +1683,10 @@
"authorized_handler.listAPIResponse": {
"type": "object",
"properties": {
"business_key": {
"description": "调用方key",
"type": "string"
},
"list": {
"type": "array",
"items": {
@@ -1551,6 +1800,15 @@
}
}
},
"menu_handler.createActionResponse": {
"type": "object",
"properties": {
"id": {
"description": "主键ID",
"type": "integer"
}
}
},
"menu_handler.createRequest": {
"type": "object",
"properties": {
@@ -1589,6 +1847,15 @@
}
}
},
"menu_handler.deleteActionResponse": {
"type": "object",
"properties": {
"id": {
"description": "主键ID",
"type": "integer"
}
}
},
"menu_handler.deleteResponse": {
"type": "object",
"properties": {
@@ -1616,6 +1883,45 @@
"name": {
"description": "菜单名称",
"type": "string"
},
"pid": {
"description": "父类ID",
"type": "integer"
}
}
},
"menu_handler.listActionData": {
"type": "object",
"properties": {
"api": {
"description": "调用方对接人",
"type": "string"
},
"hash_id": {
"description": "hashID",
"type": "string"
},
"menu_id": {
"description": "菜单栏ID",
"type": "integer"
},
"method": {
"description": "调用方secret",
"type": "string"
}
}
},
"menu_handler.listActionResponse": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/menu_handler.listActionData"
}
},
"menu_name": {
"type": "string"
}
}
},
+219 -13
View File
@@ -23,6 +23,15 @@ definitions:
description: 用户名
type: string
type: object
admin_handler.listAdminMenuResponse:
properties:
list:
items:
$ref: '#/definitions/admin_service.ListMenuData'
type: array
username:
type: string
type: object
admin_handler.listData:
properties:
created_at:
@@ -108,6 +117,21 @@ definitions:
description: 主键ID
type: integer
type: object
admin_service.ListMenuData:
properties:
id:
description: ID
type: integer
is_have:
description: 是否已拥有权限
type: integer
name:
description: 菜单名称
type: string
pid:
description: 父类ID
type: integer
type: object
authorized_handler.createAPIResponse:
properties:
id:
@@ -149,6 +173,9 @@ definitions:
type: object
authorized_handler.listAPIResponse:
properties:
business_key:
description: 调用方key
type: string
list:
items:
$ref: '#/definitions/authorized_handler.listAPIData'
@@ -227,6 +254,12 @@ definitions:
description: 邮箱地址
type: string
type: object
menu_handler.createActionResponse:
properties:
id:
description: 主键ID
type: integer
type: object
menu_handler.createRequest:
properties:
icon:
@@ -254,6 +287,12 @@ definitions:
description: 主键ID
type: integer
type: object
menu_handler.deleteActionResponse:
properties:
id:
description: 主键ID
type: integer
type: object
menu_handler.deleteResponse:
properties:
id:
@@ -274,6 +313,33 @@ definitions:
name:
description: 菜单名称
type: string
pid:
description: 父类ID
type: integer
type: object
menu_handler.listActionData:
properties:
api:
description: 调用方对接人
type: string
hash_id:
description: hashID
type: string
menu_id:
description: 菜单栏ID
type: integer
method:
description: 调用方secret
type: string
type: object
menu_handler.listActionResponse:
properties:
list:
items:
$ref: '#/definitions/menu_handler.listActionData'
type: array
menu_name:
type: string
type: object
menu_handler.listData:
properties:
@@ -404,7 +470,7 @@ paths:
/api/admin:
get:
consumes:
- application/json
- multipart/form-data
description: 管理员列表
parameters:
- description: 第几页
@@ -554,20 +620,20 @@ paths:
summary: 管理员登录
tags:
- API.admin
/api/admin/modify_password:
patch:
/api/admin/menu:
post:
consumes:
- multipart/form-data
description: 修改密码
description: 提交菜单授权
parameters:
- description: 旧密码
- description: Hashid
in: formData
name: old_password
name: id
required: true
type: string
- description: 新密码
- description: 功能权限ID,多个用,分割
in: formData
name: new_password
name: actions
required: true
type: string
produces:
@@ -576,12 +642,67 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/admin_handler.modifyPasswordResponse'
$ref: '#/definitions/admin_handler.createResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 修改密码
summary: 提交菜单授权
tags:
- API.admin
/api/admin/menu/:id:
get:
consumes:
- application/json
description: 菜单授权列表
parameters:
- description: hashId
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/admin_handler.listAdminMenuResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 菜单授权列表
tags:
- API.admin
/api/admin/modify_password:
patch:
consumes:
- multipart/form-data
description: 修改个人信息
parameters:
- description: 昵称
in: formData
name: nickname
required: true
type: string
- description: 手机号
in: formData
name: mobile
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/admin_handler.modifyPersonalInfoResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 修改个人信息
tags:
- API.admin
/api/admin/reset_password/{id}:
@@ -775,12 +896,13 @@ paths:
/api/authorized_api:
get:
consumes:
- application/json
- multipart/form-data
description: 调用方接口地址列表
parameters:
- description: 调用方key
- description: hashID
in: query
name: business_key
name: id
required: true
type: string
produces:
- application/json
@@ -1023,6 +1145,90 @@ paths:
summary: 更新菜单为启用/禁用
tags:
- API.menu
/api/menu_action:
get:
consumes:
- multipart/form-data
description: 功能权限列表
parameters:
- description: hashID
in: query
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/menu_handler.listActionResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 功能权限列表
tags:
- API.menu
post:
consumes:
- multipart/form-data
description: 创建功能权限
parameters:
- description: HashID
in: formData
name: id
required: true
type: string
- description: 请求方法
in: formData
name: method
required: true
type: string
- description: 请求地址
in: formData
name: api
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/menu_handler.createActionResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 创建功能权限
tags:
- API.menu
/api/menu_action/{id}:
delete:
consumes:
- application/json
description: 删除功能权限
parameters:
- description: hashId
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/menu_handler.deleteActionResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
summary: 删除功能权限
tags:
- API.menu
/api/tool/cache/clear:
patch:
consumes:
+20 -10
View File
@@ -45,6 +45,8 @@ const (
AdminLogOutError = 20307
AdminModifyPasswordError = 20308
AdminModifyPersonalInfoError = 20309
AdminMenuListError = 20310
AdminMenuCreateError = 20311
// 配置
ConfigEmailError = 20401
@@ -61,11 +63,14 @@ const (
SearchMySQLError = 20504
// 菜单栏
MenuCreateError = 20601
MenuUpdateError = 20602
MenuListError = 20603
MenuDeleteError = 20604
MenuDetailError = 20605
MenuCreateError = 20601
MenuUpdateError = 20602
MenuListError = 20603
MenuDeleteError = 20604
MenuDetailError = 20605
MenuCreateActionError = 20606
MenuListActionError = 20607
MenuDeleteActionError = 20608
)
var codeText = map[int]string{
@@ -102,6 +107,8 @@ var codeText = map[int]string{
AdminLogOutError: "退出失败",
AdminModifyPasswordError: "修改密码失败",
AdminModifyPersonalInfoError: "修改个人信息失败",
AdminMenuListError: "获取管理员菜单授权列表失败",
AdminMenuCreateError: "管理员菜单授权失败",
ConfigEmailError: "修改邮箱配置失败",
ConfigSaveError: "写入配置文件失败",
@@ -115,11 +122,14 @@ var codeText = map[int]string{
SearchRedisEmpty: "查询的 Redis Key 不存在",
SearchMySQLError: "查询 MySQL 失败",
MenuCreateError: "创建菜单失败",
MenuUpdateError: "更新菜单失败",
MenuDeleteError: "删除菜单失败",
MenuListError: "获取菜单列表页失败",
MenuDetailError: "获取菜单详情失败",
MenuCreateError: "创建菜单失败",
MenuUpdateError: "更新菜单失败",
MenuDeleteError: "删除菜单失败",
MenuListError: "获取菜单列表页失败",
MenuDetailError: "获取菜单详情失败",
MenuCreateActionError: "创建菜单栏功能权限失败",
MenuListActionError: "获取菜单栏功能权限列表失败",
MenuDeleteActionError: "删除菜单栏功能权限失败",
}
func Text(code int) string {
@@ -0,0 +1,72 @@
package admin_handler
import (
"net/http"
"github.com/xinliangnote/go-gin-api/internal/api/code"
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/pkg/errno"
)
type createAdminMenuRequest struct {
Id string `form:"id"` // HashID
Actions string `form:"actions"` // 功能权限ID,多个用,分割
}
type createAdminMenuResponse struct {
Id int32 `json:"id"` // 主键ID
}
// CreateAdminMenu 提交菜单授权
// @Summary 提交菜单授权
// @Description 提交菜单授权
// @Tags API.admin
// @Accept multipart/form-data
// @Produce json
// @Param id formData string true "Hashid"
// @Param actions formData string true "功能权限ID,多个用,分割"
// @Success 200 {object} createResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/menu [post]
func (h *handler) CreateAdminMenu() core.HandlerFunc {
return func(c core.Context) {
req := new(createAdminMenuRequest)
res := new(createAdminMenuResponse)
if err := c.ShouldBindForm(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
ids, err := h.hashids.HashidsDecode(req.Id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.HashIdsDecodeError,
code.Text(code.HashIdsDecodeError)).WithErr(err),
)
return
}
createData := new(admin_service.CreateMenuData)
createData.AdminId = int32(ids[0])
createData.Actions = req.Actions
err = h.adminService.CreateMenu(c, createData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.AdminMenuCreateError,
code.Text(code.AdminMenuCreateError)).WithErr(err),
)
return
}
res.Id = int32(ids[0])
c.Payload(res)
}
}
@@ -47,7 +47,7 @@ type listResponse struct {
// @Summary 管理员列表
// @Description 管理员列表
// @Tags API.admin
// @Accept json
// @Accept multipart/form-data
// @Produce json
// @Param page query int false "第几页"
// @Param page_size query string false "每页显示条数"
@@ -0,0 +1,86 @@
package admin_handler
import (
"net/http"
"github.com/xinliangnote/go-gin-api/internal/api/code"
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/pkg/errno"
)
type listAdminMenuRequest struct {
Id string `uri:"id"` // HashID
}
type listAdminMenuResponse struct {
List []admin_service.ListMenuData `json:"list"`
UserName string `json:"username"`
}
// ListAdminMenu 菜单授权列表
// @Summary 菜单授权列表
// @Description 菜单授权列表
// @Tags API.admin
// @Accept json
// @Produce json
// @Param id path string true "hashId"
// @Success 200 {object} listAdminMenuResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/menu/:id [get]
func (h *handler) ListAdminMenu() core.HandlerFunc {
return func(c core.Context) {
req := new(listAdminMenuRequest)
res := new(listAdminMenuResponse)
if err := c.ShouldBindURI(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
ids, err := h.hashids.HashidsDecode(req.Id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.HashIdsDecodeError,
code.Text(code.HashIdsDecodeError)).WithErr(err),
)
return
}
searchOneData := new(admin_service.SearchOneData)
searchOneData.Id = int32(ids[0])
searchOneData.IsUsed = 1
info, err := h.adminService.Detail(c, searchOneData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.AdminMenuListError,
code.Text(code.AdminMenuListError)).WithErr(err),
)
return
}
res.UserName = info.Username
searchData := new(admin_service.SearchListMenuData)
searchData.AdminId = int32(ids[0])
listData, err := h.adminService.ListMenu(c, searchData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.AdminMenuListError,
code.Text(code.AdminMenuListError)).WithErr(err),
)
return
}
res.List = listData
c.Payload(res)
}
}
@@ -65,6 +65,16 @@ type Handler interface {
// @Tags API.admin
// @Router /api/admin/reset_password/{id} [patch]
ResetPassword() core.HandlerFunc
// CreateAdminMenu 提交菜单授权
// @Tags API.admin
// @Router /api/admin/menu [post]
CreateAdminMenu() core.HandlerFunc
// ListAdminMenu 菜单授权列表
// @Tags API.admin
// @Router /api/admin/menu/:id [get]
ListAdminMenu() core.HandlerFunc
}
type handler struct {
@@ -24,16 +24,17 @@ type listAPIData struct {
}
type listAPIResponse struct {
List []listAPIData `json:"list"`
BusinessKey string `json:"business_key"` // 调用方key
List []listAPIData `json:"list"`
}
// ListAPI 调用方接口地址列表
// @Summary 调用方接口地址列表
// @Description 调用方接口地址列表
// @Tags API.authorized
// @Accept json
// @Accept multipart/form-data
// @Produce json
// @Param business_key query string false "调用方key"
// @Param id query string true "hashID"
// @Success 200 {object} listAPIResponse
// @Failure 400 {object} code.Failure
// @Router /api/authorized_api [get]
@@ -73,6 +74,8 @@ func (h *handler) ListAPI() core.HandlerFunc {
return
}
res.BusinessKey = authorizedInfo.BusinessKey
searchAPIData := new(authorized_service.SearchAPIData)
searchAPIData.BusinessKey = authorizedInfo.BusinessKey
+89
View File
@@ -0,0 +1,89 @@
package menu_handler
import (
"net/http"
"github.com/xinliangnote/go-gin-api/internal/api/code"
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/pkg/errno"
)
type createActionRequest struct {
Id string `form:"id"` // HashID
Method string `form:"method"` // 请求方法
API string `form:"api"` // 请求地址
}
type createActionResponse struct {
Id int32 `json:"id"` // 主键ID
}
// CreateAction 创建功能权限
// @Summary 创建功能权限
// @Description 创建功能权限
// @Tags API.menu
// @Accept multipart/form-data
// @Produce json
// @Param id formData string true "HashID"
// @Param method formData string true "请求方法"
// @Param api formData string true "请求地址"
// @Success 200 {object} createActionResponse
// @Failure 400 {object} code.Failure
// @Router /api/menu_action [post]
func (h *handler) CreateAction() core.HandlerFunc {
return func(c core.Context) {
req := new(createActionRequest)
res := new(createActionResponse)
if err := c.ShouldBindForm(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
ids, err := h.hashids.HashidsDecode(req.Id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.HashIdsDecodeError,
code.Text(code.HashIdsDecodeError)).WithErr(err),
)
return
}
id := int32(ids[0])
searchOneData := new(menu_service.SearchOneData)
searchOneData.Id = id
menuInfo, err := h.menuService.Detail(c, searchOneData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.MenuDetailError,
code.Text(code.MenuDetailError)).WithErr(err),
)
return
}
createActionData := new(menu_service.CreateMenuActionData)
createActionData.MenuId = menuInfo.Id
createActionData.Method = req.Method
createActionData.API = req.API
createId, err := h.menuService.CreateAction(c, createActionData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.MenuCreateActionError,
code.Text(code.MenuCreateActionError)).WithErr(err),
)
return
}
res.Id = createId
c.Payload(res)
}
}
+67
View File
@@ -0,0 +1,67 @@
package menu_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 deleteActionRequest struct {
Id string `uri:"id"` // HashID
}
type deleteActionResponse struct {
Id int32 `json:"id"` // 主键ID
}
// DeleteAction 删除功能权限
// @Summary 删除功能权限
// @Description 删除功能权限
// @Tags API.menu
// @Accept json
// @Produce json
// @Param id path string true "hashId"
// @Success 200 {object} deleteActionResponse
// @Failure 400 {object} code.Failure
// @Router /api/menu_action/{id} [delete]
func (h *handler) DeleteAction() core.HandlerFunc {
return func(c core.Context) {
req := new(deleteActionRequest)
res := new(deleteActionResponse)
if err := c.ShouldBindURI(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
ids, err := h.hashids.HashidsDecode(req.Id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.HashIdsDecodeError,
code.Text(code.HashIdsDecodeError)).WithErr(err),
)
return
}
id := int32(ids[0])
err = h.menuService.DeleteAction(c, id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.MenuDeleteActionError,
code.Text(code.MenuDeleteActionError)).WithErr(err),
)
return
}
res.Id = id
c.Payload(res)
}
}
@@ -15,6 +15,7 @@ type detailRequest struct {
type detailResponse struct {
Id int32 `json:"id"` // 主键ID
Pid int32 `json:"pid"` // 父类ID
Name string `json:"name"` // 菜单名称
Link string `json:"link"` // 链接地址
Icon string `json:"icon"` // 图标
@@ -69,6 +70,7 @@ func (h *handler) Detail() core.HandlerFunc {
}
res.Id = info.Id
res.Pid = info.Pid
res.Name = info.Name
res.Link = info.Link
res.Icon = info.Icon
+114
View File
@@ -0,0 +1,114 @@
package menu_handler
import (
"net/http"
"github.com/xinliangnote/go-gin-api/internal/api/code"
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/pkg/errno"
"github.com/spf13/cast"
"go.uber.org/zap"
)
type listActionRequest struct {
Id string `form:"id"` // hashID
}
type listActionData struct {
HashId string `json:"hash_id"` // hashID
MenuId int32 `json:"menu_id"` // 菜单栏ID
Method string `json:"method"` // 调用方secret
API string `json:"api"` // 调用方对接人
}
type listActionResponse struct {
MenuName string `json:"menu_name"`
List []listActionData `json:"list"`
}
// ListAction 功能权限列表
// @Summary 功能权限列表
// @Description 功能权限列表
// @Tags API.menu
// @Accept multipart/form-data
// @Produce json
// @Param id query string true "hashID"
// @Success 200 {object} listActionResponse
// @Failure 400 {object} code.Failure
// @Router /api/menu_action [get]
func (h *handler) ListAction() core.HandlerFunc {
return func(c core.Context) {
req := new(listActionRequest)
res := new(listActionResponse)
if err := c.ShouldBindForm(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
ids, err := h.hashids.HashidsDecode(req.Id)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.HashIdsDecodeError,
code.Text(code.HashIdsDecodeError)).WithErr(err),
)
return
}
id := int32(ids[0])
searchOneData := new(menu_service.SearchOneData)
searchOneData.Id = id
menuInfo, err := h.menuService.Detail(c, searchOneData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.MenuDetailError,
code.Text(code.MenuDetailError)).WithErr(err),
)
return
}
res.MenuName = menuInfo.Name
searchListData := new(menu_service.SearchListActionData)
searchListData.MenuId = menuInfo.Id
resListData, err := h.menuService.ListAction(c, searchListData)
if err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.AuthorizedListAPIError,
code.Text(code.AuthorizedListAPIError)).WithErr(err),
)
return
}
res.List = make([]listActionData, len(resListData))
for k, v := range resListData {
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
if err != nil {
h.logger.Info("hashids err", zap.Error(err))
}
data := listActionData{
HashId: hashId,
MenuId: v.MenuId,
Method: v.Method,
API: v.Api,
}
res.List[k] = data
}
c.Payload(res)
}
}
@@ -40,6 +40,21 @@ type Handler interface {
// @Tags API.menu
// @Router /api/menu [get]
List() core.HandlerFunc
// CreateAction 创建功能权限
// @Tags API.menu
// @Router /api/menu_action [post]
CreateAction() core.HandlerFunc
// ListAction 功能权限列表
// @Tags API.menu
// @Router /api/menu_action [get]
ListAction() core.HandlerFunc
// DeleteAction 删除功能权限
// @Tags API.menu
// @Router /api/menu_action/{id} [delete]
DeleteAction() core.HandlerFunc
}
type handler struct {
-3
View File
@@ -20,6 +20,3 @@
- 包名应以 `_repo` 结尾;
- `./db_repo` 目录下的包名以 `数据表名`+ `_repo` 命名;
#### 脚本生成 MySQL CURD
- 使用脚本自动生成基于表结构的 CURD 代码,见文档:`./cmd/gormgen/README.md`
-14
View File
@@ -34,18 +34,4 @@ model.Mobile = user.Mobile
id, err = model.Create(u.db.GetDbW().WithContext(ctx.RequestContext()))
// 编辑
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)
// 删除
model := user_demo_repo.NewModel()
model.Id = id
err = model.Delete(u.db.GetDbW().WithContext(ctx.RequestContext()))
```
@@ -0,0 +1,335 @@
///////////////////////////////////////////////////////////
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
// ANY CHANGES DONE HERE WILL BE LOST //
///////////////////////////////////////////////////////////
package admin_menu_repo
import (
"fmt"
"time"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/pkg/errors"
"gorm.io/gorm"
)
func NewModel() *AdminMenu {
return new(AdminMenu)
}
func NewQueryBuilder() *adminMenuRepoQueryBuilder {
return new(adminMenuRepoQueryBuilder)
}
func (t *AdminMenu) Create(db *gorm.DB) (id int32, err error) {
if err = db.Create(t).Error; err != nil {
return 0, errors.Wrap(err, "create err")
}
return t.Id, nil
}
type adminMenuRepoQueryBuilder struct {
order []string
where []struct {
prefix string
value interface{}
}
limit int
offset int
}
func (qb *adminMenuRepoQueryBuilder) 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 *adminMenuRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&AdminMenu{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *adminMenuRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&AdminMenu{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *adminMenuRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&AdminMenu{}).Count(&c)
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
c = 0
}
return c, res.Error
}
func (qb *adminMenuRepoQueryBuilder) First(db *gorm.DB) (*AdminMenu, error) {
ret := &AdminMenu{}
res := qb.buildQuery(db).First(ret)
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
ret = nil
}
return ret, res.Error
}
func (qb *adminMenuRepoQueryBuilder) QueryOne(db *gorm.DB) (*AdminMenu, error) {
qb.limit = 1
ret, err := qb.QueryAll(db)
if len(ret) > 0 {
return ret[0], err
}
return nil, err
}
func (qb *adminMenuRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*AdminMenu, error) {
var ret []*AdminMenu
err := qb.buildQuery(db).Find(&ret).Error
return ret, err
}
func (qb *adminMenuRepoQueryBuilder) Limit(limit int) *adminMenuRepoQueryBuilder {
qb.limit = limit
return qb
}
func (qb *adminMenuRepoQueryBuilder) Offset(offset int) *adminMenuRepoQueryBuilder {
qb.offset = offset
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", p),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereIdIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", "IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereIdNotIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) OrderById(asc bool) *adminMenuRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "id "+order)
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereAdminId(p db_repo.Predicate, value int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "admin_id", p),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereAdminIdIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "admin_id", "IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereAdminIdNotIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "admin_id", "NOT IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) OrderByAdminId(asc bool) *adminMenuRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "admin_id "+order)
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereMenuId(p db_repo.Predicate, value int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", p),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereMenuIdIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", "IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereMenuIdNotIn(value []int32) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", "NOT IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) OrderByMenuId(asc bool) *adminMenuRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "menu_id "+order)
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", p),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", "IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) OrderByCreatedAt(asc bool) *adminMenuRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "created_at "+order)
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", p),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedUserIn(value []string) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", "IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *adminMenuRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
value,
})
return qb
}
func (qb *adminMenuRepoQueryBuilder) OrderByCreatedUser(asc bool) *adminMenuRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "created_user "+order)
return qb
}
@@ -0,0 +1,13 @@
package admin_menu_repo
import "time"
// 管理员菜单栏表
//go:generate gormgen -structs AdminMenu -input .
type AdminMenu struct {
Id int32 // 主键
AdminId int32 // 管理员ID
MenuId int32 // 菜单栏ID
CreatedAt time.Time `gorm:"time"` // 创建时间
CreatedUser string // 创建人
}
@@ -0,0 +1,10 @@
#### go_gin_api.admin_menu
管理员菜单栏表
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
| 2 | admin_id | 管理员ID | int(11) unsigned | MUL | NO | | 0 |
| 3 | menu_id | 菜单栏ID | int(11) unsigned | | NO | | 0 |
| 4 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
| 5 | created_user | 创建人 | varchar(60) | | NO | | |
@@ -30,20 +30,6 @@ func (t *Admin) Create(db *gorm.DB) (id int32, err error) {
return t.Id, nil
}
func (t *Admin) Delete(db *gorm.DB) (err error) {
if err = db.Delete(t).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (t *Admin) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
if err = db.Model(&Admin{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
type adminRepoQueryBuilder struct {
order []string
where []struct {
@@ -66,6 +52,30 @@ func (qb *adminRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
return ret
}
func (qb *adminRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&Admin{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *adminRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&Admin{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *adminRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&Admin{}).Count(&c)
@@ -5,7 +5,7 @@
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
| 2 | username | 用户名 | varchar(32) | UNI | NO | | |
| 3 | password | 密码 | varchar(32) | | NO | | |
| 3 | password | 密码 | varchar(100) | | NO | | |
| 4 | nickname | 昵称 | varchar(60) | | NO | | |
| 5 | mobile | 手机号 | varchar(20) | | NO | | |
| 6 | is_used | 是否启用 1:是 -1:否 | tinyint(1) | | NO | | 1 |
@@ -30,20 +30,6 @@ func (t *AuthorizedApi) Create(db *gorm.DB) (id int32, err error) {
return t.Id, nil
}
func (t *AuthorizedApi) Delete(db *gorm.DB) (err error) {
if err = db.Delete(t).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (t *AuthorizedApi) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
if err = db.Model(&AuthorizedApi{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
type authorizedApiRepoQueryBuilder struct {
order []string
where []struct {
@@ -66,6 +52,30 @@ func (qb *authorizedApiRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
return ret
}
func (qb *authorizedApiRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&AuthorizedApi{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *authorizedApiRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&AuthorizedApi{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *authorizedApiRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&AuthorizedApi{}).Count(&c)
@@ -30,20 +30,6 @@ func (t *Authorized) Create(db *gorm.DB) (id int32, err error) {
return t.Id, nil
}
func (t *Authorized) Delete(db *gorm.DB) (err error) {
if err = db.Delete(t).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (t *Authorized) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
if err = db.Model(&Authorized{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
type authorizedRepoQueryBuilder struct {
order []string
where []struct {
@@ -66,6 +52,30 @@ func (qb *authorizedRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
return ret
}
func (qb *authorizedRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&Authorized{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *authorizedRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&Authorized{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *authorizedRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&Authorized{}).Count(&c)
@@ -0,0 +1,507 @@
///////////////////////////////////////////////////////////
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
// ANY CHANGES DONE HERE WILL BE LOST //
///////////////////////////////////////////////////////////
package menu_action_repo
import (
"fmt"
"time"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/pkg/errors"
"gorm.io/gorm"
)
func NewModel() *MenuAction {
return new(MenuAction)
}
func NewQueryBuilder() *menuActionRepoQueryBuilder {
return new(menuActionRepoQueryBuilder)
}
func (t *MenuAction) Create(db *gorm.DB) (id int32, err error) {
if err = db.Create(t).Error; err != nil {
return 0, errors.Wrap(err, "create err")
}
return t.Id, nil
}
type menuActionRepoQueryBuilder struct {
order []string
where []struct {
prefix string
value interface{}
}
limit int
offset int
}
func (qb *menuActionRepoQueryBuilder) 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 *menuActionRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&MenuAction{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *menuActionRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&MenuAction{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *menuActionRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&MenuAction{}).Count(&c)
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
c = 0
}
return c, res.Error
}
func (qb *menuActionRepoQueryBuilder) First(db *gorm.DB) (*MenuAction, error) {
ret := &MenuAction{}
res := qb.buildQuery(db).First(ret)
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
ret = nil
}
return ret, res.Error
}
func (qb *menuActionRepoQueryBuilder) QueryOne(db *gorm.DB) (*MenuAction, error) {
qb.limit = 1
ret, err := qb.QueryAll(db)
if len(ret) > 0 {
return ret[0], err
}
return nil, err
}
func (qb *menuActionRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*MenuAction, error) {
var ret []*MenuAction
err := qb.buildQuery(db).Find(&ret).Error
return ret, err
}
func (qb *menuActionRepoQueryBuilder) Limit(limit int) *menuActionRepoQueryBuilder {
qb.limit = limit
return qb
}
func (qb *menuActionRepoQueryBuilder) Offset(offset int) *menuActionRepoQueryBuilder {
qb.offset = offset
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereIdIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereIdNotIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderById(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "id "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMenuId(p db_repo.Predicate, value int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMenuIdIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMenuIdNotIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "menu_id", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByMenuId(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "menu_id "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMethod(p db_repo.Predicate, value string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "method", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMethodIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "method", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereMethodNotIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "method", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByMethod(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "method "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereApi(p db_repo.Predicate, value string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "api", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereApiIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "api", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereApiNotIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "api", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByApi(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "api "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "is_deleted", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereIsDeletedIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByIsDeleted(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "is_deleted "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByCreatedAt(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "created_at "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedUser(p db_repo.Predicate, value string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedUserIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereCreatedUserNotIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "created_user", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByCreatedUser(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "created_user "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_at", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByUpdatedAt(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "updated_at "+order)
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedUser(p db_repo.Predicate, value string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_user", p),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedUserIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_user", "IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) WhereUpdatedUserNotIn(value []string) *menuActionRepoQueryBuilder {
qb.where = append(qb.where, struct {
prefix string
value interface{}
}{
fmt.Sprintf("%v %v ?", "updated_user", "NOT IN"),
value,
})
return qb
}
func (qb *menuActionRepoQueryBuilder) OrderByUpdatedUser(asc bool) *menuActionRepoQueryBuilder {
order := "DESC"
if asc {
order = "ASC"
}
qb.order = append(qb.order, "updated_user "+order)
return qb
}
@@ -0,0 +1,17 @@
package menu_action_repo
import "time"
// 功能权限表
//go:generate gormgen -structs MenuAction -input .
type MenuAction struct {
Id int32 // 主键
MenuId int32 // 菜单栏ID
Method string // 请求方式
Api string // 请求地址
IsDeleted int32 // 是否删除 1:是 -1:否
CreatedAt time.Time `gorm:"time"` // 创建时间
CreatedUser string // 创建人
UpdatedAt time.Time `gorm:"time"` // 更新时间
UpdatedUser string // 更新人
}
@@ -0,0 +1,14 @@
#### go_gin_api.menu_action
功能权限表
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
| 2 | menu_id | 菜单栏ID | int(11) unsigned | MUL | NO | | 0 |
| 3 | method | 请求方式 | varchar(30) | | NO | | |
| 4 | api | 请求地址 | varchar(100) | | NO | | |
| 5 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
| 6 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
| 7 | created_user | 创建人 | varchar(60) | | NO | | |
| 8 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
| 9 | updated_user | 更新人 | varchar(60) | | NO | | |
@@ -30,20 +30,6 @@ func (t *Menu) Create(db *gorm.DB) (id int32, err error) {
return t.Id, nil
}
func (t *Menu) Delete(db *gorm.DB) (err error) {
if err = db.Delete(t).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (t *Menu) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
if err = db.Model(&Menu{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
type menuRepoQueryBuilder struct {
order []string
where []struct {
@@ -66,6 +52,30 @@ func (qb *menuRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
return ret
}
func (qb *menuRepoQueryBuilder) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
db = db.Model(&Menu{})
for _, where := range qb.where {
db.Where(where.prefix, where.value)
}
if err = db.Updates(m).Error; err != nil {
return errors.Wrap(err, "updates err")
}
return nil
}
func (qb *menuRepoQueryBuilder) Delete(db *gorm.DB) (err error) {
for _, where := range qb.where {
db = db.Where(where.prefix, where.value)
}
if err = db.Delete(&Menu{}).Error; err != nil {
return errors.Wrap(err, "delete err")
}
return nil
}
func (qb *menuRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
var c int64
res := qb.buildQuery(db).Model(&Menu{}).Count(&c)
@@ -17,7 +17,7 @@ type Service interface {
i()
CacheKeyPrefix() (pre string)
Create(ctx core.Context, authorizedData *CreateAdminData) (id int32, err error)
Create(ctx core.Context, adminData *CreateAdminData) (id int32, err error)
PageList(ctx core.Context, searchData *SearchData) (listData []*admin_repo.Admin, err error)
PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error)
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
@@ -26,6 +26,9 @@ type Service interface {
ResetPassword(ctx core.Context, id int32) (err error)
ModifyPassword(ctx core.Context, id int32, newPassword string) (err error)
ModifyPersonalInfo(ctx core.Context, id int32, modifyData *ModifyData) (err error)
CreateMenu(ctx core.Context, menuData *CreateMenuData) (err error)
ListMenu(ctx core.Context, searchData *SearchListMenuData) (menuData []ListMenuData, err error)
}
type service struct {
@@ -0,0 +1,39 @@
package admin_service
import (
"strings"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/spf13/cast"
)
type CreateMenuData struct {
AdminId int32 `form:"admin_id"` // AdminID
Actions string `form:"actions"` // 功能权限ID,多个用,分割
}
func (s *service) CreateMenu(ctx core.Context, menuData *CreateMenuData) (err error) {
qb := admin_menu_repo.NewQueryBuilder()
qb.WhereAdminId(db_repo.EqualPredicate, menuData.AdminId)
if err = qb.Delete(s.db.GetDbW().WithContext(ctx.RequestContext())); err != nil {
return
}
ActionArr := strings.Split(menuData.Actions, ",")
for _, v := range ActionArr {
createModel := admin_menu_repo.NewModel()
createModel.AdminId = menuData.AdminId
createModel.MenuId = cast.ToInt32(v)
createModel.CreatedUser = ctx.UserName()
_, err = createModel.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
if err != nil {
return
}
}
return
}
@@ -1,6 +1,7 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -8,15 +9,14 @@ import (
)
func (s *service) Delete(ctx core.Context, id int32) (err error) {
model := admin_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_deleted": 1,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := admin_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -0,0 +1,72 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_menu_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type SearchListMenuData struct {
AdminId int32 `json:"admin_id"` // 管理员ID
}
type ListMenuData struct {
Id int32 `json:"id"` // ID
Pid int32 `json:"pid"` // 父类ID
Name string `json:"name"` // 菜单名称
IsHave int32 `json:"is_have"` // 是否已拥有权限
}
func (s *service) ListMenu(ctx core.Context, searchData *SearchListMenuData) (menuData []ListMenuData, err error) {
menuQb := menu_repo.NewQueryBuilder()
menuQb.WhereIsDeleted(db_repo.EqualPredicate, -1)
menuListData, err := menuQb.
OrderById(false).
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
if err != nil {
return nil, err
}
if len(menuListData) <= 0 {
return
}
menuData = make([]ListMenuData, len(menuListData))
for k, v := range menuListData {
data := ListMenuData{
Id: v.Id,
Pid: v.Pid,
Name: v.Name,
IsHave: 0,
}
menuData[k] = data
}
adminMenuQb := admin_menu_repo.NewQueryBuilder()
if searchData.AdminId != 0 {
adminMenuQb.WhereAdminId(db_repo.EqualPredicate, searchData.AdminId)
}
adminMenuListData, err := adminMenuQb.
OrderById(false).
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
if err != nil {
return nil, err
}
if len(adminMenuListData) <= 0 {
return
}
for k, v := range menuData {
for _, haveV := range adminMenuListData {
if haveV.MenuId == v.Id {
menuData[k].IsHave = 1
}
}
}
return
}
@@ -1,6 +1,7 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -8,15 +9,14 @@ import (
)
func (s *service) ModifyPassword(ctx core.Context, id int32, newPassword string) (err error) {
model := admin_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"password": password.GeneratePassword(newPassword),
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := admin_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -1,6 +1,7 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
@@ -11,16 +12,15 @@ type ModifyData struct {
}
func (s *service) ModifyPersonalInfo(ctx core.Context, id int32, modifyData *ModifyData) (err error) {
model := admin_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"nickname": modifyData.Nickname,
"mobile": modifyData.Mobile,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := admin_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -1,6 +1,7 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -8,15 +9,14 @@ import (
)
func (s *service) ResetPassword(ctx core.Context, id int32) (err error) {
model := admin_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"password": password.ResetPassword(),
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := admin_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -1,6 +1,7 @@
package admin_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/admin_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -8,15 +9,14 @@ import (
)
func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error) {
model := admin_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_used": used,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := admin_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -20,15 +20,14 @@ func (s *service) Delete(ctx core.Context, id int32) (err error) {
return nil
}
model := authorized_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_deleted": 1,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := authorized_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -20,15 +20,14 @@ func (s *service) DeleteAPI(ctx core.Context, id int32) (err error) {
return nil
}
model := authorized_api_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_deleted": 1,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := authorized_api_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -19,15 +19,14 @@ func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error)
return nil
}
model := authorized_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_used": used,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := authorized_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -2,6 +2,7 @@ package menu_service
import (
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_action_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -23,6 +24,10 @@ type Service interface {
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
Delete(ctx core.Context, id int32) (err error)
Detail(ctx core.Context, searchOneData *SearchOneData) (info *menu_repo.Menu, err error)
CreateAction(ctx core.Context, menuActionData *CreateMenuActionData) (id int32, err error)
ListAction(ctx core.Context, searchListActionData *SearchListActionData) (listData []*menu_action_repo.MenuAction, err error)
DeleteAction(ctx core.Context, id int32) (err error)
}
type service struct {
@@ -0,0 +1,27 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_action_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type CreateMenuActionData struct {
MenuId int32 `json:"menu_id"` // 菜单栏ID
Method string `json:"method"` // 请求方法
API string `json:"api"` // 请求地址
}
func (s *service) CreateAction(ctx core.Context, menuActionData *CreateMenuActionData) (id int32, err error) {
model := menu_action_repo.NewModel()
model.MenuId = menuActionData.MenuId
model.Method = menuActionData.Method
model.Api = menuActionData.API
model.CreatedUser = ctx.UserName()
model.IsDeleted = -1
id, err = model.Create(s.db.GetDbW().WithContext(ctx.RequestContext()))
if err != nil {
return 0, err
}
return
}
@@ -1,20 +1,20 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (s *service) Delete(ctx core.Context, id int32) (err error) {
model := menu_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_deleted": 1,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := menu_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -0,0 +1,35 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_action_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"gorm.io/gorm"
)
func (s *service) DeleteAction(ctx core.Context, id int32) (err error) {
// 先查询 id 是否存在
_, err = menu_action_repo.NewQueryBuilder().
WhereIsDeleted(db_repo.EqualPredicate, -1).
WhereId(db_repo.EqualPredicate, id).
First(s.db.GetDbR().WithContext(ctx.RequestContext()))
if err == gorm.ErrRecordNotFound {
return nil
}
data := map[string]interface{}{
"is_deleted": 1,
"updated_user": ctx.UserName(),
}
qb := menu_action_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
return
}
@@ -0,0 +1,30 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_action_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type SearchListActionData struct {
MenuId int32 `json:"menu_id"` // 菜单栏ID
}
func (s *service) ListAction(ctx core.Context, searchData *SearchListActionData) (listData []*menu_action_repo.MenuAction, err error) {
qb := menu_action_repo.NewQueryBuilder()
qb.WhereIsDeleted(db_repo.EqualPredicate, -1)
if searchData.MenuId != 0 {
qb.WhereMenuId(db_repo.EqualPredicate, searchData.MenuId)
}
listData, err = qb.
OrderById(false).
QueryAll(s.db.GetDbR().WithContext(ctx.RequestContext()))
if err != nil {
return nil, err
}
return
}
@@ -1,6 +1,7 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
@@ -12,9 +13,6 @@ type UpdateMenuData struct {
}
func (s *service) Modify(ctx core.Context, id int32, menuData *UpdateMenuData) (err error) {
model := menu_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"name": menuData.Name,
"link": menuData.Link,
@@ -22,7 +20,9 @@ func (s *service) Modify(ctx core.Context, id int32, menuData *UpdateMenuData) (
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := menu_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
@@ -1,20 +1,20 @@
package menu_service
import (
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/menu_repo"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (s *service) UpdateUsed(ctx core.Context, id int32, used int32) (err error) {
model := menu_repo.NewModel()
model.Id = id
data := map[string]interface{}{
"is_used": used,
"updated_user": ctx.UserName(),
}
err = model.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
qb := menu_repo.NewQueryBuilder()
qb.WhereId(db_repo.EqualPredicate, id)
err = qb.Updates(s.db.GetDbW().WithContext(ctx.RequestContext()), data)
if err != nil {
return err
}
+25 -14
View File
@@ -14,13 +14,22 @@ func setApiRouter(r *resource) {
// admin
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
// login
login := r.mux.Group("/login", r.middles.Signature())
// 需要签名验证,无需登录验证,无需 RBAC 权限验证
login := r.mux.Group("/api", r.middles.Signature())
{
login.POST("/web", adminHandler.Login())
login.POST("/login", adminHandler.Login())
}
// api
// 需要签名验证、登录验证,无需 RBAC 权限验证
notRBAC := r.mux.Group("/api", core.WrapAuthHandler(r.middles.Token), r.middles.Signature())
{
notRBAC.POST("/admin/logout", adminHandler.Logout())
notRBAC.PATCH("/admin/modify_password", adminHandler.ModifyPassword())
notRBAC.GET("/admin/info", adminHandler.Detail())
notRBAC.PATCH("/admin/modify_personal_info", adminHandler.ModifyPersonalInfo())
}
// 需要签名验证、登录验证、RBAC 权限验证
api := r.mux.Group("/api", core.WrapAuthHandler(r.middles.Token), r.middles.Signature())
{
// authorized
@@ -37,25 +46,27 @@ func setApiRouter(r *resource) {
api.POST("/admin", adminHandler.Create())
api.GET("/admin", adminHandler.List())
api.PATCH("/admin/used", adminHandler.UpdateUsed())
api.PATCH("/admin/reset_password/:id", adminHandler.ResetPassword())
api.DELETE("/admin/:id", adminHandler.Delete())
api.POST("/admin/logout", adminHandler.Logout())
api.PATCH("/admin/modify_password", adminHandler.ModifyPassword())
api.GET("/admin/info", adminHandler.Detail())
api.PATCH("/admin/modify_personal_info", adminHandler.ModifyPersonalInfo())
api.PATCH("/admin/reset_password/:id", core.AliasForRecordMetrics("/api/admin/reset_password"), adminHandler.ResetPassword())
api.DELETE("/admin/:id", core.AliasForRecordMetrics("/api/admin"), adminHandler.Delete())
api.POST("/admin/menu", adminHandler.CreateAdminMenu())
api.GET("/admin/menu/:id", core.AliasForRecordMetrics("/api/admin/menu"), adminHandler.ListAdminMenu())
// menu
menuHandler := menu_handler.New(r.logger, r.db, r.cache)
api.POST("/menu", menuHandler.Create())
api.GET("/menu", menuHandler.List())
api.GET("/menu/:id", menuHandler.Detail())
api.GET("/menu/:id", core.AliasForRecordMetrics("/api/menu"), menuHandler.Detail())
api.PATCH("/menu/used", menuHandler.UpdateUsed())
api.DELETE("/menu/:id", menuHandler.Delete())
api.DELETE("/menu/:id", core.AliasForRecordMetrics("/api/menu"), menuHandler.Delete())
api.POST("/menu_action", menuHandler.CreateAction())
api.GET("/menu_action", menuHandler.ListAction())
api.DELETE("/menu_action/:id", core.AliasForRecordMetrics("/api/menu_action"), menuHandler.DeleteAction())
// tool
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())
api.GET("/tool/hashids/encode/:id", core.AliasForRecordMetrics("/api/tool/hashids/encode"), toolHandler.HashIdsEncode())
api.GET("/tool/hashids/decode/:id", core.AliasForRecordMetrics("/api/tool/hashids/decode"), toolHandler.HashIdsDecode())
api.POST("/tool/cache/search", toolHandler.SearchCache())
api.PATCH("/tool/cache/clear", toolHandler.ClearCache())
api.GET("/tool/data/dbs", toolHandler.Dbs())
+33 -18
View File
@@ -5,10 +5,11 @@ import (
"github.com/xinliangnote/go-gin-api/internal/web/controller/authorized_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/config_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/gencode_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/generator_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"
"github.com/xinliangnote/go-gin-api/internal/web/controller/upgrade_handler"
)
func setWebRouter(r *resource) {
@@ -16,35 +17,46 @@ 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)
generatorHandler := generator_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)
upgradeHandler := upgrade_handler.New(r.logger, r.db, r.cache)
web := r.mux.Group("", r.middles.DisableLog())
// 无需记录日志,无需 RBAC 权限验证
notRBAC := 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())
notRBAC.GET("", indexHandler.View())
// 仪表盘
web.GET("/dashboard", dashboardHandler.View())
notRBAC.GET("/dashboard", dashboardHandler.View())
// 安装
notRBAC.GET("/install", installHandler.View())
notRBAC.POST("/install/execute", installHandler.Execute())
notRBAC.POST("/install/restart", installHandler.Restart())
// 管理员
notRBAC.GET("/login", adminHandler.LoginView())
notRBAC.GET("/admin/modify_password", adminHandler.ModifyPasswordView())
notRBAC.GET("/admin/modify_info", adminHandler.ModifyInfoView())
}
// 无需记录日志,需要 RBAC 权限验证
web := r.mux.Group("", r.middles.DisableLog())
{
// 配置信息
web.GET("/config/email", configInfoHandler.EmailView())
web.GET("/config/code", configInfoHandler.CodeView())
// 代码生成工具
web.GET("/gormgen", genCodeHandler.GormView())
web.POST("/gormgen_exec", genCodeHandler.GormExecute())
// 代码生成
web.GET("/generator/gorm", generatorHandler.GormView())
web.POST("/generator/gorm/execute", generatorHandler.GormExecute())
web.GET("/handlergen", genCodeHandler.HandlerView())
web.POST("/handlergen_exec", genCodeHandler.HandlerExecute())
web.GET("/generator/handler", generatorHandler.HandlerView())
web.POST("/generator/handler/execute", generatorHandler.HandlerExecute())
// 调用方
web.GET("/authorized/list", authorizedHandler.ListView())
@@ -55,10 +67,13 @@ func setWebRouter(r *resource) {
// 管理员
web.GET("/admin/list", adminHandler.ListView())
web.GET("/admin/add", adminHandler.AddView())
web.GET("/admin/modify_password", adminHandler.ModifyPasswordView())
web.GET("/admin/modify_info", adminHandler.ModifyInfoView())
web.GET("/login", adminHandler.LoginView())
web.GET("/admin/menu", adminHandler.MenuView())
web.GET("/admin/menu_action/:id", adminHandler.MenuActionView())
web.GET("/admin/action/:id", adminHandler.AdminMenuView())
// 升级
web.GET("/upgrade", upgradeHandler.UpgradeView())
web.POST("/upgrade/execute", upgradeHandler.UpgradeExecute())
// 工具箱
web.GET("/tool/hashids", toolHandler.HashIdsView())
@@ -0,0 +1,36 @@
package admin_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 adminMenuViewRequest struct {
Id string `uri:"id"` // 主键ID
}
type adminMenuViewResponse struct {
HashID string `json:"hash_id"` // hashID
}
func (h *handler) AdminMenuView() core.HandlerFunc {
return func(c core.Context) {
req := new(adminMenuViewRequest)
if err := c.ShouldBindURI(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
obj := new(adminMenuViewResponse)
obj.HashID = req.Id
c.HTML("admin_menu", obj)
}
}
@@ -0,0 +1,36 @@
package admin_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 menuActionViewRequest struct {
Id string `uri:"id"` // 主键ID
}
type menuActionViewResponse struct {
HashID string `json:"hash_id"` // hashID
}
func (h *handler) MenuActionView() core.HandlerFunc {
return func(c core.Context) {
req := new(menuActionViewRequest)
if err := c.ShouldBindURI(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
obj := new(menuActionViewResponse)
obj.HashID = req.Id
c.HTML("menu_action", obj)
}
}
@@ -19,6 +19,8 @@ type Handler interface {
ModifyPasswordView() core.HandlerFunc
ModifyInfoView() core.HandlerFunc
MenuView() core.HandlerFunc
MenuActionView() core.HandlerFunc
AdminMenuView() core.HandlerFunc
}
type handler struct {
@@ -1,4 +1,4 @@
package gencode_handler
package generator_handler
import (
"bytes"
@@ -1,4 +1,4 @@
package gencode_handler
package generator_handler
import (
"fmt"
@@ -21,7 +21,7 @@ func (h *handler) GormView() core.HandlerFunc {
sqlTables := fmt.Sprintf("SELECT `table_name`,`table_comment` FROM `information_schema`.`tables` WHERE `table_schema`= '%s'", mysqlConf.Name)
rows, err := h.db.GetDbR().Raw(sqlTables).Rows()
if err != nil {
c.HTML("gencode_gorm", tableCollect)
c.HTML("generator_gorm", tableCollect)
return
}
defer rows.Close()
@@ -37,6 +37,6 @@ func (h *handler) GormView() core.HandlerFunc {
tableCollect = append(tableCollect, info)
}
c.HTML("gencode_gorm", tableCollect)
c.HTML("generator_gorm", tableCollect)
}
}
@@ -1,4 +1,4 @@
package gencode_handler
package generator_handler
import (
"bytes"
@@ -1,4 +1,4 @@
package gencode_handler
package generator_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
@@ -6,6 +6,6 @@ import (
func (h *handler) HandlerView() core.HandlerFunc {
return func(c core.Context) {
c.HTML("gencode_handler", nil)
c.HTML("generator_handler", nil)
}
}
@@ -1,4 +1,4 @@
package gencode_handler
package generator_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
@@ -209,6 +209,56 @@ func (h *handler) Execute() core.HandlerFunc {
}
outPutString += "初始化 MySQL 数据表:menu 成功。\n"
if err = db.Exec(mysql_table.CreateMenuTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString += "初始化 MySQL 数据表:menu 默认数据成功。\n"
if err = db.Exec(mysql_table.CreateMenuActionTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString += "初始化 MySQL 数据表:menu_action 成功。\n"
if err = db.Exec(mysql_table.CreateMenuActionTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString += "初始化 MySQL 数据表:menu_action 默认数据成功。\n"
if err = db.Exec(mysql_table.CreateAdminMenuTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString += "初始化 MySQL 数据表:admin_menu 成功。\n"
if err = db.Exec(mysql_table.CreateAdminMenuTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString += "初始化 MySQL 数据表:admin_menu 默认数据成功。\n"
// 生成 install 完成标识
f, err := os.Create(configs.ProjectInstallFile())
if err != nil {
@@ -0,0 +1,53 @@
package mysql_table
//CREATE TABLE `admin_menu` (
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
//`admin_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '管理员ID',
//`menu_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '菜单栏ID',
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
//PRIMARY KEY (`id`),
//KEY `idx_admin_id` (`admin_id`)
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员菜单栏表';
func CreateAdminMenuTableSql() (sql string) {
sql = "CREATE TABLE `admin_menu` ("
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
sql += "`admin_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '管理员ID',"
sql += "`menu_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '菜单栏ID',"
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
sql += "PRIMARY KEY (`id`),"
sql += "KEY `idx_admin_id` (`admin_id`)"
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员菜单栏表';"
return
}
func CreateAdminMenuTableDataSql() (sql string) {
sql = "INSERT INTO `admin_menu` (`id`, `admin_id`, `menu_id`, `created_user`) VALUES"
sql += "(1, 1, 16, 'init'),"
sql += "(2, 1, 21, 'init'),"
sql += "(3, 1, 20, 'init'),"
sql += "(4, 1, 19, 'init'),"
sql += "(5, 1, 18, 'init'),"
sql += "(6, 1, 17, 'init'),"
sql += "(7, 1, 13, 'init'),"
sql += "(8, 1, 15, 'init'),"
sql += "(9, 1, 14, 'init'),"
sql += "(10, 1, 10, 'init'),"
sql += "(11, 1, 12, 'init'),"
sql += "(12, 1, 11, 'init'),"
sql += "(13, 1, 7, 'init'),"
sql += "(14, 1, 9, 'init'),"
sql += "(15, 1, 8, 'init'),"
sql += "(16, 1, 4, 'init'),"
sql += "(17, 1, 6, 'init'),"
sql += "(18, 1, 5, 'init'),"
sql += "(19, 1, 1, 'init'),"
sql += "(20, 1, 3, 'init'),"
sql += "(21, 1, 2, 'init'),"
sql += "(22, 1, 22, 'init');"
return
}
@@ -35,3 +35,31 @@ func CreateMenuTableSql() (sql string) {
return
}
func CreateMenuTableDataSql() (sql string) {
sql = "INSERT INTO `menu` (`id`, `pid`, `name`, `link`, `icon`, `level`, `created_user`) VALUES"
sql += "(1, 0, '配置信息', '', 'mdi-settings-box', 1, 'init'),"
sql += "(2, 1, '告警邮箱', '/config/email', '', 2, 'init'),"
sql += "(3, 1, '错误码', '/config/code', '', 2, 'init'),"
sql += "(4, 0, '代码生成器', '', 'mdi-code-not-equal-variant', 1, 'init'),"
sql += "(5, 4, '生成数据表 CURD', '/generator/gorm', '', 2, 'init'),"
sql += "(6, 4, '生成控制器方法', '/generator/handler', '', 2, 'init'),"
sql += "(7, 0, '授权调用方', '', 'mdi-playlist-check', 1, 'init'),"
sql += "(8, 7, '调用方', '/authorized/list', '', 2, 'init'),"
sql += "(9, 7, '使用说明', '/authorized/demo', '', 2, 'init'),"
sql += "(10, 0, '系统管理员', '', 'mdi-account', 1, 'init'),"
sql += "(11, 10, '管理员', '/admin/list', '', 2, 'init'),"
sql += "(12, 10, '菜单管理', '/admin/menu', '', 2, 'init'),"
sql += "(13, 0, '查询小助手', '', 'mdi-database-search', 1, 'init'),"
sql += "(14, 13, '查询缓存', '/tool/cache', '', 2, 'init'),"
sql += "(15, 13, '查询数据', '/tool/data', '', 2, 'init'),"
sql += "(16, 0, '实用工具箱', '', 'mdi-tools', 1, 'init'),"
sql += "(17, 16, 'Hashids', '/tool/hashids', '', 2, 'init'),"
sql += "(18, 16, '调用日志', '/tool/logs', '', 2, 'init'),"
sql += "(19, 16, '接口文档', '/swagger/index.html', '', 2, 'init'),"
sql += "(20, 16, 'GraphQL', '/graphql', '', 2, 'init'),"
sql += "(21, 16, '接口指标', '/metrics', '', 2, 'init'),"
sql += "(22, 16, '服务升级', '/upgrade', '', 2, 'init');"
return
}
@@ -0,0 +1,76 @@
package mysql_table
//CREATE TABLE `menu_action` (
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
//`menu_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '菜单栏ID',
//`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',
//`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
//PRIMARY KEY (`id`),
//KEY `idx_menu_id` (`menu_id`)
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='功能权限表';
func CreateMenuActionTableSql() (sql string) {
sql = "CREATE TABLE `menu_action` ("
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
sql += "`menu_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '菜单栏ID',"
sql += "`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',"
sql += "`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',"
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
sql += "PRIMARY KEY (`id`),"
sql += "KEY `idx_menu_id` (`menu_id`)"
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='功能权限表';"
return
}
func CreateMenuActionTableDataSql() (sql string) {
sql = "INSERT INTO `menu_action` (`id`, `menu_id`, `method`, `api`, `created_user`) VALUES"
sql += "(1, 17, 'GET', '/api/tool/hashids/**', 'init'),"
sql += "(2, 14, 'POST', '/api/tool/cache/search', 'init'),"
sql += "(3, 14, 'PATCH', '/api/tool/cache/clear', 'init'),"
sql += "(4, 15, 'GET', '/api/tool/data/dbs', 'init'),"
sql += "(5, 15, 'POST', '/api/tool/data/mysql', 'init'),"
sql += "(6, 15, 'POST', '/api/tool/data/tables', 'init'),"
sql += "(7, 2, 'PATCH', '/api/config/email', 'init'),"
sql += "(8, 5, 'POST', '/generator/gorm/execute', 'init'),"
sql += "(9, 6, 'POST', '/generator/handler/execute', 'init'),"
sql += "(10, 8, 'GET', '/authorized/add', 'init'),"
sql += "(11, 8, 'GET', '/authorized/api/*', 'init'),"
sql += "(12, 8, 'GET', '/api/authorized', 'init'),"
sql += "(13, 8, 'PATCH', '/api/authorized/used', 'init'),"
sql += "(14, 8, 'DELETE', '/api/authorized/*', 'init'),"
sql += "(15, 8, 'POST', '/api/authorized', 'init'),"
sql += "(16, 8, 'GET', '/api/authorized_api', 'init'),"
sql += "(17, 8, 'POST', '/api/authorized_api', 'init'),"
sql += "(18, 8, 'DELETE', '/api/authorized_api/*', 'init'),"
sql += "(19, 11, 'GET', '/admin/add', 'init'),"
sql += "(20, 11, 'POST', '/api/admin', 'init'),"
sql += "(21, 11, 'GET', '/api/admin', 'init'),"
sql += "(22, 11, 'PATCH', '/api/admin/used', 'init'),"
sql += "(23, 11, 'PATCH', '/api/admin/reset_password/*', 'init'),"
sql += "(24, 11, 'DELETE', '/api/admin/*', 'init'),"
sql += "(25, 11, 'GET', '/admin/action/*', 'init'),"
sql += "(26, 11, 'GET', '/api/admin/menu/*', 'init'),"
sql += "(27, 11, 'POST', '/api/admin/menu', 'init'),"
sql += "(28, 12, 'GET', '/admin/menu_action/*', 'init'),"
sql += "(29, 12, 'GET', '/api/menu', 'init'),"
sql += "(30, 12, 'DELETE', '/api/menu/*', 'init'),"
sql += "(31, 12, 'GET', '/api/menu/*', 'init'),"
sql += "(32, 12, 'PATCH', '/api/menu/used', 'init'),"
sql += "(33, 12, 'POST', '/api/menu', 'init'),"
sql += "(34, 12, 'GET', '/api/menu_action', 'init'),"
sql += "(35, 12, 'POST', '/api/menu_action', 'init'),"
sql += "(36, 12, 'DELETE', '/api/menu_action/*', 'init'),"
sql += "(37, 22, 'POST', '/upgrade/execute', 'init');"
return
}
@@ -0,0 +1,178 @@
package upgrade_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/internal/web/controller/install_handler/mysql_table"
"github.com/xinliangnote/go-gin-api/pkg/errno"
)
type upgradeExecuteRequest struct {
TableName string `form:"table_name"` // 数据表
Op string `form:"op"` // 操作类型
}
func (h *handler) UpgradeExecute() core.HandlerFunc {
return func(c core.Context) {
req := new(upgradeExecuteRequest)
if err := c.ShouldBindForm(req); err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ParamBindError,
code.Text(code.ParamBindError)).WithErr(err),
)
return
}
outPutString := ""
db := h.db.GetDbW()
if req.TableName == "authorized" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateAuthorizedTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:authorized 成功。"
}
if req.TableName == "authorized" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateAuthorizedTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:authorized 默认数据成功。"
}
if req.TableName == "authorized_api" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateAuthorizedAPITableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:authorized_api 成功。"
}
if req.TableName == "authorized_api" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateAuthorizedAPITableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:authorized_api 默认数据成功。"
}
if req.TableName == "admin" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateAdminTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:admin 成功。"
}
if req.TableName == "admin" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateAdminTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:admin 默认数据成功。"
}
if req.TableName == "menu" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateMenuTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:menu 成功。"
}
if req.TableName == "menu" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateMenuTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:menu 默认数据成功。"
}
if req.TableName == "menu_action" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateMenuActionTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:menu_action 成功。"
}
if req.TableName == "menu_action" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateMenuActionTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:menu_action 默认数据成功。"
}
if req.TableName == "admin_menu" && req.Op == "table" {
if err := db.Exec(mysql_table.CreateAdminMenuTableSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:admin_menu 成功。"
}
if req.TableName == "admin_menu" && req.Op == "table_data" {
if err := db.Exec(mysql_table.CreateAdminMenuTableDataSql()).Error; err != nil {
c.AbortWithError(errno.NewError(
http.StatusBadRequest,
code.ConfigMySQLInstallError,
"MySQL "+err.Error()).WithErr(err),
)
return
}
outPutString = "初始化 MySQL 数据表:admin_menu 默认数据成功。"
}
c.Payload(outPutString)
}
}
@@ -0,0 +1,73 @@
package upgrade_handler
import (
"fmt"
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type upgradeViewResponse struct {
List []upgradeViewData `json:"list"`
}
type upgradeViewData struct {
TableName string `json:"table_name"` // 表名称
IsHave int32 `json:"is_have"` // 是否已存在 1=存在 -1=不存在
}
var tableList = []string{"authorized", "authorized_api", "admin", "menu", "menu_action", "admin_menu"}
func (h *handler) UpgradeView() core.HandlerFunc {
return func(c core.Context) {
type tableInfo struct {
Name string // name
Comment string // comment
}
var tableCollect []tableInfo
mysqlConf := configs.Get().MySQL.Read
sqlTables := fmt.Sprintf("SELECT `table_name`,`table_comment` FROM `information_schema`.`tables` WHERE `table_schema`= '%s'", mysqlConf.Name)
rows, err := h.db.GetDbR().Raw(sqlTables).Rows()
if err != nil {
c.HTML("upgrade_view", tableCollect)
return
}
defer rows.Close()
for rows.Next() {
var info tableInfo
err = rows.Scan(&info.Name, &info.Comment)
if err != nil {
fmt.Printf("execute query tables action error,had ignored, detail is [%v]\n", err.Error())
continue
}
tableCollect = append(tableCollect, info)
}
tableData := make([]upgradeViewData, len(tableList))
for k, v := range tableList {
data := upgradeViewData{
TableName: v,
IsHave: -1,
}
tableData[k] = data
}
for k, v := range tableData {
for _, haveV := range tableCollect {
if haveV.Name == v.TableName {
tableData[k].IsHave = 1
}
}
}
obj := new(upgradeViewResponse)
obj.List = tableData
c.HTML("upgrade_view", obj)
}
}
@@ -0,0 +1,34 @@
package upgrade_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()
UpgradeView() core.HandlerFunc
UpgradeExecute() core.HandlerFunc
}
type handler struct {
db db.Repo
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
return &handler{
logger: logger,
cache: cache,
db: db,
}
}
func (h *handler) i() {}