index.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import TUIChatEngine, {
  2. TUIFriendService,
  3. TUIConversationService,
  4. TUIGroupService,
  5. TUIUserService,
  6. TUITranslateService,
  7. AddFriendParams,
  8. JoinGroupParams,
  9. } from '@tencentcloud/chat-uikit-engine';
  10. import { TUIGlobal } from '@tencentcloud/universal-api';
  11. import { Toast, TOAST_TYPE } from '../../common/Toast/index';
  12. // 解析 用户头像/群头像
  13. export const generateAvatar = (item: any): string => {
  14. return (
  15. item?.avatar
  16. || item?.profile?.avatar
  17. || (item?.groupID && 'https://web.sdk.qcloud.com/im/assets/images/Public.svg')
  18. || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'
  19. );
  20. };
  21. // 解析 用户名称/群名称
  22. export const generateName = (item: any): string => {
  23. return (
  24. item?.remark
  25. || item?.name
  26. || item?.profile?.nick
  27. || item?.nick
  28. || item?.groupID
  29. || item?.userID
  30. || ''
  31. );
  32. };
  33. // 解析 信息界面 用户名称/群名称
  34. export const generateContactInfoName = (item: any): string => {
  35. return (
  36. item?.name
  37. || item?.profile?.nick
  38. || item?.nick
  39. || item?.groupID
  40. || item?.userID
  41. || ''
  42. );
  43. };
  44. // 解析 contactInfo 模块 基础信息展示内容
  45. // 群信息展示: 群ID 群类型
  46. // 用户信息展示: 用户ID 个性签名
  47. export const generateContactInfoBasic = (
  48. contactInfo: any,
  49. ): Array<{ label: string; data: string }> => {
  50. const res = [
  51. {
  52. label: contactInfo?.groupID ? '群ID' : 'ID',
  53. data: contactInfo?.groupID || contactInfo?.userID || '',
  54. },
  55. ];
  56. if (!isApplicationType(contactInfo)) {
  57. res.push({
  58. label: contactInfo?.groupID ? '群类型' : '个性签名',
  59. data: contactInfo?.type || contactInfo?.profile?.selfSignature || '',
  60. });
  61. }
  62. return res;
  63. };
  64. // 判断是否为申请
  65. export const isApplicationType = (info: any) => {
  66. return (
  67. info?.type === TUIChatEngine?.TYPES?.SNS_APPLICATION_SENT_TO_ME
  68. || info?.type === TUIChatEngine?.TYPES?.SNS_APPLICATION_SENT_BY_ME
  69. );
  70. };
  71. // 好友相关
  72. // 判断是否为双向好友关系
  73. export const isFriend = (info: any): Promise<boolean> => {
  74. return new Promise((resolve, reject) => {
  75. if (info?.groupID || !info?.userID) {
  76. resolve(false);
  77. return;
  78. }
  79. if (info?.addTime) {
  80. resolve(true);
  81. return;
  82. }
  83. TUIFriendService.checkFriend({
  84. userIDList: [info?.userID],
  85. type: TUIChatEngine.TYPES.SNS_CHECK_TYPE_BOTH,
  86. })
  87. .then((res: any) => {
  88. switch (res?.data?.successUserIDList[0]?.relation) {
  89. // 无好友关系:A 的好友表中没有 B,B 的好友表中也没有 A
  90. case TUIChatEngine.TYPES.SNS_TYPE_NO_RELATION:
  91. resolve(false);
  92. break;
  93. // 单项好友:A 的好友表中有 B,但 B 的好友表中没有 A
  94. case TUIChatEngine.TYPES.SNS_TYPE_A_WITH_B:
  95. resolve(false);
  96. break;
  97. // 单项好友:A 的好友表中没有 B,但 B 的好友表中有 A
  98. case TUIChatEngine.TYPES.SNS_TYPE_B_WITH_A:
  99. resolve(false);
  100. break;
  101. // 双向好友关系
  102. case TUIChatEngine.TYPES.SNS_TYPE_BOTH_WAY:
  103. resolve(true);
  104. break;
  105. default:
  106. resolve(false);
  107. break;
  108. }
  109. })
  110. .catch((error: any) => {
  111. console.warn('checkFriend error', error);
  112. reject(error);
  113. });
  114. });
  115. };
  116. // 修改好友备注 / change friend‘s remark
  117. export const updateFriendRemark = (userID: string, remark: string) => {
  118. // eslint-disable-next-line no-control-regex
  119. if (remark?.replace(/[^\u0000-\u00ff]/g, 'aa')?.length > 96) {
  120. Toast({
  121. message: TUITranslateService.t('TUIContact.修改备注失败: 备注长度不得超过 96 字节'),
  122. type: TOAST_TYPE.ERROR,
  123. });
  124. return;
  125. }
  126. TUIFriendService.updateFriend({
  127. userID,
  128. remark,
  129. })
  130. .then(() => {
  131. Toast({
  132. message: TUITranslateService.t('TUIContact.修改备注成功'),
  133. type: TOAST_TYPE.SUCCESS,
  134. });
  135. })
  136. .catch((error: any) => {
  137. console.warn('update friend remark failed:', error);
  138. Toast({
  139. message: TUITranslateService.t('TUIContact.修改备注失败'),
  140. type: TOAST_TYPE.ERROR,
  141. });
  142. });
  143. };
  144. // 删除某个好友 / delete one friend
  145. export const deleteFriend = (userID: string) => {
  146. TUIFriendService.deleteFriend({
  147. userIDList: [userID],
  148. type: TUIChatEngine.TYPES.SNS_DELETE_TYPE_BOTH,
  149. })
  150. .then((res: any) => {
  151. const { successUserIDList } = res.data;
  152. if (successUserIDList[0].userID === userID) {
  153. Toast({
  154. message: TUITranslateService.t('TUIContact.删除好友成功'),
  155. type: TOAST_TYPE.SUCCESS,
  156. });
  157. } else {
  158. Toast({
  159. message: TUITranslateService.t('TUIContact.删除好友失败'),
  160. type: TOAST_TYPE.ERROR,
  161. });
  162. }
  163. })
  164. .catch((error: any) => {
  165. console.warn('delete friend failed:', error);
  166. Toast({
  167. message: TUITranslateService.t('TUIContact.删除好友失败'),
  168. type: TOAST_TYPE.ERROR,
  169. });
  170. });
  171. };
  172. // 添加好友 / add friend
  173. export const addFriend = (params: AddFriendParams) => {
  174. TUIFriendService.addFriend(params)
  175. .then(() => {
  176. Toast({
  177. message: TUITranslateService.t('TUIContact.申请已发送'),
  178. type: TOAST_TYPE.SUCCESS,
  179. });
  180. })
  181. .catch((error: any) => {
  182. console.warn('delete friend failed:', error);
  183. Toast({
  184. message: TUITranslateService.t('TUIContact.申请发送失败'),
  185. type: TOAST_TYPE.ERROR,
  186. });
  187. });
  188. };
  189. // 进入会话 / enter conversation
  190. // todo:后续抽离为切换会话服务
  191. export const enterConversation = (item: any) => {
  192. const conversationID = item?.groupID
  193. ? `GROUP${item?.groupID}`
  194. : `C2C${item?.userID}`;
  195. TUIConversationService.switchConversation(conversationID).catch(
  196. (error: any) => {
  197. console.warn('switch conversation failed:', error);
  198. Toast({
  199. message: TUITranslateService.t('TUIContact.进入会话失败'),
  200. type: TOAST_TYPE.ERROR,
  201. });
  202. },
  203. );
  204. };
  205. // 同意好友申请 / accept friend application
  206. export const acceptFriendApplication = (userID: string) => {
  207. TUIFriendService.acceptFriendApplication({
  208. userID,
  209. type: TUIChatEngine.TYPES.SNS_APPLICATION_AGREE_AND_ADD,
  210. })
  211. .then(() => {
  212. Toast({
  213. message: TUITranslateService.t('TUIContact.添加好友成功'),
  214. type: TOAST_TYPE.SUCCESS,
  215. });
  216. })
  217. .catch((error: any) => {
  218. console.warn('accept friend application failed:', error);
  219. Toast({
  220. message: TUITranslateService.t('TUIContact.同意好友申请失败'),
  221. type: TOAST_TYPE.ERROR,
  222. });
  223. });
  224. };
  225. // 拒绝好友申请 / refuse friend application
  226. export const refuseFriendApplication = (userID: string) => {
  227. TUIFriendService.refuseFriendApplication(userID)
  228. .then(() => {
  229. Toast({
  230. message: TUITranslateService.t('TUIContact.拒绝成功'),
  231. type: TOAST_TYPE.SUCCESS,
  232. });
  233. })
  234. .catch((error: any) => {
  235. console.warn('accept friend application failed:', error);
  236. Toast({
  237. message: TUITranslateService.t('TUIContact.拒绝好友申请失败'),
  238. type: TOAST_TYPE.ERROR,
  239. });
  240. });
  241. };
  242. // 群组相关
  243. // todo: 后续抽离为 TUIGroup/server 中以 extension 形式提供
  244. // 解散群聊 / dismiss group
  245. export const dismissGroup = (groupID: string) => {
  246. TUIGroupService.dismissGroup(groupID)
  247. .then(() => {
  248. Toast({
  249. message: TUITranslateService.t('TUIContact.解散群聊成功'),
  250. type: TOAST_TYPE.SUCCESS,
  251. });
  252. // 解散群聊后特殊情况:
  253. // 如果当前为 TUIContact 搜索状态,即 currentContactSearchingStatus === true
  254. // 且当前打开的为 搜索结果 中的 群聊信息界面
  255. // 需要更新搜索结果相关更新数据
  256. TUIGlobal?.updateContactSearch && TUIGlobal?.updateContactSearch();
  257. })
  258. .catch((error: any) => {
  259. console.warn('dismiss group failed:', error);
  260. Toast({
  261. message: TUITranslateService.t('TUIContact.解散群聊失败'),
  262. type: TOAST_TYPE.ERROR,
  263. });
  264. });
  265. };
  266. // 退出群聊 / quit group
  267. export const quitGroup = (groupID: string) => {
  268. TUIGroupService.quitGroup(groupID)
  269. .then(() => {
  270. Toast({
  271. message: TUITranslateService.t('TUIContact.退出群组成功'),
  272. type: TOAST_TYPE.SUCCESS,
  273. });
  274. })
  275. .catch((error: any) => {
  276. console.warn('quit group failed:', error);
  277. Toast({
  278. message: TUITranslateService.t('TUIContact.退出群组失败'),
  279. type: TOAST_TYPE.ERROR,
  280. });
  281. });
  282. };
  283. // 申请加入群聊 / join group
  284. export const joinGroup = (groupID: string, applyMessage?: string) => {
  285. TUIGroupService.joinGroup({
  286. groupID,
  287. applyMessage,
  288. } as JoinGroupParams)
  289. .then((imResponse: { data: { status?: string } }) => {
  290. switch (imResponse?.data?.status) {
  291. case TUIChatEngine.TYPES.JOIN_STATUS_WAIT_APPROVAL: // 等待管理员同意
  292. Toast({
  293. message: TUITranslateService.t('TUIContact.等待管理员同意'),
  294. type: TOAST_TYPE.SUCCESS,
  295. });
  296. break;
  297. case TUIChatEngine.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
  298. // todo: 切换到群聊所在chat界面
  299. Toast({
  300. message: TUITranslateService.t('TUIContact.加群成功'),
  301. type: TOAST_TYPE.SUCCESS,
  302. });
  303. break;
  304. case TUIChatEngine.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
  305. Toast({
  306. message: TUITranslateService.t('TUIContact.您已是群成员'),
  307. type: TOAST_TYPE.SUCCESS,
  308. });
  309. break;
  310. default:
  311. break;
  312. }
  313. })
  314. .catch((error: any) => {
  315. console.warn('join group failed:', error);
  316. Toast({
  317. message: '申请入群失败',
  318. type: TOAST_TYPE.ERROR,
  319. });
  320. });
  321. };
  322. // 以下为黑名单相关逻辑
  323. // 加入黑名单
  324. export const addToBlacklist = (userID: string, successCallBack?: () => void) => {
  325. TUIUserService.addToBlacklist({
  326. userIDList: [userID],
  327. })
  328. .then(() => {
  329. successCallBack && successCallBack();
  330. })
  331. .catch((error: any) => {
  332. console.warn('add to blacklist failed:', error);
  333. Toast({
  334. message: TUITranslateService.t('TUIContact.加入黑名单失败'),
  335. type: TOAST_TYPE.ERROR,
  336. });
  337. });
  338. };
  339. // 移除黑名单
  340. export const removeFromBlacklist = (
  341. userID: string,
  342. successCallBack?: () => void,
  343. ) => {
  344. TUIUserService.removeFromBlacklist({
  345. userIDList: [userID],
  346. })
  347. .then(() => {
  348. successCallBack && successCallBack();
  349. })
  350. .catch((error: any) => {
  351. console.warn('remove from blacklist failed:', error);
  352. Toast({
  353. message: TUITranslateService.t('TUIContact.移除黑名单失败'),
  354. type: TOAST_TYPE.ERROR,
  355. });
  356. });
  357. };