| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { Friend, GroupLite, GroupMember } from '../../types' |
| | | import type { GroupMemberLite } from './group-member.vue' |
| | | |
| | | import { computed, ref, watch } from 'vue' |
| | | |
| | | import { CommonStatusEnum } from '#/packages/constants/src' |
| | | |
| | | import { Button } from 'ant-design-vue' |
| | | |
| | | import { getCurrentUserId } from '#/views/im/utils/auth' |
| | | |
| | | import { getMemberDisplayName, isGroupQuit } from '../../../utils/user' |
| | | import { useFriendStore } from '../../store/friendStore' |
| | | import { useGroupStore } from '../../store/groupStore' |
| | | import GroupAvatar from './group-avatar.vue' |
| | | import GroupMemberGrid from './group-member-grid.vue' |
| | | |
| | | defineOptions({ name: 'ImGroupInfo' }) |
| | | |
| | | const props = defineProps<{ |
| | | group: GroupLite |
| | | }>() |
| | | |
| | | const emit = defineEmits<{ |
| | | /** stranger ç¹ãå å
¥ç¾¤èãï¼ç¶çº§è´è´£å¼¹ç³è¯·çç± + è° applyJoinGroup */ |
| | | apply: [group: GroupLite] |
| | | /** member ç¹ãè¿å
¥ç¾¤èãï¼ç¶çº§è´è´£åä¼è¯ + å
³æµ®å± */ |
| | | chat: [group: GroupLite] |
| | | }>() |
| | | |
| | | const groupStore = useGroupStore() |
| | | const friendStore = useFriendStore() |
| | | |
| | | const members = ref<GroupMemberLite[]>([]) |
| | | |
| | | /** |
| | | * æ¯å¦å·²å 群ï¼åºäº"èªå·±ç¡®å®å¨æåå表é"夿 |
| | | * - ç¼åæªå½ä¸ï¼ç´æ¥ falseï¼éçç¾¤ï¼ |
| | | * - å½ä¸ä¸ members å·²æï¼ç²¾åæ¥ self.userId å¨ä¸å¨ |
| | | * - å½ä¸ä½ members æªæï¼fetchGroupList æ¥å£è¯ä¹å³ãæå å
¥ç群ãï¼å½ä¸è§ä¸º memberï¼ææååä¼èªå¨æ¶æï¼ |
| | | */ |
| | | const isMember = computed(() => { |
| | | if (!props.group?.id) { |
| | | return false |
| | | } |
| | | const cached = groupStore.getGroup(props.group.id) |
| | | if (!cached) { |
| | | return false |
| | | } |
| | | // åå²é群群ï¼ç´æ¥å¤ falseï¼é¿å
æåæªå è½½æ¶è¯¯æ¾ç¤ºãè¿å
¥ç¾¤èã |
| | | if (isGroupQuit(cached)) { |
| | | return false |
| | | } |
| | | if (cached.membersLoaded && cached.members) { |
| | | const myId = getCurrentUserId() |
| | | return cached.members.some((m) => m.userId === myId && m.status === CommonStatusEnum.ENABLE) |
| | | } |
| | | return true |
| | | }) |
| | | /** åå²é群群ï¼åªè¯»ï¼å¨ä½åºä¸¤ä¸ªæé®é½ä¸æ¸²æï¼æ¢ä¸ãè¿å
¥ç¾¤èãä¹ä¸ãå å
¥ç¾¤èãï¼ */ |
| | | const isQuitGroup = computed(() => { |
| | | const id = props.group?.id |
| | | return id != null && isGroupQuit(groupStore.getGroup(id)) |
| | | }) |
| | | /** æ¯å¦æªå ç¾¤ï¼æ idãéæåãä¸éåå²é群群ï¼åªæç·éç人æç»ãå å
¥ç¾¤èã */ |
| | | const isStranger = computed(() => !!props.group?.id && !isMember.value && !isQuitGroup.value) |
| | | |
| | | /** æåæ°ææ¡ï¼member ä¼å
ç¨æ¬å°æå°çå表é¿åº¦ï¼stranger ç¨ props.group.memberCount å¡çå¿«ç
§ */ |
| | | const memberCountText = computed(() => { |
| | | const count = isMember.value |
| | | ? props.group.memberCount || members.value.length |
| | | : props.group.memberCount |
| | | return count ? `${count} 使å` : '' |
| | | }) |
| | | |
| | | /** member å群 / é¦æï¼ææåï¼ç«æç¨ group.id æ¯å¯¹ä¸¢å¼éæ§ååºé¿å
ä¸ä¸æ¡ç¾¤æåéä½ */ |
| | | watch( |
| | | () => [props.group?.id, isMember.value] as const, |
| | | async ([id, member]) => { |
| | | members.value = [] |
| | | if (!id || !member) { |
| | | return |
| | | } |
| | | const list = await groupStore.fetchGroupMemberList(id, true) |
| | | if (props.group?.id !== id) { |
| | | return |
| | | } |
| | | members.value = list.map((m) => convertGroupMemberLite(m, friendStore.getFriend(m.userId))) |
| | | }, |
| | | { immediate: true } |
| | | ) |
| | | |
| | | /** 群æå â å表项 */ |
| | | function convertGroupMemberLite(member: GroupMember, friend: Friend | undefined): GroupMemberLite { |
| | | return { |
| | | userId: member.userId, |
| | | showName: getMemberDisplayName(member, friend), |
| | | nickname: member.nickname, |
| | | avatar: member.avatar, |
| | | status: member.status, |
| | | role: member.role |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <!-- |
| | | 群信æ¯å
容ç»ä»¶ï¼ä¸ UserInfo 对ä½ï¼ |
| | | - 头å + 群å + æåæ° + æåå®«æ ¼ + å¨ä½åºï¼çº¯å±ç¤º + æäºä»¶ï¼ä¸å¡ç±ç¶çº§æ¿æ¥ |
| | | - relation èµ° groupStore ç¼åæ¨å¯¼ï¼å½ä¸ = memberï¼å·²å 群ï¼ï¼å¦å = strangerï¼æªå 群ï¼ï¼æ id = readonly |
| | | - æåå®«æ ¼ä»
member æ¶æåï¼éç群æä¸å°ï¼ææä¿¡æ¯èµ° props.group å¡çå¿«ç
§ï¼ |
| | | --> |
| | | <div class="flex justify-center"> |
| | | <div class="w-full max-w-[320px] flex flex-col gap-3 items-center"> |
| | | <GroupAvatar |
| | | :group-id="group.id" |
| | | :url="group.showImage || group.showImageThumb" |
| | | :name="group.showGroupName || group.name" |
| | | :size="72" |
| | | :previewable="isMember" |
| | | /> |
| | | <div |
| | | class="w-full text-lg font-semibold leading-snug text-[var(--ant-color-text)] truncate text-center" |
| | | > |
| | | {{ group.showGroupName || group.name }} |
| | | </div> |
| | | <div v-if="memberCountText" class="text-13px text-[var(--ant-color-text-secondary)]"> |
| | | {{ memberCountText }} |
| | | </div> |
| | | |
| | | <!-- æåå®«æ ¼ï¼ä»
member 渲æï¼éç群æä¸å°æåï¼ --> |
| | | <div |
| | | v-if="isMember && members.length > 0" |
| | | class="flex flex-wrap gap-2 justify-center w-full pt-2" |
| | | > |
| | | <GroupMemberGrid |
| | | v-for="member in members" |
| | | :key="member.userId" |
| | | :member="member" |
| | | :group-name="group.name" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- å¨ä½åºï¼member è¿å
¥ç¾¤è / stranger å å
¥ç¾¤è / readonly 䏿¸²æ --> |
| | | <div v-if="isMember" class="mt-4"> |
| | | <Button type="primary" @click="emit('chat', group)">è¿å
¥ç¾¤è</Button> |
| | | </div> |
| | | <div v-else-if="isStranger" class="mt-4"> |
| | | <Button type="primary" @click="emit('apply', group)">å å
¥ç¾¤è</Button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |