index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. <template>
  2. <view class="group_settings_container">
  3. <custom-nav-bar title="群聊设置" />
  4. <view class="group_settings_content">
  5. <view class="setting_row info_row">
  6. <view class="group_avatar" @click="updateGroupAvatar">
  7. <my-avatar
  8. :src="storeCurrentConversation.faceURL"
  9. :isGroup="true"
  10. size="46"
  11. />
  12. <image
  13. v-if="isOwner"
  14. class="edit_icon"
  15. src="../../../static/images/group_setting_edit.png"
  16. alt=""
  17. />
  18. </view>
  19. <view class="group_info">
  20. <view class="group_info_name">
  21. <text class="group_name"
  22. >{{ storeCurrentConversation.showName }}({{
  23. storeCurrentGroup.memberCount
  24. }})</text
  25. >
  26. <image
  27. v-if="isOwner || isAdmin"
  28. @click="toUpdateGroupName"
  29. style="width: 24rpx; height: 24rpx"
  30. src="../../../static/images/group_edit.png"
  31. alt=""
  32. />
  33. </view>
  34. <text @click="copyGroupID" class="sub_title">{{
  35. storeCurrentConversation.groupID
  36. }}</text>
  37. </view>
  38. <image
  39. @click="toGroupQr"
  40. style="margin-right: 6rpx; width: 18px; height: 18px"
  41. src="../../../static/images/group_setting_qrcode.png"
  42. alt=""
  43. />
  44. </view>
  45. <group-member-row
  46. v-if="isJoinGroup"
  47. :isNomal="!isAdmin && !isOwner"
  48. :groupID="storeCurrentConversation.groupID"
  49. :memberCount="storeCurrentGroup.memberCount"
  50. :groupMemberList="groupMemberList"
  51. />
  52. <view class="setting_row">
  53. <search-action-row />
  54. </view>
  55. <view v-if="isJoinGroup" class="setting_row">
  56. <setting-item
  57. @click="toGroupAnnouncement"
  58. title="群公告"
  59. :border="false"
  60. />
  61. <setting-item
  62. v-if="isOwner || isAdmin"
  63. @click="toGroupManage"
  64. title="群管理"
  65. :border="false"
  66. />
  67. <setting-item
  68. v-if="isOwner"
  69. @click="toSetMute"
  70. title="禁言成员"
  71. :border="false"
  72. />
  73. <setting-item
  74. v-if="isOwner"
  75. @click="toSetAdmin"
  76. title="设置管理员"
  77. :border="false"
  78. />
  79. </view>
  80. <view v-if="isJoinGroup" class="setting_row">
  81. <setting-item
  82. @click="toUpdatePage"
  83. title="我在群里的昵称"
  84. :border="false"
  85. >
  86. <text class="sub_title">{{
  87. storeCurrentMemberInGroup.nickname
  88. }}</text>
  89. </setting-item>
  90. </view>
  91. <view v-if="isJoinGroup" class="setting_row">
  92. <setting-item
  93. title="聊天置顶"
  94. :loading="switchLoading.pin"
  95. @switch="changePin"
  96. :switchValue="storeCurrentConversation.isPinned"
  97. :is_switch="true"
  98. :border="false"
  99. />
  100. <!-- <setting-item
  101. title="消息免打扰"
  102. :loading="switchLoading.opt"
  103. @switch="changeOpt($event, 2)"
  104. :switchValue="storeCurrentConversation.recvMsgOpt === 2"
  105. :is_switch="true"
  106. :border="false"
  107. /> -->
  108. </view>
  109. <view class="setting_row">
  110. <setting-item
  111. danger
  112. @click="() => (confirmType = 'Clear')"
  113. title="清空聊天记录"
  114. :border="false"
  115. />
  116. <setting-item
  117. v-if="isJoinGroup"
  118. danger
  119. @click="() => (confirmType = isOwner ? 'Dismiss' : 'Quit')"
  120. :title="isOwner ? '解散群聊' : '退出群聊'"
  121. :border="false"
  122. />
  123. </view>
  124. <u-modal
  125. :content="getConfirmContent"
  126. asyncClose
  127. :show="confirmType !== null"
  128. showCancelButton
  129. @confirm="confirm"
  130. @cancel="() => (confirmType = null)"
  131. ></u-modal>
  132. </view>
  133. <u-toast ref="uToast"></u-toast>
  134. <action-sheet
  135. :groupID="storeCurrentConversation.groupID"
  136. :visible.sync="actionSheetVisible"
  137. />
  138. </view>
  139. </template>
  140. <script>
  141. import { mapGetters } from "vuex";
  142. import { GroupMemberListTypes } from "../../../constant";
  143. import IMSDK, {
  144. GroupMemberRole,
  145. GroupStatus,
  146. GroupVerificationType,
  147. IMMethods,
  148. MessageReceiveOptType,
  149. } from "openim-uniapp-polyfill";
  150. import CustomNavBar from "../../../components/CustomNavBar/index.vue";
  151. import MyAvatar from "../../../components/MyAvatar/index.vue";
  152. import SettingItem from "../../../components/SettingItem/index.vue";
  153. import GroupMemberRow from "./components/GroupMemberRow.vue";
  154. import ActionSheet from "./components/ActionSheet.vue";
  155. import SearchActionRow from "../singleSettings/components/SearchActionRow.vue";
  156. import { getPurePath } from "../../../util/common";
  157. import { premissionCheck } from "@/js_sdk/wa-permission/permission.js"
  158. const ConfirmTypes = {
  159. Clear: "Clear",
  160. Dismiss: "Dismiss",
  161. Quit: "Quit",
  162. };
  163. export default {
  164. components: {
  165. CustomNavBar,
  166. MyAvatar,
  167. SettingItem,
  168. GroupMemberRow,
  169. ActionSheet,
  170. SearchActionRow,
  171. },
  172. props: {},
  173. data() {
  174. return {
  175. actionSheetVisible: false,
  176. confirmType: null,
  177. switchLoading: {
  178. pin: false,
  179. opt: false,
  180. mute: false,
  181. },
  182. groupMemberList: [],
  183. isJoinGroup: true
  184. };
  185. },
  186. onLoad() {
  187. this.setIMListener();
  188. this.groupMemberDeletedHandler({ isInitail: true })
  189. },
  190. onUnload() {
  191. this.disposeIMListener();
  192. },
  193. watch: {
  194. "storeCurrentGroup.memberCount"() {
  195. this.getGroupMemberList();
  196. },
  197. },
  198. computed: {
  199. ...mapGetters([
  200. "storeCurrentConversation",
  201. "storeCurrentMemberInGroup",
  202. "storeCurrentGroup",
  203. ]),
  204. getConfirmContent() {
  205. if (this.confirmType === ConfirmTypes.Clear) {
  206. return "确定要清空聊天记录吗?";
  207. }
  208. if (this.confirmType === ConfirmTypes.Quit) {
  209. return "确定要退出当前群聊吗?";
  210. }
  211. if (this.confirmType === ConfirmTypes.Dismiss) {
  212. return "确定要解散当前群聊吗?";
  213. }
  214. return "";
  215. },
  216. isOwner() {
  217. return this.storeCurrentMemberInGroup.roleLevel === GroupMemberRole.Owner;
  218. },
  219. isAdmin() {
  220. return this.storeCurrentMemberInGroup.roleLevel === GroupMemberRole.Admin;
  221. },
  222. getGroupVerStr() {
  223. if (
  224. this.storeCurrentGroup.needVerification ===
  225. GroupVerificationType.ApplyNeedInviteNot
  226. ) {
  227. return "群成员邀请无需验证";
  228. }
  229. if (
  230. this.storeCurrentGroup.needVerification === GroupVerificationType.AllNot
  231. ) {
  232. return "允许所有人加群";
  233. }
  234. return "需要发送验证消息";
  235. },
  236. getGroupTypeStr() {
  237. return "工作群";
  238. },
  239. isAllMuted() {
  240. return this.storeCurrentGroup.status === GroupStatus.Muted;
  241. },
  242. },
  243. methods: {
  244. getGroupMemberList() {
  245. IMSDK.asyncApi(IMSDK.IMMethods.GetGroupMemberList, IMSDK.uuid(), {
  246. groupID: this.storeCurrentConversation.groupID,
  247. filter: 0,
  248. offset: 0,
  249. count: !this.isAdmin && !this.isOwner ? 9 : 8,
  250. }).then(({ data }) => {
  251. this.groupMemberList = [...data];
  252. }).catch((err) => {
  253. console.log(err);
  254. });
  255. },
  256. toGroupManage() {
  257. uni.navigateTo({
  258. url: "/pages_im/pages/conversation/groupManage/index",
  259. });
  260. },
  261. toMemberAuthority() {
  262. uni.navigateTo({
  263. url: "/pages_im/pages/conversation/memberAuthority/index",
  264. });
  265. },
  266. toSearchMessage() {
  267. uni.navigateTo({
  268. url: "/pages_im/pages/conversation/searchMessage/index",
  269. });
  270. },
  271. toGroupAnnouncement() {
  272. uni.navigateTo({
  273. url: `/pages_im/pages/conversation/groupAnnouncement/index`,
  274. });
  275. },
  276. toSetMute(){
  277. uni.navigateTo({
  278. url: `/pages_im/pages/conversation/groupMemberList/index?type=${GroupMemberListTypes.Mute}&groupID=${this.storeCurrentGroup.groupID}`,
  279. });
  280. },
  281. toSetAdmin() {
  282. uni.navigateTo({
  283. url: `/pages_im/pages/conversation/groupMemberList/index?type=${GroupMemberListTypes.SetAdmin}&groupID=${this.storeCurrentGroup.groupID}`,
  284. });
  285. },
  286. toUpdatePage() {
  287. uni.navigateTo({
  288. url: `/pages_im/pages/conversation/updateGroupOrNickname/index?sourceInfo=${JSON.stringify(
  289. this.storeCurrentMemberInGroup,
  290. )}`,
  291. });
  292. },
  293. toUpdateGroupName() {
  294. if (!this.isAdmin && !this.isOwner) {
  295. return;
  296. }
  297. uni.navigateTo({
  298. url: `/pages_im/pages/conversation/updateGroupOrNickname/index?sourceInfo=${JSON.stringify(
  299. this.storeCurrentGroup,
  300. )}`,
  301. });
  302. },
  303. toGroupQr() {
  304. uni.navigateTo({
  305. url: `/pages_im/pages/common/userOrGroupQrCode/index?sourceInfo=${JSON.stringify(
  306. this.storeCurrentGroup,
  307. )}`,
  308. });
  309. },
  310. toSetBg() {
  311. uni.$u.route("/pages_im/pages/conversation/setChatBackgroup/index");
  312. },
  313. toSetFontSize() {
  314. uni.$u.route("/pages_im/pages/conversation/setFontSize/index");
  315. },
  316. copyGroupID() {
  317. uni.setClipboardData({
  318. data: this.storeCurrentGroup.groupID,
  319. success: () => {
  320. uni.hideToast();
  321. this.$nextTick(() => {
  322. uni.$u.toast("复制成功");
  323. });
  324. },
  325. });
  326. },
  327. showActionSheet() {
  328. if (!this.isAdmin && !this.isOwner) {
  329. return;
  330. }
  331. this.actionSheetVisible = true;
  332. },
  333. async updateGroupAvatar() {
  334. if (!this.isAdmin && !this.isOwner) {
  335. return;
  336. }
  337. let result = await premissionCheck("EXTERNAL_STORAGE");
  338. if(result != 1) {
  339. return;
  340. }
  341. uni.chooseImage({
  342. count: 1,
  343. sizeType: ["compressed"],
  344. success: async ({ tempFilePaths }) => {
  345. const path = tempFilePaths[0];
  346. const nameIdx = path.lastIndexOf("/") + 1;
  347. const typeIdx = path.lastIndexOf(".") + 1;
  348. const fileName = path.slice(nameIdx);
  349. const fileType = path.slice(typeIdx);
  350. try {
  351. const {
  352. data: { url },
  353. } = await IMSDK.asyncApi(IMMethods.UploadFile, IMSDK.uuid(), {
  354. filepath: getPurePath(tempFilePaths[0]),
  355. name: fileName,
  356. contentType: fileType,
  357. uuid: IMSDK.uuid(),
  358. });
  359. await IMSDK.asyncApi(IMSDK.IMMethods.SetGroupInfo, IMSDK.uuid(), {
  360. groupID: this.storeCurrentConversation.groupID,
  361. faceURL: url,
  362. });
  363. uni.$u.toast("修改成功");
  364. } catch (error) {
  365. uni.$u.toast("修改失败");
  366. }
  367. },
  368. });
  369. },
  370. changePin(isPinned) {
  371. this.switchLoading.pin = true;
  372. IMSDK.asyncApi(IMSDK.IMMethods.PinConversation, IMSDK.uuid(), {
  373. conversationID: this.storeCurrentConversation.conversationID,
  374. isPinned,
  375. })
  376. .then(() => uni.$u.toast("操作成功"))
  377. .catch(() => uni.$u.toast("操作失败"))
  378. .finally(() => (this.switchLoading.pin = false));
  379. },
  380. changeOpt(notNomal, type) {
  381. this.switchLoading.opt = true;
  382. IMSDK.asyncApi(
  383. IMSDK.IMMethods.SetConversationRecvMessageOpt,
  384. IMSDK.uuid(),
  385. {
  386. conversationID: this.storeCurrentConversation.conversationID,
  387. opt: notNomal ? type : MessageReceiveOptType.Nomal,
  388. },
  389. )
  390. .then(() => uni.$u.toast("操作成功"))
  391. .catch(() => uni.$u.toast("操作失败"))
  392. .finally(() => (this.switchLoading.opt = false));
  393. },
  394. changeMute(isMute) {
  395. this.switchLoading.mute = true;
  396. IMSDK.asyncApi(IMSDK.IMMethods.ChangeGroupMute, IMSDK.uuid(), {
  397. groupID: this.storeCurrentGroup.groupID,
  398. isMute,
  399. })
  400. .then(() => uni.$u.toast("禁言成功"))
  401. .catch(() => uni.$u.toast("禁言失败"))
  402. .finally(() => (this.switchLoading.mute = false));
  403. },
  404. confirm() {
  405. let funcName = "";
  406. let sourceID = this.storeCurrentConversation.groupID;
  407. if (this.confirmType === ConfirmTypes.Clear) {
  408. sourceID = this.storeCurrentConversation.conversationID;
  409. funcName = IMSDK.IMMethods.ClearConversationAndDeleteAllMsg;
  410. }
  411. if (this.confirmType === ConfirmTypes.Quit) {
  412. funcName = IMSDK.IMMethods.QuitGroup;
  413. }
  414. if (this.confirmType === ConfirmTypes.Dismiss) {
  415. funcName = IMSDK.IMMethods.DismissGroup;
  416. }
  417. IMSDK.asyncApi(funcName, IMSDK.uuid(), sourceID)
  418. .then(() => {
  419. uni.$u.toast("操作成功");
  420. if (this.confirmType === ConfirmTypes.Clear) {
  421. this.$store.commit("message/SET_HISTORY_MESSAGE_LIST", []);
  422. this.$store.commit("message/SET_PREVIEW_IMAGE_LIST", []);
  423. } else {
  424. setTimeout(
  425. () =>
  426. uni.switchTab({
  427. url: "/pages/conversation/conversationList/index",
  428. }),
  429. 250,
  430. );
  431. }
  432. })
  433. .catch(() => uni.$u.toast("操作失败"))
  434. .finally(() => (this.confirmType = null));
  435. },
  436. groupMemberInfoChangeHandler({ data }) {
  437. if (data.groupID === this.groupMemberList[0]?.groupID) {
  438. const idx = this.groupMemberList.findIndex(
  439. (member) => member.userID === data.userID,
  440. );
  441. if (idx > -1) {
  442. this.getGroupMemberList();
  443. }
  444. }
  445. },
  446. groupMemberDeletedHandler({ data, isInitail }) {
  447. if (isInitail || data?.groupID === this.groupMemberList[0]?.groupID) {
  448. const idx = this.groupMemberList.findIndex(
  449. (member) => member.userID === data?.userID,
  450. );
  451. if (isInitail || idx > -1) {
  452. this.getGroupMemberList();
  453. IMSDK.asyncApi(
  454. IMMethods.IsJoinGroup,
  455. IMSDK.uuid(),
  456. this.storeCurrentConversation.groupID
  457. ).then((res) => {
  458. this.isJoinGroup = res.data
  459. });
  460. }
  461. }
  462. },
  463. setIMListener() {
  464. uni.$on(IMSDK.IMEvents.OnGroupMemberInfoChanged, this.groupMemberInfoChangeHandler)
  465. IMSDK.subscribe(IMSDK.IMEvents.OnGroupMemberAdded, this.groupMemberInfoChangeHandler)
  466. IMSDK.subscribe(IMSDK.IMEvents.OnGroupMemberDeleted, this.groupMemberDeletedHandler)
  467. },
  468. disposeIMListener() {
  469. uni.$off(IMSDK.IMEvents.OnGroupMemberInfoChanged, this.groupMemberInfoChangeHandler)
  470. IMSDK.unsubscribe(IMSDK.IMEvents.OnGroupMemberAdded, this.groupMemberInfoChangeHandler)
  471. IMSDK.unsubscribe(IMSDK.IMEvents.OnGroupMemberDeleted, this.groupMemberDeletedHandler)
  472. },
  473. },
  474. };
  475. </script>
  476. <style lang="scss" scoped>
  477. .group_settings_container {
  478. @include colBox(false);
  479. height: 100vh;
  480. background-color: #f6f6f6;
  481. .group_settings_content {
  482. overflow-y: auto;
  483. }
  484. .setting_row {
  485. background-color: #fff;
  486. margin: 24rpx;
  487. border-radius: 6px;
  488. overflow: hidden;
  489. }
  490. .info_row {
  491. @include vCenterBox();
  492. padding: 36rpx 44rpx;
  493. .group_avatar {
  494. margin-right: 16rpx;
  495. position: relative;
  496. .edit_icon {
  497. position: absolute;
  498. right: -6rpx;
  499. bottom: -6rpx;
  500. width: 11px;
  501. height: 11px;
  502. }
  503. }
  504. .group_info {
  505. min-height: 46px;
  506. display: flex;
  507. flex: 1;
  508. flex-direction: column;
  509. align-items: flex-start;
  510. justify-content: space-between;
  511. &_name {
  512. display: flex;
  513. flex-direction: row;
  514. align-items: center;
  515. justify-content: center;
  516. .group_name {
  517. // @include nomalEllipsis();
  518. font-size: 34rpx;
  519. max-width: 380rpx;
  520. margin-right: 24rpx;
  521. }
  522. }
  523. .sub_title {
  524. @include nomalEllipsis();
  525. margin-bottom: 0;
  526. font-size: 28rpx;
  527. color: #999;
  528. }
  529. }
  530. }
  531. }
  532. </style>