cloud-web-corejs 1.0.54-dev.678 → 1.0.54-dev.679

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.
Files changed (22) hide show
  1. package/package.json +2 -1
  2. package/src/components/baseArea/index.vue +665 -0
  3. package/src/components/xform/form-designer/form-widget/field-widget/area-select-widget.vue +158 -0
  4. package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaDataType-editor.vue +24 -0
  5. package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaName-editor.vue +20 -0
  6. package/src/components/xform/form-designer/setting-panel/propertyRegister.js +2 -0
  7. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +52 -0
  8. package/src/components/xform/form-render/container-item/data-table-mixin.js +4 -0
  9. package/src/components/xform/form-render/indexMixin.js +34 -0
  10. package/src/components/xform/lang/en-US.js +7 -0
  11. package/src/components/xform/lang/zh-CN.js +7 -0
  12. package/src/index.js +4 -0
  13. package/src/layout/components/Sidebar/default.vue +1 -1
  14. package/src/views/bd/setting/formVersion/compareBasicSection.vue +6 -7
  15. package/src/views/bd/setting/formVersion/compareCodeSection.vue +21 -17
  16. package/src/views/bd/setting/formVersion/compareContMixin.scss +14 -20
  17. package/src/views/bd/setting/formVersion/compareDialog.vue +2 -2
  18. package/src/views/bd/setting/formVersion/ftHistoryDialog.vue +3 -3
  19. package/src/views/bd/setting/formVersion/reverButton.vue +1 -1
  20. package/src/views/bd/setting/formVersion/tableDetailDiff.js +3 -2
  21. package/src/views/user/form/vform/designer.vue +3 -1
  22. package/src/views/user/form/vform/formFieldMapping.js +2 -3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloud-web-corejs",
3
3
  "private": false,
4
- "version": "1.0.54-dev.678",
4
+ "version": "1.0.54-dev.679",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "lint": "eslint --ext .js,.vue src",
@@ -122,6 +122,7 @@
122
122
  "src/components/advancedSearchDialog",
123
123
  "src/components/baseAlert",
124
124
  "src/components/baseAttachment",
125
+ "src/components/baseArea",
125
126
  "src/components/baseInputBatch",
126
127
  "src/components/baseInputExport",
127
128
  "src/components/baseInputNumber",
