cloud-web-corejs 1.0.54-dev.681 → 1.0.54-dev.682
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/baseArea/index.vue +451 -101
- package/src/components/xform/form-designer/form-widget/field-widget/area-select-widget.vue +37 -15
- package/src/components/xform/form-designer/setting-panel/property-editor/field-area-select/areaDataType-editor.vue +1 -0
- package/src/components/xform/lang/en-US.js +1 -0
- package/src/components/xform/lang/zh-CN.js +1 -0
package/package.json
CHANGED
|
@@ -135,6 +135,8 @@
|
|
|
135
135
|
|
|
136
136
|
<script>
|
|
137
137
|
const LEVEL_LABELS = ["省份", "城市", "区县", "乡镇"];
|
|
138
|
+
const AREA_LEVEL_KEYS = ["province", "city", "district", "town"];
|
|
139
|
+
const MAX_AREA_DEPTH = 4;
|
|
138
140
|
const SEARCH_DEBOUNCE = 300;
|
|
139
141
|
|
|
140
142
|
export default {
|
|
@@ -188,10 +190,10 @@ export default {
|
|
|
188
190
|
type: Number,
|
|
189
191
|
default: 630,
|
|
190
192
|
},
|
|
191
|
-
/**
|
|
193
|
+
/** leaf: 绑定末级 id;path: 兼容旧版逗号分隔路径 */
|
|
192
194
|
valueFormat: {
|
|
193
195
|
type: String,
|
|
194
|
-
default: "
|
|
196
|
+
default: "leaf",
|
|
195
197
|
},
|
|
196
198
|
},
|
|
197
199
|
data() {
|
|
@@ -209,6 +211,9 @@ export default {
|
|
|
209
211
|
searchTimer: null,
|
|
210
212
|
syncToken: 0,
|
|
211
213
|
skipValueSync: false,
|
|
214
|
+
committedBrowseSnapshot: null,
|
|
215
|
+
committedBoundValue: null,
|
|
216
|
+
lastSelectionPayload: null,
|
|
212
217
|
};
|
|
213
218
|
},
|
|
214
219
|
computed: {
|
|
@@ -219,20 +224,20 @@ export default {
|
|
|
219
224
|
return this.searchDropdownVisible && this.hasSearchKeyword;
|
|
220
225
|
},
|
|
221
226
|
displayText() {
|
|
227
|
+
if (this.labelValue) {
|
|
228
|
+
return this.labelValue;
|
|
229
|
+
}
|
|
222
230
|
const pathLabel = this.selectedPath.length
|
|
223
231
|
? this.buildPathLabel(this.selectedPath)
|
|
224
232
|
: "";
|
|
225
233
|
if (this.popoverVisible && pathLabel) {
|
|
226
234
|
return pathLabel;
|
|
227
235
|
}
|
|
228
|
-
if (this.labelValue) {
|
|
229
|
-
return this.labelValue;
|
|
230
|
-
}
|
|
231
236
|
return pathLabel || "";
|
|
232
237
|
},
|
|
233
238
|
tabs() {
|
|
234
239
|
const tabs = [];
|
|
235
|
-
for (let i = 0; i < this.
|
|
240
|
+
for (let i = 0; i < this.browseLevelCount; i++) {
|
|
236
241
|
tabs.push({
|
|
237
242
|
level: i + 1,
|
|
238
243
|
label: LEVEL_LABELS[i] || `第${i + 1}级`,
|
|
@@ -254,10 +259,13 @@ export default {
|
|
|
254
259
|
},
|
|
255
260
|
canNextLevel() {
|
|
256
261
|
return (
|
|
257
|
-
this.activeLevel < this.
|
|
262
|
+
this.activeLevel < this.browseLevelCount &&
|
|
258
263
|
this.isTabEnabled(this.activeLevel + 1)
|
|
259
264
|
);
|
|
260
265
|
},
|
|
266
|
+
browseLevelCount() {
|
|
267
|
+
return Math.max(this.maxLevel, this.selectedPath.length, 1);
|
|
268
|
+
},
|
|
261
269
|
currentLevelLabel() {
|
|
262
270
|
return LEVEL_LABELS[this.activeLevel - 1] || `第${this.activeLevel}级`;
|
|
263
271
|
},
|
|
@@ -272,10 +280,6 @@ export default {
|
|
|
272
280
|
labelValue(val) {
|
|
273
281
|
if (!val && !this.value) {
|
|
274
282
|
this.resetBrowseState(false);
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
if (this.value && !this.isValueSynced(this.parseValueIds(this.value))) {
|
|
278
|
-
this.syncFromValue();
|
|
279
283
|
}
|
|
280
284
|
},
|
|
281
285
|
},
|
|
@@ -283,47 +287,79 @@ export default {
|
|
|
283
287
|
clearTimeout(this.searchTimer);
|
|
284
288
|
},
|
|
285
289
|
methods: {
|
|
290
|
+
getResolveDepthLimit(item) {
|
|
291
|
+
if (item && item.treePath) {
|
|
292
|
+
const ids = this.parseTreePathIds(item.treePath);
|
|
293
|
+
return Math.min(Math.max(ids.length, this.maxLevel, 1), MAX_AREA_DEPTH);
|
|
294
|
+
}
|
|
295
|
+
return MAX_AREA_DEPTH;
|
|
296
|
+
},
|
|
297
|
+
isPathResolvedForItem(path, item) {
|
|
298
|
+
if (!path || !path.length || !item || item.id == null) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
return this.getAreaId(path[path.length - 1]) == item.id;
|
|
302
|
+
},
|
|
286
303
|
isSearchItemActive(item) {
|
|
287
304
|
if (!item || this.value == null || this.value === "") {
|
|
288
305
|
return false;
|
|
289
306
|
}
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
307
|
+
const leafId = this.parseValueId(this.value);
|
|
308
|
+
if (leafId == null) {
|
|
292
309
|
return false;
|
|
293
310
|
}
|
|
294
|
-
return
|
|
311
|
+
return leafId == this.getAreaId(item);
|
|
295
312
|
},
|
|
296
|
-
|
|
313
|
+
parseValueId(val) {
|
|
297
314
|
if (val == null || val === "") {
|
|
298
|
-
return
|
|
315
|
+
return null;
|
|
299
316
|
}
|
|
300
317
|
const str = String(val).trim();
|
|
301
|
-
if (this.
|
|
302
|
-
|
|
318
|
+
if (this.isLegacyPathValue(str)) {
|
|
319
|
+
const parts = str.split(",").map((part) => part.trim()).filter(Boolean);
|
|
320
|
+
return parts.length ? parts[parts.length - 1] : null;
|
|
321
|
+
}
|
|
322
|
+
return str;
|
|
323
|
+
},
|
|
324
|
+
parseLegacyPathIds(val) {
|
|
325
|
+
if (val == null || val === "") {
|
|
326
|
+
return [];
|
|
303
327
|
}
|
|
304
|
-
return
|
|
328
|
+
return String(val)
|
|
329
|
+
.split(",")
|
|
330
|
+
.map((part) => part.trim())
|
|
331
|
+
.filter((part) => part !== "");
|
|
305
332
|
},
|
|
306
|
-
|
|
333
|
+
isLegacyPathValue(val) {
|
|
307
334
|
return (
|
|
308
335
|
this.valueFormat === "path" &&
|
|
309
336
|
val != null &&
|
|
310
|
-
String(val).includes(",")
|
|
337
|
+
String(val).includes(",") &&
|
|
338
|
+
!String(val).startsWith(",")
|
|
311
339
|
);
|
|
312
340
|
},
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
return
|
|
341
|
+
parseTreePathIds(treePath) {
|
|
342
|
+
if (treePath == null || treePath === "") {
|
|
343
|
+
return [];
|
|
316
344
|
}
|
|
317
|
-
|
|
318
|
-
.
|
|
319
|
-
.
|
|
320
|
-
|
|
345
|
+
return String(treePath)
|
|
346
|
+
.split(",")
|
|
347
|
+
.map((part) => part.trim())
|
|
348
|
+
.filter((part) => part !== "");
|
|
349
|
+
},
|
|
350
|
+
formatBoundValue(path, item) {
|
|
351
|
+
const last = item || (path && path.length ? path[path.length - 1] : null);
|
|
352
|
+
const leafId = this.getAreaId(last);
|
|
353
|
+
if (leafId == null) {
|
|
321
354
|
return null;
|
|
322
355
|
}
|
|
323
|
-
if (this.valueFormat === "
|
|
324
|
-
|
|
356
|
+
if (this.valueFormat === "path") {
|
|
357
|
+
const ids = (path || [])
|
|
358
|
+
.map((node) => this.getAreaId(node))
|
|
359
|
+
.filter((id) => id != null && id !== "");
|
|
360
|
+
return ids.length ? ids.join(",") : String(leafId);
|
|
325
361
|
}
|
|
326
|
-
return
|
|
362
|
+
return leafId;
|
|
327
363
|
},
|
|
328
364
|
getAreaId(item) {
|
|
329
365
|
if (!item) {
|
|
@@ -340,11 +376,14 @@ export default {
|
|
|
340
376
|
}
|
|
341
377
|
return null;
|
|
342
378
|
},
|
|
343
|
-
isValueSynced(
|
|
344
|
-
if (
|
|
379
|
+
isValueSynced(leafId) {
|
|
380
|
+
if (leafId == null || leafId === "" || !this.selectedPath.length) {
|
|
345
381
|
return false;
|
|
346
382
|
}
|
|
347
|
-
|
|
383
|
+
const currentLeaf = this.getAreaId(
|
|
384
|
+
this.selectedPath[this.selectedPath.length - 1]
|
|
385
|
+
);
|
|
386
|
+
return currentLeaf == leafId;
|
|
348
387
|
},
|
|
349
388
|
buildPathLabel(path) {
|
|
350
389
|
if (!path || !path.length) {
|
|
@@ -359,6 +398,92 @@ export default {
|
|
|
359
398
|
.filter((name) => !!name)
|
|
360
399
|
.join("");
|
|
361
400
|
},
|
|
401
|
+
createEmptyAreaPathResult(value) {
|
|
402
|
+
return {
|
|
403
|
+
value: value != null && value !== "" ? value : null,
|
|
404
|
+
label: null,
|
|
405
|
+
path: [],
|
|
406
|
+
province: null,
|
|
407
|
+
city: null,
|
|
408
|
+
district: null,
|
|
409
|
+
town: null,
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
formatAreaPathResult(value, path, label) {
|
|
413
|
+
const result = this.createEmptyAreaPathResult(value);
|
|
414
|
+
result.label =
|
|
415
|
+
label != null && label !== ""
|
|
416
|
+
? label
|
|
417
|
+
: this.buildPathLabel(path) || this.labelValue || null;
|
|
418
|
+
result.path = path || [];
|
|
419
|
+
(path || []).forEach((node, index) => {
|
|
420
|
+
const key = AREA_LEVEL_KEYS[index];
|
|
421
|
+
if (key && Object.prototype.hasOwnProperty.call(result, key)) {
|
|
422
|
+
result[key] = node;
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
return result;
|
|
426
|
+
},
|
|
427
|
+
async ensurePathDetail(path) {
|
|
428
|
+
const result = [];
|
|
429
|
+
for (let i = 0; i < path.length; i++) {
|
|
430
|
+
const node = path[i];
|
|
431
|
+
const id = this.getAreaId(node);
|
|
432
|
+
if (id != null) {
|
|
433
|
+
const detail = await this.fetchAreaById(id);
|
|
434
|
+
result.push(detail || node);
|
|
435
|
+
} else {
|
|
436
|
+
result.push(node);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return result;
|
|
440
|
+
},
|
|
441
|
+
async getAreaPath(value) {
|
|
442
|
+
const val = value !== undefined ? value : this.value;
|
|
443
|
+
if (val == null || val === "") {
|
|
444
|
+
return this.createEmptyAreaPathResult(null);
|
|
445
|
+
}
|
|
446
|
+
const leafId = this.getLeafIdFromValue(val);
|
|
447
|
+
let path = null;
|
|
448
|
+
if (
|
|
449
|
+
leafId != null &&
|
|
450
|
+
this.isValueSynced(leafId) &&
|
|
451
|
+
!this.shouldResyncBrowsePath() &&
|
|
452
|
+
this.selectedPath.length
|
|
453
|
+
) {
|
|
454
|
+
path = this.selectedPath.map((item) => ({ ...item }));
|
|
455
|
+
}
|
|
456
|
+
if (!path || !path.length) {
|
|
457
|
+
if (this.isLegacyPathValue(val)) {
|
|
458
|
+
path = await this.resolvePathByIds(this.parseLegacyPathIds(val));
|
|
459
|
+
} else if (leafId != null) {
|
|
460
|
+
const area = await this.fetchAreaById(leafId);
|
|
461
|
+
if (area) {
|
|
462
|
+
path = await this.resolveAreaPath(area);
|
|
463
|
+
} else {
|
|
464
|
+
path = [{ id: leafId, fullName: this.labelValue || undefined }];
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (!path || !path.length) {
|
|
469
|
+
return this.createEmptyAreaPathResult(val);
|
|
470
|
+
}
|
|
471
|
+
path = await this.ensurePathDetail(path);
|
|
472
|
+
return this.formatAreaPathResult(val, path);
|
|
473
|
+
},
|
|
474
|
+
hasDisplayLabel() {
|
|
475
|
+
return !!(this.labelValue && String(this.labelValue).trim());
|
|
476
|
+
},
|
|
477
|
+
getLeafIdFromValue(val) {
|
|
478
|
+
if (val == null || val === "") {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
if (this.isLegacyPathValue(val)) {
|
|
482
|
+
const ids = this.parseLegacyPathIds(val);
|
|
483
|
+
return ids.length ? ids[ids.length - 1] : null;
|
|
484
|
+
}
|
|
485
|
+
return this.parseValueId(val);
|
|
486
|
+
},
|
|
362
487
|
emitResolvedLabelIfNeeded() {
|
|
363
488
|
if (this.popoverVisible || this.labelValue) {
|
|
364
489
|
return;
|
|
@@ -385,11 +510,89 @@ export default {
|
|
|
385
510
|
return level === 1 || this.selectedPath.length >= level - 1;
|
|
386
511
|
},
|
|
387
512
|
handlePopoverShow() {
|
|
513
|
+
this.saveCommittedBrowseSnapshot();
|
|
514
|
+
this.$emit("popover-open");
|
|
388
515
|
this.$nextTick(() => {
|
|
389
516
|
this.$refs.searchInputRef && this.$refs.searchInputRef.focus();
|
|
390
517
|
});
|
|
391
518
|
this.initBrowseStateFromValue();
|
|
392
519
|
},
|
|
520
|
+
saveCommittedBrowseSnapshot() {
|
|
521
|
+
this.committedBoundValue = this.value;
|
|
522
|
+
this.committedBrowseSnapshot = {
|
|
523
|
+
boundValue: this.value,
|
|
524
|
+
leafId: this.getLeafIdFromValue(this.value),
|
|
525
|
+
selectedPath: this.selectedPath.map((item) => ({ ...item })),
|
|
526
|
+
activeLevel: this.activeLevel,
|
|
527
|
+
};
|
|
528
|
+
},
|
|
529
|
+
isSameBoundValue(a, b) {
|
|
530
|
+
const normalize = (val) => {
|
|
531
|
+
if (val == null || val === "") {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
return String(val);
|
|
535
|
+
};
|
|
536
|
+
return normalize(a) === normalize(b);
|
|
537
|
+
},
|
|
538
|
+
emitChangeIfCommitted() {
|
|
539
|
+
const snapshot = this.committedBrowseSnapshot;
|
|
540
|
+
if (!snapshot) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const oldVal = snapshot.boundValue;
|
|
544
|
+
const newVal = this.value;
|
|
545
|
+
if (!this.isSameBoundValue(oldVal, newVal)) {
|
|
546
|
+
const payload = this.lastSelectionPayload || {
|
|
547
|
+
value: newVal,
|
|
548
|
+
row: null,
|
|
549
|
+
label: this.labelValue,
|
|
550
|
+
};
|
|
551
|
+
this.$emit("change", {
|
|
552
|
+
value: payload.value != null ? payload.value : newVal,
|
|
553
|
+
row: payload.row || null,
|
|
554
|
+
label: payload.label != null ? payload.label : this.labelValue,
|
|
555
|
+
path: payload.path || [],
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
this.committedBoundValue = null;
|
|
559
|
+
this.lastSelectionPayload = null;
|
|
560
|
+
},
|
|
561
|
+
restoreBrowseStateIfUncommitted() {
|
|
562
|
+
const snapshot = this.committedBrowseSnapshot;
|
|
563
|
+
if (!snapshot) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (!this.isSameBoundValue(this.value, snapshot.boundValue)) {
|
|
567
|
+
this.levelItems = [];
|
|
568
|
+
this.committedBrowseSnapshot = null;
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
const committedLeafId = snapshot.leafId;
|
|
572
|
+
if (this.isValueSynced(committedLeafId)) {
|
|
573
|
+
this.levelItems = [];
|
|
574
|
+
this.committedBrowseSnapshot = null;
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (snapshot.selectedPath && snapshot.selectedPath.length) {
|
|
578
|
+
this.selectedPath = snapshot.selectedPath.map((item) => ({ ...item }));
|
|
579
|
+
this.activeLevel = snapshot.activeLevel;
|
|
580
|
+
} else if (committedLeafId) {
|
|
581
|
+
this.selectedPath = [
|
|
582
|
+
{
|
|
583
|
+
id: committedLeafId,
|
|
584
|
+
fullName: this.labelValue || undefined,
|
|
585
|
+
name: this.labelValue || undefined,
|
|
586
|
+
},
|
|
587
|
+
];
|
|
588
|
+
this.activeLevel = 1;
|
|
589
|
+
} else {
|
|
590
|
+
this.selectedPath = [];
|
|
591
|
+
this.activeLevel = 1;
|
|
592
|
+
}
|
|
593
|
+
this.levelItems = [];
|
|
594
|
+
this.committedBrowseSnapshot = null;
|
|
595
|
+
},
|
|
393
596
|
syncFromValue() {
|
|
394
597
|
if (this.skipValueSync) {
|
|
395
598
|
return;
|
|
@@ -399,34 +602,68 @@ export default {
|
|
|
399
602
|
this.resetBrowseState(false);
|
|
400
603
|
return;
|
|
401
604
|
}
|
|
402
|
-
|
|
403
|
-
|
|
605
|
+
if (!this.hasDisplayLabel()) {
|
|
606
|
+
this.resolveLabelFromValue();
|
|
607
|
+
}
|
|
608
|
+
},
|
|
609
|
+
async resolveLabelFromValue() {
|
|
610
|
+
const val = this.value;
|
|
611
|
+
if (!val || this.hasDisplayLabel()) {
|
|
404
612
|
return;
|
|
405
613
|
}
|
|
406
|
-
|
|
407
|
-
|
|
614
|
+
const leafId = this.getLeafIdFromValue(val);
|
|
615
|
+
if (leafId == null) {
|
|
408
616
|
return;
|
|
409
617
|
}
|
|
410
|
-
this.
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
618
|
+
const token = ++this.syncToken;
|
|
619
|
+
const area = await this.fetchAreaById(leafId);
|
|
620
|
+
if (token !== this.syncToken || this.hasDisplayLabel()) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
const label =
|
|
624
|
+
(area && area.fullName) ||
|
|
625
|
+
(area && area.name) ||
|
|
626
|
+
null;
|
|
627
|
+
if (label) {
|
|
628
|
+
this.$emit("update:labelValue", label);
|
|
629
|
+
}
|
|
414
630
|
},
|
|
415
|
-
|
|
416
|
-
if (!this.
|
|
631
|
+
shouldResyncBrowsePath() {
|
|
632
|
+
if (!this.labelValue || !this.selectedPath.length) {
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
const pathLabel = this.buildPathLabel(this.selectedPath);
|
|
636
|
+
return pathLabel !== String(this.labelValue).trim();
|
|
637
|
+
},
|
|
638
|
+
syncBrowseStateForPopover() {
|
|
639
|
+
const val = this.value;
|
|
640
|
+
if (!val) {
|
|
417
641
|
if (!this.levelItems.length) {
|
|
418
642
|
this.loadLevelItems(this.getParentId());
|
|
419
643
|
}
|
|
420
644
|
return;
|
|
421
645
|
}
|
|
422
|
-
const
|
|
423
|
-
if (
|
|
424
|
-
this.
|
|
646
|
+
const leafId = this.getLeafIdFromValue(val);
|
|
647
|
+
if (this.isValueSynced(leafId) && !this.shouldResyncBrowsePath()) {
|
|
648
|
+
const expectedActive = this.selectedPath.length || 1;
|
|
649
|
+
if (this.activeLevel !== expectedActive) {
|
|
650
|
+
this.activeLevel = expectedActive;
|
|
651
|
+
this.loadLevelItems(this.getParentId());
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
if (!this.levelItems.length) {
|
|
655
|
+
this.loadLevelItems(this.getParentId());
|
|
656
|
+
}
|
|
425
657
|
return;
|
|
426
658
|
}
|
|
427
|
-
if (
|
|
428
|
-
this.
|
|
659
|
+
if (this.isLegacyPathValue(val)) {
|
|
660
|
+
this.syncBrowseStateFromPathIds(this.parseLegacyPathIds(val));
|
|
661
|
+
return;
|
|
429
662
|
}
|
|
663
|
+
this.syncBrowseStateFromLeafId(leafId);
|
|
664
|
+
},
|
|
665
|
+
initBrowseStateFromValue() {
|
|
666
|
+
this.syncBrowseStateForPopover();
|
|
430
667
|
},
|
|
431
668
|
getAreaRequestData(extra = {}) {
|
|
432
669
|
return {
|
|
@@ -485,22 +722,36 @@ export default {
|
|
|
485
722
|
if (id == null || id === "") {
|
|
486
723
|
return Promise.resolve(null);
|
|
487
724
|
}
|
|
488
|
-
return
|
|
489
|
-
|
|
490
|
-
|
|
725
|
+
return new Promise((resolve) => {
|
|
726
|
+
this.$http({
|
|
727
|
+
url: USER_PREFIX + "/area/get",
|
|
728
|
+
method: "post",
|
|
729
|
+
data: this.getAreaRequestData({ id }),
|
|
730
|
+
success: (res) => {
|
|
731
|
+
const objx = res && res.objx;
|
|
732
|
+
if (objx && typeof objx === "object" && !Array.isArray(objx)) {
|
|
733
|
+
resolve(objx);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
resolve(null);
|
|
737
|
+
},
|
|
738
|
+
error: () => resolve(null),
|
|
739
|
+
});
|
|
740
|
+
});
|
|
491
741
|
},
|
|
492
742
|
isAreaObject(node) {
|
|
493
743
|
return node && typeof node === "object" && node.id != null;
|
|
494
744
|
},
|
|
495
|
-
buildAreaPath(item) {
|
|
745
|
+
buildAreaPath(item, depthLimit) {
|
|
746
|
+
const limit = depthLimit == null ? this.maxLevel : depthLimit;
|
|
496
747
|
if (item.pathList && Array.isArray(item.pathList) && item.pathList.length > 1) {
|
|
497
748
|
if (this.isAreaObject(item.pathList[0])) {
|
|
498
|
-
return item.pathList.slice(0,
|
|
749
|
+
return item.pathList.slice(0, limit);
|
|
499
750
|
}
|
|
500
751
|
}
|
|
501
752
|
if (item.areaPath && Array.isArray(item.areaPath) && item.areaPath.length > 1) {
|
|
502
753
|
if (this.isAreaObject(item.areaPath[0])) {
|
|
503
|
-
return item.areaPath.slice(0,
|
|
754
|
+
return item.areaPath.slice(0, limit);
|
|
504
755
|
}
|
|
505
756
|
}
|
|
506
757
|
return null;
|
|
@@ -521,7 +772,7 @@ export default {
|
|
|
521
772
|
}
|
|
522
773
|
return null;
|
|
523
774
|
},
|
|
524
|
-
async resolvePathByFullName(item) {
|
|
775
|
+
async resolvePathByFullName(item, depthLimit) {
|
|
525
776
|
const fullName = (item.fullName || "").trim();
|
|
526
777
|
if (!fullName) {
|
|
527
778
|
return null;
|
|
@@ -529,7 +780,7 @@ export default {
|
|
|
529
780
|
const path = [];
|
|
530
781
|
let parentId = 0;
|
|
531
782
|
let prefix = "";
|
|
532
|
-
for (let level = 0; level <
|
|
783
|
+
for (let level = 0; level < MAX_AREA_DEPTH; level++) {
|
|
533
784
|
const children = await this.fetchChildren(parentId);
|
|
534
785
|
if (!children.length) {
|
|
535
786
|
break;
|
|
@@ -554,13 +805,13 @@ export default {
|
|
|
554
805
|
path.push(item);
|
|
555
806
|
}
|
|
556
807
|
}
|
|
557
|
-
return path.length ? path
|
|
808
|
+
return path.length ? path : null;
|
|
558
809
|
},
|
|
559
|
-
async resolvePathByParentChain(item) {
|
|
810
|
+
async resolvePathByParentChain(item, depthLimit) {
|
|
560
811
|
const chain = [];
|
|
561
812
|
let current = item;
|
|
562
813
|
let safety = 0;
|
|
563
|
-
while (current && safety <
|
|
814
|
+
while (current && safety < MAX_AREA_DEPTH + 2) {
|
|
564
815
|
safety += 1;
|
|
565
816
|
chain.unshift(current);
|
|
566
817
|
const parentId = this.getParentIdFromRow(current);
|
|
@@ -573,23 +824,93 @@ export default {
|
|
|
573
824
|
}
|
|
574
825
|
current = parent;
|
|
575
826
|
}
|
|
576
|
-
return chain.length ? chain
|
|
827
|
+
return chain.length ? chain : null;
|
|
577
828
|
},
|
|
578
|
-
async
|
|
579
|
-
const
|
|
580
|
-
if (
|
|
829
|
+
async resolvePathFromTreePath(area, depthLimit) {
|
|
830
|
+
const ids = this.parseTreePathIds(area && area.treePath);
|
|
831
|
+
if (!ids.length) {
|
|
832
|
+
return area && area.id != null ? [area] : null;
|
|
833
|
+
}
|
|
834
|
+
const path = [];
|
|
835
|
+
for (let i = 0; i < ids.length; i++) {
|
|
836
|
+
const id = ids[i];
|
|
837
|
+
let node = null;
|
|
838
|
+
if (area && this.getAreaId(area) == id) {
|
|
839
|
+
node = area;
|
|
840
|
+
} else {
|
|
841
|
+
node = await this.fetchAreaById(id);
|
|
842
|
+
}
|
|
843
|
+
path.push(node || { id });
|
|
844
|
+
}
|
|
845
|
+
if (area && area.id != null) {
|
|
846
|
+
const exists = path.some((node) => this.getAreaId(node) == area.id);
|
|
847
|
+
if (!exists) {
|
|
848
|
+
path.push(area);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return path.length ? path : null;
|
|
852
|
+
},
|
|
853
|
+
async resolveAreaPath(item, options = {}) {
|
|
854
|
+
if (!item || item.id == null) {
|
|
855
|
+
return item ? [item] : [];
|
|
856
|
+
}
|
|
857
|
+
const parentPath = await this.resolvePathByParentChain(item);
|
|
858
|
+
if (this.isPathResolvedForItem(parentPath, item)) {
|
|
859
|
+
return parentPath;
|
|
860
|
+
}
|
|
861
|
+
const depthLimit =
|
|
862
|
+
options.depthLimit != null
|
|
863
|
+
? options.depthLimit
|
|
864
|
+
: this.getResolveDepthLimit(item);
|
|
865
|
+
if (item.treePath) {
|
|
866
|
+
const treePath = await this.resolvePathFromTreePath(item, depthLimit);
|
|
867
|
+
if (this.isPathResolvedForItem(treePath, item)) {
|
|
868
|
+
return treePath;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
const presetPath = this.buildAreaPath(item, depthLimit);
|
|
872
|
+
if (this.isPathResolvedForItem(presetPath, item)) {
|
|
581
873
|
return presetPath;
|
|
582
874
|
}
|
|
583
|
-
const fullNamePath = await this.resolvePathByFullName(item);
|
|
584
|
-
if (fullNamePath
|
|
875
|
+
const fullNamePath = await this.resolvePathByFullName(item, depthLimit);
|
|
876
|
+
if (this.isPathResolvedForItem(fullNamePath, item)) {
|
|
585
877
|
return fullNamePath;
|
|
586
878
|
}
|
|
587
|
-
const parentPath = await this.resolvePathByParentChain(item);
|
|
588
879
|
if (parentPath && parentPath.length) {
|
|
589
880
|
return parentPath;
|
|
590
881
|
}
|
|
882
|
+
if (item.treePath) {
|
|
883
|
+
const treePath = await this.resolvePathFromTreePath(item, depthLimit);
|
|
884
|
+
if (treePath && treePath.length) {
|
|
885
|
+
return treePath;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
if (presetPath && presetPath.length) {
|
|
889
|
+
return presetPath;
|
|
890
|
+
}
|
|
891
|
+
if (fullNamePath && fullNamePath.length) {
|
|
892
|
+
return fullNamePath;
|
|
893
|
+
}
|
|
591
894
|
return [item];
|
|
592
895
|
},
|
|
896
|
+
async syncBrowseStateFromLeafId(id) {
|
|
897
|
+
if (id == null || id === "") {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
const token = ++this.syncToken;
|
|
901
|
+
const area = await this.fetchAreaById(id);
|
|
902
|
+
if (token !== this.syncToken) {
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
if (area) {
|
|
906
|
+
await this.syncBrowseStateFromArea(area);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
await this.syncBrowseStateFromArea({
|
|
910
|
+
id,
|
|
911
|
+
fullName: this.labelValue || undefined,
|
|
912
|
+
});
|
|
913
|
+
},
|
|
593
914
|
async syncBrowseStateFromArea(item) {
|
|
594
915
|
const token = ++this.syncToken;
|
|
595
916
|
let seed = item || {};
|
|
@@ -628,21 +949,16 @@ export default {
|
|
|
628
949
|
if (token !== this.syncToken) {
|
|
629
950
|
return;
|
|
630
951
|
}
|
|
631
|
-
path = path.slice(0, this.maxLevel);
|
|
632
952
|
this.selectedPath = path;
|
|
633
|
-
|
|
634
|
-
if (pathLen >= this.maxLevel) {
|
|
635
|
-
this.activeLevel = this.maxLevel;
|
|
636
|
-
} else {
|
|
637
|
-
this.activeLevel = pathLen;
|
|
638
|
-
}
|
|
953
|
+
this.activeLevel = path.length || 1;
|
|
639
954
|
this.loadLevelItems(this.getParentId());
|
|
640
955
|
this.emitResolvedLabelIfNeeded();
|
|
641
956
|
},
|
|
642
|
-
async resolvePathByIds(ids) {
|
|
957
|
+
async resolvePathByIds(ids, depthLimit) {
|
|
958
|
+
const limit = depthLimit == null ? ids.length : depthLimit;
|
|
643
959
|
const path = [];
|
|
644
960
|
let parentId = 0;
|
|
645
|
-
for (let i = 0; i < ids.length && i <
|
|
961
|
+
for (let i = 0; i < ids.length && i < limit; i++) {
|
|
646
962
|
const targetId = ids[i];
|
|
647
963
|
const children = await this.fetchChildren(parentId);
|
|
648
964
|
let matched = children.find((row) => this.getAreaId(row) == targetId);
|
|
@@ -664,7 +980,8 @@ export default {
|
|
|
664
980
|
},
|
|
665
981
|
async syncBrowseStateFromPathIds(ids) {
|
|
666
982
|
const token = ++this.syncToken;
|
|
667
|
-
const
|
|
983
|
+
const depthLimit = Math.min(Math.max(ids.length, this.maxLevel, 1), MAX_AREA_DEPTH);
|
|
984
|
+
const path = await this.resolvePathByIds(ids, depthLimit);
|
|
668
985
|
if (token !== this.syncToken) {
|
|
669
986
|
return;
|
|
670
987
|
}
|
|
@@ -674,9 +991,8 @@ export default {
|
|
|
674
991
|
}
|
|
675
992
|
return;
|
|
676
993
|
}
|
|
677
|
-
this.selectedPath = path
|
|
678
|
-
|
|
679
|
-
this.activeLevel = pathLen >= this.maxLevel ? this.maxLevel : pathLen;
|
|
994
|
+
this.selectedPath = path;
|
|
995
|
+
this.activeLevel = path.length;
|
|
680
996
|
this.loadLevelItems(this.getParentId());
|
|
681
997
|
this.emitResolvedLabelIfNeeded();
|
|
682
998
|
},
|
|
@@ -684,6 +1000,9 @@ export default {
|
|
|
684
1000
|
this.searchKeyword = "";
|
|
685
1001
|
this.searchList = [];
|
|
686
1002
|
this.searchDropdownVisible = false;
|
|
1003
|
+
this.cancelPendingSync();
|
|
1004
|
+
this.emitChangeIfCommitted();
|
|
1005
|
+
this.restoreBrowseStateIfUncommitted();
|
|
687
1006
|
},
|
|
688
1007
|
handleSearchInput() {
|
|
689
1008
|
const keyword = (this.searchKeyword || "").trim();
|
|
@@ -723,7 +1042,7 @@ export default {
|
|
|
723
1042
|
});
|
|
724
1043
|
},
|
|
725
1044
|
switchLevel(level) {
|
|
726
|
-
if (level > this.
|
|
1045
|
+
if (level > this.browseLevelCount || !this.isTabEnabled(level)) {
|
|
727
1046
|
return;
|
|
728
1047
|
}
|
|
729
1048
|
this.cancelPendingSync();
|
|
@@ -748,7 +1067,9 @@ export default {
|
|
|
748
1067
|
this.searchKeyword = "";
|
|
749
1068
|
this.searchList = [];
|
|
750
1069
|
this.searchDropdownVisible = false;
|
|
751
|
-
this.applySelection(item)
|
|
1070
|
+
this.applySelection(item).then(() => {
|
|
1071
|
+
this.popoverVisible = false;
|
|
1072
|
+
});
|
|
752
1073
|
});
|
|
753
1074
|
},
|
|
754
1075
|
selectItem(item) {
|
|
@@ -759,37 +1080,66 @@ export default {
|
|
|
759
1080
|
const level = this.activeLevel;
|
|
760
1081
|
this.selectedPath = this.selectedPath.slice(0, level - 1);
|
|
761
1082
|
this.selectedPath.push(item);
|
|
762
|
-
|
|
763
|
-
this.
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1083
|
+
this.applySelection(item).then(() => {
|
|
1084
|
+
if (level >= this.maxLevel) {
|
|
1085
|
+
this.popoverVisible = false;
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
this.fetchChildren(this.getAreaId(item)).then((children) => {
|
|
1089
|
+
if (!children.length) {
|
|
1090
|
+
this.popoverVisible = false;
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
this.activeLevel = level + 1;
|
|
1094
|
+
this.levelItems = children;
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
769
1097
|
},
|
|
770
|
-
applySelection(item) {
|
|
1098
|
+
async applySelection(item) {
|
|
771
1099
|
const path = this.selectedPath.length ? this.selectedPath : [item];
|
|
772
|
-
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
this.
|
|
1100
|
+
let last = path[path.length - 1] || item;
|
|
1101
|
+
const leafId = this.getAreaId(last);
|
|
1102
|
+
if (leafId != null && !last.fullName) {
|
|
1103
|
+
const detail = await this.fetchAreaById(leafId);
|
|
1104
|
+
if (detail) {
|
|
1105
|
+
last = detail;
|
|
1106
|
+
if (path.length) {
|
|
1107
|
+
this.$set(this.selectedPath, this.selectedPath.length - 1, detail);
|
|
1108
|
+
}
|
|
780
1109
|
}
|
|
781
1110
|
}
|
|
1111
|
+
const label = last.fullName || this.buildPathLabel(path);
|
|
1112
|
+
const formattedValue = this.formatBoundValue(path, last);
|
|
1113
|
+
this.lastSelectionPayload = {
|
|
1114
|
+
value: formattedValue,
|
|
1115
|
+
row: last,
|
|
1116
|
+
label,
|
|
1117
|
+
path: path.map((node) => ({ ...node })),
|
|
1118
|
+
};
|
|
782
1119
|
this.skipValueSync = true;
|
|
783
1120
|
this.$emit("input", formattedValue);
|
|
784
1121
|
this.$emit("update:labelValue", label);
|
|
785
|
-
this.$emit("change", { value: formattedValue, row: last, label });
|
|
786
1122
|
this.$nextTick(() => {
|
|
787
1123
|
this.skipValueSync = false;
|
|
788
1124
|
});
|
|
789
1125
|
},
|
|
790
1126
|
handleClear() {
|
|
791
|
-
this.
|
|
1127
|
+
const oldVal = this.value;
|
|
1128
|
+
const wasOpen = this.popoverVisible;
|
|
1129
|
+
this.lastSelectionPayload = { value: null, row: null, label: null };
|
|
1130
|
+
this.skipValueSync = true;
|
|
1131
|
+
this.$emit("input", null);
|
|
1132
|
+
this.$emit("update:labelValue", null);
|
|
1133
|
+
this.resetBrowseState(false);
|
|
792
1134
|
this.popoverVisible = false;
|
|
1135
|
+
this.$nextTick(() => {
|
|
1136
|
+
this.skipValueSync = false;
|
|
1137
|
+
if (!wasOpen && !this.isSameBoundValue(oldVal, null)) {
|
|
1138
|
+
this.$emit("change", this.lastSelectionPayload);
|
|
1139
|
+
this.committedBoundValue = null;
|
|
1140
|
+
this.lastSelectionPayload = null;
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
793
1143
|
},
|
|
794
1144
|
resetBrowseState(emitEvent) {
|
|
795
1145
|
this.searchKeyword = "";
|
|
@@ -797,10 +1147,10 @@ export default {
|
|
|
797
1147
|
this.selectedPath = [];
|
|
798
1148
|
this.activeLevel = 1;
|
|
799
1149
|
this.levelItems = [];
|
|
1150
|
+
this.committedBrowseSnapshot = null;
|
|
800
1151
|
if (emitEvent) {
|
|
801
1152
|
this.$emit("input", null);
|
|
802
1153
|
this.$emit("update:labelValue", null);
|
|
803
|
-
this.$emit("change", { value: null, row: null });
|
|
804
1154
|
}
|
|
805
1155
|
},
|
|
806
1156
|
},
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
/>
|
|
23
23
|
<baseArea
|
|
24
24
|
v-else
|
|
25
|
+
ref="baseAreaRef"
|
|
25
26
|
v-show="!isReadMode"
|
|
26
27
|
class="full-width-input"
|
|
27
28
|
:style="widgetStyle"
|
|
@@ -33,11 +34,11 @@
|
|
|
33
34
|
:disabled="field.options.disabled"
|
|
34
35
|
:readonly="field.options.readonly"
|
|
35
36
|
:clearable="field.options.clearable"
|
|
36
|
-
value-format="path"
|
|
37
37
|
:placeholder="getI18nLabel(field.options.placeholder || '请选择地区')"
|
|
38
38
|
:size="field.options.size || 'small'"
|
|
39
39
|
@input="handleAreaInput"
|
|
40
40
|
@change="handleAreaChange"
|
|
41
|
+
@popover-open="handleAreaPopoverOpen"
|
|
41
42
|
/>
|
|
42
43
|
<template v-if="isReadMode">
|
|
43
44
|
<span class="readonly-mode-field">{{ readModeText }}</span>
|
|
@@ -102,9 +103,12 @@ export default {
|
|
|
102
103
|
return this.field.options.areaName || null;
|
|
103
104
|
},
|
|
104
105
|
maxLevel() {
|
|
105
|
-
const areaDataType = this.field.options.areaDataType
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
const areaDataType = this.field.options.areaDataType;
|
|
107
|
+
const type =
|
|
108
|
+
areaDataType == null || areaDataType === "" ? 3 : areaDataType * 1;
|
|
109
|
+
if (type >= 0 && type <= 3) {
|
|
110
|
+
return type + 1;
|
|
111
|
+
}
|
|
108
112
|
return 4;
|
|
109
113
|
},
|
|
110
114
|
readModeText() {
|
|
@@ -177,27 +181,45 @@ export default {
|
|
|
177
181
|
}
|
|
178
182
|
this.commitAreaValue(val);
|
|
179
183
|
},
|
|
184
|
+
handleAreaPopoverOpen() {
|
|
185
|
+
if (this.designState) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.oldFieldValue = deepClone(this.fieldModel);
|
|
189
|
+
},
|
|
180
190
|
handleAreaChange(payload) {
|
|
181
191
|
if (this.designState) {
|
|
182
192
|
return;
|
|
183
193
|
}
|
|
184
|
-
const row =
|
|
185
|
-
payload && Object.prototype.hasOwnProperty.call(payload, "row")
|
|
186
|
-
? payload.row
|
|
187
|
-
: payload;
|
|
188
194
|
const value =
|
|
189
195
|
payload && Object.prototype.hasOwnProperty.call(payload, "value")
|
|
190
196
|
? payload.value
|
|
191
197
|
: this.fieldModel;
|
|
192
|
-
const label =
|
|
193
|
-
payload && payload.label != null
|
|
194
|
-
? payload.label
|
|
195
|
-
: row
|
|
196
|
-
? row.fullName || row.name || null
|
|
197
|
-
: null;
|
|
198
|
-
this.commitAreaValue(value, label);
|
|
199
198
|
this.handleChangeEvent(value);
|
|
200
199
|
},
|
|
200
|
+
createEmptyAreaPathResult(value) {
|
|
201
|
+
return {
|
|
202
|
+
value: value != null && value !== "" ? value : null,
|
|
203
|
+
label: null,
|
|
204
|
+
path: [],
|
|
205
|
+
province: null,
|
|
206
|
+
city: null,
|
|
207
|
+
district: null,
|
|
208
|
+
town: null,
|
|
209
|
+
};
|
|
210
|
+
},
|
|
211
|
+
async getAreaPath(value) {
|
|
212
|
+
if (this.designState) {
|
|
213
|
+
return this.createEmptyAreaPathResult(value);
|
|
214
|
+
}
|
|
215
|
+
const areaRef = this.$refs.baseAreaRef;
|
|
216
|
+
if (areaRef && areaRef.getAreaPath) {
|
|
217
|
+
const targetValue =
|
|
218
|
+
value !== undefined && value !== null ? value : this.getValue();
|
|
219
|
+
return areaRef.getAreaPath(targetValue);
|
|
220
|
+
}
|
|
221
|
+
return this.createEmptyAreaPathResult(value);
|
|
222
|
+
},
|
|
201
223
|
getValue() {
|
|
202
224
|
const fieldKey = this.fieldKeyName;
|
|
203
225
|
if (this.fieldModel != null && this.fieldModel !== "") {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<el-form-item :label="i18nt('designer.setting.areaDataType')">
|
|
3
3
|
<el-select v-model="optionModel.areaDataType" style="width: 100%">
|
|
4
|
+
<el-option :label="i18nt('designer.setting.areaDataType0')" :value="0" />
|
|
4
5
|
<el-option :label="i18nt('designer.setting.areaDataType1')" :value="1" />
|
|
5
6
|
<el-option :label="i18nt('designer.setting.areaDataType2')" :value="2" />
|
|
6
7
|
<el-option :label="i18nt('designer.setting.areaDataType3')" :value="3" />
|
|
@@ -192,6 +192,7 @@ export default {
|
|
|
192
192
|
htmlContent: "HTML",
|
|
193
193
|
clearable: "Clearable",
|
|
194
194
|
areaDataType: "Area Level",
|
|
195
|
+
areaDataType0: "Province",
|
|
195
196
|
areaDataType1: "Province/City",
|
|
196
197
|
areaDataType2: "Province/City/District",
|
|
197
198
|
areaDataType3: "Province/City/District/Town",
|