feat(导出模板): 添加SQL预览功能并优化模板展示界面
This commit is contained in:
parent
5d67fc95d2
commit
6bea7bc524
|
|
@ -50,6 +50,34 @@ type SysExportTemplateApi struct {
|
||||||
|
|
||||||
var sysExportTemplateService = service.ServiceGroupApp.SystemServiceGroup.SysExportTemplateService
|
var sysExportTemplateService = service.ServiceGroupApp.SystemServiceGroup.SysExportTemplateService
|
||||||
|
|
||||||
|
// PreviewSQL 预览最终生成的SQL
|
||||||
|
// @Tags SysExportTemplate
|
||||||
|
// @Summary 预览最终生成的SQL(不执行查询,仅返回SQL字符串)
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @accept application/json
|
||||||
|
// @Produce application/json
|
||||||
|
// @Param templateID query string true "导出模板ID"
|
||||||
|
// @Param params query string false "查询参数编码字符串,参考 ExportExcel 组件"
|
||||||
|
// @Success 200 {object} response.Response{data=map[string]string} "获取成功"
|
||||||
|
// @Router /sysExportTemplate/previewSQL [get]
|
||||||
|
func (sysExportTemplateApi *SysExportTemplateApi) PreviewSQL(c *gin.Context) {
|
||||||
|
templateID := c.Query("templateID")
|
||||||
|
if templateID == "" {
|
||||||
|
response.FailWithMessage("模板ID不能为空", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接复用导出接口的参数组织方式:使用 URL Query,其中 params 为内部编码的查询字符串
|
||||||
|
queryParams := c.Request.URL.Query()
|
||||||
|
|
||||||
|
if sqlPreview, err := sysExportTemplateService.PreviewSQL(templateID, queryParams); err != nil {
|
||||||
|
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||||
|
response.FailWithMessage("获取失败", c)
|
||||||
|
} else {
|
||||||
|
response.OkWithData(gin.H{"sql": sqlPreview}, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CreateSysExportTemplate 创建导出模板
|
// CreateSysExportTemplate 创建导出模板
|
||||||
// @Tags SysExportTemplate
|
// @Tags SysExportTemplate
|
||||||
// @Summary 创建导出模板
|
// @Summary 创建导出模板
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ func (s *SysExportTemplateRouter) InitSysExportTemplateRouter(Router *gin.Router
|
||||||
sysExportTemplateRouterWithoutRecord.GET("getSysExportTemplateList", exportTemplateApi.GetSysExportTemplateList) // 获取导出模板列表
|
sysExportTemplateRouterWithoutRecord.GET("getSysExportTemplateList", exportTemplateApi.GetSysExportTemplateList) // 获取导出模板列表
|
||||||
sysExportTemplateRouterWithoutRecord.GET("exportExcel", exportTemplateApi.ExportExcel) // 获取导出token
|
sysExportTemplateRouterWithoutRecord.GET("exportExcel", exportTemplateApi.ExportExcel) // 获取导出token
|
||||||
sysExportTemplateRouterWithoutRecord.GET("exportTemplate", exportTemplateApi.ExportTemplate) // 导出表格模板
|
sysExportTemplateRouterWithoutRecord.GET("exportTemplate", exportTemplateApi.ExportTemplate) // 导出表格模板
|
||||||
|
sysExportTemplateRouterWithoutRecord.GET("previewSQL", exportTemplateApi.PreviewSQL) // 预览SQL
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
sysExportTemplateRouterWithoutAuth.GET("exportExcelByToken", exportTemplateApi.ExportExcelByToken) // 通过token导出表格
|
sysExportTemplateRouterWithoutAuth.GET("exportExcelByToken", exportTemplateApi.ExportExcelByToken) // 通过token导出表格
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,16 @@ func (sysExportTemplateService *SysExportTemplateService) ExportExcel(templateID
|
||||||
sql = fmt.Sprintf("%s %s (?)", condition.Column, condition.Operator)
|
sql = fmt.Sprintf("%s %s (?)", condition.Column, condition.Operator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if condition.Operator == "BETWEEN" {
|
||||||
|
sql = fmt.Sprintf("%s BETWEEN ? AND ?", condition.Column)
|
||||||
|
startValue := paramsValues.Get("start" + condition.From)
|
||||||
|
endValue := paramsValues.Get("end" + condition.From)
|
||||||
|
if startValue != "" && endValue != "" {
|
||||||
|
db = db.Where(sql, startValue, endValue)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if value != "" {
|
if value != "" {
|
||||||
if condition.Operator == "LIKE" {
|
if condition.Operator == "LIKE" {
|
||||||
value = "%" + value + "%"
|
value = "%" + value + "%"
|
||||||
|
|
@ -317,14 +327,14 @@ func (sysExportTemplateService *SysExportTemplateService) ExportExcel(templateID
|
||||||
for j, colCell := range row {
|
for j, colCell := range row {
|
||||||
cell := fmt.Sprintf("%s%d", getColumnName(j+1), i+1)
|
cell := fmt.Sprintf("%s%d", getColumnName(j+1), i+1)
|
||||||
|
|
||||||
var sErr error
|
var sErr error
|
||||||
if v, err := strconv.ParseFloat(colCell, 64); err == nil {
|
if v, err := strconv.ParseFloat(colCell, 64); err == nil {
|
||||||
sErr = f.SetCellValue("Sheet1", cell, v)
|
sErr = f.SetCellValue("Sheet1", cell, v)
|
||||||
} else if v, err := strconv.ParseInt(colCell, 10, 64); err == nil {
|
} else if v, err := strconv.ParseInt(colCell, 10, 64); err == nil {
|
||||||
sErr = f.SetCellValue("Sheet1", cell, v)
|
sErr = f.SetCellValue("Sheet1", cell, v)
|
||||||
} else {
|
} else {
|
||||||
sErr = f.SetCellValue("Sheet1", cell, colCell)
|
sErr = f.SetCellValue("Sheet1", cell, colCell)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return nil, "", sErr
|
return nil, "", sErr
|
||||||
|
|
@ -340,6 +350,185 @@ func (sysExportTemplateService *SysExportTemplateService) ExportExcel(templateID
|
||||||
return file, template.Name, nil
|
return file, template.Name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreviewSQL 预览最终生成的 SQL(不执行查询,仅返回 SQL 字符串)
|
||||||
|
// Author [piexlmax](https://github.com/piexlmax) & [trae-ai]
|
||||||
|
func (sysExportTemplateService *SysExportTemplateService) PreviewSQL(templateID string, values url.Values) (sqlPreview string, err error) {
|
||||||
|
// 解析 params(与导出逻辑保持一致)
|
||||||
|
var params = values.Get("params")
|
||||||
|
paramsValues, _ := url.ParseQuery(params)
|
||||||
|
|
||||||
|
// 加载模板
|
||||||
|
var template system.SysExportTemplate
|
||||||
|
err = global.GVA_DB.Preload("Conditions").Preload("JoinTemplate").First(&template, "template_id = ?", templateID).Error
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析模板列
|
||||||
|
var templateInfoMap = make(map[string]string)
|
||||||
|
columns, err := utils.GetJSONKeys(template.TemplateInfo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var selectKeyFmt []string
|
||||||
|
for _, key := range columns {
|
||||||
|
selectKeyFmt = append(selectKeyFmt, key)
|
||||||
|
}
|
||||||
|
selects := strings.Join(selectKeyFmt, ", ")
|
||||||
|
|
||||||
|
// 生成 FROM 与 JOIN 片段
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString("SELECT ")
|
||||||
|
sb.WriteString(selects)
|
||||||
|
sb.WriteString(" FROM ")
|
||||||
|
sb.WriteString(template.TableName)
|
||||||
|
|
||||||
|
if len(template.JoinTemplate) > 0 {
|
||||||
|
for _, join := range template.JoinTemplate {
|
||||||
|
sb.WriteString(" ")
|
||||||
|
sb.WriteString(join.JOINS)
|
||||||
|
sb.WriteString(" ")
|
||||||
|
sb.WriteString(join.Table)
|
||||||
|
sb.WriteString(" ON ")
|
||||||
|
sb.WriteString(join.ON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WHERE 条件
|
||||||
|
var wheres []string
|
||||||
|
|
||||||
|
// 软删除过滤
|
||||||
|
filterDeleted := false
|
||||||
|
if paramsValues != nil {
|
||||||
|
filterParam := paramsValues.Get("filterDeleted")
|
||||||
|
if filterParam == "true" {
|
||||||
|
filterDeleted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filterDeleted {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", template.TableName))
|
||||||
|
if len(template.JoinTemplate) > 0 {
|
||||||
|
for _, join := range template.JoinTemplate {
|
||||||
|
if sysExportTemplateService.hasDeletedAtColumn(join.Table) {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s.deleted_at IS NULL", join.Table))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板条件(保留与 ExportExcel 同步的解析规则)
|
||||||
|
if len(template.Conditions) > 0 {
|
||||||
|
for _, condition := range template.Conditions {
|
||||||
|
op := strings.ToUpper(strings.TrimSpace(condition.Operator))
|
||||||
|
col := strings.TrimSpace(condition.Column)
|
||||||
|
|
||||||
|
// 预览优先展示传入值,没有则展示占位符
|
||||||
|
val := ""
|
||||||
|
if paramsValues != nil {
|
||||||
|
val = paramsValues.Get(condition.From)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case "BETWEEN":
|
||||||
|
startValue := ""
|
||||||
|
endValue := ""
|
||||||
|
if paramsValues != nil {
|
||||||
|
startValue = paramsValues.Get("start" + condition.From)
|
||||||
|
endValue = paramsValues.Get("end" + condition.From)
|
||||||
|
}
|
||||||
|
if startValue != "" && endValue != "" {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s BETWEEN '%s' AND '%s'", col, startValue, endValue))
|
||||||
|
} else {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s BETWEEN {start%s} AND {end%s}", col, condition.From, condition.From))
|
||||||
|
}
|
||||||
|
case "IN", "NOT IN":
|
||||||
|
if val != "" {
|
||||||
|
// 逗号分隔值做简单展示
|
||||||
|
parts := strings.Split(val, ",")
|
||||||
|
for i := range parts { parts[i] = strings.TrimSpace(parts[i]) }
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s %s ('%s')", col, op, strings.Join(parts, "','")))
|
||||||
|
} else {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s %s ({%s})", col, op, condition.From))
|
||||||
|
}
|
||||||
|
case "LIKE":
|
||||||
|
if val != "" {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s LIKE '%%%s%%'", col, val))
|
||||||
|
} else {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s LIKE {%%%s%%}", col, condition.From))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if val != "" {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s %s '%s'", col, op, val))
|
||||||
|
} else {
|
||||||
|
wheres = append(wheres, fmt.Sprintf("%s %s {%s}", col, op, condition.From))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(wheres) > 0 {
|
||||||
|
sb.WriteString(" WHERE ")
|
||||||
|
sb.WriteString(strings.Join(wheres, " AND "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
order := ""
|
||||||
|
if paramsValues != nil {
|
||||||
|
order = paramsValues.Get("order")
|
||||||
|
}
|
||||||
|
if order == "" && template.Order != "" {
|
||||||
|
order = template.Order
|
||||||
|
}
|
||||||
|
if order != "" {
|
||||||
|
sb.WriteString(" ORDER BY ")
|
||||||
|
sb.WriteString(order)
|
||||||
|
}
|
||||||
|
|
||||||
|
// limit/offset(如果传入或默认值为0,则不生成)
|
||||||
|
limitStr := ""
|
||||||
|
offsetStr := ""
|
||||||
|
if paramsValues != nil {
|
||||||
|
limitStr = paramsValues.Get("limit")
|
||||||
|
offsetStr = paramsValues.Get("offset")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理模板默认limit(仅当非0时)
|
||||||
|
if limitStr == "" && template.Limit != nil && *template.Limit != 0 {
|
||||||
|
limitStr = strconv.Itoa(*template.Limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析为数值,用于判断是否生成
|
||||||
|
limitInt := 0
|
||||||
|
offsetInt := 0
|
||||||
|
if limitStr != "" {
|
||||||
|
if v, e := strconv.Atoi(limitStr); e == nil { limitInt = v }
|
||||||
|
}
|
||||||
|
if offsetStr != "" {
|
||||||
|
if v, e := strconv.Atoi(offsetStr); e == nil { offsetInt = v }
|
||||||
|
}
|
||||||
|
|
||||||
|
if limitInt > 0 {
|
||||||
|
sb.WriteString(" LIMIT ")
|
||||||
|
sb.WriteString(strconv.Itoa(limitInt))
|
||||||
|
if offsetInt > 0 {
|
||||||
|
sb.WriteString(" OFFSET ")
|
||||||
|
sb.WriteString(strconv.Itoa(offsetInt))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 当limit未设置或为0时,仅当offset>0才生成OFFSET
|
||||||
|
if offsetInt > 0 {
|
||||||
|
sb.WriteString(" OFFSET ")
|
||||||
|
sb.WriteString(strconv.Itoa(offsetInt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ExportTemplate 导出Excel模板
|
// ExportTemplate 导出Excel模板
|
||||||
// Author [piexlmax](https://github.com/piexlmax)
|
// Author [piexlmax](https://github.com/piexlmax)
|
||||||
func (sysExportTemplateService *SysExportTemplateService) ExportTemplate(templateID string) (file *bytes.Buffer, name string, err error) {
|
func (sysExportTemplateService *SysExportTemplateService) ExportTemplate(templateID string) (file *bytes.Buffer, name string, err error) {
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ func (i *initApi) InitializeData(ctx context.Context) (context.Context, error) {
|
||||||
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/getSysExportTemplateList", Description: "获取导出模板列表"},
|
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/getSysExportTemplateList", Description: "获取导出模板列表"},
|
||||||
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/exportExcel", Description: "导出Excel"},
|
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/exportExcel", Description: "导出Excel"},
|
||||||
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/exportTemplate", Description: "下载模板"},
|
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/exportTemplate", Description: "下载模板"},
|
||||||
|
{ApiGroup: "导出模板", Method: "GET", Path: "/sysExportTemplate/previewSQL", Description: "预览SQL"},
|
||||||
{ApiGroup: "导出模板", Method: "POST", Path: "/sysExportTemplate/importExcel", Description: "导入Excel"},
|
{ApiGroup: "导出模板", Method: "POST", Path: "/sysExportTemplate/importExcel", Description: "导入Excel"},
|
||||||
|
|
||||||
{ApiGroup: "公告", Method: "POST", Path: "/info/createInfo", Description: "新建公告"},
|
{ApiGroup: "公告", Method: "POST", Path: "/info/createInfo", Description: "新建公告"},
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ func (i *initCasbin) InitializeData(ctx context.Context) (context.Context, error
|
||||||
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/getSysExportTemplateList", V2: "GET"},
|
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/getSysExportTemplateList", V2: "GET"},
|
||||||
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/exportExcel", V2: "GET"},
|
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/exportExcel", V2: "GET"},
|
||||||
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/exportTemplate", V2: "GET"},
|
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/exportTemplate", V2: "GET"},
|
||||||
|
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/previewSQL", V2: "GET"},
|
||||||
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/importExcel", V2: "POST"},
|
{Ptype: "p", V0: "888", V1: "/sysExportTemplate/importExcel", V2: "POST"},
|
||||||
|
|
||||||
{Ptype: "p", V0: "888", V1: "/info/createInfo", V2: "POST"},
|
{Ptype: "p", V0: "888", V1: "/info/createInfo", V2: "POST"},
|
||||||
|
|
|
||||||
|
|
@ -126,3 +126,20 @@ export const exportTemplate = (params) => {
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreviewSQL 预览最终生成的SQL
|
||||||
|
// @Tags SysExportTemplate
|
||||||
|
// @Summary 预览最终生成的SQL
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @accept application/json
|
||||||
|
// @Produce application/json
|
||||||
|
// @Router /sysExportTemplate/previewSQL [get]
|
||||||
|
// @Param templateID query string true "导出模板ID"
|
||||||
|
// @Param params query string false "查询参数编码字符串,参考 ExportExcel 组件"
|
||||||
|
export const previewSQL = (params) => {
|
||||||
|
return service({
|
||||||
|
url: '/sysExportTemplate/previewSQL',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
"/src/view/systemTools/index.vue": "System",
|
"/src/view/systemTools/index.vue": "System",
|
||||||
"/src/view/systemTools/installPlugin/index.vue": "Index",
|
"/src/view/systemTools/installPlugin/index.vue": "Index",
|
||||||
"/src/view/systemTools/pubPlug/pubPlug.vue": "PubPlug",
|
"/src/view/systemTools/pubPlug/pubPlug.vue": "PubPlug",
|
||||||
|
"/src/view/systemTools/sysError/sysError.vue": "SysError",
|
||||||
"/src/view/systemTools/system/system.vue": "Config",
|
"/src/view/systemTools/system/system.vue": "Config",
|
||||||
"/src/view/systemTools/version/version.vue": "SysVersion",
|
"/src/view/systemTools/version/version.vue": "SysVersion",
|
||||||
"/src/plugin/announcement/form/info.vue": "InfoForm",
|
"/src/plugin/announcement/form/info.vue": "InfoForm",
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@
|
||||||
icon="edit-pen"
|
icon="edit-pen"
|
||||||
class="table-button"
|
class="table-button"
|
||||||
@click="showCode(scope.row)"
|
@click="showCode(scope.row)"
|
||||||
>代码</el-button
|
>代码和SQL预览</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -401,28 +401,79 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
<!-- 合并:代码模板 + SQL预览 抽屉 -->
|
||||||
<el-drawer
|
<el-drawer
|
||||||
v-model="codeVisible"
|
v-model="drawerVisible"
|
||||||
size="60%"
|
size="70%"
|
||||||
:before-close="closeDialog"
|
:title="'模板与预览'"
|
||||||
:title="type === 'create' ? '添加' : '修改'"
|
:show-close="true"
|
||||||
:show-close="false"
|
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class="text-lg">模板</span>
|
<span class="text-lg">模板与预览</span>
|
||||||
<div>
|
<div>
|
||||||
<el-button type="primary" @click="closeDialog">确 定</el-button>
|
<el-button @click="drawerVisible = false">关 闭</el-button>
|
||||||
|
<el-button v-if="activeTab === 'sql'" type="primary" @click="runPreview">生 成</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<v-ace-editor
|
<el-tabs v-model="activeTab" type="border-card">
|
||||||
v-model:value="webCode"
|
<el-tab-pane label="代码模板" name="code">
|
||||||
lang="vue"
|
<v-ace-editor
|
||||||
theme="github_dark"
|
v-model:value="webCode"
|
||||||
class="h-full"
|
lang="vue"
|
||||||
/>
|
theme="github_dark"
|
||||||
|
class="w-full h-96"
|
||||||
|
:options="{ showPrintMargin: false, fontSize: 14 }"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="SQL预览" name="sql">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="w-full">
|
||||||
|
<el-form :model="previewForm" label-width="120px">
|
||||||
|
<el-form-item label="过滤已删除">
|
||||||
|
<el-switch v-model="previewForm.filterDeleted" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="默认排序">
|
||||||
|
<el-input v-model="previewForm.order" placeholder="例如: id desc" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="限制条数">
|
||||||
|
<el-input-number v-model="previewForm.limit" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="偏移量">
|
||||||
|
<el-input-number v-model="previewForm.offset" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-divider content-position="left">查询条件</el-divider>
|
||||||
|
<div v-if="previewConditions.length === 0" class="text-gray">该模板暂无条件</div>
|
||||||
|
<template v-for="(cond, idx) in previewConditions" :key="idx">
|
||||||
|
<el-form-item :label="cond.column + ' ' + cond.operator">
|
||||||
|
<template v-if="cond.operator === 'BETWEEN'">
|
||||||
|
<div class="flex gap-2 w-full">
|
||||||
|
<el-input v-model="previewForm['start' + cond.from]" placeholder="开始值: start{{cond.from}}" />
|
||||||
|
<el-input v-model="previewForm['end' + cond.from]" placeholder="结束值: end{{cond.from}}" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-input v-model="previewForm[cond.from]" :placeholder="'变量: ' + cond.from" />
|
||||||
|
</template>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<v-ace-editor
|
||||||
|
v-model:value="previewSQLCode"
|
||||||
|
lang="sql"
|
||||||
|
theme="github_dark"
|
||||||
|
class="w-full h-96"
|
||||||
|
:options="aceOptions"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -436,6 +487,7 @@
|
||||||
findSysExportTemplate,
|
findSysExportTemplate,
|
||||||
getSysExportTemplateList
|
getSysExportTemplateList
|
||||||
} from '@/api/exportTemplate.js'
|
} from '@/api/exportTemplate.js'
|
||||||
|
import { previewSQL } from '@/api/exportTemplate.js'
|
||||||
|
|
||||||
// 全量引入格式化工具 请按需保留
|
// 全量引入格式化工具 请按需保留
|
||||||
import { formatDate } from '@/utils/format'
|
import { formatDate } from '@/utils/format'
|
||||||
|
|
@ -448,6 +500,7 @@
|
||||||
|
|
||||||
import 'ace-builds/src-noconflict/mode-vue'
|
import 'ace-builds/src-noconflict/mode-vue'
|
||||||
import 'ace-builds/src-noconflict/theme-github_dark'
|
import 'ace-builds/src-noconflict/theme-github_dark'
|
||||||
|
import 'ace-builds/src-noconflict/mode-sql'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ExportTemplate'
|
name: 'ExportTemplate'
|
||||||
|
|
@ -903,7 +956,8 @@ JOINS模式下不支持导入
|
||||||
getTableData()
|
getTableData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const codeVisible = ref(false)
|
const drawerVisible = ref(false)
|
||||||
|
const activeTab = ref('code')
|
||||||
// 弹窗控制标记
|
// 弹窗控制标记
|
||||||
const dialogFormVisible = ref(false)
|
const dialogFormVisible = ref(false)
|
||||||
|
|
||||||
|
|
@ -911,7 +965,56 @@ JOINS模式下不支持导入
|
||||||
|
|
||||||
const showCode = (row) => {
|
const showCode = (row) => {
|
||||||
webCode.value = getCode(row.templateID)
|
webCode.value = getCode(row.templateID)
|
||||||
codeVisible.value = true
|
activeTab.value = 'code'
|
||||||
|
drawerVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览 SQL
|
||||||
|
const previewForm = ref({ filterDeleted: true, order: '', limit: 0, offset: 0 })
|
||||||
|
const previewSQLCode = ref('')
|
||||||
|
const previewTemplate = ref(null)
|
||||||
|
const previewConditions = ref([])
|
||||||
|
const aceOptions = { wrap: true, showPrintMargin: false, fontSize: 14 }
|
||||||
|
|
||||||
|
const openPreview = async (row) => {
|
||||||
|
// 获取模板完整信息以展示条件输入项
|
||||||
|
const res = await findSysExportTemplate({ ID: row.ID })
|
||||||
|
if (res.code === 0) {
|
||||||
|
previewTemplate.value = res.data.resysExportTemplate
|
||||||
|
previewConditions.value = (previewTemplate.value.conditions || []).map((c) => ({
|
||||||
|
from: c.from,
|
||||||
|
column: c.column,
|
||||||
|
operator: c.operator
|
||||||
|
}))
|
||||||
|
// 预填默认的排序与限制
|
||||||
|
previewForm.value.order = previewTemplate.value.order || ''
|
||||||
|
previewForm.value.limit = previewTemplate.value.limit || 0
|
||||||
|
previewForm.value.offset = 0
|
||||||
|
previewSQLCode.value = ''
|
||||||
|
activeTab.value = 'sql'
|
||||||
|
drawerVisible.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runPreview = async () => {
|
||||||
|
if (!previewTemplate.value) return
|
||||||
|
// 组装 params,与导出组件保持一致
|
||||||
|
const paramsCopy = JSON.parse(JSON.stringify(previewForm.value))
|
||||||
|
// 将布尔与数值等按照导出组件规则编码
|
||||||
|
if (paramsCopy.filterDeleted) paramsCopy.filterDeleted = 'true'
|
||||||
|
const entries = Object.entries(paramsCopy).filter(([key, v]) => {
|
||||||
|
if (v === '' || v === null || v === undefined) return false
|
||||||
|
if ((key === 'limit' || key === 'offset') && Number(v) === 0) return false
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
const params = entries
|
||||||
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||||||
|
.join('&')
|
||||||
|
|
||||||
|
const res = await previewSQL({ templateID: previewTemplate.value.templateID, params })
|
||||||
|
if (res.code === 0) {
|
||||||
|
previewSQLCode.value = res.data.sql || ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
|
|
@ -922,7 +1025,6 @@ JOINS模式下不支持导入
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
codeVisible.value = false
|
|
||||||
dialogFormVisible.value = false
|
dialogFormVisible.value = false
|
||||||
formData.value = {
|
formData.value = {
|
||||||
name: '',
|
name: '',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue