在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备
-
安装DevEco Studio 3.1+:
- 从华为开发者官网下载最新版DevEco Studio
- 安装HarmonyOS 5.0 SDK
-
项目配置:
// module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.READ_MEDIA"},{"name": "ohos.permission.NOTIFICATION"}],"abilities": [{"name": "EntryAbility","type": "page","backgroundModes": ["dataTransfer"]}]} }
2. 企业微信核心功能实现
2.1 登录认证模块
// src/main/ets/model/WeComAuth.ts
import http from '@ohos.net.http';
import { Preferences } from '@ohos.data.preferences';export class WeComAuth {private static readonly CORP_ID = 'your_corp_id';private static readonly AGENT_ID = 'your_agent_id';private static readonly REDIRECT_URI = 'entry://com.your.app/auth';static async login(): Promise<boolean> {const httpRequest = http.createHttp();try {const response = await httpRequest.request(`https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=${this.CORP_ID}&agentid=${this.AGENT_ID}&redirect_uri=${encodeURIComponent(this.REDIRECT_URI)}`,{ method: 'GET' });if (response.responseCode === 302) {const authCode = this.extractAuthCode(response.header['Location']);return this.exchangeToken(authCode);}return false;} catch (err) {console.error(`Login failed: ${err.code}, ${err.message}`);return false;}}private static async exchangeToken(authCode: string): Promise<boolean> {// 实现token交换逻辑}
}
2.2 消息列表页面
// src/main/ets/pages/MessageList.ets
import { WeComMessage } from '../model/WeComMessage';@Entry
@Component
struct MessageList {@State messages: Array<WeComMessage> = [];private timer: number = 0;aboutToAppear() {this.loadMessages();this.timer = setInterval(() => this.loadMessages(), 60000); // 每分钟刷新}aboutToDisappear() {clearInterval(this.timer);}async loadMessages() {try {this.messages = await WeComMessage.getRecentMessages();} catch (err) {console.error(`Load messages failed: ${err}`);}}build() {List({ space: 10 }) {ForEach(this.messages, (msg: WeComMessage) => {ListItem() {MessageItem({ message: msg })}}, (msg) => msg.id.toString())}.onScrollIndex((start: number) => {if (start > this.messages.length - 5) {this.loadMoreMessages();}})}
}
2.3 单聊/群聊页面
// src/main/ets/pages/ChatPage.ets
import { WeComChat } from '../model/WeComChat';@Entry
@Component
struct ChatPage {@State messages: Array<WeComMessage> = [];@State inputText: string = '';private chatId: string;build() {Column() {// 消息列表List({ space: 5 }) {ForEach(this.messages, (msg) => {ListItem() {if (msg.isSelf) {RightMessage({ message: msg })} else {LeftMessage({ message: msg })}}})}.layoutWeight(1)// 输入区域Row() {TextInput({ text: this.inputText }).onChange((value: string) => {this.inputText = value;}).layoutWeight(1)Button('发送').onClick(() => {if (this.inputText.trim()) {this.sendMessage();}})}.height(60).padding(10)}}async sendMessage() {try {await WeComChat.sendTextMessage(this.chatId, this.inputText);this.inputText = '';this.loadMessages();} catch (err) {console.error(`Send message failed: ${err}`);}}
}
3. 企业微信API封装
// src/main/ets/api/WeComApi.ts
import http from '@ohos.net.http';
import { WeComToken } from '../model/WeComToken';export class WeComApi {private static readonly BASE_URL = 'https://qyapi.weixin.qq.com/cgi-bin';static async get<T>(endpoint: string, params?: Record<string, string>): Promise<T> {const token = await WeComToken.getAccessToken();const httpRequest = http.createHttp();let url = `${this.BASE_URL}${endpoint}?access_token=${token}`;if (params) {url += '&' + Object.entries(params).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&');}try {const response = await httpRequest.request(url, { method: 'GET' });const result = JSON.parse(response.result as string);if (result.errcode !== 0) {throw new Error(`WeCom API Error: ${result.errmsg}`);}return result as T;} catch (err) {console.error(`API request failed: ${err}`);throw err;}}static async post<T>(endpoint: string, data: object): Promise<T> {// 类似GET方法的实现,使用POST请求}
}
4. 通知功能实现
// src/main/ets/utils/NotificationUtil.ts
import notification from '@ohos.notification';export class NotificationUtil {static showMessageNotification(sender: string, content: string) {try {notification.publish({id: 1,contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,content: {title: `新消息: ${sender}`,text: content,additionalText: '来自企业微信'}});} catch (err) {console.error(`Show notification failed: ${err}`);}}static cancelAll() {notification.cancelAll();}
}
5. 数据持久化
// src/main/ets/data/WeComStorage.ts
import { Preferences } from '@ohos.data.preferences';export class WeComStorage {private static readonly PREFERENCES_NAME = 'wecom_storage';private static preferences: Preferences | null = null;static async getInstance(): Promise<Preferences> {if (!this.preferences) {this.preferences = await Preferences.getPreferences(globalThis.abilityContext, this.PREFERENCES_NAME);}return this.preferences;}static async saveUserInfo(userInfo: object): Promise<void> {const prefs = await this.getInstance();await prefs.put('user_info', JSON.stringify(userInfo));await prefs.flush();}static async getUserInfo(): Promise<object | null> {const prefs = await this.getInstance();const userInfoStr = await prefs.get('user_info', '');return userInfoStr ? JSON.parse(userInfoStr) : null;}
}
6. 企业微信UI组件库
6.1 消息气泡组件
// src/main/ets/components/MessageBubble.ets
@Component
export struct MessageBubble {private message: WeComMessage;build() {Column() {Text(this.message.sender).fontSize(14).fontColor('#888888')Text(this.message.content).padding(10).backgroundColor(this.message.isSelf ? '#95EC69' : '#FFFFFF').borderRadius(8).margin({ top: 5 })Text(this.message.time).fontSize(12).fontColor('#AAAAAA').align(Alignment.End).margin({ top: 5 })}.width('80%').alignItems(this.message.isSelf ? HorizontalAlign.End : HorizontalAlign.Start)}
}
6.2 通讯录联系人组件
// src/main/ets/components/ContactItem.ets
@Component
export struct ContactItem {private contact: WeComContact;build() {Row() {Image(this.contact.avatar).width(50).height(50).borderRadius(25).margin({ right: 10 })Column() {Text(this.contact.name).fontSize(18)Text(this.contact.department).fontSize(14).fontColor('#888888')}.layoutWeight(1)Image($r('app.media.ic_arrow_right')).width(20).height(20)}.padding(10).width('100%')}
}
7. 企业微信主界面架构
// src/main/ets/MainPage.ets
@Entry
@Component
struct MainPage {@State currentTab: number = 0;build() {Tabs({ barPosition: BarPosition.End }) {TabContent() {MessageList()}.tabBar('消息')TabContent() {ContactList()}.tabBar('通讯录')TabContent() {Workbench()}.tabBar('工作台')TabContent() {MePage()}.tabBar('我')}.barMode(BarMode.Fixed).barWidth('100%').barHeight(60)}
}
8. 企业微信功能扩展建议
-
音视频通话:
- 集成华为实时音视频服务(RTC)
- 实现1对1通话和多人会议
-
文件传输:
- 使用华为云存储服务
- 实现大文件分片上传下载
-
日程管理:
- 集成系统日历服务
- 实现会议预约和提醒
-
审批流程:
- 自定义审批表单
- 实现多级审批逻辑
-
微应用集成:
- 开发企业定制化微应用
- 实现单点登录和权限控制
9. 测试与发布
-
测试要点:
- 多设备适配测试
- 网络切换测试(4G/Wi-Fi)
- 消息推送可靠性测试
-
发布流程:
- 申请企业微信开发者资质
- 提交应用到华为应用市场
- 配置企业微信应用管理后台
相关文章:
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...