feat:修改todoTree搜索
This commit is contained in:
parent
69a1bd0de3
commit
af93a92e93
|
@ -15,6 +15,11 @@ export function useChildList() {
|
||||||
});
|
});
|
||||||
// Map key为pid和他的子项
|
// Map key为pid和他的子项
|
||||||
const [childList, setChildList] = useState({});
|
const [childList, setChildList] = useState({});
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
// 当前选中的值,使用值过滤其子孙。
|
||||||
|
const [selectValue, setSelectValue] = useState([]);
|
||||||
|
const [currentLab, setCurrentLab] = useState(0);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchOptionsForValue('0', 0)
|
fetchOptionsForValue('0', 0)
|
||||||
|
@ -30,6 +35,27 @@ export function useChildList() {
|
||||||
if (options === undefined) {
|
if (options === undefined) {
|
||||||
return Cascader.optionSkeleton
|
return Cascader.optionSkeleton
|
||||||
}
|
}
|
||||||
|
// 如果有搜索有值,需要过滤,
|
||||||
|
// 根据currentLab查看需要过滤第几层,当前层可能没有值就会停留在上一层
|
||||||
|
if (searchValue && searchValue.length > 0) {
|
||||||
|
if (selectValue.length <= currentLab + 1) {
|
||||||
|
// 可能展示最新的,或没有停留在当前页面,正常是没有选择的时候搜索
|
||||||
|
console.log({searchValue}, {currentLab}, {selectValue})
|
||||||
|
if (currentLab === 0 && v === '0') {
|
||||||
|
return options.filter(option => option.label.includes(searchValue)).map(option => ({
|
||||||
|
...option,
|
||||||
|
children: generate(option.value),
|
||||||
|
}))
|
||||||
|
} else if (v === selectValue[currentLab - 1]) {
|
||||||
|
return options.filter(option => option.label.includes(searchValue)).map(option => ({
|
||||||
|
...option,
|
||||||
|
children: generate(option.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 用户切换回之前的标签,暂不处理
|
||||||
|
}
|
||||||
|
}
|
||||||
return options.map(option => ({
|
return options.map(option => ({
|
||||||
...option,
|
...option,
|
||||||
children: generate(option.value),
|
children: generate(option.value),
|
||||||
|
@ -37,7 +63,7 @@ export function useChildList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return generate('0') ?? []
|
return generate('0') ?? []
|
||||||
}, [childList])
|
}, [childList,searchValue])
|
||||||
|
|
||||||
async function fetchOptionsForValue(v, level) {
|
async function fetchOptionsForValue(v, level) {
|
||||||
if (v in childList) return
|
if (v in childList) return
|
||||||
|
@ -58,6 +84,18 @@ export function useChildList() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeSearchValue(value) {
|
||||||
|
setSearchValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeCurrentLab(value) {
|
||||||
|
setCurrentLab(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeSelectValue(value){
|
||||||
|
setSelectValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
function changeTaskId(taskId) {
|
function changeTaskId(taskId) {
|
||||||
if (!(taskId && taskId.length > 0)) {
|
if (!(taskId && taskId.length > 0)) {
|
||||||
return;
|
return;
|
||||||
|
@ -79,6 +117,9 @@ export function useChildList() {
|
||||||
return {
|
return {
|
||||||
changeTaskId,
|
changeTaskId,
|
||||||
removeTaskId,
|
removeTaskId,
|
||||||
|
changeCurrentLab,
|
||||||
|
changeSearchValue,
|
||||||
|
changeSelectValue,
|
||||||
options,
|
options,
|
||||||
task
|
task
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,18 +12,19 @@ const Home = () => {
|
||||||
<div className='body'>
|
<div className='body'>
|
||||||
|
|
||||||
{
|
{
|
||||||
location.pathname.endsWith("/calTask") ? (
|
location.pathname.endsWith("/listTask") ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div style={{marginBottom: "49px", width: "100%"}}>
|
|
||||||
<Outlet />
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
|
||||||
) : (<Fragment>
|
|
||||||
<DetailSearchBar/>
|
<DetailSearchBar/>
|
||||||
<div style={{marginTop: "40px", marginBottom: "49px", width: "100%"}}>
|
<div style={{marginTop: "40px", marginBottom: "49px", width: "100%"}}>
|
||||||
<Outlet/>
|
<Outlet/>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
) : (
|
||||||
|
<Fragment>
|
||||||
|
<div style={{marginBottom: "49px", width: "100%"}}>
|
||||||
|
<Outlet/>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<Bottom/>
|
<Bottom/>
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
|
import InfiniteScroll from 'react-infinite-scroll-component';
|
||||||
|
import './index.css'; // 用于存放样式
|
||||||
|
|
||||||
|
const ToDoTest = () => {
|
||||||
|
const [messages, setMessages] = useState([]); // 聊天消息列表
|
||||||
|
const [hasMore, setHasMore] = useState(true); // 是否还有更多消息
|
||||||
|
const [messageText, setMessageText] = useState(''); // 当前输入的消息文本
|
||||||
|
const messagesEndRef = useRef(null); // 用于自动滚动到底部
|
||||||
|
|
||||||
|
// 模拟获取初始聊天记录
|
||||||
|
useEffect(() => {
|
||||||
|
fetchInitialMessages();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchInitialMessages = async () => {
|
||||||
|
const initialMessages = await new Promise(resolve =>
|
||||||
|
setTimeout(() => resolve([
|
||||||
|
{ id: 1, text: "Hello", sender: "other" },
|
||||||
|
{ id: 2, text: "Hi there!", sender: "user" },
|
||||||
|
{ id: 3, text: "1Hi there!", sender: "user" },
|
||||||
|
{ id: 4, text: "2Hi there!", sender: "user" },
|
||||||
|
{ id: 5, text: "3Hi there!", sender: "user" },
|
||||||
|
{ id: 6, text: "4Hi there!", sender: "user" },
|
||||||
|
{ id: 7, text: "5Hi there!", sender: "user" },
|
||||||
|
{ id: 8, text: "6Hi there!", sender: "user" },
|
||||||
|
{ id: 9, text: "7Hi there!", sender: "user" },
|
||||||
|
{ id: 10, text: "8Hi there!", sender: "user" },
|
||||||
|
{ id: 11, text: "11Hello", sender: "other" },
|
||||||
|
{ id: 12, text: "12Hi there!", sender: "user" },
|
||||||
|
{ id: 13, text: "13Hi there!", sender: "user" },
|
||||||
|
{ id: 14, text: "14Hi there!", sender: "user" },
|
||||||
|
{ id: 15, text: "15Hi there!", sender: "user" },
|
||||||
|
{ id: 16, text: "16Hi there!", sender: "user" },
|
||||||
|
{ id: 17, text: "17Hi there!", sender: "user" },
|
||||||
|
{ id: 18, text: "18Hi there!", sender: "user" },
|
||||||
|
{ id: 19, text: "19Hi there!", sender: "user" },
|
||||||
|
{ id: 20, text: "20Hi there!", sender: "user" },
|
||||||
|
{ id: 31, text: "31Hello", sender: "other" },
|
||||||
|
{ id: 32, text: "32Hi there!", sender: "user" },
|
||||||
|
{ id: 33, text: "33Hi there!", sender: "user" },
|
||||||
|
{ id: 34, text: "34Hi there!", sender: "user" },
|
||||||
|
{ id: 35, text: "35Hi there!", sender: "user" },
|
||||||
|
{ id: 36, text: "36Hi there!", sender: "user" },
|
||||||
|
{ id: 37, text: "37Hi there!", sender: "user" },
|
||||||
|
{ id: 38, text: "38Hi there!", sender: "user" },
|
||||||
|
{ id: 39, text: "39Hi there!", sender: "user" },
|
||||||
|
{ id: 40, text: "40Hi there!", sender: "user" },
|
||||||
|
]), 1000));
|
||||||
|
setMessages(initialMessages);
|
||||||
|
// scrollToBottom(); // 自动滚动到最新消息
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载更多历史消息
|
||||||
|
const fetchMoreData = async () => {
|
||||||
|
console.log("fetchMoreMessages")
|
||||||
|
if (!hasMore) return;
|
||||||
|
|
||||||
|
const moreMessages = await new Promise(resolve => setTimeout(() => {
|
||||||
|
console.log("moreMessages",messages.length < 50)
|
||||||
|
if (messages.length < 500) { // 假设有50条消息作为限制
|
||||||
|
const generatedMessages = [];
|
||||||
|
for (let i = messages[0]?.id - 1; i > messages[0]?.id - 10; i--) {
|
||||||
|
generatedMessages.push({ id: i, text: `Old Message ${i}`, sender: "other" });
|
||||||
|
}
|
||||||
|
resolve(generatedMessages);
|
||||||
|
} else {
|
||||||
|
setHasMore(false); // 如果已经加载完所有消息,则设置 hasMore 为 false
|
||||||
|
resolve([]);
|
||||||
|
}
|
||||||
|
}, 1000));
|
||||||
|
|
||||||
|
setMessages([...moreMessages, ...messages]); // 新的历史消息添加到顶部
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSendMessage = () => {
|
||||||
|
if (messageText.trim()) {
|
||||||
|
const updatedMessages = [...messages, { id: Date.now(), text: messageText, sender: "user" }];
|
||||||
|
setMessages(updatedMessages);
|
||||||
|
setMessageText('');
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollToBottom = () => {
|
||||||
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="scrollableDiv"
|
||||||
|
style={{
|
||||||
|
height: 300,
|
||||||
|
overflow: 'auto',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column-reverse',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/*Put the scroll bar always on the bottom*/}
|
||||||
|
<InfiniteScroll
|
||||||
|
dataLength={messages.length}
|
||||||
|
next={fetchMoreData}
|
||||||
|
style={{display: 'flex', flexDirection: 'column-reverse'}} //To put endMessage and loader to the top.
|
||||||
|
inverse={true} //
|
||||||
|
hasMore={true}
|
||||||
|
loader={<h4>Loading...</h4>}
|
||||||
|
scrollableTarget="scrollableDiv"
|
||||||
|
>
|
||||||
|
{messages.map((_, index) => (
|
||||||
|
<div key={index}>
|
||||||
|
div - #{index}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</InfiniteScroll>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ToDoTest;
|
|
@ -1,13 +1,21 @@
|
||||||
import {Fragment} from "react";
|
import React, {Fragment, useState} from "react";
|
||||||
import {Card, CascaderView, Dialog, Toast} from "antd-mobile";
|
import {Card, CascaderView, Dialog, SearchBar, Toast} from "antd-mobile";
|
||||||
|
|
||||||
import {useChildList} from "../../hooks/useChildList";
|
import {useChildList} from "../../hooks/useChildList";
|
||||||
import {useNavigate} from "react-router-dom";
|
import {useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
export default () => {
|
const ToDoTree = () => {
|
||||||
const {task, options, changeTaskId,} = useChildList();
|
const {task, options, changeTaskId,changeSearchValue,changeCurrentLab,changeSelectValue} = useChildList();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
return <Fragment>
|
return <Fragment>
|
||||||
|
<SearchBar placeholder='搜索当前层相关标题' onChange={
|
||||||
|
// 获取当前选卡,过滤当前选项
|
||||||
|
(value) => {
|
||||||
|
changeSearchValue(value);
|
||||||
|
}
|
||||||
|
}/>
|
||||||
<Card title={task?.name} style={{height: "30vh", borderRadius: "10px"}}
|
<Card title={task?.name} style={{height: "30vh", borderRadius: "10px"}}
|
||||||
onClick={async ()=>{
|
onClick={async ()=>{
|
||||||
if (task&&task.id) {
|
if (task&&task.id) {
|
||||||
|
@ -28,8 +36,13 @@ export default () => {
|
||||||
// fetchOptionsForValue(value[value.length-1])
|
// fetchOptionsForValue(value[value.length-1])
|
||||||
console.log({value})
|
console.log({value})
|
||||||
changeTaskId(value)
|
changeTaskId(value)
|
||||||
|
changeSelectValue(value)
|
||||||
|
}}
|
||||||
|
onTabsChange={index => {
|
||||||
|
console.log("tabs", index)
|
||||||
|
changeCurrentLab(index)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
|
export default ToDoTree
|
Loading…
Reference in New Issue