快速集成 uni-app 源码(Vue 3)

更新时间: 2024/09/19 16:18:40

IM uni-app Demo 是基于网易云信 IM UIKit(NEUIKit)的一款 uni-app Demo,托管在 GitHub 开源代码仓库 nim-uikit-uniapp。该 Demo 提供了一些通用的功能,包含会话、聊天、群组等,您可以基于源码搭建您的即时通讯业务逻辑。

效果预览

IM uni-app Demo 的部分界面效果如下:

Demo.png

平台支持

当前 IM uni-app Demo 支持:Android、iOS、H5、小程序。

前提条件

开始跑通 Demo 之前,请确保您已完成了以下操作:

  1. 网易云信控制台创建应用,并获取 App Key。

  2. 注册 IM 账号,获取账号 ID 和 token。

  3. 网易云信控制台 上,为应用开通 消息漫游 开关。开启步骤请参考《控制台文档》配置应用

    image.png
  4. 调整本地开发环境,并满足如下要求:

    配置项 要求
    集成开发环境 HBuilderX
    Vue.js 版本 Vue 3
    开发语言 TypeScript
    CSS 预处理器 Sass(Sass-loader 版本 <= 10.1.1)
    Node.js 版本 12.13.0 ~ 17.0.0(推荐 LTS 版本 16.17.0)
    JavaScript 包管理器 NPM(版本请与 Node.js 版本匹配)

第一步:创建 uni-app 项目

在 HBuilderX IDE 环境中,创建 uni-app 项目。详细步骤请参考《uni-app 官网文档》通过 HBuilderX 可视化界面

如果您已创建项目,请忽略本步骤。

第二步:下载 Demo 源码

运行以下命令将 NEUIKit GitHub 源码项目 nim-uikit-uniapp.git 下载到 uni-app 项目中:

