Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:#51 优化笔记搜索,添加自定完成功能 #55

Merged
merged 1 commit into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
30 changes: 17 additions & 13 deletions components/themes/default/defaultNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {faBook, faDownload, faFile, faFileText, faHome, faPieChart} from '@forta
import SiteConfig from "../../../lib/common/siteconfig";
import {useState} from "react";
import Image from "next/image";
import {isEmptyString} from "../../../lib/util";
import {API_TYPE_CONSTANTS} from "../../../lib/constants";
import {CategoryInfo} from "../../../lib/common/categoryInfo";
import DefaultSearchBar from "./defaultSearchBar";

export default function DefaultNavbar({
props,
Expand Down Expand Up @@ -70,17 +69,22 @@ export default function DefaultNavbar({
}

<Nav.Item>
<Form onSubmit={(e) => handleSearch(e)} className={clsx("d-flex", navbarStyles.sFormGroup)}>
<Form.Control
type="text"
value={value}
placeholder="请输入关键词"
onChange={(e) => setValue(e.target.value)}
/>
<Button type="submit">
搜索
</Button>
</Form>
{
false &&
<Form onSubmit={(e) => handleSearch(e)} className={clsx("d-flex", navbarStyles.sFormGroup)}>
<Form.Control
type="text"
value={value}
placeholder="请输入关键词"
onChange={(e) => setValue(e.target.value)}
/>
<Button type="submit">
搜索
</Button>
</Form>
}

<DefaultSearchBar />
</Nav.Item>
</Container>
</Navbar>
Expand Down
137 changes: 137 additions & 0 deletions components/themes/default/defaultSearchBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, {useCallback, useState} from 'react';
import {AsyncTypeahead} from 'react-bootstrap-typeahead';

import 'react-bootstrap-typeahead/css/Typeahead.css';
import './css/searchbar.module.css';
import {Button, Form} from "react-bootstrap";
import clsx from "clsx";
import navbarStyles from "./css/navbar.module.css";
import {getRootBlocks} from "../../../lib/siyuan/siYuanApi";

const CACHE: any = {};
const PER_PAGE = 50;
// const SEARCH_URI = 'https://api.github.com/search/users';

export default function DefaultSearchBar() {
const [isLoading, setIsLoading] = useState(false);
const [options, setOptions] = useState([]);
const [query, setQuery] = useState('');

const goPage = () => {
window.location.href = "/s/" + query
}

const handleInputChange = (q: string) => {
setQuery(q);
};

const handlePagination = (e: any, shownResults: any) => {
const cachedQuery = CACHE[query];

// Don't make another request if:
// - the cached results exceed the shown results
// - we've already fetched all possible results
if (
cachedQuery.options.length > shownResults ||
cachedQuery.options.length === cachedQuery.total_count
) {
return;
}

setIsLoading(true);

const page = cachedQuery.page + 1;

makeAndHandleRequest(query, page).then((resp) => {
const options = cachedQuery.options.concat(resp.options);
CACHE[query] = {...cachedQuery, options, page};

setIsLoading(false);
setOptions(options);
});
};

// `handleInputChange` updates state and triggers a re-render, so
// use `useCallback` to prevent the debounced search handler from
// being cancelled.
const handleSearch = useCallback((q: string) => {
if (CACHE[q]) {
setOptions(CACHE[q].options);
return;
}

setIsLoading(true);
makeAndHandleRequest(q).then((resp) => {
CACHE[q] = {...resp, page: 1};

setIsLoading(false);
// @ts-ignore
setOptions(resp.options);
});
}, []);

return (
<Form className={clsx("d-flex", navbarStyles.sFormGroup)}>
<AsyncTypeahead
id="async-pagination-searchbar"
isLoading={isLoading}
labelKey="login"
maxResults={PER_PAGE - 1}
minLength={1}
onChange={goPage}
onInputChange={handleInputChange}
onPaginate={handlePagination}
onSearch={handleSearch}
options={options}
paginate
placeholder="请输入关键词"
searchText="搜索中..."
emptyLabel="暂无结果"
paginationText="加载更多"
promptText="输入关键词搜索"
renderMenuItemChildren={(option: any) => (
<div key={option.id}>
<span>{option.login}</span>
</div>
)}
useCache={false}
/>
<Button type="button" onClick={goPage}>
搜索
</Button>
</Form>
);
}

function makeAndHandleRequest(query: any, page = 0) {
return getRootBlocks(page, PER_PAGE, query).then((items: any) => {
const options: any = []

if (items && items.length > 0) {
items.forEach((i: any) => {
const item = {
id: i.root_id,
login: i.content,
}

options.push(item)
});
}
console.log("items=>", items)

const total = options.length;
const bardata = {options, total}
console.log("bardata=>", bardata)
return bardata;
})

// return fetch(`${SEARCH_URI}?q=${query}+in:login&page=${page}&per_page=${PER_PAGE}`)
// .then((resp) => resp.json())
// .then(({items, total_count}) => {
// const options = items.map((i: any) => ({
// id: i.id,
// login: i.login,
// }));
// return {options, total_count};
// });
}
39 changes: 21 additions & 18 deletions lib/siyuan/siYuanApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,12 @@ export {
*/
async function request(url: string, data: any, method?: string, useToken?: boolean) {
let resData = null
if (config.baseUrl != "") {
url = config.baseUrl + url
var baseUrl = config.baseUrl
if (typeof baseUrl == "undefined" || baseUrl == "undefined") {
baseUrl = "http://127.0.0.1:6806"
}
if (baseUrl != "") {
url = baseUrl + url
}

let m = "POST"
Expand Down Expand Up @@ -336,28 +340,27 @@ async function getHPathByID(blockId: string) {
* @param pagesize 数目
*
* select DISTINCT b2.root_id,b2.parent_id,b2.content from blocks b2
* WHERE 1==1
* WHERE 1==1
* AND b2.id IN (
* SELECT DISTINCT b1.id
* FROM blocks b1
* WHERE 1 = 1
* AND b1.parent_id=''
* AND ((b1.content LIKE '%jdbc%') OR (b1.tag LIKE '%jdbc%'))
* ORDER BY b1.created DESC LIMIT 0, 10
* SELECT DISTINCT b1.root_id
* FROM blocks b1
* WHERE 1 = 1
* AND ((b1.content LIKE '%github%') OR (b1.tag LIKE '%github%'))
* ORDER BY b1.updated DESC,b1.created DESC LIMIT 0,10
* )
* ORDER BY b2.updated DESC,b2.created DESC
*/
async function getRootBlocks(page: number, pagesize: number, keyword: string) {
let stmt = `select DISTINCT b2.root_id,b2.parent_id,b2.content from blocks b2
WHERE 1==1
AND b2.id IN (
SELECT DISTINCT b1.id
FROM blocks b1
WHERE 1 = 1
AND b1.parent_id=''
AND ((b1.content LIKE '%${keyword}%') OR (b1.tag LIKE '%${keyword}%'))
ORDER BY b1.updated DESC,b1.created DESC LIMIT ${page}, ${pagesize}
)
ORDER BY b2.updated DESC,b2.created DESC`
AND b2.id IN (
SELECT DISTINCT b1.root_id
FROM blocks b1
WHERE 1 = 1
AND ((b1.content LIKE '%${keyword}%') OR (b1.tag LIKE '%${keyword}%'))
ORDER BY b1.updated DESC,b1.created DESC LIMIT ${page},${pagesize}
)
ORDER BY b2.updated DESC,b2.created DESC`
let data = await sql(stmt)
return data
}
Expand Down
2 changes: 0 additions & 2 deletions lib/siyuan/siYuanApiAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import {exportMdContent, getBlockAttrs, getBlockByID, getBlockBySlug, getDoc, ge
import {Post} from "../common/post";
import {UserBlog} from "../common/userBlog";
import {API_TYPE_CONSTANTS} from "../constants";
import logUtil from "../logUtil";
import {render} from "../markdownUtil";
import {mdToHtml, removeTitleNumber, removeWidgetTag} from "../htmlUtil";
import {CategoryInfo} from "../common/categoryInfo";

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"plantuml-encoder": "^1.4.0",
"react": "18.2.0",
"react-bootstrap": "^2.4.0",
"react-bootstrap-typeahead": "^6.0.0",
"react-dom": "18.2.0",
"xmlrpc": "^1.3.2"
},
Expand Down
Loading