Skip to content

Commit

Permalink
feat: ✨ 完成快捷操作搜索功能
Browse files Browse the repository at this point in the history
  • Loading branch information
G committed Dec 25, 2023
1 parent 74bb8e6 commit d86ca8b
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 42 deletions.
1 change: 1 addition & 0 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"echarts": "^5.4.3",
"echarts-for-react": "^3.0.2",
"file-saver": "^2.0.5",
"fuse.js": "^7.0.0",
"gbeata": "workspace:*",
"immer": "^10.0.3",
"lodash-es": "^4.17.21",
Expand Down
88 changes: 56 additions & 32 deletions apps/admin/src/components/SearchModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/* eslint-disable consistent-return */
import { SearchOutlined } from '@ant-design/icons';
import { Badge, Input, List, Modal } from 'antd';
import { useTheme } from 'antd-style';
import React, { forwardRef, useImperativeHandle, useState } from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import Fuse from 'fuse.js';
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { Link } from 'react-router-dom';

import { treeToList } from '@/utils/helper/treeHelper';

import { getAsyncMenus } from '@/router/menus';

import useStyle from './style';

import type { AppMenu } from '@/router/types';

interface SearchModalProps {
open?: boolean;
}
Expand All @@ -16,15 +26,10 @@ export interface SearchModalMethods {

const SearchModal = forwardRef<SearchModalMethods, SearchModalProps>((props, ref) => {
const [isModalOpen, setIsModalOpen] = useState(false);

const [routes, setRoutes] = useState<AppMenu[]>([]);
const { styles } = useStyle();
const token = useTheme();

useImperativeHandle(ref, () => ({
open: () => setIsModalOpen(() => true),
close: () => setIsModalOpen(() => false),
}));

const classNames = {
body: styles['my-modal-body'],
mask: styles['my-modal-mask'],
Expand All @@ -51,37 +56,50 @@ const SearchModal = forwardRef<SearchModalMethods, SearchModalProps>((props, ref
borderTop: '1px solid #333',
},
content: {
boxShadow: '0 0 30px #999',
boxShadow: '0 0 30px #99999994',
},
};
const getMenusData = async () => {
try {
const routesData = await getAsyncMenus();
setRoutes(routesData);
} catch (error) {
return [];
}
};
useEffect(() => {
getMenusData();
}, []);
const menus = useCallback(() => treeToList(routes, { children: 'children' }), [routes]);
useImperativeHandle(ref, () => ({
open: () => setIsModalOpen(() => true),
close: () => setIsModalOpen(() => false),
}));

const data = [
{
title: 'Ant Design Title 1',
},
{
title: 'Ant Design Title 2',
},
{
title: 'Ant Design Title 1',
},
{
title: 'Ant Design Title 2',
},
{
title: 'Ant Design Title 1',
},
{
title: 'Ant Design Title 2',
},
];
const fuse = new Fuse(menus(), {
keys: ['name', 'path'],
threshold: 0.2,
});

const [value, setValue] = useState('');

// Function to highlight matching characters
const highlightText = (text: string, searchValue: string) => {
const regex = new RegExp(`(${searchValue})`, 'gi');
return text.replace(
regex,
(match, p1) => `<span style="background-color: ${token.colorPrimaryBorderHover};">${p1}</span>`,
);
};

return (
<>
<Modal
title={
<Input
size='large'
onChange={(e) => setValue(e.target.value)}
value={value}
placeholder='请输入搜索...'
prefix={<SearchOutlined />}
suffix={<Badge count={'Esc'} color={token.colorPrimaryHover} />}
Expand All @@ -97,12 +115,18 @@ const SearchModal = forwardRef<SearchModalMethods, SearchModalProps>((props, ref
>
<List
itemLayout='horizontal'
dataSource={data}
renderItem={(item, index) => (
dataSource={value ? fuse.search(value).map((item) => item.item) : menus()}
renderItem={(item: AppMenu) => (
<List.Item>
<List.Item.Meta
title={<a href='https://ant.design'>{item.title}</a>}
description='Ant Design, a design language for background applications, '
title={
<Link
to={item.path}
onClick={() => setIsModalOpen(() => false)}
dangerouslySetInnerHTML={{ __html: highlightText(item.name, value) }}
/>
}
description={<span dangerouslySetInnerHTML={{ __html: highlightText(item.path, value) }} />}
/>
</List.Item>
)}
Expand Down
1 change: 0 additions & 1 deletion apps/admin/src/router/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export function transformRouteToMenu(routes: RouteObject[]) {
if (item.meta!.hideChildrenInMenu) {
item.children = [];
}

routeList.push(item);
});

Expand Down
20 changes: 13 additions & 7 deletions apps/admin/src/utils/helper/treeHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/* eslint-disable no-continue */
/* eslint-disable no-plusplus */
/* eslint-disable no-param-reassign */
/* eslint-disable no-restricted-syntax */
interface TreeHelperConfig {
id: string
children: string
pid: string
id: string;
children: string;
pid: string;
}

const DEFAULT_CONFIG: TreeHelperConfig = {
Expand Down Expand Up @@ -152,10 +156,12 @@ export function treeMapEach(data: any, { children = 'children', conversion }: {
if (haveChildren) {
return {
...conversionData,
[children]: data[children].map((i: number) => treeMapEach(i, {
children,
conversion,
})),
[children]: data[children].map((i: number) =>
treeMapEach(i, {
children,
conversion,
}),
),
};
}
return {
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/src/views/home/components/CommitTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ function CommitTable() {
key: 'time',
},
];
const apiUrl = 'https://api.github.com/repos/anyone-yuren/react-antd-admin-pnpm/commits?sha=admin&per_page=10';
const accessToken = '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';
const apiUrl = 'https://api.github.com/repos/anyone-yuren/react-antd-admin-pnpm/commits?sha=admin&per_page=5';
const accessToken = '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';

useEffect(() => {
fetch(apiUrl, {
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d86ca8b

Please sign in to comment.