瀏覽代碼

名字表情

liuq 1 月之前
父節點
當前提交
2dc68c49a5

+ 27 - 4
src/renderer/src/App.tsx

@@ -15,6 +15,7 @@ import { UserContact, api } from './services/api'
 import { logger } from './utils/logger'
 import { formatFullDateTime } from './utils/timeUtils'
 import { formatApiMessageToMessage } from './utils/formatMessage'
+import { formatConversationRemark } from './utils/conversationRemark'
 import { getDefaultAvatar, getSessionAvatar } from './utils/avatarUtils'
 import { Contact, Message, SearchResult } from './types'
 
@@ -411,7 +412,8 @@ function App(): JSX.Element {
         avatar: getSessionAvatar(contact.id, contact.name || contact.english_name, 40),
         lastMessage: undefined,
         lastMessageTime: undefined,
-        unreadCount: 0
+        unreadCount: 0,
+        remarks: undefined
       }
 
       setContacts(prev => [newContact, ...prev])
@@ -585,7 +587,9 @@ function App(): JSX.Element {
             )}
           </div>
           <div style={{ flex: 1, overflowY: 'auto' }}>
-            {contacts.map(contact => (
+            {contacts.map(contact => {
+              const remarkLabel = formatConversationRemark(contact.remarks)
+              return (
               <div
                 key={contact.id}
                 className={`contact-item ${contact.id === activeContactId ? 'active' : ''}`}
@@ -626,7 +630,25 @@ function App(): JSX.Element {
                 </div>
                 <div style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
                   <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
-                    <span style={{ fontWeight: '500', fontSize: '14px', color: '#000' }}>{contact.name}</span>
+                    <div style={{ display: 'flex', alignItems: 'center', flex: 1, marginRight: '8px', flexWrap: 'wrap' }}>
+                      <span style={{ fontWeight: '500', fontSize: '14px', color: '#000' }}>
+                        {contact.name}
+                      </span>
+                      {remarkLabel && (
+                        <span
+                          style={{
+                            fontSize: '11px',
+                            color: '#d97706',
+                            marginLeft: '2px',
+                            whiteSpace: 'nowrap',
+                            display: 'inline-block'
+                          }}
+                          title={remarkLabel}
+                        >
+                          {remarkLabel}
+                        </span>
+                      )}
+                    </div>
                     <span style={{ fontSize: '10px', color: '#999' }}>{contact.lastMessageTime}</span>
                   </div>
                   <div style={{ fontSize: '12px', color: '#888', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
@@ -634,7 +656,8 @@ function App(): JSX.Element {
                   </div>
                 </div>
               </div>
-            ))}
+              )
+            })}
           </div>
         </>
       )

+ 2 - 1
src/renderer/src/hooks/useContacts.ts

@@ -59,7 +59,8 @@ export function useContacts(
         avatar: getSessionAvatar(contact.id, contact.name, 40),
         lastMessage: contact.last_message,
         lastMessageTime: contact.last_message_time ? formatMessageTime(contact.last_message_time) : undefined,
-        unreadCount: contact.unread_count ?? 0
+        unreadCount: contact.unread_count ?? 0,
+        remarks: contact.remarks ?? null
       }))
 
       setContacts(formattedContacts)

+ 2 - 1
src/renderer/src/hooks/useWebSocket.ts

@@ -166,7 +166,8 @@ export function useWebSocket({
             avatar: getSessionAvatar(targetContactId, systemName, 40),
             lastMessage: undefined,
             lastMessageTime: undefined,
-            unreadCount: 0
+            unreadCount: 0,
+            remarks: undefined
           }
           
           contact = systemContact

+ 20 - 2
src/renderer/src/pages/ChatPage.tsx

@@ -4,6 +4,7 @@ import { Contact, Message } from '../types'
 import { MessageBubble } from '../components/ChatWindow/MessageBubble'
 import { formatFullDateTime } from '../utils/timeUtils'
 import { isNotificationLikeMessage } from '../utils/messageTypes'
+import { formatConversationRemark } from '../utils/conversationRemark'
 import { getDefaultAvatar, getSessionAvatar } from '../utils/avatarUtils'
 
 interface ChatPageProps {
@@ -147,12 +148,29 @@ export const ChatPage: React.FC<ChatPageProps> = ({
 
   /** 负 id:应用系统通知会话(-app_id),只读,不展示发消息/发文件 */
   const isAppNotificationSession = activeContactId != null && activeContactId < 0
+  const headerRemark = formatConversationRemark(activeContact.remarks)
 
   return (
     <>
       <div style={{ padding: '0 20px', height: '60px', display: 'flex', alignItems: 'center', borderBottom: '1px solid #e7e7e7', WebkitAppRegion: 'drag' } as React.CSSProperties}>
-        <div style={{ fontWeight: 'bold', fontSize: '16px', WebkitAppRegion: 'no-drag' } as React.CSSProperties}>
-          {activeContact.name}
+        <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', WebkitAppRegion: 'no-drag' } as React.CSSProperties}>
+          <span style={{ fontWeight: 'bold', fontSize: '16px' }}>
+            {activeContact.name}
+          </span>
+          {headerRemark && (
+            <span
+              style={{
+                fontSize: '12px',
+                color: '#d97706',
+                marginLeft: '2px',
+                whiteSpace: 'nowrap',
+                display: 'inline-block'
+              }}
+              title={headerRemark}
+            >
+              {headerRemark}
+            </span>
+          )}
         </div>
       </div>
       

+ 3 - 1
src/renderer/src/services/api.ts

@@ -44,6 +44,7 @@ export interface ContactResponse {
   last_message?: string;
   last_message_time?: string;
   unread_count?: number;
+  remarks?: string | null;
 }
 
 export interface UserContact {
@@ -916,7 +917,8 @@ export const api = {
       name: item.full_name || item.username || '未知用户',
       last_message: item.last_message,
       last_message_time: item.updated_at,
-      unread_count: item.unread_count || 0
+      unread_count: item.unread_count || 0,
+      remarks: item.remarks ?? null
     }));
   },
 

+ 1 - 0
src/renderer/src/types/index.ts

@@ -24,6 +24,7 @@ export interface Contact {
   lastMessage?: string
   lastMessageTime?: string
   unreadCount: number
+  remarks?: string | null
 }
 
 export interface SearchResult {

+ 12 - 0
src/renderer/src/utils/conversationRemark.ts

@@ -0,0 +1,12 @@
+export function formatConversationRemark(remark?: string | null): string | null {
+  if (remark == null) {
+    return null
+  }
+
+  const normalized = remark.trim()
+  if (!normalized) {
+    return null
+  }
+
+  return `@${normalized}`
+}