Bash# 找一个目录,clone 组件项目
git clone https://github.com/netease-kit/nim-uikit-uniapp.git
# 在您的项目根目录下执行以下命令,拷贝组件
mkdir -p ./pages/NEUIKit
# macOS
mv ${组件项目路径}/NEUIKit/* ./pages/NEUIKit
# windows
move ${组件项目路径}/NEUIKit/* .\pages\NEUIKit

下载成功后,目录结构如下图所示:

第三步:添加依赖和图片引入

  1. 在项目的根目录下添加依赖和图片引入。

    Bashnpm init -y
    npm i nim-web-sdk-ng@10.4.0 @xkit-yx/im-store-v2@0.2.3 @xkit-yx/utils@0.5.6 dayjs@1.11.7 mobx@6.6.1 pinyin@3.1.0 --save
    
  2. 在您的项目根目录下执行以下命令,将组件需要的图片复制到 static 目录下,若命令执行不成功,请按照路径手动复制。

    Bashmkdir -p static
    
  3. 当前静态资源放置在网易对象存储(Netease Object Storage,NOS) 中,您可通过链接的方式在组件中进行访问。

    由于访问频率有限制,建议您将静态资源放置在您的 业务服务器 上,然后修改 /pages/NEUIKit/components/Icon.vue 组件中的链接即可。

    Bash# macOS
    cp -r pages/NEUIKit/static static/YX_IMG
    # windows
    xcopy /E pages\NEUIKit\static static\YX_IMG
    

第四步:引入并初始化组件

初始化 NEUIKit 组件

App.vue 文件引入 NEUIKit 组件, 参考以下代码初始化 nimstore

JSX<script lang="ts">
import RootStore from "@xkit-yx/im-store-v2";
import V2NIM, { V2NIMConst } from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
import {
  customRedirectTo,
  customReLaunch,
  customSwitchTab,
} from "./pages/NEUIKit/utils/customNavigate";
import { getMsgContentTipByType } from "./pages/NEUIKit/utils/msg";
import { STORAGE_KEY } from "./pages/NEUIKit/utils/constants";
import { isWxApp } from "./pages/NEUIKit/utils";
import {
  V2NIMMessage,
  V2NIMMessagePushConfig,
} from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK/V2NIMMessageService";

// #ifdef APP-PLUS

export default {
  onLaunch() {
   
    const imOptions = {
        appkey: "", // 请填写你的appkey
        account: "", // 请填写你的account
        token: "", // 请填写你的token
    }
    if (imOptions) {
      this.initNim(imOptions);
    } else {
      // 需要登录, 跳转登录页
    }
  },
  methods: {
    initNim(opts) {
      // 初始化nim sdk
      const nim = (uni.$UIKitNIM = V2NIM.getInstance(
        {
          appkey: opts.appkey,
          needReconnect: true,
          // "reconnectionAttempts": 5,
          debugLevel: "debug",
          apiVersion: "v2",
        },
        {
          V2NIMLoginServiceConfig: {
            lbsUrls: isWxApp
              ? ["https://lbs.netease.im/lbs/wxwebconf.jsp"]
              : ["https://lbs.netease.im/lbs/webconf.jsp"],
            linkUrl: isWxApp ? "wlnimsc0.netease.im" : "weblink.netease.im",
            /**
             * 使用固定设备ID,
             */
            isFixedDeviceId: true,
          },
        }
      ));
      // 初始化store
      const store = (uni.$UIKitStore = new RootStore(
        nim,
        {
          addFriendNeedVerify: false,
          teamAgreeMode:
            V2NIMConst.V2NIMTeamAgreeMode.V2NIM_TEAM_AGREE_MODE_NO_AUTH,
          sendMsgBefore: async (options: {
            msg: V2NIMMessage;
            conversationId: string;
            serverExtension?: Record<string, unknown>;
          }) => {
            const pushContent = getMsgContentTipByType({
              text: options.msg.text,
              messageType: options.msg.messageType,
            });
            const yxAitMsg = options.serverExtension
              ? options.serverExtension.yxAitMsg
              : { forcePushIDsList: "[]", needForcePush: false };

            // 如果是 at 消息,需要走离线强推

            const { forcePushIDsList, needForcePush } = yxAitMsg
              ? // @ts-ignore
                store.msgStore._formatExtAitToPushInfo(
                  yxAitMsg,
                  options.msg.text
                )
              : { forcePushIDsList: "[]", needForcePush: false };

            console.log("forcePushIDsList: ", forcePushIDsList);

            const { conversationId } = options;
            const conversationType =
              nim.V2NIMConversationIdUtil.parseConversationType(conversationId);
            const targetId =
              nim.V2NIMConversationIdUtil.parseConversationTargetId(
                conversationId
              );

            const pushPayload = JSON.stringify({
              // oppo
              oppoField: {
                click_action_type: 4, // 参考 oppo 官网
                click_action_activity: "", // 各端不一样 TODO
                action_parameters: {
                  sessionId: targetId,
                  sessionType: conversationType,
                }, // 自定义
              },

              // vivo
              vivoField: {
                pushMode: 0, //推送模式 0:正式推送;1:测试推送,不填默认为0
              },

              // huawei
              hwField: {
                click_action: {
                  type: 1,
                  action: "", // 各端不一样 TODO
                },
                androidConfig: {
                  category: "IM",
                  data: JSON.stringify({
                    sessionId: targetId,
                    sessionType: conversationType,
                  }),
                },
              },

              // 通用
              sessionId: targetId,
              sessionType: conversationType,
            });

            const pushConfig: V2NIMMessagePushConfig = {
              pushEnabled: true,
              pushNickEnabled: true,
              forcePush: needForcePush,
              forcePushContent: pushContent,
              forcePushAccountIds: forcePushIDsList,
              pushPayload: "{}",
              pushContent,
            };

            return { ...options, pushConfig };
          },
        },
        "UniApp"
      ));

      nim.V2NIMLoginService.login(opts.account, opts.token).then(() => {
        customSwitchTab({
          url: "/pages/Conversation/index",
        });
      });
    },
    logout() {
    },
  },
};
</script>
<style>
uni-page-body {
  height: 100%;
}
uni-page-body > uni-view {
  height: 100%;
}
</style>

初始化 NimKitCore

在初始化 NimKitCore 时,您需要根据是否是微信小程序,传入不同的 lbsUrlslinkUrl

JavaScriptconst nim = (uni.$UIKitNIM = new NimKitCore({
      initOptions: {
        appkey: "", // 请填写您的 appkey
        account: "", // 请填写您的 account
        token: "", // 请填写您的 token
        lbsUrls: isWeixinApp
          ? ["https://lbs.netease.im/lbs/wxwebconf.jsp"]
          : ["https://lbs.netease.im/lbs/webconf.jsp"],
        linkUrl: isWeixinApp ? "wlnimsc0.netease.im" : "weblink.netease.im",
        needReconnect: true,
        /**
         * 使用固定设备 ID,
         */
        isFixedDeviceId: true,
        // "reconnectionAttempts": 5,
        debugLevel: "debug",
      },
      platform: "UniApp",
    }));

