manage.vue 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. <template>
  2. <div>
  3. <i class="icon icon-chat-setting" v-if="platform == 'daya'" @click="toggleShow"></i>
  4. <div class="manage" :class="[isH5 ? 'manage-h5' : '']" v-if="show" ref="dialog">
  5. <header class="manage-header">
  6. <i class="icon icon-back" v-if="isH5 && !currentTab" @click="toggleShow"></i>
  7. <aside class="manage-header-left">
  8. <i class="icon icon-back" v-if="currentTab" @click="() =>{
  9. currentModel = 'not_mute'
  10. setTab('')
  11. }"></i>
  12. <main v-if="currentTab !== 'onlyMute'">
  13. <h1>{{ TabName }} <span v-if="currentTab === 'member'"> {{ groupDetail.memberNum || 0 }}{{ $t(`TUIChat.manage.人`) }} </span></h1>
  14. </main>
  15. </aside>
  16. <span>
  17. <i v-if="!isH5" class="icon icon-close" @click="toggleShow"></i>
  18. </span>
  19. </header>
  20. <main class="main" style="background-color: #f4f5f9; height: 100%" v-if="!currentTab">
  21. <ManageName class="space-top" :isAuth="isAuth" :isH5="isH5" :data="conversation.groupProfile" @update="updateProfile" style="background-color: #fff" />
  22. <!-- <div class="userInfo space-top" style="background-color: #fff">
  23. <header class="userInfo-header" @click="setTab('member')">
  24. <label>{{ $t(`TUIChat.manage.群成员`) }}</label>
  25. <p>
  26. <span> {{ groupDetail.memberNum || 0 }}{{ $t(`TUIChat.manage.人`) }} </span>
  27. <i class="icon icon-right"></i>
  28. </p>
  29. </header>
  30. <ol>
  31. <dl v-for="(item, index) in userInfo?.list?.slice(0, showUserNum)" :key="index">
  32. <dt>
  33. <img class="avatar" :src="item?.avatar || 'https://oss.dayaedu.com/news-info/07/1690787574969.png'" onerror="this.src='https://oss.dayaedu.com/news-info/07/1690787574969.png'" />
  34. </dt>
  35. <dd>{{ item?.nickname || item?.userID }}</dd>
  36. </dl>
  37. <dl v-if="currentUserDetail.groupRoleType === 'Owner'">
  38. <dt class="avatar" @click="toggleMask('add')">+</dt>
  39. </dl>
  40. </ol>
  41. </div> -->
  42. <ul class="content space-top" @click="editLableName = ''" style="background-color: #fff">
  43. <li @click.stop="setTab('notification')">
  44. <aside>
  45. <label>{{ $t(`TUIChat.manage.群公告`) }}</label>
  46. <article>{{ conversation.groupProfile.notification }}</article>
  47. </aside>
  48. <i class="icon icon-right end"></i>
  49. </li>
  50. <!-- <li v-if="isAdmin && isSetMuteTime" @click.stop="setTab('admin')">
  51. <label>{{ $t(`TUIChat.manage.群管理`) }}</label>
  52. <i class="icon icon-right"></i>
  53. </li>
  54. <li>
  55. <label>{{ $t(`TUIChat.manage.群ID`) }}</label>
  56. <div class="groupID">
  57. <span>{{ conversation.groupProfile.groupID }}</span>
  58. <i
  59. class="icon icon-msg-copy"
  60. @click="handleGroupIDCopy"
  61. :title="$t('TUIChat.复制')"
  62. ></i>
  63. </div>
  64. </li>
  65. <li>
  66. <label>{{ $t(`TUIChat.manage.群头像`) }}</label>
  67. <img
  68. class="avatar"
  69. :src="
  70. conversation?.groupProfile?.avatar ||
  71. 'https://oss.dayaedu.com/news-info/07/1690775328089.png'
  72. "
  73. onerror="this.src='https://oss.dayaedu.com/news-info/07/1690775328089.png'"
  74. />
  75. </li>
  76. <li>
  77. <label>{{ $t(`TUIChat.manage.群类型`) }}</label>
  78. <span>
  79. {{
  80. $t(`TUIChat.manage.${typeName[conversation.groupProfile.type]}`)
  81. }}
  82. </span>
  83. </li>
  84. <li>
  85. <label>{{ $t(`TUIChat.manage.加群方式`) }}</label>
  86. <span>
  87. {{
  88. $t(
  89. `TUIChat.manage.${
  90. typeName[conversation.groupProfile.joinOption]
  91. }`
  92. )
  93. }}
  94. </span>
  95. </li> -->
  96. </ul>
  97. <!-- <div v-if="currentUserDetail.groupRoleType === 'Owner'" class="admin-content space-top" style="background-color: #fff; padding-top: 12px">
  98. <aside>
  99. <label>学生禁言</label>
  100. </aside>
  101. <Slider :open="groupDetail.configJson.mute" @change="setAllMuteTime" />
  102. </div>
  103. <ul class="footer space-top">
  104. <li v-if="currentUserDetail.groupRoleType === 'Owner' && userInfo?.list.length > 1" @click.stop="toggleMask('changeOwner')">移交群主</li>
  105. <li v-if="currentUserDetail.groupRoleType === 'Owner'" @click.stop="dismiss(conversation.groupProfile)">解散群聊</li>
  106. <li v-else @click.stop="quit(conversation.groupProfile)">退出群组</li>
  107. </ul>-->
  108. </main>
  109. <ManageMember v-else-if="currentTab === 'member'" :self="conversation.groupProfile.selfInfo" :list="userInfo.list" :total="~~conversation.groupProfile.memberCount" @more="getMember('more')" @del="submit" @handleMemberProfileShow="handleMemberProfileShow" />
  110. <!-- :isShowDel="conversation.groupProfile.selfInfo.role === 'Owner'" -->
  111. <MemeberProfile v-else-if="currentTab === 'profile'" :userInfo="currentMember" />
  112. <ManageNotification ref="manageNotificationRef" v-else-if="currentTab === 'notification' || currentTab === 'notificationAdd' || currentTab === 'notificationUpdate'" :isAuth="isAuth" :data="conversation.groupProfile" @update="updateProfile" @changeStatus="onNotificationChangeStatus" />
  113. <ManageNotificationDetail ref="manageNotificationDetailRef" v-else-if="currentTab === 'notificationDetail' || currentTab === 'notificationAddDetail' || currentTab === 'notificationUpdateDetail'" :noticeId="noticeId" :isAuth="isAuth" :data="conversation.groupProfile" @changeStatus="onNotificationChangeStatus" />
  114. <main class="admin" v-else-if="currentTab === 'admin'">
  115. <div class="admin-list" v-if="isAdmin">
  116. <label>{{ $t(`TUIChat.manage.群管理员`) }}</label>
  117. <ol>
  118. <dl v-for="(item, index) in member.admin" :key="index">
  119. <dt>
  120. <img class="avatar" :src="item?.avatar || 'https://oss.dayaedu.com/news-info/07/1690787574969.png'" onerror="this.src='https://oss.dayaedu.com/news-info/07/1690787574969.png'" />
  121. </dt>
  122. <dd>{{ item?.nick || item?.userID }}</dd>
  123. </dl>
  124. <dl>
  125. <dt class="avatar" @click="toggleMask('addAdmin')">+</dt>
  126. </dl>
  127. <dl>
  128. <dt class="avatar" v-if="member.admin.length > 0" @click="toggleMask('removeAdmin')">-</dt>
  129. </dl>
  130. </ol>
  131. </div>
  132. <div class="admin-content space-top" v-if="isSetMuteTime">
  133. <aside>
  134. <label>{{ $t(`TUIChat.manage.学生禁言`) }}</label>
  135. <p>
  136. {{ $t(`TUIChat.manage.学生禁言开启后,只允许群主和管理员发言。`) }}
  137. </p>
  138. </aside>
  139. <Slider :open="conversation.groupProfile.muteAllMembers" @change="setAllMuteTime" />
  140. </div>
  141. <div class="admin-list last" v-if="isSetMuteTime">
  142. <label>{{ $t(`TUIChat.manage.单独禁言人员`) }}</label>
  143. <ol>
  144. <dl v-for="(item, index) in member.muteMember" :key="index">
  145. <dt>
  146. <img class="avatar" :src="item?.avatar || 'https://oss.dayaedu.com/news-info/07/1690787574969.png'" onerror="this.src='https://oss.dayaedu.com/news-info/07/1690787574969.png'" />
  147. </dt>
  148. <dd>{{ item?.nick || item?.userID }}</dd>
  149. </dl>
  150. <dl>
  151. <dt class="avatar" @click="toggleMask('addMute')">+</dt>
  152. </dl>
  153. <dl>
  154. <dt class="avatar" v-if="member.muteMember.length > 0" @click="toggleMask('removeMute')">-</dt>
  155. </dl>
  156. </ol>
  157. </div>
  158. </main>
  159. <MaskTUI :show="mask" @update:show="(e) => (mask = e)">
  160. <Transfer :title="$t(`TUIChat.manage.${transferTitle}`)" :list="transferList" :isSearch="isSearch" :isRadio="isRadio" :selectedList="selectedList" @submit="submit" @cancel="cancel" @search="handleSearchMember" :isH5="isH5" />
  161. </MaskTUI>
  162. <DialogTUI :title="$t(`TUIChat.manage.删除成员`)" :show="delDialogShow" :isH5="isH5" :center="true" :isHeaderShow="!isH5" @submit="handleManage(userList, 'remove')" @update:show="(e) => (delDialogShow = e)">
  163. <p v-if="userList.length === 1" class="delDialog-title">
  164. {{ $t(`TUIChat.manage.确定从群聊中删除该成员?`) }}
  165. </p>
  166. <p v-if="userList.length > 1" class="delDialog-title">
  167. {{ $t(`TUIChat.manage.确定从群聊中删除所选成员?`) }}
  168. </p>
  169. </DialogTUI>
  170. <DialogTUI title="退出群聊" :show="quitDialogShow" :isH5="isH5" :center="true" :isHeaderShow="!isH5" @submit="handleManage([], 'quit')" @update:show="(e) => (quitDialogShow = e)">
  171. <p class="delDialog-title">是否退出群聊?</p>
  172. </DialogTUI>
  173. <DialogTUI title="解散群聊" :show="dimmisDialogShow" :isH5="isH5" :center="true" :isHeaderShow="!isH5" @submit="handleManage([], 'dismiss')" @update:show="(e) => (dimmisDialogShow = e)">
  174. <p class="delDialog-title">是否解散群聊?</p>
  175. </DialogTUI>
  176. </div>
  177. </div>
  178. </template>
  179. <script lang="ts">
  180. import TUIMessage from "../../../components/messageTUI/index";
  181. import { defineComponent, watchEffect, reactive, toRefs, computed, watch, ref, onMounted } from "vue";
  182. import { onClickOutside } from "@vueuse/core";
  183. import MaskTUI from "../../../components/maskTUI/mask.vue";
  184. import Transfer from "../../../components/transferTUI/index.vue";
  185. import Slider from "../../../components/sliderTUI/index.vue";
  186. import ManageName from "./manage-name.vue";
  187. import ManageNotification from "./manage-notification.vue";
  188. import ManageNotificationDetail from "./manage-notification-detail.vue";
  189. import ManageMember from "./manage-member.vue";
  190. import MemeberProfile from "./member-profile.vue";
  191. import DialogTUI from "../../../components/dialogTUi/index.vue";
  192. import { imGroupChangeGroupOwner, imGroupDetail, imGroupDismiss, imGroupMemberPage, imGroupMemberSaveImAll, imGroupMemberUserDetail, imGroupMuteAll, imGroupQuit, imUserFriendPage } from "../../../../api";
  193. import Vuex from "vuex";
  194. import { handleErrorPrompts } from "../../utils";
  195. import useClipboard from "vue-clipboard3";
  196. import { eventGlobal } from "@/helpers";
  197. const manage = defineComponent({
  198. components: {
  199. MaskTUI,
  200. Transfer,
  201. Slider,
  202. ManageName,
  203. ManageNotification,
  204. ManageNotificationDetail,
  205. ManageMember,
  206. MemeberProfile,
  207. DialogTUI,
  208. },
  209. props: {
  210. userInfo: {
  211. type: Object,
  212. default: () => ({
  213. isGroup: false,
  214. list: [],
  215. }),
  216. },
  217. conversation: {
  218. type: Object,
  219. default: () => ({}),
  220. },
  221. show: {
  222. type: Boolean,
  223. default: () => false,
  224. },
  225. isH5: {
  226. type: Boolean,
  227. default: () => false,
  228. },
  229. },
  230. setup(props: any, ctx: any) {
  231. const types: any = manage.TUIServer.TUICore.TIM.TYPES;
  232. const { GroupServer } = manage;
  233. const { t } = manage.TUIServer.TUICore.config.i18n.useI18n();
  234. const data: any = reactive({
  235. conversation: {},
  236. userInfo: {
  237. isGroup: false,
  238. list: [],
  239. },
  240. isShowMuteTimeInput: false,
  241. editLableName: "",
  242. mask: false,
  243. currentTab: "",
  244. noticeId: "", // 查看公告详情时
  245. transferType: "",
  246. isSearch: false,
  247. isRadio: false,
  248. transferList: [],
  249. selectedList: [],
  250. isMuteTime: false,
  251. show: false,
  252. typeName: {
  253. [types.GRP_WORK]: "好友工作群",
  254. [types.GRP_PUBLIC]: "陌生人社交群",
  255. [types.GRP_MEETING]: "临时会议群",
  256. [types.GRP_AVCHATROOM]: "直播群",
  257. [types.JOIN_OPTIONS_FREE_ACCESS]: "自由加入",
  258. [types.JOIN_OPTIONS_NEED_PERMISSION]: "需要验证",
  259. [types.JOIN_OPTIONS_DISABLE_APPLY]: "禁止加群",
  260. },
  261. delDialogShow: false,
  262. quitDialogShow: false,
  263. dimmisDialogShow: false,
  264. userList: [],
  265. transferTitle: "",
  266. member: {
  267. admin: [],
  268. member: [],
  269. muteMember: [],
  270. },
  271. currentMember: {},
  272. classGroupDetail: {}, // 群详情
  273. page: 1, // 当前默认查询第一页数据
  274. currentUserDetail: {} as any, // 用户信息
  275. groupDetail: {} as any,
  276. platform: "",
  277. });
  278. const dialog: any = ref();
  279. const manageNotificationRef: any = ref()
  280. const manageNotificationDetailRef: any = ref()
  281. watchEffect(() => {
  282. data.conversation = props.conversation;
  283. data.userInfo = props.userInfo;
  284. data.show = props.show;
  285. });
  286. const VuexStore = ((window as any)?.TUIKitTUICore?.isOfficial && (Vuex as any)?.useStore()) || {};
  287. const TabName = computed(() => {
  288. let name = "";
  289. switch (data.currentTab) {
  290. case "notification":
  291. name = "群公告";
  292. break;
  293. case "notificationAdd":
  294. case "notificationAddDetail":
  295. name = '添加群公告';
  296. break;
  297. case "notificationUpdate":
  298. case "notificationUpdateDetail":
  299. name = '修改群公告';
  300. break;
  301. case "notificationDetail":
  302. name = "公告详情";
  303. break;
  304. case "member":
  305. name = "群成员";
  306. break;
  307. case "profile":
  308. name = "群成员";
  309. break;
  310. default:
  311. name = "群管理";
  312. break;
  313. }
  314. return name;
  315. });
  316. watch(
  317. () => data.userInfo.list,
  318. (newValue: any, oldValue: any) => {
  319. data.member = {
  320. admin: [],
  321. member: [],
  322. muteMember: [],
  323. };
  324. // TIM.TYPES.GRP_MBR_ROLE_ADMIN(群管理员),
  325. // TIM.TYPES.GRP_MBR_ROLE_MEMBER(群普通成员),
  326. // TIM.TYPES.GRP_MBR_ROLE_CUSTOM(自定义群成员角色,仅社群支持)
  327. newValue.map((item: any) => {
  328. switch (item?.groupRoleType) {
  329. case "Admin":
  330. data.member.admin.push(item);
  331. break;
  332. case "Member":
  333. data.member.member.push(item);
  334. break;
  335. default:
  336. break;
  337. }
  338. return item;
  339. });
  340. const time: number = new Date().getTime();
  341. data.member.muteMember = newValue.filter((item: any) => item?.muteUntil * 1000 - time > 0);
  342. },
  343. { deep: true }
  344. );
  345. const isDismissGroupAuth = computed(() => {
  346. const { conversation } = data;
  347. const userRole = conversation?.groupProfile?.selfInfo.role;
  348. const groupType = conversation?.groupProfile?.type;
  349. const isOwner = userRole === types.GRP_MBR_ROLE_OWNER;
  350. const isWork = groupType === types.GRP_WORK;
  351. return isOwner && !isWork;
  352. });
  353. const isShowAddMember = computed(() => {
  354. const { conversation } = data;
  355. const groupType = conversation?.groupProfile?.type;
  356. const isWork = groupType === types.GRP_WORK;
  357. if (isWork) {
  358. return true;
  359. }
  360. return false;
  361. });
  362. const showUserNum = computed(() => {
  363. let num = 3;
  364. if (!isShowAddMember.value) {
  365. num += 1;
  366. }
  367. if ((data.conversation as any).groupProfile.selfInfo.role !== "Owner") {
  368. num += 1;
  369. }
  370. return num;
  371. });
  372. const isAuth = computed(() => {
  373. const { conversation } = data;
  374. const userRole = conversation?.groupProfile?.selfInfo.role;
  375. const isOwner = userRole === types.GRP_MBR_ROLE_OWNER;
  376. const isAdmin = userRole === types.GRP_MBR_ROLE_ADMIN;
  377. return isOwner || isAdmin;
  378. });
  379. const isAdmin = computed(() => {
  380. const { conversation } = data;
  381. const groupType = conversation?.groupProfile?.type;
  382. const userRole = conversation?.groupProfile?.selfInfo.role;
  383. const isOwner = userRole === types.GRP_MBR_ROLE_OWNER;
  384. const isWork = groupType === types.GRP_WORK;
  385. const isAVChatRoom = groupType === types.GRP_AVCHATROOM;
  386. if (!isWork && !isAVChatRoom && isOwner) {
  387. return true;
  388. }
  389. return false;
  390. });
  391. const isSetMuteTime = computed(() => {
  392. const { conversation } = data;
  393. const groupType = conversation?.groupProfile?.type;
  394. const isWork = groupType === types.GRP_WORK;
  395. if (isWork || !isAuth.value) {
  396. return false;
  397. }
  398. return true;
  399. });
  400. const getMember = async (type?: string) => {
  401. try {
  402. const { conversation } = data;
  403. // console.log(conversation, "getMember -------");
  404. const options: any = {
  405. groupId: conversation?.groupProfile?.groupID,
  406. rows: 100,
  407. page: type && type === "more" ? data.page + 1 : data.page,
  408. // offset: type && type === "more" ? data.userInfo.list.length : 0,
  409. };
  410. await imGroupMemberPage(options).then((res: any) => {
  411. const rows = res.data.rows || [];
  412. rows.forEach((row: any) => {
  413. row.nick = row.nickname;
  414. });
  415. if (type && type === "more") {
  416. data.userInfo.list = [...data.userInfo.list, ...rows];
  417. } else {
  418. data.userInfo.list = rows;
  419. }
  420. });
  421. // GroupServer.getGroupMemberList(options)
  422. } catch {
  423. //
  424. }
  425. };
  426. const addMember = async (userIDList: any) => {
  427. const { conversation } = data;
  428. // const options: any = {
  429. // groupID: conversation.groupProfile.groupID,
  430. // userIDList,
  431. // };
  432. // await GroupServer.addGroupMember(options);
  433. const params: any = [];
  434. userIDList.forEach((id: any) => {
  435. params.push({
  436. groupId: conversation.groupProfile.groupID,
  437. imUserId: id,
  438. });
  439. });
  440. // console.log(params, userIDList, "userIDList");
  441. // return;
  442. try {
  443. await imGroupMemberSaveImAll(params);
  444. getGroupDetail();
  445. getMember();
  446. } catch {
  447. //
  448. }
  449. };
  450. const deleteMember = (user: any) => {
  451. const { conversation } = data;
  452. const options: any = {
  453. groupID: conversation.groupProfile.groupID,
  454. userIDList: [user.userID],
  455. };
  456. GroupServer.deleteGroupMember(options);
  457. };
  458. const changeOwner = async (userID: any) => {
  459. // const options: any = {
  460. // groupID: data.conversation.groupProfile.groupID,
  461. // newOwnerID: userID,
  462. // };
  463. // const imResponse = await GroupServer.changeGroupOwner(options);
  464. // data.conversation.groupProfile = imResponse.data.group;
  465. console.log(data.conversation.groupProfile, userID);
  466. // 腾讯IM切换人之后
  467. await imGroupChangeGroupOwner({
  468. oldOwner: data.conversation.groupProfile.ownerID,
  469. groupId: data.conversation.groupProfile.groupID,
  470. newOwner: userID,
  471. });
  472. toggleShow();
  473. data.conversation.groupProfile = {};
  474. TUIMessage({
  475. message: "转交成功",
  476. isH5: false,
  477. type: "success",
  478. });
  479. };
  480. const quit = async (group: any) => {
  481. data.quitDialogShow = true;
  482. };
  483. const dismiss = async (group: any) => {
  484. data.dimmisDialogShow = true;
  485. // console.log(manage.TUIServer.deleteConversation, "manage.TUIServer");
  486. // manage.TUIServer.deleteConversation(data.conversation.conversationID);
  487. // manage.TUIServer.store.conversation = {};
  488. // toggleShow();
  489. // await GroupServer.dismissGroup(group.groupID);
  490. // manage.TUIServer.store.conversation = {};
  491. // (window as any)?.TUIKitTUICore?.isOfficial && VuexStore?.commit && VuexStore?.commit("handleTask", 5);
  492. };
  493. const handleAdmin = async (user: any) => {
  494. const { conversation } = data;
  495. let role = "";
  496. switch (user.role) {
  497. case types.GRP_MBR_ROLE_ADMIN:
  498. role = types.GRP_MBR_ROLE_MEMBER;
  499. break;
  500. case types.GRP_MBR_ROLE_MEMBER:
  501. role = types.GRP_MBR_ROLE_ADMIN;
  502. break;
  503. }
  504. const options: any = {
  505. groupID: conversation.groupProfile.groupID,
  506. userID: user.userID,
  507. role,
  508. };
  509. await GroupServer.setGroupMemberRole(options);
  510. getMember();
  511. };
  512. const setMemberMuteTime = async (userID: string, type?: string) => {
  513. const { conversation } = data;
  514. const options: any = {
  515. groupID: conversation.groupProfile.groupID,
  516. userID,
  517. muteTime: type === "add" ? 60 * 60 * 24 * 30 : 0,
  518. };
  519. await GroupServer.setGroupMemberMuteTime(options);
  520. if (type === "add") {
  521. (window as any)?.TUIKitTUICore?.isOfficial && VuexStore?.commit && VuexStore?.commit("handleTask", 4);
  522. }
  523. getMember();
  524. };
  525. const kickedOut = async (userIDList: any) => {
  526. const { conversation } = data;
  527. const options: any = {
  528. groupID: conversation.groupProfile.groupID,
  529. userIDList,
  530. reason: "",
  531. };
  532. await GroupServer.deleteGroupMember(options);
  533. getMember();
  534. };
  535. const edit = (labelName: string) => {
  536. data.editLableName = labelName;
  537. };
  538. /** 群公告修改 */
  539. const onNotificationChangeStatus = (type: string) => {
  540. if(type === "add") {
  541. data.currentTab = 'notificationAdd'
  542. } else if(type === "edit") {
  543. data.currentTab = 'notificationUpdate'
  544. } else if(type === "submit") {
  545. data.currentTab = 'notification'
  546. } else if(type === "addDetail") {
  547. data.currentTab = 'notificationAddDetail'
  548. } else if(type === "editDetail") {
  549. data.currentTab = 'notificationUpdateDetail'
  550. } else if(type === "submitDetail") {
  551. data.currentTab = 'notificationDetail'
  552. } else if(type === "deleteDetail") {
  553. data.currentTab = ""
  554. }
  555. }
  556. const updateProfile = async (params: any) => {
  557. const { key, value } = params;
  558. const options: any = {
  559. groupID: data.conversation.groupProfile.groupID,
  560. [key]: value,
  561. };
  562. const res = await GroupServer.updateGroupProfile(options);
  563. const { conversation } = manage.TUIServer.store;
  564. conversation.groupProfile = res.data.group;
  565. manage.TUIServer.store.conversation = {};
  566. manage.TUIServer.store.conversation = conversation;
  567. data.editLableName = "";
  568. };
  569. const setTab = (tabName: string) => {
  570. if(data.currentTab === "notificationAdd" || data.currentTab === "notificationUpdate") {
  571. manageNotificationRef.value?.onCloseEdit()
  572. data.currentTab = 'notification'
  573. return
  574. }
  575. if(data.currentTab === "notificationAddDetail" || data.currentTab === "notificationUpdateDetail") {
  576. manageNotificationDetailRef.value?.onCloseEdit()
  577. data.currentTab = 'notificationDetail'
  578. return
  579. }
  580. if(tabName === 'onlyMute') {
  581. getUserList()
  582. }
  583. data.currentTab = tabName;
  584. data.editLableName = "";
  585. if (data.currentTab === "member") {
  586. data.transferType = "remove";
  587. }
  588. if (!data.currentTab) {
  589. data.transferType = "";
  590. }
  591. };
  592. const handleSearchMember = async (value: string) => {
  593. let imResponse: any = {};
  594. let imMemberResponse: any = {};
  595. const options: any = {
  596. groupID: data.conversation.groupProfile.groupID,
  597. userIDList: [value],
  598. };
  599. switch (data.transferType) {
  600. case "add":
  601. try {
  602. imMemberResponse = await GroupServer.getGroupMemberProfile(options);
  603. data.transferList = data.transferList.filter((item: any) => item.userID !== imResponse.data[0]?.userID);
  604. data.transferList = [...data.transferList, ...imResponse.data];
  605. if (imMemberResponse?.data?.memberList.length > 0) {
  606. data.transferList = data.transferList.map((item: any) => {
  607. if (item.userID === imMemberResponse?.data?.memberList[0].userID) {
  608. item.isDisabled = true;
  609. }
  610. return item;
  611. });
  612. }
  613. } catch (error) {
  614. const message = t("TUIChat.manage.该用户不存在");
  615. handleErrorPrompts(message, props);
  616. }
  617. break;
  618. case "remove":
  619. try {
  620. imResponse = await GroupServer.getGroupMemberProfile(options);
  621. if (imResponse.data.memberList.length === 0) {
  622. const message = t("TUIChat.manage.该用户不在群组内");
  623. return handleErrorPrompts(message, props);
  624. }
  625. data.transferList = data.transferList.filter(
  626. (item: any) =>
  627. // eslint-disable-next-line no-unsafe-optional-chaining
  628. item.userID !== imResponse?.data?.memberList[0]?.userID
  629. );
  630. data.transferList = [
  631. ...data.transferList,
  632. // eslint-disable-next-line no-unsafe-optional-chaining
  633. ...imResponse?.data?.memberList,
  634. ];
  635. } catch (error) {
  636. const message = t("TUIChat.manage.该用户不存在");
  637. handleErrorPrompts(message, props);
  638. }
  639. break;
  640. default:
  641. break;
  642. }
  643. };
  644. const submit = (userList: any) => {
  645. console.log(userList, data.transferType, " data.transferType");
  646. if (data.transferType === "remove") {
  647. data.userList = userList;
  648. data.delDialogShow = !data.delDialogShow;
  649. } else {
  650. handleManage(userList, data.transferType);
  651. }
  652. data.mask = false;
  653. };
  654. const friendList = async () => {
  655. const list = await imUserFriendPage({ page: 1, rows: 999 });
  656. console.log(list, "lits");
  657. const fristList = list.data.rows || [];
  658. fristList.forEach((item: any) => {
  659. item.nick = item.friendNickname;
  660. });
  661. return fristList.filter((item: any) => !data.userInfo.list.some((infoItem: any) => infoItem.imUserId === item.imUserId));
  662. };
  663. const cancel = () => {
  664. toggleMask();
  665. };
  666. const toggleMask = async (type?: string) => {
  667. data.selectedList = [];
  668. switch (type) {
  669. case "add":
  670. data.isRadio = false;
  671. data.transferList = await friendList();
  672. data.transferTitle = "添加成员";
  673. break;
  674. case "remove":
  675. data.isRadio = false;
  676. data.transferList = data.userInfo.list.filter(
  677. (item: any) =>
  678. // eslint-disable-next-line no-unsafe-optional-chaining
  679. item.userID !== data.conversation?.groupProfile?.selfInfo.userID
  680. );
  681. data.transferTitle = "删除成员";
  682. break;
  683. case "addAdmin":
  684. data.isRadio = true;
  685. data.transferList = data.member.member;
  686. data.transferTitle = "新增管理员";
  687. break;
  688. case "removeAdmin":
  689. data.isRadio = true;
  690. data.transferList = data.member.admin;
  691. data.transferTitle = "移除管理员";
  692. break;
  693. case "changeOwner":
  694. data.isRadio = true;
  695. data.transferList = [...data.member.admin, ...data.member.member];
  696. data.transferTitle = "转让群组";
  697. console.log(data.transferList, "data.transferList");
  698. break;
  699. case "addMute":
  700. data.isRadio = true;
  701. data.transferList = data.member.member;
  702. if (data.conversation.groupProfile.selfInfo.role === "Owner") {
  703. data.transferList = [...data.member.admin, ...data.member.member];
  704. }
  705. data.transferTitle = "新增禁言用户";
  706. break;
  707. case "removeMute":
  708. data.isRadio = true;
  709. data.transferList = data.member.muteMember;
  710. data.transferTitle = "移除禁言用户";
  711. break;
  712. default:
  713. break;
  714. }
  715. data.transferType = type;
  716. data.mask = !data.mask;
  717. };
  718. onClickOutside(dialog, () => {
  719. data.show = false;
  720. });
  721. const toggleShow = () => {
  722. if (!GroupServer) {
  723. const message = t("TUIChat.manage.请先注册 TUIGroup 模块");
  724. return handleErrorPrompts(message, props);
  725. }
  726. data.show = !data.show;
  727. if (!data.show) {
  728. data.currentTab = "";
  729. }
  730. if (data.show) {
  731. getMember();
  732. }
  733. };
  734. // 禁言
  735. const setAllMuteTime = async (value: boolean) => {
  736. // updateProfile({ key: "muteAllMembers", value });
  737. // (window as any)?.TUIKitTUICore?.isOfficial && VuexStore?.commit && VuexStore?.commit("handleTask", 4);
  738. try {
  739. await imGroupMuteAll({
  740. groupId: data.conversation.groupProfile.groupID,
  741. muteAll: value,
  742. });
  743. getGroupDetail();
  744. } catch {
  745. //
  746. }
  747. };
  748. const handleManage = (userList: any, type: any) => {
  749. const userIDList: any = [];
  750. userList.map((item: any) => {
  751. userIDList.push(item.imUserId);
  752. return item;
  753. });
  754. switch (type) {
  755. case "add":
  756. addMember(userIDList);
  757. break;
  758. case "remove":
  759. kickedOut(userIDList);
  760. break;
  761. case "addAdmin":
  762. handleAdmin(userList[0]);
  763. break;
  764. case "removeAdmin":
  765. handleAdmin(userList[0]);
  766. break;
  767. case "changeOwner":
  768. changeOwner(userIDList[0]);
  769. break;
  770. case "addMute":
  771. setMemberMuteTime(userIDList[0], "add");
  772. break;
  773. case "removeMute":
  774. setMemberMuteTime(userIDList[0], "remove");
  775. break;
  776. case "quit":
  777. // 退出群聊
  778. imGroupQuit({
  779. id: data.conversation.groupProfile.groupID,
  780. }).then(() => {
  781. eventGlobal.emit("removeGroup", data.conversation.groupProfile.groupID);
  782. manage.TUIServer.deleteConversation(data.conversation.conversationID);
  783. manage.TUIServer.store.conversation = {};
  784. toggleShow();
  785. });
  786. break;
  787. case "dismiss":
  788. // 解散群
  789. imGroupDismiss({
  790. id: data.conversation.groupProfile.groupID,
  791. })
  792. .then(() => {
  793. eventGlobal.emit("removeGroup", data.conversation.groupProfile.groupID);
  794. manage.TUIServer.deleteConversation(data.conversation.conversationID);
  795. manage.TUIServer.store.conversation = {};
  796. toggleShow();
  797. })
  798. .catch((err: any) => {
  799. TUIMessage({
  800. message: err.message,
  801. isH5: false,
  802. type: "error",
  803. });
  804. });
  805. break;
  806. default:
  807. break;
  808. }
  809. };
  810. const handleGroupIDCopy = async () => {
  811. try {
  812. const { toClipboard } = useClipboard();
  813. await toClipboard(data?.conversation?.groupProfile?.groupID);
  814. } catch (error) {
  815. handleErrorPrompts(error, data.env);
  816. }
  817. };
  818. const handleMemberProfileShow = (user: any) => {
  819. data.currentMember = user;
  820. setTab("profile");
  821. };
  822. const getGroupMemberUserDetail = async () => {
  823. try {
  824. const res = await imGroupMemberUserDetail({
  825. groupId: data?.conversation?.groupProfile?.groupID,
  826. imUserId: data?.conversation?.groupProfile?.selfInfo.userID,
  827. });
  828. data.currentUserDetail = res.data;
  829. } catch {
  830. //
  831. }
  832. };
  833. /** 获取群详情 */
  834. const getGroupDetail = async () => {
  835. try {
  836. const res = await imGroupDetail({ id: data?.conversation?.groupProfile?.groupID });
  837. const tdata = res.data;
  838. tdata.configJson = tdata.configJson ? JSON.parse(tdata.configJson) : {};
  839. data.groupDetail = tdata;
  840. } catch {
  841. //
  842. }
  843. };
  844. watch(
  845. () => data.show,
  846. () => {
  847. if (data.show) {
  848. try {
  849. getGroupDetail();
  850. getGroupMemberUserDetail();
  851. } catch {
  852. //
  853. }
  854. } else {
  855. data.currentTab = ""
  856. }
  857. }
  858. );
  859. onMounted(() => {
  860. eventGlobal.on('handleNotice', (id: any) => {
  861. data.show = !data.show;
  862. data.noticeId = id
  863. data.currentTab = "notificationDetail"
  864. if (data.show) {
  865. getMember();
  866. }
  867. })
  868. try {
  869. data.platform = sessionStorage.getItem("platform") || "classroom";
  870. getGroupDetail();
  871. getGroupMemberUserDetail();
  872. // console.log(data?.conversation, "data?.conversation?");
  873. // console.log(data.userInfo.list, "data.userInfo.list");
  874. } catch {
  875. //
  876. }
  877. });
  878. return {
  879. ...toRefs(data),
  880. isDismissGroupAuth,
  881. isShowAddMember,
  882. isSetMuteTime,
  883. isAdmin,
  884. isAuth,
  885. addMember,
  886. deleteMember,
  887. changeOwner,
  888. quit,
  889. dismiss,
  890. handleAdmin,
  891. setMemberMuteTime,
  892. kickedOut,
  893. edit,
  894. onNotificationChangeStatus,
  895. updateProfile,
  896. setTab,
  897. TabName,
  898. getMember,
  899. handleSearchMember,
  900. submit,
  901. cancel,
  902. toggleMask,
  903. toggleShow,
  904. setAllMuteTime,
  905. handleManage,
  906. showUserNum,
  907. dialog,
  908. manageNotificationRef,
  909. manageNotificationDetailRef,
  910. handleGroupIDCopy,
  911. handleMemberProfileShow,
  912. };
  913. },
  914. });
  915. export default manage;
  916. </script>
  917. <style lang="scss" scoped src="./style/index.scss"></style>