@@ -0,0 +1,665 @@
1
+ <template>
2
+ <div class="base-area">
3
+ <el-popover
4
+ v-model="popoverVisible"
5
+ placement="bottom-start"
6
+ trigger="click"
7
+ popper-class="base-area-popover"
8
+ :width="popoverWidth"
9
+ :disabled="disabled || readonly"
10
+ @show="handlePopoverShow"
11
+ @hide="handlePopoverHide"
12
+ >
13
+ <div class="base-area-panel">
14
+ <div class="base-area-search">
15
+ <el-input
16
+ ref="searchInputRef"
17
+ v-model="searchKeyword"
18
+ class="base-area-search-input"
19
+ size="small"
20
+ clearable
21
+ :placeholder="searchPlaceholder"
22
+ @input="handleSearchInput"
23
+ @clear="handleSearchClear"
24
+ @focus="searchDropdownVisible = true"
25
+ />
26
+ <transition name="base-area-fade">
27
+ <div
28
+ v-show="showSearchDropdown"
29
+ class="base-area-search-dropdown"
30
+ v-loading="searchLoading"
31
+ >
32
+ <div
33
+ v-for="item in searchList"
34
+ :key="'search-' + item.id"
35
+ class="base-area-result-item"
36
+ :class="{ on: value === item.id }"
37
+ @mousedown.prevent
38
+ @click="selectSearchItem(item)"
39
+ >
40
+ {{ item.fullName || item.name }}
41
+ </div>
42
+ <div
43
+ v-if="!searchLoading && !searchList.length"
44
+ class="base-area-dropdown-empty"
45
+ >
46
+ {{ emptyText }}
47
+ </div>
48
+ </div>
49
+ </transition>
50
+ </div>
51
+ <div class="base-area-tabs">
52
+ <span
53
+ v-for="(tab, index) in tabs"
54
+ :key="index"
55
+ class="base-area-tab"
56
+ :class="{
57
+ active: activeLevel === index + 1,
58
+ selected: !!tab.selected,
59
+ disabled: !isTabEnabled(index + 1),
60
+ }"
61
+ @click="switchLevel(index + 1)"
62
+ >{{ getTabLabel(tab, index) }}</span>
63
+ </div>
64
+ <div class="base-area-grid" v-loading="browseLoading">
65
+ <div
66
+ v-for="item in pageItems"
67
+ :key="item.id"
68
+ class="base-area-item"
69
+ :class="{ on: isSelected(item) }"
70
+ @click="selectItem(item)"
71
+ >
72
+ <span>{{ item.name }}</span>
73
+ </div>
74
+ <div v-if="!browseLoading && !pageItems.length" class="base-area-empty">
75
+ {{ emptyText }}
76
+ </div>
77
+ </div>
78
+ <div class="base-area-pagination">
79
+ <el-button
80
+ size="mini"
81
+ :disabled="currentPage <= 1"
82
+ @click="prevPage"
83
+ >
84
+ <i class="el-icon-arrow-left"></i>
85
+ </el-button>
86
+ <el-button
87
+ size="mini"
88
+ type="primary"
89
+ :disabled="!hasNextPage"
90
+ @click="nextPage"
91
+ >
92
+ <i class="el-icon-arrow-right"></i>
93
+ </el-button>
94
+ </div>
95
+ </div>
96
+ <div slot="reference" class="base-area-trigger">
97
+ <el-input
98
+ ref="inputRef"
99
+ class="base-area-input"
100
+ :class="{ 'is-focus': referenceFocused }"
101
+ :value="displayText"
102
+ :size="size"
103
+ :disabled="disabled"
104
+ :placeholder="placeholder"
105
+ readonly
106
+ @focus="referenceFocused = true"
107
+ @blur="referenceFocused = false"
108
+ >
109
+ <i
110
+ v-if="showClearIcon"
111
+ slot="suffix"
112
+ class="el-input__icon el-icon-circle-close base-area-clear"
113
+ @mousedown.prevent
114
+ @click.stop="handleClear"
115
+ />
116
+ </el-input>
117
+ </div>
118
+ </el-popover>
119
+ </div>
120
+ </template>
121
+
122
+ <script>
123
+ const LEVEL_LABELS = ["省份", "城市", "区县", "乡镇"];
124
+ const PAGE_SIZE = 28;
125
+ const SEARCH_DEBOUNCE = 300;
126
+
127
+ export default {
128
+ name: "baseArea",
129
+ props: {
130
+ value: {
131
+ type: [String, Number],
132
+ default: null,
133
+ },
134
+ labelValue: {
135
+ type: String,
136
+ default: null,
137
+ },
138
+ maxLevel: {
139
+ type: Number,
140
+ default: 4,
141
+ },
142
+ locale: {
143
+ type: String,
144
+ default: null,
145
+ },
146
+ disabled: {
147
+ type: Boolean,
148
+ default: false,
149
+ },
150
+ readonly: {
151
+ type: Boolean,
152
+ default: false,
153
+ },
154
+ clearable: {
155
+ type: Boolean,
156
+ default: true,
157
+ },
158
+ placeholder: {
159
+ type: String,
160
+ default: "请选择地区",
161
+ },
162
+ searchPlaceholder: {
163
+ type: String,
164
+ default: "请输入地区名称",
165
+ },
166
+ emptyText: {
167
+ type: String,
168
+ default: "暂无匹配地区",
169
+ },
170
+ size: {
171
+ type: String,
172
+ default: "small",
173
+ },
174
+ popoverWidth: {
175
+ type: Number,
176
+ default: 630,
177
+ },
178
+ },
179
+ data() {
180
+ return {
181
+ popoverVisible: false,
182
+ searchKeyword: "",
183
+ searchList: [],
184
+ selectedPath: [],
185
+ activeLevel: 1,
186
+ levelItems: [],
187
+ browseLoading: false,
188
+ searchLoading: false,
189
+ searchDropdownVisible: false,
190
+ referenceFocused: false,
191
+ currentPage: 1,
192
+ searchTimer: null,
193
+ };
194
+ },
195
+ computed: {
196
+ hasSearchKeyword() {
197
+ return !!(this.searchKeyword || "").trim();
198
+ },
199
+ showSearchDropdown() {
200
+ return this.searchDropdownVisible && this.hasSearchKeyword;
201
+ },
202
+ displayText() {
203
+ if (this.labelValue) {
204
+ return this.labelValue;
205
+ }
206
+ if (this.selectedPath.length) {
207
+ const last = this.selectedPath[this.selectedPath.length - 1];
208
+ return last.fullName || last.name || "";
209
+ }
210
+ return "";
211
+ },
212
+ tabs() {
213
+ const tabs = [];
214
+ for (let i = 0; i < this.maxLevel; i++) {
215
+ tabs.push({
216
+ level: i + 1,
217
+ label: LEVEL_LABELS[i] || `第${i + 1}级`,
218
+ selected: this.selectedPath[i] || null,
219
+ });
220
+ }
221
+ return tabs;
222
+ },
223
+ pageItems() {
224
+ const start = (this.currentPage - 1) * PAGE_SIZE;
225
+ return this.levelItems.slice(start, start + PAGE_SIZE);
226
+ },
227
+ hasNextPage() {
228
+ return this.currentPage * PAGE_SIZE < this.levelItems.length;
229
+ },
230
+ showClearIcon() {
231
+ return (
232
+ this.clearable &&
233
+ !this.readonly &&
234
+ !this.disabled &&
235
+ !!this.displayText
236
+ );
237
+ },
238
+ },
239
+ watch: {
240
+ value(val) {
241
+ if (!val) {
242
+ this.resetBrowseState(false);
243
+ }
244
+ },
245
+ },
246
+ beforeDestroy() {
247
+ clearTimeout(this.searchTimer);
248
+ },
249
+ methods: {
250
+ getTabLabel(tab, index) {
251
+ if (tab.selected) {
252
+ if (index === this.selectedPath.length - 1 && tab.selected.fullName) {
253
+ return tab.selected.fullName;
254
+ }
255
+ return tab.selected.name;
256
+ }
257
+ return tab.label;
258
+ },
259
+ isSelected(item) {
260
+ const current = this.selectedPath[this.activeLevel - 1];
261
+ return current && current.id === item.id;
262
+ },
263
+ isTabEnabled(level) {
264
+ return level === 1 || this.selectedPath.length >= level - 1;
265
+ },
266
+ handlePopoverShow() {
267
+ this.$nextTick(() => {
268
+ this.$refs.searchInputRef && this.$refs.searchInputRef.focus();
269
+ });
270
+ if (!this.levelItems.length) {
271
+ this.loadLevelItems(this.getParentId());
272
+ }
273
+ },
274
+ handlePopoverHide() {
275
+ this.searchKeyword = "";
276
+ this.searchList = [];
277
+ this.searchDropdownVisible = false;
278
+ },
279
+ handleSearchInput() {
280
+ const keyword = (this.searchKeyword || "").trim();
281
+ clearTimeout(this.searchTimer);
282
+ this.searchDropdownVisible = !!keyword;
283
+ if (!keyword) {
284
+ this.handleSearchClear();
285
+ return;
286
+ }
287
+ this.searchTimer = setTimeout(() => {
288
+ this.doSearch(keyword);
289
+ }, SEARCH_DEBOUNCE);
290
+ },
291
+ handleSearchClear() {
292
+ this.searchList = [];
293
+ this.searchDropdownVisible = false;
294
+ },
295
+ doSearch(keyword) {
296
+ this.searchLoading = true;
297
+ this.$http({
298
+ url: USER_PREFIX + "/area/listPage",
299
+ method: "post",
300
+ data: {
301
+ name: keyword,
302
+ enabled: true,
303
+ locale: this.locale || null,
304
+ pageNum: 1,
305
+ pageSize: 200,
306
+ },
307
+ success: (res) => {
308
+ this.searchList = res.objx?.records || res.objx || [];
309
+ this.searchLoading = false;
310
+ },
311
+ error: () => {
312
+ this.searchList = [];
313
+ this.searchLoading = false;
314
+ },
315
+ });
316
+ },
317
+ getParentId() {
318
+ if (this.activeLevel <= 1) {
319
+ return 0;
320
+ }
321
+ const parent = this.selectedPath[this.activeLevel - 2];
322
+ return parent ? parent.id : 0;
323
+ },
324
+ loadLevelItems(parentId) {
325
+ this.browseLoading = true;
326
+ this.$http({
327
+ url: USER_PREFIX + "/area/getChildren",
328
+ method: "post",
329
+ data: {
330
+ id: parentId,
331
+ locale: this.locale || null,
332
+ enabled: true,
333
+ },
334
+ success: (res) => {
335
+ this.levelItems = res.objx || [];
336
+ this.browseLoading = false;
337
+ },
338
+ error: () => {
339
+ this.levelItems = [];
340
+ this.browseLoading = false;
341
+ },
342
+ });
343
+ },
344
+ switchLevel(level) {
345
+ if (level > this.maxLevel || !this.isTabEnabled(level)) {
346
+ return;
347
+ }
348
+ this.activeLevel = level;
349
+ this.currentPage = 1;
350
+ if (level <= this.selectedPath.length) {
351
+ this.selectedPath = this.selectedPath.slice(0, level - 1);
352
+ }
353
+ this.loadLevelItems(this.getParentId());
354
+ },
355
+ selectSearchItem(item) {
356
+ this.applySelection(item);
357
+ this.popoverVisible = false;
358
+ },
359
+ selectItem(item) {
360
+ if (!this.isTabEnabled(this.activeLevel)) {
361
+ return;
362
+ }
363
+ const level = this.activeLevel;
364
+ this.selectedPath = this.selectedPath.slice(0, level - 1);
365
+ this.selectedPath.push(item);
366
+ if (level >= this.maxLevel) {
367
+ this.applySelection(item);
368
+ this.popoverVisible = false;
369
+ return;
370
+ }
371
+ this.activeLevel = level + 1;
372
+ this.currentPage = 1;
373
+ this.loadLevelItems(item.id);
374
+ },
375
+ applySelection(item) {
376
+ const label = item.fullName || item.name || "";
377
+ this.$emit("input", item.id);
378
+ this.$emit("update:labelValue", label);
379
+ this.$emit("change", item);
380
+ },
381
+ handleClear() {
382
+ this.resetBrowseState(true);
383
+ this.popoverVisible = false;
384
+ },
385
+ resetBrowseState(emitEvent) {
386
+ this.searchKeyword = "";
387
+ this.searchList = [];
388
+ this.selectedPath = [];
389
+ this.activeLevel = 1;
390
+ this.currentPage = 1;
391
+ this.levelItems = [];
392
+ if (emitEvent) {
393
+ this.$emit("input", null);
394
+ this.$emit("update:labelValue", null);
395
+ this.$emit("change", null);
396
+ }
397
+ },
398
+ prevPage() {
399
+ if (this.currentPage > 1) {
400
+ this.currentPage -= 1;
401
+ }
402
+ },
403
+ nextPage() {
404
+ if (this.hasNextPage) {
405
+ this.currentPage += 1;
406
+ }
407
+ },
408
+ },
409
+ };
410
+ </script>
411
+
412
+ <style lang="scss" scoped>
413
+ @import "~@/styles/variables.scss";
414
+
415
+ .base-area {
416
+ width: 100%;
417
+ display: block;
418
+ box-sizing: border-box;
419
+ }
420
+
421
+ .base-area-trigger {
422
+ display: block;
423
+ width: 100%;
424
+ box-sizing: border-box;
425
+ }
426
+
427
+ .base-area-input {
428
+ width: 100%;
429
+ cursor: pointer;
430
+
431
+ .base-area-clear {
432
+ cursor: pointer;
433
+ display: none;
434
+ }
435
+
436
+ &:hover .base-area-clear,
437
+ &.is-focus .base-area-clear {
438
+ display: inline-block;
439
+ }
440
+ }
441
+
442
+ .base-area-panel {
443
+ padding: 4px 0 0;
444
+ overflow: visible;
445
+ }
446
+
447
+ .base-area-search {
448
+ position: relative;
449
+ margin-bottom: 8px;
450
+ z-index: 2;
451
+ }
452
+
453
+ .base-area-search-dropdown {
454
+ position: absolute;
455
+ top: calc(100% + 4px);
456
+ left: 0;
457
+ right: 0;
458
+ max-height: 200px;
459
+ overflow-y: auto;
460
+ background: #fff;
461
+ border: 1px solid #e4e7ed;
462
+ border-radius: 4px;
463
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
464
+ z-index: 20;
465
+ }
466
+
467
+ .base-area-dropdown-empty {
468
+ padding: 12px 10px;
469
+ text-align: center;
470
+ color: #909399;
471
+ font-size: 12px;
472
+ }
473
+
474
+ .base-area-fade-enter-active,
475
+ .base-area-fade-leave-active {
476
+ transition: opacity 0.15s ease;
477
+ }
478
+
479
+ .base-area-fade-enter,
480
+ .base-area-fade-leave-to {
481
+ opacity: 0;
482
+ }
483
+
484
+ .base-area-result-item {
485
+ padding: 8px 10px;
486
+ font-size: 12px;
487
+ line-height: 1.4;
488
+ color: #606266;
489
+ cursor: pointer;
490
+ border-radius: 4px;
491
+
492
+ &:hover {
493
+ background: rgba($baseColor, 0.08);
494
+ color: $baseColor;
495
+ }
496
+
497
+ &.on {
498
+ background: rgba($baseColor, 0.12);
499
+ color: $baseColor;
500
+ }
501
+ }
502
+
503
+ .base-area-tabs {
504
+ display: flex;
505
+ flex-wrap: wrap;
506
+ width: 100%;
507
+ margin-bottom: 8px;
508
+ gap: 6px;
509
+ }
510
+
511
+ .base-area-tab {
512
+ flex: 1;
513
+ min-width: 0;
514
+ display: inline-block;
515
+ max-width: 100%;
516
+ padding: 0 10px;
517
+ height: 28px;
518
+ line-height: 28px;
519
+ border: 1px solid #eee;
520
+ border-radius: 4px;
521
+ font-size: 12px;
522
+ color: #606266;
523
+ cursor: pointer;
524
+ overflow: hidden;
525
+ text-overflow: ellipsis;
526
+ white-space: nowrap;
527
+
528
+ &.active {
529
+ background: $baseColor;
530
+ border-color: $baseColor;
531
+ color: #fff;
532
+ }
533
+
534
+ &.selected:not(.active) {
535
+ color: $baseColor;
536
+ border-color: rgba($baseColor, 0.35);
537
+ }
538
+
539
+ &.disabled {
540
+ color: #c0c4cc;
541
+ cursor: not-allowed;
542
+ background: #f5f7fa;
543
+ border-color: #eee;
544
+ pointer-events: none;
545
+ }
546
+ }
547
+
548
+ .base-area-grid {
549
+ display: flex;
550
+ flex-wrap: wrap;
551
+ min-height: 120px;
552
+ margin: 0 -4px;
553
+ }
554
+
555
+ .base-area-item {
556
+ width: calc(25% - 8px);
557
+ margin: 0 4px 8px;
558
+ padding: 0 10px;
559
+ height: 34px;
560
+ line-height: 34px;
561
+ border: 1px solid #eee;
562
+ border-radius: 8px;
563
+ font-size: 12px;
564
+ cursor: pointer;
565
+ overflow: hidden;
566
+ text-overflow: ellipsis;
567
+ white-space: nowrap;
568
+
569
+ &:hover {
570
+ color: $baseColor;
571
+ border-color: $baseColor;
572
+ }
573
+
574
+ &.on {
575
+ background: $baseColor;
576
+ border-color: $baseColor;
577
+ color: #fff;
578
+ }
579
+ }
580
+
581
+ .base-area-empty {
582
+ width: 100%;
583
+ padding: 24px 0;
584
+ text-align: center;
585
+ color: #909399;
586
+ font-size: 12px;
587
+ }
588
+
589
+ .base-area-pagination {
590
+ display: flex;
591
+ justify-content: space-between;
592
+ margin-top: 4px;
593
+ }
594
+ </style>
595
+
596
+ <style lang="scss">
597
+ @import "~@/styles/variables.scss";
598
+
599
+ /* el-popover 根节点为 inline span,需强制块级铺满 */
600
+ .base-area {
601
+ width: 100% !important;
602
+ display: block !important;
603
+ box-sizing: border-box;
604
+
605
+ > span {
606
+ display: block !important;
607
+ width: 100% !important;
608
+ box-sizing: border-box;
609
+ }
610
+
611
+ .el-popover__reference-wrapper,
612
+ .el-popover__reference,
613
+ .base-area-trigger {
614
+ display: block !important;
615
+ width: 100% !important;
616
+ box-sizing: border-box;
617
+ }
618
+
619
+ .base-area-input.el-input {
620
+ width: 100% !important;
621
+ display: block !important;
622
+ }
623
+
624
+ .base-area-input .base-area-clear {
625
+ cursor: pointer;
626
+ display: none;
627
+ }
628
+
629
+ .base-area-input:hover .base-area-clear,
630
+ .base-area-input.is-focus .base-area-clear {
631
+ display: inline-block;
632
+ }
633
+ }
634
+
635
+ .base-area-popover {
636
+ padding: 10px 12px;
637
+ overflow: visible;
638
+ box-sizing: border-box;
639
+
640
+ .base-area-panel {
641
+ width: 100%;
642
+ box-sizing: border-box;
643
+ }
644
+
645
+ .base-area-search {
646
+ width: 100%;
647
+ box-sizing: border-box;
648
+ }
649
+
650
+ .base-area-search-input,
651
+ .base-area-search .el-input {
652
+ width: 100% !important;
653
+ display: block;
654
+ box-sizing: border-box;
655
+ }
656
+
657
+ .base-area-tab.disabled {
658
+ color: #c0c4cc;
659
+ cursor: not-allowed;
660
+ background: #f5f7fa;
661
+ border-color: #eee;
662
+ pointer-events: none;
663
+ }
664
+ }
665
+ </style>