mirror of
https://github.com/xinliangnote/go-gin-api.git
synced 2024-04-21 12:31:46 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fd9a005d1 | ||
|
|
4530dab87b | ||
|
|
bf4a413bd0 | ||
|
|
79aa86f278 | ||
|
|
866bed5522 | ||
|
|
61cc349cb4 | ||
|
|
6825b4e5b1 | ||
|
|
62d7ac5cd9 | ||
|
|
b630456b90 | ||
|
|
bbe181817c | ||
|
|
15e99398cb | ||
|
|
dd19eab5d5 | ||
|
|
7cdb8ee6b4 | ||
|
|
400e0bb3f2 | ||
|
|
14f6853c2b | ||
|
|
4c37a7e6b5 | ||
|
|
fc7e58db04 | ||
|
|
4e3c2afafd | ||
|
|
63499a432e | ||
|
|
498033753e | ||
|
|
b05ed0b59d | ||
|
|
8ed27cdce1 | ||
|
|
9aa0067e07 | ||
|
|
e2cecae7b1 | ||
|
|
e22593b708 | ||
|
|
05f337088e | ||
|
|
17be120c06 |
@@ -14,3 +14,6 @@
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Project runtime log
|
||||
logs/*.log
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
# FROM 基于 golang:1.15-alpine
|
||||
FROM golang:1.15-alpine AS builder
|
||||
# FROM 基于 golang:1.16-alpine
|
||||
FROM golang:1.16-alpine AS builder
|
||||
|
||||
# ENV 设置环境变量
|
||||
ENV GOPATH=/opt/repo
|
||||
ENV GO111MODULE=on
|
||||
ENV GOPROXY=https://goproxy.io,direct
|
||||
|
||||
# ADD 源路径 目标路径
|
||||
# COPY 源路径 目标路径
|
||||
COPY . $GOPATH/src/github.com/xinliangnote/go-gin-api
|
||||
|
||||
# RUN 执行 go build .
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
1. 支持 [Swagger](https://github.com/swaggo/gin-swagger) 接口文档生成
|
||||
1. 支持 [GraphQL](https://github.com/99designs/gqlgen) 查询语言
|
||||
1. 支持 trace 项目内部链路追踪
|
||||
1. 支持 [pprof](https://github.com/gin-contrib/pprof) 性能剖析
|
||||
1. 支持 [jwt](https://github.com/dgrijalva/jwt-go) 接口鉴权
|
||||
1. 支持 [pprof](https://github.com/gin-contrib/pprof) 性能剖析
|
||||
1. 支持 errno 统一定义错误码
|
||||
1. 支持 [zap](https://go.uber.org/zap) 日志收集
|
||||
1. 支持 [viper](https://github.com/spf13/viper) 配置文件解析
|
||||
@@ -22,17 +21,29 @@
|
||||
1. 支持 [go-redis](https://github.com/go-redis/redis/v7) 组件
|
||||
1. 支持 RESTful API 返回值规范
|
||||
1. 支持 生成数据表 CURD、控制器方法 等代码生成器
|
||||
1. 支持 [cron](https://github.com/jakecoffman/cron) 定时任务,在后台可界面配置
|
||||
1. 支持 [websocket](https://github.com/gorilla/websocket) 实时通讯,在后台有界面演示
|
||||
1. 支持 web 界面,使用的 [Light Year Admin 模板](https://gitee.com/yinqi/Light-Year-Admin-Using-Iframe)
|
||||
|
||||
|
||||
## 文档索引
|
||||
## 文档索引(可加入交流群)
|
||||
|
||||
- 中文文档:[go-gin-api - 语雀](https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5)
|
||||
- English Document:[en.md](https://github.com/xinliangnote/go-gin-api/blob/master/en.md)
|
||||
|
||||
## 轻量版
|
||||
|
||||
为了满足开发者对于简单、轻量级 API 框架的需求,开发了 gin-api-mono,旨在提供更便捷的业务开发体验。
|
||||
|
||||
相比于 go-gin-api,首先 gin-api-mono 去掉了一些集成的功能和界面,使得整个框架更加简洁、轻量。其次 gin-api-mono 对框架代码进行了升级,以确保其在性能和稳定性方面的优势。这样,开发者就可以更灵活地选择所需的功能,并获得更好的性能和稳定性。
|
||||
|
||||
详见链接:https://xiaobot.net/post/e9f7ef4c-81b1-4ffc-9053-bec55c3abb12
|
||||
|
||||
## 其他
|
||||
|
||||
查看 Jaeger 链路追踪代码,请查看 [v1.0版](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0),文档点这里 [jaeger.md](https://github.com/xinliangnote/go-gin-api/blob/master/docs/jaeger.md) 。
|
||||
查看 Jaeger 链路追踪 Demo 代码,请查看 [v1.0 版](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0) ,链接地址:http://127.0.0.1:9999/jaeger_test
|
||||
|
||||
调用的其他服务端 Demo 代码为 [https://github.com/xinliangnote/go-jaeger-demo](https://github.com/xinliangnote/go-jaeger-demo)
|
||||
|
||||
## 联系作者
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package assets
|
||||
|
||||
import "embed"
|
||||
|
||||
var (
|
||||
//go:embed bootstrap
|
||||
Bootstrap embed.FS
|
||||
|
||||
//go:embed templates
|
||||
Templates embed.FS
|
||||
)
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,32 @@
|
||||
document.write('<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-notify/bootstrap-notify.min.js"></script>');
|
||||
|
||||
function SuccessNotify(content) {
|
||||
$.notify({
|
||||
icon: "mdi mdi-alert",
|
||||
title: "",
|
||||
message: content,
|
||||
url: "",
|
||||
target: ""
|
||||
}, {
|
||||
type: "success",
|
||||
allow_dismiss: true,
|
||||
newest_on_top: false,
|
||||
placement: {
|
||||
from: "top",
|
||||
align: "right",
|
||||
},
|
||||
offset: {
|
||||
x: "20",
|
||||
y: "20"
|
||||
},
|
||||
spacing: "10",
|
||||
z_index: "1031",
|
||||
delay: "3000",
|
||||
animate: {
|
||||
enter: "animated fadeInDown",
|
||||
exit: "animated fadeOutUp"
|
||||
},
|
||||
onClosed: null,
|
||||
mouse_over: null
|
||||
});
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/ksort.js"></script>');
|
||||
document.write('<script type="text/javascript" src="../../bootstrap/js/authorization/crypto-js.min.js"></script>');
|
||||
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('<script type="text/javascript" src="/assets/bootstrap/js/authorization/ksort.js"></script>');
|
||||
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/crypto-js.min.js"></script>');
|
||||
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/hmac-sha256.js"></script>');
|
||||
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/enc-base64.min.js"></script>');
|
||||
document.write('<script type="text/javascript" src="/assets/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) {
|
||||
@@ -11,7 +11,7 @@ function GenerateAuthorization(path, method, params) {
|
||||
|
||||
let date = new Date();
|
||||
let datetime = date.getFullYear() + "-" // "年"
|
||||
+ ((date.getMonth() + 1) > 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
|
||||
+ ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
|
||||
+ (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " " // "日"
|
||||
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" // "小时"
|
||||
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":" // "分钟"
|
||||
@@ -44,10 +44,13 @@ function AjaxError(response) {
|
||||
let errCode = response.status;
|
||||
let errMsg = response.responseText;
|
||||
|
||||
if (errCode === 401) { // 跳转到登录页
|
||||
// 关闭当前界面
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
if (errCode === 401) {
|
||||
// 跳转到登录页
|
||||
if (window.frames.length !== parent.frames.length) {
|
||||
parent.window.open("/login",'_self');
|
||||
}else{
|
||||
window.open("/login",'_self');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -51,13 +51,13 @@
|
||||
</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" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -53,11 +53,11 @@
|
||||
|
||||
</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" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
// 加载列表页数据
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<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">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/assets/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 rel="stylesheet" type="text/css" href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../bootstrap/css/style.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/style.min.css">
|
||||
|
||||
<style>
|
||||
.login-form .has-feedback {
|
||||
@@ -47,7 +47,7 @@
|
||||
<body class="center-vh">
|
||||
<div class="card card-shadowed p-5 w-420 mb-0 mr-2 ml-2">
|
||||
<div class="text-center mb-3">
|
||||
<img src="../../bootstrap/images/logo-sidebar.png">
|
||||
<img src="/assets/bootstrap/images/logo-sidebar.png">
|
||||
</div>
|
||||
<form class="login-form">
|
||||
<div class="form-group has-feedback">
|
||||
@@ -71,10 +71,10 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -53,12 +53,12 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
const hash_id = {{ .HashID }}
|
||||
|
||||
+11
-11
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -44,12 +44,12 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
+17
-14
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -46,13 +46,13 @@
|
||||
</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" src="../../bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/authorization/md5.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
@@ -132,8 +132,11 @@
|
||||
okay: {
|
||||
text: '关闭',
|
||||
action: function () {
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
if (window.frames.length !== parent.frames.length) {
|
||||
parent.window.open("/login",'_self');
|
||||
}else{
|
||||
window.open("/login",'_self');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -46,12 +46,12 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -67,13 +67,13 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -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/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -206,10 +206,10 @@ console.log({authorization: key + " " + digest, date: datetime});
|
||||
</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/main.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/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,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -51,11 +51,11 @@
|
||||
|
||||
</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" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
// 加载列表页数据
|
||||
|
||||
@@ -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="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -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/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -56,10 +56,10 @@
|
||||
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -138,12 +138,12 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -137,12 +137,12 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -57,12 +57,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.pagination.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -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="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -18,7 +18,12 @@
|
||||
<div class="card-title">项目信息 <span class="badge badge-pill badge-warning">{{ .ProjectVersion }}</span> </div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<p>操作系统:{{ .GoOS }} <span class="badge badge-brown"> {{ .GoArch }} </span> <span class="badge badge-info"> {{ .GoVersion }} </span></p>
|
||||
<p>操作系统:{{ .GoOS }}
|
||||
<span class="badge badge-brown"> {{ .GoArch }} </span>
|
||||
<span class="badge badge-info"> {{ .GoVersion }} </span>
|
||||
<span class="badge badge-danger"> mysql{{ .MySQLVersion }} </span>
|
||||
<span class="badge badge-danger"> redis{{ .RedisVersion }} </span>
|
||||
</p>
|
||||
<p>项目地址:{{ .ProjectPath }}</p>
|
||||
<p>项目域名:{{ .Host }} <span class="badge badge-secondary"> {{ .Env }} </span></p>
|
||||
</div>
|
||||
@@ -82,7 +87,7 @@
|
||||
<div class="card-title">开源信息</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<p>GitHub 地址:<a target="_blank" href="https://github.com/xinliangnote/go-gin-api">xinliangnote/go-gin-api</a></p>
|
||||
<p>GitHub 地址:<a target="_blank" href="https://github.com/xinliangnote/go-gin-api">[go-gin-api 源码地址]</a> <a target="_blank" href="https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5">[中文文档]</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>
|
||||
@@ -96,7 +101,7 @@
|
||||
</header>
|
||||
<div class="card-body text-center">
|
||||
<p style="height: 105px;">
|
||||
<img style="height: 100px;" src="../../bootstrap/images/qr-code.png"/>
|
||||
<img style="height: 100px;" src="/assets/bootstrap/images/qr-code.png"/>
|
||||
</p>
|
||||
</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="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -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="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#btnOk").click(function(){
|
||||
|
||||
@@ -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="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -16,7 +16,7 @@
|
||||
<header class="card-header"><div class="card-title"> 生成控制器方法 </div></header>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="handlerName">handler 名称,例如:<code>user_handler</code></label>
|
||||
<label for="handlerName">API handler 名称,例如:<code>user</code>,<small>user 为 internal/api 目录下的文件夹名称</small></label>
|
||||
<input type="text" class="form-control" id="handlerName" placeholder="请输入 handler 名称">
|
||||
</div>
|
||||
|
||||
@@ -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="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#btnOk").click(function(){
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
<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">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/assets/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 rel="stylesheet" type="text/css" href="bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/js/bootstrap-multitabs/multitabs.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/animate.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap/css/style.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/animate.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/bootstrap/css/style.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -26,7 +26,7 @@
|
||||
<!-- logo -->
|
||||
<div id="logo" class="sidebar-header">
|
||||
<a href="/">
|
||||
<img src="bootstrap/images/logo-sidebar.png"/>
|
||||
<img src="/assets/bootstrap/images/logo-sidebar.png"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="lyear-layout-sidebar-info lyear-scroll">
|
||||
@@ -170,7 +170,7 @@
|
||||
|
||||
<li class="dropdown dropdown-profile">
|
||||
<a href="javascript:void(0)" data-toggle="dropdown" class="dropdown-toggle">
|
||||
<img class="img-avatar img-avatar-48 m-r-10" src="bootstrap/images/users/avatar.png">
|
||||
<img class="img-avatar img-avatar-48 m-r-10" src="/assets/bootstrap/images/users/avatar.png">
|
||||
<span id="nickname"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
@@ -210,15 +210,15 @@
|
||||
</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/perfect-scrollbar.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/jquery.cookie.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/index.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/perfect-scrollbar.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.cookie.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/index.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
AjaxForm(
|
||||
@@ -281,8 +281,11 @@
|
||||
$.cookie('_nav_title_', '');
|
||||
$.cookie('_login_token_', '');
|
||||
|
||||
parent.window.close();
|
||||
window.open("/login");
|
||||
if (window.frames.length !== parent.frames.length) {
|
||||
parent.window.open("/login",'_self');
|
||||
}else{
|
||||
window.open("/login",'_self');
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
AjaxError(response);
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
<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">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/assets/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/bootstrap-select/bootstrap-select.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">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-select/bootstrap-select.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -27,7 +27,7 @@
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><span class="badge badge-info">检测 · 环境</span></h5>
|
||||
<div class="input-group mb-3">
|
||||
<p class="text-left">所需版本:<code>go1.15+</code> (<small>当前版本 </small><code>{{.GoVersion}}</code>)</p>
|
||||
<p class="text-left">所需版本:<code>go{{.MinGoVersion}}+</code> (<small>当前版本 </small><code>{{.GoVersion}}</code>)</p>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title"><span class="badge badge-info">配置 · 语言</span></h5>
|
||||
@@ -98,19 +98,9 @@
|
||||
</div>
|
||||
<input type="text" class="form-control" id="mysql_name" value="{{ .Config.MySQL.Write.Name }}"
|
||||
placeholder="请输入数据库名">
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<small>
|
||||
<i class="mdi mdi-checkbox-marked-circle"></i>
|
||||
初始化 MySQL 数据表:<code>authorized</code>、
|
||||
<code>authorized_api</code> 、
|
||||
<code>admin</code>、
|
||||
<code>menu</code>、
|
||||
<code>menu_action</code>、
|
||||
<code>admin_menu</code>、
|
||||
<code>cron_task</code>;
|
||||
</small>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><code>请确保此数据库已存在!</code></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="btnOk" class="btn btn-primary">初始化项目</button>
|
||||
@@ -135,13 +125,13 @@
|
||||
|
||||
</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-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('.select-picker').selectpicker();
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<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">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/assets/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">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -95,15 +95,30 @@
|
||||
<p>5、退出重新登录,即可以看到自己新增的模块。</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p class="h6">
|
||||
<span class="badge badge-pill badge-warning">v1.2.7</span>
|
||||
->
|
||||
<span class="badge badge-pill badge-warning">v1.2.8</span>
|
||||
</p>
|
||||
|
||||
<p>1、源代码升级:
|
||||
<mark>拉取最新代码,覆盖旧版本代码即可。</mark>
|
||||
</p>
|
||||
<p>2、系统管理员->菜单管理,新增侧边栏:实用工具箱 -> WebSocket,同时添加菜单栏的功能权限。</p>
|
||||
<p>3、系统管理员->管理员,对管理员进行菜单授权。</p>
|
||||
<p>4、退出重新登录,即可以看到自己新增的模块。</p>
|
||||
|
||||
<hr/>
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$(document).on('click', '.upgrade', function () {
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -69,13 +69,13 @@
|
||||
</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" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<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/js/jquery-treegrid/jquery.treegrid.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-select/bootstrap-select.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/js/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-treegrid/jquery.treegrid.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-select/bootstrap-select.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -76,18 +76,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-table/bootstrap-table.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-treegrid/jquery.treegrid.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-table/bootstrap-table.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-treegrid/jquery.treegrid.min.js"></script>
|
||||
<script type="text/javascript"
|
||||
src="../../bootstrap/js/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
src="/assets/bootstrap/js/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('.select-picker').selectpicker();
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -61,11 +61,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<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/js/bootstrap-select/bootstrap-select.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/bootstrap-select/bootstrap-select.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -96,15 +96,15 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/vkbeautify.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/main.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/vkbeautify.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/main.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/bootstrap-select.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-select/i18n/defaults-zh_CN.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('.select-picker').selectpicker();
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
|
||||
<link href="../../bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -75,12 +75,12 @@
|
||||
</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-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="../../bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
|
||||
|
||||
@@ -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/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="../../bootstrap/css/style.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -97,9 +97,9 @@
|
||||
</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="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/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>
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
<!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="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/animate.min.css" rel="stylesheet">
|
||||
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid p-t-15">
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<div class="card-title">WebSocket 示例</div>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
|
||||
<ul class="lyear-timeline lyear-timeline-left timeline-content">
|
||||
<li class="lyear-timeline-item">
|
||||
<div class="lyear-timeline-item-dot">
|
||||
<span class="badge"></span>
|
||||
</div>
|
||||
<div class="lyear-timeline-item-content">
|
||||
<p class="mb-1"><strong class="connect-content"></strong></p>
|
||||
<p class="mb-0 connect-url"></p>
|
||||
<p>
|
||||
<time class="mb-3 connect-time"></time>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">WebSocket 示例</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#send_message"
|
||||
aria-selected="true">发送消息</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade active show" id="send_message">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">消息内容</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="message_content" placeholder="请输入消息内容">
|
||||
</div>
|
||||
|
||||
<button type="button" id="btnSend" class="btn btn-primary">发送</button>
|
||||
<button type="button" id="btnSending" 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
|
||||
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-notify/notify.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
const ws = new WebSocket("ws://127.0.0.1:9999/socket/system/message");
|
||||
|
||||
//连接打开时触发
|
||||
ws.onopen = function (evt) {
|
||||
if (evt.isTrusted) {
|
||||
$(".badge").addClass("badge-success");
|
||||
$(".connect-content").html("Socket 连接成功");
|
||||
$(".connect-url").html("连接地址:" + evt.currentTarget.url);
|
||||
$(".connect-time").html(getCSTTime());
|
||||
} else {
|
||||
$(".badge").addClass("badge-danger");
|
||||
$(".connect-content").html("Socket 连接失败");
|
||||
$(".connect-url").html("请确认连接地址是否正确");
|
||||
$(".connect-time").html(getCSTTime());
|
||||
}
|
||||
};
|
||||
|
||||
//接收到消息时触发
|
||||
ws.onmessage = function (evt) {
|
||||
const messageData = JSON.parse(evt.data);
|
||||
|
||||
let html = '<li class="lyear-timeline-item">';
|
||||
html += '<div class="lyear-timeline-item-dot"><span class="badge badge-success"></span></div>';
|
||||
html += '<div class="lyear-timeline-item-content">';
|
||||
html += '<p class="mb-1"><strong>' + messageData.username + '</strong></p>';
|
||||
html += '<p class="mb-0">' + messageData.message + '</p>';
|
||||
html += '<p><time class="mb-3">' + messageData.time + '</time></p>';
|
||||
html += '</div></li>';
|
||||
|
||||
$(".timeline-content").prepend(html);
|
||||
};
|
||||
|
||||
//连接关闭时触发
|
||||
ws.onclose = function (evt) {
|
||||
|
||||
let html = '<li class="lyear-timeline-item">';
|
||||
html += '<div class="lyear-timeline-item-dot"><span class="badge badge-muted"></span></div>';
|
||||
html += '<div class="lyear-timeline-item-content">';
|
||||
html += '<p class="mb-1"><strong>Socket 连接关闭</strong></p>';
|
||||
html += '<p class="mb-0">连接已关闭</p>';
|
||||
html += '<p><time class="mb-3">' + getCSTTime() + '</time></p>';
|
||||
html += '</div></li>';
|
||||
|
||||
$(".timeline-content").prepend(html);
|
||||
|
||||
};
|
||||
|
||||
function getCSTTime() {
|
||||
let date = new Date();
|
||||
let datetime = date.getFullYear() + "-" // "年"
|
||||
+ ((date.getMonth() + 1) > 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
|
||||
+ (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " " // "日"
|
||||
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" // "小时"
|
||||
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":" // "分钟"
|
||||
+ (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()); // "秒"
|
||||
|
||||
return datetime;
|
||||
}
|
||||
|
||||
$('#btnSend').on('click', function () {
|
||||
const messageContent = $("#message_content").val();
|
||||
if (messageContent === "") {
|
||||
$.alert({
|
||||
title: '温馨提示',
|
||||
icon: 'mdi mdi-alert',
|
||||
type: 'orange',
|
||||
content: '请输入消息内容。',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
AjaxForm(
|
||||
"POST",
|
||||
"/api/tool/send_message",
|
||||
{message: messageContent},
|
||||
function () {
|
||||
$(this).hide();
|
||||
$("#btnSendLoading").show();
|
||||
},
|
||||
function (data) {
|
||||
$("#btnSendLoading").hide();
|
||||
$("#btnSend").show();
|
||||
|
||||
if (data.status === 'OK') {
|
||||
$("#message_content").val("");
|
||||
SuccessNotify("消息发送成功");
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
$("#btnSendLoading").hide();
|
||||
$("#btnSend").show();
|
||||
|
||||
AjaxError(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
@@ -135,7 +135,7 @@ func (qb *{{.QueryBuilderName}}) Offset(offset int) *{{.QueryBuilderName}} {
|
||||
|
||||
{{$queryBuilderName := .QueryBuilderName}}
|
||||
{{range .OptionFields}}
|
||||
func (qb *{{$queryBuilderName}}) Where{{call $.Helpers.Titelize .FieldName}}(p db_repo.Predicate, value {{.FieldType}}) *{{$queryBuilderName}} {
|
||||
func (qb *{{$queryBuilderName}}) Where{{call $.Helpers.Titelize .FieldName}}(p mysql.Predicate, value {{.FieldType}}) *{{$queryBuilderName}} {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
## 执行命令
|
||||
|
||||
```$xslt
|
||||
// test_handler 为 ./internal/api/controller/ 中的包名
|
||||
./scripts/handlergen.sh test_handler
|
||||
```
|
||||
|
||||
## 模板文件参考
|
||||
|
||||
```go
|
||||
package test_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
|
||||
// Create 创建用户
|
||||
// @Tags Test
|
||||
// @Router /test/create [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// Update 编辑用户
|
||||
// @Tags Test
|
||||
// @Router /test/update [post]
|
||||
Update() core.HandlerFunc
|
||||
|
||||
// Delete 删除用户
|
||||
// @Tags Test
|
||||
// @Router /test/delete [post]
|
||||
Delete() core.HandlerFunc
|
||||
|
||||
// Detail 用户详情
|
||||
// @Tags Test
|
||||
// @Router /test/detail [post]
|
||||
Detail() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
userService user_service.UserService
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
|
||||
```
|
||||
|
||||
以上会生成 4 个文件
|
||||
- func_create.go
|
||||
- func_update.go
|
||||
- func_delete.go
|
||||
- func_detail.go
|
||||
|
||||
## func_create.go 参考
|
||||
|
||||
```go
|
||||
package test_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type createRequest struct{}
|
||||
|
||||
type createResponse struct{}
|
||||
|
||||
// Create 创建用户
|
||||
// @Summary 创建用户
|
||||
// @Description 创建用户
|
||||
// @Tags Test
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Request body createRequest true "请求信息"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /test/create [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@@ -25,7 +25,7 @@ func init() {
|
||||
|
||||
func main() {
|
||||
fs := token.NewFileSet()
|
||||
filePath := fmt.Sprintf("./internal/api/controller/%s", handlerName)
|
||||
filePath := fmt.Sprintf("./internal/api/%s", handlerName)
|
||||
parsedFile, err := decorator.ParseFile(fs, filePath+"/handler.go", nil, 0)
|
||||
if err != nil {
|
||||
log.Fatalf("parsing package: %s: %s\n", filePath, err)
|
||||
@@ -59,7 +59,7 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
filepath := "./internal/api/controller/" + handlerName
|
||||
filepath := "./internal/api/" + handlerName
|
||||
filename := fmt.Sprintf("%s/func_%s.go", filepath, strings.ToLower(v.Names[0].String()))
|
||||
funcFile, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0766)
|
||||
if err != nil {
|
||||
@@ -89,14 +89,14 @@ func main() {
|
||||
funcContent += fmt.Sprintf("// @Description%s \n", nameArr[1])
|
||||
// Tags
|
||||
funcContent += fmt.Sprintf("%s \n", v.Decorations().Start.All()[1])
|
||||
funcContent += fmt.Sprintf("// @Accept json \n")
|
||||
funcContent += fmt.Sprintf("// @Accept application/x-www-form-urlencoded \n")
|
||||
funcContent += fmt.Sprintf("// @Produce json \n")
|
||||
funcContent += fmt.Sprintf("// @Param Request body %sRequest true \"请求信息\" \n", Lcfirst(v.Names[0].String()))
|
||||
funcContent += fmt.Sprintf("// @Success 200 {object} %sResponse \n", Lcfirst(v.Names[0].String()))
|
||||
funcContent += fmt.Sprintf("// @Failure 400 {object} code.Failure \n")
|
||||
// Router
|
||||
funcContent += fmt.Sprintf("%s \n", v.Decorations().Start.All()[2])
|
||||
funcContent += fmt.Sprintf("func (h *handler) %s() core.HandlerFunc { \n return func(c core.Context) {\n\n}}", v.Names[0].String())
|
||||
funcContent += fmt.Sprintf("func (h *handler) %s() core.HandlerFunc { \n return func(ctx core.Context) {\n\n}}", v.Names[0].String())
|
||||
|
||||
funcFile.WriteString(funcContent)
|
||||
funcFile.Close()
|
||||
|
||||
+4
-4
@@ -75,7 +75,7 @@ func main() {
|
||||
|
||||
for _, table := range tables {
|
||||
|
||||
filepath := "./internal/api/repository/db_repo/" + table.Name + "_repo"
|
||||
filepath := "./internal/repository/mysql/" + table.Name
|
||||
_ = os.Mkdir(filepath, 0766)
|
||||
fmt.Println("create dir : ", filepath)
|
||||
|
||||
@@ -85,7 +85,7 @@ func main() {
|
||||
fmt.Printf("markdown file error %v\n", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(" └── file : ", table.Name+"_repo/gen_table.md")
|
||||
fmt.Println(" └── file : ", table.Name+"/gen_table.md")
|
||||
|
||||
modelName := fmt.Sprintf("%s/gen_model.go", filepath)
|
||||
modelFile, err := os.OpenFile(modelName, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0766)
|
||||
@@ -93,9 +93,9 @@ func main() {
|
||||
fmt.Printf("create and open model file error %v\n", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(" └── file : ", table.Name+"_repo/gen_model.go")
|
||||
fmt.Println(" └── file : ", table.Name+"/gen_model.go")
|
||||
|
||||
modelContent := fmt.Sprintf("package %s%s\n", table.Name, "_repo")
|
||||
modelContent := fmt.Sprintf("package %s\n", table.Name)
|
||||
modelContent += fmt.Sprintf(`import "time"`)
|
||||
modelContent += fmt.Sprintf("\n\n// %s %s \n", capitalize(table.Name), table.Comment.String)
|
||||
modelContent += fmt.Sprintf("//go:generate gormgen -structs %s -input . \n", capitalize(table.Name))
|
||||
|
||||
+59
-15
@@ -1,9 +1,15 @@
|
||||
package configs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/file"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
@@ -49,16 +55,6 @@ type Config struct {
|
||||
To string `toml:"to"`
|
||||
} `toml:"mail"`
|
||||
|
||||
JWT struct {
|
||||
Secret string `toml:"secret"`
|
||||
ExpireDuration time.Duration `toml:"expireDuration"`
|
||||
} `toml:"jwt"`
|
||||
|
||||
URLToken struct {
|
||||
Secret string `toml:"secret"`
|
||||
ExpireDuration time.Duration `toml:"expireDuration"`
|
||||
} `toml:"urlToken"`
|
||||
|
||||
HashIds struct {
|
||||
Secret string `toml:"secret"`
|
||||
Length int `toml:"length"`
|
||||
@@ -69,12 +65,39 @@ type Config struct {
|
||||
} `toml:"language"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
var (
|
||||
//go:embed dev_configs.toml
|
||||
devConfigs []byte
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
//go:embed fat_configs.toml
|
||||
fatConfigs []byte
|
||||
|
||||
//go:embed uat_configs.toml
|
||||
uatConfigs []byte
|
||||
|
||||
//go:embed pro_configs.toml
|
||||
proConfigs []byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
var r io.Reader
|
||||
|
||||
switch env.Active().Value() {
|
||||
case "dev":
|
||||
r = bytes.NewReader(devConfigs)
|
||||
case "fat":
|
||||
r = bytes.NewReader(fatConfigs)
|
||||
case "uat":
|
||||
r = bytes.NewReader(uatConfigs)
|
||||
case "pro":
|
||||
r = bytes.NewReader(proConfigs)
|
||||
default:
|
||||
r = bytes.NewReader(fatConfigs)
|
||||
}
|
||||
|
||||
viper.SetConfigType("toml")
|
||||
|
||||
if err := viper.ReadConfig(r); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -82,6 +105,27 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.AddConfigPath("./configs")
|
||||
|
||||
configFile := "./configs/" + env.Active().Value() + "_configs.toml"
|
||||
_, ok := file.IsExists(configFile)
|
||||
if !ok {
|
||||
if err := os.MkdirAll(filepath.Dir(configFile), 0766); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f, err := os.Create(configFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
viper.WatchConfig()
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
if err := viper.Unmarshal(config); err != nil {
|
||||
|
||||
+15
-4
@@ -1,8 +1,13 @@
|
||||
package configs
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
// MinGoVersion 最小 Go 版本
|
||||
MinGoVersion = 1.16
|
||||
|
||||
// ProjectVersion 项目版本
|
||||
ProjectVersion = "v1.2.7"
|
||||
ProjectVersion = "v1.2.8"
|
||||
|
||||
// ProjectName 项目名称
|
||||
ProjectName = "go-gin-api"
|
||||
@@ -25,14 +30,14 @@ const (
|
||||
// HeaderLoginToken 登录验证 Token,Header 中传递的参数
|
||||
HeaderLoginToken = "Token"
|
||||
|
||||
// HeaderSignToken 签名验证 Token,Header 中传递的参数
|
||||
// HeaderSignToken 签名验证 Authorization,Header 中传递的参数
|
||||
HeaderSignToken = "Authorization"
|
||||
|
||||
// HeaderSignTokenDate 签名验证 Date,Header 中传递的参数
|
||||
HeaderSignTokenDate = "Authorization-Date"
|
||||
|
||||
// RedisKeyPrefixRequestID Redis Key 前缀 - 防止重复提交
|
||||
RedisKeyPrefixRequestID = ProjectName + ":request-id:"
|
||||
// HeaderSignTokenTimeout 签名有效期为 2 分钟
|
||||
HeaderSignTokenTimeout = time.Minute * 2
|
||||
|
||||
// RedisKeyPrefixLoginUser Redis Key 前缀 - 登录用户信息
|
||||
RedisKeyPrefixLoginUser = ProjectName + ":login-user:"
|
||||
@@ -45,4 +50,10 @@ const (
|
||||
|
||||
// EnUS 英文 - 美国
|
||||
EnUS = "en-us"
|
||||
|
||||
// MaxRequestsPerSecond 每秒最大请求量
|
||||
MaxRequestsPerSecond = 10000
|
||||
|
||||
// LoginSessionTTL 登录有效期为 24 小时
|
||||
LoginSessionTTL = time.Hour * 24
|
||||
)
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
length = 12
|
||||
secret = "6ab6122836cfef95f8db"
|
||||
|
||||
[jwt]
|
||||
expireduration = 24
|
||||
secret = "i1ydX9RtHyuJTrw7frcu"
|
||||
|
||||
[language]
|
||||
local = "zh-cn"
|
||||
|
||||
@@ -43,7 +39,3 @@
|
||||
minidleconns = 5
|
||||
pass = ""
|
||||
poolsize = 10
|
||||
|
||||
[urltoken]
|
||||
expireduration = 10
|
||||
secret = "i1ydX9RtHyuJTrw7frcu"
|
||||
|
||||
+788
-251
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
## Jaeger Demo 代码
|
||||
|
||||
- 代码在 [v1.0](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0) 版本。
|
||||
|
||||
#### Jaeger Demo 文档
|
||||
|
||||
访问:
|
||||
|
||||
```
|
||||
http://127.0.0.1:9999/jaeger_test
|
||||
```
|
||||
|
||||
服务端测试代码:
|
||||
|
||||
- [https://github.com/xinliangnote/go-jaeger-demo](https://github.com/xinliangnote/go-jaeger-demo)
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
+776
-245
File diff suppressed because it is too large
Load Diff
+488
-188
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,6 @@ Features:
|
||||
1. GraphQL supported by [GraphQL](https://github.com/99designs/gqlgen)
|
||||
1. Trace project internal invoking
|
||||
1. Visualized performance analysis supported by [pprof](https://github.com/gin-contrib/pprof)
|
||||
1. Industry standard RFC 7519 method for authentication supported by [jwt](https://github.com/dgrijalva/jwt-go)
|
||||
1. Uniformly defined error codes supported by errno
|
||||
1. Blazing fast, structured, leveled logging system by [zap](https://go.uber.org/zap)
|
||||
1. Complete configuration solution supported by [viper](https://github.com/spf13/viper)
|
||||
@@ -29,10 +28,6 @@ Features:
|
||||
|
||||
**Detailed documentation:[https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5](https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5)**
|
||||
|
||||
## Others
|
||||
|
||||
To check Jaeger code, [v1.0](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0),documentation:[jaeger.md](https://github.com/xinliangnote/go-gin-api/blob/master/docs/jaeger.md) 。
|
||||
|
||||
## Contributing
|
||||
|
||||
Help us with translating `go-gin-api` to your native language.
|
||||
|
||||
@@ -1,49 +1,39 @@
|
||||
module github.com/xinliangnote/go-gin-api
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.13.0
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/99designs/gqlgen v0.14.0
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/dave/dst v0.26.2
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/gin-contrib/pprof v1.3.0
|
||||
github.com/gin-gonic/gin v1.7.0
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-openapi/spec v0.20.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0
|
||||
github.com/go-playground/universal-translator v0.17.0
|
||||
github.com/go-playground/validator/v10 v10.4.1
|
||||
github.com/go-redis/redis/v7 v7.4.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/go-playground/locales v0.14.0
|
||||
github.com/go-playground/universal-translator v0.18.0
|
||||
github.com/go-playground/validator/v10 v10.9.0
|
||||
github.com/go-redis/redis/v7 v7.4.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jakecoffman/cron v0.0.0-20190106200828-7e2009c226a5
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/onsi/ginkgo v1.14.2 // indirect
|
||||
github.com/onsi/gomega v1.10.4 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/shirou/gopsutil v3.21.2+incompatible
|
||||
github.com/speps/go-hashids v2.0.0+incompatible
|
||||
github.com/spf13/cast v1.3.1
|
||||
github.com/spf13/viper v1.8.0
|
||||
github.com/swaggo/gin-swagger v1.3.0
|
||||
github.com/swaggo/swag v1.7.0
|
||||
github.com/tklauser/go-sysconf v0.3.4 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.1.0
|
||||
go.uber.org/multierr v1.6.0
|
||||
go.uber.org/zap v1.17.0
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
|
||||
golang.org/x/tools v0.1.4
|
||||
google.golang.org/grpc v1.38.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/rs/cors v1.8.0
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible
|
||||
github.com/speps/go-hashids v1.0.0
|
||||
github.com/spf13/cast v1.4.1
|
||||
github.com/spf13/viper v1.9.0
|
||||
github.com/swaggo/gin-swagger v1.3.3
|
||||
github.com/swaggo/swag v1.7.4
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.2.0
|
||||
go.uber.org/multierr v1.7.0
|
||||
go.uber.org/zap v1.19.1
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
|
||||
golang.org/x/tools v0.1.7
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
gorm.io/driver/mysql v1.0.3
|
||||
gorm.io/gorm v1.20.9
|
||||
gorm.io/driver/mysql v1.2.0
|
||||
gorm.io/gorm v1.22.3
|
||||
)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package alert
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/proposal"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errors"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/mail"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// NotifyHandler 告警通知
|
||||
func NotifyHandler(logger *zap.Logger) func(msg *proposal.AlertMessage) {
|
||||
if logger == nil {
|
||||
panic("logger required")
|
||||
}
|
||||
|
||||
return func(msg *proposal.AlertMessage) {
|
||||
cfg := configs.Get().Mail
|
||||
if cfg.Host == "" || cfg.Port == 0 || cfg.User == "" || cfg.Pass == "" || cfg.To == "" {
|
||||
logger.Error("Mail config error")
|
||||
return
|
||||
}
|
||||
|
||||
subject, body, err := newHTMLEmail(
|
||||
msg.Method,
|
||||
msg.HOST,
|
||||
msg.URI,
|
||||
msg.TraceID,
|
||||
msg.ErrorMessage,
|
||||
msg.ErrorStack,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error("email template error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
options := &mail.Options{
|
||||
MailHost: cfg.Host,
|
||||
MailPort: cfg.Port,
|
||||
MailUser: cfg.User,
|
||||
MailPass: cfg.Pass,
|
||||
MailTo: cfg.To,
|
||||
Subject: subject,
|
||||
Body: body,
|
||||
}
|
||||
if err := mail.Send(options); err != nil {
|
||||
logger.Error("发送告警通知邮件失败", zap.Error(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,54 @@
|
||||
package templates
|
||||
package alert
|
||||
|
||||
const PanicMail = `
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewHTMLEmail 告警邮件模板
|
||||
func newHTMLEmail(method, host, uri, id string, msg interface{}, stack string) (subject string, body string, err error) {
|
||||
mailData := &struct {
|
||||
URL string
|
||||
ID string
|
||||
Msg string
|
||||
Stack string
|
||||
Year int
|
||||
}{
|
||||
URL: fmt.Sprintf("%s %s%s", method, host, uri),
|
||||
ID: id,
|
||||
Msg: fmt.Sprintf("%+v", msg),
|
||||
Stack: stack,
|
||||
Year: time.Now().Year(),
|
||||
}
|
||||
|
||||
// subject 邮件主题
|
||||
subject = fmt.Sprintf("[系统告警]-%s", uri)
|
||||
|
||||
// body 邮件内容
|
||||
body, err = getEmailHTMLContent(mailTemplate, mailData)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// getEmailHTMLContent 获取邮件模板
|
||||
func getEmailHTMLContent(mailTpl string, mailData interface{}) (string, error) {
|
||||
tpl, err := template.New("email tpl").Parse(mailTpl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
err = tpl.Execute(buffer, mailData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
const mailTemplate = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
@@ -27,7 +75,7 @@ const PanicMail = `
|
||||
<!-- Logo -->
|
||||
<tr>
|
||||
<td style="padding: 25px 0; text-align: center;">
|
||||
系统异常
|
||||
系统告警
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -84,7 +132,7 @@ const PanicMail = `
|
||||
Stack:
|
||||
</td>
|
||||
<td style="width: 90%;">
|
||||
{{.Stack}}}
|
||||
{{.Stack}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
+12
-12
@@ -1,20 +1,19 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
Username string `form:"username" binding:"required"` // 用户名
|
||||
Nickname string `form:"nickname" binding:"required"` // 昵称
|
||||
Mobile string `form:"mobile" binding:"required"` // 手机号
|
||||
Password string `form:"password" binding:"required"` // 密码
|
||||
Password string `form:"password" binding:"required"` // MD5后的密码
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
@@ -25,29 +24,30 @@ type createResponse struct {
|
||||
// @Summary 新增管理员
|
||||
// @Description 新增管理员
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param username formData string true "用户名"
|
||||
// @Param nickname formData string true "昵称"
|
||||
// @Param mobile formData string true "手机号"
|
||||
// @Param password formData string true "密码"
|
||||
// @Param password formData string true "MD5后的密码"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(admin_service.CreateAdminData)
|
||||
createData := new(admin.CreateAdminData)
|
||||
createData.Nickname = req.Nickname
|
||||
createData.Username = req.Username
|
||||
createData.Mobile = req.Mobile
|
||||
@@ -55,10 +55,10 @@ func (h *handler) Create() core.HandlerFunc {
|
||||
|
||||
id, err := h.adminService.Create(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminCreateError,
|
||||
code.Text(code.AdminCreateError)).WithErr(err),
|
||||
code.Text(code.AdminCreateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+12
-12
@@ -1,12 +1,11 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type createAdminMenuRequest struct {
|
||||
@@ -22,46 +21,47 @@ type createAdminMenuResponse struct {
|
||||
// @Summary 提交菜单授权
|
||||
// @Description 提交菜单授权
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @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]
|
||||
// @Security LoginToken
|
||||
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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(admin_service.CreateMenuData)
|
||||
createData := new(admin.CreateMenuData)
|
||||
createData.AdminId = int32(ids[0])
|
||||
createData.Actions = req.Actions
|
||||
|
||||
err = h.adminService.CreateMenu(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminMenuCreateError,
|
||||
code.Text(code.AdminMenuCreateError)).WithErr(err),
|
||||
code.Text(code.AdminMenuCreateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
@@ -26,25 +25,26 @@ type deleteResponse struct {
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/{id} [delete]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) Delete() core.HandlerFunc {
|
||||
|
||||
err = h.adminService.Delete(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDeleteError,
|
||||
code.Text(code.AdminDeleteError)).WithErr(err),
|
||||
code.Text(code.AdminDeleteError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type detailResponse struct {
|
||||
Username string `json:"username"` // 用户名
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
Menu []admin.ListMyMenuData `json:"menu"` // 菜单栏
|
||||
}
|
||||
|
||||
// Detail 管理员详情
|
||||
// @Summary 管理员详情
|
||||
// @Description 管理员详情
|
||||
// @Tags API.admin
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/info [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
res := new(detailResponse)
|
||||
|
||||
searchOneData := new(admin.SearchOneData)
|
||||
searchOneData.Id = ctx.SessionUserInfo().UserID
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(ctx, searchOneData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
menuCacheData, err := h.cache.Get(configs.RedisKeyPrefixLoginUser+password.GenerateLoginToken(searchOneData.Id)+":menu", redis.WithTrace(ctx.Trace()))
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var menuData []admin.ListMyMenuData
|
||||
err = json.Unmarshal([]byte(menuCacheData), &menuData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = info.Username
|
||||
res.Nickname = info.Nickname
|
||||
res.Mobile = info.Mobile
|
||||
res.Menu = menuData
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
+19
-19
@@ -1,15 +1,14 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/timeutil"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -49,25 +48,26 @@ type listResponse struct {
|
||||
// @Summary 管理员列表
|
||||
// @Description 管理员列表
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param page query int true "第几页" default(1)
|
||||
// @Param page_size query int true "每页显示条数" default(10)
|
||||
// @Param username query string false "用户名"
|
||||
// @Param nickname query string false "昵称"
|
||||
// @Param mobile query string false "手机号"
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (h *handler) List() core.HandlerFunc {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(admin_service.SearchData)
|
||||
searchData := new(admin.SearchData)
|
||||
searchData.Page = page
|
||||
searchData.PageSize = pageSize
|
||||
searchData.Username = req.Username
|
||||
@@ -91,20 +91,20 @@ func (h *handler) List() core.HandlerFunc {
|
||||
|
||||
resListData, err := h.adminService.PageList(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminListError,
|
||||
code.Text(code.AdminListError)).WithErr(err),
|
||||
code.Text(code.AdminListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.adminService.PageListCount(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminListError,
|
||||
code.Text(code.AdminListError)).WithErr(err),
|
||||
code.Text(code.AdminListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -116,10 +116,10 @@ func (h *handler) List() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -137,9 +137,9 @@ func (h *handler) List() core.HandlerFunc {
|
||||
Mobile: v.Mobile,
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
IsOnline: isOnline,
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
CreatedAt: v.CreatedAt.Format(timeutil.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedAt: v.UpdatedAt.Format(timeutil.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
+18
-18
@@ -1,12 +1,11 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type listAdminMenuRequest struct {
|
||||
@@ -14,68 +13,69 @@ type listAdminMenuRequest struct {
|
||||
}
|
||||
|
||||
type listAdminMenuResponse struct {
|
||||
List []admin_service.ListMenuData `json:"list"`
|
||||
UserName string `json:"username"`
|
||||
List []admin.ListMenuData `json:"list"`
|
||||
UserName string `json:"username"`
|
||||
}
|
||||
|
||||
// ListAdminMenu 菜单授权列表
|
||||
// @Summary 菜单授权列表
|
||||
// @Description 菜单授权列表
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} listAdminMenuResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/menu/:id [get]
|
||||
// @Router /api/admin/menu/{id} [get]
|
||||
// @Security LoginToken
|
||||
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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData := new(admin.SearchOneData)
|
||||
searchOneData.Id = int32(ids[0])
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminMenuListError,
|
||||
code.Text(code.AdminMenuListError)).WithErr(err),
|
||||
code.Text(code.AdminMenuListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.UserName = info.Username
|
||||
|
||||
searchData := new(admin_service.SearchListMenuData)
|
||||
searchData := new(admin.SearchListMenuData)
|
||||
searchData.AdminId = int32(ids[0])
|
||||
|
||||
listData, err := h.adminService.ListMenu(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminMenuListError,
|
||||
code.Text(code.AdminMenuListError)).WithErr(err),
|
||||
code.Text(code.AdminMenuListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+35
-44
@@ -1,17 +1,16 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/proposal"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -28,86 +27,78 @@ type loginResponse struct {
|
||||
// @Summary 管理员登录
|
||||
// @Description 管理员登录
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param username formData string true "用户名"
|
||||
// @Param password formData string true "密码"
|
||||
// @Param password formData string true "MD5后的密码"
|
||||
// @Success 200 {object} loginResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/login [post]
|
||||
// @Router /api/login [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Login() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(loginRequest)
|
||||
res := new(loginResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData := new(admin.SearchOneData)
|
||||
searchOneData.Username = req.Username
|
||||
searchOneData.Password = password.GeneratePassword(req.Password)
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if info == nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(errors.New("未查询出符合条件的用户")),
|
||||
code.Text(code.AdminLoginError)).WithError(errors.New("未查询出符合条件的用户")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
token := password.GenerateLoginToken(info.Id)
|
||||
|
||||
adminCacheData := &struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
Username string `json:"username"` // 用户名
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}{
|
||||
Id: info.Id,
|
||||
Username: info.Username,
|
||||
Nickname: info.Nickname,
|
||||
Mobile: info.Mobile,
|
||||
// 用户信息
|
||||
sessionUserInfo := &proposal.SessionUserInfo{
|
||||
UserID: info.Id,
|
||||
UserName: info.Username,
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
adminJsonInfo, _ := json.Marshal(adminCacheData)
|
||||
|
||||
// 将用户信息记录到 Redis 中
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token, string(adminJsonInfo), time.Hour*24, cache.WithTrace(c.Trace()))
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token, string(sessionUserInfo.Marshal()), configs.LoginSessionTTL, redis.WithTrace(c.Trace()))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchMenuData := new(admin_service.SearchMyMenuData)
|
||||
searchMenuData := new(admin.SearchMyMenuData)
|
||||
searchMenuData.AdminId = info.Id
|
||||
menu, err := h.adminService.MyMenu(c, searchMenuData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -116,24 +107,24 @@ func (h *handler) Login() core.HandlerFunc {
|
||||
menuJsonInfo, _ := json.Marshal(menu)
|
||||
|
||||
// 将菜单栏信息记录到 Redis 中
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token+":menu", string(menuJsonInfo), time.Hour*24, cache.WithTrace(c.Trace()))
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token+":menu", string(menuJsonInfo), configs.LoginSessionTTL, redis.WithTrace(c.Trace()))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchActionData := new(admin_service.SearchMyActionData)
|
||||
searchActionData := new(admin.SearchMyActionData)
|
||||
searchActionData.AdminId = info.Id
|
||||
action, err := h.adminService.MyAction(c, searchActionData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -142,12 +133,12 @@ func (h *handler) Login() core.HandlerFunc {
|
||||
actionJsonInfo, _ := json.Marshal(action)
|
||||
|
||||
// 将可访问接口信息记录到 Redis 中
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token+":action", string(actionJsonInfo), time.Hour*24, cache.WithTrace(c.Trace()))
|
||||
err = h.cache.Set(configs.RedisKeyPrefixLoginUser+token+":action", string(actionJsonInfo), configs.LoginSessionTTL, redis.WithTrace(c.Trace()))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLoginError,
|
||||
code.Text(code.AdminLoginError)).WithErr(err),
|
||||
code.Text(code.AdminLoginError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+10
-10
@@ -1,13 +1,12 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -19,21 +18,22 @@ type logoutResponse struct {
|
||||
// @Summary 管理员登出
|
||||
// @Description 管理员登出
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Success 200 {object} logoutResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/login [post]
|
||||
// @Router /api/admin/logout [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Logout() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
res := new(logoutResponse)
|
||||
res.Username = c.UserName()
|
||||
res.Username = c.SessionUserInfo().UserName
|
||||
|
||||
if !h.cache.Del(configs.RedisKeyPrefixLoginUser+c.GetHeader(configs.HeaderLoginToken), cache.WithTrace(c.Trace())) {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if !h.cache.Del(configs.RedisKeyPrefixLoginUser+c.GetHeader(configs.HeaderLoginToken), redis.WithTrace(c.Trace())) {
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminLogOutError,
|
||||
code.Text(code.AdminLogOutError)).WithErr(errors.New("cache del err")),
|
||||
code.Text(code.AdminLogOutError)).WithError(errors.New("cache del err")),
|
||||
)
|
||||
return
|
||||
}
|
||||
+19
-23
@@ -1,15 +1,12 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type modifyPasswordRequest struct {
|
||||
@@ -25,53 +22,52 @@ type modifyPasswordResponse struct {
|
||||
// @Summary 修改密码
|
||||
// @Description 修改密码
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param old_password formData string true "旧密码"
|
||||
// @Param new_password formData string true "新密码"
|
||||
// @Success 200 {object} modifyPasswordResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/modify_password [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) ModifyPassword() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
return func(ctx core.Context) {
|
||||
req := new(modifyPasswordRequest)
|
||||
res := new(modifyPasswordResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
userId := cast.ToInt32(c.UserID())
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData.Id = userId
|
||||
searchOneData := new(admin.SearchOneData)
|
||||
searchOneData.Id = ctx.SessionUserInfo().UserID
|
||||
searchOneData.Password = password.GeneratePassword(req.OldPassword)
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
info, err := h.adminService.Detail(ctx, searchOneData)
|
||||
if err != nil || info == nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPasswordError,
|
||||
code.Text(code.AdminModifyPasswordError)).WithErr(err),
|
||||
code.Text(code.AdminModifyPasswordError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.adminService.ModifyPassword(c, userId, req.NewPassword); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := h.adminService.ModifyPassword(ctx, ctx.SessionUserInfo().UserID, req.NewPassword); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPasswordError,
|
||||
code.Text(code.AdminModifyPasswordError)).WithErr(err),
|
||||
code.Text(code.AdminModifyPasswordError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = c.UserName()
|
||||
c.Payload(res)
|
||||
res.Username = ctx.SessionUserInfo().UserName
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
+16
-20
@@ -1,14 +1,11 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
)
|
||||
|
||||
type modifyPersonalInfoRequest struct {
|
||||
@@ -24,42 +21,41 @@ type modifyPersonalInfoResponse struct {
|
||||
// @Summary 修改个人信息
|
||||
// @Description 修改个人信息
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param nickname formData string true "昵称"
|
||||
// @Param mobile formData string true "手机号"
|
||||
// @Success 200 {object} modifyPersonalInfoResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/modify_password [patch]
|
||||
// @Router /api/admin/modify_personal_info [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) ModifyPersonalInfo() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
return func(ctx core.Context) {
|
||||
req := new(modifyPersonalInfoRequest)
|
||||
res := new(modifyPersonalInfoResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
userId := cast.ToInt32(c.UserID())
|
||||
|
||||
modifyData := new(admin_service.ModifyData)
|
||||
modifyData := new(admin.ModifyData)
|
||||
modifyData.Nickname = req.Nickname
|
||||
modifyData.Mobile = req.Mobile
|
||||
|
||||
if err := h.adminService.ModifyPersonalInfo(c, userId, modifyData); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
if err := h.adminService.ModifyPersonalInfo(ctx, ctx.SessionUserInfo().UserID, modifyData); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminModifyPersonalInfoError,
|
||||
code.Text(code.AdminModifyPersonalInfoError)).WithErr(err),
|
||||
code.Text(code.AdminModifyPersonalInfoError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = c.UserName()
|
||||
c.Payload(res)
|
||||
res.Username = ctx.SessionUserInfo().UserName
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -1,14 +1,13 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
)
|
||||
|
||||
type offlineRequest struct {
|
||||
@@ -23,40 +22,41 @@ type offlineResponse struct {
|
||||
// @Summary 下线管理员
|
||||
// @Description 下线管理员
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Success 200 {object} offlineResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/offline [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Offline() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(offlineRequest)
|
||||
res := new(offlineResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
b := h.cache.Del(configs.RedisKeyPrefixLoginUser+password.GenerateLoginToken(id), cache.WithTrace(c.Trace()))
|
||||
b := h.cache.Del(configs.RedisKeyPrefixLoginUser+password.GenerateLoginToken(id), redis.WithTrace(c.Trace()))
|
||||
if !b {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminOfflineError,
|
||||
code.Text(code.AdminOfflineError)),
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type resetPasswordRequest struct {
|
||||
@@ -26,25 +25,26 @@ type resetPasswordResponse struct {
|
||||
// @Success 200 {object} resetPasswordResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/reset_password/{id} [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) ResetPassword() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(resetPasswordRequest)
|
||||
res := new(resetPasswordResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) ResetPassword() core.HandlerFunc {
|
||||
|
||||
err = h.adminService.ResetPassword(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminResetPasswordError,
|
||||
code.Text(code.AdminResetPasswordError)).WithErr(err),
|
||||
code.Text(code.AdminResetPasswordError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+10
-10
@@ -1,11 +1,10 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
@@ -21,32 +20,33 @@ type updateUsedResponse struct {
|
||||
// @Summary 更新管理员为启用/禁用
|
||||
// @Description 更新管理员为启用/禁用
|
||||
// @Tags API.admin
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/used [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -55,10 +55,10 @@ func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
|
||||
err = h.adminService.UpdateUsed(c, id, req.Used)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminUpdateError,
|
||||
code.Text(code.AdminUpdateError)).WithErr(err),
|
||||
code.Text(code.AdminUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package admin_handler
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/admin"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -18,7 +18,7 @@ type Handler interface {
|
||||
|
||||
// Login 管理员登录
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/login [post]
|
||||
// @Router /api/login [post]
|
||||
Login() core.HandlerFunc
|
||||
|
||||
// Logout 管理员登出
|
||||
@@ -78,23 +78,23 @@ type Handler interface {
|
||||
|
||||
// ListAdminMenu 菜单授权列表
|
||||
// @Tags API.admin
|
||||
// @Router /api/admin/menu/:id [get]
|
||||
// @Router /api/admin/menu/{id} [get]
|
||||
ListAdminMenu() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
cache redis.Repo
|
||||
hashids hash.Hash
|
||||
adminService admin_service.Service
|
||||
adminService admin.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
adminService: admin_service.New(db, cache),
|
||||
adminService: admin.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,12 +1,11 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
@@ -23,7 +22,7 @@ type createResponse struct {
|
||||
// @Summary 新增调用方
|
||||
// @Description 新增调用方
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param business_key formData string true "调用方key"
|
||||
// @Param business_developer formData string true "调用方对接人"
|
||||
@@ -31,30 +30,31 @@ type createResponse struct {
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(authorized_service.CreateAuthorizedData)
|
||||
createData := new(authorized.CreateAuthorizedData)
|
||||
createData.BusinessKey = req.BusinessKey
|
||||
createData.BusinessDeveloper = req.BusinessDeveloper
|
||||
createData.Remark = req.Remark
|
||||
|
||||
id, err := h.authorizedService.Create(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedCreateError,
|
||||
code.Text(code.AuthorizedCreateError)).WithErr(err),
|
||||
code.Text(code.AuthorizedCreateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+14
-14
@@ -1,12 +1,11 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
)
|
||||
|
||||
type createAPIRequest struct {
|
||||
@@ -23,7 +22,7 @@ type createAPIResponse struct {
|
||||
// @Summary 授权调用方接口地址
|
||||
// @Description 授权调用方接口地址
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "HashID"
|
||||
// @Param method formData string true "请求方法"
|
||||
@@ -31,25 +30,26 @@ type createAPIResponse struct {
|
||||
// @Success 200 {object} createAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) CreateAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createAPIRequest)
|
||||
res := new(createAPIResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -59,25 +59,25 @@ func (h *handler) CreateAPI() core.HandlerFunc {
|
||||
// 通过 id 查询出 business_key
|
||||
authorizedInfo, err := h.authorizedService.Detail(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDetailError,
|
||||
code.Text(code.AuthorizedDetailError)).WithErr(err),
|
||||
code.Text(code.AuthorizedDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createAPIData := new(authorized_service.CreateAuthorizedAPIData)
|
||||
createAPIData := new(authorized.CreateAuthorizedAPIData)
|
||||
createAPIData.BusinessKey = authorizedInfo.BusinessKey
|
||||
createAPIData.Method = req.Method
|
||||
createAPIData.API = req.API
|
||||
|
||||
createId, err := h.authorizedService.CreateAPI(c, createAPIData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedCreateAPIError,
|
||||
code.Text(code.AuthorizedCreateAPIError)).WithErr(err),
|
||||
code.Text(code.AuthorizedCreateAPIError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
@@ -26,25 +25,26 @@ type deleteResponse struct {
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized/{id} [delete]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) Delete() core.HandlerFunc {
|
||||
|
||||
err = h.authorizedService.Delete(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDeleteError,
|
||||
code.Text(code.AuthorizedDeleteError)).WithErr(err),
|
||||
code.Text(code.AuthorizedDeleteError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteAPIRequest struct {
|
||||
@@ -26,25 +25,26 @@ type deleteAPIResponse struct {
|
||||
// @Success 200 {object} deleteAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api/{id} [delete]
|
||||
// @Security LoginToken
|
||||
func (h *handler) DeleteAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteAPIRequest)
|
||||
res := new(deleteAPIResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) DeleteAPI() core.HandlerFunc {
|
||||
|
||||
err = h.authorizedService.DeleteAPI(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDeleteAPIError,
|
||||
code.Text(code.AuthorizedDeleteAPIError)).WithErr(err),
|
||||
code.Text(code.AuthorizedDeleteAPIError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+19
-19
@@ -1,13 +1,12 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/timeutil"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -48,10 +47,10 @@ type listResponse struct {
|
||||
// @Summary 调用方列表
|
||||
// @Description 调用方列表
|
||||
// @Tags API.authorized
|
||||
// @Accept json
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param page query int true "第几页" default(1)
|
||||
// @Param page_size query int true "每页显示条数" default(10)
|
||||
// @Param business_key query string false "调用方key"
|
||||
// @Param business_secret query string false "调用方secret"
|
||||
// @Param business_developer query string false "调用方对接人"
|
||||
@@ -59,15 +58,16 @@ type listResponse struct {
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (h *handler) List() core.HandlerFunc {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(authorized_service.SearchData)
|
||||
searchData := new(authorized.SearchData)
|
||||
searchData.Page = page
|
||||
searchData.PageSize = pageSize
|
||||
searchData.BusinessKey = req.BusinessKey
|
||||
@@ -91,20 +91,20 @@ func (h *handler) List() core.HandlerFunc {
|
||||
|
||||
resListData, err := h.authorizedService.PageList(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListError,
|
||||
code.Text(code.AuthorizedListError)).WithErr(err),
|
||||
code.Text(code.AuthorizedListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.authorizedService.PageListCount(c, searchData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListError,
|
||||
code.Text(code.AuthorizedListError)).WithErr(err),
|
||||
code.Text(code.AuthorizedListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -116,10 +116,10 @@ func (h *handler) List() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -132,9 +132,9 @@ func (h *handler) List() core.HandlerFunc {
|
||||
BusinessDeveloper: v.BusinessDeveloper,
|
||||
Remark: v.Remark,
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
CreatedAt: v.CreatedAt.Format(timeutil.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedAt: v.UpdatedAt.Format(timeutil.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
+16
-16
@@ -1,12 +1,11 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -31,31 +30,32 @@ type listAPIResponse struct {
|
||||
// @Summary 调用方接口地址列表
|
||||
// @Description 调用方接口地址列表
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id query string true "hashID"
|
||||
// @Success 200 {object} listAPIResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized_api [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) ListAPI() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(listAPIRequest)
|
||||
res := new(listAPIResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -65,25 +65,25 @@ func (h *handler) ListAPI() core.HandlerFunc {
|
||||
// 通过 id 查询出 business_key
|
||||
authorizedInfo, err := h.authorizedService.Detail(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedDetailError,
|
||||
code.Text(code.AuthorizedDetailError)).WithErr(err),
|
||||
code.Text(code.AuthorizedDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.BusinessKey = authorizedInfo.BusinessKey
|
||||
|
||||
searchAPIData := new(authorized_service.SearchAPIData)
|
||||
searchAPIData := new(authorized.SearchAPIData)
|
||||
searchAPIData.BusinessKey = authorizedInfo.BusinessKey
|
||||
|
||||
resListData, err := h.authorizedService.ListAPI(c, searchAPIData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListAPIError,
|
||||
code.Text(code.AuthorizedListAPIError)).WithErr(err),
|
||||
code.Text(code.AuthorizedListAPIError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -93,10 +93,10 @@ func (h *handler) ListAPI() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+11
-11
@@ -1,11 +1,10 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
@@ -21,32 +20,33 @@ type updateUsedResponse struct {
|
||||
// @Summary 更新调用方为启用/禁用
|
||||
// @Description 更新调用方为启用/禁用
|
||||
// @Tags API.authorized
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param id formData string true "hashID"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/authorized/used [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -55,10 +55,10 @@ func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
|
||||
err = h.authorizedService.UpdateUsed(c, id, req.Used)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedUpdateError,
|
||||
code.Text(code.AuthorizedUpdateError)).WithErr(err),
|
||||
code.Text(code.AuthorizedUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+8
-8
@@ -1,11 +1,11 @@
|
||||
package authorized_handler
|
||||
package authorized
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/authorized_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -54,16 +54,16 @@ type Handler interface {
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
authorizedService authorized_service.Service
|
||||
cache redis.Repo
|
||||
authorizedService authorized.Service
|
||||
hashids hash.Hash
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
authorizedService: authorized_service.New(db, cache),
|
||||
authorizedService: authorized.New(db, cache),
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
}
|
||||
}
|
||||
+10
-14
@@ -1,14 +1,13 @@
|
||||
package config_handler
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/mail"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
@@ -31,7 +30,7 @@ type emailResponse struct {
|
||||
// @Summary 修改邮件配置
|
||||
// @Description 修改邮件配置
|
||||
// @Tags API.config
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param host formData string true "邮箱服务器"
|
||||
// @Param port formData string true "端口"
|
||||
@@ -41,15 +40,16 @@ type emailResponse struct {
|
||||
// @Success 200 {object} emailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/config/email [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Email() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(emailRequest)
|
||||
res := new(emailResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -64,18 +64,14 @@ func (h *handler) Email() core.HandlerFunc {
|
||||
Body: fmt.Sprintf("%s[%s] 已添加您为系统告警通知人。", configs.ProjectName, env.Active().Value()),
|
||||
}
|
||||
if err := mail.Send(options); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.SendEmailError,
|
||||
code.Text(code.SendEmailError)+err.Error()).WithErr(err),
|
||||
code.Text(code.SendEmailError)+err.Error()).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
|
||||
viper.Set("mail.host", req.Host)
|
||||
viper.Set("mail.port", cast.ToInt(req.Port))
|
||||
viper.Set("mail.user", req.User)
|
||||
@@ -84,10 +80,10 @@ func (h *handler) Email() core.HandlerFunc {
|
||||
|
||||
err := viper.WriteConfig()
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.WriteConfigError,
|
||||
code.Text(code.WriteConfigError)).WithErr(err),
|
||||
code.Text(code.WriteConfigError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package config_handler
|
||||
package config
|
||||
|
||||
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"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -21,10 +21,10 @@ type Handler interface {
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
cache redis.Repo
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
@@ -1,9 +0,0 @@
|
||||
## controller
|
||||
|
||||
控制器层。
|
||||
|
||||
主要接收参数、验证参数、调用 `service` 层的业务逻辑处理,最后返回数据。
|
||||
|
||||
命名规范:
|
||||
|
||||
- 包名以 `_handler` 结尾。
|
||||
@@ -1,79 +0,0 @@
|
||||
package admin_handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/admin_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/password"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type detailResponse struct {
|
||||
Username string `json:"username"` // 用户名
|
||||
Nickname string `json:"nickname"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
Menu []admin_service.ListMyMenuData `json:"menu"` // 菜单栏
|
||||
}
|
||||
|
||||
// Detail 管理员详情
|
||||
// @Summary 管理员详情
|
||||
// @Description 管理员详情
|
||||
// @Tags API.admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/info [get]
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
res := new(detailResponse)
|
||||
|
||||
searchOneData := new(admin_service.SearchOneData)
|
||||
searchOneData.Id = cast.ToInt32(c.UserID())
|
||||
searchOneData.IsUsed = 1
|
||||
|
||||
info, err := h.adminService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
menuCacheData, err := h.cache.Get(configs.RedisKeyPrefixLoginUser+password.GenerateLoginToken(searchOneData.Id)+":menu", cache.WithTrace(c.Trace()))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var menuData []admin_service.ListMyMenuData
|
||||
err = json.Unmarshal([]byte(menuCacheData), &menuData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AdminDetailError,
|
||||
code.Text(code.AdminDetailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Username = info.Username
|
||||
res.Nickname = info.Nickname
|
||||
res.Mobile = info.Mobile
|
||||
res.Menu = menuData
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -1,13 +1,12 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/cron"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
@@ -35,7 +34,7 @@ type createResponse struct {
|
||||
// @Summary 创建任务
|
||||
// @Description 创建任务
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param name formData string true "任务名称"
|
||||
// @Param spec formData string true "crontab 表达式"
|
||||
@@ -54,20 +53,21 @@ type createResponse struct {
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createData := new(cron_service.CreateCronTaskData)
|
||||
createData := new(cron.CreateCronTaskData)
|
||||
createData.Name = req.Name
|
||||
createData.Spec = req.Spec
|
||||
createData.Command = req.Command
|
||||
@@ -85,10 +85,10 @@ func (h *handler) Create() core.HandlerFunc {
|
||||
|
||||
id, err := h.cronService.Create(ctx, createData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronCreateError,
|
||||
code.Text(code.CronCreateError)).WithErr(err),
|
||||
code.Text(code.CronCreateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+12
-12
@@ -1,13 +1,12 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/cron"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -42,39 +41,40 @@ type detailResponse struct {
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/:id [get]
|
||||
// @Router /api/cron/{id} [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(detailRequest)
|
||||
res := new(detailResponse)
|
||||
if err := ctx.ShouldBindURI(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
searchOneData := new(cron_service.SearchOneData)
|
||||
searchOneData := new(cron.SearchOneData)
|
||||
searchOneData.Id = cast.ToInt32(ids[0])
|
||||
|
||||
info, err := h.cronService.Detail(ctx, searchOneData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronDetailError,
|
||||
code.Text(code.CronDetailError)).WithErr(err),
|
||||
code.Text(code.CronDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+10
-10
@@ -1,12 +1,11 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -28,36 +27,37 @@ type executeResponse struct {
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/:id [patch]
|
||||
// @Router /api/cron/exec/{id} [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Execute() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(executeRequest)
|
||||
res := new(executeResponse)
|
||||
if err := ctx.ShouldBindURI(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.cronService.Execute(ctx, cast.ToInt32(ids[0]))
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronExecuteError,
|
||||
code.Text(code.CronExecuteError)).WithErr(err),
|
||||
code.Text(code.CronExecuteError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+24
-24
@@ -1,15 +1,14 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/cron_task_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/time_parse"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql/cron_task"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/cron"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/timeutil"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -58,25 +57,26 @@ type listResponse struct {
|
||||
// @Summary 任务列表
|
||||
// @Description 任务列表
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param page query int false "第几页"
|
||||
// @Param page_size query string false "每页显示条数"
|
||||
// @Param page query int true "第几页" default(1)
|
||||
// @Param page_size query int true "每页显示条数" default(10)
|
||||
// @Param name query string false "任务名称"
|
||||
// @Param protocol query int false "执行方式 1:shell 2:http"
|
||||
// @Param is_used query int false "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(listRequest)
|
||||
res := new(listResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (h *handler) List() core.HandlerFunc {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
searchData := new(cron_service.SearchData)
|
||||
searchData := new(cron.SearchData)
|
||||
searchData.Page = req.Page
|
||||
searchData.PageSize = req.PageSize
|
||||
searchData.Name = req.Name
|
||||
@@ -100,20 +100,20 @@ func (h *handler) List() core.HandlerFunc {
|
||||
|
||||
resListData, err := h.cronService.PageList(ctx, searchData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronListError,
|
||||
code.Text(code.CronListError)).WithErr(err),
|
||||
code.Text(code.CronListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resCountData, err := h.cronService.PageListCount(ctx, searchData)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronListError,
|
||||
code.Text(code.CronListError)).WithErr(err),
|
||||
code.Text(code.CronListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -126,10 +126,10 @@ func (h *handler) List() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -139,21 +139,21 @@ func (h *handler) List() core.HandlerFunc {
|
||||
HashID: hashId,
|
||||
Name: v.Name,
|
||||
Protocol: cast.ToInt(v.Protocol),
|
||||
ProtocolText: cron_task_repo.ProtocolText[v.Protocol],
|
||||
ProtocolText: cron_task.ProtocolText[v.Protocol],
|
||||
Spec: v.Spec,
|
||||
Command: v.Command,
|
||||
HttpMethod: cast.ToInt(v.HttpMethod),
|
||||
HttpMethodText: cron_task_repo.HttpMethodText[v.HttpMethod],
|
||||
HttpMethodText: cron_task.HttpMethodText[v.HttpMethod],
|
||||
Timeout: cast.ToInt(v.Timeout),
|
||||
RetryTimes: cast.ToInt(v.RetryTimes),
|
||||
RetryInterval: cast.ToInt(v.RetryInterval),
|
||||
NotifyStatus: cast.ToInt(v.NotifyStatus),
|
||||
NotifyStatusText: cron_task_repo.NotifyStatusText[v.NotifyStatus],
|
||||
NotifyStatusText: cron_task.NotifyStatusText[v.NotifyStatus],
|
||||
IsUsed: cast.ToInt(v.IsUsed),
|
||||
IsUsedText: cron_task_repo.IsUsedText[v.IsUsed],
|
||||
CreatedAt: v.CreatedAt.Format(time_parse.CSTLayout),
|
||||
IsUsedText: cron_task.IsUsedText[v.IsUsed],
|
||||
CreatedAt: v.CreatedAt.Format(timeutil.CSTLayout),
|
||||
CreatedUser: v.CreatedUser,
|
||||
UpdatedAt: v.UpdatedAt.Format(time_parse.CSTLayout),
|
||||
UpdatedAt: v.UpdatedAt.Format(timeutil.CSTLayout),
|
||||
UpdatedUser: v.UpdatedUser,
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,12 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/cron"
|
||||
)
|
||||
|
||||
type modifyRequest struct {
|
||||
@@ -36,9 +35,9 @@ type modifyResponse struct {
|
||||
// @Summary 编辑任务
|
||||
// @Description 编辑任务
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param id formData string true "hashID"
|
||||
// @Param name formData string true "任务名称"
|
||||
// @Param spec formData string true "crontab 表达式"
|
||||
// @Param command formData string true "执行命令"
|
||||
@@ -56,32 +55,33 @@ type modifyResponse struct {
|
||||
// @Success 200 {object} modifyResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/{id} [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Modify() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(modifyRequest)
|
||||
res := new(modifyResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
modifyData := new(cron_service.ModifyCronTaskData)
|
||||
modifyData := new(cron.ModifyCronTaskData)
|
||||
modifyData.Name = req.Name
|
||||
modifyData.Spec = req.Spec
|
||||
modifyData.Command = req.Command
|
||||
@@ -98,10 +98,10 @@ func (h *handler) Modify() core.HandlerFunc {
|
||||
modifyData.IsUsed = req.IsUsed
|
||||
|
||||
if err := h.cronService.Modify(ctx, id, modifyData); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.CronUpdateError,
|
||||
code.Text(code.CronUpdateError)).WithErr(err),
|
||||
code.Text(code.CronUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+11
-11
@@ -1,12 +1,11 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/validation"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
@@ -22,32 +21,33 @@ type updateUsedResponse struct {
|
||||
// @Summary 更新任务为启用/禁用
|
||||
// @Description 更新任务为启用/禁用
|
||||
// @Tags API.cron
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param id formData string true "hashID"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/cron/used [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
validation.Error(err)).WithErr(err),
|
||||
validation.Error(err)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -56,10 +56,10 @@ func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
|
||||
err = h.cronService.UpdateUsed(ctx, id, req.Used)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(errno.NewError(
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AdminUpdateError,
|
||||
code.Text(code.AdminUpdateError)).WithErr(err),
|
||||
code.Text(code.AdminUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package cron_handler
|
||||
package cron
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/cron_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/cron/cron_server"
|
||||
"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"
|
||||
cronRepo "github.com/xinliangnote/go-gin-api/internal/repository/cron"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/cron"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -39,28 +39,28 @@ type Handler interface {
|
||||
|
||||
// Detail 获取单条任务详情
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron/:id [get]
|
||||
// @Router /api/cron/{id} [get]
|
||||
Detail() core.HandlerFunc
|
||||
|
||||
// Execute 手动执行任务
|
||||
// @Tags API.cron
|
||||
// @Router /api/cron/:id [patch]
|
||||
// @Router /api/cron/exec/{id} [patch]
|
||||
Execute() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
cache redis.Repo
|
||||
hashids hash.Hash
|
||||
cronService cron_service.Service
|
||||
cronService cron.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo, cron cron_server.Server) Handler {
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo, cronServer cronRepo.Server) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
cronService: cron_service.New(db, cache, cron),
|
||||
cronService: cron.New(db, cache, cronServer),
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type md5Request struct {
|
||||
Str string `uri:"str" binding:"required"` // 需要加密的字符串
|
||||
}
|
||||
|
||||
type md5Response struct {
|
||||
Md5Str string `json:"md5_str"` // MD5后的字符串
|
||||
}
|
||||
|
||||
// Md5 加密
|
||||
// @Summary 加密
|
||||
// @Description 加密
|
||||
// @Tags Helper
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param str path string true "需要加密的字符串"
|
||||
// @Success 200 {object} md5Response
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /helper/md5/{str} [get]
|
||||
func (h *handler) Md5() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(md5Request)
|
||||
res := new(md5Response)
|
||||
|
||||
if err := ctx.ShouldBindURI(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
m := md5.New()
|
||||
m.Write([]byte(req.Str))
|
||||
res.Md5Str = hex.EncodeToString(m.Sum(nil))
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errors"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/signature"
|
||||
)
|
||||
|
||||
type signRequest struct {
|
||||
Key string `form:"key" binding:"required"` // 调用方 KEY
|
||||
Path string `form:"path" binding:"required"` // 请求路径 (不附带 querystring),例如:/api/login
|
||||
Method string `form:"method" binding:"required"` // 请求方式,例如:POST
|
||||
Params string `form:"params" binding:"required"` // 请求参数,例如:username=tom&password=123456
|
||||
}
|
||||
|
||||
type signResponse struct {
|
||||
Authorization string `json:"authorization"` // 签名信息-Authorization
|
||||
AuthorizationDate string `json:"authorization_date"` // 签名信息-Authorization-Date
|
||||
}
|
||||
|
||||
// Sign 签名
|
||||
// @Summary 签名
|
||||
// @Description 签名
|
||||
// @Tags Helper
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param key formData string true "调用方 KEY"
|
||||
// @Param path formData string true "请求路径 (不附带 querystring),例如:/api/login"
|
||||
// @Param method formData string true "请求方式,例如:POST"
|
||||
// @Param params formData string true "请求参数,例如:username=tom&password=123456"
|
||||
// @Success 200 {object} signResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /helper/sign [post]
|
||||
func (h *handler) Sign() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(signRequest)
|
||||
res := new(signResponse)
|
||||
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
authorizedInfo, err := h.authorizedService.DetailByKey(ctx, req.Key)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if authorizedInfo.IsUsed == -1 {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithError(errors.New(req.Key + " 已被禁止调用")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(req.Params)
|
||||
|
||||
params, err := url.ParseQuery(req.Params)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
"params 传递格式不正确"),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
sign := signature.New(req.Key, authorizedInfo.Secret, configs.HeaderSignTokenTimeout)
|
||||
authorized, date, err := sign.Generate(req.Path, req.Method, params)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
"sign 生成失败"),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Authorization = authorized
|
||||
res.AuthorizationDate = date
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/authorized"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// Md5 加密
|
||||
// @Tags Helper
|
||||
// @Router /helper/md5/{str} [get]
|
||||
Md5() core.HandlerFunc
|
||||
|
||||
// Sign 签名
|
||||
// @Tags Helper
|
||||
// @Router /helper/sign [post]
|
||||
Sign() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
db mysql.Repo
|
||||
authorizedService authorized.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
db: db,
|
||||
authorizedService: authorized.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
+15
-15
@@ -1,12 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -28,21 +27,22 @@ type createResponse struct {
|
||||
// @Summary 创建/编辑菜单
|
||||
// @Description 创建/编辑菜单
|
||||
// @Tags API.menu
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param Request body createRequest true "请求信息"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu [post]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -50,27 +50,27 @@ func (h *handler) Create() core.HandlerFunc {
|
||||
if req.Id != "" { // 编辑功能
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
updateData := new(menu_service.UpdateMenuData)
|
||||
updateData := new(menu.UpdateMenuData)
|
||||
updateData.Name = req.Name
|
||||
updateData.Icon = req.Icon
|
||||
updateData.Link = req.Link
|
||||
|
||||
err = h.menuService.Modify(c, id, updateData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuUpdateError,
|
||||
code.Text(code.MenuUpdateError)).WithErr(err),
|
||||
code.Text(code.MenuUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (h *handler) Create() core.HandlerFunc {
|
||||
level = 1
|
||||
}
|
||||
|
||||
createData := new(menu_service.CreateMenuData)
|
||||
createData := new(menu.CreateMenuData)
|
||||
createData.Pid = pid
|
||||
createData.Name = req.Name
|
||||
createData.Icon = req.Icon
|
||||
@@ -97,10 +97,10 @@ func (h *handler) Create() core.HandlerFunc {
|
||||
|
||||
id, err := h.menuService.Create(c, createData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuCreateError,
|
||||
code.Text(code.MenuCreateError)).WithErr(err),
|
||||
code.Text(code.MenuCreateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+15
-15
@@ -1,12 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
)
|
||||
|
||||
type createActionRequest struct {
|
||||
@@ -23,7 +22,7 @@ type createActionResponse struct {
|
||||
// @Summary 创建功能权限
|
||||
// @Description 创建功能权限
|
||||
// @Tags API.menu
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "HashID"
|
||||
// @Param method formData string true "请求方法"
|
||||
@@ -31,54 +30,55 @@ type createActionResponse struct {
|
||||
// @Success 200 {object} createActionResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu_action [post]
|
||||
// @Security LoginToken
|
||||
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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
searchOneData := new(menu_service.SearchOneData)
|
||||
searchOneData := new(menu.SearchOneData)
|
||||
searchOneData.Id = id
|
||||
menuInfo, err := h.menuService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuDetailError,
|
||||
code.Text(code.MenuDetailError)).WithErr(err),
|
||||
code.Text(code.MenuDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createActionData := new(menu_service.CreateMenuActionData)
|
||||
createActionData := new(menu.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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuCreateActionError,
|
||||
code.Text(code.MenuCreateActionError)).WithErr(err),
|
||||
code.Text(code.MenuCreateActionError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
@@ -26,25 +25,26 @@ type deleteResponse struct {
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu/{id} [delete]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) Delete() core.HandlerFunc {
|
||||
|
||||
err = h.menuService.Delete(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuDeleteError,
|
||||
code.Text(code.MenuDeleteError)).WithErr(err),
|
||||
code.Text(code.MenuDeleteError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+9
-9
@@ -1,11 +1,10 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteActionRequest struct {
|
||||
@@ -26,25 +25,26 @@ type deleteActionResponse struct {
|
||||
// @Success 200 {object} deleteActionResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu_action/{id} [delete]
|
||||
// @Security LoginToken
|
||||
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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) DeleteAction() core.HandlerFunc {
|
||||
|
||||
err = h.menuService.DeleteAction(c, id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuDeleteActionError,
|
||||
code.Text(code.MenuDeleteActionError)).WithErr(err),
|
||||
code.Text(code.MenuDeleteActionError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+12
-12
@@ -1,12 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
)
|
||||
|
||||
type detailRequest struct {
|
||||
@@ -25,46 +24,47 @@ type detailResponse struct {
|
||||
// @Summary 菜单详情
|
||||
// @Description 菜单详情
|
||||
// @Tags API.menu
|
||||
// @Accept json
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id path string true "hashId"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu/{id} [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(detailRequest)
|
||||
res := new(detailResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
searchOneData := new(menu_service.SearchOneData)
|
||||
searchOneData := new(menu.SearchOneData)
|
||||
searchOneData.Id = id
|
||||
|
||||
info, err := h.menuService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuDetailError,
|
||||
code.Text(code.MenuDetailError)).WithErr(err),
|
||||
code.Text(code.MenuDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+10
-10
@@ -1,12 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -30,20 +29,21 @@ type listResponse struct {
|
||||
// @Summary 菜单列表
|
||||
// @Description 菜单列表
|
||||
// @Tags API.menu
|
||||
// @Accept json
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Success 200 {object} listResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu [get]
|
||||
// @Security LoginToken
|
||||
func (h *handler) List() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
res := new(listResponse)
|
||||
resListData, err := h.menuService.List(c, new(menu_service.SearchData))
|
||||
resListData, err := h.menuService.List(c, new(menu.SearchData))
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuListError,
|
||||
code.Text(code.MenuListError)).WithErr(err),
|
||||
code.Text(code.MenuListError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -53,10 +53,10 @@ func (h *handler) List() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+17
-17
@@ -1,12 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -31,61 +30,62 @@ type listActionResponse struct {
|
||||
// @Summary 功能权限列表
|
||||
// @Description 功能权限列表
|
||||
// @Tags API.menu
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id query string true "hashID"
|
||||
// @Success 200 {object} listActionResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu_action [get]
|
||||
// @Security LoginToken
|
||||
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(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
id := int32(ids[0])
|
||||
|
||||
searchOneData := new(menu_service.SearchOneData)
|
||||
searchOneData := new(menu.SearchOneData)
|
||||
searchOneData.Id = id
|
||||
|
||||
menuInfo, err := h.menuService.Detail(c, searchOneData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuDetailError,
|
||||
code.Text(code.MenuDetailError)).WithErr(err),
|
||||
code.Text(code.MenuDetailError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.MenuName = menuInfo.Name
|
||||
|
||||
searchListData := new(menu_service.SearchListActionData)
|
||||
searchListData := new(menu.SearchListActionData)
|
||||
searchListData.MenuId = menuInfo.Id
|
||||
|
||||
resListData, err := h.menuService.ListAction(c, searchListData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizedListAPIError,
|
||||
code.Text(code.AuthorizedListAPIError)).WithErr(err),
|
||||
code.Text(code.AuthorizedListAPIError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -95,10 +95,10 @@ func (h *handler) ListAction() core.HandlerFunc {
|
||||
for k, v := range resListData {
|
||||
hashId, err := h.hashids.HashidsEncode([]int{cast.ToInt(v.Id)})
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsEncodeError,
|
||||
code.Text(code.HashIdsEncodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsEncodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+11
-11
@@ -1,11 +1,10 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateSortRequest struct {
|
||||
@@ -21,32 +20,33 @@ type updateSortResponse struct {
|
||||
// @Summary 更新菜单排序
|
||||
// @Description 更新菜单排序
|
||||
// @Tags API.menu
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param id formData string true "hashId"
|
||||
// @Param sort formData int true "排序"
|
||||
// @Success 200 {object} updateSortResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu/sort [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) UpdateSort() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateSortRequest)
|
||||
res := new(updateSortResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -55,10 +55,10 @@ func (h *handler) UpdateSort() core.HandlerFunc {
|
||||
|
||||
err = h.menuService.UpdateSort(c, id, req.Sort)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuUpdateError,
|
||||
code.Text(code.MenuUpdateError)).WithErr(err),
|
||||
code.Text(code.MenuUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
+11
-11
@@ -1,11 +1,10 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateUsedRequest struct {
|
||||
@@ -21,32 +20,33 @@ type updateUsedResponse struct {
|
||||
// @Summary 更新菜单为启用/禁用
|
||||
// @Description 更新菜单为启用/禁用
|
||||
// @Tags API.menu
|
||||
// @Accept multipart/form-data
|
||||
// @Accept application/x-www-form-urlencoded
|
||||
// @Produce json
|
||||
// @Param id formData string true "Hashid"
|
||||
// @Param id formData string true "hashId"
|
||||
// @Param used formData int true "是否启用 1:是 -1:否"
|
||||
// @Success 200 {object} updateUsedResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/menu/used [patch]
|
||||
// @Security LoginToken
|
||||
func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateUsedRequest)
|
||||
res := new(updateUsedResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
code.Text(code.ParamBindError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := h.hashids.HashidsDecode(req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.HashIdsDecodeError,
|
||||
code.Text(code.HashIdsDecodeError)).WithErr(err),
|
||||
code.Text(code.HashIdsDecodeError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -55,10 +55,10 @@ func (h *handler) UpdateUsed() core.HandlerFunc {
|
||||
|
||||
err = h.menuService.UpdateUsed(c, id, req.Used)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
c.AbortWithError(core.Error(
|
||||
http.StatusBadRequest,
|
||||
code.MenuUpdateError,
|
||||
code.Text(code.MenuUpdateError)).WithErr(err),
|
||||
code.Text(code.MenuUpdateError)).WithError(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package menu_handler
|
||||
package menu
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/menu_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
|
||||
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
|
||||
"github.com/xinliangnote/go-gin-api/internal/services/menu"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/hash"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -64,17 +64,17 @@ type Handler interface {
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
cache redis.Repo
|
||||
hashids hash.Hash
|
||||
menuService menu_service.Service
|
||||
menuService menu.Service
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
func New(logger *zap.Logger, db mysql.Repo, cache redis.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
hashids: hash.New(configs.Get().HashIds.Secret, configs.Get().HashIds.Length),
|
||||
menuService: menu_service.New(db, cache),
|
||||
menuService: menu.New(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user