7575 <el-button size =" small" @click =" deleteCol" >删列</el-button >
7676 <el-button size =" small" :disabled =" !canUndo" @click =" undo" title =" Ctrl+Z" >↩</el-button >
7777 <el-button size =" small" :disabled =" !canRedo" @click =" redo" title =" Ctrl+Y" >↪</el-button >
78+ <el-button size =" small" type =" primary" plain @click =" paramDialogVisible = true" >查询参数</el-button >
7879 <span style =" font-size :11px ;color :#888 ;margin-left :4px " >Ctrl多选</span >
7980 </div >
8081 <div class =" grid-wrapper" @scroll =" onGridScroll" >
@@ -362,10 +363,38 @@ NOW() / TODAY() / ROW() 当前时间 / 日期 / 行号</pre>
362363 </div >
363364 </el-dialog >
364365
366+ <!-- 查询参数配置 -->
367+ <el-dialog v-model =" paramDialogVisible" title =" 查询参数配置" width =" 820px" append-to-body >
368+ <div v-for =" (p, i) in previewParams" :key =" i" style =" display :flex ;gap :6px ;margin-bottom :6px ;align-items :center " >
369+ <el-input v-model =" p.name" placeholder =" 参数名(如 beginDate)" size =" small" style =" width :150px ;flex-shrink :0 " />
370+ <el-input v-model =" p.label" placeholder =" 显示名" size =" small" style =" width :110px ;flex-shrink :0 " />
371+ <el-select v-model =" p.type" size =" small" style =" width :90px ;flex-shrink :0 " >
372+ <el-option value =" text" label =" 文本" />
373+ <el-option value =" number" label =" 数字" />
374+ <el-option value =" date" label =" 日期" />
375+ <el-option value =" switch" label =" 开关" />
376+ <el-option value =" select" label =" 下拉" />
377+ </el-select >
378+ <el-input v-if =" p.type==='select'" v-model =" p.options" placeholder =" 选项,逗号/换行分隔" size =" small" style =" width :180px ;flex-shrink :0 " />
379+ <el-input v-else-if =" p.type!=='switch'" v-model =" p.default" placeholder =" 默认值" size =" small" style =" width :110px ;flex-shrink :0 " />
380+ <el-switch v-else v-model =" p.default" size =" small" />
381+ <span v-if =" p.type==='switch'" style =" font-size :11px ;color :#888 ;width :70px ;flex-shrink :0 " >{{ p.default ? '默认开' : '默认关' }}</span >
382+ <el-button size =" small" type =" danger" link @click =" previewParams.splice(i, 1)" >删</el-button >
383+ </div >
384+ <el-button size =" small" @click =" previewParams.push({ name:'', label:'', type:'text', default:'' })" >+添加参数</el-button >
385+ <div style =" margin-top :8px ;color :#909399 ;font-size :12px " >
386+ 参数类型:文本/数字/日期/开关/下拉(下拉需填选项,逗号或换行分隔)。默认值在正式访问页生效;访问 URL 带同参数名(如 ?beginDate=2026-01-01)时以 URL 值为准。<br >
387+ 数据集 SQL 中用 <code >@参数名</code > 引用即可按查询条件过滤,推荐写成 <code >(@参数名 IS NULL OR 字段 = @参数名)</code > / <code >(@kw IS NULL OR 字段 LIKE '%' || @kw || '%')</code > — 未填值时该条件自动失效(不过滤)。
388+ </div >
389+ <template #footer >
390+ <el-button @click =" paramDialogVisible=false" >关闭</el-button >
391+ </template >
392+ </el-dialog >
393+
365394 <!-- 预览 -->
366395 <el-dialog v-model =" showPreview" title =" 预览" width =" 90%" top =" 5vh" >
367- <div v-if = " previewParams.length>0 " style =" display :flex ;gap :8px ;margin-bottom :12px ;flex-wrap :wrap " >
368- <el-input v-for = " p in previewParams" :key = " p.name " v-model = " previewValues[p.name] " size = " small " style = " width : 160 px " :placeholder = " p.label||p.name " />
396+ <div style =" display :flex ;gap :8px ;margin-bottom :12px ;flex-wrap :wrap ; align-items : flex-end " >
397+ <ReportParams : params = " previewParams " :values = " previewValues " />
369398 <el-button size =" small" type =" primary" @click =" doRender" >查询</el-button >
370399 <el-button size =" small" @click =" doPrint" >打印</el-button >
371400 </div >
@@ -392,7 +421,9 @@ import { Edit, View, Refresh, Loading, Close } from '@element-plus/icons-vue'
392421import request from ' ../../utils/request'
393422import DbObjectBrowser from ' ../../components/DbObjectBrowser.vue'
394423import SqlTestDialog from ' ../../components/SqlTestDialog.vue'
424+ import ReportParams from ' ../../components/ReportParams.vue'
395425import { generateColumnMapping } from ' ../../utils/dbAssist'
426+ import { initParamValues , buildParamPayload } from ' ../../utils/reportParams'
396427
397428const route = useRoute ()
398429const router = useRouter ()
@@ -442,6 +473,7 @@ const rowDataset = ref('') // 当前选中行绑定的数据
442473const rowZebras = ref <Record <number , boolean >>({}) // 行号 → 斑马纹开关
443474const rowZebra = ref (false ) // 当前选中行的斑马纹
444475const showPreview = ref (false ), pageSettingsVisible = ref (false )
476+ const paramDialogVisible = ref (false )
445477const formulaHelpVisible = ref (false )
446478const previewHtml = ref (' ' ), previewParams = ref <any []>([])
447479const previewValues = ref <Record <string ,any >>({})
@@ -1061,11 +1093,26 @@ async function saveReport() { saveLayoutJson()
10611093 else { const res= await request .post (' /report/add' ,form ); form .id = res .data ; ElMessage .success (' 已创建' ) }
10621094}
10631095
1064- function openPreview() { saveLayoutJson (); showPreview .value = true ; doRender () }
1096+ function openPreview() {
1097+ saveLayoutJson ()
1098+ previewValues .value = initParamValues (previewParams .value )
1099+ showPreview .value = true
1100+ doRender ()
1101+ }
10651102
1066- async function doRender() { try { const res= await request .post (' /report/preview' ,{id:form .id ,params:previewValues .value }); previewHtml .value = res .data ?.html || ' ' } catch { ElMessage .error (' 预览失败' ) } }
1103+ async function doRender() {
1104+ try {
1105+ const res = await request .post (' /report/preview' , { id: form .id , params: buildParamPayload (previewParams .value , previewValues .value ) })
1106+ previewHtml .value = res .data ?.html || ' '
1107+ } catch { ElMessage .error (' 预览失败' ) }
1108+ }
10671109
1068- function doPrint() { window .print () }
1110+ function doPrint() {
1111+ const w = window .open (' ' , ' _blank' )
1112+ if (! w || ! previewHtml .value ) { ElMessage .warning (' 请先预览再打印' ); return }
1113+ w .document .write (` <html><head><title>${form .name }</title><meta charset="utf-8"><style>@media print{@page{size:A4;margin:15mm}}body{font-family:'Microsoft YaHei',sans-serif}</style></head><body>${previewHtml .value }</body></html> ` )
1114+ w .document .close (); w .focus (); setTimeout (() => { w .print () }, 300 )
1115+ }
10691116
10701117function colLetter(n : number ): string { return String .fromCharCode (65 + n ) }
10711118 </script >
0 commit comments