141 lines
5.5 KiB
TypeScript
141 lines
5.5 KiB
TypeScript
import Banner, { type BannerConfig } from "@/components/Banner";
|
|
import Section from "@/components/layout/Section";
|
|
import styles from "./Search.module.css";
|
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
import { dateFormat } from "@/utils";
|
|
import { useStore } from "@/store";
|
|
import appApi from "@/api/app";
|
|
import Pagination from "@/components/Pagination";
|
|
import { Link } from "react-router-dom";
|
|
type SearchData = {
|
|
id: number;
|
|
title: string;
|
|
content: string;
|
|
createTime: string;
|
|
lang: "ZH" | "EN";
|
|
path: string;
|
|
};
|
|
|
|
export default function Search() {
|
|
const appConfig = useStore((s) => s.appConfig);
|
|
const locale = useStore((s) => s.locale);
|
|
const supportLocales = useStore((s) => s.supportLocales);
|
|
const categoryList = useStore((s) => s.categoryList);
|
|
const data = appConfig?.others?.search;
|
|
const banner = data?.banner;
|
|
const searchTips = data?.tips || {
|
|
keyword: "关键词",
|
|
placeholder: "请输入",
|
|
search: "搜索",
|
|
total: "共",
|
|
result: "个结果",
|
|
}
|
|
const [page, setPage] = useState(1);
|
|
const [size] = useState(2 * supportLocales.length);
|
|
const [total, setTotal] = useState(0);
|
|
const categoryId = String(categoryList?.find((item: any) => item.name.includes('集团发布'))?.id ?? '');
|
|
|
|
const [searched, setSearched] = useState(false);
|
|
const [searchKeyword, setSearchKeyword] = useState("");
|
|
const [searchData, setSearchData] = useState<SearchData[]>([]);
|
|
const localSearchData = useMemo(() => {
|
|
return searchData.filter((item) => item.lang.toLowerCase() === locale.split('-')[0]);
|
|
}, [searchData, locale]);
|
|
|
|
const handleSearch = useCallback(() => {
|
|
appApi.getNewsList({
|
|
page,
|
|
size,
|
|
title: searchKeyword,
|
|
category_id: categoryId,
|
|
}).then((res) => {
|
|
setSearched(true);
|
|
const data = res.data.items.map((item: any) => {
|
|
return {
|
|
id: item.id,
|
|
title: item.title,
|
|
content: item.content,
|
|
createTime: item.create_time,
|
|
lang: item.lang,
|
|
path: `/news/detail/${item.id}`,
|
|
}
|
|
})
|
|
setSearchData(data);
|
|
setTotal(res.data.total);
|
|
});
|
|
}, [searchKeyword, page, size, categoryId]);
|
|
|
|
useEffect(() => {
|
|
handleSearch();
|
|
}, [page, size]);
|
|
|
|
|
|
|
|
return (
|
|
<div>
|
|
<Banner
|
|
title={banner?.title ?? "搜索结果"}
|
|
content={(banner as BannerConfig)?.content}
|
|
titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
|
|
backgroundImage={banner?.backgroundImage ?? "/images/search-banner.png"}
|
|
/>
|
|
|
|
<section className={styles.searchRow}>
|
|
<div className={styles.searchRowInner}>
|
|
<span className={styles.searchRowTitle}>{searchTips.keyword}</span>
|
|
<div className={styles.searchInputWrapper}>
|
|
<input
|
|
type="text"
|
|
placeholder={searchTips.placeholder}
|
|
className={styles.searchInput}
|
|
value={searchKeyword}
|
|
onChange={(e) => setSearchKeyword(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Enter") handleSearch();
|
|
}}
|
|
/>
|
|
{searched && (
|
|
<div className={styles.searchKeyword}>
|
|
{searchTips.search}:
|
|
<span className={styles.searchKeywordKeyword}>
|
|
{searchKeyword}
|
|
</span>
|
|
{searchTips.total}:
|
|
<span>{total / 2}</span>
|
|
{searchTips.result}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<button
|
|
type="button"
|
|
className={styles.searchBtn}
|
|
onClick={handleSearch}
|
|
>
|
|
{searchTips.search}:
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<Section background="" maskBackground="#fff">
|
|
<div className={styles.searchItemList}>
|
|
{localSearchData.map((item) => (
|
|
<Link to={item.path ?? ''} key={item.id} className={styles.searchItem}>
|
|
<div className={styles.searchItemTitleRow}>
|
|
<span className={styles.searchItemTitle}>{item.title}</span>
|
|
<span className={styles.searchItemCreateTime}>
|
|
{locale.startsWith("zh")
|
|
? dateFormat(item.createTime, "yyyy年MM月dd日")
|
|
: dateFormat(item.createTime, "yyyy-MM-dd")
|
|
}
|
|
</span>
|
|
</div>
|
|
<div className={styles.searchItemContent}>{item.content}</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
<Pagination total={total} size={size} page={page} onChange={setPage} />
|
|
</Section>
|
|
</div>
|
|
);
|
|
}
|