更新云信相关代码

This commit is contained in:
XiuYun CHEN
2025-07-10 08:57:32 +08:00
parent a297e0452f
commit 5954f51701
523 changed files with 61546 additions and 1488 deletions
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
* Use of this source code is governed by a MIT license that can be
* found in the LICENSE file.
*
*/
import { preferenceStore,BasicConstant } from '@itcast/basic'
export class AppConfig {
// appKey 和 userName 在网易云信控制台获取
// appKey 网易云信应用appkey
// public static appKey: string = '885dea390870814acf3ba8558c717572'
// // userName 网易云信应用下账号ID
// public static userId: string = 'ga5lemoxchskxmrqfnl'
// // userName 网易云信应用下账号Token
// public static userToken: string = '81900d287f6102fca1b27ae0302a2633'
public static appKey: string = '885dea390870814acf3ba8558c717572'
// userName 网易云信应用下账号ID
public static userId: string = preferenceStore.getItemString(BasicConstant.YX_accid)
// userName 网易云信应用下账号Token
public static userToken: string = preferenceStore.getItemString(BasicConstant.YX_token)
}
@@ -0,0 +1,70 @@
/**
* IMBackgroundTask
* NIM-WS-TS
*
* @author hongru
* @since 2025−04-17
*
* Copyright © 2025 Netease. All rights reserved.
*/
import { backgroundTaskManager } from "@kit.BackgroundTasksKit";
import { BusinessError } from "@kit.BasicServicesKit";
const TAG = '[IMBackgroundTask]'
export class IMBackgroundTask {
private taskId?: number // 申请短期任务ID
private delayTime?: number; // 本次申请短时任务的剩余时间
private static instance: IMBackgroundTask;
public static getInstance(): IMBackgroundTask {
if (!IMBackgroundTask.instance) {
IMBackgroundTask.instance = new IMBackgroundTask();
}
return IMBackgroundTask.instance;
}
constructor() {
}
// 申请短时任务
requestSuspendDelay() {
try {
console.info(TAG, 'requestSuspendDelay')
let myReason = 'data storage request suspend delay'; // 申请原因
let delayInfo = backgroundTaskManager.requestSuspendDelay(myReason, () => {
// 回调函数。应用申请的短时任务即将超时,通过此函数回调应用,执行一些清理和标注工作,并取消短时任务
console.info(TAG, 'suspend delay task will timeout');
if (this.taskId) {
backgroundTaskManager.cancelSuspendDelay(this.taskId);
}
})
this.taskId = delayInfo.requestId;
this.delayTime = delayInfo.actualDelayTime;
console.info(TAG, `requestSuspendDelay id: ${delayInfo.requestId} time: ${delayInfo.actualDelayTime}`)
} catch (e) {
console.warn(TAG, 'requestSuspendDelay failed', e)
}
}
async getRemainingDelayTime() {
backgroundTaskManager.getRemainingDelayTime(this.taskId).then((res: number) => {
console.info(TAG, 'Succeeded in getting remaining delay time.', res);
}).catch((err: BusinessError) => {
console.error(TAG, `Failed to get remaining delay time. Code: ${err.code}, message: ${err.message}`);
})
}
cancelSuspendDelay() {
try {
if (this.taskId) {
console.info(TAG, 'cancelSuspendDelay')
backgroundTaskManager.cancelSuspendDelay(this.taskId);
}
} catch (e) {
console.warn(TAG, 'cancelSuspendDelay failed', e)
}
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
* Use of this source code is governed by a MIT license that can be
* found in the LICENSE file.
*
*/
/**
* Route constants for Router.
*/
export class RouteConstants {
/**
* Route of page for the ResponsiveLayout.
*/
static readonly RESPONSIVE_ROUTE: string = 'pages/ResponsiveIndex';
/**
* Route of page for the AdaptiveLayout.
*/
static readonly ADAPTIVE_ROUTE: string = 'pages/AdaptiveIndex';
/**
* Route of page for the SystemCapabilities.
*/
static readonly SYSTEM_CAPABILITIES_ROUTE: string = 'pages/SystemCapabilitiesIndex';
}
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
* Use of this source code is governed by a MIT license that can be
* found in the LICENSE file.
*
*/
import common from '@ohos.app.ability.common'
import { LogLevel, NIMInitializeOptions, NIMInterface, NIMServiceOptions,
V2NIMEnableServiceType,
V2NIMProvidedServiceType } from '@nimsdk/base'
import { NIMSdk } from '@nimsdk/nim'
import { V2NIMTeamServiceImpl } from '@nimsdk/team'
import { V2NIMConversationServiceImpl } from '@nimsdk/conversation'
import { V2NIMUserServiceImpl } from '@nimsdk/user'
import { V2NIMFriendServiceImpl } from '@nimsdk/friend'
import { V2NIMClientAntispamUtil, V2NIMMessageServiceImpl } from '@nimsdk/message'
import { AppConfig } from '../constants/AppConfig'
import { ChatKitClient, IMKitConfigCenter } from '@nimkit/chatkit'
import { router } from '@kit.ArkUI'
import { IMSDKConfigManager } from '../manager/IMSDKConfigManager'
import { V2NIMLocalConversationServiceImpl } from '@nimsdk/localconversation'
export class NimRepository {
private static instance?: NimRepository
private _context: common.Context
constructor(context: common.Context) {
this._context = context
}
private _nim: NIMInterface | undefined
public get nim(): NIMInterface {
if (!this._nim) {
this.createDefaultNim(this._context)
}
return this._nim!
}
public static getInstance(context: common.Context): NimRepository {
if (!NimRepository.instance) {
NimRepository.instance = new NimRepository(context)
NimRepository.instance.nim
}
return NimRepository.instance
}
async login(accountId: string, token: string, appKey: string) {
try {
console.debug(`Performance Test im start loginSuccess`)
await this.nim.loginService.login(accountId, token);
console.error('----------- 登录成功 -----------')
router.pushUrl({
url: 'pages/Netease/imTabPage'
});
console.debug(`Performance Test im loginSuccess`)
ChatKitClient.init(this.nim, appKey)
} catch (error) {
console.error('----------- 登录失败 -----------', error)
throw error as Error
}
}
createDefaultNim(context: common.Context) {
console.warn('------------- 创建NIM实例 --------------')
let initializeOptions: NIMInitializeOptions = {
appkey: AppConfig.appKey,
}
let serviceOptions: NIMServiceOptions = {
loginServiceConfig: {},
}
// 正式服
initializeOptions = {
appkey: AppConfig.appKey,
logLevel: LogLevel.Debug,
// ...其他属性
};
const customConfig = IMSDKConfigManager.getConfig()
if (customConfig?.enableCustomConfig) {
if (customConfig.configOptions) {
serviceOptions = customConfig.configOptions
let appKey = serviceOptions.databaseServiceConfig?.appKey
if (appKey) {
initializeOptions.appkey = appKey
}
}
} else {
serviceOptions = {
loginServiceConfig: {
lbsUrls: ['https://lbs.netease.im/lbs/webconf.jsp'],
linkUrl: 'weblink.netease.im:443'
//lbsUrls: ['https://imtest.netease.im/lbs/webconf'],
//linkUrl: 'imtest-jd.netease.im:8091'
},
pushServiceConfig: {
harmonyCertificateName: "DEMO_HMOS_PUSH"
},
databaseServiceConfig: {
encrypt: false,
appKey: AppConfig.appKey,
}
}
}
this.initNim(initializeOptions, serviceOptions)
console.log("net ease nim from createDefaultNim: " + this._nim)
}
initNim(initializeOptions: NIMInitializeOptions, serviceOptions?: NIMServiceOptions) {
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_TEAM,
(core, serviceName, serviceConfig) => new V2NIMTeamServiceImpl(core, serviceName, serviceConfig))
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_CLIENT_ANTISPAM_UTIL,
(core, serviceName, serviceConfig) => new V2NIMClientAntispamUtil(core, serviceName, serviceConfig));
// if (IMKitConfigCenter.enableLocalConversation) {
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_LOCAL_CONVERSATION,
(core, serviceName, serviceConfig) => new V2NIMLocalConversationServiceImpl(core, serviceName, serviceConfig));
// } else {
// NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_CONVERSATION,
// (core, serviceName, serviceConfig) => new V2NIMConversationServiceImpl(core, serviceName, serviceConfig));
// }
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_MESSAGE,
(core, serviceName, serviceConfig) => new V2NIMMessageServiceImpl(core, serviceName, serviceConfig));
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_USER,
(core, serviceName, serviceConfig) => new V2NIMUserServiceImpl(core, serviceName, serviceConfig));
NIMSdk.registerCustomServices(V2NIMProvidedServiceType.V2NIM_PROVIDED_SERVICE_FRIEND,
(core, serviceName, serviceConfig) => new V2NIMFriendServiceImpl(core, serviceName, serviceConfig));
initializeOptions.isOpenConsoleLog = true
this._nim = NIMSdk.newInstance(this._context, initializeOptions, serviceOptions)
console.log("nim from initNim: " + this._nim)
}
isLocalConversation(): boolean {
if (this._nim?.isServiceEnable(V2NIMEnableServiceType.LOCAL_CONVERSATION)) {
return true
}
return false
}
}
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
* Use of this source code is governed by a MIT license that can be
* found in the LICENSE file.
*
*/
import fs from '@ohos.file.fs';
import { NIMServiceOptions } from '@nimsdk/base';
export class IMSDKConfigModel {
configOptions?: NIMServiceOptions
customJson?: string
enableCustomConfig: boolean = false
accountId?: string
accountIdToken?: string
}
export class IMSDKConfigManager {
static configModel?: IMSDKConfigModel
static fileName = 'sdk_config'
/// 保存私有化配置
static saveConfig(model: IMSDKConfigModel) {
IMSDKConfigManager.clearConfig()
IMSDKConfigManager.configModel = model
let path = getContext().filesDir + '/' + IMSDKConfigManager.fileName
// 新建并打开文件
let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 写入一段内容至文件
fs.writeSync(file.fd, JSON.stringify(model));
// 关闭文件
fs.closeSync(file);
}
/// 获取私有化配置
static getConfig() {
if (IMSDKConfigManager.configModel) {
return IMSDKConfigManager.configModel
}
let path = getContext().filesDir + '/' + IMSDKConfigManager.fileName
if (fs.accessSync(path)) {
const line = fs.readTextSync(path)
const data = JSON.parse(line) as IMSDKConfigModel
if (data) {
IMSDKConfigManager.configModel = data
return data
}
}
return undefined
}
/// 删除配置
static clearConfig() {
let path = getContext().filesDir + '/' + IMSDKConfigManager.fileName
if (fs.accessSync(path)) {
fs.unlinkSync(path)
}
IMSDKConfigManager.configModel = undefined
}
}
@@ -3,6 +3,8 @@ import { BasicConstant, themeManager } from '@itcast/basic';
import { emitter } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { NimRepository } from '../entryability/NimRepository'
import { AppConfig } from '../constants/AppConfig'
@Entry
@Component
@@ -11,12 +13,23 @@ struct Home {
@Watch('onChangeIndex')
activeIndex: number = 0
login = async (accountId: string, token: string) => {
const nimRepository = NimRepository.getInstance(getContext(this))
try {
await nimRepository.login(accountId, token, AppConfig.appKey)
} catch (err) {
}
}
aboutToAppear(): void {
emitter.on({ eventId: 10000 }, (e) => {
if (e.data && e.data.activeIndex) {
this.activeIndex = e.data.activeIndex
}
})
this.login(AppConfig.userId, AppConfig.userToken)//暂时隐蔽云信登录
}
onChangeIndex() {
@@ -1,13 +1,31 @@
import { LoginComp } from 'register'
import { NimRepository } from '../../entryability/NimRepository'
import { AppConfig } from '../../constants/AppConfig'
@Entry
@Component
struct LoginPage {
@State
@Watch('onLogins')
logins: boolean=false
login = async (accountId: string, token: string) => {
const nimRepository = NimRepository.getInstance(getContext(this))
try {
await nimRepository.login(accountId, token, AppConfig.appKey)
} catch (err) {
}
}
build() {
Column() {
LoginComp()
LoginComp({ loginstatus: this.logins })
}
}
onLogins()
{
this.login(AppConfig.userId, AppConfig.userToken)
}
}
@@ -0,0 +1,17 @@
import { router } from '@kit.ArkUI'
import { ConsultationDetailComp } from 'netease'
@Entry
@Component
struct ConsultationDetailPage {
// @State params:Record<string, string> = router.getParams() as Record<string, string>;
build() {
RelativeContainer() {
ConsultationDetailComp()
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,15 @@
import { InterrogationDetailComp } from 'netease'
@Entry
@Component
struct InterrogationDetailCompPage {
build() {
RelativeContainer() {
InterrogationDetailComp()
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,15 @@
import { MyOpinionComp } from 'netease'
@Entry
@Component
struct MyOpinionPage {
build() {
RelativeContainer() {
MyOpinionComp()
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,15 @@
import { PatientSimplyComp } from 'netease'
@Entry
@Component
struct PatientSimplyPage {
build() {
RelativeContainer() {
PatientSimplyComp()
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,16 @@
import { PreviewPhotos } from '@itcast/basic';
// import { PreviewPhoto } from 'netease';
@Entry
@Component
struct PreviewPhotoPage {
@State message: string = 'Hello World';
build() {
RelativeContainer() {
PreviewPhotos()
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,35 @@
import { TabBarConsultationComp } from 'netease';
@Entry
@Component
struct PublicConsultationPage {
@State
@Watch('onChangeIndex')
activeIndex: number = 0
aboutToAppear(): void {
}
onChangeIndex() {
}
onPageShow(): void {
this.onChangeIndex()
}
onPageHide(): void {
this.onChangeIndex()
}
build() {
Flex() {
TabBarConsultationComp({ activeIndex: this.activeIndex})
}
.backgroundColor($r('app.color.white'))
// .backgroundColor(Color.Red)
// .height('100%')
// .width('100%')
}
}
@@ -0,0 +1,37 @@
import { TabBarComp } from 'netease';
@Entry
@Component
struct ImTabPage {
pathStack: NavPathStack = new NavPathStack()
@State
@Watch('onChangeIndex')
activeIndex: number = 0
aboutToAppear(): void {
// this.pathStack.pushPath({ name: "ChatP2PPage", param:'111111111234' })
}
onChangeIndex() {
}
onPageShow(): void {
this.onChangeIndex()
}
onPageHide(): void {
this.onChangeIndex()
}
build() {
Navigation(this.pathStack) {
Flex() {
TabBarComp({ activeIndex: this.activeIndex, pathStack: this.pathStack})
}
.backgroundColor($r('app.color.white'))
// .backgroundColor(Color.Red)
// .height('100%')
// .width('100%')
}
.mode(NavigationMode.Auto)
.hideTitleBar(true)
}
}
@@ -4,6 +4,7 @@ import { TabBarCompModel } from '../../models/TabBarCompModel'
import { TabBarItems } from '../../contants/TabBarItems'
import { BasicConstant,AESEncryptionDecryption,authStore,preferenceStore } from '@itcast/basic'
import mediaquery from '@ohos.mediaquery';
import { MessageComp } from 'netease'
@Component
export struct TabBarComp {
@@ -27,6 +27,13 @@
"pages/VideoPage/VideoGandanPage",
"pages/VideoPage/CommentReplyPage",
"pages/SearchPage/VideoSearchPage",
"pages/VideoPage/VideoSelectedPage"
"pages/VideoPage/VideoSelectedPage",
"pages/Netease/imTabPage",
"pages/Netease/PublicConsultationPage",
"pages/Netease/ConsultationDetailPage",
"pages/Netease/PreviewPhotoPage",
"pages/Netease/InterrogationDetailCompPage",
"pages/Netease/PatientSimplyPage",
"pages/Netease/MyOpinionPage"
]
}