From 91c82965b2d987452ca276e3a03b48c8dcda2ae9 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 19 八月 2026 11:47:26 +0800
Subject: [PATCH] config(env): 更新生产环境配置和公司名称

---
 src/views/im/home/pages/contact/friend-request-list.vue |  138 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/src/views/im/home/pages/contact/friend-request-list.vue b/src/views/im/home/pages/contact/friend-request-list.vue
new file mode 100644
index 0000000..f5044fc
--- /dev/null
+++ b/src/views/im/home/pages/contact/friend-request-list.vue
@@ -0,0 +1,138 @@
+<script lang="ts" setup>
+import type { FriendRequest } from '../../types'
+
+import { computed, ref } from 'vue'
+
+import { DICT_TYPE } from '#/packages/constants/src'
+import { getDictLabel } from '#/packages/effects/hooks/src'
+import { IconifyIcon as Icon } from '#/packages/icons/src'
+
+import { Badge } from 'ant-design-vue'
+
+import { getCurrentUserId } from '#/views/im/utils/auth'
+
+import { UserAvatar } from '../../components/user'
+import { useFriendStore } from '../../store/friendStore'
+
+defineOptions({ name: 'ImContactFriendRequestList' })
+
+const props = defineProps<{
+  activeId?: number
+  requests: FriendRequest[]
+}>()
+
+const emit = defineEmits<{
+  select: [request: FriendRequest]
+}>()
+
+const friendStore = useFriendStore()
+const expanded = ref(true)
+/** 褰撳墠鐧诲綍鐢ㄦ埛缂栧彿锛涚敤 computed 鍖呬竴灞傦紝鍒囪处鍙峰悗闅� wsCache 閲嶅彇锛岄伩鍏嶉《灞傛眰鍊煎湪 keep-alive 瀹炰緥閲屾寔鏈夋棫 id */
+const currentUserId = computed(() => getCurrentUserId())
+
+/** 鍒楄〃椤瑰睍绀哄绔細fromUserId == 鎴� 鈫� 瀵圭 = toUser锛涘惁鍒欏绔� = fromUser */
+function getPeer(request: FriendRequest) {
+  const sentByMe = request.fromUserId === currentUserId.value
+  return {
+    id: sentByMe ? request.toUserId : request.fromUserId,
+    nickname: sentByMe
+      ? request.toNickname || String(request.toUserId)
+      : request.fromNickname || String(request.fromUserId),
+    avatar: sentByMe ? request.toAvatar : request.fromAvatar
+  }
+}
+
+/** 鍒楄〃椤归鍏堥檮 peer 瀛楁锛屾ā鏉块噷鐩存帴 {{ peer.xxx }} 涓�娆℃垚鍨嬶紝鐪� 3 娆� helper 璋冪敤 */
+const enrichedRequests = computed(() =>
+  props.requests.map((request) => ({ request, peer: getPeer(request) }))
+)
+
+const loadingMore = ref(false) // 鐐瑰嚮銆屽姞杞芥洿澶氥�嶆媺涓嬩竴椤碉紱store 鍐呴儴鎸� maxId 娓告爣鍒嗛〉 + pending 鍘婚噸
+async function handleLoadMore() {
+  if (loadingMore.value) {
+    return
+  }
+  loadingMore.value = true
+  try {
+    await friendStore.loadMoreFriendRequestList()
+  } finally {
+    loadingMore.value = false
+  }
+}
+</script>
+
+<template>
+  <!--
+    閫氳褰� - 鏂扮殑鏈嬪弸鍒嗙粍
+    - 鑷不锛氭姌鍙犵姸鎬佺敱缁勪欢鍐� ref 绠$悊锛岄粯璁ゅ睍寮�
+    - 鍒楄〃椤瑰睍绀猴細澶村儚 + 鏄电О + 鐢宠鐞嗙敱 + 鐘舵�佹爣绛撅紙绛夊緟楠岃瘉 / 宸叉坊鍔� / 宸叉嫆缁濓級
+    - 閫変腑鎬佺敱鐖剁骇 activeId 閫忎紶锛涚偣鍑昏Е鍙� select 浜嬩欢
+  -->
+  <div>
+    <!-- 鎶樺彔鍒嗙粍澶� -->
+    <div
+      class="flex gap-2 items-center px-3.5 py-2.5 text-15px text-[var(--ant-color-text)] cursor-pointer select-none hover:bg-[var(--ant-color-fill-secondary)]"
+      @click="expanded = !expanded"
+    >
+      <Icon :icon="expanded ? 'ep:caret-bottom' : 'ep:caret-right'" :size="14" />
+      <span class="flex-1">鏂扮殑鏈嬪弸</span>
+      <!-- 绾㈢偣锛氭湭澶勭悊涓斿埆浜哄姞鎴戠殑锛堢粺涓�璧� store getter锛岄伩鍏嶆湰鍦� computed 璺� store 鍙屽彛寰勶級 -->
+      <Badge
+        v-if="friendStore.getUnhandledRequestCount > 0"
+        :count="friendStore.getUnhandledRequestCount"
+        :max="99"
+        class="mr-2"
+      />
+      <span class="text-sm text-[var(--ant-color-text-secondary)]">{{ requests.length }}</span>
+    </div>
+    <div v-show="expanded">
+      <div
+        v-for="{ request, peer } in enrichedRequests"
+        :key="request.id"
+        class="flex gap-3 items-start px-3.5 py-2.5 cursor-pointer transition-colors hover:bg-[var(--ant-color-fill-secondary)]"
+        :class="{
+          'bg-[var(--ant-color-fill)]': activeId === request.id
+        }"
+        @click="emit('select', request)"
+      >
+        <UserAvatar
+          :id="peer.id"
+          :url="peer.avatar"
+          :name="peer.nickname"
+          :size="36"
+          :clickable="false"
+        />
+        <div class="flex-1 min-w-0 overflow-hidden">
+          <div class="flex justify-between gap-2 items-center">
+            <span class="flex-1 text-sm font-medium truncate text-[var(--ant-color-text)]">
+              {{ peer.nickname }}
+            </span>
+            <span class="flex-shrink-0 text-12px text-[var(--ant-color-text-secondary)]">
+              {{ getDictLabel(DICT_TYPE.IM_FRIEND_REQUEST_HANDLE_RESULT, request.handleResult) }}
+            </span>
+          </div>
+          <div
+            v-if="request.applyContent"
+            class="mt-0.5 text-xs truncate text-[var(--ant-color-text-secondary)]"
+          >
+            {{ request.applyContent }}
+          </div>
+        </div>
+      </div>
+      <div
+        v-if="requests.length === 0"
+        class="py-3 text-12px text-center text-[var(--ant-color-text-disabled)]"
+      >
+        鏆傛棤鏂扮殑鏈嬪弸
+      </div>
+      <!-- 鍔犺浇鏇村锛氭寜鏈湴鏈�鏃� requestId 娓告爣鍒嗛〉鎷変笅涓�鎵癸紱hasMore=false 涓嶅睍绀� -->
+      <div
+        v-else-if="friendStore.hasMoreFriendRequests"
+        class="py-2 text-12px text-center cursor-pointer text-[var(--ant-color-text-secondary)] hover:bg-[var(--ant-color-fill-secondary)]"
+        @click="handleLoadMore"
+      >
+        {{ loadingMore ? '鍔犺浇涓��' : '鍔犺浇鏇村' }}
+      </div>
+    </div>
+  </div>
+</template>

--
Gitblit v1.9.3