feat: 联系人搜索

This commit is contained in:
2021-11-26 01:01:48 +08:00
parent 147972e96e
commit 1054c501c2
6 changed files with 82 additions and 56 deletions
+4 -2
View File
@@ -85,8 +85,10 @@ function getContacts(socket) {
nickname: contact.NickName, nickname: contact.NickName,
displayName: getDisplayName(contact), displayName: getDisplayName(contact),
signature: contact.Signature, signature: contact.Signature,
nameInitial: contact.PYInitial || contact.RemarkPYInitial, nameInitial: contact.RemarkPYInitial,
nameQuanPin: contact.PYQuanPin || contact.RemarkPYQuanPin, nickNameInitial: contact.PYInitial,
nameQuanPin: contact.RemarkPYQuanPin,
nickNameQuanPin: contact.PYQuanPin,
avatar: `${config.baseUrl}/session/${socketIDToSessionID.get( avatar: `${config.baseUrl}/session/${socketIDToSessionID.get(
socket.id socket.id
)}/avatar/${contact.UserName}`, )}/avatar/${contact.UserName}`,
+32
View File
@@ -18,6 +18,7 @@
"dayjs": "^1.10.7", "dayjs": "^1.10.7",
"filesize": "^7.0.0", "filesize": "^7.0.0",
"linaria": "^2.1.0", "linaria": "^2.1.0",
"lodash-es": "^4.17.21",
"log4js": "^6.3.0", "log4js": "^6.3.0",
"multer": "^1.4.3", "multer": "^1.4.3",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
@@ -60,6 +61,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@types/ali-oss": "^6.0.10", "@types/ali-oss": "^6.0.10",
"@types/loadable__component": "^5.13.4", "@types/loadable__component": "^5.13.4",
"@types/lodash-es": "^4.17.5",
"@types/platform": "^1.3.4", "@types/platform": "^1.3.4",
"@types/prismjs": "^1.16.6", "@types/prismjs": "^1.16.6",
"@types/pure-render-decorator": "^0.2.28", "@types/pure-render-decorator": "^0.2.28",
@@ -2239,6 +2241,21 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/lodash": {
"version": "4.14.177",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz",
"integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
"dev": true
},
"node_modules/@types/lodash-es": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz",
"integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
"version": "3.0.5", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
@@ -13513,6 +13530,21 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/lodash": {
"version": "4.14.177",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz",
"integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
"dev": true
},
"@types/lodash-es": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz",
"integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==",
"dev": true,
"requires": {
"@types/lodash": "*"
}
},
"@types/minimatch": { "@types/minimatch": {
"version": "3.0.5", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+2
View File
@@ -17,6 +17,7 @@
"dayjs": "^1.10.7", "dayjs": "^1.10.7",
"filesize": "^7.0.0", "filesize": "^7.0.0",
"linaria": "^2.1.0", "linaria": "^2.1.0",
"lodash-es": "^4.17.21",
"log4js": "^6.3.0", "log4js": "^6.3.0",
"multer": "^1.4.3", "multer": "^1.4.3",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
@@ -59,6 +60,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@types/ali-oss": "^6.0.10", "@types/ali-oss": "^6.0.10",
"@types/loadable__component": "^5.13.4", "@types/loadable__component": "^5.13.4",
"@types/lodash-es": "^4.17.5",
"@types/platform": "^1.3.4", "@types/platform": "^1.3.4",
"@types/prismjs": "^1.16.6", "@types/prismjs": "^1.16.6",
"@types/pure-render-decorator": "^0.2.28", "@types/pure-render-decorator": "^0.2.28",
@@ -1,11 +1,25 @@
import React from 'react'; import React from 'react';
import { uniq } from 'lodash-es';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { State } from '../../state/reducer'; import { State } from '../../state/reducer';
import ContactComponent from './Contact'; import ContactComponent from './Contact';
import Style from './ContactList.less'; import Style from './ContactList.less';
function ContactList() { function ContactList({ keyword = '' }) {
const contacts = useSelector((state: State) => state.contacts); let contacts =
useSelector((state: State) => [...state.groups, ...state.contacts]) ||
[];
if (keyword) {
keyword = keyword.toLowerCase();
contacts = [
...contacts.filter((c) => c.displayName?.toLowerCase().includes(keyword)),
...contacts.filter((c) => c.nameQuanPin?.toLowerCase().includes(keyword)),
...contacts.filter((c) => c.nickname?.toLowerCase().includes(keyword)),
...contacts.filter((c) => c.nickname?.toLowerCase().includes(keyword)),
];
contacts = uniq(contacts);
}
console.log(contacts);
return ( return (
<div className={Style.linkmanList}> <div className={Style.linkmanList}>
@@ -1,23 +1,18 @@
import React from 'react'; import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import useAction from '../../hooks/useAction';
import useAero from '../../hooks/useAero';
import useIsLogin from '../../hooks/useIsLogin'; import useIsLogin from '../../hooks/useIsLogin';
import { State } from '../../state/reducer';
import ContactList from './ContactList'; import ContactList from './ContactList';
import SearchBar from './SearchBar'; import SearchBar from './SearchBar';
import Style from './FunctionBarAndContactList.less'; import Style from './FunctionBarAndContactList.less';
function FunctionBarAndContactList() { function FunctionBarAndContactList() {
const isLogin = useIsLogin(); const isLogin = useIsLogin();
const action = useAction(); const [keyword, setKeyword] = useState('');
const aero = useAero();
return ( return (
<div className={Style.contactList} role="button"> <div className={Style.contactList} role="button">
<div className={Style.container}> <div className={Style.container}>
{isLogin && <SearchBar />} {isLogin && <SearchBar onSearch={setKeyword} />}
<ContactList /> <ContactList keyword={keyword} />
</div> </div>
</div> </div>
); );
@@ -1,47 +1,30 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useCallback, useContext, useState } from 'react';
import Avatar from '../../components/Avatar'; import { debounce } from 'lodash-es';
import IconButton from '../../components/IconButton';
import Input from '../../components/Input'; import Input from '../../components/Input';
import Message from '../../components/Message';
import {
ScrollableInkTabBar,
TabContent,
TabPane,
Tabs as div,
} from '../../components/Tabs';
import { ShowUserOrGroupInfoContext } from '../../context';
import Style from './SearchBar.less'; import Style from './SearchBar.less';
type SearchResult = { function FunctionBar({ onSearch }) {
users: any[]; const [keyword, setKeyword] = useState('');
groups: any[];
};
function FunctionBar() { const triggerSearch = useCallback(
const [keywords, setKeywords] = useState(''); debounce((kw: string) => {
const [searchResultVisible, toggleSearchResultVisible] = useState(false); onSearch && onSearch(kw);
const [searchResult, setSearchResult] = useState<SearchResult>({ }, 500),
users: [], [onSearch],
groups: [], );
}); const handleInputChange = useCallback(
(kw) => {
console.log('aaaaa',kw);
const context = useContext(ShowUserOrGroupInfoContext); setKeyword(kw);
const placeholder = '搜索群组/用户'; triggerSearch(kw);
},
[triggerSearch],
);
function resetSearch() { const handleInputEnter = useCallback(() => {
setSearchResult({ users: [], groups: [] }); triggerSearch.flush();
setKeywords(''); }, [triggerSearch]);
}
function handleInputChange(value: string) {
setKeywords(value);
if (!value) {
resetSearch();
}
}
function handleInputEnter() {
}
return ( return (
<div className={Style.functionBar}> <div className={Style.functionBar}>
@@ -51,12 +34,10 @@ function FunctionBar() {
onSubmit={(e) => e.preventDefault()} onSubmit={(e) => e.preventDefault()}
> >
<Input <Input
className={`${Style.input} ${ className={Style.input}
searchResultVisible ? Style.inputFocus : ''
}`}
type="text" type="text"
placeholder={placeholder} placeholder="搜索用户/群组"
value={keywords} value={keyword}
onChange={handleInputChange} onChange={handleInputChange}
onEnter={handleInputEnter} onEnter={handleInputEnter}
/> />