vue2-client 1.18.49 → 1.18.51
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/.claude/settings.local.json +28 -21
- package/docs/image.png +0 -0
- package/package.json +1 -1
- package/src/base-client/components/common/XAddNativeForm/demo.vue +20 -24
- package/src/base-client/components/common/XForm/XForm.vue +121 -64
- package/src/base-client/components/common/XFormCol/XFormCol.vue +43 -36
- package/src/base-client/components/common/XFormTable/XFormTable.vue +4 -1
- package/src/router/async/router.map.js +2 -2
- package/vue.config.js +40 -42
|
@@ -1,21 +1,28 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"WebSearch",
|
|
5
|
-
"WebFetch(domain:context7.com)",
|
|
6
|
-
"Bash(npm run lint)",
|
|
7
|
-
"mcp__context7__resolve-library-id",
|
|
8
|
-
"mcp__context7__get-library-docs",
|
|
9
|
-
"WebFetch(domain:github.com)",
|
|
10
|
-
"Bash(npm run serve:*)",
|
|
11
|
-
"mcp__serena__get_current_config",
|
|
12
|
-
"mcp__serena__activate_project",
|
|
13
|
-
"mcp__serena__get_symbols_overview",
|
|
14
|
-
"mcp__serena__list_dir",
|
|
15
|
-
"mcp__serena__find_file"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"WebSearch",
|
|
5
|
+
"WebFetch(domain:context7.com)",
|
|
6
|
+
"Bash(npm run lint)",
|
|
7
|
+
"mcp__context7__resolve-library-id",
|
|
8
|
+
"mcp__context7__get-library-docs",
|
|
9
|
+
"WebFetch(domain:github.com)",
|
|
10
|
+
"Bash(npm run serve:*)",
|
|
11
|
+
"mcp__serena__get_current_config",
|
|
12
|
+
"mcp__serena__activate_project",
|
|
13
|
+
"mcp__serena__get_symbols_overview",
|
|
14
|
+
"mcp__serena__list_dir",
|
|
15
|
+
"mcp__serena__find_file",
|
|
16
|
+
"mcp__serena__list_memories",
|
|
17
|
+
"mcp__serena__check_onboarding_performed",
|
|
18
|
+
"mcp__serena__read_memory",
|
|
19
|
+
"mcp__serena__think_about_collected_information",
|
|
20
|
+
"mcp__sequential-thinking__sequentialthinking",
|
|
21
|
+
"Bash(npm run lint:*)",
|
|
22
|
+
"mcp__serena__find_symbol"
|
|
23
|
+
],
|
|
24
|
+
"deny": [],
|
|
25
|
+
"ask": [],
|
|
26
|
+
"defaultMode": "acceptEdits"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/docs/image.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -5,26 +5,28 @@ import { getConfigByNameAsync } from '@vue2-client/services/api/common'
|
|
|
5
5
|
export default {
|
|
6
6
|
name: 'Demo',
|
|
7
7
|
components: { XAddNativeForm },
|
|
8
|
-
data
|
|
8
|
+
data() {
|
|
9
9
|
return {
|
|
10
|
-
|
|
10
|
+
form: {}
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
-
mounted
|
|
14
|
-
getConfigByNameAsync('
|
|
15
|
-
this.$refs.xAddFrom.init(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
mounted() {
|
|
14
|
+
getConfigByNameAsync('CardSellGasForm', 'af-revenue').then(res => {
|
|
15
|
+
this.$refs.xAddFrom.init(
|
|
16
|
+
Object.assign(res, {
|
|
17
|
+
modifyModelData: {
|
|
18
|
+
data: {}
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
)
|
|
20
22
|
})
|
|
21
23
|
},
|
|
22
24
|
methods: {
|
|
23
|
-
aaa
|
|
25
|
+
aaa(value) {
|
|
24
26
|
this.form = Object.assign({}, value.realForm)
|
|
25
27
|
this.$refs.xAddFrom.loading = false
|
|
26
28
|
},
|
|
27
|
-
singLocal
|
|
29
|
+
singLocal() {
|
|
28
30
|
console.log('singLocal')
|
|
29
31
|
}
|
|
30
32
|
}
|
|
@@ -33,22 +35,16 @@ export default {
|
|
|
33
35
|
|
|
34
36
|
<template>
|
|
35
37
|
<div>
|
|
36
|
-
<a-card :style="{ width: '
|
|
37
|
-
<x-add-native-form
|
|
38
|
-
ref="xAddFrom"
|
|
39
|
-
@getinfo="aaa"
|
|
40
|
-
@onSubmit="aaa"
|
|
41
|
-
@singLocal="singLocal"
|
|
42
|
-
/>
|
|
38
|
+
<a-card :style="{ width: '650px' }">
|
|
39
|
+
<x-add-native-form ref="xAddFrom" @getinfo="aaa" @onSubmit="aaa" @singLocal="singLocal" />
|
|
43
40
|
</a-card>
|
|
44
41
|
<a-card>
|
|
45
|
-
<pre
|
|
46
|
-
form ? JSON.stringify(form, null, 2) : '请先点击获取表单数据' }}
|
|
47
|
-
</pre
|
|
42
|
+
<pre
|
|
43
|
+
>{{ form ? JSON.stringify(form, null, 2) : '请先点击获取表单数据' }}
|
|
44
|
+
</pre
|
|
45
|
+
>
|
|
48
46
|
</a-card>
|
|
49
47
|
</div>
|
|
50
48
|
</template>
|
|
51
49
|
|
|
52
|
-
<style scoped lang="less">
|
|
53
|
-
|
|
54
|
-
</style>
|
|
50
|
+
<style scoped lang="less"></style>
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :style="{marginBottom: !visible ? '12px':''}">
|
|
2
|
+
<div :style="{ marginBottom: !visible ? '12px' : '' }">
|
|
3
3
|
<div v-if="visible && realJsonData.length > 0" class="table-page-search-wrapper">
|
|
4
|
-
<a-form-model
|
|
5
|
-
v-if="loaded"
|
|
6
|
-
ref="form"
|
|
7
|
-
:model="form"
|
|
8
|
-
:rules="rules"
|
|
9
|
-
layout="inline">
|
|
4
|
+
<a-form-model v-if="loaded" ref="form" :model="form" :rules="rules" layout="inline">
|
|
10
5
|
<a-row :gutter="24" type="flex">
|
|
11
6
|
<x-form-item
|
|
12
7
|
v-for="item in visibleItems"
|
|
@@ -38,25 +33,25 @@
|
|
|
38
33
|
<a-col style="margin-left: auto">
|
|
39
34
|
<span
|
|
40
35
|
:style="advanced ? { float: 'right', overflow: 'hidden' } : {}"
|
|
41
|
-
class="table-page-search-submitButtons"
|
|
36
|
+
class="table-page-search-submitButtons"
|
|
37
|
+
>
|
|
42
38
|
<template v-if="hiddenItems.length > 0">
|
|
43
39
|
<a @click="toggleAdvanced">
|
|
44
|
-
<span v-if="!advanced" style="display: inline-flex; align-items: center
|
|
45
|
-
<a-icon type="eye" :style="iconStyle" class="form-expand-icon"></a-icon
|
|
40
|
+
<span v-if="!advanced" style="display: inline-flex; align-items: center">
|
|
41
|
+
<a-icon type="eye" :style="iconStyle" class="form-expand-icon"></a-icon>
|
|
42
|
+
更多条件
|
|
46
43
|
</span>
|
|
47
|
-
<span v-else style="display: inline-flex; align-items: center
|
|
48
|
-
<a-icon type="eye-invisible" :style="iconStyle" class="form-expand-icon rotated"></a-icon
|
|
44
|
+
<span v-else style="display: inline-flex; align-items: center">
|
|
45
|
+
<a-icon type="eye-invisible" :style="iconStyle" class="form-expand-icon rotated"></a-icon>
|
|
46
|
+
收起更多
|
|
49
47
|
</span>
|
|
50
48
|
</a>
|
|
51
|
-
<a-divider type="vertical"/>
|
|
49
|
+
<a-divider type="vertical" />
|
|
52
50
|
</template>
|
|
53
51
|
<a-space>
|
|
54
|
-
<a-button
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
type="primary"
|
|
58
|
-
@click="onSubmit">
|
|
59
|
-
<a-icon :style="iconStyle" type="search"></a-icon>查询
|
|
52
|
+
<a-button v-if="!simpleMode" htmlType="submit" type="primary" @click="onSubmit">
|
|
53
|
+
<a-icon :style="iconStyle" type="search"></a-icon>
|
|
54
|
+
查询
|
|
60
55
|
</a-button>
|
|
61
56
|
<a-button v-if="!simpleMode" @click="resetForm">重置</a-button>
|
|
62
57
|
<slot></slot>
|
|
@@ -84,7 +79,7 @@ export default {
|
|
|
84
79
|
XFormItem
|
|
85
80
|
},
|
|
86
81
|
mixins: [formValidationMixin],
|
|
87
|
-
data
|
|
82
|
+
data() {
|
|
88
83
|
return {
|
|
89
84
|
// 内容加载是否完成
|
|
90
85
|
loaded: false,
|
|
@@ -124,21 +119,28 @@ export default {
|
|
|
124
119
|
...mapState('account', { currUser: 'user' }),
|
|
125
120
|
// 过滤掉仅用于新增/修改场景的表单项
|
|
126
121
|
realJsonData: function () {
|
|
127
|
-
return this.formItems.filter(
|
|
122
|
+
return this.formItems.filter(
|
|
123
|
+
item =>
|
|
124
|
+
(!item.isOnlyAddOrEdit && item.type !== 'group') ||
|
|
125
|
+
(item.type === 'group' && item.groupItems.some(groupItem => !groupItem.isOnlyAddOrEdit))
|
|
126
|
+
)
|
|
128
127
|
},
|
|
129
128
|
// 过滤出用于新增/修改场景的表单项
|
|
130
129
|
groupJsonData: function () {
|
|
131
|
-
return this.formItems
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
return this.formItems
|
|
131
|
+
.filter(item => {
|
|
132
|
+
return item.type === 'group'
|
|
133
|
+
})
|
|
134
|
+
.map(item => {
|
|
135
|
+
item.groupItems = item.groupItems
|
|
136
|
+
.filter(item => !item.isOnlyAddOrEdit)
|
|
137
|
+
.map(groupItem => {
|
|
138
|
+
// 只保留第一个下划线后面的内容
|
|
139
|
+
// groupItem.model = groupItem.model.substring(groupItem.model.indexOf('_') + 1)
|
|
140
|
+
return groupItem
|
|
141
|
+
})
|
|
139
142
|
return item
|
|
140
|
-
}
|
|
141
|
-
)
|
|
143
|
+
})
|
|
142
144
|
},
|
|
143
145
|
// 合并所有来源的表单项
|
|
144
146
|
allFormItems: function () {
|
|
@@ -170,20 +172,22 @@ export default {
|
|
|
170
172
|
...item,
|
|
171
173
|
_originalIndex: this.visibleItemCount + index
|
|
172
174
|
}))
|
|
173
|
-
}
|
|
175
|
+
}
|
|
174
176
|
},
|
|
175
|
-
provide
|
|
177
|
+
provide() {
|
|
176
178
|
return {
|
|
177
179
|
XFormContext: this,
|
|
178
180
|
// 移除必填项
|
|
179
181
|
removeRequired: this.removeRequired,
|
|
180
182
|
// 设置必填项
|
|
181
183
|
setRequired: this.setRequired,
|
|
184
|
+
// 全局 label 宽度,确保所有表单项的 label 宽度一致
|
|
185
|
+
globalLabelWidth: this.globalLabelWidth
|
|
182
186
|
}
|
|
183
187
|
},
|
|
184
188
|
methods: {
|
|
185
189
|
// 根据flex值计算可见表单项数量
|
|
186
|
-
updateVisibleItemCount
|
|
190
|
+
updateVisibleItemCount(flex) {
|
|
187
191
|
// flex值与显示数量的映射关系
|
|
188
192
|
const flexToCountMap = {
|
|
189
193
|
24: 2, // 小屏:1个/行,显示2个(2行)
|
|
@@ -201,7 +205,7 @@ export default {
|
|
|
201
205
|
},
|
|
202
206
|
|
|
203
207
|
// 递归查找第一个XFormCol实例
|
|
204
|
-
findFirstXFormCol
|
|
208
|
+
findFirstXFormCol(components = this.$children) {
|
|
205
209
|
for (const component of components) {
|
|
206
210
|
if (component.$options.name === 'XFormCol') {
|
|
207
211
|
return component
|
|
@@ -214,7 +218,7 @@ export default {
|
|
|
214
218
|
},
|
|
215
219
|
|
|
216
220
|
// 设置flex监听
|
|
217
|
-
setupFlexWatcher
|
|
221
|
+
setupFlexWatcher() {
|
|
218
222
|
this.$nextTick(() => {
|
|
219
223
|
const firstXFormCol = this.findFirstXFormCol()
|
|
220
224
|
if (firstXFormCol) {
|
|
@@ -224,7 +228,7 @@ export default {
|
|
|
224
228
|
// 设置监听
|
|
225
229
|
this._flexWatcher = this.$watch(
|
|
226
230
|
() => firstXFormCol.computedFlex,
|
|
227
|
-
|
|
231
|
+
newFlex => {
|
|
228
232
|
this.updateVisibleItemCount(newFlex)
|
|
229
233
|
}
|
|
230
234
|
)
|
|
@@ -235,10 +239,16 @@ export default {
|
|
|
235
239
|
})
|
|
236
240
|
},
|
|
237
241
|
|
|
238
|
-
init
|
|
242
|
+
init(params) {
|
|
239
243
|
const {
|
|
240
|
-
formItems,
|
|
241
|
-
|
|
244
|
+
formItems,
|
|
245
|
+
serviceName,
|
|
246
|
+
getDataParams = {},
|
|
247
|
+
env = 'prod',
|
|
248
|
+
simpleMode = false,
|
|
249
|
+
funcData = {},
|
|
250
|
+
queryParamsName = 'localConfig',
|
|
251
|
+
defaultQueryForm = {}
|
|
242
252
|
} = params
|
|
243
253
|
this.mountedCount = 0
|
|
244
254
|
this.queryParamsName = queryParamsName
|
|
@@ -276,9 +286,11 @@ export default {
|
|
|
276
286
|
if (!funcData.queryFormInit.startsWith('async')) {
|
|
277
287
|
funcData.queryFormInit = `async ${funcData.queryFormInit}`
|
|
278
288
|
}
|
|
279
|
-
executeStrFunctionByContext(this, funcData.queryFormInit, [util, runLogic, getConfigByNameAsync]).then(
|
|
280
|
-
|
|
281
|
-
|
|
289
|
+
executeStrFunctionByContext(this, funcData.queryFormInit, [util, runLogic, getConfigByNameAsync]).then(
|
|
290
|
+
res => {
|
|
291
|
+
this.form = Object.assign({}, this.form, res)
|
|
292
|
+
}
|
|
293
|
+
)
|
|
282
294
|
}
|
|
283
295
|
} catch (e) {
|
|
284
296
|
console.error('queryFormInit error', e)
|
|
@@ -286,7 +298,7 @@ export default {
|
|
|
286
298
|
this.getDataParams = getDataParams
|
|
287
299
|
this.loaded = true
|
|
288
300
|
},
|
|
289
|
-
onItemMounted
|
|
301
|
+
onItemMounted(_h) {
|
|
290
302
|
this.mountedCount += 1
|
|
291
303
|
if (this.mountedCount === this.allFormItems.length) {
|
|
292
304
|
// 所有 x-from-item 挂载完成,触发父组件中的 xTable.init
|
|
@@ -294,7 +306,7 @@ export default {
|
|
|
294
306
|
}
|
|
295
307
|
},
|
|
296
308
|
// 时间组件赋默认值
|
|
297
|
-
getDateRange
|
|
309
|
+
getDateRange({ type, queryFormDefault: defaultValue, queryType, queryValueFormat: defaultFormat, name }) {
|
|
298
310
|
const formatMap = {
|
|
299
311
|
yearPicker: 'YYYY',
|
|
300
312
|
yearRangePicker: 'YYYY',
|
|
@@ -303,7 +315,7 @@ export default {
|
|
|
303
315
|
datePicker: 'YYYY-MM-DD',
|
|
304
316
|
rangePicker: 'YYYY-MM-DD HH:mm:ss',
|
|
305
317
|
timePicker: 'HH:mm:ss',
|
|
306
|
-
timeRangePicker: 'HH:mm:ss'
|
|
318
|
+
timeRangePicker: 'HH:mm:ss'
|
|
307
319
|
}
|
|
308
320
|
let format = formatMap[type]
|
|
309
321
|
|
|
@@ -347,12 +359,26 @@ export default {
|
|
|
347
359
|
}
|
|
348
360
|
return [start, end]
|
|
349
361
|
},
|
|
350
|
-
setFormProps
|
|
362
|
+
setFormProps(formData, item) {
|
|
351
363
|
formData[item.model] = undefined
|
|
352
364
|
if (item.queryFormDefault) {
|
|
353
|
-
if (
|
|
365
|
+
if (
|
|
366
|
+
[
|
|
367
|
+
'datePicker',
|
|
368
|
+
'rangePicker',
|
|
369
|
+
'yearPicker',
|
|
370
|
+
'monthPicker',
|
|
371
|
+
'yearRangePicker',
|
|
372
|
+
'monthRangePicker',
|
|
373
|
+
'timePicker',
|
|
374
|
+
'timeRangePicker'
|
|
375
|
+
].includes(item.type)
|
|
376
|
+
) {
|
|
354
377
|
formData[item.model] = this.getDateRange(item)
|
|
355
|
-
} else if (
|
|
378
|
+
} else if (
|
|
379
|
+
['treeSelect', 'select', 'checkbox'].includes(item.type) &&
|
|
380
|
+
['curOrgId', 'curDepId', 'curUserId'].includes(item.queryFormDefault)
|
|
381
|
+
) {
|
|
356
382
|
if (item.queryFormDefault === 'curOrgId') {
|
|
357
383
|
formData[item.model] = item.type === 'select' ? this.currUser.orgid : [this.currUser.orgid]
|
|
358
384
|
}
|
|
@@ -369,7 +395,11 @@ export default {
|
|
|
369
395
|
this.defaultMap[item.model] = formData[item.model]
|
|
370
396
|
}
|
|
371
397
|
} else {
|
|
372
|
-
if (
|
|
398
|
+
if (
|
|
399
|
+
['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(
|
|
400
|
+
item.type
|
|
401
|
+
)
|
|
402
|
+
) {
|
|
373
403
|
if (item.queryType === 'BETWEEN') {
|
|
374
404
|
formData[item.model] = []
|
|
375
405
|
}
|
|
@@ -377,7 +407,9 @@ export default {
|
|
|
377
407
|
}
|
|
378
408
|
if (item.rule) {
|
|
379
409
|
this.rules[item.model] = []
|
|
380
|
-
const required = item.rule.queryRequired
|
|
410
|
+
const required = item.rule.queryRequired
|
|
411
|
+
? item.rule.queryRequired === true || item.rule.queryRequired === 'true'
|
|
412
|
+
: false
|
|
381
413
|
let trigger
|
|
382
414
|
let message
|
|
383
415
|
if (required) {
|
|
@@ -422,36 +454,48 @@ export default {
|
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
456
|
},
|
|
425
|
-
customJsValidate
|
|
457
|
+
customJsValidate(rule, value, callback, item) {
|
|
426
458
|
if (item.rule.customQueryValidatorFunc) {
|
|
427
|
-
executeStrFunctionByContext(this, item.rule.customQueryValidatorFunc, [
|
|
459
|
+
executeStrFunctionByContext(this, item.rule.customQueryValidatorFunc, [
|
|
460
|
+
rule,
|
|
461
|
+
value,
|
|
462
|
+
callback,
|
|
463
|
+
this.form,
|
|
464
|
+
item,
|
|
465
|
+
util,
|
|
466
|
+
runLogic,
|
|
467
|
+
getConfigByNameAsync
|
|
468
|
+
])
|
|
428
469
|
} else {
|
|
429
470
|
callback()
|
|
430
471
|
}
|
|
431
472
|
},
|
|
432
|
-
toggleAdvanced
|
|
473
|
+
toggleAdvanced() {
|
|
433
474
|
this.advanced = !this.advanced
|
|
434
475
|
this.$emit('toggleAdvanced')
|
|
435
476
|
},
|
|
436
|
-
toggleVisible
|
|
477
|
+
toggleVisible() {
|
|
437
478
|
this.visible = !this.visible
|
|
438
479
|
return this.visible
|
|
439
480
|
},
|
|
440
|
-
resetForm
|
|
481
|
+
resetForm() {
|
|
441
482
|
this.$refs.form.resetFields()
|
|
442
483
|
},
|
|
443
|
-
emitFunc
|
|
484
|
+
emitFunc(func, data, value) {
|
|
444
485
|
this.$emit(func, data, value)
|
|
445
486
|
this.$emit('x-form-item-emit-func', func, data, value)
|
|
446
487
|
},
|
|
447
|
-
onSubmit
|
|
488
|
+
onSubmit() {
|
|
448
489
|
this.$refs.form.validate(valid => {
|
|
449
490
|
for (const key of Object.keys(this.form)) {
|
|
450
491
|
if (this.form[key] === null || this.form[key] === '') {
|
|
451
492
|
this.form[key] = undefined
|
|
452
493
|
}
|
|
453
494
|
// 树形选择框重置后会重置为[undefined],查询时为[null]
|
|
454
|
-
if (
|
|
495
|
+
if (
|
|
496
|
+
Array.isArray(this.form[key]) &&
|
|
497
|
+
(this.form[key].length === 0 || this.form[key][0] === null || this.form[key][0] === undefined)
|
|
498
|
+
) {
|
|
455
499
|
this.form[key] = undefined
|
|
456
500
|
}
|
|
457
501
|
// 如果 form 中没有值,但是有默认值
|
|
@@ -467,23 +511,36 @@ export default {
|
|
|
467
511
|
this.$emit('onSubmit', data)
|
|
468
512
|
})
|
|
469
513
|
},
|
|
470
|
-
exports
|
|
514
|
+
exports() {
|
|
471
515
|
this.$emit('exports', this.form)
|
|
472
516
|
},
|
|
473
|
-
setForm
|
|
517
|
+
setForm(obj) {
|
|
474
518
|
this.form = Object.assign(this.form, obj)
|
|
475
519
|
},
|
|
520
|
+
/**
|
|
521
|
+
* 主动触发表单提交
|
|
522
|
+
* 用于 queryTable 等场景,确保走相同的数据处理流程
|
|
523
|
+
* @param {Object} conditionParams - 额外的查询条件参数
|
|
524
|
+
*/
|
|
525
|
+
submitForm(conditionParams = {}) {
|
|
526
|
+
// 将外部参数合并到表单中
|
|
527
|
+
if (Object.keys(conditionParams).length > 0) {
|
|
528
|
+
this.form = Object.assign({}, this.form, conditionParams)
|
|
529
|
+
}
|
|
530
|
+
// 调用现有的 onSubmit 方法,触发 emit
|
|
531
|
+
this.onSubmit()
|
|
532
|
+
}
|
|
476
533
|
},
|
|
477
|
-
mounted
|
|
534
|
+
mounted() {
|
|
478
535
|
console.log('XForm mounted, setting up flex watcher')
|
|
479
536
|
this.setupFlexWatcher()
|
|
480
537
|
},
|
|
481
|
-
beforeDestroy
|
|
538
|
+
beforeDestroy() {
|
|
482
539
|
// 清理watcher
|
|
483
540
|
if (this._flexWatcher) {
|
|
484
541
|
this._flexWatcher()
|
|
485
542
|
}
|
|
486
|
-
}
|
|
543
|
+
}
|
|
487
544
|
}
|
|
488
545
|
</script>
|
|
489
546
|
<style lang="less" scoped>
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<a-col :style="computedStyles">
|
|
3
|
-
<div
|
|
4
|
-
class="x-form-col-wrapper"
|
|
5
|
-
:style="computedWrapperStyles"
|
|
6
|
-
>
|
|
3
|
+
<div class="x-form-col-wrapper" :style="computedWrapperStyles">
|
|
7
4
|
<slot></slot>
|
|
8
5
|
</div>
|
|
9
6
|
</a-col>
|
|
@@ -15,7 +12,7 @@ const BREAKPOINTS = {
|
|
|
15
12
|
sm: 768,
|
|
16
13
|
md: 992,
|
|
17
14
|
lg: 1200,
|
|
18
|
-
xl: 1600
|
|
15
|
+
xl: 1600
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
const defaultFlex = {
|
|
@@ -24,10 +21,10 @@ const defaultFlex = {
|
|
|
24
21
|
md: 8, // 中屏(768px-992px):3个/行
|
|
25
22
|
lg: 6, // 大屏(992px-1200px):4个/行
|
|
26
23
|
xl: 6, // 超大屏(1200px-1600px):4个/行
|
|
27
|
-
xxl: 4
|
|
24
|
+
xxl: 4 // 超超大屏(>1600px):4个/行
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
function debounce
|
|
27
|
+
function debounce(fn, delay) {
|
|
31
28
|
let timeout = null
|
|
32
29
|
return function (...args) {
|
|
33
30
|
if (timeout) clearTimeout(timeout)
|
|
@@ -42,64 +39,73 @@ export default {
|
|
|
42
39
|
props: {
|
|
43
40
|
flex: {
|
|
44
41
|
type: Object,
|
|
45
|
-
default: () => defaultFlex
|
|
42
|
+
default: () => defaultFlex
|
|
46
43
|
},
|
|
47
44
|
occupyCol: {
|
|
48
45
|
type: Number,
|
|
49
|
-
default: 1
|
|
46
|
+
default: 1
|
|
50
47
|
},
|
|
51
48
|
layout: {
|
|
52
49
|
type: String,
|
|
53
|
-
default: 'horizontal'
|
|
50
|
+
default: 'horizontal'
|
|
54
51
|
},
|
|
55
52
|
labelCol: {
|
|
56
53
|
type: Object,
|
|
57
|
-
default: () => {
|
|
54
|
+
default: () => {
|
|
55
|
+
return { span: 8 }
|
|
56
|
+
}
|
|
58
57
|
}
|
|
59
58
|
},
|
|
60
59
|
computed: {
|
|
61
|
-
computedFlex
|
|
60
|
+
computedFlex() {
|
|
62
61
|
const parentWidth = this.parentWidth
|
|
63
62
|
return this.getFlex(parentWidth, this.flex)
|
|
64
63
|
},
|
|
65
|
-
computedWrapperStyles
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// 2.
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
computedWrapperStyles() {
|
|
65
|
+
// 1. 强制使用默认flex配置计算label宽度(确保所有字段label宽度统一)
|
|
66
|
+
const singleFlex = this.getFlex(this.parentWidth, defaultFlex)
|
|
67
|
+
|
|
68
|
+
// 2. 计算单列(occupyCol=1)的列数
|
|
69
|
+
const columnsCount = 24 / singleFlex
|
|
70
|
+
|
|
71
|
+
// 3. 计算单列的基准列宽(所有表单项统一使用此宽度计算label)
|
|
72
|
+
const baseColumnWidth = this.parentWidth / columnsCount - (columnsCount - 1) * 16
|
|
73
|
+
|
|
74
|
+
// 4. 计算label宽度(统一基于单列宽度,不考虑occupyCol)
|
|
75
|
+
const labelWidth = Math.max(baseColumnWidth * (this.labelCol.span / 24), 80)
|
|
76
|
+
|
|
77
|
+
// 5. 计算偏移量
|
|
74
78
|
const offset = this.labelCol.offset ? (this.labelCol.offset / 24) * 100 : 0
|
|
79
|
+
|
|
75
80
|
if (this.layout === 'vertical') {
|
|
76
81
|
return {
|
|
77
82
|
'--form-label-width': '',
|
|
78
|
-
'--form-offset': ''
|
|
83
|
+
'--form-offset': ''
|
|
79
84
|
}
|
|
80
85
|
}
|
|
86
|
+
|
|
81
87
|
return {
|
|
82
88
|
'--form-label-width': `${labelWidth}px`,
|
|
83
|
-
'--form-offset': `${offset}
|
|
89
|
+
'--form-offset': `${offset}%`
|
|
84
90
|
}
|
|
85
91
|
},
|
|
86
|
-
computedStyles
|
|
92
|
+
computedStyles() {
|
|
87
93
|
const realFlex = Math.min(this.computedFlex * this.occupyCol, 24)
|
|
88
94
|
const flexValue = (realFlex / 24) * 100
|
|
89
95
|
|
|
90
96
|
return {
|
|
91
97
|
flex: `0 0 ${flexValue}%`,
|
|
92
|
-
maxWidth: `${flexValue}
|
|
98
|
+
maxWidth: `${flexValue}%`
|
|
93
99
|
}
|
|
94
|
-
}
|
|
100
|
+
}
|
|
95
101
|
},
|
|
96
|
-
data
|
|
102
|
+
data() {
|
|
97
103
|
return {
|
|
98
|
-
parentWidth: 0
|
|
104
|
+
parentWidth: 0
|
|
99
105
|
}
|
|
100
106
|
},
|
|
101
107
|
methods: {
|
|
102
|
-
getFlex
|
|
108
|
+
getFlex(parentWidth, flex = defaultFlex) {
|
|
103
109
|
if (parentWidth === 0) {
|
|
104
110
|
return flex.md
|
|
105
111
|
}
|
|
@@ -109,18 +115,18 @@ export default {
|
|
|
109
115
|
if (parentWidth < BREAKPOINTS.lg) return flex.lg
|
|
110
116
|
if (parentWidth < BREAKPOINTS.xl) return flex.xl
|
|
111
117
|
return flex.xxl
|
|
112
|
-
}
|
|
118
|
+
}
|
|
113
119
|
},
|
|
114
|
-
mounted
|
|
120
|
+
mounted() {
|
|
115
121
|
// 根据父容器宽度响应式
|
|
116
122
|
this.$nextTick(() => {
|
|
117
123
|
const container = this.$el.parentNode
|
|
118
124
|
this.parentWidth = container.offsetWidth
|
|
119
|
-
const updateWidth = debounce(
|
|
125
|
+
const updateWidth = debounce(width => {
|
|
120
126
|
this.parentWidth = width
|
|
121
127
|
}, 100)
|
|
122
128
|
|
|
123
|
-
this.resizeObserver = new ResizeObserver(
|
|
129
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
124
130
|
for (const entry of entries) {
|
|
125
131
|
updateWidth(entry.contentRect.width)
|
|
126
132
|
}
|
|
@@ -128,11 +134,11 @@ export default {
|
|
|
128
134
|
this.resizeObserver.observe(container)
|
|
129
135
|
})
|
|
130
136
|
},
|
|
131
|
-
beforeUnmount
|
|
137
|
+
beforeUnmount() {
|
|
132
138
|
if (this.resizeObserver) {
|
|
133
139
|
this.resizeObserver.disconnect()
|
|
134
140
|
}
|
|
135
|
-
}
|
|
141
|
+
}
|
|
136
142
|
}
|
|
137
143
|
</script>
|
|
138
144
|
|
|
@@ -140,7 +146,8 @@ export default {
|
|
|
140
146
|
.x-form-col-wrapper {
|
|
141
147
|
:deep(.ant-form-item) {
|
|
142
148
|
.ant-form-item-label {
|
|
143
|
-
|
|
149
|
+
width: var(--form-label-width);
|
|
150
|
+
min-width: var(--form-label-width);
|
|
144
151
|
}
|
|
145
152
|
.ant-form-item-control-wrapper {
|
|
146
153
|
width: calc(100% - var(--form-label-width) - var(--form-offset) - var(--form-offset));
|
|
@@ -1032,7 +1032,10 @@ export default {
|
|
|
1032
1032
|
if (this.tableShowMode === 'popup') {
|
|
1033
1033
|
this.formQueryLoading = true
|
|
1034
1034
|
}
|
|
1035
|
-
|
|
1035
|
+
// 调用 XForm 的 submitForm 方法
|
|
1036
|
+
// 这会触发 emit 'onSubmit',然后走现有的 onSearchSubmit 逻辑
|
|
1037
|
+
// 最终通过 setQueryForm → refresh → loadData 进行数据处理
|
|
1038
|
+
this.$refs.xForm.submitForm(conditionParams)
|
|
1036
1039
|
},
|
|
1037
1040
|
/**
|
|
1038
1041
|
* 向外暴露 resetForm 函数
|
|
@@ -55,13 +55,13 @@ routerResource.example = {
|
|
|
55
55
|
// component: () => import('@vue2-client/base-client/components/common/XDescriptions/demo.vue'),
|
|
56
56
|
// component: () => import('@vue2-client/base-client/components/his/HChart/demo.vue'),
|
|
57
57
|
// component: () => import('@vue2-client/pages/WorkflowDetail/WorkFlowDemo.vue'),
|
|
58
|
-
component: () => import('@vue2-client/base-client/components/common/XFormTable/demo.vue')
|
|
58
|
+
// component: () => import('@vue2-client/base-client/components/common/XFormTable/demo.vue')
|
|
59
59
|
// component: () => import('@vue2-client/base-client/components/common/ImagePreviewModal/demo.vue'),
|
|
60
60
|
// component: () => import('@vue2-client/components/xScrollBox/example.vue'),
|
|
61
61
|
// component: () => import('@vue2-client/pages/WorkflowDetail/WorkFlowDemo.vue'),
|
|
62
62
|
// component: () => import('@vue2-client/pages/addressSelect/addressDemo.vue'),
|
|
63
63
|
// component: () => import('@vue2-client/base-client/components/common/XDescriptions/demo.vue'),
|
|
64
|
-
|
|
64
|
+
component: () => import('@vue2-client/base-client/components/common/XAddNativeForm/demo.vue')
|
|
65
65
|
// component: () => import('@vue2-client/base-client/components/common/XFormGroup/demo.vue'),
|
|
66
66
|
// component: () => import('@vue2-client/base-client/components/common/XReport/XReportDemo.vue'),
|
|
67
67
|
// component: () => import('@vue2-client/base-client/components/common/XReportGrid/XReportDemo.vue'),
|
package/vue.config.js
CHANGED
|
@@ -62,11 +62,6 @@ module.exports = {
|
|
|
62
62
|
target: 'http://127.0.0.1:9012',
|
|
63
63
|
changeOrigin: true
|
|
64
64
|
},
|
|
65
|
-
'/api/af-revenue/': {
|
|
66
|
-
pathRewrite: { '^/api/af-revenue/': '/' },
|
|
67
|
-
target: 'http://127.0.0.1:9026',
|
|
68
|
-
changeOrigin: true
|
|
69
|
-
},
|
|
70
65
|
// '/api/af-system/resource': {
|
|
71
66
|
// pathRewrite: { '^/api/af-system': '/' },
|
|
72
67
|
// target: testUpload,
|
|
@@ -132,7 +127,7 @@ module.exports = {
|
|
|
132
127
|
target: OSSServerDev,
|
|
133
128
|
pathRewrite: { '^/oss': '/' },
|
|
134
129
|
changeOrigin: true
|
|
135
|
-
}
|
|
130
|
+
}
|
|
136
131
|
},
|
|
137
132
|
client: {
|
|
138
133
|
overlay: false
|
|
@@ -147,19 +142,17 @@ module.exports = {
|
|
|
147
142
|
configureWebpack: config => {
|
|
148
143
|
config.devtool = 'inline-source-map'
|
|
149
144
|
// 忽略.md文件
|
|
150
|
-
config.module.rules.push(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
)
|
|
145
|
+
config.module.rules.push({
|
|
146
|
+
test: /\.md$/,
|
|
147
|
+
exclude: /node_modules/,
|
|
148
|
+
use: 'ignore-loader'
|
|
149
|
+
})
|
|
157
150
|
config.context = path.resolve(__dirname, './')
|
|
158
151
|
config.resolve = {
|
|
159
152
|
extensions: ['.js', '.vue', '.json'],
|
|
160
153
|
alias: {
|
|
161
154
|
'@vue2-client': path.resolve('src'),
|
|
162
|
-
'@': path.resolve('src')
|
|
155
|
+
'@': path.resolve('src')
|
|
163
156
|
}
|
|
164
157
|
}
|
|
165
158
|
config.entry.app = ['core-js/stable', 'regenerator-runtime/runtime', 'whatwg-fetch', './src/main.js']
|
|
@@ -177,23 +170,26 @@ module.exports = {
|
|
|
177
170
|
)
|
|
178
171
|
}
|
|
179
172
|
// Ignore all locale files of moment.js
|
|
180
|
-
config.plugins.push(new webpack.IgnorePlugin({
|
|
181
|
-
resourceRegExp: /^\.\/locale$/,
|
|
182
|
-
contextRegExp: /moment$/
|
|
183
|
-
}))
|
|
184
|
-
|
|
185
173
|
config.plugins.push(
|
|
174
|
+
new webpack.IgnorePlugin({
|
|
175
|
+
resourceRegExp: /^\.\/locale$/,
|
|
176
|
+
contextRegExp: /moment$/
|
|
177
|
+
})
|
|
186
178
|
)
|
|
187
179
|
|
|
180
|
+
config.plugins.push()
|
|
181
|
+
|
|
188
182
|
// 生产环境下将资源压缩成gzip格式
|
|
189
183
|
if (isProd) {
|
|
190
184
|
// add `CompressionWebpack` plugin to webpack plugins
|
|
191
|
-
config.plugins.push(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
185
|
+
config.plugins.push(
|
|
186
|
+
new CompressionWebpackPlugin({
|
|
187
|
+
algorithm: 'gzip',
|
|
188
|
+
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
|
|
189
|
+
threshold: 10240,
|
|
190
|
+
minRatio: 0.8
|
|
191
|
+
})
|
|
192
|
+
)
|
|
197
193
|
}
|
|
198
194
|
// if prod, add externals
|
|
199
195
|
// if (isProd) {
|
|
@@ -203,31 +199,33 @@ module.exports = {
|
|
|
203
199
|
chainWebpack: config => {
|
|
204
200
|
// 生产环境下关闭css压缩的 colormin 项,因为此项优化与主题色替换功能冲突
|
|
205
201
|
if (isProd) {
|
|
206
|
-
config.optimization.minimizer('css').use(CssMinimizerPlugin, [
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
202
|
+
config.optimization.minimizer('css').use(CssMinimizerPlugin, [
|
|
203
|
+
{
|
|
204
|
+
minimizerOptions: {
|
|
205
|
+
preset: [
|
|
206
|
+
'default',
|
|
207
|
+
{
|
|
208
|
+
discardComments: { removeAll: true },
|
|
209
|
+
colormin: false
|
|
210
|
+
}
|
|
211
|
+
],
|
|
212
|
+
ignoreOrder: true
|
|
213
|
+
}
|
|
216
214
|
}
|
|
217
|
-
|
|
215
|
+
])
|
|
218
216
|
}
|
|
219
217
|
config.resolve.alias.set('@vue2-client', path.resolve(__dirname, 'src'))
|
|
220
218
|
},
|
|
221
219
|
css: {
|
|
222
220
|
extract: !isProd
|
|
223
221
|
? {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
filename: 'css/[name].css',
|
|
223
|
+
chunkFilename: 'css/[name].css',
|
|
224
|
+
ignoreOrder: true
|
|
225
|
+
}
|
|
228
226
|
: {
|
|
229
|
-
|
|
230
|
-
|
|
227
|
+
ignoreOrder: true
|
|
228
|
+
},
|
|
231
229
|
loaderOptions: {
|
|
232
230
|
less: {
|
|
233
231
|
lessOptions: {
|