第五步:配置路由

  1. pages/NEUIKit/utils/customNavigate.ts 中,修改 preUrl

    JavaScriptconst preUrl = '/pages/NEUIKit'
    
  2. 在您项目的 pages.json 文件中的更新 pages 路由:

    JSON{
    "pages": [
        {
        "path": "pages/NEUIKit/pages/Conversation/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Login/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Chat/message/p2p-set",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/group-info-edit",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Contact/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Contact/contact-list/group-list",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Contact/contact-list/valid-list",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Contact/contact-list/black-list",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Chat/index",
        "style": {
            "navigationBarBackgroundColor": "#F6F8FA",
            "navigationBarTextStyle": "black",
            "navigationStyle": "custom",
            "enablePullDownRefresh": false,
            "app-plus": {
            "softinputNavBar": "none",
            "bounce": "none"
            }
        }
        },
        {
        "path": "pages/NEUIKit/pages/Chat/video-play",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-member/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-create/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-add/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Friend/add-friend/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/user-card/friend/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/user-card/my/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/user-card/my/setting",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/user-card/my-detail/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/user-card/detail-item/index",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/nick-in-team",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/group-manage",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/transform-team",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/group-manager-list",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Group/group-set/add-group-manager",
        "style": {
            "navigationStyle": "custom"
        }
        },
        {
        "path": "pages/NEUIKit/pages/Chat/forward",
        "style": {
            "navigationStyle": "custom"
        }
        }
    ],
    "globalStyle": {
        "navigationBarTextStyle": "black"
    },
    "tabBar": {
        "backgroundColor": "#F6F8FA",
        "color": "#999999",
        "selectedColor": "#337EFF",
        "height": "60px",
        "list": [
            {
            "text": "消息",
            "iconPath": "static/YX_IMG/conversation.png",
            "selectedIconPath": "static/YX_IMG/conversation-selected.png",
            "pagePath": "pages/NEUIKit/pages/Conversation/index"
            },
            {
            "text": "通讯录",
            "iconPath": "static/YX_IMG/contact.png",
            "selectedIconPath": "static/YX_IMG/contact-selected.png",
            "pagePath": "pages/NEUIKit/pages/Contact/index"
            },
            {
            "text": "我的",
            "pagePath": "pages/NEUIKit/pages/user-card/my/index",
            "iconPath": "static/YX_IMG/me.png",
            "selectedIconPath": "static/YX_IMG/me-selected.png"
            }
        ]
        }
    }
    

第六步:运行 Demo

在 uni-app IDE 中,运行 Demo:

运行.png

自定义开发

API 参考

IM uni-app Demo 基于 UIKitStore 开发,相关 API 详情请参考 UIKitStore

例如,您想获取 IM uni-app UIKit 的会话未读数,示例代码如下:

JavaScriptconst unRead = store.uiStore.sessionUnread

使用原生 SDK 中的方法

如果您需要自行实现目前 uni-app UIKit 还未实现,但原生的 IM uni-app SDK 已提供的能力。您可以通过调用原生 IM uni-app SDK 中提供的接口来实现。原生 uni-app SDK 中的 API,请参考 NIM Web SDK

例如,您想对 IM uni-app UIKit 的消息历史进行全文检索(按时间分页搜索),可以调用原生 SDK 中的 msgFtsInServerByTiming 方法,示例代码如下:

JavaScriptuni.$UIKitNIM.nim.msgFtsInServerByTiming({
  keyword: '您好',
})

以上示例中的 uni.$UIKitNIM.nim 为原生 NIM uni-app SDK 的实例。

常见问题

集成过程中如果遇到任何问题,请 提交工单 联系网易云信技术支持工程师或参考 常见问题

此文档是否对你有帮助?
有帮助
去反馈
  • 效果预览
  • 平台支持
  • 前提条件
  • 第一步:创建 uni-app 项目
  • 第二步:下载 Demo 源码
  • 第三步:添加依赖和图片引入
  • 第四步:引入并初始化组件
  • 初始化 NEUIKit 组件
  • 初始化 NimKitCore
  • 第五步:配置路由
  • 第六步:运行 Demo
  • 自定义开发
  • API 参考
  • 使用原生 SDK 中的方法
  • 常见问题