|
133 | 133 | <h4 style="margin:0 0 8px">单元格属性</h4> |
134 | 134 | <div v-if="hasSelection" style="font-size:12px"> |
135 | 135 | <p>位置: {{ hasSelection ? colLetter(selC) + (selR+1) : '' }} {{ selectedCells.length>1 ? `(+${selectedCells.length-1}格)` : '' }}</p> |
136 | | - <p>值:</p> |
| 136 | + <div style="display:flex;align-items:center;justify-content:space-between;margin:8px 0 2px"> |
| 137 | + <span>值:</span> |
| 138 | + <el-button size="small" icon="QuestionFilled" link title="公式语法帮助" @click="formulaHelpVisible = true">公式帮助</el-button> |
| 139 | + </div> |
137 | 140 | <el-input v-model="cellValue" type="textarea" :rows="3" size="small" @input="updateCellValue" placeholder="文本 / ${fieldName} / =SUM(A1:A10)" /> |
138 | 141 | <p style="margin:8px 0 4px">类型:</p> |
139 | 142 | <el-select v-model="rowType" size="small" style="width:100%" @change="updateRowType"> |
|
155 | 158 | 渲染 1 次,用于表格列头(姓名/金额/日期…)。 |
156 | 159 | </div> |
157 | 160 | <div v-else-if="rowType==='data'" style="margin-top:6px;color:#909399;font-size:11px;line-height:1.6"> |
158 | | - 绑定数据集后按<b>每条数据自动扩展一行</b>。单元格可写 <code>${'${字段名}'}</code>、<code>${'${数据集.字段}'}</code>、<code>${'${rowIndex}'}</code>(行号)或 <code>=公式</code>。 |
| 161 | + 绑定数据集后按<b>每条数据自动扩展一行</b>。单元格可写 <code>${字段名}</code>、<code>${数据集.字段}</code>、<code>${rowIndex}</code>(行号)或 <code>=公式</code>。 |
159 | 162 | </div> |
160 | 163 | <div v-else-if="rowType==='footer'" style="margin-top:6px;color:#909399;font-size:11px;line-height:1.6"> |
161 | | - 渲染 1 次(数据行下方)。绑定数据集后支持聚合:<code>${'${金额:SUM}'}</code>、<code>${'${字段:AVG}'}</code>、MIN / MAX / COUNT。 |
| 164 | + 渲染 1 次(数据行下方)。绑定数据集后支持聚合:<code>${金额:SUM}</code>、<code>${字段:AVG}</code>、MIN / MAX / COUNT。 |
162 | 165 | </div> |
163 | 166 | </div> |
164 | 167 | <el-empty v-else description="点击单元格查看属性" /> |
|
287 | 290 | </div> |
288 | 291 | </el-dialog> |
289 | 292 |
|
| 293 | + <!-- 单元格公式语法帮助 --> |
| 294 | + <el-dialog v-model="formulaHelpVisible" title="❓ 单元格公式语法帮助" width="680px" append-to-body> |
| 295 | + <div class="formula-help"> |
| 296 | + <div class="fh-section">一、占位符(数据行 / 表头 / 汇总行均可使用)</div> |
| 297 | + <pre>${字段名} 当前数据行该字段的值,如 ${name} |
| 298 | +${数据集.字段} 指定数据集的字段(跨数据集引用,取第 0 行),如 ${订单.amount} |
| 299 | +${rowIndex} 数据行行号(从 1 开始)</pre> |
| 300 | + <div class="fh-section">二、聚合占位符(汇总行绑定数据集后生效)</div> |
| 301 | + <pre>${金额:SUM} 合计 |
| 302 | +${金额:AVG} 平均值 |
| 303 | +${金额:MIN} 最小值 |
| 304 | +${金额:MAX} 最大值 |
| 305 | +${金额:COUNT} 条数 |
| 306 | +(支持 ${数据集.金额:SUM} 指定数据集)</pre> |
| 307 | + <div class="fh-section">三、公式(= 开头,数据行可用当前行字段参与计算)</div> |
| 308 | + <pre>=IF(${amount} >= 100, '大额', '小额') 条件判断 |
| 309 | +=${amount} * 1.1 算术 |
| 310 | +=ROUND(${amount} / 3, 2) 四舍五入 |
| 311 | +=SUM(A1:A10) 静态单元格范围求和 |
| 312 | +=UPPER(${name}) 转大写</pre> |
| 313 | + <div class="fh-section">四、可用函数</div> |
| 314 | + <pre>SUM / AVG / MIN / MAX / COUNT 统计(支持范围引用 A1:A10) |
| 315 | +IF(条件, 真值, 假值) 条件函数 |
| 316 | +SUBSTR(文本, 起, 长) 截取 LEN 长度 |
| 317 | +UPPER / LOWER / TRIM 大小写 / 去空格 |
| 318 | +CONCAT(a, b) 拼接 ROUND(x, 位) ABS(x) |
| 319 | +NOW() / TODAY() / ROW() 当前时间 / 日期 / 行号</pre> |
| 320 | + <div class="fh-section">五、运算符</div> |
| 321 | + <pre>算术: + - * / % 比较: == != > < >= <= |
| 322 | +逻辑: && || ! 三元: 条件 ? 真值 : 假值</pre> |
| 323 | + <div class="fh-note" style="margin-top:8px"> |
| 324 | + 占位符在数据行逐行替换;汇总行用聚合占位符。公式以 = 开头时用公式引擎计算,优先级:先替换占位符再算公式。 |
| 325 | + </div> |
| 326 | + </div> |
| 327 | + </el-dialog> |
| 328 | + |
290 | 329 | <!-- 预览 --> |
291 | 330 | <el-dialog v-model="showPreview" title="预览" width="90%" top="5vh"> |
292 | 331 | <div v-if="previewParams.length>0" style="display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap"> |
@@ -359,6 +398,7 @@ const rowTypes = ref<string[]>([]) // 每行类型: title/header/data |
359 | 398 | const rowDatasets = ref<Record<number, string>>({}) // 行号 → 数据集id |
360 | 399 | const rowDataset = ref('') // 当前选中行绑定的数据集 |
361 | 400 | const showPreview = ref(false), pageSettingsVisible = ref(false) |
| 401 | +const formulaHelpVisible = ref(false) |
362 | 402 | const previewHtml = ref(''), previewParams = ref<any[]>([]) |
363 | 403 | const previewValues = ref<Record<string,any>>({}) |
364 | 404 |
|
@@ -874,6 +914,11 @@ function colLetter(n:number):string { return String.fromCharCode(65+n) } |
874 | 914 | <style scoped> |
875 | 915 | .designer-container{height:100vh;display:flex;flex-direction:column;background:#f5f5f5} |
876 | 916 | .code-editor :deep(textarea) { font-family: Consolas, Monaco, 'Courier New', monospace; font-size: 12px; } |
| 917 | +.formula-help { max-height: 60vh; overflow-y: auto; } |
| 918 | +.formula-help pre { background: #f6f8fa; border: 1px solid #e4e7ed; border-radius: 6px; padding: 8px 10px; font-size: 12px; line-height: 1.9; margin: 0 0 4px; overflow-x: auto; font-family: Consolas, Monaco, 'Courier New', monospace; white-space: pre; } |
| 919 | +.formula-help .fh-section { font-weight: 600; margin: 12px 0 4px; color: #303133; } |
| 920 | +.formula-help .fh-section:first-child { margin-top: 0; } |
| 921 | +.formula-help .fh-note { color: #909399; font-size: 12px; } |
877 | 922 | .toolbar{display:flex;justify-content:space-between;align-items:center;padding:6px 12px;background:#001529;color:#fff;flex-shrink:0} |
878 | 923 | .designer-body{flex:1;display:flex;overflow:hidden} |
879 | 924 | .left-panel{width:220px;border-right:1px solid #ddd;padding:6px;overflow-y:auto;background:#fff;flex-shrink:0} |
|
0 commit comments