Compare commits
10 Commits
9ed09350f0
...
c46fbd2646
Author | SHA1 | Date |
---|---|---|
|
c46fbd2646 | |
|
9e7996c617 | |
|
41ad91a89d | |
|
e8fba65f81 | |
|
95459b659a | |
|
7a09798e5b | |
|
f47616a7b8 | |
|
f1a6add174 | |
|
366e824545 | |
|
49d6146e3f |
|
@ -10,7 +10,7 @@
|
|||
|
||||
# production
|
||||
/build
|
||||
|
||||
.idea
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="c22c6a78-950d-4bff-ac7a-ed800fcbb7de" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/src/components/DataPickerItem/index.jsx" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/components/DetailForm/index.css" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/components/DetailForm/index.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/components/DetailNavBar/index.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/components/ParentTask/index.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/ToDoList/index.css" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/ToDoList/index.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/utils/requestUtil.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/App.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/App.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/Bottom/index.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Bottom/index.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/Bottom/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Bottom/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/Home/index.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Home/index.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/Home/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Home/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/Map/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Map/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/WidthUseNavigate/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/WidthUseNavigate/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/index.js" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 8
|
||||
}</component>
|
||||
<component name="ProjectId" id="2KWNUOdtRQIUIJvVRsdpzzM23Bg" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "D:/electron/assistant-todo-mobile",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"npm.start.executor": "Run",
|
||||
"ts.external.directory.path": "C:\\Program Files\\JetBrains\\WebStorm 2024.1.5\\plugins\\javascript-plugin\\jsLanguageServicesImpl\\external",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="D:\electron\assistant-todo-mobile\src\components\DataPickerItem" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="start" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
|
||||
<package-json value="$PROJECT_DIR$/package.json" />
|
||||
<command value="run" />
|
||||
<scripts>
|
||||
<script value="start" />
|
||||
</scripts>
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="npm.start" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-js-predefined-1d06a55b98c1-0b3e54e931b4-JavaScript-WS-241.18034.50" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="c22c6a78-950d-4bff-ac7a-ed800fcbb7de" name="Changes" comment="" />
|
||||
<created>1674086393783</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1674086393783</updated>
|
||||
<workItem from="1735199009773" duration="4532000" />
|
||||
<workItem from="1735203621890" duration="33395000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "hkzf-mobile",
|
||||
"name": "assistant-todo-mobile",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
|
@ -8,10 +8,14 @@
|
|||
"@testing-library/user-event": "^13.5.0",
|
||||
"antd-mobile": "^5.27.0",
|
||||
"axios": "^1.2.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"node-gyp": "^9.3.1",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"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,23 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Web site created using create-react-app" />
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> -->
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<script src="http://localhost:8097"></script>
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> -->
|
||||
<!-- <script src="http://localhost:8097"></script> -->
|
||||
<script type="text/javascript"
|
||||
src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=FrkiO8MEXi5umzVgTYTZAYhhnr2cpAhc">
|
||||
</script>
|
||||
<!-- Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
|
@ -25,12 +27,13 @@
|
|||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>华宇平台</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
<title>华宇平台</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- <noscript>You need to enable JavaScript to run this app.</noscript> -->
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
|
@ -40,5 +43,6 @@
|
|||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
.App {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
|
|
69
src/App.js
69
src/App.js
|
@ -1,31 +1,54 @@
|
|||
import { BrowserRouter as Router, Route, Navigate , Routes } from 'react-router-dom';
|
||||
import { Todo, Message, PersonalCenter, Bottom } from './pages/Bottom/index'
|
||||
import { Home } from './pages/Home';
|
||||
import {BrowserRouter as Router, Route, Navigate, Routes} from 'react-router-dom';
|
||||
import Home from './pages/Home';
|
||||
import Map from './pages/Map';
|
||||
import Index from './pages/Index'
|
||||
import './pages/Bottom/index.css'
|
||||
import { NavBar, TabBar } from 'antd-mobile'
|
||||
import CityList from './pages/CityList';
|
||||
import {Todo, Message, PersonalCenter} from './pages/Bottom'
|
||||
import ToDoList from "./pages/ToDoList";
|
||||
import DetailForm from "./components/DetailForm";
|
||||
import {NavBar} from "antd-mobile";
|
||||
import DetailNavBar from "./components/DetailNavBar";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<div className='app'>
|
||||
<div className='top'>
|
||||
return (
|
||||
<Router>
|
||||
<div className='app'>
|
||||
{/* <div className='top'>
|
||||
<NavBar >配合路由使用</NavBar>
|
||||
</div>
|
||||
<div className='body'>
|
||||
<Routes>
|
||||
<Route path='/' element={<Navigate to="/home"/>}>
|
||||
</Route>
|
||||
<Route path='/home' element={<Home />}></Route>
|
||||
<Route path='/todo' element={<Todo />}></Route>
|
||||
</div> */}
|
||||
{/* <div className='body'> */}
|
||||
<Routes>
|
||||
{/* <Route path='/' element={<Navigate to="/home" />}>
|
||||
</Route> */}
|
||||
<Route path='/' element={<Home/>}>
|
||||
<Route index path='/home' element={<Index/>}/>
|
||||
<Route path='/home/todo' element={<ToDoList/>}></Route>
|
||||
<Route path='/home/message' element={<Message/>}></Route>
|
||||
<Route path='/home/me' element={<PersonalCenter/>}></Route>
|
||||
</Route>
|
||||
<Route path='/detail' element={<DetailNavBar/>}>
|
||||
<Route path='addTask' element={<DetailForm/>}></Route>
|
||||
</Route>
|
||||
|
||||
{/* <Route path='/home' element={<Home />}>
|
||||
<Route path='/home/todo' element={<Todo />}></Route>
|
||||
<Route path='/home/message' element={<Message />}></Route>
|
||||
<Route path='/home/me' element={<PersonalCenter />}></Route>
|
||||
</Route> */}
|
||||
{/* <Route path='/todo' element={<Todo />}></Route>
|
||||
<Route path='/message' element={<Message />}></Route>
|
||||
<Route path='/me' element={<PersonalCenter />}></Route>
|
||||
</Routes>
|
||||
</div>
|
||||
<div>
|
||||
<Route path='/me' element={<PersonalCenter />}></Route> */}
|
||||
<Route path='/citylist' element={<CityList/>}></Route>
|
||||
<Route path='/map' element={<Map/>}></Route>
|
||||
</Routes>
|
||||
{/* </div> */}
|
||||
{/* <div>
|
||||
<Bottom />
|
||||
</div>
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
</div> */}
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import {useCallback, useState} from "react";
|
||||
import {
|
||||
Form,
|
||||
DatePicker,
|
||||
} from 'antd-mobile'
|
||||
import dayjs from 'dayjs'
|
||||
import {CloseCircleFill} from 'antd-mobile-icons'
|
||||
|
||||
const DatePickerItem = (props) => {
|
||||
const [pickerVisible, setPickerVisible] = useState(false)
|
||||
const {fieldName, labelName} = props
|
||||
const labelRenderer = useCallback((type, data) => {
|
||||
switch (type) {
|
||||
case 'year':
|
||||
return data + '年'
|
||||
case 'month':
|
||||
return data + '月'
|
||||
case 'day':
|
||||
return data + '日'
|
||||
case 'hour':
|
||||
return data + '时'
|
||||
case 'minute':
|
||||
return data + '分'
|
||||
case 'second':
|
||||
return data + '秒'
|
||||
default:
|
||||
return data
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prevValues, curValues) =>
|
||||
prevValues.fieldName !== curValues.fieldName
|
||||
}
|
||||
>
|
||||
{({getFieldValue, setFieldsValue}) => (
|
||||
<Form.Item
|
||||
name={fieldName}
|
||||
label={labelName}
|
||||
trigger='onConfirm'
|
||||
arrow={
|
||||
getFieldValue(fieldName) ? (
|
||||
<CloseCircleFill
|
||||
style={{
|
||||
color: 'var(--adm-color-light)',
|
||||
fontSize: 14,
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
setFieldsValue({fieldName: null})
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
true
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
setPickerVisible(true)
|
||||
}}
|
||||
>
|
||||
<DatePicker
|
||||
precision='minute'
|
||||
visible={pickerVisible}
|
||||
renderLabel={labelRenderer}
|
||||
onClose={() => {
|
||||
setPickerVisible(false)
|
||||
}}
|
||||
>
|
||||
{value =>
|
||||
value ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '请选择日期'
|
||||
}
|
||||
</DatePicker>
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
export default DatePickerItem;
|
|
@ -0,0 +1,3 @@
|
|||
.adm-tag {
|
||||
font-size: var(--adm-font-size-9);
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Dialog,
|
||||
TextArea,
|
||||
Space,
|
||||
Checkbox, Selector, Tag, Radio
|
||||
} from 'antd-mobile'
|
||||
import ParentTask from "../ParentTask";
|
||||
import DatePickerItem from "../DataPickerItem"
|
||||
import "./index.css"
|
||||
export default () => {
|
||||
const now = new Date()
|
||||
const onFinish = (values) => {
|
||||
Dialog.alert({
|
||||
content: <pre>{JSON.stringify(values, null, 2)}</pre>,
|
||||
})
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Form
|
||||
layout='horizontal'
|
||||
onFinish={onFinish}
|
||||
footer={
|
||||
<Button block type='submit' color='primary' size='large'>
|
||||
提交
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<ParentTask/>
|
||||
<Form.Item
|
||||
name='name'
|
||||
label='任务名称'
|
||||
rules={[{required: true, message: '任务名称不能为空'}]}
|
||||
>
|
||||
<Input onChange={console.log} placeholder='任务名称'/>
|
||||
</Form.Item>
|
||||
<Form.Item name='address' label='任务描述' help='详情地址'>
|
||||
<TextArea
|
||||
placeholder='请输入地址'
|
||||
maxLength={100}
|
||||
rows={2}
|
||||
showCount
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name='state' label='任务状态' required>
|
||||
<Radio.Group>
|
||||
<Space direction='vertical'>
|
||||
<Radio value='1'><Tag color='danger'>未开始</Tag></Radio>
|
||||
<Radio value='2'><Tag color='warning'>进行中</Tag></Radio>
|
||||
<Radio value='3'><Tag color='success'>已完成</Tag></Radio>
|
||||
<Radio value='4'><Tag>已关闭</Tag></Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item name='priority' label='任务优先级'>
|
||||
<Radio.Group>
|
||||
<Space direction='vertical'>
|
||||
<Radio value='1'><Tag color='danger'>紧急重要</Tag></Radio>
|
||||
<Radio value='2'><Tag color='warning'>不紧急重要</Tag></Radio>
|
||||
<Radio value='3'><Tag>紧急不重要</Tag></Radio>
|
||||
<Radio value='4'><Tag color='success'>不紧急不重要</Tag></Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<DatePickerItem fieldName={"expectedStartTime"} labelName={"预计开始时间"}/>
|
||||
<DatePickerItem fieldName={"expectedEndTime"} labelName={"预计结束时间"}/>
|
||||
<DatePickerItem fieldName={"actualStartTime"} labelName={"实际开始时间"}/>
|
||||
<DatePickerItem fieldName={"actualEndTime"} labelName={"实际结束时间"}/>
|
||||
</Form>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import React from "react";
|
||||
import {Outlet,useNavigate} from "react-router-dom";
|
||||
import {NavBar} from "antd-mobile";
|
||||
|
||||
const DetailNavBar = () => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleClick =()=> {
|
||||
console.log("click",navigate.length);
|
||||
navigate(-1)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='detail'>
|
||||
<NavBar back='返回' onBack={handleClick}>标题</NavBar><Outlet/>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
export default DetailNavBar;
|
|
@ -0,0 +1,4 @@
|
|||
.navbar {
|
||||
color: #333;
|
||||
background-color: #f6f5f6;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import React from "react";
|
||||
import { NavBar } from "antd-mobile";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PropTypes from 'prop-types'
|
||||
import styles from './index.module.css'
|
||||
export default function NavHeader({children,back}){
|
||||
const defaultHandler =()=>navigate(-1);
|
||||
const navigate = useNavigate();
|
||||
return (<NavBar className={styles.NavBar} back='返回' onBack={back||defaultHandler} >{children}</NavBar>)
|
||||
}
|
||||
// 添加校验
|
||||
NavHeader.propTypes={
|
||||
children:PropTypes.string.isRequired,
|
||||
back:PropTypes.func
|
||||
}
|
||||
// export default withRouter(NavHeader)
|
|
@ -0,0 +1,8 @@
|
|||
.navbar {
|
||||
color: #333;
|
||||
background-color: #f6f5f6;
|
||||
}
|
||||
/* 全局类型处理 */
|
||||
.navbar :global(.am-navbar-title){
|
||||
color: #333;
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
import {Cascader,Input, Toast} from "antd-mobile";
|
||||
import React, {useState} from "react";
|
||||
import {
|
||||
Form,
|
||||
} from 'antd-mobile'
|
||||
const options = [
|
||||
{
|
||||
label: '浙江',
|
||||
value: '浙江',
|
||||
children: [
|
||||
{
|
||||
label: '杭州',
|
||||
value: '杭州',
|
||||
children: [
|
||||
{
|
||||
label: '西湖区',
|
||||
value: '西湖区',
|
||||
},
|
||||
{
|
||||
label: '上城区',
|
||||
value: '上城区',
|
||||
},
|
||||
{
|
||||
label: '余杭区',
|
||||
value: '余杭区',
|
||||
disabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '温州',
|
||||
value: '温州',
|
||||
children: [
|
||||
{
|
||||
label: '鹿城区',
|
||||
value: '鹿城区',
|
||||
},
|
||||
{
|
||||
label: '龙湾区',
|
||||
value: '龙湾区',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
label: '瓯海区',
|
||||
value: '瓯海区',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '宁波',
|
||||
value: '宁波',
|
||||
children: [
|
||||
{
|
||||
label: '海曙区',
|
||||
value: '海曙区',
|
||||
},
|
||||
{
|
||||
label: '江北区',
|
||||
value: '江北区',
|
||||
},
|
||||
{
|
||||
label: '镇海区',
|
||||
value: '镇海区',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '安徽',
|
||||
value: '安徽',
|
||||
children: [
|
||||
{
|
||||
label: '合肥',
|
||||
value: '合肥',
|
||||
children: [
|
||||
{
|
||||
label: '包河区',
|
||||
value: '包河区',
|
||||
},
|
||||
{
|
||||
label: '蜀山区',
|
||||
value: '蜀山区',
|
||||
},
|
||||
{
|
||||
label: '瑶海区',
|
||||
value: '瑶海区',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '芜湖',
|
||||
value: '芜湖',
|
||||
children: [
|
||||
{
|
||||
label: '镜湖区',
|
||||
value: '镜湖区',
|
||||
},
|
||||
{
|
||||
label: '弋江区',
|
||||
value: '弋江区',
|
||||
},
|
||||
{
|
||||
label: '湾沚区',
|
||||
value: '湾沚区',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '江苏',
|
||||
value: '江苏',
|
||||
children: [
|
||||
{
|
||||
label: '南京',
|
||||
value: '南京',
|
||||
children: [
|
||||
{
|
||||
label: '玄武区',
|
||||
value: '玄武区',
|
||||
},
|
||||
{
|
||||
label: '秦淮区',
|
||||
value: '秦淮区',
|
||||
},
|
||||
{
|
||||
label: '建邺区',
|
||||
value: '建邺区',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '苏州',
|
||||
value: '苏州',
|
||||
children: [
|
||||
{
|
||||
label: '虎丘区',
|
||||
value: '虎丘区',
|
||||
},
|
||||
{
|
||||
label: '吴中区',
|
||||
value: '吴中区',
|
||||
},
|
||||
{
|
||||
label: '相城区',
|
||||
value: '相城区',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
const ParentTask = ()=>{
|
||||
const [parentValue, setParentValue] = useState("")
|
||||
const [visible, setVisible] = useState(false)
|
||||
return <Form.Item
|
||||
name='pid'
|
||||
label='主线任务'
|
||||
onClick={() => {
|
||||
setVisible(true)
|
||||
}}
|
||||
>
|
||||
<Cascader
|
||||
options={options}
|
||||
visible={visible}
|
||||
onClose={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
value={parentValue}
|
||||
onConfirm={setParentValue}
|
||||
onSelect={(val, extend) => {
|
||||
console.log('onSelect', val, extend.items)
|
||||
}}
|
||||
>
|
||||
{items => {
|
||||
if (items.every(item => item === null)) {
|
||||
return <span style={{color:"#cccccc"}}>主线任务选线</span>
|
||||
} else {
|
||||
return items.map(item => item?.label ??
|
||||
<span style={{color: "#cccccc"}}>主线任务选线</span>).join('-')
|
||||
}
|
||||
}}
|
||||
</Cascader>
|
||||
</Form.Item>
|
||||
// const [parentValue, setParentValue] = useState("")
|
||||
// return <Form.Item
|
||||
// name='name'
|
||||
// label='主线任务'
|
||||
// onClick={async () => {
|
||||
// const value = await Cascader.prompt({
|
||||
// options: options,
|
||||
// placeholder: '请选择',
|
||||
// })
|
||||
// Toast.show(
|
||||
// value ? `你选择了 ${value.join(' - ')}` : '你没有进行选择'
|
||||
// )
|
||||
// if (value){
|
||||
// setParentValue(value.join(' - '))
|
||||
// }
|
||||
// }}
|
||||
// >
|
||||
// <Input
|
||||
// defaultValue={parentValue}
|
||||
// value={parentValue}
|
||||
// readOnly={true}
|
||||
// placeholder='主线任务名称选填'>
|
||||
// {parentValue}
|
||||
// </Input>
|
||||
// </Form.Item>
|
||||
}
|
||||
export default ParentTask;
|
|
@ -9,10 +9,15 @@ html,body {
|
|||
font-family: Microsoft YaHei;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,body,#root, .App{
|
||||
height: 100%;
|
||||
}
|
||||
/* code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
.adm-tab-bar {
|
||||
flex: 0;
|
||||
background: white;
|
||||
border-top: solid 1px var(--adm-color-border);
|
||||
width:100%;
|
||||
position: fixed;
|
||||
|
|
|
@ -1,71 +1,109 @@
|
|||
import React ,{FC} from "react";
|
||||
import { NavBar, TabBar } from 'antd-mobile'
|
||||
import React, {FC, Fragment} from "react";
|
||||
import {TabBar, FloatingBubble, Toast} from 'antd-mobile'
|
||||
import WidthUseNavigate from './../WidthUseNavigate/index'
|
||||
import {
|
||||
Route,Routes,
|
||||
useLocation,
|
||||
MemoryRouter as Router,
|
||||
useNavigate,
|
||||
} from 'react-router-dom'
|
||||
import {
|
||||
AppOutline,
|
||||
MessageOutline,
|
||||
UnorderedListOutline,
|
||||
UserOutline,
|
||||
AppOutline,
|
||||
MessageOutline,
|
||||
UnorderedListOutline,
|
||||
UserOutline,
|
||||
AddOutline,
|
||||
} from 'antd-mobile-icons'
|
||||
export 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: '/todo',
|
||||
title: '待办',
|
||||
icon: <UnorderedListOutline />,
|
||||
badge: '2',
|
||||
},
|
||||
{
|
||||
key: '/message',
|
||||
title: '消息',
|
||||
icon: <MessageOutline />,
|
||||
badge: '3',
|
||||
},
|
||||
{
|
||||
key: '/me',
|
||||
title: '我的',
|
||||
icon: <UserOutline />,
|
||||
badge: '4',
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<TabBar activeKey={pathname} onChange={value => setRouteActive(value)}>
|
||||
{tabs.map(item => (
|
||||
<TabBar.Item key={item.key} icon={item.icon} title={item.title} badge= {item.badge}/>
|
||||
))}
|
||||
</TabBar>
|
||||
)
|
||||
}
|
||||
import "./index.css"
|
||||
import DetailForm from "../../components/DetailForm";
|
||||
|
||||
|
||||
export function Todo() {
|
||||
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
|
||||
}
|
||||
|
||||
// 组件接收到新的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
|
||||
})
|
||||
}
|
||||
onClick = () => {
|
||||
// Toast.show('你点击了气泡')
|
||||
this.props.to("/detail/addTask")
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Fragment>
|
||||
<FloatingBubble
|
||||
axis='x'
|
||||
magnetic='x'
|
||||
style={{
|
||||
'--initial-position-bottom': '80px',
|
||||
'--initial-position-right': '24px',
|
||||
'--edge-distance': '24px',
|
||||
}}
|
||||
onClick={this.onClick}
|
||||
>
|
||||
<AddOutline fontSize={32}/>
|
||||
</FloatingBubble>
|
||||
<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>
|
||||
</Fragment>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function Todo() {
|
||||
return <div>待办</div>
|
||||
}
|
||||
|
||||
export function Message() {
|
||||
}
|
||||
|
||||
export function Message() {
|
||||
return <div>消息</div>
|
||||
}
|
||||
|
||||
export function PersonalCenter() {
|
||||
return <div>我的</div>
|
||||
}
|
||||
}
|
||||
|
||||
export function PersonalCenter() {
|
||||
return <div>pc端可访问:http://www.hauruyu.com</div>
|
||||
}
|
||||
|
||||
// 使用高阶组件包裹当前类组件
|
||||
const Bottom = WidthUseNavigate(BottomInner);
|
||||
export default Bottom
|
|
@ -0,0 +1,34 @@
|
|||
.citylist{
|
||||
height: 100%;
|
||||
/* padding-top: 45px; */
|
||||
}
|
||||
ul{
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.city-index {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
right: 5px;
|
||||
z-index: 1;
|
||||
height: 90%;
|
||||
box-sizing: border-box;
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.city-index .city-index-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.city-index .index-active {
|
||||
color: #fff;
|
||||
background-color: #21b97a;
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
}
|
|
@ -1,6 +1,192 @@
|
|||
import React from "react";
|
||||
export default class CityList extends React.Component{
|
||||
render(){
|
||||
return (<div>城市选择页面</div>)
|
||||
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";
|
||||
import WidthUseNavigate from "../WidthUseNavigate";
|
||||
import NavHeader from "../../components/NavHeader";
|
||||
import styles from './index.module.css'
|
||||
console.log(styles)
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
const HOUSE_CITY= ['北京','上海','广州','深圳']
|
||||
// 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>
|
||||
// );
|
||||
// }
|
||||
class CityListInner extends React.Component {
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
cityList: {},
|
||||
cityIndex: [],
|
||||
activeIndex: 0
|
||||
}
|
||||
this.cityListComponent = React.createRef()
|
||||
}
|
||||
async componentDidMount() {
|
||||
await this.getCityList()
|
||||
//提前计算list高度
|
||||
this.cityListComponent.current.measureAllRows()
|
||||
}
|
||||
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('#')
|
||||
|
||||
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} onClick={()=>this.changeCity(item)}>{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} onClick={()=>{this.cityListComponent.current.scrollToRow(index)}}>
|
||||
<span className={activeIndex === index ? "index-active" : ''}>{item === 'hot' ? '热' : item.toUpperCase()}</span>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
// 用户获取list组件渲染行数据
|
||||
onRowsRendered=({startIndex})=>{
|
||||
if(this.state.activeIndex!=startIndex){
|
||||
this.setState({
|
||||
activeIndex:startIndex
|
||||
})
|
||||
}
|
||||
}
|
||||
changeCity({label,value}){
|
||||
if(HOUSE_CITY.indexOf(label)>-1){
|
||||
localStorage.setItem('local_city',JSON.stringify({label,value}))
|
||||
// 返回上一个页面
|
||||
this.props.to(-1)
|
||||
}else{
|
||||
Toast.show('该城市暂无房源数据')
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="citylist"><NavHeader>城市选择</NavHeader>
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<List
|
||||
width={width}
|
||||
height={height}
|
||||
ref={this.cityListComponent}
|
||||
rowCount={this.state.cityIndex.length}
|
||||
rowHeight={this.getRowHeight}
|
||||
rowRenderer={this.rowRenderer}
|
||||
onRowsRendered={this.onRowsRendered}
|
||||
scrollToAlignment="start" />
|
||||
)}
|
||||
</AutoSizer>
|
||||
<ul className="city-index">{this.renderCityIndex()}</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
// 使用高阶组件包裹当前类组件
|
||||
const CityList = WidthUseNavigate(CityListInner);
|
||||
export default CityList
|
|
@ -6,10 +6,32 @@
|
|||
user-select: none;
|
||||
align-items: top;
|
||||
} */
|
||||
.context-swapper {
|
||||
height: 212px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
width: 100%;
|
||||
padding: 0, 10px;
|
||||
}
|
||||
|
||||
.adm-grid-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.context h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.context {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.adm-search-bar{
|
||||
height: 40px;
|
||||
}
|
||||
.adm-search-bar-input-box {
|
||||
height: 40px;
|
||||
}
|
|
@ -1,59 +1,22 @@
|
|||
import React from 'react'
|
||||
import { Swiper, CapsuleTabs, Grid } from 'antd-mobile'
|
||||
import axios from 'axios';
|
||||
import Bottom from './../Bottom/index'
|
||||
import './index.css'
|
||||
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 { redirect, useNavigate } from 'react-router-dom';
|
||||
const localCatalog = [
|
||||
{ "imgSrc": ImgZZ, "title": "整租" ,"path":"/todo"},
|
||||
{ "imgSrc": ImgHZ, "title": "合租" ,"path":"/todo"},
|
||||
{ "imgSrc": ImgDTZF, "title": "地图找房" ,"path":"/message"},
|
||||
{ "imgSrc": ImgQCZ, "title": "去出租" ,"path":"/me"}
|
||||
]
|
||||
export class Home extends React.Component {
|
||||
state = {
|
||||
swipers: []
|
||||
}
|
||||
async getSwitpers() {
|
||||
const res = await axios.get('http://localhost:8080/home/swiper')
|
||||
console.log('轮播图信息' + res.data.body)
|
||||
this.setState(
|
||||
{ swipers: res.data.body }
|
||||
// ()=>{
|
||||
// return{swipers:res.data.body}
|
||||
// }
|
||||
import {Outlet} from 'react-router-dom'
|
||||
import {SearchBar} from "antd-mobile";
|
||||
|
||||
export default class Home extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className='body'>
|
||||
<div style={{"position": "fixed","top":"0","left":"0","width":"100%","zIndex":100}}>
|
||||
<SearchBar placeholder='请输入内容'/>
|
||||
</div>
|
||||
<div style={{marginTop:"40px",width:"100%"}}>
|
||||
<Outlet/>
|
||||
</div>
|
||||
|
||||
<Bottom/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
componentDidMount() {
|
||||
this.getSwitpers()
|
||||
}
|
||||
|
||||
renderSwipers() {
|
||||
return this.state.swipers.map(item => (<Swiper.Item key={item.id}>
|
||||
<img
|
||||
src={'http://localhost:8080' + item.imgSrc}
|
||||
style={{ width: '100%', verticalAlign: 'top' }}
|
||||
/>
|
||||
</Swiper.Item>))
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className='context'>
|
||||
<Swiper autoplay loop>{this.renderSwipers()}</Swiper>
|
||||
<Grid columns={4}>
|
||||
{
|
||||
localCatalog.map((item,index) => (
|
||||
<Grid.Item key={index} onClick={()=>{
|
||||
console.log("点击跳转")
|
||||
this.props.navigate=item.path}}>
|
||||
<div ><img src={item.imgSrc} /><h2>{item.title}</h2></div>
|
||||
</Grid.Item>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
</div>
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.home {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.home .iconfont {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.home .am-tab-bar-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import React from 'react'
|
||||
import { BrowserRouter as Router, Route, Navigate , Routes } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import { Swiper,Grid } from 'antd-mobile';
|
||||
import WidthUseNavigate from './../WidthUseNavigate/index'
|
||||
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" }
|
||||
]
|
||||
class IndexInner extends React.Component {
|
||||
state = {
|
||||
swipers: [],
|
||||
isSwiperLoaded: false,
|
||||
groups: [],
|
||||
curCityName:''
|
||||
}
|
||||
// 获取轮播图
|
||||
async getSwitpers() {
|
||||
const res = await axios.get('http://localhost:8080/home/swiper')
|
||||
this.setState(
|
||||
{
|
||||
swipers: res.data.body,
|
||||
isSwiperLoaded: true
|
||||
},
|
||||
|
||||
// ()=>{
|
||||
// return{swipers:res.data.body}
|
||||
// }
|
||||
)
|
||||
}
|
||||
// 获取租房小组
|
||||
async getGroups() {
|
||||
const res = await axios.get('http://localhost:8080/home/groups', {
|
||||
params: {
|
||||
area: 'AREA%7C88cff55c-aaa4-e2e0'
|
||||
}
|
||||
})
|
||||
this.setState(
|
||||
() => {
|
||||
return { groups: res.data.body }
|
||||
}
|
||||
)
|
||||
}
|
||||
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() {
|
||||
return this.state.swipers.map(item => (<Swiper.Item key={item.id}>
|
||||
<img height='212'
|
||||
src={'http://localhost:8080' + item.imgSrc}
|
||||
style={{ width: '100%', verticalAlign: 'top' }}
|
||||
/>
|
||||
</Swiper.Item>))
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className='context'>
|
||||
|
||||
{/* 轮播图 */}
|
||||
<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>
|
||||
|
||||
{/* 本地导航 */}
|
||||
<Grid columns={4}>
|
||||
{
|
||||
localCatalog.map((item, index) => (
|
||||
<Grid.Item key={index} onClick={() => {
|
||||
console.log("点击跳转")
|
||||
this.props.to(item.path)
|
||||
}}>
|
||||
<div ><img src={item.imgSrc} /><h2>{item.title}</h2></div>
|
||||
</Grid.Item>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
{/* 租房小组 */}
|
||||
<div className='group'>
|
||||
<h3 className='title'>
|
||||
租房小组<span className='more'>更多</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
};
|
||||
}
|
||||
// 使用高阶组件包裹当前类组件
|
||||
const Index = WidthUseNavigate(IndexInner);
|
||||
export default Index
|
|
@ -0,0 +1,4 @@
|
|||
#container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
import React from "react";
|
||||
// import './index.css'
|
||||
import 'react-virtualized/styles.css'
|
||||
import NavHeader from "../../components/NavHeader";
|
||||
import styles from './index.module.css'
|
||||
import axios from "axios";
|
||||
import Item from "antd-mobile/es/components/dropdown/item";
|
||||
import { type } from "@testing-library/user-event/dist/type";
|
||||
|
||||
export default class Map extends React.Component {
|
||||
async renderOverlays(id){
|
||||
const res = await axios.get('http://localhost:8080/area/map?id='+id)
|
||||
const {nextZoom,type} = this.getTypeAndZoom
|
||||
res.data.body.forEach(element => {
|
||||
this.createOverlays(element,nextZoom,type)
|
||||
})
|
||||
}
|
||||
createCircle(element){
|
||||
const {coord:{longitude,latitude},label:areaName,count,value}=element;
|
||||
console.info(longitude,latitude)
|
||||
var label = new window.BMapGL.Label(`
|
||||
<div class="${styles.bubble}">
|
||||
<p class="${styles.name}">${areaName}</p>
|
||||
<p>${count}</p>
|
||||
`, { // 创建文本标注
|
||||
position: new window.BMapGL.Point(longitude,latitude), // 设置标注的地理位置
|
||||
offset: new window.BMapGL.Size(10, 20) // 设置标注的偏移量
|
||||
})
|
||||
this.map.addOverlay(label);
|
||||
label.id=value
|
||||
label.addEventListener('click',()=>{
|
||||
console.log(value)
|
||||
// // 放大地图
|
||||
// this.map.centerAndZoom(new window.BMapGL.Point(longitude,latitude),nextZoom)
|
||||
// // 清除当前覆盖物信息
|
||||
// this.map.clearOverlays()
|
||||
})
|
||||
}
|
||||
createRect(element){
|
||||
const {coord:{longitude,latitude},label:areaName,count,value}=element;
|
||||
console.info(longitude,latitude)
|
||||
var label = new window.BMapGL.Label(`
|
||||
<div class="${styles.bubble}">
|
||||
<p class="${styles.name}">${areaName}</p>
|
||||
<p>${count}</p>
|
||||
`, { // 创建文本标注
|
||||
position: new window.BMapGL.Point(longitude,latitude), // 设置标注的地理位置
|
||||
offset: new window.BMapGL.Size(10, 20) // 设置标注的偏移量
|
||||
})
|
||||
this.map.addOverlay(label);
|
||||
label.id=value
|
||||
label.addEventListener('click',()=>{
|
||||
console.log(value)
|
||||
this.getHousesList(value)
|
||||
})
|
||||
}
|
||||
async getHousesList(id){
|
||||
const res = await axios.get(`http://localhost:8080/houses?cityId=${id}`)
|
||||
|
||||
}
|
||||
createOverlays(element,nextZoom,type){
|
||||
if(type === 'circle'){
|
||||
this.createCircle(element)
|
||||
}else{
|
||||
this.createRect(element)
|
||||
}
|
||||
}
|
||||
getTypeAndZoom(){
|
||||
const zoom = this.map.getZoom()
|
||||
let nextZoom,type
|
||||
if(zoom>=10&&zoom<12){
|
||||
nextZoom=13
|
||||
type='circle'
|
||||
}else if(zoom>=12&&zoom<14){
|
||||
nextZoom=15
|
||||
type='circle'
|
||||
}else if(zoom>=14&&zoom<16){
|
||||
type='rect'
|
||||
}
|
||||
return {nextZoom,type}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// 获取当前城市
|
||||
const {label,value}=JSON.parse(localStorage.getItem('local_city'))
|
||||
console.log(label,value)
|
||||
// 解析当前坐标
|
||||
|
||||
var myGeo = new window.BMapGL.Geocoder();
|
||||
// 将地址解析结果显示在地图上,并调整地图视野
|
||||
// myGeo.getPoint('北京市海淀区上地10街', function(point){
|
||||
// if(point){
|
||||
// map.centerAndZoom(point, 16);
|
||||
// map.addOverlay(new window.BMapGL.Marker(point, {title: '北京市海淀区上地10街'}))
|
||||
// }else{
|
||||
// alert('您选择的地址没有解析到结果!');
|
||||
// }
|
||||
// }, '北京市')
|
||||
var map = new window.BMapGL.Map("container")
|
||||
// 在其他方法中可以使用map
|
||||
this.map = map
|
||||
myGeo.getPoint(label,async point=>{
|
||||
if(point){
|
||||
map.centerAndZoom(point,11)
|
||||
// map.addOverlay(new window.BMapGL.Marker(point))
|
||||
var scaleCtrl = new window.BMapGL.ScaleControl(); // 添加比例尺控件
|
||||
map.addControl(scaleCtrl);
|
||||
var zoomCtrl = new window.BMapGL.ZoomControl(); // 添加缩放控件
|
||||
map.addControl(zoomCtrl);
|
||||
var cityCtrl = new window.BMapGL.CityListControl(); // 添加城市列表控件
|
||||
map.addControl(cityCtrl);
|
||||
this.renderOverlays(value)
|
||||
// 文本覆盖物
|
||||
// const res = await axios.get('http://localhost:8080/area/map?id='+value)
|
||||
// res.data.body.forEach(element => {
|
||||
// //
|
||||
// const {coord:{longitude,latitude},label:areaName,count,value}=element;
|
||||
// console.info(longitude,latitude)
|
||||
// var label = new window.BMapGL.Label(`
|
||||
// <div class="${styles.bubble}">
|
||||
// <p class="${styles.name}">${areaName}</p>
|
||||
// <p>${count}</p>
|
||||
// `, { // 创建文本标注
|
||||
// position: new window.BMapGL.Point(longitude,latitude), // 设置标注的地理位置
|
||||
// offset: new window.BMapGL.Size(10, 20) // 设置标注的偏移量
|
||||
// })
|
||||
// map.addOverlay(label);
|
||||
// label.id=value
|
||||
// label.addEventListener('click',()=>{
|
||||
// console.log(value)
|
||||
// // 放大地图
|
||||
// map.centerAndZoom(new window.BMapGL.Point(longitude,latitude),13)
|
||||
// // 清除当前覆盖物信息
|
||||
// map.clearOverlays()
|
||||
// })
|
||||
|
||||
// });
|
||||
// var point = new BMapGL.Point(116.404, 39.915);
|
||||
// var content = "文本覆盖物";
|
||||
// var label = new window.BMapGL.Label(content, { // 创建文本标注
|
||||
// position: point, // 设置标注的地理位置
|
||||
// offset: new window.BMapGL.Size(10, 20) // 设置标注的偏移量
|
||||
// })
|
||||
// label.setStyle({color:'red'})
|
||||
// map.addOverlay(label);
|
||||
}
|
||||
},label)
|
||||
// 设置中心点
|
||||
// var point = new window.BMapGL.Point(116.404, 39.915);
|
||||
// map.centerAndZoom(point, 15);
|
||||
map.enableScrollWheelZoom(true);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.map}>
|
||||
<NavHeader>地图找房</NavHeader>
|
||||
<div id="container" className={styles.container}>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
.map{
|
||||
padding-top: 45px;
|
||||
height: 100%;
|
||||
}
|
||||
.container{
|
||||
height: 100%;
|
||||
}
|
||||
.map :global(.adm-nav-bar){
|
||||
margin-top: -45px;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.adm-list-default{
|
||||
width:100%;
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
import {Dialog,Image, List, SwipeAction} from 'antd-mobile'
|
||||
import React, {useEffect, useRef, useState} from 'react'
|
||||
import {
|
||||
DragDropContext,
|
||||
Draggable,
|
||||
Droppable,
|
||||
// DropResult,
|
||||
} from 'react-beautiful-dnd'
|
||||
import {getTaskList} from "../../utils";
|
||||
import "./index.css"
|
||||
|
||||
const reorder = (
|
||||
list,
|
||||
startIndex,
|
||||
endIndex
|
||||
) => {
|
||||
const result = Array.from(list)
|
||||
const [removed] = result.splice(startIndex, 1)
|
||||
result.splice(endIndex, 0, removed)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const ToDoList = () => {
|
||||
const [taskList, setTaskList] = useState([])
|
||||
useEffect(() => {
|
||||
getTaskList().then(result => {
|
||||
console.log("getTaskList()", result)
|
||||
setTaskList(result.data.data.content)
|
||||
})
|
||||
}, [])
|
||||
const onDragEnd = (result) => {
|
||||
if (!result.destination) return
|
||||
const newList = reorder(taskList, result.source.index, result.destination.index)
|
||||
setTaskList([...newList])
|
||||
}
|
||||
const ref = useRef(null)
|
||||
return (
|
||||
<List
|
||||
// header='任务清单'
|
||||
>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId='droppable'>
|
||||
{droppableProvided => (
|
||||
<div ref={droppableProvided.innerRef}>
|
||||
{taskList.map((item, index) => (
|
||||
<Draggable key={item.id} draggableId={item.id} index={index}>
|
||||
{(provided, snapshot) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
style={{
|
||||
...provided.draggableProps.style,
|
||||
opacity: snapshot.isDragging ? 0.8 : 1,
|
||||
}}
|
||||
>
|
||||
<SwipeAction
|
||||
ref={ref}
|
||||
closeOnAction={false}
|
||||
closeOnTouchOutside={false}
|
||||
rightActions={[
|
||||
{
|
||||
key: 'delete',
|
||||
text: '删除',
|
||||
color: 'danger',
|
||||
onClick: async () => {
|
||||
await Dialog.confirm({
|
||||
content: '确定要关闭吗?',
|
||||
})
|
||||
ref.current?.close()
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'close',
|
||||
text: '关闭',
|
||||
color: 'warning',
|
||||
onClick: async () => {
|
||||
await Dialog.confirm({
|
||||
content: '确定要关闭吗?',
|
||||
})
|
||||
ref.current?.close()
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'update',
|
||||
text: '修改',
|
||||
color: 'primary',
|
||||
onClick: async () => {
|
||||
await Dialog.confirm({
|
||||
content: '确定要修改吗?',
|
||||
})
|
||||
ref.current?.close()
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'complete',
|
||||
text: '完成',
|
||||
color: 'success',
|
||||
onClick: async () => {
|
||||
await Dialog.confirm({
|
||||
content: '确定要完成吗?',
|
||||
})
|
||||
ref.current?.close()
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<List.Item
|
||||
key={item.id}
|
||||
// prefix={
|
||||
// <Image
|
||||
// src={item.avatar}
|
||||
// style={{ borderRadius: 20 }}
|
||||
// fit='cover'
|
||||
// width={40}
|
||||
// height={40}
|
||||
// />
|
||||
// }
|
||||
description={item.description}
|
||||
onClick={
|
||||
()=>{console.log("dianji")}
|
||||
}
|
||||
>
|
||||
{item.name}
|
||||
</List.Item>
|
||||
</SwipeAction>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
{droppableProvided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
</List>
|
||||
)
|
||||
}
|
||||
export default ToDoList;
|
|
@ -2,19 +2,19 @@ import { useNavigate } from 'react-router-dom'
|
|||
// 高阶组件包装useNavigate()功能
|
||||
// 原因:类组件中无法使用useNavigate(),会报错
|
||||
// React Hook "useNavigate" cannot be called in a class component.
|
||||
function WidthUseNavigate(WrapCompontent) {
|
||||
function WidthUseNavigate(WrapComponent) {
|
||||
// 设置别名
|
||||
WrapCompontent.displayName = `widthUseNavigate${getDisplayName(WrapCompontent)}`
|
||||
return function NavigateCompont() {
|
||||
WrapComponent.displayName = `widthUseNavigate${getDisplayName(WrapComponent)}`
|
||||
return function NavigateComponent() {
|
||||
const navigate = useNavigate()
|
||||
// 给传入的组件新增一个to方法,传给原始组件的props,在原始组件中通过this.props.to(参数)使用
|
||||
return <WrapCompontent to={navigate}></WrapCompontent>
|
||||
return <WrapComponent to={navigate}></WrapComponent>
|
||||
}
|
||||
}
|
||||
|
||||
// 别名
|
||||
function getDisplayName(WrapCompontent) {
|
||||
return WrapCompontent.displayname || WrapCompontent.name || 'Component'
|
||||
function getDisplayName(WrapComponent) {
|
||||
return WrapComponent.displayname || WrapComponent.name || 'Component'
|
||||
}
|
||||
|
||||
export default WidthUseNavigate
|
|
@ -0,0 +1,30 @@
|
|||
import axios from "axios"
|
||||
import {requestUtil} from "./requestUtil";
|
||||
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)
|
||||
}
|
||||
|
||||
export const getTaskList= () => {
|
||||
return requestUtil.get('/todo-server/search/task_message_tree?search=%7B%22pageSize%22%3A20%2C%22pageNumber%22%3A1%2C%22data%22%3A%5B%7B%22name%22%3A%22tree%22%2C%22value%22%3A%22TRUE%22%2C%22operateType%22%3A%22TREE-FILTER%22%7D%2C%7B%22name%22%3A%22state%22%2C%22value%22%3A%228%2C9%22%2C%22operateType%22%3A%22IN%22%7D%5D%7D');
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import axios from "axios";
|
||||
|
||||
export const requestUtil = axios.create({
|
||||
baseURL: 'http://www.huaruyu.com/',
|
||||
timeout: 1000,
|
||||
headers: {'Authorization': 'Bearer eyJraWQiOiIwNzdlYzBjMi1iZDQwLTRjODktOGE5OC05OTI1YmZkNzJlZjAiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzaGl4aWFvaHVhIiwic3ViIjoie1wiaWRcIjpcIjM2OTg0Nzc3MTAxODAzNTIwXCIsXCJuaWNrbmFtZVwiOlwi5biI5pmT5Y2OXCIsXCJ1c2VybmFtZVwiOlwic2hpeGlhb2h1YVwifSJ9.WiNGZYbWlIdu3WL7ujtlKsGa42IblW93SG-Mf4jDOuECWrDHFNA0gJBKUQkWKQfpWWRaIzcBmUC78WkIM5yFIHiB2_wBXyywHyjVCWBYC3sTJghtWogLB9ceR69eNfCZanm_ZlrcIEWJ9rqCk-hmMEuWwIk9xJ-M4hFGHkoAr_ftYJiBkGqgKpXOeVE_Tish6SqYZtN-V6Dcnyny3k7T6lG1jzXGyhokEzg_0B5hYpRvvA-GJx14Q1RO6Sv3vgMFOX63bhKX3L7KCSwLO2NJ5GkFHXqcDCf_-pnbiHUtP1JrchzXGWpI_Blrlf_65CdrMWuyVSGtDJ6_Z-Ef4Uq_tQ'}
|
||||
});
|
Loading…
Reference in New Issue