feat(registration): 优化经销商注册流程并增加地址定位功能

- 修改导航栏标题从“邀请注册”为“注册成为会员”
- 修复重复提交问题并移除不必要的submitting状态
- 增加昵称和头像的必填验证提示
- 添加用户角色缺失时的默认角色写入机制
- 集成地图选点功能,支持经纬度获取和地址解析
- 实现微信地址导入功能,自动填充基本信息
- 增加定位权限检查和错误处理机制
- 添加.gitignore规则忽略备份文件夹src__bak
- 移除已废弃的银行卡和客户管理页面代码
- 优化表单验证规则和错误提示信息
- 实现经销商注册成功后自动跳转到“我的”页面
- 添加用户信息缓存刷新机制确保角色信息同步
```
This commit is contained in:
2026-03-01 12:35:41 +08:00
parent 945351be91
commit eee4644d06
296 changed files with 28845 additions and 6664 deletions

View File

@@ -1,130 +1,82 @@
import {useMemo, useState} from 'react'
import Taro from '@tarojs/taro'
import {Input, Text, View} from '@tarojs/components'
import {Search} from '@nutui/icons-react-taro'
import {useEffect, useState} from "react";
import Taro from '@tarojs/taro';
import {pageCmsArticle} from "@/api/cms/cmsArticle";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import {NavBar, Cell} from '@nutui/nutui-react-taro';
import {Text} from '@tarojs/components';
import {ArrowRight, ImageRectangle, Coupon, Follow} from '@nutui/icons-react-taro'
import './find.scss'
import navTo from "@/utils/common";
type SiteItem = {
id: string
cityName: string
address: string
phone: string
contact: string
distanceMeter: number
}
const MOCK_SITES: SiteItem[] = [
{
id: '1',
cityName: '北京朝阳区网点',
address: '地安门西大街(南门)',
phone: '15878179339',
contact: '刘先生',
distanceMeter: 100
},
{
id: '2',
cityName: '兰州某某区网点',
address: '地安门西大街(南门)',
phone: '15878179339',
contact: '黄先生',
distanceMeter: 150
},
{
id: '3',
cityName: '合肥市某某区网点',
address: '地安门西大街(南门)',
phone: '15878179339',
contact: '黄先生',
distanceMeter: 250
},
{
id: '4',
cityName: '南宁市某某区网点',
address: '广西壮族自治区南宁市良庆区五象新区五象大道403号富雅国际金融中心G1栋高层6006',
phone: '15878179339',
contact: '柳先生',
distanceMeter: 1250
}
]
/**
* 文章终极列表
* @constructor
*/
const Find = () => {
const [keyword, setKeyword] = useState<string>('')
const [statusBarHeight, setStatusBarHeight] = useState<number>()
const [loading, setLoading] = useState<boolean>(false)
const [list, setList] = useState<CmsArticle[]>()
const filtered = useMemo(() => {
const key = keyword.trim()
if (!key) return MOCK_SITES
return MOCK_SITES.filter((it) => it.cityName.includes(key))
}, [keyword])
const onNavigate = (item: SiteItem) => {
Taro.showToast({title: `导航至:${item.cityName}(示例)`, icon: 'none'})
const reload = async () => {
setLoading(true)
const article = await pageCmsArticle({categoryId: 4289, status: 0})
if (article) {
setList(article?.list)
setLoading(false)
}
}
const onSearch = () => {
Taro.showToast({title: '查询(示例)', icon: 'none'})
}
useEffect(() => {
Taro.getSystemInfo({
success: (res) => {
setStatusBarHeight(res.statusBarHeight)
},
})
reload().then(() => {
console.log('初始化完成')
})
}, [])
return (
<View className='sitePage'>
<View className='searchArea'>
<View className='searchBox'>
<Input
className='searchInput'
value={keyword}
placeholder='请输入城市名称查询'
placeholderClass='searchPlaceholder'
confirmType='search'
onInput={(e) => setKeyword(e.detail.value)}
onConfirm={onSearch}
<>
{loading && (<div></div>)}
<NavBar
fixed={false}
style={{marginTop: `${statusBarHeight}px`, backgroundColor: 'transparent'}}
onBackClick={() => {
}}
>
<span></span>
</NavBar>
{list && (
<>
<Cell title={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<ImageRectangle size={18}/>
<Text className={'pl-3'} style={{fontSize: '16px'}}></Text>
</div>
} extra={<ArrowRight color="#cccccc" size={18}/>}/>
<Cell
title={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<Coupon size={18}/>
<span className={'pl-3'} style={{fontSize: '16px'}}></span>
</div>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
onClick={() => {
navTo('/shop/shopArticle/index', true)
}}
/>
<View className='searchIconWrap' onClick={onSearch}>
<Search size={18} color='#b51616' />
</View>
</View>
</View>
<View className='siteList'>
{filtered.map((item) => (
<View key={item.id} className='siteCard'>
<View className='siteCardInner'>
<View className='siteInfo'>
<View className='siteRow siteRowTop'>
<Text className='siteLabel'></Text>
<Text className='siteValue siteValueStrong'>{item.cityName}</Text>
</View>
<View className='siteDivider' />
<View className='siteRow'>
<Text className='siteLabel'></Text>
<Text className='siteValue'>{item.address}</Text>
</View>
<View className='siteRow'>
<Text className='siteLabel'></Text>
<Text className='siteValue'>{item.phone}</Text>
</View>
<View className='siteRow'>
<Text className='siteLabel'></Text>
<Text className='siteValue'>{item.contact}</Text>
</View>
</View>
<View className='siteSide' onClick={() => onNavigate(item)}>
<View className='navArrow' />
<Text className='distanceText'>{item.distanceMeter}</Text>
</View>
</View>
</View>
))}
{filtered.length === 0 && (
<View className='emptyWrap'>
<Text className='emptyText'></Text>
</View>
)}
</View>
<View className='bottomSafe' />
</View>
<Cell title={
<div style={{display: 'inline-flex', alignItems: 'center'}}>
<Follow size={18}/>
<span className={'pl-3'} style={{fontSize: '16px'}}></span>
</div>
} extra={<ArrowRight color="#cccccc" size={18}/>}/>
</>
)}
</>
)
}
export default Find