mirror of
https://github.com/TangSengDaoDao/TangSengDaoDaoWeb
synced 2025-06-04 08:08:44 +00:00
591 lines
19 KiB
TypeScript
591 lines
19 KiB
TypeScript
import { EndpointCommon } from "./EndpointCommon";
|
||
import APIClient from "./Service/APIClient";
|
||
import MenusManager from "./Service/Menus";
|
||
import { EndpointManager, IModule, ModuleManager } from "./Service/Module";
|
||
import { ProviderListener } from "./Service/Provider";
|
||
import RouteManager, { ContextRouteManager } from "./Service/Route";
|
||
import { Channel, ChannelTypeGroup, ChannelTypePerson, WKSDK, Message, MessageContentType } from "wukongimjssdk";
|
||
import { IConversationProvider } from "./Service/DataSource/DataProvider";
|
||
import MessageManager from "./Service/MessageManager";
|
||
import { DefaultEmojiService, EmojiService } from "./Service/EmojiService";
|
||
import SectionManager, { Row, Section } from "./Service/Section";
|
||
import { EndpointCategory } from "./Service/Const";
|
||
import { DataSource } from "./Service/DataSource/DataSource";
|
||
import { ConnectAddrCallback } from "wukongimjssdk";
|
||
|
||
import 'animate.css';
|
||
import "./App.css"
|
||
import RouteContext from "./Service/Context";
|
||
import { ConnectStatus } from "wukongimjssdk";
|
||
import { WKBaseContext } from "./Components/WKBase";
|
||
import StorageService from "./Service/StorageService";
|
||
import axios from "axios";
|
||
|
||
export enum ThemeMode {
|
||
light,
|
||
dark
|
||
}
|
||
export class WKConfig {
|
||
appName: string = "唐僧叨叨"
|
||
appVersion: string = "0.0.0" // app版本
|
||
themeColor: string = "#E46342" // 主题颜色
|
||
secondColor: string = "rgba(232, 234, 237)"
|
||
pageSize: number = 15 // 数据页大小
|
||
pageSizeOfMessage: number = 30 // 每次请求消息数量
|
||
fileHelperUID: string = "fileHelper" // 文件助手UID
|
||
systemUID: string = "u_10000" // 系统uid
|
||
|
||
private _themeMode: ThemeMode = ThemeMode.light // 主题模式
|
||
|
||
set themeMode(v: ThemeMode) {
|
||
this._themeMode = v
|
||
const body = document.body;
|
||
if (v === ThemeMode.dark) {
|
||
if (body.hasAttribute('theme-mode')) {
|
||
body.removeAttribute('theme-mode');
|
||
body.setAttribute('theme-mode', 'dark');
|
||
} else {
|
||
body.setAttribute('theme-mode', 'dark');
|
||
}
|
||
} else {
|
||
body.removeAttribute('theme-mode');
|
||
}
|
||
StorageService.shared.setItem("theme-mode", `${v}`)
|
||
WKApp.shared.notifyListener()
|
||
}
|
||
|
||
get themeMode() {
|
||
return this._themeMode
|
||
}
|
||
|
||
}
|
||
|
||
export class WKRemoteConfig {
|
||
revokeSecond: number = 2 * 60 // 撤回时间
|
||
requestSuccess: boolean = false
|
||
|
||
async startRequestConfig() {
|
||
await this.requestConfig()
|
||
|
||
if (!this.requestSuccess) {
|
||
setTimeout(() => {
|
||
this.startRequestConfig()
|
||
}, 3000);
|
||
}
|
||
}
|
||
|
||
requestConfig() {
|
||
return WKApp.apiClient.get("common/appconfig").then((result) => {
|
||
this.requestSuccess = true
|
||
this.revokeSecond = result["revoke_second"]
|
||
})
|
||
}
|
||
}
|
||
|
||
export type MessageDeleteListener = (message: Message, preMessage?: Message) => void;
|
||
|
||
export class LoginInfo {
|
||
appID!: string
|
||
shortNo!: string // 短号
|
||
token?: string
|
||
uid?: string
|
||
name: string | undefined
|
||
role!: string
|
||
isWork!: boolean
|
||
sex!: number
|
||
|
||
/**
|
||
* save 保存登录信息
|
||
*/
|
||
public save() {
|
||
|
||
this.setStorageItemForSID("app_id", this.appID ?? "")
|
||
this.setStorageItemForSID("short_no", this.shortNo ?? "")
|
||
this.setStorageItemForSID("uid", this.uid ?? "");
|
||
this.setStorageItemForSID("token", this.token ?? "");
|
||
this.setStorageItemForSID("name", this.name ?? "");
|
||
this.setStorageItemForSID("role", this.role ?? "")
|
||
this.setStorageItemForSID("is_work", this.isWork ? "1" : "0")
|
||
this.setStorageItemForSID("sex", this.sex == 1 ? "1" : "0")
|
||
}
|
||
|
||
// 获取查询参数
|
||
public getQueryVariable(variable: string) {
|
||
var query = window.location.search.substring(1);
|
||
var vars = query.split("&");
|
||
for (var i = 0; i < vars.length; i++) {
|
||
var pair = vars[i].split("=");
|
||
if (pair[0] === variable) { return pair[1]; }
|
||
}
|
||
return (false);
|
||
}
|
||
|
||
public setStorageItemForSID(key: string, value: string) {
|
||
let sid = this.getSID()
|
||
|
||
this.setStorageItem(key + sid, value)
|
||
}
|
||
|
||
public getStorageItemForSID(key: string): string | null {
|
||
let sid = this.getSID()
|
||
return this.getStorageItem(key + sid)
|
||
}
|
||
|
||
public removeStorageItemForSID(key: string) {
|
||
let sid = this.getSID()
|
||
this.removeStorageItem(key + sid)
|
||
}
|
||
|
||
public getSID(): string {
|
||
let sid = this.getQueryVariable("sid") || "";
|
||
return sid
|
||
}
|
||
|
||
public setStorageItem(key: string, value: string) {
|
||
StorageService.shared.setItem(key, value)
|
||
}
|
||
public getStorageItem(key: string): string | null {
|
||
return StorageService.shared.getItem(key)
|
||
}
|
||
public removeStorageItem(key: string) {
|
||
StorageService.shared.removeItem(key)
|
||
}
|
||
|
||
|
||
/**
|
||
* load 加载登录信息
|
||
*/
|
||
public load() {
|
||
this.uid = this.getStorageItemForSID('uid') || '';
|
||
this.shortNo = this.getStorageItemForSID('short_no') || '';
|
||
this.token = this.getStorageItemForSID('token') || '';
|
||
this.name = this.getStorageItemForSID("name") || "";
|
||
this.appID = this.getStorageItemForSID("app_id") || '';
|
||
this.role = this.getStorageItemForSID("role") || ''
|
||
const isWorkStr = this.getStorageItemForSID("is_work")
|
||
if (isWorkStr === "1") {
|
||
this.isWork = true
|
||
} else {
|
||
this.isWork = false
|
||
}
|
||
|
||
const sexStr = this.getStorageItemForSID("sex")
|
||
if (sexStr === "1") {
|
||
this.sex = 1
|
||
} else {
|
||
this.sex = 0
|
||
}
|
||
}
|
||
// 是否登录
|
||
isLogined() {
|
||
if (!this.token || this.token === '') {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
logout() {
|
||
this.token = undefined;
|
||
this.appID = "";
|
||
this.role = ""
|
||
this.removeStorageItem('token');
|
||
this.removeStorageItem('app_id')
|
||
this.removeStorageItem('role')
|
||
this.removeStorageItem('is_work')
|
||
}
|
||
}
|
||
|
||
|
||
export default class WKApp extends ProviderListener {
|
||
private constructor() {
|
||
super()
|
||
}
|
||
public static shared = new WKApp()
|
||
static route = RouteManager.shared // 路由管理
|
||
static routeLeft = new ContextRouteManager() // 左边页面路由
|
||
static routeRight = new ContextRouteManager() // 右边(main)页面路由
|
||
static menus = MenusManager.shared // 菜单
|
||
static apiClient = APIClient.shared // api客户端
|
||
static config: WKConfig = new WKConfig() // app配置
|
||
static remoteConfig: WKRemoteConfig = new WKRemoteConfig() // 远程配置
|
||
static loginInfo: LoginInfo = new LoginInfo() // 登录信息
|
||
static endpoints: EndpointCommon = new EndpointCommon() // 常用端点
|
||
static conversationProvider: IConversationProvider // 最近会话相关数据源
|
||
static messageManager: MessageManager = new MessageManager() // 消息管理
|
||
static emojiService: EmojiService = DefaultEmojiService.shared // emoji
|
||
static sectionManager: SectionManager = new SectionManager() // section管理
|
||
static dataSource: DataSource = new DataSource() // 数据源
|
||
static endpointManager: EndpointManager = EndpointManager.shared // 端点管理
|
||
private messageDeleteListeners: MessageDeleteListener[] = new Array<MessageDeleteListener>(); // 消息删除监听
|
||
|
||
supportFavorites = [MessageContentType.text, MessageContentType.image] // 注册收藏的消息
|
||
|
||
notSupportForward: number[] = [] // 不支持转发的消息
|
||
|
||
openChannel?: Channel // 当前打开的会话频道
|
||
content?: JSX.Element
|
||
|
||
baseContext!: WKBaseContext // 唐僧叨叨基础上下文
|
||
|
||
|
||
private _notificationIsClose: boolean = false // 通知是否关闭
|
||
|
||
private wsaddrs = new Array<string>() // ws的连接地址
|
||
private addrUsed = false // 地址是否被使用
|
||
|
||
set notificationIsClose(v: boolean) {
|
||
this._notificationIsClose = v
|
||
StorageService.shared.setItem("NotificationIsClose", v ? "1" : "")
|
||
}
|
||
|
||
get notificationIsClose() {
|
||
return this._notificationIsClose
|
||
}
|
||
|
||
|
||
// app启动
|
||
startup() {
|
||
WKApp.loginInfo.load() // 加载登录信息
|
||
|
||
const themeMode = StorageService.shared.getItem("theme-mode")
|
||
if (themeMode === "1") {
|
||
WKApp.config.themeMode = ThemeMode.dark
|
||
}
|
||
|
||
WKSDK.shared().config.provider.connectAddrCallback = async (callback: ConnectAddrCallback) => {
|
||
if (!this.wsaddrs || this.wsaddrs.length == 0) {
|
||
this.wsaddrs = await WKApp.dataSource.commonDataSource.imConnectAddrs()
|
||
}
|
||
if (this.wsaddrs.length > 0) {
|
||
console.log("connectAddrs--->", this.wsaddrs)
|
||
this.addrUsed = true
|
||
callback(this.wsaddrs[0])
|
||
}
|
||
|
||
}
|
||
|
||
WKApp.endpoints.addOnLogin(() => {
|
||
this.startMain()
|
||
})
|
||
|
||
if (WKApp.loginInfo.isLogined()) {
|
||
this.startMain()
|
||
}
|
||
|
||
WKSDK.shared().connectManager.addConnectStatusListener((status: ConnectStatus, reasonCode?: number) => {
|
||
if (status === ConnectStatus.ConnectKick) {
|
||
console.log("被踢--->", reasonCode)
|
||
WKApp.shared.logout()
|
||
} else if (reasonCode == 2) { // 认证失败!
|
||
WKApp.shared.logout()
|
||
} else if (status === ConnectStatus.Disconnect) {
|
||
if (this.addrUsed && this.wsaddrs.length > 1) {
|
||
const oldwsAddr = this.wsaddrs[0]
|
||
this.wsaddrs.splice(0, 1)
|
||
this.wsaddrs.push(oldwsAddr)
|
||
this.addrUsed = false
|
||
console.log("连接失败!切换地址->", this.wsaddrs)
|
||
}
|
||
|
||
|
||
}
|
||
})
|
||
|
||
// 通知设置
|
||
const notificationIsClose = StorageService.shared.getItem("NotificationIsClose")
|
||
if (notificationIsClose === "1") {
|
||
this._notificationIsClose = true
|
||
} else {
|
||
this._notificationIsClose = false
|
||
}
|
||
|
||
WKApp.remoteConfig.startRequestConfig()
|
||
|
||
}
|
||
|
||
startMain() {
|
||
this.connectIM()
|
||
WKApp.dataSource.contactsSync()
|
||
}
|
||
|
||
connectIM() {
|
||
WKSDK.shared().config.uid = WKApp.loginInfo.uid
|
||
WKSDK.shared().config.token = WKApp.loginInfo.token
|
||
WKSDK.shared().connect()
|
||
}
|
||
|
||
registerModule(module: IModule) {
|
||
ModuleManager.shared.register(module);
|
||
}
|
||
|
||
restContent(content: JSX.Element) {
|
||
this.content = content
|
||
this.notifyListener()
|
||
}
|
||
|
||
|
||
|
||
// 是否登录
|
||
isLogined() {
|
||
return WKApp.loginInfo.isLogined()
|
||
}
|
||
// 登出
|
||
logout() {
|
||
WKApp.loginInfo.logout()
|
||
window.location.reload()
|
||
}
|
||
|
||
avatarChannel(channel: Channel) {
|
||
if (!channel) {
|
||
return ""
|
||
}
|
||
let avatarTag = this.getChannelAvatarTag()
|
||
if (!avatarTag) {
|
||
avatarTag = "0"
|
||
}
|
||
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel)
|
||
if (channelInfo && channelInfo.logo && channelInfo.logo !== "") {
|
||
let logo = channelInfo.logo;
|
||
if (logo.indexOf("?") != -1) {
|
||
logo += "&v=" + avatarTag
|
||
} else {
|
||
logo += "?v=" + avatarTag
|
||
}
|
||
return WKApp.dataSource.commonDataSource.getImageURL(logo)
|
||
}
|
||
const baseURl = WKApp.apiClient.config.apiURL
|
||
if (channel.channelType === ChannelTypePerson) {
|
||
return `${baseURl}users/${channel.channelID}/avatar?v=${avatarTag}`
|
||
} else if (channel.channelType == ChannelTypeGroup) {
|
||
return `${baseURl}groups/${channel.channelID}/avatar?v=${avatarTag}`
|
||
}
|
||
return ""
|
||
}
|
||
|
||
avatarUser(uid: string) {
|
||
const c = new Channel(uid, ChannelTypePerson)
|
||
return this.avatarChannel(c)
|
||
}
|
||
|
||
// 我的用户头像发送改变
|
||
myUserAvatarChange() {
|
||
this.changeChannelAvatarTag()
|
||
}
|
||
|
||
changeChannelAvatarTag() {
|
||
let myAvatarTag = "channelAvatarTag"
|
||
WKApp.loginInfo.setStorageItem(myAvatarTag, new Date().getTime() + "")
|
||
}
|
||
getChannelAvatarTag() {
|
||
let myAvatarTag = "channelAvatarTag"
|
||
const tag = WKApp.loginInfo.getStorageItem(myAvatarTag)
|
||
if (!tag) {
|
||
return ""
|
||
}
|
||
return tag
|
||
}
|
||
|
||
avatarGroup(groupNo: string) {
|
||
const channel = new Channel(groupNo, ChannelTypeGroup)
|
||
return this.avatarChannel(channel)
|
||
}
|
||
|
||
// 注册频道设置
|
||
channelSettingRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined, sort?: number) {
|
||
WKApp.sectionManager.register(EndpointCategory.channelSetting, sectionID, sectionFnc, sort)
|
||
}
|
||
|
||
// 获取频道设置
|
||
channelSettings(context: RouteContext<any>): Section[] {
|
||
return WKApp.sectionManager.sections(EndpointCategory.channelSetting, context)
|
||
}
|
||
|
||
// 注册管理设置
|
||
channelManageRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined) {
|
||
WKApp.sectionManager.register(EndpointCategory.channelManage, sectionID, sectionFnc)
|
||
}
|
||
|
||
// 获取频道管理
|
||
channelManages(context: RouteContext<any>): Section[] {
|
||
return WKApp.sectionManager.sections(EndpointCategory.channelManage, context)
|
||
}
|
||
|
||
chatMenusRegister(sid: string, f: (param: any) => ChatMenus, sort?: number) {
|
||
WKApp.endpointManager.setMethod(sid, (param) => {
|
||
return f(param)
|
||
}, {
|
||
category: EndpointCategory.chatMenusPopover,
|
||
sort: sort,
|
||
})
|
||
}
|
||
chatMenus(param?: any): ChatMenus[] {
|
||
return WKApp.endpointManager.invokes<ChatMenus>(EndpointCategory.chatMenusPopover, param)
|
||
}
|
||
|
||
sectionAddRow(sectionID: string, row: Row, context: RouteContext<any>) {
|
||
const section = WKApp.sectionManager.section(sectionID, context)
|
||
if (section) {
|
||
if (!section.rows) {
|
||
section.rows = []
|
||
}
|
||
section.rows.push(row)
|
||
}
|
||
}
|
||
|
||
// 注册用户信息
|
||
userInfoRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined, sort?: number) {
|
||
WKApp.sectionManager.register(EndpointCategory.userInfo, sectionID, sectionFnc)
|
||
}
|
||
|
||
// 获取用户信息
|
||
userInfos(context: RouteContext<any>): Section[] {
|
||
return WKApp.sectionManager.sections(EndpointCategory.userInfo, context)
|
||
}
|
||
|
||
private getFriendApplysKey() {
|
||
return `${WKApp.loginInfo.uid}friendApplys`
|
||
}
|
||
|
||
|
||
public getFriendApplys(): Array<FriendApply> {
|
||
var friendApplys = new Array<FriendApply>()
|
||
const value = WKApp.loginInfo.getStorageItem(this.getFriendApplysKey())
|
||
if (!value || value === "") {
|
||
return friendApplys
|
||
}
|
||
const friendApplyObjs = JSON.parse(value)
|
||
|
||
if (friendApplyObjs && friendApplyObjs.length > 0) {
|
||
for (const friendApplyObj of friendApplyObjs) {
|
||
const f = new FriendApply()
|
||
f.uid = friendApplyObj.uid
|
||
f.name = friendApplyObj.name
|
||
f.remark = friendApplyObj.remark
|
||
f.state = friendApplyObj.state
|
||
f.token = friendApplyObj.token
|
||
f.unread = friendApplyObj.unread
|
||
f.createdAt = friendApplyObj.createdAt
|
||
friendApplys.push(f)
|
||
}
|
||
}
|
||
friendApplys.sort((a, b) => {
|
||
return b.createdAt - a.createdAt
|
||
})
|
||
return friendApplys
|
||
}
|
||
|
||
public getFriendApplysUnreadCount() {
|
||
const friendApplys = this.getFriendApplys()
|
||
let unreadCount = 0
|
||
if (friendApplys && friendApplys.length > 0) {
|
||
for (const friendApply of friendApplys) {
|
||
if (friendApply.unread) {
|
||
unreadCount++
|
||
}
|
||
}
|
||
}
|
||
return unreadCount
|
||
}
|
||
|
||
public friendApplyMarkAllReaded() {
|
||
let friendApplys = this.getFriendApplys()
|
||
if (!friendApplys) {
|
||
friendApplys = new Array<FriendApply>()
|
||
}
|
||
var change = false
|
||
for (const friendApply of friendApplys) {
|
||
if (friendApply.unread) {
|
||
friendApply.unread = false
|
||
change = true
|
||
}
|
||
}
|
||
if (change) {
|
||
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
|
||
WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange)
|
||
}
|
||
}
|
||
|
||
public addFriendApply(friendApply: FriendApply) {
|
||
let friendApplys = this.getFriendApplys()
|
||
if (!friendApplys) {
|
||
friendApplys = new Array<FriendApply>()
|
||
}
|
||
|
||
var exist = false
|
||
for (let index = 0; index < friendApplys.length; index++) {
|
||
const friendAy = friendApplys[index];
|
||
if (friendAy.uid === friendApply.uid) {
|
||
friendApplys[index] = friendApply
|
||
exist = true
|
||
break
|
||
}
|
||
}
|
||
if (!exist) {
|
||
friendApplys.push(friendApply)
|
||
}
|
||
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
|
||
WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange)
|
||
}
|
||
|
||
public updateFriendApply(friendApply: FriendApply) {
|
||
let friendApplys = this.getFriendApplys()
|
||
if (!friendApplys) {
|
||
friendApplys = new Array<FriendApply>()
|
||
}
|
||
var exist = false
|
||
for (let index = 0; index < friendApplys.length; index++) {
|
||
const friendAy = friendApplys[index];
|
||
if (friendAy.uid === friendApply.uid) {
|
||
friendApplys[index] = friendApply
|
||
exist = true
|
||
break
|
||
}
|
||
}
|
||
if (exist) {
|
||
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
|
||
}
|
||
}
|
||
|
||
public addMessageDeleteListener(listener: MessageDeleteListener) {
|
||
this.messageDeleteListeners.push(listener)
|
||
}
|
||
public removeMessageDeleteListener(listener: MessageDeleteListener) {
|
||
const len = this.messageDeleteListeners.length;
|
||
for (let i = 0; i < len; i++) {
|
||
if (listener === this.messageDeleteListeners[i]) {
|
||
this.messageDeleteListeners.splice(i, 1)
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
public notifyMessageDeleteListener(message: Message, preMessage?: Message) {
|
||
const len = this.messageDeleteListeners.length;
|
||
for (let i = 0; i < len; i++) {
|
||
this.messageDeleteListeners[i](message, preMessage)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
export enum FriendApplyState {
|
||
apply,
|
||
accepted
|
||
}
|
||
// 好友申请
|
||
export class FriendApply {
|
||
uid!: string
|
||
name!: string
|
||
remark?: string
|
||
token?: string
|
||
state!: FriendApplyState
|
||
unread: boolean = false // 是否未读
|
||
createdAt!: number // 创建时间
|
||
}
|
||
|
||
|
||
export class ChatMenus {
|
||
icon!: string
|
||
title!: string
|
||
sort?: number = 0
|
||
onClick?: () => void
|
||
} |