后端重构
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package example
|
||||
|
||||
import "kra/internal/biz/example"
|
||||
|
||||
// ApiGroup Example API组
|
||||
type ApiGroup struct {
|
||||
FileUploadApi
|
||||
CustomerApi
|
||||
AttachmentCategoryApi
|
||||
}
|
||||
|
||||
// 业务层依赖
|
||||
var (
|
||||
fileUploadUsecase *example.FileUploadUsecase
|
||||
customerUsecase *example.CustomerUsecase
|
||||
attachmentCategoryUsecase *example.AttachmentCategoryUsecase
|
||||
)
|
||||
|
||||
// InitUsecases 初始化业务层依赖
|
||||
func InitUsecases(
|
||||
fileUpload *example.FileUploadUsecase,
|
||||
customer *example.CustomerUsecase,
|
||||
attachmentCategory *example.AttachmentCategoryUsecase,
|
||||
) {
|
||||
fileUploadUsecase = fileUpload
|
||||
customerUsecase = customer
|
||||
attachmentCategoryUsecase = attachmentCategory
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"kra/internal/biz/example"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AttachmentCategoryApi struct{}
|
||||
|
||||
// AddCategory 创建/更新分类
|
||||
// @Summary 创建/更新分类
|
||||
// @Tags ExaAttachmentCategory
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body CategoryRequest true "分类信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /attachmentCategory/addCategory [post]
|
||||
func (api *AttachmentCategoryApi) AddCategory(c *gin.Context) {
|
||||
var req CategoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
category := &example.AttachmentCategory{
|
||||
ID: req.ID,
|
||||
Name: req.Name,
|
||||
Pid: req.Pid,
|
||||
}
|
||||
|
||||
if err := attachmentCategoryUsecase.AddCategory(c.Request.Context(), category); err != nil {
|
||||
response.FailWithMessage("创建/更新失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("创建/更新成功", c)
|
||||
}
|
||||
|
||||
// DeleteCategory 删除分类
|
||||
// @Summary 删除分类
|
||||
// @Tags ExaAttachmentCategory
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body DeleteCategoryRequest true "分类ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /attachmentCategory/deleteCategory [post]
|
||||
func (api *AttachmentCategoryApi) DeleteCategory(c *gin.Context) {
|
||||
var req DeleteCategoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if req.ID == 0 {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := attachmentCategoryUsecase.DeleteCategory(c.Request.Context(), req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// GetCategoryList 获取分类列表
|
||||
// @Summary 获取分类列表
|
||||
// @Tags ExaAttachmentCategory
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Response{data=[]CategoryResponse}
|
||||
// @Router /attachmentCategory/getCategoryList [get]
|
||||
func (api *AttachmentCategoryApi) GetCategoryList(c *gin.Context) {
|
||||
list, err := attachmentCategoryUsecase.GetCategoryList(c.Request.Context())
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取分类列表失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
respList := toCategoryResponseList(list)
|
||||
response.OkWithData(respList, c)
|
||||
}
|
||||
|
||||
// Request/Response 结构
|
||||
type CategoryRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"name"`
|
||||
Pid uint `json:"pid"`
|
||||
}
|
||||
|
||||
type DeleteCategoryRequest struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
|
||||
type CategoryResponse struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"name"`
|
||||
Pid uint `json:"pid"`
|
||||
Children []CategoryResponse `json:"children"`
|
||||
}
|
||||
|
||||
func toCategoryResponseList(categories []*example.AttachmentCategory) []CategoryResponse {
|
||||
result := make([]CategoryResponse, len(categories))
|
||||
for i, cat := range categories {
|
||||
result[i] = CategoryResponse{
|
||||
ID: cat.ID,
|
||||
Name: cat.Name,
|
||||
Pid: cat.Pid,
|
||||
Children: toCategoryResponseList(cat.Children),
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"kra/internal/biz/example"
|
||||
"kra/pkg/response"
|
||||
"kra/pkg/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type CustomerApi struct{}
|
||||
|
||||
// CreateExaCustomer 创建客户
|
||||
// @Summary 创建客户
|
||||
// @Tags ExaCustomer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body CustomerRequest true "客户信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /customer/customer [post]
|
||||
func (api *CustomerApi) CreateExaCustomer(c *gin.Context) {
|
||||
var req CustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
customer := &example.Customer{
|
||||
CustomerName: req.CustomerName,
|
||||
CustomerPhoneData: req.CustomerPhoneData,
|
||||
SysUserID: utils.GetUserID(c),
|
||||
SysUserAuthorityID: utils.GetUserAuthorityId(c),
|
||||
}
|
||||
|
||||
if err := customerUsecase.CreateExaCustomer(c.Request.Context(), customer); err != nil {
|
||||
response.FailWithMessage("创建失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteExaCustomer 删除客户
|
||||
// @Summary 删除客户
|
||||
// @Tags ExaCustomer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body DeleteCustomerRequest true "客户ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /customer/customer [delete]
|
||||
func (api *CustomerApi) DeleteExaCustomer(c *gin.Context) {
|
||||
var req DeleteCustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := customerUsecase.DeleteExaCustomer(c.Request.Context(), req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateExaCustomer 更新客户
|
||||
// @Summary 更新客户
|
||||
// @Tags ExaCustomer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body CustomerRequest true "客户信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /customer/customer [put]
|
||||
func (api *CustomerApi) UpdateExaCustomer(c *gin.Context) {
|
||||
var req CustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
customer := &example.Customer{
|
||||
ID: req.ID,
|
||||
CustomerName: req.CustomerName,
|
||||
CustomerPhoneData: req.CustomerPhoneData,
|
||||
}
|
||||
|
||||
if err := customerUsecase.UpdateExaCustomer(c.Request.Context(), customer); err != nil {
|
||||
response.FailWithMessage("更新失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// GetExaCustomer 获取客户信息
|
||||
// @Summary 获取客户信息
|
||||
// @Tags ExaCustomer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body GetCustomerRequest true "客户ID"
|
||||
// @Success 200 {object} response.Response{data=CustomerResponse}
|
||||
// @Router /customer/customer [get]
|
||||
func (api *CustomerApi) GetExaCustomer(c *gin.Context) {
|
||||
var req GetCustomerRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
customer, err := customerUsecase.GetExaCustomer(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithDetailed(toCustomerResponse(customer), "获取成功", c)
|
||||
}
|
||||
|
||||
// GetExaCustomerList 分页获取客户列表
|
||||
// @Summary 分页获取客户列表
|
||||
// @Tags ExaCustomer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body GetCustomerListRequest true "分页参数"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult}
|
||||
// @Router /customer/customerList [get]
|
||||
func (api *CustomerApi) GetExaCustomerList(c *gin.Context) {
|
||||
var req GetCustomerListRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
authorityId := utils.GetUserAuthorityId(c)
|
||||
list, total, err := customerUsecase.GetCustomerInfoList(c.Request.Context(), authorityId, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
respList := make([]CustomerResponse, len(list))
|
||||
for i, cust := range list {
|
||||
respList[i] = *toCustomerResponse(cust)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: respList,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// Request/Response 结构
|
||||
type CustomerRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
CustomerName string `json:"customerName"`
|
||||
CustomerPhoneData string `json:"customerPhoneData"`
|
||||
}
|
||||
|
||||
type DeleteCustomerRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
}
|
||||
|
||||
type GetCustomerRequest struct {
|
||||
ID uint `form:"ID"`
|
||||
}
|
||||
|
||||
type GetCustomerListRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"pageSize"`
|
||||
}
|
||||
|
||||
type CustomerResponse struct {
|
||||
ID uint `json:"ID"`
|
||||
CustomerName string `json:"customerName"`
|
||||
CustomerPhoneData string `json:"customerPhoneData"`
|
||||
SysUserID uint `json:"sysUserId"`
|
||||
SysUserAuthorityID uint `json:"sysUserAuthorityID"`
|
||||
SysUserName string `json:"sysUserName"`
|
||||
}
|
||||
|
||||
func toCustomerResponse(c *example.Customer) *CustomerResponse {
|
||||
return &CustomerResponse{
|
||||
ID: c.ID,
|
||||
CustomerName: c.CustomerName,
|
||||
CustomerPhoneData: c.CustomerPhoneData,
|
||||
SysUserID: c.SysUserID,
|
||||
SysUserAuthorityID: c.SysUserAuthorityID,
|
||||
SysUserName: c.SysUserName,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"kra/internal/biz/example"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type FileUploadApi struct{}
|
||||
|
||||
// UploadFile 上传文件
|
||||
// @Summary 上传文件
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Param file formance file true "上传文件"
|
||||
// @Success 200 {object} response.Response{data=FileUploadResponse}
|
||||
// @Router /fileUploadAndDownload/upload [post]
|
||||
func (api *FileUploadApi) UploadFile(c *gin.Context) {
|
||||
noSave := c.DefaultQuery("noSave", "0")
|
||||
classIdStr := c.DefaultQuery("classId", "0")
|
||||
classId, _ := strconv.Atoi(classIdStr)
|
||||
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
file, err := fileUploadUsecase.UploadFile(c.Request.Context(), header, noSave, classId)
|
||||
if err != nil {
|
||||
response.FailWithMessage("上传失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithDetailed(toFileUploadResponse(file), "上传成功", c)
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
// @Summary 删除文件
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body DeleteFileRequest true "文件ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /fileUploadAndDownload/deleteFile [post]
|
||||
func (api *FileUploadApi) DeleteFile(c *gin.Context) {
|
||||
var req DeleteFileRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := fileUploadUsecase.DeleteFile(c.Request.Context(), req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// EditFileName 编辑文件名
|
||||
// @Summary 编辑文件名
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body EditFileNameRequest true "文件信息"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /fileUploadAndDownload/editFileName [post]
|
||||
func (api *FileUploadApi) EditFileName(c *gin.Context) {
|
||||
var req EditFileNameRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := fileUploadUsecase.EditFileName(c.Request.Context(), req.ID, req.Name); err != nil {
|
||||
response.FailWithMessage("编辑失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("编辑成功", c)
|
||||
}
|
||||
|
||||
// GetFileList 分页获取文件列表
|
||||
// @Summary 分页获取文件列表
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body GetFileListRequest true "分页参数"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult}
|
||||
// @Router /fileUploadAndDownload/getFileList [post]
|
||||
func (api *FileUploadApi) GetFileList(c *gin.Context) {
|
||||
var req GetFileListRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
searchReq := &example.FileUploadSearchReq{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Keyword: req.Keyword,
|
||||
ClassId: req.ClassId,
|
||||
}
|
||||
|
||||
list, total, err := fileUploadUsecase.GetFileRecordInfoList(c.Request.Context(), searchReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
respList := make([]FileUploadResponse, len(list))
|
||||
for i, f := range list {
|
||||
respList[i] = *toFileUploadResponse(f)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: respList,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ImportURL 导入URL
|
||||
// @Summary 导入URL
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body []FileUploadResponse true "文件列表"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /fileUploadAndDownload/importURL [post]
|
||||
func (api *FileUploadApi) ImportURL(c *gin.Context) {
|
||||
var req []FileUploadResponse
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
files := make([]*example.FileUpload, len(req))
|
||||
for i, r := range req {
|
||||
files[i] = &example.FileUpload{
|
||||
Name: r.Name,
|
||||
ClassId: r.ClassId,
|
||||
Url: r.Url,
|
||||
Tag: r.Tag,
|
||||
Key: r.Key,
|
||||
}
|
||||
}
|
||||
|
||||
if err := fileUploadUsecase.ImportURL(c.Request.Context(), files); err != nil {
|
||||
response.FailWithMessage("导入失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
|
||||
// Request/Response 结构
|
||||
type DeleteFileRequest struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
|
||||
type EditFileNameRequest struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type GetFileListRequest struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Keyword string `json:"keyword"`
|
||||
ClassId int `json:"classId"`
|
||||
}
|
||||
|
||||
type FileUploadResponse struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"name"`
|
||||
ClassId int `json:"classId"`
|
||||
Url string `json:"url"`
|
||||
Tag string `json:"tag"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
func toFileUploadResponse(f *example.FileUpload) *FileUploadResponse {
|
||||
return &FileUploadResponse{
|
||||
ID: f.ID,
|
||||
Name: f.Name,
|
||||
ClassId: f.ClassId,
|
||||
Url: f.Url,
|
||||
Tag: f.Tag,
|
||||
Key: f.Key,
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,18 @@ type ApiGroup struct {
|
||||
AuthorityApi
|
||||
MenuApi
|
||||
DictionaryApi
|
||||
DictionaryDetailApi
|
||||
CasbinApi
|
||||
JwtApi
|
||||
OperationRecordApi
|
||||
ParamsApi
|
||||
ErrorApi
|
||||
VersionApi
|
||||
SystemApi
|
||||
ExportTemplateApi
|
||||
DBApi
|
||||
AutoCodeApi
|
||||
AutoCodeHistoryApi
|
||||
}
|
||||
|
||||
// 业务层依赖
|
||||
@@ -28,6 +36,12 @@ var (
|
||||
jwtBlacklistUsecase *system.JwtBlacklistUsecase
|
||||
operationRecordUsecase *system.OperationRecordUsecase
|
||||
paramsUsecase *system.ParamsUsecase
|
||||
errorUsecase *system.ErrorUsecase
|
||||
versionUsecase *system.VersionUsecase
|
||||
systemUsecase *system.SystemUsecase
|
||||
exportTemplateUsecase *system.ExportTemplateUsecase
|
||||
autoCodeUsecase *system.AutoCodeUsecase
|
||||
autoCodeHistoryUsecase *system.AutoCodeHistoryUsecase
|
||||
)
|
||||
|
||||
// InitUsecases 初始化业务层依赖
|
||||
@@ -42,6 +56,12 @@ func InitUsecases(
|
||||
jwtBlacklist *system.JwtBlacklistUsecase,
|
||||
operationRecord *system.OperationRecordUsecase,
|
||||
params *system.ParamsUsecase,
|
||||
sysError *system.ErrorUsecase,
|
||||
version *system.VersionUsecase,
|
||||
sysSystem *system.SystemUsecase,
|
||||
exportTemplate *system.ExportTemplateUsecase,
|
||||
autoCode *system.AutoCodeUsecase,
|
||||
autoCodeHistory *system.AutoCodeHistoryUsecase,
|
||||
) {
|
||||
userUsecase = user
|
||||
apiUsecase = api
|
||||
@@ -53,4 +73,10 @@ func InitUsecases(
|
||||
jwtBlacklistUsecase = jwtBlacklist
|
||||
operationRecordUsecase = operationRecord
|
||||
paramsUsecase = params
|
||||
errorUsecase = sysError
|
||||
versionUsecase = version
|
||||
systemUsecase = sysSystem
|
||||
exportTemplateUsecase = exportTemplate
|
||||
autoCodeUsecase = autoCode
|
||||
autoCodeHistoryUsecase = autoCodeHistory
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AutoCodeApi struct{}
|
||||
|
||||
// GetDB 获取当前所有数据库
|
||||
// @Summary 获取当前所有数据库
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Router /autoCode/getDB [get]
|
||||
func (api *AutoCodeApi) GetDB(c *gin.Context) {
|
||||
dbs, err := autoCodeUsecase.GetDB(c.Request.Context())
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"dbs": dbs}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetTables 获取当前数据库所有表
|
||||
// @Summary 获取当前数据库所有表
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param dbName query string false "数据库名"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Router /autoCode/getTables [get]
|
||||
func (api *AutoCodeApi) GetTables(c *gin.Context) {
|
||||
dbName := c.Query("dbName")
|
||||
if dbName == "" {
|
||||
response.FailWithMessage("数据库名不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
tables, err := autoCodeUsecase.GetTables(c.Request.Context(), dbName)
|
||||
if err != nil {
|
||||
response.FailWithMessage("查询table失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"tables": tables}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetColumn 获取当前表所有字段
|
||||
// @Summary 获取当前表所有字段
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param dbName query string false "数据库名"
|
||||
// @Param tableName query string true "表名"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Router /autoCode/getColumn [get]
|
||||
func (api *AutoCodeApi) GetColumn(c *gin.Context) {
|
||||
dbName := c.Query("dbName")
|
||||
tableName := c.Query("tableName")
|
||||
if tableName == "" {
|
||||
response.FailWithMessage("表名不能为空", c)
|
||||
return
|
||||
}
|
||||
if dbName == "" {
|
||||
response.FailWithMessage("数据库名不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
columns, err := autoCodeUsecase.GetColumn(c.Request.Context(), tableName, dbName)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"columns": columns}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"kra/internal/biz/system"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AutoCodeHistoryApi struct{}
|
||||
|
||||
// GetByIdReq 获取请求
|
||||
type GetByIdReq struct {
|
||||
ID uint `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
// First 获取meta信息
|
||||
// @Summary 获取meta信息
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body GetByIdReq true "请求参数"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Router /autoCode/getMeta [post]
|
||||
func (api *AutoCodeHistoryApi) First(c *gin.Context) {
|
||||
var req GetByIdReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := autoCodeHistoryUsecase.First(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"meta": data}, "获取成功", c)
|
||||
}
|
||||
|
||||
// Delete 删除回滚记录
|
||||
// @Summary 删除回滚记录
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body GetByIdReq true "请求参数"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /autoCode/delSysHistory [post]
|
||||
func (api *AutoCodeHistoryApi) Delete(c *gin.Context) {
|
||||
var req GetByIdReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
err := autoCodeHistoryUsecase.Delete(c.Request.Context(), req.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// RollBack 回滚自动生成代码
|
||||
// @Summary 回滚自动生成代码
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body system.SysAutoHistoryRollBack true "请求参数"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /autoCode/rollback [post]
|
||||
func (api *AutoCodeHistoryApi) RollBack(c *gin.Context) {
|
||||
var req system.SysAutoHistoryRollBack
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
err := autoCodeHistoryUsecase.RollBack(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("回滚成功", c)
|
||||
}
|
||||
|
||||
// PageInfoReq 分页请求
|
||||
type PageInfoReq struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
// GetList 查询回滚记录
|
||||
// @Summary 查询回滚记录
|
||||
// @Tags AutoCode
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body PageInfoReq true "请求参数"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult}
|
||||
// @Router /autoCode/getSysHistory [post]
|
||||
func (api *AutoCodeHistoryApi) GetList(c *gin.Context) {
|
||||
var req PageInfoReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
list, total, err := autoCodeHistoryUsecase.GetList(c.Request.Context(), req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type DictionaryDetailApi struct{}
|
||||
|
||||
// DictionaryDetailRequest 字典详情请求
|
||||
type DictionaryDetailRequest struct {
|
||||
ID uint `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
Extend string `json:"extend"`
|
||||
Status *bool `json:"status"`
|
||||
Sort int `json:"sort"`
|
||||
SysDictionaryID uint `json:"sysDictionaryID"`
|
||||
ParentID *uint `json:"parentId"`
|
||||
}
|
||||
|
||||
// DictionaryDetailSearchRequest 字典详情搜索请求
|
||||
type DictionaryDetailSearchRequest struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
Label string `json:"label" form:"label"`
|
||||
Value string `json:"value" form:"value"`
|
||||
Status *bool `json:"status" form:"status"`
|
||||
SysDictionaryID uint `json:"sysDictionaryID" form:"sysDictionaryID"`
|
||||
ParentID *uint `json:"parentId" form:"parentId"`
|
||||
Level *int `json:"level" form:"level"`
|
||||
}
|
||||
|
||||
// GetDictionaryDetailsByParentRequest 根据父级获取字典详情请求
|
||||
type GetDictionaryDetailsByParentRequest struct {
|
||||
SysDictionaryID uint `json:"sysDictionaryID" form:"sysDictionaryID" binding:"required"`
|
||||
ParentID *uint `json:"parentId" form:"parentId"`
|
||||
IncludeChildren bool `json:"includeChildren" form:"includeChildren"`
|
||||
}
|
||||
|
||||
// CreateSysDictionaryDetail 创建字典详情
|
||||
func (d *DictionaryDetailApi) CreateSysDictionaryDetail(c *gin.Context) {
|
||||
var req DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
detail := &system.DictionaryDetail{
|
||||
Label: req.Label,
|
||||
Value: req.Value,
|
||||
Extend: req.Extend,
|
||||
Status: req.Status,
|
||||
Sort: req.Sort,
|
||||
SysDictionaryID: req.SysDictionaryID,
|
||||
ParentID: req.ParentID,
|
||||
}
|
||||
|
||||
if err := dictionaryUsecase.CreateDictionaryDetail(c.Request.Context(), detail); err != nil {
|
||||
response.FailWithMessage("创建失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysDictionaryDetail 删除字典详情
|
||||
func (d *DictionaryDetailApi) DeleteSysDictionaryDetail(c *gin.Context) {
|
||||
var req DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dictionaryUsecase.DeleteDictionaryDetail(c.Request.Context(), req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysDictionaryDetail 更新字典详情
|
||||
func (d *DictionaryDetailApi) UpdateSysDictionaryDetail(c *gin.Context) {
|
||||
var req DictionaryDetailRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
detail := &system.DictionaryDetail{
|
||||
ID: req.ID,
|
||||
Label: req.Label,
|
||||
Value: req.Value,
|
||||
Extend: req.Extend,
|
||||
Status: req.Status,
|
||||
Sort: req.Sort,
|
||||
SysDictionaryID: req.SysDictionaryID,
|
||||
ParentID: req.ParentID,
|
||||
}
|
||||
|
||||
if err := dictionaryUsecase.UpdateDictionaryDetail(c.Request.Context(), detail); err != nil {
|
||||
response.FailWithMessage("更新失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysDictionaryDetail 根据ID获取字典详情
|
||||
func (d *DictionaryDetailApi) FindSysDictionaryDetail(c *gin.Context) {
|
||||
idStr := c.Query("ID")
|
||||
if idStr == "" {
|
||||
response.FailWithMessage("缺少参数: ID", c)
|
||||
return
|
||||
}
|
||||
id, _ := strconv.ParseUint(idStr, 10, 32)
|
||||
|
||||
detail, err := dictionaryUsecase.GetDictionaryDetail(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
response.FailWithMessage("查询失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"reSysDictionaryDetail": toDictionaryDetailResponse(detail)}, "查询成功", c)
|
||||
}
|
||||
|
||||
// GetSysDictionaryDetailList 分页获取字典详情列表
|
||||
func (d *DictionaryDetailApi) GetSysDictionaryDetailList(c *gin.Context) {
|
||||
var req DictionaryDetailSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Page == 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
|
||||
filters := make(map[string]interface{})
|
||||
if req.Label != "" {
|
||||
filters["label"] = req.Label
|
||||
}
|
||||
if req.Value != "" {
|
||||
filters["value"] = req.Value
|
||||
}
|
||||
if req.Status != nil {
|
||||
filters["status"] = req.Status
|
||||
}
|
||||
if req.SysDictionaryID != 0 {
|
||||
filters["sysDictionaryID"] = req.SysDictionaryID
|
||||
}
|
||||
if req.ParentID != nil {
|
||||
filters["parentId"] = req.ParentID
|
||||
}
|
||||
if req.Level != nil {
|
||||
filters["level"] = req.Level
|
||||
}
|
||||
|
||||
list, total, err := dictionaryUsecase.GetDictionaryDetailList(c.Request.Context(), req.Page, req.PageSize, filters)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, len(list))
|
||||
for i, item := range list {
|
||||
result[i] = toDictionaryDetailResponse(item)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: result,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetDictionaryTreeList 获取字典详情树形结构
|
||||
func (d *DictionaryDetailApi) GetDictionaryTreeList(c *gin.Context) {
|
||||
sysDictionaryID := c.Query("sysDictionaryID")
|
||||
if sysDictionaryID == "" {
|
||||
response.FailWithMessage("字典ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(sysDictionaryID, 10, 32)
|
||||
if err != nil {
|
||||
response.FailWithMessage("字典ID格式错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dictionaryUsecase.GetDictionaryTreeList(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"list": toDictionaryDetailTreeResponse(list)}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetDictionaryTreeListByType 根据字典类型获取字典详情树形结构
|
||||
func (d *DictionaryDetailApi) GetDictionaryTreeListByType(c *gin.Context) {
|
||||
dictType := c.Query("type")
|
||||
if dictType == "" {
|
||||
response.FailWithMessage("字典类型不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dictionaryUsecase.GetDictionaryTreeListByType(c.Request.Context(), dictType)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"list": toDictionaryDetailTreeResponse(list)}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetDictionaryDetailsByParent 根据父级ID获取字典详情
|
||||
func (d *DictionaryDetailApi) GetDictionaryDetailsByParent(c *gin.Context) {
|
||||
var req GetDictionaryDetailsByParentRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dictionaryUsecase.GetDictionaryDetailsByParent(c.Request.Context(), req.SysDictionaryID, req.ParentID, req.IncludeChildren)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"list": toDictionaryDetailTreeResponse(list)}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetDictionaryPath 获取字典详情的完整路径
|
||||
func (d *DictionaryDetailApi) GetDictionaryPath(c *gin.Context) {
|
||||
idStr := c.Query("id")
|
||||
if idStr == "" {
|
||||
response.FailWithMessage("字典详情ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
response.FailWithMessage("字典详情ID格式错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
path, err := dictionaryUsecase.GetDictionaryPath(c.Request.Context(), uint(id))
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, len(path))
|
||||
for i, item := range path {
|
||||
result[i] = toDictionaryDetailResponse(item)
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"path": result}, "获取成功", c)
|
||||
}
|
||||
|
||||
func toDictionaryDetailResponse(d *system.DictionaryDetail) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": d.ID,
|
||||
"label": d.Label,
|
||||
"value": d.Value,
|
||||
"extend": d.Extend,
|
||||
"status": d.Status,
|
||||
"sort": d.Sort,
|
||||
"sysDictionaryID": d.SysDictionaryID,
|
||||
"parentId": d.ParentID,
|
||||
"level": d.Level,
|
||||
"path": d.Path,
|
||||
"disabled": d.Disabled,
|
||||
}
|
||||
}
|
||||
|
||||
func toDictionaryDetailTreeResponse(list []*system.DictionaryDetail) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, len(list))
|
||||
for i, item := range list {
|
||||
resp := toDictionaryDetailResponse(item)
|
||||
if len(item.Children) > 0 {
|
||||
resp["children"] = toDictionaryDetailTreeResponse(item.Children)
|
||||
}
|
||||
result[i] = resp
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ErrorApi struct{}
|
||||
|
||||
// SysErrorRequest 错误日志请求
|
||||
type SysErrorRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Form string `json:"form" binding:"required"`
|
||||
Info string `json:"info"`
|
||||
Level string `json:"level"`
|
||||
Solution string `json:"solution"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// SysErrorSearchRequest 错误日志搜索请求
|
||||
type SysErrorSearchRequest struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
Form *string `json:"form" form:"form"`
|
||||
Info *string `json:"info" form:"info"`
|
||||
CreatedAtRange []time.Time `json:"createdAtRange" form:"createdAtRange[]"`
|
||||
}
|
||||
|
||||
// CreateSysError 创建错误日志
|
||||
func (e *ErrorApi) CreateSysError(c *gin.Context) {
|
||||
var req SysErrorRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
sysError := &system.SysError{
|
||||
Form: req.Form,
|
||||
Info: req.Info,
|
||||
Level: req.Level,
|
||||
Status: "未处理",
|
||||
}
|
||||
|
||||
if err := errorUsecase.CreateSysError(c.Request.Context(), sysError); err != nil {
|
||||
response.FailWithMessage("创建失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysError 删除错误日志
|
||||
func (e *ErrorApi) DeleteSysError(c *gin.Context) {
|
||||
id := c.Query("ID")
|
||||
if id == "" {
|
||||
response.FailWithMessage("缺少参数: ID", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := errorUsecase.DeleteSysError(c.Request.Context(), id); err != nil {
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysErrorByIds 批量删除错误日志
|
||||
func (e *ErrorApi) DeleteSysErrorByIds(c *gin.Context) {
|
||||
ids := c.QueryArray("IDs[]")
|
||||
if len(ids) == 0 {
|
||||
response.FailWithMessage("缺少参数: IDs", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := errorUsecase.DeleteSysErrorByIds(c.Request.Context(), ids); err != nil {
|
||||
response.FailWithMessage("批量删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysError 更新错误日志
|
||||
func (e *ErrorApi) UpdateSysError(c *gin.Context) {
|
||||
var req SysErrorRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
sysError := &system.SysError{
|
||||
ID: req.ID,
|
||||
Form: req.Form,
|
||||
Info: req.Info,
|
||||
Level: req.Level,
|
||||
Solution: req.Solution,
|
||||
Status: req.Status,
|
||||
}
|
||||
|
||||
if err := errorUsecase.UpdateSysError(c.Request.Context(), sysError); err != nil {
|
||||
response.FailWithMessage("更新失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysError 根据ID获取错误日志
|
||||
func (e *ErrorApi) FindSysError(c *gin.Context) {
|
||||
id := c.Query("ID")
|
||||
if id == "" {
|
||||
response.FailWithMessage("缺少参数: ID", c)
|
||||
return
|
||||
}
|
||||
|
||||
sysError, err := errorUsecase.GetSysError(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
response.FailWithMessage("查询失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(toErrorResponse(sysError), c)
|
||||
}
|
||||
|
||||
// GetSysErrorList 分页获取错误日志列表
|
||||
func (e *ErrorApi) GetSysErrorList(c *gin.Context) {
|
||||
var req SysErrorSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Page == 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
|
||||
searchReq := &system.ErrorSearchReq{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Form: req.Form,
|
||||
Info: req.Info,
|
||||
CreatedAtRange: req.CreatedAtRange,
|
||||
}
|
||||
|
||||
list, total, err := errorUsecase.GetSysErrorInfoList(c.Request.Context(), searchReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, len(list))
|
||||
for i, item := range list {
|
||||
result[i] = toErrorResponse(item)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: result,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetSysErrorSolution 触发AI处理错误日志
|
||||
func (e *ErrorApi) GetSysErrorSolution(c *gin.Context) {
|
||||
id := c.Query("id")
|
||||
if id == "" {
|
||||
response.FailWithMessage("缺少参数: id", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := errorUsecase.GetSysErrorSolution(c.Request.Context(), id); err != nil {
|
||||
response.FailWithMessage("处理触发失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("已提交至AI处理", c)
|
||||
}
|
||||
|
||||
// toErrorResponse 转换错误日志响应
|
||||
func toErrorResponse(e *system.SysError) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": e.ID,
|
||||
"form": e.Form,
|
||||
"info": e.Info,
|
||||
"level": e.Level,
|
||||
"solution": e.Solution,
|
||||
"status": e.Status,
|
||||
"createdAt": e.CreatedAt,
|
||||
"updatedAt": e.UpdatedAt,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/pkg/response"
|
||||
"kra/pkg/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 用于token一次性存储
|
||||
var (
|
||||
exportTokenCache = make(map[string]interface{})
|
||||
exportTokenExpiration = make(map[string]time.Time)
|
||||
tokenMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// 五分钟检测窗口过期
|
||||
func cleanupExpiredTokens() {
|
||||
for {
|
||||
time.Sleep(5 * time.Minute)
|
||||
tokenMutex.Lock()
|
||||
now := time.Now()
|
||||
for token, expiry := range exportTokenExpiration {
|
||||
if now.After(expiry) {
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
}
|
||||
}
|
||||
tokenMutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
go cleanupExpiredTokens()
|
||||
}
|
||||
|
||||
type ExportTemplateApi struct{}
|
||||
|
||||
// CreateSysExportTemplateRequest 创建导出模板请求
|
||||
type CreateSysExportTemplateRequest struct {
|
||||
DBName string `json:"dbName"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
TableName string `json:"tableName"`
|
||||
TemplateID string `json:"templateID"`
|
||||
TemplateInfo string `json:"templateInfo"`
|
||||
Limit *int `json:"limit"`
|
||||
Order string `json:"order"`
|
||||
Conditions []*ConditionRequest `json:"conditions"`
|
||||
JoinTemplate []*JoinTemplateRequest `json:"joinTemplate"`
|
||||
}
|
||||
|
||||
type ConditionRequest struct {
|
||||
TemplateID string `json:"templateID"`
|
||||
From string `json:"from"`
|
||||
Column string `json:"column"`
|
||||
Operator string `json:"operator"`
|
||||
}
|
||||
|
||||
type JoinTemplateRequest struct {
|
||||
TemplateID string `json:"templateID"`
|
||||
Joins string `json:"joins"`
|
||||
Table string `json:"table"`
|
||||
On string `json:"on"`
|
||||
}
|
||||
|
||||
// UpdateSysExportTemplateRequest 更新导出模板请求
|
||||
type UpdateSysExportTemplateRequest struct {
|
||||
ID uint `json:"ID" binding:"required"`
|
||||
DBName string `json:"dbName"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
TableName string `json:"tableName"`
|
||||
TemplateID string `json:"templateID"`
|
||||
TemplateInfo string `json:"templateInfo"`
|
||||
Limit *int `json:"limit"`
|
||||
Order string `json:"order"`
|
||||
Conditions []*ConditionRequest `json:"conditions"`
|
||||
JoinTemplate []*JoinTemplateRequest `json:"joinTemplate"`
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplateRequest 删除导出模板请求
|
||||
type DeleteSysExportTemplateRequest struct {
|
||||
ID uint `json:"ID" binding:"required"`
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplateByIdsRequest 批量删除导出模板请求
|
||||
type DeleteSysExportTemplateByIdsRequest struct {
|
||||
Ids []uint `json:"ids" binding:"required"`
|
||||
}
|
||||
|
||||
// GetSysExportTemplateListRequest 获取导出模板列表请求
|
||||
type GetSysExportTemplateListRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"pageSize"`
|
||||
Name string `form:"name"`
|
||||
TableName string `form:"tableName"`
|
||||
TemplateID string `form:"templateID"`
|
||||
StartCreatedAt *time.Time `form:"startCreatedAt"`
|
||||
EndCreatedAt *time.Time `form:"endCreatedAt"`
|
||||
}
|
||||
|
||||
// CreateSysExportTemplate 创建导出模板
|
||||
func (e *ExportTemplateApi) CreateSysExportTemplate(c *gin.Context) {
|
||||
var req CreateSysExportTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
template := &system.ExportTemplate{
|
||||
DBName: req.DBName,
|
||||
Name: req.Name,
|
||||
TableName: req.TableName,
|
||||
TemplateID: req.TemplateID,
|
||||
TemplateInfo: req.TemplateInfo,
|
||||
Limit: req.Limit,
|
||||
Order: req.Order,
|
||||
}
|
||||
|
||||
// 转换条件
|
||||
if len(req.Conditions) > 0 {
|
||||
template.Conditions = make([]*system.Condition, len(req.Conditions))
|
||||
for i, c := range req.Conditions {
|
||||
template.Conditions[i] = &system.Condition{
|
||||
TemplateID: c.TemplateID,
|
||||
From: c.From,
|
||||
Column: c.Column,
|
||||
Operator: c.Operator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换关联
|
||||
if len(req.JoinTemplate) > 0 {
|
||||
template.JoinTemplate = make([]*system.JoinTemplate, len(req.JoinTemplate))
|
||||
for i, j := range req.JoinTemplate {
|
||||
template.JoinTemplate[i] = &system.JoinTemplate{
|
||||
TemplateID: j.TemplateID,
|
||||
Joins: j.Joins,
|
||||
Table: j.Table,
|
||||
On: j.On,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := exportTemplateUsecase.CreateExportTemplate(c, template); err != nil {
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplate 删除导出模板
|
||||
func (e *ExportTemplateApi) DeleteSysExportTemplate(c *gin.Context) {
|
||||
var req DeleteSysExportTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := exportTemplateUsecase.DeleteExportTemplate(c, req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplateByIds 批量删除导出模板
|
||||
func (e *ExportTemplateApi) DeleteSysExportTemplateByIds(c *gin.Context) {
|
||||
var req DeleteSysExportTemplateByIdsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := exportTemplateUsecase.DeleteExportTemplateByIds(c, req.Ids); err != nil {
|
||||
response.FailWithMessage("批量删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysExportTemplate 更新导出模板
|
||||
func (e *ExportTemplateApi) UpdateSysExportTemplate(c *gin.Context) {
|
||||
var req UpdateSysExportTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
template := &system.ExportTemplate{
|
||||
ID: req.ID,
|
||||
DBName: req.DBName,
|
||||
Name: req.Name,
|
||||
TableName: req.TableName,
|
||||
TemplateID: req.TemplateID,
|
||||
TemplateInfo: req.TemplateInfo,
|
||||
Limit: req.Limit,
|
||||
Order: req.Order,
|
||||
}
|
||||
|
||||
// 转换条件
|
||||
if len(req.Conditions) > 0 {
|
||||
template.Conditions = make([]*system.Condition, len(req.Conditions))
|
||||
for i, c := range req.Conditions {
|
||||
template.Conditions[i] = &system.Condition{
|
||||
TemplateID: c.TemplateID,
|
||||
From: c.From,
|
||||
Column: c.Column,
|
||||
Operator: c.Operator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换关联
|
||||
if len(req.JoinTemplate) > 0 {
|
||||
template.JoinTemplate = make([]*system.JoinTemplate, len(req.JoinTemplate))
|
||||
for i, j := range req.JoinTemplate {
|
||||
template.JoinTemplate[i] = &system.JoinTemplate{
|
||||
TemplateID: j.TemplateID,
|
||||
Joins: j.Joins,
|
||||
Table: j.Table,
|
||||
On: j.On,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := exportTemplateUsecase.UpdateExportTemplate(c, template); err != nil {
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysExportTemplate 根据ID获取导出模板
|
||||
func (e *ExportTemplateApi) FindSysExportTemplate(c *gin.Context) {
|
||||
var req struct {
|
||||
ID uint `form:"ID" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
template, err := exportTemplateUsecase.GetExportTemplate(c, req.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage("查询失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{"resysExportTemplate": toExportTemplateResponse(template)}, c)
|
||||
}
|
||||
|
||||
// GetSysExportTemplateList 分页获取导出模板列表
|
||||
func (e *ExportTemplateApi) GetSysExportTemplateList(c *gin.Context) {
|
||||
var req GetSysExportTemplateListRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
searchReq := &system.ExportTemplateSearchReq{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Name: req.Name,
|
||||
TableName: req.TableName,
|
||||
TemplateID: req.TemplateID,
|
||||
StartCreatedAt: req.StartCreatedAt,
|
||||
EndCreatedAt: req.EndCreatedAt,
|
||||
}
|
||||
|
||||
list, total, err := exportTemplateUsecase.GetExportTemplateList(c, searchReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
respList := make([]interface{}, len(list))
|
||||
for i, t := range list {
|
||||
respList[i] = toExportTemplateResponse(t)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: respList,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ExportExcel 导出Excel(获取token)
|
||||
func (e *ExportTemplateApi) ExportExcel(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
queryParams := c.Request.URL.Query()
|
||||
|
||||
// 创造一次性token
|
||||
token := utils.RandomString(32)
|
||||
|
||||
// 记录本次请求参数
|
||||
exportParams := map[string]interface{}{
|
||||
"templateID": templateID,
|
||||
"queryParams": queryParams,
|
||||
}
|
||||
|
||||
// 参数保留记录完成鉴权
|
||||
tokenMutex.Lock()
|
||||
exportTokenCache[token] = exportParams
|
||||
exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 生成一次性链接
|
||||
exportUrl := fmt.Sprintf("/sysExportTemplate/exportExcelByToken?token=%s", token)
|
||||
response.OkWithData(exportUrl, c)
|
||||
}
|
||||
|
||||
// ExportExcelByToken 通过token导出Excel
|
||||
func (e *ExportTemplateApi) ExportExcelByToken(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
response.FailWithMessage("导出token不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取token并且从缓存中剔除
|
||||
tokenMutex.RLock()
|
||||
exportParamsRaw, exists := exportTokenCache[token]
|
||||
expiry, _ := exportTokenExpiration[token]
|
||||
tokenMutex.RUnlock()
|
||||
|
||||
if !exists || time.Now().After(expiry) {
|
||||
response.FailWithMessage("导出token无效或已过期", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 从token获取参数
|
||||
exportParams, ok := exportParamsRaw.(map[string]interface{})
|
||||
if !ok {
|
||||
response.FailWithMessage("解析导出参数失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取导出参数
|
||||
templateID := exportParams["templateID"].(string)
|
||||
queryParams := exportParams["queryParams"].(url.Values)
|
||||
|
||||
// 清理一次性token
|
||||
tokenMutex.Lock()
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 导出
|
||||
file, name, err := exportTemplateUsecase.ExportExcel(c, templateID, queryParams)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+utils.RandomString(6)+".csv"))
|
||||
c.Header("success", "true")
|
||||
c.Data(http.StatusOK, "text/csv", file.Bytes())
|
||||
}
|
||||
|
||||
// PreviewSQL 预览SQL
|
||||
func (e *ExportTemplateApi) PreviewSQL(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
queryParams := c.Request.URL.Query()
|
||||
|
||||
sqlPreview, err := exportTemplateUsecase.PreviewSQL(c, templateID, queryParams)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{"sql": sqlPreview}, c)
|
||||
}
|
||||
|
||||
// ExportTemplate 导出Excel模板(获取token)
|
||||
func (e *ExportTemplateApi) ExportTemplate(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 创造一次性token
|
||||
token := utils.RandomString(32)
|
||||
|
||||
// 记录本次请求参数
|
||||
exportParams := map[string]interface{}{
|
||||
"templateID": templateID,
|
||||
"isTemplate": true,
|
||||
}
|
||||
|
||||
// 参数保留记录完成鉴权
|
||||
tokenMutex.Lock()
|
||||
exportTokenCache[token] = exportParams
|
||||
exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 生成一次性链接
|
||||
exportUrl := fmt.Sprintf("/sysExportTemplate/exportTemplateByToken?token=%s", token)
|
||||
response.OkWithData(exportUrl, c)
|
||||
}
|
||||
|
||||
// ExportTemplateByToken 通过token导出模板
|
||||
func (e *ExportTemplateApi) ExportTemplateByToken(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
response.FailWithMessage("导出token不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取token并且从缓存中剔除
|
||||
tokenMutex.RLock()
|
||||
exportParamsRaw, exists := exportTokenCache[token]
|
||||
expiry, _ := exportTokenExpiration[token]
|
||||
tokenMutex.RUnlock()
|
||||
|
||||
if !exists || time.Now().After(expiry) {
|
||||
response.FailWithMessage("导出token无效或已过期", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 从token获取参数
|
||||
exportParams, ok := exportParamsRaw.(map[string]interface{})
|
||||
if !ok {
|
||||
response.FailWithMessage("解析导出参数失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为模板导出
|
||||
isTemplate, _ := exportParams["isTemplate"].(bool)
|
||||
if !isTemplate {
|
||||
response.FailWithMessage("token类型错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取导出参数
|
||||
templateID := exportParams["templateID"].(string)
|
||||
|
||||
// 清理一次性token
|
||||
tokenMutex.Lock()
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 导出模板
|
||||
file, name, err := exportTemplateUsecase.ExportTemplate(c, templateID)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+"模板.csv"))
|
||||
c.Header("success", "true")
|
||||
c.Data(http.StatusOK, "text/csv", file.Bytes())
|
||||
}
|
||||
|
||||
// ImportExcel 导入Excel
|
||||
func (e *ExportTemplateApi) ImportExcel(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
response.FailWithMessage("文件获取失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := exportTemplateUsecase.ImportExcel(c, templateID, file); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
|
||||
// 转换为响应结构
|
||||
func toExportTemplateResponse(t *system.ExportTemplate) map[string]interface{} {
|
||||
resp := map[string]interface{}{
|
||||
"ID": t.ID,
|
||||
"dbName": t.DBName,
|
||||
"name": t.Name,
|
||||
"tableName": t.TableName,
|
||||
"templateID": t.TemplateID,
|
||||
"templateInfo": t.TemplateInfo,
|
||||
"limit": t.Limit,
|
||||
"order": t.Order,
|
||||
"createdAt": t.CreatedAt,
|
||||
"updatedAt": t.UpdatedAt,
|
||||
}
|
||||
|
||||
if len(t.Conditions) > 0 {
|
||||
conditions := make([]map[string]interface{}, len(t.Conditions))
|
||||
for i, c := range t.Conditions {
|
||||
conditions[i] = map[string]interface{}{
|
||||
"ID": c.ID,
|
||||
"templateID": c.TemplateID,
|
||||
"from": c.From,
|
||||
"column": c.Column,
|
||||
"operator": c.Operator,
|
||||
}
|
||||
}
|
||||
resp["conditions"] = conditions
|
||||
}
|
||||
|
||||
if len(t.JoinTemplate) > 0 {
|
||||
joins := make([]map[string]interface{}, len(t.JoinTemplate))
|
||||
for i, j := range t.JoinTemplate {
|
||||
joins[i] = map[string]interface{}{
|
||||
"ID": j.ID,
|
||||
"templateID": j.TemplateID,
|
||||
"joins": j.Joins,
|
||||
"table": j.Table,
|
||||
"on": j.On,
|
||||
}
|
||||
}
|
||||
resp["joinTemplate"] = joins
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type DBApi struct{}
|
||||
|
||||
// InitDBRequest 初始化数据库请求
|
||||
type InitDBRequest struct {
|
||||
AdminPassword string `json:"adminPassword" binding:"required"`
|
||||
DBType string `json:"dbType"`
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
UserName string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
DBName string `json:"dbName"`
|
||||
DBPath string `json:"dbPath"`
|
||||
}
|
||||
|
||||
// InitDB 初始化数据库
|
||||
// 注意:KRA 项目使用 Kratos 框架,数据库配置通过 config.yaml 管理
|
||||
// 此接口主要用于兼容 GVA 前端
|
||||
func (d *DBApi) InitDB(c *gin.Context) {
|
||||
// KRA 项目数据库已通过配置文件初始化
|
||||
// 此接口返回成功以兼容前端
|
||||
response.OkWithMessage("数据库已初始化", c)
|
||||
}
|
||||
|
||||
// CheckDB 检测是否需要初始化数据库
|
||||
func (d *DBApi) CheckDB(c *gin.Context) {
|
||||
// KRA 项目数据库通过配置文件管理,无需初始化
|
||||
response.OkWithDetailed(gin.H{"needInit": false}, "数据库无需初始化", c)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SystemApi struct{}
|
||||
|
||||
// GetServerInfo 获取服务器信息
|
||||
func (s *SystemApi) GetServerInfo(c *gin.Context) {
|
||||
serverInfo, err := systemUsecase.GetServerInfo(c.Request.Context())
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"server": serverInfo}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetSystemConfig 获取配置文件内容
|
||||
func (s *SystemApi) GetSystemConfig(c *gin.Context) {
|
||||
// 简化实现:返回基本配置信息
|
||||
response.OkWithDetailed(gin.H{
|
||||
"config": gin.H{
|
||||
"system": gin.H{
|
||||
"env": "production",
|
||||
},
|
||||
},
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// SetSystemConfig 设置配置文件内容
|
||||
func (s *SystemApi) SetSystemConfig(c *gin.Context) {
|
||||
// 简化实现:配置设置功能
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
|
||||
// ReloadSystem 重载系统
|
||||
func (s *SystemApi) ReloadSystem(c *gin.Context) {
|
||||
// 简化实现:系统重载功能
|
||||
response.OkWithMessage("重载系统成功", c)
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VersionApi struct{}
|
||||
|
||||
// VersionSearchRequest 版本搜索请求
|
||||
type VersionSearchRequest struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
VersionName *string `json:"versionName" form:"versionName"`
|
||||
VersionCode *string `json:"versionCode" form:"versionCode"`
|
||||
CreatedAtRange []time.Time `json:"createdAtRange" form:"createdAtRange[]"`
|
||||
}
|
||||
|
||||
// ExportVersionRequest 导出版本请求
|
||||
type ExportVersionRequest struct {
|
||||
VersionName string `json:"versionName" binding:"required"`
|
||||
VersionCode string `json:"versionCode" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
MenuIds []uint `json:"menuIds"`
|
||||
ApiIds []uint `json:"apiIds"`
|
||||
DictIds []uint `json:"dictIds"`
|
||||
}
|
||||
|
||||
// VersionInfo 版本信息
|
||||
type VersionInfo struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Description string `json:"description"`
|
||||
ExportTime string `json:"exportTime"`
|
||||
}
|
||||
|
||||
// ExportVersionResponse 导出版本响应
|
||||
type ExportVersionResponse struct {
|
||||
Version VersionInfo `json:"version"`
|
||||
Menus []map[string]interface{} `json:"menus"`
|
||||
Apis []map[string]interface{} `json:"apis"`
|
||||
Dictionaries []map[string]interface{} `json:"dictionaries"`
|
||||
}
|
||||
|
||||
// DeleteSysVersion 删除版本
|
||||
func (v *VersionApi) DeleteSysVersion(c *gin.Context) {
|
||||
id := c.Query("ID")
|
||||
if id == "" {
|
||||
response.FailWithMessage("缺少参数: ID", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := versionUsecase.DeleteSysVersion(c.Request.Context(), id); err != nil {
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysVersionByIds 批量删除版本
|
||||
func (v *VersionApi) DeleteSysVersionByIds(c *gin.Context) {
|
||||
ids := c.QueryArray("IDs[]")
|
||||
if len(ids) == 0 {
|
||||
response.FailWithMessage("缺少参数: IDs", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := versionUsecase.DeleteSysVersionByIds(c.Request.Context(), ids); err != nil {
|
||||
response.FailWithMessage("批量删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// FindSysVersion 根据ID获取版本
|
||||
func (v *VersionApi) FindSysVersion(c *gin.Context) {
|
||||
id := c.Query("ID")
|
||||
if id == "" {
|
||||
response.FailWithMessage("缺少参数: ID", c)
|
||||
return
|
||||
}
|
||||
|
||||
version, err := versionUsecase.GetSysVersion(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
response.FailWithMessage("查询失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(toVersionResponse(version), c)
|
||||
}
|
||||
|
||||
// GetSysVersionList 分页获取版本列表
|
||||
func (v *VersionApi) GetSysVersionList(c *gin.Context) {
|
||||
var req VersionSearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Page == 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
|
||||
searchReq := &system.VersionSearchReq{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
VersionName: req.VersionName,
|
||||
VersionCode: req.VersionCode,
|
||||
CreatedAtRange: req.CreatedAtRange,
|
||||
}
|
||||
|
||||
list, total, err := versionUsecase.GetSysVersionInfoList(c.Request.Context(), searchReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, len(list))
|
||||
for i, item := range list {
|
||||
result[i] = toVersionResponse(item)
|
||||
}
|
||||
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: result,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetSysVersionPublic 公开版本接口
|
||||
func (v *VersionApi) GetSysVersionPublic(c *gin.Context) {
|
||||
response.OkWithDetailed(gin.H{
|
||||
"info": "不需要鉴权的版本管理接口信息",
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ExportVersion 创建发版数据
|
||||
func (v *VersionApi) ExportVersion(c *gin.Context) {
|
||||
var req ExportVersionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// 获取选中的菜单数据
|
||||
var menuData []map[string]interface{}
|
||||
if len(req.MenuIds) > 0 {
|
||||
menus, err := versionUsecase.GetMenusByIds(ctx, req.MenuIds)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取菜单数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
for _, m := range menus {
|
||||
menuData = append(menuData, map[string]interface{}{
|
||||
"path": m.Path,
|
||||
"name": m.Name,
|
||||
"hidden": m.Hidden,
|
||||
"component": m.Component,
|
||||
"sort": m.Sort,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取选中的API数据
|
||||
var apiData []map[string]interface{}
|
||||
if len(req.ApiIds) > 0 {
|
||||
apis, err := versionUsecase.GetApisByIds(ctx, req.ApiIds)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取API数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
for _, a := range apis {
|
||||
apiData = append(apiData, map[string]interface{}{
|
||||
"path": a.Path,
|
||||
"description": a.Description,
|
||||
"apiGroup": a.ApiGroup,
|
||||
"method": a.Method,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取选中的字典数据
|
||||
var dictData []map[string]interface{}
|
||||
if len(req.DictIds) > 0 {
|
||||
dicts, err := versionUsecase.GetDictionariesByIds(ctx, req.DictIds)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取字典数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
for _, d := range dicts {
|
||||
dictData = append(dictData, map[string]interface{}{
|
||||
"name": d.Name,
|
||||
"type": d.Type,
|
||||
"status": d.Status,
|
||||
"desc": d.Desc,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 构建导出数据
|
||||
exportData := ExportVersionResponse{
|
||||
Version: VersionInfo{
|
||||
Name: req.VersionName,
|
||||
Code: req.VersionCode,
|
||||
Description: req.Description,
|
||||
ExportTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
Menus: menuData,
|
||||
Apis: apiData,
|
||||
Dictionaries: dictData,
|
||||
}
|
||||
|
||||
// 转换为JSON
|
||||
jsonData, err := json.MarshalIndent(exportData, "", " ")
|
||||
if err != nil {
|
||||
response.FailWithMessage("JSON序列化失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存版本记录
|
||||
version := &system.SysVersion{
|
||||
VersionName: req.VersionName,
|
||||
VersionCode: req.VersionCode,
|
||||
Description: req.Description,
|
||||
VersionData: string(jsonData),
|
||||
}
|
||||
|
||||
if err := versionUsecase.CreateSysVersion(ctx, version); err != nil {
|
||||
response.FailWithMessage("保存版本记录失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("创建发版成功", c)
|
||||
}
|
||||
|
||||
// DownloadVersionJson 下载版本JSON数据
|
||||
func (v *VersionApi) DownloadVersionJson(c *gin.Context) {
|
||||
id := c.Query("ID")
|
||||
if id == "" {
|
||||
response.FailWithMessage("版本ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
version, err := versionUsecase.GetSysVersion(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取版本记录失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
var jsonData []byte
|
||||
if version.VersionData != "" {
|
||||
jsonData = []byte(version.VersionData)
|
||||
} else {
|
||||
basicData := ExportVersionResponse{
|
||||
Version: VersionInfo{
|
||||
Name: version.VersionName,
|
||||
Code: version.VersionCode,
|
||||
Description: version.Description,
|
||||
ExportTime: version.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
}
|
||||
jsonData, _ = json.MarshalIndent(basicData, "", " ")
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("version_%s_%s.json", version.VersionCode, time.Now().Format("20060102150405"))
|
||||
c.Header("Content-Type", "application/json")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
|
||||
c.Header("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
|
||||
c.Data(http.StatusOK, "application/json", jsonData)
|
||||
}
|
||||
|
||||
// ImportVersion 导入版本数据
|
||||
func (v *VersionApi) ImportVersion(c *gin.Context) {
|
||||
var importData map[string]interface{}
|
||||
if err := c.ShouldBindJSON(&importData); err != nil {
|
||||
response.FailWithMessage("解析JSON数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证数据格式
|
||||
versionInfo, ok := importData["version"].(map[string]interface{})
|
||||
if !ok {
|
||||
response.FailWithMessage("版本信息格式错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
name, _ := versionInfo["name"].(string)
|
||||
code, _ := versionInfo["code"].(string)
|
||||
desc, _ := versionInfo["description"].(string)
|
||||
|
||||
if name == "" || code == "" {
|
||||
response.FailWithMessage("版本名称和版本号不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建导入记录
|
||||
jsonData, _ := json.Marshal(importData)
|
||||
version := &system.SysVersion{
|
||||
VersionName: name,
|
||||
VersionCode: fmt.Sprintf("%s_imported_%s", code, time.Now().Format("20060102150405")),
|
||||
Description: fmt.Sprintf("导入版本: %s", desc),
|
||||
VersionData: string(jsonData),
|
||||
}
|
||||
|
||||
if err := versionUsecase.CreateSysVersion(c.Request.Context(), version); err != nil {
|
||||
response.FailWithMessage("保存导入记录失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
|
||||
// toVersionResponse 转换版本响应
|
||||
func toVersionResponse(v *system.SysVersion) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": v.ID,
|
||||
"versionName": v.VersionName,
|
||||
"versionCode": v.VersionCode,
|
||||
"description": v.Description,
|
||||
"versionData": v.VersionData,
|
||||
"createdAt": v.CreatedAt,
|
||||
"updatedAt": v.UpdatedAt,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user