vue2-client 1.14.68 → 1.14.69
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/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +0 -1
- package/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +1 -2
- package/package.json +1 -1
- package/src/base-client/components/common/XReport/XReport.vue +72 -1
- package/src/base-client/components/common/XReport/XReportDemo.vue +1 -2
- package/src/base-client/components/common/XReport/XReportTrGroup.vue +218 -29
- package/src/base-client/components/common/XReport/index.md +59 -0
- package/src/base-client/components/common/XUploadFilesView/index.vue +485 -485
- package/src/base-client/components/his/XTextCard/XTextCard.vue +207 -207
- package/src/base-client/components/his/XTreeRows/TreeNode.vue +100 -100
- package/src/base-client/components/his/XTreeRows/XTreeRows.vue +197 -197
- package/src/base-client/components/his/threeTestOrders/editor.vue +111 -111
- package/src/pages/WorkflowDetail/WorkFlowDemo.vue +1 -1
- package/src/pages/WorkflowDetail/WorkflowPageDetail/LeaveMessage.vue +388 -388
- package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandle.vue +1 -1
- package/src/router/async/router.map.js +2 -2
- package/.history/public/his/editor/editor_20250606134713.html +0 -51
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527173925.vue +0 -509
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174316.vue +0 -524
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174419.vue +0 -524
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174422.vue +0 -524
- package/.history/src/base-client/components/common/XForm/XFormItem_20250508134122.vue +0 -1320
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171604.vue +0 -1332
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171613.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171703.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171720.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527174327.vue +0 -1339
- package/.history/src/base-client/components/his/XList/XList_20250609135848.vue +0 -173
- package/.history/src/base-client/components/his/XList/XList_20250609141026.vue +0 -222
- package/.history/src/base-client/components/his/XList/XList_20250609141035.vue +0 -229
- package/.history/src/base-client/components/his/XList/XList_20250609141103.vue +0 -229
- package/.history/src/base-client/components/his/XList/XList_20250609141105.vue +0 -229
- package/.history/src/base-client/components/his/XList/XList_20250609141334.vue +0 -241
- package/.history/src/base-client/components/his/XList/XList_20250609141404.vue +0 -241
- package/.history/src/base-client/components/his/XList/XList_20250609141406.vue +0 -241
- package/.history/src/base-client/components/his/XList/XList_20250609141801.vue +0 -245
- package/.history/src/base-client/components/his/XList/XList_20250609142033.vue +0 -245
- package/.history/src/base-client/components/his/XList/XList_20250609142038.vue +0 -245
- package/.history/src/base-client/components/his/XList/XList_20250609142435.vue +0 -255
- package/.history/src/base-client/components/his/XList/XList_20250609142503.vue +0 -255
- package/.history/src/base-client/components/his/XList/XList_20250609142504.vue +0 -255
- package/.history/src/base-client/components/his/XList/XList_20250609143012.vue +0 -270
- package/.history/src/base-client/components/his/XList/XList_20250609143044.vue +0 -270
- package/.history/src/base-client/components/his/XList/XList_20250609143046.vue +0 -270
- package/.history/src/base-client/components/his/XList/XList_20250609143210.vue +0 -270
- package/.history/src/base-client/components/his/XList/XList_20250609144339.vue +0 -294
- package/.history/src/base-client/components/his/XList/XList_20250609144410.vue +0 -294
- package/.history/src/base-client/components/his/XList/XList_20250609144412.vue +0 -294
- package/.history/src/base-client/components/his/XList/XList_20250609144647.vue +0 -303
- package/.history/src/base-client/components/his/XList/XList_20250609144716.vue +0 -303
- package/.history/src/base-client/components/his/XList/XList_20250609144729.vue +0 -303
- package/.history/src/base-client/components/his/XList/XList_20250609151232.vue +0 -288
- package/.history/src/base-client/components/his/XList/XList_20250609151247.vue +0 -288
- package/.history/src/base-client/components/his/XList/XList_20250609151252.vue +0 -288
- package/.history/src/base-client/components/his/XList/XList_20250609161220.vue +0 -317
- package/.history/src/base-client/components/his/XList/XList_20250609161258.vue +0 -306
- package/.history/src/base-client/components/his/XList/XList_20250609161319.vue +0 -306
- package/.history/src/base-client/components/his/XList/XList_20250609161320.vue +0 -306
- package/Users/objecrt/af-vue2-client/src/base-client/components/his/XShiftSchedule/XShiftSchedule.vue +0 -36
- package/src/base-client/components/TreeList/TreeList.vue +0 -91
- package/src/base-client/components/TreeList/TreeNode.vue +0 -81
- package/src/base-client/components/common/XCardSet/XTiltle.vue +0 -191
package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
- ENV 对应 一个 org.json.JSONObject {tenantName:"租户名称",orgName:"分公司名称",applicationName:"应用名称",dbType:"数据库类型"}
|
|
12
12
|
- logic 对应 LogicService 类,其中有方法
|
|
13
13
|
* logic.run(logicName,param) 执行logic / logicName 执行的业务逻辑名称,param 参数 返回 org.json.JSONObject
|
|
14
|
-
* logic.remoteRun("服务名","logicName", "param")
|
|
15
14
|
- sql 对应 [SqlService]() 类,其中有方法
|
|
16
15
|
* sql.query(sql别名 string,sql参数 string) 执行已经注册的sql 返回 org.json.JSONArray
|
|
17
16
|
* sql.query(sql别名 string,sql参数 string,页数 int,每页行数 int) 执行已经注册的sql 返回 org.json.JSONArray
|
|
@@ -60,8 +60,7 @@ this.openDialog('xxx', 5, {}, {}, {})
|
|
|
60
60
|
afterDelete( res (删除接口返回数据)) 删除后触发
|
|
61
61
|
action(record (当前记录), id (当前记录主键), actionType (操作类型)) 操作按钮触发
|
|
62
62
|
- expandedGrid:"栅格名"
|
|
63
|
-
|
|
64
|
-
- "pageMaxSize": (int) num,
|
|
63
|
+
|
|
65
64
|
# x-report 插槽 使用说明
|
|
66
65
|
|
|
67
66
|
- init(configName,configData) 配置名称 / 报表数据
|
package/package.json
CHANGED
|
@@ -247,7 +247,17 @@ export default {
|
|
|
247
247
|
this.$emit('updateImg', data)
|
|
248
248
|
},
|
|
249
249
|
// 导出数据,某些外部需要统一控制数据的变动
|
|
250
|
-
exportData () {
|
|
250
|
+
exportData (skipValidation = false) {
|
|
251
|
+
// 如果不跳过校验,先进行必填字段校验
|
|
252
|
+
if (!skipValidation) {
|
|
253
|
+
const validation = this.validateRequiredFields()
|
|
254
|
+
if (!validation.isValid) {
|
|
255
|
+
const errorMessages = validation.errors.map(error => error.message).join(';')
|
|
256
|
+
console.warn(`数据导出警告:存在必填字段未填写 - ${errorMessages}`)
|
|
257
|
+
// 在导出时只警告,不阻止导出
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
251
261
|
// 获取当前修改后的数据
|
|
252
262
|
let tempData
|
|
253
263
|
if (this.activeConfig === undefined || this.activeConfig === null) {
|
|
@@ -296,8 +306,68 @@ export default {
|
|
|
296
306
|
}
|
|
297
307
|
}
|
|
298
308
|
},
|
|
309
|
+
// 验证必填字段
|
|
310
|
+
validateRequiredFields () {
|
|
311
|
+
const errors = []
|
|
312
|
+
const config = this.type === 'display' ? this.originalConfig : this.activeConfig
|
|
313
|
+
|
|
314
|
+
if (!config || !config.columns) {
|
|
315
|
+
return { isValid: true, errors: [] }
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 遍历所有配置项检查必填字段
|
|
319
|
+
config.columns.forEach((row, rowIndex) => {
|
|
320
|
+
row.forEach((cell, cellIndex) => {
|
|
321
|
+
if (cell.required && cell.dataIndex) {
|
|
322
|
+
let value
|
|
323
|
+
if (cell.dataIndex.indexOf('@@@') !== -1) {
|
|
324
|
+
// 处理深层嵌套数据
|
|
325
|
+
// const arr = cell.dataIndex.split('@@@')
|
|
326
|
+
value = config.tempData && config.tempData[cell.dataIndex]
|
|
327
|
+
} else {
|
|
328
|
+
value = config.data[cell.dataIndex]
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 检查值是否为空
|
|
332
|
+
if (!value || (typeof value === 'string' && value.trim() === '')) {
|
|
333
|
+
const message = cell.requiredMessage || this.getDefaultRequiredMessage(cell.type)
|
|
334
|
+
errors.push({
|
|
335
|
+
dataIndex: cell.dataIndex,
|
|
336
|
+
message: message,
|
|
337
|
+
rowIndex: rowIndex,
|
|
338
|
+
cellIndex: cellIndex,
|
|
339
|
+
type: cell.type
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
isValid: errors.length === 0,
|
|
348
|
+
errors: errors
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
// 获取默认的必填提示信息
|
|
352
|
+
getDefaultRequiredMessage (fieldType) {
|
|
353
|
+
const defaultMessages = {
|
|
354
|
+
datePicker: '请选择日期',
|
|
355
|
+
timePicker: '请选择日期时间',
|
|
356
|
+
input: '请填写此字段',
|
|
357
|
+
inputs: '请填写此字段'
|
|
358
|
+
}
|
|
359
|
+
return defaultMessages[fieldType] || '此字段为必填项'
|
|
360
|
+
},
|
|
299
361
|
// 正常的保存方法,当前修改内容会直接全部导出到外部
|
|
300
362
|
saveConfig () {
|
|
363
|
+
// 先进行必填字段校验
|
|
364
|
+
const validation = this.validateRequiredFields()
|
|
365
|
+
if (!validation.isValid) {
|
|
366
|
+
const errorMessages = validation.errors.map(error => error.message).join(';')
|
|
367
|
+
this.$message.error(`保存失败:${errorMessages}`)
|
|
368
|
+
return false
|
|
369
|
+
}
|
|
370
|
+
|
|
301
371
|
if (this.activeConfig === undefined || this.activeConfig === null) {
|
|
302
372
|
return this.originalConfig.data
|
|
303
373
|
} else {
|
|
@@ -306,6 +376,7 @@ export default {
|
|
|
306
376
|
this.changeDeepObject(this.activeConfig.data, key, this.activeConfig.tempData[key])
|
|
307
377
|
})
|
|
308
378
|
this.$emit('saveConfig', this.$refs.XReportDesign.activatedConfig)
|
|
379
|
+
return true
|
|
309
380
|
}
|
|
310
381
|
},
|
|
311
382
|
// 通过@@@分割临时变量,找到对应的key,并修改它的值
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
@updateImg="updateImg"
|
|
5
5
|
ref="main"
|
|
6
6
|
:use-oss-for-img="false"
|
|
7
|
-
config-name="
|
|
7
|
+
config-name="用户户内通气点火工艺流程"
|
|
8
8
|
server-name="af-system"
|
|
9
|
-
:config-data="{aaa:'data:image/png;base64,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115LdHotwujfv7+JFURlIIGUgLUeH3/8sfd7qH306dPHdO+KykECSQjWgyMNGLy9du1a7/exbfT0009X71WFIYEkxFoP37Z2wHocc8wxUb9+/VSfqDAkkARgPWhnp3CXxHpQwGP//f7775/e4kQqSCAJoO7x1ltvRR9++KH3ewjODzzwQBOca+dg5SGBeGKr5s8//7x35gqwHoMGDTJ7z0XlIYF4QLvHmjVrTGD+ySefeL/PWg8EwgwwUXlIIB7QsctmqBdffNF7xyBgPQYMGGB2DorKRAIpAtZjyZIl0dNPP212Dfpircd5550Xde7cOcUVijSRQIpAYE6r+TvvvJPofTb2OOGEE1JamcgCCcSBPXl2woQJXhuWLFgP9nyQ2pX1qGwkkH8B12rZsmXRU089lailBEjnXnDBBdGxxx6b0upEVkgg/8L69evNEdWTJk1KFJhTKWcYw4UXXqjMVREovDLwIs9oR+E2IGs1Z86caNy4caZr1xc2RO2+++7R8OHD1ZRYBCw03Qg8gDgHnfvFURh5G4MkgWwFHxxTSp588snErhU9VwxjIPZQS3txEAj3mfuNO8qkSYSCBWZrQKgzQVoigbQAcXDwDb1WSV0rAnN6rbAenPkh3HCvub+4sl988YU5T6Wmpua/Oy7pPEAoCIYZxjx8QiCBtIAP7P33348eeeSRaPHixYnei2tAYE5Luzp2i4NASKEztaXlvxmfRLcC8dvhhx9upr8ccsghptiKaJhlnOX9lUD+hrjj008/jcaOHRt9/fXXid7LB8YHedlll5kYRPjBPd+WlbaTXGgKZVsBYuH+nn322eY0riz31CiLFf0v7qDe8e677yZ6L4E5/vK1116rUaIJsS6WCysWWn2mT5+eedarzQvEDn977rnnEscdgGtFOwkvtbP7Y4fiUWvygQdRbW2t2ZmZJW1eIPi9r7/+evTwww8njjsIHGklueaaazRnNyEIhDNVkgy9YCJ+1pmtNi0QG5Tfd999iRoRwWat8Il9xoiKf2Izhr5gQXbbbbfM6yRtViCI44MPPojuv//+RIOnLQSOzMEdOHBgLvL1lYbdY+MLDySC86zTvW1SILZSfvfddycOygFBkM698sorjV8skoNAigXoLbGHDmVNmxMIHboUpkjn0sKeNCi3J9PedNNNaidpBaVYEAqGWdOmBGKPSnvwwQej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'}"
|
|
10
9
|
:show-img-in-cell="true"
|
|
11
10
|
:edit-mode="false"
|
|
12
11
|
:show-save-button="false"
|
|
@@ -37,6 +37,22 @@
|
|
|
37
37
|
{{ deserializeFunctionAndRun(cell.customFunction, configData[cell.dataIndex], config) }}
|
|
38
38
|
</template>
|
|
39
39
|
</template>
|
|
40
|
+
<template v-else-if="cell.type === 'datePicker'">
|
|
41
|
+
<template v-if="cell.customFunction === undefined">
|
|
42
|
+
{{ getDeepObject(configData, cell.dataIndex) }}
|
|
43
|
+
</template>
|
|
44
|
+
<template v-else>
|
|
45
|
+
{{ deserializeFunctionAndRun(cell.customFunction, configData[cell.dataIndex], config) }}
|
|
46
|
+
</template>
|
|
47
|
+
</template>
|
|
48
|
+
<template v-else-if="cell.type === 'timePicker'">
|
|
49
|
+
<template v-if="cell.customFunction === undefined">
|
|
50
|
+
{{ getDeepObject(configData, cell.dataIndex) }}
|
|
51
|
+
</template>
|
|
52
|
+
<template v-else>
|
|
53
|
+
{{ deserializeFunctionAndRun(cell.customFunction, configData[cell.dataIndex], config) }}
|
|
54
|
+
</template>
|
|
55
|
+
</template>
|
|
40
56
|
<template v-else-if="cell.type === 'inputs'">
|
|
41
57
|
<template v-if="cell.customFunction === undefined">
|
|
42
58
|
{{ showSubRowValue(cell) }}
|
|
@@ -131,6 +147,26 @@
|
|
|
131
147
|
}}
|
|
132
148
|
</template>
|
|
133
149
|
</template>
|
|
150
|
+
<template v-else-if="cell.type === 'datePicker'">
|
|
151
|
+
<template v-if="cell.customFunction === undefined">
|
|
152
|
+
{{ getDeepObject(configData.arr[inputColumnsDefinitionIndex], cell.dataIndex) }}
|
|
153
|
+
</template>
|
|
154
|
+
<template v-else>
|
|
155
|
+
{{
|
|
156
|
+
deserializeFunctionAndRun(cell.customFunction, configData.arr[inputColumnsDefinitionIndex][cell.dataIndex], config)
|
|
157
|
+
}}
|
|
158
|
+
</template>
|
|
159
|
+
</template>
|
|
160
|
+
<template v-else-if="cell.type === 'timePicker'">
|
|
161
|
+
<template v-if="cell.customFunction === undefined">
|
|
162
|
+
{{ getDeepObject(configData.arr[inputColumnsDefinitionIndex], cell.dataIndex) }}
|
|
163
|
+
</template>
|
|
164
|
+
<template v-else>
|
|
165
|
+
{{
|
|
166
|
+
deserializeFunctionAndRun(cell.customFunction, configData.arr[inputColumnsDefinitionIndex][cell.dataIndex], config)
|
|
167
|
+
}}
|
|
168
|
+
</template>
|
|
169
|
+
</template>
|
|
134
170
|
<template v-else-if="cell.type === 'inputs'">
|
|
135
171
|
<template v-if="cell.customFunction === undefined">
|
|
136
172
|
{{ getDeepObject(configData.arr[inputColumnsDefinitionIndex], cell.dataIndex) }}
|
|
@@ -178,39 +214,61 @@
|
|
|
178
214
|
>{{ cell.text || '确认' }}
|
|
179
215
|
</a-button>
|
|
180
216
|
</template>
|
|
217
|
+
<template v-else-if="cell.type === 'datePicker'">
|
|
218
|
+
<div>
|
|
219
|
+
<a-date-picker
|
|
220
|
+
@change="handleDatePickerChange($event, cell.dataIndex, cell)"
|
|
221
|
+
:value="formatDateValue(configData[cell.dataIndex])"
|
|
222
|
+
format="YYYY-MM-DD"
|
|
223
|
+
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
224
|
+
:disabled="cell.inputReadOnly===true"
|
|
225
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData[cell.dataIndex]}"/>
|
|
226
|
+
<div v-if="isFieldRequired(cell) && !configData[cell.dataIndex]" class="required-message">
|
|
227
|
+
{{ getRequiredMessage(cell, 'datePicker') }}
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</template>
|
|
231
|
+
<template v-else-if="cell.type === 'timePicker'">
|
|
232
|
+
<div>
|
|
233
|
+
<a-date-picker
|
|
234
|
+
@change="handleTimePickerChange($event, cell.dataIndex, cell)"
|
|
235
|
+
:value="formatDateValue(configData[cell.dataIndex])"
|
|
236
|
+
format="YYYY-MM-DD HH:mm:ss"
|
|
237
|
+
show-time
|
|
238
|
+
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
239
|
+
:disabled="cell.inputReadOnly===true"
|
|
240
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData[cell.dataIndex]}"/>
|
|
241
|
+
<div v-if="isFieldRequired(cell) && !configData[cell.dataIndex]" class="required-message">
|
|
242
|
+
{{ getRequiredMessage(cell, 'timePicker') }}
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</template>
|
|
181
246
|
<template v-else-if="cell.type === 'signature'">
|
|
182
247
|
<img :src="configData[cell.dataIndex]" alt="签名加载失败" style="max-height: 2rem">
|
|
183
248
|
<a-button v-if="!configData[cell.dataIndex]" type="dashed" >需要在手机端签名 </a-button>
|
|
184
249
|
</template>
|
|
185
250
|
<template v-else-if="cell.type === 'input'">
|
|
186
|
-
<
|
|
251
|
+
<div>
|
|
187
252
|
<template v-if="cell.dataIndex.indexOf('@@@') !== -1">
|
|
188
253
|
<a-input
|
|
189
|
-
@change="handleInputDeepChange($event, cell.dataIndex)"
|
|
254
|
+
@change="handleInputDeepChange($event, cell.dataIndex, cell)"
|
|
190
255
|
v-model="config.tempData[cell.dataIndex]"
|
|
191
256
|
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
192
|
-
:disabled="true"
|
|
257
|
+
:disabled="cell.inputReadOnly === true"
|
|
258
|
+
:class="{'required-field-error': isFieldRequired(cell) && !config.tempData[cell.dataIndex]}"/>
|
|
193
259
|
</template>
|
|
194
260
|
<template v-else>
|
|
195
261
|
<a-input
|
|
262
|
+
@change="handleInputChange($event, cell.dataIndex, cell)"
|
|
196
263
|
v-model="configData[cell.dataIndex]"
|
|
197
264
|
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
198
|
-
:disabled="true"
|
|
265
|
+
:disabled="cell.inputReadOnly === true"
|
|
266
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData[cell.dataIndex]}"/>
|
|
199
267
|
</template>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
@change="handleInputDeepChange($event, cell.dataIndex)"
|
|
205
|
-
v-model="config.tempData[cell.dataIndex]"
|
|
206
|
-
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"/>
|
|
207
|
-
</template>
|
|
208
|
-
<template v-else>
|
|
209
|
-
<a-input
|
|
210
|
-
v-model="configData[cell.dataIndex]"
|
|
211
|
-
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"/>
|
|
212
|
-
</template>
|
|
213
|
-
</template>
|
|
268
|
+
<div v-if="isFieldRequired(cell) && !getInputValue(cell)" class="required-message">
|
|
269
|
+
{{ getRequiredMessage(cell, 'input') }}
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
214
272
|
</template>
|
|
215
273
|
<template v-else-if="cell.type === 'inputs'">
|
|
216
274
|
<template v-if="cell.inputReadOnly === true">
|
|
@@ -219,7 +277,7 @@
|
|
|
219
277
|
<span class="inputsDivItemLabel">{{ displayFormatStartText(cell.format) }}</span>
|
|
220
278
|
<template v-if="cell.dataIndex.indexOf('@@@') !== -1">
|
|
221
279
|
<a-input
|
|
222
|
-
@change="handleInputDeepChange($event, cell.dataIndex)"
|
|
280
|
+
@change="handleInputDeepChange($event, cell.dataIndex, cell)"
|
|
223
281
|
v-model="config.tempData[cell.dataIndex][index]"
|
|
224
282
|
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
225
283
|
:disabled="true"/>
|
|
@@ -240,7 +298,7 @@
|
|
|
240
298
|
<span class="inputsDivItemLabel">{{ displayFormatStartText(cell.format) }}</span>
|
|
241
299
|
<template v-if="cell.dataIndex.indexOf('@@@') !== -1">
|
|
242
300
|
<a-input
|
|
243
|
-
@change="handleInputDeepChange($event, cell.dataIndex)"
|
|
301
|
+
@change="handleInputDeepChange($event, cell.dataIndex, cell)"
|
|
244
302
|
v-model="config.tempData[cell.dataIndex][index]"
|
|
245
303
|
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"/>
|
|
246
304
|
</template>
|
|
@@ -337,6 +395,35 @@
|
|
|
337
395
|
>{{ cell.text || '确认' }}
|
|
338
396
|
</a-button>
|
|
339
397
|
</template>
|
|
398
|
+
<template v-else-if="cell.type === 'datePicker'">
|
|
399
|
+
<div>
|
|
400
|
+
<a-date-picker
|
|
401
|
+
@change="handleArrayDatePickerChange($event, inputColumnsDefinitionIndex, cell.dataIndex, cell)"
|
|
402
|
+
:value="formatDateValue(configData.arr[inputColumnsDefinitionIndex][cell.dataIndex])"
|
|
403
|
+
format="YYYY-MM-DD"
|
|
404
|
+
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
405
|
+
:disabled="cell.inputReadOnly === true"
|
|
406
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]}"/>
|
|
407
|
+
<div v-if="isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]" class="required-message">
|
|
408
|
+
{{ getRequiredMessage(cell, 'datePicker') }}
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
</template>
|
|
412
|
+
<template v-else-if="cell.type === 'timePicker'">
|
|
413
|
+
<div>
|
|
414
|
+
<a-date-picker
|
|
415
|
+
@change="handleArrayTimePickerChange($event, inputColumnsDefinitionIndex, cell.dataIndex, cell)"
|
|
416
|
+
:value="formatDateValue(configData.arr[inputColumnsDefinitionIndex][cell.dataIndex])"
|
|
417
|
+
format="YYYY-MM-DD HH:mm:ss"
|
|
418
|
+
show-time
|
|
419
|
+
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
420
|
+
:disabled="cell.inputReadOnly === true"
|
|
421
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]}"/>
|
|
422
|
+
<div v-if="isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]" class="required-message">
|
|
423
|
+
{{ getRequiredMessage(cell, 'timePicker') }}
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
</template>
|
|
340
427
|
<template v-else-if="cell.type === 'signature'">
|
|
341
428
|
<img :src="configData[cell.dataIndex]" alt="签名加载失败" style="max-height: 2rem">
|
|
342
429
|
<a-button v-if="!configData[cell.dataIndex]" type="dashed" >需要在手机端签名</a-button>
|
|
@@ -345,17 +432,17 @@
|
|
|
345
432
|
{{ configData.arr[inputColumnsDefinitionIndex][cell.dataIndex] }}
|
|
346
433
|
</template>
|
|
347
434
|
<template v-else-if="cell.type === 'input'">
|
|
348
|
-
<
|
|
435
|
+
<div>
|
|
349
436
|
<a-input
|
|
437
|
+
@change="handleArrayInputChange($event, inputColumnsDefinitionIndex, cell.dataIndex, cell)"
|
|
350
438
|
v-model="configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]"
|
|
351
439
|
:style="'width:' + (cell.inputWidth ? cell.inputWidth : '100') + '%'"
|
|
352
|
-
:disabled="true"
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
</template>
|
|
440
|
+
:disabled="cell.inputReadOnly === true"
|
|
441
|
+
:class="{'required-field-error': isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]}"/>
|
|
442
|
+
<div v-if="isFieldRequired(cell) && !configData.arr[inputColumnsDefinitionIndex][cell.dataIndex]" class="required-message">
|
|
443
|
+
{{ getRequiredMessage(cell, 'input') }}
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
359
446
|
</template>
|
|
360
447
|
<template v-else-if="cell.type === 'inputs'">
|
|
361
448
|
<template v-if="cell.inputReadOnly === true">
|
|
@@ -379,6 +466,7 @@
|
|
|
379
466
|
import Upload from '@vue2-client/base-client/components/common/Upload'
|
|
380
467
|
import { formatDate } from '@vue2-client/utils/util'
|
|
381
468
|
import { nanoid } from 'nanoid'
|
|
469
|
+
import moment from 'moment'
|
|
382
470
|
|
|
383
471
|
export default {
|
|
384
472
|
name: 'XReportTrGroup',
|
|
@@ -582,9 +670,35 @@ export default {
|
|
|
582
670
|
return result
|
|
583
671
|
},
|
|
584
672
|
// 表格中数据key含有@@@,需要手动触发更新
|
|
585
|
-
handleInputDeepChange () {
|
|
673
|
+
handleInputDeepChange (event, dataIndex, cell = null) {
|
|
674
|
+
// 如果字段必填且有值,触发重新渲染以移除错误样式
|
|
675
|
+
if (cell && this.isFieldRequired(cell) && event.target.value) {
|
|
676
|
+
this.$forceUpdate()
|
|
677
|
+
}
|
|
586
678
|
this.$forceUpdate()
|
|
587
679
|
},
|
|
680
|
+
// 处理普通input变化
|
|
681
|
+
handleInputChange (event, dataIndex, cell = null) {
|
|
682
|
+
// 如果字段必填且有值,触发重新渲染以移除错误样式
|
|
683
|
+
if (cell && this.isFieldRequired(cell) && event.target.value) {
|
|
684
|
+
this.$forceUpdate()
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
// 处理动态行中input变化
|
|
688
|
+
handleArrayInputChange (event, arrayIndex, dataIndex, cell = null) {
|
|
689
|
+
// 如果字段必填且有值,触发重新渲染以移除错误样式
|
|
690
|
+
if (cell && this.isFieldRequired(cell) && event.target.value) {
|
|
691
|
+
this.$forceUpdate()
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
// 获取input的值,用于必填校验
|
|
695
|
+
getInputValue (cell) {
|
|
696
|
+
if (cell.dataIndex.indexOf('@@@') !== -1) {
|
|
697
|
+
return this.config.tempData[cell.dataIndex]
|
|
698
|
+
} else {
|
|
699
|
+
return this.configData[cell.dataIndex]
|
|
700
|
+
}
|
|
701
|
+
},
|
|
588
702
|
// 路径中含有@@@的key,将其解析,并返回其数据
|
|
589
703
|
getDeepObject (obj, strPath) {
|
|
590
704
|
const arr = strPath.split('@@@')
|
|
@@ -610,6 +724,69 @@ export default {
|
|
|
610
724
|
}
|
|
611
725
|
this.configData = Object.assign({}, this.configData)
|
|
612
726
|
},
|
|
727
|
+
// 通用的日期时间选择器变化处理方法
|
|
728
|
+
handleDateTimePickerChange (date, dataIndex, format, arrayIndex = null, cell = null) {
|
|
729
|
+
const dateStr = date ? moment(date).format(format) : ''
|
|
730
|
+
|
|
731
|
+
if (arrayIndex !== null) {
|
|
732
|
+
// 处理动态行中的日期时间选择器
|
|
733
|
+
this.configData.arr[arrayIndex][dataIndex] = dateStr
|
|
734
|
+
} else if (dataIndex.indexOf('@@@') !== -1) {
|
|
735
|
+
// 处理深层嵌套的数据
|
|
736
|
+
this.handleInputDeepChange({ target: { value: dateStr } }, dataIndex, cell)
|
|
737
|
+
} else {
|
|
738
|
+
// 处理普通的数据
|
|
739
|
+
this.configData[dataIndex] = dateStr
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// 如果字段必填且有值,触发重新渲染以移除错误样式
|
|
743
|
+
if (cell && this.isFieldRequired(cell) && dateStr) {
|
|
744
|
+
this.$forceUpdate()
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
this.configData = Object.assign({}, this.configData)
|
|
748
|
+
},
|
|
749
|
+
// 日期选择器变化处理(YYYY-MM-DD格式)
|
|
750
|
+
handleDatePickerChange (date, dataIndex, cell = null) {
|
|
751
|
+
this.handleDateTimePickerChange(date, dataIndex, 'YYYY-MM-DD', null, cell)
|
|
752
|
+
},
|
|
753
|
+
// 时间选择器变化处理(YYYY-MM-DD HH:mm:ss格式)
|
|
754
|
+
handleTimePickerChange (date, dataIndex, cell = null) {
|
|
755
|
+
this.handleDateTimePickerChange(date, dataIndex, 'YYYY-MM-DD HH:mm:ss', null, cell)
|
|
756
|
+
},
|
|
757
|
+
// 动态行中日期选择器变化处理
|
|
758
|
+
handleArrayDatePickerChange (date, arrayIndex, dataIndex, cell = null) {
|
|
759
|
+
this.handleDateTimePickerChange(date, dataIndex, 'YYYY-MM-DD', arrayIndex, cell)
|
|
760
|
+
},
|
|
761
|
+
// 动态行中时间选择器变化处理
|
|
762
|
+
handleArrayTimePickerChange (date, arrayIndex, dataIndex, cell = null) {
|
|
763
|
+
this.handleDateTimePickerChange(date, dataIndex, 'YYYY-MM-DD HH:mm:ss', arrayIndex, cell)
|
|
764
|
+
},
|
|
765
|
+
// 判断字段是否必填
|
|
766
|
+
isFieldRequired (cell) {
|
|
767
|
+
return cell && cell.required === true
|
|
768
|
+
},
|
|
769
|
+
// 获取必填字段的提示信息
|
|
770
|
+
getRequiredMessage (cell, fieldType) {
|
|
771
|
+
if (cell.requiredMessage) {
|
|
772
|
+
return cell.requiredMessage
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// 默认提示信息
|
|
776
|
+
const defaultMessages = {
|
|
777
|
+
datePicker: '请选择日期',
|
|
778
|
+
timePicker: '请选择日期时间',
|
|
779
|
+
input: '请填写此字段'
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return defaultMessages[fieldType] || '此字段为必填项'
|
|
783
|
+
},
|
|
784
|
+
// 格式化日期值,用于日期选择器的value
|
|
785
|
+
formatDateValue (dateStr) {
|
|
786
|
+
if (!dateStr) return null
|
|
787
|
+
const date = moment(dateStr)
|
|
788
|
+
return date.isValid() ? date : null
|
|
789
|
+
},
|
|
613
790
|
// 反序列化函数并执行
|
|
614
791
|
deserializeFunctionAndRun (functionStr, value) {
|
|
615
792
|
// eslint-disable-next-line no-eval
|
|
@@ -813,4 +990,16 @@ export default {
|
|
|
813
990
|
border-bottom: 1px solid #000;
|
|
814
991
|
padding: 8px;
|
|
815
992
|
}
|
|
993
|
+
|
|
994
|
+
.required-field-error {
|
|
995
|
+
border-color: #ff4d4f !important;
|
|
996
|
+
box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2) !important;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.required-message {
|
|
1000
|
+
color: #ff4d4f;
|
|
1001
|
+
font-size: 12px;
|
|
1002
|
+
margin-top: 4px;
|
|
1003
|
+
line-height: 1.2;
|
|
1004
|
+
}
|
|
816
1005
|
</style>
|
|
@@ -36,9 +36,68 @@ export default {
|
|
|
36
36
|
```vue
|
|
37
37
|
<XReport :config-name="'test_tableConfig'" :activated-slot-name="'test_tableConfig_slot'"/>
|
|
38
38
|
```
|
|
39
|
+
|
|
40
|
+
## 支持的表单项目类型
|
|
41
|
+
|
|
42
|
+
| 类型 | 说明 | 输出格式 | 备注 |
|
|
43
|
+
|-----------------|------|-------|-----------|
|
|
44
|
+
| input | 文本输入框 | 字符串 | 标准文本输入 |
|
|
45
|
+
| datePicker| 日期选择器 | YYYY-MM-DD | 日期格式 |
|
|
46
|
+
| timePicker | 时间选择器 | YYYY-MM-DD HH:mm:ss | 日期时间格式 |
|
|
47
|
+
| curDateInput | 当前日期按钮 | YYYY-MM-DD HH:mm:ss | 点击获取当前时间|
|
|
48
|
+
| signature | 签名框 | 图片URL | 需要在手机端操作|
|
|
49
|
+
| images | 图片上传 | 图片数组 | 支持多图片上传|
|
|
50
|
+
|
|
51
|
+
## 配置例子
|
|
52
|
+
|
|
53
|
+
### 日期选择器配置
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"type": "datePicker",
|
|
57
|
+
"dataIndex": "selectedDate",
|
|
58
|
+
"inputWidth": "100%",
|
|
59
|
+
"inputReadOnly": false,
|
|
60
|
+
"required": true,
|
|
61
|
+
"requiredMessage": "请选择操作日期"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 时间选择器配置
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"type": "timePicker",
|
|
69
|
+
"dataIndex": "selectedDateTime",
|
|
70
|
+
"inputWidth": "100%",
|
|
71
|
+
"inputReadOnly": false,
|
|
72
|
+
"required": true,
|
|
73
|
+
"requiredMessage": "请选择具体时间"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 必填字段配置说明
|
|
78
|
+
|
|
79
|
+
| 参数 | 说明 | 类型 | 默认值 |
|
|
80
|
+
|-----------------|------|-------|-----------|
|
|
81
|
+
| required | 是否必填 | Boolean | false |
|
|
82
|
+
| requiredMessage| 必填提示信息 | String | 根据字段类型自动生成 |
|
|
83
|
+
|
|
84
|
+
**默认提示信息:**
|
|
85
|
+
- datePicker: "请选择日期"
|
|
86
|
+
- timePicker: "请选择日期时间"
|
|
87
|
+
- input: "请填写此字段"
|
|
88
|
+
- 其他类型: "此字段为必填项"
|
|
89
|
+
|
|
90
|
+
**必填校验特性:**
|
|
91
|
+
- 必填字段为空时会显示红色边框和错误提示
|
|
92
|
+
- 保存时会自动校验所有必填字段,校验失败会阻止保存并显示错误信息
|
|
93
|
+
- 导出数据时会进行校验提醒,但不会阻止导出
|
|
94
|
+
|
|
39
95
|
## 注意事项
|
|
40
96
|
|
|
41
97
|
> 在某些情况下,比如手机端,只需要输入表格中一部分的内容。
|
|
42
98
|
> 可以将这部分内容作为插槽,并在activatedSlotName中填写插槽名。
|
|
43
99
|
> 则会在设计页面仅展示插槽中的输入项,并在预览窗口中,根据configName中的配置,
|
|
44
100
|
> 渲染出来完整的表格
|
|
101
|
+
|
|
102
|
+
> 新增的datePicker和timePicker支持在普通行、动态行中使用,
|
|
103
|
+
> 会自动格式化为指定的日期时间格式并保存到配置数据中。支持必填校验功能。
|