feat:添加日历

This commit is contained in:
1708-huayu 2025-01-01 21:16:32 +08:00
parent abc20d99c2
commit b3d1fce71f
9 changed files with 187 additions and 82 deletions

View File

@ -4,12 +4,13 @@ import Map from './pages/Map';
import Index from './pages/Index' import Index from './pages/Index'
import './pages/Bottom/index.css' import './pages/Bottom/index.css'
import CityList from './pages/CityList'; import CityList from './pages/CityList';
import { PersonalCenter} from './pages/Bottom' import {PersonalCenter} from './pages/Bottom'
import ToDoList from "./pages/ToDoList"; import ToDoList from "./pages/ToDoList";
import DetailForm from "./components/DetailForm"; import DetailForm from "./components/DetailForm";
import {NavBar} from "antd-mobile"; import {NavBar} from "antd-mobile";
import DetailNavBar from "./components/DetailNavBar"; import DetailNavBar from "./components/DetailNavBar";
import DetailSearchContext from "./pages/DetailSearchContext"; import DetailSearchContext from "./pages/DetailSearchContext";
import ToDoCal from "./pages/ToDoCal";
function App() { function App() {
return ( return (
@ -20,12 +21,14 @@ function App() {
</div> */} </div> */}
{/* <div className='body'> */} {/* <div className='body'> */}
<Routes> <Routes>
{/* <Route path='/' element={<Navigate to="/home" />}> <Route path='/' element={<Navigate to="/home/listTask" />}>
</Route> */}
<Route path='/' element={<Home/>}> </Route>
<Route index path='/home' element={<Index/>}/> <Route path='/home' element={<Home/>}>
<Route path='/home/todo' element={<ToDoList/>}></Route> <Route path='treeTask' element={<Index/>}/>
<Route path='/home/me' element={<PersonalCenter/>}></Route> <Route index path='listTask' element={<ToDoList/>}></Route>
<Route path='calTask' element={<ToDoCal/>}/>
<Route path='me' element={<PersonalCenter/>}></Route>
</Route> </Route>
<Route path='/detail' element={<DetailNavBar/>}> <Route path='/detail' element={<DetailNavBar/>}>
<Route path='addTask' element={<DetailForm/>}></Route> <Route path='addTask' element={<DetailForm/>}></Route>

View File

@ -10,14 +10,17 @@ const DetailSearchBar = (props) => {
// const location = useLocation(); // const location = useLocation();
// const searchUpdate = location.state?.search; // const searchUpdate = location.state?.search;
// 父子传值从搜索框传来的search // 父子传值从搜索框传来的search
const {search,updateSearch} = props; const {search,updateSearch,pName} = props;
console.log("DetailSearchBar.search", search) console.log("DetailSearchBar.search", search.data)
const [tags, setTags] = useState([]); const [tags, setTags] = useState([]);
useEffect(() => { useEffect(() => {
if (search && search.data) { if (search && search.data) {
Promise.all( Promise.all(
search.data.map(async (searchObj) => { search.data.map(async (searchObj) => {
if (searchObj.name === "state") { console.log("DetailSearchContext.search", searchObj)
if (searchObj.name === "pid") {
return <Tag>{pName}</Tag>
}else if (searchObj.name === "state") {
const dictionary = await getDictionary("2"); const dictionary = await getDictionary("2");
const items = searchObj.value.split(','); const items = searchObj.value.split(',');
const itemPromises = items.map((item) => { const itemPromises = items.map((item) => {
@ -25,6 +28,16 @@ const DetailSearchBar = (props) => {
return dict ? <Tag key={dict.id} color={dict.jsonValue?.color}>{dict.itemName}</Tag> : null; return dict ? <Tag key={dict.id} color={dict.jsonValue?.color}>{dict.itemName}</Tag> : null;
}); });
return Promise.all(itemPromises); return Promise.all(itemPromises);
}else if (searchObj.name === "priority"){
const dictionary = await getDictionary("1");
const items = searchObj.value.split(',');
const itemPromises = items.map((item) => {
const dict = dictionary.get(item);
return dict ? <Tag key={dict.id} color={dict.jsonValue?.color}>{dict.itemName}</Tag> : null;
});
return Promise.all(itemPromises);
}else if (searchObj.name === "todoDay"){
return <Tag >{searchObj.value}</Tag>;
} }
}) })
).then((results) => { ).then((results) => {

View File

@ -9,23 +9,22 @@ import {
AddOutline, AddOutline,
} from 'antd-mobile-icons' } from 'antd-mobile-icons'
import "./index.css" import "./index.css"
import DetailForm from "../../components/DetailForm";
const tabs = [ const tabs = [
{ {
key: '/home', key: '/home/treeTask',
title: '树状任务', title: '树状任务',
icon: <AppOutline/>, icon: <AppOutline/>,
badge: '1', badge: '1',
}, },
{ {
key: '/home/todo', key: '/home/listTask',
title: '列表任务', title: '列表任务',
icon: <UnorderedListOutline/>, icon: <UnorderedListOutline/>,
badge: '2', badge: '2',
}, },
{ {
key: '/home/message', key: '/home/calTask',
title: '日历任务', title: '日历任务',
icon: <MessageOutline/>, icon: <MessageOutline/>,
badge: '3', badge: '3',

View File

@ -1,30 +1,78 @@
import {Button, Checkbox, DatePicker, Form, Input, Space, Switch, Tag} from "antd-mobile"; import {Button, Checkbox, DatePicker, Form, Input, Space, Switch, Tag} from "antd-mobile";
import ParentTask from "../../components/ParentTask"; import ParentTask from "../../components/ParentTask";
import React from "react"; import React, {useEffect} from "react";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {CloseCircleFill} from "antd-mobile-icons"; import {CloseCircleFill} from "antd-mobile-icons";
import {useLocation, useNavigate, useOutletContext} from "react-router-dom"; import {useLocation, useNavigate, useOutletContext} from "react-router-dom";
const now = new Date() import {getDictionary} from "../../utils/dictUtil";
import {getTaskById} from "../../utils";
const DetailSearchContext = () => { const DetailSearchContext = () => {
// 使用Outlet,传值修改标题
const {setTitle} = useOutletContext();
setTitle("搜索查询")
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();
const [visible, setVisible] = React.useState(false); const [visible, setVisible] = React.useState(false);
const location = useLocation(); const location = useLocation();
console.log("DetailSearchContext",location); console.log("DetailSearchContext", location);
const {search,updateSearch} = location.state; const {search} = location?.state || undefined;
console.log("DetailSearchContext.search",search) console.log("DetailSearchContext.search", search)
const [stateList, setStateList] = React.useState([]);
const [priorityList, setPriorityList] = React.useState([]);
// 使用Outlet,传值修改标题
const {setTitle} = useOutletContext();
useEffect(() => {
// 使用Outlet,传值修改标题
setTitle("搜索查询")
initDate()
}, [])
async function initDate() {
let stateDictionary = await getDictionary("2");
let priorityDictionary = await getDictionary("1");
setStateList(Array.from(stateDictionary.values()));
setPriorityList(Array.from(priorityDictionary.values()));
if (!search) {
return
}
let searchMap = new Map(search.data.map(searchObj => [searchObj.name, searchObj]));
if (searchMap.has("pid")) {
let task = await getTaskById(searchMap.get("pid"));
// form.setFieldValue(task.name);
}
if (searchMap.has("state")) {
form.setFieldValue("state", searchMap.get("state").value.split(','))
}
if (searchMap.has("priority")) {
form.setFieldValue("priority", searchMap.get("priority").value.split(','))
}
if (searchMap.has("todoDay")) {
form.setFieldValue("todoDay", searchMap.get("todoDay").value)
}
}
return ( return (
<Form <Form
form={form} form={form}
layout='horizontal' layout='horizontal'
onFinish={(values)=>{ onFinish={(values) => {
// navigate("/home/todo", { state: { search: values } }) console.log(values)
// 根据values处理search let searchCondition = [];
// updateSearch() const {pidArray, name, priority, state, todoDay} = values;
navigate("/home/todo") if (pidArray && pidArray.length !== 0) {
searchCondition.push({"name": "name", "value": pidArray[pidArray.length - 1], "operateType": "="})
}
if (name && name !== "") {
searchCondition.push({"name": "name", "value": name, "operateType": "LIKE"})
}
if (priority && priority.length !== 0) {
searchCondition.push({"name": "priority", "value": priority.join(","), "operateType": "IN"})
}
if (state && state.length !== 0) {
searchCondition.push({"name": "state", "value": state.join(","), "operateType": "IN"})
}
if (todoDay !== undefined) {
searchCondition.push({"name": "todoDay", "value": todoDay, "operateType": "IN"})
}
navigate("/home/listTask", {state: {search: JSON.stringify(searchCondition)}})
}} }}
footer={ footer={
<Button block type='submit' color='primary' size='large'> <Button block type='submit' color='primary' size='large'>
@ -40,24 +88,29 @@ const DetailSearchContext = () => {
<Input onChange={console.log} placeholder='任务信息'/> <Input onChange={console.log} placeholder='任务信息'/>
</Form.Item> </Form.Item>
<Form.Item name='state' label='任务状态' required> <Form.Item name='state' label='任务状态'>
<Checkbox.Group> <Checkbox.Group>
<Space direction='vertical'> <Space direction='vertical'>
<Checkbox value='8'><Tag color='danger'>未开始</Tag></Checkbox> {
<Checkbox value='9'><Tag color='warning'>进行中</Tag></Checkbox> stateList.map(stateDict =>
<Checkbox value='7'><Tag color='success'>已完成</Tag></Checkbox> <Checkbox value={stateDict.itemCode}>
<Checkbox value='10'><Tag color='success'>未完成</Tag></Checkbox> <Tag color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
<Checkbox value='6'><Tag>已关闭</Tag></Checkbox> </Checkbox>
)
}
</Space> </Space>
</Checkbox.Group> </Checkbox.Group>
</Form.Item> </Form.Item>
<Form.Item name='priority' label='任务优先级'> <Form.Item name='priority' label='任务优先级'>
<Checkbox.Group> <Checkbox.Group>
<Space direction='vertical'> <Space direction='vertical'>
<Checkbox value='3'><Tag color='danger'>紧急重要</Tag></Checkbox> {
<Checkbox value='2'><Tag color='warning'>不紧急重要</Tag></Checkbox> priorityList.map(stateDict =>
<Checkbox value='1'><Tag>紧急不重要</Tag></Checkbox> <Checkbox value={stateDict.itemCode}>
<Checkbox value='0'><Tag color='success'>不紧急不重要</Tag></Checkbox> <Tag color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
</Checkbox>
)
}
</Space> </Space>
</Checkbox.Group> </Checkbox.Group>
</Form.Item> </Form.Item>
@ -66,7 +119,7 @@ const DetailSearchContext = () => {
prevValues.todoDay !== curValues.todoDay prevValues.todoDay !== curValues.todoDay
} }
> >
{({ getFieldValue, setFieldsValue }) => ( {({getFieldValue, setFieldsValue}) => (
<Form.Item <Form.Item
name='todoDay' name='todoDay'
trigger='onConfirm' trigger='onConfirm'
@ -81,7 +134,7 @@ const DetailSearchContext = () => {
}} }}
onClick={e => { onClick={e => {
e.stopPropagation() e.stopPropagation()
setFieldsValue({ todoDay: null }) setFieldsValue({todoDay: null})
}} }}
/>) : true />) : true
@ -103,13 +156,14 @@ const DetailSearchContext = () => {
</Form.Item> </Form.Item>
)} )}
</Form.Item> </Form.Item>
<Form.Item {/*后期嵌套or*/}
name='delivery' {/*<Form.Item*/}
label='延期任务' {/* name='allOverdueTasks'*/}
childElementPosition='right' {/* label='所有逾期任务'*/}
> {/* childElementPosition='right'*/}
<Switch defaultChecked={true}/> {/*>*/}
</Form.Item> {/* <Switch/>*/}
{/*</Form.Item>*/}
</Form>) </Form>)
} }
export default DetailSearchContext; export default DetailSearchContext;

View File

@ -1,35 +1,39 @@
import React from 'react' import React from 'react'
import Bottom from './../Bottom/index' import Bottom from './../Bottom/index'
import './index.css' import './index.css'
import {Outlet} from 'react-router-dom' import {Outlet, useLocation} from 'react-router-dom'
import DetailSearchBar from "../../components/DetailSearchBar"; import DetailSearchBar from "../../components/DetailSearchBar";
export default class Home extends React.Component { const Home = () => {
constructor(props) {
super(props); const location = useLocation();
this.state = { console.log("Home", location);
search:{ const searchUrl = location?.state?.search;
"pageSize":10, const [pName, setName] = React.useState("");
"pageNumber":1, const [search, setSearch] = React.useState({
"data":[ "pageSize": 12,
{"name":"state","value":"8,9","operateType":"IN"}, "pageNumber": 1,
{"name":"expectedStartTime","value":"2024-12-29T16:00:00.000Z","operateType":">="}, "data": searchUrl ? JSON.parse(searchUrl) : [
{"name":"expectedStartTime","value":"2024-12-29T16:00:00.000Z","operateType":"<="}]} {"name": "state", "value": "8,9", "operateType": "IN"},
{"name": "expectedStartTime", "value": "2024-12-29T16:00:00.000Z", "operateType": ">="},
{"name": "expectedStartTime", "value": "2024-12-29T16:00:00.000Z", "operateType": "<="}
]
})
const updateSearch = (values) => {
this.setState({search: values});
}; };
}
updateSearch = (values) => {
this.setState({search:values});
};
render() {
return ( return (
<div className='body'> <div className='body'>
<DetailSearchBar search={ this.state.search } updateSearch={this.updateSearch} /> <DetailSearchBar search={search}
<div style={{marginTop:"40px",marginBottom:"49px",width:"100%"}}> updateSearch={updateSearch}
pName={pName}/>
<div style={{marginTop: "40px", marginBottom: "49px", width: "100%"}}>
<Outlet/> <Outlet/>
</div> </div>
<Bottom/> <Bottom/>
</div> </div>
) )
}
} }
export default Home;

View File

@ -0,0 +1,23 @@
import {Calendar} from "antd-mobile";
import dayjs from "dayjs";
const ToDoCal = (props) => {
const defaultSingle = new Date()
const today = dayjs()
return (
<Calendar
selectionMode='single'
renderLabel={date => {
if (dayjs(date).isSame(today, 'day')) return '今天'
if (date.getDay() === 0 || date.getDay() === 6) {
return '周末'
}
}}
defaultValue={defaultSingle}
onChange={val => {
console.log(val)
}}
/>
)
}
export default ToDoCal;

View File

@ -1,4 +1,4 @@
import { useNavigate } from 'react-router-dom' import {useLocation, useNavigate} from 'react-router-dom'
// 高阶组件包装useNavigate()功能 // 高阶组件包装useNavigate()功能
// 原因类组件中无法使用useNavigate(),会报错 // 原因类组件中无法使用useNavigate(),会报错
// React Hook "useNavigate" cannot be called in a class component. // React Hook "useNavigate" cannot be called in a class component.
@ -7,8 +7,9 @@ function WidthUseNavigate(WrapComponent) {
WrapComponent.displayName = `widthUseNavigate${getDisplayName(WrapComponent)}` WrapComponent.displayName = `widthUseNavigate${getDisplayName(WrapComponent)}`
return function NavigateComponent() { return function NavigateComponent() {
const navigate = useNavigate() const navigate = useNavigate()
const location = useLocation()
// 给传入的组件新增一个to方法传给原始组件的props在原始组件中通过this.props.to(参数)使用 // 给传入的组件新增一个to方法传给原始组件的props在原始组件中通过this.props.to(参数)使用
return <WrapComponent to={navigate}></WrapComponent> return <WrapComponent to={navigate} useLocation={location.pathname}></WrapComponent>
} }
} }

View File

@ -1,17 +1,20 @@
import {requestUtil} from "./requestUtil"; import {requestUtil} from "./requestUtil";
const dict = new Map(); const dict = new Map();
export const getDictionary= async (typeId) => { export const getDictionary = async (typeId) => {
if (dict.has(typeId)) { if (dict.has(typeId)) {
return dict.get(typeId); return dict.get(typeId);
} }
let search = encodeURI(`{"data":[{"code":"type_id","value":"${typeId}","operateType":"="}]}`) let search = encodeURI(`{"data":[
{"code":"type_id","value":"${typeId}","operateType":"="},
{"code":"enable_flag","value":"1","operateType":"="}
]}`)
let todo = await requestUtil.get(`/todo-server/search/dict_items?search=${search}`); let todo = await requestUtil.get(`/todo-server/search/dict_items?search=${search}`);
let context = todo.content; let context = todo.content;
let result; let result;
if (context.length>0){ if (context.length > 0) {
result = new Map(context.map(item => [item.itemCode, item])) result = new Map(context.map(item => [item.itemCode, item]))
dict.set(typeId,result); dict.set(typeId, result);
} }
return result; return result;
} }

View File

@ -32,6 +32,11 @@ export const getTaskList= (pageNumber) => {
export const getTaskByPid = (pid) => { export const getTaskByPid = (pid) => {
return requestUtil.get('/todo-server/search/task_message_tree?search=%7B%22pageSize%22%3A1000%2C%22pageNumber%22%3A1%2C%22data%22%3A%5B%7B%22name%22%3A%22pid%22%2C%22value%22%3A%22'+pid+'%22%2C%22operateType%22%3A%22%3D%22%7D%5D%7D'); return requestUtil.get('/todo-server/search/task_message_tree?search=%7B%22pageSize%22%3A1000%2C%22pageNumber%22%3A1%2C%22data%22%3A%5B%7B%22name%22%3A%22pid%22%2C%22value%22%3A%22'+pid+'%22%2C%22operateType%22%3A%22%3D%22%7D%5D%7D');
} }
export const getTaskById= (id) => {
let request = encodeURI(`{"data":[{"name":"id","value":"${id}","operateType":"="}]}`)
return requestUtil.get('/todo-server/search/task_message_tree?search='+request);
}
export const addTask = async (entity) => { export const addTask = async (entity) => {
// 使用 Axios 发送 POST 请求添加数据 // 使用 Axios 发送 POST 请求添加数据
return await requestUtil.post('/todo-server' + '/task', entity); return await requestUtil.post('/todo-server' + '/task', entity);