优化结构
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Announcement struct{ service *service.AnnouncementService }
|
||||
|
||||
func NewAnnouncement(service *service.AnnouncementService) *Announcement {
|
||||
return &Announcement{service: service}
|
||||
}
|
||||
|
||||
func announcementInput(req service.AnnouncementRequest) service.AnnouncementInput {
|
||||
return service.AnnouncementInput{ID: req.ID, Title: req.Title, Content: req.Content, UserID: req.UserID, Attachments: req.Attachments}
|
||||
}
|
||||
|
||||
func (h *Announcement) Create(c *gin.Context) {
|
||||
var req service.AnnouncementRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Create(c.Request.Context(), announcementInput(req)); err != nil {
|
||||
Fail(c, "创建失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
|
||||
func (h *Announcement) Delete(c *gin.Context) {
|
||||
if err := h.service.Delete(c.Request.Context(), c.Query("ID")); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Announcement) DeleteByIDs(c *gin.Context) {
|
||||
if err := h.service.DeleteByIDs(c.Request.Context(), c.QueryArray("IDs[]")); err != nil {
|
||||
Fail(c, "批量删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
|
||||
func (h *Announcement) Update(c *gin.Context) {
|
||||
var req service.AnnouncementRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Update(c.Request.Context(), announcementInput(req)); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
|
||||
func (h *Announcement) Find(c *gin.Context) {
|
||||
item, err := h.service.Find(c.Request.Context(), c.Query("ID"))
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, item)
|
||||
}
|
||||
|
||||
func (h *Announcement) List(c *gin.Context) {
|
||||
var req service.AnnouncementSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.List(c.Request.Context(), req.Page, req.PageSize, req.StartCreatedAt, req.EndCreatedAt)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Announcement) DataSource(c *gin.Context) {
|
||||
users, err := h.service.UserOptions(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, gin.H{"userID": users})
|
||||
}
|
||||
|
||||
func (h *Announcement) Public(c *gin.Context) {
|
||||
Write(c, CodeSuccess, gin.H{"info": "不需要鉴权的公告接口信息"}, "获取成功")
|
||||
}
|
||||
|
||||
func parseTime(value string) (*time.Time, error) {
|
||||
if value == "" {
|
||||
return nil, nil
|
||||
}
|
||||
parsed, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &parsed, nil
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type API struct{ service *service.APIService }
|
||||
|
||||
func NewAPI(service *service.APIService) *API { return &API{service: service} }
|
||||
|
||||
func (h *API) List(c *gin.Context) {
|
||||
var req service.APIListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Page == 0 {
|
||||
Fail(c, "Page值不能为空")
|
||||
return
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
Fail(c, "PageSize值不能为空")
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.ListAPI(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *API) All(c *gin.Context) {
|
||||
items, err := h.service.AllAPI(c.Request.Context(), true)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"apis": items}, "获取成功")
|
||||
}
|
||||
func (h *API) Create(c *gin.Context) {
|
||||
var req service.APIRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if message := validateAPIRequest(&req); message != "" {
|
||||
Fail(c, message)
|
||||
return
|
||||
}
|
||||
created, err := h.service.CreateAPIRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "创建失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, created, "创建成功")
|
||||
}
|
||||
func (h *API) Update(c *gin.Context) {
|
||||
var req service.APIRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if message := validateAPIRequest(&req); message != "" {
|
||||
Fail(c, message)
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateAPIRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "修改失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "修改成功")
|
||||
}
|
||||
func (h *API) Delete(c *gin.Context) {
|
||||
var req service.DeleteAPIRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteAPI(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *API) DeleteByIDs(c *gin.Context) {
|
||||
var req service.DeleteAPIsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteAPIs(c.Request.Context(), req.IDs); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *API) Find(c *gin.Context) {
|
||||
var req service.GetAPIRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.FindAPIResponse(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"api": item}, "获取成功")
|
||||
}
|
||||
func (h *API) Groups(c *gin.Context) {
|
||||
groups, groupAPIMap, err := h.service.Groups(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, gin.H{"groups": groups, "apiGroupMap": groupAPIMap})
|
||||
}
|
||||
func (h *API) Roles(c *gin.Context) {
|
||||
path, method := c.Query("path"), c.Query("method")
|
||||
if path == "" || method == "" {
|
||||
Fail(c, "API路径和请求方法不能为空")
|
||||
return
|
||||
}
|
||||
ids, err := h.service.APIRoleIDs(c.Request.Context(), path, method)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, ids, "获取成功")
|
||||
}
|
||||
func (h *API) SetRoles(c *gin.Context) {
|
||||
var req service.SetAPIRolesRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Path == "" || req.Method == "" {
|
||||
Fail(c, "API路径和请求方法不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetAPIRoles(c.Request.Context(), req.Path, req.Method, req.AuthorityIDs); err != nil {
|
||||
Fail(c, "设置失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
func (h *API) Sync(engine *gin.Engine) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
routes := engine.Routes()
|
||||
values := make([]service.APIRequest, 0, len(routes))
|
||||
for _, route := range routes {
|
||||
values = append(values, service.APIRequest{Path: route.Path, Method: route.Method})
|
||||
}
|
||||
result, err := h.service.SyncAPIResponses(c.Request.Context(), values)
|
||||
if err != nil {
|
||||
Fail(c, "同步失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
}
|
||||
func (h *API) Ignore(c *gin.Context) {
|
||||
var req service.IgnoreAPIRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.SetAPIIgnored(c.Request.Context(), req.Path, req.Method, req.Flag); err != nil {
|
||||
Fail(c, "忽略失败")
|
||||
return
|
||||
}
|
||||
OK(c)
|
||||
}
|
||||
func (h *API) ApplySync(c *gin.Context) {
|
||||
var req service.ApplyAPISyncRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.ApplyAPISyncRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "忽略失败")
|
||||
return
|
||||
}
|
||||
OK(c)
|
||||
}
|
||||
func (h *API) FreshCasbin(c *gin.Context) {
|
||||
if err := h.service.FreshCasbin(c.Request.Context()); err != nil {
|
||||
Fail(c, "刷新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "刷新成功")
|
||||
}
|
||||
|
||||
func (h *API) SetPolicyPaths(c *gin.Context) {
|
||||
var req service.SetPolicyPathsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetPolicyPathsRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *API) PolicyPaths(c *gin.Context) {
|
||||
var req service.GetPolicyPathsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
paths, err := h.service.PolicyPathResponses(c.Request.Context(), req.AuthorityID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"paths": paths}, "获取成功")
|
||||
}
|
||||
|
||||
func validateAPIRequest(req *service.APIRequest) string {
|
||||
switch {
|
||||
case req.Path == "":
|
||||
return "Path值不能为空"
|
||||
case req.Description == "":
|
||||
return "Description值不能为空"
|
||||
case req.APIGroup == "":
|
||||
return "ApiGroup值不能为空"
|
||||
case req.Method == "":
|
||||
return "Method值不能为空"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type APIToken struct {
|
||||
service *service.TokenService
|
||||
}
|
||||
|
||||
func NewAPIToken(service *service.TokenService) *APIToken {
|
||||
return &APIToken{service: service}
|
||||
}
|
||||
|
||||
func (h *APIToken) Create(c *gin.Context) {
|
||||
var req service.CreateAPITokenRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
token, err := h.service.CreateAPIToken(c.Request.Context(), req.UserID, req.AuthorityID, req.Days, req.Remark)
|
||||
if err != nil {
|
||||
Fail(c, "签发失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"token": token}, "签发成功")
|
||||
}
|
||||
|
||||
func (h *APIToken) List(c *gin.Context) {
|
||||
var req service.APITokenListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.APITokens(c.Request.Context(), req.Page, req.PageSize, req.UserID, req.Status)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *APIToken) Delete(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DisableAPIToken(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "作废失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "作废成功")
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz"
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Audit struct {
|
||||
service *service.AuditService
|
||||
recorder *service.AuditRecorder
|
||||
logs *service.LogViewerService
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func NewAudit(service *service.AuditService, recorder *service.AuditRecorder, logs *service.LogViewerService, logger *slog.Logger) *Audit {
|
||||
return &Audit{service: service, recorder: recorder, logs: logs, logger: logger}
|
||||
}
|
||||
|
||||
func (h *Audit) Operations(c *gin.Context) {
|
||||
var req service.OperationRecordSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.OperationsFilter(c.Request.Context(), req.Page, req.PageSize, req.Path, req.Method, req.Status)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *Audit) Operation(c *gin.Context) {
|
||||
var req service.AuditIDQuery
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Operation(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"reSysOperationRecord": item}, "查询成功")
|
||||
}
|
||||
func (h *Audit) DeleteOperation(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteOperations(c.Request.Context(), []int{int(req.ID)}); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Audit) DeleteOperations(c *gin.Context) {
|
||||
var req service.AuditIDsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteOperations(c.Request.Context(), req.IDs); err != nil {
|
||||
Fail(c, "批量删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
|
||||
func (h *Audit) Logins(c *gin.Context) {
|
||||
var req service.LoginLogSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.LoginsFilter(c.Request.Context(), req.Page, req.PageSize, req.Username, req.Status)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *Audit) Login(c *gin.Context) {
|
||||
var req service.AuditIDQuery
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.service.Login(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, item, "查询成功")
|
||||
}
|
||||
func (h *Audit) DeleteLogin(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteLogins(c.Request.Context(), []int{int(req.ID)}); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Audit) DeleteLogins(c *gin.Context) {
|
||||
var req service.AuditIDsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteLogins(c.Request.Context(), req.IDs); err != nil {
|
||||
Fail(c, "批量删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
|
||||
func (h *Audit) DataAccess(c *gin.Context) {
|
||||
var req service.DataAccessListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.DataAccessRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *Audit) DeleteDataAccess(c *gin.Context) {
|
||||
var req service.IDsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteDataAccess(c.Request.Context(), req.IDs); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Audit) LogDates(c *gin.Context) {
|
||||
month := c.Query("month")
|
||||
// Month uses `binding:"required"`; an omitted or empty query is a
|
||||
// generic parameter error, not the service's format-specific error.
|
||||
if month == "" {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
data, err := h.logs.LogDates(c.Request.Context(), month)
|
||||
if err != nil {
|
||||
failLogViewer(c, err, h.logger)
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, data, "获取成功")
|
||||
}
|
||||
func (h *Audit) LogFiles(c *gin.Context) {
|
||||
date := c.Query("date")
|
||||
if date == "" {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
data, err := h.logs.LogFiles(c.Request.Context(), date)
|
||||
if err != nil {
|
||||
failLogViewer(c, err, h.logger)
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, data, "获取成功")
|
||||
}
|
||||
func (h *Audit) LogContent(c *gin.Context) {
|
||||
date, path := c.Query("date"), c.Query("path")
|
||||
if date == "" || path == "" {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
var cursor *int64
|
||||
if raw := c.Query("cursor"); raw != "" {
|
||||
value, err := strconv.ParseInt(raw, 10, 64)
|
||||
if err != nil {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
cursor = &value
|
||||
}
|
||||
// Preserve negative cursors for the usecase to classify with the compatible
|
||||
// "日志文件路径不合法" error rather than rejecting them as binding errors.
|
||||
data, err := h.logs.LogContent(c.Request.Context(), date, path, cursor)
|
||||
if err != nil {
|
||||
failLogViewer(c, err, h.logger)
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, data, "获取成功")
|
||||
}
|
||||
|
||||
func failLogViewer(c *gin.Context, err error, logger *slog.Logger) {
|
||||
if logger != nil {
|
||||
logger.ErrorContext(c.Request.Context(), "日志查看失败", "mod", "log-viewer", "error", err)
|
||||
}
|
||||
message := "读取日志失败"
|
||||
switch {
|
||||
case errors.Is(err, biz.ErrInvalidLogMonth):
|
||||
message = "日志月份格式不正确"
|
||||
case errors.Is(err, biz.ErrInvalidLogDate):
|
||||
message = "日志日期格式不正确"
|
||||
case errors.Is(err, biz.ErrInvalidLogPath):
|
||||
message = "日志文件路径不合法"
|
||||
case errors.Is(err, biz.ErrLogFileNotFound):
|
||||
message = "日志文件不存在"
|
||||
case errors.Is(err, biz.ErrLogFileUnreadable):
|
||||
message = "日志文件不可读取"
|
||||
case errors.Is(err, biz.ErrLogRootUnavailable):
|
||||
message = "日志目录不可读取"
|
||||
}
|
||||
Fail(c, message)
|
||||
}
|
||||
|
||||
func (h *Audit) DeleteError(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Query("ID"), 10, 64)
|
||||
if err := h.service.DeleteErrors(c.Request.Context(), []uint{uint(id)}); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Audit) DeleteErrors(c *gin.Context) {
|
||||
if err := h.service.DeleteErrors(c.Request.Context(), IDsFromQuery(c)); err != nil {
|
||||
Fail(c, "批量删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
func (h *Audit) UpdateError(c *gin.Context) {
|
||||
var req service.ErrorRecordMutationRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateErrorRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Audit) Error(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Query("ID"), 10, 64)
|
||||
item, err := h.service.Error(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
Fail(c, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, item)
|
||||
}
|
||||
func (h *Audit) Errors(c *gin.Context) {
|
||||
p, size, err := page(c)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
createdAtRange := make([]time.Time, 0, 2)
|
||||
for _, raw := range c.QueryArray("createdAtRange[]") {
|
||||
value, parseErr := time.Parse(time.RFC3339, raw)
|
||||
if parseErr != nil {
|
||||
Fail(c, parseErr.Error())
|
||||
return
|
||||
}
|
||||
createdAtRange = append(createdAtRange, value)
|
||||
}
|
||||
items, total, err := h.service.ErrorsFilter(c.Request.Context(), p, size, c.Query("form"), c.Query("info"), createdAtRange)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: p, PageSize: size}, "获取成功")
|
||||
}
|
||||
func (h *Audit) CreateError(c *gin.Context) {
|
||||
var req service.ErrorRecordMutationRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.recorder.CreateErrorMutationRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Authority struct{ service *service.AuthorityService }
|
||||
|
||||
func NewAuthority(service *service.AuthorityService) *Authority { return &Authority{service: service} }
|
||||
|
||||
func (h *Authority) List(c *gin.Context) {
|
||||
items, err := h.service.Authorities(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, items, "获取成功")
|
||||
}
|
||||
func (h *Authority) Create(c *gin.Context) {
|
||||
var req service.AuthorityRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if req.AuthorityName == "" {
|
||||
Fail(c, "AuthorityName值不能为空")
|
||||
return
|
||||
}
|
||||
value, err := h.service.CreateAuthorityRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "创建失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"authority": value}, "创建成功")
|
||||
}
|
||||
func (h *Authority) Copy(c *gin.Context) {
|
||||
var req service.CopyAuthorityRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.OldAuthorityID == 0 {
|
||||
Fail(c, "OldAuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Authority.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Authority.AuthorityName == "" {
|
||||
Fail(c, "AuthorityName值不能为空")
|
||||
return
|
||||
}
|
||||
value, err := h.service.CopyAuthorityRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "拷贝失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"authority": value}, "拷贝成功")
|
||||
}
|
||||
func (h *Authority) Update(c *gin.Context) {
|
||||
var req service.AuthorityRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if req.AuthorityName == "" {
|
||||
Fail(c, "AuthorityName值不能为空")
|
||||
return
|
||||
}
|
||||
value, err := h.service.UpdateAuthorityRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "更新失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"authority": value}, "更新成功")
|
||||
}
|
||||
func (h *Authority) Delete(c *gin.Context) {
|
||||
var req service.DeleteAuthorityRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteAuthority(c.Request.Context(), req.AuthorityID); err != nil {
|
||||
Fail(c, "删除失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Authority) SetUsers(c *gin.Context) {
|
||||
var req service.SetRoleUsersRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "角色ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetAuthorityUsers(c.Request.Context(), req.AuthorityID, req.UserIDs); err != nil {
|
||||
Fail(c, "设置失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
func (h *Authority) Users(c *gin.Context) {
|
||||
var req service.SetRoleUsersRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
ids, err := h.service.AuthorityUserIDs(c.Request.Context(), req.AuthorityID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, ids, "获取成功")
|
||||
}
|
||||
func (h *Authority) SetDataScope(c *gin.Context) {
|
||||
var req service.SetDataScopeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "角色ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetDataScope(c.Request.Context(), req.AuthorityID, req.DataScope, req.DepartmentIDs); err != nil {
|
||||
Fail(c, "设置失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
func (h *Authority) DataScopeDepartments(c *gin.Context) {
|
||||
var req service.SetDataScopeRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
ids, err := h.service.DataScopeDepartmentIDs(c.Request.Context(), req.AuthorityID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, ids, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Dictionary struct{ service *service.DictionaryService }
|
||||
|
||||
func NewDictionary(service *service.DictionaryService) *Dictionary {
|
||||
return &Dictionary{service: service}
|
||||
}
|
||||
|
||||
func (h *Dictionary) Create(c *gin.Context) {
|
||||
var req service.DictionaryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
created, err := h.service.CreateDictionaryRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "创建失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, created, "创建成功")
|
||||
}
|
||||
func (h *Dictionary) Update(c *gin.Context) {
|
||||
var req service.DictionaryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateDictionaryRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Dictionary) Delete(c *gin.Context) {
|
||||
var req service.DictionaryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteDictionary(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Dictionary) Find(c *gin.Context) {
|
||||
var req service.DictionaryRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.service.Dictionary(c.Request.Context(), req.ID, req.Type, req.Status, true)
|
||||
if err != nil {
|
||||
Fail(c, "字典未创建或未开启")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"resysDictionary": item}, "查询成功")
|
||||
}
|
||||
func (h *Dictionary) List(details bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
items, _, err := h.service.Dictionaries(c.Request.Context(), 0, 0, c.Query("name"), "", details)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, items, "获取成功")
|
||||
}
|
||||
}
|
||||
func (h *Dictionary) Export(c *gin.Context) {
|
||||
var req service.DictionaryRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "字典ID不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.ExportDictionary(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "导出失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, item, "导出成功")
|
||||
}
|
||||
func (h *Dictionary) Import(c *gin.Context) {
|
||||
var req service.ImportDictionaryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.ImportDictionaryJSON(c.Request.Context(), req.JSON); err != nil {
|
||||
Fail(c, "导入失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "导入成功")
|
||||
}
|
||||
|
||||
func (h *Dictionary) CreateDetail(c *gin.Context) {
|
||||
var req service.DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.CreateDictionaryDetailRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
func (h *Dictionary) UpdateDetail(c *gin.Context) {
|
||||
var req service.DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateDictionaryDetailRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Dictionary) DeleteDetail(c *gin.Context) {
|
||||
var req service.DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteDictionaryDetail(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Dictionary) FindDetail(c *gin.Context) {
|
||||
var req service.DictionaryDetailRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.DictionaryDetail(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"reSysDictionaryDetail": item}, "查询成功")
|
||||
}
|
||||
func (h *Dictionary) Details(c *gin.Context) {
|
||||
p, size, err := page(c)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
var dictionaryID uint64
|
||||
if raw, exists := c.GetQuery("sysDictionaryID"); exists && raw != "" {
|
||||
var parseErr error
|
||||
dictionaryID, parseErr = strconv.ParseUint(raw, 10, 0)
|
||||
if parseErr != nil {
|
||||
Fail(c, parseErr.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
filter := service.DictionaryDetailListRequest{DictionaryID: uint(dictionaryID), Label: c.Query("label"), Value: c.Query("value")}
|
||||
if raw, exists := c.GetQuery("status"); exists {
|
||||
value, parseErr := strconv.ParseBool(raw)
|
||||
if parseErr != nil {
|
||||
Fail(c, parseErr.Error())
|
||||
return
|
||||
}
|
||||
filter.Status = &value
|
||||
}
|
||||
if raw, exists := c.GetQuery("parentID"); exists {
|
||||
value, parseErr := strconv.ParseUint(raw, 10, 64)
|
||||
if parseErr != nil {
|
||||
Fail(c, parseErr.Error())
|
||||
return
|
||||
}
|
||||
parentID := uint(value)
|
||||
filter.ParentID = &parentID
|
||||
}
|
||||
if raw, exists := c.GetQuery("level"); exists {
|
||||
value, parseErr := strconv.Atoi(raw)
|
||||
if parseErr != nil {
|
||||
Fail(c, parseErr.Error())
|
||||
return
|
||||
}
|
||||
filter.Level = &value
|
||||
}
|
||||
items, total, err := h.service.DictionaryDetailsRequest(c.Request.Context(), p, size, filter)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: p, PageSize: size}, "获取成功")
|
||||
}
|
||||
func (h *Dictionary) Tree(byType bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
rawID := c.Query("sysDictionaryID")
|
||||
id, parseErr := strconv.ParseUint(rawID, 10, 32)
|
||||
typ := ""
|
||||
if byType {
|
||||
typ = c.Query("type")
|
||||
if typ == "" {
|
||||
Fail(c, "字典类型不能为空")
|
||||
return
|
||||
}
|
||||
} else if rawID == "" {
|
||||
Fail(c, "字典ID不能为空")
|
||||
return
|
||||
} else if parseErr != nil {
|
||||
Fail(c, "字典ID格式错误")
|
||||
return
|
||||
}
|
||||
items, err := h.service.DictionaryTree(c.Request.Context(), uint(id), typ)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"list": items}, "获取成功")
|
||||
}
|
||||
}
|
||||
func (h *Dictionary) DetailsByParent(c *gin.Context) {
|
||||
var req service.DictionaryDetailsByParentRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, err := h.service.DictionaryDetailsByParent(c.Request.Context(), req.DictionaryID, req.ParentID, req.IncludeChildren)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"list": items}, "获取成功")
|
||||
}
|
||||
func (h *Dictionary) Path(c *gin.Context) {
|
||||
rawID := c.Query("id")
|
||||
if rawID == "" {
|
||||
Fail(c, "字典详情ID不能为空")
|
||||
return
|
||||
}
|
||||
id, parseErr := strconv.ParseUint(rawID, 10, 32)
|
||||
if parseErr != nil {
|
||||
Fail(c, "字典详情ID格式错误")
|
||||
return
|
||||
}
|
||||
path, err := h.service.DictionaryPath(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"path": path}, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Email struct{ service *service.EmailService }
|
||||
|
||||
func NewEmail(service *service.EmailService) *Email { return &Email{service: service} }
|
||||
|
||||
func (h *Email) Test(c *gin.Context) {
|
||||
if err := h.service.Test(c.Request.Context()); err != nil {
|
||||
Fail(c, "发送失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "发送成功")
|
||||
}
|
||||
|
||||
func (h *Email) Send(c *gin.Context) {
|
||||
var req service.SendEmailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Send(c.Request.Context(), req.To, req.Subject, req.Body); err != nil {
|
||||
Fail(c, "发送失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "发送成功")
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"kra/internal/service"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Export struct {
|
||||
service *service.ExportService
|
||||
}
|
||||
|
||||
func NewExport(service *service.ExportService) *Export {
|
||||
return &Export{service: service}
|
||||
}
|
||||
|
||||
func exportParams(values url.Values) (map[string]string, error) {
|
||||
out := map[string]string{}
|
||||
nested, err := url.ParseQuery(values.Get("params"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for key, items := range nested {
|
||||
if len(items) > 0 {
|
||||
out[key] = items[0]
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func exportIssueParams(values url.Values, blank bool) (map[string]string, error) {
|
||||
params, err := exportParams(values)
|
||||
if err != nil && blank {
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
return params, err
|
||||
}
|
||||
|
||||
func (h *Export) Create(c *gin.Context) {
|
||||
var req service.ExportTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "Name值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.CreateRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
func (h *Export) Update(c *gin.Context) {
|
||||
var req service.ExportTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "Name值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Export) Delete(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
// Deleting an empty model is rejected by GORM's global-update guard in the
|
||||
// reference endpoint. Preserve the same externally visible failure.
|
||||
if req.ID == 0 {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(c.Request.Context(), []uint{req.ID}); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Export) DeleteMany(c *gin.Context) {
|
||||
var req service.IDsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(c.Request.Context(), req.IDs); err != nil {
|
||||
Fail(c, "批量删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
func (h *Export) Find(c *gin.Context) {
|
||||
var req service.ExportTemplateRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.service.Template(c.Request.Context(), req.ID, "")
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, gin.H{"resysExportTemplate": item})
|
||||
}
|
||||
func (h *Export) List(c *gin.Context) {
|
||||
p, size, err := page(c)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
start, startErr := parseTime(c.Query("startCreatedAt"))
|
||||
end, endErr := parseTime(c.Query("endCreatedAt"))
|
||||
if startErr != nil || endErr != nil {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.TemplatesFilter(c.Request.Context(), p, size, c.Query("name"), c.Query("tableName"), c.Query("templateID"), start, end)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: p, PageSize: size}, "获取成功")
|
||||
}
|
||||
func (h *Export) Preview(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
Fail(c, "模板ID不能为空")
|
||||
return
|
||||
}
|
||||
params, _ := exportParams(c.Request.URL.Query())
|
||||
sql, err := h.service.Preview(c.Request.Context(), templateID, params)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, gin.H{"sql": sql})
|
||||
}
|
||||
|
||||
func (h *Export) Issue(blank bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
Fail(c, "模板ID不能为空")
|
||||
return
|
||||
}
|
||||
params, err := exportIssueParams(c.Request.URL.Query(), blank)
|
||||
if err != nil {
|
||||
Fail(c, "解析 params 参数失败")
|
||||
return
|
||||
}
|
||||
token, err := h.service.IssueToken(c.Request.Context(), templateID, params, blank)
|
||||
if err != nil {
|
||||
Fail(c, "导出令牌创建失败")
|
||||
return
|
||||
}
|
||||
path := "/sysExportTemplate/exportExcelByToken?token=" + token
|
||||
if blank {
|
||||
path = "/sysExportTemplate/exportTemplateByToken?token=" + token
|
||||
}
|
||||
OKWithData(c, path)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Export) Import(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
Fail(c, "模板ID不能为空")
|
||||
return
|
||||
}
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
Fail(c, "文件获取失败")
|
||||
return
|
||||
}
|
||||
opened, err := file.Open()
|
||||
if err != nil {
|
||||
Fail(c, "读取文件失败")
|
||||
return
|
||||
}
|
||||
defer opened.Close()
|
||||
if err = h.service.Import(c.Request.Context(), templateID, opened); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "导入成功")
|
||||
}
|
||||
|
||||
func (h *Export) Download(expectBlank bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
Fail(c, "导出token不能为空")
|
||||
return
|
||||
}
|
||||
value, err := h.service.ConsumeToken(c.Request.Context(), token, expectBlank)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, service.ErrExportTokenMalformed):
|
||||
Fail(c, "解析导出参数失败")
|
||||
case errors.Is(err, service.ErrExportTokenType):
|
||||
Fail(c, "token类型错误")
|
||||
default:
|
||||
Fail(c, "导出token无效或已过期")
|
||||
}
|
||||
return
|
||||
}
|
||||
var data []byte
|
||||
var name string
|
||||
if expectBlank {
|
||||
data, name, err = h.service.ExportBlankTemplate(c.Request.Context(), value.TemplateID)
|
||||
} else {
|
||||
data, name, err = h.service.Export(c.Request.Context(), value.TemplateID, value.Params)
|
||||
}
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
if expectBlank {
|
||||
name = strings.TrimSuffix(name, "_template.xlsx") + "模板.xlsx"
|
||||
} else {
|
||||
name = strings.TrimSuffix(name, ".xlsx") + strings.ReplaceAll(uuid.NewString(), "-", "")[:6] + ".xlsx"
|
||||
}
|
||||
c.Header("Content-Disposition", "attachment; filename="+name)
|
||||
c.Header("success", "true")
|
||||
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExportParamsRejectsMalformedNestedQuery(t *testing.T) {
|
||||
_, err := exportParams(url.Values{"params": {"name=%zz"}})
|
||||
if err == nil {
|
||||
t.Fatal("exportParams accepted malformed nested query")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportParamsUsesFirstValue(t *testing.T) {
|
||||
got, err := exportParams(url.Values{"params": {"name=first&name=second"}})
|
||||
if err != nil {
|
||||
t.Fatalf("exportParams returned error: %v", err)
|
||||
}
|
||||
if got["name"] != "first" {
|
||||
t.Fatalf("exportParams name = %q, want first", got["name"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportIssueParamsKeepsBlankTemplateCompatible(t *testing.T) {
|
||||
got, err := exportIssueParams(url.Values{"params": {"name=%zz"}}, true)
|
||||
if err != nil {
|
||||
t.Fatalf("blank template params returned error: %v", err)
|
||||
}
|
||||
if len(got) != 0 {
|
||||
t.Fatalf("blank template params = %#v, want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportIssueParamsRejectsMalformedExcelParams(t *testing.T) {
|
||||
_, err := exportIssueParams(url.Values{"params": {"name=%zz"}}, false)
|
||||
if err == nil {
|
||||
t.Fatal("Excel export accepted malformed nested query")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"kra/internal/biz"
|
||||
"kra/internal/server/httpx"
|
||||
"kra/internal/server/middleware"
|
||||
)
|
||||
|
||||
const (
|
||||
CodeSuccess = httpx.CodeSuccess
|
||||
CodeError = httpx.CodeError
|
||||
CodePasswordChangeRequired = httpx.CodePasswordChangeRequired
|
||||
)
|
||||
|
||||
type Response = httpx.Response
|
||||
type PageResult = httpx.PageResult
|
||||
|
||||
func Write(c *gin.Context, code int, data any, message string) { httpx.Write(c, code, data, message) }
|
||||
func OK(c *gin.Context) { httpx.OK(c) }
|
||||
func OKWithData(c *gin.Context, data any) { httpx.OKWithData(c, data) }
|
||||
func Fail(c *gin.Context, message string) { httpx.Fail(c, message) }
|
||||
func NoAuth(c *gin.Context, message string) { httpx.NoAuth(c, message) }
|
||||
func SetTokenCookie(c *gin.Context, value string, maxAge int) { httpx.SetTokenCookie(c, value, maxAge) }
|
||||
func Claims(c *gin.Context) *biz.AuthClaims { return middleware.Claims(c) }
|
||||
@@ -0,0 +1,54 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type IntegrationConfig struct {
|
||||
service *service.IntegrationConfigService
|
||||
}
|
||||
|
||||
func NewIntegrationConfig(service *service.IntegrationConfigService) *IntegrationConfig {
|
||||
return &IntegrationConfig{service: service}
|
||||
}
|
||||
|
||||
func (h *IntegrationConfig) List(c *gin.Context) {
|
||||
configs, err := h.service.List(c.Request.Context(), c.Param("kind"))
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, configs)
|
||||
}
|
||||
|
||||
func (h *IntegrationConfig) Find(c *gin.Context) {
|
||||
config, err := h.service.Find(c.Request.Context(), c.Param("kind"), c.Param("provider"))
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, config)
|
||||
}
|
||||
|
||||
func (h *IntegrationConfig) Save(c *gin.Context) {
|
||||
var req service.IntegrationConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Save(c.Request.Context(), c.Param("kind"), c.Param("provider"), &req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OK(c)
|
||||
}
|
||||
|
||||
func (h *IntegrationConfig) Delete(c *gin.Context) {
|
||||
if err := h.service.Delete(c.Request.Context(), c.Param("kind"), c.Param("provider")); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OK(c)
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"kra/internal/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Media struct{ service *service.MediaService }
|
||||
|
||||
func NewMedia(service *service.MediaService) *Media { return &Media{service: service} }
|
||||
|
||||
func (h *Media) limitMultipartBody(c *gin.Context) int64 {
|
||||
limit := h.service.MediaConfig().EffectiveMaxFileSize()
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, limit+(1<<20))
|
||||
return limit
|
||||
}
|
||||
|
||||
func rejectMediaTooLarge(c *gin.Context, err error, message string) bool {
|
||||
var tooLarge *http.MaxBytesError
|
||||
if !errors.As(err, &tooLarge) {
|
||||
return false
|
||||
}
|
||||
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, Response{Code: CodeError, Data: gin.H{}, Msg: message})
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *Media) Upload(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil {
|
||||
Fail(c, "接收文件失败")
|
||||
return
|
||||
}
|
||||
limit := h.limitMultipartBody(c)
|
||||
header, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
if rejectMediaTooLarge(c, err, "文件超过大小上限") {
|
||||
return
|
||||
}
|
||||
Fail(c, "接收文件失败")
|
||||
return
|
||||
}
|
||||
if header.Size > limit {
|
||||
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, Response{Code: CodeError, Data: gin.H{}, Msg: "文件超过大小上限"})
|
||||
return
|
||||
}
|
||||
opened, err := header.Open()
|
||||
if err != nil {
|
||||
// Let the upload service surface this as the generic upload
|
||||
// failure; keep the endpoint message consistent.
|
||||
Fail(c, "上传文件失败")
|
||||
return
|
||||
}
|
||||
defer opened.Close()
|
||||
category, _ := strconv.Atoi(c.DefaultPostForm("classId", "0"))
|
||||
save := c.DefaultQuery("noSave", "0") == "0"
|
||||
item, err := h.service.Upload(c.Request.Context(), claims.ID, header.Filename, header.Header.Get("Content-Type"), category, opened, save)
|
||||
if err != nil {
|
||||
Fail(c, "上传文件失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"file": item}, "上传成功")
|
||||
}
|
||||
|
||||
func (h *Media) List(c *gin.Context) {
|
||||
var req service.MediaListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.MediaListRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *Media) Delete(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Media) DeleteMany(c *gin.Context) {
|
||||
var req service.MediaBatchDeleteRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
failed := []uint{}
|
||||
for _, id := range req.IDs {
|
||||
if h.service.Delete(c.Request.Context(), id) != nil {
|
||||
failed = append(failed, id)
|
||||
}
|
||||
}
|
||||
if len(failed) > 0 {
|
||||
Write(c, CodeSuccess, gin.H{"failedIds": failed}, "部分文件删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
func (h *Media) Find(c *gin.Context) {
|
||||
id, parseErr := strconv.ParseUint(c.Query("id"), 10, 64)
|
||||
if parseErr != nil {
|
||||
Fail(c, "文件ID非法")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Media(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, item)
|
||||
}
|
||||
func (h *Media) Rename(c *gin.Context) {
|
||||
var req service.RenameMediaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Rename(c.Request.Context(), req.ID, req.Name); err != nil {
|
||||
Fail(c, "编辑失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "编辑成功")
|
||||
}
|
||||
func (h *Media) ImportURLs(c *gin.Context) {
|
||||
var req []service.ImportMediaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.ImportURLRequests(c.Request.Context(), req); err != nil {
|
||||
Fail(c, "导入URL失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "导入URL成功")
|
||||
}
|
||||
func (h *Media) Storage(c *gin.Context) {
|
||||
var req service.StorageListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, next, more, err := h.service.Storage(c.Request.Context(), req.Prefix, req.Cursor, req.Limit)
|
||||
if err != nil {
|
||||
Fail(c, "列举存储桶文件失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"list": items, "nextCursor": next, "hasMore": more}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Media) Categories(c *gin.Context) {
|
||||
items, err := h.service.Categories(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取分类列表失败")
|
||||
return
|
||||
}
|
||||
OKWithData(c, items)
|
||||
}
|
||||
func (h *Media) SaveCategory(c *gin.Context) {
|
||||
var req service.CategoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if err := h.service.SaveCategoryRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建/更新失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建/更新成功")
|
||||
}
|
||||
func (h *Media) DeleteCategory(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if c.ShouldBindJSON(&req) != nil || req.ID == 0 {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteCategory(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Media) InitUpload(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
var req service.InitUploadRequest
|
||||
if claims == nil {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if config := h.service.MediaConfig(); config.MaxFileSize > 0 && req.FileSize > config.MaxFileSize {
|
||||
Fail(c, "文件超过大小上限")
|
||||
return
|
||||
}
|
||||
result, err := h.service.InitUpload(c.Request.Context(), claims.ID, req.FileName, req.FileHash, req.FileSize, req.ChunkSize, req.ChunkTotal)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, result, "成功")
|
||||
}
|
||||
func (h *Media) SaveChunk(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil {
|
||||
Fail(c, "接收分片失败")
|
||||
return
|
||||
}
|
||||
limit := h.limitMultipartBody(c)
|
||||
header, err := c.FormFile("chunk")
|
||||
if err != nil {
|
||||
if rejectMediaTooLarge(c, err, "分片超过大小上限") {
|
||||
return
|
||||
}
|
||||
Fail(c, "接收分片失败")
|
||||
return
|
||||
}
|
||||
if header.Size > limit {
|
||||
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, Response{Code: CodeError, Data: gin.H{}, Msg: "分片超过大小上限"})
|
||||
return
|
||||
}
|
||||
uploadID, parseErr := strconv.ParseUint(c.PostForm("uploadId"), 10, 64)
|
||||
if parseErr != nil || uploadID == 0 {
|
||||
Fail(c, "上传会话 ID 非法")
|
||||
return
|
||||
}
|
||||
index, parseErr := strconv.Atoi(c.PostForm("chunkIndex"))
|
||||
if parseErr != nil || index < 0 {
|
||||
Fail(c, "分片序号非法")
|
||||
return
|
||||
}
|
||||
opened, err := header.Open()
|
||||
if err != nil {
|
||||
Fail(c, "分片读取失败")
|
||||
return
|
||||
}
|
||||
defer opened.Close()
|
||||
if err = h.service.SaveChunk(c.Request.Context(), claims.ID, uint(uploadID), index, c.PostForm("chunkHash"), opened); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "ok")
|
||||
}
|
||||
func (h *Media) CompleteUpload(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
var req service.CompleteUploadRequest
|
||||
if claims == nil {
|
||||
Fail(c, "参数错误")
|
||||
return
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.service.CompleteUpload(c.Request.Context(), claims.ID, req.UploadID)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"media": item}, "成功")
|
||||
}
|
||||
func (h *Media) CancelUpload(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
id, _ := strconv.ParseUint(c.Param("uploadId"), 10, 64)
|
||||
if claims == nil {
|
||||
Fail(c, "未登录")
|
||||
return
|
||||
}
|
||||
if err := h.service.CancelUpload(c.Request.Context(), claims.ID, uint(id)); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "已取消")
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Menu struct{ service *service.MenuService }
|
||||
|
||||
func NewMenu(service *service.MenuService) *Menu { return &Menu{service: service} }
|
||||
|
||||
func (h *Menu) List(c *gin.Context) {
|
||||
items, err := h.service.Tree(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, items, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Menu) Tree(c *gin.Context) {
|
||||
items, err := h.service.Tree(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"menus": items}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Menu) Create(c *gin.Context) {
|
||||
var req service.MenuRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Path == "" {
|
||||
Fail(c, "Path值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "Name值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Component == "" {
|
||||
Fail(c, "Component值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Sort < 0 {
|
||||
Fail(c, "Sort长度或值不在合法范围,ge=0")
|
||||
return
|
||||
}
|
||||
if req.Meta.Title == "" {
|
||||
Fail(c, "Title值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.Create(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "添加失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "添加成功")
|
||||
}
|
||||
|
||||
func (h *Menu) Update(c *gin.Context) {
|
||||
var req service.MenuRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Path == "" {
|
||||
Fail(c, "Path值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "Name值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Component == "" {
|
||||
Fail(c, "Component值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Sort < 0 {
|
||||
Fail(c, "Sort长度或值不在合法范围,ge=0")
|
||||
return
|
||||
}
|
||||
if req.Meta.Title == "" {
|
||||
Fail(c, "Title值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.Update(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
|
||||
func (h *Menu) Delete(c *gin.Context) {
|
||||
var req service.DeleteMenuRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(c.Request.Context(), uint(req.ID)); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Menu) Find(c *gin.Context) {
|
||||
var req service.GetMenuRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Find(c.Request.Context(), uint(req.ID))
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"menu": item}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Menu) SetAuthorityMenus(c *gin.Context) {
|
||||
var req service.SetAuthorityMenusRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetAuthorityMenus(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "添加失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "添加成功")
|
||||
}
|
||||
|
||||
func (h *Menu) AuthorityMenus(c *gin.Context) {
|
||||
var req service.GetAuthorityMenusRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
menus, err := h.service.AuthorityMenus(c.Request.Context(), req.AuthorityID)
|
||||
if err != nil {
|
||||
Write(c, CodeError, gin.H{"menus": menus}, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"menus": menus}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Menu) RoleIDs(c *gin.Context) {
|
||||
var req service.SetMenuRolesRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.MenuID == 0 {
|
||||
Fail(c, "菜单ID不能为空")
|
||||
return
|
||||
}
|
||||
ids, err := h.service.RoleIDs(c.Request.Context(), req.MenuID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
defaultIDs, err := h.service.DefaultRouterRoleIDs(c.Request.Context(), req.MenuID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败"+err.Error())
|
||||
return
|
||||
}
|
||||
if defaultIDs == nil {
|
||||
defaultIDs = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"authorityIds": ids, "defaultRouterAuthorityIds": defaultIDs}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Menu) SetRoles(c *gin.Context) {
|
||||
var req service.SetMenuRolesRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.MenuID == 0 {
|
||||
Fail(c, "菜单ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.SetRoles(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Navigation struct{ service *service.UserService }
|
||||
|
||||
func NewNavigation(service *service.UserService) *Navigation { return &Navigation{service: service} }
|
||||
func (h *Navigation) Menu(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
menus, err := h.service.Menus(c.Request.Context(), claims.AuthorityID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"menus": menus}, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Organization struct {
|
||||
departments *service.DepartmentService
|
||||
positions *service.PositionService
|
||||
}
|
||||
|
||||
func NewOrganization(departments *service.DepartmentService, positions *service.PositionService) *Organization {
|
||||
return &Organization{departments: departments, positions: positions}
|
||||
}
|
||||
|
||||
func (h *Organization) ListDepartments(c *gin.Context) {
|
||||
var req service.DepartmentListRequest
|
||||
_ = c.ShouldBindJSON(&req)
|
||||
items, err := h.departments.Departments(c.Request.Context(), req.Name)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, items, "获取成功")
|
||||
}
|
||||
func (h *Organization) CreateDepartment(c *gin.Context) {
|
||||
var req service.DepartmentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "部门名称不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.departments.Create(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
func (h *Organization) UpdateDepartment(c *gin.Context) {
|
||||
var req service.DepartmentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "部门ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.departments.Update(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Organization) DeleteDepartment(c *gin.Context) {
|
||||
var req service.DeleteDepartmentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.departments.Delete(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Organization) FindDepartment(c *gin.Context) {
|
||||
var req service.DeleteDepartmentRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.departments.Department(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, item, "获取成功")
|
||||
}
|
||||
func (h *Organization) DepartmentUsers(c *gin.Context) {
|
||||
var req service.SetDepartmentUsersRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
ids, err := h.departments.UserIDs(c.Request.Context(), req.DepartmentID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, ids, "获取成功")
|
||||
}
|
||||
func (h *Organization) SetDepartmentUsers(c *gin.Context) {
|
||||
var req service.SetDepartmentUsersRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.DepartmentID == 0 {
|
||||
Fail(c, "部门ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.departments.SetUsers(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
func (h *Organization) SetUserDepartments(c *gin.Context) {
|
||||
var req service.SetUserDepartmentsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "用户ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.departments.SetUserDepartments(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
|
||||
func (h *Organization) ListPositions(c *gin.Context) {
|
||||
var req service.PositionListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.positions.Positions(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
func (h *Organization) CreatePosition(c *gin.Context) {
|
||||
var req service.PositionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
Fail(c, "岗位名称不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.positions.Create(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
func (h *Organization) UpdatePosition(c *gin.Context) {
|
||||
var req service.PositionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "岗位ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.positions.Update(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
func (h *Organization) DeletePosition(c *gin.Context) {
|
||||
var req service.DeletePositionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.positions.Delete(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Organization) FindPosition(c *gin.Context) {
|
||||
var req service.DeletePositionRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
item, err := h.positions.Position(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, item, "获取成功")
|
||||
}
|
||||
func (h *Organization) PositionUsers(c *gin.Context) {
|
||||
var req service.SetPositionUsersRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
ids, err := h.positions.UserIDs(c.Request.Context(), req.PositionID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
if ids == nil {
|
||||
ids = []uint{}
|
||||
}
|
||||
Write(c, CodeSuccess, ids, "获取成功")
|
||||
}
|
||||
func (h *Organization) SetPositionUsers(c *gin.Context) {
|
||||
var req service.SetPositionUsersRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.PositionID == 0 {
|
||||
Fail(c, "岗位ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.positions.SetUsers(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
func (h *Organization) SetUserPositions(c *gin.Context) {
|
||||
var req service.SetUserPositionsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "用户ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.positions.SetUserPositions(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Parameter struct {
|
||||
service *service.ParameterService
|
||||
}
|
||||
|
||||
func NewParameter(service *service.ParameterService) *Parameter {
|
||||
return &Parameter{service: service}
|
||||
}
|
||||
|
||||
func (h *Parameter) Create(c *gin.Context) {
|
||||
var req service.SystemParameterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.CreateParameterRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "创建失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
|
||||
func (h *Parameter) Update(c *gin.Context) {
|
||||
var req service.SystemParameterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateParameterRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
|
||||
func (h *Parameter) Delete(c *gin.Context) {
|
||||
if err := h.service.DeleteParameters(c.Request.Context(), []string{c.Query("ID")}); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Parameter) DeleteMany(c *gin.Context) {
|
||||
ids := c.QueryArray("IDs[]")
|
||||
if err := h.service.DeleteParameters(c.Request.Context(), ids); err != nil {
|
||||
Fail(c, "批量删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
|
||||
func (h *Parameter) Find(c *gin.Context) {
|
||||
item, err := h.service.ParameterByID(c.Request.Context(), c.Query("ID"))
|
||||
if err != nil {
|
||||
Fail(c, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, item)
|
||||
}
|
||||
|
||||
func (h *Parameter) Get(c *gin.Context) {
|
||||
item, err := h.service.ParameterByKey(c.Request.Context(), c.Query("key"))
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, item, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Parameter) List(c *gin.Context) {
|
||||
var req service.SystemParameterSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.ParametersFilter(c.Request.Context(), req.Page, req.PageSize, req.Name, req.Key, req.StartCreatedAt, req.EndCreatedAt)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"io"
|
||||
"kra/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Payment struct{ service *service.PaymentService }
|
||||
|
||||
func NewPayment(service *service.PaymentService) *Payment { return &Payment{service: service} }
|
||||
func (h *Payment) Order(c *gin.Context) {
|
||||
var req service.PaymentQueryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
order, err := h.service.Order(c.Request.Context(), req.Provider, req.TradeNo)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, order)
|
||||
}
|
||||
|
||||
func (h *Payment) OrderByPath(c *gin.Context) {
|
||||
order, err := h.service.Order(c.Request.Context(), c.Param("provider"), c.Param("tradeNo"))
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, order)
|
||||
}
|
||||
|
||||
func (h *Payment) RefundByPath(c *gin.Context) {
|
||||
var req struct {
|
||||
Amount int64 `json:"amount"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := h.service.Refund(c.Request.Context(), &service.PaymentRefundRequest{
|
||||
Provider: c.Param("provider"), TradeNo: c.Param("tradeNo"), Amount: req.Amount,
|
||||
})
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
|
||||
func (h *Payment) FulfillByPath(c *gin.Context) {
|
||||
result, err := h.service.Fulfill(c.Request.Context(), &service.PaymentFulfillRequest{
|
||||
Provider: c.Param("provider"), TradeNo: c.Param("tradeNo"),
|
||||
})
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
|
||||
func (h *Payment) Orders(c *gin.Context) {
|
||||
var req service.PaymentOrderListRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, page, pageSize, err := h.service.Orders(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: page, PageSize: pageSize}, "获取成功")
|
||||
}
|
||||
func (h *Payment) Create(c *gin.Context) {
|
||||
var req service.PaymentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
req.ClientIP = c.ClientIP()
|
||||
result, err := h.service.Create(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
func (h *Payment) Query(c *gin.Context) {
|
||||
var req service.PaymentQueryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := h.service.Query(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
func (h *Payment) Refund(c *gin.Context) {
|
||||
var req service.PaymentRefundRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := h.service.Refund(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
|
||||
func (h *Payment) Fulfill(c *gin.Context) {
|
||||
var req service.PaymentFulfillRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := h.service.Fulfill(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, result)
|
||||
}
|
||||
func (h *Payment) Callback(c *gin.Context) {
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 8<<20)
|
||||
raw, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
writePaymentCallbackAck(c, service.DefaultPaymentCallbackAck(c.Param("provider"), false))
|
||||
return
|
||||
}
|
||||
headers := map[string]string{}
|
||||
for k, v := range c.Request.Header {
|
||||
if len(v) > 0 {
|
||||
headers[k] = v[0]
|
||||
}
|
||||
}
|
||||
query := map[string]string{}
|
||||
for k, v := range c.Request.URL.Query() {
|
||||
if len(v) > 0 {
|
||||
query[k] = v[0]
|
||||
}
|
||||
}
|
||||
ack, err := h.service.Callback(c.Request.Context(), &service.PaymentCallbackRequest{Provider: c.Param("provider"), Headers: headers, Body: raw, Query: query})
|
||||
writePaymentCallbackAck(c, ack)
|
||||
_ = err
|
||||
}
|
||||
|
||||
func writePaymentCallbackAck(c *gin.Context, ack service.PaymentCallbackAck) {
|
||||
if ack.StatusCode == 0 {
|
||||
ack.StatusCode = http.StatusInternalServerError
|
||||
}
|
||||
if ack.ContentType != "" {
|
||||
c.Header("Content-Type", ack.ContentType)
|
||||
}
|
||||
c.Status(ack.StatusCode)
|
||||
if len(ack.Body) > 0 {
|
||||
_, _ = c.Writer.Write(ack.Body)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"kra/internal/service"
|
||||
)
|
||||
|
||||
func TestWritePaymentCallbackAckDoesNotExposeError(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
recorder := httptest.NewRecorder()
|
||||
context, _ := gin.CreateTestContext(recorder)
|
||||
writePaymentCallbackAck(context, service.PaymentCallbackAck{
|
||||
StatusCode: 500,
|
||||
ContentType: "text/plain; charset=utf-8",
|
||||
Body: []byte("failure"),
|
||||
})
|
||||
if recorder.Code != 500 {
|
||||
t.Fatalf("status = %d, want 500", recorder.Code)
|
||||
}
|
||||
if recorder.Body.String() != "failure" {
|
||||
t.Fatalf("body = %q, want fixed failure ack", recorder.Body.String())
|
||||
}
|
||||
if recorder.Body.String() == "internal order resolver details" {
|
||||
t.Fatal("internal error was exposed in callback response")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Permission struct{ service *service.PermissionService }
|
||||
|
||||
func NewPermission(service *service.PermissionService) *Permission {
|
||||
return &Permission{service: service}
|
||||
}
|
||||
|
||||
func (h *Permission) Buttons(c *gin.Context) {
|
||||
var req service.GetAuthorityButtonsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
selected, err := h.service.SelectedButtons(c.Request.Context(), req.AuthorityID, req.MenuID)
|
||||
if err != nil {
|
||||
Fail(c, "查询失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"selected": selected}, "查询成功")
|
||||
}
|
||||
|
||||
func (h *Permission) SetButtons(c *gin.Context) {
|
||||
var req service.SetAuthorityButtonsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.SetSelectedButtons(c.Request.Context(), req.AuthorityID, req.MenuID, req.Selected); err != nil {
|
||||
Fail(c, "分配失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "分配成功")
|
||||
}
|
||||
|
||||
func (h *Permission) CanRemoveButton(c *gin.Context) {
|
||||
allowed, err := h.service.CanRemoveButton(c.Request.Context(), c.Query("id"))
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if !allowed {
|
||||
Fail(c, "此按钮正在被使用无法删除")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package handler
|
||||
|
||||
import "github.com/google/wire"
|
||||
|
||||
// ProviderSet wires the system HTTP handlers.
|
||||
var ProviderSet = wire.NewSet(
|
||||
NewAuthority, NewMenu, NewAPI, NewPermission, NewOrganization,
|
||||
NewAnnouncement, NewEmail, NewPayment, NewTask, NewMedia, NewAudit,
|
||||
NewExport, NewVersion, NewDictionary, NewParameter, NewAPIToken,
|
||||
NewSystemConfig, NewPublic, NewUser, NewNavigation, NewSession, NewSet,
|
||||
NewIntegrationConfig,
|
||||
)
|
||||
@@ -0,0 +1,167 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz"
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
)
|
||||
|
||||
type Public struct {
|
||||
auth *service.AuthService
|
||||
system *service.SystemConfigService
|
||||
settings *service.SecurityService
|
||||
store *captchaStore
|
||||
}
|
||||
|
||||
func NewPublic(auth *service.AuthService, system *service.SystemConfigService, settings *service.SecurityService) *Public {
|
||||
return &Public{auth: auth, system: system, settings: settings, store: &captchaStore{service: settings}}
|
||||
}
|
||||
|
||||
func (h *Public) captchaConfig() (int, int, int) {
|
||||
config := h.settings.CaptchaSettings()
|
||||
return config.KeyLong, config.ImageWidth, config.ImageHeight
|
||||
}
|
||||
|
||||
func (h *Public) Captcha(c *gin.Context) {
|
||||
keyLong, width, height := h.captchaConfig()
|
||||
security, err := h.settings.CurrentSecurity(c.Request.Context())
|
||||
if err != nil || security == nil {
|
||||
Fail(c, "安全服务暂不可用")
|
||||
return
|
||||
}
|
||||
openCaptcha := true
|
||||
if security != nil {
|
||||
keyLong, width, height = security.KeyLong, security.ImgWidth, security.ImgHeight
|
||||
ttl := time.Duration(security.CaptchaTimeout) * time.Second
|
||||
failures, counterErr := h.settings.EnsureLoginIPCounter(c.Request.Context(), c.ClientIP(), ttl)
|
||||
if counterErr != nil {
|
||||
Fail(c, "安全服务暂不可用")
|
||||
return
|
||||
}
|
||||
openCaptcha = security.CaptchaOpen == 0 || failures > security.CaptchaOpen
|
||||
}
|
||||
driver := base64Captcha.NewDriverDigit(height, width, keyLong, 0.7, 80)
|
||||
id, picture, _, err := base64Captcha.NewCaptcha(driver, h.store).Generate()
|
||||
if err != nil {
|
||||
Fail(c, "验证码获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"captchaId": id, "picPath": picture, "captchaLength": keyLong, "openCaptcha": openCaptcha}, "验证码获取成功")
|
||||
}
|
||||
|
||||
func (h *Public) Login(c *gin.Context) {
|
||||
var req service.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Username == "" {
|
||||
Fail(c, "Username值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Password == "" {
|
||||
Fail(c, "Password值不能为空")
|
||||
return
|
||||
}
|
||||
result, err := h.auth.Login(c.Request.Context(), &req, c.ClientIP(), c.Request.UserAgent())
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, biz.ErrAccountLocked):
|
||||
var locked *biz.AccountLockedError
|
||||
errors.As(err, &locked)
|
||||
minutes := 0
|
||||
if locked != nil {
|
||||
minutes = locked.Minutes
|
||||
}
|
||||
Fail(c, "账号已锁定,请 "+strconv.Itoa(minutes)+" 分钟后再试")
|
||||
case errors.Is(err, biz.ErrCaptchaInvalid):
|
||||
Fail(c, "验证码错误")
|
||||
case errors.Is(err, biz.ErrUserDisabled):
|
||||
Fail(c, "用户被禁止登录")
|
||||
case errors.Is(err, biz.ErrTokenIssue):
|
||||
Fail(c, "获取token失败")
|
||||
case errors.Is(err, biz.ErrLoginState):
|
||||
Fail(c, "设置登录状态失败")
|
||||
case errors.Is(err, biz.ErrTokenRevoke):
|
||||
Fail(c, "jwt作废失败")
|
||||
default:
|
||||
Fail(c, "用户名不存在或者密码错误")
|
||||
}
|
||||
return
|
||||
}
|
||||
maxAge := int(time.UnixMilli(result.ExpiresAt).Unix() - time.Now().Unix())
|
||||
SetTokenCookie(c, result.Token, maxAge)
|
||||
Write(c, CodeSuccess, result, "登录成功")
|
||||
}
|
||||
|
||||
func (h *Public) CheckDatabase(c *gin.Context) {
|
||||
initialized, err := h.system.IsInitialized(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "数据库状态检查失败")
|
||||
return
|
||||
}
|
||||
message := "数据库无需初始化"
|
||||
if !initialized {
|
||||
message = "前往初始化数据库"
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"needInit": !initialized}, message)
|
||||
}
|
||||
|
||||
func (h *Public) InitializeDatabase(engine *gin.Engine) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
initialized, err := h.system.IsInitialized(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "数据库状态检查失败")
|
||||
return
|
||||
}
|
||||
if initialized {
|
||||
Fail(c, "已存在数据库配置")
|
||||
return
|
||||
}
|
||||
var input service.DatabaseInitRequest
|
||||
if c.ShouldBindJSON(&input) != nil {
|
||||
Fail(c, "参数校验不通过")
|
||||
return
|
||||
}
|
||||
routes := engine.Routes()
|
||||
values := make([]service.Route, 0, len(routes))
|
||||
for _, route := range routes {
|
||||
values = append(values, service.Route{Path: route.Path, Method: route.Method})
|
||||
}
|
||||
if err := h.system.InitializeRoutes(c.Request.Context(), &input, values); err != nil {
|
||||
Fail(c, "自动创建数据库失败,请查看后台日志,检查后在进行初始化")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "自动创建数据库成功")
|
||||
}
|
||||
}
|
||||
|
||||
type captchaStore struct {
|
||||
service *service.SecurityService
|
||||
}
|
||||
|
||||
func (s *captchaStore) Set(id, value string) error {
|
||||
expiration := s.service.CaptchaSettings().StoreExpiration
|
||||
return s.service.SetCaptcha(context.Background(), id, value, expiration)
|
||||
}
|
||||
func (s *captchaStore) Get(id string, clear bool) string {
|
||||
value, ok, err := s.service.GetCaptcha(context.Background(), id)
|
||||
if err != nil || !ok {
|
||||
return ""
|
||||
}
|
||||
if clear {
|
||||
_ = s.service.DeleteCaptcha(context.Background(), id)
|
||||
}
|
||||
return value
|
||||
}
|
||||
func (s *captchaStore) Verify(id, answer string, clear bool) bool {
|
||||
return id != "" && answer != "" && strings.EqualFold(s.Get(id, clear), answer)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func page(c *gin.Context) (int, int, error) {
|
||||
var value, size int
|
||||
if raw, exists := c.GetQuery("page"); exists && raw != "" {
|
||||
parsed, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
value = parsed
|
||||
}
|
||||
if raw, exists := c.GetQuery("pageSize"); exists && raw != "" {
|
||||
parsed, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
size = parsed
|
||||
}
|
||||
return value, size, nil
|
||||
}
|
||||
|
||||
func IDsFromQuery(c *gin.Context) []uint {
|
||||
values := c.QueryArray("IDs[]")
|
||||
ids := make([]uint, 0, len(values))
|
||||
for _, value := range values {
|
||||
id, _ := strconv.ParseUint(value, 10, 64)
|
||||
if id > 0 {
|
||||
ids = append(ids, uint(id))
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Session struct{ tokens *service.TokenService }
|
||||
|
||||
func NewSession(tokens *service.TokenService) *Session { return &Session{tokens: tokens} }
|
||||
func (h *Session) Logout(c *gin.Context) {
|
||||
token := c.GetHeader("x-token")
|
||||
if token == "" {
|
||||
token, _ = c.Cookie("x-token")
|
||||
}
|
||||
if err := h.tokens.BlacklistToken(c.Request.Context(), token); err != nil {
|
||||
Fail(c, "jwt作废失败")
|
||||
return
|
||||
}
|
||||
SetTokenCookie(c, "", -1)
|
||||
Write(c, CodeSuccess, gin.H{}, "jwt作废成功")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package handler
|
||||
|
||||
type Set struct {
|
||||
Authority *Authority
|
||||
Menu *Menu
|
||||
API *API
|
||||
Permission *Permission
|
||||
Organization *Organization
|
||||
Announcement *Announcement
|
||||
Email *Email
|
||||
Payment *Payment
|
||||
Task *Task
|
||||
Media *Media
|
||||
Audit *Audit
|
||||
Export *Export
|
||||
Version *Version
|
||||
Dictionary *Dictionary
|
||||
Parameter *Parameter
|
||||
APIToken *APIToken
|
||||
SystemConfig *SystemConfig
|
||||
Public *Public
|
||||
User *User
|
||||
Navigation *Navigation
|
||||
Session *Session
|
||||
IntegrationConfig *IntegrationConfig
|
||||
}
|
||||
|
||||
func NewSet(authority *Authority, menu *Menu, api *API, permission *Permission, organization *Organization, announcement *Announcement, email *Email, payment *Payment, task *Task, media *Media, audit *Audit, export *Export, version *Version, dictionary *Dictionary, parameter *Parameter, apiToken *APIToken, systemConfig *SystemConfig, public *Public, user *User, navigation *Navigation, session *Session, integrationConfig *IntegrationConfig) *Set {
|
||||
return &Set{Authority: authority, Menu: menu, API: api, Permission: permission, Organization: organization, Announcement: announcement, Email: email, Payment: payment, Task: task, Media: media, Audit: audit, Export: export, Version: version, Dictionary: dictionary, Parameter: parameter, APIToken: apiToken, SystemConfig: systemConfig, Public: public, User: user, Navigation: navigation, Session: session, IntegrationConfig: integrationConfig}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SystemConfig struct {
|
||||
system *service.SystemConfigService
|
||||
settings *service.SecurityService
|
||||
}
|
||||
|
||||
func NewSystemConfig(system *service.SystemConfigService, settings *service.SecurityService) *SystemConfig {
|
||||
return &SystemConfig{system: system, settings: settings}
|
||||
}
|
||||
|
||||
func (h *SystemConfig) GetSecurity(c *gin.Context) {
|
||||
value, err := h.settings.Security(c.Request.Context())
|
||||
if err != nil {
|
||||
Fail(c, "获取安全配置失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, value, "获取成功")
|
||||
}
|
||||
|
||||
func (h *SystemConfig) SetSecurity(c *gin.Context) {
|
||||
var req service.SecurityConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := h.settings.SaveSecurityRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "设置安全配置失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, result, "设置成功")
|
||||
}
|
||||
|
||||
func (h *SystemConfig) Get(c *gin.Context) {
|
||||
value, err := h.system.SystemConfig()
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, value, "获取成功")
|
||||
}
|
||||
|
||||
func (h *SystemConfig) Set(c *gin.Context) {
|
||||
var req service.SetSystemConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.system.SaveSystemConfig(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "设置失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
|
||||
func (h *SystemConfig) Reload(c *gin.Context) {
|
||||
if err := h.system.ReloadConfig(c.Request.Context()); err != nil {
|
||||
Fail(c, "重载系统失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "重载系统成功")
|
||||
}
|
||||
|
||||
func (h *SystemConfig) ServerInfo(c *gin.Context) {
|
||||
server, err := h.system.ServerInfo()
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"server": server}, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kra/internal/service"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Task struct {
|
||||
service *service.TaskService
|
||||
}
|
||||
|
||||
func NewTask(service *service.TaskService) *Task {
|
||||
return &Task{service: service}
|
||||
}
|
||||
|
||||
func (h *Task) Create(c *gin.Context) {
|
||||
var req service.TaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
_, err := h.service.CreateRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "创建失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建成功")
|
||||
}
|
||||
|
||||
func (h *Task) Update(c *gin.Context) {
|
||||
var req service.TaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "更新失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "更新成功")
|
||||
}
|
||||
|
||||
func (h *Task) Delete(c *gin.Context) {
|
||||
var req service.DeleteTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *Task) Toggle(c *gin.Context) {
|
||||
var req service.ToggleTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Toggle(c.Request.Context(), req.ID, req.Enabled); err != nil {
|
||||
Fail(c, "操作失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "操作成功")
|
||||
}
|
||||
|
||||
func (h *Task) Trigger(c *gin.Context) {
|
||||
var req service.DeleteTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Trigger(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "触发失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "已触发, 执行结果见执行日志")
|
||||
}
|
||||
|
||||
func (h *Task) List(c *gin.Context) {
|
||||
var req service.TaskListRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.ListRequest(c.Request.Context(), req.Page, req.PageSize, req.Name, req.ExecutorType, req.Enabled)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Task) Logs(c *gin.Context) {
|
||||
var req service.TaskLogListRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.Logs(c.Request.Context(), req.Page, req.PageSize, req.TaskID, req.Status)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Task) Methods(c *gin.Context) {
|
||||
Write(c, CodeSuccess, gin.H{"methods": h.service.RegisteredMethods()}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Task) AlertStream(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil || claims.ID == 0 {
|
||||
Fail(c, "未获取到用户身份")
|
||||
return
|
||||
}
|
||||
c.Header("Content-Type", "text/event-stream; charset=utf-8")
|
||||
c.Header("Cache-Control", "no-cache, no-transform")
|
||||
c.Header("Connection", "keep-alive")
|
||||
c.Header("X-Accel-Buffering", "no")
|
||||
flusher, ok := c.Writer.(http.Flusher)
|
||||
if !ok {
|
||||
Fail(c, "SSE 不受支持")
|
||||
return
|
||||
}
|
||||
// Remove the normal server deadline for long-lived SSE connections.
|
||||
controller := http.NewResponseController(c.Writer)
|
||||
_ = controller.SetWriteDeadline(time.Time{})
|
||||
_ = controller.SetReadDeadline(time.Time{})
|
||||
events := h.service.Subscribe(claims.ID)
|
||||
defer h.service.Unsubscribe(claims.ID, events)
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
_, _ = fmt.Fprint(c.Writer, ": connected\n\n")
|
||||
flusher.Flush()
|
||||
for {
|
||||
select {
|
||||
case event, open := <-events:
|
||||
if !open {
|
||||
return
|
||||
}
|
||||
_, _ = fmt.Fprintf(c.Writer, "event: timedTask:alert\ndata: %s\n\n", event)
|
||||
flusher.Flush()
|
||||
case <-ticker.C:
|
||||
_, _ = fmt.Fprint(c.Writer, ": ping\n\n")
|
||||
flusher.Flush()
|
||||
case <-c.Request.Context().Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"kra/internal/service"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
service *service.UserService
|
||||
auth *service.AuthService
|
||||
}
|
||||
|
||||
func NewUser(user *service.UserService, auth *service.AuthService) *User {
|
||||
return &User{service: user, auth: auth}
|
||||
}
|
||||
|
||||
func (h *User) List(c *gin.Context) {
|
||||
var req service.UserListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Page == 0 {
|
||||
Fail(c, "Page值不能为空")
|
||||
return
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
Fail(c, "PageSize值不能为空")
|
||||
return
|
||||
}
|
||||
items, total, err := h.service.ListUsersRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *User) Create(c *gin.Context) {
|
||||
var req service.UserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Username == "" {
|
||||
Fail(c, "Username值不能为空")
|
||||
return
|
||||
}
|
||||
if req.Password == "" {
|
||||
Fail(c, "Password值不能为空")
|
||||
return
|
||||
}
|
||||
if req.NickName == "" {
|
||||
Fail(c, "NickName值不能为空")
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
result, err := h.service.CreateUserRequest(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
if service.IsPasswordPolicyError(err) {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if result == nil {
|
||||
result = &service.UserResponse{}
|
||||
}
|
||||
Write(c, CodeError, gin.H{"user": result}, "注册失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"user": result}, "注册成功")
|
||||
}
|
||||
|
||||
func (h *User) Update(c *gin.Context) {
|
||||
var req service.UserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateUserRequest(c.Request.Context(), &req); err != nil {
|
||||
Fail(c, "修改失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
|
||||
func (h *User) UpdateSelf(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
var req service.SelfUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateSelfUserRequest(c.Request.Context(), claims.ID, &req); err != nil {
|
||||
Fail(c, "修改失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
|
||||
func (h *User) Delete(c *gin.Context) {
|
||||
var req service.IDRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.ID == 0 {
|
||||
Fail(c, "ID值不能为空")
|
||||
return
|
||||
}
|
||||
claims := Claims(c)
|
||||
if claims != nil && claims.ID == req.ID {
|
||||
Fail(c, "删除失败, 无法删除自己。")
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteUser(c.Request.Context(), req.ID); err != nil {
|
||||
Fail(c, "删除失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
|
||||
func (h *User) ResetPassword(c *gin.Context) {
|
||||
var req service.ResetPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.ResetPassword(c.Request.Context(), req.ID, req.Password); err != nil {
|
||||
if service.IsPasswordPolicyError(err) {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Fail(c, "重置失败"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "重置成功")
|
||||
}
|
||||
|
||||
func (h *User) ChangePassword(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
var req service.ChangePasswordRequest
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.Password == "" {
|
||||
Fail(c, "Password值不能为空")
|
||||
return
|
||||
}
|
||||
if req.NewPassword == "" {
|
||||
Fail(c, "NewPassword值不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.ChangePassword(c.Request.Context(), claims.ID, req.Password, req.NewPassword); err != nil {
|
||||
if service.IsPasswordPolicyError(err) {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
Fail(c, "修改失败,原密码与当前账户不符")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "修改成功")
|
||||
}
|
||||
|
||||
func (h *User) SetSelfSetting(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
var setting map[string]any
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
if err := c.ShouldBindJSON(&setting); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.SetUserSetting(c.Request.Context(), claims.ID, setting); err != nil {
|
||||
Fail(c, "设置失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "设置成功")
|
||||
}
|
||||
|
||||
func (h *User) SetAuthorities(c *gin.Context) {
|
||||
var req service.UserAuthoritiesRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.SetUserAuthorities(c.Request.Context(), req.ID, req.AuthorityIDs); err != nil {
|
||||
Fail(c, "修改失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "修改成功")
|
||||
}
|
||||
|
||||
func (h *User) SwitchAuthority(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
var req service.SwitchAuthorityRequest
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if req.AuthorityID == 0 {
|
||||
Fail(c, "AuthorityId值不能为空")
|
||||
return
|
||||
}
|
||||
login, err := h.auth.SwitchAuthority(c.Request.Context(), claims, req.AuthorityID)
|
||||
if err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.Header("new-token", login.Token)
|
||||
c.Header("new-expires-at", strconv.FormatInt(login.ExpiresAt/1000, 10))
|
||||
maxAge := int(time.UnixMilli(login.ExpiresAt).Unix() - time.Now().Unix())
|
||||
SetTokenCookie(c, login.Token, maxAge)
|
||||
Write(c, CodeSuccess, gin.H{}, "修改成功")
|
||||
}
|
||||
|
||||
func (h *User) Get(c *gin.Context) {
|
||||
claims := Claims(c)
|
||||
if claims == nil {
|
||||
NoAuth(c, "未登录或非法访问")
|
||||
return
|
||||
}
|
||||
result, err := h.service.UserByUUID(c.Request.Context(), claims.UUID)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败")
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{"userInfo": result}, "获取成功")
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz"
|
||||
"kra/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Version struct{ service *service.VersionService }
|
||||
|
||||
func NewVersion(service *service.VersionService) *Version { return &Version{service: service} }
|
||||
|
||||
func versionStage(err error) (biz.VersionStage, bool) {
|
||||
var stageErr *biz.VersionStageError
|
||||
if !errors.As(err, &stageErr) {
|
||||
return "", false
|
||||
}
|
||||
return stageErr.Stage, true
|
||||
}
|
||||
|
||||
func (h *Version) Delete(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Query("ID"), 10, 64)
|
||||
if err := h.service.DeleteVersions(c.Request.Context(), []uint{uint(id)}); err != nil {
|
||||
Fail(c, "删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "删除成功")
|
||||
}
|
||||
func (h *Version) DeleteMany(c *gin.Context) {
|
||||
raw := c.QueryArray("IDs[]")
|
||||
ids := make([]uint, 0, len(raw))
|
||||
for _, value := range raw {
|
||||
id, _ := strconv.ParseUint(value, 10, 64)
|
||||
ids = append(ids, uint(id))
|
||||
}
|
||||
if err := h.service.DeleteVersions(c.Request.Context(), ids); err != nil {
|
||||
Fail(c, "批量删除失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "批量删除成功")
|
||||
}
|
||||
func (h *Version) Find(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Query("ID"), 10, 64)
|
||||
item, err := h.service.Version(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
Fail(c, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
OKWithData(c, item)
|
||||
}
|
||||
func (h *Version) List(c *gin.Context) {
|
||||
var req service.VersionSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
name, code := "", ""
|
||||
if req.VersionName != nil {
|
||||
name = *req.VersionName
|
||||
}
|
||||
if req.VersionCode != nil {
|
||||
code = *req.VersionCode
|
||||
}
|
||||
createdAtRange := make([]*time.Time, 0, len(req.CreatedAtRange))
|
||||
for i := range req.CreatedAtRange {
|
||||
createdAtRange = append(createdAtRange, &req.CreatedAtRange[i])
|
||||
}
|
||||
items, total, err := h.service.Versions(c.Request.Context(), req.Page, req.PageSize, name, code, createdAtRange)
|
||||
if err != nil {
|
||||
Fail(c, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, PageResult{List: items, Total: total, Page: req.Page, PageSize: req.PageSize}, "获取成功")
|
||||
}
|
||||
|
||||
func (h *Version) Export(c *gin.Context) {
|
||||
var req service.ExportVersionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.Export(c.Request.Context(), req.VersionName, req.VersionCode, req.Description, req.MenuIDs, req.APIIDs, req.DictIDs); err != nil {
|
||||
switch stage, _ := versionStage(err); stage {
|
||||
case biz.VersionStageMenus:
|
||||
Fail(c, "获取菜单数据失败:"+err.Error())
|
||||
case biz.VersionStageAPIs:
|
||||
Fail(c, "获取API数据失败:"+err.Error())
|
||||
case biz.VersionStageDictionaries:
|
||||
Fail(c, "获取字典数据失败:"+err.Error())
|
||||
case biz.VersionStageJSON:
|
||||
Fail(c, "JSON序列化失败:"+err.Error())
|
||||
case biz.VersionStageSave:
|
||||
Fail(c, "保存版本记录失败:"+err.Error())
|
||||
default:
|
||||
Fail(c, "创建发版失败:"+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "创建发版成功")
|
||||
}
|
||||
func (h *Version) Download(c *gin.Context) {
|
||||
rawID := c.Query("ID")
|
||||
if rawID == "" {
|
||||
Fail(c, "版本ID不能为空")
|
||||
return
|
||||
}
|
||||
id, _ := strconv.ParseUint(rawID, 10, 64)
|
||||
raw, code, err := h.service.VersionData(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
Fail(c, "获取版本记录失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
name := fmt.Sprintf("version_%s_%s.json", code, time.Now().Format("20060102150405"))
|
||||
c.Header("Content-Type", "application/json")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name))
|
||||
c.Header("Content-Length", strconv.Itoa(len(raw)))
|
||||
c.Data(http.StatusOK, "application/json", []byte(raw))
|
||||
}
|
||||
func (h *Version) Import(c *gin.Context) {
|
||||
var req service.ImportVersionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
Fail(c, "解析JSON数据失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.service.ImportRequest(c.Request.Context(), &req); err != nil {
|
||||
if errors.Is(err, biz.ErrInvalidVersion) {
|
||||
Fail(c, "版本信息格式错误")
|
||||
return
|
||||
}
|
||||
switch stage, _ := versionStage(err); stage {
|
||||
case biz.VersionStageMenus:
|
||||
Fail(c, "导入菜单失败: "+err.Error())
|
||||
case biz.VersionStageAPIs:
|
||||
Fail(c, "导入API失败: "+err.Error())
|
||||
case biz.VersionStageDictionaries:
|
||||
Fail(c, "导入字典失败: "+err.Error())
|
||||
default:
|
||||
Fail(c, "导入失败:"+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
Write(c, CodeSuccess, gin.H{}, "导入成功")
|
||||
}
|
||||
Reference in New Issue
Block a user