vue-quokit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -0
- package/dist/index.cjs +14 -0
- package/dist/index.js +2538 -0
- package/dist/style.css +1 -0
- package/package.json +35 -0
- package/src/components/vue-quokit/index.d.ts +193 -0
package/README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# vue-quokit
|
|
2
|
+
|
|
3
|
+
一个基于 **Vue 3** 的可视化报价单生成组件库。一份 JSON 模板驱动整个流程:设计模板 → 填写数据 → 预览 / 导出 Excel / 打印。
|
|
4
|
+
|
|
5
|
+
## ✨ 特性
|
|
6
|
+
|
|
7
|
+
- 🎨 **可视化模板设计器** — 表头列、页面头/尾、汇总区,所见即所得
|
|
8
|
+
- 📐 **6 种列类型** — 文本、数字、下拉、多行、自动序号、自动计算
|
|
9
|
+
- 🔢 **公式引擎** — 自动计算列可引用同行字段,汇总项支持 `group_total`、`quantity_sum` 等内置变量
|
|
10
|
+
- 🧩 **模块化架构** — 整个用或单独用某个模块都行(如只用列设计器)
|
|
11
|
+
- 📄 **ExcelJS 导出** — 一键导出 `.xlsx`,撑长模式自动加高行高
|
|
12
|
+
- 🖨️ **打印** — 原生 window.print,支持横版 / 竖版
|
|
13
|
+
- 💪 **TypeScript 友好** — 内置 `.d.ts` 类型声明,props / expose / composable 全有类型
|
|
14
|
+
|
|
15
|
+
## 🖼️ 效果预览
|
|
16
|
+
|
|
17
|
+
<table>
|
|
18
|
+
<tr>
|
|
19
|
+
<td align="center"><b>① 表头列设计</b></td>
|
|
20
|
+
<td align="center"><b>② 页面头部</b></td>
|
|
21
|
+
</tr>
|
|
22
|
+
<tr>
|
|
23
|
+
<td><img src="docs/1.png" alt="表头列" /></td>
|
|
24
|
+
<td><img src="docs/2.png" alt="页面头部" /></td>
|
|
25
|
+
</tr>
|
|
26
|
+
<tr>
|
|
27
|
+
<td align="center"><b>③ 汇总区域</b></td>
|
|
28
|
+
<td align="center"><b>④ 页面底部</b></td>
|
|
29
|
+
</tr>
|
|
30
|
+
<tr>
|
|
31
|
+
<td><img src="docs/3.png" alt="汇总区域" /></td>
|
|
32
|
+
<td><img src="docs/4.png" alt="页面底部" /></td>
|
|
33
|
+
</tr>
|
|
34
|
+
<tr>
|
|
35
|
+
<td colspan="2" align="center"><b>⑤ 总体预览 / 导出 / 打印</b></td>
|
|
36
|
+
</tr>
|
|
37
|
+
<tr>
|
|
38
|
+
<td colspan="2"><img src="docs/5.png" alt="总体预览" /></td>
|
|
39
|
+
</tr>
|
|
40
|
+
</table>
|
|
41
|
+
|
|
42
|
+
## 📦 安装
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm add vue-quokit
|
|
46
|
+
# 或
|
|
47
|
+
npm install vue-quokit
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
依赖要求:`vue ^3.4`、`exceljs ^4`
|
|
51
|
+
|
|
52
|
+
## 🚀 快速开始
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<template>
|
|
56
|
+
<QuokitTemplate v-model:tpl="tpl" />
|
|
57
|
+
<QuokitData :tpl="tpl" v-model:data="rows" />
|
|
58
|
+
<QuokitSheet ref="sheetRef" :tpl="tpl" :data="rows" />
|
|
59
|
+
<button @click="sheetRef?.exportExcel()">导出 Excel</button>
|
|
60
|
+
<button @click="sheetRef?.print()">打印</button>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<script setup>
|
|
64
|
+
import { ref } from 'vue';
|
|
65
|
+
import { QuokitTemplate, QuokitData, QuokitSheet } from 'vue-quokit';
|
|
66
|
+
|
|
67
|
+
const tpl = ref({
|
|
68
|
+
columns: [
|
|
69
|
+
{ field: 'seq', title: '#', editor: 'AUTO_SEQ', width: 50 },
|
|
70
|
+
{ field: 'name', title: '名称', editor: 'INPUT', width: 200 },
|
|
71
|
+
{ field: 'qty', title: '数量', editor: 'NUMBER', width: 80 },
|
|
72
|
+
{ field: 'price', title: '单价', editor: 'NUMBER', width: 100 },
|
|
73
|
+
{ field: 'subtotal', title: '小计', editor: 'AUTO_CALC', formula: 'qty * price', width: 120 }
|
|
74
|
+
],
|
|
75
|
+
group_rules: null,
|
|
76
|
+
header_sections: [],
|
|
77
|
+
footer_sections: [],
|
|
78
|
+
summary_fields: []
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const rows = ref([]);
|
|
82
|
+
const sheetRef = ref(null);
|
|
83
|
+
</script>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 🧩 单独使用某个模块
|
|
87
|
+
|
|
88
|
+
不想用整个 `QuokitTemplate`?可以只拿列设计器 / 头设计器 / 汇总设计器:
|
|
89
|
+
|
|
90
|
+
```vue
|
|
91
|
+
<template>
|
|
92
|
+
<DesignCols :columns="colsState.columns" :group-rules="colsState.groupRules" />
|
|
93
|
+
</template>
|
|
94
|
+
|
|
95
|
+
<script setup>
|
|
96
|
+
import { useColumns } from 'vue-quokit';
|
|
97
|
+
import DesignCols from 'vue-quokit/modules/columns/DesignCols.vue';
|
|
98
|
+
|
|
99
|
+
const colsState = useColumns([
|
|
100
|
+
{ field: 'name', title: '名称', editor: 'INPUT', width: 200 },
|
|
101
|
+
{ field: 'qty', title: '数量', editor: 'NUMBER', width: 80 }
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
// colsState.columns ← 当前列(reactive,自动解包)
|
|
105
|
+
// colsState.groupRules ← 分组配置
|
|
106
|
+
// colsState.tpl ← 可直接塞进模板 JSON 的 computed
|
|
107
|
+
// colsState.setColumns() ← 重新加载一批列
|
|
108
|
+
</script>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
三个 composable 分别是 `useColumns`、`useSections`、`useSummary`,对应 columns、header/footer、summary 三个域。
|
|
112
|
+
|
|
113
|
+
## 📚 API 参考
|
|
114
|
+
|
|
115
|
+
### `<QuokitTemplate>`
|
|
116
|
+
|
|
117
|
+
模板设计器(整体容器,5 个 tab)。
|
|
118
|
+
|
|
119
|
+
| prop | 类型 | 默认 | 说明 |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| `tpl` | `QuokitTemplateData` | `{ columns: [], group_rules: null, header_sections: [], footer_sections: [], summary_fields: [] }` | 完整模板对象 |
|
|
122
|
+
| `breakpoint` | `number` | `1100` | 窄布局切换阈值(窗口宽度 ≤ 此值时切换窄布局) |
|
|
123
|
+
|
|
124
|
+
**Events:** `update:tpl` — 模板变更时 debounce 200ms 触发
|
|
125
|
+
|
|
126
|
+
**Expose(ref 调用):**
|
|
127
|
+
|
|
128
|
+
| 方法 | 返回值 | 说明 |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `getTemplateJSON()` | `QuokitTemplateData` | 取当前完整模板 JSON |
|
|
131
|
+
| `showHelp()` | `void` | 弹出帮助对话框 |
|
|
132
|
+
|
|
133
|
+
### `<QuokitData>`
|
|
134
|
+
|
|
135
|
+
数据填写器,按模板生成表单。
|
|
136
|
+
|
|
137
|
+
| prop | 类型 | 默认 | 说明 |
|
|
138
|
+
|---|---|---|---|
|
|
139
|
+
| `tpl` | `QuokitTemplateData` | — | **必填**,模板对象 |
|
|
140
|
+
| `data` | `Record<string, any>[]` | `[]` | 明细行数组 |
|
|
141
|
+
|
|
142
|
+
**Events:** `update:data`
|
|
143
|
+
|
|
144
|
+
### `<QuokitSheet>`
|
|
145
|
+
|
|
146
|
+
纯渲染 + 导出 + 打印。
|
|
147
|
+
|
|
148
|
+
| prop | 类型 | 默认 | 说明 |
|
|
149
|
+
|---|---|---|---|
|
|
150
|
+
| `tpl` | `QuokitTemplateData` | — | **必填**,模板对象 |
|
|
151
|
+
| `data` | `Record<string, any>[]` | `[]` | 明细行数组 |
|
|
152
|
+
| `placeholder` | `string` | `'-'` | 空值占位符 |
|
|
153
|
+
|
|
154
|
+
**Expose:**
|
|
155
|
+
|
|
156
|
+
| 方法 | 说明 |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `exportExcel(expandRowHeight?)` | 导出 `.xlsx`,可选撑长模式 |
|
|
159
|
+
| `print(vertical?)` | 打印,可选竖版 |
|
|
160
|
+
|
|
161
|
+
### Composables
|
|
162
|
+
|
|
163
|
+
#### `useColumns(initialColumns?, initialGroupRules?)`
|
|
164
|
+
|
|
165
|
+
| 返回 | 类型 | 说明 |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `columns` | `Ref<ColumnDef[]>` | 当前列(已 normalize) |
|
|
168
|
+
| `groupRules` | `Ref<{ merge_field, show_detail_subtotal }>` | 分组配置 |
|
|
169
|
+
| `tpl` | `ComputedRef<{ columns, group_rules }>` | 输出到模板的转换格式 |
|
|
170
|
+
| `setColumns(raw)` | 方法 | 重新加载列 |
|
|
171
|
+
| `setGroupRules(raw)` | 方法 | 重新加载分组配置 |
|
|
172
|
+
|
|
173
|
+
#### `useSections(initialSections?, options?)`
|
|
174
|
+
|
|
175
|
+
| 参数 | 说明 |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `isHeader` | `true` 时空数组自动填充默认"报价单大标题";`false` 时空就是空 |
|
|
178
|
+
|
|
179
|
+
#### `useSummary(initialFields?)`
|
|
180
|
+
|
|
181
|
+
返回 `{ fields, tpl, setFields, toTpl }`
|
|
182
|
+
|
|
183
|
+
### 工具函数
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
import { generateMockRows } from 'vue-quokit';
|
|
187
|
+
generateMockRows([...columns], 5); // 生成 5 行模拟数据
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## 🗂️ 目录结构
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
src/components/vue-quokit/
|
|
194
|
+
├── index.js ← 入口(统一导出)
|
|
195
|
+
├── index.d.ts ← TypeScript 类型声明
|
|
196
|
+
├── QuokitTemplate.vue ← 整体容器(5 个 tab)
|
|
197
|
+
├── QuokitData.vue ← 数据填写器
|
|
198
|
+
│
|
|
199
|
+
├── modules/
|
|
200
|
+
│ ├── columns/ ← 表头列域
|
|
201
|
+
│ │ ├── DesignCols.vue
|
|
202
|
+
│ │ ├── GroupDialog.vue
|
|
203
|
+
│ │ ├── useColumns.js
|
|
204
|
+
│ │ └── schema.js
|
|
205
|
+
│ ├── sections/ ← 页面头/尾域
|
|
206
|
+
│ │ ├── DesignHeader.vue
|
|
207
|
+
│ │ ├── DesignFooter.vue
|
|
208
|
+
│ │ ├── useSections.js
|
|
209
|
+
│ │ └── schema.js
|
|
210
|
+
│ ├── summary/ ← 汇总区域
|
|
211
|
+
│ │ ├── DesignSummary.vue
|
|
212
|
+
│ │ ├── useSummary.js
|
|
213
|
+
│ │ └── schema.js
|
|
214
|
+
│ └── preview/ ← 渲染域
|
|
215
|
+
│ ├── QuokitSheet.vue
|
|
216
|
+
│ └── mockData.js
|
|
217
|
+
│
|
|
218
|
+
├── shared/ ← 跨域共享
|
|
219
|
+
│ ├── utils.js ← deepClone / debounce
|
|
220
|
+
│ ├── sectionHelpers.js ← section 默认值 / border 工具
|
|
221
|
+
│ └── HelpModal.vue
|
|
222
|
+
│
|
|
223
|
+
└── internal/ ← 内部函数
|
|
224
|
+
├── evalFormula.js ← 公式解析器
|
|
225
|
+
├── exportExcel.js ← Excel 导出
|
|
226
|
+
└── useResponsiveBreakpoint.js
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## 📐 模板数据结构
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
interface QuokitTemplateData {
|
|
233
|
+
columns: ColumnDef[];
|
|
234
|
+
group_rules?: GroupRules | null;
|
|
235
|
+
header_sections?: SectionRow[];
|
|
236
|
+
footer_sections?: SectionRow[];
|
|
237
|
+
summary_fields?: SummaryField[];
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### columns(6 种 editor)
|
|
242
|
+
|
|
243
|
+
| editor | 说明 | 专属字段 |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `AUTO_SEQ` | 自动序号 | — |
|
|
246
|
+
| `AUTO_CALC` | 自动计算 | `formula` — 引用同行其他 field,如 `qty * price * 0.9` |
|
|
247
|
+
| `INPUT` | 文本输入 | — |
|
|
248
|
+
| `NUMBER` | 数字输入 | — |
|
|
249
|
+
| `TEXTAREA` | 多行文本 | — |
|
|
250
|
+
| `SELECT` | 下拉选择 | `dict: string[]` — 选项数组 |
|
|
251
|
+
|
|
252
|
+
### summary_fields 可用变量
|
|
253
|
+
|
|
254
|
+
| 变量 | 含义 |
|
|
255
|
+
|---|---|
|
|
256
|
+
| `group_total` | 所有行 AUTO_CALC 列求和 |
|
|
257
|
+
| `quantity_sum` | 所有行 `quantity` 字段求和(字段名自适应) |
|
|
258
|
+
| 手动项的 `field` | 互相引用,如 `service_fee`、`labor_cost` |
|
|
259
|
+
|
|
260
|
+
## 🛠️ Demo
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
pnpm install
|
|
264
|
+
pnpm run dev # 开发服务器
|
|
265
|
+
pnpm run build # 生产构建
|
|
266
|
+
pnpm run preview # 预览
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## 📄 License
|
|
270
|
+
|
|
271
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),ce=require("exceljs");function P(d,o){if(!d)return 0;const a=String(d).replace(/\s+/g,"");if(!a)return 0;let u=0;function f(){return a[u]}function m(){return a[u++]}function b(t){if(f()!==t)throw new Error("公式解析错误: 期望 "+t+" at "+u);u++}function g(){const t=f();if(t==="("){m();const n=s();return b(")"),n}if(t==="-")return m(),-g();if(t==="+")return m(),g();if(t>="0"&&t<="9"||t==="."){let n="";for(;u<a.length&&(a[u]>="0"&&a[u]<="9"||a[u]===".");)n+=a[u++];return parseFloat(n)}if(t>="a"&&t<="z"||t>="A"&&t<="Z"||t==="_"){let n="";for(;u<a.length&&(a[u]>="a"&&a[u]<="z"||a[u]>="A"&&a[u]<="Z"||a[u]==="_"||a[u]>="0"&&a[u]<="9");)n+=a[u++];return Number(o[n]||0)}throw new Error('公式解析错误: 非法字符 "'+t+'" at '+u)}function w(){let t=g();for(;u<a.length&&(f()==="*"||f()==="/");){const n=m(),p=g();t=n==="*"?t*p:p===0?0:t/p}return t}function s(){let t=w();for(;u<a.length&&(f()==="+"||f()==="-");){const n=m(),p=w();t=n==="+"?t+p:t-p}return t}try{const t=s();return Math.round(t*100)/100}catch{return 0}}function L(d){let o="";for(;d>=0;)o=String.fromCharCode(65+d%26)+o,d=Math.floor(d/26)-1;return o}function J(d){return typeof d=="string"?parseFloat(d)/100:0}const j={style:"thin",color:{argb:"FFDCDFE6"}},ue={top:j,left:j,right:j,bottom:j},Q={style:"medium",color:{argb:"FF606266"}},me=11;function oe(d){if(d==null)return 0;if(typeof d=="number")return String(d).length;const o=String(d);let a=0;for(const u of o)u!==`
|
|
2
|
+
`&&(/[\u4e00-\u9fa5\u3000-\u303f\uff00-\uffef\u2e80-\u2fdf\u31c0-\u31ef]/.test(u)?a+=2:a+=1);return a}function Y(d,o=11){let a=1;for(const u of d){const f=String(u??""),m=f.split(`
|
|
3
|
+
`).length,b=oe(f),w=f.length===0?1:Math.ceil(b/12);a=Math.max(a,m,w)}return Math.max(28,a*(o+4)+6)}function K(d,o,a,u,f){for(let m=o;m<=a;m++)for(let b=u;b<=f;b++){const g=d.getCell(m,b);g.border=ue}}function ee(d,o,a,u,f){for(let m=u;m<=f;m++)d.getCell(o,m).border={...d.getCell(o,m).border||{},top:Q},d.getCell(a,m).border={...d.getCell(a,m).border||{},bottom:Q};for(let m=o;m<=a;m++)d.getCell(m,u).border={...d.getCell(m,u).border||{},left:Q},d.getCell(m,f).border={...d.getCell(m,f).border||{},right:Q}}async function pe(d,o,a={}){var h;const u=a.layout||"auto-wrap",f=u==="auto-wrap",m=new ce.Workbook,b=m.addWorksheet("报价单"),g=d.columns.length,w=L(g-1);let s=1;const t=()=>(d.columns||[]).find(c=>c.editor==="AUTO_CALC"),n=c=>{const r=t(),v=(r==null?void 0:r.formula)||"quantity * unit_price";return P(v,c)};if(d.header_sections){for(const c of d.header_sections)if(c.type==="title"){b.mergeCells(`A${s}:${w}${s}`);const r=b.getCell(`A${s}`);r.value=c.text;const v=c.style||{},V=v.fontSize||18;if(r.font={size:V,bold:v.bold!==!1,italic:v.italic===!0,name:"微软雅黑"},v.color){const y=v.color.replace("#","").toUpperCase();r.font.color={argb:y.length===6?"FF"+y:y}}r.alignment={horizontal:v.align||"center",vertical:"middle"},b.getRow(s).height=V*2+10,s++}else if(c.type==="divider")s++;else if(c.type==="text"){b.mergeCells(`A${s}:${w}${s}`);const r=b.getCell(`A${s}`);r.value=c.text;const v=c.style||{},V=v.fontSize||13;if(r.font={size:V,bold:v.bold===!0,italic:v.italic===!0,name:"微软雅黑"},v.color){const y=v.color.replace("#","").toUpperCase();r.font.color={argb:y.length===6?"FF"+y:y}}r.alignment={horizontal:v.align||c.align||"left",vertical:"middle"},b.getRow(s).height=V*2+10,s++}else if(c.type==="row"&&c.cells){const r=c.cells.map(y=>{var E;return J((E=y.style)==null?void 0:E.width)||1/c.cells.length});let v=0;const V=r.map(y=>{const E=Math.round(v*g);v+=y;const x=Math.round(v*g)-1;return{start:E,end:Math.max(x,E)}});for(let y=0;y<c.cells.length;y++){const E=c.cells[y],x=V[y],U=`${L(x.start)}${s}`,T=`${L(x.end)}${s}`;U!==T&&b.mergeCells(`${U}:${T}`);const C=b.getCell(U);C.value=E.type==="field"?`${E.label}:${E.value??""}`:E.text;const N=E.style||{},D=N.fontSize||11;if(C.font={size:D,bold:N.bold===!0,italic:N.italic===!0,name:"微软雅黑"},N.color){const A=N.color.replace("#","").toUpperCase();C.font.color={argb:A.length===6?"FF"+A:A}}C.alignment={horizontal:N.align||"left",vertical:"middle"}}b.getRow(s).height=22,s++}}const p=s,l=b.getRow(s);l.values=d.columns.map(c=>c.title),l.font={bold:!0,name:"微软雅黑",size:12},l.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFE0E0E0"}},l.alignment={horizontal:"center",vertical:"middle",wrapText:f},l.height=f?32:28,s++;const $=d.group_rules,i=$==null?void 0:$.merge_field,S=d.columns;if(i){let c=0,r=0;for(;c<o.length;){const v=[];let V=c;for(;V<o.length&&o[V][i]===o[c][i];)v.push(o[V]),V++;const y=s;for(let U=0;U<v.length;U++){r++;const T=v[U],C=S.map(D=>D.editor==="AUTO_SEQ"?r:D.editor==="AUTO_CALC"?n(T):T[D.field]??""),N=b.getRow(s);N.values=C,N.font={name:"微软雅黑",size:11},N.alignment={horizontal:"center",vertical:"middle",wrapText:f,indent:1},N.height=f?Y(C,11):28,s++}const E=s-1;for(let U=0;U<S.length;U++){const T=S[U];if(T.merge_on_group!==!0)continue;let C=y;for(let N=1;N<v.length;N++)v[N][T.field]!==v[N-1][T.field]&&(y+N-1>C&&b.mergeCells(`${L(U)}${C}:${L(U)}${y+N-1}`),C=y+N);E>C&&b.mergeCells(`${L(U)}${C}:${L(U)}${E}`)}if($.show_detail_subtotal!==!1&&o[c][i]!==void 0&&o[c][i]!==null&&o[c][i]!==""){const U=v.reduce((A,F)=>A+Number(n(F)||0),0),T=L(Math.max(0,g-2));b.mergeCells(`A${s}:${T}${s}`);const C=b.getCell(`A${s}`);C.value=`小计(${o[c][i]})`,C.alignment={horizontal:"right",vertical:"middle"},C.font={bold:!0,italic:!0,color:{argb:"FF409EFF"},name:"微软雅黑",size:11};const N=b.getCell(`${w}${s}`);N.value=U,N.numFmt="#,##0.00",N.alignment={horizontal:"right",vertical:"middle"},N.font={bold:!0,italic:!0,color:{argb:"FF409EFF"},name:"微软雅黑",size:11};const D=b.getRow(s);D.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FFF0F9FF"}},D.alignment={horizontal:"right",vertical:"middle",wrapText:!0},D.height=26,s++}c=V}}else for(let c=0;c<o.length;c++){const r=o[c],v=S.map(y=>y.editor==="AUTO_SEQ"?c+1:y.editor==="AUTO_CALC"?n(r):r[y.field]??""),V=b.getRow(s);V.values=v,V.font={name:"微软雅黑",size:11},V.alignment={horizontal:"center",vertical:"middle",wrapText:f,indent:1},V.height=f?Y(v,11):28,s++}const k=s-1;if(d.summary_fields){s+=1;const c=L(Math.max(0,g-2)),r=L(g-1),v=o.reduce((E,x)=>E+Number(n(x)||0),0),V={group_total:v,quantity_sum:o.reduce((E,x)=>E+Number(x.quantity||0),0)};for(const E of d.summary_fields)E.type==="MANUAL_INPUT"&&(V[E.field]=Number(E.default??0));V.grand_total=v+d.summary_fields.filter(E=>E.type==="MANUAL_INPUT").reduce((E,x)=>E+V[x.field],0);for(const E of d.summary_fields)E.type==="AUTO_CALC"&&(V[E.field]=P(E.formula||"group_total",V));for(const E of d.summary_fields){let x;E.type==="AUTO_CALC"?x=P(E.formula||"group_total",V):E.type==="PLAIN_TEXT"?x=E.text||"":x=Number(E.default??0);const U=((h=E.style)==null?void 0:h.fontSize)||me,T=b.getCell(`${c}${s}`),C=b.getCell(`${r}${s}`);T.value=E.label,T.alignment={horizontal:"right",vertical:"middle"};const N=E.style||{},D=()=>{const A={name:"微软雅黑",size:U,bold:!!N.bold,italic:!!N.italic};if(N.color){const F=N.color.replace("#","").toUpperCase();A.color={argb:F.length===6?"FF"+F:F}}return A};T.font=D(),C.value=x,C.alignment={horizontal:"right",vertical:"middle"},C.font=D(),typeof x=="number"&&(C.numFmt="#,##0.00"),b.getRow(s).height=Math.max(22,U*2+6),s++}const y=s-1;K(b,p,y,1,g),ee(b,p,y,1,g)}else K(b,p,k,1,g),ee(b,p,k,1,g);if(d.footer_sections){s+=1;for(const c of d.footer_sections)if(c.type==="divider")s++;else if(c.type==="text"){b.mergeCells(`A${s}:${w}${s}`);const r=b.getCell(`A${s}`);r.value=c.text;const v=c.style||{},V=v.fontSize||13;if(r.font={size:V,bold:v.bold===!0,italic:v.italic===!0,name:"微软雅黑"},v.color){const y=v.color.replace("#","").toUpperCase();r.font.color={argb:y.length===6?"FF"+y:y}}r.alignment={horizontal:v.align||c.align||"left",vertical:"middle"},b.getRow(s).height=V*2+10,s++}else if(c.type==="row"&&c.cells){const r=c.cells.map(y=>{var E;return J((E=y.style)==null?void 0:E.width)||1/c.cells.length});let v=0;const V=r.map(y=>{const E=Math.round(v*g);v+=y;const x=Math.round(v*g)-1;return{start:E,end:Math.max(x,E)}});for(let y=0;y<c.cells.length;y++){const E=c.cells[y],x=V[y],U=`${L(x.start)}${s}`,T=`${L(x.end)}${s}`;U!==T&&b.mergeCells(`${U}:${T}`);const C=b.getCell(U);C.value=E.text;const N=E.style||{};C.alignment={horizontal:N.align||"left",vertical:"middle"};const D={name:"微软雅黑",size:N.fontSize||11,bold:N.bold===!0,italic:N.italic===!0};if(N.color){const A=N.color.replace("#","").toUpperCase();D.color={argb:A.length===6?"FF"+A:A}}C.font=D}b.getRow(s).height=22,s++}}const _=50,B=6;for(let c=0;c<g;c++){const r=d.columns[c],v=c+1;if(u==="auto-wrap")b.getColumn(v).width=r.width?Math.max(r.width/7,8):12;else{let V=0;for(let x=1;x<s;x++)V=Math.max(V,oe(b.getCell(x,v).value));const y=r.width?Math.max(r.width/7,10):12,E=Math.min(Math.max(V+2,B),_);b.getColumn(v).width=Math.max(E,y)}}const z=await m.xlsx.writeBuffer();return new Blob([z],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})}const O=(d,o)=>{const a=d.__vccOpts||d;for(const[u,f]of o)a[u]=f;return a},fe={class:"quote-sheet"},ve={key:1,class:"q-divider"},be={key:3,class:"q-row"},ye={class:"q-label"},Ve={class:"q-value"},he={key:0,class:"q-table-wrap"},Ee={class:"q-table"},_e={key:0,class:"subtotal-row"},ge=["colspan"],ke={class:"subtotal-value"},Ne={key:1},we=["rowspan"],$e={key:0,class:"empty-row"},xe=["colspan"],Ce={key:1,class:"q-summary"},Be={class:"q-summary-label"},Ue={key:0,class:"q-divider"},Se={key:2,class:"q-row"},Te={__name:"QuokitSheet",props:{tpl:{type:Object,required:!0},data:{type:Array,default:()=>[]},placeholder:{type:String,default:"-"}},setup(d,{expose:o}){function a(h){const c=(h.header_sections||[]).flatMap(r=>r.cells||[]).find(r=>r.type==="field"&&r.value);return(c==null?void 0:c.value)||"untitled"}const u=d,f=e.computed(()=>u.data);function m(h){const c=h.style||{},r={width:c.width||"auto"};r.textAlign=c.align||"left",c.color&&(r.color=c.color),c.fontSize&&(r.fontSize=c.fontSize+"px"),c.bold&&(r.fontWeight="bold"),c.italic&&(r.fontStyle="italic");const v=c.border;if(v)for(const V of["top","bottom","left","right"]){const y=v[V];y&&y.style&&y.width>0&&(r["border-"+V]=`${y.width}px ${y.style} ${y.color||"#dcdfe6"}`)}return r}function b(h){return"¥ "+(Number(h)||0).toFixed(2)}const g=e.computed(()=>(u.tpl.columns||[]).find(h=>h.editor==="AUTO_CALC"));function w(h){var r;const c=((r=g.value)==null?void 0:r.formula)||"quantity * unit_price";return P(c,h)}const s=e.computed(()=>f.value.reduce((h,c)=>h+Number(w(c)||0),0)),t=e.computed(()=>f.value.reduce((h,c)=>h+Number(c.quantity||0),0));function n(){let h=s.value;if(u.tpl.summary_fields)for(const c of u.tpl.summary_fields)c.type==="MANUAL_INPUT"&&(h+=$(c));return h}function p(h){const c={},r=h.style||{};return r.color&&(c.color=r.color),r.fontSize&&(c.fontSize=r.fontSize+"px"),r.bold&&(c.fontWeight="bold"),r.italic&&(c.fontStyle="italic"),c}function l(h){const c={},r=h.style||{};return r.color&&(c.color=r.color),r.fontSize&&(c.fontSize=r.fontSize+"px"),r.bold&&(c.fontWeight="bold"),r.italic&&(c.fontStyle="italic"),r.align?c.textAlign=r.align:h.align&&(c.textAlign=h.align),c}function $(h){return Number(h.default??0)}function i(){const h={group_total:s.value,quantity_sum:t.value};if(u.tpl.summary_fields){for(const c of u.tpl.summary_fields)c.type==="MANUAL_INPUT"&&(h[c.field]=$(c));for(const c of u.tpl.summary_fields)c.type==="AUTO_CALC"&&(h[c.field]=P(c.formula||"group_total",h))}return h.grand_total=n(),h}function S(h){if(h.type==="PLAIN_TEXT")return h.text||"";if(h.type==="AUTO_CALC"){const c=i();return c[h.field]??P(h.formula||"group_total",c)}return $(h)}const k=e.computed(()=>{var y;const h=f.value.map(E=>({...E})),c=(y=u.tpl)==null?void 0:y.group_rules;if(!(c!=null&&c.merge_field))return h;const r=[],v=c.merge_field;let V=0;for(;V<h.length;){const E=[h[V]];let x=V+1;for(;x<h.length&&h[x][v]===h[V][v];)E.push(h[x]),x++;if(r.push(...E),(c.show_detail_subtotal??!0)&&h[V][v]!==void 0&&h[V][v]!==null&&h[V][v]!==""){const T=E.reduce((C,N)=>C+Number(w(N)||0),0);r.push({__is_subtotal:!0,__group_key:h[V][v],__group_sum:T})}V=x}return r});function _(h,c){var C,N,D,A;const r=k.value,v=r[h];if(!v||v.__is_subtotal)return 1;const V=(C=u.tpl)==null?void 0:C.group_rules,y=V==null?void 0:V.merge_field,E=u.tpl.columns.find(F=>F.field===c),x=y&&c===y,U=(E==null?void 0:E.merge_on_group)===!0;if(!x&&!U)return 1;const T=(()=>{var M,X;if(!y)return r.length;const F=v[y];let R=h+1;for(;R<r.length&&((M=r[R])==null?void 0:M[y])===F&&!((X=r[R])!=null&&X.__is_subtotal);)R++;return R})();if(x)return h>0&&((N=r[h-1])==null?void 0:N[y])===v[y]&&!((D=r[h-1])!=null&&D.__is_subtotal)?0:T-h;if(U){const F=v[c];if(h>0){const M=r[h-1];if((!y||(M==null?void 0:M[y])===v[y]&&!(M!=null&&M.__is_subtotal))&&(M==null?void 0:M[c])===F)return 0}let R=1;for(let M=h+1;M<T&&((A=r[M])==null?void 0:A[c])===F;M++)R++;return R}return 1}async function B(h=!1){const c=await pe(u.tpl,u.data,h?{layout:"auto-width"}:void 0),r=URL.createObjectURL(c),v=document.createElement("a");v.href=r,v.download=`报价单_${a(u.tpl)}_${new Date().toISOString().slice(0,10)}.xlsx`,v.click(),URL.revokeObjectURL(r)}function z(h=!1){const c=document.querySelector(".quote-sheet");if(!c)return;const r=h!==!0,v=window.open("","_blank",r?"width=1200,height=900":"width=900,height=1200");if(!v)return;const V=Array.from(document.styleSheets).map(E=>{try{return Array.from(E.cssRules).map(x=>x.cssText).join(`
|
|
4
|
+
`)}catch{return""}}).join(`
|
|
5
|
+
`),y=c.outerHTML;v.document.write(`<!doctype html>
|
|
6
|
+
<html><head><meta charset="utf-8"><title>报价单打印</title>
|
|
7
|
+
<style>${V}
|
|
8
|
+
@page { size: ${r?"landscape":"portrait"}; margin: 15mm; }
|
|
9
|
+
body { margin: 0; padding: 20px; background: #fff; }
|
|
10
|
+
@media print { body { padding: 0; } }
|
|
11
|
+
</style></head><body>${y}</body></html>`),v.document.close(),v.onload=()=>{v.print()}}return o({print:z,exportExcel:B}),(h,c)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("div",fe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.tpl.header_sections,(r,v)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:"h"+v},[r.type==="title"?(e.openBlock(),e.createElementBlock("h1",{key:0,class:"q-title",style:e.normalizeStyle(l(r))},e.toDisplayString(r.text),5)):r.type==="divider"?(e.openBlock(),e.createElementBlock("div",ve)):r.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:2,class:"q-text",style:e.normalizeStyle(l(r))},e.toDisplayString(r.text),5)):r.type==="row"?(e.openBlock(),e.createElementBlock("div",be,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.cells,(V,y)=>(e.openBlock(),e.createElementBlock("div",{key:y,class:"q-cell",style:e.normalizeStyle(m(V))},[V.type==="field"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("span",ye,e.toDisplayString(V.label)+":",1),e.createElementVNode("span",Ve,e.toDisplayString(V.value??d.placeholder),1)],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(e.toDisplayString(V.text),1)],64))],4))),128))])):e.createCommentVNode("",!0)],64))),128)),d.tpl.columns&&d.tpl.columns.length>0?(e.openBlock(),e.createElementBlock("div",he,[e.createElementVNode("table",Ee,[e.createElementVNode("thead",null,[e.createElementVNode("tr",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.tpl.columns,r=>(e.openBlock(),e.createElementBlock("th",{key:r.field,style:e.normalizeStyle({width:r.width+"px"})},e.toDisplayString(r.title),5))),128))])]),e.createElementVNode("tbody",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(k.value,(r,v)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:v},[r.__is_subtotal?(e.openBlock(),e.createElementBlock("tr",_e,[e.createElementVNode("td",{colspan:d.tpl.columns.length-1,class:"subtotal-label"},"小计("+e.toDisplayString(r.__group_key)+")",9,ge),e.createElementVNode("td",ke,e.toDisplayString(b(r.__group_sum)),1)])):(e.openBlock(),e.createElementBlock("tr",Ne,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.tpl.columns,(V,y)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:V.field},[_(k.value.indexOf(r),V.field)>0?(e.openBlock(),e.createElementBlock("td",{key:0,rowspan:_(k.value.indexOf(r),V.field),class:e.normalizeClass({"merged-cell":_(k.value.indexOf(r),V.field)>1})},[V.editor==="AUTO_SEQ"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(v+1),1)],64)):V.editor==="AUTO_CALC"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(e.toDisplayString(b(w(r))),1)],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:2},[e.createTextVNode(e.toDisplayString(r[V.field]??""),1)],64))],10,we)):e.createCommentVNode("",!0)],64))),128))]))],64))),128)),k.value.length===0?(e.openBlock(),e.createElementBlock("tr",$e,[e.createElementVNode("td",{colspan:d.tpl.columns.length,class:"q-empty"},"(暂无数据)",8,xe)])):e.createCommentVNode("",!0)])])])):e.createCommentVNode("",!0),d.tpl.summary_fields&&d.tpl.summary_fields.length>0?(e.openBlock(),e.createElementBlock("div",Ce,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.tpl.summary_fields,r=>(e.openBlock(),e.createElementBlock("div",{key:r.field,class:"q-summary-row"},[e.createElementVNode("span",Be,e.toDisplayString(r.label),1),e.createElementVNode("span",{class:"q-summary-value",style:e.normalizeStyle(p(r))},e.toDisplayString(r.type==="PLAIN_TEXT"?r.text:b(S(r))),5)]))),128))])):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.tpl.footer_sections,(r,v)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:"f"+v},[r.type==="divider"?(e.openBlock(),e.createElementBlock("div",Ue)):r.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:1,class:"q-text",style:e.normalizeStyle(l(r))},e.toDisplayString(r.text),5)):r.type==="row"?(e.openBlock(),e.createElementBlock("div",Se,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.cells,(V,y)=>(e.openBlock(),e.createElementBlock("div",{key:y,class:"q-cell",style:e.normalizeStyle(m(V))},e.toDisplayString(V.text),5))),128))])):e.createCommentVNode("",!0)],64))),128))])]))}},ne=O(Te,[["__scopeId","data-v-b623c085"]]);function q(d){return JSON.parse(JSON.stringify(d))}function De(d,o){let a=null;const u=function(...f){clearTimeout(a),a=setTimeout(()=>d.apply(this,f),o)};return u.cancel=()=>{clearTimeout(a),a=null},Object.defineProperty(u,"timer",{get(){return a},configurable:!0}),u}function te(d=[]){return Array.isArray(d)?d.map(o=>{const a=Array.isArray(o.dict)?o.dict:[];return{...o,field:o.field||"",title:o.title||"",editor:o.editor||"INPUT",width:o.width??130,dictStr:a.length?a.join(","):o.dictStr||"",formula:o.formula||"",merge_on_group:o.merge_on_group??!1}}):[]}function Me(d){return d.map(o=>{const a={field:o.field,title:o.title,editor:o.editor,width:o.width};return o.editor==="SELECT_DICT"&&(a.dict=(o.dictStr||"").split(",").map(u=>u.trim()).filter(Boolean)),o.editor==="AUTO_CALC"&&(a.formula=o.formula||""),o.editor!=="AUTO_SEQ"&&o.editor!=="AUTO_CALC"&&(a.merge_on_group=!!o.merge_on_group),a})}function Ae(d,o,a){const u={INPUT:"文本",NUMBER:"数值",SELECT_DICT:"选项",TEXTAREA:"说明",AUTO_CALC:"计算值",AUTO_SEQ:"序号"},f={INPUT:130,NUMBER:100,SELECT_DICT:130,TEXTAREA:200,AUTO_CALC:120,AUTO_SEQ:60};return{field:o,title:u[d]||a||"新列",editor:d,width:f[d]||120,dictStr:"",formula:"",merge_on_group:!1}}function ae(d=[],o={}){const a=e.ref(te(q(d))),u=e.ref({merge_field:o.merge_field||"",show_detail_subtotal:o.show_detail_subtotal??!0}),f=e.computed(()=>({columns:Me(a.value),group_rules:(()=>{const g=u.value.merge_field;return g?{merge_field:g,show_detail_subtotal:u.value.show_detail_subtotal??!0}:null})()}));function m(g){a.value=te(q(g||[]))}function b(g){u.value={merge_field:g.merge_field||"",show_detail_subtotal:g.show_detail_subtotal??!0}}return e.reactive({columns:a,groupRules:u,tpl:f,setColumns:m,setGroupRules:b})}function de(){return{top:{style:"",width:1,color:"#dcdfe6"},bottom:{style:"",width:1,color:"#dcdfe6"},left:{style:"",width:1,color:"#dcdfe6"},right:{style:"",width:1,color:"#dcdfe6"}}}function I(d="auto"){return{width:d,color:"#303133",fontSize:13,bold:!1,italic:!1,align:"left",border:de()}}function W(d,o){d.style||(d.style=I());const a=o==="none"?{style:"",width:0,color:"#dcdfe6"}:{style:"solid",width:1,color:"#dcdfe6"};d.style.border={top:{...a},bottom:{...a},left:{...a},right:{...a}}}function ie(d){const o=d.style||{},a={width:o.width||"auto"};a.textAlign=o.align||"left",o.color&&(a.color=o.color),o.fontSize&&(a.fontSize=o.fontSize+"px"),o.bold&&(a.fontWeight="bold"),o.italic&&(a.fontStyle="italic");const u=o.border;if(u)for(const f of["top","bottom","left","right"]){const m=u[f];m&&m.style&&m.width>0&&(a["border-"+f]=`${m.width}px ${m.style} ${m.color||"#dcdfe6"}`)}return a}function ze(d=[]){for(const o of d)o.type==="title"&&(o.type="text",o.style=o.style||{color:"#303133",fontSize:18,bold:!0,italic:!1,align:"center"},o.align&&!o.style.align&&(o.style.align=o.align,delete o.align)),o.type==="text"&&(o.style=o.style||{},o.align&&!o.style.align&&(o.style.align=o.align,delete o.align),o.style.color===void 0&&(o.style.color="#303133"),o.style.fontSize===void 0&&(o.style.fontSize=14),o.style.bold===void 0&&(o.style.bold=!1),o.style.italic===void 0&&(o.style.italic=!1),o.style.align===void 0&&(o.style.align="left"))}function Fe(d=[]){for(const o of d)if(o.type==="row"&&o.cells)for(const a of o.cells)a.style||(a.style=I()),a.style.width===void 0&&(a.style.width="auto"),a.style.color===void 0&&(a.style.color="#303133"),a.style.fontSize===void 0&&(a.style.fontSize=13),a.style.bold===void 0&&(a.style.bold=!1),a.style.italic===void 0&&(a.style.italic=!1),a.style.align===void 0&&(a.style.align="left"),a.style.border===void 0&&(a.style.border=de())}function Le(){return[{type:"text",text:"报 价 单",style:{color:"#303133",fontSize:22,bold:!0,italic:!1,align:"center"}},{type:"divider"},{type:"row",cells:[{type:"field",label:"项目名称",bind:"projectName",style:I("50%")},{type:"field",label:"日期",bind:"quotationDate",style:I("50%")}]}]}function le(d,o=!1){if(!d||d.length===0)if(o)d=Le();else return[];return ze(d),Fe(d),d}function Z(d=[],o={}){const{isHeader:a=!1}=o,u=e.ref(q(le(d,a)));function f(b){u.value=q(le(b||[],a))}function m(){return q(u.value)}return e.reactive({sections:u,setSections:f,toTpl:m})}function G(d=[]){let o=0;for(const a of d)if(a.field){const u=/^field_(\d+)$/.exec(a.field);u&&(o=Math.max(o,parseInt(u[1],10)))}for(const a of d)a.field||(a.field="field_"+String(++o).padStart(4,"0")),a.type==="AUTO_CALC"&&!a.formula&&(a.formula="group_total"),a.style===void 0&&(a.style={color:"#606266",fontSize:13,bold:!1,italic:!1}),a.style.color===void 0&&(a.style.color="#606266"),a.style.fontSize===void 0&&(a.style.fontSize=13),a.style.bold===void 0&&(a.style.bold=!1),a.style.italic===void 0&&(a.style.italic=!1)}function se(d=[]){const o=e.ref(q(d||[]));G(o.value);const a=e.computed(()=>q(o.value));function u(m){o.value=q(m||[]),G(o.value)}function f(){return G(o.value),q(o.value)}return e.reactive({fields:o,tpl:a,setFields:u,toTpl:f})}const qe=["XXXX","YYYY","ZZZZ","WWWW"];function re(d,o=3){const a=[],u=qe;for(let f=0;f<o;f++){const m={};for(const b of d)if(!(b.editor==="AUTO_SEQ"||b.editor==="AUTO_CALC"))if(b.editor==="NUMBER")m[b.field]=Math.floor(Math.random()*900+100);else if(b.editor==="SELECT_DICT"){const g=(b.dictStr||(b.dict?b.dict.join(","):"")).split(",").map(w=>w.trim()).filter(Boolean);m[b.field]=g[f%Math.max(g.length,1)]||u[f%u.length]}else m[b.field]=u[f%u.length];a.push(m)}return a}function H(d=1100){const o=e.ref(!1);function a(){o.value=window.innerWidth<=d}return e.onMounted(()=>{a(),window.addEventListener("resize",a)}),e.onUnmounted(()=>{window.removeEventListener("resize",a)}),{isNarrow:o}}const Oe={class:"toolbar"},Re={class:"btn-group-inline"},Ie={class:"design-table"},Pe={class:"idx"},je=["onUpdate:modelValue"],Qe=["onUpdate:modelValue"],We=["onUpdate:modelValue"],He=["onUpdate:modelValue"],Xe=["onUpdate:modelValue"],Ge=["onUpdate:modelValue"],Ze={key:2,class:"muted"},Je={key:3,class:"muted"},Ye={class:"col-merge"},Ke={key:0},et=["onUpdate:modelValue"],tt={key:1,class:"muted"},lt=["disabled","onClick"],ot=["disabled","onClick"],nt=["onClick"],at={__name:"DesignCols",props:{columns:{type:Array,required:!0},groupRules:{type:Object,default:()=>({})},breakpoint:{type:Number,default:1100}},emits:["help","open-group"],setup(d){const o=d,{isNarrow:a}=H(o.breakpoint),u=e.computed(()=>!!o.groupRules.merge_field);function f(s,t){let n=s,p=2;for(;t.has(n);)n=s+"_"+p++;return n}function m(){let s=0;for(const t of o.columns){const n=/^custom_(\d+)$/.exec(t.field);n&&(s=Math.max(s,parseInt(n[1],10)))}return s+1}function b(s){const t=new Set([...o.columns.map(l=>l.field)]),n="custom_"+String(m()).padStart(4,"0"),p=Ae(s,f(n,t));o.columns.push(p)}function g(s){o.columns.splice(s,1)}function w(s,t){const n=s+t;n<0||n>=o.columns.length||([o.columns[s],o.columns[n]]=[o.columns[n],o.columns[s]])}return(s,t)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("div",Oe,[t[3]||(t[3]=e.createElementVNode("span",{class:"tip"},[e.createTextVNode("拖动或点 ↑↓ 调整顺序;支持自动序号和公式计算列,公式里可直接引用其他字段名,如 "),e.createElementVNode("code",null,"quantity * unit_price * 0.9")],-1)),e.createElementVNode("div",Re,[e.createElementVNode("button",{class:e.normalizeClass(["btn",{"btn-primary":u.value}]),onClick:t[0]||(t[0]=n=>s.$emit("open-group"))},"分组 & 小计"+e.toDisplayString(u.value?" ✓":""),3),e.createElementVNode("button",{class:"btn btn-primary",onClick:t[1]||(t[1]=n=>b("INPUT"))},"+ 添加字段"),e.createElementVNode("button",{class:"btn",onClick:t[2]||(t[2]=n=>s.$emit("help"))},"帮助")])]),e.createElementVNode("div",{class:e.normalizeClass(["table-wrap",{"is-narrow":e.unref(a)}])},[e.createElementVNode("table",Ie,[t[6]||(t[6]=e.createElementVNode("thead",null,[e.createElementVNode("tr",null,[e.createElementVNode("th",{width:"50"},"#"),e.createElementVNode("th",{width:"150"},"字段名"),e.createElementVNode("th",{width:"150"},"列标题"),e.createElementVNode("th",{width:"160"},"类型"),e.createElementVNode("th",{width:"100"},"宽度"),e.createElementVNode("th",null,"专属配置"),e.createElementVNode("th",{width:"130"},"分组时合并"),e.createElementVNode("th",{width:"140"},"操作")])],-1)),e.createElementVNode("tbody",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.columns,(n,p)=>(e.openBlock(),e.createElementBlock("tr",{key:p},[e.createElementVNode("td",Pe,e.toDisplayString(p+1),1),e.createElementVNode("td",null,[e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":l=>n.field=l},null,8,je),[[e.vModelText,n.field]])]),e.createElementVNode("td",null,[e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":l=>n.title=l},null,8,Qe),[[e.vModelText,n.title]])]),e.createElementVNode("td",null,[e.withDirectives(e.createElementVNode("select",{class:"cell-input","onUpdate:modelValue":l=>n.editor=l},[...t[4]||(t[4]=[e.createStaticVNode('<option value="AUTO_SEQ" data-v-e3cbb539>自动序号</option><option value="AUTO_CALC" data-v-e3cbb539>自动计算(公式)</option><option value="INPUT" data-v-e3cbb539>文本输入</option><option value="NUMBER" data-v-e3cbb539>数字输入</option><option value="TEXTAREA" data-v-e3cbb539>多行文本</option><option value="SELECT_DICT" data-v-e3cbb539>下拉选择</option>',6)])],8,We),[[e.vModelSelect,n.editor]])]),e.createElementVNode("td",null,[e.withDirectives(e.createElementVNode("input",{class:"cell-input",type:"number",min:"50",max:"500","onUpdate:modelValue":l=>n.width=l},null,8,He),[[e.vModelText,n.width,void 0,{number:!0}]])]),e.createElementVNode("td",null,[n.editor==="SELECT_DICT"?e.withDirectives((e.openBlock(),e.createElementBlock("input",{key:0,class:"cell-input","onUpdate:modelValue":l=>n.dictStr=l,placeholder:"下拉选项,逗号分隔 如:设备,材料,安装"},null,8,Xe)),[[e.vModelText,n.dictStr]]):n.editor==="AUTO_CALC"?e.withDirectives((e.openBlock(),e.createElementBlock("input",{key:1,class:"cell-input","onUpdate:modelValue":l=>n.formula=l,placeholder:"公式,如 quantity * unit_price + tax"},null,8,Ge)),[[e.vModelText,n.formula]]):n.editor==="AUTO_SEQ"?(e.openBlock(),e.createElementBlock("span",Ze,"自动生成序号,无需配置")):(e.openBlock(),e.createElementBlock("span",Je,"-"))]),e.createElementVNode("td",Ye,[n.editor!=="AUTO_SEQ"&&n.editor!=="AUTO_CALC"?(e.openBlock(),e.createElementBlock("label",Ke,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":l=>n.merge_on_group=l},null,8,et),[[e.vModelCheckbox,n.merge_on_group]]),t[5]||(t[5]=e.createElementVNode("span",null,"相同值合并",-1))])):(e.openBlock(),e.createElementBlock("span",tt,"—"))]),e.createElementVNode("td",null,[e.createElementVNode("button",{class:"mini-btn",disabled:p===0,onClick:l=>w(p,-1)},"↑",8,lt),e.createElementVNode("button",{class:"mini-btn",disabled:p>=d.columns.length-1,onClick:l=>w(p,1)},"↓",8,ot),e.createElementVNode("button",{class:"mini-btn danger",onClick:l=>g(p)},"删",8,nt)])]))),128))])])],2)]))}},dt=O(at,[["__scopeId","data-v-e3cbb539"]]),it={class:"gr-dialog"},st={class:"gr-header"},rt={class:"gr-content"},ct={class:"gr-form"},ut={class:"gr-form-row"},mt=["value","disabled"],pt={class:"gr-form-row"},ft={class:"gr-checkbox",style:{flex:"1"}},vt={class:"gr-footer"},bt={__name:"GroupDialog",props:{visible:{type:Boolean,default:!1},columns:{type:Array,default:()=>[]},groupRules:{type:Object,required:!0}},setup(d){const o=d,a=e.reactive({merge_field:o.groupRules.merge_field||"",show_detail_subtotal:o.groupRules.show_detail_subtotal??!0});return e.watch(()=>o.groupRules,u=>{Object.assign(a,{merge_field:u.merge_field||"",show_detail_subtotal:u.show_detail_subtotal??!0})},{deep:!0}),e.watch(a,()=>{Object.assign(o.groupRules,{merge_field:a.merge_field,show_detail_subtotal:a.show_detail_subtotal})},{deep:!0}),(u,f)=>d.visible?(e.openBlock(),e.createElementBlock("div",{key:0,class:"gr-mask",onClick:f[4]||(f[4]=e.withModifiers(m=>u.$emit("close"),["self"]))},[e.createElementVNode("div",it,[e.createElementVNode("div",st,[f[5]||(f[5]=e.createElementVNode("span",null,"分组规则 & 小计配置",-1)),e.createElementVNode("button",{class:"gr-close",onClick:f[0]||(f[0]=m=>u.$emit("close"))},"✕")]),e.createElementVNode("div",rt,[f[10]||(f[10]=e.createElementVNode("div",{class:"gr-tips"},[e.createElementVNode("p",null,[e.createElementVNode("b",null,"分组是什么?"),e.createTextVNode(" 选择某一列后,相同值的行会自动合并单元格(比如按「系统名称」分组,同系统的多条明细会合并成一个单元格)。每组末尾自动显示一行小计。")])],-1)),e.createElementVNode("div",ct,[e.createElementVNode("div",ut,[f[7]||(f[7]=e.createElementVNode("label",{class:"gr-form-label"},"按哪一列分组",-1)),e.withDirectives(e.createElementVNode("select",{class:"cell-input","onUpdate:modelValue":f[1]||(f[1]=m=>d.groupRules.merge_field=m),style:{flex:"1"}},[f[6]||(f[6]=e.createElementVNode("option",{value:""},"— 不分组 —",-1)),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.columns,m=>(e.openBlock(),e.createElementBlock("option",{key:m.field,value:m.field,disabled:m.editor==="AUTO_SEQ"||m.editor==="AUTO_CALC"},e.toDisplayString(m.title)+"("+e.toDisplayString(m.field)+")",9,mt))),128))],512),[[e.vModelSelect,d.groupRules.merge_field]])]),e.createElementVNode("div",pt,[f[9]||(f[9]=e.createElementVNode("label",{class:"gr-form-label"},"明细小计",-1)),e.createElementVNode("label",ft,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":f[2]||(f[2]=m=>d.groupRules.show_detail_subtotal=m)},null,512),[[e.vModelCheckbox,d.groupRules.show_detail_subtotal]]),f[8]||(f[8]=e.createElementVNode("span",null,"分组末尾显示小计行",-1))])])])]),e.createElementVNode("div",vt,[e.createElementVNode("button",{class:"btn",onClick:f[3]||(f[3]=m=>u.$emit("close"))},"关闭")])])])):e.createCommentVNode("",!0)}},yt=O(bt,[["__scopeId","data-v-bd77a67d"]]),Vt={class:"toolbar"},ht={class:"col-left"},Et={class:"sec-header"},_t={class:"sec-type"},gt={class:"sec-actions"},kt=["disabled","onClick"],Nt=["disabled","onClick"],wt=["onClick"],$t={class:"sec-row"},xt=["onUpdate:modelValue"],Ct={class:"sec-row"},Bt=["onUpdate:modelValue"],Ut=["onUpdate:modelValue"],St={class:"chk-label"},Tt=["onUpdate:modelValue"],Dt={class:"chk-label"},Mt=["onUpdate:modelValue"],At={class:"sec-row"},zt=["onUpdate:modelValue"],Ft={class:"cells-list"},Lt={class:"cell-toolbar"},qt=["onClick"],Ot={class:"sec-row"},Rt=["onUpdate:modelValue"],It={key:0,class:"sec-row"},Pt=["onUpdate:modelValue"],jt={key:1,class:"sec-row"},Qt=["onUpdate:modelValue"],Wt={key:2,class:"sec-row"},Ht=["onUpdate:modelValue"],Xt={key:3,class:"sec-row"},Gt=["onUpdate:modelValue"],Zt={class:"sec-row"},Jt=["onUpdate:modelValue"],Yt={class:"inline-group"},Kt=["onUpdate:modelValue"],el={class:"sec-row"},tl=["onUpdate:modelValue"],ll=["onUpdate:modelValue"],ol={class:"chk-label"},nl=["onUpdate:modelValue"],al={class:"chk-label"},dl=["onUpdate:modelValue"],il={class:"sec-row border-config"},sl={class:"border-group"},rl={class:"border-item"},cl=["onUpdate:modelValue"],ul=["onUpdate:modelValue"],ml=["onUpdate:modelValue"],pl={class:"border-item"},fl=["onUpdate:modelValue"],vl=["onUpdate:modelValue"],bl=["onUpdate:modelValue"],yl={class:"border-item"},Vl=["onUpdate:modelValue"],hl=["onUpdate:modelValue"],El=["onUpdate:modelValue"],_l={class:"border-item"},gl=["onUpdate:modelValue"],kl=["onUpdate:modelValue"],Nl=["onUpdate:modelValue"],wl=["onClick"],$l=["onClick"],xl=["onClick"],Cl={class:"col-right"},Bl={class:"preview-box"},Ul={class:"preview-inner"},Sl={key:1,class:"p-divider"},Tl={key:3,class:"p-row"},Dl={class:"p-label"},Ml={class:"p-value"},Al={__name:"DesignHeader",props:{sections:{type:Array,required:!0},breakpoint:{type:Number,default:1100}},setup(d){const o=d,{isNarrow:a}=H(o.breakpoint);function u(s){s==="divider"?o.sections.push({type:s}):s==="text"?o.sections.push({type:s,text:"纯文本内容",style:{color:"#303133",fontSize:14,bold:!1,italic:!1,align:"left"}}):s==="row"&&o.sections.push({type:s,cells:[{type:"field",label:"字段",bind:"field1",style:I("50%")}]})}function f(s){o.sections.splice(s,1)}function m(s,t){const n=s+t;n<0||n>=o.sections.length||([o.sections[s],o.sections[n]]=[o.sections[n],o.sections[s]])}function b(s){s.cells||(s.cells=[]),s.cells.push({type:"field",label:"新字段",bind:"newField",style:I("33%")})}function g(s,t){s.cells.splice(t,1)}function w(s){const t={},n=s.style||{};return n.color&&(t.color=n.color),n.fontSize&&(t.fontSize=n.fontSize+"px"),n.bold&&(t.fontWeight="bold"),n.italic&&(t.fontStyle="italic"),n.align&&(t.textAlign=n.align),t}return(s,t)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("div",Vt,[t[3]||(t[3]=e.createElementVNode("span",{class:"tip"},"这里定义报价单的大标题、项目信息行等,左侧是设计器,右侧实时预览",-1)),e.createElementVNode("button",{class:"btn",onClick:t[0]||(t[0]=n=>u("row"))},"+ 字段行"),e.createElementVNode("button",{class:"btn",onClick:t[1]||(t[1]=n=>u("divider"))},"+ 分隔线"),e.createElementVNode("button",{class:"btn",onClick:t[2]||(t[2]=n=>u("text"))},"+ 纯文本")]),e.createElementVNode("div",{class:e.normalizeClass(["two-col",{"is-narrow":e.unref(a)}])},[e.createElementVNode("div",ht,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.sections,(n,p)=>(e.openBlock(),e.createElementBlock("div",{key:p,class:"sec-block"},[e.createElementVNode("div",Et,[e.createElementVNode("span",_t,e.toDisplayString(n.type==="row"?"字段行":n.type==="divider"?"分隔线":"纯文本"),1),e.createElementVNode("div",gt,[e.createElementVNode("button",{class:"mini-btn",disabled:p===0,onClick:l=>m(p,-1)},"↑",8,kt),e.createElementVNode("button",{class:"mini-btn",disabled:p>=d.sections.length-1,onClick:l=>m(p,1)},"↓",8,Nt),e.createElementVNode("button",{class:"mini-btn danger",onClick:l=>f(p)},"删",8,wt)])]),n.type==="text"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("div",$t,[t[4]||(t[4]=e.createElementVNode("label",null,"文字",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":l=>n.text=l,class:"cell-input"},null,8,xt),[[e.vModelText,n.text]])]),e.createElementVNode("div",Ct,[t[7]||(t[7]=e.createElementVNode("label",null,"颜色",-1)),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":l=>n.style.color=l,class:"color-input"},null,8,Bt),[[e.vModelText,n.style.color]]),t[8]||(t[8]=e.createElementVNode("label",null,"字号",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":l=>n.style.fontSize=l,type:"number",class:"cell-input tiny",min:"10",max:"48"},null,8,Ut),[[e.vModelText,n.style.fontSize,void 0,{number:!0}]]),e.createElementVNode("label",St,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":l=>n.style.bold=l},null,8,Tt),[[e.vModelCheckbox,n.style.bold]]),t[5]||(t[5]=e.createTextVNode(" 加粗 ",-1))]),e.createElementVNode("label",Dt,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":l=>n.style.italic=l},null,8,Mt),[[e.vModelCheckbox,n.style.italic]]),t[6]||(t[6]=e.createTextVNode(" 斜体 ",-1))])]),e.createElementVNode("div",At,[t[10]||(t[10]=e.createElementVNode("label",null,"对齐",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":l=>n.style.align=l,class:"cell-input small"},[...t[9]||(t[9]=[e.createElementVNode("option",{value:"left"},"左",-1),e.createElementVNode("option",{value:"center"},"中",-1),e.createElementVNode("option",{value:"right"},"右",-1)])],8,zt),[[e.vModelSelect,n.style.align]])])],64)):n.type==="row"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",Ft,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.cells,(l,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:"cell-block"},[e.createElementVNode("div",Lt,[e.createElementVNode("strong",null,e.toDisplayString($+1),1),e.createElementVNode("button",{class:"mini-btn danger",onClick:i=>g(n,$)},"×",8,qt)]),e.createElementVNode("div",Ot,[t[12]||(t[12]=e.createElementVNode("label",null,"类型",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.type=i,class:"cell-input small"},[...t[11]||(t[11]=[e.createElementVNode("option",{value:"field"},"字段(可编辑)",-1),e.createElementVNode("option",{value:"text"},"纯文本",-1)])],8,Rt),[[e.vModelSelect,l.type]])]),l.type==="field"?(e.openBlock(),e.createElementBlock("div",It,[t[13]||(t[13]=e.createElementVNode("label",null,"标签",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.label=i,class:"cell-input"},null,8,Pt),[[e.vModelText,l.label]])])):e.createCommentVNode("",!0),l.type==="field"?(e.openBlock(),e.createElementBlock("div",jt,[t[14]||(t[14]=e.createElementVNode("label",null,"值",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.value=i,class:"cell-input",placeholder:"字段的值"},null,8,Qt),[[e.vModelText,l.value]])])):e.createCommentVNode("",!0),l.type==="field"?(e.openBlock(),e.createElementBlock("div",Wt,[t[15]||(t[15]=e.createElementVNode("label",null,"绑定字段",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.bind=i,class:"cell-input",placeholder:"如 projectName"},null,8,Ht),[[e.vModelText,l.bind]])])):e.createCommentVNode("",!0),l.type==="text"?(e.openBlock(),e.createElementBlock("div",Xt,[t[16]||(t[16]=e.createElementVNode("label",null,"文字",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.text=i,class:"cell-input"},null,8,Gt),[[e.vModelText,l.text]])])):e.createCommentVNode("",!0),e.createElementVNode("div",Zt,[t[19]||(t[19]=e.createElementVNode("label",null,"宽度",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.style.width=i,class:"cell-input small",placeholder:"如 33%"},null,8,Jt),[[e.vModelText,l.style.width]]),e.createElementVNode("div",Yt,[t[18]||(t[18]=e.createElementVNode("label",{class:"muted"},"对齐",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.align=i,class:"cell-input small"},[...t[17]||(t[17]=[e.createElementVNode("option",{value:"left"},"左",-1),e.createElementVNode("option",{value:"center"},"中",-1),e.createElementVNode("option",{value:"right"},"右",-1)])],8,Kt),[[e.vModelSelect,l.style.align]])])]),e.createElementVNode("div",el,[t[22]||(t[22]=e.createElementVNode("label",null,"颜色",-1)),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.color=i,class:"color-input"},null,8,tl),[[e.vModelText,l.style.color]]),t[23]||(t[23]=e.createElementVNode("label",null,"字号",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.style.fontSize=i,type:"number",class:"cell-input tiny",min:"10",max:"48"},null,8,ll),[[e.vModelText,l.style.fontSize,void 0,{number:!0}]]),e.createElementVNode("label",ol,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.bold=i},null,8,nl),[[e.vModelCheckbox,l.style.bold]]),t[20]||(t[20]=e.createTextVNode(" 加粗 ",-1))]),e.createElementVNode("label",al,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.italic=i},null,8,dl),[[e.vModelCheckbox,l.style.italic]]),t[21]||(t[21]=e.createTextVNode(" 斜体 ",-1))])]),e.createElementVNode("div",il,[t[32]||(t[32]=e.createElementVNode("label",null,"边框",-1)),e.createElementVNode("div",sl,[e.createElementVNode("div",rl,[t[25]||(t[25]=e.createElementVNode("span",null,"上",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.top.style=i,class:"cell-input tiny"},[...t[24]||(t[24]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,cl),[[e.vModelSelect,l.style.border.top.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.top.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,ul),[[e.vModelText,l.style.border.top.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.top.color=i,class:"color-input"},null,8,ml),[[e.vModelText,l.style.border.top.color]])]),e.createElementVNode("div",pl,[t[27]||(t[27]=e.createElementVNode("span",null,"下",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.bottom.style=i,class:"cell-input tiny"},[...t[26]||(t[26]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,fl),[[e.vModelSelect,l.style.border.bottom.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.bottom.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,vl),[[e.vModelText,l.style.border.bottom.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.bottom.color=i,class:"color-input"},null,8,bl),[[e.vModelText,l.style.border.bottom.color]])]),e.createElementVNode("div",yl,[t[29]||(t[29]=e.createElementVNode("span",null,"左",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.left.style=i,class:"cell-input tiny"},[...t[28]||(t[28]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,Vl),[[e.vModelSelect,l.style.border.left.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.left.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,hl),[[e.vModelText,l.style.border.left.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.left.color=i,class:"color-input"},null,8,El),[[e.vModelText,l.style.border.left.color]])]),e.createElementVNode("div",_l,[t[31]||(t[31]=e.createElementVNode("span",null,"右",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.right.style=i,class:"cell-input tiny"},[...t[30]||(t[30]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,gl),[[e.vModelSelect,l.style.border.right.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.right.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,kl),[[e.vModelText,l.style.border.right.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.right.color=i,class:"color-input"},null,8,Nl),[[e.vModelText,l.style.border.right.color]])])]),e.createElementVNode("button",{class:"mini-btn",onClick:i=>e.unref(W)(l,"all")},"全",8,wl),e.createElementVNode("button",{class:"mini-btn",onClick:i=>e.unref(W)(l,"none")},"无",8,$l)])]))),128))]),e.createElementVNode("button",{class:"btn btn-ghost",onClick:l=>b(n)},"+ 添加一个单元格",8,xl)],64)):e.createCommentVNode("",!0)]))),128))]),e.createElementVNode("div",Cl,[e.createElementVNode("div",Bl,[t[33]||(t[33]=e.createElementVNode("div",{class:"preview-label"},"实时预览",-1)),e.createElementVNode("div",Ul,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.sections,(n,p)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:p},[n.type==="title"?(e.openBlock(),e.createElementBlock("div",{key:0,class:"p-title",style:e.normalizeStyle(w(n))},e.toDisplayString(n.text||"大标题"),5)):n.type==="divider"?(e.openBlock(),e.createElementBlock("div",Sl)):n.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:2,class:"p-text",style:e.normalizeStyle(w(n))},e.toDisplayString(n.text||"纯文本"),5)):n.type==="row"?(e.openBlock(),e.createElementBlock("div",Tl,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.cells,(l,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:"p-cell",style:e.normalizeStyle(e.unref(ie)(l))},[l.type==="field"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("span",Dl,e.toDisplayString(l.label)+":",1),e.createElementVNode("span",Ml,e.toDisplayString(l.value||"字段值"),1)],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(e.toDisplayString(l.text||"纯文本"),1)],64))],4))),128))])):e.createCommentVNode("",!0)],64))),128))])])])],2)]))}},zl=O(Al,[["__scopeId","data-v-197b51e4"]]),Fl={class:"toolbar"},Ll={class:"col-left"},ql={class:"sec-header"},Ol={class:"sec-type"},Rl={class:"sec-actions"},Il=["disabled","onClick"],Pl=["disabled","onClick"],jl=["onClick"],Ql={class:"cells-list"},Wl={class:"cell-toolbar"},Hl=["onClick"],Xl={class:"sec-row"},Gl=["onUpdate:modelValue"],Zl={class:"sec-row"},Jl=["onUpdate:modelValue"],Yl={class:"sec-row"},Kl=["onUpdate:modelValue"],eo={class:"inline-group"},to=["onUpdate:modelValue"],lo={class:"sec-row"},oo=["onUpdate:modelValue"],no=["onUpdate:modelValue"],ao={class:"chk-label"},io=["onUpdate:modelValue"],so={class:"chk-label"},ro=["onUpdate:modelValue"],co={class:"sec-row border-config"},uo={class:"border-group"},mo={class:"border-item"},po=["onUpdate:modelValue"],fo=["onUpdate:modelValue"],vo=["onUpdate:modelValue"],bo={class:"border-item"},yo=["onUpdate:modelValue"],Vo=["onUpdate:modelValue"],ho=["onUpdate:modelValue"],Eo={class:"border-item"},_o=["onUpdate:modelValue"],go=["onUpdate:modelValue"],ko=["onUpdate:modelValue"],No={class:"border-item"},wo=["onUpdate:modelValue"],$o=["onUpdate:modelValue"],xo=["onUpdate:modelValue"],Co=["onClick"],Bo=["onClick"],Uo=["onClick"],So={class:"sec-row"},To=["onUpdate:modelValue"],Do={class:"sec-row"},Mo=["onUpdate:modelValue"],Ao=["onUpdate:modelValue"],zo={class:"chk-label"},Fo=["onUpdate:modelValue"],Lo={class:"chk-label"},qo=["onUpdate:modelValue"],Oo={class:"sec-row"},Ro=["onUpdate:modelValue"],Io={class:"col-right"},Po={class:"preview-box"},jo={class:"preview-inner"},Qo={key:0,class:"p-divider"},Wo={key:2,class:"p-row"},Ho={__name:"DesignFooter",props:{sections:{type:Array,required:!0},breakpoint:{type:Number,default:1100}},setup(d){const o=d,{isNarrow:a}=H(o.breakpoint);function u(s){s==="divider"?o.sections.push({type:s}):s==="text"?o.sections.push({type:s,text:"纯文本",style:{color:"#303133",fontSize:14,bold:!1,italic:!1,align:"left"}}):s==="row"&&o.sections.push({type:s,cells:[{type:"text",text:"客户签字:",style:I("50%")}]})}function f(s){o.sections.splice(s,1)}function m(s,t){const n=s+t;n<0||n>=o.sections.length||([o.sections[s],o.sections[n]]=[o.sections[n],o.sections[s]])}function b(s){s.cells||(s.cells=[]),s.cells.push({type:"text",text:"签字:",style:I("50%")})}function g(s,t){s.cells.splice(t,1)}function w(s){const t={},n=s.style||{};return n.color&&(t.color=n.color),n.fontSize&&(t.fontSize=n.fontSize+"px"),n.bold&&(t.fontWeight="bold"),n.italic&&(t.fontStyle="italic"),n.align&&(t.textAlign=n.align),t}return(s,t)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("div",Fl,[t[3]||(t[3]=e.createElementVNode("span",{class:"tip"},"💡 页面底部显示签字栏、盖章区等,结构和页面头部一样",-1)),e.createElementVNode("button",{class:"btn",onClick:t[0]||(t[0]=n=>u("divider"))},"+ 分隔线"),e.createElementVNode("button",{class:"btn",onClick:t[1]||(t[1]=n=>u("row"))},"+ 字段行"),e.createElementVNode("button",{class:"btn",onClick:t[2]||(t[2]=n=>u("text"))},"+ 纯文本")]),e.createElementVNode("div",{class:e.normalizeClass(["two-col",{"is-narrow":e.unref(a)}])},[e.createElementVNode("div",Ll,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.sections,(n,p)=>(e.openBlock(),e.createElementBlock("div",{key:p,class:"sec-block"},[e.createElementVNode("div",ql,[e.createElementVNode("span",Ol,e.toDisplayString(n.type==="row"?"字段行":n.type==="divider"?"分隔线":"纯文本"),1),e.createElementVNode("div",Rl,[e.createElementVNode("button",{class:"mini-btn",disabled:p===0,onClick:l=>m(p,-1)},"↑",8,Il),e.createElementVNode("button",{class:"mini-btn",disabled:p>=d.sections.length-1,onClick:l=>m(p,1)},"↓",8,Pl),e.createElementVNode("button",{class:"mini-btn danger",onClick:l=>f(p)},"删",8,jl)])]),n.type==="row"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("div",Ql,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.cells,(l,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:"cell-block"},[e.createElementVNode("div",Wl,[e.createElementVNode("strong",null,e.toDisplayString($+1),1),e.createElementVNode("button",{class:"mini-btn danger",onClick:i=>g(n,$)},"×",8,Hl)]),e.createElementVNode("div",Xl,[t[5]||(t[5]=e.createElementVNode("label",null,"类型",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.type=i,class:"cell-input small"},[...t[4]||(t[4]=[e.createElementVNode("option",{value:"text"},"纯文本",-1)])],8,Gl),[[e.vModelSelect,l.type]])]),e.createElementVNode("div",Zl,[t[6]||(t[6]=e.createElementVNode("label",null,"文字",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.text=i,class:"cell-input"},null,8,Jl),[[e.vModelText,l.text]])]),e.createElementVNode("div",Yl,[t[9]||(t[9]=e.createElementVNode("label",null,"宽度",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.style.width=i,class:"cell-input small",placeholder:"如 50%"},null,8,Kl),[[e.vModelText,l.style.width]]),e.createElementVNode("div",eo,[t[8]||(t[8]=e.createElementVNode("label",{class:"muted"},"对齐",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.align=i,class:"cell-input small"},[...t[7]||(t[7]=[e.createElementVNode("option",{value:"left"},"左",-1),e.createElementVNode("option",{value:"center"},"中",-1),e.createElementVNode("option",{value:"right"},"右",-1)])],8,to),[[e.vModelSelect,l.style.align]])])]),e.createElementVNode("div",lo,[t[12]||(t[12]=e.createElementVNode("label",null,"颜色",-1)),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.color=i,class:"color-input"},null,8,oo),[[e.vModelText,l.style.color]]),t[13]||(t[13]=e.createElementVNode("label",null,"字号",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":i=>l.style.fontSize=i,type:"number",class:"cell-input tiny",min:"10",max:"48"},null,8,no),[[e.vModelText,l.style.fontSize,void 0,{number:!0}]]),e.createElementVNode("label",ao,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.bold=i},null,8,io),[[e.vModelCheckbox,l.style.bold]]),t[10]||(t[10]=e.createTextVNode(" 加粗 ",-1))]),e.createElementVNode("label",so,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.italic=i},null,8,ro),[[e.vModelCheckbox,l.style.italic]]),t[11]||(t[11]=e.createTextVNode(" 斜体 ",-1))])]),e.createElementVNode("div",co,[t[22]||(t[22]=e.createElementVNode("label",null,"边框",-1)),e.createElementVNode("div",uo,[e.createElementVNode("div",mo,[t[15]||(t[15]=e.createElementVNode("span",null,"上",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.top.style=i,class:"cell-input tiny"},[...t[14]||(t[14]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,po),[[e.vModelSelect,l.style.border.top.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.top.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,fo),[[e.vModelText,l.style.border.top.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.top.color=i,class:"color-input"},null,8,vo),[[e.vModelText,l.style.border.top.color]])]),e.createElementVNode("div",bo,[t[17]||(t[17]=e.createElementVNode("span",null,"下",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.bottom.style=i,class:"cell-input tiny"},[...t[16]||(t[16]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,yo),[[e.vModelSelect,l.style.border.bottom.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.bottom.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,Vo),[[e.vModelText,l.style.border.bottom.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.bottom.color=i,class:"color-input"},null,8,ho),[[e.vModelText,l.style.border.bottom.color]])]),e.createElementVNode("div",Eo,[t[19]||(t[19]=e.createElementVNode("span",null,"左",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.left.style=i,class:"cell-input tiny"},[...t[18]||(t[18]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,_o),[[e.vModelSelect,l.style.border.left.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.left.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,go),[[e.vModelText,l.style.border.left.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.left.color=i,class:"color-input"},null,8,ko),[[e.vModelText,l.style.border.left.color]])]),e.createElementVNode("div",No,[t[21]||(t[21]=e.createElementVNode("span",null,"右",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":i=>l.style.border.right.style=i,class:"cell-input tiny"},[...t[20]||(t[20]=[e.createElementVNode("option",{value:""},"无",-1),e.createElementVNode("option",{value:"solid"},"实线",-1),e.createElementVNode("option",{value:"dashed"},"虚线",-1),e.createElementVNode("option",{value:"dotted"},"点线",-1)])],8,wo),[[e.vModelSelect,l.style.border.right.style]]),e.withDirectives(e.createElementVNode("input",{type:"number","onUpdate:modelValue":i=>l.style.border.right.width=i,class:"cell-input tiny",min:"0",max:"20",step:"1"},null,8,$o),[[e.vModelText,l.style.border.right.width,void 0,{number:!0}]]),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.border.right.color=i,class:"color-input"},null,8,xo),[[e.vModelText,l.style.border.right.color]])])]),e.createElementVNode("button",{class:"mini-btn",onClick:i=>e.unref(W)(l,"all")},"全",8,Co),e.createElementVNode("button",{class:"mini-btn",onClick:i=>e.unref(W)(l,"none")},"无",8,Bo)])]))),128))]),e.createElementVNode("button",{class:"btn btn-ghost",onClick:l=>b(n)},"+ 添加一个单元格",8,Uo)],64)):n.type==="text"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",So,[t[23]||(t[23]=e.createElementVNode("label",null,"文字",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":l=>n.text=l,class:"cell-input"},null,8,To),[[e.vModelText,n.text]])]),e.createElementVNode("div",Do,[t[26]||(t[26]=e.createElementVNode("label",null,"颜色",-1)),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":l=>n.style.color=l,class:"color-input"},null,8,Mo),[[e.vModelText,n.style.color]]),t[27]||(t[27]=e.createElementVNode("label",null,"字号",-1)),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":l=>n.style.fontSize=l,type:"number",class:"cell-input tiny",min:"10",max:"48"},null,8,Ao),[[e.vModelText,n.style.fontSize,void 0,{number:!0}]]),e.createElementVNode("label",zo,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":l=>n.style.bold=l},null,8,Fo),[[e.vModelCheckbox,n.style.bold]]),t[24]||(t[24]=e.createTextVNode(" 加粗 ",-1))]),e.createElementVNode("label",Lo,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":l=>n.style.italic=l},null,8,qo),[[e.vModelCheckbox,n.style.italic]]),t[25]||(t[25]=e.createTextVNode(" 斜体 ",-1))])]),e.createElementVNode("div",Oo,[t[29]||(t[29]=e.createElementVNode("label",null,"对齐",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":l=>n.style.align=l,class:"cell-input small"},[...t[28]||(t[28]=[e.createElementVNode("option",{value:"left"},"左",-1),e.createElementVNode("option",{value:"center"},"中",-1),e.createElementVNode("option",{value:"right"},"右",-1)])],8,Ro),[[e.vModelSelect,n.style.align]])])],64)):e.createCommentVNode("",!0)]))),128))]),e.createElementVNode("div",Io,[e.createElementVNode("div",Po,[t[30]||(t[30]=e.createElementVNode("div",{class:"preview-label"},"底部预览",-1)),e.createElementVNode("div",jo,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.sections,(n,p)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:p},[n.type==="divider"?(e.openBlock(),e.createElementBlock("div",Qo)):n.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:1,class:"p-text",style:e.normalizeStyle(w(n))},e.toDisplayString(n.text||"纯文本"),5)):n.type==="row"?(e.openBlock(),e.createElementBlock("div",Wo,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.cells,(l,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:"p-cell",style:e.normalizeStyle(e.unref(ie)(l))},e.toDisplayString(l.text),5))),128))])):e.createCommentVNode("",!0)],64))),128))])])])],2)]))}},Xo=O(Ho,[["__scopeId","data-v-3b5d8a7a"]]),Go={class:"col-left"},Zo={class:"sec-header"},Jo={class:"sec-type"},Yo={class:"sec-actions"},Ko=["disabled","onClick"],en=["disabled","onClick"],tn=["onClick"],ln={class:"sec-row"},on=["onUpdate:modelValue"],nn=["onUpdate:modelValue"],an={class:"sec-row"},dn=["onUpdate:modelValue"],sn={key:0,class:"sec-row"},rn=["onUpdate:modelValue"],cn={key:1,class:"sec-row"},un=["onUpdate:modelValue"],mn={key:2,class:"sec-row"},pn=["onUpdate:modelValue"],fn={class:"sec-row"},vn=["onUpdate:modelValue"],bn=["onUpdate:modelValue"],yn={class:"chk-label"},Vn=["onUpdate:modelValue"],hn={class:"chk-label"},En=["onUpdate:modelValue"],_n={key:0,class:"empty-hint"},gn={class:"col-right"},kn={class:"summary-preview"},Nn={class:"sp-label"},wn={key:0,class:"empty-hint"},$n={__name:"DesignSummary",props:{fields:{type:Array,required:!0},breakpoint:{type:Number,default:1100}},setup(d){const o=d,{isNarrow:a}=H(o.breakpoint);function u(n){return n==="MANUAL_INPUT"?"手动输入":n==="AUTO_CALC"?"自动计算":"纯文本"}function f(n,p){let l=n,$=2;for(;p.has(l);)l=n+"_"+$++;return l}function m(){let n=0;for(const p of o.fields){const l=/^field_(\d+)$/.exec(p.field);l&&(n=Math.max(n,parseInt(l[1],10)))}return n+1}function b(){const n=new Set([...o.fields.map(l=>l.field)]),p="field_"+String(m()).padStart(4,"0");o.fields.push({field:f(p,n),label:"新款项",type:"MANUAL_INPUT",default:0,formula:"",style:{color:"#606266",fontSize:13,bold:!1,italic:!1}})}function g(n){o.fields.splice(n,1)}function w(n,p){const l=n+p;l<0||l>=o.fields.length||([o.fields[n],o.fields[l]]=[o.fields[l],o.fields[n]])}function s(n){const p={},l=n.style||{};return l.color&&(p.color=l.color),l.fontSize&&(p.fontSize=l.fontSize+"px"),l.bold&&(p.fontWeight="bold"),l.italic&&(p.fontStyle="italic"),p}function t(n){return n.type==="AUTO_CALC"?n.formula||"group_total":n.type==="PLAIN_TEXT"?n.text||"(未填写文字)":n.default??0}return(n,p)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("div",{class:"toolbar"},[p[0]||(p[0]=e.createElementVNode("span",{class:"tip"},"💡 汇总区域显示在表格底部,支持手动输入、公式自动计算和纯文本展示",-1)),e.createElementVNode("button",{class:"btn",onClick:b},"+ 添加字段")]),e.createElementVNode("div",{class:e.normalizeClass(["two-col",{"is-narrow":e.unref(a)}])},[e.createElementVNode("div",Go,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.fields,(l,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:"sec-block"},[e.createElementVNode("div",Zo,[e.createElementVNode("span",Jo,e.toDisplayString(u(l.type)),1),e.createElementVNode("div",Yo,[e.createElementVNode("button",{class:"mini-btn",disabled:$===0,onClick:i=>w($,-1)},"↑",8,Ko),e.createElementVNode("button",{class:"mini-btn",disabled:$>=d.fields.length-1,onClick:i=>w($,1)},"↓",8,en),e.createElementVNode("button",{class:"mini-btn danger",onClick:i=>g($)},"删",8,tn)])]),e.createElementVNode("div",ln,[p[1]||(p[1]=e.createElementVNode("label",null,"字段名",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":i=>l.field=i},null,8,on),[[e.vModelText,l.field]]),p[2]||(p[2]=e.createElementVNode("label",null,"显示标签",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":i=>l.label=i},null,8,nn),[[e.vModelText,l.label]])]),e.createElementVNode("div",an,[p[4]||(p[4]=e.createElementVNode("label",null,"类型",-1)),e.withDirectives(e.createElementVNode("select",{class:"cell-input","onUpdate:modelValue":i=>l.type=i},[...p[3]||(p[3]=[e.createElementVNode("option",{value:"MANUAL_INPUT"},"手动输入(自定义金额)",-1),e.createElementVNode("option",{value:"AUTO_CALC"},"自动计算(公式)",-1),e.createElementVNode("option",{value:"PLAIN_TEXT"},"纯文本(固定文字)",-1)])],8,dn),[[e.vModelSelect,l.type]])]),l.type==="MANUAL_INPUT"?(e.openBlock(),e.createElementBlock("div",sn,[p[5]||(p[5]=e.createElementVNode("label",null,"默认值",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input",type:"number","onUpdate:modelValue":i=>l.default=i,placeholder:"可选,切换模板时自动填充"},null,8,rn),[[e.vModelText,l.default,void 0,{number:!0}]])])):e.createCommentVNode("",!0),l.type==="AUTO_CALC"?(e.openBlock(),e.createElementBlock("div",cn,[p[6]||(p[6]=e.createElementVNode("label",null,"公式",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":i=>l.formula=i,placeholder:"如 group_total + service_fee 或 group_total * 0.06"},null,8,un),[[e.vModelText,l.formula]])])):e.createCommentVNode("",!0),l.type==="PLAIN_TEXT"?(e.openBlock(),e.createElementBlock("div",mn,[p[7]||(p[7]=e.createElementVNode("label",null,"文字内容",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input","onUpdate:modelValue":i=>l.text=i,placeholder:"如:税率 1%"},null,8,pn),[[e.vModelText,l.text]])])):e.createCommentVNode("",!0),e.createElementVNode("div",fn,[p[10]||(p[10]=e.createElementVNode("label",null,"颜色",-1)),e.withDirectives(e.createElementVNode("input",{type:"color","onUpdate:modelValue":i=>l.style.color=i,class:"color-input"},null,8,vn),[[e.vModelText,l.style.color]]),p[11]||(p[11]=e.createElementVNode("label",null,"字号",-1)),e.withDirectives(e.createElementVNode("input",{class:"cell-input tiny",type:"number","onUpdate:modelValue":i=>l.style.fontSize=i,min:"10",max:"48",placeholder:"14"},null,8,bn),[[e.vModelText,l.style.fontSize,void 0,{number:!0}]]),e.createElementVNode("label",yn,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.bold=i},null,8,Vn),[[e.vModelCheckbox,l.style.bold]]),p[8]||(p[8]=e.createTextVNode(" 加粗 ",-1))]),e.createElementVNode("label",hn,[e.withDirectives(e.createElementVNode("input",{type:"checkbox","onUpdate:modelValue":i=>l.style.italic=i},null,8,En),[[e.vModelCheckbox,l.style.italic]]),p[9]||(p[9]=e.createTextVNode(" 斜体 ",-1))])])]))),128)),d.fields.length===0?(e.openBlock(),e.createElementBlock("div",_n,"还没有汇总项,点右上角按钮添加")):e.createCommentVNode("",!0)]),e.createElementVNode("div",gn,[p[12]||(p[12]=e.createElementVNode("h4",{class:"preview-title"},"实时预览",-1)),e.createElementVNode("div",kn,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.fields,(l,$)=>(e.openBlock(),e.createElementBlock("div",{class:"sp-row",key:$},[e.createElementVNode("span",Nn,e.toDisplayString(l.label||"标签"),1),e.createElementVNode("span",{class:"sp-value",style:e.normalizeStyle(s(l))},e.toDisplayString(t(l)),5)]))),128)),d.fields.length===0?(e.openBlock(),e.createElementBlock("div",wn,"暂无汇总项")):e.createCommentVNode("",!0)]),p[13]||(p[13]=e.createStaticVNode('<div class="preview-help" data-v-8464c396><p data-v-8464c396><b data-v-8464c396>可用变量:</b></p><p data-v-8464c396><code data-v-8464c396>group_total</code> 明细小计合计</p><p data-v-8464c396><code data-v-8464c396>quantity_sum</code> 数量总和(需字段名为 quantity)</p><p data-v-8464c396><code data-v-8464c396>grand_total</code> 报价总额</p><p data-v-8464c396><code data-v-8464c396>各手动输入项字段名</code> 互相引用</p><p style="margin-top:6px;color:#909399;font-size:12px;" data-v-8464c396>完整列表请看使用教程</p></div>',1))])],2)]))}},xn=O($n,[["__scopeId","data-v-8464c396"]]),Cn={class:"help-dialog"},Bn={class:"help-header"},Un={__name:"HelpModal",props:{visible:{type:Boolean,default:!1}},emits:["close"],setup(d){return(o,a)=>d.visible?(e.openBlock(),e.createElementBlock("div",{key:0,class:"help-modal",onClick:a[1]||(a[1]=e.withModifiers(u=>o.$emit("close"),["self"]))},[e.createElementVNode("div",Cn,[e.createElementVNode("div",Bn,[a[2]||(a[2]=e.createElementVNode("h3",null,"📖 报价单生成器 — 使用教程",-1)),e.createElementVNode("button",{class:"close-btn",onClick:a[0]||(a[0]=u=>o.$emit("close"))},"✕")]),a[3]||(a[3]=e.createStaticVNode(`<div class="help-body" data-v-9af33ede><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>🔁 整体三步流程</h4><p data-v-9af33ede>顶部导航栏有三个步骤,按顺序操作即可生成一份完整报价单:</p><ol class="steps" data-v-9af33ede><li data-v-9af33ede><b data-v-9af33ede>① 设计模板</b> — 定义表头列、页面头部信息、汇总区域、底部签字栏等</li><li data-v-9af33ede><b data-v-9af33ede>② 填写数据</b> — 根据模板录入每条明细,自动分组、自动算小计</li><li data-v-9af33ede><b data-v-9af33ede>③ 预览导出</b> — 查看最终效果,一键导出 Excel 或打印</li></ol><p class="tip-box" data-v-9af33ede>💡 也可以从第 ② 步开始,系统已内置 3 个示例模板可直接使用</p></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>① 表头列 — 定义表格里有哪些列</h4><p data-v-9af33ede>点击顶部工具栏的 <b data-v-9af33ede>+ 添加字段</b> 按钮可以新增一列,然后在表格中把「类型」改成你想要的:</p><table class="help-table" data-v-9af33ede><thead data-v-9af33ede><tr data-v-9af33ede><th data-v-9af33ede>按钮</th><th data-v-9af33ede>字段类型</th><th data-v-9af33ede>说明</th></tr></thead><tbody data-v-9af33ede><tr data-v-9af33ede><td data-v-9af33ede>文本列</td><td data-v-9af33ede>INPUT</td><td data-v-9af33ede>普通文字输入,用于名称、描述等</td></tr><tr data-v-9af33ede><td data-v-9af33ede>数字列</td><td data-v-9af33ede>NUMBER</td><td data-v-9af33ede>只能填数字,用于数量、单价等</td></tr><tr data-v-9af33ede><td data-v-9af33ede>下拉列</td><td data-v-9af33ede>SELECT_DICT</td><td data-v-9af33ede>固定选项,点击列中的"下拉选项"输入选项,用逗号分隔,如 <code data-v-9af33ede>设备,材料,安装</code></td></tr><tr data-v-9af33ede><td data-v-9af33ede>多行文本列</td><td data-v-9af33ede>TEXTAREA</td><td data-v-9af33ede>可输入较长文字,用于备注、说明等</td></tr></tbody></table><p data-v-9af33ede><b data-v-9af33ede>特殊类型列:</b></p><ul data-v-9af33ede><li data-v-9af33ede><b data-v-9af33ede>自动序号</b> — 自动从 1 开始递增,字段名随便改(建议叫 <code data-v-9af33ede>seq</code>)</li><li data-v-9af33ede><b data-v-9af33ede>自动计算(公式)</b> — 用任意公式算值,公式里可引用<b data-v-9af33ede>同一行其他列的字段名</b>,如 <code data-v-9af33ede>quantity * unit_price</code>。字段名必须和你在表头里设置的一致,比如数量列叫 <code data-v-9af33ede>qty</code> 就要写 <code data-v-9af33ede>qty * unit_price</code></li></ul><p data-v-9af33ede><b data-v-9af33ede>列顺序:</b>点行末的 ↑ ↓ 按钮上下移动,或拖动行来调整</p><p data-v-9af33ede><b data-v-9af33ede>列宽度:</b>单位是像素(px),在"宽度"列填数字</p><p class="tip-box" data-v-9af33ede>💡 下拉列的选项是写在逗号分隔的输入框里,保存后切换到「填写数据」页面时会变成下拉选择框</p></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>② 页面头部 — 报价单的标题和项目信息</h4><p data-v-9af33ede>头部由多个"段落"顺序组成,每个段落可以是以下 4 种类型:</p><table class="help-table" data-v-9af33ede><thead data-v-9af33ede><tr data-v-9af33ede><th data-v-9af33ede>类型</th><th data-v-9af33ede>说明</th><th data-v-9af33ede>配置项</th></tr></thead><tbody data-v-9af33ede><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>大标题</b></td><td data-v-9af33ede>最顶部的报价单标题</td><td data-v-9af33ede>文字、字号、粗体、对齐方式</td></tr><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>字段行</b></td><td data-v-9af33ede>一行可以放多个单元格,每个单元格要么是可编辑字段,要么是固定文字</td><td data-v-9af33ede>每个单元格单独配置</td></tr><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>分隔线</b></td><td data-v-9af33ede>画一条灰色横线</td><td data-v-9af33ede>无配置</td></tr><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>纯文本</b></td><td data-v-9af33ede>一段固定文字,如"此报价单有效期30天"</td><td data-v-9af33ede>文字内容、对齐方式</td></tr></tbody></table><p data-v-9af33ede><b data-v-9af33ede>字段行详解:</b></p><ul data-v-9af33ede><li data-v-9af33ede>点"➕ 添加一个单元格"来增加这一行里的格子数量</li><li data-v-9af33ede>每个格子选"类型":<b data-v-9af33ede>字段(可编辑)</b> 或 <b data-v-9af33ede>纯文本</b></li><li data-v-9af33ede>字段类型要填 <b data-v-9af33ede>标签</b>(如"项目名称")和 <b data-v-9af33ede>绑定字段</b>(如 <code data-v-9af33ede>projectName</code>)</li><li data-v-9af33ede>绑定字段是关键!同一个绑定字段名在整个模板中要保持一致,后续数据填写和导出都靠它</li><li data-v-9af33ede>宽度用百分比,如 <code data-v-9af33ede>50%</code>、<code data-v-9af33ede>33%</code>,一行所有格子宽度加起来建议 = 100%</li></ul><p class="tip-box" data-v-9af33ede>💡 右侧"实时预览"区域会随着你的编辑即时变化,所见即所得</p></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>③ 汇总区域 — 表格底部的费用合计</h4><p data-v-9af33ede>汇总项显示在明细表格的下方(导出 Excel 时会自动排在表格右侧底部)。</p><table class="help-table" data-v-9af33ede><thead data-v-9af33ede><tr data-v-9af33ede><th data-v-9af33ede>类型</th><th data-v-9af33ede>说明</th></tr></thead><tbody data-v-9af33ede><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>手动输入(自定义金额)</b></td><td data-v-9af33ede>任意需要手工填写的金额项:人工费、服务费、运费、税费、折扣、其他费用等。可以在"默认值"里预设一个初始值</td></tr><tr data-v-9af33ede><td data-v-9af33ede><b data-v-9af33ede>自动计算(公式)</b></td><td data-v-9af33ede>系统自动算好的值,需要写公式。<code data-v-9af33ede>grand_total</code> 会自动把所有手动输入项加进去</td></tr></tbody></table><p data-v-9af33ede><b data-v-9af33ede>自动计算公式里的可用变量(固定):</b></p><table class="help-table" data-v-9af33ede><thead data-v-9af33ede><tr data-v-9af33ede><th data-v-9af33ede>变量名</th><th data-v-9af33ede>含义</th><th data-v-9af33ede>说明</th></tr></thead><tbody data-v-9af33ede><tr data-v-9af33ede><td data-v-9af33ede><code data-v-9af33ede>group_total</code></td><td data-v-9af33ede>明细小计合计</td><td data-v-9af33ede>所有行的自动计算列(小计列)求和</td></tr><tr data-v-9af33ede><td data-v-9af33ede><code data-v-9af33ede>grand_total</code></td><td data-v-9af33ede>报价总额</td><td data-v-9af33ede>group_total + 所有手动输入项之和</td></tr><tr data-v-9af33ede><td data-v-9af33ede><code data-v-9af33ede>quantity_sum</code></td><td data-v-9af33ede>数量总和</td><td data-v-9af33ede>所有行 <b data-v-9af33ede>字段名为 quantity</b> 的列求和。如果表头数量列不叫 quantity,这个值就是 0</td></tr></tbody></table><p data-v-9af33ede><b data-v-9af33ede>动态可用变量(随你的模板定义):</b></p><p data-v-9af33ede>你在汇总区域里定义的<b data-v-9af33ede>每一个手动输入项的字段名</b>,都会自动成为可用变量,它们之间也能互相引用。</p><p data-v-9af33ede>举个例子:如果你定义了 <code data-v-9af33ede>labor_cost</code>、<code data-v-9af33ede>service_fee</code>、<code data-v-9af33ede>discount</code> 三个手动项,那么自动计算公式里可以写:</p><pre class="code" data-v-9af33ede>group_total + labor_cost + service_fee - discount</pre><p data-v-9af33ede><b data-v-9af33ede>字段名命名建议:</b></p><ul data-v-9af33ede><li data-v-9af33ede><code data-v-9af33ede>grand_total</code> — 报价总额(特殊字段,系统会把所有手动项加进去)</li><li data-v-9af33ede><code data-v-9af33ede>group_total</code> — 明细小计(建议不要手动改成别的,公式里会用到)</li><li data-v-9af33ede><code data-v-9af33ede>quantity</code> — 表头里的数量列字段名(如果想用 <code data-v-9af33ede>quantity_sum</code> 变量,必须叫这个)</li><li data-v-9af33ede>其他手动项随意,如 <code data-v-9af33ede>service_fee</code>、<code data-v-9af33ede>freight</code>、<code data-v-9af33ede>tax_amount</code>、<code data-v-9af33ede>discount</code> 等</li></ul></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>④ 页面底部 — 签字栏、盖章区</h4><p data-v-9af33ede>结构和"页面头部"完全一样,支持:分隔线、字段行、纯文本。</p><p data-v-9af33ede>常见用法:</p><ul data-v-9af33ede><li data-v-9af33ede>分隔线 → 分隔表格和签字区</li><li data-v-9af33ede>字段行 → 左边"客户签字:________",右边"业务员签字:________"</li><li data-v-9af33ede>纯文本 → 居中写"公司盖章:"</li></ul></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>💾 保存与模板管理</h4><ul data-v-9af33ede><li data-v-9af33ede><b data-v-9af33ede>💾 保存修改</b> — 直接更新当前选中的模板</li><li data-v-9af33ede><b data-v-9af33ede>➕ 另存为新模板</b> — 输入一个新名字,基于当前模板复制出一个全新的模板</li><li data-v-9af33ede>顶部的下拉框可以在已有的模板之间切换,切换后下方所有配置会自动加载</li></ul><p class="tip-box" data-v-9af33ede>⚠️ 目前模板数据保存在浏览器内存中(刷新后会恢复默认),如果要持久化存储,需要把模板同步到后端接口</p></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>🔢 分组与计算规则(高级)</h4><p data-v-9af33ede>在「表头列」tab 的列表下方,有一个<b data-v-9af33ede>分组规则</b>配置框:</p><ul data-v-9af33ede><li data-v-9af33ede><b data-v-9af33ede>按哪一列分组</b> — 选择一列后,相同值的行会自动合并单元格,每组末尾自动生成小计行。选「不分组」则不分组、不显示小计,但列上勾选了「相同值合并」的列仍然会对相邻相同值做合并</li></ul><p data-v-9af33ede>对应模板数据结构:</p><pre class="code" data-v-9af33ede>{
|
|
12
|
+
group_rules: { merge_field: 'system_name' },
|
|
13
|
+
// 不分组时 group_rules 为 null 或 { merge_field: '' }
|
|
14
|
+
}</pre><p data-v-9af33ede>例如模板 TPL-001 按 <code data-v-9af33ede>system_name</code>(系统名称)分组,相同系统名称的多条明细会自动合并成一个单元格,每组末尾自动生成小计行。</p></section><section class="help-section" data-v-9af33ede><h4 data-v-9af33ede>📝 切换到「填写数据」</h4><p data-v-9af33ede>模板设计好后,点顶部的"下一步"进入填写数据页面,注意:</p><ul data-v-9af33ede><li data-v-9af33ede>点 ➕ 添加新条目,会弹出表单,表单字段完全根据你的模板表头列生成</li><li data-v-9af33ede>分组字段(如 <code data-v-9af33ede>system_name</code>)会自动继承上一行的值,让同组合并不间断</li><li data-v-9af33ede>右侧"实时汇总"卡片会根据汇总区域配置动态显示</li></ul></section><section class="help-section tip-box final-tip" data-v-9af33ede> 🎯 <b data-v-9af33ede>推荐操作顺序:</b>选一个最接近的示例模板 → 点"另存为新模板"复制一份 → 按需要改表头列 / 头部信息 / 汇总项 → 保存 → 下一步填写数据 → 导出 Excel </section></div>`,1))])])):e.createCommentVNode("",!0)}},Sn=O(Un,[["__scopeId","data-v-9af33ede"]]),Tn={class:"designer"},Dn={class:"tabs"},Mn={key:0,class:"tab-content"},An={key:1,class:"tab-content"},zn={key:2,class:"tab-content"},Fn={key:3,class:"tab-content"},Ln={key:4,class:"tab-content tab-content-preview"},qn={__name:"QuokitTemplate",props:{tpl:{type:Object,required:!0},breakpoint:{type:Number,default:1100}},emits:["update:tpl"],setup(d,{expose:o,emit:a}){const u=d,f=a,m=e.ref("cols"),b=e.ref(!1),g=e.ref(!1),w=ae([],{}),s=Z([],{isHeader:!0}),t=Z([],{isHeader:!1}),n=se([]);let p=!1;e.watch(()=>u.tpl,()=>{if(p)return;p=!0;const k=u.tpl||{};w.setColumns(k.columns||[]),w.setGroupRules(k.group_rules||{}),s.setSections(k.header_sections||[]),t.setSections(k.footer_sections||[]),n.setFields(k.summary_fields||[])},{immediate:!0});const l=De(k=>{f("update:tpl",k)},200),$=e.computed(()=>({...w.tpl,header_sections:s.toTpl(),footer_sections:t.toTpl(),summary_fields:n.toTpl()}));e.watch($,()=>{if(p){p=!1;return}l($.value)},{deep:!0}),e.onBeforeUnmount(()=>{l.cancel()});const i=e.computed(()=>$.value),S=e.computed(()=>re(w.tpl.columns,3));return o({getTemplateJSON(){return $.value},showHelp(){b.value=!0}}),(k,_)=>(e.openBlock(),e.createElementBlock("div",Tn,[e.createElementVNode("div",Dn,[e.createElementVNode("div",{class:e.normalizeClass(["tab",{active:m.value==="cols"}]),onClick:_[0]||(_[0]=B=>m.value="cols")},"① 表头列",2),e.createElementVNode("div",{class:e.normalizeClass(["tab",{active:m.value==="header"}]),onClick:_[1]||(_[1]=B=>m.value="header")},"② 页面头部",2),e.createElementVNode("div",{class:e.normalizeClass(["tab",{active:m.value==="summary"}]),onClick:_[2]||(_[2]=B=>m.value="summary")},"③ 汇总区域",2),e.createElementVNode("div",{class:e.normalizeClass(["tab",{active:m.value==="footer"}]),onClick:_[3]||(_[3]=B=>m.value="footer")},"④ 页面底部",2),e.createElementVNode("div",{class:e.normalizeClass(["tab",{active:m.value==="preview"}]),onClick:_[4]||(_[4]=B=>m.value="preview")},"⑤ 总体预览",2)]),m.value==="cols"?(e.openBlock(),e.createElementBlock("div",Mn,[e.createVNode(dt,{columns:e.unref(w).columns,"group-rules":e.unref(w).groupRules,breakpoint:d.breakpoint,onHelp:_[5]||(_[5]=B=>b.value=!0),onOpenGroup:_[6]||(_[6]=B=>g.value=!0)},null,8,["columns","group-rules","breakpoint"])])):e.createCommentVNode("",!0),m.value==="header"?(e.openBlock(),e.createElementBlock("div",An,[e.createVNode(zl,{sections:e.unref(s).sections,breakpoint:d.breakpoint},null,8,["sections","breakpoint"])])):e.createCommentVNode("",!0),m.value==="summary"?(e.openBlock(),e.createElementBlock("div",zn,[e.createVNode(xn,{fields:e.unref(n).fields,breakpoint:d.breakpoint},null,8,["fields","breakpoint"])])):e.createCommentVNode("",!0),m.value==="footer"?(e.openBlock(),e.createElementBlock("div",Fn,[e.createVNode(Xo,{sections:e.unref(t).sections,breakpoint:d.breakpoint},null,8,["sections","breakpoint"])])):e.createCommentVNode("",!0),m.value==="preview"?(e.openBlock(),e.createElementBlock("div",Ln,[e.createVNode(ne,{tpl:i.value,data:S.value},null,8,["tpl","data"])])):e.createCommentVNode("",!0),e.createVNode(Sn,{visible:b.value,onClose:_[7]||(_[7]=B=>b.value=!1)},null,8,["visible"]),e.createVNode(yt,{visible:g.value,columns:e.unref(w).columns,"group-rules":e.unref(w).groupRules,onClose:_[8]||(_[8]=B=>g.value=!1)},null,8,["visible","columns","group-rules"])]))}},On=O(qn,[["__scopeId","data-v-88fcba25"]]),Rn={class:"page"},In={key:0,class:"empty-tip"},Pn={key:1,class:"data-table"},jn={class:"main-table"},Qn=["onClick"],Wn={key:1,class:"subtotal"},Hn=["onClick"],Xn=["onClick"],Gn={class:"de-dialog"},Zn={class:"de-header"},Jn={class:"de-content"},Yn={class:"form-grid"},Kn={class:"form-cell-label"},ea=["onUpdate:modelValue","placeholder"],ta=["step","min","max","onUpdate:modelValue"],la=["onUpdate:modelValue","placeholder"],oa=["onUpdate:modelValue"],na=["value"],aa={class:"de-footer"},da={__name:"QuokitData",props:{tpl:{type:Object,required:!0},data:{type:Array,default:()=>[]}},emits:["update:data"],setup(d,{emit:o}){const a=d,u=o,f=e.computed(()=>a.data),m=e.computed(()=>{var S;return((S=a.tpl)==null?void 0:S.columns)||[]}),b=e.computed(()=>m.value.filter(S=>S.editor!=="AUTO_SEQ"&&S.editor!=="AUTO_CALC")),g=e.ref(!1),w=e.ref("add"),s=e.ref(-1),t=e.ref({});function n(){const S={};for(const k of b.value)k.editor==="NUMBER"?S[k.field]=k.default??k.min??0:S[k.field]=k.default??"";return S}function p(){w.value="add",s.value=-1,t.value=n(),g.value=!0}function l(S){w.value="edit",s.value=S,t.value={...f.value[S]},g.value=!0}function $(S){if(!confirm("确定删除这条明细?"))return;const k=[...f.value];k.splice(S,1),u("update:data",k)}function i(){if(w.value==="edit"){const S=[...f.value];S[s.value]={...t.value},u("update:data",S)}else u("update:data",[...f.value,{...t.value}]);g.value=!1}return(S,k)=>(e.openBlock(),e.createElementBlock("div",Rn,[e.createElementVNode("div",{class:"toolbar"},[k[4]||(k[4]=e.createElementVNode("span",{class:"tip"},"点击行可快速编辑,预估总价会自动计算",-1)),e.createElementVNode("div",{class:"btn-group-inline"},[e.createElementVNode("button",{class:"btn",onClick:p},"+ 添加新条目")])]),f.value.length===0?(e.openBlock(),e.createElementBlock("div",In,[...k[5]||(k[5]=[e.createElementVNode("div",{class:"empty-icon"},"📋",-1),e.createElementVNode("div",{class:"empty-text"},"暂无数据,点击下方按钮添加第一条明细",-1)])])):e.createCommentVNode("",!0),f.value.length>0?(e.openBlock(),e.createElementBlock("div",Pn,[e.createElementVNode("table",jn,[e.createElementVNode("thead",null,[e.createElementVNode("tr",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m.value,_=>(e.openBlock(),e.createElementBlock("th",{key:_.field,style:e.normalizeStyle({width:_.width+"px"})},e.toDisplayString(_.title),5))),128)),k[6]||(k[6]=e.createElementVNode("th",{width:"140"},"操作",-1))])]),e.createElementVNode("tbody",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(f.value,(_,B)=>(e.openBlock(),e.createElementBlock("tr",{key:B,onClick:z=>l(B)},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m.value,z=>(e.openBlock(),e.createElementBlock("td",{key:z.field},[z.editor==="AUTO_SEQ"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(B+1),1)],64)):z.editor==="AUTO_CALC"?(e.openBlock(),e.createElementBlock("span",Wn,"¥ "+e.toDisplayString(e.unref(P)(z.formula||"0",_).toFixed(2)),1)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:2},[e.createTextVNode(e.toDisplayString(_[z.field]),1)],64))]))),128)),e.createElementVNode("td",{class:"op-cell",onClick:k[0]||(k[0]=e.withModifiers(()=>{},["stop"]))},[e.createElementVNode("button",{class:"row-btn",onClick:z=>l(B)},"编辑",8,Hn),e.createElementVNode("button",{class:"row-btn danger",onClick:z=>$(B)},"删除",8,Xn)])],8,Qn))),128))])])])):e.createCommentVNode("",!0),g.value?(e.openBlock(),e.createElementBlock("div",{key:2,class:"de-mask",onClick:k[3]||(k[3]=e.withModifiers(_=>g.value=!1,["self"]))},[e.createElementVNode("div",Gn,[e.createElementVNode("div",Zn,[e.createElementVNode("span",null,e.toDisplayString(w.value==="edit"?"编辑明细":"添加明细"),1),e.createElementVNode("button",{class:"de-close",onClick:k[1]||(k[1]=_=>g.value=!1)},"✕")]),e.createElementVNode("div",Jn,[e.createElementVNode("div",Yn,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(b.value,_=>(e.openBlock(),e.createElementBlock("div",{key:_.field,class:e.normalizeClass(["form-cell",{full:_.editor==="TEXTAREA"}])},[e.createElementVNode("label",Kn,e.toDisplayString(_.title),1),_.editor==="INPUT"||_.editor===void 0?e.withDirectives((e.openBlock(),e.createElementBlock("input",{key:0,class:"cell-input","onUpdate:modelValue":B=>t.value[_.field]=B,placeholder:_.title},null,8,ea)),[[e.vModelText,t.value[_.field]]]):_.editor==="NUMBER"?e.withDirectives((e.openBlock(),e.createElementBlock("input",{key:1,class:"cell-input",type:"number",step:_.step??(_.min??0)<1?"0.01":"1",min:_.min,max:_.max,"onUpdate:modelValue":B=>t.value[_.field]=B},null,8,ta)),[[e.vModelText,t.value[_.field],void 0,{number:!0}]]):_.editor==="TEXTAREA"?e.withDirectives((e.openBlock(),e.createElementBlock("textarea",{key:2,class:"cell-input",rows:"3","onUpdate:modelValue":B=>t.value[_.field]=B,placeholder:_.title},null,8,la)),[[e.vModelText,t.value[_.field]]]):_.editor==="SELECT_DICT"?e.withDirectives((e.openBlock(),e.createElementBlock("select",{key:3,class:"cell-input","onUpdate:modelValue":B=>t.value[_.field]=B},[k[7]||(k[7]=e.createElementVNode("option",{value:""},"-- 请选择 --",-1)),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(_.dict||[],B=>(e.openBlock(),e.createElementBlock("option",{key:B,value:B},e.toDisplayString(B),9,na))),128))],8,oa)),[[e.vModelSelect,t.value[_.field]]]):e.createCommentVNode("",!0)],2))),128))])]),e.createElementVNode("div",aa,[e.createElementVNode("button",{class:"btn",onClick:k[2]||(k[2]=_=>g.value=!1)},"取消"),e.createElementVNode("button",{class:"btn btn-primary",onClick:i},"确定")])])])):e.createCommentVNode("",!0)]))}},ia=O(da,[["__scopeId","data-v-554cd100"]]);exports.QuokitData=ia;exports.QuokitSheet=ne;exports.QuokitTemplate=On;exports.generateMockRows=re;exports.useColumns=ae;exports.useSections=Z;exports.useSummary=se;
|