✨ Feat: [前台]:添加搜索功能;适配手机端
This commit is contained in:
parent
828af36c03
commit
1244c33785
100
front/src/components/Search/index.jsx
Normal file
100
front/src/components/Search/index.jsx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Input } from "antd";
|
||||||
|
import styles from "./index.module.less";
|
||||||
|
import httpUtil from "../../util/httpUtil";
|
||||||
|
|
||||||
|
class Search extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
content: "",
|
||||||
|
currentIndex: 0,
|
||||||
|
isFocus: false,
|
||||||
|
resultList: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
contentChange(e) {
|
||||||
|
const content = e.target.value.trim();
|
||||||
|
this.setState({ content });
|
||||||
|
this.search(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(content) {
|
||||||
|
if (content.length === 0) {
|
||||||
|
this.setState({ resultList: [] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
httpUtil.get("/bookmark/searchUserBookmark?content=" + encodeURIComponent(content)).then(res => this.setState({ resultList: res }));
|
||||||
|
}
|
||||||
|
|
||||||
|
goTo(url) {
|
||||||
|
window.open(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
keyUp(e) {
|
||||||
|
const { isFocus, resultList } = this.state;
|
||||||
|
let currentIndex = this.state.currentIndex;
|
||||||
|
if (!isFocus || resultList.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (e.keyCode) {
|
||||||
|
//上
|
||||||
|
case 38:
|
||||||
|
currentIndex--;
|
||||||
|
break;
|
||||||
|
//下
|
||||||
|
case 40:
|
||||||
|
currentIndex++;
|
||||||
|
break;
|
||||||
|
// enter
|
||||||
|
case 13:
|
||||||
|
this.goTo(resultList[currentIndex].url);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentIndex < 0) {
|
||||||
|
currentIndex = resultList.length - 1;
|
||||||
|
} else if (currentIndex > resultList.length - 1) {
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
this.setState({ currentIndex });
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { content, resultList, currentIndex } = this.state;
|
||||||
|
return (
|
||||||
|
<div className={styles.main}>
|
||||||
|
<Input.Search
|
||||||
|
ref="searchInput"
|
||||||
|
value={content}
|
||||||
|
placeholder="搜索书签"
|
||||||
|
enterButton
|
||||||
|
allowClear
|
||||||
|
onChange={this.contentChange.bind(this)}
|
||||||
|
onKeyDown={this.keyUp.bind(this)}
|
||||||
|
onFocus={() => this.setState({ isFocus: true })}
|
||||||
|
onBlur={() => this.setState({ isFocus: false })}
|
||||||
|
/>
|
||||||
|
{resultList.length > 0 ? (
|
||||||
|
<div className={styles.resultList}>
|
||||||
|
{resultList.map((item, index) => (
|
||||||
|
<div
|
||||||
|
className={`${styles.item} ${index === currentIndex ? styles.checked : ""}`}
|
||||||
|
key={item.bookmarkId}
|
||||||
|
onClick={this.goTo.bind(this, item.url)}
|
||||||
|
>
|
||||||
|
<span style={{ fontWeight: 600 }}>{item.name} </span>
|
||||||
|
<span style={{ fontSize: "0.8em", fontWeight: 400 }}>{item.url}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Search;
|
51
front/src/components/Search/index.module.less
Normal file
51
front/src/components/Search/index.module.less
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
.main {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.resultList {
|
||||||
|
position: absolute;
|
||||||
|
background: white;
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.1em 0.2em;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .item > span {
|
||||||
|
// display: inline-block;
|
||||||
|
// padding-right: 0.5em;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .item:first-child {
|
||||||
|
// flex: 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .item:last-child {
|
||||||
|
// flex: 2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background: #f2f4f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked {
|
||||||
|
background: #f2f4f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-input-affix-wrapper .ant-input {
|
||||||
|
// border: none;
|
||||||
|
// border-bottom: 1px solid white !important;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,16 @@
|
|||||||
color: #969696 !important;
|
color: #969696 !important;
|
||||||
background: white;
|
background: white;
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
|
@media screen {
|
||||||
|
width: 98%;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.head {
|
.head {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
@import "../../global.less";
|
@import "../../global.less";
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
background-color: @mainBgColor;
|
background-color: @mainBgColor;
|
||||||
min-width: 1366px;
|
|
||||||
|
.header {
|
||||||
.header {
|
display: flex;
|
||||||
display: flex;
|
justify-content: space-between;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
align-items: center;
|
padding: 0.1rem 0.5rem;
|
||||||
padding: 0.1rem 0.5rem;
|
}
|
||||||
}
|
|
||||||
|
.content {
|
||||||
.content {
|
margin: 0 auto;
|
||||||
margin: 0 10%;
|
margin-top: 0.2rem;
|
||||||
margin-top: 0.2rem;
|
height: calc(100% - 0.8rem);
|
||||||
height: calc(100% - 0.8rem);
|
|
||||||
}
|
@media screen {
|
||||||
}
|
width: 98%;
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
width: 98%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -56,9 +56,12 @@ class AddModal extends React.Component {
|
|||||||
*/
|
*/
|
||||||
editOne(node) {
|
editOne(node) {
|
||||||
const { addName, addValue } = this.state;
|
const { addName, addValue } = this.state;
|
||||||
|
const { bookmarkId, type } = this.props.currentEditNode;
|
||||||
const body = {
|
const body = {
|
||||||
|
bookmarkId,
|
||||||
name: addName,
|
name: addName,
|
||||||
url: addValue
|
url: addValue,
|
||||||
|
type
|
||||||
};
|
};
|
||||||
httpUtil.post("/bookmark/updateOne", body).then(() => {
|
httpUtil.post("/bookmark/updateOne", body).then(() => {
|
||||||
message.success("编辑成功");
|
message.success("编辑成功");
|
||||||
|
@ -5,6 +5,7 @@ import httpUtil from "../../../util/httpUtil";
|
|||||||
import styles from "./index.module.less";
|
import styles from "./index.module.less";
|
||||||
import { batchDelete, renderTreeNodes, onDrop } from "./function.js";
|
import { batchDelete, renderTreeNodes, onDrop } from "./function.js";
|
||||||
import AddModal from "./AddModal";
|
import AddModal from "./AddModal";
|
||||||
|
import Search from "../../../components/Search";
|
||||||
|
|
||||||
import * as action from "../../../redux/action/BookmarkTreeOverview";
|
import * as action from "../../../redux/action/BookmarkTreeOverview";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@ -80,6 +81,7 @@ class OverView extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<div className={styles.main}>
|
<div className={styles.main}>
|
||||||
|
<Search />
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
<span className={styles.myTree}>我的书签树</span>
|
<span className={styles.myTree}>我的书签树</span>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
.main {
|
.main {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
width: 4rem;
|
width: 100%;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
.main {
|
.main {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
width: 4rem;
|
width: 100%;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
padding: 0.1rem 0;
|
padding: 0.1rem 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit {
|
.submit {
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global {
|
:global {
|
||||||
.ant-input {
|
.ant-input {
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user