├── .gitattributes
├── .gitignore
├── .idea
├── .gitignore
├── YeIM-Uni-SDK.iml
├── modules.xml
└── vcs.xml
├── LICENSE
├── README.md
├── babel.config.js
├── dist
└── yeim-uni-sdk.min.js
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
├── const
├── yeim-defines.js
└── yeim-status-code.js
├── func
├── callback.js
├── common.js
├── event.js
├── formatMessage.js
├── log.js
├── request.js
├── storage.js
└── websocket.js
├── service
├── conversationService.js
├── friendService.js
├── groupService.js
├── messageService.js
├── pushService.js
├── uploadService.js
└── userService.js
├── utils
├── CryptoJS.js
├── fetch.js
├── md5.js
├── mitt.umd.js
└── queryParams.js
├── yeim-uni-sdk.js
└── yeim-uni-sdk.min.d.ts
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | node_modules
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/.idea/YeIM-Uni-SDK.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 | YeIM-Uni-SDK
5 |
6 |
7 | 即时通讯JSSDK
8 |
9 |
10 | 查看文档
11 | | 备用文档
12 |
13 |
14 |
15 |
16 | `此为社区开源项目,用于学习交流使用,禁止用于非法途径。如作他用所造成的一切法律责任均不由作者承担。`
17 |
18 | - 注:不是聊天项目!不是聊天项目!不是聊天项目!只是SDK,通过使用SDK里的一系列接口可实现聊天,跟环信、融云、腾讯云即时通信等等类似的一种可实现聊天的IMSDK。
19 |
20 | `YeIM-Uni-SDK`是可以`私有化部署`的`全开源`即时通讯`js-sdk`,仅需集成 SDK 即可轻松实现聊天能力,支持Web、[uni-app](https://uniapp.dcloud.net.cn/)接入使用,满足通信需要。
21 |
22 | 支持私聊和群聊,支持发送的消息类型:文字消息、图片消息、语音消息、视频消息、位置消息、自定义消息。
23 |
24 | 必须搭配[YeIM-Uni-Server](https://github.com/wzJun1/YeIM-Uni-Server)服务端,开箱即用。
25 |
26 | ## 支持哪些端?
27 |
28 | `YeIM-Uni-SDK`由`JavaScript`构建,支持Web端、uni-app端的项目接入使用。
29 |
30 | 当项目在uni环境打包,SDK将使用`uni-app API`,否则使用JS相关API,详情可查看源码。
31 |
32 | 作为通用JSSDK,`YeIM-Uni-SDK`支持包括不限于H5(uni和非uni环境均可)、Android APP、iOS APP、微信小程序、字节小程序、支付宝小程序、百度小程序(仅限uni环境)等平台项目。
33 |
34 | ## 使用文档
35 |
36 | 查看文档
37 | | 备用文档
38 |
39 | ## 反馈与共建
40 |
41 | - 普通交流QQ群:[391276294](https://qm.qq.com/cgi-bin/qm/qr?k=hEQnVRj3c1B0gDpD2QJrD7UIfWMzCUuM&jump_from=webapi&authKey=kbrD7NHXGIPaiVb2puw+vJeRCIQSXVhIci7eFvFLBH/UjGt+hrdOk4upK731S+1+)
42 |
43 | ## 源码编译
44 |
45 | ```shell
46 | npm i
47 | ```
48 |
49 | ```shell
50 | npm run build
51 | ```
52 |
53 | ## 基于YeIM-Uni-SDK的演示案例
54 |
55 | ### 代码
56 |
57 | [下载基于YeIM-Uni-SDK的演示案例源码](https://ext.dcloud.net.cn/plugin?id=10266)
58 |
59 | ### Android App Demo
60 |
61 |
62 |
63 | ### Electron 桌面端 Demo
64 |
65 | [https://github.com/wzJun1/YeIM-Uni-SDK-Electron-Demo](https://github.com/wzJun1/YeIM-Uni-SDK-Electron-Demo)
66 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false
7 | }
8 | ]
9 | ],
10 | "plugins": [
11 | [
12 | "@babel/plugin-transform-runtime"
13 | ]
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yeim-uni-sdk",
3 | "version": "1.2.83",
4 | "description": "可私有化部署的全开源即时通讯uni-app js-sdk,仅需植入 sdk 即可轻松集成聊天能力,支持Web、uni-app项目接入使用,满足通信需要。",
5 | "scripts": {
6 | "dev": "rollup -w -c --bundleConfigAsCjs",
7 | "build": "rollup -c --bundleConfigAsCjs",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "wzjun1",
11 | "license": "Apache-2.0",
12 | "types": "src/yeim-uni-sdk.min.d.ts",
13 | "main": "dist/yeim-uni-sdk.min.js",
14 | "module": "dist/yeim-uni-sdk.min.js",
15 | "devDependencies": {
16 | "@babel/core": "^7.21.3",
17 | "@babel/plugin-transform-runtime": "^7.21.0",
18 | "@babel/preset-env": "^7.20.2",
19 | "@rollup/plugin-babel": "^6.0.3",
20 | "@rollup/plugin-commonjs": "^24.0.1",
21 | "@rollup/plugin-json": "^6.0.0",
22 | "@rollup/plugin-node-resolve": "^15.0.1",
23 | "@rollup/plugin-terser": "^0.4.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import resolve from '@rollup/plugin-node-resolve'
3 | import commonjs from '@rollup/plugin-commonjs'
4 | import terser from "@rollup/plugin-terser";
5 | import babel from "@rollup/plugin-babel";
6 | import json from "@rollup/plugin-json";
7 | const env = process.env.NODE_ENV
8 | const config = {
9 | input: path.resolve(__dirname, 'src/yeim-uni-sdk.js'),
10 | output: {
11 | file: './dist/yeim-uni-sdk.min.js',
12 | format: 'es',
13 | name: 'YeIMUniSDK',
14 | },
15 | plugins: [
16 | resolve(),
17 | commonjs(),
18 | json(),
19 | babel({ babelHelpers: 'runtime' })
20 | ]
21 | }
22 |
23 | config.plugins.push(terser({
24 | compress: {
25 | pure_getters: true, unsafe: true, unsafe_comps: true, warnings: false
26 | }
27 | }))
28 |
29 | if (env === 'production') {
30 | config.plugins.push(terser({
31 | compress: {
32 | pure_getters: true, unsafe: true, unsafe_comps: true, warnings: false
33 | }
34 | }))
35 | }
36 |
37 | export default config
38 |
--------------------------------------------------------------------------------
/src/const/yeim-defines.js:
--------------------------------------------------------------------------------
1 | //SDK常量
2 |
3 | var YeIMUniSDKDefines = {};
4 |
5 | //事件类型
6 | YeIMUniSDKDefines.EVENT = {};
7 | YeIMUniSDKDefines.EVENT.NET_CHANGED = "net_changed"; //网络状态变化
8 | YeIMUniSDKDefines.EVENT.CONVERSATION_LIST_CHANGED = "conversation_list_changed"; // 会话列表变化
9 | YeIMUniSDKDefines.EVENT.MESSAGE_RECEIVED = "message_received"; // 收到消息
10 | YeIMUniSDKDefines.EVENT.MESSAGE_REVOKED = "message_revoked"; // 撤回消息
11 | YeIMUniSDKDefines.EVENT.PRIVATE_READ_RECEIPT = "private_read_receipt"; //私聊会话已读回执
12 | YeIMUniSDKDefines.EVENT.FRIEND_LIST_CHANGED = "friend_list_changed"; //好友列表变化
13 | YeIMUniSDKDefines.EVENT.FRIEND_APPLY_LIST_CHANGED = "friend_apply_list_changed"; //好友申请列表变化
14 | YeIMUniSDKDefines.EVENT.FRIEND_APPLY_REFUSE = "friend_apply_refuse"; //好友申请被拒
15 | YeIMUniSDKDefines.EVENT.KICKED_OUT = "kicked_out"; //用户被踢下线
16 |
17 | //会话类型
18 | YeIMUniSDKDefines.CONVERSATION_TYPE = {};
19 | YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 'private'; //私聊
20 | YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 'group'; //群聊
21 |
22 | //消息类型
23 | YeIMUniSDKDefines.MESSAGE_TYPE = {};
24 | YeIMUniSDKDefines.MESSAGE_TYPE.TEXT = 'text'; //文本消息
25 | YeIMUniSDKDefines.MESSAGE_TYPE.TEXT_AT = 'text_at'; //文本@消息
26 | YeIMUniSDKDefines.MESSAGE_TYPE.IMAGE = 'image'; //图片消息
27 | YeIMUniSDKDefines.MESSAGE_TYPE.AUDIO = 'audio'; //语音消息
28 | YeIMUniSDKDefines.MESSAGE_TYPE.VIDEO = 'video'; //小视频消息
29 | YeIMUniSDKDefines.MESSAGE_TYPE.LOCATION = 'location'; //位置消息
30 | YeIMUniSDKDefines.MESSAGE_TYPE.CUSTOM = 'custom'; //自定义消息
31 | YeIMUniSDKDefines.MESSAGE_TYPE.MERGER = 'merger'; //合并消息
32 | YeIMUniSDKDefines.MESSAGE_TYPE.FORWARD = 'forward'; //转发消息
33 | YeIMUniSDKDefines.MESSAGE_TYPE.SYS_NOTICE = 'sys_notice'; //私聊系统通知
34 | YeIMUniSDKDefines.MESSAGE_TYPE.GROUP_SYS_NOTICE = 'group_sys_notice'; //群聊系统通知
35 |
36 |
37 | //用户
38 | YeIMUniSDKDefines.USER = {};
39 |
40 | //加好友验证方式
41 | YeIMUniSDKDefines.USER.ADDFRIEND = {};
42 | YeIMUniSDKDefines.USER.ADDFRIEND.ALLOW = 1; //允许任何人添加自己为好友
43 | YeIMUniSDKDefines.USER.ADDFRIEND.CONFIRM = 2; //需要经过自己确认才能添加自己为好友
44 | YeIMUniSDKDefines.USER.ADDFRIEND.DENY = 3; //拒绝加好友
45 |
46 | //群组
47 | YeIMUniSDKDefines.GROUP = {};
48 |
49 | //群申请处理方式
50 | YeIMUniSDKDefines.GROUP.JOINMODE = {};
51 | YeIMUniSDKDefines.GROUP.JOINMODE.FREE = 1; //自有加入,不需要申请和审核,不需要被邀请人允许。
52 | YeIMUniSDKDefines.GROUP.JOINMODE.CHECK = 2; //验证加入,需要申请,以及群主或管理员的同意才能入群
53 | YeIMUniSDKDefines.GROUP.JOINMODE.FORBIDDEN = 3; //禁止加入
54 |
55 | //入群申请处理结果
56 | YeIMUniSDKDefines.GROUP.APPLYSTATUS = {};
57 | YeIMUniSDKDefines.GROUP.APPLYSTATUS.PENDING = 1; //待处理
58 | YeIMUniSDKDefines.GROUP.APPLYSTATUS.AGREE = 2; //同意
59 | YeIMUniSDKDefines.GROUP.APPLYSTATUS.REFUSE = 3; //拒绝
60 |
61 | export {
62 | YeIMUniSDKDefines
63 | };
64 |
--------------------------------------------------------------------------------
/src/const/yeim-status-code.js:
--------------------------------------------------------------------------------
1 | //客户端状态码
2 |
3 | var YeIMUniSDKStatusCode = {
4 | NORMAL_SUCCESS: {
5 | code: 200,
6 | describe: '接口调用成功' //接口调用成功的统一状态码
7 | },
8 | APPLY_NEED: {
9 | code: 20020,
10 | describe: '好友申请已发送,请等待对方处理'
11 | },
12 | NORMAL_ERROR: {
13 | code: 500,
14 | describe: '未知错误' //未知错误的统一状态码
15 | },
16 | SDK_PARAMS_ERROR: {
17 | code: 9001,
18 | describe: 'YeIMUniSDK 初始化失败,请检查参数是否存在异常'
19 | },
20 | CONNECT_ERROR: {
21 | code: 10001,
22 | describe: '聊天服务网络连接错误'
23 | },
24 | NO_USERID: {
25 | code: 10002,
26 | describe: '用户验证失败,请检查userId、token'
27 | },
28 | LOGIN_EXPIRE: {
29 | code: 10003,
30 | describe: '用户登录状态过期,请重新登录'
31 | },
32 | NO_CONVERSATION: {
33 | code: 10004,
34 | describe: '未找到此会话'
35 | },
36 | PARAMS_ERROR: {
37 | code: 10008,
38 | describe: '请求参数错误'
39 | },
40 | LOGIN_ERROR: {
41 | code: 10103,
42 | describe: '用户登录失败,请稍后再试'
43 | },
44 | GROUP_APPLY_REPEAT: {
45 | code: 10251,
46 | describe: '此用户已在当前群组,请勿重复加入'
47 | },
48 | GROUP_APPLY_ERROR: {
49 | code: 10252,
50 | describe: '申请入群异常,请稍后重试'
51 | },
52 | GROUP_APPLY_WAIT: {
53 | code: 10253,
54 | describe: '已发送入群申请,请等待审核'
55 | },
56 | UPLOAD_ERROR: {
57 | code: 10300,
58 | describe: '本地上传失败,请检查配置'
59 | },
60 | DOWNLOAD_ERROR: {
61 | code: 10301,
62 | describe: '文件下载失败'
63 | },
64 | COS_UPLOAD_ERROR: {
65 | code: 10302,
66 | describe: '腾讯云COS上传文件失败,请检查配置是否填写正确'
67 | },
68 | COS_DOWNLOAD_ERROR_1: {
69 | code: 10303,
70 | describe: '腾讯云媒体截图接口:下载视频缩略图失败,请检查网络或开启万象功能'
71 | },
72 | OSS_UPLOAD_ERROR: {
73 | code: 10304,
74 | describe: '阿里云OSS上传文件失败,请检查配置是否填写正确'
75 | },
76 | };
77 |
78 | export {
79 | YeIMUniSDKStatusCode
80 | };
81 |
--------------------------------------------------------------------------------
/src/func/callback.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 格式化成功对象
3 | */
4 | function buildSuccessObject(code = 200, message, data = null) {
5 | return {
6 | code: code,
7 | message: message,
8 | data: data
9 | }
10 | }
11 |
12 | /**
13 | * 格式化失败对象
14 | */
15 | function buildErrObject(code = 500, message, data = null) {
16 | return {
17 | code: code,
18 | message: message,
19 | data: data
20 | }
21 | }
22 |
23 | /**
24 | * 参数函数成功回调
25 | *
26 | * @param {Object} options 包含成功回调函数参数的对象
27 | * @param {Function} [options.success] - 成功回调
28 | * @param {String} message 消息提示
29 | * @param {Object} data 回调参数
30 | * @param {Number} code 状态码
31 | */
32 | function successHandle(options, message, data = null, code = 200) {
33 | try {
34 | if (options != null && options.success !== undefined && typeof options.success === "function") {
35 | options.success(buildSuccessObject(code, message, data));
36 | }
37 | } catch (e) {
38 | console.error(e)
39 | }
40 | }
41 |
42 | /**
43 | * 参数函数失败回调
44 | *
45 | * @param {Object} options 包含失败回调函数参数的对象
46 | * @param {Function} [options.fail] - 失败回调
47 | * @param {Number} code 状态码
48 | * @param {String} message 消息提示
49 | * @param {Object} data 回调参数
50 | */
51 | function errHandle(options, code = 500, message, data = null) {
52 | try {
53 | if (options != null && options.fail !== undefined && typeof options.fail === "function") {
54 | options.fail(buildErrObject(code, message, data));
55 | }
56 | } catch (e) {
57 | console.error(e)
58 | }
59 | }
60 |
61 | export {
62 | buildSuccessObject,
63 | buildErrObject,
64 | successHandle,
65 | errHandle
66 | }
67 |
--------------------------------------------------------------------------------
/src/func/common.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * 判断链接是否为h5 object url
4 | *
5 | * @param {*} url
6 | * @returns
7 | */
8 | function isBlobURL(url) {
9 | return url.startsWith('blob:');
10 | }
11 |
12 | /**
13 | *
14 | * 判断是否为网络链接
15 | *
16 | * @param {*} url
17 | * @returns
18 | */
19 | function isHttpURL(url) {
20 | // 先判断是否是微信的临时链接
21 | if (url.indexOf('http://tmp/') === 0) {
22 | return false;
23 | }
24 | return url.startsWith('http:') || url.startsWith('https:') || url.startsWith('ftp:');
25 | }
26 |
27 | export {
28 | isBlobURL,
29 | isHttpURL
30 | }
31 |
--------------------------------------------------------------------------------
/src/func/event.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from "../yeim-uni-sdk";
4 |
5 | /**
6 | * 触发事件
7 | * @param {Object} event
8 | * @param {Object} data
9 | */
10 | function emit(event, data) {
11 | instance.emitter.emit(instance.defaults.eventPrefix + event, data)
12 | }
13 |
14 | /**
15 | * 添加事件监听器
16 | * @param {Object} event
17 | * @param {Object} callback
18 | */
19 | function addEventListener(event, callback) {
20 | if (event) {
21 | instance.emitter.on(instance.defaults.eventPrefix + event, callback);
22 | }
23 | }
24 |
25 | /**
26 | * 移除事件监听器
27 | * @param {Object} event
28 | * @param {Object} callback
29 | */
30 | function removeEventListener(event, callback) {
31 | if (event) {
32 | instance.emitter.off(instance.defaults.eventPrefix + event, callback);
33 | }
34 | }
35 |
36 | export {
37 | emit,
38 | addEventListener,
39 | removeEventListener
40 | };
41 |
--------------------------------------------------------------------------------
/src/func/formatMessage.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from "../yeim-uni-sdk";
4 |
5 | /**
6 | * 生成消息ID
7 | */
8 | // function createMessageId() {
9 | // if (!instance.nextIdGen) {
10 | // log(1, "分布式消息ID异常,请检查后端代码");
11 | // return null;
12 | // }
13 | // return instance.nextIdGen + "-" + (new Date()).getTime();
14 | // }
15 |
16 | /**
17 | * 统一消息格式
18 | * @param {Object} params
19 | */
20 | function formatMessage(params) {
21 | return {
22 | // 取消本地生成messageId,改为服务端统一调配
23 | // messageId: createMessageId(),
24 | conversationId: params.to, //会话ID
25 | conversationType: params.conversationType, //会话类型
26 | fromUserInfo: {
27 | nickname: instance.user.nickname,
28 | avatarUrl: instance.user.avatarUrl
29 | }, // 发送者用户信息
30 | from: instance.userId, //发送者ID
31 | to: params.to, //接收者ID
32 | type: params.type, //消息内容类型
33 | isRead: 0, //是否已读
34 | isRevoke: 0, //是否撤回
35 | isDeleted: 0, //是否删除
36 | status: 'unSend', //消息状态
37 | time: (new Date()).getTime(), //发送时间戳
38 | body: params.body, //消息体
39 | extra: params.extra ? params.extra : "" //自定义扩展数据
40 | }
41 | }
42 |
43 | export default formatMessage
44 |
--------------------------------------------------------------------------------
/src/func/log.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from "../yeim-uni-sdk";
4 | /**
5 | * 日志输出
6 | * logLevel
7 | * 0 普通日志,日志量较多,接入时建议使用
8 | * 1 关键性日志,日志量较少,生产环境时建议使用
9 | * 2 无日志级别,SDK 将不打印任何日志
10 | * @param {Object} level
11 | * @param {Object} msg
12 | * @param {Boolean} error
13 | */
14 | function log(level, msg, error = false) {
15 | if (instance.defaults.logLevel == 0) {
16 | error ? console.error("【YeIMUniSDK Log】", msg) : console.log("【YeIMUniSDK Log】", msg)
17 | } else if (instance.defaults.logLevel == 2) {
18 | return;
19 | } else {
20 | if (level == 1) {
21 | error ? console.error("【YeIMUniSDK Log】", msg) : console.log("【YeIMUniSDK Log】", msg)
22 | }
23 | }
24 | }
25 |
26 | export default log
27 |
--------------------------------------------------------------------------------
/src/func/request.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable*/
2 |
3 | import {
4 | YeIMUniSDKStatusCode
5 | } from '../const/yeim-status-code';
6 | import {
7 | fetch
8 | } from '../utils/fetch';
9 | import queryParams from '../utils/queryParams';
10 | import {
11 | isBlobURL
12 | } from '../func/common.js';
13 | import {
14 | instance
15 | } from '../yeim-uni-sdk';
16 | import {
17 | errHandle,
18 | successHandle
19 | } from './callback';
20 | import log from './log';
21 |
22 | /**
23 | * APIURL
24 | */
25 | let Api = {
26 | //用户相关接口
27 | User: {
28 | //根据userId查询用户资料
29 | fetchUserInfoById: '/user/info',
30 | //用户更新资料
31 | updateUserInfo: '/user/update',
32 | //黑名单列表
33 | getBlackUserList: '/user/black/list',
34 | //添加到黑名单
35 | addToBlackUserList: '/user/black/add',
36 | //移出黑名单
37 | removeFromBlacklist: '/user/black/remove'
38 | },
39 | //群组相关接口
40 | Group: {
41 | //创建群组
42 | create: '/group/create',
43 | //更新群组
44 | update: '/group/edit',
45 | //解散群组
46 | dissolve: '/group/dissolve',
47 | //通过群ID获取群组资料
48 | fetchGroupInfoById: '/group/get',
49 | //获取当前登录用户群组列表
50 | list: '/group/list',
51 | //转让群组
52 | transferLeader: '/group/transferLeader',
53 | //添加用户入群
54 | addUser: '/group/user/add',
55 | //退出群组
56 | leave: '/group/user/leave',
57 | //移除群成员
58 | remove: '/group/user/delete',
59 | //获取群成员列表
60 | memberList: '/group/user/list',
61 | //设置群管理员
62 | adminstrator: '/group/user/set/adminstrator',
63 | //获取入群申请请求列表
64 | applyList: '/group/user/apply/list',
65 | //处理入群申请
66 | handleApply: '/group/user/apply/change',
67 | //禁言群成员
68 | setMute: '/group/user/set/mute'
69 | },
70 | //会话相关接口
71 | Conversation: {
72 | //查询用户会话列表
73 | fetchConversationList: '/conversation/list',
74 | //清除私聊会话未读数
75 | clearConversationUnread: '/conversation/update/unread',
76 | //删除会话,将同时删除聊天记录
77 | deleteConversation: '/conversation/delete'
78 | },
79 | //消息相关接口
80 | Message: {
81 | //通过http发送消息
82 | sendMessage: '/message/save',
83 | //获取历史消息记录
84 | fetchHistoryMessageList: '/v117/message/list',
85 | //删除消息
86 | deleteMessage: '/message/delete',
87 | //撤回消息
88 | revokeMessage: '/message/revoke'
89 | },
90 | //好友相关接口
91 | Friend: {
92 | //获取好友申请列表
93 | fetchList: '/friend/list',
94 | //获取好友申请列表
95 | fetchApplyList: '/friend/apply/list',
96 | //将全部好友申请设置为已读状态
97 | setRead: '/friend/apply/set/read',
98 | //同意好友申请
99 | acceptApply: '/friend/apply/accept',
100 | //拒绝好友申请
101 | refuseApply: '/friend/apply/refuse',
102 | //添加好友
103 | addFriend: '/friend/add',
104 | //删除好友
105 | deleteFriend: '/friend/delete',
106 | //更新好友资料
107 | updateFriend: '/friend/update'
108 | },
109 | //推送相关
110 | Push: {
111 | //APP开启离线推送后,绑定个推clientID
112 | bindClientId: '/user/bind/push/id'
113 | },
114 | //上传相关
115 | Upload: {
116 | //获取上传配置信息
117 | sign: '/upload/sign',
118 | //通用上传
119 | normal: '/upload',
120 | //图片上传
121 | image: '/upload/image',
122 | //视频上传
123 | video: '/upload/video'
124 | }
125 | }
126 |
127 | /**
128 | * 公共请求
129 | *
130 | *
131 | * @param {String} url - 请求路由
132 | * @param {String} method - 请求方法
133 | * @param {Object} data - 请求参数
134 | *
135 | * @return uni.request Promise
136 | *
137 | */
138 | function request(url, method = 'GET', data = null) {
139 |
140 | return new Promise((resolve, reject) => {
141 |
142 | if (instance.uni) {
143 | uni.request({
144 | url: instance.defaults.baseURL + url,
145 | data: data,
146 | method: method,
147 | header: {
148 | 'content-type': 'application/json',
149 | 'token': instance.token != null ? instance.token : ''
150 | },
151 | success: (result) => {
152 | if (result.data == null) {
153 | return reject({
154 | code: YeIMUniSDKStatusCode.NORMAL_ERROR.code,
155 | message: result.message ? result.message : YeIMUniSDKStatusCode
156 | .NORMAL_ERROR.describe,
157 | data: null
158 | });
159 | }
160 | result = result.data;
161 | let code = result.code;
162 | if (code === YeIMUniSDKStatusCode.NORMAL_SUCCESS.code) {
163 | resolve(result.data ? result.data : null);
164 | } else {
165 | reject(result);
166 | }
167 | },
168 | fail: (fail) => {
169 | log(1, fail);
170 | reject({
171 | code: YeIMUniSDKStatusCode.NORMAL_ERROR.code,
172 | message: JSON.stringify(fail),
173 | data: null
174 | });
175 | }
176 | });
177 | } else {
178 |
179 | let options = {
180 | method: method,
181 | body: JSON.stringify(data),
182 | headers: {
183 | "Content-Type": "application/json",
184 | 'token': instance.token != null ? instance.token : ''
185 | },
186 | };
187 |
188 | if (method == "GET") {
189 | url = url + queryParams(data, true);
190 | delete options.body;
191 | }
192 |
193 | fetch(instance.defaults.baseURL + url, options).then(async (response) => {
194 | let result = await response.json();
195 | if (result == null) {
196 | return reject({
197 | code: YeIMUniSDKStatusCode.NORMAL_ERROR.code,
198 | message: result.message ? result.message : YeIMUniSDKStatusCode
199 | .NORMAL_ERROR.describe,
200 | data: null
201 | });
202 | }
203 | let code = result.code;
204 | if (code === YeIMUniSDKStatusCode.NORMAL_SUCCESS.code) {
205 | resolve(result.data ? result.data : null);
206 | } else {
207 | reject(result);
208 | }
209 | }, (error) => {
210 | log(1, error);
211 | reject({
212 | code: YeIMUniSDKStatusCode.NORMAL_ERROR.code,
213 | message: JSON.stringify(error.message),
214 | data: null
215 | });
216 | })
217 | }
218 | });
219 | }
220 |
221 |
222 | /**
223 | * 公共上传
224 | *
225 | * @param {Object} options - 请求参数
226 | * @param {String} options.url - 请求地址
227 | * @param {String} options.name - 文件上传的标识符
228 | * @param {Object} options.header - 请求头
229 | * @param {Object} options.data - 请求参数
230 | * @param {String} options.filePath - 上传文件资源的路径
231 | * @param {Boolean} options.ignoreResult - 是否忽略结果
232 | * @param {(result)=>{}} [options.success] - 成功回调
233 | * @param {(error)=>{}} [options.fail] - 失败回调
234 | *
235 | * @return uploadTask
236 | *
237 | */
238 | function upload(options) {
239 | if (instance.uni) {
240 | return uni.uploadFile({
241 | url: options.url,
242 | name: options.name,
243 | formData: options.data,
244 | header: options.header,
245 | filePath: options.filePath,
246 | success: (result) => {
247 | //忽略结果
248 | if (options.ignoreResult) {
249 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe)
250 | } else {
251 | if (result.data == null) reject(null);
252 | result = JSON.parse(result.data);
253 | let code = result.code;
254 | if (code === YeIMUniSDKStatusCode.NORMAL_SUCCESS.code) {
255 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result.data ?
256 | result.data : null)
257 | } else {
258 | errHandle(options, code, result.message);
259 | }
260 | }
261 | },
262 | fail: (fail) => {
263 | log(1, fail);
264 | errHandle(options, YeIMUniSDKStatusCode.NORMAL_ERROR.code, fail);
265 | }
266 | });
267 | } else {
268 | return new Promise(async (resolve, reject) => {
269 | const formdata = new FormData()
270 | for (let key in options.data) {
271 | formdata.append(key, options.data[key])
272 | }
273 | if (isBlobURL(options.filePath)) {
274 | const blobResp = await fetch(blobUrl);
275 | const blob = await blobResp.blob();
276 | formData.append('file', blob);
277 | } else {
278 | formdata.append('file', options.filePath)
279 | }
280 |
281 | fetch(options.url, {
282 | method: 'POST',
283 | body: formdata,
284 | headers: options.header
285 | }).then(async res => {
286 | if (res.ok) {
287 | let json = await res.json();
288 | if (json.code == YeIMUniSDKStatusCode.NORMAL_SUCCESS.code) {
289 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe,
290 | json.data ?
291 | json.data : null)
292 | } else {
293 | log(1, json.message);
294 | errHandle(options, YeIMUniSDKStatusCode.NORMAL_ERROR.code, json
295 | .message);
296 | }
297 | } else {
298 | log(1, 'network error');
299 | errHandle(options, YeIMUniSDKStatusCode.NORMAL_ERROR.code, 'network error');
300 | }
301 | }).then(fail => {
302 | log(1, fail);
303 | errHandle(options, YeIMUniSDKStatusCode.NORMAL_ERROR.code, fail);
304 | })
305 | });
306 | }
307 | }
308 |
309 | /**
310 | * 公共下载
311 | *
312 | * @param {Object} options - 请求参数
313 | * @param {String} options.url - 请求的下载地址
314 | * @param {Object} options.header - 请求头
315 | * @param {(result)=>{}} [options.success] - 成功回调
316 | * @param {(error)=>{}} [options.fail] - 失败回调
317 | *
318 | * @return downloadTask
319 | *
320 | */
321 | function download(options) {
322 | if (instance.uni) {
323 | return uni.downloadFile({
324 | url: options.url,
325 | header: options.header,
326 | success: (downloadRes) => {
327 | if (downloadRes.statusCode === 200) {
328 | successHandle(options, YeIMUniSDKStatusCode
329 | .NORMAL_SUCCESS.describe, downloadRes.tempFilePath)
330 | } else {
331 | errHandle(options, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
332 | .code, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
333 | .code.describe);
334 | }
335 | },
336 | fail: (fail) => {
337 | log(1, fail);
338 | errHandle(options, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
339 | .code, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
340 | .code.describe);
341 | }
342 | });
343 | } else {
344 | return fetch(options.url, {
345 | header: options.header,
346 | })
347 | .then(response => response.blob())
348 | .then(blob => {
349 | var file = new File([blob], options.filename ? options.filename : '1.jpg');
350 | successHandle(options, YeIMUniSDKStatusCode
351 | .NORMAL_SUCCESS.describe, file)
352 | }).catch(error => {
353 | log(1, fail);
354 | errHandle(options, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
355 | .code, YeIMUniSDKStatusCode.DOWNLOAD_ERROR
356 | .code.describe);
357 | });
358 | }
359 | }
360 |
361 | export {
362 | Api,
363 | request,
364 | upload,
365 | download
366 | }
--------------------------------------------------------------------------------
/src/func/storage.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable*/
2 |
3 | import { instance } from "../yeim-uni-sdk"
4 |
5 |
6 | /**
7 | * 从本地缓存中同步获取指定 key 对应的内容
8 | *
9 | * @param {String} key - 缓存名称
10 | * @returns {Object}
11 | */
12 | function getCache(key) {
13 | if (instance.uni) {
14 | return uni.getStorageSync(key);
15 | } else {
16 | return localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key)) : null;
17 | }
18 | }
19 |
20 | /**
21 | * 将 value 存储在本地缓存中指定的 key 中
22 | *
23 | * @param {String} key - 缓存名称
24 | * @param {Object} value - 缓存值
25 | * @returns {void}
26 | */
27 | function setCache(key, value) {
28 | if (instance.uni) {
29 | uni.setStorageSync(key, value);
30 | } else {
31 | localStorage.setItem(key, JSON.stringify(value));
32 | }
33 | }
34 |
35 | /**
36 | * 从本地缓存中同步移除指定 key
37 | *
38 | * @param {String} key - 缓存名称
39 | * @returns {void}
40 | */
41 | function removeCache(key) {
42 | if (instance.uni) {
43 | uni.removeStorageSync(key);
44 | } else {
45 | localStorage.removeItem(key);
46 | }
47 | }
48 |
49 | export {
50 | getCache,
51 | setCache,
52 | removeCache
53 | }
--------------------------------------------------------------------------------
/src/func/websocket.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable*/
2 |
3 | import { instance } from "../yeim-uni-sdk";
4 | import log from "./log";
5 |
6 | export default class WebSocketUtil {
7 |
8 | socketTask = undefined;
9 |
10 | onMessageCallBack = [];
11 |
12 | constructor(url) {
13 | if (instance.uni) {
14 | this.socketTask = uni.connectSocket({
15 | url: url,
16 | success: () => { },
17 | fail: () => { },
18 | complete: () => { }
19 | });
20 | } else {
21 | this.socketTask = new WebSocket(url);
22 | this.socketTask.onmessage = (res) => {
23 | if (this.onMessageCallBack) {
24 | for (let index = 0; index < this.onMessageCallBack.length; index++) {
25 | this.onMessageCallBack[index](res);
26 | }
27 | }
28 | };
29 | }
30 | }
31 | onOpen(callback) {
32 | try {
33 | if (instance.uni) {
34 | this.socketTask.onOpen(callback);
35 | } else {
36 | this.socketTask.onopen = callback;
37 | }
38 | } catch (e) {
39 | log(0, e, true);
40 | }
41 | }
42 | onClose(callback) {
43 | try {
44 | if (instance.uni) {
45 | this.socketTask.onClose(callback);
46 | } else {
47 | this.socketTask.onclose = callback;
48 | }
49 | } catch (e) {
50 | log(0, e, true);
51 | }
52 | }
53 | onError(callback) {
54 | try {
55 | if (instance.uni) {
56 | this.socketTask.onError(callback);
57 | } else {
58 | this.socketTask.onerror = callback;
59 | }
60 | } catch (e) {
61 | log(0, e, true);
62 | }
63 | }
64 | onMessage(callback) {
65 | try {
66 | if (instance.uni) {
67 | this.socketTask.onMessage(callback);
68 | } else {
69 | this.onMessageCallBack.push(callback);
70 | }
71 | } catch (e) {
72 | log(0, e, true);
73 | }
74 | }
75 | send(str) {
76 | if (this.socketTask) {
77 | try {
78 | if (instance.uni) {
79 | this.socketTask.send({
80 | data: JSON.stringify(str)
81 | });
82 | } else {
83 | this.socketTask.send(JSON.stringify(str));
84 | }
85 | } catch (e) {
86 | log(0, e, true);
87 | }
88 | }
89 | }
90 | close() {
91 | try {
92 | this.socketTask.close();
93 | } catch (e) {
94 | log(0, e, true);
95 | }
96 | }
97 | destroy() {
98 | this.socketTask = undefined;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/service/conversationService.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from '../yeim-uni-sdk';
4 | import {
5 | YeIMUniSDKDefines
6 | } from '../const/yeim-defines';
7 | import {
8 | emit
9 | } from '../func/event';
10 | import log from '../func/log';
11 | import md5 from '../utils/md5';
12 | import {
13 | buildSuccessObject,
14 | buildErrObject,
15 | successHandle,
16 | errHandle
17 | } from '../func/callback';
18 | import {
19 | YeIMUniSDKStatusCode
20 | } from '../const/yeim-status-code';
21 | import {
22 | Api,
23 | request
24 | } from '../func/request';
25 | import {
26 | getCache,
27 | removeCache,
28 | setCache
29 | } from '../func/storage';
30 |
31 |
32 | /**
33 | * 更新、保存单个会话到本地会话列表、发送会话列表更新事件
34 | *
35 | * @param {Conversation} conversation - 会话对象
36 | * @return {void}
37 | */
38 | function saveAndUpdateConversation(conversation) {
39 |
40 | let key = `yeim:conversationList:${md5(instance.userId)}`;
41 | let list = getCache(key);
42 | list = list ? list : [];
43 | let index = list.findIndex(item => {
44 | return item.conversationId === conversation.conversationId
45 | });
46 | if (index === -1) {
47 | list.unshift(conversation);
48 | } else {
49 | list.splice(index, 1);
50 | list.unshift(conversation);
51 | }
52 | saveConversationList(list);
53 |
54 | }
55 |
56 | /**
57 | * 根据会话ID获取本地会话详情
58 | *
59 | * @param {String} conversationId - 会话ID
60 | * @return {Conversation} conversation
61 | */
62 | function getConversation(conversationId) {
63 |
64 | if (!instance.checkLogged()) {
65 | return buildErrObject(YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
66 | }
67 | if (!conversationId) {
68 | return buildErrObject(YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'conversationId 不能为空');
69 | }
70 | let key = `yeim:conversationList:${md5(instance.userId)}`;
71 | let result = getCache(key);
72 | result = result ? result : [];
73 | let index = result.findIndex(item => {
74 | return item.conversationId === conversationId;
75 | });
76 | if (index !== -1) {
77 | return buildSuccessObject(YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result[index]);
78 | } else {
79 | return buildErrObject(YeIMUniSDKStatusCode.NO_CONVERSATION.code, YeIMUniSDKStatusCode.NO_CONVERSATION.describe);
80 | }
81 |
82 | }
83 |
84 | /**
85 | * 获取本地会话列表
86 | *
87 | * @param {Object} options - 参数对象
88 | *
89 | * @param {String} options.page - 页码
90 | * @param {String} options.limit - 每页数量
91 | * @param {(result)=>{}} [options.success] - 成功回调
92 | * @param {(error)=>{}} [options.fail] - 失败回调
93 | */
94 | function getConversationList(options) {
95 | if (!instance.checkLogged()) {
96 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
97 | }
98 | let page = options.page;
99 | let limit = options.limit;
100 | let key = `yeim:conversationList:${md5(instance.userId)}`;
101 | let result = getCache(key);
102 | result = result ? result : [];
103 | let skipNum = (page - 1) * limit;
104 | let list = (skipNum + limit >= result.length) ? result.slice(skipNum, result.length) : result.slice(skipNum,
105 | skipNum + limit);
106 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, list);
107 | }
108 |
109 | /**
110 | * 从云端获取会话列表保存到本地、并发送会话列表更新事件
111 | *
112 | * @return {void}
113 | */
114 | function saveCloudConversationListToLocal() {
115 | request(Api.Conversation.fetchConversationList, 'GET', {
116 | page: 1,
117 | limit: 999999,
118 | }).then((result) => {
119 | //查询结果保存到本地
120 | saveConversationList(result.records);
121 | }).catch((fail) => {
122 | log(1, fail);
123 | });
124 |
125 | }
126 |
127 | /**
128 | * 保存会话列表到本地,并发送会话更新事件
129 | *
130 | * @param {Array} list - 会话对象数组
131 | * @return {void}
132 | */
133 | function saveConversationList(list) {
134 | let key = `yeim:conversationList:${md5(instance.userId)}`;
135 | setCache(key, list);
136 | emit(YeIMUniSDKDefines.EVENT.CONVERSATION_LIST_CHANGED, list);
137 | }
138 |
139 | /**
140 | * 清除指定会话未读数
141 | *
142 | * 云端同时发送给对端已读事件(私聊)
143 | *
144 | * @param {String} conversationId - 会话ID
145 | * @return {void}
146 | */
147 | function clearConversationUnread(conversationId) {
148 |
149 | if (!instance.checkLogged()) {
150 | return buildErrObject(YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
151 | }
152 |
153 | //本地清除会话未读数
154 | let key = `yeim:conversationList:${md5(instance.userId)}`;
155 | let result = getCache(key);
156 | result = result ? result : [];
157 | let index = result.findIndex(item => {
158 | return item.conversationId === conversationId;
159 | });
160 | if (index !== -1) {
161 | result[index].unread = 0;
162 | setCache(key, result);
163 | }
164 | //云端清除会话未读数
165 | request(Api.Conversation.clearConversationUnread, "GET", {
166 | conversationId: conversationId
167 | }).then(() => { }).catch((fail) => {
168 | log(1, fail);
169 | });
170 | //发送会话列表更新事件
171 | emit(YeIMUniSDKDefines.EVENT.CONVERSATION_LIST_CHANGED, result);
172 |
173 | }
174 |
175 | /**
176 | * 收到某对端会话消息已读事件,处理本地会话消息已读字段,并发送给当前用户对端会话已读事件
177 | *
178 | * @param {Object} conversationId
179 | * @return {void}
180 | */
181 | function handlePrivateConversationReadReceipt(conversationId) {
182 |
183 | if (!conversationId) {
184 | return log(1, 'conversationId 为空,无法继续执行');
185 | }
186 | //查出当前会话发出的消息
187 | let messageKey = `yeim:messageList:${md5(instance.userId)}:conversationId:${md5(conversationId)}`;
188 | let result = getCache(messageKey);
189 | result = result ? result : [];
190 | if (result) {
191 | let tempList = [];
192 | for (let i = 0; i < result.length; i++) {
193 | let message = result[i];
194 | if (message.direction == 'out') {
195 | message.isRead = 1;
196 | result[i].isRead = 1;
197 | tempList.push(message);
198 | }
199 | }
200 | setCache(messageKey, result);
201 | //发送私聊会话已读事件
202 | emit(YeIMUniSDKDefines.EVENT.PRIVATE_READ_RECEIPT, {
203 | conversationId: conversationId,
204 | list: tempList
205 | });
206 | }
207 |
208 | }
209 |
210 | /**
211 | * 根据会话ID删除会话和聊天记录(包括云端)
212 | *
213 | * @param {Object} conversationId
214 | * @return {void}
215 | */
216 | function deleteConversation(conversationId) {
217 |
218 | if (!instance.checkLogged()) {
219 | return buildErrObject(YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
220 | }
221 |
222 | //1.删除本地会话
223 | let key = `yeim:conversationList:${md5(instance.userId)}`;
224 | let result = getCache(key);
225 | result = result ? result : [];
226 | let index = result.findIndex(item => {
227 | return item.conversationId === conversationId;
228 | });
229 | if (index !== -1) {
230 | result.splice(index, 1);
231 | setCache(key, result);
232 | }
233 | //2.删除本地会话内的聊天记录
234 | let messageKey = `yeim:messageList:${md5(instance.userId)}:conversationId:${md5(conversationId)}`;
235 | removeCache(messageKey);
236 |
237 | //3.删除云端会话和云端聊天记录
238 | request(Api.Conversation.deleteConversation, 'GET', {
239 | conversationId: conversationId
240 | }).then(() => { }).catch((fail) => {
241 | log(1, fail);
242 | });
243 |
244 | //4.发出会话列表更新事件
245 | emit(YeIMUniSDKDefines.EVENT.CONVERSATION_LIST_CHANGED, result);
246 |
247 | }
248 |
249 | export {
250 | saveAndUpdateConversation,
251 | clearConversationUnread,
252 | deleteConversation,
253 | getConversation,
254 | getConversationList,
255 | saveCloudConversationListToLocal,
256 | handlePrivateConversationReadReceipt
257 | }
258 |
--------------------------------------------------------------------------------
/src/service/friendService.js:
--------------------------------------------------------------------------------
1 | import {
2 | YeIMUniSDKDefines,
3 | instance
4 | } from '../yeim-uni-sdk';
5 | import {
6 | Api,
7 | request
8 | } from '../func/request';
9 | import {
10 | successHandle,
11 | errHandle
12 | } from '../func/callback';
13 | import {
14 | YeIMUniSDKStatusCode
15 | } from '../const/yeim-status-code';
16 | import {
17 | emit
18 | } from '../func/event';
19 | import log from '../func/log';
20 | import {
21 | getCache,
22 | setCache
23 | } from '../func/storage';
24 | import md5 from '../utils/md5';
25 |
26 | /**
27 | *
28 | * 从云端获取好友列表
29 | *
30 | * @param {Object} options - 参数对象
31 | * @param {Boolean} options.cloud - 是否从云端拉取
32 | * @param {Number} options.profile - 资料类型,0=简略资料,1=详细资料 (云端拉取有效)
33 | * @param {Number} options.page - 页码
34 | * @param {Number} options.limit - 每页数量
35 | *
36 | * @param {(result)=>{}} [options.success] - 成功回调
37 | * @param {(error)=>{}} [options.fail] - 失败回调
38 | */
39 | function getFriendList(options) {
40 |
41 | let key = `yeim:friendList:${md5(instance.userId)}`;
42 | let page = options.page ? options.page : 1;
43 | let limit = options.limit ? options.limit : 20;
44 | if (options.cloud) {
45 | //从云端获取好友列表
46 | request(Api.Friend.fetchList, 'GET', {
47 | profile: options.profile ? 0 : 1,
48 | page: page,
49 | limit: limit,
50 | }).then((result) => {
51 | const {
52 | records
53 | } = result;
54 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, records);
55 | }).catch((fail) => {
56 | errHandle(options, fail.code, fail.message);
57 | log(1, fail);
58 | });
59 | } else {
60 | //从本地获取好友列表
61 |
62 | //查询本地缓存
63 | let list = getCache(key);
64 | list = list ? list : [];
65 | let skipNum = (page - 1) * limit;
66 | list = (skipNum + limit >= list.length) ? list.slice(skipNum, list.length) : list.slice(skipNum,
67 | skipNum + limit);
68 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, list);
69 | }
70 | }
71 |
72 | /**
73 | *
74 | * 响应好友列表更新
75 | *
76 | */
77 | function handleFriendListChanged() {
78 | //获取最新记录
79 | getFriendList({
80 | cloud: true,
81 | page: 1,
82 | limit: 9999999,
83 | success: (result) => {
84 | let key = `yeim:friendList:${md5(instance.userId)}`;
85 | setCache(key, result.data);
86 | emit(YeIMUniSDKDefines.EVENT.FRIEND_LIST_CHANGED, result);
87 | },
88 | fail: () => {
89 | emit(YeIMUniSDKDefines.EVENT.FRIEND_LIST_CHANGED, null);
90 | }
91 | });
92 | }
93 |
94 | /**
95 | *
96 | * 响应好友申请列表更新
97 | *
98 | */
99 | function handleFriendApplyListChanged(type = 0) {
100 | //获取最新记录
101 | getFriendApplyList({
102 | cloud: true,
103 | type: type,
104 | page: 1,
105 | limit: 9999999,
106 | success: (result) => {
107 | const {
108 | data: {
109 | records,
110 | unread
111 | }
112 | } = result;
113 | let listKey = `yeim:friendApplyList:${md5(instance.userId)}`;
114 | let unreadKey = `yeim:friendApplyUnread:${md5(instance.userId)}`;
115 | setCache(listKey, records);
116 | setCache(unreadKey, unread);
117 | emit(YeIMUniSDKDefines.EVENT.FRIEND_APPLY_LIST_CHANGED, result);
118 | },
119 | fail: () => {
120 | emit(YeIMUniSDKDefines.EVENT.FRIEND_APPLY_LIST_CHANGED, null);
121 | }
122 | });
123 | }
124 |
125 | /**
126 | *
127 | * 从云端获取好友申请列表
128 | *
129 | * @param {Object} options - 参数对象
130 | *
131 | * @param {Boolean} options.cloud - 是否从云端拉取
132 | * @param {Number} options.type - 类型,0=发给我申请,1=我发出去的申请 (云端拉取有效)
133 | * @param {Number} options.page - 页码
134 | * @param {Number} options.limit - 每页数量
135 | *
136 | * @param {(result)=>{}} [options.success] - 成功回调
137 | * @param {(error)=>{}} [options.fail] - 失败回调
138 | */
139 | function getFriendApplyList(options) {
140 |
141 | let listKey = `yeim:friendApplyList:${md5(instance.userId)}`;
142 | let unreadKey = `yeim:friendApplyUnread:${md5(instance.userId)}`;
143 | let page = options.page ? options.page : 1;
144 | let limit = options.limit ? options.limit : 20;
145 | if (options.cloud) {
146 | //从云端获取好友申请列表
147 | request(Api.Friend.fetchApplyList, 'GET', {
148 | type: options.type ? options.type : 0,
149 | page: page,
150 | limit: limit,
151 | }).then((result) => {
152 | const {
153 | apply: {
154 | records
155 | },
156 | unread
157 | } = result;
158 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
159 | records,
160 | unread
161 | });
162 | }).catch((fail) => {
163 | errHandle(options, fail.code, fail.message);
164 | log(1, fail);
165 | });
166 | } else {
167 | //从本地获取好友列表
168 |
169 | //查询本地缓存
170 | let list = getCache(listKey);
171 | list = list ? list : [];
172 | let skipNum = (page - 1) * limit;
173 | list = (skipNum + limit >= list.length) ? list.slice(skipNum, list.length) : list.slice(skipNum,
174 | skipNum + limit);
175 |
176 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
177 | list,
178 | unread: getCache(unreadKey) ? getCache(unreadKey) : 0
179 | });
180 |
181 | }
182 | }
183 |
184 | /**
185 | *
186 | * 将全部好友申请设置为已读状态
187 | *
188 | * @param {Object} options - 参数对象
189 | *
190 | * @param {(result)=>{}} [options.success] - 成功回调
191 | * @param {(error)=>{}} [options.fail] - 失败回调
192 | */
193 | function setApplyListRead(options) {
194 | request(Api.Friend.setRead, 'GET', {}).then(() => {
195 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
196 | }).catch((fail) => {
197 | errHandle(options, fail.code, fail.message);
198 | log(1, fail);
199 | });
200 | }
201 |
202 |
203 | /**
204 | *
205 | * 同意好友申请
206 | *
207 | * @param {Object} options - 参数对象
208 | *
209 | * @param {Number} options.id - 申请ID
210 | * @param {String} options.remark - 备注
211 | *
212 | * @param {(result)=>{}} [options.success] - 成功回调
213 | * @param {(error)=>{}} [options.fail] - 失败回调
214 | */
215 | function acceptApply(options) {
216 |
217 | if (!instance.checkLogged()) {
218 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
219 | }
220 |
221 | if (!options.id) {
222 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'id 不能为空');
223 | }
224 |
225 | request(Api.Friend.acceptApply, 'GET', {
226 | id: options.id,
227 | remark: options.remark ? options.remark : null
228 | }).then(() => {
229 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
230 | }).catch((fail) => {
231 | errHandle(options, fail.code, fail.message);
232 | log(1, fail);
233 | });
234 | }
235 |
236 | /**
237 | *
238 | * 拒绝好友申请
239 | *
240 | * @param {Object} options - 参数对象
241 | *
242 | * @param {Number} options.id - 申请ID
243 | *
244 | * @param {(result)=>{}} [options.success] - 成功回调
245 | * @param {(error)=>{}} [options.fail] - 失败回调
246 | */
247 | function refuseApply(options) {
248 |
249 | if (!instance.checkLogged()) {
250 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
251 | }
252 |
253 | if (!options.id) {
254 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'id 不能为空');
255 | }
256 |
257 | request(Api.Friend.refuseApply, 'GET', {
258 | id: options.id
259 | }).then(() => {
260 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
261 | }).catch((fail) => {
262 | errHandle(options, fail.code, fail.message);
263 | log(1, fail);
264 | });
265 | }
266 |
267 | /**
268 | *
269 | * 添加好友
270 | *
271 | * @param {Object} options - 参数对象
272 | *
273 | * @param {String} options.userId - 用户ID
274 | * @param {String} options.remark - 好友备注
275 | * @param {String} options.extraMessage - 附言
276 | *
277 | * @param {(result)=>{}} [options.success] - 成功回调
278 | * @param {(error)=>{}} [options.fail] - 失败回调
279 | */
280 | function addFriend(options) {
281 |
282 | if (!instance.checkLogged()) {
283 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
284 | }
285 |
286 | if (!options.userId) {
287 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'userId 不能为空');
288 | }
289 |
290 | request(Api.Friend.addFriend, 'POST', {
291 | userId: options.userId,
292 | remark: options.remark ? options.remark : null,
293 | extraMessage: options.extraMessage ? options.extraMessage : null
294 | }).then(() => {
295 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
296 | }).catch((fail) => {
297 | if (fail.code === YeIMUniSDKStatusCode.APPLY_NEED.code) {
298 | successHandle(options, YeIMUniSDKStatusCode.APPLY_NEED.describe, null, YeIMUniSDKStatusCode
299 | .APPLY_NEED.code);
300 | } else {
301 | errHandle(options, fail.code, fail.message);
302 | log(1, fail);
303 | }
304 | });
305 |
306 | }
307 |
308 | /**
309 | *
310 | * 删除好友
311 | *
312 | * @param {Object} options - 参数对象
313 | *
314 | * @param {Array} options.members - 好友ID列表
315 | *
316 | * @param {(result)=>{}} [options.success] - 成功回调
317 | * @param {(error)=>{}} [options.fail] - 失败回调
318 | */
319 | function deleteFriend(options) {
320 |
321 | if (!instance.checkLogged()) {
322 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
323 | }
324 |
325 | if (!options.members) {
326 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'members 不能为空');
327 | }
328 |
329 | request(Api.Friend.deleteFriend, 'POST', {
330 | members: options.members
331 | }).then(() => {
332 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
333 | }).catch((fail) => {
334 | errHandle(options, fail.code, fail.message);
335 | log(1, fail);
336 | });
337 |
338 | }
339 |
340 | /**
341 | *
342 | * 更新好友资料
343 | *
344 | * @param {Object} options - 参数对象
345 | *
346 | * @param {String} options.userId - 好友ID
347 | * @param {String} options.remark - 好友备注
348 | * @param {String} options.extend - 自定义扩展字段
349 | *
350 | * @param {(result)=>{}} [options.success] - 成功回调
351 | * @param {(error)=>{}} [options.fail] - 失败回调
352 | */
353 | function updateFriend(options) {
354 |
355 | if (!instance.checkLogged()) {
356 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
357 | }
358 |
359 | if (!options.userId) {
360 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'userId 不能为空');
361 | }
362 |
363 | if (!options.remark && !options.extend) {
364 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, '请至少传入一个参数更新');
365 | }
366 |
367 | request(Api.Friend.updateFriend, 'POST', {
368 | userId: options.userId,
369 | remark: options.remark ? options.remark : null,
370 | extend: options.extend ? options.extend : null,
371 | }).then(() => {
372 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, null);
373 | }).catch((fail) => {
374 | errHandle(options, fail.code, fail.message);
375 | log(1, fail);
376 | });
377 |
378 | }
379 |
380 | export {
381 | getFriendList,
382 | handleFriendListChanged,
383 | handleFriendApplyListChanged,
384 | getFriendApplyList,
385 | setApplyListRead,
386 | addFriend,
387 | deleteFriend,
388 | updateFriend,
389 | acceptApply,
390 | refuseApply
391 | }
--------------------------------------------------------------------------------
/src/service/groupService.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from '../yeim-uni-sdk';
4 | import {
5 | YeIMUniSDKDefines
6 | } from '../const/yeim-defines';
7 | import log from '../func/log';
8 | import {
9 | successHandle,
10 | errHandle
11 | } from '../func/callback';
12 | import {
13 | Api,
14 | request
15 | } from '../func/request';
16 | import {
17 | YeIMUniSDKStatusCode
18 | } from '../const/yeim-status-code';
19 |
20 | /**
21 | *
22 | * 创建群组
23 | *
24 | * @param {Object} options - 参数对象
25 | *
26 | * { "name":"群名称","avatarUrl":"群头像", success: (result) => {}, fail: (error) => {} }
27 | *
28 | * @param {String} options.name - 群名称
29 | * @param {String} options.avatarUrl - 群头像
30 | * @param {String} [options.groupId] - 群ID,未填写时系统自动生成
31 | * @param {YeIMUniSDKDefines.GROUP.JOINMODE} [options.joinMode] - 群申请处理方式
32 | * @param {String} [options.introduction] - 群简介
33 | * @param {String} [options.notification] - 群公告
34 | * @param {Array} [options.members] - 创建群聊初始化成员(用户ID数组)
35 | * @param {(result)=>{}} [options.success] - 成功回调
36 | * @param {(error)=>{}} [options.fail] - 失败回调
37 | *
38 | * @example
39 | * createGroup({
40 | name: "",
41 | avatarUrl: "",
42 | success: (result) => {},
43 | fail: (error) => {}
44 | });
45 | */
46 |
47 | function createGroup(options) {
48 |
49 | if (!instance.checkLogged()) {
50 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
51 | }
52 |
53 | if (!options.name) {
54 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'name 不能为空');
55 | }
56 |
57 | if (!options.avatarUrl) {
58 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'avatarUrl 不能为空');
59 | }
60 |
61 | request(Api.Group.create, 'POST', options).then(() => {
62 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
63 | }).catch((fail) => {
64 | errHandle(options, fail.code, fail.message);
65 | log(1, fail);
66 | });
67 |
68 | }
69 |
70 | /**
71 | *
72 | * 解散群组
73 | *
74 | * 仅群主可操作
75 | *
76 | * @param {Object} options - 参数对象
77 | *
78 | * { "groupId":"群ID", success: (result) => {}, fail: (error) => {} }
79 | *
80 | * @param {String} [options.groupId] - 群ID
81 | * @param {(result)=>{}} [options.success] - 成功回调
82 | * @param {(error)=>{}} [options.fail] - 失败回调
83 | *
84 | * @example
85 | * dissolveGroup({
86 | groupId: "",
87 | success: (result) => {},
88 | fail: (error) => {}
89 | });
90 | */
91 | function dissolveGroup(options) {
92 |
93 | if (!instance.checkLogged()) {
94 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
95 | }
96 |
97 | if (!options.groupId) {
98 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
99 | }
100 |
101 | request(Api.Group.dissolve, 'GET', {
102 | groupId: options.groupId
103 | }).then(() => {
104 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
105 | }).catch((fail) => {
106 | errHandle(options, fail.code, fail.message);
107 | log(1, fail);
108 | });
109 |
110 | }
111 |
112 | /**
113 | *
114 | * 转让群主
115 | *
116 | * 仅群主可操作
117 | *
118 | * @param {Object} options - 参数对象
119 | *
120 | * { "groupId":"群ID", "userId":"转让用户ID", success: (result) => {}, fail: (error) => {} }
121 | *
122 | * @param {String} [options.groupId] - 群ID
123 | * @param {String} [options.userId] - 转让用户ID
124 | * @param {(result)=>{}} [options.success] - 成功回调
125 | * @param {(error)=>{}} [options.fail] - 失败回调
126 | *
127 | * @example
128 | * transferLeader({
129 | groupId: "",
130 | userId: "",
131 | success: (result) => {},
132 | fail: (error) => {}
133 | });
134 | */
135 | function transferLeader(options) {
136 |
137 | if (!instance.checkLogged()) {
138 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
139 | }
140 |
141 | if (!options.groupId) {
142 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
143 | }
144 |
145 | if (!options.userId) {
146 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'userId 不能为空');
147 | }
148 |
149 | request(Api.Group.transferLeader, 'GET', {
150 | groupId: options.groupId,
151 | userId: options.userId
152 | }).then(() => {
153 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
154 | }).catch((fail) => {
155 | errHandle(options, fail.code, fail.message);
156 | log(1, fail);
157 | });
158 | }
159 |
160 | /**
161 | *
162 | * 更新群组资料
163 | *
164 | * @param {Object} options - 参数对象
165 | *
166 | * { "groupId":"群ID", "name":"群名称","avatarUrl":"群头像", success: (result) => {}, fail: (error) => {} }
167 | *
168 | * @param {String} [options.groupId] - 群ID
169 | * @param {String} [options.name] - 群名称
170 | * @param {String} [options.avatarUrl] - 群头像
171 | * @param {YeIMUniSDKDefines.GROUP.JOINMODE} [options.joinMode] - 群申请处理方式
172 | * @param {String} [options.introduction] - 群简介
173 | * @param {String} [options.notification] - 群公告
174 | * @param {Number} [options.isMute] - 全体禁言 0,1
175 | * @param {(result)=>{}} [options.success] - 成功回调
176 | * @param {(error)=>{}} [options.fail] - 失败回调
177 | *
178 | * @example
179 | * updateGroup({
180 | groupId: "",
181 | name: "",
182 | avatarUrl: "",
183 | success: (result) => {},
184 | fail: (error) => {}
185 | });
186 | */
187 | function updateGroup(options) {
188 |
189 | if (!instance.checkLogged()) {
190 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
191 | }
192 |
193 | if (!options.groupId) {
194 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
195 | }
196 |
197 | request(Api.Group.update, 'POST', options).then(() => {
198 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
199 | }).catch((fail) => {
200 | errHandle(options, fail.code, fail.message);
201 | log(1, fail);
202 | });
203 |
204 | }
205 |
206 | /**
207 | *
208 | * 通过群ID获取群组资料
209 | *
210 | * @param {Object} options - 参数对象
211 | *
212 | * { "groupId":"群ID", success: (result) => {}, fail: (error) => {} }
213 | *
214 | * @param {String} options.groupId - 群ID
215 | * @param {(result)=>{}} [options.success] - 成功回调
216 | * @param {(error)=>{}} [options.fail] - 失败回调
217 | *
218 | * @example
219 | * getGroup({
220 | groupId: "",
221 | success: (result) => {},
222 | fail: (error) => {}
223 | });
224 | */
225 | function getGroup(options) {
226 |
227 | if (!instance.checkLogged()) {
228 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
229 | }
230 |
231 | if (!options.groupId) {
232 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
233 | }
234 |
235 | request(Api.Group.fetchGroupInfoById, 'GET', {
236 | groupId: options.groupId
237 | }).then((result) => {
238 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
239 | }).catch((fail) => {
240 | errHandle(options, fail.code, fail.message);
241 | log(1, fail);
242 | });
243 |
244 | }
245 |
246 | /**
247 | *
248 | * 获取我的群组列表
249 | *
250 | * @param {Object} options - 参数对象
251 | *
252 | * @param {(result)=>{}} [options.success] - 成功回调
253 | * @param {(error)=>{}} [options.fail] - 失败回调
254 | *
255 | * @example
256 | * getGroupList({
257 | success: (result) => {},
258 | fail: (error) => {}
259 | });
260 | */
261 | function getGroupList(options) {
262 |
263 | if (!instance.checkLogged()) {
264 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
265 | }
266 |
267 | request(Api.Group.list, 'GET', {}).then((result) => {
268 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
269 | }).catch((fail) => {
270 | errHandle(options, fail.code, fail.message);
271 | log(1, fail);
272 | });
273 |
274 | }
275 |
276 | /**
277 | *
278 | * 用户申请入群
279 | *
280 | * IM内用户均可调用此接口申请进入传入的群组ID的群,根据群申请处理方式不同,可能直接进入,也可能等待审核
281 | *
282 | * @param {Object} options - 参数对象
283 | *
284 | * { "groupId": "群ID", success: (result) => {}, fail: (error) => {} }
285 | *
286 | * @param {String} options.groupId - 群ID
287 | * @param {(result)=>{}} [options.success] - 成功回调
288 | * @param {(error)=>{}} [options.fail] - 失败回调
289 | *
290 | * @example
291 | * joinGroup({
292 | groupId: "",
293 | success: (result) => {},
294 | fail: (error) => {}
295 | });
296 | */
297 | function joinGroup(options) {
298 |
299 | if (!instance.checkLogged()) {
300 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
301 | }
302 |
303 | if (!options.groupId) {
304 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
305 | }
306 |
307 | request(Api.Group.addUser, 'POST', {
308 | groupId: options.groupId,
309 | members: [
310 | instance.userId
311 | ]
312 | }).then((result) => {
313 |
314 | //群组信息
315 | let group = result.group;
316 | //操作成功的用户ID列表
317 | let successList = result.successList;
318 | //忽略了的用户ID列表
319 | let ignoreList = result.ignoreList;
320 |
321 | //添加的用户重复加入
322 | if (ignoreList.indexOf(instance.userId) != -1) {
323 | return errHandle(options, YeIMUniSDKStatusCode.GROUP_APPLY_REPEAT.code, YeIMUniSDKStatusCode
324 | .GROUP_APPLY_REPEAT.describe);
325 | }
326 |
327 | //判断成功列表中是否包含当前申请的用户
328 | let success = false;
329 | if (successList.indexOf(instance.userId) != -1) {
330 | success = true;
331 | }
332 |
333 | //申请入群的接口异常
334 | if (!success) {
335 | return errHandle(options, YeIMUniSDKStatusCode.GROUP_APPLY_ERROR.code, YeIMUniSDKStatusCode
336 | .GROUP_APPLY_ERROR.describe);
337 | }
338 |
339 | //自由加入,无需申请
340 | if (group.joinMode == YeIMUniSDKDefines.GROUP.JOINMODE.FREE) {
341 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.code, '成功加入群组');
342 | } else if (group.joinMode == YeIMUniSDKDefines.GROUP.JOINMODE.CHECK) {
343 | successHandle(options, YeIMUniSDKStatusCode.GROUP_APPLY_WAIT.code, YeIMUniSDKStatusCode
344 | .GROUP_APPLY_WAIT.describe);
345 | } else {
346 | return errHandle(options, YeIMUniSDKStatusCode.NORMAL_ERROR.code, YeIMUniSDKStatusCode
347 | .NORMAL_ERROR.describe);
348 | }
349 |
350 | }).catch((fail) => {
351 | errHandle(options, fail.code, fail.message);
352 | log(1, fail);
353 | });
354 | }
355 |
356 | /**
357 | *
358 | * 退出群组
359 | *
360 | * @param {Object} options - 参数对象
361 | *
362 | * { "groupId":"群ID", success: (result) => {}, fail: (error) => {} }
363 | *
364 | * @param {String} options.groupId - 群ID
365 | * @param {(result)=>{}} [options.success] - 成功回调
366 | * @param {(error)=>{}} [options.fail] - 失败回调
367 | *
368 | * @example
369 | * leaveGroup({
370 | groupId: "",
371 | success: (result) => {},
372 | fail: (error) => {}
373 | });
374 | */
375 | function leaveGroup(options) {
376 |
377 | if (!instance.checkLogged()) {
378 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
379 | }
380 |
381 | if (!options.groupId) {
382 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
383 | }
384 |
385 | request(Api.Group.leave, 'GET', {
386 | groupId: options.groupId
387 | }).then(() => {
388 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
389 | }).catch((fail) => {
390 | errHandle(options, fail.code, fail.message);
391 | log(1, fail);
392 | });
393 |
394 | }
395 |
396 | /**
397 | *
398 | * 添加群成员
399 | *
400 | * 不限权限,IM内用户均可调用此接口,但根据群申请处理方式不同,可能直接进入,也可能等待审核
401 | *
402 | * @param {Object} options - 参数对象
403 | *
404 | * { "groupId":"群ID", "members": ["user1", "user2"], success: (result) => {}, fail: (error) => {} }
405 | *
406 | * @param {String} options.groupId - 群ID
407 | * @param {Array} options.members - 用户ID列表
408 | * @param {(result)=>{}} [options.success] - 成功回调
409 | * @param {(error)=>{}} [options.fail] - 失败回调
410 | *
411 | * @example
412 | * addGroupUsers({
413 | groupId: "",
414 | members: ["user1", "user2"],
415 | success: (result) => {},
416 | fail: (error) => {}
417 | });
418 | */
419 | function addGroupUsers(options) {
420 |
421 | if (!instance.checkLogged()) {
422 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
423 | }
424 |
425 | if (!options.groupId) {
426 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
427 | }
428 |
429 | if (!options.members || options.members.length <= 0) {
430 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'members 不能为空');
431 | }
432 |
433 | request(Api.Group.addUser, 'POST', {
434 | groupId: options.groupId,
435 | members: options.members
436 | }).then((result) => {
437 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
438 | }).catch((fail) => {
439 | errHandle(options, fail.code, fail.message);
440 | log(1, fail);
441 | });
442 |
443 | }
444 |
445 | /**
446 | *
447 | * 移除群成员
448 | *
449 | * 仅群主可使用此接口
450 | *
451 | * @param {Object} options - 参数对象
452 | *
453 | * { "groupId":"群ID", "members": ["user1", "user2"], success: (result) => {}, fail: (error) => {} }
454 | *
455 | * @param {String} options.groupId - 群ID
456 | * @param {Array} options.members - 用户ID列表
457 | * @param {(result)=>{}} [options.success] - 成功回调
458 | * @param {(error)=>{}} [options.fail] - 失败回调
459 | *
460 | * @example
461 | * removeGroupUsers({
462 | groupId: "",
463 | members: ["user1", "user2"],
464 | success: (result) => {},
465 | fail: (error) => {}
466 | });
467 | */
468 | function removeGroupUsers(options) {
469 |
470 | if (!instance.checkLogged()) {
471 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
472 | }
473 |
474 | if (!options.groupId) {
475 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
476 | }
477 |
478 | if (!options.members || options.members.length <= 0) {
479 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'members 不能为空');
480 | }
481 |
482 | request(Api.Group.remove, 'POST', {
483 | groupId: options.groupId,
484 | members: options.members
485 | }).then(() => {
486 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
487 | }).catch((fail) => {
488 | errHandle(options, fail.code, fail.message);
489 | log(1, fail);
490 | });
491 |
492 | }
493 |
494 | /**
495 | *
496 | * 获取群成员列表
497 | *
498 | * @param {Object} options - 参数对象
499 | *
500 | * { "groupId":"群ID", success: (result) => {}, fail: (error) => {} }
501 | *
502 | * @param {String} options.groupId - 群ID
503 | * @param {(result)=>{}} [options.success] - 成功回调
504 | * @param {(error)=>{}} [options.fail] - 失败回调
505 | *
506 | * @example
507 | * getGroupUserList({
508 | groupId: "group_1",
509 | success: (result) => {},
510 | fail: (error) => {}
511 | });
512 | */
513 | function getGroupUserList(options) {
514 |
515 | if (!instance.checkLogged()) {
516 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
517 | }
518 |
519 | if (!options.groupId) {
520 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
521 | }
522 |
523 | request(Api.Group.memberList, 'GET', {
524 | groupId: options.groupId
525 | }).then((result) => {
526 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
527 | }).catch((fail) => {
528 | errHandle(options, fail.code, fail.message);
529 | log(1, fail);
530 | });
531 |
532 | }
533 |
534 | /**
535 | *
536 | * 设置群管理员
537 | *
538 | * 仅群主可操作此接口
539 | *
540 | * @param {Object} options - 参数对象
541 | *
542 | * { "groupId":"群ID","userId":"要设置的用户ID","isAdmin":"是否设置管理员,0=取消,1=设置", success: (result) => {}, fail: (error) => {} }
543 | *
544 | * @param {String} options.groupId - 群ID
545 | * @param {String} options.userId - 要设置的用户ID
546 | * @param {Number} options.isAdmin - 是否设置管理员,0=取消,1=设置
547 | * @param {(result)=>{}} [options.success] - 成功回调
548 | * @param {(error)=>{}} [options.fail] - 失败回调
549 | *
550 | * @example
551 | * setAdminstrator({
552 | groupId: "",
553 | userId: "",
554 | isAdmin: 1,
555 | success: (result) => {},
556 | fail: (error) => {}
557 | });
558 | */
559 | function setAdminstrator(options) {
560 |
561 | if (!instance.checkLogged()) {
562 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
563 | }
564 |
565 | if (!options.groupId) {
566 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
567 | }
568 |
569 | request(Api.Group.adminstrator, 'GET', {
570 | groupId: options.groupId,
571 | userId: options.userId,
572 | isAdmin: isAdmin === 1 ? isAdmin : 0
573 | }).then(() => {
574 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
575 | }).catch((fail) => {
576 | errHandle(options, fail.code, fail.message);
577 | log(1, fail);
578 | });
579 |
580 | }
581 |
582 | /**
583 | *
584 | * 获取群组用户入群申请列表
585 | *
586 | * 群主或管理员调用此接口可获取名下所有群组入群申请列表
587 | *
588 | * @param {Object} options - 参数对象
589 | * @param {(result)=>{}} [options.success] - 成功回调
590 | * @param {(error)=>{}} [options.fail] - 失败回调
591 | *
592 | * @example
593 | * getGroupApplyList({
594 | success: (result) => {},
595 | fail: (error) => {}
596 | });
597 | */
598 | function getGroupApplyList(options) {
599 |
600 | if (!instance.checkLogged()) {
601 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
602 | }
603 |
604 | if (!options.groupId) {
605 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
606 | }
607 |
608 | request(Api.Group.applyList, 'GET', {}).then((result) => {
609 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
610 | }).catch((fail) => {
611 | errHandle(options, fail.code, fail.message);
612 | log(1, fail);
613 | });
614 |
615 | }
616 |
617 | /**
618 | *
619 | * 处理群组用户入群申请
620 | *
621 | * 申请记录所在的群组中群主或管理员可调用此接口处理申请
622 | *
623 | * @param {Object} options - 参数对象
624 | * @param {Number} options.id - 申请记录的ID
625 | * @param {YeIMUniSDKDefines.GROUP.APPLYSTATUS} options.status - 处理结果
626 | * @param {(result)=>{}} [options.success] - 成功回调
627 | * @param {(error)=>{}} [options.fail] - 失败回调
628 | *
629 | * @example
630 | * handleApply({
631 | id: 5, //申请记录的ID
632 | status: YeIMUniSDKDefines.GROUP.APPLYSTATUS.AGREE, //同意
633 | success: (result) => {},
634 | fail: (error) => {}
635 | });
636 | */
637 | function handleApply(options) {
638 |
639 | if (!instance.checkLogged()) {
640 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
641 | }
642 |
643 | if (!options.id) {
644 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'id 不能为空');
645 | }
646 |
647 | if (!options.status) {
648 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'status 不能为空');
649 | }
650 |
651 | request(Api.Group.handleApply, 'GET', {
652 | id: options.id,
653 | status: options.status
654 | }).then(() => {
655 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
656 | }).catch((fail) => {
657 | errHandle(options, fail.code, fail.message);
658 | log(1, fail);
659 | });
660 |
661 | }
662 |
663 | /**
664 | *
665 | * 禁言群成员
666 | *
667 | * 群组中群主或管理员可调用此接口禁言群成员,每次设置的分钟数均从操作时间开始算起,设置0则取消禁言
668 | *
669 | * @param {Object} options - 参数对象
670 | *
671 | * { "groupId":"群ID","userId":"禁言用户ID","time":"禁言分钟数", success: (result) => {}, fail: (error) => {} }
672 | *
673 | * @param {String} options.groupId - 群ID
674 | * @param {String} options.userId - 禁言用户ID
675 | * @param {Number} options.time - 禁言分钟数
676 | * @param {(result)=>{}} [options.success] - 成功回调
677 | * @param {(error)=>{}} [options.fail] - 失败回调
678 | *
679 | * @example
680 | * setMute({
681 | groupId: "group_1",
682 | userId: "user1",
683 | time: 10,
684 | success: (result) => {},
685 | fail: (error) => {}
686 | });
687 | */
688 | function setMute(options) {
689 |
690 | if (!instance.checkLogged()) {
691 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
692 | }
693 |
694 | if (!options.groupId) {
695 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'groupId 不能为空');
696 | }
697 |
698 | if (!options.userId) {
699 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'userId 不能为空');
700 | }
701 |
702 | if (!options.time) {
703 | options.time = 0;
704 | }
705 |
706 | request(Api.Group.setMute, 'GET', {
707 | groupId: options.groupId,
708 | userId: options.userId,
709 | time: options.time
710 | }).then(() => {
711 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
712 | }).catch((fail) => {
713 | errHandle(options, fail.code, fail.message);
714 | log(1, fail);
715 | });
716 |
717 | }
718 |
719 | export {
720 | createGroup,
721 | dissolveGroup,
722 | getGroup,
723 | getGroupList,
724 | transferLeader,
725 | updateGroup,
726 | joinGroup,
727 | leaveGroup,
728 | addGroupUsers,
729 | getGroupUserList,
730 | removeGroupUsers,
731 | setAdminstrator,
732 | getGroupApplyList,
733 | handleApply,
734 | setMute
735 | }
736 |
--------------------------------------------------------------------------------
/src/service/pushService.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable*/
2 |
3 | import {
4 | instance
5 | } from '../yeim-uni-sdk';
6 |
7 | import log from '../func/log';
8 | import {
9 | Api,
10 | request
11 | } from '../func/request';
12 |
13 | /**
14 | * 检测设备通知权限及跳转系统设置通知页面
15 | */
16 | function setPushPermissions() {
17 | let systemInfo = uni.getSystemInfoSync();
18 | if (systemInfo.uniPlatform == 'app' && systemInfo.osName ==
19 | 'android') { // 判断是Android
20 | var main = plus.android.runtimeMainActivity();
21 | var pkName = main.getPackageName();
22 | var uid = main.getApplicationInfo().plusGetAttribute('uid');
23 | var NotificationManagerCompat = plus.android.importClass('android.support.v4.app.NotificationManagerCompat');
24 | //android.support.v4升级为androidx
25 | if (NotificationManagerCompat == null) {
26 | NotificationManagerCompat = plus.android.importClass('androidx.core.app.NotificationManagerCompat');
27 | }
28 | var areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();
29 |
30 | // 未开通‘允许通知’权限,则弹窗提醒开通,并点击确认后,跳转到系统设置页面进行设置
31 | var firstFlag = uni.getStorageSync('first_flag') || false;
32 | if (!areNotificationsEnabled && !firstFlag) {
33 | uni.setStorageSync('first_flag', true);
34 | uni.showModal({
35 | title: '通知权限开启提醒',
36 | content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
37 | showCancel: false,
38 | confirmText: '去设置',
39 | success: function (res) {
40 | if (res.confirm) {
41 | var Intent = plus.android.importClass('android.content.Intent');
42 | var Build = plus.android.importClass("android.os.Build");
43 | //android 8.0引导
44 | if (Build.VERSION.SDK_INT >= 26) {
45 | var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
46 | intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
47 | } else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
48 | var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
49 | intent.putExtra('app_package', pkName);
50 | intent.putExtra('app_uid', uid);
51 | } else { //(<21)其他--跳转到该应用管理的详情页
52 | intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
53 | var uri = Uri.fromParts('package', mainActivity.getPackageName(), null);
54 | intent.setData(uri);
55 | }
56 | // 跳转到该应用的系统通知设置页
57 | main.startActivity(intent);
58 | }
59 | }
60 | });
61 | }
62 | } else if (systemInfo.uniPlatform == 'app' && systemInfo.osName ==
63 | 'ios') { // 判断是IOS
64 | var isOn = undefined;
65 | var types = 0;
66 | var app = plus.ios.invoke('UIApplication', 'sharedApplication');
67 | var settings = plus.ios.invoke(app, 'currentUserNotificationSettings');
68 | if (settings) {
69 | types = settings.plusGetAttribute('types');
70 | plus.ios.deleteObject(settings);
71 | } else {
72 | types = plus.ios.invoke(app, 'enabledRemoteNotificationTypes');
73 | }
74 | plus.ios.deleteObject(app);
75 | isOn = (0 != types);
76 | if (isOn == false) {
77 | uni.showModal({
78 | title: '通知权限开启提醒',
79 | content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
80 | showCancel: false,
81 | confirmText: '去设置',
82 | success: function (res) {
83 | if (res.confirm) {
84 | var app = plus.ios.invoke('UIApplication', 'sharedApplication');
85 | var setting = plus.ios.invoke('NSURL', 'URLWithString:', 'app-settings:');
86 | plus.ios.invoke(app, 'openURL:', setting);
87 | plus.ios.deleteObject(setting);
88 | plus.ios.deleteObject(app);
89 | }
90 | }
91 | });
92 | }
93 | }
94 | }
95 |
96 | /**
97 | *
98 | * Android8.0
99 | * 创建推送渠道
100 | *
101 | */
102 | function createNotificationChannel() {
103 | let systemInfo = uni.getSystemInfoSync();
104 | if (systemInfo.uniPlatform == 'app' && systemInfo.osName ==
105 | 'android' && instance.defaults.notification && instance.defaults.notification.oppoChannelId) {
106 | var Build = plus.android.importClass('android.os.Build');
107 | if (Build.VERSION.SDK_INT >= 26) {
108 | let oppoChannelId = instance.defaults.notification.oppoChannelId;
109 | let channelName = '聊天离线通知';
110 | let main = plus.android.runtimeMainActivity();
111 | let Context = plus.android.importClass('android.content.Context');
112 | let NotificationManager = plus.android.importClass('android.app.NotificationManager');
113 | let nManager = main.getSystemService(Context.NOTIFICATION_SERVICE);
114 | let channel = nManager.getNotificationChannel(oppoChannelId);
115 | let NotificationChannel = plus.android.importClass('android.app.NotificationChannel');
116 | let Notification = plus.android.importClass('android.app.Notification');
117 | if (channel) {
118 | nManager.deleteNotificationChannel(channel);
119 | }
120 | //OPPO创建本地通道
121 | if (!channel || channel == null || channel == 'null' || channel == undefined) {
122 | let channel = new NotificationChannel(oppoChannelId, channelName, NotificationManager
123 | .IMPORTANCE_HIGH);
124 | channel.setDescription('用于用户离线时推送消息通知');
125 | channel.enableVibration(true);
126 | channel.enableLights(true);
127 | channel.setBypassDnd(true);
128 | channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
129 | nManager.createNotificationChannel(channel);
130 | }
131 | }
132 | }
133 | }
134 |
135 | /**
136 | *
137 | * 注册APP用户推送标识符
138 | * 将个推cid绑定到后端,用于离线推送消息通知
139 | *
140 | */
141 | function bindAppUserPushCID() {
142 | let systemInfo = uni.getSystemInfoSync();
143 | if (!instance.checkLogged() || systemInfo.uniPlatform != 'app') {
144 | return;
145 | }
146 | plus.push.getClientInfoAsync((info) => {
147 | let clientId = info['clientid'];
148 | if (clientId) {
149 | request(Api.Push.bindClientId, 'GET', {
150 | clientId: clientId
151 | }).then(() => {
152 | log(0, "注册APP用户离线通知推送标识符成功,当前获取的cid为:" + clientId);
153 | }).catch((fail) => {
154 | log(1, "注册APP用户离线通知推送标识符异常:" + fail.message);
155 | })
156 | }
157 | });
158 | }
159 |
160 |
161 | export {
162 | setPushPermissions,
163 | createNotificationChannel,
164 | bindAppUserPushCID
165 | }
166 |
--------------------------------------------------------------------------------
/src/service/uploadService.js:
--------------------------------------------------------------------------------
1 | import {
2 | instance
3 | } from '../yeim-uni-sdk';
4 |
5 | import {
6 | successHandle,
7 | errHandle
8 | } from '../func/callback';
9 |
10 | import md5 from '../utils/md5';
11 |
12 | import log from '../func/log';
13 |
14 | import CryptoJS from '../utils/CryptoJS';
15 |
16 | import {
17 | YeIMUniSDKStatusCode
18 | } from '../const/yeim-status-code';
19 |
20 | import {
21 | Api,
22 | download,
23 | request,
24 | upload as commonUpload
25 | } from '../func/request';
26 |
27 | /**
28 | * 获取媒体上传参数
29 | */
30 | async function getMediaUploadParams() {
31 |
32 | let response = await request(Api.Upload.sign, 'GET', {});
33 | if (response.code) {
34 | log(1, '媒体上传参数获取失败', true);
35 | } else {
36 | instance.mediaUploadParams = response;
37 | }
38 |
39 | }
40 |
41 | /**
42 | * 获取上传URL
43 | */
44 | function getUploadURL() {
45 | //默认本地上传URL
46 | let url = instance.defaults.baseURL;
47 | if (instance.mediaUploadParams.storage == "cos") {
48 | url = `https://${instance.mediaUploadParams.bucket}.cos.${instance.mediaUploadParams.region}.myqcloud.com`;
49 | } else if (instance.mediaUploadParams.storage == "oss") {
50 | url = `https://${instance.mediaUploadParams.bucket}.${instance.mediaUploadParams.region}.aliyuncs.com`;
51 | }
52 | return url;
53 | }
54 |
55 | /**
56 | * 获取访问URL
57 | */
58 | function getVisitURL() {
59 | return (instance.mediaUploadParams.customDomain ? instance.mediaUploadParams.customDomain : getUploadURL());
60 | }
61 |
62 | /**
63 | * 获取上传的文件名称带路径
64 | *
65 | * 拼接上传的文件保存目录,默认规则 baseDir/文件类型/日期/文件名称
66 | *
67 | * @param {String} filename 文件名称
68 | * @param {String} dir 文件类型,目前可选为image、video、audio、files
69 | */
70 | function getUploadFilePath(filename, dir = 'files') {
71 | let key = filename;
72 | //完整文件名,如果设置了baseDir,则 = baseDir/filename,否则 = filename
73 | if (!instance.mediaUploadParams.baseDir && !instance.mediaUploadParams.storage === 'local') {
74 | return key;
75 | } else {
76 | //文件保存根目录
77 | let baseDir = instance.mediaUploadParams.baseDir;
78 | //日期目录
79 | let date = new Date();
80 | //修复Android上日期显示异常问题
81 | let dateDir = date.getFullYear() + '-' + JSON.stringify(date.getMonth() + 1).padStart(2, 0) + '-' + JSON
82 | .stringify(date.getDate()).padStart(2, 0);
83 | //后半路径
84 | let suffix = dir + '/' + dateDir + '/' + filename;
85 | if (instance.mediaUploadParams.storage !== 'local') {
86 | //去除路径前的/
87 | if (baseDir.substring(0, 1) == '/') {
88 | baseDir = baseDir.substring(1);
89 | }
90 | //去除路径后的/
91 | if (baseDir.substring(baseDir.length - 1, baseDir.length) === '/') {
92 | baseDir = baseDir.substring(0, baseDir.length) + baseDir.substring(baseDir.length + 1);
93 | }
94 | //如果baseDir没了,返回不带baseDir的后半路径
95 | if (!baseDir) {
96 | return suffix;
97 | }
98 | //公有云对象存储最终保存路径
99 | key = baseDir + '/' + suffix;
100 | } else {
101 | //本地存储最终保存路径
102 | key = suffix;
103 | }
104 | }
105 | return key;
106 | }
107 |
108 | /**
109 | * 生成腾讯云COS 对象存储 请求签名 Authorization
110 | * @url https://cloud.tencent.com/document/product/436/7778
111 | *
112 | * @param {String} method @description 请求方法名称
113 | * @param {String} path @description url-param-list
114 | * @param {String} headers @description q-header-list
115 | */
116 | async function buildCosAuthorization(method, path, headers) {
117 | let time = parseInt((new Date()).getTime() / 1000) - 1;
118 | if (!instance.mediaUploadParams || time > instance.mediaUploadParams.expireTime) {
119 | //过期,重新获取
120 | await getMediaUploadParams();
121 | }
122 | let nowTime = instance.mediaUploadParams.nowTime;
123 | let expireTime = instance.mediaUploadParams.expireTime;
124 | let qSignAlgorithm = 'sha1';
125 | let qAk = instance.mediaUploadParams.secretId;
126 | let qSignTime = nowTime + ';' + expireTime;
127 | let qKeyTime = nowTime + ';' + expireTime;
128 | let signKey = instance.mediaUploadParams.signKey;
129 | let httpString = method + '\n' + path + '\n\n' + headers + '\n';
130 | let stringToSign = qSignAlgorithm + '\n' + qKeyTime + '\n' + CryptoJS.SHA1(httpString) + '\n';
131 | let signature = CryptoJS.HmacSHA1(stringToSign, signKey);
132 | let authorization =
133 | `q-sign-algorithm=${qSignAlgorithm}&q-ak=${qAk}&q-sign-time=${qSignTime}&q-key-time=${qKeyTime}&q-header-list=&q-url-param-list=&q-signature=${signature}`;
134 | return authorization;
135 | }
136 |
137 | /**
138 | * 生成阿里云OSS 对象存储 请求签名 signature
139 | * @url https://help.aliyun.com/document_detail/31988.html
140 | */
141 | async function buildOSSSignature() {
142 | let time = parseInt((new Date()).getTime() / 1000) - 1;
143 | if (!instance.mediaUploadParams || time > instance.mediaUploadParams.expireTime) {
144 | //过期,重新获取
145 | await getMediaUploadParams();
146 | }
147 | return instance.mediaUploadParams;
148 | }
149 |
150 | /**
151 | *
152 | * 通用上传接口
153 | *
154 | * @param {Object} options
155 | * @param {String} options.filename - 文件名称(需带后缀)
156 | * @param {String} options.filepath - 本地文件临时路径
157 | * @param {(result)=>{}} [options.success] - 成功回调
158 | * @param {(error)=>{}} [options.fail] - 失败回调
159 | * @param {(progress)=>{}} [options.onProgress] - 上传进度回调
160 | *
161 | */
162 | function upload(options) {
163 |
164 | if (!instance.checkLogged()) {
165 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
166 | }
167 |
168 | if (!instance.mediaUploadParams) {
169 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, '上传参数异常,暂无法使用此接口');
170 | }
171 |
172 | let mediaUploadParams = instance.mediaUploadParams;
173 | let suffix = options.filename.substring(options.filename.lastIndexOf('.'));
174 | let filename = md5((new Date()).getTime() + '_' + options.filename) + '_other' + suffix;
175 |
176 | //上传URL
177 | let uploadUrl = getUploadURL();
178 |
179 | //上传完成后的资源访问URL
180 | let resUrl = getVisitURL() + '/' + getUploadFilePath(filename);
181 |
182 | //腾讯云COS对象存储
183 | if (mediaUploadParams.storage === 'cos') {
184 | setTimeout(async () => {
185 | let authorization = await buildCosAuthorization('post', '/', '');
186 | let uploadTask = commonUpload({
187 | url: uploadUrl,
188 | name: 'file',
189 | data: {
190 | 'key': getUploadFilePath(filename),
191 | 'success_action_status': 200,
192 | 'Signature': authorization,
193 | 'Content-Type': ''
194 | },
195 | header: {
196 | Authorization: authorization,
197 | },
198 | filePath: options.filepath,
199 | ignoreResult: true,
200 | success: () => {
201 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
202 | url: resUrl
203 | })
204 | },
205 | fail: () => {
206 | errHandle(options, YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.code,
207 | YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.describe);
208 | }
209 | });
210 | //上传进度回调
211 | if (options.onProgress !== undefined && typeof options.onProgress === "function") {
212 | uploadTask.onProgressUpdate((res) => {
213 | options.onProgress(res);
214 | });
215 | }
216 | }, 0);
217 | } else if (mediaUploadParams.storage === 'oss') {
218 | //阿里云对象存储
219 | setTimeout(async () => {
220 | await buildOSSSignature();
221 | let uploadTask = commonUpload({
222 | url: uploadUrl,
223 | name: 'file',
224 | data: {
225 | 'key': getUploadFilePath(filename),
226 | 'policy': mediaUploadParams.policyBase64,
227 | 'OSSAccessKeyId': mediaUploadParams.accessKeyId,
228 | 'success_action_status': 200,
229 | 'signature': mediaUploadParams.signature,
230 | },
231 | filePath: options.filepath,
232 | ignoreResult: true,
233 | success: () => {
234 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
235 | url: resUrl
236 | })
237 | },
238 | fail: () => {
239 | errHandle(options, YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.code,
240 | YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.describe);
241 | }
242 | })
243 | //上传进度回调
244 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
245 | uploadTask.onProgressUpdate((res) => {
246 | options.onProgress(res);
247 | });
248 | }
249 | });
250 | } else if (mediaUploadParams.storage === 'local') {
251 | //本地上传
252 | let uploadTask = commonUpload({
253 | url: uploadUrl + Api.Upload.normal,
254 | name: 'file',
255 | data: {
256 | 'key': getUploadFilePath(filename)
257 | },
258 | header: {
259 | 'token': instance.token
260 | },
261 | filePath: options.filepath,
262 | ignoreResult: false,
263 | success: (result) => {
264 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
265 | url: getVisitURL() + result.data.url,
266 | })
267 | },
268 | fail: () => {
269 | errHandle(options, YeIMUniSDKStatusCode.UPLOAD_ERROR.code, YeIMUniSDKStatusCode.UPLOAD_ERROR
270 | .describe);
271 | }
272 | })
273 | //上传进度回调
274 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
275 | uploadTask.onProgressUpdate((res) => {
276 | options.onProgress(res);
277 | });
278 | }
279 | }
280 |
281 | }
282 |
283 | /**
284 | *
285 | * 上传图片
286 | * 外部暴露
287 | *
288 | * @param {Object} options
289 | * @param {String} options.filename @description 文件名称
290 | * @param {String} options.filepath @description 本地图片文件临时路径
291 | * @param {Number} options.width @description 图片宽度
292 | * @param {Number} options.height @description 图片高度
293 | * @param {(result)=>{}} [options.success] - 成功回调
294 | * @param {(error)=>{}} [options.fail] - 失败回调
295 | * @param {(progress)=>{}} options.onProgress @description 上传进度回调
296 | *
297 | */
298 | function uploadImage(options) {
299 |
300 | if (!instance.mediaUploadParams) {
301 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, '上传参数异常,暂无法使用此接口');
302 | }
303 |
304 | let mediaUploadParams = instance.mediaUploadParams;
305 | let suffix = options.filename.substring(options.filename.lastIndexOf('.'));
306 | let filename = md5((new Date()).getTime() + '_' + options.filename) + '_image' + suffix;
307 |
308 | //上传URL
309 | let uploadUrl = getUploadURL();
310 | //上传完成后的资源访问URL
311 | let resUrl = getVisitURL() + '/' + getUploadFilePath(filename, 'image');
312 |
313 | //腾讯云COS对象存储
314 | if (mediaUploadParams.storage === 'cos') {
315 |
316 | setTimeout(async () => {
317 | let authorization = await buildCosAuthorization('post', '/', '');
318 |
319 | let uploadTask = commonUpload({
320 | url: uploadUrl,
321 | name: 'file',
322 | data: {
323 | 'key': getUploadFilePath(filename, 'image'),
324 | 'success_action_status': 200,
325 | 'Signature': authorization,
326 | 'Content-Type': ''
327 | },
328 | header: {
329 | Authorization: authorization,
330 | },
331 | filePath: options.filepath,
332 | ignoreResult: true,
333 | success: () => {
334 | let thumbnailHeight = 0;
335 | let thumbnailWidth = 0;
336 |
337 | if (options.height > 198) {
338 | let d = 198 / options.height;
339 | thumbnailHeight = parseInt(options.height *
340 | d);
341 | thumbnailWidth = parseInt(options.width * d);
342 | } else if (options.width > 198) {
343 | let d = 198 / options.width;
344 | thumbnailHeight = parseInt(options.height *
345 | d);
346 | thumbnailWidth = parseInt(options.width * d);
347 | }
348 |
349 | let thumbnailUrl = resUrl + '?imageMogr2/thumbnail/' + thumbnailWidth +
350 | 'x' + thumbnailHeight;
351 |
352 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
353 | url: resUrl,
354 | thumbnailUrl: thumbnailUrl,
355 | thumbnailWidth: thumbnailWidth,
356 | thumbnailHeight: thumbnailHeight
357 | })
358 | },
359 | fail: () => {
360 | errHandle(options, YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.code,
361 | YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.describe);
362 | }
363 | });
364 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
365 | uploadTask.onProgressUpdate((res) => {
366 | options.onProgress(res);
367 | });
368 | }
369 | }, 0);
370 | } else if (mediaUploadParams.storage === 'oss') {
371 |
372 | //阿里云对象存储
373 | setTimeout(async () => {
374 | await buildOSSSignature();
375 | let uploadTask = commonUpload({
376 | url: uploadUrl,
377 | name: 'file',
378 | data: {
379 | 'key': getUploadFilePath(filename, 'image'),
380 | 'policy': mediaUploadParams.policyBase64,
381 | 'OSSAccessKeyId': mediaUploadParams.accessKeyId,
382 | 'success_action_status': 200,
383 | 'signature': mediaUploadParams.signature,
384 | },
385 | filePath: options.filepath,
386 | ignoreResult: true,
387 | success: () => {
388 | //阿里云图片缩放
389 | let thumbnailHeight = 0;
390 | let thumbnailWidth = 0;
391 |
392 | if (options.height > 198) {
393 | let d = 198 / options.height;
394 | thumbnailHeight = parseInt(options.height *
395 | d);
396 | thumbnailWidth = parseInt(options.width * d);
397 | } else if (options.width > 198) {
398 | let d = 198 / options.width;
399 | thumbnailHeight = parseInt(options.height *
400 | d);
401 | thumbnailWidth = parseInt(options.width * d);
402 | }
403 |
404 | let thumbnailUrl = resUrl + '?x-oss-process=image/resize,m_fixed,h_' +
405 | thumbnailHeight + ',w_' + thumbnailWidth;
406 |
407 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
408 | url: resUrl,
409 | thumbnailUrl: thumbnailUrl,
410 | thumbnailWidth: thumbnailWidth,
411 | thumbnailHeight: thumbnailHeight
412 | })
413 | },
414 | fail: () => {
415 | errHandle(options, YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.code,
416 | YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.describe);
417 | }
418 | });
419 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
420 | uploadTask.onProgressUpdate((res) => {
421 | options.onProgress(res);
422 | });
423 | }
424 | });
425 | } else if (mediaUploadParams.storage === 'local') {
426 | //本地上传
427 | let uploadTask = commonUpload({
428 | url: uploadUrl + Api.Upload.image,
429 | name: 'file',
430 | data: {
431 | 'key': getUploadFilePath(filename, 'image')
432 | },
433 | header: {
434 | 'token': instance.token
435 | },
436 | filePath: options.filepath,
437 | ignoreResult: false,
438 | success: (result) => {
439 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
440 | url: getVisitURL() + result.data.url,
441 | thumbnailUrl: getVisitURL() + result.data.thumbnailUrl,
442 | thumbnailWidth: result.data.thumbnailWidth,
443 | thumbnailHeight: result.data.thumbnailHeight
444 | })
445 | },
446 | fail: () => {
447 | errHandle(options, YeIMUniSDKStatusCode.UPLOAD_ERROR.code, YeIMUniSDKStatusCode.UPLOAD_ERROR
448 | .describe);
449 | }
450 | });
451 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
452 | uploadTask.onProgressUpdate((res) => {
453 | options.onProgress(res);
454 | });
455 | }
456 | }
457 | }
458 |
459 | /**
460 | * 上传音频
461 | *
462 | * @param {Object} options
463 | * @param {String} options.filename @description 文件名称
464 | * @param {String} options.filepath @description 本地文件临时路径
465 | * @param {Function} options.onProgress @description 上传进度回调
466 | */
467 | function uploadAudio(options) {
468 |
469 | if (!instance.mediaUploadParams) {
470 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, '上传参数异常,暂无法使用此接口');
471 | }
472 |
473 | let mediaUploadParams = instance.mediaUploadParams;
474 | let suffix = options.filename.substring(options.filename.lastIndexOf('.'));
475 | let filename = md5((new Date()).getTime() + '_' + options.filename) + '_audio' + suffix;
476 |
477 | //上传URL
478 | let uploadUrl = getUploadURL();
479 | //上传完成后的资源访问URL
480 | let resUrl = getVisitURL() + '/' + getUploadFilePath(filename, 'audio');
481 |
482 | //腾讯云COS对象存储
483 | if (mediaUploadParams.storage === 'cos') {
484 |
485 | setTimeout(async () => {
486 | let authorization = await buildCosAuthorization('post', '/', '');
487 | let uploadTask = commonUpload({
488 | url: uploadUrl,
489 | name: 'file',
490 | data: {
491 | 'key': getUploadFilePath(filename, 'audio'),
492 | 'success_action_status': 200,
493 | 'Signature': authorization,
494 | 'Content-Type': ''
495 | },
496 | header: {
497 | Authorization: authorization,
498 | },
499 | filePath: options.filepath,
500 | ignoreResult: true,
501 | success: () => {
502 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
503 | url: resUrl
504 | })
505 | },
506 | fail: () => {
507 | errHandle(options, YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.code,
508 | YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.describe);
509 | }
510 | });
511 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
512 | uploadTask.onProgressUpdate((res) => {
513 | options.onProgress(res);
514 | });
515 | }
516 | }, 0);
517 | } else if (mediaUploadParams.storage === 'oss') {
518 |
519 | //阿里云对象存储
520 | setTimeout(async () => {
521 | await buildOSSSignature();
522 | let uploadTask = commonUpload({
523 | url: uploadUrl,
524 | name: 'file',
525 | data: {
526 | 'key': getUploadFilePath(filename, 'audio'),
527 | 'policy': mediaUploadParams.policyBase64,
528 | 'OSSAccessKeyId': mediaUploadParams.accessKeyId,
529 | 'success_action_status': 200,
530 | 'signature': mediaUploadParams.signature,
531 | },
532 | filePath: options.filepath,
533 | ignoreResult: true,
534 | success: () => {
535 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
536 | url: resUrl
537 | })
538 | },
539 | fail: () => {
540 | errHandle(options, YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.code,
541 | YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.describe);
542 | }
543 | });
544 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
545 | uploadTask.onProgressUpdate((res) => {
546 | options.onProgress(res);
547 | });
548 | }
549 | });
550 | } else if (mediaUploadParams.storage === 'local') {
551 | //本地上传
552 | let uploadTask = commonUpload({
553 | url: uploadUrl + "/upload",
554 | name: 'file',
555 | data: {
556 | 'key': getUploadFilePath(filename, "audio")
557 | },
558 | header: {
559 | 'token': instance.token
560 | },
561 | filePath: options.filepath,
562 | ignoreResult: false,
563 | success: (result) => {
564 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
565 | url: getVisitURL() + result.data.url,
566 | })
567 | },
568 | fail: () => {
569 | errHandle(options, YeIMUniSDKStatusCode.UPLOAD_ERROR.code, YeIMUniSDKStatusCode.UPLOAD_ERROR
570 | .describe);
571 | }
572 | });
573 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
574 | uploadTask.onProgressUpdate((res) => {
575 | options.onProgress(res);
576 | });
577 | }
578 | }
579 |
580 | }
581 |
582 |
583 | /**
584 | * 上传视频
585 | *
586 | * @param {Object} options
587 | * @param {String} options.filename - 文件名称
588 | * @param {String} options.filepath - 本地文件临时路径
589 | * @param {(result)=>{}} options.onProgress - 上传进度回调
590 | */
591 | function uploadVideo(options) {
592 | if (!instance.mediaUploadParams) {
593 | return log(1, '媒体上传参数获取失败', true);
594 | }
595 | let mediaUploadParams = instance.mediaUploadParams;
596 | let suffix = options.filename.substring(options.filename.lastIndexOf('.'));
597 | let filename = md5((new Date()).getTime() + '_' + options.filename) + '_video' + suffix;
598 |
599 | //上传URL
600 | let uploadUrl = getUploadURL();
601 | //上传完成后的资源访问URL
602 | let resUrl = getVisitURL() + '/' + getUploadFilePath(filename, 'video');
603 |
604 | //腾讯云COS对象存储
605 | if (mediaUploadParams.storage == "cos") {
606 | setTimeout(async () => {
607 | let postAuthorization = await buildCosAuthorization('post', '/', '');
608 | let uploadTask = commonUpload({
609 | url: uploadUrl,
610 | name: 'file',
611 | data: {
612 | 'key': getUploadFilePath(filename, 'video'),
613 | 'success_action_status': 200,
614 | 'Signature': postAuthorization,
615 | 'Content-Type': ''
616 | },
617 | header: {
618 | Authorization: postAuthorization,
619 | },
620 | filePath: options.filepath,
621 | ignoreResult: true,
622 | success: async () => {
623 | let getAuthorization = await buildCosAuthorization('get', '/' +
624 | getUploadFilePath(filename, 'video'), '');
625 | //下载视频缩略图,腾讯云COS 媒体截图接口:https://cloud.tencent.com/document/product/436/55671
626 | download({
627 | url: uploadUrl + '/' + getUploadFilePath(filename, 'video') +
628 | '?ci-process=snapshot&time=1',
629 | header: {
630 | 'Authorization': getAuthorization
631 | },
632 | success: (result) => {
633 | uploadImage({
634 | filename: md5(filename + result.data) +
635 | '_videoThumb.jpg',
636 | filepath: result.data,
637 | success: (thumb) => {
638 | successHandle(options,
639 | YeIMUniSDKStatusCode
640 | .NORMAL_SUCCESS.describe, {
641 | videoUrl: resUrl,
642 | thumbnailUrl: thumb
643 | .data.url
644 | });
645 | },
646 | fail: (err) => {
647 | errHandle(options,
648 | YeIMUniSDKStatusCode
649 | .NORMAL_ERROR.code, err);
650 | }
651 | })
652 | },
653 | fail: () => {
654 | errHandle(options, YeIMUniSDKStatusCode
655 | .COS_DOWNLOAD_ERROR_1
656 | .code, YeIMUniSDKStatusCode.COS_DOWNLOAD_ERROR_1
657 | .describe);
658 | }
659 | });
660 | },
661 | fail: () => {
662 | errHandle(options, YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.code,
663 | YeIMUniSDKStatusCode.COS_UPLOAD_ERROR.describe);
664 | }
665 | });
666 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
667 | uploadTask.onProgressUpdate((res) => {
668 | options.onProgress(res);
669 | });
670 | }
671 | }, 0);
672 | } else if (mediaUploadParams.storage === 'oss') {
673 |
674 | //阿里云对象存储
675 | setTimeout(async () => {
676 | await buildOSSSignature();
677 | let uploadTask = commonUpload({
678 | url: uploadUrl,
679 | name: 'file',
680 | data: {
681 | 'key': getUploadFilePath(filename, 'video'),
682 | 'policy': mediaUploadParams.policyBase64,
683 | 'OSSAccessKeyId': mediaUploadParams.accessKeyId,
684 | 'success_action_status': 200,
685 | 'signature': mediaUploadParams.signature,
686 | },
687 | filePath: options.filepath,
688 | ignoreResult: true,
689 | success: () => {
690 | //阿里云视频截帧
691 | //?x-oss-process=video/snapshot,t_1000,f_jpg,m_fast
692 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
693 | videoUrl: resUrl,
694 | thumbnailUrl: resUrl +
695 | '?x-oss-process=video/snapshot,t_1000,f_jpg,m_fast'
696 | })
697 | },
698 | fail: () => {
699 | errHandle(options, YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.code,
700 | YeIMUniSDKStatusCode.OSS_UPLOAD_ERROR.describe);
701 | }
702 | });
703 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
704 | uploadTask.onProgressUpdate((res) => {
705 | options.onProgress(res);
706 | });
707 | }
708 | });
709 | } else if (mediaUploadParams.storage === 'local') {
710 | //本地上传
711 | let uploadTask = commonUpload({
712 | url: uploadUrl + Api.Upload.video,
713 | name: 'file',
714 | data: {
715 | 'key': getUploadFilePath(filename, 'video')
716 | },
717 | header: {
718 | 'token': instance.token
719 | },
720 | filePath: options.filepath,
721 | ignoreResult: false,
722 | success: (result) => {
723 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, {
724 | videoUrl: getVisitURL() + result.data.url,
725 | thumbnailUrl: getVisitURL() + result.data.thumbnailUrl
726 | })
727 | },
728 | fail: () => {
729 | errHandle(options, YeIMUniSDKStatusCode.UPLOAD_ERROR.code, YeIMUniSDKStatusCode.UPLOAD_ERROR
730 | .describe);
731 | }
732 | });
733 | if (options.onProgress !== undefined && typeof options.onProgress === 'function') {
734 | uploadTask.onProgressUpdate((res) => {
735 | options.onProgress(res);
736 | });
737 | }
738 | }
739 | }
740 |
741 | export {
742 | getMediaUploadParams,
743 | upload,
744 | uploadImage,
745 | uploadAudio,
746 | uploadVideo
747 | }
--------------------------------------------------------------------------------
/src/service/userService.js:
--------------------------------------------------------------------------------
1 | import {
2 | YeIMUniSDKDefines,
3 | instance
4 | } from '../yeim-uni-sdk';
5 | import {
6 | Api,
7 | request
8 | } from '../func/request';
9 | import {
10 | successHandle,
11 | errHandle
12 | } from '../func/callback';
13 | import {
14 | YeIMUniSDKStatusCode
15 | } from '../const/yeim-status-code';
16 | import {
17 | getCache,
18 | setCache
19 | } from '../func/storage';
20 | import md5 from '../utils/md5';
21 |
22 | /**
23 | *
24 | * 获取用户信息
25 | *
26 | * @param {Object} options - 参数对象
27 | *
28 | * @param {String} options.userId - 用户ID
29 | * @param {Boolean} options.cloud - 从云端获取
30 | * @param {(result)=>{}} [options.success] - 成功回调
31 | * @param {(error)=>{}} [options.fail] - 失败回调
32 | *
33 | */
34 | function getUserInfo(options) {
35 |
36 | if (!instance.checkLogged()) {
37 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
38 | }
39 |
40 | if (!options.userId) {
41 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'userId 不能为空');
42 | }
43 |
44 | let key = `yeim:userList:${md5(instance.userId)}`;
45 |
46 | if (options.cloud) {
47 | request(Api.User.fetchUserInfoById, 'GET', {
48 | userId: options.userId
49 | }).then((result) => {
50 | //保存到本地
51 | let list = getCache(key);
52 | list = list ? list : [];
53 | list.push(result);
54 | setCache(key, list);
55 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
56 | }).catch((fail) => {
57 | errHandle(options, fail.code, fail.message);
58 | log(1, fail);
59 | });
60 | } else {
61 | //查询本地缓存
62 | let list = getCache(key);
63 | list = list ? list : [];
64 | let index = list.findIndex(item => {
65 | return item.userId === options.userId;
66 | });
67 | if (index !== -1) {
68 | //返回本地缓存
69 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, list[index]);
70 | //从云端更新一次本地缓存
71 | request(Api.User.fetchUserInfoById, 'GET', {
72 | userId: options.userId
73 | }).then((result) => {
74 | let list = getCache(key);
75 | list = list ? list : [];
76 | list[index] = result;
77 | setCache(key, list);
78 | }).catch((fail) => {
79 | errHandle(options, fail.code, fail.message);
80 | log(1, fail);
81 | });
82 | } else {
83 | //本地没有缓存则从云端获取
84 | request(Api.User.fetchUserInfoById, 'GET', {
85 | userId: options.userId
86 | }).then((result) => {
87 | //保存到本地
88 | let list = getCache(key);
89 | list = list ? list : [];
90 | list.push(result);
91 | setCache(key, list);
92 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
93 | }).catch((fail) => {
94 | errHandle(options, fail.code, fail.message);
95 | log(1, fail);
96 | });
97 | }
98 | }
99 |
100 | }
101 |
102 | /**
103 | *
104 | * 更新我的用户资料
105 | *
106 | * @param {Object} options - 参数对象
107 | *
108 | * @param {String} options.nickname - 昵称
109 | * @param {String} options.avatarUrl - 头像地址
110 | * @param {Number} options.gender - 性别,0=未知,1=男性,2=女性
111 | * @param {Number} options.mobile - 电话
112 | * @param {String} options.email - 邮箱
113 | * @param {String} options.birthday - 生日
114 | * @param {String} options.motto - 个性签名
115 | * @param {String} options.extend - 用户自定义扩展字段
116 | * @param {Number} options.addFriendType - 好友添加我的方式
117 | * @param {(result)=>{}} [options.success] - 成功回调
118 | * @param {(error)=>{}} [options.fail] - 失败回调
119 | *
120 | */
121 | function updateUserInfo(options) {
122 |
123 | if (!instance.checkLogged()) {
124 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
125 | }
126 |
127 | if (Object.keys(options).length <= 0) {
128 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, '请至少选择一个属性进行更新');
129 | }
130 |
131 | request(Api.User.updateUserInfo, 'POST', options).then(() => {
132 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
133 | }).catch((fail) => {
134 | errHandle(options, fail.code, fail.message);
135 | log(1, fail);
136 | });
137 |
138 | }
139 |
140 | /**
141 | *
142 | * 获取黑名单列表
143 | *
144 | * @param {Object} options - 参数对象
145 | *
146 | * @param {(result)=>{}} [options.success] - 成功回调
147 | * @param {(error)=>{}} [options.fail] - 失败回调
148 | *
149 | */
150 | function getBlackUserList(options) {
151 |
152 | if (!instance.checkLogged()) {
153 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
154 | }
155 |
156 | request(Api.User.getBlackUserList, 'GET', {}).then((result) => {
157 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, result);
158 | }).catch((fail) => {
159 | errHandle(options, fail.code, fail.message);
160 | log(1, fail);
161 | });
162 |
163 | }
164 |
165 | /**
166 | *
167 | * 添加用户到黑名单
168 | *
169 | *
170 | * @param {Object} options - 参数对象
171 | *
172 | * {"members": ["user1", "user2"], success: (result) => {}, fail: (error) => {} }
173 |
174 | *
175 | * @param {Array} options.members - 用户ID列表
176 | * @param {(result)=>{}} [options.success] - 成功回调
177 | * @param {(error)=>{}} [options.fail] - 失败回调
178 | *
179 | * @example
180 | * addToBlackUserList({
181 | members: ["user1", "user2"],
182 | success: (result) => {},
183 | fail: (error) => {}
184 | });
185 | */
186 | function addToBlackUserList(options) {
187 |
188 | if (!instance.checkLogged()) {
189 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
190 | }
191 |
192 | if (!options.members || options.members.length == 0) {
193 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'members 不能为空');
194 | }
195 |
196 | request(Api.User.addToBlackUserList, 'POST', {
197 | members: options.members
198 | }).then(() => {
199 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
200 | }).catch((fail) => {
201 | errHandle(options, fail.code, fail.message);
202 | log(1, fail);
203 | });
204 |
205 | }
206 |
207 | /**
208 | *
209 | * 移除黑名单
210 | *
211 | *
212 | * @param {Object} options - 参数对象
213 | *
214 | * {"members": ["user1", "user2"], success: (result) => {}, fail: (error) => {} }
215 |
216 | *
217 | * @param {String} options.members - 用户ID列表
218 | * @param {(result)=>{}} [options.success] - 成功回调
219 | * @param {(error)=>{}} [options.fail] - 失败回调
220 | *
221 | * @example
222 | * removeFromBlacklist({
223 | members: ["user1", "user2"],
224 | success: (result) => {},
225 | fail: (error) => {}
226 | });
227 | */
228 | function removeFromBlacklist(options) {
229 |
230 | if (!instance.checkLogged()) {
231 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_EXPIRE.code, YeIMUniSDKStatusCode.LOGIN_EXPIRE.describe);
232 | }
233 |
234 | if (!options.members || options.members.length == 0) {
235 | return errHandle(options, YeIMUniSDKStatusCode.PARAMS_ERROR.code, 'members 不能为空');
236 | }
237 |
238 | request(Api.User.removeFromBlacklist, 'POST', {
239 | members: options.members
240 | }).then(() => {
241 | successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe);
242 | }).catch((fail) => {
243 | errHandle(options, fail.code, fail.message);
244 | log(1, fail);
245 | });
246 |
247 | }
248 |
249 | export {
250 | getUserInfo,
251 | updateUserInfo,
252 | getBlackUserList,
253 | addToBlackUserList,
254 | removeFromBlacklist
255 | }
--------------------------------------------------------------------------------
/src/utils/CryptoJS.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = CryptoJS || function(g, l) {
2 | var e = {},
3 | d = e.lib = {},
4 | m = function() {},
5 | k = d.Base = {
6 | extend: function(a) {
7 | m.prototype = this;
8 | var c = new m;
9 | a && c.mixIn(a);
10 | c.hasOwnProperty("init") || (c.init = function() {
11 | c.$super.init.apply(this, arguments)
12 | });
13 | c.init.prototype = c;
14 | c.$super = this;
15 | return c
16 | },
17 | create: function() {
18 | var a = this.extend();
19 | a.init.apply(a, arguments);
20 | return a
21 | },
22 | init: function() {},
23 | mixIn: function(a) {
24 | for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]);
25 | a.hasOwnProperty("toString") && (this.toString = a.toString)
26 | },
27 | clone: function() {
28 | return this.init.prototype.extend(this)
29 | }
30 | },
31 | p = d.WordArray = k.extend({
32 | init: function(a, c) {
33 | a = this.words = a || [];
34 | this.sigBytes = c != l ? c : 4 * a.length
35 | },
36 | toString: function(a) {
37 | return (a || n).stringify(this)
38 | },
39 | concat: function(a) {
40 | var c = this.words,
41 | q = a.words,
42 | f = this.sigBytes;
43 | a = a.sigBytes;
44 | this.clamp();
45 | if (f % 4)
46 | for (var b = 0; b < a; b++) c[f + b >>> 2] |= (q[b >>> 2] >>> 24 - 8 * (b % 4) & 255) <<
47 | 24 - 8 * ((f + b) % 4);
48 | else if (65535 < q.length)
49 | for (b = 0; b < a; b += 4) c[f + b >>> 2] = q[b >>> 2];
50 | else c.push.apply(c, q);
51 | this.sigBytes += a;
52 | return this
53 | },
54 | clamp: function() {
55 | var a = this.words,
56 | c = this.sigBytes;
57 | a[c >>> 2] &= 4294967295 <<
58 | 32 - 8 * (c % 4);
59 | a.length = g.ceil(c / 4)
60 | },
61 | clone: function() {
62 | var a = k.clone.call(this);
63 | a.words = this.words.slice(0);
64 | return a
65 | },
66 | random: function(a) {
67 | for (var c = [], b = 0; b < a; b += 4) c.push(4294967296 * g.random() | 0);
68 | return new p.init(c, a)
69 | }
70 | }),
71 | b = e.enc = {},
72 | n = b.Hex = {
73 | stringify: function(a) {
74 | var c = a.words;
75 | a = a.sigBytes;
76 | for (var b = [], f = 0; f < a; f++) {
77 | var d = c[f >>> 2] >>> 24 - 8 * (f % 4) & 255;
78 | b.push((d >>> 4).toString(16));
79 | b.push((d & 15).toString(16))
80 | }
81 | return b.join("")
82 | },
83 | parse: function(a) {
84 | for (var c = a.length, b = [], f = 0; f < c; f += 2) b[f >>> 3] |= parseInt(a.substr(f,
85 | 2), 16) << 24 - 4 * (f % 8);
86 | return new p.init(b, c / 2)
87 | }
88 | },
89 | j = b.Latin1 = {
90 | stringify: function(a) {
91 | var c = a.words;
92 | a = a.sigBytes;
93 | for (var b = [], f = 0; f < a; f++) b.push(String.fromCharCode(c[f >>> 2] >>> 24 - 8 * (f % 4) &
94 | 255));
95 | return b.join("")
96 | },
97 | parse: function(a) {
98 | for (var c = a.length, b = [], f = 0; f < c; f++) b[f >>> 2] |= (a.charCodeAt(f) & 255) << 24 -
99 | 8 * (f % 4);
100 | return new p.init(b, c)
101 | }
102 | },
103 | h = b.Utf8 = {
104 | stringify: function(a) {
105 | try {
106 | return decodeURIComponent(escape(j.stringify(a)))
107 | } catch (c) {
108 | throw Error("Malformed UTF-8 data");
109 | }
110 | },
111 | parse: function(a) {
112 | return j.parse(unescape(encodeURIComponent(a)))
113 | }
114 | },
115 | r = d.BufferedBlockAlgorithm = k.extend({
116 | reset: function() {
117 | this._data = new p.init;
118 | this._nDataBytes = 0
119 | },
120 | _append: function(a) {
121 | "string" == typeof a && (a = h.parse(a));
122 | this._data.concat(a);
123 | this._nDataBytes += a.sigBytes
124 | },
125 | _process: function(a) {
126 | var c = this._data,
127 | b = c.words,
128 | f = c.sigBytes,
129 | d = this.blockSize,
130 | e = f / (4 * d),
131 | e = a ? g.ceil(e) : g.max((e | 0) - this._minBufferSize, 0);
132 | a = e * d;
133 | f = g.min(4 * a, f);
134 | if (a) {
135 | for (var k = 0; k < a; k += d) this._doProcessBlock(b, k);
136 | k = b.splice(0, a);
137 | c.sigBytes -= f
138 | }
139 | return new p.init(k, f)
140 | },
141 | clone: function() {
142 | var a = k.clone.call(this);
143 | a._data = this._data.clone();
144 | return a
145 | },
146 | _minBufferSize: 0
147 | });
148 | d.Hasher = r.extend({
149 | cfg: k.extend(),
150 | init: function(a) {
151 | this.cfg = this.cfg.extend(a);
152 | this.reset()
153 | },
154 | reset: function() {
155 | r.reset.call(this);
156 | this._doReset()
157 | },
158 | update: function(a) {
159 | this._append(a);
160 | this._process();
161 | return this
162 | },
163 | finalize: function(a) {
164 | a && this._append(a);
165 | return this._doFinalize()
166 | },
167 | blockSize: 16,
168 | _createHelper: function(a) {
169 | return function(b, d) {
170 | return (new a.init(d)).finalize(b)
171 | }
172 | },
173 | _createHmacHelper: function(a) {
174 | return function(b, d) {
175 | return (new s.HMAC.init(a,
176 | d)).finalize(b)
177 | }
178 | }
179 | });
180 | var s = e.algo = {};
181 | return e
182 | }(Math);
183 | (function() {
184 | var g = CryptoJS,
185 | l = g.lib,
186 | e = l.WordArray,
187 | d = l.Hasher,
188 | m = [],
189 | l = g.algo.SHA1 = d.extend({
190 | _doReset: function() {
191 | this._hash = new e.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520])
192 | },
193 | _doProcessBlock: function(d, e) {
194 | for (var b = this._hash.words, n = b[0], j = b[1], h = b[2], g = b[3], l = b[4], a = 0; 80 >
195 | a; a++) {
196 | if (16 > a) m[a] = d[e + a] | 0;
197 | else {
198 | var c = m[a - 3] ^ m[a - 8] ^ m[a - 14] ^ m[a - 16];
199 | m[a] = c << 1 | c >>> 31
200 | }
201 | c = (n << 5 | n >>> 27) + l + m[a];
202 | c = 20 > a ? c + ((j & h | ~j & g) + 1518500249) : 40 > a ? c + ((j ^ h ^ g) +
203 | 1859775393) : 60 > a ? c + ((j & h | j & g | h & g) - 1894007588) : c + ((j ^
204 | h ^
205 | g) - 899497514);
206 | l = g;
207 | g = h;
208 | h = j << 30 | j >>> 2;
209 | j = n;
210 | n = c
211 | }
212 | b[0] = b[0] + n | 0;
213 | b[1] = b[1] + j | 0;
214 | b[2] = b[2] + h | 0;
215 | b[3] = b[3] + g | 0;
216 | b[4] = b[4] + l | 0
217 | },
218 | _doFinalize: function() {
219 | var d = this._data,
220 | e = d.words,
221 | b = 8 * this._nDataBytes,
222 | g = 8 * d.sigBytes;
223 | e[g >>> 5] |= 128 << 24 - g % 32;
224 | e[(g + 64 >>> 9 << 4) + 14] = Math.floor(b / 4294967296);
225 | e[(g + 64 >>> 9 << 4) + 15] = b;
226 | d.sigBytes = 4 * e.length;
227 | this._process();
228 | return this._hash
229 | },
230 | clone: function() {
231 | var e = d.clone.call(this);
232 | e._hash = this._hash.clone();
233 | return e
234 | }
235 | });
236 | g.SHA1 = d._createHelper(l);
237 | g.HmacSHA1 = d._createHmacHelper(l)
238 | })();
239 | (function() {
240 | var g = CryptoJS,
241 | l = g.enc.Utf8;
242 | g.algo.HMAC = g.lib.Base.extend({
243 | init: function(e, d) {
244 | e = this._hasher = new e.init;
245 | "string" == typeof d && (d = l.parse(d));
246 | var g = e.blockSize,
247 | k = 4 * g;
248 | d.sigBytes > k && (d = e.finalize(d));
249 | d.clamp();
250 | for (var p = this._oKey = d.clone(), b = this._iKey = d.clone(), n = p.words, j = b.words,
251 | h = 0; h < g; h++) n[h] ^= 1549556828, j[h] ^= 909522486;
252 | p.sigBytes = b.sigBytes = k;
253 | this.reset()
254 | },
255 | reset: function() {
256 | var e = this._hasher;
257 | e.reset();
258 | e.update(this._iKey)
259 | },
260 | update: function(e) {
261 | this._hasher.update(e);
262 | return this
263 | },
264 | finalize: function(e) {
265 | var d =
266 | this._hasher;
267 | e = d.finalize(e);
268 | d.reset();
269 | return d.finalize(this._oKey.clone().concat(e))
270 | }
271 | })
272 | })();
273 | export default CryptoJS;
274 |
--------------------------------------------------------------------------------
/src/utils/fetch.js:
--------------------------------------------------------------------------------
1 | var global =
2 | (typeof globalThis !== 'undefined' && globalThis) ||
3 | (typeof self !== 'undefined' && self) ||
4 | (typeof global !== 'undefined' && global) ||
5 | {}
6 |
7 | var support = {
8 | searchParams: 'URLSearchParams' in global,
9 | iterable: 'Symbol' in global && 'iterator' in Symbol,
10 | blob:
11 | 'FileReader' in global &&
12 | 'Blob' in global &&
13 | (function () {
14 | try {
15 | new Blob()
16 | return true
17 | } catch (e) {
18 | return false
19 | }
20 | })(),
21 | formData: 'FormData' in global,
22 | arrayBuffer: 'ArrayBuffer' in global
23 | }
24 |
25 | function isDataView(obj) {
26 | return obj && DataView.prototype.isPrototypeOf(obj)
27 | }
28 |
29 | if (support.arrayBuffer) {
30 | var viewClasses = [
31 | '[object Int8Array]',
32 | '[object Uint8Array]',
33 | '[object Uint8ClampedArray]',
34 | '[object Int16Array]',
35 | '[object Uint16Array]',
36 | '[object Int32Array]',
37 | '[object Uint32Array]',
38 | '[object Float32Array]',
39 | '[object Float64Array]'
40 | ]
41 |
42 | var isArrayBufferView =
43 | ArrayBuffer.isView ||
44 | function (obj) {
45 | return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
46 | }
47 | }
48 |
49 | function normalizeName(name) {
50 | if (typeof name !== 'string') {
51 | name = String(name)
52 | }
53 | if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
54 | throw new TypeError('Invalid character in header field name: "' + name + '"')
55 | }
56 | return name.toLowerCase()
57 | }
58 |
59 | function normalizeValue(value) {
60 | if (typeof value !== 'string') {
61 | value = String(value)
62 | }
63 | return value
64 | }
65 |
66 | // Build a destructive iterator for the value list
67 | function iteratorFor(items) {
68 | var iterator = {
69 | next: function () {
70 | var value = items.shift()
71 | return { done: value === undefined, value: value }
72 | }
73 | }
74 |
75 | if (support.iterable) {
76 | iterator[Symbol.iterator] = function () {
77 | return iterator
78 | }
79 | }
80 |
81 | return iterator
82 | }
83 |
84 | export function Headers(headers) {
85 | this.map = {}
86 |
87 | if (headers instanceof Headers) {
88 | headers.forEach(function (value, name) {
89 | this.append(name, value)
90 | }, this)
91 | } else if (Array.isArray(headers)) {
92 | headers.forEach(function (header) {
93 | this.append(header[0], header[1])
94 | }, this)
95 | } else if (headers) {
96 | Object.getOwnPropertyNames(headers).forEach(function (name) {
97 | this.append(name, headers[name])
98 | }, this)
99 | }
100 | }
101 |
102 | Headers.prototype.append = function (name, value) {
103 | name = normalizeName(name)
104 | value = normalizeValue(value)
105 | var oldValue = this.map[name]
106 | this.map[name] = oldValue ? oldValue + ', ' + value : value
107 | }
108 |
109 | Headers.prototype['delete'] = function (name) {
110 | delete this.map[normalizeName(name)]
111 | }
112 |
113 | Headers.prototype.get = function (name) {
114 | name = normalizeName(name)
115 | return this.has(name) ? this.map[name] : null
116 | }
117 |
118 | Headers.prototype.has = function (name) {
119 | return this.map.hasOwnProperty(normalizeName(name))
120 | }
121 |
122 | Headers.prototype.set = function (name, value) {
123 | this.map[normalizeName(name)] = normalizeValue(value)
124 | }
125 |
126 | Headers.prototype.forEach = function (callback, thisArg) {
127 | for (var name in this.map) {
128 | if (this.map.hasOwnProperty(name)) {
129 | callback.call(thisArg, this.map[name], name, this)
130 | }
131 | }
132 | }
133 |
134 | Headers.prototype.keys = function () {
135 | var items = []
136 | this.forEach(function (value, name) {
137 | items.push(name)
138 | })
139 | return iteratorFor(items)
140 | }
141 |
142 | Headers.prototype.values = function () {
143 | var items = []
144 | this.forEach(function (value) {
145 | items.push(value)
146 | })
147 | return iteratorFor(items)
148 | }
149 |
150 | Headers.prototype.entries = function () {
151 | var items = []
152 | this.forEach(function (value, name) {
153 | items.push([name, value])
154 | })
155 | return iteratorFor(items)
156 | }
157 |
158 | if (support.iterable) {
159 | Headers.prototype[Symbol.iterator] = Headers.prototype.entries
160 | }
161 |
162 | function consumed(body) {
163 | if (body.bodyUsed) {
164 | return Promise.reject(new TypeError('Already read'))
165 | }
166 | body.bodyUsed = true
167 | }
168 |
169 | function fileReaderReady(reader) {
170 | return new Promise(function (resolve, reject) {
171 | reader.onload = function () {
172 | resolve(reader.result)
173 | }
174 | reader.onerror = function () {
175 | reject(reader.error)
176 | }
177 | })
178 | }
179 |
180 | function readBlobAsArrayBuffer(blob) {
181 | var reader = new FileReader()
182 | var promise = fileReaderReady(reader)
183 | reader.readAsArrayBuffer(blob)
184 | return promise
185 | }
186 |
187 | function readBlobAsText(blob) {
188 | var reader = new FileReader()
189 | var promise = fileReaderReady(reader)
190 | reader.readAsText(blob)
191 | return promise
192 | }
193 |
194 | function readArrayBufferAsText(buf) {
195 | var view = new Uint8Array(buf)
196 | var chars = new Array(view.length)
197 |
198 | for (var i = 0; i < view.length; i++) {
199 | chars[i] = String.fromCharCode(view[i])
200 | }
201 | return chars.join('')
202 | }
203 |
204 | function bufferClone(buf) {
205 | if (buf.slice) {
206 | return buf.slice(0)
207 | } else {
208 | var view = new Uint8Array(buf.byteLength)
209 | view.set(new Uint8Array(buf))
210 | return view.buffer
211 | }
212 | }
213 |
214 | function Body() {
215 | this.bodyUsed = false
216 |
217 | this._initBody = function (body) {
218 | /*
219 | fetch-mock wraps the Response object in an ES6 Proxy to
220 | provide useful test harness features such as flush. However, on
221 | ES5 browsers without fetch or Proxy support pollyfills must be used;
222 | the proxy-pollyfill is unable to proxy an attribute unless it exists
223 | on the object before the Proxy is created. This change ensures
224 | Response.bodyUsed exists on the instance, while maintaining the
225 | semantic of setting Request.bodyUsed in the constructor before
226 | _initBody is called.
227 | */
228 | this.bodyUsed = this.bodyUsed
229 | this._bodyInit = body
230 | if (!body) {
231 | this._bodyText = ''
232 | } else if (typeof body === 'string') {
233 | this._bodyText = body
234 | } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
235 | this._bodyBlob = body
236 | } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
237 | this._bodyFormData = body
238 | } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
239 | this._bodyText = body.toString()
240 | } else if (support.arrayBuffer && support.blob && isDataView(body)) {
241 | this._bodyArrayBuffer = bufferClone(body.buffer)
242 | // IE 10-11 can't handle a DataView body.
243 | this._bodyInit = new Blob([this._bodyArrayBuffer])
244 | } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
245 | this._bodyArrayBuffer = bufferClone(body)
246 | } else {
247 | this._bodyText = body = Object.prototype.toString.call(body)
248 | }
249 |
250 | if (!this.headers.get('content-type')) {
251 | if (typeof body === 'string') {
252 | this.headers.set('content-type', 'text/plain;charset=UTF-8')
253 | } else if (this._bodyBlob && this._bodyBlob.type) {
254 | this.headers.set('content-type', this._bodyBlob.type)
255 | } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
256 | this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
257 | }
258 | }
259 | }
260 |
261 | if (support.blob) {
262 | this.blob = function () {
263 | var rejected = consumed(this)
264 | if (rejected) {
265 | return rejected
266 | }
267 |
268 | if (this._bodyBlob) {
269 | return Promise.resolve(this._bodyBlob)
270 | } else if (this._bodyArrayBuffer) {
271 | return Promise.resolve(new Blob([this._bodyArrayBuffer]))
272 | } else if (this._bodyFormData) {
273 | throw new Error('could not read FormData body as blob')
274 | } else {
275 | return Promise.resolve(new Blob([this._bodyText]))
276 | }
277 | }
278 |
279 | this.arrayBuffer = function () {
280 | if (this._bodyArrayBuffer) {
281 | var isConsumed = consumed(this)
282 | if (isConsumed) {
283 | return isConsumed
284 | }
285 | if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
286 | return Promise.resolve(
287 | this._bodyArrayBuffer.buffer.slice(
288 | this._bodyArrayBuffer.byteOffset,
289 | this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
290 | )
291 | )
292 | } else {
293 | return Promise.resolve(this._bodyArrayBuffer)
294 | }
295 | } else {
296 | return this.blob().then(readBlobAsArrayBuffer)
297 | }
298 | }
299 | }
300 |
301 | this.text = function () {
302 | var rejected = consumed(this)
303 | if (rejected) {
304 | return rejected
305 | }
306 |
307 | if (this._bodyBlob) {
308 | return readBlobAsText(this._bodyBlob)
309 | } else if (this._bodyArrayBuffer) {
310 | return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
311 | } else if (this._bodyFormData) {
312 | throw new Error('could not read FormData body as text')
313 | } else {
314 | return Promise.resolve(this._bodyText)
315 | }
316 | }
317 |
318 | if (support.formData) {
319 | this.formData = function () {
320 | return this.text().then(decode)
321 | }
322 | }
323 |
324 | this.json = function () {
325 | return this.text().then(JSON.parse)
326 | }
327 |
328 | return this
329 | }
330 |
331 | // HTTP methods whose capitalization should be normalized
332 | var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
333 |
334 | function normalizeMethod(method) {
335 | var upcased = method.toUpperCase()
336 | return methods.indexOf(upcased) > -1 ? upcased : method
337 | }
338 |
339 | export function Request(input, options) {
340 | if (!(this instanceof Request)) {
341 | throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
342 | }
343 |
344 | options = options || {}
345 | var body = options.body
346 |
347 | if (input instanceof Request) {
348 | if (input.bodyUsed) {
349 | throw new TypeError('Already read')
350 | }
351 | this.url = input.url
352 | this.credentials = input.credentials
353 | if (!options.headers) {
354 | this.headers = new Headers(input.headers)
355 | }
356 | this.method = input.method
357 | this.mode = input.mode
358 | this.signal = input.signal
359 | if (!body && input._bodyInit != null) {
360 | body = input._bodyInit
361 | input.bodyUsed = true
362 | }
363 | } else {
364 | this.url = String(input)
365 | }
366 |
367 | this.credentials = options.credentials || this.credentials || 'same-origin'
368 | if (options.headers || !this.headers) {
369 | this.headers = new Headers(options.headers)
370 | }
371 | this.method = normalizeMethod(options.method || this.method || 'GET')
372 | this.mode = options.mode || this.mode || null
373 | this.signal = options.signal || this.signal || (function () {
374 | if ('AbortController' in global) {
375 | var ctrl = new AbortController();
376 | return ctrl.signal;
377 | }
378 | }());
379 | this.referrer = null
380 |
381 | if ((this.method === 'GET' || this.method === 'HEAD') && body) {
382 | throw new TypeError('Body not allowed for GET or HEAD requests')
383 | }
384 | this._initBody(body)
385 |
386 | if (this.method === 'GET' || this.method === 'HEAD') {
387 | if (options.cache === 'no-store' || options.cache === 'no-cache') {
388 | // Search for a '_' parameter in the query string
389 | var reParamSearch = /([?&])_=[^&]*/
390 | if (reParamSearch.test(this.url)) {
391 | // If it already exists then set the value with the current time
392 | this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime())
393 | } else {
394 | // Otherwise add a new '_' parameter to the end with the current time
395 | var reQueryString = /\?/
396 | this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime()
397 | }
398 | }
399 | }
400 | }
401 |
402 | Request.prototype.clone = function () {
403 | return new Request(this, { body: this._bodyInit })
404 | }
405 |
406 | function decode(body) {
407 | var form = new FormData()
408 | body
409 | .trim()
410 | .split('&')
411 | .forEach(function (bytes) {
412 | if (bytes) {
413 | var split = bytes.split('=')
414 | var name = split.shift().replace(/\+/g, ' ')
415 | var value = split.join('=').replace(/\+/g, ' ')
416 | form.append(decodeURIComponent(name), decodeURIComponent(value))
417 | }
418 | })
419 | return form
420 | }
421 |
422 | function parseHeaders(rawHeaders) {
423 | var headers = new Headers()
424 | // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
425 | // https://tools.ietf.org/html/rfc7230#section-3.2
426 | var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
427 | // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill
428 | // https://github.com/github/fetch/issues/748
429 | // https://github.com/zloirock/core-js/issues/751
430 | preProcessedHeaders
431 | .split('\r')
432 | .map(function (header) {
433 | return header.indexOf('\n') === 0 ? header.substr(1, header.length) : header
434 | })
435 | .forEach(function (line) {
436 | var parts = line.split(':')
437 | var key = parts.shift().trim()
438 | if (key) {
439 | var value = parts.join(':').trim()
440 | headers.append(key, value)
441 | }
442 | })
443 | return headers
444 | }
445 |
446 | Body.call(Request.prototype)
447 |
448 | export function Response(bodyInit, options) {
449 | if (!(this instanceof Response)) {
450 | throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
451 | }
452 | if (!options) {
453 | options = {}
454 | }
455 |
456 | this.type = 'default'
457 | this.status = options.status === undefined ? 200 : options.status
458 | this.ok = this.status >= 200 && this.status < 300
459 | this.statusText = options.statusText === undefined ? '' : '' + options.statusText
460 | this.headers = new Headers(options.headers)
461 | this.url = options.url || ''
462 | this._initBody(bodyInit)
463 | }
464 |
465 | Body.call(Response.prototype)
466 |
467 | Response.prototype.clone = function () {
468 | return new Response(this._bodyInit, {
469 | status: this.status,
470 | statusText: this.statusText,
471 | headers: new Headers(this.headers),
472 | url: this.url
473 | })
474 | }
475 |
476 | Response.error = function () {
477 | var response = new Response(null, { status: 0, statusText: '' })
478 | response.type = 'error'
479 | return response
480 | }
481 |
482 | var redirectStatuses = [301, 302, 303, 307, 308]
483 |
484 | Response.redirect = function (url, status) {
485 | if (redirectStatuses.indexOf(status) === -1) {
486 | throw new RangeError('Invalid status code')
487 | }
488 |
489 | return new Response(null, { status: status, headers: { location: url } })
490 | }
491 |
492 | export var DOMException = global.DOMException
493 | try {
494 | new DOMException()
495 | } catch (err) {
496 | DOMException = function (message, name) {
497 | this.message = message
498 | this.name = name
499 | var error = Error(message)
500 | this.stack = error.stack
501 | }
502 | DOMException.prototype = Object.create(Error.prototype)
503 | DOMException.prototype.constructor = DOMException
504 | }
505 |
506 | export function fetch(input, init) {
507 | return new Promise(function (resolve, reject) {
508 | var request = new Request(input, init)
509 |
510 | if (request.signal && request.signal.aborted) {
511 | return reject(new DOMException('Aborted', 'AbortError'))
512 | }
513 |
514 | var xhr = new XMLHttpRequest()
515 |
516 | function abortXhr() {
517 | xhr.abort()
518 | }
519 |
520 | xhr.onload = function () {
521 | var options = {
522 | status: xhr.status,
523 | statusText: xhr.statusText,
524 | headers: parseHeaders(xhr.getAllResponseHeaders() || '')
525 | }
526 | options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
527 | var body = 'response' in xhr ? xhr.response : xhr.responseText
528 | setTimeout(function () {
529 | resolve(new Response(body, options))
530 | }, 0)
531 | }
532 |
533 | xhr.onerror = function () {
534 | setTimeout(function () {
535 | reject(new TypeError('Network request failed'))
536 | }, 0)
537 | }
538 |
539 | xhr.ontimeout = function () {
540 | setTimeout(function () {
541 | reject(new TypeError('Network request failed'))
542 | }, 0)
543 | }
544 |
545 | xhr.onabort = function () {
546 | setTimeout(function () {
547 | reject(new DOMException('Aborted', 'AbortError'))
548 | }, 0)
549 | }
550 |
551 | function fixUrl(url) {
552 | try {
553 | return url === '' && global.location.href ? global.location.href : url
554 | } catch (e) {
555 | return url
556 | }
557 | }
558 |
559 | xhr.open(request.method, fixUrl(request.url), true)
560 |
561 | if (request.credentials === 'include') {
562 | xhr.withCredentials = true
563 | } else if (request.credentials === 'omit') {
564 | xhr.withCredentials = false
565 | }
566 |
567 | if ('responseType' in xhr) {
568 | if (support.blob) {
569 | xhr.responseType = 'blob'
570 | } else if (
571 | support.arrayBuffer &&
572 | request.headers.get('Content-Type') &&
573 | request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1
574 | ) {
575 | xhr.responseType = 'arraybuffer'
576 | }
577 | }
578 |
579 | if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers)) {
580 | Object.getOwnPropertyNames(init.headers).forEach(function (name) {
581 | xhr.setRequestHeader(name, normalizeValue(init.headers[name]))
582 | })
583 | } else {
584 | request.headers.forEach(function (value, name) {
585 | xhr.setRequestHeader(name, value)
586 | })
587 | }
588 |
589 | if (request.signal) {
590 | request.signal.addEventListener('abort', abortXhr)
591 |
592 | xhr.onreadystatechange = function () {
593 | // DONE (success or failure)
594 | if (xhr.readyState === 4) {
595 | request.signal.removeEventListener('abort', abortXhr)
596 | }
597 | }
598 | }
599 |
600 | xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
601 | })
602 | }
603 |
604 | fetch.polyfill = true
605 |
606 | if (!global.fetch) {
607 | global.fetch = fetch
608 | global.Headers = Headers
609 | global.Request = Request
610 | global.Response = Response
611 | }
--------------------------------------------------------------------------------
/src/utils/md5.js:
--------------------------------------------------------------------------------
1 | var rotateLeft = function(lValue, iShiftBits) {
2 | return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
3 | }
4 |
5 | var addUnsigned = function(lX, lY) {
6 | var lX4, lY4, lX8, lY8, lResult;
7 | lX8 = (lX & 0x80000000);
8 | lY8 = (lY & 0x80000000);
9 | lX4 = (lX & 0x40000000);
10 | lY4 = (lY & 0x40000000);
11 | lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
12 | if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
13 | if (lX4 | lY4) {
14 | if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
15 | else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
16 | } else {
17 | return (lResult ^ lX8 ^ lY8);
18 | }
19 | }
20 |
21 | var F = function(x, y, z) {
22 | return (x & y) | ((~x) & z);
23 | }
24 |
25 | var G = function(x, y, z) {
26 | return (x & z) | (y & (~z));
27 | }
28 |
29 | var H = function(x, y, z) {
30 | return (x ^ y ^ z);
31 | }
32 |
33 | var I = function(x, y, z) {
34 | return (y ^ (x | (~z)));
35 | }
36 |
37 | var FF = function(a, b, c, d, x, s, ac) {
38 | a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
39 | return addUnsigned(rotateLeft(a, s), b);
40 | };
41 |
42 | var GG = function(a, b, c, d, x, s, ac) {
43 | a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
44 | return addUnsigned(rotateLeft(a, s), b);
45 | };
46 |
47 | var HH = function(a, b, c, d, x, s, ac) {
48 | a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
49 | return addUnsigned(rotateLeft(a, s), b);
50 | };
51 |
52 | var II = function(a, b, c, d, x, s, ac) {
53 | a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
54 | return addUnsigned(rotateLeft(a, s), b);
55 | };
56 |
57 | var convertToWordArray = function(string) {
58 | var lWordCount;
59 | var lMessageLength = string.length;
60 | var lNumberOfWordsTempOne = lMessageLength + 8;
61 | var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
62 | var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
63 | var lWordArray = Array(lNumberOfWords - 1);
64 | var lBytePosition = 0;
65 | var lByteCount = 0;
66 | while (lByteCount < lMessageLength) {
67 | lWordCount = (lByteCount - (lByteCount % 4)) / 4;
68 | lBytePosition = (lByteCount % 4) * 8;
69 | lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
70 | lByteCount++;
71 | }
72 | lWordCount = (lByteCount - (lByteCount % 4)) / 4;
73 | lBytePosition = (lByteCount % 4) * 8;
74 | lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
75 | lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
76 | lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
77 | return lWordArray;
78 | };
79 |
80 | var wordToHex = function(lValue) {
81 | var WordToHexValue = "",
82 | WordToHexValueTemp = "",
83 | lByte, lCount;
84 | for (lCount = 0; lCount <= 3; lCount++) {
85 | lByte = (lValue >>> (lCount * 8)) & 255;
86 | WordToHexValueTemp = "0" + lByte.toString(16);
87 | WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
88 | }
89 | return WordToHexValue;
90 | };
91 |
92 | var uTF8Encode = function(string) {
93 | string = string.replace(/\x0d\x0a/g, "\x0a");
94 | var output = "";
95 | for (var n = 0; n < string.length; n++) {
96 | var c = string.charCodeAt(n);
97 | if (c < 128) {
98 | output += String.fromCharCode(c);
99 | } else if ((c > 127) && (c < 2048)) {
100 | output += String.fromCharCode((c >> 6) | 192);
101 | output += String.fromCharCode((c & 63) | 128);
102 | } else {
103 | output += String.fromCharCode((c >> 12) | 224);
104 | output += String.fromCharCode(((c >> 6) & 63) | 128);
105 | output += String.fromCharCode((c & 63) | 128);
106 | }
107 | }
108 | return output;
109 | };
110 |
111 | function md5(string) {
112 | string = string + "";
113 | var x = Array();
114 | var k, AA, BB, CC, DD, a, b, c, d;
115 | var S11 = 7,
116 | S12 = 12,
117 | S13 = 17,
118 | S14 = 22;
119 | var S21 = 5,
120 | S22 = 9,
121 | S23 = 14,
122 | S24 = 20;
123 | var S31 = 4,
124 | S32 = 11,
125 | S33 = 16,
126 | S34 = 23;
127 | var S41 = 6,
128 | S42 = 10,
129 | S43 = 15,
130 | S44 = 21;
131 | string = uTF8Encode(string);
132 | x = convertToWordArray(string);
133 | a = 0x67452301;
134 | b = 0xEFCDAB89;
135 | c = 0x98BADCFE;
136 | d = 0x10325476;
137 | for (k = 0; k < x.length; k += 16) {
138 | AA = a;
139 | BB = b;
140 | CC = c;
141 | DD = d;
142 | a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
143 | d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
144 | c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
145 | b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
146 | a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
147 | d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
148 | c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
149 | b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
150 | a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
151 | d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
152 | c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
153 | b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
154 | a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
155 | d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
156 | c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
157 | b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
158 | a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
159 | d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
160 | c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
161 | b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
162 | a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
163 | d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
164 | c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
165 | b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
166 | a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
167 | d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
168 | c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
169 | b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
170 | a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
171 | d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
172 | c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
173 | b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
174 | a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
175 | d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
176 | c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
177 | b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
178 | a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
179 | d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
180 | c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
181 | b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
182 | a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
183 | d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
184 | c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
185 | b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
186 | a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
187 | d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
188 | c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
189 | b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
190 | a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
191 | d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
192 | c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
193 | b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
194 | a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
195 | d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
196 | c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
197 | b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
198 | a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
199 | d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
200 | c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
201 | b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
202 | a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
203 | d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
204 | c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
205 | b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
206 | a = addUnsigned(a, AA);
207 | b = addUnsigned(b, BB);
208 | c = addUnsigned(c, CC);
209 | d = addUnsigned(d, DD);
210 | }
211 | var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
212 | return tempValue.toLowerCase();
213 | }
214 |
215 | export default md5
216 |
--------------------------------------------------------------------------------
/src/utils/mitt.umd.js:
--------------------------------------------------------------------------------
1 | !function (e, n) { "object" == typeof exports && "undefined" != typeof module ? module.exports = n() : "function" == typeof define && define.amd ? define(n) : (e = e || self).mitt = n() }(this, function () { return function (e) { return { all: e = e || new Map, on: function (n, t) { var f = e.get(n); f ? f.push(t) : e.set(n, [t]) }, off: function (n, t) { var f = e.get(n); f && (t ? f.splice(f.indexOf(t) >>> 0, 1) : e.set(n, [])) }, emit: function (n, t) { var f = e.get(n); f && f.slice().map(function (e) { e(t) }), (f = e.get("*")) && f.slice().map(function (e) { e(n, t) }) } } } });
--------------------------------------------------------------------------------
/src/utils/queryParams.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 对象转url参数
3 | * @param {*} data,对象
4 | * @param {*} isPrefix,是否自动加上"?"
5 | */
6 | function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
7 | let prefix = isPrefix ? '?' : ''
8 | let _result = []
9 | if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
10 | for (let key in data) {
11 | let value = data[key]
12 | // 去掉为空的参数
13 | if (['', undefined, null].indexOf(value) >= 0) {
14 | continue;
15 | }
16 | // 如果值为数组,另行处理
17 | if (value.constructor === Array) {
18 | // e.g. {ids: [1, 2, 3]}
19 | switch (arrayFormat) {
20 | case 'indices':
21 | // 结果: ids[0]=1&ids[1]=2&ids[2]=3
22 | for (let i = 0; i < value.length; i++) {
23 | _result.push(key + '[' + i + ']=' + value[i])
24 | }
25 | break;
26 | case 'brackets':
27 | // 结果: ids[]=1&ids[]=2&ids[]=3
28 | value.forEach(_value => {
29 | _result.push(key + '[]=' + _value)
30 | })
31 | break;
32 | case 'repeat':
33 | // 结果: ids=1&ids=2&ids=3
34 | value.forEach(_value => {
35 | _result.push(key + '=' + _value)
36 | })
37 | break;
38 | case 'comma':
39 | // 结果: ids=1,2,3
40 | let commaStr = "";
41 | value.forEach(_value => {
42 | commaStr += (commaStr ? "," : "") + _value;
43 | })
44 | _result.push(key + '=' + commaStr)
45 | break;
46 | default:
47 | value.forEach(_value => {
48 | _result.push(key + '[]=' + _value)
49 | })
50 | }
51 | } else {
52 | _result.push(key + '=' + value)
53 | }
54 | }
55 | return _result.length ? prefix + _result.join('&') : ''
56 | }
57 |
58 | export default queryParams;
--------------------------------------------------------------------------------
/src/yeim-uni-sdk.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable*/
2 |
3 | /**
4 | *
5 | * YeIM-Uni-SDK
6 | * 可以私有化部署的全开源即时通讯js-sdk,仅需集成 SDK 即可轻松实现聊天能力,支持Web或uni-app项目接入使用,满足通信需要。
7 | *
8 | * @author wzJun1
9 | * @link https://github.com/wzJun1/YeIM-Uni-SDK
10 | * @doc https://wzjun1.netlify.app/ye_plugins/sdk/yeimunisdk
11 | * @copyright wzJun1 2022, 2024. All rights reserved.
12 | * @license Apache-2.0
13 | *
14 | */
15 |
16 | import {
17 | version
18 | } from '../package.json';
19 |
20 | import {
21 | YeIMUniSDKDefines
22 | } from './const/yeim-defines';
23 |
24 | import {
25 | YeIMUniSDKStatusCode
26 | } from './const/yeim-status-code';
27 |
28 | import WebSocketUtil from './func/websocket';
29 |
30 | import {
31 | successHandle,
32 | errHandle
33 | } from './func/callback';
34 |
35 | import mitt from './utils/mitt.umd'
36 |
37 | import {
38 | emit,
39 | addEventListener,
40 | removeEventListener
41 | } from './func/event';
42 |
43 | import log from './func/log';
44 |
45 | import {
46 | createTextMessage,
47 | createTextAtMessage,
48 | createImageMessage,
49 | createImageMessageFromUrl,
50 | createAudioMessage,
51 | createAudioMessageFromUrl,
52 | createLocationMessage,
53 | createVideoMessage,
54 | createVideoMessageFromUrl,
55 | createCustomMessage,
56 | createMergerMessage,
57 | createForwardMessage,
58 | sendMessage,
59 | saveMessage,
60 | getHistoryMessageList,
61 | revokeMessage,
62 | deleteMessage,
63 | handleMessageRevoked
64 | } from './service/messageService'
65 |
66 | import {
67 | deleteConversation,
68 | saveAndUpdateConversation,
69 | clearConversationUnread,
70 | getConversation,
71 | getConversationList,
72 | saveCloudConversationListToLocal,
73 | handlePrivateConversationReadReceipt
74 | } from './service/conversationService'
75 |
76 | import {
77 | createGroup,
78 | dissolveGroup,
79 | getGroup,
80 | getGroupList,
81 | transferLeader,
82 | updateGroup,
83 | joinGroup,
84 | leaveGroup,
85 | addGroupUsers,
86 | removeGroupUsers,
87 | setAdminstrator,
88 | getGroupApplyList,
89 | getGroupUserList,
90 | handleApply,
91 | setMute
92 | } from './service/groupService'
93 |
94 | import {
95 | getMediaUploadParams,
96 | upload,
97 | } from './service/uploadService'
98 |
99 | import {
100 | getUserInfo,
101 | updateUserInfo,
102 | getBlackUserList,
103 | addToBlackUserList,
104 | removeFromBlacklist
105 | } from './service/userService'
106 |
107 | import {
108 | setPushPermissions,
109 | createNotificationChannel,
110 | bindAppUserPushCID
111 | } from './service/pushService'
112 |
113 | import {
114 | acceptApply,
115 | addFriend,
116 | deleteFriend,
117 | getFriendApplyList,
118 | getFriendList,
119 | handleFriendApplyListChanged,
120 | handleFriendListChanged,
121 | refuseApply,
122 | setApplyListRead,
123 | updateFriend
124 | } from './service/friendService';
125 |
126 | /**
127 | * YeIMUniSDK实例化对象
128 | */
129 | let instance;
130 |
131 | /**
132 | * YeIMUniSDK
133 | * @class
134 | */
135 | class YeIMUniSDK {
136 |
137 | /**
138 | * @constructs
139 | */
140 | constructor(options = {}) {
141 |
142 | /**
143 | * 全局配置参数
144 | */
145 | this.defaults = {
146 |
147 | /**
148 | * http url
149 | */
150 | baseURL: undefined,
151 |
152 | /**
153 | * socket url
154 | */
155 | socketURL: undefined,
156 |
157 | /**
158 | * 事件前缀
159 | */
160 | eventPrefix: 'YeIM_',
161 |
162 | /**
163 | * 最大重连次数,0不限制一直重连
164 | */
165 | reConnectTotal: 15,
166 |
167 | /**
168 | * 重连时间间隔
169 | */
170 | reConnectInterval: 3000,
171 |
172 | /**
173 | * 心跳时间间隔(默认30s)
174 | */
175 | heartInterval: 30000,
176 |
177 | /**
178 | * 日志等级
179 | * 0 普通日志,日志量较多,接入时建议使用
180 | * 1 关键性日志,日志量较少,生产环境时建议使用
181 | * 2 无日志级别,SDK 将不打印任何日志
182 | */
183 | logLevel: 0,
184 |
185 | /**
186 | * SDK自定义初始化参数
187 | */
188 | ...options,
189 |
190 | /**
191 | * APP离线通知配置
192 | */
193 | notification: {
194 |
195 | /**
196 | * 登录后是否自动检测通知权限
197 | */
198 | autoPermission: false,
199 |
200 | /**
201 | * 手机安卓8.0以上的通知渠道ID(需要申请)
202 | */
203 | oppoChannelId: 'Default', //OPPO手机安卓8.0以上的通知渠道ID
204 |
205 | /**
206 | * 小米手机重要级别消息通知渠道ID(需要申请,一般默认为high_system)
207 | */
208 | xiaomiChannelId: 'high_system',
209 |
210 | ...options.notification
211 | },
212 |
213 | };
214 |
215 | /**
216 | * uni环境
217 | */
218 | if (typeof uni !== 'undefined') {
219 | this.uni = true;
220 | } else {
221 | this.uni = false;
222 | }
223 | /**
224 | * 版本号
225 | */
226 | this.version = version;
227 | /**
228 | * 事件总线
229 | */
230 | this.emitter = mitt();
231 | /**
232 | * 是否首次连接
233 | */
234 | this.firstConnect = true;
235 | /**
236 | * webSocket
237 | */
238 | this.webSocket = undefined;
239 | /**
240 | * 是否已登陆YeIMServer
241 | */
242 | this.socketLogged = false;
243 | /**
244 | * 是否允许重连
245 | */
246 | this.allowReconnect = true;
247 | /**
248 | * 重连锁,防止多重调用
249 | */
250 | this.lockReconnect = false;
251 | /**
252 | * 重连次数
253 | */
254 | this.reConnectNum = 0;
255 | /**
256 | * 登录连接超时定时器
257 | */
258 | this.connectTimer = undefined;
259 | /**
260 | * 心跳定时器
261 | */
262 | this.heartTimer = undefined;
263 | /**
264 | * 检测定时器
265 | */
266 | this.checkTimer = undefined;
267 | /**
268 | * 用户信息
269 | */
270 | this.user = {};
271 | /**
272 | * 用户ID
273 | */
274 | this.userId = undefined;
275 | /**
276 | * 登陆token
277 | */
278 | this.token = undefined;
279 | /**
280 | * 媒体上传参数
281 | */
282 | this.mediaUploadParams = {};
283 | /**
284 | * 移动端推送标识符
285 | */
286 | this.mobileDeviceId = undefined;
287 | /**
288 | * APP是否在前台
289 | */
290 | this.inApp = true;
291 | }
292 |
293 | /**
294 | * 初始化SDK
295 | * @param options 配置项
296 | * @returns YeIMUniSDK实例化对象
297 | */
298 | static init(options = {}) {
299 | if (typeof uni !== 'undefined' && uni.$YeIMInstance) {
300 | instance = uni.$YeIMInstance;
301 | }
302 | if (instance) {
303 | return instance;
304 | }
305 | if (!options.baseURL || !options.socketURL) {
306 | return console.error(YeIMUniSDKStatusCode.SDK_PARAMS_ERROR.describe);
307 | }
308 | instance = new YeIMUniSDK(options);
309 | if (typeof uni !== 'undefined') {
310 | uni.$YeIMInstance = instance;
311 | }
312 | YeIMUniSDK.prototype.createTextMessage = createTextMessage; //创建文字消息
313 | YeIMUniSDK.prototype.createTextAtMessage = createTextAtMessage; //创建群聊文字@消息
314 | YeIMUniSDK.prototype.createImageMessage = createImageMessage; //创建图片消息
315 | YeIMUniSDK.prototype.createImageMessageFromUrl = createImageMessageFromUrl; //创建图片Url直发消息
316 | YeIMUniSDK.prototype.createAudioMessage = createAudioMessage; //创建语音消息
317 | YeIMUniSDK.prototype.createAudioMessageFromUrl = createAudioMessageFromUrl; //创建语音Url直发消息
318 | YeIMUniSDK.prototype.createVideoMessage = createVideoMessage; //创建小视频消息
319 | YeIMUniSDK.prototype.createVideoMessageFromUrl = createVideoMessageFromUrl; //创建小视频Url直发消息
320 | YeIMUniSDK.prototype.createLocationMessage = createLocationMessage; //创建位置消息
321 | YeIMUniSDK.prototype.createCustomMessage = createCustomMessage; //创建自定义消息
322 | YeIMUniSDK.prototype.createMergerMessage = createMergerMessage; //创建合并消息
323 | YeIMUniSDK.prototype.createForwardMessage = createForwardMessage; //创建转发消息
324 | YeIMUniSDK.prototype.upload = upload; //通用上传接口
325 | YeIMUniSDK.prototype.sendMessage = sendMessage; //发送消息统一接口
326 | YeIMUniSDK.prototype.getHistoryMessageList =
327 | getHistoryMessageList; //v1.1.7开始使用!获取历史消息记录(本地默认只存取每个会话的最新20条记录,剩余记录均从云端拉取)
328 | YeIMUniSDK.prototype.revokeMessage = revokeMessage; //撤回消息
329 | YeIMUniSDK.prototype.deleteMessage = deleteMessage; //删除消息
330 | YeIMUniSDK.prototype.getConversation = getConversation; //获取会话详情
331 | YeIMUniSDK.prototype.getConversationList = getConversationList; //获取会话列表
332 | YeIMUniSDK.prototype.clearConversationUnread = clearConversationUnread; //清除指定会话未读数
333 | YeIMUniSDK.prototype.deleteConversation = deleteConversation; //删除指定会话和聊天记录
334 | YeIMUniSDK.prototype.getUserInfo = getUserInfo; //获取用户资料
335 | YeIMUniSDK.prototype.updateUserInfo = updateUserInfo; //更新用户昵称和头像
336 | YeIMUniSDK.prototype.getBlackUserList = getBlackUserList; //获取黑名单列表
337 | YeIMUniSDK.prototype.addToBlackUserList = addToBlackUserList; //添加用户到黑名单
338 | YeIMUniSDK.prototype.removeFromBlacklist = removeFromBlacklist; //把用户从黑名单移除
339 | YeIMUniSDK.prototype.addEventListener = addEventListener; //设置监听器
340 | YeIMUniSDK.prototype.removeEventListener = removeEventListener; //移除监听器
341 | YeIMUniSDK.prototype.createGroup = createGroup; //创建群组
342 | YeIMUniSDK.prototype.dissolveGroup = dissolveGroup; //解散群组
343 | YeIMUniSDK.prototype.updateGroup = updateGroup; //更新群组资料
344 | YeIMUniSDK.prototype.getGroup = getGroup; //获取群组资料
345 | YeIMUniSDK.prototype.transferLeader = transferLeader; //转让群主
346 | YeIMUniSDK.prototype.getGroupList = getGroupList; //获取我的群组列表
347 | YeIMUniSDK.prototype.joinGroup = joinGroup; //申请入群
348 | YeIMUniSDK.prototype.leaveGroup = leaveGroup; //退出群组
349 | YeIMUniSDK.prototype.addGroupUsers = addGroupUsers; //添加群成员
350 | YeIMUniSDK.prototype.getGroupUserList = getGroupUserList; //获取群成员列表
351 | YeIMUniSDK.prototype.removeGroupUsers = removeGroupUsers; //移除群成员
352 | YeIMUniSDK.prototype.setAdminstrator = setAdminstrator; //设置群管理员
353 | YeIMUniSDK.prototype.setMute = setMute; //禁言群成员
354 | YeIMUniSDK.prototype.getGroupApplyList = getGroupApplyList; //获取名下群组用户入群申请列表
355 | YeIMUniSDK.prototype.handleApply = handleApply; //处理入群申请
356 | YeIMUniSDK.prototype.getFriendList = getFriendList; //获取好友列表
357 | YeIMUniSDK.prototype.getFriendApplyList = getFriendApplyList; //获取好友申请列表
358 | YeIMUniSDK.prototype.setApplyListRead = setApplyListRead; //将全部好友申请设置为已读状态
359 | YeIMUniSDK.prototype.acceptApply = acceptApply; //同意好友申请
360 | YeIMUniSDK.prototype.refuseApply = refuseApply; //拒绝好友申请
361 | YeIMUniSDK.prototype.addFriend = addFriend; //添加好友
362 | YeIMUniSDK.prototype.deleteFriend = deleteFriend; //添加好友
363 | YeIMUniSDK.prototype.updateFriend = updateFriend; //更新好友资料
364 | log(1, "============= YeIMUniSDK 初始化成功!版本号:" + instance.version + " =============");
365 | return instance;
366 | }
367 |
368 | /**
369 | * 获取SDK实例化对象
370 | */
371 | static getInstance() {
372 | if (typeof uni !== 'undefined' && uni.$YeIMInstance) {
373 | instance = uni.$YeIMInstance;
374 | }
375 | if (instance) {
376 | return instance;
377 | }
378 | console.error("SDK未初始化,无法获取实例化对象")
379 | return undefined;
380 | }
381 |
382 | /**
383 | * 连接YeIMServer
384 | * @param options 配置项
385 | * @returns YeIMUniSDK实例化对象
386 | */
387 | connect(options = {}) {
388 |
389 | if (!options.userId || !options.token) {
390 | return errHandle(options, YeIMUniSDKStatusCode.NO_USERID.code, YeIMUniSDKStatusCode.NO_USERID
391 | .describe);
392 | }
393 |
394 | //拼接websocket连接url
395 | let url = this.defaults.socketURL + "/" + options.userId + "/" + options.token;
396 | //创建websocket连接
397 | this.webSocket = new WebSocketUtil(url);
398 |
399 | //设置websocket相关监听
400 | this.webSocket.onOpen(this.socketOpen.bind(this));
401 | this.webSocket.onClose(this.socketClose.bind(this));
402 | this.webSocket.onError(this.socketError.bind(this));
403 | this.webSocket.onMessage(this.socketMessage.bind(this));
404 |
405 | //连接异常
406 | if (this.connectTimer) {
407 | clearTimeout(this.connectTimer);
408 | this.connectTimer = undefined;
409 | }
410 | this.connectTimer = setTimeout(() => {
411 | this.connectTimer = undefined;
412 | log(1, '连接服务端失败,请检查配置');
413 | return errHandle(options, YeIMUniSDKStatusCode.CONNECT_ERROR.code, YeIMUniSDKStatusCode
414 | .CONNECT_ERROR
415 | .describe);
416 | }, this.defaults.reConnectInterval + 1000);
417 |
418 | //临时设置监听onMessage
419 | this.webSocket.onMessage((res) => {
420 | if (this.socketLogged) {
421 | clearTimeout(this.connectTimer);
422 | this.connectTimer = undefined;
423 | return;
424 | z
425 | }
426 | clearTimeout(this.connectTimer);
427 | this.connectTimer = undefined;
428 | let data = JSON.parse(res.data);
429 | //监听到登陆成功
430 | if (data.code == 201) {
431 | //设置用户相关参数
432 | let user = data.data.user;
433 | this.user = user;
434 | this.userId = options.userId;
435 | this.token = options.token;
436 | //设置推送参数
437 | let pushConfig = data.data.pushConfig;
438 | if (pushConfig.oppoChannelId) {
439 | this.defaults.notification.oppoChannelId = pushConfig.oppoChannelId;
440 | }
441 | if (pushConfig.xiaomiChannelId) {
442 | this.defaults.notification.xiaomiChannelId = pushConfig.xiaomiChannelId;
443 | }
444 | //设置socket state(socketLogged)登陆成功
445 | this.socketLogged = true;
446 | this.reConnectNum = 0;
447 | log(1, `YeIMServer登陆成功,登陆用户:${options.userId}`)
448 | //登陆成功后从服务端获取一下全部会话,并发送事件CONVERSATION_LIST_CHANGED
449 | saveCloudConversationListToLocal(1, 100000);
450 | //登陆成功触发一次好友列表更新事件
451 | handleFriendListChanged();
452 | //登陆成功触发一次好友申请列表更新事件
453 | handleFriendApplyListChanged();
454 | //获取媒体上传参数
455 | getMediaUploadParams();
456 | //如果在uni环境下,执行以下操作
457 | if (this.uni) {
458 | //3.1 申请权限
459 | if (this.defaults.notification.autoPermission) {
460 | setPushPermissions();
461 | }
462 | //创建推送渠道
463 | createNotificationChannel();
464 | //APP用户绑定个推CID到后端,用于离线推送
465 | bindAppUserPushCID();
466 | //监听在线透传消息
467 | let uuidList = [];
468 | uni.onPushMessage((res) => {
469 | //APP在后台,并且没被杀掉的时候,收到透传消息在客户端创建通知提示
470 | if (!this.inApp && res.type == 'receive') {
471 | let uuid = res.data.__UUID__;
472 | if (uuidList.indexOf(uuid) <= 0) {
473 | uuidList.push(uuid);
474 | uni.createPushMessage({
475 | title: res.data.title,
476 | content: res.data.content,
477 | sound: 'system',
478 | success: () => {},
479 | fail: () => {}
480 | })
481 | }
482 | }
483 | })
484 | }
485 | return successHandle(options, YeIMUniSDKStatusCode.NORMAL_SUCCESS.describe, user);
486 | } else {
487 | return errHandle(options, YeIMUniSDKStatusCode.LOGIN_ERROR.code, YeIMUniSDKStatusCode
488 | .LOGIN_ERROR
489 | .describe);
490 | }
491 | })
492 | }
493 |
494 | /**
495 | * 断开连接
496 | * 手动操作断开连接后,不会重连
497 | */
498 | disConnect() {
499 | this.allowReconnect = false;
500 | this.webSocket.close();
501 | this.webSocket.destroy();
502 | }
503 |
504 | /**
505 | * 重连
506 | */
507 | reConnect() {
508 |
509 | if (this.allowReconnect && !this.lockReconnect) {
510 | //没有用户信息,取消重连
511 | if (!this.userId || !this.token) {
512 | this.allowReconnect = false;
513 | return;
514 | }
515 | //设置了最大重连次数,并且已经到了限制,不再连。
516 | if (this.defaults.reConnectTotal > 0 && this.defaults.reConnectTotal <= this.reConnectNum) {
517 | this.allowReconnect = false;
518 | return;
519 | }
520 | this.reConnectNum++;
521 | this.lockReconnect = true;
522 | //没连接上会一直重连,设置延迟避免请求过多
523 | //通知网络状态变化
524 | emit(YeIMUniSDKDefines.EVENT.NET_CHANGED, 'connecting');
525 | setTimeout(() => {
526 | log(1, `WebSocket 正在进行第${this.reConnectNum}次重连`)
527 | try {
528 | this.connect({
529 | userId: this.userId,
530 | token: this.token
531 | });
532 | } catch (e) {
533 | console.log(e)
534 | }
535 | this.lockReconnect = false;
536 | }, this.defaults.reConnectInterval); //这里设置重连间隔(ms)
537 |
538 | }
539 | }
540 |
541 | /**
542 | * 获取当前连接状态
543 | * "CLOSED":3,"CLOSING":2,"CONNECTING":0,"OPEN":1
544 | */
545 | readyState() {
546 | if (this.webSocket && this.webSocket.socketTask) {
547 | return this.webSocket.socketTask.readyState;
548 | } else {
549 | return 3;
550 | }
551 | }
552 |
553 | /**
554 | * 开始心跳
555 | */
556 | startHeartTimer() {
557 | this.clearHeartTimer();
558 | if (this.webSocket && this.webSocket.socketTask) {
559 | this.heartTimer = setTimeout(() => {
560 | if (this.readyState() == 1) {
561 | let heartJson = {
562 | type: 'heart',
563 | data: 'ping'
564 | };
565 | this.webSocket.send(heartJson);
566 | this.checkTimer = setTimeout(() => {
567 | this.webSocket.close();
568 | }, this.defaults.heartInterval)
569 | }
570 | }, this.defaults.heartInterval)
571 | }
572 | }
573 |
574 | /**
575 | * 清除心跳定时器,取消心跳
576 | */
577 | clearHeartTimer() {
578 | clearTimeout(this.heartTimer);
579 | clearTimeout(this.checkTimer);
580 | return this;
581 | }
582 |
583 |
584 | /**
585 | * socket 打开回调
586 | * @param {Object} info
587 | */
588 | socketOpen(info) {
589 | log(1, 'WebSocket成功连接');
590 | emit(YeIMUniSDKDefines.EVENT.NET_CHANGED, 'connected');
591 | }
592 |
593 | /**
594 | * socket 关闭回调
595 | * @param {Object} err
596 | */
597 | socketClose(err) {
598 | log(1, 'WebSocket断开连接');
599 | this.socketLogged = false;
600 | this.webSocket.close();
601 | this.webSocket.destroy();
602 | emit(YeIMUniSDKDefines.EVENT.NET_CHANGED, 'closed');
603 | this.reConnect();
604 | }
605 |
606 | /**
607 | * socket 错误回调
608 | * @param {Object} err
609 | */
610 | socketError(err) {
611 | log(1, err);
612 | this.reConnect();
613 | }
614 |
615 | /**
616 | * socket 消息回调
617 | * @param {Object} res
618 | */
619 | socketMessage(res) {
620 | log(0, res);
621 | //收到任意消息代表心跳成功
622 | this.startHeartTimer();
623 | if (!this.socketLogged) return;
624 | let data = JSON.parse(res.data);
625 | if (data) {
626 | this.socketMessageHandle(data);
627 | } else {
628 | log(1, res);
629 | }
630 | }
631 |
632 | /**
633 | * WebSocket消息统一处理
634 | * @param {Object} data
635 | */
636 | socketMessageHandle(data) {
637 | if (data.code == 200) {
638 | //收到消息
639 | let message = data.data;
640 |
641 | //1. 保存消息,会话数据由在线推送
642 | saveMessage(message);
643 |
644 | //2. 发送消息接收事件
645 | emit(YeIMUniSDKDefines.EVENT.MESSAGE_RECEIVED, message);
646 |
647 | } else if (data.code == 203) {
648 | //收到会话更新
649 | let conversation = data.data;
650 | saveAndUpdateConversation(conversation);
651 | } else if (data.code == 205) {
652 | //收到私聊会话已读回执
653 | let conversation = data.data;
654 | handlePrivateConversationReadReceipt(conversation.conversationId);
655 | } else if (data.code == 207) {
656 | //收到消息撤回事件
657 | handleMessageRevoked(data.data);
658 | } else if (data.code == 208) {
659 | //好友列表更新事件
660 | setTimeout(() => {
661 | handleFriendListChanged();
662 | }, 500);
663 | } else if (data.code == 209) {
664 | //好友申请列表更新
665 | setTimeout(() => {
666 | handleFriendApplyListChanged();
667 | }, 500);
668 | } else if (data.code == 210) {
669 | //好友申请被拒绝
670 | emit(YeIMUniSDKDefines.EVENT.FRIEND_APPLY_REFUSE, data.data);
671 | //更新好友申请列表
672 | setTimeout(() => {
673 | handleFriendApplyListChanged(1);
674 | }, 500);
675 | } else if (data.code == 10009) {
676 | //被踢下线不允许重连
677 | this.allowReconnect = false;
678 | this.clearHeartTimer();
679 | this.webSocket.close();
680 | emit(YeIMUniSDKDefines.EVENT.KICKED_OUT, true);
681 | log(1, `用户:${this.userId} 由于多个实例同时登录被踢出`);
682 | }
683 | }
684 |
685 |
686 | /**
687 | * 拦截登陆状态
688 | */
689 | checkLogged() {
690 | if (!this.socketLogged || !this.userId || !this.token) {
691 | return false;
692 | } else {
693 | return true;
694 | }
695 | }
696 |
697 | /**
698 | * 设置APP在前台
699 | */
700 | intoApp() {
701 | this.inApp = true;
702 | }
703 |
704 | /**
705 | * 设置APP已进入后台
706 | */
707 | leaveApp() {
708 | this.inApp = false;
709 | }
710 |
711 | }
712 |
713 | export {
714 | instance,
715 | YeIMUniSDK,
716 | YeIMUniSDKDefines
717 | };
718 |
--------------------------------------------------------------------------------
/src/yeim-uni-sdk.min.d.ts:
--------------------------------------------------------------------------------
1 | export declare module './yeim-uni-sdk.min.js' {
2 | /**
3 | *
4 | * YeIM-Uni-SDK
5 | * 可以私有化部署的全开源即时通讯js-sdk,仅需集成 SDK 即可轻松实现聊天能力,支持Web或uni-app项目接入使用,满足通信需要。
6 | *
7 | * @author wzJun1
8 | * @link https://github.com/wzJun1/YeIM-Uni-SDK
9 | * @doc https://wzjun1.netlify.app/ye_plugins/sdk/yeimunisdk
10 | * @copyright wzJun1 2022, 2023. All rights reserved.
11 | * @license Apache-2.0
12 | *
13 | */
14 | declare class YeIMUniSDK {
15 |
16 | /**
17 | * 初始化SDK
18 | *
19 | * @param options 配置项
20 | * @param options.baseURL - YeIMServer http url (如无特殊需求,服务端启动后仅需修改ip或者域名即可)
21 | * @param options.socketURL - YeIMServer socket url(如无特殊需求,服务端启动后仅需修改ip或者域名即可)
22 | * @param options.logLevel - SDK 日志等级
23 | * @param options.reConnectInterval - socket 重连时间间隔
24 | * @param options.reConnectTotal - socket 最大重连次数,0不限制一直重连
25 | * @param options.heartInterval - socket 心跳时间间隔(默认30s)
26 | * @param options.notification - APP离线通知配置
27 | * @returns {YeIMUniSDK} YeIMUniSDK实例化对象
28 | */
29 | static init(options : {
30 |
31 | /**
32 | * YeIMServer http url (如无特殊需求,服务端启动后仅需修改ip或者域名即可)
33 | */
34 | baseURL : string;
35 |
36 | /**
37 | * YeIMServer socket url(如无特殊需求,服务端启动后仅需修改ip或者域名即可)
38 | */
39 | socketURL : string;
40 | /**
41 | * SDK 日志等级
42 | * 0 普通日志,日志量较多,接入时建议使用
43 | * 1 关键性日志,日志量较少,生产环境时建议使用
44 | * 2 无日志级别,SDK 将不打印任何日志
45 | */
46 |
47 | logLevel ?: number;
48 | /**
49 | * socket 重连时间间隔
50 | */
51 |
52 | reConnectInterval ?: number;
53 |
54 | /**
55 | * socket 最大重连次数,0不限制一直重连
56 | */
57 |
58 | reConnectTotal ?: number;
59 |
60 | /**
61 | * socket 心跳时间间隔(默认30s)
62 | */
63 | heartInterval ?: number;
64 |
65 | /**
66 | * APP离线通知配置
67 | */
68 | notification ?: object;
69 |
70 | }) : YeIMUniSDK;
71 |
72 | /**
73 | * 获取SDK实例化对象
74 | */
75 | static getInstance() : YeIMUniSDK?;
76 |
77 | /**
78 | * 连接登录YeIM
79 | *
80 | * @param options 配置项
81 | * @param options.userId 已注册的用户ID字符串
82 | * @param options.token 登录token,由请求服务端Http接口换取
83 | * @param {(result)=>void} [options.success] - 成功回调
84 | * @param {(error)=>void} [options.fail] - 失败回调
85 | * @returns {void}
86 | */
87 | connect(options : {
88 | userId : string,
89 | token : string,
90 | success ?: (result : any) => void,
91 | fail ?: (error : any) => void
92 | }) : void;
93 |
94 | /**
95 | * 创建文本消息
96 | *
97 | * @param {Options} options - 创建消息参数对象
98 | *
99 | * @param {String} options.toId - 接受者用户ID
100 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
101 | * @param {Object} options.body - 文本消息对象
102 | * @param {String} options.body.text - 文本消息内容
103 | * @param {String} options.extra - 自定义扩展数据
104 | *
105 | * @return {(Object|Message)} Message 消息对象
106 | *
107 | */
108 | createTextMessage(options : {
109 | toId : string,
110 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
111 | body : {
112 | text : string
113 | },
114 | extra ?: string
115 | }) : Message | Object;
116 |
117 | /**
118 | * 创建群聊 @ 艾特消息
119 | *
120 | * @param {Options} options - 创建消息参数对象
121 | *
122 | * @param {String} options.toId - 群ID
123 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊 当前消息仅支持群里
124 | * @param {Body} options.body - 文本消息对象
125 | * @param {String} options.body.text - 文本消息内容
126 | * @param {Array} options.body.atUserIdList - 要艾特的用户ID列表
127 | * @param {String} options.extra - 自定义扩展数据
128 | *
129 | * @return {(Object|Message)} Message 消息对象
130 | *
131 | */
132 | createTextAtMessage(options : {
133 | toId : string,
134 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
135 | body : {
136 | text : string,
137 | atUserIdList : Array
138 | },
139 | extra ?: string
140 | }) : Message | Object;
141 |
142 | /**
143 | * 创建图片消息
144 | *
145 | * 仅支持单张图片
146 | *
147 | * @param {Options} options - 创建消息参数对象
148 | *
149 | * @param {String} options.toId - 接受者用户ID
150 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
151 | * @param {Body} options.body - 图片消息对象
152 | * @param {File} options.body.file - 图片消息对象
153 | * @param {String} options.body.file.tempFilePath - 本地图片文件临时路径
154 | * @param {Number} options.body.file.width - 图片宽度
155 | * @param {Number} options.body.file.height - 图片高度
156 | * @param {String} options.extra - 自定义扩展数据
157 | *
158 | * @return {(Object|Message)} Message 消息对象
159 | *
160 | */
161 | createImageMessage(options : {
162 | toId : string,
163 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
164 | body : {
165 | file : {
166 | tempFilePath : string,
167 | width : number,
168 | height : number
169 | }
170 | },
171 | extra ?: string
172 | }) : Message | Object;
173 |
174 | /**
175 | * 创建图片Url直发消息
176 | *
177 | * 仅支持单张图片
178 | *
179 | * @param {Options} options - 创建消息参数对象
180 | *
181 | * @param {String} options.toId - 接受者用户ID
182 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
183 | * @param {Body} options.body - 图片消息对象
184 | * @param {String} options.body.originalUrl - 原图网络Url
185 | * @param {Number} options.body.originalWidth - 原图宽度
186 | * @param {Number} options.body.originalHeight - 原图高度
187 | * @param {String} options.body.thumbnailUrl - 缩略图网络Url
188 | * @param {Number} options.body.thumbnailWidth - 缩略图宽度
189 | * @param {Number} options.body.thumbnailHeight - 缩略图高度
190 | * @param {String} options.extra - 自定义扩展数据
191 | *
192 | * @return {(Object|Message)} Message 消息对象
193 | *
194 | */
195 | createImageMessageFromUrl(options : {
196 | toId : string,
197 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
198 | body : {
199 | originalUrl : string,
200 | originalWidth : number,
201 | originalHeight : number,
202 | thumbnailUrl : string,
203 | thumbnailWidth : number,
204 | thumbnailHeight : number
205 | },
206 | extra ?: string
207 | }) : Message | Object;
208 |
209 |
210 | /**
211 | * 创建语音消息
212 | *
213 | * 仅支持AAC格式音频
214 | *
215 | * @param {Options} options - 创建消息参数对象
216 | *
217 | * @param {String} options.toId - 接受者用户ID
218 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
219 | * @param {Body} options.body - 音频消息对象
220 | * @param {File} options.body.file - 音频文件信息
221 | * @param {String} options.body.file.tempFilePath - 本地音频文件临时路径
222 | * @param {Number} options.body.file.duration - 音频时长,单位秒
223 | * @param {String} options.extra - 自定义扩展数据
224 | *
225 | * @return {(Object|Message)} Message 消息对象
226 | *
227 | */
228 | createAudioMessage(options : {
229 | toId : string,
230 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
231 | body : {
232 | file : {
233 | tempFilePath : string,
234 | duration : number
235 | }
236 | },
237 | extra ?: string
238 | }) : Message | Object;
239 |
240 | /**
241 | * 创建语音Url直发消息
242 | *
243 | * @param {Options} options - 创建消息参数对象
244 | *
245 | * @param {String} options.toId - 接受者用户ID
246 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
247 | * @param {Body} options.body - 音频消息对象
248 | * @param {String} options.body.audioUrl - 音频网络Url
249 | * @param {Number} options.body.duration - 音频时长,单位秒
250 | * @param {String} options.extra - 自定义扩展数据
251 | *
252 | * @return {(Object|Message)} Message 消息对象
253 | *
254 | */
255 | createAudioMessageFromUrl(options : {
256 | toId : string,
257 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
258 | body : {
259 | tempFilePath : string,
260 | duration : number
261 | },
262 | extra ?: string
263 | }) : Message | Object;
264 |
265 | /**
266 | * 创建小视频消息
267 | *
268 | * @param {Options} options - 创建消息参数对象
269 | *
270 | * @param {String} options.toId - 接受者用户ID
271 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
272 | * @param {Body} options.body - 视频消息对象
273 | * @param {File} options.body.file - 视频文件信息
274 | * @param {String} options.body.file.tempFilePath - 本地小视频文件临时路径
275 | * @param {Number} options.body.file.duration - 视频时长
276 | * @param {Number} options.body.file.width - 视频宽度
277 | * @param {Number} options.body.file.height - 视频高度
278 | * @param {String} options.extra - 自定义扩展数据
279 | *
280 | * @return {(Object|Message)} Message 消息对象
281 | *
282 | */
283 | createVideoMessage(options : {
284 | toId : string,
285 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
286 | body : {
287 | file : {
288 | tempFilePath : string,
289 | duration : number,
290 | width : number,
291 | height : number
292 | }
293 | },
294 | extra ?: string
295 | }) : Message | Object;
296 |
297 | /**
298 | * 创建小视频Url直发消息
299 | *
300 | * @param {Options} options - 创建消息参数对象
301 | *
302 | * @param {String} options.toId - 接受者用户ID
303 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
304 | * @param {Body} options.body - 视频消息对象
305 | * @param {String} options.body.videoUrl - 视频网络Url
306 | * @param {String} options.body.thumbnailUrl - 视频缩略图网络Url
307 | * @param {Number} options.body.duration - 视频时长
308 | * @param {Number} options.body.width - 视频宽度
309 | * @param {Number} options.body.height - 视频高度
310 | * @param {String} options.extra - 自定义扩展数据
311 | *
312 | * @return {(Object|Message)} Message 消息对象
313 | *
314 | */
315 | createVideoMessageFromUrl(options : {
316 | toId : string,
317 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
318 | body : {
319 | videoUrl : string,
320 | thumbnailUrl : string,
321 | duration : number,
322 | width : number,
323 | height : number
324 | },
325 | extra ?: string
326 | }) : Message | Object;
327 |
328 | /**
329 | * 创建位置消息
330 | *
331 | * @param {Options} options - 创建消息参数对象
332 | *
333 | * { "toId": "接受者用户ID", "conversationType": YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE, body: { address: "地址名称", description: "地址详细描述", longitude: 105.000000, latitude: 31.000000 }}
334 | *
335 | * @param {String} options.toId - 接受者用户ID
336 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
337 | * @param {Body} options.body - 位置消息对象
338 | * @param {String} options.body.address - 地址名称
339 | * @param {String} options.body.description - 地址详细描述
340 | * @param {Number} options.body.longitude - 经度
341 | * @param {Number} options.body.latitude - 纬度
342 | * @param {String} options.extra - 自定义扩展数据
343 | *
344 | * @return {(Object|Message)} Message 消息对象
345 | *
346 | */
347 | createLocationMessage(options : {
348 | toId : string,
349 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
350 | body : {
351 | address : string,
352 | description : string,
353 | longitude : number,
354 | latitude : number
355 | },
356 | extra ?: string
357 | }) : Message | Object;
358 |
359 | /**
360 | * 创建自定义消息
361 | *
362 | * 自定义消息内容放在body字段
363 | *
364 | * @param {Options} options - 创建消息参数对象
365 | *
366 | * { "toId": "接受者用户ID", "conversationType": YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE, body: {} }
367 | *
368 | * @param {String} options.toId - 接受者用户ID
369 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
370 | * @param {Body} options.body - 自定义消息内容
371 | * @param {String|Object} options.body.custom - 消息内容
372 | * @param {String} options.extra - 自定义扩展数据
373 | *
374 | * @return {(Object|Message)} Message 消息对象
375 | *
376 | */
377 | createCustomMessage(options : {
378 | toId : string,
379 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
380 | body : {
381 | custom : string | object
382 | },
383 | extra ?: string
384 | }) : Message | Object;
385 |
386 | /**
387 | * 创建合并消息
388 | *
389 | * @param {Options} options - 创建消息参数对象
390 | *
391 | * @param {String} options.toId - 接受者用户ID
392 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
393 | * @param {Body} options.body - 文本消息对象
394 | * @param {String} options.body.title - 合并消息的标题
395 | * @param {Array} options.body.messageList - 合并消息的标题
396 | * @param {Array} options.body.summaryList - 合并消息的标题
397 | * @param {String} options.extra - 自定义扩展数据
398 | *
399 | * @return {(Object|Message)} Message 消息对象
400 | *
401 | */
402 | createMergerMessage(options : {
403 | toId : string,
404 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
405 | body : {
406 | title : string,
407 | messageList : Array,
408 | summaryList : Array
409 | },
410 | extra ?: string
411 | }) : Message | Object;
412 |
413 | /**
414 | * 创建转发消息
415 | *
416 | * @param {Options} options - 创建消息参数对象
417 | *
418 | * @param {String} options.toId - 接受者用户ID
419 | * @param {String} options.conversationType - 会话类型(私聊、群聊)定义在YeIMUniSDKDefines,YeIMUniSDKDefines.CONVERSATION_TYPE.PRIVATE = 私聊,YeIMUniSDKDefines.CONVERSATION_TYPE.GROUP = 群聊
420 | * @param {Body} options.body - 文本消息对象
421 | * @param {Message} options.body.message - 要转发的消息
422 | * @param {String} options.extra - 自定义扩展数据
423 | *
424 | * @return {(Object|Message)} Message 消息对象
425 | *
426 | */
427 | createForwardMessage(options : {
428 | toId : string,
429 | conversationType : YeIMUniSDKDefines.CONVERSATION_TYPE,
430 | body : {
431 | message : Message | object,
432 | },
433 | extra ?: string
434 | }) : Message | Object;
435 |
436 | /**
437 | *
438 | * 通用上传接口
439 | *
440 | * @param {Options} options
441 | * @param {String} options.filename - 文件名称(需带后缀)
442 | * @param {String} options.filepath - 本地文件临时路径
443 | * @param {(result)=>void} [options.success] - 成功回调
444 | * @param {(error)=>void} [options.fail] - 失败回调
445 | * @param {(progress)=>void} [options.onProgress] - 上传进度回调
446 | *
447 | */
448 | upload(options : {
449 | filename : string,
450 | filepath : string,
451 | success ?: (result : any) => void,
452 | fail ?: (error : any) => void
453 | }) : void;
454 |
455 | /**
456 | *
457 | * @version 1.1.7
458 | *
459 | * 获取历史消息记录
460 | *
461 | * @param {Options} options - 参数对象
462 | *
463 | * @param {String} options.nextMessageId - 下次拉取的开始ID
464 | * @param {String} options.conversationId - 会话ID
465 | * @param {Number} options.limit - 拉取数量,默认:20
466 | * @param {(result)=>void} options.success - 成功回调
467 | * @param {(error)=>void} options.fail - 失败回调
468 | *
469 | */
470 | getHistoryMessageList(options : {
471 | nextMessageId ?: string,
472 | conversationId : string,
473 | limit ?: number,
474 | success ?: (result : any) => void,
475 | fail ?: (error : any) => void
476 | }) : void;
477 |
478 | /**
479 | *
480 | * 删除消息
481 | *
482 | * @param {Options} options - 参数对象
483 | *
484 | * @param {Message} message - 要删除的消息对象
485 | * @param {(result)=>void} options.success - 成功回调
486 | * @param {(error)=>void} options.fail - 失败回调
487 | *
488 | */
489 | deleteMessage(options : {
490 | message : Message | object,
491 | success ?: (result : any) => void,
492 | fail ?: (error : any) => void
493 | }) : void;
494 |
495 | /**
496 | *
497 | * 撤回消息
498 | *
499 | * @param {Options} options - 参数对象
500 | *
501 | * @param {Message} message - 要撤回的消息对象
502 | * @param {(result)=>void} options.success - 成功回调
503 | * @param {(error)=>void} options.fail - 失败回调
504 | *
505 | */
506 | revokeMessage(options : {
507 | message : Message | object,
508 | success ?: (result : any) => void,
509 | fail ?: (error : any) => void
510 | }) : void;
511 |
512 | /**
513 | * 根据会话ID获取本地会话详情
514 | *
515 | * @param {String} conversationId - 会话ID
516 | * @return {Conversation} conversation
517 | */
518 | getConversation(conversationId : string) : Conversation | object;
519 |
520 | /**
521 | * 获取本地会话列表
522 | *
523 | * @param {Options} options - 参数对象
524 | *
525 | * @param {String} options.page - 页码
526 | * @param {String} options.limit - 每页数量
527 | * @param {(result)=>{}} [options.success] - 成功回调
528 | * @param {(error)=>{}} [options.fail] - 失败回调
529 | */
530 | getConversationList(options : {
531 | page : number,
532 | limit : number,
533 | success ?: (result : any) => void,
534 | fail ?: (error : any) => void
535 | }) : void;
536 |
537 | /**
538 | * 根据会话ID删除会话和聊天记录(包括云端)
539 | *
540 | * @param {Object} conversationId
541 | * @return {void}
542 | */
543 | deleteConversation(conversationId : string) : void;
544 |
545 | /**
546 | * 清除指定会话未读数
547 | *
548 | * 云端同时发送给对端已读事件(私聊)
549 | *
550 | * @param {String} conversationId - 会话ID
551 | * @return {void}
552 | */
553 | clearConversationUnread(conversationId : string) : void;
554 |
555 | /**
556 | *
557 | * 发送消息统一入口
558 | *
559 | * @param {Options} options - 参数对象
560 | *
561 | * @param {Message} options.message - 消息对象
562 | * @param {(result)=>void} [options.success] - 成功回调
563 | * @param {(error)=>void} [options.fail] - 失败回调
564 | *
565 | * @example
566 | * sendMessage({
567 | message: message,
568 | success: (result) => {},
569 | fail: (error) => {}
570 | });
571 | */
572 | sendMessage(options : {
573 | message : Message | Object | undefined,
574 | success ?: (result : any) => void,
575 | fail ?: (error : any) => void
576 | }) : void;
577 |
578 | /**
579 | *
580 | * 获取用户信息
581 | *
582 | * @param {Options} options - 参数对象
583 | *
584 | * @param {String} options.userId - 用户ID
585 | * @param {(result)=>void} [options.success] - 成功回调
586 | * @param {(error)=>void} [options.fail] - 失败回调
587 | *
588 | */
589 | getUserInfo(options : {
590 | userId : string,
591 | success ?: (result : any) => void,
592 | fail ?: (error : any) => void
593 | }) : void;
594 |
595 | /**
596 | *
597 | * 更新我的用户资料
598 | *
599 | * @param {Options} options - 参数对象
600 | *
601 | * @param {String} options.nickname - 昵称
602 | * @param {String} options.avatarUrl - 头像地址
603 | * @param {Number} options.gender - 性别,0=未知,1=男性,2=女性
604 | * @param {Number} options.mobile - 电话
605 | * @param {String} options.email - 邮箱
606 | * @param {String} options.birthday - 生日
607 | * @param {String} options.motto - 个性签名
608 | * @param {String} options.extend - 用户自定义扩展字段
609 | * @param {Number} options.addFriendType - 好友添加我的方式
610 | * @param {(result)=>void} [options.success] - 成功回调
611 | * @param {(error)=>void} [options.fail] - 失败回调
612 | *
613 | */
614 | updateUserInfo(options : {
615 | nickname ?: string,
616 | avatarUrl ?: string,
617 | gender ?: number,
618 | mobile ?: number,
619 | email ?: string,
620 | birthday ?: string,
621 | motto ?: string,
622 | extend ?: string,
623 | addFriendType ?: YeIMUniSDKDefines.USER.ADDFRIEND,
624 | success ?: (result : any) => void,
625 | fail ?: (error : any) => void
626 | }) : void;
627 |
628 | /**
629 | *
630 | * 获取黑名单列表
631 | *
632 | * @param {Options} options - 参数对象
633 | *
634 | * @param {(result)=>void} [options.success] - 成功回调
635 | * @param {(error)=>void} [options.fail] - 失败回调
636 | *
637 | */
638 | getBlackUserList(options : {
639 | success ?: (result : any) => void,
640 | fail ?: (error : any) => void
641 | }) : void;
642 |
643 | /**
644 | *
645 | * 添加用户到黑名单
646 | *
647 | *
648 | * @param {Options} options - 参数对象
649 | *
650 | *
651 | * @param {Array} options.members - 用户ID列表
652 | * @param {(result)=>void} [options.success] - 成功回调
653 | * @param {(error)=>void} [options.fail] - 失败回调
654 | *
655 | * @example
656 | * addToBlackUserList({
657 | members: ["user1", "user2"],
658 | success: (result) => {},
659 | fail: (error) => {}
660 | });
661 | */
662 | addToBlackUserList(options : {
663 | members : Array
664 | success ?: (result : any) => void,
665 | fail ?: (error : any) => void
666 | }) : void;
667 |
668 | /**
669 | *
670 | * 把用户移出黑名单
671 | *
672 | *
673 | * @param {Options} options - 参数对象
674 | *
675 | *
676 | * @param {Array} options.members - 用户ID列表
677 | * @param {(result)=>void} [options.success] - 成功回调
678 | * @param {(error)=>void} [options.fail] - 失败回调
679 | *
680 | * @example
681 | * removeFromBlacklist({
682 | members: ["user1", "user2"],
683 | success: (result) => {},
684 | fail: (error) => {}
685 | });
686 | */
687 | removeFromBlacklist(options : {
688 | members : Array
689 | success ?: (result : any) => void,
690 | fail ?: (error : any) => void
691 | }) : void;
692 |
693 | /**
694 | * 添加IM事件监听器
695 | * @param {Object} event - 事件类型 YeIMUniSDKDefines.EVENT
696 | * @param {(result)=>void} callback 监听回调方法
697 | */
698 | addEventListener(event : string, callback : (result : any) => void);
699 |
700 | /**
701 | * 移除IM事件监听器
702 | * @param {Object} event - 事件类型 YeIMUniSDKDefines.EVENT
703 | * @param {(result)=>void} callback 监听回调方法
704 | */
705 | removeEventListener(event : string, callback : (result : any) => void);
706 |
707 | /**
708 | *
709 | * 创建群组
710 | *
711 | * @param {Options} options - 参数对象
712 | *
713 | * @param {String} options.name - 群名称
714 | * @param {String} options.avatarUrl - 群头像
715 | * @param {String} [options.groupId] - 群ID,未填写时系统自动生成
716 | * @param {Number} [options.joinMode] - 群申请处理方式 - YeIMUniSDKDefines.GROUP.JOINMODE
717 | * @param {String} [options.introduction] - 群简介
718 | * @param {String} [options.notification] - 群公告
719 | * @param {Array} [options.members] - 创建群聊初始化成员(用户ID数组)
720 | * @param {(result)=>void} [options.success] - 成功回调
721 | * @param {(error)=>void} [options.fail] - 失败回调
722 | *
723 | * @example
724 | * createGroup({
725 | name: "",
726 | avatarUrl: "",
727 | success: (result) => {},
728 | fail: (error) => {}
729 | });
730 | */
731 | createGroup(options : {
732 | name : string,
733 | avatarUrl : string,
734 | groupId ?: string,
735 | joinMode ?: number,
736 | introduction ?: string,
737 | notification ?: string,
738 | members ?: Array,
739 | success ?: (result : any) => void,
740 | fail ?: (error : any) => void
741 | }) : void;
742 |
743 | /**
744 | *
745 | * 解散群组
746 | *
747 | * 仅群主可操作
748 | *
749 | * @param {Options} options - 参数对象
750 | *
751 | * @param {String} [options.groupId] - 群ID
752 | * @param {(result)=>void} [options.success] - 成功回调
753 | * @param {(error)=>void} [options.fail] - 失败回调
754 | *
755 | * @example
756 | * dissolveGroup({
757 | groupId: "",
758 | success: (result) => {},
759 | fail: (error) => {}
760 | });
761 | */
762 | dissolveGroup(options : {
763 | groupId : string,
764 | success ?: (result : any) => void,
765 | fail ?: (error : any) => void
766 | }) : void;
767 |
768 | /**
769 | *
770 | * 更新群组资料
771 | *
772 | * @param {Options} options - 参数对象
773 | *
774 | * @param {String} [options.groupId] - 群ID
775 | * @param {String} [options.name] - 群名称
776 | * @param {String} [options.avatarUrl] - 群头像
777 | * @param {YeIMUniSDKDefines.GROUP.JOINMODE} [options.joinMode] - 群申请处理方式
778 | * @param {String} [options.introduction] - 群简介
779 | * @param {String} [options.notification] - 群公告
780 | * @param {Number} [options.isMute] - 全体禁言 0,1
781 | * @param {(result)=>void} [options.success] - 成功回调
782 | * @param {(error)=>void} [options.fail] - 失败回调
783 | *
784 | * @example
785 | * updateGroup({
786 | groupId: "",
787 | name: "",
788 | avatarUrl: "",
789 | success: (result) => {},
790 | fail: (error) => {}
791 | });
792 | */
793 | updateGroup(options : {
794 | groupId : string,
795 | name ?: string,
796 | avatarUrl ?: string,
797 | joinMode ?: number,
798 | introduction ?: string,
799 | notification ?: string,
800 | members ?: Array,
801 | success ?: (result : any) => void,
802 | fail ?: (error : any) => void
803 | }) : void;
804 |
805 | /**
806 | *
807 | * 通过群ID获取群组资料
808 | *
809 | * @param {Options} options - 参数对象
810 | *
811 | * @param {String} options.groupId - 群ID
812 | * @param {(result)=>void} [options.success] - 成功回调
813 | * @param {(error)=>void} [options.fail] - 失败回调
814 | *
815 | * @example
816 | * getGroup({
817 | groupId: "",
818 | success: (result) => {},
819 | fail: (error) => {}
820 | });
821 | */
822 | getGroup(options : {
823 | groupId : string,
824 | success ?: (result : any) => void,
825 | fail ?: (error : any) => void
826 | }) : void;
827 |
828 | /**
829 | *
830 | * 转让群主
831 | *
832 | * 仅群主可操作
833 | *
834 | * @param {Options} options - 参数对象
835 | *
836 | * @param {String} [options.groupId] - 群ID
837 | * @param {String} [options.userId] - 转让用户ID
838 | * @param {(result)=>void} [options.success] - 成功回调
839 | * @param {(error)=>void} [options.fail] - 失败回调
840 | *
841 | * @example
842 | * transferLeader({
843 | groupId: "",
844 | userId: "",
845 | success: (result) => {},
846 | fail: (error) => {}
847 | });
848 | */
849 | transferLeader(options : {
850 | groupId : string,
851 | userId : string,
852 | success ?: (result : any) => void,
853 | fail ?: (error : any) => void
854 | }) : void;
855 |
856 | /**
857 | *
858 | * 获取我的群组列表
859 | *
860 | * @param {Options} options - 参数对象
861 | *
862 | * @param {(result)=>void} [options.success] - 成功回调
863 | * @param {(error)=>void} [options.fail] - 失败回调
864 | *
865 | * @example
866 | * getGroupList({
867 | success: (result) => {},
868 | fail: (error) => {}
869 | });
870 | */
871 | getGroupList(options : {
872 | success ?: (result : any) => void,
873 | fail ?: (error : any) => void
874 | }) : void;
875 |
876 | /**
877 | *
878 | * 用户申请入群
879 | *
880 | * IM内用户均可调用此接口申请进入传入的群组ID的群,根据群申请处理方式不同,可能直接进入,也可能等待审核
881 | *
882 | * @param {Options} options - 参数对象
883 | *
884 | * @param {String} options.groupId - 群ID
885 | * @param {(result)=>void} [options.success] - 成功回调
886 | * @param {(error)=>void} [options.fail] - 失败回调
887 | *
888 | * @example
889 | * joinGroup({
890 | groupId: "",
891 | success: (result) => {},
892 | fail: (error) => {}
893 | });
894 | */
895 | joinGroup(options : {
896 | groupId : string,
897 | success ?: (result : any) => void,
898 | fail ?: (error : any) => void
899 | }) : void;
900 |
901 | /**
902 | *
903 | * 退出群组
904 | *
905 | * @param {Options} options - 参数对象
906 | *
907 | * @param {String} options.groupId - 群ID
908 | * @param {(result)=>void} [options.success] - 成功回调
909 | * @param {(error)=>void} [options.fail] - 失败回调
910 | *
911 | * @example
912 | * leaveGroup({
913 | groupId: "",
914 | success: (result) => {},
915 | fail: (error) => {}
916 | });
917 | */
918 | leaveGroup(options : {
919 | groupId : string,
920 | success ?: (result : any) => void,
921 | fail ?: (error : any) => void
922 | }) : void;
923 |
924 | /**
925 | *
926 | * 添加群成员
927 | *
928 | * 不限权限,IM内用户均可调用此接口,但根据群申请处理方式不同,可能直接进入,也可能等待审核
929 | *
930 | * @param {Options} options - 参数对象
931 | *
932 | * @param {String} options.groupId - 群ID
933 | * @param {Array} options.members - 用户ID列表
934 | * @param {(result)=>void} [options.success] - 成功回调
935 | * @param {(error)=>void} [options.fail] - 失败回调
936 | *
937 | * @example
938 | * addGroupUsers({
939 | groupId: "",
940 | members: ["user1", "user2"],
941 | success: (result) => {},
942 | fail: (error) => {}
943 | });
944 | */
945 | addGroupUsers(options : {
946 | groupId : string,
947 | members : Array,
948 | success ?: (result : any) => void,
949 | fail ?: (error : any) => void
950 | }) : void;
951 |
952 | /**
953 | *
954 | * 移除群成员
955 | *
956 | * 仅群主可使用此接口
957 | *
958 | * @param {Object} options - 参数对象
959 | *
960 | * @param {String} options.groupId - 群ID
961 | * @param {Array} options.members - 用户ID列表
962 | * @param {(result)=>void} [options.success] - 成功回调
963 | * @param {(error)=>void} [options.fail] - 失败回调
964 | *
965 | * @example
966 | * removeGroupUsers({
967 | groupId: "",
968 | members: ["user1", "user2"],
969 | success: (result) => {},
970 | fail: (error) => {}
971 | });
972 | */
973 | removeGroupUsers(options : {
974 | groupId : string,
975 | members : Array,
976 | success ?: (result : any) => void,
977 | fail ?: (error : any) => void
978 | }) : void;
979 |
980 | /**
981 | *
982 | * 设置群管理员
983 | *
984 | * 仅群主可操作此接口
985 | *
986 | * @param {Options} options - 参数对象
987 | *
988 | * @param {String} options.groupId - 群ID
989 | * @param {String} options.userId - 要设置的用户ID
990 | * @param {Number} options.isAdmin - 是否设置管理员,0=取消,1=设置
991 | * @param {(result)=>void} [options.success] - 成功回调
992 | * @param {(error)=>void} [options.fail] - 失败回调
993 | *
994 | * @example
995 | * setAdminstrator({
996 | groupId: "",
997 | userId: "",
998 | isAdmin: 1,
999 | success: (result) => {},
1000 | fail: (error) => {}
1001 | });
1002 | */
1003 | setAdminstrator(options : {
1004 | groupId : string,
1005 | userId : string,
1006 | isAdmin : number,
1007 | success ?: (result : any) => void,
1008 | fail ?: (error : any) => void
1009 | }) : void;
1010 |
1011 | /**
1012 | *
1013 | * 禁言群成员
1014 | *
1015 | * 群组中群主或管理员可调用此接口禁言群成员,每次设置的分钟数均从操作时间开始算起,设置0则取消禁言
1016 | *
1017 | * @param {Options} options - 参数对象
1018 | *
1019 | * @param {String} options.groupId - 群ID
1020 | * @param {String} options.userId - 禁言用户ID
1021 | * @param {Number} options.time - 禁言分钟数
1022 | * @param {(result)=>void} [options.success] - 成功回调
1023 | * @param {(error)=>void} [options.fail] - 失败回调
1024 | *
1025 | * @example
1026 | * setMute({
1027 | groupId: "group_1",
1028 | userId: "user1",
1029 | time: 10,
1030 | success: (result) => {},
1031 | fail: (error) => {}
1032 | });
1033 | */
1034 | setMute(options : {
1035 | groupId : string,
1036 | userId : string,
1037 | time : number,
1038 | success ?: (result : any) => void,
1039 | fail ?: (error : any) => void
1040 | }) : void;
1041 |
1042 | /**
1043 | *
1044 | * 获取群组用户入群申请列表
1045 | *
1046 | * 群主或管理员调用此接口可获取名下所有群组入群申请列表
1047 | *
1048 | * @param {Options} options - 参数对象
1049 | *
1050 | * @param {(result)=>void} [options.success] - 成功回调
1051 | * @param {(error)=>void} [options.fail] - 失败回调
1052 | *
1053 | * @example
1054 | * getGroupApplyList({
1055 | success: (result) => {},
1056 | fail: (error) => {}
1057 | });
1058 | */
1059 | getGroupApplyList(options : {
1060 | success ?: (result : any) => void,
1061 | fail ?: (error : any) => void
1062 | }) : void;
1063 |
1064 | /**
1065 | *
1066 | * 处理群组用户入群申请
1067 | *
1068 | * 申请记录所在的群组中群主或管理员可调用此接口处理申请
1069 | *
1070 | * @param {Options} options - 参数对象
1071 | *
1072 | * @param {Number} options.id - 申请记录的ID
1073 | * @param {Number} options.status - 处理结果 YeIMUniSDKDefines.GROUP.APPLYSTATU
1074 | * @param {(result)=>void} [options.success] - 成功回调
1075 | * @param {(error)=>void} [options.fail] - 失败回调
1076 | *
1077 | * @example
1078 | * handleApply({
1079 | id: 5,
1080 | status: YeIMUniSDKDefines.GROUP.APPLYSTATUS.AGREE,
1081 | success: (result) => {},
1082 | fail: (error) => {}
1083 | });
1084 | */
1085 | handleApply(options : {
1086 | id : number,
1087 | status : number
1088 | success ?: (result : any) => void,
1089 | fail ?: (error : any) => void
1090 | }) : void;
1091 |
1092 | /**
1093 | *
1094 | * 获取群成员列表
1095 | *
1096 | * @param {Options} options - 参数对象
1097 | *
1098 | * @param {String} options.groupId - 群ID
1099 | * @param {(result)=>void} [options.success] - 成功回调
1100 | * @param {(error)=>void} [options.fail] - 失败回调
1101 | *
1102 | * @example
1103 | * getGroupUserList({
1104 | groupId: "group_1",
1105 | success: (result) => {},
1106 | fail: (error) => {}
1107 | });
1108 | */
1109 | getGroupUserList(options : {
1110 | groupId : string,
1111 | success ?: (result : any) => void,
1112 | fail ?: (error : any) => void
1113 | }) : void;
1114 |
1115 | /**
1116 | *
1117 | * 从云端获取好友列表
1118 | *
1119 | * @param {Options} options - 参数对象
1120 | *
1121 | * @param {Boolean} options.cloud - 是否从云端拉取
1122 | * @param {Number} options.profile - 资料类型,0=简略资料,1=详细资料 (云端拉取有效)
1123 | * @param {Number} options.page - 页码
1124 | * @param {Number} options.limit - 每页数量
1125 | *
1126 | * @param {(result)=>{}} [options.success] - 成功回调
1127 | * @param {(error)=>{}} [options.fail] - 失败回调
1128 | */
1129 | getFriendList(options : {
1130 | cloud ?: boolean,
1131 | profile ?: number,
1132 | page ?: number,
1133 | limit ?: number,
1134 | success ?: (result : any) => void,
1135 | fail ?: (error : any) => void
1136 | }) : void;
1137 |
1138 | /**
1139 | *
1140 | * 从云端获取好友申请列表
1141 | *
1142 | * @param {Options} options - 参数对象
1143 | *
1144 | * @param {Boolean} options.cloud - 是否从云端拉取
1145 | * @param {Number} options.type - 类型,0=发给我申请,1=我发出去的申请 (云端拉取有效)
1146 | * @param {Number} options.page - 页码
1147 | * @param {Number} options.limit - 每页数量
1148 | *
1149 | * @param {(result)=>{}} [options.success] - 成功回调
1150 | * @param {(error)=>{}} [options.fail] - 失败回调
1151 | */
1152 | getFriendApplyList(options : {
1153 | cloud ?: boolean,
1154 | type ?: number,
1155 | page ?: number,
1156 | limit ?: number,
1157 | success ?: (result : any) => void,
1158 | fail ?: (error : any) => void
1159 | }) : void;
1160 |
1161 | /**
1162 | *
1163 | * 将全部好友申请设置为已读状态
1164 | *
1165 | * @param {Options} options - 参数对象
1166 | *
1167 | * @param {(result)=>{}} [options.success] - 成功回调
1168 | * @param {(error)=>{}} [options.fail] - 失败回调
1169 | */
1170 | setApplyListRead(options : {
1171 | success ?: (result : any) => void,
1172 | fail ?: (error : any) => void
1173 | }) : void;
1174 |
1175 | /**
1176 | *
1177 | * 添加好友
1178 | *
1179 | * @param {Options} options - 参数对象
1180 | *
1181 | * @param {String} options.userId - 用户ID
1182 | * @param {String} options.remark - 好友备注
1183 | * @param {String} options.extraMessage - 附言
1184 | *
1185 | * @param {(result)=>{}} [options.success] - 成功回调
1186 | * @param {(error)=>{}} [options.fail] - 失败回调
1187 | */
1188 | addFriend(options : {
1189 | userId : string,
1190 | remark ?: string,
1191 | extraMessage ?: string,
1192 | success ?: (result : any) => void,
1193 | fail ?: (error : any) => void
1194 | }) : void;
1195 |
1196 | /**
1197 | *
1198 | * 删除好友
1199 | *
1200 | * @param {Options} options - 参数对象
1201 | *
1202 | * @param {Array} options.members - 好友ID列表
1203 | *
1204 | * @param {(result)=>{}} [options.success] - 成功回调
1205 | * @param {(error)=>{}} [options.fail] - 失败回调
1206 | */
1207 | deleteFriend(options : {
1208 | members : Array,
1209 | success ?: (result : any) => void,
1210 | fail ?: (error : any) => void
1211 | }) : void;
1212 |
1213 | /**
1214 | *
1215 | * 更新好友资料
1216 | *
1217 | * @param {Options} options - 参数对象
1218 | *
1219 | * @param {String} options.userId - 好友ID
1220 | * @param {String} options.remark - 好友备注
1221 | * @param {String} options.extend - 自定义扩展字段
1222 | *
1223 | * @param {(result)=>{}} [options.success] - 成功回调
1224 | * @param {(error)=>{}} [options.fail] - 失败回调
1225 | */
1226 | updateFriend(options : {
1227 | userId : string,
1228 | remark ?: string,
1229 | extend ?: string,
1230 | success ?: (result : any) => void,
1231 | fail ?: (error : any) => void
1232 | }) : void;
1233 |
1234 | /**
1235 | *
1236 | * 同意好友申请
1237 | *
1238 | * @param {Options} options - 参数对象
1239 | *
1240 | * @param {Number} options.id - 申请ID
1241 | * @param {String} options.remark - 备注
1242 | *
1243 | * @param {(result)=>{}} [options.success] - 成功回调
1244 | * @param {(error)=>{}} [options.fail] - 失败回调
1245 | */
1246 | acceptApply(options : {
1247 | id : number,
1248 | remark ?: string,
1249 | success ?: (result : any) => void,
1250 | fail ?: (error : any) => void
1251 | }) : void;
1252 |
1253 | /**
1254 | *
1255 | * 拒绝好友申请
1256 | *
1257 | * @param {Options} options - 参数对象
1258 | *
1259 | * @param {Number} options.id - 申请ID
1260 | *
1261 | * @param {(result)=>{}} [options.success] - 成功回调
1262 | * @param {(error)=>{}} [options.fail] - 失败回调
1263 | */
1264 | refuseApply(options : {
1265 | id : number,
1266 | success ?: (result : any) => void,
1267 | fail ?: (error : any) => void
1268 | }) : void;
1269 |
1270 | /**
1271 | * 断开连接,此操作不会重连
1272 | */
1273 | disConnect() : void;
1274 |
1275 | /**
1276 | * 获取当前连接状态
1277 | *
1278 | * 0:连接中 1:连接已打开 2:连接关闭中 3:连接已关闭
1279 | * @returns {number}
1280 | */
1281 | readyState() : number;
1282 |
1283 | /**
1284 | * 设置APP在前台
1285 | */
1286 | intoApp() : void;
1287 |
1288 | /**
1289 | * 设置APP已进入后台
1290 | */
1291 | leaveApp() : void;
1292 |
1293 | }
1294 |
1295 | interface Message {
1296 |
1297 | }
1298 |
1299 | interface Conversation {
1300 |
1301 | }
1302 |
1303 | /**
1304 | * YeIMUniSDK预定义常量
1305 | */
1306 | // @ts-ignore
1307 | declare const YeIMUniSDKDefines = {
1308 | /**
1309 | * 事件类型
1310 | */
1311 | EVENT: {
1312 | /**
1313 | * 网络状态变化
1314 | */
1315 | NET_CHANGED,
1316 | /**
1317 | * 会话列表变化
1318 | */
1319 | CONVERSATION_LIST_CHANGED,
1320 | /**
1321 | * 收到消息
1322 | */
1323 | MESSAGE_RECEIVED,
1324 | /**
1325 | * 撤回消息
1326 | */
1327 | MESSAGE_REVOKED,
1328 | /**
1329 | * 私聊会话已读回执
1330 | */
1331 | PRIVATE_READ_RECEIPT,
1332 | /**
1333 | * 用户被踢下线
1334 | */
1335 | KICKED_OUT
1336 | },
1337 | /**
1338 | * 会话类型
1339 | */
1340 | CONVERSATION_TYPE: {
1341 | /**
1342 | * 私聊
1343 | */
1344 | PRIVATE,
1345 | /**
1346 | * 群聊
1347 | */
1348 | GROUP
1349 | },
1350 | /**
1351 | * 消息类型
1352 | */
1353 | MESSAGE_TYPE: {
1354 | /**
1355 | * 文本消息
1356 | */
1357 | TEXT,
1358 | /**
1359 | * 文本 @ 消息
1360 | */
1361 | TEXT_AT,
1362 | /**
1363 | * 图片消息
1364 | */
1365 | IMAGE,
1366 | /**
1367 | * 语音消息
1368 | */
1369 | AUDIO,
1370 | /**
1371 | * 小视频消息
1372 | */
1373 | VIDEO,
1374 | /**
1375 | * 位置消息
1376 | */
1377 | LOCATION,
1378 | /**
1379 | * 自定义消息
1380 | */
1381 | CUSTOM,
1382 | /**
1383 | * 合并消息
1384 | */
1385 | MERGER,
1386 | /**
1387 | * 转发消息
1388 | */
1389 | FORWARD,
1390 | /**
1391 | * 群聊系统通知
1392 | */
1393 | GROUP_SYS_NOTICE
1394 | },
1395 | /**
1396 | * 用户相关常量
1397 | */
1398 | USER: {
1399 | /**
1400 | * 加好友验证方式
1401 | */
1402 | ADDFRIEND: {
1403 | /**
1404 | * 允许任何人添加自己为好友
1405 | */
1406 | ALLOW,
1407 | /**
1408 | * 需要经过自己确认才能添加自己为好友
1409 | */
1410 | CONFIRM,
1411 | /**
1412 | * 拒绝加好友
1413 | */
1414 | DENY
1415 | }
1416 | },
1417 | /**
1418 | * 群组相关常量
1419 | */
1420 | GROUP: {
1421 | /**
1422 | * 群申请处理方式
1423 | */
1424 | JOINMODE: {
1425 | /**
1426 | * 自有加入,不需要申请和审核,不需要被邀请人允许。
1427 | */
1428 | FREE,
1429 | /**
1430 | * 验证加入,需要申请,以及群主或管理员的同意才能入群
1431 | */
1432 | CHECK,
1433 | /**
1434 | * 禁止加入
1435 | */
1436 | FORBIDDEN
1437 | },
1438 | /**
1439 | * 入群申请处理结果
1440 | */
1441 | APPLYSTATUS: {
1442 | /**
1443 | * 待处理
1444 | */
1445 | PENDING,
1446 | /**
1447 | * 同意
1448 | */
1449 | AGREE,
1450 | /**
1451 | * 拒绝
1452 | */
1453 | REFUSE
1454 | }
1455 | },
1456 | }
1457 | }
--------------------------------------------------------------------------------