af-mobile-client-vue3 1.0.85 → 1.0.87
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/package.json +1 -1
- package/src/components/core/Uploader/index.vue +11 -2
- package/src/components/data/XCellList/XCellList.md +275 -275
- package/src/components/data/XFormItem/index.vue +16 -2
- package/src/components/data/XReportGrid/XReport.vue +973 -973
- package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
- package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
- package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
- package/src/components/data/XReportGrid/XReportJsonRender.vue +386 -386
- package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
- package/src/components/data/XReportGrid/index.md +44 -44
- package/src/components/data/XReportGrid/print.js +184 -184
- package/src/layout/GridView/index.vue +16 -16
- package/src/views/component/XCellListView/index.vue +5 -5
- package/src/views/component/XFormGroupView/index.vue +2 -2
- package/src/views/component/XReportGridView/index.vue +18 -18
- package/tsconfig.json +43 -43
- package/src/views/component/test/index.vue +0 -52
|
@@ -1,592 +1,592 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, defineAsyncComponent, inject, nextTick, onBeforeMount, ref, watch } from 'vue'
|
|
3
|
-
import {
|
|
4
|
-
Col as VanCol,
|
|
5
|
-
Row as VanRow,
|
|
6
|
-
showDialog,
|
|
7
|
-
} from 'vant'
|
|
8
|
-
|
|
9
|
-
// import { getRealKeyData } from '@af-mobile-client-vue3/utils/util'
|
|
10
|
-
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
|
|
11
|
-
|
|
12
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
13
|
-
showImgInCell: false,
|
|
14
|
-
config: () => ({}),
|
|
15
|
-
serverName: '',
|
|
16
|
-
env: 'prod',
|
|
17
|
-
display: true,
|
|
18
|
-
useOssForImg: false,
|
|
19
|
-
noTopBorder: false,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
// Emits
|
|
23
|
-
const emit = defineEmits<{
|
|
24
|
-
(e: 'update:configData', value: any): void
|
|
25
|
-
(e: 'change', value: any): void
|
|
26
|
-
(e: 'updateImg', value: any): void
|
|
27
|
-
(e: 'selectRow', value: any): void
|
|
28
|
-
(e: 'slotRendered'): void
|
|
29
|
-
(e: 'listClick', value: any): void
|
|
30
|
-
}>()
|
|
31
|
-
|
|
32
|
-
// import { getMicroData, getWindow, isMicroAppEnv, microDispatch } from '@af-mobile-client-vue3/utils/microAppUtils'
|
|
33
|
-
// import { isInAModal } from '@af-mobile-client-vue3/utils/microAppUtils'
|
|
34
|
-
|
|
35
|
-
// 定义isInAModal变量(原来从微应用工具中导入,现在手动定义)
|
|
36
|
-
const isInAModal = ref(false)
|
|
37
|
-
|
|
38
|
-
// 动态导入组件
|
|
39
|
-
const XFormTable = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/data/XCellList/index.vue'))
|
|
40
|
-
// const XAddNativeForm = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XAddNativeForm/XAddNativeForm.vue'))
|
|
41
|
-
// const XFormGroup = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XFormGroup/XFormGroup.vue'))
|
|
42
|
-
// const XTreePro = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTree/XTreePro.vue'))
|
|
43
|
-
// const XHisEditor = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XHisEditor/XHisEditor.vue'))
|
|
44
|
-
// const XTab = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTab/XTab.vue'))
|
|
45
|
-
// const XReport = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XReport/XReport.vue'))
|
|
46
|
-
// const XButtons = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XButtons/XButtons.vue'))
|
|
47
|
-
// const XLabelSelect = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XLabelSelect/XLabelSelect.vue'))
|
|
48
|
-
// const XConversation = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XConversation/XConversation.vue'))
|
|
49
|
-
// const XCheckList = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCheckList/XCheckList.vue'))
|
|
50
|
-
// const XCardSet = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCardSet/XCardSet.vue'))
|
|
51
|
-
// const XCollapse = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCollapse/XCollapse.vue'))
|
|
52
|
-
// const XHDescriptions = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XHDescriptions/XHDescriptions.vue'))
|
|
53
|
-
// const XSidebar = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XSidebar/XSidebar.vue'))
|
|
54
|
-
// const XList = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XList/XList.vue'))
|
|
55
|
-
// const XInput = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XInput/XInput.vue'))
|
|
56
|
-
// const XTimeLine = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTimeline/XTimeline.vue'))
|
|
57
|
-
// const XRadio = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XRadio/XRadio.vue'))
|
|
58
|
-
// const XCalendar = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCalendar/XCalendar.vue'))
|
|
59
|
-
// const XTimeSelect = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XTimeSelect/XTimeSelect.vue'))
|
|
60
|
-
// const XCheckbox = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XCheckbox/XCheckbox.vue'))
|
|
61
|
-
// const XTitle = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XTitle/XTitle.vue'))
|
|
62
|
-
|
|
63
|
-
// 组件映射表 - 将kebab-case的组件名映射到实际组件对象
|
|
64
|
-
const componentMap: Record<string, any> = {
|
|
65
|
-
'x-form-table': XFormTable,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// 可用的插槽组件列表
|
|
69
|
-
const slotComponents = [
|
|
70
|
-
'x-form-table',
|
|
71
|
-
'x-add-native-form',
|
|
72
|
-
'x-tree-pro',
|
|
73
|
-
'x-his-editor',
|
|
74
|
-
'x-tab',
|
|
75
|
-
'x-form-group',
|
|
76
|
-
'x-report',
|
|
77
|
-
'x-buttons',
|
|
78
|
-
'x-label-select',
|
|
79
|
-
'x-conversation',
|
|
80
|
-
'x-check-list',
|
|
81
|
-
'x-cardSet',
|
|
82
|
-
'x-collapse',
|
|
83
|
-
'x-h-descriptions',
|
|
84
|
-
'x-sidebar',
|
|
85
|
-
'x-list',
|
|
86
|
-
'x-input',
|
|
87
|
-
'x-time-line',
|
|
88
|
-
'x-radio',
|
|
89
|
-
'x-calendar',
|
|
90
|
-
'x-time-select',
|
|
91
|
-
'x-checkbox',
|
|
92
|
-
'x-title',
|
|
93
|
-
]
|
|
94
|
-
|
|
95
|
-
// 类型定义
|
|
96
|
-
interface ComponentRef {
|
|
97
|
-
init: (config: any) => void
|
|
98
|
-
refresh?: () => void
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
interface MixinData {
|
|
102
|
-
businessType?: string
|
|
103
|
-
files?: any[]
|
|
104
|
-
images?: any[]
|
|
105
|
-
[key: string]: any
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
interface InjectFunctions {
|
|
109
|
-
getMixinData: () => MixinData
|
|
110
|
-
getSelectedId: () => string | number
|
|
111
|
-
getSelectedData: () => any
|
|
112
|
-
getOutEnv: () => string
|
|
113
|
-
getConfigByName: (configName: string, serviceName: string, callback: (config: any) => void, isDev?: boolean) => void
|
|
114
|
-
runLogic: (config: any, selectedId?: any, serviceName?: string) => Promise<any>
|
|
115
|
-
getComponentByName: (name: string) => ComponentRef | undefined
|
|
116
|
-
registerComponent: (name: string, component: ComponentRef | undefined) => void
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
interface UploadConfig {
|
|
120
|
-
type: string
|
|
121
|
-
accept: string[]
|
|
122
|
-
resUploadStock: number
|
|
123
|
-
pathKey: string
|
|
124
|
-
resUploadMode?: string
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
interface GutterItem {
|
|
128
|
-
xs: number
|
|
129
|
-
sm: number
|
|
130
|
-
md: number
|
|
131
|
-
lg: number
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
type Gutter = [number, GutterItem]
|
|
135
|
-
|
|
136
|
-
// Props
|
|
137
|
-
interface Props {
|
|
138
|
-
columns: any[]
|
|
139
|
-
showImgInCell?: boolean
|
|
140
|
-
config?: Record<string, any>
|
|
141
|
-
serverName?: string
|
|
142
|
-
env?: string
|
|
143
|
-
configData: Record<string, any>
|
|
144
|
-
display?: boolean
|
|
145
|
-
useOssForImg?: boolean
|
|
146
|
-
noTopBorder?: boolean
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// 注入依赖
|
|
150
|
-
const openDialog = inject('openDialog')
|
|
151
|
-
const emitEvent = inject('emitEvent')
|
|
152
|
-
const registerComponent = inject('registerComponent') as InjectFunctions['registerComponent']
|
|
153
|
-
const setColSpanByName = inject('setColSpanByName')
|
|
154
|
-
const setGlobalData = inject('setGlobalData')
|
|
155
|
-
const getGlobalData = inject('getGlobalData')
|
|
156
|
-
const getComponentByName = inject('getComponentByName') as InjectFunctions['getComponentByName']
|
|
157
|
-
const runLogicInject = inject('runLogic') as InjectFunctions['runLogic']
|
|
158
|
-
const getMixinData = inject('getMixinData', () => ({})) as InjectFunctions['getMixinData']
|
|
159
|
-
const getSelectedId = inject('getSelectedId', () => '') as InjectFunctions['getSelectedId']
|
|
160
|
-
const getSelectedData = inject('getSelectedData', () => ({})) as InjectFunctions['getSelectedData']
|
|
161
|
-
const getOutEnv = inject('getOutEnv', () => '') as InjectFunctions['getOutEnv']
|
|
162
|
-
const currUser = inject('currUser')
|
|
163
|
-
const isWidget = inject('isWidget', false)
|
|
164
|
-
const getConfigByNameInject = inject('getConfigByName', () => {}) as InjectFunctions['getConfigByName']
|
|
165
|
-
|
|
166
|
-
// 状态
|
|
167
|
-
const gutter = ref([8, 8])
|
|
168
|
-
const maxColSpan = ref(12)
|
|
169
|
-
const uploadConfig = ref<UploadConfig>({
|
|
170
|
-
type: 'image',
|
|
171
|
-
accept: ['image/jpeg', 'image/png', 'image/gif'],
|
|
172
|
-
resUploadStock: 9,
|
|
173
|
-
pathKey: 'cs',
|
|
174
|
-
resUploadMode: 'single',
|
|
175
|
-
})
|
|
176
|
-
const mixinData = ref<MixinData>({})
|
|
177
|
-
const flexItemBodyState = ref({
|
|
178
|
-
padding: '24px',
|
|
179
|
-
})
|
|
180
|
-
const slotRendered = ref(0)
|
|
181
|
-
|
|
182
|
-
// Refs
|
|
183
|
-
const trGroupRefs = ref(new Map())
|
|
184
|
-
const dynamicComponentRefs = ref(new Map<string, ComponentRef>())
|
|
185
|
-
|
|
186
|
-
// 计算属性
|
|
187
|
-
const allSlotSum = computed(() => {
|
|
188
|
-
let sum = 0
|
|
189
|
-
props.columns.forEach((item) => {
|
|
190
|
-
if (Array.isArray(item)) {
|
|
191
|
-
item.forEach((cell) => {
|
|
192
|
-
if (cell.type === 'slot') {
|
|
193
|
-
sum++
|
|
194
|
-
}
|
|
195
|
-
})
|
|
196
|
-
}
|
|
197
|
-
else if (item.type && item.type === 'slot') {
|
|
198
|
-
sum++
|
|
199
|
-
}
|
|
200
|
-
})
|
|
201
|
-
return sum
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
// Methods
|
|
205
|
-
function setTrGroupRef(el: any, key: string) {
|
|
206
|
-
if (el)
|
|
207
|
-
trGroupRefs.value.set(key, el)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function setDynamicComponentRef(el: any, key: string) {
|
|
211
|
-
if (el)
|
|
212
|
-
dynamicComponentRefs.value.set(key, el)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function listClick(data: any) {
|
|
216
|
-
emit('listClick', data)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function calculateColSpan(cell: any) {
|
|
220
|
-
return Array.isArray(cell)
|
|
221
|
-
? cell[0][0]?.colSpan * 2
|
|
222
|
-
: (cell?.colSpan ?? cell?.def?.colSpan ?? 1) * 2
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function calcTDBorder(cellNoBorder = false) {
|
|
226
|
-
if (cellNoBorder)
|
|
227
|
-
return 'tdNoBorder'
|
|
228
|
-
|
|
229
|
-
return props.noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function determineCellStyle(cell: any) {
|
|
233
|
-
if (!cell.style)
|
|
234
|
-
return {}
|
|
235
|
-
return cell.style
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function getEventHandlers(cell: any) {
|
|
239
|
-
const handlers: Record<string, Function> = {}
|
|
240
|
-
if (!cell?.events || cell?.events?.length === 0)
|
|
241
|
-
return handlers
|
|
242
|
-
|
|
243
|
-
cell.events.forEach((event: any) => {
|
|
244
|
-
handlers[event.type] = async (...args: any[]) => {
|
|
245
|
-
console.info('Event handled:', event.type, args)
|
|
246
|
-
let func = event.customFunction
|
|
247
|
-
if (func && func.startsWith('function'))
|
|
248
|
-
func = func.replace('function', 'async function')
|
|
249
|
-
|
|
250
|
-
const result = await executeStrFunctionByContext(null, func, args)
|
|
251
|
-
if (result instanceof Promise) {
|
|
252
|
-
result.then((res) => {
|
|
253
|
-
if (!res)
|
|
254
|
-
return
|
|
255
|
-
let messageType = 'success'
|
|
256
|
-
|
|
257
|
-
if (res?.name) {
|
|
258
|
-
const waitRefreshRef = getComponentByName?.(res.name)
|
|
259
|
-
if (waitRefreshRef)
|
|
260
|
-
waitRefreshRef.refresh()
|
|
261
|
-
else
|
|
262
|
-
console.warn(`未找到组件${res.name}无法刷新`)
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (res?.messageType)
|
|
266
|
-
messageType = res.messageType
|
|
267
|
-
|
|
268
|
-
if (res?.message) {
|
|
269
|
-
showDialog({
|
|
270
|
-
message: res.message,
|
|
271
|
-
})
|
|
272
|
-
}
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
return handlers
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function getComponentName(queryParamsName: string, serviceName: string, componentName: string) {
|
|
282
|
-
// 从映射表中获取组件,如果没有则返回原始组件名
|
|
283
|
-
return componentMap[componentName] || componentName
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async function onComponentMounted(h: any, cell: any, cellIndex: number) {
|
|
287
|
-
slotRendered.value += 1
|
|
288
|
-
if (slotRendered.value >= allSlotSum.value)
|
|
289
|
-
emit('slotRendered')
|
|
290
|
-
|
|
291
|
-
if (getMixinData && getMixinData())
|
|
292
|
-
mixinData.value = getMixinData()
|
|
293
|
-
|
|
294
|
-
if (cell.slotRef)
|
|
295
|
-
registerComponent?.(cell.slotRef, dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`))
|
|
296
|
-
|
|
297
|
-
console.log(`插槽组件已经初始化 slotType ${cell.slotType},ref= dynamicComponent_${cell.slotRef || cellIndex} , serviceName = ${cell.serviceName}`)
|
|
298
|
-
|
|
299
|
-
const shouldInit = cell.shouldInit ?? true
|
|
300
|
-
if (shouldInit) {
|
|
301
|
-
if (cell.slotType === 'x-add-native-form')
|
|
302
|
-
initAddNativeForm(cell, cellIndex)
|
|
303
|
-
else if (cell.slotType === 'x-form-group')
|
|
304
|
-
initFormGroup(cell, cellIndex)
|
|
305
|
-
else if (cell.slotType === 'x-buttons')
|
|
306
|
-
initButtons(cell, cellIndex)
|
|
307
|
-
else if (cell.slotType === 'x-label-select')
|
|
308
|
-
initLabelSelect(cell, cellIndex)
|
|
309
|
-
else if (cell.slotType === 'x-report')
|
|
310
|
-
initReport(cell, cellIndex)
|
|
311
|
-
else if (cell.slotType === 'x-conversation')
|
|
312
|
-
initConversation(cell, cellIndex)
|
|
313
|
-
else if (cell.slotType === 'x-check-list')
|
|
314
|
-
initCheckList(cell, cellIndex)
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// 初始化各种组件的方法
|
|
319
|
-
async function initAddNativeForm(cell: any, cellIndex: number) {
|
|
320
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, async (res: any) => {
|
|
321
|
-
let param = { ...mixinData.value }
|
|
322
|
-
let selectedId
|
|
323
|
-
if (res.paramLogicName) {
|
|
324
|
-
if (getSelectedId) {
|
|
325
|
-
selectedId = getSelectedId()
|
|
326
|
-
if (typeof selectedId !== 'object')
|
|
327
|
-
selectedId = { selectedId }
|
|
328
|
-
}
|
|
329
|
-
param = Object.assign(param, await runLogicInject(res.paramLogicName, selectedId, cell.serviceName))
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
333
|
-
if (componentRef) {
|
|
334
|
-
componentRef.init({
|
|
335
|
-
serviceName: cell.serviceName,
|
|
336
|
-
configName: cell.slotConfig,
|
|
337
|
-
formItems: res.formJson,
|
|
338
|
-
showSubmitBtn: !isInAModal.value,
|
|
339
|
-
businessType: param.businessType || '新增',
|
|
340
|
-
layout: res.xAddFormLayout,
|
|
341
|
-
primaryKey: res.primaryKey,
|
|
342
|
-
...res,
|
|
343
|
-
fixedAddForm: param,
|
|
344
|
-
modifyModelData: {
|
|
345
|
-
files: param.files,
|
|
346
|
-
images: param.images,
|
|
347
|
-
},
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
async function initFormGroup(cell: any, cellIndex: number) {
|
|
354
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
355
|
-
const param = { ...mixinData.value }
|
|
356
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
357
|
-
if (componentRef) {
|
|
358
|
-
componentRef.init({
|
|
359
|
-
...res,
|
|
360
|
-
serviceName: cell.serviceName,
|
|
361
|
-
showSubmitBtn: !isInAModal.value,
|
|
362
|
-
businessType: param.businessType || '新增',
|
|
363
|
-
modifyModelData: param,
|
|
364
|
-
showLeftTab: true,
|
|
365
|
-
})
|
|
366
|
-
}
|
|
367
|
-
})
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
async function initButtons(cell: any, cellIndex: number) {
|
|
371
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
372
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
373
|
-
if (componentRef) {
|
|
374
|
-
componentRef.init({
|
|
375
|
-
...res,
|
|
376
|
-
serviceName: cell.serviceName,
|
|
377
|
-
})
|
|
378
|
-
}
|
|
379
|
-
})
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
async function initLabelSelect(cell: any, cellIndex: number) {
|
|
383
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
384
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
385
|
-
if (componentRef) {
|
|
386
|
-
componentRef.init({
|
|
387
|
-
...res,
|
|
388
|
-
serviceName: cell.serviceName,
|
|
389
|
-
})
|
|
390
|
-
}
|
|
391
|
-
})
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async function initReport(cell: any, cellIndex: number) {
|
|
395
|
-
const param = { ...mixinData.value }
|
|
396
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
397
|
-
if (componentRef)
|
|
398
|
-
componentRef.init(param)
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
async function initConversation(cell: any, cellIndex: number) {
|
|
402
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
403
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
404
|
-
if (componentRef) {
|
|
405
|
-
componentRef.init({
|
|
406
|
-
serviceName: cell.serviceName,
|
|
407
|
-
...res,
|
|
408
|
-
})
|
|
409
|
-
}
|
|
410
|
-
})
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
async function initCheckList(cell: any, cellIndex: number) {
|
|
414
|
-
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
415
|
-
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
416
|
-
if (componentRef) {
|
|
417
|
-
componentRef.init({
|
|
418
|
-
serviceName: cell.serviceName,
|
|
419
|
-
...res,
|
|
420
|
-
})
|
|
421
|
-
}
|
|
422
|
-
})
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function recalculateItem(item: any[]) {
|
|
426
|
-
const totalColSpan = item.reduce((sum, cell) => {
|
|
427
|
-
return sum + (cell._isManualColSpan ? 0 : (cell.colSpan || 1))
|
|
428
|
-
}, 0)
|
|
429
|
-
return item.map((cell) => {
|
|
430
|
-
if (cell._isManualColSpan)
|
|
431
|
-
return cell
|
|
432
|
-
const newColSpan = Math.round((cell.colSpan || 1) / totalColSpan * 12)
|
|
433
|
-
return {
|
|
434
|
-
...cell,
|
|
435
|
-
colSpan: newColSpan,
|
|
436
|
-
_isAutoCalculated: true,
|
|
437
|
-
}
|
|
438
|
-
})
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// 生命周期钩子
|
|
442
|
-
onBeforeMount(() => {
|
|
443
|
-
if (props.useOssForImg)
|
|
444
|
-
uploadConfig.value.resUploadMode = 'oss'
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
// 监听器
|
|
448
|
-
watch(() => props.columns, (newVal) => {
|
|
449
|
-
console.log('columns变化:', JSON.parse(JSON.stringify(newVal)))
|
|
450
|
-
nextTick(() => {
|
|
451
|
-
// Vue 3 不需要$forceUpdate
|
|
452
|
-
})
|
|
453
|
-
}, { deep: true, immediate: true })
|
|
454
|
-
|
|
455
|
-
// 暴露方法
|
|
456
|
-
defineExpose({
|
|
457
|
-
// getWindow,
|
|
458
|
-
// isMicroAppEnv,
|
|
459
|
-
// microDispatch,
|
|
460
|
-
// getMicroData,
|
|
461
|
-
// getRealKeyData
|
|
462
|
-
})
|
|
463
|
-
</script>
|
|
464
|
-
|
|
465
|
-
<template>
|
|
466
|
-
<VanRow type="flex" :gutter="gutter" :style="isWidget ? { margin: '0px' } : { 'margin-bottom': '.5rem' }">
|
|
467
|
-
<template v-for="(cell, cellIndex) in columns" :key="cellIndex">
|
|
468
|
-
<VanCol
|
|
469
|
-
v-if="Array.isArray(cell) || !cell?.dontShowRow"
|
|
470
|
-
:ref="(el) => setTrGroupRef(el, cell.slotRef || cellIndex)"
|
|
471
|
-
:class="calcTDBorder(cell.noBoarder)"
|
|
472
|
-
:span="calculateColSpan(cell)"
|
|
473
|
-
:style="Array.isArray(cell) ? {} : determineCellStyle(cell)"
|
|
474
|
-
>
|
|
475
|
-
<div v-if="isWidget" id="report_widget">
|
|
476
|
-
<!-- 插槽渲染111 -->
|
|
477
|
-
<template v-if="Array.isArray(cell)">
|
|
478
|
-
<!-- 处理 cell 是数组的情况 -->
|
|
479
|
-
<div v-for="(item, index) in cell" :key="index">
|
|
480
|
-
<XReportTrGroup
|
|
481
|
-
:env="env"
|
|
482
|
-
:columns="recalculateItem(item)"
|
|
483
|
-
:config-data="configData"
|
|
484
|
-
:config="config"
|
|
485
|
-
:display="true"
|
|
486
|
-
/>
|
|
487
|
-
</div>
|
|
488
|
-
</template>
|
|
489
|
-
<template v-else-if="cell.type === 'slot'">
|
|
490
|
-
<template
|
|
491
|
-
v-if="slotComponents.includes(cell.slotType)"
|
|
492
|
-
>
|
|
493
|
-
<component
|
|
494
|
-
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
495
|
-
:ref="(el) => setDynamicComponentRef(el, cell.slotRef || cellIndex)"
|
|
496
|
-
:service-name="cell.serviceName"
|
|
497
|
-
:server-name="cell.serviceName"
|
|
498
|
-
:query-params-name="cell.slotConfig"
|
|
499
|
-
:config-name="cell.slotConfig"
|
|
500
|
-
:count-visible="false"
|
|
501
|
-
:env="env"
|
|
502
|
-
v-on="getEventHandlers(cell)"
|
|
503
|
-
@mounted="(h) => onComponentMounted(h, cell, cellIndex)"
|
|
504
|
-
/>
|
|
505
|
-
</template>
|
|
506
|
-
</template>
|
|
507
|
-
</div>
|
|
508
|
-
<div v-else class="flexItem" :bordered="false" :body-style="flexItemBodyState">
|
|
509
|
-
<!-- 插槽渲染2222 -->
|
|
510
|
-
<template v-if="Array.isArray(cell)">
|
|
511
|
-
<!-- 处理 cell 是数组的情况 -->
|
|
512
|
-
<div v-for="(item, index) in cell" :key="index">
|
|
513
|
-
<XReportTrGroup
|
|
514
|
-
:server-name="serverName"
|
|
515
|
-
:env="env"
|
|
516
|
-
:columns="recalculateItem(item)"
|
|
517
|
-
:config-data="configData"
|
|
518
|
-
:config="config"
|
|
519
|
-
:display="true"
|
|
520
|
-
/>
|
|
521
|
-
</div>
|
|
522
|
-
</template>
|
|
523
|
-
<template v-else-if="cell.type === 'slot'">
|
|
524
|
-
<!-- 插槽渲染222 -->
|
|
525
|
-
<template
|
|
526
|
-
v-if="slotComponents.includes(cell.slotType)"
|
|
527
|
-
>
|
|
528
|
-
<component
|
|
529
|
-
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
530
|
-
:ref="(el) => setDynamicComponentRef(el, cell.slotRef || cellIndex)"
|
|
531
|
-
:service-name="cell.serviceName"
|
|
532
|
-
:server-name="cell.serviceName"
|
|
533
|
-
:query-params-name="cell.slotConfig"
|
|
534
|
-
:config-name="cell.slotConfig"
|
|
535
|
-
:count-visible="false"
|
|
536
|
-
:env="env"
|
|
537
|
-
v-on="getEventHandlers(cell)"
|
|
538
|
-
@mounted="(h) => onComponentMounted(h, cell, cellIndex)"
|
|
539
|
-
@list-click="listClick"
|
|
540
|
-
/>
|
|
541
|
-
</template>
|
|
542
|
-
</template>
|
|
543
|
-
</div>
|
|
544
|
-
</VanCol>
|
|
545
|
-
</template>
|
|
546
|
-
</VanRow>
|
|
547
|
-
</template>
|
|
548
|
-
|
|
549
|
-
<style scoped lang="less">
|
|
550
|
-
.inputsDiv {
|
|
551
|
-
display: flex;
|
|
552
|
-
justify-content: space-between;
|
|
553
|
-
|
|
554
|
-
.inputsDivItem {
|
|
555
|
-
display: flex;
|
|
556
|
-
align-items: center;
|
|
557
|
-
padding: 0 4px;
|
|
558
|
-
white-space: nowrap;
|
|
559
|
-
|
|
560
|
-
.inputsDivItemLabel {
|
|
561
|
-
padding: 0 4px;
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
.tdNoBorder {
|
|
567
|
-
border: none;
|
|
568
|
-
//border-left: 1px solid #000;
|
|
569
|
-
//border-right: 1px solid #000;
|
|
570
|
-
padding: 8px;
|
|
571
|
-
}
|
|
572
|
-
// 手机端显示边框线很奇怪 先去掉
|
|
573
|
-
.tdWithBorder {
|
|
574
|
-
border: none;
|
|
575
|
-
//border: 1px solid #000;
|
|
576
|
-
padding: 8px;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
.tdWithNoTopBorder {
|
|
580
|
-
border: none;
|
|
581
|
-
//border-top-style: none;
|
|
582
|
-
//border-left: 1px solid #000;
|
|
583
|
-
//border-right: 1px solid #000;
|
|
584
|
-
//border-bottom: 1px solid #000;
|
|
585
|
-
padding: 8px;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
.flexItem {
|
|
589
|
-
border-radius: 8px;
|
|
590
|
-
height: 100%;
|
|
591
|
-
}
|
|
592
|
-
</style>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, defineAsyncComponent, inject, nextTick, onBeforeMount, ref, watch } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
Col as VanCol,
|
|
5
|
+
Row as VanRow,
|
|
6
|
+
showDialog,
|
|
7
|
+
} from 'vant'
|
|
8
|
+
|
|
9
|
+
// import { getRealKeyData } from '@af-mobile-client-vue3/utils/util'
|
|
10
|
+
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
13
|
+
showImgInCell: false,
|
|
14
|
+
config: () => ({}),
|
|
15
|
+
serverName: '',
|
|
16
|
+
env: 'prod',
|
|
17
|
+
display: true,
|
|
18
|
+
useOssForImg: false,
|
|
19
|
+
noTopBorder: false,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// Emits
|
|
23
|
+
const emit = defineEmits<{
|
|
24
|
+
(e: 'update:configData', value: any): void
|
|
25
|
+
(e: 'change', value: any): void
|
|
26
|
+
(e: 'updateImg', value: any): void
|
|
27
|
+
(e: 'selectRow', value: any): void
|
|
28
|
+
(e: 'slotRendered'): void
|
|
29
|
+
(e: 'listClick', value: any): void
|
|
30
|
+
}>()
|
|
31
|
+
|
|
32
|
+
// import { getMicroData, getWindow, isMicroAppEnv, microDispatch } from '@af-mobile-client-vue3/utils/microAppUtils'
|
|
33
|
+
// import { isInAModal } from '@af-mobile-client-vue3/utils/microAppUtils'
|
|
34
|
+
|
|
35
|
+
// 定义isInAModal变量(原来从微应用工具中导入,现在手动定义)
|
|
36
|
+
const isInAModal = ref(false)
|
|
37
|
+
|
|
38
|
+
// 动态导入组件
|
|
39
|
+
const XFormTable = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/data/XCellList/index.vue'))
|
|
40
|
+
// const XAddNativeForm = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XAddNativeForm/XAddNativeForm.vue'))
|
|
41
|
+
// const XFormGroup = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XFormGroup/XFormGroup.vue'))
|
|
42
|
+
// const XTreePro = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTree/XTreePro.vue'))
|
|
43
|
+
// const XHisEditor = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XHisEditor/XHisEditor.vue'))
|
|
44
|
+
// const XTab = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTab/XTab.vue'))
|
|
45
|
+
// const XReport = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XReport/XReport.vue'))
|
|
46
|
+
// const XButtons = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XButtons/XButtons.vue'))
|
|
47
|
+
// const XLabelSelect = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XLabelSelect/XLabelSelect.vue'))
|
|
48
|
+
// const XConversation = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XConversation/XConversation.vue'))
|
|
49
|
+
// const XCheckList = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCheckList/XCheckList.vue'))
|
|
50
|
+
// const XCardSet = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCardSet/XCardSet.vue'))
|
|
51
|
+
// const XCollapse = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCollapse/XCollapse.vue'))
|
|
52
|
+
// const XHDescriptions = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XHDescriptions/XHDescriptions.vue'))
|
|
53
|
+
// const XSidebar = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XSidebar/XSidebar.vue'))
|
|
54
|
+
// const XList = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XList/XList.vue'))
|
|
55
|
+
// const XInput = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XInput/XInput.vue'))
|
|
56
|
+
// const XTimeLine = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XTimeline/XTimeline.vue'))
|
|
57
|
+
// const XRadio = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XRadio/XRadio.vue'))
|
|
58
|
+
// const XCalendar = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/common/XCalendar/XCalendar.vue'))
|
|
59
|
+
// const XTimeSelect = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XTimeSelect/XTimeSelect.vue'))
|
|
60
|
+
// const XCheckbox = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XCheckbox/XCheckbox.vue'))
|
|
61
|
+
// const XTitle = defineAsyncComponent(() => import('@af-mobile-client-vue3/components/his/XTitle/XTitle.vue'))
|
|
62
|
+
|
|
63
|
+
// 组件映射表 - 将kebab-case的组件名映射到实际组件对象
|
|
64
|
+
const componentMap: Record<string, any> = {
|
|
65
|
+
'x-form-table': XFormTable,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 可用的插槽组件列表
|
|
69
|
+
const slotComponents = [
|
|
70
|
+
'x-form-table',
|
|
71
|
+
'x-add-native-form',
|
|
72
|
+
'x-tree-pro',
|
|
73
|
+
'x-his-editor',
|
|
74
|
+
'x-tab',
|
|
75
|
+
'x-form-group',
|
|
76
|
+
'x-report',
|
|
77
|
+
'x-buttons',
|
|
78
|
+
'x-label-select',
|
|
79
|
+
'x-conversation',
|
|
80
|
+
'x-check-list',
|
|
81
|
+
'x-cardSet',
|
|
82
|
+
'x-collapse',
|
|
83
|
+
'x-h-descriptions',
|
|
84
|
+
'x-sidebar',
|
|
85
|
+
'x-list',
|
|
86
|
+
'x-input',
|
|
87
|
+
'x-time-line',
|
|
88
|
+
'x-radio',
|
|
89
|
+
'x-calendar',
|
|
90
|
+
'x-time-select',
|
|
91
|
+
'x-checkbox',
|
|
92
|
+
'x-title',
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
// 类型定义
|
|
96
|
+
interface ComponentRef {
|
|
97
|
+
init: (config: any) => void
|
|
98
|
+
refresh?: () => void
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface MixinData {
|
|
102
|
+
businessType?: string
|
|
103
|
+
files?: any[]
|
|
104
|
+
images?: any[]
|
|
105
|
+
[key: string]: any
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface InjectFunctions {
|
|
109
|
+
getMixinData: () => MixinData
|
|
110
|
+
getSelectedId: () => string | number
|
|
111
|
+
getSelectedData: () => any
|
|
112
|
+
getOutEnv: () => string
|
|
113
|
+
getConfigByName: (configName: string, serviceName: string, callback: (config: any) => void, isDev?: boolean) => void
|
|
114
|
+
runLogic: (config: any, selectedId?: any, serviceName?: string) => Promise<any>
|
|
115
|
+
getComponentByName: (name: string) => ComponentRef | undefined
|
|
116
|
+
registerComponent: (name: string, component: ComponentRef | undefined) => void
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface UploadConfig {
|
|
120
|
+
type: string
|
|
121
|
+
accept: string[]
|
|
122
|
+
resUploadStock: number
|
|
123
|
+
pathKey: string
|
|
124
|
+
resUploadMode?: string
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface GutterItem {
|
|
128
|
+
xs: number
|
|
129
|
+
sm: number
|
|
130
|
+
md: number
|
|
131
|
+
lg: number
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
type Gutter = [number, GutterItem]
|
|
135
|
+
|
|
136
|
+
// Props
|
|
137
|
+
interface Props {
|
|
138
|
+
columns: any[]
|
|
139
|
+
showImgInCell?: boolean
|
|
140
|
+
config?: Record<string, any>
|
|
141
|
+
serverName?: string
|
|
142
|
+
env?: string
|
|
143
|
+
configData: Record<string, any>
|
|
144
|
+
display?: boolean
|
|
145
|
+
useOssForImg?: boolean
|
|
146
|
+
noTopBorder?: boolean
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 注入依赖
|
|
150
|
+
const openDialog = inject('openDialog')
|
|
151
|
+
const emitEvent = inject('emitEvent')
|
|
152
|
+
const registerComponent = inject('registerComponent') as InjectFunctions['registerComponent']
|
|
153
|
+
const setColSpanByName = inject('setColSpanByName')
|
|
154
|
+
const setGlobalData = inject('setGlobalData')
|
|
155
|
+
const getGlobalData = inject('getGlobalData')
|
|
156
|
+
const getComponentByName = inject('getComponentByName') as InjectFunctions['getComponentByName']
|
|
157
|
+
const runLogicInject = inject('runLogic') as InjectFunctions['runLogic']
|
|
158
|
+
const getMixinData = inject('getMixinData', () => ({})) as InjectFunctions['getMixinData']
|
|
159
|
+
const getSelectedId = inject('getSelectedId', () => '') as InjectFunctions['getSelectedId']
|
|
160
|
+
const getSelectedData = inject('getSelectedData', () => ({})) as InjectFunctions['getSelectedData']
|
|
161
|
+
const getOutEnv = inject('getOutEnv', () => '') as InjectFunctions['getOutEnv']
|
|
162
|
+
const currUser = inject('currUser')
|
|
163
|
+
const isWidget = inject('isWidget', false)
|
|
164
|
+
const getConfigByNameInject = inject('getConfigByName', () => {}) as InjectFunctions['getConfigByName']
|
|
165
|
+
|
|
166
|
+
// 状态
|
|
167
|
+
const gutter = ref([8, 8])
|
|
168
|
+
const maxColSpan = ref(12)
|
|
169
|
+
const uploadConfig = ref<UploadConfig>({
|
|
170
|
+
type: 'image',
|
|
171
|
+
accept: ['image/jpeg', 'image/png', 'image/gif'],
|
|
172
|
+
resUploadStock: 9,
|
|
173
|
+
pathKey: 'cs',
|
|
174
|
+
resUploadMode: 'single',
|
|
175
|
+
})
|
|
176
|
+
const mixinData = ref<MixinData>({})
|
|
177
|
+
const flexItemBodyState = ref({
|
|
178
|
+
padding: '24px',
|
|
179
|
+
})
|
|
180
|
+
const slotRendered = ref(0)
|
|
181
|
+
|
|
182
|
+
// Refs
|
|
183
|
+
const trGroupRefs = ref(new Map())
|
|
184
|
+
const dynamicComponentRefs = ref(new Map<string, ComponentRef>())
|
|
185
|
+
|
|
186
|
+
// 计算属性
|
|
187
|
+
const allSlotSum = computed(() => {
|
|
188
|
+
let sum = 0
|
|
189
|
+
props.columns.forEach((item) => {
|
|
190
|
+
if (Array.isArray(item)) {
|
|
191
|
+
item.forEach((cell) => {
|
|
192
|
+
if (cell.type === 'slot') {
|
|
193
|
+
sum++
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
else if (item.type && item.type === 'slot') {
|
|
198
|
+
sum++
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
return sum
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
// Methods
|
|
205
|
+
function setTrGroupRef(el: any, key: string) {
|
|
206
|
+
if (el)
|
|
207
|
+
trGroupRefs.value.set(key, el)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function setDynamicComponentRef(el: any, key: string) {
|
|
211
|
+
if (el)
|
|
212
|
+
dynamicComponentRefs.value.set(key, el)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function listClick(data: any) {
|
|
216
|
+
emit('listClick', data)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function calculateColSpan(cell: any) {
|
|
220
|
+
return Array.isArray(cell)
|
|
221
|
+
? cell[0][0]?.colSpan * 2
|
|
222
|
+
: (cell?.colSpan ?? cell?.def?.colSpan ?? 1) * 2
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function calcTDBorder(cellNoBorder = false) {
|
|
226
|
+
if (cellNoBorder)
|
|
227
|
+
return 'tdNoBorder'
|
|
228
|
+
|
|
229
|
+
return props.noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function determineCellStyle(cell: any) {
|
|
233
|
+
if (!cell.style)
|
|
234
|
+
return {}
|
|
235
|
+
return cell.style
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function getEventHandlers(cell: any) {
|
|
239
|
+
const handlers: Record<string, Function> = {}
|
|
240
|
+
if (!cell?.events || cell?.events?.length === 0)
|
|
241
|
+
return handlers
|
|
242
|
+
|
|
243
|
+
cell.events.forEach((event: any) => {
|
|
244
|
+
handlers[event.type] = async (...args: any[]) => {
|
|
245
|
+
console.info('Event handled:', event.type, args)
|
|
246
|
+
let func = event.customFunction
|
|
247
|
+
if (func && func.startsWith('function'))
|
|
248
|
+
func = func.replace('function', 'async function')
|
|
249
|
+
|
|
250
|
+
const result = await executeStrFunctionByContext(null, func, args)
|
|
251
|
+
if (result instanceof Promise) {
|
|
252
|
+
result.then((res) => {
|
|
253
|
+
if (!res)
|
|
254
|
+
return
|
|
255
|
+
let messageType = 'success'
|
|
256
|
+
|
|
257
|
+
if (res?.name) {
|
|
258
|
+
const waitRefreshRef = getComponentByName?.(res.name)
|
|
259
|
+
if (waitRefreshRef)
|
|
260
|
+
waitRefreshRef.refresh()
|
|
261
|
+
else
|
|
262
|
+
console.warn(`未找到组件${res.name}无法刷新`)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (res?.messageType)
|
|
266
|
+
messageType = res.messageType
|
|
267
|
+
|
|
268
|
+
if (res?.message) {
|
|
269
|
+
showDialog({
|
|
270
|
+
message: res.message,
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
return handlers
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getComponentName(queryParamsName: string, serviceName: string, componentName: string) {
|
|
282
|
+
// 从映射表中获取组件,如果没有则返回原始组件名
|
|
283
|
+
return componentMap[componentName] || componentName
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function onComponentMounted(h: any, cell: any, cellIndex: number) {
|
|
287
|
+
slotRendered.value += 1
|
|
288
|
+
if (slotRendered.value >= allSlotSum.value)
|
|
289
|
+
emit('slotRendered')
|
|
290
|
+
|
|
291
|
+
if (getMixinData && getMixinData())
|
|
292
|
+
mixinData.value = getMixinData()
|
|
293
|
+
|
|
294
|
+
if (cell.slotRef)
|
|
295
|
+
registerComponent?.(cell.slotRef, dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`))
|
|
296
|
+
|
|
297
|
+
console.log(`插槽组件已经初始化 slotType ${cell.slotType},ref= dynamicComponent_${cell.slotRef || cellIndex} , serviceName = ${cell.serviceName}`)
|
|
298
|
+
|
|
299
|
+
const shouldInit = cell.shouldInit ?? true
|
|
300
|
+
if (shouldInit) {
|
|
301
|
+
if (cell.slotType === 'x-add-native-form')
|
|
302
|
+
initAddNativeForm(cell, cellIndex)
|
|
303
|
+
else if (cell.slotType === 'x-form-group')
|
|
304
|
+
initFormGroup(cell, cellIndex)
|
|
305
|
+
else if (cell.slotType === 'x-buttons')
|
|
306
|
+
initButtons(cell, cellIndex)
|
|
307
|
+
else if (cell.slotType === 'x-label-select')
|
|
308
|
+
initLabelSelect(cell, cellIndex)
|
|
309
|
+
else if (cell.slotType === 'x-report')
|
|
310
|
+
initReport(cell, cellIndex)
|
|
311
|
+
else if (cell.slotType === 'x-conversation')
|
|
312
|
+
initConversation(cell, cellIndex)
|
|
313
|
+
else if (cell.slotType === 'x-check-list')
|
|
314
|
+
initCheckList(cell, cellIndex)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 初始化各种组件的方法
|
|
319
|
+
async function initAddNativeForm(cell: any, cellIndex: number) {
|
|
320
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, async (res: any) => {
|
|
321
|
+
let param = { ...mixinData.value }
|
|
322
|
+
let selectedId
|
|
323
|
+
if (res.paramLogicName) {
|
|
324
|
+
if (getSelectedId) {
|
|
325
|
+
selectedId = getSelectedId()
|
|
326
|
+
if (typeof selectedId !== 'object')
|
|
327
|
+
selectedId = { selectedId }
|
|
328
|
+
}
|
|
329
|
+
param = Object.assign(param, await runLogicInject(res.paramLogicName, selectedId, cell.serviceName))
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
333
|
+
if (componentRef) {
|
|
334
|
+
componentRef.init({
|
|
335
|
+
serviceName: cell.serviceName,
|
|
336
|
+
configName: cell.slotConfig,
|
|
337
|
+
formItems: res.formJson,
|
|
338
|
+
showSubmitBtn: !isInAModal.value,
|
|
339
|
+
businessType: param.businessType || '新增',
|
|
340
|
+
layout: res.xAddFormLayout,
|
|
341
|
+
primaryKey: res.primaryKey,
|
|
342
|
+
...res,
|
|
343
|
+
fixedAddForm: param,
|
|
344
|
+
modifyModelData: {
|
|
345
|
+
files: param.files,
|
|
346
|
+
images: param.images,
|
|
347
|
+
},
|
|
348
|
+
})
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async function initFormGroup(cell: any, cellIndex: number) {
|
|
354
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
355
|
+
const param = { ...mixinData.value }
|
|
356
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
357
|
+
if (componentRef) {
|
|
358
|
+
componentRef.init({
|
|
359
|
+
...res,
|
|
360
|
+
serviceName: cell.serviceName,
|
|
361
|
+
showSubmitBtn: !isInAModal.value,
|
|
362
|
+
businessType: param.businessType || '新增',
|
|
363
|
+
modifyModelData: param,
|
|
364
|
+
showLeftTab: true,
|
|
365
|
+
})
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async function initButtons(cell: any, cellIndex: number) {
|
|
371
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
372
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
373
|
+
if (componentRef) {
|
|
374
|
+
componentRef.init({
|
|
375
|
+
...res,
|
|
376
|
+
serviceName: cell.serviceName,
|
|
377
|
+
})
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async function initLabelSelect(cell: any, cellIndex: number) {
|
|
383
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
384
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
385
|
+
if (componentRef) {
|
|
386
|
+
componentRef.init({
|
|
387
|
+
...res,
|
|
388
|
+
serviceName: cell.serviceName,
|
|
389
|
+
})
|
|
390
|
+
}
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async function initReport(cell: any, cellIndex: number) {
|
|
395
|
+
const param = { ...mixinData.value }
|
|
396
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
397
|
+
if (componentRef)
|
|
398
|
+
componentRef.init(param)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
async function initConversation(cell: any, cellIndex: number) {
|
|
402
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
403
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
404
|
+
if (componentRef) {
|
|
405
|
+
componentRef.init({
|
|
406
|
+
serviceName: cell.serviceName,
|
|
407
|
+
...res,
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async function initCheckList(cell: any, cellIndex: number) {
|
|
414
|
+
getConfigByNameInject(cell.slotConfig, cell.serviceName, (res: any) => {
|
|
415
|
+
const componentRef = dynamicComponentRefs.value.get(`dynamicComponent_${cell.slotRef || cellIndex}`)
|
|
416
|
+
if (componentRef) {
|
|
417
|
+
componentRef.init({
|
|
418
|
+
serviceName: cell.serviceName,
|
|
419
|
+
...res,
|
|
420
|
+
})
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function recalculateItem(item: any[]) {
|
|
426
|
+
const totalColSpan = item.reduce((sum, cell) => {
|
|
427
|
+
return sum + (cell._isManualColSpan ? 0 : (cell.colSpan || 1))
|
|
428
|
+
}, 0)
|
|
429
|
+
return item.map((cell) => {
|
|
430
|
+
if (cell._isManualColSpan)
|
|
431
|
+
return cell
|
|
432
|
+
const newColSpan = Math.round((cell.colSpan || 1) / totalColSpan * 12)
|
|
433
|
+
return {
|
|
434
|
+
...cell,
|
|
435
|
+
colSpan: newColSpan,
|
|
436
|
+
_isAutoCalculated: true,
|
|
437
|
+
}
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// 生命周期钩子
|
|
442
|
+
onBeforeMount(() => {
|
|
443
|
+
if (props.useOssForImg)
|
|
444
|
+
uploadConfig.value.resUploadMode = 'oss'
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
// 监听器
|
|
448
|
+
watch(() => props.columns, (newVal) => {
|
|
449
|
+
console.log('columns变化:', JSON.parse(JSON.stringify(newVal)))
|
|
450
|
+
nextTick(() => {
|
|
451
|
+
// Vue 3 不需要$forceUpdate
|
|
452
|
+
})
|
|
453
|
+
}, { deep: true, immediate: true })
|
|
454
|
+
|
|
455
|
+
// 暴露方法
|
|
456
|
+
defineExpose({
|
|
457
|
+
// getWindow,
|
|
458
|
+
// isMicroAppEnv,
|
|
459
|
+
// microDispatch,
|
|
460
|
+
// getMicroData,
|
|
461
|
+
// getRealKeyData
|
|
462
|
+
})
|
|
463
|
+
</script>
|
|
464
|
+
|
|
465
|
+
<template>
|
|
466
|
+
<VanRow type="flex" :gutter="gutter" :style="isWidget ? { margin: '0px' } : { 'margin-bottom': '.5rem' }">
|
|
467
|
+
<template v-for="(cell, cellIndex) in columns" :key="cellIndex">
|
|
468
|
+
<VanCol
|
|
469
|
+
v-if="Array.isArray(cell) || !cell?.dontShowRow"
|
|
470
|
+
:ref="(el) => setTrGroupRef(el, cell.slotRef || cellIndex)"
|
|
471
|
+
:class="calcTDBorder(cell.noBoarder)"
|
|
472
|
+
:span="calculateColSpan(cell)"
|
|
473
|
+
:style="Array.isArray(cell) ? {} : determineCellStyle(cell)"
|
|
474
|
+
>
|
|
475
|
+
<div v-if="isWidget" id="report_widget">
|
|
476
|
+
<!-- 插槽渲染111 -->
|
|
477
|
+
<template v-if="Array.isArray(cell)">
|
|
478
|
+
<!-- 处理 cell 是数组的情况 -->
|
|
479
|
+
<div v-for="(item, index) in cell" :key="index">
|
|
480
|
+
<XReportTrGroup
|
|
481
|
+
:env="env"
|
|
482
|
+
:columns="recalculateItem(item)"
|
|
483
|
+
:config-data="configData"
|
|
484
|
+
:config="config"
|
|
485
|
+
:display="true"
|
|
486
|
+
/>
|
|
487
|
+
</div>
|
|
488
|
+
</template>
|
|
489
|
+
<template v-else-if="cell.type === 'slot'">
|
|
490
|
+
<template
|
|
491
|
+
v-if="slotComponents.includes(cell.slotType)"
|
|
492
|
+
>
|
|
493
|
+
<component
|
|
494
|
+
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
495
|
+
:ref="(el) => setDynamicComponentRef(el, cell.slotRef || cellIndex)"
|
|
496
|
+
:service-name="cell.serviceName"
|
|
497
|
+
:server-name="cell.serviceName"
|
|
498
|
+
:query-params-name="cell.slotConfig"
|
|
499
|
+
:config-name="cell.slotConfig"
|
|
500
|
+
:count-visible="false"
|
|
501
|
+
:env="env"
|
|
502
|
+
v-on="getEventHandlers(cell)"
|
|
503
|
+
@mounted="(h) => onComponentMounted(h, cell, cellIndex)"
|
|
504
|
+
/>
|
|
505
|
+
</template>
|
|
506
|
+
</template>
|
|
507
|
+
</div>
|
|
508
|
+
<div v-else class="flexItem" :bordered="false" :body-style="flexItemBodyState">
|
|
509
|
+
<!-- 插槽渲染2222 -->
|
|
510
|
+
<template v-if="Array.isArray(cell)">
|
|
511
|
+
<!-- 处理 cell 是数组的情况 -->
|
|
512
|
+
<div v-for="(item, index) in cell" :key="index">
|
|
513
|
+
<XReportTrGroup
|
|
514
|
+
:server-name="serverName"
|
|
515
|
+
:env="env"
|
|
516
|
+
:columns="recalculateItem(item)"
|
|
517
|
+
:config-data="configData"
|
|
518
|
+
:config="config"
|
|
519
|
+
:display="true"
|
|
520
|
+
/>
|
|
521
|
+
</div>
|
|
522
|
+
</template>
|
|
523
|
+
<template v-else-if="cell.type === 'slot'">
|
|
524
|
+
<!-- 插槽渲染222 -->
|
|
525
|
+
<template
|
|
526
|
+
v-if="slotComponents.includes(cell.slotType)"
|
|
527
|
+
>
|
|
528
|
+
<component
|
|
529
|
+
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
530
|
+
:ref="(el) => setDynamicComponentRef(el, cell.slotRef || cellIndex)"
|
|
531
|
+
:service-name="cell.serviceName"
|
|
532
|
+
:server-name="cell.serviceName"
|
|
533
|
+
:query-params-name="cell.slotConfig"
|
|
534
|
+
:config-name="cell.slotConfig"
|
|
535
|
+
:count-visible="false"
|
|
536
|
+
:env="env"
|
|
537
|
+
v-on="getEventHandlers(cell)"
|
|
538
|
+
@mounted="(h) => onComponentMounted(h, cell, cellIndex)"
|
|
539
|
+
@list-click="listClick"
|
|
540
|
+
/>
|
|
541
|
+
</template>
|
|
542
|
+
</template>
|
|
543
|
+
</div>
|
|
544
|
+
</VanCol>
|
|
545
|
+
</template>
|
|
546
|
+
</VanRow>
|
|
547
|
+
</template>
|
|
548
|
+
|
|
549
|
+
<style scoped lang="less">
|
|
550
|
+
.inputsDiv {
|
|
551
|
+
display: flex;
|
|
552
|
+
justify-content: space-between;
|
|
553
|
+
|
|
554
|
+
.inputsDivItem {
|
|
555
|
+
display: flex;
|
|
556
|
+
align-items: center;
|
|
557
|
+
padding: 0 4px;
|
|
558
|
+
white-space: nowrap;
|
|
559
|
+
|
|
560
|
+
.inputsDivItemLabel {
|
|
561
|
+
padding: 0 4px;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.tdNoBorder {
|
|
567
|
+
border: none;
|
|
568
|
+
//border-left: 1px solid #000;
|
|
569
|
+
//border-right: 1px solid #000;
|
|
570
|
+
padding: 8px;
|
|
571
|
+
}
|
|
572
|
+
// 手机端显示边框线很奇怪 先去掉
|
|
573
|
+
.tdWithBorder {
|
|
574
|
+
border: none;
|
|
575
|
+
//border: 1px solid #000;
|
|
576
|
+
padding: 8px;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.tdWithNoTopBorder {
|
|
580
|
+
border: none;
|
|
581
|
+
//border-top-style: none;
|
|
582
|
+
//border-left: 1px solid #000;
|
|
583
|
+
//border-right: 1px solid #000;
|
|
584
|
+
//border-bottom: 1px solid #000;
|
|
585
|
+
padding: 8px;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.flexItem {
|
|
589
|
+
border-radius: 8px;
|
|
590
|
+
height: 100%;
|
|
591
|
+
}
|
|
592
|
+
</style>
|