openxiangda 1.0.129 → 1.0.131

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.
@@ -13556,7 +13556,42 @@ var modeDepth = (mode) => {
13556
13556
  return 3;
13557
13557
  };
13558
13558
  var activeLevels = (mode) => LEVELS.slice(0, modeDepth(mode));
13559
- var valueToPath = (value) => LEVELS.map((level) => value?.[level]?.value).filter(Boolean);
13559
+ var stringifyValue = (value) => {
13560
+ if (value === void 0 || value === null || value === "") return void 0;
13561
+ return String(value);
13562
+ };
13563
+ var normalizeAddressPart = (part) => {
13564
+ if (part === void 0 || part === null || part === "") return void 0;
13565
+ if (typeof part === "object") {
13566
+ const value2 = stringifyValue(part.value ?? part.adcode ?? part.code ?? part.id ?? part.label);
13567
+ if (!value2) return void 0;
13568
+ const label = stringifyValue(part.label ?? part.name ?? part.title) ?? "";
13569
+ return { label, value: value2 };
13570
+ }
13571
+ const value = stringifyValue(part);
13572
+ return value ? { label: "", value } : void 0;
13573
+ };
13574
+ var normalizeAddressValue = (raw) => {
13575
+ if (!raw || typeof raw !== "object") return void 0;
13576
+ const next = {};
13577
+ LEVELS.forEach((level) => {
13578
+ const part = normalizeAddressPart(raw[level]);
13579
+ if (part) next[level] = part;
13580
+ });
13581
+ if (raw.detail !== void 0 && raw.detail !== null) {
13582
+ next.detail = String(raw.detail);
13583
+ }
13584
+ if (typeof raw.fullAddress === "string" && raw.fullAddress) {
13585
+ next.fullAddress = raw.fullAddress;
13586
+ }
13587
+ return Object.keys(next).length > 0 ? next : void 0;
13588
+ };
13589
+ var getDisplayLabel = (part) => {
13590
+ const label = part?.label?.trim();
13591
+ if (!label) return void 0;
13592
+ return label === part?.value ? void 0 : label;
13593
+ };
13594
+ var valueToPath = (value, levels) => levels.map((level) => value?.[level]?.value).filter(Boolean);
13560
13595
  var normalizeDivision = (item, level, depth, index) => ({
13561
13596
  label: String(item.name || item.label || item.adcode || item.value),
13562
13597
  value: String(item.adcode || item.value || item.id),
@@ -13565,7 +13600,66 @@ var normalizeDivision = (item, level, depth, index) => ({
13565
13600
  });
13566
13601
  var composeFullAddress = (value, levels = LEVELS) => {
13567
13602
  if (!value) return "";
13568
- return [...levels.map((level) => value[level]?.label), value.detail].filter(Boolean).join("");
13603
+ return [...levels.map((level) => getDisplayLabel(value[level])), value.detail].filter(Boolean).join("");
13604
+ };
13605
+ var mergeValuePathIntoOptions = (source, value, levels, depth) => {
13606
+ if (!value) return source;
13607
+ const mergeAt = (items, index) => {
13608
+ const level = levels[index];
13609
+ const part = level ? value[level] : void 0;
13610
+ if (!level || !part?.value) return items;
13611
+ let matched = false;
13612
+ const nextItems = items.map((item) => {
13613
+ if (String(item.value) !== part.value) return item;
13614
+ matched = true;
13615
+ const label = getDisplayLabel(part) ?? getDisplayLabel(item) ?? "\u5730\u5740\u52A0\u8F7D\u4E2D";
13616
+ const hasNextPath = Boolean(levels[index + 1] && value[levels[index + 1]]?.value);
13617
+ return {
13618
+ ...item,
13619
+ label,
13620
+ level: item.level ?? level,
13621
+ isLeaf: index + 1 >= depth || !hasNextPath && item.isLeaf === true,
13622
+ children: hasNextPath ? mergeAt(item.children ?? [], index + 1) : item.children
13623
+ };
13624
+ });
13625
+ if (!matched) {
13626
+ const hasNextPath = Boolean(levels[index + 1] && value[levels[index + 1]]?.value);
13627
+ const option = {
13628
+ label: getDisplayLabel(part) ?? "\u5730\u5740\u52A0\u8F7D\u4E2D",
13629
+ value: part.value,
13630
+ level,
13631
+ isLeaf: index + 1 >= depth
13632
+ };
13633
+ if (hasNextPath) option.children = mergeAt([], index + 1);
13634
+ nextItems.push(option);
13635
+ }
13636
+ return nextItems;
13637
+ };
13638
+ return mergeAt(source, 0);
13639
+ };
13640
+ var setNestedChildren = (source, selectedOptions, children) => {
13641
+ const [current, ...rest] = selectedOptions;
13642
+ if (!current) return source;
13643
+ const currentValue = String(current.value);
13644
+ let matched = false;
13645
+ const next = source.map((item) => {
13646
+ if (String(item.value) !== currentValue) return item;
13647
+ matched = true;
13648
+ return {
13649
+ ...item,
13650
+ children: rest.length ? setNestedChildren(item.children ?? [], rest, children) : children
13651
+ };
13652
+ });
13653
+ if (!matched) {
13654
+ next.push({
13655
+ label: String(current.label || current.value),
13656
+ value: currentValue,
13657
+ level: current.level,
13658
+ isLeaf: false,
13659
+ children: rest.length ? setNestedChildren([], rest, children) : children
13660
+ });
13661
+ }
13662
+ return next;
13569
13663
  };
13570
13664
  function AddressField(props) {
13571
13665
  const {
@@ -13587,7 +13681,8 @@ function AddressField(props) {
13587
13681
  const { formData, fieldBehaviors, setFieldValue, registerField, unregisterField, api } = useFormContext();
13588
13682
  const { isMobile } = useDeviceDetect();
13589
13683
  const behavior = propBehavior ?? fieldBehaviors[fieldId] ?? "NORMAL";
13590
- const value = formData[fieldId];
13684
+ const rawValue = formData[fieldId];
13685
+ const value = (0, import_react55.useMemo)(() => normalizeAddressValue(rawValue), [rawValue]);
13591
13686
  const [options, setOptions] = (0, import_react55.useState)([]);
13592
13687
  const [loadingRoots, setLoadingRoots] = (0, import_react55.useState)(false);
13593
13688
  const [mobileOpen, setMobileOpen] = (0, import_react55.useState)(false);
@@ -13597,24 +13692,78 @@ function AddressField(props) {
13597
13692
  const [tempValue, setTempValue] = (0, import_react55.useState)();
13598
13693
  const depth = modeDepth(mode);
13599
13694
  const levels = (0, import_react55.useMemo)(() => activeLevels(mode), [mode]);
13695
+ const valuePath = (0, import_react55.useMemo)(() => valueToPath(value, levels), [levels, value]);
13696
+ const displayOptions = (0, import_react55.useMemo)(
13697
+ () => mergeValuePathIntoOptions(options, value, levels, depth),
13698
+ [depth, levels, options, value]
13699
+ );
13600
13700
  const detailEnabled = mode === "province-city-district-street-detail";
13601
13701
  const disabled = behavior === "DISABLED";
13602
13702
  const MobilePopup = getMobileComponent3("Popup");
13603
13703
  (0, import_react55.useEffect)(() => {
13604
13704
  registerField(fieldId);
13605
- if (defaultValue !== void 0 && formData[fieldId] === void 0) {
13705
+ return () => unregisterField(fieldId);
13706
+ }, [fieldId, registerField, unregisterField]);
13707
+ (0, import_react55.useEffect)(() => {
13708
+ if (defaultValue !== void 0 && rawValue === void 0) {
13606
13709
  setFieldValue(fieldId, defaultValue);
13607
13710
  }
13608
- return () => unregisterField(fieldId);
13609
- }, [fieldId]);
13610
- const loadDivisions = async (parentAdcode, level, index) => {
13611
- const list = await api.getChinaDivisions(parentAdcode);
13612
- return list.map((item) => normalizeDivision(item, level, depth, index));
13613
- };
13711
+ }, [defaultValue, fieldId, rawValue, setFieldValue]);
13712
+ const loadDivisions = (0, import_react55.useCallback)(
13713
+ async (parentAdcode, level, index) => {
13714
+ const list = await api.getChinaDivisions(parentAdcode);
13715
+ return list.map((item) => normalizeDivision(item, level, depth, index));
13716
+ },
13717
+ [api, depth]
13718
+ );
13614
13719
  (0, import_react55.useEffect)(() => {
13720
+ let mounted = true;
13615
13721
  setLoadingRoots(true);
13616
- loadDivisions(void 0, "province", 0).then(setOptions).finally(() => setLoadingRoots(false));
13617
- }, [api, depth]);
13722
+ loadDivisions(void 0, "province", 0).then((nextOptions) => {
13723
+ if (mounted) setOptions(nextOptions);
13724
+ }).finally(() => {
13725
+ if (mounted) setLoadingRoots(false);
13726
+ });
13727
+ return () => {
13728
+ mounted = false;
13729
+ };
13730
+ }, [loadDivisions]);
13731
+ (0, import_react55.useEffect)(() => {
13732
+ if (!value) return;
13733
+ let cancelled = false;
13734
+ const hydrateMissingLabels = async () => {
13735
+ let nextValue = { ...value };
13736
+ let changed = false;
13737
+ let parentAdcode;
13738
+ for (let index = 0; index < levels.length; index += 1) {
13739
+ const level = levels[index];
13740
+ const part = nextValue[level];
13741
+ if (!part?.value) break;
13742
+ if (!getDisplayLabel(part)) {
13743
+ const divisions = await loadDivisions(parentAdcode, level, index);
13744
+ const matched = divisions.find((option) => option.value === part.value);
13745
+ if (matched) {
13746
+ nextValue = { ...nextValue, [level]: { label: matched.label, value: matched.value } };
13747
+ changed = true;
13748
+ }
13749
+ }
13750
+ parentAdcode = part.value;
13751
+ }
13752
+ const fullAddress = composeFullAddress(nextValue, levels);
13753
+ if (fullAddress && nextValue.fullAddress !== fullAddress) {
13754
+ nextValue = { ...nextValue, fullAddress };
13755
+ changed = true;
13756
+ }
13757
+ if (!cancelled && changed) {
13758
+ setFieldValue(fieldId, nextValue);
13759
+ }
13760
+ };
13761
+ hydrateMissingLabels().catch(() => {
13762
+ });
13763
+ return () => {
13764
+ cancelled = true;
13765
+ };
13766
+ }, [fieldId, levels, loadDivisions, setFieldValue, value]);
13618
13767
  (0, import_react55.useEffect)(() => {
13619
13768
  if (!mobileOpen) return;
13620
13769
  const level = levels[mobileLevelIndex] || "province";
@@ -13622,7 +13771,7 @@ function AddressField(props) {
13622
13771
  const parentAdcode = parentLevel ? tempValue?.[parentLevel]?.value : void 0;
13623
13772
  setMobileLoading(true);
13624
13773
  loadDivisions(parentAdcode, level, mobileLevelIndex).then(setMobileOptions).finally(() => setMobileLoading(false));
13625
- }, [mobileOpen, mobileLevelIndex, tempValue, levels]);
13774
+ }, [loadDivisions, mobileOpen, mobileLevelIndex, tempValue, levels]);
13626
13775
  if (behavior === "HIDDEN") return null;
13627
13776
  const setAddressValue = (next) => {
13628
13777
  const normalized = next ? { ...next, fullAddress: composeFullAddress(next, levels) } : void 0;
@@ -13758,18 +13907,20 @@ function AddressField(props) {
13758
13907
  import_antd24.Cascader,
13759
13908
  {
13760
13909
  style: { width: "100%" },
13761
- options,
13910
+ options: displayOptions,
13762
13911
  allowClear,
13763
13912
  disabled,
13764
- value: valueToPath(value),
13913
+ value: valuePath,
13765
13914
  placeholder: props.placeholder || "\u8BF7\u9009\u62E9\u5730\u5740",
13766
13915
  loading: loadingRoots,
13916
+ displayRender: (labels) => labels.filter(Boolean).join(" / ") || (valuePath.length ? "\u5730\u5740\u52A0\u8F7D\u4E2D" : ""),
13767
13917
  loadData: async (selectedOptions) => {
13768
13918
  const target = selectedOptions[selectedOptions.length - 1];
13769
13919
  const nextLevel = levels[selectedOptions.length] ?? "street";
13770
13920
  const children = await loadDivisions(target.value, nextLevel, selectedOptions.length);
13771
- target.children = children;
13772
- setOptions([...options]);
13921
+ setOptions(
13922
+ (currentOptions) => setNestedChildren(currentOptions, selectedOptions, children)
13923
+ );
13773
13924
  },
13774
13925
  onChange: (_path, selectedOptions) => {
13775
13926
  if (!selectedOptions?.length) {