城市合伙人端开店城市屁默认郑州
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { codeToText } from 'element-china-area-data';
|
||||
import { CHINA_REGION_OPTIONS, formatRegionLabel, parseRegionCodes } from '../lib/china-region';
|
||||
import {
|
||||
CHINA_REGION_OPTIONS,
|
||||
DEFAULT_REGION_CODES,
|
||||
formatRegionLabel,
|
||||
parseRegionCodes,
|
||||
} from '../lib/china-region';
|
||||
|
||||
type RegionNode = {
|
||||
value: string;
|
||||
@@ -40,10 +45,26 @@ function lockBodyScroll(lock: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildInitialDraft(value: string[]): { draft: string[]; step: number } {
|
||||
if (value.length === 3) {
|
||||
return { draft: [...value], step: 2 };
|
||||
}
|
||||
if (value.length > 0) {
|
||||
const draft = [...value];
|
||||
for (let i = value.length; i < DEFAULT_REGION_CODES.length; i += 1) {
|
||||
draft.push(DEFAULT_REGION_CODES[i]);
|
||||
}
|
||||
return { draft, step: Math.min(value.length, 2) };
|
||||
}
|
||||
return { draft: [...DEFAULT_REGION_CODES], step: 1 };
|
||||
}
|
||||
|
||||
export default function ChinaRegionPicker({ value = [], onChange, disabled }: ChinaRegionPickerProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [draft, setDraft] = useState<string[]>(value);
|
||||
const [step, setStep] = useState(0);
|
||||
const listRef = useRef<HTMLDivElement>(null);
|
||||
const activeItemRef = useRef<HTMLButtonElement | null>(null);
|
||||
|
||||
const options = CHINA_REGION_OPTIONS as RegionNode[];
|
||||
const parsed = parseRegionCodes(value);
|
||||
@@ -69,11 +90,23 @@ export default function ChinaRegionPicker({ value = [], onChange, disabled }: Ch
|
||||
return () => lockBodyScroll(false);
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
const timer = window.setTimeout(() => {
|
||||
const container = listRef.current;
|
||||
const activeEl = activeItemRef.current;
|
||||
if (!container || !activeEl) return;
|
||||
const offset = activeEl.offsetTop - container.clientHeight / 2 + activeEl.clientHeight / 2;
|
||||
container.scrollTo({ top: Math.max(0, offset), behavior: 'smooth' });
|
||||
}, 0);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [open, step, activeCode, listItems]);
|
||||
|
||||
function openPicker() {
|
||||
if (disabled) return;
|
||||
const next = value.length === 3 ? [...value] : [];
|
||||
const { draft: next, step: initialStep } = buildInitialDraft(value);
|
||||
setDraft(next);
|
||||
setStep(next.length >= 3 ? 2 : next.length);
|
||||
setStep(initialStep);
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
@@ -147,13 +180,14 @@ export default function ChinaRegionPicker({ value = [], onChange, disabled }: Ch
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="partner-region-list" role="listbox">
|
||||
<div className="partner-region-list" role="listbox" ref={listRef}>
|
||||
{listItems.map((item) => (
|
||||
<button
|
||||
key={item.value}
|
||||
type="button"
|
||||
role="option"
|
||||
aria-selected={activeCode === item.value}
|
||||
ref={activeCode === item.value ? (el) => { activeItemRef.current = el; } : undefined}
|
||||
className={`partner-region-item${activeCode === item.value ? ' partner-region-item--active' : ''}`}
|
||||
onClick={() => selectItem(item.value)}
|
||||
>
|
||||
@@ -175,4 +209,4 @@ export default function ChinaRegionPicker({ value = [], onChange, disabled }: Ch
|
||||
{typeof document !== 'undefined' ? createPortal(modal, document.body) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,20 @@ export function formatRegionLabel(region: ParsedChinaRegion): string {
|
||||
return `${region.province} / ${region.city} / ${region.district}`;
|
||||
}
|
||||
|
||||
/** 合伙人录店默认省市区 adcode:河南省 / 郑州市 / 金水区 */
|
||||
export const DEFAULT_REGION_CODES = ['41', '4101', '410105'] as const;
|
||||
|
||||
export function getDefaultPartnerRegionForm() {
|
||||
const regionCodes = [...DEFAULT_REGION_CODES];
|
||||
const parsed = parseRegionCodes(regionCodes);
|
||||
return {
|
||||
regionCodes,
|
||||
province: parsed?.province ?? '河南省',
|
||||
city: parsed?.city ?? '郑州市',
|
||||
district: parsed?.district ?? '金水区',
|
||||
};
|
||||
}
|
||||
|
||||
export function matchOpenCityId(cities: OpenCityRef[], districtCode: string): string | undefined {
|
||||
const cityCode = districtCodeToCityCode(districtCode);
|
||||
return (
|
||||
|
||||
@@ -27,12 +27,11 @@ export function storeDraftKey(accountId?: string): string {
|
||||
return accountId ? `${STORE_DRAFT_KEY}_${accountId}` : STORE_DRAFT_KEY;
|
||||
}
|
||||
|
||||
import { getDefaultPartnerRegionForm } from './china-region';
|
||||
|
||||
export const defaultStoreForm = (): StoreDraftForm => ({
|
||||
regionCodes: [],
|
||||
...getDefaultPartnerRegionForm(),
|
||||
cityId: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
address: '',
|
||||
@@ -54,7 +53,7 @@ export function normalizeStringArray(raw: unknown, length: number): string[] {
|
||||
|
||||
function normalizeForm(raw: Record<string, unknown>): StoreDraftForm {
|
||||
const base = defaultStoreForm();
|
||||
const regionCodes = Array.isArray(raw.regionCodes)
|
||||
const regionCodes = Array.isArray(raw.regionCodes) && raw.regionCodes.length >= 3
|
||||
? raw.regionCodes.map((code) => String(code))
|
||||
: base.regionCodes;
|
||||
return {
|
||||
|
||||
@@ -168,6 +168,30 @@ export default function StoreCreatePage() {
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (!cities.length || form.regionCodes.length < 3 || form.cityId) return;
|
||||
|
||||
const binding = resolveRegionBinding(form.regionCodes, cities);
|
||||
|
||||
if (!binding) return;
|
||||
|
||||
patchForm({
|
||||
|
||||
cityId: binding.cityId ?? '',
|
||||
|
||||
province: binding.region.province,
|
||||
|
||||
city: binding.region.city,
|
||||
|
||||
district: binding.region.district,
|
||||
|
||||
});
|
||||
|
||||
}, [cities, form.regionCodes, form.cityId]);
|
||||
|
||||
|
||||
|
||||
const regionBindingHint = useMemo(() => {
|
||||
|
||||
if (!form.regionCodes.length) return null;
|
||||
|
||||
Reference in New Issue
Block a user