feat: 更新多个模块以支持新的数据结构和日志格式

This commit is contained in:
TsMask
2025-02-20 10:08:27 +08:00
parent 045a2b6b01
commit f3c33b31ac
272 changed files with 13246 additions and 15885 deletions

View File

@@ -1,36 +1,38 @@
package controller
import (
"fmt"
"strings"
"be.ems/src/framework/config"
commonConstants "be.ems/src/framework/constants/common"
tokenConstants "be.ems/src/framework/constants/token"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
tokenUtils "be.ems/src/framework/utils/token"
"be.ems/src/framework/vo"
"be.ems/src/framework/vo/result"
commonModel "be.ems/src/modules/common/model"
commonService "be.ems/src/modules/common/service"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/token"
"be.ems/src/modules/common/model"
"be.ems/src/modules/common/service"
systemModelVO "be.ems/src/modules/system/model/vo"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 AccountController 结构体
var NewAccount = &AccountController{
accountService: commonService.NewAccount,
sysLogLoginService: systemService.NewSysLogLoginImpl,
accountService: service.NewAccount,
sysLogLoginService: systemService.NewSysLogLogin,
}
// 账号身份操作处理
//
// PATH /
type AccountController struct {
accountService *commonService.Account // 账号身份操作服务
// 系统登录访问
sysLogLoginService systemService.ISysLogLogin
accountService *service.Account // 账号身份操作服务
sysLogLoginService *systemService.SysLogLogin // 系统登录访问
}
// 系统登录
// Login 系统登录
//
// POST /login
//
@@ -42,62 +44,62 @@ type AccountController struct {
// @Summary System Login
// @Description System Login
// @Router /login [post]
func (s *AccountController) Login(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var loginBody commonModel.LoginBody
if err := c.ShouldBindJSON(&loginBody); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
func (s AccountController) Login(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var body model.LoginBody
if err := c.ShouldBindJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
// 当前请求信息
ipaddr, location := ctx.IPAddrLocation(c)
os, browser := ctx.UaOsBrowser(c)
ipaddr, location := reqctx.IPAddrLocation(c)
os, browser := reqctx.UaOsBrowser(c)
// 校验验证码
err := s.accountService.ValidateCaptcha(
loginBody.Code,
loginBody.UUID,
)
// 根据错误信息,创建系统访问记录
if err != nil {
s.sysLogLoginService.CreateSysLogLogin(
loginBody.Username, commonConstants.STATUS_NO, err.Error(),
ipaddr, location, os, browser,
// 校验验证码 根据错误信息,创建系统访问记录
if err := s.accountService.ValidateCaptcha(body.Code, body.UUID); err != nil {
msg := fmt.Sprintf("%s code: %s", err.Error(), body.Code)
s.sysLogLoginService.Insert(
body.Username, constants.STATUS_NO, msg,
[4]string{ipaddr, location, os, browser},
)
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
c.JSON(400, resp.CodeMsg(40012, i18n.TKey(language, err.Error())))
return
}
// 登录用户信息
loginUser, err := s.accountService.LoginByUsername(loginBody.Username, loginBody.Password)
loginUser, err := s.accountService.ByUsername(body.Username, body.Password)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
return
}
// 生成令牌,创建系统访问记录
tokenStr := tokenUtils.Create(&loginUser, ipaddr, location, os, browser)
tokenStr := token.Create(&loginUser, [4]string{ipaddr, location, os, browser})
if tokenStr == "" {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
} else {
s.accountService.UpdateLoginDateAndIP(&loginUser)
s.accountService.UpdateLoginDateAndIP(loginUser)
// 登录成功
s.sysLogLoginService.CreateSysLogLogin(
loginBody.Username, commonConstants.STATUS_YES, "app.common.loginSuccess",
ipaddr, location, os, browser,
s.sysLogLoginService.Insert(
body.Username, constants.STATUS_YES, "app.common.loginSuccess",
[4]string{ipaddr, location, os, browser},
)
}
c.JSON(200, result.OkData(map[string]any{
tokenConstants.RESPONSE_FIELD: tokenStr,
c.JSON(200, resp.OkData(map[string]any{
"accessToken": tokenStr,
"tokenType": strings.TrimRight(constants.HEADER_PREFIX, " "),
"expiresIn": (loginUser.ExpireTime - loginUser.LoginTime) / 1000,
"userId": loginUser.UserId,
}))
}
// 登录用户信息
// Me 登录用户信息
//
// GET /getInfo
// GET /me
//
// @Tags common/authorization
// @Accept json
@@ -106,35 +108,35 @@ func (s *AccountController) Login(c *gin.Context) {
// @Security TokenAuth
// @Summary Login User Information
// @Description Login User Information
// @Router /getInfo [get]
func (s *AccountController) Info(c *gin.Context) {
language := ctx.AcceptLanguage(c)
loginUser, err := ctx.LoginUser(c)
// @Router /me [get]
func (s AccountController) Me(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
info, err := reqctx.LoginUser(c)
if err != nil {
c.JSON(401, result.CodeMsg(401, i18n.TKey(language, err.Error())))
c.JSON(401, resp.CodeMsg(40003, err.Error()))
return
}
// 角色权限集合,管理员拥有所有权限
isAdmin := config.IsAdmin(loginUser.UserID)
roles, perms := s.accountService.RoleAndMenuPerms(loginUser.UserID, isAdmin)
// 角色权限集合,系统管理员拥有所有权限
isSystemUser := config.IsSystemUser(info.UserId)
roles, perms := s.accountService.RoleAndMenuPerms(info.UserId, isSystemUser)
loginUser.User.NickName = i18n.TKey(language, loginUser.User.NickName)
loginUser.User.Remark = i18n.TKey(language, loginUser.User.Remark)
loginUser.User.Dept.DeptName = i18n.TKey(language, loginUser.User.Dept.DeptName)
for ri := range loginUser.User.Roles {
loginUser.User.Roles[ri].RoleName = i18n.TKey(language, loginUser.User.Roles[ri].RoleName)
info.User.NickName = i18n.TKey(language, info.User.NickName)
info.User.Remark = i18n.TKey(language, info.User.Remark)
info.User.Dept.DeptName = i18n.TKey(language, info.User.Dept.DeptName)
for ri := range info.User.Roles {
info.User.Roles[ri].RoleName = i18n.TKey(language, info.User.Roles[ri].RoleName)
}
c.JSON(200, result.OkData(map[string]any{
"user": loginUser.User,
c.JSON(200, resp.OkData(map[string]any{
"user": info.User,
"roles": roles,
"permissions": perms,
}))
}
// 登录用户路由信息
// Router 登录用户路由信息
//
// GET /getRouters
// GET /router
//
// @Tags common/authorization
// @Accept json
@@ -143,18 +145,18 @@ func (s *AccountController) Info(c *gin.Context) {
// @Security TokenAuth
// @Summary Login User Routing Information
// @Description Login User Routing Information
// @Router /getRouters [get]
func (s *AccountController) Router(c *gin.Context) {
userID := ctx.LoginUserToUserID(c)
// @Router /router [get]
func (s AccountController) Router(c *gin.Context) {
userId := reqctx.LoginUserToUserID(c)
// 前端路由,管理员拥有所有
isAdmin := config.IsAdmin(userID)
buildMenus := s.accountService.RouteMenus(userID, isAdmin)
// 前端路由,系统管理员拥有所有
isSystemUser := config.IsSystemUser(userId)
buildMenus := s.accountService.RouteMenus(userId, isSystemUser)
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
var converI18n func(language string, arr *[]vo.Router)
converI18n = func(language string, arr *[]vo.Router) {
language := reqctx.AcceptLanguage(c)
var converI18n func(language string, arr *[]systemModelVO.Router)
converI18n = func(language string, arr *[]systemModelVO.Router) {
for i := range *arr {
(*arr)[i].Meta.Title = i18n.TKey(language, (*arr)[i].Meta.Title)
if len((*arr)[i].Children) > 0 {
@@ -164,10 +166,10 @@ func (s *AccountController) Router(c *gin.Context) {
}
converI18n(language, &buildMenus)
c.JSON(200, result.OkData(buildMenus))
c.JSON(200, resp.OkData(buildMenus))
}
// 系统登出
// Logout 系统登出
//
// POST /logout
//
@@ -179,25 +181,23 @@ func (s *AccountController) Router(c *gin.Context) {
// @Summary System Logout
// @Description System Logout
// @Router /logout [post]
func (s *AccountController) Logout(c *gin.Context) {
language := ctx.AcceptLanguage(c)
tokenStr := ctx.Authorization(c)
func (s AccountController) Logout(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
tokenStr := reqctx.Authorization(c)
if tokenStr != "" {
// 存在token时记录退出信息
userName := tokenUtils.Remove(tokenStr)
userName := token.Remove(tokenStr)
if userName != "" {
// 当前请求信息
ipaddr, location := ctx.IPAddrLocation(c)
os, browser := ctx.UaOsBrowser(c)
// 创建系统访问记录 退出成功
s.sysLogLoginService.CreateSysLogLogin(
userName, commonConstants.STATUS_YES, "app.common.logoutSuccess",
ipaddr, location, os, browser,
ipaddr, location := reqctx.IPAddrLocation(c)
os, browser := reqctx.UaOsBrowser(c)
// 创建系统访问记录
s.sysLogLoginService.Insert(
userName, constants.STATUS_YES, "app.common.logoutSuccess",
[4]string{ipaddr, location, os, browser},
)
}
}
c.JSON(200, result.OkMsg(i18n.TKey(language, "app.common.logoutSuccess")))
c.JSON(200, resp.OkMsg(i18n.TKey(language, "app.common.logoutSuccess")))
}

View File

@@ -1,34 +1,33 @@
package controller
import (
adminConstants "be.ems/src/framework/constants/admin"
"be.ems/src/framework/constants/common"
tokenConstants "be.ems/src/framework/constants/token"
"strings"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/token"
"be.ems/src/framework/utils/machine"
"be.ems/src/framework/utils/regular"
tokenUtils "be.ems/src/framework/utils/token"
"be.ems/src/framework/vo"
"be.ems/src/framework/vo/result"
commonService "be.ems/src/modules/common/service"
"be.ems/src/modules/common/service"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 BootloaderController 结构体
var NewBootloader = &BootloaderController{
accountService: commonService.NewAccount,
sysUserService: systemService.NewSysUserImpl,
accountService: service.NewAccount,
sysUserService: systemService.NewSysUser,
}
// 系统引导初始化
//
// PATH /bootloader
type BootloaderController struct {
accountService *commonService.Account // 账号身份操作服务
// 用户信息服务
sysUserService systemService.ISysUser
accountService *service.Account // 账号身份操作服务
sysUserService *systemService.SysUser // 用户信息服务
}
// 首次引导开始
@@ -38,44 +37,47 @@ func (s *BootloaderController) Start(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
if v, ok := launchInfo[constants.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, resp.ErrMsg("bootloader done"))
return
}
// 查询用户登录账号
sysUser := s.sysUserService.SelectUserById("1")
if sysUser.UserID != "1" {
c.JSON(200, result.ErrMsg("not found user data"))
sysUser := s.sysUserService.FindById(1)
if sysUser.UserId != 1 {
c.JSON(200, resp.ErrMsg("not found user data"))
return
}
// 登录用户信息
loginUser := vo.LoginUser{
UserID: sysUser.UserID,
DeptID: sysUser.DeptID,
loginUser := token.TokenInfo{
UserId: sysUser.UserId,
DeptId: sysUser.DeptId,
User: sysUser,
Permissions: []string{adminConstants.PERMISSION},
Permissions: []string{constants.SYS_PERMISSION_SYSTEM},
}
// 当前请求信息
ipaddr, location := ctx.IPAddrLocation(c)
os, browser := ctx.UaOsBrowser(c)
ipaddr, location := reqctx.IPAddrLocation(c)
os, browser := reqctx.UaOsBrowser(c)
// 生成令牌,创建系统访问记录
tokenStr := tokenUtils.Create(&loginUser, ipaddr, location, os, browser)
tokenStr := token.Create(&loginUser, [4]string{ipaddr, location, os, browser})
if tokenStr == "" {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
} else {
s.accountService.UpdateLoginDateAndIP(&loginUser)
s.accountService.UpdateLoginDateAndIP(loginUser)
}
c.JSON(200, result.OkData(map[string]any{
tokenConstants.RESPONSE_FIELD: tokenStr,
c.JSON(200, resp.OkData(map[string]any{
"accessToken": tokenStr,
"tokenType": strings.TrimRight(constants.HEADER_PREFIX, " "),
"expiresIn": (loginUser.ExpireTime - loginUser.LoginTime) / 1000,
"userId": loginUser.UserId,
}))
}
@@ -86,23 +88,23 @@ func (s *BootloaderController) Done(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
if v, ok := launchInfo[constants.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, resp.ErrMsg("bootloader done"))
return
}
// 标记引导完成
if err := machine.Bootloader(false); err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 清除授权信息
tokenUtils.Remove(ctx.Authorization(c))
c.JSON(200, result.Ok(nil))
token.Remove(reqctx.Authorization(c))
c.JSON(200, resp.Ok(nil))
}
// 引导系统数据重置
@@ -112,69 +114,69 @@ func (s *BootloaderController) Reset(c *gin.Context) {
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && v.(bool) {
c.JSON(200, result.ErrMsg("bootloader not done"))
if v, ok := launchInfo[constants.LAUNCH_BOOTLOADER]; ok && v.(bool) {
c.JSON(200, resp.ErrMsg("bootloader not done"))
return
}
if err := machine.Reset(); err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
// 清除授权信息
tokenUtils.Remove(ctx.Authorization(c))
c.JSON(200, result.Ok(nil))
token.Remove(reqctx.Authorization(c))
c.JSON(200, resp.Ok(nil))
}
// 账号变更
//
// PUT /account
func (s *BootloaderController) Account(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
var body struct {
UserName string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if !regular.ValidPassword(body.Password) {
// 登录密码至少包含大小写字母、数字、特殊符号且不少于6位
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.errPasswd")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.errPasswd")))
return
}
// 是否完成引导
launchInfo := machine.LaunchInfo
if launchInfo == nil {
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
return
}
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, result.ErrMsg("bootloader done"))
if v, ok := launchInfo[constants.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
c.JSON(200, resp.ErrMsg("bootloader done"))
return
}
// 查询用户登录账号
sysUser := s.sysUserService.SelectUserById("2")
if sysUser.UserID != "2" {
c.JSON(200, result.ErrMsg("not found user data"))
sysUser := s.sysUserService.FindById(2)
if sysUser.UserId != 2 {
c.JSON(200, resp.ErrMsg("not found user data"))
return
}
sysUser.UserName = body.UserName
sysUser.NickName = body.UserName
sysUser.Password = body.Password
sysUser.UpdateBy = ctx.LoginUserToUserName(c)
rows := s.sysUserService.UpdateUser(sysUser)
sysUser.UpdateBy = reqctx.LoginUserToUserName(c)
rows := s.sysUserService.Update(sysUser)
if rows > 0 {
c.JSON(200, result.Ok(nil))
c.JSON(200, resp.Ok(nil))
return
}
c.JSON(200, result.Err(nil))
c.JSON(200, resp.Err(nil))
}

View File

@@ -4,12 +4,11 @@ import (
"time"
"be.ems/src/framework/config"
"be.ems/src/framework/constants/cachekey"
"be.ems/src/framework/constants/captcha"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/logger"
"be.ems/src/framework/redis"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/parse"
"be.ems/src/framework/vo/result"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
@@ -18,15 +17,14 @@ import (
// 实例化控制层 CaptchaController 结构体
var NewCaptcha = &CaptchaController{
sysConfigService: systemService.NewSysConfigImpl,
sysConfigService: systemService.NewSysConfig,
}
// 验证码操作处理
//
// PATH /
type CaptchaController struct {
// 参数配置服务
sysConfigService systemService.ISysConfig
sysConfigService *systemService.SysConfig // 参数配置服务
}
// 获取验证码
@@ -43,10 +41,10 @@ type CaptchaController struct {
// @Router /captchaImage [get]
func (s *CaptchaController) Image(c *gin.Context) {
// 从数据库配置获取验证码开关 true开启false关闭
captchaEnabledStr := s.sysConfigService.SelectConfigValueByKey("sys.account.captchaEnabled")
captchaEnabledStr := s.sysConfigService.FindValueByKey("sys.account.captchaEnabled")
captchaEnabled := parse.Boolean(captchaEnabledStr)
if !captchaEnabled {
c.JSON(200, result.Ok(map[string]any{
c.JSON(200, resp.Ok(map[string]any{
"captchaEnabled": captchaEnabled,
}))
return
@@ -61,8 +59,8 @@ func (s *CaptchaController) Image(c *gin.Context) {
}
// 从数据库配置获取验证码类型 math 数值计算 char 字符验证
captchaType := s.sysConfigService.SelectConfigValueByKey("sys.account.captchaType")
if captchaType == captcha.TYPE_MATH {
captchaType := s.sysConfigService.FindValueByKey("sys.account.captchaType")
if captchaType == constants.CAPTCHA_TYPE_MATH {
math := config.Get("mathCaptcha").(map[string]any)
driverCaptcha := &base64Captcha.DriverMath{
//Height png height in pixel.
@@ -87,12 +85,12 @@ func (s *CaptchaController) Image(c *gin.Context) {
} else {
data["uuid"] = id
data["img"] = item.EncodeB64string()
expiration := captcha.EXPIRATION * time.Second
verifyKey = cachekey.CAPTCHA_CODE_KEY + id
expiration := constants.CAPTCHA_EXPIRATION * time.Second
verifyKey = constants.CACHE_CAPTCHA_CODE + ":" + id
redis.SetByExpire("", verifyKey, answer, expiration)
}
}
if captchaType == captcha.TYPE_CHAR {
if captchaType == constants.CAPTCHA_TYPE_CHAR {
char := config.Get("charCaptcha").(map[string]any)
driverCaptcha := &base64Captcha.DriverString{
//Height png height in pixel.
@@ -121,8 +119,8 @@ func (s *CaptchaController) Image(c *gin.Context) {
} else {
data["uuid"] = id
data["img"] = item.EncodeB64string()
expiration := captcha.EXPIRATION * time.Second
verifyKey = cachekey.CAPTCHA_CODE_KEY + id
expiration := constants.CAPTCHA_EXPIRATION * time.Second
verifyKey = constants.CACHE_CAPTCHA_CODE + ":" + id
redis.SetByExpire("", verifyKey, answer, expiration)
}
}
@@ -131,8 +129,8 @@ func (s *CaptchaController) Image(c *gin.Context) {
if config.Env() == "local" {
text, _ := redis.Get("", verifyKey)
data["text"] = text
c.JSON(200, result.Ok(data))
c.JSON(200, resp.Ok(data))
return
}
c.JSON(200, result.Ok(data))
c.JSON(200, resp.Ok(data))
}

View File

@@ -1,37 +1,92 @@
package controller
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"hash"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/vo/result"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
commonService "be.ems/src/modules/common/service"
"github.com/gin-gonic/gin"
)
// 实例化控制层 CommontController 结构体
var NewCommont = &CommontController{
// 实例化控制层 CommonController 结构体
var NewCommon = &CommonController{
commontService: commonService.NewCommont,
}
// 通用请求
//
// PATH /
type CommontController struct {
type CommonController struct {
commontService *commonService.Commont // 通用请求服务
}
// 哈希加密
// Hash 哈希编码
//
// POST /hash
func (s *CommontController) Hash(c *gin.Context) {
c.String(200, "commont Hash")
func (s CommonController) Hash(c *gin.Context) {
var body struct {
Type string `json:"type" binding:"required,oneof=sha1 sha256 sha512 md5"`
Str string `json:"str" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(200, gin.H{
"code": 400,
"msg": "参数错误",
})
return
}
var h hash.Hash
var err error
switch body.Type {
case "sha1":
h = sha1.New()
case "sha256":
h = sha256.New()
case "sha512":
h = sha512.New()
case "md5":
h = md5.New()
default:
c.JSON(200, gin.H{
"code": 400,
"msg": fmt.Sprintf("不支持的哈希算法: %s", body.Type),
})
return
}
// 写入需要哈希的数据
if _, err = h.Write([]byte(body.Str)); err != nil {
c.JSON(500, gin.H{
"code": 500,
"msg": "哈希写入错误",
})
return
}
// 计算哈希值的16进制表示
hashed := h.Sum(nil)
text := hex.EncodeToString(hashed)
c.JSON(200, gin.H{
"code": 200,
"msg": "success",
"data": text,
})
}
// 多语言处理
//
// GET /i18n
func (s *CommontController) I18n(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s *CommonController) I18n(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
i18nLang := i18n.TKey(language, "i18n")
hello := i18n.TKey(language, "hello")
@@ -57,11 +112,11 @@ func (s *CommontController) I18n(c *gin.Context) {
// @Summary Configuration information for the system
// @Description Configuration information for the system
// @Router /sys-conf [get]
func (s *CommontController) SysConfig(c *gin.Context) {
func (s CommonController) SysConfig(c *gin.Context) {
data := s.commontService.SystemConfigInfo()
// 闭包函数处理多语言
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
converI18n := func(language string, arr *map[string]string) {
for k, v := range *arr {
(*arr)[k] = i18n.TKey(language, v)
@@ -69,5 +124,5 @@ func (s *CommontController) SysConfig(c *gin.Context) {
}
converI18n(language, &data)
c.JSON(200, result.OkData(data))
c.JSON(200, resp.OkData(data))
}

View File

@@ -8,14 +8,13 @@ import (
"strings"
"be.ems/src/framework/config"
"be.ems/src/framework/constants/uploadsubpath"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/file"
"be.ems/src/framework/vo/result"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 FileController 结构体
@@ -30,16 +29,16 @@ type FileController struct{}
//
// GET /download/:filePath
func (s *FileController) Download(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
filePath := c.Param("filePath")
if len(filePath) < 8 {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// base64解析出地址
decodedBytes, err := base64.StdEncoding.DecodeString(filePath)
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(400, resp.CodeMsg(400, err.Error()))
return
}
routerPath := string(decodedBytes)
@@ -48,7 +47,7 @@ func (s *FileController) Download(c *gin.Context) {
headerRange := c.GetHeader("Range")
resultMap, err := file.ReadUploadFileStream(routerPath, headerRange)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
@@ -83,29 +82,29 @@ func (s *FileController) Download(c *gin.Context) {
// @Description Upload a file, interface param use <fileName>
// @Router /file/upload [post]
func (s *FileController) Upload(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
// 上传的文件
formFile, err := c.FormFile("file")
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 子路径
subPath := c.PostForm("subPath")
if _, ok := uploadsubpath.UploadSubpath[subPath]; !ok {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if _, ok := constants.UPLOAD_SUB_PATH[subPath]; !ok {
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 上传文件转存
upFilePath, err := file.TransferUploadFile(formFile, subPath, nil)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
newFileName := upFilePath[strings.LastIndex(upFilePath, "/")+1:]
c.JSON(200, result.OkData(map[string]string{
c.JSON(200, resp.OkData(map[string]string{
"url": "//" + c.Request.Host + upFilePath,
"fileName": upFilePath,
"newFileName": newFileName,
@@ -127,7 +126,7 @@ func (s *FileController) Upload(c *gin.Context) {
// @Description Slice file checking
// @Router /file/chunkCheck [post]
func (s *FileController) ChunkCheck(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
var body struct {
// 唯一标识
Identifier string `json:"identifier" binding:"required"`
@@ -136,17 +135,17 @@ func (s *FileController) ChunkCheck(c *gin.Context) {
}
err := c.ShouldBindJSON(&body)
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 读取标识目录
chunks, err := file.ChunkCheckFile(body.Identifier, body.FileName)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(chunks))
c.JSON(200, resp.OkData(chunks))
}
// 切片文件合并
@@ -163,7 +162,7 @@ func (s *FileController) ChunkCheck(c *gin.Context) {
// @Description Slice file merge
// @Router /file/chunkMerge [post]
func (s *FileController) ChunkMerge(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
var body struct {
// 唯一标识
Identifier string `json:"identifier" binding:"required"`
@@ -174,23 +173,23 @@ func (s *FileController) ChunkMerge(c *gin.Context) {
}
err := c.ShouldBindJSON(&body)
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if _, ok := uploadsubpath.UploadSubpath[body.SubPath]; !ok {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if _, ok := constants.UPLOAD_SUB_PATH[body.SubPath]; !ok {
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 切片文件合并
mergeFilePath, err := file.ChunkMergeFile(body.Identifier, body.FileName, body.SubPath)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
newFileName := mergeFilePath[strings.LastIndex(mergeFilePath, "/")+1:]
c.JSON(200, result.OkData(map[string]string{
c.JSON(200, resp.OkData(map[string]string{
"url": "//" + c.Request.Host + mergeFilePath,
"fileName": mergeFilePath,
"newFileName": newFileName,
@@ -214,7 +213,7 @@ func (s *FileController) ChunkMerge(c *gin.Context) {
// @Description Sliced file upload
// @Router /file/chunkUpload [post]
func (s *FileController) ChunkUpload(c *gin.Context) {
language := ctx.AcceptLanguage(c)
language := reqctx.AcceptLanguage(c)
// 切片编号
index := c.PostForm("index")
// 切片唯一标识
@@ -222,31 +221,31 @@ func (s *FileController) ChunkUpload(c *gin.Context) {
// 上传的文件
formFile, err := c.FormFile("file")
if index == "" || identifier == "" || err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 上传文件转存
chunkFilePath, err := file.TransferChunkUploadFile(formFile, index, identifier)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
c.JSON(206, result.OkData(chunkFilePath))
c.JSON(206, resp.OkData(chunkFilePath))
}
// 转存指定对应文件到静态目录
//
// POST /transferStaticFile
func (s *CommontController) TransferStaticFile(c *gin.Context) {
language := ctx.AcceptLanguage(c)
func (s *FileController) TransferStaticFile(c *gin.Context) {
var body struct {
UploadPath string `json:"uploadPath" binding:"required"`
StaticPath string `json:"staticPath" binding:"required"`
Language string `json:"language" binding:"required"`
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
@@ -257,7 +256,7 @@ func (s *CommontController) TransferStaticFile(c *gin.Context) {
static := config.Get("staticFile.default").(map[string]any)
dir, err := filepath.Abs(static["dir"].(string))
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(400, resp.CodeMsg(400, err.Error()))
return
}
@@ -267,10 +266,10 @@ func (s *CommontController) TransferStaticFile(c *gin.Context) {
err = file.CopyUploadFile(body.UploadPath, newFile)
if err != nil {
c.JSON(400, result.CodeMsg(400, err.Error()))
c.JSON(400, resp.CodeMsg(400, err.Error()))
return
}
urlPath := strings.Replace(newFile, dir, static["prefix"].(string), 1)
c.JSON(200, result.OkData(filepath.ToSlash(urlPath)))
c.JSON(200, resp.OkData(filepath.ToSlash(urlPath)))
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
libGlobal "be.ems/lib/global"
"be.ems/src/framework/vo/result"
"be.ems/src/framework/resp"
"github.com/gin-gonic/gin"
)
@@ -32,6 +32,6 @@ func (s *IndexController) Handler(c *gin.Context) {
name := "OMC"
version := libGlobal.Version
// str := "欢迎使用%s核心网管理平台当前版本%s请通过前台地址访问。"
str := "Welcome to the %s Core Network Management Platform, current version: %s, please access via the frontend address."
c.JSON(200, result.OkMsg(fmt.Sprintf(str, name, version)))
str := "%s Core Network Management, current version: %s"
c.JSON(200, resp.OkMsg(fmt.Sprintf(str, name, version)))
}

View File

@@ -1,13 +1,15 @@
package controller
import (
commonConstants "be.ems/src/framework/constants/common"
"fmt"
"be.ems/src/framework/constants"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/regular"
"be.ems/src/framework/vo/result"
commonModel "be.ems/src/modules/common/model"
commonService "be.ems/src/modules/common/service"
"be.ems/src/modules/common/model"
"be.ems/src/modules/common/service"
systemService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
@@ -15,77 +17,77 @@ import (
// 实例化控制层 RegisterController 结构体
var NewRegister = &RegisterController{
registerService: commonService.NewRegisterImpl,
sysLogLoginService: systemService.NewSysLogLoginImpl,
registerService: service.NewRegister,
sysLogLoginService: systemService.NewSysLogLogin,
}
// 账号注册操作处理
//
// PATH /
type RegisterController struct {
// 账号注册操作服务
registerService commonService.IRegister
// 系统登录访问
sysLogLoginService systemService.ISysLogLogin
registerService *service.Register // 账号注册操作服务
sysLogLoginService *systemService.SysLogLogin // 系统登录访问服务
}
// 账号注册
//
// GET /register
func (s *RegisterController) Register(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var registerBody commonModel.RegisterBody
if err := c.ShouldBindJSON(&registerBody); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
language := reqctx.AcceptLanguage(c)
var body model.RegisterBody
if err := c.ShouldBindJSON(&body); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(40422, errMsgs))
return
}
// 判断必传参数
if !regular.ValidUsername(registerBody.Username) {
if !regular.ValidUsername(body.Username) {
// 账号不能以数字开头可包含大写小写字母数字且不少于5位
c.JSON(200, result.ErrMsg(i18n.TKey(language, "register.errUsername")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errUsername")))
return
}
if !regular.ValidPassword(registerBody.Password) {
if !regular.ValidPassword(body.Password) {
// 登录密码至少包含大小写字母、数字、特殊符号且不少于6位
c.JSON(200, result.ErrMsg(i18n.TKey(language, "register.errPasswd")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errPasswd")))
return
}
if registerBody.Password != registerBody.ConfirmPassword {
if body.Password != body.ConfirmPassword {
// 用户确认输入密码不一致
c.JSON(200, result.ErrMsg(i18n.TKey(language, "register.errPasswdNotEq")))
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errPasswdNotEq")))
return
}
// 当前请求信息
ipaddr, location := ctx.IPAddrLocation(c)
os, browser := ctx.UaOsBrowser(c)
ipaddr, location := reqctx.IPAddrLocation(c)
os, browser := reqctx.UaOsBrowser(c)
// 校验验证码
err := s.registerService.ValidateCaptcha(
registerBody.Code,
registerBody.UUID,
body.Code,
body.UUID,
)
// 根据错误信息,创建系统访问记录
if err != nil {
s.sysLogLoginService.CreateSysLogLogin(
registerBody.Username, commonConstants.STATUS_NO, err.Error(),
ipaddr, location, os, browser,
msg := err.Error() + " code: " + body.Code
s.sysLogLoginService.Insert(
body.Username, constants.STATUS_NO, msg,
[4]string{ipaddr, location, os, browser},
)
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
userID, err := s.registerService.ByUserName(registerBody.Username, registerBody.Password, registerBody.UserType)
userId, err := s.registerService.ByUserName(body.Username, body.Password)
if err == nil {
msg := i18n.TTemplate(language, "register.successMsg", map[string]any{"name": registerBody.Username, "id": userID})
s.sysLogLoginService.CreateSysLogLogin(
registerBody.Username, commonConstants.STATUS_YES, msg,
ipaddr, location, os, browser,
msg := i18n.TTemplate(language, "register.successMsg", map[string]any{"name": body.Username, "id": userId})
s.sysLogLoginService.Insert(
body.Username, constants.STATUS_YES, msg,
[4]string{ipaddr, location, os, browser},
)
// 注册成功
c.JSON(200, result.OkMsg(i18n.TKey(language, "register.success")))
c.JSON(200, resp.OkMsg(i18n.TKey(language, "register.success")))
return
}
c.JSON(200, result.ErrMsg(err.Error()))
c.JSON(200, resp.ErrMsg(err.Error()))
}