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

View File

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

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 { getPinyin } from "../../Utils/pinYin";
import { toSimplized } from "../../Utils/t2s";
import "./index.css";
import { IconSearchStroked } from "@douyinfe/semi-icons";
import { animateScroll, scroller } from "react-scroll";
import "./index.css";
export class IndexTableItem {
id!: string;
name!: string;

View File

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

View File

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

View File

@ -162,15 +162,10 @@ export class EndpointCommon {
);
}
organizationalTool(
channel: Channel,
disableSelectList?: string[],
render?: JSX.Element
): JSX.Element {
organizationalTool(channel: Channel, render?: JSX.Element): JSX.Element {
return EndpointManager.shared.invoke(EndpointCategory.organizational, {
channel,
disableSelectList,
render,
channel: channel,
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, {
channel,
disableSelectList,
channel: channel,
});
}

View File

@ -1,232 +1,231 @@
.wk-chat {
width: 100%;
height: 100%;
width: 100%;
height: 100%;
}
.wk-chat-content {
display: flex;
width: 100%;
height: 100%;
display: flex;
width: 100%;
height: 100%;
}
.wk-chat-content-left {
width: var(--wk-wdith-conversation-list);
height: 100%;
border-right: var(--wk-line);
width: var(--wk-wdith-conversation-list);
height: 100%;
border-right: var(--wk-line);
}
.wk-chat-search {
height: var(--wk-height-chat-search);
width: 100%;
padding: 0px 20px 0px 20px;
display: flex;
align-items: center;
justify-content: space-between;
height: var(--wk-height-chat-search);
width: 100%;
padding: 0px 20px 0px 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.wk-chat-search-add {
padding: 5px;
cursor: pointer;
color: black;
padding: 5px;
cursor: pointer;
color: black;
}
body[theme-mode="dark"] .wk-chat-search-add {
color: white;
body[theme-mode=dark] .wk-chat-search-add {
color: white;
}
.wk-chat-title {
width: 250px;
font-size: 24px;
font-weight: 500;
width: 250px;
font-size: 24px;
font-weight: 500;
}
body[theme-mode="dark"] .wk-chat-title {
color: white;
body[theme-mode=dark] .wk-chat-title {
color: white;
}
.wk-chat-conversation-list {
width: 100%;
height: calc(100% - var(--wk-height-chat-search));
width: 100%;
height: calc(100% - var(--wk-height-chat-search));
}
.wk-chat-content-right {
width: 100%;
height: 100%;
display: flex;
position: relative;
width: 100%;
height: 100%;
display: flex;
position: relative;
}
@media screen and (max-width: 640px) {
.wk-chat-content-right {
width: 100%;
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
transform: translate3d(0, 0, 0);
transition: transform var(--wk-layer-transition);
}
@media screen and (max-width: 640px) {
.wk-chat-content-right {
width: 100%;
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
transform: translate3d(0, 0, 0);
transition: transform var(--wk-layer-transition);
}
.wk-chat-content:not(.wk-conversation-open) .wk-chat-content-right {
transform: translate3d(100vw, 0, 0);
}
.wk-chat-content:not(.wk-conversation-open) .wk-chat-content-right {
transform: translate3d(100vw, 0, 0);
}
.wk-chat-content-left {
width: 100%;
}
.wk-chat-content-left {
width: 100%;
}
.wk-chat-conversation-header-back {
display: flex !important;
}
.wk-chat-conversation-header-back {
display: flex !important;
}
}
.wk-chat-content-chat {
width: 100%;
height: 100%;
transition: width 150ms ease-in-out 0s;
width: 100%;
height: 100%;
transition: width 150ms ease-in-out 0s;
}
.wk-chat-content-right.wk-chat-channelsetting-open .wk-chat-content-chat {
width: calc(100% - var(--wk-wdith-chat-channelsetting));
width: calc(100% - var(--wk-wdith-chat-channelsetting));
}
.wk-chat-conversation {
width: 100%;
height: calc(100% - var(--wk-height-chat-conversation-header));
width: 100%;
height: calc(100% - var(--wk-height-chat-conversation-header));
}
.wk-chat-empty {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: var(--wk-color-secondary);
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: var(--wk-color-secondary);
}
.wk-chat-empty img {
height: 340px;
transform: scale(1.14);
height: 340px;
transform: scale(1.14);
}
.wk-chat-conversation-header {
height: var(--wk-height-chat-conversation-header);
width: 100%;
background-color: white;
display: flex;
align-items: center;
box-shadow: 0 1px 1px rgba(114, 114, 114, 0.168627);
z-index: 11;
padding: 0.5rem 0.8125rem 0.5rem 1.5rem;
position: relative;
cursor: pointer;
box-sizing: border-box;
height: var(--wk-height-chat-conversation-header);
width: 100%;
background-color: white;
display: flex;
align-items: center;
box-shadow: 0 1px 1px rgba(114,114,114,0.168627);
z-index: 11;
padding: 0.5rem 0.8125rem 0.5rem 1.5rem;
position: relative;
cursor: pointer;
box-sizing: border-box;
}
body[theme-mode="dark"] .wk-chat-conversation-header {
background-color: var(--wk-color-secondary);
body[theme-mode=dark] .wk-chat-conversation-header {
background-color: var(--wk-color-secondary);
}
.wk-chat-conversation-header-left {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.wk-chat-conversation-header-back {
width: 40px;
height: 40px;
display: none;
position: relative;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
display: none;
position: relative;
justify-content: center;
align-items: center;
}
.wk-chat-conversation-header-back-icon {
position: absolute;
/* transform: rotate(-45deg); */
transform: rotate(180deg);
position: absolute;
/* transform: rotate(-45deg); */
transform: rotate(180deg);
}
.wk-chat-conversation-header-back-icon::before,
.wk-chat-conversation-header-back-icon::after {
position: absolute;
left: 0;
top: 0;
content: "";
.wk-chat-conversation-header-back-icon::before, .wk-chat-conversation-header-back-icon::after {
position: absolute;
left: 0;
top: 0;
content: "";
}
.wk-chat-conversation-header-back-icon::after {
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::before {
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::before,
.wk-chat-conversation-header-back-icon::after {
width: 1.125rem;
height: 0.125rem;
border-radius: 0.125rem;
background-color: rgb(112, 117, 121);
transition: transform var(--wk-slide-transition);
.wk-chat-conversation-header-back-icon, .wk-chat-conversation-header-back-icon::before, .wk-chat-conversation-header-back-icon::after {
width: 1.125rem;
height: 0.125rem;
border-radius: 0.125rem;
background-color: rgb(112,117,121);
transition: transform var(--wk-slide-transition);
}
.wk-chat-conversation-header-channel {
display: flex;
display: flex;
}
.wk-chat-conversation-header-channel-avatar img {
width: 40px;
height: 40px;
border-radius: 40%;
width: 40px;
height: 40px;
border-radius: 40%;
}
.wk-chat-conversation-header-channel-info {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.wk-chat-conversation-header-channel-info-name {
margin-left: 10px;
font-size: 14px;
font-weight: 600;
margin-left: 10px;
font-size: 14px;
font-weight: 600;
}
body[theme-mode="dark"] .wk-chat-conversation-header-channel-info-name {
color: white;
body[theme-mode=dark] .wk-chat-conversation-header-channel-info-name {
color: white;
}
.wk-chat-conversation-header-content {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.wk-chat-conversation-header-right {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.wk-chat-conversation-header-right div {
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
.wk-chat-conversation-header-right div {
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.wk-chat-conversation-header-right div:last-child {
margin-right: 0px;
margin-right: 0px;
}
.wk-chat-conversation-header-setting {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.wk-chat-channelsetting {
@ -258,73 +257,68 @@ body[theme-mode=dark] .wk-chat-channelsetting {
}
.wk-chat-content-right.wk-chat-channelsetting-open .wk-chat-channelsetting {
margin-right: 0px;
margin-right: 0px;
}
.wk-chat-conversation-list-loading {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
display: flex;
width: 100%;
justify-content: center;
align-items: center;
}
.wk-chatmenuspopover {
width: 100%;
height: 100%;
width: 100%;
height: 100%;
}
.wk-chatmenuspopover ul {
margin-bottom: 0px;
width: 100%;
height: 100%;
margin-bottom: 0px;
width: 100%;
height: 100%;
}
body[theme-mode="dark"] .wk-chat-popover {
background-color: var(--wk-color-secondary);
color: white;
--color-popover-bg-default: red;
body[theme-mode=dark] .wk-chat-popover {
background-color: var(--wk-color-secondary);
color: white;
--color-popover-bg-default: red
}
.wk-chatmenuspopover li {
display: flex;
align-items: center;
cursor: pointer;
padding: 10px;
display: flex;
align-items: center;
cursor: pointer;
padding: 10px;
}
.wk-chatmenuspopover li:first-child {
margin-top: 0px;
margin-top: 0px;
}
.wk-chatmenuspopover li img {
width: 18px;
height: 18px;
color: white;
width: 20px;
height: 20px;
color: white;
}
.wk-chatmenuspopover-title {
margin-left: 10px;
font-size: 14px;
}
.wk-chatmenuspopover-avatar {
display: flex;
align-items: center;
margin-left: 10px;
font-size: 14px;
}
.wk-chat-conversation-header-right-item {
position: relative;
position: relative;
}
.wk-conversation-header-mask {
background-color: rgb(0, 0, 0, 0);
position: absolute;
width: 100%;
height: 100%;
top: 0px;
border-radius: 100%;
background-color: rgb(0,0,0,0.0);
position: absolute;
width: 100%;
height: 100%;
top: 0px;
border-radius: 100%;
}
.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";
}
init(): void {
APIClient.shared.logoutCallback = () => {
WKApp.shared.logout();
};
@ -227,9 +229,7 @@ export default class BaseModule implements IModule {
cmdContent.param.from_name
);
} else if (cmdContent.cmd === "groupAvatarUpdate") {
WKApp.shared.changeChannelAvatarTag(
new Channel(param.group_no, ChannelTypeGroup)
);
WKApp.shared.changeChannelAvatarTag(new Channel(param.group_no, ChannelTypeGroup));
// 群头像更新
WKSDK.shared().channelManager.fetchChannelInfo(
new Channel(param.group_no, ChannelTypeGroup)
@ -343,11 +343,8 @@ export default class BaseModule implements IModule {
ConversationAction.update
);
}
} else if (cmdContent.cmd === "userAvatarUpdate") {
// 用户头像更新
WKApp.shared.changeChannelAvatarTag(
new Channel(param.uid, ChannelTypePerson)
);
} else if (cmdContent.cmd === "userAvatarUpdate") { // 用户头像更新
WKApp.shared.changeChannelAvatarTag(new Channel(param.uid, ChannelTypePerson));
WKApp.dataSource.notifyContactsChange();
}
});
@ -453,16 +450,15 @@ export default class BaseModule implements IModule {
return;
}
if (window.Notification && Notification.permission !== "denied") {
const options = {
body: description,
icon: WKApp.shared.avatarChannel(message.channel),
lang: "zh-CN",
tag: "tag",
renotify: true,
};
const notify = new Notification(
channelInfo ? channelInfo.orgData.displayName : "通知",
options
{
body: description,
icon: WKApp.shared.avatarChannel(message.channel),
lang: "zh-CN",
tag: "tag",
// renotify: true,
}
);
notify.onclick = () => {
@ -513,7 +509,7 @@ export default class BaseModule implements IModule {
icon={require("./assets/toolbars/func_screenshot.svg").default}
onClick={() => {
if ((window as any).__POWERED_ELECTRON__) {
(window as any).ipc.send("screenshots-start", {});
(window as any).ipc.send('screenshots-start', {})
} else {
window.open("https://www.snipaste.com");
}
@ -536,11 +532,10 @@ export default class BaseModule implements IModule {
const isDark = WKApp.config.themeMode === ThemeMode.dark;
return {
title: "发起群聊",
icon: require(`${
isDark
? "./assets/popmenus_startchat_dark.png"
: "./assets/popmenus_startchat.png"
}`),
icon: require(`${isDark
? "./assets/popmenus_startchat_dark.png"
: "./assets/popmenus_startchat.png"
}`),
onClick: () => {
const channel: any = {
channelID: localStorage.uid,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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