This commit is contained in:
parent
f1a6add174
commit
f47616a7b8
|
@ -18,6 +18,7 @@
|
|||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.6.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"web-vitals": "^2.1.4"
|
||||
}
|
||||
},
|
||||
|
@ -5743,6 +5744,14 @@
|
|||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz",
|
||||
|
@ -6643,6 +6652,15 @@
|
|||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
|
@ -14075,6 +14093,11 @@
|
|||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||
},
|
||||
"node_modules/react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||
|
@ -14185,6 +14208,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-virtualized": {
|
||||
"version": "9.22.3",
|
||||
"resolved": "https://registry.npmmirror.com/react-virtualized/-/react-virtualized-9.22.3.tgz",
|
||||
"integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.2",
|
||||
"clsx": "^1.0.4",
|
||||
"dom-helpers": "^5.1.3",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.3.0 || ^16.0.0-alpha",
|
||||
"react-dom": "^15.3.0 || ^16.0.0-alpha"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.6.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -1,60 +1,73 @@
|
|||
import React ,{FC} from "react";
|
||||
import { NavBar, TabBar } from 'antd-mobile'
|
||||
import {
|
||||
Route,Routes,
|
||||
useLocation,
|
||||
MemoryRouter as Router,
|
||||
useNavigate,
|
||||
} from 'react-router-dom'
|
||||
import { TabBar } from 'antd-mobile'
|
||||
import WidthUseNavigate from './../WidthUseNavigate/index'
|
||||
import {
|
||||
AppOutline,
|
||||
MessageOutline,
|
||||
UnorderedListOutline,
|
||||
UserOutline,
|
||||
} from 'antd-mobile-icons'
|
||||
export default function Bottom (){
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation()
|
||||
const pathname = location
|
||||
|
||||
const setRouteActive = (value) => {
|
||||
navigate(value)
|
||||
const tabs = [
|
||||
{
|
||||
key: '/home',
|
||||
title: '首页',
|
||||
icon: <AppOutline />,
|
||||
badge: '1',
|
||||
},
|
||||
{
|
||||
key: '/home/todo',
|
||||
title: '待办',
|
||||
icon: <UnorderedListOutline />,
|
||||
badge: '2',
|
||||
},
|
||||
{
|
||||
key: '/home/message',
|
||||
title: '消息',
|
||||
icon: <MessageOutline />,
|
||||
badge: '3',
|
||||
},
|
||||
{
|
||||
key: '/home/me',
|
||||
title: '我的',
|
||||
icon: <UserOutline />,
|
||||
badge: '4',
|
||||
},
|
||||
]
|
||||
|
||||
class BottomInner extends React.Component{
|
||||
|
||||
state = {
|
||||
// 默认选中的TabBar菜单项
|
||||
selectedTab: this.props.useLocation
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
key: '/home',
|
||||
title: '首页',
|
||||
icon: <AppOutline />,
|
||||
badge: '1',
|
||||
},
|
||||
{
|
||||
key: '/home/todo',
|
||||
title: '待办',
|
||||
icon: <UnorderedListOutline />,
|
||||
badge: '2',
|
||||
},
|
||||
{
|
||||
key: '/home/message',
|
||||
title: '消息',
|
||||
icon: <MessageOutline />,
|
||||
badge: '3',
|
||||
},
|
||||
{
|
||||
key: '/home/me',
|
||||
title: '我的',
|
||||
icon: <UserOutline />,
|
||||
badge: '4',
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<TabBar activeKey={pathname} onChange={value => setRouteActive(value)}>
|
||||
|
||||
// 组件接收到新的props(此处,实际上是路由信息)就会触发该钩子函数
|
||||
componentDidUpdate(prevProps) {
|
||||
// prevProps 上一次的props,此处也就是上一次的路由信息
|
||||
// this.props 当前最新的props,此处也就是最新的路由信息
|
||||
// 注意:在该钩子函数中更新状态时,一定要在 条件判断 中进行,否则会造成递归更新的问题
|
||||
if (prevProps.useLocation !== this.props.useLocation) {
|
||||
// 此时,就说明路由发生切换了
|
||||
this.setState({
|
||||
selectedTab: this.props.useLocation
|
||||
})
|
||||
}
|
||||
}
|
||||
setRouteActive = (value) => {
|
||||
this.props.to(value)
|
||||
this.setState({
|
||||
selectedTab: value
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return <TabBar activeKey={this.state.selectedTab} onChange={value => this.setRouteActive(value)}>
|
||||
{tabs.map(item => (
|
||||
<TabBar.Item key={item.key} icon={item.icon} title={item.title} badge= {item.badge}/>
|
||||
))}
|
||||
</TabBar>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,4 +81,8 @@ export default function Bottom (){
|
|||
|
||||
export function PersonalCenter() {
|
||||
return <div>我的</div>
|
||||
}
|
||||
}
|
||||
|
||||
// 使用高阶组件包裹当前类组件
|
||||
const Bottom = WidthUseNavigate(BottomInner);
|
||||
export default Bottom
|
|
@ -0,0 +1,12 @@
|
|||
.citylist{
|
||||
height: 100%;
|
||||
padding-top: 45px;
|
||||
}
|
||||
.citylist-navbar {
|
||||
background: #f6f5f6;
|
||||
margin-top: -45px;
|
||||
}
|
||||
ul{
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
|
@ -1,7 +1,159 @@
|
|||
import React from "react";
|
||||
import { NavBar, Space, Toast } from 'antd-mobile'
|
||||
import { SearchOutline, MoreOutline, CloseOutline } from 'antd-mobile-icons'
|
||||
import './index.css'
|
||||
import axios from "axios";
|
||||
import { getCurrentCity } from "../../utils";
|
||||
import { List, AutoSizer } from "react-virtualized";
|
||||
// list:[{},{}]
|
||||
const formatCityIndex = (letter) => {
|
||||
switch (letter) {
|
||||
case '#':
|
||||
return '当前城市'
|
||||
case 'hot':
|
||||
return '热门城市'
|
||||
default:
|
||||
return letter.toUpperCase()
|
||||
}
|
||||
}
|
||||
const formatCityData = (list) => {
|
||||
// {{'a':{},'b':{}}}
|
||||
const cityList = {}
|
||||
// 遍历
|
||||
list.forEach(element => {
|
||||
//获取短名称的第一个字母
|
||||
const first = element.short.substr(0, 1)
|
||||
//判断cityList中是否包含
|
||||
if (cityList[first]) {
|
||||
cityList[first].push(element)
|
||||
} else {
|
||||
cityList[first] = [element]
|
||||
}
|
||||
});
|
||||
const cityIndex = Object.keys(cityList).sort()
|
||||
return {
|
||||
cityList,
|
||||
cityIndex
|
||||
}
|
||||
}
|
||||
|
||||
export default class CityList extends React.Component{
|
||||
render(){
|
||||
return (<div>城市选择页面</div>)
|
||||
// const right = (
|
||||
// <div style={{ fontSize: 24 }}>
|
||||
// <Space style={{ '--gap': '16px' }}>
|
||||
// <SearchOutline />
|
||||
// <MoreOutline />
|
||||
// </Space>
|
||||
// </div>
|
||||
// )
|
||||
|
||||
const back = () => { }
|
||||
// Toast.show({
|
||||
// content: '点击了返回区域',
|
||||
// duration: 1000,
|
||||
// })
|
||||
// const list =
|
||||
// // [
|
||||
// // 'Brian Vaughn',
|
||||
// // // And so on...
|
||||
// // ];
|
||||
// Array(100).fill('Brian Vaughn')
|
||||
// function rowRenderer({
|
||||
// key, // Unique key within array of rows
|
||||
// index, // Index of row within collection
|
||||
// isScrolling, // The List is currently being scrolled
|
||||
// isVisible, // This row is visible within the List (eg it is not an overscanned row)
|
||||
// style, // Style object to be applied to row (to position it)
|
||||
// }) {
|
||||
// return (
|
||||
// <div key={key} style={style}>
|
||||
// {list[index]}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
export default class CityList extends React.Component {
|
||||
state = {
|
||||
cityList: {},
|
||||
cityIndex: [],
|
||||
activeIndex: 0
|
||||
}
|
||||
componentDidMount() {
|
||||
this.getCityList()
|
||||
console.info("componentDidMount")
|
||||
}
|
||||
async getCityList() {
|
||||
const res = await axios.get('http://localhost:8080/area/city?level=1')
|
||||
const { cityList, cityIndex } = formatCityData(res.data.body)
|
||||
|
||||
// 热门城市数据
|
||||
const hotRes = await axios.get('http://localhost:8080/area/hot')
|
||||
cityList['hot'] = hotRes.data.body
|
||||
// 放在第一位
|
||||
cityIndex.unshift('hot')
|
||||
|
||||
const curCity = await getCurrentCity();
|
||||
cityList['#'] = [curCity]
|
||||
cityIndex.unshift('#')
|
||||
|
||||
console.info('shezhi zhuangtai')
|
||||
this.setState({
|
||||
cityList,
|
||||
cityIndex
|
||||
})
|
||||
// this.setState(()=>{
|
||||
// return {
|
||||
// cityList:cityList,
|
||||
// cityIndex:cityIndex
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
rowRenderer = ({
|
||||
key, // Unique key within array of rows
|
||||
index, // Index of row within collection
|
||||
isScrolling, // The List is currently being scrolled
|
||||
isVisible, // This row is visible within the List (eg it is not an overscanned row)
|
||||
style, // Style object to be applied to row (to position it)
|
||||
}) => {
|
||||
const cityIndex = this.state.cityIndex
|
||||
const letter = cityIndex[index]
|
||||
return (
|
||||
<div key={key} style={style} className="city">
|
||||
<div className="title">{formatCityIndex(letter)}</div>
|
||||
{
|
||||
this.state.cityList[letter].map(item => (
|
||||
<div className="name" key={item.value}>{item.label}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
getRowHeight = ({ index }) => {
|
||||
return 36 + this.state.cityList[this.state.cityIndex[index]].length * 20
|
||||
}
|
||||
|
||||
renderCityIndex() {
|
||||
const { cityIndex, activeIndex } = this.state
|
||||
return cityIndex.map((item, index) => {
|
||||
<li className="city-index-item" key={item}>
|
||||
<span className={activeIndex === index ? "index-active" : ''}>{item === 'hot' ? '热' : item.toUpperCase()}</span>
|
||||
</li>
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="citylist"><NavBar className="citylist-navbar" back='返回' onBack={back}>城市选择</NavBar>
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<List
|
||||
width={width}
|
||||
height={height}
|
||||
rowCount={this.state.cityIndex.length}
|
||||
rowHeight={this.getRowHeight}
|
||||
rowRenderer={this.rowRenderer}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
<ul className="city-index">{this.renderCityIndex()}</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -2,10 +2,11 @@ import React from 'react'
|
|||
import Bottom from './../Bottom/index'
|
||||
import './index.css'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import WidthUseNavigate from '../WidthUseNavigate'
|
||||
export default class Home extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className='body'><Outlet /><Bottom /></div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.home {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.home .iconfont {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.home .am-tab-bar-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
}
|
||||
|
|
@ -7,21 +7,19 @@ import ImgZZ from './../../assets/images/nav-1.png'
|
|||
import ImgHZ from './../../assets/images/nav-2.png'
|
||||
import ImgDTZF from './../../assets/images/nav-3.png'
|
||||
import ImgQCZ from './../../assets/images/nav-4.png'
|
||||
|
||||
import './index.css'
|
||||
const localCatalog = [
|
||||
{ "imgSrc": ImgZZ, "title": "整租", "path": "/todo" },
|
||||
{ "imgSrc": ImgHZ, "title": "合租", "path": "/todo" },
|
||||
{ "imgSrc": ImgDTZF, "title": "地图找房", "path": "/map" },
|
||||
{ "imgSrc": ImgQCZ, "title": "去出租", "path": "/me" }
|
||||
]
|
||||
navigator.geolocation.getCurrentPosition(position=>{
|
||||
console.log("当前位置信息",position)
|
||||
})
|
||||
class IndexInner extends React.Component {
|
||||
state = {
|
||||
swipers: [],
|
||||
isSwiperLoaded: false,
|
||||
groups: []
|
||||
groups: [],
|
||||
curCityName:''
|
||||
}
|
||||
// 获取轮播图
|
||||
async getSwitpers() {
|
||||
|
@ -53,6 +51,14 @@ class IndexInner extends React.Component {
|
|||
componentDidMount() {
|
||||
this.getSwitpers()
|
||||
this.getGroups()
|
||||
const curCity = new window.BMapGL.LocalCity()
|
||||
curCity.get(async res=>{
|
||||
this.setState(()=>{
|
||||
return {curCityName:res.name}
|
||||
})
|
||||
const result = await axios.get('http://localhost:8080/area/info?name=${res.name}')
|
||||
console.log(result)
|
||||
})
|
||||
}
|
||||
|
||||
renderSwipers() {
|
||||
|
@ -69,9 +75,38 @@ class IndexInner extends React.Component {
|
|||
|
||||
{/* 轮播图 */}
|
||||
<div className='context-swapper'>
|
||||
<div>
|
||||
{
|
||||
this.state.isSwiperLoaded ? <Swiper autoplay loop autoplayInterval='1500'>{this.renderSwipers()}</Swiper> : ""
|
||||
}
|
||||
</div>
|
||||
<div className="search-box">
|
||||
{/* 左侧白色区域 */}
|
||||
<div className="search">
|
||||
{/* 位置 */}
|
||||
<div
|
||||
className="location"
|
||||
onClick={() => this.props.to('/citylist')}
|
||||
>
|
||||
<span className="name">{this.state.curCityName}</span>
|
||||
<i className="iconfont icon-arrow" />
|
||||
</div>
|
||||
|
||||
{/* 搜索表单 */}
|
||||
<div
|
||||
className="form"
|
||||
onClick={() => this.props.to('/search')}
|
||||
>
|
||||
<i className="iconfont icon-seach" />
|
||||
<span className="text">请输入小区或地址</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* 右侧地图图标 */}
|
||||
<i
|
||||
className="iconfont icon-map"
|
||||
onClick={() => this.props.history.push('/map')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 本地导航 */}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import './index.css'
|
||||
import 'react-virtualized/styles.css'
|
||||
|
||||
export default class Map extends React.Component {
|
||||
componentDidMount() {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import axios from "axios"
|
||||
export const getCurrentCity=()=>{
|
||||
const localCity = JSON.parse(localStorage.getItem('local_city'))
|
||||
if(!localCity){
|
||||
return new Promise((resolve,reject)=>{
|
||||
const curCity = new window.BMapGL.LocalCity()
|
||||
curCity.get(async res=>{
|
||||
try{
|
||||
const result = await axios.get('http://localhost:8080/area/info?name=${res.name}')
|
||||
localStorage.setItem('local_city',JSON.stringify(result.data.body))
|
||||
resolve(result.data.body)
|
||||
}catch(e){
|
||||
reject(e)
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
// return new Promise((resolve)=>{
|
||||
// return resolve(localCity)
|
||||
// })
|
||||
return Promise.resolve(localCity)
|
||||
}
|
Loading…
Reference in New Issue