A simple admin ui without any functionalities

Signed-off-by: Yuan Si <do4suki@gmail.com>
This commit is contained in:
2023-04-26 08:50:16 +08:00
parent 75856025b4
commit e55b2ce7cd
24 changed files with 830 additions and 5 deletions
+5 -1
View File
@@ -6,7 +6,8 @@ require github.com/gin-gonic/gin v1.8.2
require ( require (
github.com/forgoer/openssl v1.5.0 github.com/forgoer/openssl v1.5.0
github.com/mattn/go-sqlite3 v1.14.16 github.com/gin-contrib/sessions v0.0.5
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/tidwall/gjson v1.14.4 github.com/tidwall/gjson v1.14.4
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978
xorm.io/xorm v1.3.2 xorm.io/xorm v1.3.2
@@ -14,6 +15,9 @@ require (
require ( require (
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/sessions v1.2.1 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
) )
+9 -2
View File
@@ -65,6 +65,8 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE=
github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
@@ -125,9 +127,14 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@@ -254,8 +261,8 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+61
View File
@@ -0,0 +1,61 @@
package handler
import (
"honoka-chan/model"
"net/http"
"github.com/forgoer/openssl"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)
func WebLogin(ctx *gin.Context) {
area := ctx.PostForm("area")
user := ctx.PostForm("user")
pass := ctx.PostForm("pass")
if area == "" || user == "" || pass == "" {
ctx.JSON(http.StatusOK, model.Msg{
Code: 1,
Message: "参数不完整!",
Redirect: "",
})
return
}
userName := " " + area + "-" + user
exists, err := UserEng.Table("users").Where("phone = ? AND password = ?", userName, openssl.Md5ToString(pass)).Exist()
CheckErr(err)
if !exists {
ctx.JSON(http.StatusOK, model.Msg{
Code: 1,
Message: "账号不存在或者密码有误!",
Redirect: "",
})
return
}
session := sessions.Default(ctx)
session.Options(sessions.Options{
MaxAge: 3600 * 24,
})
session.Set("username", userName)
session.Save()
ctx.JSON(http.StatusOK, model.Msg{
Code: 0,
Message: "登录成功!",
Redirect: "/admin/index",
})
}
func WebLogout(ctx *gin.Context) {
session := sessions.Default(ctx)
session.Clear()
session.Options(sessions.Options{
Path: "/admin",
MaxAge: -1,
})
session.Save()
ctx.Redirect(http.StatusFound, "/admin/login")
}
+45 -2
View File
@@ -6,7 +6,12 @@ import (
"honoka-chan/middleware" "honoka-chan/middleware"
_ "honoka-chan/tools" _ "honoka-chan/tools"
"net/http" "net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -18,7 +23,19 @@ func main() {
// Router // Router
r := gin.Default() r := gin.Default()
r.Static("/static", "static") r.Static("/static", "static")
r.LoadHTMLGlob("static/templates/**/*.html")
var files []string
filepath.Walk("static/templates", func(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(path, ".html") {
files = append(files, path)
}
return nil
})
r.LoadHTMLFiles(files...)
// session
store := cookie.NewStore([]byte("llsif"))
r.Use(sessions.Sessions("llsif", store))
// / // /
r.Any("/", func(ctx *gin.Context) { r.Any("/", func(ctx *gin.Context) {
@@ -96,11 +113,37 @@ func main() {
r.GET("/webview.php/announce/index", handler.AnnounceIndex) r.GET("/webview.php/announce/index", handler.AnnounceIndex)
// Server APIs // Server APIs
// Web
// Manga // Manga
r.GET("/manga", func(ctx *gin.Context) { r.GET("/manga", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "common/manga.html", gin.H{}) ctx.HTML(http.StatusOK, "common/manga.html", gin.H{})
}) })
// WebUI
w := r.Group("admin").Use(middleware.WebAuth)
{
w.GET("/index", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
"url": strings.Split(ctx.Request.URL.String(), "?")[0],
})
})
w.GET("/login", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "admin/login.html", gin.H{})
})
w.POST("/login", handler.WebLogin)
w.GET("/logout", handler.WebLogout)
w.GET("/card", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "admin/card.html", gin.H{
"menu": 1,
"url": strings.Split(ctx.Request.URL.String(), "?")[0],
})
})
w.GET("/deck", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "admin/card.html", gin.H{
"menu": 1,
"url": strings.Split(ctx.Request.URL.String(), "?")[0],
})
})
}
r.Run(":80") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080") r.Run(":80") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
} }
+28
View File
@@ -0,0 +1,28 @@
package middleware
import (
"net/http"
"strings"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)
func WebAuth(ctx *gin.Context) {
session := sessions.Default(ctx)
requestUrl := strings.Split(ctx.Request.URL.String(), "?")[0] // 过滤 GET 参数
_, ok := session.Get("username").(string)
if ok {
if requestUrl == "/admin/login" {
ctx.Redirect(http.StatusFound, "/admin/index")
ctx.Abort()
}
} else {
if requestUrl != "/admin/login" {
ctx.Redirect(http.StatusFound, "/admin/login")
ctx.Abort()
}
}
ctx.Next()
}
+7
View File
@@ -0,0 +1,7 @@
package model
type Msg struct {
Code int `json:"code"`
Message string `json:"message"`
Redirect string `json:"redirect"`
}
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
{{ define "admin/card.html" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>SIF 小助手</title>
{{ template "admin/nav/css.html" . }}
</head>
<body>
<div class="layui-layout layui-layout-admin">
{{ template "admin/nav/header.html" . }}
{{ template "admin/nav/side.html" . }}
<div class="layui-body">
<div style="padding: 15px;">{{ .url }}</div>
</div>
{{ template "admin/nav/footer.html" . }}
</div>
<script src="/static/js/layui.js"></script>
</body>
</html>
{{ end }}
+27
View File
@@ -0,0 +1,27 @@
{{ define "admin/deck.html" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>SIF 小助手</title>
{{ template "admin/nav/css.html" . }}
</head>
<body>
<div class="layui-layout layui-layout-admin">
{{ template "admin/nav/header.html" . }}
{{ template "admin/nav/side.html" . }}
<div class="layui-body">
<div style="padding: 15px;">{{ .url }}</div>
</div>
{{ template "admin/nav/footer.html" . }}
</div>
<script src="/static/js/layui.js"></script>
</body>
</html>
{{ end }}
+27
View File
@@ -0,0 +1,27 @@
{{ define "admin/index.html" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>SIF 小助手</title>
{{ template "admin/nav/css.html" . }}
</head>
<body>
<div class="layui-layout layui-layout-admin">
{{ template "admin/nav/header.html" . }}
{{ template "admin/nav/side.html" . }}
<div class="layui-body">
<div style="padding: 15px;">{{ .url }}</div>
</div>
{{ template "admin/nav/footer.html" . }}
</div>
<script src="/static/js/layui.js"></script>
</body>
</html>
{{ end }}
+113
View File
@@ -0,0 +1,113 @@
{{ define "admin/login.html" }}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SIF 小助手</title>
{{ template "admin/nav/css.html" . }}
<style>
body {
background: url("/static/images/admin/top-bg.jpg") no-repeat;
background-size: cover;
}
.login-btn {
margin-top: 1%;
border: 0px;
color: azure;
background: #e4007f;
}
.login-btn:hover {
color: aliceblue;
}
.layui-input {
width: 85%;
}
</style>
</head>
<body>
<div class="layui-container">
<button type="button" class="layui-btn layui-btn-lg layui-btn-primary layui-btn-radius login-btn">点击登录</button>
</div>
<script src="/static/js/layui.js"></script>
<script>
layui.use('layer', function () {
var $ = layui.$
, layer = layui.layer;
$(".login-btn").click(function () {
layer.open({
type: 1,
area: ['600px', '280px'],
title: "登录",
content: $('#login-form'),
shade: 0
})
})
$("#login-submit").click(function () {
let area = $("#area option:selected").val();
let user = $("#sifuser").val();
let pass = $("#sifpass").val();
console.log(area)
console.log(user)
console.log(pass)
$.post("/admin/login", { area: area, user: user, pass: pass }, function (data) {
if (data.code != 0) {
layer.msg(data.message)
return
}
layer.msg(data.message)
setTimeout(function () {
window.location.href = data.redirect;
}, 1500)
})
})
});
</script>
</body>
<div id="login-form" style="display: none; padding: 10px;">
<form class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">地区</label>
<div class="layui-input-block">
<select name="area" id="area" lay-verify="required">
<option value="86" selected>中国大陆(+86</option>
<option value="852">中国香港(+852</option>
<option value="853">中国澳门(+853</option>
<option value="886">中国台湾(+886</option>
<option value="1">美国(+1</option>
<option value="81">日本(+81</option>
<option value="82">韩国(+82</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">账号</label>
<div class="layui-input-block">
<input type="text" name="sifuser" id="sifuser" required lay-verify="required" placeholder="请输入账号"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码</label>
<div class="layui-input-block">
<input type="password" name="sifpass" id="sifpass" required lay-verify="required" placeholder="请输入密码"
autocomplete="off" class="layui-input">
</div>
</div>
</form>
<div class="layui-input-block">
<button class="layui-btn" id="login-submit">登录</button>
</div>
</div>
</html>
{{ end }}
+30
View File
@@ -0,0 +1,30 @@
{{ define "admin/nav/css.html" }}
<link rel="stylesheet" href="/static/css/layui.css">
<style>
.sif-title {
font-size: 1.3em;
color: aliceblue;
}
.layui-header {
background-color: #e4007f !important;
}
.layui-side {
background-color: #e4007f;
}
.layui-nav {
background-color: #e4007f;
}
.layui-nav-tree .layui-nav-child dd.layui-this,
.layui-nav-tree .layui-nav-child dd.layui-this a,
.layui-nav-tree .layui-this,
.layui-nav-tree .layui-this>a,
.layui-nav-tree .layui-this>a:hover {
background-color: #ff6699 !important;
}
</style>
{{ end }}
+5
View File
@@ -0,0 +1,5 @@
{{ define "admin/nav/footer.html" }}
<div class="layui-footer">
Copyright © 2023 YumeMichi
</div>
{{ end }}
+23
View File
@@ -0,0 +1,23 @@
{{ define "admin/nav/header.html" }}
<div class="layui-header">
<div class="layui-logo layui-hide-xs"><a href="/admin/index"><span class="sif-title">SIF
小助手</span></a></div>
<ul class="layui-nav layui-layout-left">
<li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
<i class="layui-icon layui-icon-spread-left"></i>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item layui-hide layui-show-md-inline-block">
<a href="javascript:;">
<img src="/static/images/admin/ic_launcher.png" class="layui-nav-img">
设置
</a>
<dl class="layui-nav-child">
<dd><a href="">个人信息</a></dd>
<dd><a href="/admin/logout">登出</a></dd>
</dl>
</li>
</ul>
</div>
{{ end }}
+16
View File
@@ -0,0 +1,16 @@
{{ define "admin/nav/side.html" }}
<div class="layui-side">
<div class="layui-side-scroll">
<ul class="layui-nav layui-nav-tree" lay-filter="test">
<li class="layui-nav-item {{ if eq .menu 1 }} layui-nav-itemed {{ end }}">
<a class="" href="javascript:;">卡片管理</a>
<dl class="layui-nav-child">
<dd {{ if eq .url "/admin/card" }} class="layui-this" {{ end }}><a href="/admin/card">卡片一览</a></dd>
<dd {{ if eq .url "/admin/deck" }} class="layui-this" {{ end }}><a href="/admin/deck">编队管理</a></dd>
</dd>
</dl>
</li>
</ul>
</div>
</div>
{{ end }}