upgrade
This commit is contained in:
@@ -41,10 +41,17 @@ const (
|
||||
AdminDeleteError = 20303
|
||||
AdminUpdateError = 20304
|
||||
AdminResetPasswordError = 20305
|
||||
AdminLoginError = 20307
|
||||
AdminLogOutError = 20308
|
||||
AdminModifyPasswordError = 20309
|
||||
AdminModifyPersonalInfoError = 20310
|
||||
AdminLoginError = 20306
|
||||
AdminLogOutError = 20307
|
||||
AdminModifyPasswordError = 20308
|
||||
AdminModifyPersonalInfoError = 20309
|
||||
|
||||
// 配置
|
||||
ConfigEmailError = 20401
|
||||
ConfigSaveError = 20402
|
||||
ConfigRedisConnectError = 20403
|
||||
ConfigMySQLConnectError = 20404
|
||||
ConfigMySQLInstallError = 20405
|
||||
)
|
||||
|
||||
var codeText = map[int]string{
|
||||
@@ -81,6 +88,12 @@ var codeText = map[int]string{
|
||||
AdminLogOutError: "退出失败",
|
||||
AdminModifyPasswordError: "修改密码失败",
|
||||
AdminModifyPersonalInfoError: "修改个人信息失败",
|
||||
|
||||
ConfigEmailError: "修改邮箱配置失败",
|
||||
ConfigSaveError: "写入配置文件失败",
|
||||
ConfigRedisConnectError: "Redis 连接失败",
|
||||
ConfigMySQLConnectError: "MySQL 连接失败",
|
||||
ConfigMySQLInstallError: "MySQL 初始化数据失败",
|
||||
}
|
||||
|
||||
func Text(code int) string {
|
||||
|
||||
98
internal/api/controller/config_handler/func_email.go
Executable file
98
internal/api/controller/config_handler/func_email.go
Executable file
@@ -0,0 +1,98 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/mail"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type emailRequest struct {
|
||||
Host string `form:"host"` // 邮箱服务器
|
||||
Port string `form:"port"` // 端口
|
||||
User string `form:"user"` // 发件人邮箱
|
||||
Pass string `form:"pass"` // 发件人密码
|
||||
To string `form:"to"` // 收件人邮箱地址,多个用,分割
|
||||
}
|
||||
|
||||
type emailResponse struct {
|
||||
Email string `json:"email"` // 邮箱地址
|
||||
}
|
||||
|
||||
// Email 修改邮件配置
|
||||
// @Summary 修改邮件配置
|
||||
// @Description 修改邮件配置
|
||||
// @Tags API.config
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param host formData string true "邮箱服务器"
|
||||
// @Param port formData string true "端口"
|
||||
// @Param user formData string true "发件人邮箱"
|
||||
// @Param pass formData string true "发件人密码"
|
||||
// @Param to formData string true "收件人邮箱地址,多个用,分割"
|
||||
// @Success 200 {object} emailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/config/email [patch]
|
||||
func (h *handler) Email() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(emailRequest)
|
||||
res := new(emailResponse)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
options := &mail.Options{
|
||||
MailHost: req.Host,
|
||||
MailPort: cast.ToInt(req.Port),
|
||||
MailUser: req.User,
|
||||
MailPass: req.Pass,
|
||||
MailTo: req.To,
|
||||
Subject: fmt.Sprintf("%s[%s] 邮箱告警人调整通知。", configs.ProjectName(), env.Active().Value()),
|
||||
Body: fmt.Sprintf("%s[%s] 已添加您为系统告警通知人。", configs.ProjectName(), env.Active().Value()),
|
||||
}
|
||||
if err := mail.Send(options); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigEmailError,
|
||||
"Mail Send error: "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
|
||||
viper.Set("mail.host", req.Host)
|
||||
viper.Set("mail.port", cast.ToInt(req.Port))
|
||||
viper.Set("mail.user", req.User)
|
||||
viper.Set("mail.pass", req.Pass)
|
||||
viper.Set("mail.to", req.To)
|
||||
|
||||
err := viper.WriteConfig()
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigEmailError,
|
||||
code.Text(code.ConfigEmailError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Email = req.To
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
34
internal/api/controller/config_handler/handler.go
Normal file
34
internal/api/controller/config_handler/handler.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
// Email 修改邮件配置
|
||||
// @Tags API.config
|
||||
// @Router /api/config/email [patch]
|
||||
Email() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,47 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/token"
|
||||
)
|
||||
|
||||
type authResponse struct {
|
||||
Authorization string `json:"authorization"` // 签名
|
||||
ExpireTime int64 `json:"expire_time"` // 过期时间
|
||||
}
|
||||
|
||||
// 获取授权信息
|
||||
// @Summary 获取授权信息
|
||||
// @Description 获取授权信息
|
||||
// @Tags Demo
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} authResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /auth/get [post]
|
||||
func (h *handler) Auth() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
cfg := configs.Get().JWT
|
||||
tokenString, err := token.New(cfg.Secret).JwtSign(1, "xinliangnote", time.Hour*cfg.ExpireDuration)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.AuthorizationError,
|
||||
code.Text(code.AuthorizationError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res := new(authResponse)
|
||||
res.Authorization = tokenString
|
||||
res.ExpireTime = time.Now().Add(time.Hour * cfg.ExpireDuration).Unix()
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (h *handler) Get() core.HandlerFunc {
|
||||
type request struct {
|
||||
Name string `uri:"name"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Name string `json:"name"`
|
||||
Job string `json:"job"`
|
||||
}
|
||||
|
||||
return func(c core.Context) {
|
||||
req := new(request)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "Tom" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.Name != Tom")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(&response{
|
||||
Name: "Tom",
|
||||
Job: "Student",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (h *handler) Post() core.HandlerFunc {
|
||||
type request struct {
|
||||
Name string `form:"name"`
|
||||
}
|
||||
|
||||
type response struct {
|
||||
Name string `json:"name"`
|
||||
Job string `json:"job"`
|
||||
}
|
||||
|
||||
return func(c core.Context) {
|
||||
req := new(request)
|
||||
if err := c.ShouldBindPostForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "Jack" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.Name != Jack")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(&response{
|
||||
Name: "Jack",
|
||||
Job: "Teacher",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/third_party_request/go_gin_api"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/httpclient"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/p"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type traceResponse []struct {
|
||||
Name string `json:"name"` //用户名
|
||||
Job string `json:"job"` //工作
|
||||
}
|
||||
|
||||
// Trace 示例
|
||||
// @Summary Trace 示例
|
||||
// @Description Trace 示例
|
||||
// @Tags Demo
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} traceResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /demo/trace [get]
|
||||
func (h *handler) Trace() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
// 三方请求信息
|
||||
res1, err := go_gin_api.DemoGet("Tom",
|
||||
httpclient.WithTTL(time.Second*5),
|
||||
httpclient.WithTrace(c.Trace()),
|
||||
httpclient.WithLogger(c.Logger()),
|
||||
httpclient.WithHeader("Authorization", c.GetHeader("Authorization")),
|
||||
httpclient.WithOnFailedRetry(3, time.Second*1, go_gin_api.DemoGetRetryVerify),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("get [demo/get] err", zap.Error(err))
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CallHTTPError,
|
||||
code.Text(code.CallHTTPError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
p.Println("res1.Name", res1.Name, p.WithTrace(c.Trace()))
|
||||
|
||||
// 三方请求信息
|
||||
res2, err := go_gin_api.DemoPost("Jack",
|
||||
httpclient.WithTTL(time.Second*5),
|
||||
httpclient.WithTrace(c.Trace()),
|
||||
httpclient.WithLogger(c.Logger()),
|
||||
httpclient.WithHeader("Authorization", c.GetHeader("Authorization")),
|
||||
httpclient.WithOnFailedRetry(3, time.Second*1, go_gin_api.DemoPostRetryVerify),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("post [demo/post] err", zap.Error(err))
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.CallHTTPError,
|
||||
code.Text(code.CallHTTPError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
p.Println("res2.Name",
|
||||
res2.Name,
|
||||
p.WithTrace(c.Trace()),
|
||||
)
|
||||
|
||||
// 执行 SQL 信息
|
||||
h.userService.GetUserByUserName(c, "test_user")
|
||||
|
||||
// 执行 Redis 信息
|
||||
_ = h.cache.Set("name", "tom", time.Minute*10, cache.WithTrace(c.Trace()))
|
||||
val, _ := h.cache.Get("name", cache.WithTrace(c.Trace()))
|
||||
p.Println("redis-name", val, p.WithTrace(c.Trace()))
|
||||
|
||||
// 初始化客户端
|
||||
// client := hello.NewHelloClient(d.grpConn.Conn())
|
||||
// client.SayHello(grpc.ContextWithValueAndTimeout(c, time.Second*3), &hello.HelloRequest{Name: "Hello World"})
|
||||
|
||||
data := &traceResponse{
|
||||
{
|
||||
Name: res1.Name,
|
||||
Job: res1.Job,
|
||||
},
|
||||
{
|
||||
Name: res2.Name,
|
||||
Job: res2.Job,
|
||||
},
|
||||
}
|
||||
c.Payload(data)
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package demo_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/grpc"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
// 示例:支持 get 请求的方法
|
||||
Get() core.HandlerFunc
|
||||
// 示例:支持 post 请求的方法
|
||||
Post() core.HandlerFunc
|
||||
|
||||
// 获取授权信息
|
||||
// @Tags Demo
|
||||
// @Router /auth/get [post]
|
||||
Auth() core.HandlerFunc
|
||||
|
||||
// Trace 示例
|
||||
// @Tags Demo
|
||||
// @Router /demo/trace [get]
|
||||
Trace() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
grpConn grpc.ClientConn
|
||||
userService user_service.UserService
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
grpConn: grpConn,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,77 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type createRequest struct {
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
type createResponse struct {
|
||||
Id int32 `json:"id"` // 主键ID
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
// @Summary 创建用户
|
||||
// @Description 创建用户
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Request body createRequest true "请求信息"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} createResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/create [post]
|
||||
func (h *handler) Create() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(createRequest)
|
||||
res := new(createResponse)
|
||||
if err := c.ShouldBindJSON(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if req.UserName == "" {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.IllegalUserName,
|
||||
code.Text(code.IllegalUserName)).WithErr(errors.New("req.UserName = ''")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
createUserData := new(user_service.CreateUserInfo)
|
||||
createUserData.Mobile = req.Mobile
|
||||
createUserData.NickName = req.NickName
|
||||
createUserData.UserName = req.UserName
|
||||
|
||||
id, err := h.userService.Create(c, createUserData)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserCreateError,
|
||||
code.Text(code.UserCreateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = id
|
||||
c.Payload(res)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type deleteRequest struct {
|
||||
Id int32 `uri:"id"` // 用户ID
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
// @Summary 删除用户
|
||||
// @Description 删除用户
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "用户ID"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} deleteResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/delete/{id} [patch]
|
||||
func (h *handler) Delete() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(deleteRequest)
|
||||
res := new(deleteResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.userService.Delete(c, req.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserUpdateError,
|
||||
code.Text(code.UserUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = req.Id
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/ddm"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type detailRequest struct {
|
||||
UserName string `uri:"username"` // 用户名
|
||||
}
|
||||
|
||||
type detailResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile ddm.Mobile `json:"mobile"` // 手机号(脱敏)
|
||||
}
|
||||
|
||||
// 用户详情
|
||||
// @Summary 用户详情
|
||||
// @Description 用户详情
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param username path string true "用户名"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} detailResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/info/{username} [get]
|
||||
func (h *handler) Detail() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(detailRequest)
|
||||
res := new(detailResponse)
|
||||
if err := c.ShouldBindURI(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.userService.GetUserByUserName(c, req.UserName)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserSearchError,
|
||||
code.Text(code.UserSearchError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = user.Id
|
||||
res.UserName = user.UserName
|
||||
res.NickName = user.NickName
|
||||
res.Mobile = ddm.Mobile(user.Mobile)
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
)
|
||||
|
||||
type updateNickNameByIDRequest struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
}
|
||||
|
||||
type updateNickNameByIDResponse struct {
|
||||
Id int32 `json:"id"` // 用户主键ID
|
||||
}
|
||||
|
||||
// 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Summary 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Description 编辑用户 - 通过用户主键ID更新用户昵称
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Request body updateNickNameByIDRequest true "请求信息"
|
||||
// @Param Authorization header string true "签名"
|
||||
// @Success 200 {object} updateNickNameByIDResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Failure 401 {object} code.Failure
|
||||
// @Router /user/update [put]
|
||||
func (h *handler) UpdateNickNameByID() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(updateNickNameByIDRequest)
|
||||
res := new(updateNickNameByIDResponse)
|
||||
if err := c.ShouldBindJSON(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.userService.UpdateNickNameByID(c, req.Id, req.NickName)
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.UserUpdateError,
|
||||
code.Text(code.UserUpdateError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
res.Id = req.Id
|
||||
|
||||
c.Payload(res)
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
|
||||
// Create 创建用户
|
||||
// @Tags User
|
||||
// @Router /user/create [post]
|
||||
Create() core.HandlerFunc
|
||||
|
||||
// UpdateNickNameByID 编辑用户 - 通过主键ID更新用户昵称
|
||||
// @Tags User
|
||||
// @Router /user/update [put]
|
||||
UpdateNickNameByID() core.HandlerFunc
|
||||
|
||||
// Delete 删除用户
|
||||
// @Tags User
|
||||
// @Router /user/delete/{id} [patch]
|
||||
Delete() core.HandlerFunc
|
||||
|
||||
// Detail 用户详情
|
||||
// @Tags User
|
||||
// @Router /user/info/{username} [get]
|
||||
Detail() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
userService user_service.UserService
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -1,15 +0,0 @@
|
||||
package user_demo_repo
|
||||
|
||||
import "time"
|
||||
|
||||
// 用户Demo表
|
||||
//go:generate gormgen -structs UserDemo -input .
|
||||
type UserDemo struct {
|
||||
Id int32 // 主键
|
||||
UserName string // 用户名
|
||||
NickName string // 昵称
|
||||
Mobile string // 手机号
|
||||
IsDeleted int32 // 是否删除 1:是 -1:否
|
||||
CreatedAt time.Time `gorm:"time"` // 创建时间
|
||||
UpdatedAt time.Time `gorm:"time"` // 更新时间
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#### go_gin_api.user_demo
|
||||
用户Demo表
|
||||
|
||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
||||
| 1 | id | 主键 | int(11) unsigned | PRI | NO | auto_increment | |
|
||||
| 2 | user_name | 用户名 | varchar(32) | | NO | | |
|
||||
| 3 | nick_name | 昵称 | varchar(100) | | NO | | |
|
||||
| 4 | mobile | 手机号 | varchar(20) | | NO | | |
|
||||
| 5 | is_deleted | 是否删除 1:是 -1:否 | tinyint(1) | | NO | | -1 |
|
||||
| 6 | created_at | 创建时间 | timestamp | | NO | | CURRENT_TIMESTAMP |
|
||||
| 7 | updated_at | 更新时间 | timestamp | | NO | on update CURRENT_TIMESTAMP | CURRENT_TIMESTAMP |
|
||||
@@ -1,411 +0,0 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// THIS FILE IS AUTO GENERATED by gormgen, DON'T EDIT IT //
|
||||
// ANY CHANGES DONE HERE WILL BE LOST //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
package user_demo_repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func NewModel() *UserDemo {
|
||||
return new(UserDemo)
|
||||
}
|
||||
|
||||
func NewQueryBuilder() *userDemoRepoQueryBuilder {
|
||||
return new(userDemoRepoQueryBuilder)
|
||||
}
|
||||
|
||||
func (t *UserDemo) Create(db *gorm.DB) (id int32, err error) {
|
||||
if err = db.Create(t).Error; err != nil {
|
||||
return 0, errors.Wrap(err, "create err")
|
||||
}
|
||||
return t.Id, nil
|
||||
}
|
||||
|
||||
func (t *UserDemo) Delete(db *gorm.DB) (err error) {
|
||||
if err = db.Delete(t).Error; err != nil {
|
||||
return errors.Wrap(err, "delete err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *UserDemo) Updates(db *gorm.DB, m map[string]interface{}) (err error) {
|
||||
if err = db.Model(&UserDemo{}).Where("id = ?", t.Id).Updates(m).Error; err != nil {
|
||||
return errors.Wrap(err, "updates err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type userDemoRepoQueryBuilder struct {
|
||||
order []string
|
||||
where []struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}
|
||||
limit int
|
||||
offset int
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) buildQuery(db *gorm.DB) *gorm.DB {
|
||||
ret := db
|
||||
for _, where := range qb.where {
|
||||
ret = ret.Where(where.prefix, where.value)
|
||||
}
|
||||
for _, order := range qb.order {
|
||||
ret = ret.Order(order)
|
||||
}
|
||||
ret = ret.Limit(qb.limit).Offset(qb.offset)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) Count(db *gorm.DB) (int64, error) {
|
||||
var c int64
|
||||
res := qb.buildQuery(db).Model(&UserDemo{}).Count(&c)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
c = 0
|
||||
}
|
||||
return c, res.Error
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) First(db *gorm.DB) (*UserDemo, error) {
|
||||
ret := &UserDemo{}
|
||||
res := qb.buildQuery(db).First(ret)
|
||||
if res.Error != nil && res.Error == gorm.ErrRecordNotFound {
|
||||
ret = nil
|
||||
}
|
||||
return ret, res.Error
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) QueryOne(db *gorm.DB) (*UserDemo, error) {
|
||||
qb.limit = 1
|
||||
ret, err := qb.QueryAll(db)
|
||||
if len(ret) > 0 {
|
||||
return ret[0], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) QueryAll(db *gorm.DB) ([]*UserDemo, error) {
|
||||
var ret []*UserDemo
|
||||
err := qb.buildQuery(db).Find(&ret).Error
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) Limit(limit int) *userDemoRepoQueryBuilder {
|
||||
qb.limit = limit
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) Offset(offset int) *userDemoRepoQueryBuilder {
|
||||
qb.offset = offset
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereId(p db_repo.Predicate, value int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIdIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIdNotIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "id", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderById(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "id "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserName(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserNameIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUserNameNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "user_name", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByUserName(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "user_name "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickName(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickNameIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereNickNameNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "nick_name", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByNickName(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "nick_name "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobile(p db_repo.Predicate, value string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobileIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereMobileNotIn(value []string) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "mobile", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByMobile(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "mobile "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeleted(p db_repo.Predicate, value int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeletedIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereIsDeletedNotIn(value []int32) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "is_deleted", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByIsDeleted(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "is_deleted "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAt(p db_repo.Predicate, value time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAtIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereCreatedAtNotIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "created_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByCreatedAt(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "created_at "+order)
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAt(p db_repo.Predicate, value time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", p),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAtIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) WhereUpdatedAtNotIn(value []time.Time) *userDemoRepoQueryBuilder {
|
||||
qb.where = append(qb.where, struct {
|
||||
prefix string
|
||||
value interface{}
|
||||
}{
|
||||
fmt.Sprintf("%v %v ?", "updated_at", "NOT IN"),
|
||||
value,
|
||||
})
|
||||
return qb
|
||||
}
|
||||
|
||||
func (qb *userDemoRepoQueryBuilder) OrderByUpdatedAt(asc bool) *userDemoRepoQueryBuilder {
|
||||
order := "DESC"
|
||||
if asc {
|
||||
order = "ASC"
|
||||
}
|
||||
|
||||
qb.order = append(qb.order, "updated_at "+order)
|
||||
return qb
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
|
||||
)
|
||||
|
||||
var _ UserService = (*userSer)(nil)
|
||||
|
||||
type UserService interface {
|
||||
// i 为了避免被其他包实现
|
||||
i()
|
||||
|
||||
Create(ctx core.Context, user *CreateUserInfo) (id int32, err error)
|
||||
UpdateNickNameByID(ctx core.Context, id int32, username string) (err error)
|
||||
GetUserByUserName(ctx core.Context, username string) (user *user_demo_repo.UserDemo, err error)
|
||||
Delete(ctx core.Context, id int32) (err error)
|
||||
}
|
||||
|
||||
type userSer struct {
|
||||
db db.Repo
|
||||
cache cache.Repo
|
||||
}
|
||||
|
||||
func NewUserService(db db.Repo, cache cache.Repo) UserService {
|
||||
return &userSer{
|
||||
db: db,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *userSer) i() {}
|
||||
@@ -1,25 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
type CreateUserInfo struct {
|
||||
UserName string `json:"user_name"` // 用户名
|
||||
NickName string `json:"nick_name"` // 昵称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
}
|
||||
|
||||
func (u *userSer) Create(ctx core.Context, user *CreateUserInfo) (id int32, err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.UserName = user.UserName
|
||||
model.NickName = user.NickName
|
||||
model.Mobile = user.Mobile
|
||||
|
||||
id, err = model.Create(u.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) Delete(ctx core.Context, id int32) (err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.Id = id
|
||||
err = model.Delete(u.db.GetDbW().WithContext(ctx.RequestContext()))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) GetUserByUserName(ctx core.Context, username string) (user *user_demo_repo.UserDemo, err error) {
|
||||
user, err = user_demo_repo.NewQueryBuilder().
|
||||
WhereUserName(db_repo.EqualPredicate, username).
|
||||
QueryOne(u.db.GetDbR().WithContext(ctx.RequestContext()))
|
||||
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
user = user_demo_repo.NewModel()
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package user_service
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/repository/db_repo/user_demo_repo"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (u *userSer) UpdateNickNameByID(ctx core.Context, id int32, nickname string) (err error) {
|
||||
model := user_demo_repo.NewModel()
|
||||
model.Id = id
|
||||
|
||||
data := map[string]interface{}{
|
||||
"nick_name": nickname,
|
||||
}
|
||||
|
||||
err = model.Updates(u.db.GetDbW().WithContext(ctx.RequestContext()), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package resolvers
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
|
||||
"github.com/xinliangnote/go-gin-api/internal/graph/generated"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
@@ -21,17 +20,17 @@ type mutationResolver struct{ *Resolver }
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
type Resolver struct {
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
userService user_service.UserService
|
||||
logger *zap.Logger
|
||||
cache cache.Repo
|
||||
//userService user_service.UserService
|
||||
}
|
||||
|
||||
func NewRootResolvers(logger *zap.Logger, db db.Repo, cache cache.Repo) generated.Config {
|
||||
c := generated.Config{
|
||||
Resolvers: &Resolver{
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
userService: user_service.NewUserService(db, cache),
|
||||
logger: logger,
|
||||
cache: cache,
|
||||
//userService: user_service.NewUserService(db, cache),
|
||||
},
|
||||
}
|
||||
return c
|
||||
|
||||
@@ -24,18 +24,49 @@ type resource struct {
|
||||
middles middleware.Middleware
|
||||
}
|
||||
|
||||
func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) (core.Mux, error) {
|
||||
var openBrowserUri = "http://127.0.0.1:9999"
|
||||
|
||||
_, ok := file.IsExists(configs.InitDBLockFile())
|
||||
if !ok {
|
||||
openBrowserUri = "http://127.0.0.1:9999/init?init=db"
|
||||
}
|
||||
type Server struct {
|
||||
Mux core.Mux
|
||||
Db db.Repo
|
||||
Cache cache.Repo
|
||||
GrpClient grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewHTTPServer(logger *zap.Logger) (*Server, error) {
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger required")
|
||||
}
|
||||
|
||||
r := new(resource)
|
||||
r.logger = logger
|
||||
|
||||
openBrowserUri := "http://127.0.0.1" + configs.ProjectPort()
|
||||
|
||||
_, ok := file.IsExists(configs.ProjectInstallFile())
|
||||
if !ok { // 未安装
|
||||
openBrowserUri += "/install"
|
||||
} else { // 已安装
|
||||
// 初始化 DB
|
||||
dbRepo, err := db.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new db err", zap.Error(err))
|
||||
}
|
||||
r.db = dbRepo
|
||||
|
||||
// 初始化 Cache
|
||||
cacheRepo, err := cache.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new cache err", zap.Error(err))
|
||||
}
|
||||
r.cache = cacheRepo
|
||||
|
||||
// 初始化 gRPC client
|
||||
gRPCRepo, err := grpc.New()
|
||||
if err != nil {
|
||||
logger.Fatal("new grpc err", zap.Error(err))
|
||||
}
|
||||
r.grpConn = gRPCRepo
|
||||
}
|
||||
|
||||
mux, err := core.New(logger,
|
||||
core.WithEnableOpenBrowser(openBrowserUri),
|
||||
core.WithEnableCors(),
|
||||
@@ -48,13 +79,8 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.C
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r := new(resource)
|
||||
r.mux = mux
|
||||
r.logger = logger
|
||||
r.db = db
|
||||
r.cache = cache
|
||||
r.grpConn = grpConn
|
||||
r.middles = middleware.New(logger, cache, db)
|
||||
r.middles = middleware.New(logger, r.cache, r.db)
|
||||
|
||||
// 设置 WEB 路由
|
||||
setWebRouter(r)
|
||||
@@ -65,5 +91,11 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.C
|
||||
// 设置 GraphQL 路由
|
||||
setGraphQLRouter(r)
|
||||
|
||||
return mux, nil
|
||||
s := new(Server)
|
||||
s.Mux = mux
|
||||
s.Db = r.db
|
||||
s.Cache = r.cache
|
||||
s.GrpClient = r.grpConn
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -3,47 +3,17 @@ package router
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/demo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/tool_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func setApiRouter(r *resource) {
|
||||
// demo 控制器
|
||||
demoHandler := demo_handler.New(r.logger, r.db, r.cache, r.grpConn)
|
||||
demo := r.mux.Group("/demo", core.WrapAuthHandler(r.middles.Jwt)) // 使用 jwt 验证
|
||||
{
|
||||
// 为了演示 Trace ,增加了一些看起来无意义的调试信息和 SQL 信息。
|
||||
demo.GET("/trace", demoHandler.Trace())
|
||||
|
||||
// 模拟数据
|
||||
demo.GET("get/:name", core.AliasForRecordMetrics("/demo/get"), demoHandler.Get())
|
||||
demo.POST("post", demoHandler.Post())
|
||||
}
|
||||
|
||||
demoNoAuth := r.mux.Group("/auth") // 不使用 jwt 验证
|
||||
{
|
||||
demoNoAuth.POST("/get", demoHandler.Auth())
|
||||
}
|
||||
|
||||
// user 控制器
|
||||
userHandler := user_handler.New(r.logger, r.db, r.cache)
|
||||
user := r.mux.Group("/user", core.WrapAuthHandler(r.middles.Jwt))
|
||||
{
|
||||
user.POST("/create", userHandler.Create())
|
||||
user.PUT("/update", userHandler.UpdateNickNameByID())
|
||||
user.PATCH("/delete/:id", userHandler.Delete())
|
||||
user.GET("/info/:username", core.AliasForRecordMetrics("/user/info"), userHandler.Detail())
|
||||
}
|
||||
|
||||
// authorized
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// admin
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
// 登录
|
||||
// login
|
||||
login := r.mux.Group("/login", r.middles.Signature())
|
||||
{
|
||||
login.POST("/web", adminHandler.Login())
|
||||
@@ -52,14 +22,16 @@ func setApiRouter(r *resource) {
|
||||
// api
|
||||
api := r.mux.Group("/api", core.WrapAuthHandler(r.middles.Token), r.middles.Signature())
|
||||
{
|
||||
// authorized
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
api.POST("/authorized", authorizedHandler.Create())
|
||||
api.GET("/authorized", authorizedHandler.List())
|
||||
api.PATCH("/authorized/used", authorizedHandler.UpdateUsed())
|
||||
api.DELETE("/authorized/:id", authorizedHandler.Delete())
|
||||
api.DELETE("/authorized/:id", core.AliasForRecordMetrics("/api/authorized/info"), authorizedHandler.Delete())
|
||||
|
||||
api.POST("/authorized_api", authorizedHandler.CreateAPI())
|
||||
api.GET("/authorized_api", authorizedHandler.ListAPI())
|
||||
api.DELETE("/authorized_api/:id", authorizedHandler.DeleteAPI())
|
||||
api.DELETE("/authorized_api/:id", core.AliasForRecordMetrics("/api/authorized_api/info"), authorizedHandler.DeleteAPI())
|
||||
|
||||
api.POST("/admin", adminHandler.Create())
|
||||
api.GET("/admin", adminHandler.List())
|
||||
@@ -75,5 +47,10 @@ func setApiRouter(r *resource) {
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
api.GET("/tool/hashids/encode/:id", toolHandler.HashIdsEncode())
|
||||
api.GET("/tool/hashids/decode/:id", toolHandler.HashIdsDecode())
|
||||
|
||||
// config
|
||||
configHandler := config_handler.New(r.logger, r.db, r.cache)
|
||||
api.PATCH("/config/email", configHandler.Email())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,38 +3,43 @@ package router
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/admin_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/authorized_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/configinfo_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/config_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/gencode_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/index_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/install_handler"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/tool_handler"
|
||||
)
|
||||
|
||||
func setWebRouter(r *resource) {
|
||||
|
||||
installHandler := install_handler.New(r.logger)
|
||||
indexHandler := index_handler.New(r.logger, r.db, r.cache)
|
||||
dashboardHandler := dashboard_handler.New(r.logger, r.db, r.cache)
|
||||
genCodeHandler := gencode_handler.New(r.logger, r.db, r.cache)
|
||||
configInfoHandler := configinfo_handler.New(r.logger, r.db, r.cache)
|
||||
configInfoHandler := config_handler.New(r.logger, r.db, r.cache)
|
||||
authorizedHandler := authorized_handler.New(r.logger, r.db, r.cache)
|
||||
toolHandler := tool_handler.New(r.logger, r.db, r.cache)
|
||||
adminHandler := admin_handler.New(r.logger, r.db, r.cache)
|
||||
|
||||
web := r.mux.Group("", r.middles.DisableLog())
|
||||
{
|
||||
// 首页侧边栏
|
||||
// 首页
|
||||
web.GET("", indexHandler.View())
|
||||
|
||||
// 安装
|
||||
web.GET("/install", installHandler.View())
|
||||
web.POST("/install/execute", installHandler.Execute())
|
||||
web.POST("/install/restart", installHandler.Restart())
|
||||
|
||||
// 仪表盘
|
||||
web.GET("/dashboard", dashboardHandler.View())
|
||||
|
||||
// 配置信息
|
||||
web.GET("/configinfo", configInfoHandler.View())
|
||||
|
||||
// 代码生成
|
||||
web.GET("/init", genCodeHandler.InitView())
|
||||
web.POST("/init_exec", genCodeHandler.InitExecute())
|
||||
web.GET("/config/email", configInfoHandler.EmailView())
|
||||
web.GET("/config/code", configInfoHandler.CodeView())
|
||||
|
||||
// 代码生成工具
|
||||
web.GET("/gormgen", genCodeHandler.GormView())
|
||||
web.POST("/gormgen_exec", genCodeHandler.GormExecute())
|
||||
|
||||
|
||||
56
internal/web/controller/config_handler/func_codeview.go
Normal file
56
internal/web/controller/config_handler/func_codeview.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"log"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"github.com/dave/dst"
|
||||
"github.com/dave/dst/decorator"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func (h *handler) CodeView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
fs := token.NewFileSet()
|
||||
filePath := "./internal/api/code/code.go"
|
||||
parsedFile, err := decorator.ParseFile(fs, filePath, nil, 0)
|
||||
if err != nil {
|
||||
log.Fatalf("parsing package: %s: %s\n", filePath, err)
|
||||
}
|
||||
|
||||
type codes struct {
|
||||
Code int `json:"code"` // 错误码
|
||||
Message string `json:"message"` // 错误码信息
|
||||
}
|
||||
|
||||
var constCodes []codes
|
||||
|
||||
dst.Inspect(parsedFile, func(n dst.Node) bool {
|
||||
decl, ok := n.(*dst.GenDecl)
|
||||
if !ok || decl.Tok != token.CONST {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, spec := range decl.Specs {
|
||||
valueSpec, _ok := spec.(*dst.ValueSpec)
|
||||
if !_ok {
|
||||
continue
|
||||
}
|
||||
|
||||
codeInt := cast.ToInt(valueSpec.Values[0].(*dst.BasicLit).Value)
|
||||
|
||||
constCodes = append(constCodes, codes{
|
||||
Code: codeInt,
|
||||
Message: code.Text(codeInt),
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
c.HTML("config_code", constCodes)
|
||||
}
|
||||
}
|
||||
12
internal/web/controller/config_handler/func_emailview.go
Normal file
12
internal/web/controller/config_handler/func_emailview.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) EmailView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("config_email", configs.Get())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package configinfo_handler
|
||||
package config_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
|
||||
@@ -13,7 +13,8 @@ var _ Handler = (*handler)(nil)
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
View() core.HandlerFunc
|
||||
EmailView() core.HandlerFunc
|
||||
CodeView() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
@@ -25,10 +26,12 @@ func (h *handler) GormExecute() core.HandlerFunc {
|
||||
mysqlConf := configs.Get().MySQL.Read
|
||||
shellPath := fmt.Sprintf("./scripts/gormgen.sh %s %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name, req.Tables)
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
@@ -21,10 +22,13 @@ func (h *handler) HandlerExecute() core.HandlerFunc {
|
||||
}
|
||||
|
||||
shellPath := fmt.Sprintf("./scripts/handlergen.sh %s", req.Name)
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package gencode_handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) InitExecute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
mysqlConf := configs.Get().MySQL.Read
|
||||
shellPath := fmt.Sprintf("./scripts/init.sh %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name)
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
|
||||
|
||||
// windows 版本
|
||||
//command := exec.Command("cmd", "/C", shellPath)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
c.Payload(stderr.String())
|
||||
return
|
||||
}
|
||||
|
||||
c.Payload(string(output))
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package gencode_handler
|
||||
|
||||
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
func (h *handler) InitView() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("gencode_init", nil)
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,6 @@ var _ Handler = (*handler)(nil)
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
InitView() core.HandlerFunc
|
||||
InitExecute() core.HandlerFunc
|
||||
|
||||
HandlerView() core.HandlerFunc
|
||||
HandlerExecute() core.HandlerFunc
|
||||
|
||||
|
||||
204
internal/web/controller/install_handler/func_execute.go
Normal file
204
internal/web/controller/install_handler/func_execute.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
"github.com/xinliangnote/go-gin-api/internal/api/code"
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
"github.com/xinliangnote/go-gin-api/internal/web/controller/install_handler/mysql_table"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/env"
|
||||
"github.com/xinliangnote/go-gin-api/pkg/errno"
|
||||
|
||||
"github.com/go-redis/redis/v7"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/viper"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
type initExecuteRequest struct {
|
||||
RedisAddr string `form:"redis_addr"` // 连接地址,例如:127.0.0.1:6379
|
||||
RedisPass string `form:"redis_pass"` // 连接密码
|
||||
RedisDb string `form:"redis_db"` // 连接 db
|
||||
|
||||
MySQLAddr string `form:"mysql_addr"`
|
||||
MySQLUser string `form:"mysql_user"`
|
||||
MySQLPass string `form:"mysql_pass"`
|
||||
MySQLName string `form:"mysql_name"`
|
||||
}
|
||||
|
||||
func (h *handler) Execute() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
req := new(initExecuteRequest)
|
||||
if err := c.ShouldBindForm(req); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ParamBindError,
|
||||
code.Text(code.ParamBindError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString := ""
|
||||
|
||||
cfg := configs.Get()
|
||||
redisClient := redis.NewClient(&redis.Options{
|
||||
Addr: req.RedisAddr,
|
||||
Password: req.RedisPass,
|
||||
DB: cast.ToInt(req.RedisDb),
|
||||
MaxRetries: cfg.Redis.MaxRetries,
|
||||
PoolSize: cfg.Redis.PoolSize,
|
||||
MinIdleConns: cfg.Redis.MinIdleConns,
|
||||
})
|
||||
|
||||
if err := redisClient.Ping().Err(); err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigRedisConnectError,
|
||||
code.Text(code.ConfigRedisConnectError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
defer redisClient.Close()
|
||||
|
||||
outPutString += "已检测 Redis 配置可用。\n"
|
||||
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
|
||||
req.MySQLUser,
|
||||
req.MySQLPass,
|
||||
req.MySQLAddr,
|
||||
req.MySQLName,
|
||||
true,
|
||||
"Local")
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true,
|
||||
},
|
||||
//Logger: logger.Default.LogMode(logger.Info), // 日志配置
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLConnectError,
|
||||
code.Text(code.ConfigMySQLConnectError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
db.Set("gorm:table_options", "CHARSET=utf8mb4")
|
||||
|
||||
dbClient, _ := db.DB()
|
||||
defer dbClient.Close()
|
||||
|
||||
outPutString += "已检测 MySQL 配置可用。\n"
|
||||
|
||||
viper.SetConfigName(env.Active().Value() + "_configs")
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath("./configs")
|
||||
viper.Set("redis.addr", req.RedisAddr)
|
||||
viper.Set("redis.pass", req.RedisPass)
|
||||
viper.Set("redis.db", req.RedisDb)
|
||||
|
||||
viper.Set("mysql.read.addr", req.MySQLAddr)
|
||||
viper.Set("mysql.read.user", req.MySQLUser)
|
||||
viper.Set("mysql.read.pass", req.MySQLPass)
|
||||
viper.Set("mysql.read.name", req.MySQLName)
|
||||
|
||||
viper.Set("mysql.write.addr", req.MySQLAddr)
|
||||
viper.Set("mysql.write.user", req.MySQLUser)
|
||||
viper.Set("mysql.write.pass", req.MySQLPass)
|
||||
viper.Set("mysql.write.name", req.MySQLName)
|
||||
|
||||
if viper.WriteConfig() != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigSaveError,
|
||||
code.Text(code.ConfigSaveError)).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += "配置项 Redis、MySQL 配置成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedAPITableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized_api 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAuthorizedAPITableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:authorized_api 默认数据成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminTableSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin 成功。\n"
|
||||
|
||||
if err = db.Exec(mysql_table.CreateAdminTableDataSql()).Error; err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"MySQL "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
outPutString += "初始化 MySQL 数据表:admin 默认数据成功。\n"
|
||||
|
||||
// 生成 install 完成标识
|
||||
f, err := os.Create(configs.ProjectInstallFile())
|
||||
if err != nil {
|
||||
c.AbortWithError(errno.NewError(
|
||||
http.StatusBadRequest,
|
||||
code.ConfigMySQLInstallError,
|
||||
"create lock file err: "+err.Error()).WithErr(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
c.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
37
internal/web/controller/install_handler/func_restart.go
Normal file
37
internal/web/controller/install_handler/func_restart.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
)
|
||||
|
||||
func (h *handler) Restart() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
shellPath := "./scripts/restart.sh"
|
||||
|
||||
// runtime.GOOS = linux or darwin
|
||||
command := exec.Command("/bin/bash", "-c", shellPath)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
command = exec.Command("cmd", "/C", shellPath)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
outPutString := ""
|
||||
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
outPutString += stderr.String()
|
||||
c.Payload(outPutString)
|
||||
return
|
||||
}
|
||||
|
||||
outPutString += string(output)
|
||||
|
||||
c.Payload(outPutString)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package configinfo_handler
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/configs"
|
||||
@@ -7,6 +7,6 @@ import (
|
||||
|
||||
func (h *handler) View() core.HandlerFunc {
|
||||
return func(c core.Context) {
|
||||
c.HTML("configinfo", configs.Get())
|
||||
c.HTML("install_view", configs.Get())
|
||||
}
|
||||
}
|
||||
29
internal/web/controller/install_handler/handler.go
Normal file
29
internal/web/controller/install_handler/handler.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package install_handler
|
||||
|
||||
import (
|
||||
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var _ Handler = (*handler)(nil)
|
||||
|
||||
type Handler interface {
|
||||
i()
|
||||
|
||||
View() core.HandlerFunc
|
||||
Execute() core.HandlerFunc
|
||||
Restart() core.HandlerFunc
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func New(logger *zap.Logger) Handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) i() {}
|
||||
@@ -0,0 +1,44 @@
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `admin` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
//`password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
|
||||
//`nickname` varchar(60) NOT NULL DEFAULT '' COMMENT '昵称',
|
||||
//`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
//`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`),
|
||||
//UNIQUE KEY `unique_username` (`username`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
|
||||
|
||||
func CreateAdminTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `admin` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',"
|
||||
sql += "`password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',"
|
||||
sql += "`nickname` varchar(60) NOT NULL DEFAULT '' COMMENT '昵称',"
|
||||
sql += "`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',"
|
||||
sql += "`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`),"
|
||||
sql += "UNIQUE KEY `unique_username` (`username`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAdminTableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `admin` (`id`, `username`, `password`, `nickname`, `mobile`, `created_user`) VALUES"
|
||||
sql += "(1, 'admin', 'f78382de80cf583cf854bbac0b6e796fbde36fe2739ca4ae072637010f179cb0', '管理员', '13888888888', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `authorized` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`business_key` varchar(32) NOT NULL DEFAULT '' COMMENT '调用方key',
|
||||
//`business_secret` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方secret',
|
||||
//`business_developer` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方对接人',
|
||||
//`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
|
||||
//`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`),
|
||||
//UNIQUE KEY `unique_business_key` (`business_key`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';
|
||||
|
||||
func CreateAuthorizedTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `authorized` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`business_key` varchar(32) NOT NULL DEFAULT '' COMMENT '调用方key',"
|
||||
sql += "`business_secret` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方secret',"
|
||||
sql += "`business_developer` varchar(60) NOT NULL DEFAULT '' COMMENT '调用方对接人',"
|
||||
sql += "`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',"
|
||||
sql += "`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 1:是 -1:否',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`),"
|
||||
sql += "UNIQUE KEY `unique_business_key` (`business_key`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权的调用方表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAuthorizedTableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `authorized` (`id`, `business_key`, `business_secret`, `business_developer`, `remark`, `created_user`) VALUES (1, 'admin', '12878dd962115106db6d', '管理员', '管理面板调用', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `authorized_api` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`business_key` varchar(30) NOT NULL DEFAULT '' COMMENT '调用方key',
|
||||
//`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',
|
||||
//`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',
|
||||
//PRIMARY KEY (`id`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址表';
|
||||
|
||||
func CreateAuthorizedAPITableSql() (sql string) {
|
||||
sql = "CREATE TABLE `authorized_api` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`business_key` varchar(30) NOT NULL DEFAULT '' COMMENT '调用方key',"
|
||||
sql += "`method` varchar(30) NOT NULL DEFAULT '' COMMENT '请求方式',"
|
||||
sql += "`api` varchar(100) NOT NULL DEFAULT '' COMMENT '请求地址',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`created_user` varchar(60) NOT NULL DEFAULT '' COMMENT '创建人',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "`updated_user` varchar(60) NOT NULL DEFAULT '' COMMENT '更新人',"
|
||||
sql += "PRIMARY KEY (`id`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='已授权接口地址表';"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateAuthorizedAPITableDataSql() (sql string) {
|
||||
sql = "INSERT INTO `authorized_api` (`id`, `business_key`, `method`, `api`,`created_user`) VALUES"
|
||||
sql += "(1, 'admin', 'GET', '/api/**', 'init'),"
|
||||
sql += "(2, 'admin', 'POST', '/api/**', 'init'),"
|
||||
sql += "(3, 'admin', 'PUT', '/api/**', 'init'),"
|
||||
sql += "(4, 'admin', 'DELETE', '/api/**', 'init'),"
|
||||
sql += "(5, 'admin', 'PATCH', '/api/**', 'init');"
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package mysql_table
|
||||
|
||||
//CREATE TABLE `user_demo` (
|
||||
//`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
//`user_name` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',
|
||||
//`nick_name` varchar(100) NOT NULL DEFAULT '' COMMENT '昵称',
|
||||
//`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
//`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',
|
||||
//`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
//`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
//PRIMARY KEY (`id`)
|
||||
//) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户Demo表';
|
||||
|
||||
func CreateUserDemoTableSql() (sql string) {
|
||||
sql = "CREATE TABLE `user_demo` ("
|
||||
sql += "`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',"
|
||||
sql += "`user_name` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',"
|
||||
sql += "`nick_name` varchar(100) NOT NULL DEFAULT '' COMMENT '昵称',"
|
||||
sql += "`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',"
|
||||
sql += "`is_deleted` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否删除 1:是 -1:否',"
|
||||
sql += "`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
|
||||
sql += "`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',"
|
||||
sql += "PRIMARY KEY (`id`)"
|
||||
sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户Demo表';"
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user