feat(find): 将发现页面重构为网点查询功能
- 修改页面标题为"网点"并设置导航栏样式 - 替换原有文章列表功能为网点搜索和展示功能 - 添加搜索框组件支持城市名称查询 - 实现网点卡片布局显示城市、地址、电话等信息 - 集成模拟数据展示网点列表 - 添加距离计算和导航功能 - 优化页面样式和用户体验
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '发现',
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '网点',
|
||||
navigationBarTextStyle: 'black',
|
||||
navigationBarBackgroundColor: '#ffffff'
|
||||
})
|
||||
|
||||
@@ -1,4 +1,144 @@
|
||||
page {
|
||||
background: linear-gradient(to bottom, #e9fff2, #f9fafb);
|
||||
background-size: 100%;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.sitePage {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #fde8ea 0%, #f7f7f7 320rpx, #f7f7f7 100%);
|
||||
padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.searchArea {
|
||||
padding: 22rpx 24rpx 18rpx;
|
||||
}
|
||||
|
||||
.searchBox {
|
||||
height: 86rpx;
|
||||
background: #fff;
|
||||
border: 2rpx solid #b51616;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.searchInput {
|
||||
flex: 1;
|
||||
height: 86rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.searchPlaceholder {
|
||||
color: #9e9e9e;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.searchIconWrap {
|
||||
width: 88rpx;
|
||||
height: 86rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.siteList {
|
||||
padding: 0 24rpx 24rpx;
|
||||
}
|
||||
|
||||
.siteCard {
|
||||
background: #fff;
|
||||
border-radius: 18rpx;
|
||||
padding: 22rpx 22rpx 18rpx;
|
||||
margin-top: 18rpx;
|
||||
box-shadow: 0 10rpx 24rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.siteCardInner {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.siteInfo {
|
||||
flex: 1;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.siteRow {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.siteRowTop {
|
||||
padding-top: 2rpx;
|
||||
padding-bottom: 14rpx;
|
||||
}
|
||||
|
||||
.siteLabel {
|
||||
width: 170rpx;
|
||||
flex: 0 0 170rpx;
|
||||
color: #9a9a9a;
|
||||
font-size: 30rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.siteValue {
|
||||
flex: 1;
|
||||
color: #222;
|
||||
font-size: 30rpx;
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.siteValueStrong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.siteDivider {
|
||||
height: 2rpx;
|
||||
background: #ededed;
|
||||
}
|
||||
|
||||
.siteSide {
|
||||
width: 160rpx;
|
||||
flex: 0 0 160rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding-left: 12rpx;
|
||||
}
|
||||
|
||||
.navArrow {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-top: 8rpx solid #e60012;
|
||||
border-right: 8rpx solid #e60012;
|
||||
border-radius: 4rpx;
|
||||
transform: rotate(45deg);
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.distanceText {
|
||||
margin-top: 18rpx;
|
||||
font-size: 28rpx;
|
||||
color: #e60012;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.emptyWrap {
|
||||
padding: 40rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.emptyText {
|
||||
font-size: 28rpx;
|
||||
color: #9a9a9a;
|
||||
}
|
||||
|
||||
.bottomSafe {
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
@@ -1,82 +1,130 @@
|
||||
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 {useMemo, useState} from 'react'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {Input, Text, View} from '@tarojs/components'
|
||||
import {Search} from '@nutui/icons-react-taro'
|
||||
import './find.scss'
|
||||
import navTo from "@/utils/common";
|
||||
|
||||
/**
|
||||
* 文章终极列表
|
||||
* @constructor
|
||||
*/
|
||||
const Find = () => {
|
||||
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [list, setList] = useState<CmsArticle[]>()
|
||||
|
||||
const reload = async () => {
|
||||
setLoading(true)
|
||||
const article = await pageCmsArticle({categoryId: 4289, status: 0})
|
||||
if (article) {
|
||||
setList(article?.list)
|
||||
setLoading(false)
|
||||
}
|
||||
type SiteItem = {
|
||||
id: string
|
||||
cityName: string
|
||||
address: string
|
||||
phone: string
|
||||
contact: string
|
||||
distanceMeter: number
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
Taro.getSystemInfo({
|
||||
success: (res) => {
|
||||
setStatusBarHeight(res.statusBarHeight)
|
||||
const MOCK_SITES: SiteItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
cityName: '北京朝阳区网点',
|
||||
address: '地安门西大街(南门)',
|
||||
phone: '15878179339',
|
||||
contact: '刘先生',
|
||||
distanceMeter: 100
|
||||
},
|
||||
})
|
||||
reload().then(() => {
|
||||
console.log('初始化完成')
|
||||
})
|
||||
}, [])
|
||||
{
|
||||
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
|
||||
}
|
||||
]
|
||||
|
||||
const Find = () => {
|
||||
const [keyword, setKeyword] = useState<string>('')
|
||||
|
||||
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 onSearch = () => {
|
||||
Taro.showToast({title: '查询(示例)', icon: 'none'})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{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='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}
|
||||
/>
|
||||
<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}/>}/>
|
||||
</>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
export default Find
|
||||
|
||||
Reference in New Issue
Block a user