搜索功能完成
This commit is contained in:
parent
289e739f80
commit
d4d882cd65
|
|
@ -4,16 +4,21 @@ import { useHomeContext } from './context/homeContext';
|
|||
import EssaysByLabel from './essays/byLabel';
|
||||
|
||||
const FrontendBody = () => {
|
||||
const { selectedLabelId, selectedCategoryId } = useHomeContext();
|
||||
const { selectedLabelId, selectedCategoryId, searchParam } =
|
||||
useHomeContext();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!selectedLabelId ? (
|
||||
<Essays oakPath='essays' categoryId={selectedCategoryId!}></Essays>
|
||||
<Essays
|
||||
oakPath='essays'
|
||||
categoryId={selectedCategoryId!}
|
||||
searchParam={searchParam}
|
||||
></Essays>
|
||||
) : (
|
||||
<EssaysByLabel
|
||||
oakPath='essaysByLabel'
|
||||
oakId={selectedLabelId!}
|
||||
oakId={selectedLabelId!}
|
||||
></EssaysByLabel>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import React from 'react';
|
||||
import { createContext } from 'react';
|
||||
|
||||
type SearchType = 'title' | 'content';
|
||||
|
||||
type HomeContextType = {
|
||||
// label selection
|
||||
selectedLabelId: string | undefined;
|
||||
|
|
@ -8,6 +10,15 @@ type HomeContextType = {
|
|||
// category selection
|
||||
selectedCategoryId: string | undefined;
|
||||
setSelectedCategoryId: (categoryId: string | null) => void;
|
||||
// search
|
||||
searchParam: {
|
||||
searchType: SearchType;
|
||||
searchText: string;
|
||||
};
|
||||
setSearchParam: (param: {
|
||||
searchType?: SearchType;
|
||||
searchText?: string;
|
||||
}) => void;
|
||||
};
|
||||
|
||||
const HomeContext = createContext<HomeContextType | undefined>(undefined);
|
||||
|
|
@ -17,6 +28,10 @@ export const HomeProvider: React.FC<{
|
|||
}> = ({ children }) => {
|
||||
const [selectedLabelId, _setSelectedLabelId] = React.useState<string>();
|
||||
const setSelectedLabelId = (tagId: string | null) => {
|
||||
// 清空搜索
|
||||
setSearchParam({
|
||||
searchText: '',
|
||||
});
|
||||
_setSelectedLabelId(tagId || undefined);
|
||||
};
|
||||
|
||||
|
|
@ -24,9 +39,37 @@ export const HomeProvider: React.FC<{
|
|||
React.useState<string>();
|
||||
const setSelectedCategoryId = (categoryId: string | null) => {
|
||||
_setSelectedLabelId(undefined);
|
||||
// 清空搜索
|
||||
setSearchParam({
|
||||
searchText: '',
|
||||
});
|
||||
_setSelectedCategoryId(categoryId || undefined);
|
||||
};
|
||||
|
||||
// search
|
||||
const [searchParam, _setSearchParam] = React.useState<{
|
||||
searchType: SearchType;
|
||||
searchText: string;
|
||||
}>({
|
||||
searchType: 'title',
|
||||
searchText: '',
|
||||
});
|
||||
|
||||
const setSearchParam = (param: {
|
||||
searchType?: SearchType;
|
||||
searchText?: string;
|
||||
}) => {
|
||||
// 如果有搜索值,则清空选择的label和category
|
||||
if (param.searchText) {
|
||||
setSelectedLabelId(null);
|
||||
setSelectedCategoryId(null);
|
||||
}
|
||||
_setSearchParam({
|
||||
searchType: param.searchType || 'title',
|
||||
searchText: param.searchText || '',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<HomeContext.Provider
|
||||
value={{
|
||||
|
|
@ -34,6 +77,8 @@ export const HomeProvider: React.FC<{
|
|||
setSelectedLabelId,
|
||||
selectedCategoryId,
|
||||
setSelectedCategoryId,
|
||||
searchParam,
|
||||
setSearchParam,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ const EssaysByLabel = (
|
|||
item={item}
|
||||
navigateTo={navigateTo}
|
||||
t={t}
|
||||
key={item.id}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,44 @@ export default OakComponent({
|
|||
},
|
||||
},
|
||||
],
|
||||
listeners: {
|
||||
searchParam(prev, next) {
|
||||
// 如果searchParam变化,则重新获取数据
|
||||
if (prev.searchParam !== next.searchParam) {
|
||||
this.setNamedFilters(
|
||||
[
|
||||
{
|
||||
// 如果存在searchParam,则按照searchParam过滤
|
||||
filter() {
|
||||
if (!next.searchParam.searchText) {
|
||||
return {};
|
||||
}
|
||||
switch (next.searchParam.searchType) {
|
||||
case 'title':
|
||||
return {
|
||||
title: {
|
||||
$includes:
|
||||
next.searchParam.searchText,
|
||||
},
|
||||
};
|
||||
case 'content':
|
||||
return {
|
||||
$text: {
|
||||
$search:
|
||||
next.searchParam.searchText,
|
||||
},
|
||||
};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
'#name': 'searchParam',
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
formData({ data }) {
|
||||
return {
|
||||
list: data.map((item) => {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,26 @@ const i18ns: I18n[] = [
|
|||
"categories": "分类"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "6fd812246bb915f692124fc05bb9ffd4",
|
||||
namespace: "new-demo-c-frontend-home-labels-byCategory",
|
||||
language: "zh-CN",
|
||||
module: "new-demo",
|
||||
position: "src/components/frontend/home/labels/byCategory",
|
||||
data: {
|
||||
"labelsByCategory": "当前分类下的标签"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "784729f3cc436498cf82829030273cdb",
|
||||
namespace: "new-demo-c-frontend-home-labels",
|
||||
language: "zh-CN",
|
||||
module: "new-demo",
|
||||
position: "src/components/frontend/home/labels",
|
||||
data: {
|
||||
"labelsAll": "全部标签"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "66807ab52114b7a250380d6a509aea19",
|
||||
namespace: "new-demo-l-common",
|
||||
|
|
|
|||
|
|
@ -1,24 +1,22 @@
|
|||
import FrontendHeader from '@project/components/frontend/home/FrontendHeader';
|
||||
import React from 'react';
|
||||
import Styles from './styles.module.less';
|
||||
import { HomeProvider } from '@project/components/frontend/home/context/homeContext';
|
||||
|
||||
import FrontendBody from '@project/components/frontend/home/FrontendBody';
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
<HomeProvider>
|
||||
<div className={Styles.body}>
|
||||
<div className={Styles.header}>
|
||||
<FrontendHeader />
|
||||
</div>
|
||||
<div className={Styles.content}>
|
||||
<FrontendBody />
|
||||
</div>
|
||||
<div className={Styles.footer}>
|
||||
<h1>Footer</h1>
|
||||
</div>
|
||||
<div className={Styles.body}>
|
||||
<div className={Styles.header}>
|
||||
<FrontendHeader />
|
||||
</div>
|
||||
</HomeProvider>
|
||||
<div className={Styles.content}>
|
||||
<FrontendBody />
|
||||
</div>
|
||||
<div className={Styles.footer}>
|
||||
<h1>Footer</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import Styles from './web.pc.module.less';
|
||||
import { Button, Space, Modal } from 'antd';
|
||||
import { Button, Space, Modal, Input, Select } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import useFeatures from '@project/hooks/useFeatures';
|
||||
import ConsoleAvatar from '../consoleAvatar';
|
||||
import { useHomeContext } from '@project/components/frontend/home/context/homeContext';
|
||||
|
||||
export default function render() {
|
||||
const features = useFeatures();
|
||||
|
|
@ -19,6 +20,27 @@ export default function render() {
|
|||
});
|
||||
}, []);
|
||||
|
||||
const { searchParam, setSearchParam } = useHomeContext();
|
||||
|
||||
const selectBefore = (
|
||||
<Select
|
||||
defaultValue='title'
|
||||
className={Styles.select}
|
||||
onChange={(value) => {
|
||||
setSearchParam({
|
||||
searchType: value as 'title' | 'content',
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Option value='title'>
|
||||
{features.locales.t('title')}
|
||||
</Select.Option>
|
||||
<Select.Option value='content'>
|
||||
{features.locales.t('content')}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={Styles.header}>
|
||||
<div
|
||||
|
|
@ -45,7 +67,24 @@ export default function render() {
|
|||
{features.locales.t('welcome')} {user?.name || user?.nickname}
|
||||
</div> */}
|
||||
</div>
|
||||
<div style={{ flex: 1 }} />
|
||||
<div className={Styles.search} >
|
||||
{/* 搜索框 */}
|
||||
<Space.Compact className={Styles.input}>
|
||||
<Input
|
||||
addonBefore={selectBefore}
|
||||
placeholder={features.locales.t('searchPlaceholder')}
|
||||
value={searchParam.searchText}
|
||||
onChange={(e) => {
|
||||
setSearchParam({
|
||||
searchText: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button type='primary' className={Styles.btn}>
|
||||
{features.locales.t('search')}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</div>
|
||||
<div className={Styles.right}>
|
||||
{user ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -3,5 +3,9 @@
|
|||
"console": "控制台",
|
||||
"logout": "退出",
|
||||
"close": "关闭",
|
||||
"login": "登录"
|
||||
"login": "登录",
|
||||
"searchPlaceholder": "搜索文章",
|
||||
"title": "标题",
|
||||
"content": "内容",
|
||||
"search": "搜索"
|
||||
}
|
||||
|
|
@ -55,4 +55,25 @@
|
|||
.right {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.search {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.input {
|
||||
width: 30%;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #6661f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select {
|
||||
width: 100px;
|
||||
}
|
||||
|
|
@ -1,15 +1,18 @@
|
|||
import React from 'react';
|
||||
import { Outlet, Route } from 'react-router-dom';
|
||||
import FrontendHeader from '../../components/frontendHeader';
|
||||
import Styles from './styles.module.less'
|
||||
import Styles from './styles.module.less';
|
||||
import { HomeProvider } from '@project/components/frontend/home/context/homeContext';
|
||||
|
||||
function Frontend() {
|
||||
return (
|
||||
<div>
|
||||
<FrontendHeader />
|
||||
<div className={Styles.body}>
|
||||
<Outlet />
|
||||
</div>
|
||||
<HomeProvider>
|
||||
<FrontendHeader />
|
||||
<div className={Styles.body}>
|
||||
<Outlet />
|
||||
</div>
|
||||
</HomeProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue