mirror of
https://github.com/TangSengDaoDao/TangSengDaoDaoWeb
synced 2025-06-06 09:08:59 +00:00
feat: add GlobalSearch components and styles for improved search functionality
This commit is contained in:
parent
559812ec8b
commit
16fc0b6221
@ -480,12 +480,12 @@ export class Conversation extends Component<ConversationProps> implements Conver
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { chatBg, channel } = this.props
|
const { chatBg, channel,initLocateMessageSeq } = this.props
|
||||||
|
|
||||||
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel)
|
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel)
|
||||||
|
|
||||||
return <Provider create={() => {
|
return <Provider create={() => {
|
||||||
this.vm = new ConversationVM(channel)
|
this.vm = new ConversationVM(channel,initLocateMessageSeq)
|
||||||
return this.vm
|
return this.vm
|
||||||
}} render={(vm: ConversationVM) => {
|
}} render={(vm: ConversationVM) => {
|
||||||
return <>
|
return <>
|
||||||
|
@ -24,7 +24,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
currentConversation?: Conversation // 当前最近会话
|
currentConversation?: Conversation // 当前最近会话
|
||||||
messagesOfOrigin: MessageWrap[] = [] // 原始消息集合(不包含时间消息等本地消息)
|
messagesOfOrigin: MessageWrap[] = [] // 原始消息集合(不包含时间消息等本地消息)
|
||||||
browseToMessageSeq: number = 0 // 已经预览到的最新的messageSeq
|
browseToMessageSeq: number = 0 // 已经预览到的最新的messageSeq
|
||||||
initLocateMessageSeq: number = 0 // 初始定位的消息messageSeq 0为不定位
|
initLocateMessageSeq?: number = 0 // 初始定位的消息messageSeq 0为不定位
|
||||||
shouldShowHistorySplit: boolean = false // 是否应该显示历史消息分割线
|
shouldShowHistorySplit: boolean = false // 是否应该显示历史消息分割线
|
||||||
private _editOn: boolean = false // 是否开启编辑模式
|
private _editOn: boolean = false // 是否开启编辑模式
|
||||||
orgUnreadCount: number = 0 // 原未读数量
|
orgUnreadCount: number = 0 // 原未读数量
|
||||||
@ -57,10 +57,14 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
|
|
||||||
onFirstMessagesLoaded?: Function // 第一屏消息已加载完成
|
onFirstMessagesLoaded?: Function // 第一屏消息已加载完成
|
||||||
|
|
||||||
constructor(channel: Channel) {
|
constructor(channel: Channel, initLocateMessageSeq?: number) {
|
||||||
super()
|
super()
|
||||||
this.channel = channel
|
this.channel = channel
|
||||||
// this.initLocateMessageSeq = initLocateMessageSeq
|
if(initLocateMessageSeq==0) {
|
||||||
|
this.initLocateMessageSeq = undefined
|
||||||
|
}else {
|
||||||
|
this.initLocateMessageSeq = initLocateMessageSeq
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentReplyMessage() {
|
get currentReplyMessage() {
|
||||||
@ -131,7 +135,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 选中消息
|
// 选中消息
|
||||||
checkedMessage(message: Message, checked: boolean): void {
|
checkedMessage(message: Message, checked: boolean): void {
|
||||||
let messageWrap = this.findMessageWithClientMsgNo(message.clientMsgNo)
|
let messageWrap = this.findMessageWithClientMsgNo(message.clientMsgNo)
|
||||||
@ -255,11 +259,11 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
didMount(): void {
|
didMount(): void {
|
||||||
|
|
||||||
this.conversationListener = (conversation: Conversation, action: ConversationAction) => {
|
this.conversationListener = (conversation: Conversation, action: ConversationAction) => {
|
||||||
if(!conversation.channel.isEqual(this.channel)) {
|
if (!conversation.channel.isEqual(this.channel)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(action == ConversationAction.update) {
|
if (action == ConversationAction.update) {
|
||||||
console.log("update-2--->",conversation.unread)
|
console.log("update-2--->", conversation.unread)
|
||||||
this.unreadCount = conversation.unread
|
this.unreadCount = conversation.unread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,8 +319,8 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
|
|
||||||
WKApp.endpointManager.setMethod(EndpointID.clearChannelMessages, (channel: Channel) => {
|
WKApp.endpointManager.setMethod(EndpointID.clearChannelMessages, (channel: Channel) => {
|
||||||
if (channel.isEqual(this.channel)) {
|
if (channel.isEqual(this.channel)) {
|
||||||
if(this.messagesOfOrigin.length > 0) {
|
if (this.messagesOfOrigin.length > 0) {
|
||||||
this.browseToMessageSeq = this.messagesOfOrigin[this.messagesOfOrigin.length-1].messageSeq
|
this.browseToMessageSeq = this.messagesOfOrigin[this.messagesOfOrigin.length - 1].messageSeq
|
||||||
}
|
}
|
||||||
this.messagesOfOrigin = []
|
this.messagesOfOrigin = []
|
||||||
this.messages = []
|
this.messages = []
|
||||||
@ -364,7 +368,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
this.orgUnreadCount = unread
|
this.orgUnreadCount = unread
|
||||||
this.unreadCount = unread
|
this.unreadCount = unread
|
||||||
this.currentConversation = conversation
|
this.currentConversation = conversation
|
||||||
|
|
||||||
|
|
||||||
this.shouldShowHistorySplit = unread > 0
|
this.shouldShowHistorySplit = unread > 0
|
||||||
if (unread > 0) {
|
if (unread > 0) {
|
||||||
@ -383,7 +387,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
WKSDK.shared().conversationManager.openConversation = conversation
|
WKSDK.shared().conversationManager.openConversation = conversation
|
||||||
}
|
}
|
||||||
|
|
||||||
this.requestMessagesOfFirstPage(undefined, () => {
|
this.requestMessagesOfFirstPage(this.initLocateMessageSeq, () => {
|
||||||
if (this.onFirstMessagesLoaded) {
|
if (this.onFirstMessagesLoaded) {
|
||||||
this.onFirstMessagesLoaded()
|
this.onFirstMessagesLoaded()
|
||||||
}
|
}
|
||||||
@ -404,8 +408,8 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加载频道信息完成
|
// 加载频道信息完成
|
||||||
async loadChannelInfoFinished() {
|
async loadChannelInfoFinished() {
|
||||||
if(this.channel.channelType !== ChannelTypeGroup) {
|
if (this.channel.channelType !== ChannelTypeGroup) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.reloadSubscribers()
|
this.reloadSubscribers()
|
||||||
@ -416,25 +420,25 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
this.reloadSubscribers()
|
this.reloadSubscribers()
|
||||||
})
|
})
|
||||||
|
|
||||||
if(this.channelInfo?.orgData?.group_type == SuperGroup) {
|
if (this.channelInfo?.orgData?.group_type == SuperGroup) {
|
||||||
// 如果是超级群则只获取第一页成员
|
// 如果是超级群则只获取第一页成员
|
||||||
this.subscribers = await this.getFirstPageMembers()
|
this.subscribers = await this.getFirstPageMembers()
|
||||||
WKSDK.shared().channelManager.subscribeCacheMap.set(this.channel.getChannelKey(), this.subscribers)
|
WKSDK.shared().channelManager.subscribeCacheMap.set(this.channel.getChannelKey(), this.subscribers)
|
||||||
WKSDK.shared().channelManager.notifySubscribeChangeListeners(this.channel)
|
WKSDK.shared().channelManager.notifySubscribeChangeListeners(this.channel)
|
||||||
this.notifyListener()
|
this.notifyListener()
|
||||||
}else {
|
} else {
|
||||||
WKSDK.shared().channelManager.syncSubscribes(this.channel)
|
WKSDK.shared().channelManager.syncSubscribes(this.channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取第一页成员列表(超大群)
|
// 获取第一页成员列表(超大群)
|
||||||
getFirstPageMembers() {
|
getFirstPageMembers() {
|
||||||
return WKApp.dataSource.channelDataSource.subscribers(this.channel,{
|
return WKApp.dataSource.channelDataSource.subscribers(this.channel, {
|
||||||
limit: 100,
|
limit: 100,
|
||||||
page: 1
|
page: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记提醒已完成
|
// 标记提醒已完成
|
||||||
@ -690,7 +694,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
|
|
||||||
// 刷新新消息数量
|
// 刷新新消息数量
|
||||||
refreshNewMsgCount() {
|
refreshNewMsgCount() {
|
||||||
|
|
||||||
const oldUnreadCount = this.unreadCount
|
const oldUnreadCount = this.unreadCount
|
||||||
if (this.browseToMessageSeq == 0) {
|
if (this.browseToMessageSeq == 0) {
|
||||||
this.unreadCount = 0
|
this.unreadCount = 0
|
||||||
@ -1023,7 +1027,7 @@ export default class ConversationVM extends ProviderListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newMessages.push(message)
|
newMessages.push(message)
|
||||||
if (shouldShowHistorySplit && this.initLocateMessageSeq > 0 && message.messageSeq === this.initLocateMessageSeq) {
|
if (shouldShowHistorySplit && this.initLocateMessageSeq && this.initLocateMessageSeq > 0 && message.messageSeq === this.initLocateMessageSeq) {
|
||||||
newMessages.push(new MessageWrap(this.getHistorySplit()))
|
newMessages.push(new MessageWrap(this.getHistorySplit()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
126
packages/tsdaodaobase/src/Components/GlobalSearch/index.tsx
Normal file
126
packages/tsdaodaobase/src/Components/GlobalSearch/index.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import React from "react";
|
||||||
|
import { Input } from '@douyinfe/semi-ui';
|
||||||
|
import { IconSearch } from '@douyinfe/semi-icons';
|
||||||
|
import { Tabs } from '@douyinfe/semi-ui';
|
||||||
|
import Provider from "../../Service/Provider";
|
||||||
|
import GlobalSearchVM from "./vm";
|
||||||
|
import TabAll from "./tab-all";
|
||||||
|
import TabContacts from "./tab-contacts";
|
||||||
|
import TabGroup from "./tab-group";
|
||||||
|
import TabFile from "./tab-file";
|
||||||
|
import { Channel } from "wukongimjssdk";
|
||||||
|
|
||||||
|
interface GlobalSearchProps {
|
||||||
|
channel?: Channel; // 查询指定频道的聊天记录
|
||||||
|
// item点击事件,传递item和type,type为contacts、group、message,file
|
||||||
|
onClick?: (item: any, type: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GlobalSearch extends Component<GlobalSearchProps> {
|
||||||
|
vm!: GlobalSearchVM
|
||||||
|
|
||||||
|
|
||||||
|
tabPanel(key: string) {
|
||||||
|
|
||||||
|
// message
|
||||||
|
if (key === 'all') {
|
||||||
|
return <TabAll
|
||||||
|
searchResult={this.vm.searchResult}
|
||||||
|
keyword={this.vm.keyword}
|
||||||
|
loadMore={() => {
|
||||||
|
this.vm.loadMore()
|
||||||
|
}}
|
||||||
|
onClick={(item, type) => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, type)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
// contacts
|
||||||
|
if (key === 'contacts') {
|
||||||
|
return <TabContacts
|
||||||
|
friends={this.vm.searchResult?.friends}
|
||||||
|
keyword={this.vm.keyword}
|
||||||
|
onClick={(item) => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "contacts")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
></TabContacts>
|
||||||
|
}
|
||||||
|
|
||||||
|
// groups
|
||||||
|
if (key === 'groups') {
|
||||||
|
return <TabGroup
|
||||||
|
groups={this.vm.searchResult?.groups}
|
||||||
|
keyword={this.vm.keyword}
|
||||||
|
onClick={(item) => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "group")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
></TabGroup>
|
||||||
|
}
|
||||||
|
|
||||||
|
// files
|
||||||
|
if (key === 'files') {
|
||||||
|
return <TabFile
|
||||||
|
files={this.vm.searchResult?.messages}
|
||||||
|
keyword={this.vm.keyword}
|
||||||
|
loadMore={() => {
|
||||||
|
this.vm.loadMore()
|
||||||
|
}}
|
||||||
|
onClick={(item) => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "file")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
const { channel } = this.props;
|
||||||
|
return <Provider
|
||||||
|
create={() => {
|
||||||
|
this.vm = new GlobalSearchVM()
|
||||||
|
this.vm.channel = channel
|
||||||
|
return this.vm
|
||||||
|
}}
|
||||||
|
render={(vm: GlobalSearchVM) => {
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
{
|
||||||
|
vm.searchInChannel ? <div style={{ fontSize: "14px", fontWeight: "500",width:"100%",textAlign:"center",marginBottom: "10px" }}>{vm.searchTitle}</div> : undefined
|
||||||
|
}
|
||||||
|
<Input
|
||||||
|
prefix={<IconSearch />}
|
||||||
|
showClear
|
||||||
|
style={{ height: "40px" }}
|
||||||
|
onCompositionStart={() => { vm.isComposing = true; }}
|
||||||
|
onCompositionEnd={(e: any) => {
|
||||||
|
vm.isComposing = false;
|
||||||
|
vm.handleInputChange(e.target.value);
|
||||||
|
}}
|
||||||
|
onChange={(value) => {
|
||||||
|
vm.handleInputChange(value);
|
||||||
|
}}></Input>
|
||||||
|
<div className="wk-search-tabs">
|
||||||
|
<Tabs
|
||||||
|
tabList={vm.tabList}
|
||||||
|
onChange={key => {
|
||||||
|
vm.onTabClick(key);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.tabPanel(vm.selectedTabKey)}
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}}>
|
||||||
|
|
||||||
|
</Provider>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
.wk-item-contacts {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-contacts:hover {
|
||||||
|
background-color: #f0f0f0; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-contacts:hover {
|
||||||
|
background-color: #333333; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-contacts-name {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: var(--wk-text-item);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-contacts-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background-color: transparent; /* 移除默认背景色 */
|
||||||
|
color: var(--wk-color-theme); /* 设置文本颜色为红色,可以根据需要更改 */
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import WKAvatar from "../WKAvatar";
|
||||||
|
import "./item-contacts.css"
|
||||||
|
interface ItemContactsProps {
|
||||||
|
avatar: string;
|
||||||
|
name: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ItemContacts extends Component<ItemContactsProps> {
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div className="wk-item-contacts" onClick={()=>{
|
||||||
|
if(this.props.onClick){
|
||||||
|
this.props.onClick()
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<WKAvatar src={this.props.avatar} style={{width:"40px",height:"40px"}}></WKAvatar>
|
||||||
|
<div className="wk-item-contacts-name" dangerouslySetInnerHTML={{ __html: this.props.name }}></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.wk-item-file-icon {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-file {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
grid-template-rows: auto auto; /* 两行 */
|
||||||
|
gap: 0px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-file:hover {
|
||||||
|
background-color: #f0f0f0; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-file:hover {
|
||||||
|
background-color: #333333; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.wk-item-file-icon {
|
||||||
|
grid-column: 1 / 2; /* 第一列 */
|
||||||
|
grid-row: 1 / 3; /* 第一行 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-file-name {
|
||||||
|
grid-column: 2 / 3; /* 第二列 */
|
||||||
|
grid-row: 1 / 2; /* 第一行 */
|
||||||
|
margin-left: 15px;
|
||||||
|
color: var(--wk-text-item);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-file-desc {
|
||||||
|
grid-row: 2 / 3; /* 第二行 */
|
||||||
|
grid-column: 2 / 3; /* 第二列 */
|
||||||
|
display: flex;
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-file-line {
|
||||||
|
width: 1px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #666;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import "./item-file.css"
|
||||||
|
import FileHelper from "../../Utils/filehelper";
|
||||||
|
import { getTimeStringAutoShort2 } from "../../Utils/time";
|
||||||
|
interface ItemFileProps {
|
||||||
|
message: any;
|
||||||
|
sender?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ItemFile extends Component<ItemFileProps> {
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
const file = this.props.message.payload;
|
||||||
|
const channel = this.props.message.channel;
|
||||||
|
const realName = file.name?.replaceAll("<mark>", "").replaceAll("</mark>", "");
|
||||||
|
const fileIconInfo = FileHelper.getFileIconInfo(realName);
|
||||||
|
return <div className="wk-item-file" onClick={() => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick()
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<div className="wk-item-file-icon" style={{ backgroundColor: fileIconInfo?.color, borderRadius: "4px" }}>
|
||||||
|
<img alt="" src={fileIconInfo?.icon} style={{ width: '32px', height: '32px' }} />
|
||||||
|
</div>
|
||||||
|
<div className="wk-item-file-name" dangerouslySetInnerHTML={{ __html: file.name }}></div>
|
||||||
|
<div className="wk-item-file-desc">
|
||||||
|
<div className="wk-item-file-sender">{this.props.sender}</div><div className="wk-item-file-line" />
|
||||||
|
<div className="wk-item-file-recv">{channel.channel_name}</div><div className="wk-item-file-line" />
|
||||||
|
<div className="wk-item-file-size">{FileHelper.getFileSizeFormat(file.size || 0)}</div><div className="wk-item-file-line" />
|
||||||
|
<div className="wk-item-file-time">{getTimeStringAutoShort2(this.props.message.timestamp * 1000, true)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
.wk-item-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-group:hover {
|
||||||
|
background-color: #333333; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-group:hover {
|
||||||
|
background-color: #f0f0f0; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-group-name {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-group-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import WKAvatar from "../WKAvatar";
|
||||||
|
import "./item-group.css"
|
||||||
|
interface ItemGroupProps {
|
||||||
|
avatar: string;
|
||||||
|
name: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ItemGroup extends Component<ItemGroupProps> {
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div className="wk-item-group" onClick={()=>{
|
||||||
|
if(this.props.onClick){
|
||||||
|
this.props.onClick()
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<WKAvatar src={this.props.avatar} style={{width:"40px",height:"40px"}}></WKAvatar>
|
||||||
|
<div className="wk-item-group-name" dangerouslySetInnerHTML={{ __html: this.props.name }}></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
.wk-item-message {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-message:hover {
|
||||||
|
background-color: #f0f0f0; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
body[theme-mode=dark] .wk-item-message:hover {
|
||||||
|
background-color: #333333; /* Change this color to your desired hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-message-content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr; /* 两列,左边自适应,右边自动宽度 */
|
||||||
|
grid-template-rows: auto auto; /* 两行 */
|
||||||
|
gap: 0px;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 420px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-item-message-name {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
grid-column: 1 / 2; /* 第一列 */
|
||||||
|
grid-row: 1 / 2; /* 第一行 */
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme-mode=dark] .wk-item-message-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.wk-item-message-digest {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #999;
|
||||||
|
white-space: nowrap; /* 不换行 */
|
||||||
|
overflow: hidden; /* 超出部分隐藏 */
|
||||||
|
text-overflow: ellipsis; /* 超出部分以省略号显示 */
|
||||||
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background-color: transparent; /* 移除默认背景色 */
|
||||||
|
color: var(--wk-color-theme); /* 设置文本颜色为红色,可以根据需要更改 */
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import WKAvatar from "../WKAvatar";
|
||||||
|
import "./item-message.css"
|
||||||
|
interface ItemMessageProps {
|
||||||
|
avatar: string; // 会话头像
|
||||||
|
name: string; // 会话名字
|
||||||
|
digest: string; // 消息摘要
|
||||||
|
sender?: string; // 发送者
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ItemMessage extends Component<ItemMessageProps> {
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
|
||||||
|
let digest = this.props?.digest
|
||||||
|
if(this.props.sender && this.props.sender !== ""){
|
||||||
|
digest = this.props.sender + ": " + digest
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="wk-item-message" onClick={() => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick()
|
||||||
|
}
|
||||||
|
} }>
|
||||||
|
<WKAvatar src={this.props.avatar} style={{ width: "40px", height: "40px" }}></WKAvatar>
|
||||||
|
<div className="wk-item-message-content">
|
||||||
|
<div className="wk-item-message-name">{this.props.name}</div>
|
||||||
|
{/* <div className="wk-item-message-time">{this.props.time}</div> */}
|
||||||
|
<div className="wk-item-message-digest" dangerouslySetInnerHTML={{ __html: digest}}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
interface SectionProps {
|
||||||
|
title: string;
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Section extends Component<SectionProps> {
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div>
|
||||||
|
<div style={{color:"#666",marginLeft:"10px",marginTop:"10px"}}>{this.props.title}</div>
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.wk-tab-all {
|
||||||
|
width: 100%;
|
||||||
|
height: 50vh;
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
131
packages/tsdaodaobase/src/Components/GlobalSearch/tab-all.tsx
Normal file
131
packages/tsdaodaobase/src/Components/GlobalSearch/tab-all.tsx
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import Section from "./section";
|
||||||
|
import ItemContacts from "./item-contacts";
|
||||||
|
import ItemGroup from "./item-group";
|
||||||
|
import ItemMessage from "./item-message";
|
||||||
|
import WKApp from "../../App";
|
||||||
|
import "./tab-all.css"
|
||||||
|
import WKSDK, { Channel, ChannelTypePerson, MessageContentType } from "wukongimjssdk";
|
||||||
|
import { MessageContentTypeConst } from "../../Service/Const";
|
||||||
|
|
||||||
|
|
||||||
|
interface TabAllProps {
|
||||||
|
keyword?: string;
|
||||||
|
searchResult?: any;
|
||||||
|
loadMore?: () => void; // 添加加载更多的回调函数
|
||||||
|
// item点击事件,传递item和type,type为contacts、group、message
|
||||||
|
onClick?: (item: any, type: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TabAll extends Component<TabAllProps> {
|
||||||
|
|
||||||
|
handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = event.currentTarget;
|
||||||
|
if (scrollTop + clientHeight >= scrollHeight) {
|
||||||
|
if (this.props.loadMore) {
|
||||||
|
this.props.loadMore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
|
||||||
|
let existFriends = this.props.searchResult?.friends.length > 0
|
||||||
|
let existGroups = this.props.searchResult?.groups.length > 0
|
||||||
|
let existMessages = this.props.searchResult?.messages.length > 0
|
||||||
|
|
||||||
|
return <div className="wk-tab-all" onScroll={this.handleScroll}>
|
||||||
|
|
||||||
|
{
|
||||||
|
existFriends ? (<Section title="联系人">
|
||||||
|
{
|
||||||
|
this.props.searchResult.friends.map((item: any) => {
|
||||||
|
return <ItemContacts
|
||||||
|
key={item.channel_id}
|
||||||
|
name={item.channel_name}
|
||||||
|
avatar={WKApp.shared.avatarUser(item.channel_id)}
|
||||||
|
onClick={() => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "contacts")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Section>) : null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
existGroups ? (
|
||||||
|
<Section title="群组">
|
||||||
|
{
|
||||||
|
this.props.searchResult?.groups.map((item: any) => {
|
||||||
|
if (this.props.keyword && item.channel_name.indexOf(this.props.keyword) !== -1) {
|
||||||
|
item.channel_name = item.channel_name.replace(this.props.keyword, `<mark>${this.props.keyword}</mark>`)
|
||||||
|
}
|
||||||
|
return <ItemGroup
|
||||||
|
key={item.channel_id}
|
||||||
|
name={item.channel_name}
|
||||||
|
avatar={WKApp.shared.avatarGroup(item.channel_id)}
|
||||||
|
onClick={() => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "group")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Section>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
existMessages ? (
|
||||||
|
<Section title="消息">
|
||||||
|
{
|
||||||
|
this.props.searchResult?.messages.map((item: any) => {
|
||||||
|
let digest = "[未知消息]"
|
||||||
|
if(item.content) {
|
||||||
|
digest = item.content.conversationDigest
|
||||||
|
}else {
|
||||||
|
if (item.payload.type === MessageContentType.text) {
|
||||||
|
digest = item.payload.content
|
||||||
|
} else if (item.payload.type === MessageContentTypeConst.file) {
|
||||||
|
digest = `[${item.payload.name}]`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let sender;
|
||||||
|
if (item.channel.channel_type !== ChannelTypePerson && item.from_uid && item.from_uid !== "") {
|
||||||
|
const senderChannel = new Channel(item.from_uid, ChannelTypePerson)
|
||||||
|
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(senderChannel)
|
||||||
|
if (channelInfo) {
|
||||||
|
sender = channelInfo.title
|
||||||
|
} else {
|
||||||
|
WKSDK.shared().channelManager.fetchChannelInfo(senderChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ItemMessage
|
||||||
|
key={item.message_idstr}
|
||||||
|
sender={sender}
|
||||||
|
digest={digest}
|
||||||
|
name={item.channel.channel_name}
|
||||||
|
avatar={WKApp.shared.avatarChannel(new Channel(item.channel.channel_id, item.channel.channel_type))}
|
||||||
|
onClick={() => {
|
||||||
|
if (this.props.onClick) {
|
||||||
|
this.props.onClick(item, "message")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Section>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
.wk-tab-contacts {
|
||||||
|
width: 100%;
|
||||||
|
height: 50vh;
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import ItemContacts from "./item-contacts";
|
||||||
|
import WKApp from "../../App";
|
||||||
|
import "./tab-contacts.css"
|
||||||
|
|
||||||
|
interface TabContactsProps {
|
||||||
|
keyword?: string;
|
||||||
|
friends?: any[];
|
||||||
|
onClick?: (item: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TabContacts extends Component<TabContactsProps> {
|
||||||
|
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div className="wk-tab-contacts">
|
||||||
|
{
|
||||||
|
this.props.friends?.map((item: any) => {
|
||||||
|
if (this.props.keyword && item.channel_name.indexOf(this.props.keyword) !== -1) {
|
||||||
|
item.channel_name = item.channel_name.replace(this.props.keyword, `<mark>${this.props.keyword}</mark>`)
|
||||||
|
}
|
||||||
|
return <ItemContacts
|
||||||
|
key={item.channel_id}
|
||||||
|
name={item.channel_name}
|
||||||
|
avatar={WKApp.shared.avatarUser(item.channel_id)}
|
||||||
|
onClick={()=>{
|
||||||
|
if(this.props.onClick) {
|
||||||
|
this.props.onClick(item)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
.wk-tab-file {
|
||||||
|
width: 100%;
|
||||||
|
height: 50vh;
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import ItemFile from "./item-file";
|
||||||
|
import WKApp from "../../App";
|
||||||
|
import "./tab-file.css"
|
||||||
|
import WKSDK, { Channel, ChannelTypePerson } from "wukongimjssdk";
|
||||||
|
|
||||||
|
interface TabFileProps {
|
||||||
|
keyword?: string;
|
||||||
|
files?: any[];
|
||||||
|
loadMore?: () => void; // 添加加载更多的回调函数
|
||||||
|
onClick?: (item: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TabFile extends Component<TabFileProps> {
|
||||||
|
|
||||||
|
handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = event.currentTarget;
|
||||||
|
if (scrollTop + clientHeight >= scrollHeight) {
|
||||||
|
if (this.props.loadMore) {
|
||||||
|
this.props.loadMore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div className="wk-tab-file" onScroll={this.handleScroll}>
|
||||||
|
{
|
||||||
|
this.props.files?.map((item: any) => {
|
||||||
|
let sender;
|
||||||
|
const senderChannel = new Channel(item.from_uid, ChannelTypePerson)
|
||||||
|
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(senderChannel)
|
||||||
|
if (channelInfo) {
|
||||||
|
sender = channelInfo.title
|
||||||
|
} else {
|
||||||
|
WKSDK.shared().channelManager.fetchChannelInfo(senderChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ItemFile
|
||||||
|
key={item.message_idstr}
|
||||||
|
sender={sender}
|
||||||
|
message={item}
|
||||||
|
onClick={()=>{
|
||||||
|
if(this.props.onClick) {
|
||||||
|
this.props.onClick(item)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.wk-tab-group {
|
||||||
|
width: 100%;
|
||||||
|
height: 50vh;
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import ItemGroup from "./item-group";
|
||||||
|
import WKApp from "../../App";
|
||||||
|
import "./tab-group.css"
|
||||||
|
|
||||||
|
interface TabGroupProps {
|
||||||
|
keyword?: string;
|
||||||
|
groups?: any[];
|
||||||
|
onClick?: (item: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TabGroup extends Component<TabGroupProps> {
|
||||||
|
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
return <div className="wk-tab-group">
|
||||||
|
{
|
||||||
|
this.props.groups?.map((item: any) => {
|
||||||
|
if (this.props.keyword && item.channel_name.indexOf(this.props.keyword) !== -1) {
|
||||||
|
item.channel_name = item.channel_name.replace(this.props.keyword, `<mark>${this.props.keyword}</mark>`)
|
||||||
|
}
|
||||||
|
return <ItemGroup
|
||||||
|
key={item.channel_id}
|
||||||
|
name={item.channel_name}
|
||||||
|
avatar={WKApp.shared.avatarGroup(item.channel_id)}
|
||||||
|
onClick={()=>{
|
||||||
|
if(this.props.onClick) {
|
||||||
|
this.props.onClick(item)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
219
packages/tsdaodaobase/src/Components/GlobalSearch/vm.ts
Normal file
219
packages/tsdaodaobase/src/Components/GlobalSearch/vm.ts
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
import WKSDK, { Channel, ChannelInfo, ChannelInfoListener, ChannelTypePerson, MessageContentManager, SystemContent } from "wukongimjssdk";
|
||||||
|
import APIClient from "../../Service/APIClient";
|
||||||
|
import { MessageContentTypeConst } from "../../Service/Const";
|
||||||
|
import { ProviderListener } from "../../Service/Provider";
|
||||||
|
|
||||||
|
export default class GlobalSearchVM extends ProviderListener {
|
||||||
|
// 选中的tab组件
|
||||||
|
private _selectedTabKey = "all";
|
||||||
|
|
||||||
|
public page = 1 // 当前页码
|
||||||
|
public limit = 20 // 每页条数
|
||||||
|
public keyword = "" // 搜索关键字
|
||||||
|
public searchResult: any
|
||||||
|
public isComposing: boolean = false; // 是否正在输入(防止中文输入法干扰)
|
||||||
|
public loadMoreing = false; // 是否正在加载更多中
|
||||||
|
public loadFinish = false; // 是否加载完成
|
||||||
|
public contentTypes = new Array<number>() // 内容类型
|
||||||
|
private channelInfoListener!: ChannelInfoListener;
|
||||||
|
public channel?: Channel // 查询指定频道的消息
|
||||||
|
// tab数据列表
|
||||||
|
public get tabList() {
|
||||||
|
if (this.searchInChannel) {
|
||||||
|
return [
|
||||||
|
{ tab: '聊天', itemKey: 'all' },
|
||||||
|
{ tab: '文件', itemKey: 'files' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{ tab: '聊天', itemKey: 'all' },
|
||||||
|
{ tab: '联系人', itemKey: 'contacts' },
|
||||||
|
{ tab: '群组', itemKey: 'groups' },
|
||||||
|
{ tab: '文件', itemKey: 'files' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get selectedTabKey() {
|
||||||
|
return this._selectedTabKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set selectedTabKey(value: string) {
|
||||||
|
this._selectedTabKey = value;
|
||||||
|
this.notifyListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否在频道内搜索
|
||||||
|
public get searchInChannel(): boolean {
|
||||||
|
return this.channel !== undefined
|
||||||
|
}
|
||||||
|
// 搜索标题
|
||||||
|
public get searchTitle() {
|
||||||
|
if (this.searchInChannel) {
|
||||||
|
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(this.channel!)
|
||||||
|
if(channelInfo) {
|
||||||
|
return `与“${channelInfo.title}”的聊天记录`
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// tab选中事件
|
||||||
|
public onTabClick(key: string) {
|
||||||
|
if (key === "files") {
|
||||||
|
this.contentTypes = [MessageContentTypeConst.file]
|
||||||
|
this.initLoad()
|
||||||
|
this.requestSearch()
|
||||||
|
} else {
|
||||||
|
this.contentTypes = []
|
||||||
|
this.initLoad()
|
||||||
|
this.requestSearch()
|
||||||
|
}
|
||||||
|
this.selectedTabKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
didMount(): void {
|
||||||
|
this.requestSearch()
|
||||||
|
|
||||||
|
this.channelInfoListener = (channelInfo: ChannelInfo) => {
|
||||||
|
if (channelInfo.channel.channelType !== ChannelTypePerson) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.searchResult?.messages && this.searchResult.messages.length > 0) {
|
||||||
|
this.searchResult.messages.forEach((item: any) => {
|
||||||
|
if (item.from_uid === channelInfo.channel.channelID) {
|
||||||
|
this.notifyListener()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WKSDK.shared().channelManager.addListener(this.channelInfoListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
didUnMount(): void {
|
||||||
|
WKSDK.shared().channelManager.removeListener(this.channelInfoListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入框输入事件
|
||||||
|
public handleInputChange = (value: string) => {
|
||||||
|
if (!this.isComposing) {
|
||||||
|
this.keyword = value;
|
||||||
|
console.log(this.keyword);
|
||||||
|
this.initLoad()
|
||||||
|
this.requestSearch();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public initLoad() {
|
||||||
|
this.page = 1
|
||||||
|
this.loadFinish = false
|
||||||
|
this.loadMoreing = false
|
||||||
|
this.searchResult = null
|
||||||
|
this.notifyListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求搜索
|
||||||
|
public requestSearch() {
|
||||||
|
|
||||||
|
const param: any = {
|
||||||
|
keyword: this.keyword || "",
|
||||||
|
page: this.page,
|
||||||
|
limit: this.limit,
|
||||||
|
content_type: this.contentTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.channel) {
|
||||||
|
param.channel_id = this.channel.channelID
|
||||||
|
param.channel_type = this.channel.channelType
|
||||||
|
param.only_message = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("requestSearch", param);
|
||||||
|
|
||||||
|
|
||||||
|
APIClient.shared.post("/search/global", param).then(res => {
|
||||||
|
|
||||||
|
if (res.messages.length < this.limit) {
|
||||||
|
this.loadFinish = true
|
||||||
|
}
|
||||||
|
if (this.loadMoreing) {
|
||||||
|
if (this.searchResult) {
|
||||||
|
this.searchResult.messages = this.searchResult.messages?.concat(res.messages)
|
||||||
|
} else {
|
||||||
|
this.searchResult = res
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.searchResult = res
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换备注如果有备注的话
|
||||||
|
this.searchResult.friends?.forEach((v: any) => {
|
||||||
|
if (v.channel_remark && v.channel_remark !== "") {
|
||||||
|
v.channel_name = v.channel_remark
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.searchResult.groups?.forEach((v: any) => {
|
||||||
|
if (v.channel_remark && v.channel_remark !== "") {
|
||||||
|
v.channel_name = v.channel_remark
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.searchResult.messages?.forEach((v: any) => {
|
||||||
|
if (v.channel.channel_remark && v.channel.channel_remark !== "") {
|
||||||
|
v.channel.channel_name = v.channel.channel_remark
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析消息内容
|
||||||
|
if(v.payload) {
|
||||||
|
const contentType = v.payload.type
|
||||||
|
|
||||||
|
const messageContent = MessageContentManager.shared().getMessageContent(contentType)
|
||||||
|
if (messageContent) {
|
||||||
|
messageContent.decode(this.jsonToUint8Array(v.payload))
|
||||||
|
}
|
||||||
|
|
||||||
|
if(messageContent instanceof SystemContent) {
|
||||||
|
messageContent.content["content"] = "[系统消息]"
|
||||||
|
}
|
||||||
|
|
||||||
|
v.content = messageContent
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}).finally(() => {
|
||||||
|
this.loadMoreing = false
|
||||||
|
this.notifyListener()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonToUint8Array(json: any): Uint8Array {
|
||||||
|
// 将 JSON 对象转换为字符串
|
||||||
|
const jsonString = JSON.stringify(json);
|
||||||
|
|
||||||
|
return this.stringToUint8Array(jsonString)
|
||||||
|
}
|
||||||
|
|
||||||
|
stringToUint8Array(str: string): Uint8Array {
|
||||||
|
const newStr = unescape(encodeURIComponent(str))
|
||||||
|
const arr = new Array<number>();
|
||||||
|
for (let i = 0, j = newStr.length; i < j; ++i) {
|
||||||
|
arr.push(newStr.charCodeAt(i));
|
||||||
|
}
|
||||||
|
const tmpUint8Array = new Uint8Array(arr);
|
||||||
|
return tmpUint8Array
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多消息
|
||||||
|
loadMore() {
|
||||||
|
if (this.loadMoreing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loadMoreing = true
|
||||||
|
this.page++
|
||||||
|
this.requestSearch()
|
||||||
|
console.log("加载更多");
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ export class GlobalModalOptions {
|
|||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
closable?: boolean;
|
closable?: boolean;
|
||||||
|
onCancel?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WKBaseProps {
|
export interface WKBaseProps {
|
||||||
@ -248,6 +249,7 @@ export default class WKBase
|
|||||||
visible={this.state.showGlobalModal}
|
visible={this.state.showGlobalModal}
|
||||||
width={this.state.globalModalOptions?.width}
|
width={this.state.globalModalOptions?.width}
|
||||||
footer={this.state.globalModalOptions?.footer}
|
footer={this.state.globalModalOptions?.footer}
|
||||||
|
onCancel={this.state.globalModalOptions?.onCancel}
|
||||||
>
|
>
|
||||||
{this.state.globalModalOptions?.body}
|
{this.state.globalModalOptions?.body}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -11,6 +11,11 @@ export class MessageContextMenus {
|
|||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ShowConversationOptions {
|
||||||
|
// 聊天消息定位的messageSeq
|
||||||
|
initLocateMessageSeq?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class EndpointCommon {
|
export class EndpointCommon {
|
||||||
private _onLogins: VoidFunction[] = []; // 登录成功
|
private _onLogins: VoidFunction[] = []; // 登录成功
|
||||||
|
|
||||||
@ -32,10 +37,11 @@ export class EndpointCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showConversation(channel: Channel) {
|
showConversation(channel: Channel, opts?: ShowConversationOptions) {
|
||||||
WKApp.shared.openChannel = channel;
|
WKApp.shared.openChannel = channel;
|
||||||
EndpointManager.shared.invoke(EndpointID.showConversation, {
|
EndpointManager.shared.invoke(EndpointID.showConversation, {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
|
opts: opts,
|
||||||
});
|
});
|
||||||
WKApp.shared.notifyListener();
|
WKApp.shared.notifyListener();
|
||||||
}
|
}
|
||||||
@ -65,21 +71,38 @@ export class EndpointCommon {
|
|||||||
EndpointID.showConversation,
|
EndpointID.showConversation,
|
||||||
(param: any) => {
|
(param: any) => {
|
||||||
const channel = param.channel as Channel;
|
const channel = param.channel as Channel;
|
||||||
const conversation =
|
let opts: ShowConversationOptions = {}
|
||||||
WKSDK.shared().conversationManager.findConversation(channel);
|
if (param.opts) {
|
||||||
let initLocateMessageSeq = 0;
|
opts = param.opts
|
||||||
if (
|
|
||||||
conversation &&
|
|
||||||
conversation.lastMessage &&
|
|
||||||
conversation.unread > 0 &&
|
|
||||||
conversation.lastMessage.messageSeq > conversation.unread
|
|
||||||
) {
|
|
||||||
initLocateMessageSeq =
|
|
||||||
conversation.lastMessage.messageSeq - conversation.unread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let initLocateMessageSeq = 0;
|
||||||
|
if (opts && opts.initLocateMessageSeq && opts.initLocateMessageSeq > 0) {
|
||||||
|
initLocateMessageSeq = opts.initLocateMessageSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initLocateMessageSeq <= 0) {
|
||||||
|
const conversation =
|
||||||
|
WKSDK.shared().conversationManager.findConversation(channel);
|
||||||
|
if (
|
||||||
|
conversation &&
|
||||||
|
conversation.lastMessage &&
|
||||||
|
conversation.unread > 0 &&
|
||||||
|
conversation.lastMessage.messageSeq > conversation.unread
|
||||||
|
) {
|
||||||
|
initLocateMessageSeq =
|
||||||
|
conversation.lastMessage.messageSeq - conversation.unread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = channel.getChannelKey()
|
||||||
|
if (initLocateMessageSeq > 0) {
|
||||||
|
key = `${key}-${initLocateMessageSeq}`
|
||||||
|
}
|
||||||
|
|
||||||
WKApp.routeRight.replaceToRoot(
|
WKApp.routeRight.replaceToRoot(
|
||||||
<ChatContentPage
|
<ChatContentPage
|
||||||
key={channel.getChannelKey()}
|
key={key}
|
||||||
channel={channel}
|
channel={channel}
|
||||||
initLocateMessageSeq={initLocateMessageSeq}
|
initLocateMessageSeq={initLocateMessageSeq}
|
||||||
></ChatContentPage>
|
></ChatContentPage>
|
||||||
|
@ -3,9 +3,9 @@ import { Conversation } from "../../Components/Conversation";
|
|||||||
import ConversationList from "../../Components/ConversationList";
|
import ConversationList from "../../Components/ConversationList";
|
||||||
import Provider from "../../Service/Provider";
|
import Provider from "../../Service/Provider";
|
||||||
|
|
||||||
import { Spin, Button, Popover } from "@douyinfe/semi-ui";
|
import { Spin, Modal, Popover } from "@douyinfe/semi-ui";
|
||||||
import { IconPlus } from "@douyinfe/semi-icons";
|
import { IconPlus, IconSearch } from "@douyinfe/semi-icons";
|
||||||
import { ChatVM } from "./vm";
|
import { ChatVM, handleGlobalSearchClick } from "./vm";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { ConversationWrap } from "../../Service/Model";
|
import { ConversationWrap } from "../../Service/Model";
|
||||||
import WKApp, { ThemeMode } from "../../App";
|
import WKApp, { ThemeMode } from "../../App";
|
||||||
@ -15,11 +15,12 @@ import { Channel, ChannelInfo, WKSDK } from "wukongimjssdk";
|
|||||||
import { ChannelInfoListener } from "wukongimjssdk";
|
import { ChannelInfoListener } from "wukongimjssdk";
|
||||||
import { ChatMenus } from "../../App";
|
import { ChatMenus } from "../../App";
|
||||||
import ConversationContext from "../../Components/Conversation/context";
|
import ConversationContext from "../../Components/Conversation/context";
|
||||||
import { EndpointID } from "../../Service/Const";
|
import GlobalSearch from "../../Components/GlobalSearch";
|
||||||
|
import { ShowConversationOptions } from "../../EndpointCommon";
|
||||||
|
|
||||||
export interface ChatContentPageProps {
|
export interface ChatContentPageProps {
|
||||||
channel: Channel;
|
channel: Channel;
|
||||||
initLocateMessageSeq?: number;
|
initLocateMessageSeq?: number; // 打开时定位到某条消息
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatContentPageState {
|
export interface ChatContentPageState {
|
||||||
@ -180,7 +181,7 @@ export default class ChatPage extends Component<any> {
|
|||||||
|
|
||||||
componentWillUnmount() { }
|
componentWillUnmount() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render(): ReactNode {
|
render(): ReactNode {
|
||||||
return (
|
return (
|
||||||
@ -201,6 +202,14 @@ export default class ChatPage extends Component<any> {
|
|||||||
<div className="wk-chat-content-left">
|
<div className="wk-chat-content-left">
|
||||||
<div className="wk-chat-search">
|
<div className="wk-chat-search">
|
||||||
<div className="wk-chat-title">{vm.connectTitle}</div>
|
<div className="wk-chat-title">{vm.connectTitle}</div>
|
||||||
|
<div
|
||||||
|
style={{ marginRight: '20px', alignItems: 'center', display: 'flex', cursor: 'pointer' }}
|
||||||
|
onClick={() => {
|
||||||
|
vm.showGlobalSearch = true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconSearch size="large" />
|
||||||
|
</div>
|
||||||
<Popover
|
<Popover
|
||||||
onClickOutSide={() => {
|
onClickOutSide={() => {
|
||||||
vm.showAddPopover = false;
|
vm.showAddPopover = false;
|
||||||
@ -220,6 +229,7 @@ export default class ChatPage extends Component<any> {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="wk-chat-search-add"
|
className="wk-chat-search-add"
|
||||||
|
style={{ alignItems: 'center', display: 'flex' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
vm.showAddPopover = !vm.showAddPopover;
|
vm.showAddPopover = !vm.showAddPopover;
|
||||||
}}
|
}}
|
||||||
@ -253,6 +263,23 @@ export default class ChatPage extends Component<any> {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Modal
|
||||||
|
visible={vm.showGlobalSearch}
|
||||||
|
closeOnEsc={true}
|
||||||
|
onCancel={() => {
|
||||||
|
vm.showGlobalSearch = false
|
||||||
|
}}
|
||||||
|
footer={null}
|
||||||
|
width="80%"
|
||||||
|
>
|
||||||
|
<div style={{ marginTop: '30px' }}>
|
||||||
|
<GlobalSearch onClick={(item,type:string)=>{
|
||||||
|
handleGlobalSearchClick(item,type,()=>{
|
||||||
|
vm.showGlobalSearch = false
|
||||||
|
})
|
||||||
|
}}/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -9,6 +9,7 @@ import { ProviderListener } from "../../Service/Provider";
|
|||||||
import { animateScroll, scroller } from 'react-scroll';
|
import { animateScroll, scroller } from 'react-scroll';
|
||||||
import { ProhibitwordsService } from "../../Service/ProhibitwordsService";
|
import { ProhibitwordsService } from "../../Service/ProhibitwordsService";
|
||||||
import { EndpointID } from "../../Service/Const";
|
import { EndpointID } from "../../Service/Const";
|
||||||
|
import { ShowConversationOptions } from "../../EndpointCommon";
|
||||||
|
|
||||||
export class ChatVM extends ProviderListener {
|
export class ChatVM extends ProviderListener {
|
||||||
conversations: ConversationWrap[] = new Array()
|
conversations: ConversationWrap[] = new Array()
|
||||||
@ -22,6 +23,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
private channelListener!: ChannelInfoListener
|
private channelListener!: ChannelInfoListener
|
||||||
private messageDeleteListener!: MessageDeleteListener
|
private messageDeleteListener!: MessageDeleteListener
|
||||||
private conversationListID = "wk-conversationlist"
|
private conversationListID = "wk-conversationlist"
|
||||||
|
private _showGlobalSearch = false // 是否显示全局搜索
|
||||||
|
|
||||||
|
|
||||||
set showAddPopover(v: boolean) {
|
set showAddPopover(v: boolean) {
|
||||||
@ -33,6 +35,15 @@ export class ChatVM extends ProviderListener {
|
|||||||
return this._showAddPopover
|
return this._showAddPopover
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set showGlobalSearch(v: boolean) {
|
||||||
|
this._showGlobalSearch = v
|
||||||
|
this.notifyListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
get showGlobalSearch() {
|
||||||
|
return this._showGlobalSearch
|
||||||
|
}
|
||||||
|
|
||||||
set selectedConversation(v: ConversationWrap | undefined) {
|
set selectedConversation(v: ConversationWrap | undefined) {
|
||||||
this._selectedConversation = v
|
this._selectedConversation = v
|
||||||
this.notifyListener()
|
this.notifyListener()
|
||||||
@ -64,7 +75,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
// 根据连接状态设置标题
|
// 根据连接状态设置标题
|
||||||
this.setConnectTitleWithConnectStatus(WKSDK.shared().connectManager.status)
|
this.setConnectTitleWithConnectStatus(WKSDK.shared().connectManager.status)
|
||||||
|
|
||||||
if(WKSDK.shared().connectManager.status == ConnectStatus.Connected){ // 如果已经连接则直接加载
|
if (WKSDK.shared().connectManager.status == ConnectStatus.Connected) { // 如果已经连接则直接加载
|
||||||
this.reloadRequestConversationList()
|
this.reloadRequestConversationList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +98,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
}
|
}
|
||||||
if (action === ConversationAction.add) {
|
if (action === ConversationAction.add) {
|
||||||
console.log("ConversationAction-----add")
|
console.log("ConversationAction-----add")
|
||||||
if(conversation.lastMessage?.content && conversation.lastMessage?.contentType === MessageContentType.text) {
|
if (conversation.lastMessage?.content && conversation.lastMessage?.contentType === MessageContentType.text) {
|
||||||
conversation.lastMessage.content.text = ProhibitwordsService.shared.filter(conversation.lastMessage?.content.text)
|
conversation.lastMessage.content.text = ProhibitwordsService.shared.filter(conversation.lastMessage?.content.text)
|
||||||
}
|
}
|
||||||
this.conversations = [new ConversationWrap(conversation), ...this.conversations]
|
this.conversations = [new ConversationWrap(conversation), ...this.conversations]
|
||||||
@ -97,7 +108,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
const existConversation = this.findConversation(conversation.channel)
|
const existConversation = this.findConversation(conversation.channel)
|
||||||
if (existConversation) {
|
if (existConversation) {
|
||||||
existConversation.conversation = conversation
|
existConversation.conversation = conversation
|
||||||
if(existConversation.lastMessage?.content && existConversation.lastMessage?.contentType === MessageContentType.text) {
|
if (existConversation.lastMessage?.content && existConversation.lastMessage?.contentType === MessageContentType.text) {
|
||||||
existConversation.lastMessage.content.text = ProhibitwordsService.shared.filter(existConversation.lastMessage?.content.text)
|
existConversation.lastMessage.content.text = ProhibitwordsService.shared.filter(existConversation.lastMessage?.content.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,11 +194,11 @@ export class ChatVM extends ProviderListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearMessages(channel: Channel) {
|
async clearMessages(channel: Channel) {
|
||||||
|
|
||||||
const conversationWrap = this.findConversation(channel)
|
const conversationWrap = this.findConversation(channel)
|
||||||
if (!conversationWrap) {
|
if (!conversationWrap) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await WKApp.conversationProvider.clearConversationMessages(conversationWrap.conversation)
|
await WKApp.conversationProvider.clearConversationMessages(conversationWrap.conversation)
|
||||||
conversationWrap.conversation.lastMessage = undefined
|
conversationWrap.conversation.lastMessage = undefined
|
||||||
@ -195,7 +206,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
WKApp.endpointManager.invoke(EndpointID.clearChannelMessages, channel)
|
WKApp.endpointManager.invoke(EndpointID.clearChannelMessages, channel)
|
||||||
this.sortConversations()
|
this.sortConversations()
|
||||||
this.notifyListener()
|
this.notifyListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setConnectTitleWithConnectStatus(connectStatus: ConnectStatus) {
|
setConnectTitleWithConnectStatus(connectStatus: ConnectStatus) {
|
||||||
@ -255,7 +266,7 @@ export class ChatVM extends ProviderListener {
|
|||||||
const conversations = await WKSDK.shared().conversationManager.sync({})
|
const conversations = await WKSDK.shared().conversationManager.sync({})
|
||||||
if (conversations && conversations.length > 0) {
|
if (conversations && conversations.length > 0) {
|
||||||
for (const conversation of conversations) {
|
for (const conversation of conversations) {
|
||||||
if(conversation.lastMessage?.content && conversation.lastMessage?.contentType == MessageContentType.text) {
|
if (conversation.lastMessage?.content && conversation.lastMessage?.contentType == MessageContentType.text) {
|
||||||
conversation.lastMessage.content.text = ProhibitwordsService.shared.filter(conversation.lastMessage.content.text)
|
conversation.lastMessage.content.text = ProhibitwordsService.shared.filter(conversation.lastMessage.content.text)
|
||||||
}
|
}
|
||||||
conversationWraps.push(new ConversationWrap(conversation))
|
conversationWraps.push(new ConversationWrap(conversation))
|
||||||
@ -268,4 +279,32 @@ export class ChatVM extends ProviderListener {
|
|||||||
|
|
||||||
WKApp.menus.refresh()
|
WKApp.menus.refresh()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理搜索内容点击事件
|
||||||
|
export function handleGlobalSearchClick(item: any, type: string,hideModal?:()=>void) {
|
||||||
|
if (type === "contacts" || type === "group") {
|
||||||
|
if(hideModal){
|
||||||
|
hideModal()
|
||||||
|
}
|
||||||
|
WKApp.endpoints.showConversation(new Channel(item.channel_id, item.channel_type))
|
||||||
|
} else if (type === "message") {
|
||||||
|
const opts = new ShowConversationOptions()
|
||||||
|
opts.initLocateMessageSeq = item.message_seq
|
||||||
|
if(hideModal){
|
||||||
|
hideModal()
|
||||||
|
}
|
||||||
|
WKApp.endpoints.showConversation(new Channel(item.channel.channel_id, item.channel.channel_type), opts)
|
||||||
|
} else if (type === "file") {
|
||||||
|
// 下载文件
|
||||||
|
const payload = item.payload
|
||||||
|
let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(payload.url || '')
|
||||||
|
if (downloadURL.indexOf("?") != -1) {
|
||||||
|
downloadURL += "&filename=" + payload.name
|
||||||
|
} else {
|
||||||
|
downloadURL += "?filename=" + payload.name
|
||||||
|
}
|
||||||
|
window.open(`${downloadURL}`, 'top');
|
||||||
|
}
|
||||||
}
|
}
|
@ -80,6 +80,8 @@ import { ScreenshotCell, ScreenshotContent } from "./Messages/Screenshot";
|
|||||||
import ImageToolbar from "./Components/ImageToolbar";
|
import ImageToolbar from "./Components/ImageToolbar";
|
||||||
import { ProhibitwordsService } from "./Service/ProhibitwordsService";
|
import { ProhibitwordsService } from "./Service/ProhibitwordsService";
|
||||||
import { SubscriberList } from "./Components/Subscribers/list";
|
import { SubscriberList } from "./Components/Subscribers/list";
|
||||||
|
import GlobalSearch from "./Components/GlobalSearch";
|
||||||
|
import { handleGlobalSearchClick } from "./Pages/Chat/vm";
|
||||||
|
|
||||||
export default class BaseModule implements IModule {
|
export default class BaseModule implements IModule {
|
||||||
messageTone?: Howl;
|
messageTone?: Howl;
|
||||||
@ -1211,6 +1213,40 @@ export default class BaseModule implements IModule {
|
|||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
|
|
||||||
|
WKApp.shared.channelSettingRegister(
|
||||||
|
"channel.base.settingMessageHistory",
|
||||||
|
(context) => {
|
||||||
|
const data = context.routeData() as ChannelSettingRouteData;
|
||||||
|
const channel = data.channel
|
||||||
|
|
||||||
|
return new Section({
|
||||||
|
rows: [
|
||||||
|
new Row({
|
||||||
|
cell: ListItem,
|
||||||
|
properties: {
|
||||||
|
title: "查找聊天内容",
|
||||||
|
onClick: () => {
|
||||||
|
WKApp.shared.baseContext.showGlobalModal({
|
||||||
|
body: <GlobalSearch channel={channel} onClick={(item: any, type: string) => {
|
||||||
|
handleGlobalSearchClick(item, type,()=>{
|
||||||
|
WKApp.shared.baseContext.hideGlobalModal()
|
||||||
|
})
|
||||||
|
}} />,
|
||||||
|
width: "80%",
|
||||||
|
height: "80%",
|
||||||
|
onCancel: () => {
|
||||||
|
WKApp.shared.baseContext.hideGlobalModal()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
1100
|
||||||
|
);
|
||||||
|
|
||||||
WKApp.shared.channelSettingRegister(
|
WKApp.shared.channelSettingRegister(
|
||||||
"channel.base.setting2",
|
"channel.base.setting2",
|
||||||
(context) => {
|
(context) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user