638 lines
19 KiB
Go
638 lines
19 KiB
Go
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 创建导出模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param data body CreateSysExportTemplateRequest true "创建导出模板"
|
|
// @Success 200 {object} response.Response{msg=string} "创建成功"
|
|
// @Router /sysExportTemplate/createSysExportTemplate [post]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 删除导出模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param data body DeleteSysExportTemplateRequest true "删除导出模板"
|
|
// @Success 200 {object} response.Response{msg=string} "删除成功"
|
|
// @Router /sysExportTemplate/deleteSysExportTemplate [delete]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 批量删除导出模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param data body DeleteSysExportTemplateByIdsRequest true "批量删除导出模板"
|
|
// @Success 200 {object} response.Response{msg=string} "批量删除成功"
|
|
// @Router /sysExportTemplate/deleteSysExportTemplateByIds [delete]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 更新导出模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param data body UpdateSysExportTemplateRequest true "更新导出模板"
|
|
// @Success 200 {object} response.Response{msg=string} "更新成功"
|
|
// @Router /sysExportTemplate/updateSysExportTemplate [put]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 用id查询导出模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param ID query uint true "用id查询导出模板"
|
|
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "查询成功"
|
|
// @Router /sysExportTemplate/findSysExportTemplate [get]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 分页获取导出模板列表
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param data query GetSysExportTemplateListRequest true "分页获取导出模板列表"
|
|
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功"
|
|
// @Router /sysExportTemplate/getSysExportTemplateList [get]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 导出表格token
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param templateID query string true "模板ID"
|
|
// @Success 200 {object} response.Response{data=string,msg=string} "获取导出链接"
|
|
// @Router /sysExportTemplate/exportExcel [get]
|
|
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
|
|
// @Tags ExportExcelByToken
|
|
// @Summary 导出表格
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param token query string true "导出token"
|
|
// @Success 200 {file} csv "导出CSV文件"
|
|
// @Router /sysExportTemplate/exportExcelByToken [get]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 预览最终生成的SQL
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param templateID query string true "导出模板ID"
|
|
// @Param params query string false "查询参数编码字符串"
|
|
// @Success 200 {object} response.Response{data=map[string]string,msg=string} "获取成功"
|
|
// @Router /sysExportTemplate/previewSQL [get]
|
|
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
|
|
// @Tags SysExportTemplate
|
|
// @Summary 导出表格模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param templateID query string true "模板ID"
|
|
// @Success 200 {object} response.Response{data=string,msg=string} "获取导出链接"
|
|
// @Router /sysExportTemplate/exportTemplate [get]
|
|
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
|
|
// @Tags ExportTemplateByToken
|
|
// @Summary 通过token导出表格模板
|
|
// @Security ApiKeyAuth
|
|
// @accept application/json
|
|
// @Produce application/json
|
|
// @Param token query string true "导出token"
|
|
// @Success 200 {file} csv "导出CSV模板文件"
|
|
// @Router /sysExportTemplate/exportTemplateByToken [get]
|
|
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
|
|
// @Tags SysImportTemplate
|
|
// @Summary 导入表格
|
|
// @Security ApiKeyAuth
|
|
// @accept multipart/form-data
|
|
// @Produce application/json
|
|
// @Param templateID query string true "模板ID"
|
|
// @Param file formData file true "导入文件"
|
|
// @Success 200 {object} response.Response{msg=string} "导入成功"
|
|
// @Router /sysExportTemplate/importExcel [post]
|
|
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
|
|
}
|