index.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. <template>
  2. <div ref="manageRef" class="manage">
  3. <header
  4. v-if="!isUniFrameWork || currentTab === 'admin'"
  5. class="manage-header"
  6. >
  7. <div @click="back">
  8. <Icon :file="backSVG" />
  9. </div>
  10. <div class="manage-header-content">
  11. {{ TUITranslateService.t(`TUIGroup.${TabName}`) }}
  12. </div>
  13. </header>
  14. <main
  15. v-if="!currentTab || (isUniFrameWork && currentTab != 'admin')"
  16. class="main"
  17. >
  18. <ManageName
  19. class="space-top"
  20. :isAuthor="isAuthor"
  21. :data="currentGroup"
  22. @update="updateProfile"
  23. />
  24. <div class="user-info space-top">
  25. <header class="user-info-header" @click="setCurrentTab('member')">
  26. <label class="user-info-header-left">
  27. {{ TUITranslateService.t(`TUIGroup.群成员`) }}
  28. </label>
  29. <div class="user-info-header-right">
  30. <span class="span">
  31. {{ currentGroup.memberCount || groupMemberList.length }}
  32. {{ TUITranslateService.t(`TUIGroup.人`) }}
  33. </span>
  34. <Icon :file="rightIcon" />
  35. </div>
  36. </header>
  37. <ol class="user-info-list">
  38. <dl
  39. v-for="(item, index) in groupMemberList.slice(0, showUserNum)"
  40. :key="index"
  41. class="user-info-list-item"
  42. >
  43. <dt
  44. class="user-info-list-item-main"
  45. @click="handleMemberProfileShow(item)"
  46. >
  47. <img
  48. class="avatar"
  49. :src="
  50. item.avatar ||
  51. 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'
  52. "
  53. onerror="this.onerror=null;this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
  54. />
  55. </dt>
  56. <dd class="user-info-list-item-info">
  57. {{ item.nick || item.userID }}
  58. </dd>
  59. </dl>
  60. <dl v-if="isShowAddMember" class="user-info-list-item">
  61. <dt class="avatar" @click="toggleMask('add')">+</dt>
  62. </dl>
  63. <dl v-if="currentSelfRole === 'Owner'" class="user-info-list-item">
  64. <dt class="avatar" @click="toggleMask('remove')">-</dt>
  65. </dl>
  66. </ol>
  67. </div>
  68. <ul class="content list space-top" @click="editLableName = ''">
  69. <li class="list-item" @click="setCurrentTab('notification')">
  70. <aside class="aside">
  71. <label class="label">{{
  72. TUITranslateService.t(`TUIGroup.群公告`)
  73. }}</label>
  74. <article class="article">
  75. {{ currentGroup.notification }}
  76. </article>
  77. </aside>
  78. <Icon :file="rightIcon" class="end" />
  79. </li>
  80. <li
  81. v-if="isAdmin && isSetMuteTime"
  82. class="list-item"
  83. @click="setCurrentTab('admin')"
  84. >
  85. <label class="label">{{
  86. TUITranslateService.t(`TUIGroup.群管理`)
  87. }}</label>
  88. <Icon :file="rightIcon" />
  89. </li>
  90. <!-- <li class="list-item">
  91. <label class="label">{{ TUITranslateService.t(`TUIGroup.群ID`) }}</label>
  92. <div class="groupID">
  93. <span class="span">{{ currentGroupID }}</span>
  94. </div>
  95. </li> -->
  96. <li class="list-item">
  97. <label class="label">{{
  98. TUITranslateService.t(`TUIGroup.群头像`)
  99. }}</label>
  100. <img
  101. class="avatar"
  102. :src="
  103. currentGroup.avatar ||
  104. 'https://web.sdk.qcloud.com/im/demo/TUIkit/web/img/constomer.svg'
  105. "
  106. onerror="this.onerror=null;this.src='https://web.sdk.qcloud.com/im/demo/TUIkit/web/img/constomer.svg'"
  107. />
  108. </li>
  109. <li class="list-item">
  110. <label class="label">{{
  111. TUITranslateService.t(`TUIGroup.群类型`)
  112. }}</label>
  113. <span class="span">{{
  114. TUITranslateService.t(`TUIGroup.${typeName[currentGroup.type]}`)
  115. }}</span>
  116. </li>
  117. <li class="list-item">
  118. <label class="label">{{
  119. TUITranslateService.t(`TUIGroup.加群方式`)
  120. }}</label>
  121. <span class="span">{{
  122. TUITranslateService.t(
  123. `TUIGroup.${typeName[currentGroup.joinOption]}`
  124. )
  125. }}</span>
  126. </li>
  127. </ul>
  128. <ul class="footer list space-top">
  129. <!-- <li
  130. v-if="currentSelfRole === 'Owner' && groupMemberList.length > 1"
  131. class="list-item"
  132. @click.stop="toggleMask('changeOwner')"
  133. >
  134. {{ TUITranslateService.t(`TUIGroup.转让群组`) }}
  135. </li> -->
  136. <li
  137. v-if="canIDissmissGroup"
  138. class="list-item"
  139. @click.stop="dismissGroup(currentGroup)"
  140. >
  141. {{ TUITranslateService.t(`TUIGroup.解散群聊`) }}
  142. </li>
  143. <li v-else class="list-item" @click.stop="quitGroup(currentGroup)">
  144. {{ TUITranslateService.t(`TUIGroup.退出群组`) }}
  145. </li>
  146. </ul>
  147. </main>
  148. <ManageMember
  149. v-if="currentTab === 'member'"
  150. :self="currentGroup.selfInfo"
  151. :list="groupMemberList"
  152. :total="~~currentGroup.memberCount"
  153. :isShowDel="currentSelfRole === 'Owner' && canDelMember"
  154. @more="getMember('more')"
  155. @del="submit"
  156. @handleMemberProfileShow="handleMemberProfileShow"
  157. @close="setCurrentTab('')"
  158. />
  159. <ManageProfile
  160. v-if="currentTab === 'profile'"
  161. :userInfo="currentMember"
  162. @close="setCurrentTab('')"
  163. />
  164. <ManageNotification
  165. v-if="currentTab === 'notification'"
  166. :isAuthor="isAuthor"
  167. :data="currentGroup"
  168. @update="updateProfile"
  169. @close="setCurrentTab('')"
  170. />
  171. <ManageAdmin
  172. v-if="currentTab === 'admin'"
  173. v-show="isAdmin"
  174. :isSetMuteTime="isSetMuteTime"
  175. :member="member"
  176. :currentGroup="currentGroup"
  177. @addAdmin="toggleMask('addAdmin')"
  178. @removeAdmin="toggleMask('removeAdmin')"
  179. @setAllMuteTime="setAllMuteTime"
  180. @addMute="toggleMask('addMute')"
  181. @removeMute="toggleMask('removeMute')"
  182. @close="setCurrentTab('')"
  183. />
  184. <MaskLayer :show="mask" @update:show="(e) => (mask = e)">
  185. <Transfer
  186. :title="TUITranslateService.t(`TUIGroup.${transferTitle}`)"
  187. :list="transferList"
  188. :isSearch="isSearch"
  189. :isRadio="isRadio"
  190. :selectedList="selectedList"
  191. :isH5="!isPC"
  192. @submit="submit"
  193. @cancel="cancel"
  194. @search="handleSearchMember"
  195. />
  196. </MaskLayer>
  197. <Dialog
  198. class="deleted-dialog"
  199. :title="TUITranslateService.t(`TUIGroup.删除成员`)"
  200. :show="delDialogShow"
  201. :isH5="!isPC"
  202. :center="true"
  203. :isHeaderShow="isPC"
  204. @submit="handleManage(deletedUserList, 'remove')"
  205. @update:show="(e) => (delDialogShow = e)"
  206. >
  207. <p v-if="deletedUserList.length === 1" class="del-dialog-title">
  208. {{ TUITranslateService.t(`TUIGroup.确定从群聊中删除该成员?`) }}
  209. </p>
  210. <p v-if="deletedUserList.length > 1" class="del-dialog-title">
  211. {{ TUITranslateService.t(`TUIGroup.确定从群聊中删除所选成员?`) }}
  212. </p>
  213. </Dialog>
  214. </div>
  215. </template>
  216. <script lang="ts" setup>
  217. import * as MesApi from "../../../../api/message";
  218. import {
  219. ref,
  220. computed,
  221. watchEffect,
  222. onMounted,
  223. nextTick,
  224. } from "../../../adapter-vue";
  225. import TUIChatEngine, {
  226. TUITranslateService,
  227. TUIGroupService,
  228. TUIFriendService,
  229. TUIStore,
  230. StoreName,
  231. IGroupModel,
  232. TUIConversationService,
  233. IConversationModel,
  234. IGroupMember,
  235. } from "@tencentcloud/chat-uikit-engine";
  236. import { TUIGlobal, outsideClick } from "@tencentcloud/universal-api";
  237. import MaskLayer from "../../common/MaskLayer/index.vue";
  238. import Dialog from "../../common/Dialog/index.vue";
  239. import Transfer from "../../common/Transfer/index.vue";
  240. import ManageName from "./manage-name.vue";
  241. import ManageNotification from "./manage-notification.vue";
  242. import ManageMember from "./manage-member.vue";
  243. import ManageProfile from "./manage-profile.vue";
  244. import ManageAdmin from "./manage-admin.vue";
  245. import Icon from "../../common/Icon.vue";
  246. import backSVG from "../../../assets/icon/back.svg";
  247. import rightIcon from "../../../assets/icon/right-icon.svg";
  248. import { Toast, TOAST_TYPE } from "../../common/Toast/index";
  249. import { isPC, isUniFrameWork } from "../../../utils/env";
  250. import Server from "../server";
  251. import { enableSampleTaskStatus } from "../../../utils/enableSampleTaskStatus";
  252. const TUIGroupServer = Server.getInstance();
  253. const TUIConstants = TUIGroupServer.constants;
  254. const props = defineProps({
  255. groupID: {
  256. type: String,
  257. default: "",
  258. },
  259. groupCurrentTab: {
  260. type: String,
  261. default: "",
  262. },
  263. });
  264. const manageRef = ref<any>(undefined);
  265. const currentTab = ref("");
  266. const editLableName = ref("");
  267. const transferType = ref("");
  268. const mask = ref(false);
  269. const currentGroupID = ref("");
  270. const userInfo = ref({
  271. list: [] as Array<typeof IGroupMember>,
  272. });
  273. const currentMember = ref<typeof IGroupMember>({});
  274. const typeName = ref({
  275. [TUIChatEngine.TYPES.GRP_WORK]: "好友工作群",
  276. [TUIChatEngine.TYPES.GRP_PUBLIC]: "陌生人社交群",
  277. [TUIChatEngine.TYPES.GRP_MEETING]: "临时会议群",
  278. [TUIChatEngine.TYPES.GRP_AVCHATROOM]: "直播群",
  279. [TUIChatEngine.TYPES.GRP_COMMUNITY]: "社群",
  280. [TUIChatEngine.TYPES.JOIN_OPTIONS_FREE_ACCESS]: "自由加入",
  281. [TUIChatEngine.TYPES.JOIN_OPTIONS_NEED_PERMISSION]: "需要验证",
  282. [TUIChatEngine.TYPES.JOIN_OPTIONS_DISABLE_APPLY]: "禁止加群",
  283. });
  284. const member = ref({
  285. admin: [] as Array<typeof IGroupMember>,
  286. member: [] as Array<typeof IGroupMember>,
  287. muteMember: [] as Array<typeof IGroupMember>,
  288. });
  289. const transferList = ref<Array<typeof IGroupMember>>([]);
  290. const transferTitle = ref("");
  291. const isSearch = ref(false);
  292. const isRadio = ref(false);
  293. const selectedList = ref([]);
  294. const delDialogShow = ref(false);
  295. const groupMemberList = ref<Array<typeof IGroupMember>>([]);
  296. const deletedUserList = ref([]);
  297. const currentGroup = ref<IGroupModel>();
  298. const currentSelfRole = ref("");
  299. const groupIDValue = ref<string>("");
  300. onMounted(() => {
  301. nextTick(() => {
  302. if (manageRef.value) {
  303. outsideClick.listen({
  304. domRefs: manageRef.value,
  305. handler: handleCompleteManage,
  306. });
  307. }
  308. });
  309. });
  310. TUIStore.watch(StoreName.GRP, {
  311. currentGroup: (group: IGroupModel) => {
  312. if (group) {
  313. currentGroup.value = group;
  314. currentSelfRole.value = currentGroup.value?.selfInfo?.role;
  315. }
  316. },
  317. currentGroupMemberList: (memberList: Array<typeof IGroupMember>) => {
  318. groupMemberList.value = memberList;
  319. member.value = {
  320. admin: [],
  321. member: [],
  322. muteMember: [],
  323. };
  324. Array.from(memberList).map((item: any) => {
  325. switch (item?.role) {
  326. case TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN:
  327. member.value.admin.push(item);
  328. break;
  329. case TUIChatEngine.TYPES.GRP_MBR_ROLE_MEMBER:
  330. member.value.member.push(item);
  331. break;
  332. default:
  333. break;
  334. }
  335. return item;
  336. });
  337. const time: number = new Date().getTime();
  338. member.value.muteMember = Array.from(memberList).filter(
  339. (item: any) => item?.muteUntil * 1000 - time > 0
  340. );
  341. },
  342. });
  343. TUIStore.watch(StoreName.CONV, {
  344. currentConversation: (conversation: IConversationModel) => {
  345. groupIDValue.value = conversation?.groupProfile?.groupID;
  346. },
  347. });
  348. watchEffect(() => {
  349. const params = TUIGroupServer.getOnCallParams(
  350. TUIConstants.TUIGroup.SERVICE.METHOD.OPEN_GROUP_MANAGEMENT
  351. );
  352. currentGroupID.value = params.groupID || groupIDValue.value;
  353. currentTab.value = props.groupCurrentTab;
  354. });
  355. const TabName = computed(() => {
  356. let name = "";
  357. switch (currentTab.value) {
  358. case "notification":
  359. name = "群公告";
  360. break;
  361. case "member":
  362. name = "群成员";
  363. break;
  364. case "profile":
  365. name = "群成员";
  366. break;
  367. default:
  368. name = "群管理";
  369. break;
  370. }
  371. return name;
  372. });
  373. const isAuthor = computed(() => {
  374. // 判断是否是群主/管理员
  375. const userRole = currentGroup?.value?.selfInfo?.role;
  376. const isOwner = userRole === TUIChatEngine.TYPES.GRP_MBR_ROLE_OWNER;
  377. const isAdmin = userRole === TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN;
  378. return isOwner || isAdmin;
  379. });
  380. const isAdmin = computed(() => {
  381. const groupType = currentGroup?.value?.type;
  382. const userRole = currentGroup?.value?.selfInfo?.role;
  383. const isOwner = userRole === TUIChatEngine.TYPES.GRP_MBR_ROLE_OWNER;
  384. const isWork = groupType === TUIChatEngine.TYPES.GRP_WORK;
  385. const isAVChatRoom = groupType === TUIChatEngine.TYPES.GRP_AVCHATROOM;
  386. if (!isWork && !isAVChatRoom && isOwner) {
  387. return true;
  388. }
  389. return false;
  390. });
  391. const isSetMuteTime = computed(() => {
  392. const groupType = currentGroup?.value?.type;
  393. const isWork = groupType === TUIChatEngine.TYPES.GRP_WORK;
  394. if (isWork || !isAuthor.value) {
  395. return false;
  396. }
  397. return true;
  398. });
  399. const canDelMember = computed(() => {
  400. const groupType = currentGroup?.value?.type;
  401. const isAVChatRoom = groupType === TUIChatEngine.TYPES.GRP_AVCHATROOM;
  402. if (isAVChatRoom) {
  403. return false;
  404. }
  405. return true;
  406. });
  407. const updateProfile = async (newGroupProfile: any) => {
  408. const { key, value } = newGroupProfile;
  409. const options: any = {
  410. groupID: currentGroup.value.groupID,
  411. [key]: value,
  412. };
  413. let res = await MesApi.default.updateGroup(options);
  414. if (res.code == 200) {
  415. currentGroup.value = res.data.group;
  416. editLableName.value = "";
  417. } else {
  418. Toast({
  419. message: error?.message,
  420. type: TOAST_TYPE.ERROR,
  421. });
  422. }
  423. // TUIGroupService.updateGroupProfile(options)
  424. // .then((res: any) => {
  425. // currentGroup.value = res.data.group;
  426. // editLableName.value = "";
  427. // })
  428. // .catch((error: any) => {
  429. // Toast({
  430. // message: error?.message,
  431. // type: TOAST_TYPE.ERROR,
  432. // });
  433. // });
  434. };
  435. const setCurrentTab = (tabName: string) => {
  436. currentTab.value = tabName;
  437. editLableName.value = "";
  438. if (currentTab.value === "member") {
  439. transferType.value = "remove";
  440. }
  441. if (!currentTab.value) {
  442. transferType.value = "";
  443. }
  444. };
  445. const cancel = () => {
  446. toggleMask();
  447. };
  448. const toggleMask = async (type?: string) => {
  449. selectedList.value = [];
  450. switch (type) {
  451. case "add":
  452. isRadio.value = false;
  453. transferList.value = await friendList();
  454. transferTitle.value = "添加成员";
  455. break;
  456. case "remove":
  457. isRadio.value = false;
  458. transferList.value = groupMemberList.value.filter(
  459. (item: any) => item.userID !== currentGroup?.value?.selfInfo?.userID
  460. );
  461. transferTitle.value = "删除成员";
  462. break;
  463. case "addAdmin":
  464. isRadio.value = true;
  465. transferList.value = member.value.member;
  466. transferTitle.value = "新增管理员";
  467. break;
  468. case "removeAdmin":
  469. isRadio.value = true;
  470. transferList.value = member.value.admin;
  471. transferTitle.value = "移除管理员";
  472. break;
  473. case "changeOwner":
  474. isRadio.value = true;
  475. transferList.value = [...member.value.admin, ...member.value.member];
  476. transferTitle.value = "转让群组";
  477. break;
  478. case "addMute":
  479. isRadio.value = true;
  480. transferList.value = member.value.member;
  481. if (currentGroup.value.selfInfo.role === "Owner") {
  482. transferList.value = [...member.value.admin, ...member.value.member];
  483. }
  484. transferList.value = transferList?.value?.filter((item: any) => {
  485. return member?.value?.muteMember?.indexOf(item) < 0;
  486. });
  487. transferTitle.value = "新增禁言用户";
  488. break;
  489. case "removeMute":
  490. isRadio.value = true;
  491. transferList.value = member.value.muteMember;
  492. transferTitle.value = "移除禁言用户";
  493. break;
  494. default:
  495. break;
  496. }
  497. type && (transferType.value = type);
  498. mask.value = !mask.value;
  499. };
  500. const friendList = async () => {
  501. const imResponse = await TUIFriendService.getFriendList();
  502. const friendList = imResponse.data.map((item: any) => item?.profile);
  503. return friendList.filter(
  504. (item: any) =>
  505. !userInfo.value.list.some(
  506. (infoItem: any) => infoItem.userID === item.userID
  507. )
  508. );
  509. };
  510. const canIDissmissGroup = computed(() => {
  511. const userRole = currentGroup?.value?.selfInfo?.role;
  512. const groupType = currentGroup?.value?.type;
  513. return (
  514. userRole === TUIChatEngine.TYPES.GRP_MBR_ROLE_OWNER &&
  515. groupType !== TUIChatEngine.TYPES.GRP_WORK
  516. );
  517. });
  518. const isShowAddMember = computed(() => {
  519. const groupType = currentGroup?.value?.type;
  520. return groupType === TUIChatEngine.TYPES.GRP_WORK;
  521. });
  522. const showUserNum = computed(() => {
  523. let num = 3;
  524. if (!isShowAddMember.value) {
  525. num += 1;
  526. }
  527. if (currentGroup?.value?.selfInfo?.role !== "Owner") {
  528. num += 1;
  529. }
  530. return num;
  531. });
  532. const getMember = async (type?: string) => {
  533. const groupID = currentGroupID.value;
  534. const options = {
  535. groupID,
  536. count: 100,
  537. offset: type && type === "more" ? userInfo.value.list.length : 0,
  538. };
  539. await TUIGroupService.getGroupMemberList(options).then((res: any) => {
  540. if (type && type === "more") {
  541. userInfo.value.list = [...userInfo.value.list, ...res.data.memberList];
  542. } else {
  543. userInfo.value.list = res.data.memberList;
  544. }
  545. });
  546. };
  547. const handleMemberProfileShow = (user: any) => {
  548. currentMember.value = user;
  549. setCurrentTab("profile");
  550. };
  551. const submit = (userList: any) => {
  552. // 进行成员移除等等相关操作
  553. if (transferType.value === "remove") {
  554. deletedUserList.value = userList;
  555. delDialogShow.value = !delDialogShow.value;
  556. } else {
  557. handleManage(userList, transferType.value);
  558. }
  559. mask.value = false;
  560. };
  561. const dismissGroup = async (group: any) => {
  562. TUIGlobal.showModal({
  563. title: "提示",
  564. content: "是否确认解散该群聊",
  565. success: async (res: any) => {
  566. if (res.confirm) {
  567. // 调起客户端小程序设置界面,返回用户设置的操作结果。(重新让用户授权)
  568. let res = await MesApi.default.delGroupByIdDisband({
  569. id: group.groupID,
  570. });
  571. if (res.code == 200) {
  572. enableSampleTaskStatus("dismissGroup");
  573. Toast({
  574. message: TUITranslateService.t("TUIGroup.群组解散成功"),
  575. type: TOAST_TYPE.SUCCESS,
  576. });
  577. TUIConversationService.deleteConversation(`GROUP${group.groupID}`);
  578. clearGroupInfo();
  579. }
  580. } else if (res.cancel) {
  581. return Toast({
  582. message: TUITranslateService.t("component.已取消"),
  583. type: TOAST_TYPE.ERROR,
  584. });
  585. }
  586. },
  587. });
  588. // // 解散群组
  589. // await TUIGroupService.dismissGroup(group.groupID);
  590. // enableSampleTaskStatus("dismissGroup");
  591. // Toast({
  592. // message: TUITranslateService.t("TUIGroup.群组解散成功"),
  593. // type: TOAST_TYPE.SUCCESS,
  594. // });
  595. // clearGroupInfo();
  596. };
  597. function capitalize(str: string): string {
  598. if (!str) return "";
  599. return str.charAt(0).toUpperCase() + str.slice(1);
  600. }
  601. const clearGroupInfo = () => {
  602. if (isUniFrameWork) {
  603. TUIGlobal?.navigateTo({
  604. url: `/TUIKit-${capitalize(
  605. uni.getStorageSync("Identity")
  606. )}/components/TUIConversation/index`,
  607. });
  608. } else {
  609. handleCompleteManage();
  610. // 回到chat default 页
  611. TUIConversationService.switchConversation();
  612. }
  613. };
  614. const setAllMuteTime = (value: boolean) => {
  615. // 设置全体禁言时间
  616. updateProfile({ key: "muteAllMembers", value });
  617. if (value) {
  618. enableSampleTaskStatus("muteGroup");
  619. Toast({
  620. message: TUITranslateService.t("TUIGroup.禁言设置成功"),
  621. type: TOAST_TYPE.SUCCESS,
  622. });
  623. } else {
  624. Toast({
  625. message: TUITranslateService.t("TUIGroup.取消禁言成功"),
  626. type: TOAST_TYPE.SUCCESS,
  627. });
  628. }
  629. };
  630. const handleSearchMember = async (value: string) => {
  631. let imResponse: any = {};
  632. let imMemberResponse: any = {};
  633. const options: any = {
  634. groupID: currentGroupID.value,
  635. userIDList: [value],
  636. };
  637. switch (transferType.value) {
  638. case "add":
  639. try {
  640. imMemberResponse = await TUIGroupService.getGroupMemberProfile(options);
  641. transferList.value = transferList.value.filter(
  642. (item: any) => item.userID !== imResponse.data[0]?.userID
  643. );
  644. transferList.value = [...transferList.value, ...imResponse.data];
  645. if (imMemberResponse?.data?.memberList.length > 0) {
  646. transferList.value = transferList.value.map((item: any) => {
  647. if (item.userID === imMemberResponse?.data?.memberList[0].userID) {
  648. item.isDisabled = true;
  649. }
  650. return item;
  651. });
  652. }
  653. } catch (error: any) {
  654. const message = TUITranslateService.t("TUIGroup.该用户不存在");
  655. Toast({
  656. message,
  657. type: TOAST_TYPE.ERROR,
  658. });
  659. }
  660. break;
  661. case "remove":
  662. try {
  663. imResponse = await TUIGroupService.getGroupMemberProfile(options);
  664. if (imResponse.data.memberList.length === 0) {
  665. const message = TUITranslateService.t("TUIGroup.该用户不在群组内");
  666. Toast({
  667. message,
  668. type: TOAST_TYPE.ERROR,
  669. });
  670. }
  671. transferList.value = transferList.value.filter(
  672. (item: any) => item.userID !== imResponse?.data?.memberList[0]?.userID
  673. );
  674. if (imResponse?.data?.memberList.length) {
  675. transferList.value = [
  676. ...transferList.value,
  677. ...imResponse.data.memberList,
  678. ];
  679. }
  680. } catch (error: any) {
  681. const message = TUITranslateService.t("TUIGroup.该用户不存在");
  682. Toast({
  683. message,
  684. type: TOAST_TYPE.ERROR,
  685. });
  686. }
  687. break;
  688. default:
  689. break;
  690. }
  691. };
  692. const handleManage = (userList: any, type: any) => {
  693. const userIDList: any = [];
  694. userList.map((item: any) => {
  695. userIDList.push(item.userID);
  696. return item;
  697. });
  698. switch (type) {
  699. case "add":
  700. addMember(userIDList);
  701. break;
  702. case "remove":
  703. deleteGroupMember(userIDList);
  704. break;
  705. case "addAdmin":
  706. handleAdmin(userList[0]);
  707. break;
  708. case "removeAdmin":
  709. handleAdmin(userList[0]);
  710. break;
  711. case "changeOwner":
  712. changeOwner(userIDList[0]);
  713. break;
  714. case "addMute":
  715. setMemberMuteTime(userIDList[0], "add");
  716. break;
  717. case "removeMute":
  718. setMemberMuteTime(userIDList[0], "remove");
  719. break;
  720. default:
  721. break;
  722. }
  723. };
  724. const addMember = async (userIDList: any) => {
  725. const options: any = {
  726. groupID: currentGroupID.value,
  727. userIDList,
  728. };
  729. await TUIGroupService.addGroupMember(options);
  730. };
  731. const changeOwner = async (userID: any) => {
  732. const options: any = {
  733. groupID: currentGroupID.value,
  734. newOwnerID: userID,
  735. };
  736. const imResponse = await TUIGroupService.changeGroupOwner(options);
  737. currentGroup.value = {};
  738. currentGroup.value = imResponse.data.group;
  739. };
  740. const setMemberMuteTime = async (userID: string, type?: string) => {
  741. const options: any = {
  742. groupID: currentGroupID.value,
  743. userID,
  744. muteTime: type === "add" ? 60 * 60 * 24 * 30 : 0,
  745. };
  746. await TUIGroupService.setGroupMemberMuteTime(options);
  747. };
  748. const handleAdmin = async (user: any) => {
  749. let role = "";
  750. switch (user.role) {
  751. case TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN:
  752. role = TUIChatEngine.TYPES.GRP_MBR_ROLE_MEMBER;
  753. break;
  754. case TUIChatEngine.TYPES.GRP_MBR_ROLE_MEMBER:
  755. role = TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN;
  756. break;
  757. }
  758. const options: any = {
  759. groupID: currentGroupID.value,
  760. userID: user.userID,
  761. role,
  762. };
  763. await TUIGroupService.setGroupMemberRole(options);
  764. };
  765. const deleteGroupMember = async (userIDList: any) => {
  766. const options: any = {
  767. groupId: currentGroupID.value,
  768. memberlist: userIDList,
  769. reason: "",
  770. };
  771. let res = await MesApi.default.groupdelUse(options);
  772. if (res.code == 200) {
  773. uni.$u.toast("移除成功");
  774. clearGroupInfo();
  775. }
  776. // await TUIGroupService.deleteGroupMember(options);
  777. };
  778. const quitGroup = async (group: any) => {
  779. let userId = group.selfInfo.userID;
  780. let params = {
  781. memberlist: [userId],
  782. groupId: group.groupID,
  783. };
  784. TUIGlobal.showModal({
  785. title: "提示",
  786. content: "是否确认退出该群聊",
  787. success: async (res: any) => {
  788. if (res.confirm) {
  789. await MesApi.default.quitGroup(params);
  790. await TUIGroupService.quitGroup(group.groupID);
  791. clearGroupInfo();
  792. } else if (res.cancel) {
  793. return Toast({
  794. message: TUITranslateService.t("component.已取消"),
  795. type: TOAST_TYPE.ERROR,
  796. });
  797. }
  798. },
  799. });
  800. };
  801. const back = () => {
  802. if (currentTab.value) {
  803. setCurrentTab("");
  804. } else {
  805. handleCompleteManage();
  806. }
  807. };
  808. const handleCompleteManage = () => {
  809. TUIStore.update(StoreName.GRP, "isShowManageComponent", false);
  810. const callback = TUIGroupServer.getOnCallCallback(
  811. TUIConstants.TUIGroup.SERVICE.METHOD.OPEN_GROUP_MANAGEMENT
  812. );
  813. callback && callback();
  814. };
  815. </script>
  816. <style lang="scss" scoped src="./style/index.scss"></style>