vue2-client 1.9.81 → 1.9.83
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/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +1 -0
- package/package.json +1 -1
- package/src/base-client/components/common/Recording/Recording.vue +115 -31
- package/src/base-client/components/common/Recording/index.js +2 -2
- package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +1 -2
- package/src/base-client/components/common/XForm/XFormItem.vue +5 -1
- package/src/base-client/components/common/XFormTable/XFormTable.vue +8 -2
- package/src/base-client/components/common/XReportGrid/XReport.vue +75 -28
- package/src/base-client/components/common/XReportGrid/XReportDemo.vue +1 -1
- package/src/base-client/components/common/XReportGrid/XReportDesign.vue +2 -1
- package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +37 -6
- package/src/base-client/components/common/XTable/XTable.vue +4 -0
- package/src/pages/Recording/index.vue +3 -2
|
@@ -31,6 +31,7 @@ this.openDialog('xxx', 5, {}, {}, {})
|
|
|
31
31
|
- refreshTable 重新查询
|
|
32
32
|
- clearRowKeys 清除选中的行
|
|
33
33
|
- getTableData() 获取全部数据
|
|
34
|
+
- setTableData(data) 设置表格内数据
|
|
34
35
|
- Object.assign(this.fixedQueryForm, data) 给查询条件传值
|
|
35
36
|
- 事件相关
|
|
36
37
|
- afterSubmit( type(新增/修改/擦和讯), id: (所操作的主键id), form: (请求的表单内容)) 提交后触发
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<button @click="startRecording" :disabled="isRecording">开始录音</button>
|
|
4
|
-
<button @click="stopRecording" :disabled="!isRecording">停止录音</button>
|
|
3
|
+
<a-button type="primary" @click="startRecording" :disabled="isRecording">开始录音</a-button>
|
|
4
|
+
<a-button type="primary" @click="stopRecording" :disabled="!isRecording">停止录音</a-button>
|
|
5
5
|
<!-- <audio v-if="audioUrl" :src="audioUrl" controls></audio>-->
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
@@ -20,8 +20,7 @@ export default {
|
|
|
20
20
|
config: {}
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
-
props: {
|
|
24
|
-
},
|
|
23
|
+
props: {},
|
|
25
24
|
watch: {},
|
|
26
25
|
components: {},
|
|
27
26
|
created () {
|
|
@@ -31,29 +30,30 @@ export default {
|
|
|
31
30
|
},
|
|
32
31
|
methods: {
|
|
33
32
|
async startRecording () {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
this.inputData = ''
|
|
34
|
+
this.audioChunks = []
|
|
35
|
+
const url = this.config.webSocketURL ? this.config.webSocketURL : 'ws://192.168.50.67:31090/websocket/bash' // WebSocket地址
|
|
36
|
+
this.setupWebSocket(url)
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// 等待 WebSocket 连接成功
|
|
39
|
+
await this.waitForWebSocketConnection()
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
this.isRecording = true
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// 初始化 AudioContext
|
|
44
|
+
this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
'录音软件不支持您的浏览器!请使用现代浏览器或确保您正在使用 HTTPS。'
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
// 获取麦克风输入流
|
|
53
|
+
this.audioStream = await navigator.mediaDevices.getUserMedia({ audio: true })
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// 设置音频处理流程
|
|
56
|
+
this.setupAudioProcessing()
|
|
57
57
|
},
|
|
58
58
|
setupWebSocket (url) {
|
|
59
59
|
this.ws = new WebSocket(url)
|
|
@@ -64,6 +64,10 @@ export default {
|
|
|
64
64
|
if (data.result !== undefined) {
|
|
65
65
|
this.inputData += data.result
|
|
66
66
|
}
|
|
67
|
+
if (!this.isRecording) {
|
|
68
|
+
this.ws.close()
|
|
69
|
+
this.resRecordingData()
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
this.ws.onclose = () => console.log('WebSocket closed.')
|
|
@@ -93,9 +97,13 @@ export default {
|
|
|
93
97
|
|
|
94
98
|
const inputData = e.inputBuffer.getChannelData(0)
|
|
95
99
|
|
|
100
|
+
// 收集音频数据块
|
|
101
|
+
|
|
96
102
|
// Resample to 16000 Hz if needed
|
|
97
103
|
const resampledData = this.resample(inputData, this.audioContext.sampleRate, 16000)
|
|
98
104
|
|
|
105
|
+
this.audioChunks.push(new Float32Array(resampledData))
|
|
106
|
+
|
|
99
107
|
// Convert to 16-bit PCM and send via WebSocket
|
|
100
108
|
const byteArray = this.convertTo16BitPCM(resampledData)
|
|
101
109
|
this.ws.send(byteArray)
|
|
@@ -108,24 +116,97 @@ export default {
|
|
|
108
116
|
throw error
|
|
109
117
|
}
|
|
110
118
|
},
|
|
119
|
+
|
|
111
120
|
stopRecording () {
|
|
112
121
|
this.isRecording = false
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.ws.onclose = () => {
|
|
116
|
-
console.log('WebSocket closed.')
|
|
117
|
-
// 这里可以添加WebSocket关闭后的清理工作
|
|
118
|
-
}
|
|
119
|
-
// 关闭WebSocket连接
|
|
120
|
-
this.ws.close()
|
|
121
|
-
}
|
|
122
|
+
|
|
123
|
+
// 停止麦克风流
|
|
122
124
|
if (this.audioStream) {
|
|
123
|
-
this.audioStream.getTracks().forEach(track => track.stop())
|
|
125
|
+
this.audioStream.getTracks().forEach((track) => track.stop())
|
|
124
126
|
}
|
|
127
|
+
|
|
128
|
+
// 合并音频数据块并保存为文件
|
|
129
|
+
// this.saveAudioFile()
|
|
130
|
+
|
|
131
|
+
// 关闭 WebSocket
|
|
132
|
+
// if (this.ws) {
|
|
133
|
+
// this.ws.close()
|
|
134
|
+
// }
|
|
135
|
+
|
|
125
136
|
if (this.audioContext) {
|
|
126
137
|
this.audioContext.close()
|
|
127
138
|
}
|
|
128
139
|
},
|
|
140
|
+
|
|
141
|
+
saveAudioFile () {
|
|
142
|
+
// 合并所有音频块
|
|
143
|
+
const audioBuffer = this.mergeAudioChunks(this.audioChunks)
|
|
144
|
+
|
|
145
|
+
// 转换为 WAV 格式
|
|
146
|
+
const wavBlob = this.encodeWAV(audioBuffer, 16000)
|
|
147
|
+
|
|
148
|
+
// 创建下载链接并触发下载
|
|
149
|
+
const url = URL.createObjectURL(wavBlob)
|
|
150
|
+
const a = document.createElement('a')
|
|
151
|
+
a.style.display = 'none'
|
|
152
|
+
a.href = url
|
|
153
|
+
a.download = 'recording.wav'
|
|
154
|
+
document.body.appendChild(a)
|
|
155
|
+
a.click()
|
|
156
|
+
window.URL.revokeObjectURL(url)
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
mergeAudioChunks (chunks) {
|
|
160
|
+
const length = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
|
|
161
|
+
const result = new Float32Array(length)
|
|
162
|
+
let offset = 0
|
|
163
|
+
for (const chunk of chunks) {
|
|
164
|
+
result.set(chunk, offset)
|
|
165
|
+
offset += chunk.length
|
|
166
|
+
}
|
|
167
|
+
return result
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
encodeWAV (samples, sampleRate) {
|
|
171
|
+
const buffer = new ArrayBuffer(44 + samples.length * 2) // 每个样本占2字节
|
|
172
|
+
const view = new DataView(buffer)
|
|
173
|
+
|
|
174
|
+
const writeString = (view, offset, string) => {
|
|
175
|
+
for (let i = 0; i < string.length; i++) {
|
|
176
|
+
view.setUint8(offset + i, string.charCodeAt(i))
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// WAV文件头
|
|
181
|
+
writeString(view, 0, 'RIFF') // ChunkID
|
|
182
|
+
view.setUint32(4, 36 + samples.length * 2, true) // ChunkSize
|
|
183
|
+
writeString(view, 8, 'WAVE') // Format
|
|
184
|
+
|
|
185
|
+
// fmt子块
|
|
186
|
+
writeString(view, 12, 'fmt ') // Subchunk1ID
|
|
187
|
+
view.setUint32(16, 16, true) // Subchunk1Size (PCM格式固定为16)
|
|
188
|
+
view.setUint16(20, 1, true) // AudioFormat (PCM为1)
|
|
189
|
+
view.setUint16(22, 1, true) // NumChannels (单声道为1)
|
|
190
|
+
view.setUint32(24, sampleRate, true) // SampleRate
|
|
191
|
+
view.setUint32(28, sampleRate * 2, true) // ByteRate (SampleRate * NumChannels * BitsPerSample/8)
|
|
192
|
+
view.setUint16(32, 2, true) // BlockAlign (NumChannels * BitsPerSample/8)
|
|
193
|
+
view.setUint16(34, 16, true) // BitsPerSample
|
|
194
|
+
|
|
195
|
+
// data子块
|
|
196
|
+
writeString(view, 36, 'data') // Subchunk2ID
|
|
197
|
+
view.setUint32(40, samples.length * 2, true) // Subchunk2Size
|
|
198
|
+
|
|
199
|
+
// 写入PCM数据
|
|
200
|
+
let offset = 44
|
|
201
|
+
for (let i = 0; i < samples.length; i++) {
|
|
202
|
+
const s = Math.max(-1, Math.min(1, samples[i])) // 限制范围为[-1, 1]
|
|
203
|
+
view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true) // 转换为16位PCM
|
|
204
|
+
offset += 2
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return new Blob([buffer], { type: 'audio/wav' })
|
|
208
|
+
},
|
|
209
|
+
|
|
129
210
|
resample (data, inputSampleRate, outputSampleRate) {
|
|
130
211
|
if (inputSampleRate === outputSampleRate) {
|
|
131
212
|
return data
|
|
@@ -148,6 +229,9 @@ export default {
|
|
|
148
229
|
},
|
|
149
230
|
getRecordingData () {
|
|
150
231
|
return this.inputData
|
|
232
|
+
},
|
|
233
|
+
resRecordingData () {
|
|
234
|
+
this.$emit('recordingData', this.inputData)
|
|
151
235
|
}
|
|
152
236
|
}
|
|
153
237
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Recording from './Recording.vue'
|
|
2
2
|
|
|
3
|
-
export default
|
|
3
|
+
export default Recording
|
|
@@ -235,7 +235,7 @@ export default {
|
|
|
235
235
|
} else {
|
|
236
236
|
this.layout = layout
|
|
237
237
|
}
|
|
238
|
-
if (isHandleFormKey && !isKeyHandle) {
|
|
238
|
+
if ((isHandleFormKey === null || isHandleFormKey === undefined) && !isKeyHandle) {
|
|
239
239
|
this.isHandleFormKey = isKeyHandle
|
|
240
240
|
} else if (isHandleFormKey) {
|
|
241
241
|
this.isHandleFormKey = isHandleFormKey
|
|
@@ -246,7 +246,6 @@ export default {
|
|
|
246
246
|
this.configContent = configContent
|
|
247
247
|
this.formItems = this.getFromItem(formItems, formJson)
|
|
248
248
|
this.viewMode = viewMode
|
|
249
|
-
this.isHandleFormKey = isHandleFormKey
|
|
250
249
|
this.showSubmitBtn = showSubmitBtn
|
|
251
250
|
this.serviceName = serviceName
|
|
252
251
|
this.businessType = businessType
|
|
@@ -617,7 +617,7 @@
|
|
|
617
617
|
:flex="attr.flex">
|
|
618
618
|
<recording
|
|
619
619
|
ref="recording"
|
|
620
|
-
@
|
|
620
|
+
@recordingData="recordingData"
|
|
621
621
|
>
|
|
622
622
|
</recording>
|
|
623
623
|
</x-form-col>
|
|
@@ -1151,7 +1151,11 @@ export default {
|
|
|
1151
1151
|
// 获取 recording 转换后的数据
|
|
1152
1152
|
getRecodingData () {
|
|
1153
1153
|
return this.$refs.recording.getRecordingData()
|
|
1154
|
+
},
|
|
1155
|
+
recordingData (data) {
|
|
1156
|
+
this.emitFunc('recordingData', data)
|
|
1154
1157
|
}
|
|
1158
|
+
|
|
1155
1159
|
}
|
|
1156
1160
|
}
|
|
1157
1161
|
</script>
|
|
@@ -525,7 +525,7 @@ export default {
|
|
|
525
525
|
formItems: res.formJson,
|
|
526
526
|
viewMode: this.viewMode,
|
|
527
527
|
localEditMode: this.localEditMode,
|
|
528
|
-
|
|
528
|
+
isKeyHandle: !Boolean(this.localEditMode),
|
|
529
529
|
serviceName: this.serviceName,
|
|
530
530
|
fixedAddForm: this.fixedAddForm,
|
|
531
531
|
getDataParams: this.getDataParams,
|
|
@@ -566,7 +566,7 @@ export default {
|
|
|
566
566
|
formItems: res.formJson,
|
|
567
567
|
viewMode: this.viewMode,
|
|
568
568
|
localEditMode: this.localEditMode,
|
|
569
|
-
|
|
569
|
+
isKeyHandle: !Boolean(this.localEditMode),
|
|
570
570
|
serviceName: this.serviceName,
|
|
571
571
|
fixedAddForm: this.fixedAddForm,
|
|
572
572
|
getDataParams: this.getDataParams,
|
|
@@ -648,6 +648,12 @@ export default {
|
|
|
648
648
|
getTableData () {
|
|
649
649
|
return this.$refs.xTable.getTableData()
|
|
650
650
|
},
|
|
651
|
+
/**
|
|
652
|
+
* 设置表格数据
|
|
653
|
+
*/
|
|
654
|
+
setTableData (data) {
|
|
655
|
+
this.$refs.xTable.setTableData(data)
|
|
656
|
+
},
|
|
651
657
|
/**
|
|
652
658
|
* 表单本地提交
|
|
653
659
|
*/
|
|
@@ -275,34 +275,80 @@ export default {
|
|
|
275
275
|
console.log('内部注册完成', this.$refs)
|
|
276
276
|
},
|
|
277
277
|
|
|
278
|
-
transformArray (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
278
|
+
transformArray (inputList) {
|
|
279
|
+
let operationIndex = 0
|
|
280
|
+
let operationList = []
|
|
281
|
+
const outputList = []
|
|
282
|
+
for (const lst of inputList) {
|
|
283
|
+
// 如果列表为空或只有一个元素,则所有元素相等。比较列表中每个元素是否与第一个元素相等
|
|
284
|
+
if (lst.length >= 1 && !lst.every(x => Array.isArray(x) || Array.isArray(lst[0]) || x.rowSpan === lst[0].rowSpan)) {
|
|
285
|
+
operationList = lst
|
|
286
|
+
break // 使用 break 退出整个循环
|
|
287
|
+
} else {
|
|
288
|
+
// 被操作的行
|
|
289
|
+
operationIndex += 1
|
|
290
|
+
}
|
|
291
|
+
}
|
|
282
292
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
let maxMergeRow = 0
|
|
294
|
+
|
|
295
|
+
// 没有需要合并的行,直接返回
|
|
296
|
+
if (operationList.length === 0) {
|
|
297
|
+
return inputList
|
|
298
|
+
} else {
|
|
299
|
+
// 当前行的最大值
|
|
300
|
+
const maxRow = Math.max(...operationList.map(item => item.rowSpan))
|
|
301
|
+
let mergeIndexCol = 0
|
|
302
|
+
for (let index = 0; index < operationList.length; index++) {
|
|
303
|
+
const row = operationList[index]
|
|
304
|
+
let rowSpan = row.rowSpan
|
|
305
|
+
// 需要合并的行
|
|
306
|
+
let mergeIndexRow = operationIndex + 1
|
|
307
|
+
// 存放合并后的行
|
|
308
|
+
const rows = []
|
|
309
|
+
// 添加当前行
|
|
310
|
+
if (rowSpan < maxRow && mergeIndexRow < inputList.length) {
|
|
311
|
+
rows.push([row])
|
|
312
|
+
}
|
|
313
|
+
// 当前需要被操作并且操作行没有超出列表的高度
|
|
314
|
+
while (rowSpan < maxRow && mergeIndexRow < inputList.length) {
|
|
315
|
+
rowSpan += inputList[mergeIndexRow][mergeIndexCol].rowSpan
|
|
316
|
+
// 放一行到合并结果
|
|
317
|
+
rows.push([inputList[mergeIndexRow][mergeIndexCol]])
|
|
318
|
+
if (mergeIndexRow > maxMergeRow) {
|
|
319
|
+
// 记录最多操作到了哪行
|
|
320
|
+
maxMergeRow = mergeIndexRow
|
|
321
|
+
}
|
|
322
|
+
mergeIndexRow++
|
|
323
|
+
}
|
|
324
|
+
// operation_list赋值, 没有变化的,不处理
|
|
325
|
+
if (rows.length !== 0) {
|
|
326
|
+
operationList[index] = rows
|
|
327
|
+
}
|
|
328
|
+
if (row.rowSpan !== maxRow) {
|
|
329
|
+
mergeIndexCol++ // 操作列转为下一列
|
|
330
|
+
}
|
|
295
331
|
}
|
|
296
|
-
|
|
297
|
-
})
|
|
332
|
+
}
|
|
298
333
|
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
334
|
+
// 组成outputlist, operation_list前部填入
|
|
335
|
+
let putindex = 0
|
|
336
|
+
while (operationIndex > 0) {
|
|
337
|
+
outputList.push(inputList[putindex])
|
|
338
|
+
putindex++
|
|
339
|
+
operationIndex -= 1
|
|
302
340
|
}
|
|
303
341
|
|
|
304
|
-
|
|
305
|
-
|
|
342
|
+
outputList.push(operationList)
|
|
343
|
+
|
|
344
|
+
// 组成outputlist, operation_list后部填入
|
|
345
|
+
while (maxMergeRow < inputList.length - 1) {
|
|
346
|
+
outputList.push(inputList[maxMergeRow + 1])
|
|
347
|
+
maxMergeRow += 1
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
console.log('转换完成了', outputList)
|
|
351
|
+
return this.transformArray(outputList)
|
|
306
352
|
},
|
|
307
353
|
|
|
308
354
|
// 根据名字从注册到组件中获取组件
|
|
@@ -887,14 +933,15 @@ export default {
|
|
|
887
933
|
}
|
|
888
934
|
})
|
|
889
935
|
})
|
|
890
|
-
this.$nextTick(() => {
|
|
891
|
-
this.scanFinish = true
|
|
892
|
-
})
|
|
893
936
|
|
|
894
937
|
// 对配置进行转换
|
|
895
938
|
console.log('转换前配置', this.config)
|
|
896
|
-
|
|
897
|
-
console.log('转换后的列描述',
|
|
939
|
+
this.originalConfig.columns = this.transformArray(this.config.columns)
|
|
940
|
+
console.log('转换后的列描述', this.originalConfig.columns)
|
|
941
|
+
|
|
942
|
+
this.$nextTick(() => {
|
|
943
|
+
this.scanFinish = true
|
|
944
|
+
})
|
|
898
945
|
},
|
|
899
946
|
// 初始化JSON配置
|
|
900
947
|
jsonConfigInit () {
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a-row type="flex" :gutter="gutter" style="margin-bottom:
|
|
2
|
+
<a-row type="flex" :gutter="gutter" style="margin-bottom: .5rem;">
|
|
3
3
|
<!-- 预览页展示 -->
|
|
4
4
|
<template v-if="display">
|
|
5
5
|
<template v-if="!inputColumns">
|
|
6
6
|
<a-col
|
|
7
7
|
name="trGroup"
|
|
8
|
-
style="flex: 1;"
|
|
9
8
|
v-for="(cell, cellIndex) in columns"
|
|
10
|
-
v-if="!cell.dontShowRow"
|
|
9
|
+
v-if="Array.isArray(cell) || !cell.dontShowRow"
|
|
11
10
|
:key="cellIndex"
|
|
12
|
-
:style="determineCellStyle(cell)"
|
|
13
|
-
:span="cell.colSpan ? cell.colSpan * 2 : undefined">
|
|
11
|
+
:style="Array.isArray(cell) ? {} : determineCellStyle(cell)"
|
|
12
|
+
:span="Array.isArray(cell) ? cell[0][0].colSpan * 2 : (cell.colSpan ? cell.colSpan * 2 : undefined)">
|
|
14
13
|
<a-card class="flexItem" :bordered="false" :body-style="flexItemBodyState">
|
|
15
14
|
<!-- 插槽渲染 -->
|
|
16
|
-
<template v-if="cell
|
|
15
|
+
<template v-if="Array.isArray(cell)">
|
|
16
|
+
<!-- 处理 cell 是数组的情况 -->
|
|
17
|
+
<div v-for="(item, index) in cell" :key="index">
|
|
18
|
+
<x-report-tr-group
|
|
19
|
+
@updateImg="updateImg"
|
|
20
|
+
:show-img-in-cell="showImgInCell"
|
|
21
|
+
:img-prefix="imgPrefix"
|
|
22
|
+
:server-name="serverName"
|
|
23
|
+
:env="env"
|
|
24
|
+
:use-oss-for-img="useOssForImg"
|
|
25
|
+
:key="index"
|
|
26
|
+
:columns="recalculateItem(item)"
|
|
27
|
+
:no-top-border="noTopBorder"
|
|
28
|
+
:config-data="configData"
|
|
29
|
+
:config="config"
|
|
30
|
+
:display="true">
|
|
31
|
+
</x-report-tr-group>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
<template v-else-if="cell.type === 'slot'">
|
|
17
35
|
<template
|
|
18
36
|
v-if="['x-form-table','x-add-native-form','x-tree-pro', 'x-his-editor', 'x-tab', 'x-form-group', 'x-report', 'x-buttons', 'x-conversation'].includes(cell.slotType)">
|
|
19
37
|
<component
|
|
@@ -592,6 +610,19 @@ export default {
|
|
|
592
610
|
}, this.env === 'dev')
|
|
593
611
|
}
|
|
594
612
|
},
|
|
613
|
+
|
|
614
|
+
// 对于嵌套情况,对colSpan重新分配
|
|
615
|
+
recalculateItem (item) {
|
|
616
|
+
const totalColSpan = item.reduce((sum, cell) => sum + (cell.colSpan || 1), 0) // 计算总的 colSpan
|
|
617
|
+
return item.map(cell => {
|
|
618
|
+
const newColSpan = Math.round((cell.colSpan || 1) / totalColSpan * 12) // 按比例重新分配 colSpan
|
|
619
|
+
return {
|
|
620
|
+
...cell,
|
|
621
|
+
colSpan: newColSpan // 更新 colSpan
|
|
622
|
+
}
|
|
623
|
+
})
|
|
624
|
+
},
|
|
625
|
+
|
|
595
626
|
getEventHandlers (cell) {
|
|
596
627
|
const handlers = {}
|
|
597
628
|
if (!cell?.events || cell?.events?.length === 0) {
|
|
@@ -1124,6 +1124,10 @@ export default {
|
|
|
1124
1124
|
getTableData () {
|
|
1125
1125
|
return this.$refs.table.localDataSource
|
|
1126
1126
|
},
|
|
1127
|
+
// 设置表格内数据
|
|
1128
|
+
setTableData (data) {
|
|
1129
|
+
Object.assign(this.$refs.table, { localDataSource: data })
|
|
1130
|
+
},
|
|
1127
1131
|
// 获取所有本地数据
|
|
1128
1132
|
getLocalData () {
|
|
1129
1133
|
return this.localEditModeDataSource
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div id="test" v-if="showReport">
|
|
3
|
-
<
|
|
3
|
+
<recording
|
|
4
4
|
@updateImg="updateImg"
|
|
5
5
|
ref="main"
|
|
6
6
|
:use-oss-for-img="false"
|
|
@@ -22,7 +22,8 @@ import { exportHTMLNodeToPDF } from '@vue2-client/utils/htmlToPDFApi'
|
|
|
22
22
|
export default {
|
|
23
23
|
name: 'Example',
|
|
24
24
|
components: {
|
|
25
|
-
XReport
|
|
25
|
+
XReport,
|
|
26
|
+
Recording: () => import('@vue2-client/base-client/components/common/Recording')
|
|
26
27
|
},
|
|
27
28
|
mounted () {
|
|
28
29
|
console.log(this.$route)
|