feat:搜索栏

This commit is contained in:
1708-huayu 2025-01-08 19:28:29 +08:00
parent f39917ffbb
commit 8f20efb98e
6 changed files with 151 additions and 64 deletions

View File

@ -14,13 +14,14 @@ import "./index.css"
import {addTask} from "../../utils"; import {addTask} from "../../utils";
import {useNavigate, useOutletContext} from "react-router-dom"; import {useNavigate, useOutletContext} from "react-router-dom";
export default () => { export default () => {
// 设置标题栏
const {setTitle} = useOutletContext(); const {setTitle} = useOutletContext();
setTitle("添加任务") setTitle("添加任务")
// 路由
const navigate = useNavigate();
// 获取form引用
const [form] = Form.useForm(); const [form] = Form.useForm();
const onFinish = (values) => { const onFinish = (values) => {
// Dialog.alert({
// content: <pre>{JSON.stringify(values, null, 2)}</pre>,
// })
console.log("提交:",values) console.log("提交:",values)
if (values.pidArray===undefined){ if (values.pidArray===undefined){
values.pid='0' values.pid='0'
@ -28,9 +29,29 @@ export default () => {
values.pid=values.pidArray[values.pidArray.length-1]; values.pid=values.pidArray[values.pidArray.length-1];
} }
addTask(values).then(values=>{ addTask(values).then(values=>{
Dialog.alert({ Dialog.show({
content: '添加任务成功' + values.data, content: `添加任务${values.name}成功`,
onConfirm:()=>{} closeOnAction:true,
actions: [
[
{
key: 'back',
text: '回到列表',
onClick:()=>{
navigate("/home/listTask")
}
},
{
key: 'create',
text: '创建下一条',
onClick:()=>{
// 清空值
form.resetFields();
form.setFieldValue("pidArray",values.pidArray);
}
},
],
],
}) })
}) })
} }
@ -65,11 +86,10 @@ export default () => {
<Form.Item name='state' label='任务状态' required> <Form.Item name='state' label='任务状态' required>
<Radio.Group> <Radio.Group>
<Space direction='vertical'> <Space direction='vertical'>
<Radio value='8'><Tag color='danger'>未开始</Tag></Radio> <Radio value='8'><Tag color='primary'>未开始</Tag></Radio>
<Radio value='9'><Tag color='warning'>进行中</Tag></Radio> <Radio value='9'><Tag color='warning'>进行中</Tag></Radio>
<Radio value='7'><Tag color='success'>已完成</Tag></Radio> <Radio value='7'><Tag color='success'>已完成</Tag></Radio>
<Radio value='10'><Tag color='success'>未完成</Tag></Radio> <Radio value='10'><Tag color='danger'>已逾期</Tag></Radio>
<Radio value='6'><Tag>已关闭</Tag></Radio>
</Space> </Space>
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>

View File

@ -1,26 +1,29 @@
import {Tag,} from "antd-mobile"; import {Tag,} from "antd-mobile";
import React, {useEffect, useState} from "react"; import React, {Fragment, useEffect, useState} from "react";
import {useLocation, useNavigate} from 'react-router-dom'; import {useLocation, useNavigate} from 'react-router-dom';
import {CloseOutline, SearchOutline} from "antd-mobile-icons"; import {AddOutline, CloseOutline, SearchOutline} from "antd-mobile-icons";
import "./index.css" import "./index.css"
import {getDictionary} from "../../utils/dictUtil"; import {getDictionary} from "../../utils/dictUtil";
import dayjs from "dayjs";
const DetailSearchBar = (props) => { const DetailSearchBar = (props) => {
// 从搜索设置中传来的search // 从搜索设置中传来的search
// const location = useLocation(); // const location = useLocation();
// const searchUpdate = location.state?.search; // const searchUpdate = location.state?.search;
// 父子传值从搜索框传来的search // 父子传值从搜索框传来的search
const {search,updateSearch,pName} = props; const {search, updateSearch, pName} = props;
console.log("DetailSearchBar.search", search) console.log("DetailSearchBar.search", search)
const [tags, setTags] = useState([]); const [tags, setTags] = useState([]);
const showCloseOutline = search && search.data &&
(search.data.andList?.length > 0 || search.data.orList?.length > 0)
useEffect(() => { useEffect(() => {
if (search && search.data) { if (search && search.data) {
Promise.all( Promise.all([
search.data.andList.map(async (searchObj) => { ...search.data.andList.map(async (searchObj) => {
console.log("DetailSearchContext.search", searchObj) console.log("DetailSearchContext.search", searchObj)
if (searchObj.name === "pid") { if (searchObj.name === "pid") {
return <Tag>{pName}</Tag> return <Tag>{pName}</Tag>
}else if (searchObj.name === "state") { } 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) => {
@ -28,7 +31,7 @@ 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"){ } else if (searchObj.name === "priority") {
const dictionary = await getDictionary("1"); const dictionary = await getDictionary("1");
const items = searchObj.value.split(','); const items = searchObj.value.split(',');
const itemPromises = items.map((item) => { const itemPromises = items.map((item) => {
@ -36,10 +39,26 @@ 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 === "todoDay"){ } else if (searchObj.name === "expectedEndTime") {
return <Tag >{searchObj.value}</Tag>; console.log("searchObj.value" + searchObj.value, dayjs(searchObj.value).format("YYYY-MM-DD"))
return <Tag>{dayjs(searchObj.value).format("YYYY-MM-DD")}</Tag>;
} else if (searchObj.name === "name") {
return <Tag>{searchObj.value}</Tag>;
} }
}) }),
...search.data.orList.map(async (searchObj) => {
console.log("DetailSearchContext.search", searchObj)
if (searchObj.name === "state" && searchObj.value === "10") {
const dictionary = await getDictionary("2");
const dict = dictionary.get(searchObj.value);
return dict ?
<Fragment><AddOutline/>
<Tag key={dict.id} color={dict.jsonValue?.color}>
{dict.itemName}
</Tag>
</Fragment> : null;
}
})]
).then((results) => { ).then((results) => {
// Flatten the results and filter out null values // Flatten the results and filter out null values
const flattenedResults = results.flat().filter(Boolean); const flattenedResults = results.flat().filter(Boolean);
@ -52,17 +71,21 @@ const DetailSearchBar = (props) => {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<div className="detailSearchBar"> <div className="detailSearchBar">
<div className={"onSearchItem " + (search ? "onSearchItemWidth" : "onSearchItemOnlyWidth")} onClick={() => { <div className={"onSearchItem " + (showCloseOutline ? "onSearchItemWidth" : "onSearchItemOnlyWidth")} onClick={() => {
navigate("/detail/searchTask", {state: {"search":search}}); navigate("/detail/searchTask", {state: {"search": search}});
}}> }}>
<SearchOutline/> <SearchOutline/>
{/*根据search处理搜素框展示内容*/} {/*根据search处理搜素框展示内容*/}
{tags} {tags}
</div> </div>
{search && <div className="CloseOutline-CloseOutline" onClick={() => { {showCloseOutline && <div className="CloseOutline-CloseOutline" onClick={() => {
updateSearch({ updateSearch({
"pageSize": 20, "pageSize": 20,
"pageNumber": 1, "pageNumber": 1,
"data": {
"andList": [],
"orList": []
}
}); });
setTags([]); setTags([]);
}}> }}>

View File

@ -1,7 +1,7 @@
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, {useEffect} from "react"; import React, {useEffect} from "react";
import dayjs from "dayjs"; import dayjs, {isDayjs} 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";
import {getDictionary} from "../../utils/dictUtil"; import {getDictionary} from "../../utils/dictUtil";
@ -33,7 +33,7 @@ const DetailSearchContext = () => {
if (!search) { if (!search) {
return return
} }
let searchMap = new Map(search.data.map(searchObj => [searchObj.name, searchObj])); let searchMap = new Map(search.data.andList.map(searchObj => [searchObj.name, searchObj]));
if (searchMap.has("pid")) { if (searchMap.has("pid")) {
let task = await getTaskById(searchMap.get("pid")); let task = await getTaskById(searchMap.get("pid"));
// form.setFieldValue(task.name); // form.setFieldValue(task.name);
@ -44,8 +44,17 @@ const DetailSearchContext = () => {
if (searchMap.has("priority")) { if (searchMap.has("priority")) {
form.setFieldValue("priority", searchMap.get("priority").value.split(',')) form.setFieldValue("priority", searchMap.get("priority").value.split(','))
} }
if (searchMap.has("todoDay")) { // 结束时间大于todo日开始时间小于结束日
form.setFieldValue("todoDay", searchMap.get("todoDay").value) if (searchMap.has("expectedEndTime")) {
let value = searchMap.get("expectedEndTime").value;
form.setFieldValue("todoDay", dayjs(value).toDate())
}
if (searchMap.has("name")) {
form.setFieldValue("name", searchMap.get("name").value)
}
let orMap = new Map(search.data.orList.map(searchObj => [searchObj.name, searchObj]));
if (orMap.has("state") && orMap.get("state").value === "10") {
form.setFieldValue("allOverdueTasks", 'checked')
} }
} }
@ -54,9 +63,10 @@ const DetailSearchContext = () => {
form={form} form={form}
layout='horizontal' layout='horizontal'
onFinish={(values) => { onFinish={(values) => {
console.log(values) console.log("Form", values)
let searchCondition = []; let searchCondition = [];
const {pidArray, name, priority, state, todoDay} = values; let orList = []
const {pidArray, name, priority, state, todoDay, allOverdueTasks} = values;
if (pidArray && pidArray.length !== 0) { if (pidArray && pidArray.length !== 0) {
searchCondition.push({"name": "name", "value": pidArray[pidArray.length - 1], "operateType": "="}) searchCondition.push({"name": "name", "value": pidArray[pidArray.length - 1], "operateType": "="})
} }
@ -69,16 +79,33 @@ const DetailSearchContext = () => {
if (state && state.length !== 0) { if (state && state.length !== 0) {
searchCondition.push({"name": "state", "value": state.join(","), "operateType": "IN"}) searchCondition.push({"name": "state", "value": state.join(","), "operateType": "IN"})
} }
if (todoDay !== undefined) { if (todoDay) {
searchCondition.push({"name": "todoDay", "value": todoDay, "operateType": "IN"}) searchCondition.push({
"name": "expectedStartTime",
"value": dayjs(todoDay).add(1, "d").set('h', 0).set('m', 0).set('s', 0).set('ms', 0).format(),
"operateType": "<"
})
searchCondition.push({
"name": "expectedEndTime",
"value": dayjs(todoDay).set('h', 0).set('m', 0).set('s', 0).set('ms', 0).format(),
"operateType": ">"
})
} }
navigate("/home/listTask", {state: {search:{ if (allOverdueTasks) {
orList.push({"name": "state", "value": "10", "operateType": "="})
}
navigate("/home/listTask", {
state: {
search: {
"pageSize": 12, "pageSize": 12,
"pageNumber": 1, "pageNumber": 1,
"data":{ "data": {
"andList":searchCondition "andList": searchCondition,
orList
}
}
}
} }
}}}
) )
}} }}
footer={ footer={
@ -100,8 +127,9 @@ const DetailSearchContext = () => {
<Space direction='vertical'> <Space direction='vertical'>
{ {
stateList.map(stateDict => stateList.map(stateDict =>
<Checkbox value={stateDict.itemCode}> <Checkbox key={stateDict.itemCode} value={stateDict.itemCode}>
<Tag color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag> <Tag key={stateDict.itemCode}
color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
</Checkbox> </Checkbox>
) )
} }
@ -113,8 +141,9 @@ const DetailSearchContext = () => {
<Space direction='vertical'> <Space direction='vertical'>
{ {
priorityList.map(stateDict => priorityList.map(stateDict =>
<Checkbox value={stateDict.itemCode}> <Checkbox key={stateDict.itemCode} value={stateDict.itemCode}>
<Tag color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag> <Tag key={stateDict.itemCode}
color={stateDict.jsonValue?.color}>{stateDict.itemName}</Tag>
</Checkbox> </Checkbox>
) )
} }
@ -122,13 +151,15 @@ const DetailSearchContext = () => {
</Checkbox.Group> </Checkbox.Group>
</Form.Item> </Form.Item>
<Form.Item noStyle <Form.Item noStyle
shouldUpdate={(prevValues, curValues) => shouldUpdate={(prevValues, curValues) =>{
prevValues.todoDay !== curValues.todoDay console.log("prevValues,curValues",prevValues,curValues)
return prevValues.todoDay !== curValues.todoDay}
} }
> >
{({getFieldValue, setFieldsValue}) => ( {({getFieldValue, setFieldsValue}) => (
<Form.Item <Form.Item
name='todoDay' name='todoDay'
initialValue={null}
trigger='onConfirm' trigger='onConfirm'
label='TODO日' label='TODO日'
help='期望开始时间和期望结束时间包含当日时间段' help='期望开始时间和期望结束时间包含当日时间段'
@ -163,14 +194,15 @@ const DetailSearchContext = () => {
</Form.Item> </Form.Item>
)} )}
</Form.Item> </Form.Item>
{/*后期嵌套or*/} <Form.Item
{/*<Form.Item*/} name='allOverdueTasks'
{/* name='allOverdueTasks'*/} label='所有逾期任务'
{/* label='所有逾期任务'*/} childElementPosition='right'
{/* childElementPosition='right'*/} initialValue={false}
{/*>*/} valuePropName='checked' // 确保为 Switch 设置正确的 prop
{/* <Switch/>*/} >
{/*</Form.Item>*/} <Switch/>
</Form.Item>
</Form>) </Form>)
} }
export default DetailSearchContext; export default DetailSearchContext;

View File

@ -1,4 +1,4 @@
import React from 'react' import React, {Fragment} from 'react'
import Bottom from './../Bottom/index' import Bottom from './../Bottom/index'
import './index.css' import './index.css'
import {Outlet, useLocation} from 'react-router-dom' import {Outlet, useLocation} from 'react-router-dom'
@ -12,21 +12,21 @@ const Home = () => {
console.log("Home", location); console.log("Home", location);
const searchUrl = location?.state?.search; const searchUrl = location?.state?.search;
const [pName, setName] = React.useState(""); const [pName, setName] = React.useState("");
const [search, setSearch] = React.useState({ const [search, setSearch] = React.useState(searchUrl ? searchUrl : {
"pageSize": 20, "pageSize": 20,
"pageNumber": 1, "pageNumber": 1,
"data": searchUrl ? searchUrl : { "data": {
"andList": [ "andList": [
{"name": "state", "value": "8,9", "operateType": "IN"} {"name": "state", "value": "8,9", "operateType": "IN"}
, ,
{ {
"name": "expectedStartTime", "name": "expectedStartTime",
"value": dayjs().add(1, "d").set('h', 0).set('m', 0).set('s', 0).set('ms', 0), "value": dayjs().add(1, "d").set('h', 0).set('m', 0).set('s', 0).set('ms', 0).format(),
"operateType": "<" "operateType": "<"
}, },
{ {
"name": "expectedEndTime", "name": "expectedEndTime",
"value": dayjs().set('h', 0).set('m', 0).set('s', 0).set('ms', 0), "value": dayjs().set('h', 0).set('m', 0).set('s', 0).set('ms', 0).format(),
"operateType": ">" "operateType": ">"
} }
], ],
@ -36,16 +36,28 @@ const Home = () => {
} }
}) })
const updateSearch = (values) => { const updateSearch = (values) => {
setSearch( values); setSearch(values);
}; };
return ( return (
<div className='body'> <div className='body'>
{
location.pathname.endsWith("/calTask") ? (
<Fragment>
<div style={{marginBottom: "49px", width: "100%"}}>
<Outlet context={{"search": search}}/>
</div>
</Fragment>
) : (<Fragment>
<DetailSearchBar search={search} <DetailSearchBar search={search}
updateSearch={updateSearch} updateSearch={updateSearch}
pName={pName}/> pName={pName}/>
<div style={{marginTop: "40px", marginBottom: "49px", width: "100%"}}> <div style={{marginTop: "40px", marginBottom: "49px", width: "100%"}}>
<Outlet context={{"search": search}}/> <Outlet context={{"search": search}}/>
</div> </div>
</Fragment>
)
}
<Bottom/> <Bottom/>
</div> </div>
) )

View File

@ -26,7 +26,7 @@ const reorder = (
const ToDoList = () => { const ToDoList = () => {
const [taskList, setTaskList] = useState([]) const [taskList, setTaskList] = useState([])
const [hasMore, setHasMore] = useState(false) const [hasMore, setHasMore] = useState(true)
const [pageNumber, setPageNumber] = useState(1) const [pageNumber, setPageNumber] = useState(1)
let loading = false; let loading = false;
const location = useLocation(); const location = useLocation();

View File

@ -2,7 +2,7 @@ import axios from "axios";
export const requestUtil = axios.create({ export const requestUtil = axios.create({
baseURL: 'http://www.huaruyu.com/', baseURL: 'http://www.huaruyu.com/',
timeout: 1000, timeout: 10000,
headers: {'Authorization': 'Bearer eyJraWQiOiJjZDE5YjcxYy05ZDkwLTQyY2EtOGM5NC02YmMyNWY4YTdmNjgiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzaGl4aWFvaHVhIiwic3ViIjoie1wiaWRcIjpcIjM2OTg0Nzc3MTAxODAzNTIwXCIsXCJuaWNrbmFtZVwiOlwi5biI5pmT5Y2OXCIsXCJ1c2VybmFtZVwiOlwic2hpeGlhb2h1YVwifSJ9.3Wu8VMAuk59WP_EIRGX6hVp1ShuvYiAwFmvE6CGe5zA_9AzvUVMyRGWWcEQQzuU3BlZ14cV8-9b_g9_tZepQE_mSlDn0yJ92jB3ATxFPsAdcC5m2o7UY6spUs3zrlJ7v99Gtd6YzzUZvk0JTPjJCIpSi5-_PtIcOmZEkjgLwa2fnOj8eh9U3B2YdQ6p8J8r1ZeNfSMlzFuIyVcLFR-ftDz3Gr6wbs3fPgh03GqevL-HKyTCku2Fb9oYWis4UYDYQFfEVYVLzocsS3DpKyeq8BGxRRqQkSXsodDaO2piib-60Zp5WOg6hQb0n9utH-fQDVU5hIhUYkAbKkGDmTrnyqg'} headers: {'Authorization': 'Bearer eyJraWQiOiJjZDE5YjcxYy05ZDkwLTQyY2EtOGM5NC02YmMyNWY4YTdmNjgiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzaGl4aWFvaHVhIiwic3ViIjoie1wiaWRcIjpcIjM2OTg0Nzc3MTAxODAzNTIwXCIsXCJuaWNrbmFtZVwiOlwi5biI5pmT5Y2OXCIsXCJ1c2VybmFtZVwiOlwic2hpeGlhb2h1YVwifSJ9.3Wu8VMAuk59WP_EIRGX6hVp1ShuvYiAwFmvE6CGe5zA_9AzvUVMyRGWWcEQQzuU3BlZ14cV8-9b_g9_tZepQE_mSlDn0yJ92jB3ATxFPsAdcC5m2o7UY6spUs3zrlJ7v99Gtd6YzzUZvk0JTPjJCIpSi5-_PtIcOmZEkjgLwa2fnOj8eh9U3B2YdQ6p8J8r1ZeNfSMlzFuIyVcLFR-ftDz3Gr6wbs3fPgh03GqevL-HKyTCku2Fb9oYWis4UYDYQFfEVYVLzocsS3DpKyeq8BGxRRqQkSXsodDaO2piib-60Zp5WOg6hQb0n9utH-fQDVU5hIhUYkAbKkGDmTrnyqg'}
}); });
// 添加响应拦截器 // 添加响应拦截器