([]) // 用于 OwnerEntryCard(仅加载一次)
const isLoading = ref(false)
const searchQuery = ref('')
@@ -107,7 +107,7 @@ async function loadMembers() {
}
}
-// 加载所有成员(用于 OwnerSelector)
+// 加载所有成员(用于 OwnerEntryCard)
async function loadAllMembers() {
if (!props.sessionId) return
try {
@@ -166,7 +166,7 @@ async function confirmDelete() {
if (success) {
// 重新加载当前页数据
await loadMembers()
- // 同时更新 allMembers(用于 OwnerSelector)
+ // 同时更新 allMembers(用于 OwnerEntryCard)
await loadAllMembers()
// 通知父组件刷新数据
emit('data-changed')
@@ -275,13 +275,7 @@ onMounted(() => {
-
+
diff --git a/src/i18n/locales/en-US/members.json b/src/i18n/locales/en-US/members.json
index 55459ff3..ad37170e 100644
--- a/src/i18n/locales/en-US/members.json
+++ b/src/i18n/locales/en-US/members.json
@@ -1,10 +1,22 @@
{
- "ownerSelector": {
- "title": "Select Your Identity",
- "unset": "Not Set",
- "selectMember": "Select Member",
- "currentOwner": "Current: {name}",
- "hint": "1. Shown on the right side of chat viewer 2. Identifies you in AI conversations"
+ "ownerPrompt": {
+ "title": "Who Are You?",
+ "subtitle": "Select your identity in this chat",
+ "description": "Your messages will appear on the right side of the chat viewer, and AI conversations can identify you for more accurate analysis. Other chats from the same platform will be filled in automatically.",
+ "searchPlaceholder": "Search members",
+ "noMatch": "No matching members found",
+ "empty": "No member data",
+ "later": "Later",
+ "dontRemind": "Don't remind me for this chat",
+ "save": "Save",
+ "clear": "Clear current selection",
+ "saved": "Your identity has been set",
+ "appliedToOthers": "Automatically applied to {count} chats from the same platform",
+ "saveFailed": "Failed to set identity",
+ "currentOwner": "I am: {name}",
+ "choose": "Choose who I am",
+ "change": "Change",
+ "helper": "Helps AI identify you in conversations for more accurate analysis"
},
"list": {
"title": "Group Member Management",
diff --git a/src/i18n/locales/ja-JP/members.json b/src/i18n/locales/ja-JP/members.json
index e0658ee0..1de3fcbc 100644
--- a/src/i18n/locales/ja-JP/members.json
+++ b/src/i18n/locales/ja-JP/members.json
@@ -1,10 +1,22 @@
{
- "ownerSelector": {
- "title": "あなたを選択してください",
- "unset": "未設定",
- "selectMember": "メンバーを選択",
- "currentOwner": "現在:{name}",
- "hint": "1. チャット履歴ビューアの右側に表示されます 2. AI との会話ではあなた本人として扱われます"
+ "ownerPrompt": {
+ "title": "あなたはどなたですか?",
+ "subtitle": "このチャットでのあなたの身元を選択してください",
+ "description": "設定するとあなたのメッセージがチャット履歴ビューアの右側に表示され、AI との会話でもあなた本人として認識され、分析がより正確になります。同じプラットフォームの他のチャットにも自動的に適用されます。",
+ "searchPlaceholder": "メンバーを検索",
+ "noMatch": "一致するメンバーが見つかりません",
+ "empty": "メンバーデータがありません",
+ "later": "後で",
+ "dontRemind": "このチャットでは再通知しない",
+ "save": "保存",
+ "clear": "現在の選択をクリア",
+ "saved": "あなたの身元を設定しました",
+ "appliedToOthers": "同じプラットフォームの {count} 件のチャットに自動適用しました",
+ "saveFailed": "身元の設定に失敗しました",
+ "currentOwner": "私は:{name}",
+ "choose": "自分を選択",
+ "change": "変更",
+ "helper": "設定すると AI があなたを認識し、分析がより正確になります"
},
"list": {
"title": "メンバー管理",
diff --git a/src/i18n/locales/zh-CN/members.json b/src/i18n/locales/zh-CN/members.json
index 093536a0..5ff808bc 100644
--- a/src/i18n/locales/zh-CN/members.json
+++ b/src/i18n/locales/zh-CN/members.json
@@ -1,10 +1,22 @@
{
- "ownerSelector": {
- "title": "选择你是谁",
- "unset": "未设置",
- "selectMember": "选择成员",
- "currentOwner": "当前:{name}",
- "hint": "1. 将会显示在聊天记录查看器中的右侧 2. AI对话中会标识你的身份"
+ "ownerPrompt": {
+ "title": "你是谁?",
+ "subtitle": "选择你在这个对话中的身份",
+ "description": "设置后你的消息会显示在聊天记录查看器右侧,AI 对话也能识别你的身份,分析更准确。同平台的其他对话会自动套用。",
+ "searchPlaceholder": "搜索成员",
+ "noMatch": "没有找到匹配的成员",
+ "empty": "暂无成员数据",
+ "later": "稍后",
+ "dontRemind": "本会话不再提醒",
+ "save": "保存",
+ "clear": "清除当前选择",
+ "saved": "已设置你的身份",
+ "appliedToOthers": "已自动应用到 {count} 个同平台会话",
+ "saveFailed": "设置身份失败",
+ "currentOwner": "我是:{name}",
+ "choose": "选择我是谁",
+ "change": "修改",
+ "helper": "设置后 AI 对话能识别你的身份,分析更准确"
},
"list": {
"title": "成员管理",
diff --git a/src/i18n/locales/zh-TW/members.json b/src/i18n/locales/zh-TW/members.json
index 0b17fad0..3331141e 100644
--- a/src/i18n/locales/zh-TW/members.json
+++ b/src/i18n/locales/zh-TW/members.json
@@ -1,10 +1,22 @@
{
- "ownerSelector": {
- "title": "選擇你是誰",
- "unset": "未設定",
- "selectMember": "選擇成員",
- "currentOwner": "目前:{name}",
- "hint": "1. 會顯示在聊天紀錄檢視器右側 2. AI 對話中也會標示你的身分"
+ "ownerPrompt": {
+ "title": "你是誰?",
+ "subtitle": "選擇你在這個對話中的身分",
+ "description": "設定後你的訊息會顯示在聊天紀錄檢視器右側,AI 對話也能識別你的身分,分析更準確。同平台的其他對話會自動套用。",
+ "searchPlaceholder": "搜尋成員",
+ "noMatch": "沒有找到符合的成員",
+ "empty": "暫無成員資料",
+ "later": "稍後",
+ "dontRemind": "此對話不再提醒",
+ "save": "儲存",
+ "clear": "清除目前選擇",
+ "saved": "已設定你的身分",
+ "appliedToOthers": "已自動套用到 {count} 個同平台對話",
+ "saveFailed": "設定身分失敗",
+ "currentOwner": "我是:{name}",
+ "choose": "選擇我是誰",
+ "change": "修改",
+ "helper": "設定後 AI 對話能識別你的身分,分析更準確"
},
"list": {
"title": "成員管理",
diff --git a/src/pages/group-chat/index.vue b/src/pages/group-chat/index.vue
index dd95846c..f2bc025a 100644
--- a/src/pages/group-chat/index.vue
+++ b/src/pages/group-chat/index.vue
@@ -13,6 +13,7 @@ import MemberList from '@/components/common/member/MemberList.vue'
import NicknameHistoryEntry from './components/member/NicknameHistoryEntry.vue'
import SessionAnalysisHeader from '@/components/layout/session/SessionAnalysisHeader.vue'
import SessionIndexModal from '@/components/analysis/SessionIndexModal.vue'
+import OwnerPromptModal from '@/components/analysis/member/OwnerPromptModal.vue'
import IncrementalImportModal from '@/components/analysis/IncrementalImportModal.vue'
const MessageExportModal = defineAsyncComponent(() => import('@/components/MessageExport/MessageExportModal.vue'))
import ActionToolsPanel from '@/components/layout/ActionToolsPanel.vue'
@@ -35,6 +36,9 @@ const { currentSessionId } = storeToRefs(sessionStore)
// 会话索引弹窗状态
const showSessionIndexModal = ref(false)
+// "我是谁"提示弹窗状态
+const showOwnerPromptModal = ref(false)
+
// 增量导入弹窗状态
const showIncrementalImportModal = ref(false)
@@ -219,6 +223,15 @@ const filteredMemberCount = computed(() => {
:message-count="session.messageCount"
/>
+
+
+
{
-
+
diff --git a/src/pages/private-chat/index.vue b/src/pages/private-chat/index.vue
index e143b54d..e4f76a6a 100644
--- a/src/pages/private-chat/index.vue
+++ b/src/pages/private-chat/index.vue
@@ -12,6 +12,7 @@ import ViewTab from './components/ViewTab.vue'
import MemberManagementPanel from './components/MemberTab.vue'
import SessionAnalysisHeader from '@/components/layout/session/SessionAnalysisHeader.vue'
import SessionIndexModal from '@/components/analysis/SessionIndexModal.vue'
+import OwnerPromptModal from '@/components/analysis/member/OwnerPromptModal.vue'
import IncrementalImportModal from '@/components/analysis/IncrementalImportModal.vue'
const MessageExportModal = defineAsyncComponent(() => import('@/components/MessageExport/MessageExportModal.vue'))
import ActionToolsPanel from '@/components/layout/ActionToolsPanel.vue'
@@ -34,6 +35,9 @@ const { currentSessionId } = storeToRefs(sessionStore)
// 会话索引弹窗状态
const showSessionIndexModal = ref(false)
+// "我是谁"提示弹窗状态
+const showOwnerPromptModal = ref(false)
+
// 增量导入弹窗状态
const showIncrementalImportModal = ref(false)
@@ -229,6 +233,15 @@ const otherMemberAvatar = computed(() => {
:message-count="session.messageCount"
/>
+
+
+
{
+ return post(`/sessions/${sessionId}/owner/apply-profile`, {})
+ }
+
+ setOwnerAndApplyProfile(sessionId: string, ownerPlatformId: string): Promise {
+ return post(`/sessions/${sessionId}/owner/select`, { ownerPlatformId })
+ }
+
+ async dismissOwnerPrompt(sessionId: string): Promise {
+ const result = await post<{ success: boolean }>(`/sessions/${sessionId}/owner/dismiss-prompt`, {})
+ return result.success
+ }
+
// ==================== 时间范围 ====================
getAvailableYears(sessionId: string): Promise {
diff --git a/src/services/data/types.ts b/src/services/data/types.ts
index fca94810..e61de9d1 100644
--- a/src/services/data/types.ts
+++ b/src/services/data/types.ts
@@ -6,7 +6,7 @@
*/
import type { AnalysisSession, MessageType } from '@/types/base'
-import type { TimeFilter } from '@openchatlab/shared-types'
+import type { TimeFilter, ApplyOwnerProfileResult, SetOwnerAndApplyProfileResult } from '@openchatlab/shared-types'
import type {
MemberActivity,
MemberWithStats,
@@ -86,6 +86,9 @@ export interface DataAdapter {
deleteSession(sessionId: string): Promise
renameSession(sessionId: string, newName: string): Promise
updateSessionOwnerId(sessionId: string, ownerId: string | null): Promise
+ tryApplyOwnerProfile(sessionId: string): Promise
+ setOwnerAndApplyProfile(sessionId: string, ownerPlatformId: string): Promise
+ dismissOwnerPrompt(sessionId: string): Promise
// ==================== 时间范围 ====================
diff --git a/src/stores/session.ts b/src/stores/session.ts
index 4d7814e9..c2875797 100644
--- a/src/stores/session.ts
+++ b/src/stores/session.ts
@@ -290,6 +290,8 @@ export const useSessionStore = defineStore(
console.error('自动生成会话索引失败:', error)
}
+ await applyOwnerProfileAfterImport(importResult.sessionId)
+
return { success: true, diagnostics: importResult.diagnostics }
} else {
return {
@@ -420,6 +422,7 @@ export const useSessionStore = defineStore(
} catch (error) {
console.error('自动生成会话索引失败:', error)
}
+ await applyOwnerProfileAfterImport(importResult.sessionId)
} else {
file.status = 'failed'
file.error = importResult.error || 'error.import_failed'
@@ -443,6 +446,7 @@ export const useSessionStore = defineStore(
console.error('自动生成会话索引失败:', error)
}
}
+ await applyOwnerProfileAfterImport(importResult.sessionId)
} else {
file.status = 'failed'
file.error = importResult.error || 'error.import_failed'
@@ -684,6 +688,53 @@ export const useSessionStore = defineStore(
}
}
+ /**
+ * 手动选择"我是谁":写入当前会话 owner,更新平台 owner profile,
+ * 并批量应用到同平台其他未设置 owner 的会话
+ */
+ async function setOwnerAndApplyProfile(id: string, ownerPlatformId: string) {
+ const result = await useDataService().setOwnerAndApplyProfile(id, ownerPlatformId)
+ for (const sessionId of [id, ...result.updatedSessionIds]) {
+ const session = sessions.value.find((s) => s.id === sessionId)
+ if (session) {
+ session.ownerId = result.ownerId
+ }
+ }
+ return result
+ }
+
+ /**
+ * 尝试用已保存的平台 owner profile 自动补全会话 owner(唯一匹配才写入)
+ */
+ async function tryApplyOwnerProfile(id: string) {
+ const result = await useDataService().tryApplyOwnerProfile(id)
+ if (result.applied && result.ownerId) {
+ const session = sessions.value.find((s) => s.id === id)
+ if (session) {
+ session.ownerId = result.ownerId
+ }
+ }
+ return result
+ }
+
+ /**
+ * 本会话不再提醒"选择我是谁"(仅抑制弹窗,不影响自动补全)
+ */
+ function dismissOwnerPrompt(id: string): Promise {
+ return useDataService().dismissOwnerPrompt(id)
+ }
+
+ /**
+ * 导入成功后静默尝试应用平台 owner profile(失败不影响导入流程)
+ */
+ async function applyOwnerProfileAfterImport(id: string): Promise {
+ try {
+ await tryApplyOwnerProfile(id)
+ } catch (error) {
+ console.warn('导入后应用 owner profile 失败:', error)
+ }
+ }
+
// 置顶会话 ID 列表
const pinnedSessionIds = ref([])
@@ -774,6 +825,9 @@ export const useSessionStore = defineStore(
renameSession,
clearSelection,
updateSessionOwnerId,
+ setOwnerAndApplyProfile,
+ tryApplyOwnerProfile,
+ dismissOwnerPrompt,
togglePinSession,
isPinned,
// 批量导入