fix: fixed many bugs

This commit is contained in:
tangtaoit 2024-11-18 12:51:43 +08:00
parent 9de9346720
commit 2dfcce944d
15 changed files with 558 additions and 761 deletions

View File

@ -256,12 +256,6 @@ export default class WKApp extends ProviderListener {
WKApp.loginInfo.load(); // 加载登录信息 WKApp.loginInfo.load(); // 加载登录信息
const themeMode = StorageService.shared.getItem("theme-mode"); const themeMode = StorageService.shared.getItem("theme-mode");
const currentSystemThemeModeIsDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
if (!themeMode && currentSystemThemeModeIsDark) {
WKApp.config.themeMode = ThemeMode.dark;
}
if (themeMode === "1") { if (themeMode === "1") {
WKApp.config.themeMode = ThemeMode.dark; WKApp.config.themeMode = ThemeMode.dark;
} }
@ -380,16 +374,14 @@ export default class WKApp extends ProviderListener {
return this.avatarChannel(c); return this.avatarChannel(c);
} }
avatarOrg(orgID: string) { avatarOrg(orgID: string){
const baseURl = WKApp.apiClient.config.apiURL; const baseURl = WKApp.apiClient.config.apiURL;
return `${baseURl}organizations/${orgID}/logo`; return `${baseURl}organizations/${orgID}/logo`;
} }
// 我的用户头像发送改变 // 我的用户头像发送改变
myUserAvatarChange() { myUserAvatarChange() {
this.changeChannelAvatarTag( this.changeChannelAvatarTag(new Channel(WKApp.loginInfo.uid||"", ChannelTypePerson));
new Channel(WKApp.loginInfo.uid || "", ChannelTypePerson)
);
} }
changeChannelAvatarTag(channel: Channel) { changeChannelAvatarTag(channel: Channel) {
@ -397,17 +389,17 @@ export default class WKApp extends ProviderListener {
if (channel) { if (channel) {
myAvatarTag = `channelAvatarTag:${channel.channelType}${channel.channelID}`; myAvatarTag = `channelAvatarTag:${channel.channelType}${channel.channelID}`;
} }
console.log("changeChannelAvatarTag0----->"); console.log('changeChannelAvatarTag0----->')
const t = new Date().getTime(); const t = new Date().getTime();
WKApp.loginInfo.setStorageItem(myAvatarTag, `${t}`); WKApp.loginInfo.setStorageItem(myAvatarTag, `${t}`);
} }
getChannelAvatarTag(channel?: Channel) { getChannelAvatarTag(channel? :Channel) {
let myAvatarTag = "channelAvatarTag"; let myAvatarTag = "channelAvatarTag";
if (channel) { if (channel) {
myAvatarTag = `channelAvatarTag:${channel.channelType}${channel.channelID}`; myAvatarTag = `channelAvatarTag:${channel.channelType}${channel.channelID}`;
} }
const tag = WKApp.loginInfo.getStorageItem(myAvatarTag); const tag = WKApp.loginInfo.getStorageItem(myAvatarTag);
if (!tag) { if(!tag) {
return ""; return "";
} }
return tag; return tag;
@ -538,16 +530,13 @@ export default class WKApp extends ProviderListener {
return friendApplys; return friendApplys;
} }
public setFriendApplysUnreadCount() { public setFriendApplysUnreadCount(){
if (WKApp.loginInfo.isLogined()) { if(WKApp.loginInfo.isLogined()){
WKApp.apiClient.get(`/user/reddot/friendApply`).then((res) => { WKApp.apiClient.get(`/user/reddot/friendApply`).then(res=>{
WKApp.mittBus.emit("friend-applys-unread-count", res.count); WKApp.mittBus.emit('friend-applys-unread-count', res.count)
WKApp.loginInfo.setStorageItem( WKApp.loginInfo.setStorageItem(`${WKApp.loginInfo.uid}-friend-applys-unread-count`, res.count);
`${WKApp.loginInfo.uid}-friend-applys-unread-count`,
res.count
);
WKApp.menus.refresh(); WKApp.menus.refresh();
}); })
} }
} }
@ -562,9 +551,7 @@ export default class WKApp extends ProviderListener {
// } // }
// } // }
if (WKApp.loginInfo.isLogined()) { if (WKApp.loginInfo.isLogined()) {
const num = WKApp.loginInfo.getStorageItem( const num = WKApp.loginInfo.getStorageItem(`${WKApp.loginInfo.uid}-friend-applys-unread-count`)
`${WKApp.loginInfo.uid}-friend-applys-unread-count`
);
unreadCount = Number(num); unreadCount = Number(num);
} }
return unreadCount; return unreadCount;
@ -590,10 +577,7 @@ export default class WKApp extends ProviderListener {
// WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange); // WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange);
// } // }
if (WKApp.loginInfo.isLogined()) { if (WKApp.loginInfo.isLogined()) {
WKApp.loginInfo.setStorageItem( WKApp.loginInfo.setStorageItem(`${WKApp.loginInfo.uid}-friend-applys-unread-count`, '0')
`${WKApp.loginInfo.uid}-friend-applys-unread-count`,
"0"
);
} }
await WKApp.apiClient.delete(`/user/reddot/friendApply`); await WKApp.apiClient.delete(`/user/reddot/friendApply`);
} }

View File

@ -31,7 +31,7 @@ export class Conversation extends Component<ConversationProps> implements Conver
contextMenusContext!: ContextMenusContext contextMenusContext!: ContextMenusContext
avatarMenusContext!: ContextMenusContext // 点击头像弹出的菜单 avatarMenusContext!: ContextMenusContext // 点击头像弹出的菜单
_messageInputContext!: MessageInputContext _messageInputContext!: MessageInputContext
scrollTimer?: NodeJS.Timer scrollTimer: number | null = null
updateBrowseToMessageSeqAndReminderDoneing: boolean = false updateBrowseToMessageSeqAndReminderDoneing: boolean = false
private _dragFileCallback?: (file: File) => void private _dragFileCallback?: (file: File) => void
@ -249,8 +249,9 @@ export class Conversation extends Component<ConversationProps> implements Conver
handleScroll(e: any) { handleScroll(e: any) {
if (this.scrollTimer) { if (this.scrollTimer) {
clearTimeout(this.scrollTimer) clearTimeout(this.scrollTimer)
this.scrollTimer = null
} }
this.scrollTimer = setTimeout(() => { this.scrollTimer = window.setTimeout(() => {
this.handleScrollEnd() this.handleScrollEnd()
}, 500) }, 500)
this.contextMenusContext.hide() this.contextMenusContext.hide()

View File

@ -1,12 +1,11 @@
import { Checkbox } from "@douyinfe/semi-ui"; import { Checkbox } from "@douyinfe/semi-ui/lib/es/checkbox";
import React, { Component } from "react"; import React, { Component } from "react";
import { getPinyin } from "../../Utils/pinYin"; import { getPinyin } from "../../Utils/pinYin";
import { toSimplized } from "../../Utils/t2s"; import { toSimplized } from "../../Utils/t2s";
import "./index.css";
import { IconSearchStroked } from "@douyinfe/semi-icons"; import { IconSearchStroked } from "@douyinfe/semi-icons";
import { animateScroll, scroller } from "react-scroll"; import { animateScroll, scroller } from "react-scroll";
import "./index.css";
export class IndexTableItem { export class IndexTableItem {
id!: string; id!: string;
name!: string; name!: string;

View File

@ -1,6 +1,6 @@
import React, { Component } from "react"; import React, { Component } from "react";
import "./index.css" import "./index.css"
import { Input } from "@douyinfe/semi-ui"; import { Input } from "@douyinfe/semi-ui/lib/es/input";
import { IconSearchStroked } from '@douyinfe/semi-icons'; import { IconSearchStroked } from '@douyinfe/semi-icons';
export interface SearchProps { export interface SearchProps {

View File

@ -3,14 +3,12 @@ import React from "react";
import { Component } from "react"; import { Component } from "react";
import Provider from "../../Service/Provider"; import Provider from "../../Service/Provider";
import WKApp from "../../App"; import WKApp from "../../App";
import "./index.css";
import { SubscribersVM } from "./vm"; import { SubscribersVM } from "./vm";
import IndexTable, { IndexTableItem } from "../IndexTable"; import IndexTable, { IndexTableItem } from "../IndexTable";
import WKBase, { WKBaseContext } from "../WKBase"; import WKBase, { WKBaseContext } from "../WKBase";
import RouteContext, { RouteContextConfig } from "../../Service/Context"; import RouteContext, { RouteContextConfig } from "../../Service/Context";
import { SubscriberList } from "./list"; import { SubscriberList } from "./list";
import { ChannelSettingRouteData } from "../../Components/ChannelSetting/context";
import "./index.css";
export interface SubscribersProps { export interface SubscribersProps {
context: RouteContext<any>; context: RouteContext<any>;
@ -46,10 +44,6 @@ export class Subscribers extends Component<SubscribersProps> {
render() { render() {
const { context, onAdd, onRemove, channel } = this.props; const { context, onAdd, onRemove, channel } = this.props;
const data = context.routeData() as ChannelSettingRouteData;
const disableSelectList = data.subscribers.map((subscriber) => {
return subscriber.uid;
});
return ( return (
<Provider <Provider
create={() => { create={() => {
@ -86,7 +80,6 @@ export class Subscribers extends Component<SubscribersProps> {
{vm.showAdd() {vm.showAdd()
? WKApp.endpoints.organizationalTool( ? WKApp.endpoints.organizationalTool(
channel, channel,
disableSelectList,
<div className="wk-subscribers-item"> <div className="wk-subscribers-item">
<img <img
src={require("./assets/icon_add_more_gray.png")} src={require("./assets/icon_add_more_gray.png")}

View File

@ -162,15 +162,10 @@ export class EndpointCommon {
); );
} }
organizationalTool( organizationalTool(channel: Channel, render?: JSX.Element): JSX.Element {
channel: Channel,
disableSelectList?: string[],
render?: JSX.Element
): JSX.Element {
return EndpointManager.shared.invoke(EndpointCategory.organizational, { return EndpointManager.shared.invoke(EndpointCategory.organizational, {
channel, channel: channel,
disableSelectList, render: render,
render,
}); });
} }
@ -189,10 +184,9 @@ export class EndpointCommon {
); );
} }
organizationalLayer(channel: Channel, disableSelectList?: string[]): void { organizationalLayer(channel: Channel): void {
return EndpointManager.shared.invoke(EndpointCategory.organizationalLayer, { return EndpointManager.shared.invoke(EndpointCategory.organizationalLayer, {
channel, channel: channel,
disableSelectList,
}); });
} }

View File

@ -30,7 +30,7 @@
color: black; color: black;
} }
body[theme-mode="dark"] .wk-chat-search-add { body[theme-mode=dark] .wk-chat-search-add {
color: white; color: white;
} }
@ -40,7 +40,7 @@ body[theme-mode="dark"] .wk-chat-search-add {
font-weight: 500; font-weight: 500;
} }
body[theme-mode="dark"] .wk-chat-title { body[theme-mode=dark] .wk-chat-title {
color: white; color: white;
} }
@ -96,6 +96,7 @@ body[theme-mode="dark"] .wk-chat-title {
height: calc(100% - var(--wk-height-chat-conversation-header)); height: calc(100% - var(--wk-height-chat-conversation-header));
} }
.wk-chat-empty { .wk-chat-empty {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -116,7 +117,7 @@ body[theme-mode="dark"] .wk-chat-title {
background-color: white; background-color: white;
display: flex; display: flex;
align-items: center; align-items: center;
box-shadow: 0 1px 1px rgba(114, 114, 114, 0.168627); box-shadow: 0 1px 1px rgba(114,114,114,0.168627);
z-index: 11; z-index: 11;
padding: 0.5rem 0.8125rem 0.5rem 1.5rem; padding: 0.5rem 0.8125rem 0.5rem 1.5rem;
position: relative; position: relative;
@ -124,7 +125,7 @@ body[theme-mode="dark"] .wk-chat-title {
box-sizing: border-box; box-sizing: border-box;
} }
body[theme-mode="dark"] .wk-chat-conversation-header { body[theme-mode=dark] .wk-chat-conversation-header {
background-color: var(--wk-color-secondary); background-color: var(--wk-color-secondary);
} }
@ -148,8 +149,7 @@ body[theme-mode="dark"] .wk-chat-conversation-header {
transform: rotate(180deg); transform: rotate(180deg);
} }
.wk-chat-conversation-header-back-icon::before, .wk-chat-conversation-header-back-icon::before, .wk-chat-conversation-header-back-icon::after {
.wk-chat-conversation-header-back-icon::after {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@ -164,16 +164,15 @@ body[theme-mode="dark"] .wk-chat-conversation-header {
transform: rotate(45deg) scaleX(0.75) translate(0, -0.375rem); transform: rotate(45deg) scaleX(0.75) translate(0, -0.375rem);
} }
.wk-chat-conversation-header-back-icon, .wk-chat-conversation-header-back-icon, .wk-chat-conversation-header-back-icon::before, .wk-chat-conversation-header-back-icon::after {
.wk-chat-conversation-header-back-icon::before,
.wk-chat-conversation-header-back-icon::after {
width: 1.125rem; width: 1.125rem;
height: 0.125rem; height: 0.125rem;
border-radius: 0.125rem; border-radius: 0.125rem;
background-color: rgb(112, 117, 121); background-color: rgb(112,117,121);
transition: transform var(--wk-slide-transition); transition: transform var(--wk-slide-transition);
} }
.wk-chat-conversation-header-channel { .wk-chat-conversation-header-channel {
display: flex; display: flex;
} }
@ -195,7 +194,7 @@ body[theme-mode="dark"] .wk-chat-conversation-header {
font-weight: 600; font-weight: 600;
} }
body[theme-mode="dark"] .wk-chat-conversation-header-channel-info-name { body[theme-mode=dark] .wk-chat-conversation-header-channel-info-name {
color: white; color: white;
} }
@ -279,10 +278,10 @@ body[theme-mode=dark] .wk-chat-channelsetting {
height: 100%; height: 100%;
} }
body[theme-mode="dark"] .wk-chat-popover { body[theme-mode=dark] .wk-chat-popover {
background-color: var(--wk-color-secondary); background-color: var(--wk-color-secondary);
color: white; color: white;
--color-popover-bg-default: red; --color-popover-bg-default: red
} }
.wk-chatmenuspopover li { .wk-chatmenuspopover li {
@ -297,8 +296,8 @@ body[theme-mode="dark"] .wk-chat-popover {
} }
.wk-chatmenuspopover li img { .wk-chatmenuspopover li img {
width: 18px; width: 20px;
height: 18px; height: 20px;
color: white; color: white;
} }
@ -307,17 +306,12 @@ body[theme-mode="dark"] .wk-chat-popover {
font-size: 14px; font-size: 14px;
} }
.wk-chatmenuspopover-avatar {
display: flex;
align-items: center;
}
.wk-chat-conversation-header-right-item { .wk-chat-conversation-header-right-item {
position: relative; position: relative;
} }
.wk-conversation-header-mask { .wk-conversation-header-mask {
background-color: rgb(0, 0, 0, 0); background-color: rgb(0,0,0,0.0);
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -326,5 +320,5 @@ body[theme-mode="dark"] .wk-chat-popover {
} }
.wk-conversation-header-mask:hover { .wk-conversation-header-mask:hover {
background-color: rgb(0, 0, 0, 0.1); background-color: rgb(0,0,0,0.1);
} }

View File

@ -88,6 +88,8 @@ export default class BaseModule implements IModule {
return "base"; return "base";
} }
init(): void { init(): void {
APIClient.shared.logoutCallback = () => { APIClient.shared.logoutCallback = () => {
WKApp.shared.logout(); WKApp.shared.logout();
}; };
@ -227,9 +229,7 @@ export default class BaseModule implements IModule {
cmdContent.param.from_name cmdContent.param.from_name
); );
} else if (cmdContent.cmd === "groupAvatarUpdate") { } else if (cmdContent.cmd === "groupAvatarUpdate") {
WKApp.shared.changeChannelAvatarTag( WKApp.shared.changeChannelAvatarTag(new Channel(param.group_no, ChannelTypeGroup));
new Channel(param.group_no, ChannelTypeGroup)
);
// 群头像更新 // 群头像更新
WKSDK.shared().channelManager.fetchChannelInfo( WKSDK.shared().channelManager.fetchChannelInfo(
new Channel(param.group_no, ChannelTypeGroup) new Channel(param.group_no, ChannelTypeGroup)
@ -343,11 +343,8 @@ export default class BaseModule implements IModule {
ConversationAction.update ConversationAction.update
); );
} }
} else if (cmdContent.cmd === "userAvatarUpdate") { } else if (cmdContent.cmd === "userAvatarUpdate") { // 用户头像更新
// 用户头像更新 WKApp.shared.changeChannelAvatarTag(new Channel(param.uid, ChannelTypePerson));
WKApp.shared.changeChannelAvatarTag(
new Channel(param.uid, ChannelTypePerson)
);
WKApp.dataSource.notifyContactsChange(); WKApp.dataSource.notifyContactsChange();
} }
}); });
@ -453,16 +450,15 @@ export default class BaseModule implements IModule {
return; return;
} }
if (window.Notification && Notification.permission !== "denied") { if (window.Notification && Notification.permission !== "denied") {
const options = { const notify = new Notification(
channelInfo ? channelInfo.orgData.displayName : "通知",
{
body: description, body: description,
icon: WKApp.shared.avatarChannel(message.channel), icon: WKApp.shared.avatarChannel(message.channel),
lang: "zh-CN", lang: "zh-CN",
tag: "tag", tag: "tag",
renotify: true, // renotify: true,
}; }
const notify = new Notification(
channelInfo ? channelInfo.orgData.displayName : "通知",
options
); );
notify.onclick = () => { notify.onclick = () => {
@ -513,7 +509,7 @@ export default class BaseModule implements IModule {
icon={require("./assets/toolbars/func_screenshot.svg").default} icon={require("./assets/toolbars/func_screenshot.svg").default}
onClick={() => { onClick={() => {
if ((window as any).__POWERED_ELECTRON__) { if ((window as any).__POWERED_ELECTRON__) {
(window as any).ipc.send("screenshots-start", {}); (window as any).ipc.send('screenshots-start', {})
} else { } else {
window.open("https://www.snipaste.com"); window.open("https://www.snipaste.com");
} }
@ -536,8 +532,7 @@ export default class BaseModule implements IModule {
const isDark = WKApp.config.themeMode === ThemeMode.dark; const isDark = WKApp.config.themeMode === ThemeMode.dark;
return { return {
title: "发起群聊", title: "发起群聊",
icon: require(`${ icon: require(`${isDark
isDark
? "./assets/popmenus_startchat_dark.png" ? "./assets/popmenus_startchat_dark.png"
: "./assets/popmenus_startchat.png" : "./assets/popmenus_startchat.png"
}`), }`),

View File

@ -5,7 +5,6 @@
"dependencies": { "dependencies": {
"@tsdaodao/base": "*", "@tsdaodao/base": "*",
"axios": "^0.25.0", "axios": "^0.25.0",
"classnames": "^2.3.1", "classnames": "^2.3.1"
"react-infinite-scroller": "^1.2.6"
} }
} }

View File

@ -1,287 +1,246 @@
import React from "react"; import React from "react";
import { Component } from "react"; import { Component } from "react";
import { import { Contacts, ContactsChangeListener, ContextMenus, ContextMenusContext, WKApp, WKBase, WKBaseContext, WKNavMainHeader, Search, UserRelation } from "@tsdaodao/base"
Contacts, import "./index.css"
ContactsChangeListener,
ContextMenus,
ContextMenusContext,
WKApp,
WKBase,
WKBaseContext,
WKNavMainHeader,
Search,
UserRelation,
} from "@tsdaodao/base";
import "./index.css";
import { toSimplized } from "@tsdaodao/base"; import { toSimplized } from "@tsdaodao/base";
import { getPinyin } from "@tsdaodao/base"; import { getPinyin } from "@tsdaodao/base";
import classnames from "classnames"; import classnames from "classnames";
import { Toast } from "@douyinfe/semi-ui"; import { Toast } from "@douyinfe/semi-ui";
import { import { Channel, ChannelTypePerson, WKSDK,ChannelInfoListener,ChannelInfo } from "wukongimjssdk";
Channel,
ChannelTypePerson,
WKSDK,
ChannelInfoListener,
ChannelInfo,
} from "wukongimjssdk";
import { ContactsListManager } from "../Service/ContactsListManager"; import { ContactsListManager } from "../Service/ContactsListManager";
import { Card } from "@tsdaodao/base/src/Messages/Card"; import { Card } from "@tsdaodao/base/src/Messages/Card";
import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar"; import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar";
export class ContactsState { export class ContactsState {
indexList: string[] = []; indexList: string[] = []
indexItemMap: Map<string, Contacts[]> = new Map(); indexItemMap: Map<string, Contacts[]> = new Map()
keyword?: string; keyword?: string
selectedItem?: Contacts; // 被选中的联系人 selectedItem?: Contacts // 被选中的联系人
} }
export default class ContactsList extends Component<any, ContactsState> { export default class ContactsList extends Component<any, ContactsState> {
contactsChangeListener!: ContactsChangeListener; contactsChangeListener!: ContactsChangeListener
channelInfoListener!: ChannelInfoListener; channelInfoListener!: ChannelInfoListener
contextMenusContext!: ContextMenusContext; contextMenusContext!: ContextMenusContext
baseContext!: WKBaseContext; baseContext!: WKBaseContext
constructor(props: any) { constructor(props: any) {
super(props); super(props)
this.state = { this.state = {
indexList: [], indexList: [],
indexItemMap: new Map(), indexItemMap: new Map()
}; }
} }
componentDidMount() { componentDidMount() {
this.contactsChangeListener = () => {
this.rebuildIndex();
};
this.channelInfoListener = (channelInfo: ChannelInfo) => { this.contactsChangeListener = () => {
if (channelInfo.channel.channelType !== ChannelTypePerson) { this.rebuildIndex()
return; }
this.channelInfoListener = (channelInfo:ChannelInfo)=>{
if(channelInfo.channel.channelType !== ChannelTypePerson) {
return
} }
//是否包含 //是否包含
let exist = false; let exist = false
WKApp.dataSource.contactsList.forEach((v) => { WKApp.dataSource.contactsList.forEach((v)=>{
if (v.uid === channelInfo.channel.channelID) { if(v.uid === channelInfo.channel.channelID) {
exist = true; exist = true
v.name = channelInfo.title; v.name = channelInfo.title
v.remark = channelInfo?.orgData.remark; v.remark = channelInfo?.orgData.remark
return; return
}
})
if(exist) {
this.rebuildIndex()
} }
});
if (exist) {
this.rebuildIndex();
} }
};
WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener); WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener)
this.rebuildIndex(); this.rebuildIndex()
WKSDK.shared().channelManager.addListener(this.channelInfoListener); WKSDK.shared().channelManager.addListener(this.channelInfoListener)
ContactsListManager.shared.setRefreshList = () => { ContactsListManager.shared.setRefreshList = () => {
this.setState({}); this.setState({})
}; }
} }
componentWillUnmount() { componentWillUnmount() {
ContactsListManager.shared.setRefreshList = undefined; ContactsListManager.shared.setRefreshList = undefined
WKApp.dataSource.removeContactsChangeListener(this.contactsChangeListener); WKApp.dataSource.removeContactsChangeListener(this.contactsChangeListener)
WKSDK.shared().channelManager.removeListener(this.channelInfoListener); WKSDK.shared().channelManager.removeListener(this.channelInfoListener)
} }
rebuildIndex() { rebuildIndex() {
console.log("rebuildIndex---->"); console.log("rebuildIndex---->")
this.buildIndex(this.contactsList()); this.buildIndex(this.contactsList())
} }
contactsList() { contactsList() {
const { keyword } = this.state; const { keyword } = this.state
return WKApp.dataSource.contactsList.filter((v) => { return WKApp.dataSource.contactsList.filter((v) => {
if (v.status === UserRelation.blacklist) { if (v.status === UserRelation.blacklist) {
return false; return false
} }
if (v.follow !== 1) { if (v.follow !== 1) {
return false; return false
} }
if (!keyword || keyword === "") { if (!keyword || keyword === "") {
return true; return true
} }
if (v.remark && v.remark !== "") { if (v.remark && v.remark !== "") {
if (v.remark.indexOf(keyword) !== -1) { if (v.remark.indexOf(keyword) !== -1) {
return true; return true
} }
} }
return v.name.indexOf(keyword) !== -1; return v.name.indexOf(keyword) !== -1
}); })
} }
buildIndex(contacts: Contacts[]) { buildIndex(contacts: Contacts[]) {
const indexItemMap = new Map<string, Contacts[]>(); const indexItemMap = new Map<string, Contacts[]>()
let indexList = []; let indexList = []
for (const item of contacts) { for (const item of contacts) {
let name = item.name; let name = item.name
if (item.remark && item.remark !== "") { if (item.remark && item.remark !== "") {
name = item.remark; name = item.remark
} }
let pinyinNick = getPinyin(toSimplized(name)).toUpperCase(); let pinyinNick = getPinyin(toSimplized(name)).toUpperCase();
let indexName = let indexName = !pinyinNick || /[^a-z]/i.test(pinyinNick[0]) ? "#" : pinyinNick[0];
!pinyinNick || /[^a-z]/i.test(pinyinNick[0]) ? "#" : pinyinNick[0];
let existItems = indexItemMap.get(indexName); let existItems = indexItemMap.get(indexName)
if (!existItems) { if (!existItems) {
existItems = []; existItems = []
indexList.push(indexName); indexList.push(indexName)
} }
existItems.push(item); existItems.push(item)
indexItemMap.set(indexName, existItems); indexItemMap.set(indexName, existItems)
} }
indexList = indexList.sort((a, b) => { indexList = indexList.sort((a, b) => {
if (a === "#") { if (a === "#") {
return -1; return -1
} }
if (b === "#") { if (b === "#") {
return 1; return 1
} }
return a.localeCompare(b); return a.localeCompare(b)
}); })
this.setState({ this.setState({
indexList: indexList, indexList: indexList,
indexItemMap: indexItemMap, indexItemMap: indexItemMap,
}); })
} }
_handleContextMenu(item: Contacts, event: React.MouseEvent) { _handleContextMenu(item: Contacts, event: React.MouseEvent) {
this.contextMenusContext.show(event); this.contextMenusContext.show(event)
this.setState({ this.setState({
selectedItem: item, selectedItem: item,
}); })
} }
sectionUI(indexName: string) { sectionUI(indexName: string) {
const { indexItemMap } = this.state; const { indexItemMap } = this.state
const { canSelect } = this.props; const { canSelect } = this.props
const items = indexItemMap.get(indexName); const items = indexItemMap.get(indexName)
return ( return <div key={indexName} className="wk-contacts-section">
<div key={indexName} className="wk-contacts-section">
<div className="wk-contacts-section-list"> <div className="wk-contacts-section-list">
{items?.map((item, i) => { {
let name = item.name; items?.map((item, i) => {
let name = item.name
if (item.remark && item.remark !== "") { if (item.remark && item.remark !== "") {
name = item.remark; name = item.remark
} }
return ( return <div key={item.uid} className={classnames("wk-contacts-section-item", WKApp.shared.openChannel?.channelType === ChannelTypePerson && WKApp.shared.openChannel?.channelID === item.uid ? "wk-contacts-section-item-selected" : undefined)} onClick={() => {
<div const channel = new Channel(item.uid, ChannelTypePerson)
key={item.uid} WKApp.endpoints.showConversation(channel)
className={classnames( this.setState({})
"wk-contacts-section-item", }} onContextMenu={(e) => {
WKApp.shared.openChannel?.channelType === ChannelTypePerson && this._handleContextMenu(item, e)
WKApp.shared.openChannel?.channelID === item.uid }}>
? "wk-contacts-section-item-selected"
: undefined
)}
onClick={() => {
const channel = new Channel(item.uid, ChannelTypePerson);
WKApp.endpoints.showConversation(channel);
this.setState({});
}}
onContextMenu={(e) => {
this._handleContextMenu(item, e);
}}
>
<div className="wk-contacts-section-item-index"> <div className="wk-contacts-section-item-index">
{i === 0 ? indexName : ""} {i === 0 ? indexName : ""}
</div> </div>
<div className="wk-contacts-section-item-avatar"> <div className="wk-contacts-section-item-avatar">
<WKAvatar <WKAvatar channel={new Channel(item.uid, ChannelTypePerson)}></WKAvatar>
channel={new Channel(item.uid, ChannelTypePerson)}
></WKAvatar>
</div> </div>
<div className="wk-contacts-section-item-name">{name}</div> <div className="wk-contacts-section-item-name">
</div> {name}
);
})}
</div> </div>
</div> </div>
); })
}
</div>
</div>
} }
render() { render() {
const { indexList } = this.state; const { indexList } = this.state
return ( return <WKBase onContext={(baseCtx) => {
<WKBase this.baseContext = baseCtx
onContext={(baseCtx) => { }}>
this.baseContext = baseCtx;
}}
>
<div className="wk-contacts"> <div className="wk-contacts">
<WKNavMainHeader title="联系人"></WKNavMainHeader> <WKNavMainHeader title="联系人"></WKNavMainHeader>
<div className="wk-contacts-content"> <div className="wk-contacts-content">
<div className="wk-contacts-content-header"> <div className="wk-contacts-content-header">
<Search <Search placeholder="搜索" onChange={(v) => {
placeholder="搜索" this.setState({
onChange={(v) => { keyword: v
this.setState( }, () => {
{ this.rebuildIndex()
keyword: v, })
}, }}></Search>
() => {
this.rebuildIndex();
}
);
}}
></Search>
</div> </div>
<div className="wk-contacts-content-fnc"> <div className="wk-contacts-content-fnc">
{WKApp.endpoints.contactsHeaders().map((view, i) => { {
return <div key={i}>{view}</div>; WKApp.endpoints.contactsHeaders().map((view, i) => {
})} return <div key={i}>{view}</div>
})
}
</div> </div>
<div className="wk-contacts-content-contacts"> <div className="wk-contacts-content-contacts">
{indexList.map((indexName) => { {
return this.sectionUI(indexName); indexList.map((indexName) => {
})} return this.sectionUI(indexName)
})
}
</div> </div>
</div> </div>
<ContextMenus <ContextMenus onContext={(context: ContextMenusContext) => {
onContext={(context: ContextMenusContext) => { this.contextMenusContext = context
this.contextMenusContext = context; }} menus={[{
}} title: "查看资料", onClick: () => {
menus={[ const { selectedItem } = this.state
{ this.baseContext.showUserInfo(selectedItem?.uid || "")
title: "查看资料", }
onClick: () => { }, {
const { selectedItem } = this.state; title: "分享给朋友...", onClick: () => {
this.baseContext.showUserInfo(selectedItem?.uid || ""); WKApp.shared.baseContext.showConversationSelect((channels: Channel[]) => {
}, const { selectedItem } = this.state
},
{
title: "分享给朋友...",
onClick: () => {
WKApp.shared.baseContext.showConversationSelect(
(channels: Channel[]) => {
const { selectedItem } = this.state;
if (channels && channels.length > 0) { if (channels && channels.length > 0) {
for (const channel of channels) { for (const channel of channels) {
const card = new Card(); const card = new Card()
card.uid = selectedItem?.uid || ""; card.uid = selectedItem?.uid || ""
card.name = selectedItem?.name || ""; card.name = selectedItem?.name || ""
card.vercode = selectedItem?.vercode || ""; card.vercode = selectedItem?.vercode||""
WKSDK.shared().chatManager.send(card, channel); WKSDK.shared().chatManager.send(card, channel)
} }
Toast.success("分享成功!"); Toast.success("分享成功!")
} }
}, }, "分享名片")
"分享名片" }
); }]} />
},
},
]}
/>
</div> </div>
</WKBase> </WKBase>
);
} }
} }

View File

@ -1,98 +1,81 @@
import { WKApp, WKViewQueueHeader, QRCodeMy, Search } from "@tsdaodao/base"; import { WKApp, WKViewQueueHeader, QRCodeMy, Search } from "@tsdaodao/base";
import { WKBase, WKBaseContext } from "@tsdaodao/base"; import {WKBase, WKBaseContext } from "@tsdaodao/base";
import React from "react"; import React from "react";
import { Component, ReactNode } from "react"; import { Component, ReactNode } from "react";
import { Spin, Toast } from "@douyinfe/semi-ui"; import { Spin,Toast } from '@douyinfe/semi-ui';
import "./index.css"; import "./index.css"
export interface FriendAddProps { export interface FriendAddProps {
onBack?: () => void; onBack?: () => void
} }
export class FriendAddState { export class FriendAddState {
spinning!: boolean; spinning!:boolean
keyword?: string; keyword?:string
result?: any; result?:any
} }
export class FriendAdd extends Component<FriendAddProps, FriendAddState> { export class FriendAdd extends Component<FriendAddProps,FriendAddState> {
baseContext!: WKBaseContext; baseContext!:WKBaseContext
constructor(props: any) { constructor(props:any) {
super(props); super(props)
this.state = { this.state = {
spinning: false, spinning: false,
}; }
} }
async searchUser() { async searchUser() {
const { keyword } = this.state; const { keyword } = this.state
if (!keyword) { if(!keyword) {
return; return
} }
this.setState({ this.setState({
spinning: true, spinning: true,
}); })
const result = await WKApp.dataSource.commonDataSource const result = await WKApp.dataSource.commonDataSource.searchUser(keyword).catch((err)=>{
.searchUser(keyword) Toast.error(err.msg)
.catch((err) => { })
Toast.error(err.msg); if(result) {
});
if (result) {
this.setState({ this.setState({
result: result, result: result,
spinning: false, spinning: false,
}); })
if (result.exist !== 1) { if(result.exist !== 1) {
Toast.error("用户不存在!"); Toast.error("用户不存在!")
} else { }else {
WKApp.shared.baseContext.showUserInfo( WKApp.shared.baseContext.showUserInfo(result.data.uid,undefined,result.data.vercode)
result.data.uid,
undefined,
result.data.vercode
);
} }
} }
} }
render(): ReactNode { render(): ReactNode {
const { onBack } = this.props; const { onBack } = this.props
const { spinning } = this.state; const { spinning } = this.state
return ( return <WKBase onContext={(ctx)=>{
<WKBase this.baseContext = ctx
onContext={(ctx) => { }}>
this.baseContext = ctx;
}}
>
<div className="wk-friendadd"> <div className="wk-friendadd">
<WKViewQueueHeader title="添加好友" onBack={onBack} /> <WKViewQueueHeader title="添加好友" onBack={onBack} />
<div className="wk-friendadd-content"> <div className="wk-friendadd-content">
<Spin spinning={spinning}> <Spin spinning={spinning}>
<Search <Search placeholder={`${WKApp.config.appName}号/手机号`} onChange={(v)=>{
placeholder={`${WKApp.config.appName}号/手机号`}
onChange={(v) => {
this.setState({ this.setState({
keyword: v, keyword: v
}); })
}} }} onEnterPress={()=>{
onEnterPress={() => { this.searchUser()
this.searchUser(); }}></Search>
}}
></Search>
</Spin> </Spin>
<div className="wk-friendadd-content-qrcode"> <div className="wk-friendadd-content-qrcode">
{WKApp.config.appName}{WKApp.loginInfo.shortNo}{" "} {WKApp.config.appName}{WKApp.loginInfo.shortNo} <img onClick={()=>{
<img WKApp.routeLeft.push(<QRCodeMy></QRCodeMy>)
onClick={() => { }} src={require("./assets/icon_qrcode.png")}></img>
WKApp.routeLeft.push(<QRCodeMy></QRCodeMy>);
}}
src={require("./assets/icon_qrcode.png")}
></img>
</div> </div>
</div> </div>
</div> </div>
</WKBase> </WKBase>
);
} }
} }

View File

@ -1,80 +1,32 @@
import React from "react"; import React, { Component, ReactNode } from "react";
import { import { Button } from '@douyinfe/semi-ui';
FriendApply, import { FriendApplyState, WKApp, WKViewQueueHeader, Provider } from "@tsdaodao/base";
FriendApplyState,
WKApp,
ContextMenus,
ContextMenusContext,
WKViewQueueHeader,
Provider,
} from "@tsdaodao/base";
import { Component, ReactNode } from "react";
import { Button } from "@douyinfe/semi-ui";
import { NewFriendVM } from "./vm";
import { FriendAdd } from "../FriendAdd"; import { FriendAdd } from "../FriendAdd";
import { NewFriendVM } from "./vm";
import "./index.css"; import "./index.css";
export class NewFriendState { export class NewFriend extends Component {
selectedItem?: FriendApply; // 被选中的好友
}
export class NewFriend extends Component<any, NewFriendState> {
contextMenusContext!: ContextMenusContext;
constructor(props: any) {
super(props);
}
_handleContextMenu(item: FriendApply, event: React.MouseEvent) {
console.log(item);
this.contextMenusContext.show(event);
this.setState({
selectedItem: item,
});
}
render(): ReactNode { render(): ReactNode {
return ( return <Provider create={() => {
<Provider return new NewFriendVM()
create={() => { }} render={(vm: NewFriendVM) => {
return new NewFriendVM();
}} return <div className="wk-newfriend">
render={(vm: NewFriendVM) => { <WKViewQueueHeader title="新朋友" onBack={() => {
return ( WKApp.routeLeft.pop()
<div className="wk-newfriend"> }} action={<div className="wk-viewqueueheader-content-action">
<WKViewQueueHeader <Button size="small" onClick={()=>{
title="新朋友" WKApp.routeLeft.push(<FriendAdd onBack={()=>{
onBack={() => { WKApp.routeLeft.pop()
WKApp.routeLeft.pop(); }}></FriendAdd>)
}} }} ></Button>
action={ </div>}></WKViewQueueHeader>
<div className="wk-viewqueueheader-content-action">
<Button
size="small"
onClick={() => {
WKApp.routeLeft.push(
<FriendAdd
onBack={() => {
WKApp.routeLeft.pop();
}}
></FriendAdd>
);
}}
>
</Button>
</div>
}
></WKViewQueueHeader>
<div className="wk-newfriend-content"> <div className="wk-newfriend-content">
<ul> <ul>
{vm.friendApplys.map((f) => { {
return ( vm.friendApplys.map((f) => {
<li return <li key={f.to_uid} >
key={f.to_uid}
onContextMenu={(e) => {
this._handleContextMenu(f, e);
}}
>
<div className="wk-newfriend-content-avatar"> <div className="wk-newfriend-content-avatar">
<img src={WKApp.shared.avatarUser(f.to_uid)}></img> <img src={WKApp.shared.avatarUser(f.to_uid)}></img>
</div> </div>
@ -87,44 +39,18 @@ export class NewFriend extends Component<any, NewFriendState> {
</div> </div>
</div> </div>
<div className="wk-newfriend-content-action"> <div className="wk-newfriend-content-action">
<Button <Button loading={vm.currentFriendApply?.to_uid === f.to_uid && vm.sureLoading } disabled={f.status == FriendApplyState.accepted} onClick={()=>{
loading={ vm.friendSure(f)
vm.currentFriendApply?.to_uid === f.to_uid && }}>{f.status == FriendApplyState.accepted ? "已添加" : "确认"}</Button>
vm.sureLoading
}
disabled={f.status == FriendApplyState.accepted}
onClick={() => {
vm.friendSure(f);
}}
>
{f.status == FriendApplyState.accepted
? "已添加"
: "确认"}
</Button>
</div> </div>
</li> </li>
); })
})} }
</ul> </ul>
</div> </div>
<ContextMenus
onContext={(context: ContextMenusContext) => {
this.contextMenusContext = context;
}}
menus={[
{
title: "删除",
onClick: () => {
const { selectedItem } = this.state;
selectedItem && vm.delFriendApply(selectedItem);
},
},
]}
/>
</div> </div>
); }}>
}}
></Provider> </Provider>
);
} }
} }

View File

@ -14,8 +14,6 @@ import {
import { BasicTreeNodeData } from "@douyinfe/semi-foundation/lib/cjs/tree/foundation"; import { BasicTreeNodeData } from "@douyinfe/semi-foundation/lib/cjs/tree/foundation";
import { WKApp, ThemeMode, WKViewQueueHeader } from "@tsdaodao/base"; import { WKApp, ThemeMode, WKViewQueueHeader } from "@tsdaodao/base";
import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar"; import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar";
import { ContactsStatus } from "@tsdaodao/base/src/Service/DataSource/DataSource";
import "./index.css"; import "./index.css";
interface IPorpsOrganizationalGroupNew { interface IPorpsOrganizationalGroupNew {
@ -23,7 +21,6 @@ interface IPorpsOrganizationalGroupNew {
channelID: string; channelID: string;
channelType: number; channelType: number;
}; };
disableSelectList?: string[];
showAdd?: boolean; showAdd?: boolean;
render?: JSX.Element; render?: JSX.Element;
remove?: () => void; remove?: () => void;
@ -188,8 +185,7 @@ export class OrganizationalGroupNew extends Component<
} }
OTree.push({ OTree.push({
label: label: employeesNum > 0 ? `${item.name}(${employeesNum})` : `${item.name}`,
employeesNum > 0 ? `${item.name}(${employeesNum})` : `${item.name}`,
value: item.dept_id, value: item.dept_id,
key: item.short_no, key: item.short_no,
icon: ( icon: (
@ -295,11 +291,9 @@ export class OrganizationalGroupNew extends Component<
getFriendData() { getFriendData() {
const setFriendData: any[] = []; const setFriendData: any[] = [];
WKApp.dataSource.contactsList WKApp.dataSource.contactsList.map((item) => {
.filter((c) => c.status !== ContactsStatus.Blacklist)
.map((item) => {
setFriendData.push({ setFriendData.push({
name: item.remark || item.name, name: item.name,
uid: item.uid, uid: item.uid,
}); });
}); });
@ -407,18 +401,6 @@ export class OrganizationalGroupNew extends Component<
} }
} }
isDisableItem(id: string) {
const { disableSelectList } = this.props;
if (disableSelectList && disableSelectList.length > 0) {
for (const disableSelect of disableSelectList) {
if (disableSelect === id) {
return true;
}
}
}
return false;
}
render(): ReactNode { render(): ReactNode {
const isDark = WKApp.config.themeMode === ThemeMode.dark; const isDark = WKApp.config.themeMode === ThemeMode.dark;
const { const {
@ -549,7 +531,6 @@ export class OrganizationalGroupNew extends Component<
<Checkbox <Checkbox
key={friend.uid} key={friend.uid}
value={friend.uid} value={friend.uid}
disabled={this.isDisableItem(friend.uid)}
className="friend-opt-item" className="friend-opt-item"
> >
<WKAvatar <WKAvatar

View File

@ -45,7 +45,7 @@ export default class ContactsModule implements IModule {
WKApp.endpoints.registerContactsHeader("friends.new", (param: any) => { WKApp.endpoints.registerContactsHeader("friends.new", (param: any) => {
return ( return (
<IconListItem <IconListItem
badge={WKApp.shared.getFriendApplysUnreadCount()} badge={ WKApp.shared.getFriendApplysUnreadCount() }
title="新朋友" title="新朋友"
icon={require("./assets/friend_new.png")} icon={require("./assets/friend_new.png")}
backgroudColor={"var(--wk-color-secondary)"} backgroudColor={"var(--wk-color-secondary)"}
@ -111,15 +111,8 @@ export default class ContactsModule implements IModule {
"contacts.organizational.group.add", "contacts.organizational.group.add",
(param) => { (param) => {
const channel = param.channel as any; const channel = param.channel as any;
const disableSelectList = param.disableSelectList as
| string[]
| undefined;
return ( return (
<OrganizationalGroupNew <OrganizationalGroupNew channel={channel} render={param.render} />
channel={channel}
disableSelectList={disableSelectList}
render={param.render}
/>
); );
} }
); );
@ -128,9 +121,6 @@ export default class ContactsModule implements IModule {
"contacts.organizational.layer", "contacts.organizational.layer",
(param) => { (param) => {
const channel = param.channel as any; const channel = param.channel as any;
const disableSelectList = param.disableSelectList as
| string[]
| undefined;
const div = document.createElement("div"); const div = document.createElement("div");
const ref: any = React.createRef(); const ref: any = React.createRef();
document.body.appendChild(div); document.body.appendChild(div);
@ -145,7 +135,6 @@ export default class ContactsModule implements IModule {
<OrganizationalGroupNew <OrganizationalGroupNew
ref={ref} ref={ref}
channel={channel} channel={channel}
disableSelectList={disableSelectList}
remove={remove} remove={remove}
/>, />,
div div

View File

@ -7,9 +7,6 @@ import { WKApp, Provider } from "@tsdaodao/base"
import { LoginStatus, LoginType, LoginVM } from "./login_vm"; import { LoginStatus, LoginType, LoginVM } from "./login_vm";
import classNames from "classnames"; import classNames from "classnames";
type LoginState = { type LoginState = {
loginStatus: string loginStatus: string
loginUUID: string loginUUID: string
@ -20,6 +17,9 @@ type LoginState = {
class Login extends Component<any, LoginState> { class Login extends Component<any, LoginState> {
render() { render() {
return <Provider create={() => { return <Provider create={() => {
@ -29,7 +29,7 @@ class Login extends Component<any, LoginState> {
<div className="wk-login-content"> <div className="wk-login-content">
<div className="wk-login-content-phonelogin" style={{ "display": vm.loginType === LoginType.phone ? "block" : "none" }}> <div className="wk-login-content-phonelogin" style={{ "display": vm.loginType === LoginType.phone ? "block" : "none" }}>
<div className="wk-login-content-logo"> <div className="wk-login-content-logo">
<img src={`/logo.png`} alt="logo" /> <img src={`${process.env.PUBLIC_URL}/logo.png`} alt="logo" />
</div> </div>
<div className="wk-login-content-slogan"> <div className="wk-login-content-slogan">