yinweiwen
2 years ago
13 changed files with 274 additions and 31 deletions
@ -0,0 +1,17 @@ |
|||
import React, { useEffect } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Spin, Card, Input } from 'antd'; |
|||
import '../style.less'; |
|||
|
|||
// todo AutoComplete
|
|||
const SerachBar= (props) => { |
|||
const { dispatch, actions, user, loading } = props |
|||
|
|||
return ( |
|||
<div className="parent"> |
|||
<Input className="search" type="text" placeholder=" "></Input> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default SerachBar; |
@ -1,5 +1,6 @@ |
|||
'use strict'; |
|||
|
|||
import Search from './search'; |
|||
import SearchRes from './searchRes'; |
|||
|
|||
export { Search }; |
|||
export { Search, SearchRes }; |
@ -0,0 +1,142 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Affix, List, Input, Space, Empty } from 'antd'; |
|||
import '../style.less'; |
|||
import { |
|||
DatabaseOutlined, |
|||
} from '@ant-design/icons'; |
|||
import { push } from 'react-router-redux' |
|||
|
|||
const IconText = ({ icon, text }) => ( |
|||
<Space> |
|||
{React.createElement(icon)} |
|||
{text} |
|||
</Space> |
|||
); |
|||
|
|||
function getHighlightedText(text, highlight) { |
|||
// Split text on highlight term, include term itself into parts, ignore case
|
|||
const parts = text.split(new RegExp(`(${highlight})`, 'gi')); |
|||
return <span>{parts.map(part => part.toLowerCase() === highlight.toLowerCase() ? <span style={{ color: "red" }}><b>{part}</b></span> : part)}</span>; |
|||
} |
|||
|
|||
const searchRes = (props) => { |
|||
const { dispatch, actions, user, loading, searchDatas } = props |
|||
|
|||
const [controlSearchData, setControlSearchData] = useState([]) |
|||
|
|||
// params
|
|||
const keyword = props.match?.params?.wd |
|||
|
|||
const [inputValue, setInputValue] = useState(keyword) |
|||
|
|||
useEffect(() => { |
|||
if (!!keyword && keyword.length > 0) { |
|||
dispatch(actions.search.search(keyword)) |
|||
} |
|||
}, [keyword]) |
|||
|
|||
useEffect(() => { |
|||
setControlSearchData(searchDatas) |
|||
}, [searchDatas]) |
|||
|
|||
const onSearch = (v) => { |
|||
console.log(`search for ${v}`) |
|||
dispatch(actions.search.search(v)) |
|||
} |
|||
|
|||
const onSearchEnv = (v) => { |
|||
console.log(`search for ${v.target.value}`) |
|||
dispatch(actions.search.search(v.target.value)) |
|||
} |
|||
|
|||
const SafeSearch = (v) => { |
|||
let kwd = '' |
|||
if (typeof v === "string") { |
|||
kwd = v; |
|||
} else { |
|||
kwd = v.target.value; |
|||
} |
|||
if (kwd) { |
|||
dispatch(push(`/s/${kwd}`)) |
|||
} else { |
|||
setControlSearchData([]) |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div className="parent-top"> |
|||
<Input.Search |
|||
className="search-top" |
|||
placeholder=" " |
|||
onSearch={SafeSearch} |
|||
enterButton="Search" |
|||
allowClear |
|||
size="large" |
|||
onPressEnter={SafeSearch} |
|||
maxLength={255} |
|||
value={inputValue} |
|||
onChange={(e) => setInputValue(e.target.value)} |
|||
/> |
|||
{ |
|||
controlSearchData && controlSearchData.length > 0 ? |
|||
<List |
|||
className='search-list' |
|||
itemLayout="vertical" |
|||
size="large" |
|||
pagination={{ |
|||
position: "both", |
|||
showQuickJumper: true, |
|||
onChange: (page) => { |
|||
console.log(page); |
|||
}, |
|||
pageSize: 10, |
|||
}} |
|||
dataSource={controlSearchData} |
|||
footer={ |
|||
<div> |
|||
<b>Free-Sun</b> 搜索结果 |
|||
</div> |
|||
} |
|||
renderItem={(item) => ( |
|||
<List.Item |
|||
key={item.title} |
|||
actions={[ |
|||
<IconText icon={DatabaseOutlined} text="from iota database" />, |
|||
]} |
|||
extra={ |
|||
item.ext?.img ? |
|||
<img |
|||
width={200} |
|||
alt="img" |
|||
src={item.ext.img} |
|||
/> : null |
|||
} |
|||
> |
|||
<List.Item.Meta |
|||
title={<a href={item.link}>{getHighlightedText(item.title, keyword)}</a>} |
|||
description={item.ext?.desc ? item.ext.desc : undefined} |
|||
// description={item.content}
|
|||
/> |
|||
{getHighlightedText(item.content, keyword)} |
|||
</List.Item> |
|||
)} |
|||
/> : <Empty className='search-empty' /> |
|||
} |
|||
|
|||
</div> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps(state) { |
|||
const { auth, global, searchRes } = state; |
|||
console.log(searchRes) |
|||
return { |
|||
loading: searchRes.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
searchDatas: searchRes.data || [], |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(searchRes); |
File diff suppressed because one or more lines are too long
@ -1,12 +1,18 @@ |
|||
'use strict'; |
|||
import { Search, } from './containers'; |
|||
import { Search, SearchRes } from './containers'; |
|||
|
|||
export default [{ |
|||
type: 'inner', |
|||
route: { |
|||
path: '/search', |
|||
path: '/', |
|||
key: 'search', |
|||
breadcrumb: '搜索引擎', |
|||
component: Search |
|||
component: Search, |
|||
childRoutes: [{ |
|||
path: '/s/:wd', |
|||
key: 'searchRes', |
|||
breadcrumb: '搜索结果', |
|||
component: SearchRes, |
|||
}] |
|||
} |
|||
}]; |
@ -1,3 +1,48 @@ |
|||
#example:hover { |
|||
font-size: larger; |
|||
} |
|||
.search { |
|||
width: 500px; |
|||
font: 16px arial,sans-serif; |
|||
} |
|||
// .search:hover, .search:focus { |
|||
// outline: none; |
|||
// box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); |
|||
// } |
|||
|
|||
.parent{ |
|||
display:flex; |
|||
flex-direction: column; |
|||
// justify-content: center; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
} |
|||
|
|||
.parent-top{ |
|||
margin-left: 20%; |
|||
margin-bottom: 10%; |
|||
display:flex; |
|||
flex-wrap: nowrap; |
|||
flex-direction: column; |
|||
justify-content: flex-start; |
|||
align-items: flex-start; // 垂直居中展示 |
|||
} |
|||
|
|||
.search-top { |
|||
width: 75%; |
|||
height: 50px; |
|||
font: 16px arial,sans-serif; |
|||
// margin:auto; |
|||
} |
|||
|
|||
.search-empty{ |
|||
align-self: center; |
|||
} |
|||
|
|||
.search-content { |
|||
width: 75%; |
|||
} |
|||
|
|||
.search-list{ |
|||
width: 75%; |
|||
} |
Binary file not shown.
Loading…
Reference in new issue