diff --git a/src/components/modals/ShareModal.vue b/src/components/modals/ShareModal.vue index 0af6fbc..3e628a5 100644 --- a/src/components/modals/ShareModal.vue +++ b/src/components/modals/ShareModal.vue @@ -34,18 +34,14 @@
- 已选择 {{ selectedCount }} 个对话 - 最多分享 10 个对话 + 当前对话 + 仅支持单个对话分享
-
-
+
+
- {{ conv.title }} - {{ conv.messages.length }} 条消息 + {{ shareConversation.title }} + {{ shareConversation.messages.length }} 条消息
@@ -120,10 +116,15 @@ const settingsStore = useSettingsStore(); const chatStore = useChatStore(); const show = computed(() => settingsStore.showShareModal); -const { selectedConversations, selectedCount, isMessageSelectMode, selectedMessages, selectedMessageCount } = storeToRefs(chatStore); +const { shareConversationId } = storeToRefs(settingsStore); +const { isMessageSelectMode, selectedMessages, selectedMessageCount } = storeToRefs(chatStore); // 是否是消息分享模式 const isMessageShare = computed(() => isMessageSelectMode.value); +const shareConversation = computed(() => { + if (!shareConversationId.value) return null; + return chatStore.conversations.find((c) => c.id === shareConversationId.value) || null; +}); const password = ref(""); const showPassword = ref(false); @@ -173,16 +174,13 @@ async function handleCreateShare() { }); } else { // 对话分享模式 - // 检查数量限制 - if (selectedCount.value > SHARE_LIMITS.MAX_CONVERSATIONS) { - window.$toast?.(`最多分享 ${SHARE_LIMITS.MAX_CONVERSATIONS} 个对话`, 'error'); + if (!shareConversation.value) { + window.$toast?.('请先选择要分享的对话', 'error'); return; } - const conversationIds = selectedConversations.value.map(c => c.id); - result = await shareApi.createShare({ - conversationIds, + conversationIds: [shareConversation.value.id], passwordHash, expiresIn: SHARE_LIMITS.DEFAULT_EXPIRE_SECONDS, }); @@ -207,8 +205,6 @@ async function handleCreateShare() { password.value = ""; if (isMessageShare.value) { chatStore.exitMessageSelectMode(); - } else { - chatStore.exitSelectMode(); } } catch (error) { diff --git a/src/components/sidebar/ChatSidebar.vue b/src/components/sidebar/ChatSidebar.vue index 634b9a5..4ed87dc 100644 --- a/src/components/sidebar/ChatSidebar.vue +++ b/src/components/sidebar/ChatSidebar.vue @@ -76,7 +76,7 @@
@@ -91,7 +91,7 @@ @@ -210,6 +210,10 @@ function togglePinConversation(id: string) { chatStore.togglePinConversation(id); } +function handleShareConversation(id: string) { + settingsStore.openConversationShareModal(id); +} + function toggleConversationSelection(id: string) { chatStore.toggleConversationSelection(id); } diff --git a/src/components/sidebar/ConversationItem.vue b/src/components/sidebar/ConversationItem.vue index f04509e..b722e71 100644 --- a/src/components/sidebar/ConversationItem.vue +++ b/src/components/sidebar/ConversationItem.vue @@ -52,7 +52,7 @@ @@ -108,6 +108,7 @@ const emit = defineEmits<{ rename: [id: string, title: string]; togglePin: [id: string]; toggleSelect: [id: string]; + share: [id: string]; }>(); const isEditing = ref(false); @@ -134,6 +135,10 @@ function handleTogglePin() { emit("togglePin", props.conversation.id); } +function handleShare() { + emit("share", props.conversation.id); +} + function handleRename() { if (props.isSelectMode) return; isEditing.value = true; @@ -201,6 +206,11 @@ function handleDelete() { .item-title { font-weight: 700; } + + .item-actions { + opacity: 1; + pointer-events: auto; + } } } @@ -278,6 +288,10 @@ function handleDelete() { transition: opacity 0.2s ease; } +.conversation-item.active .pin-indicator { + opacity: 0; +} + .action-btn { display: flex; align-items: center; diff --git a/src/components/sidebar/ShareButton.vue b/src/components/sidebar/ShareButton.vue index 0d9ab1d..0c56b28 100644 --- a/src/components/sidebar/ShareButton.vue +++ b/src/components/sidebar/ShareButton.vue @@ -1,32 +1,9 @@ @@ -39,21 +16,12 @@ import { Share2 } from "@/components/icons"; const chatStore = useChatStore(); const settingsStore = useSettingsStore(); -const { isSelectMode, selectedCount, conversations } = storeToRefs(chatStore); +const { currentConversation } = storeToRefs(chatStore); -function handleStartSelect() { - chatStore.enterSelectMode(); -} - -function handleCancel() { - chatStore.exitSelectMode(); -} - -function handleConfirm() { - if (chatStore.selectedCount > 0) { - // 打开分享设置模态框 - settingsStore.openShareModal(); - } +function handleShareCurrent() { + const conversation = currentConversation.value; + if (!conversation) return; + settingsStore.openConversationShareModal(conversation.id); } @@ -162,4 +130,4 @@ function handleConfirm() { } } } - \ No newline at end of file + diff --git a/src/router/index.ts b/src/router/index.ts index 8b44679..2c8f84a 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -13,6 +13,7 @@ const router = createRouter({ path: '/share/:id', name: 'share', component: () => import('@/views/ShareView.vue'), + alias: ['/chat-ui/share/:id'], }, { path: '/demo/cards', @@ -22,4 +23,4 @@ const router = createRouter({ ], }) -export default router \ No newline at end of file +export default router diff --git a/src/stores/settings.ts b/src/stores/settings.ts index d9a532c..fd26f86 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -101,6 +101,7 @@ export const useSettingsStore = defineStore("settings", () => { const showShareModal = ref(false); const showShareResultModal = ref(false); const shareResult = ref(null); + const shareConversationId = ref(null); // 主题相关 function applyTheme(theme: AppSettings["theme"]) { @@ -196,8 +197,14 @@ export const useSettingsStore = defineStore("settings", () => { showShareModal.value = true; } + function openConversationShareModal(conversationId: string) { + shareConversationId.value = conversationId; + showShareModal.value = true; + } + function closeShareModal() { showShareModal.value = false; + shareConversationId.value = null; } function openShareResultModal() { @@ -343,6 +350,7 @@ export const useSettingsStore = defineStore("settings", () => { showShareModal, showShareResultModal, shareResult, + shareConversationId, // 方法 toggleTheme, @@ -360,6 +368,7 @@ export const useSettingsStore = defineStore("settings", () => { closeConversationSettingsModal, // 分享模态框方法 openShareModal, + openConversationShareModal, closeShareModal, openShareResultModal, closeShareResultModal, diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index d801ca0..0dce253 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -10,21 +10,36 @@ export function formatTimestamp(timestamp: number): string { const date = new Date(timestamp); const now = new Date(); const diff = now.getTime() - date.getTime(); + const absDiff = Math.abs(diff); - if (diff < 60 * 1000) { + if (diff >= 0 && diff < 60 * 1000) { return "刚刚"; } - if (diff < 60 * 60 * 1000) { + if (diff < 0 && absDiff < 60 * 1000) { + return "即将"; + } + + if (diff >= 0 && diff < 60 * 60 * 1000) { const minutes = Math.floor(diff / (60 * 1000)); return `${minutes}分钟前`; } - if (diff < 24 * 60 * 60 * 1000) { + if (diff < 0 && absDiff < 60 * 60 * 1000) { + const minutes = Math.floor(absDiff / (60 * 1000)); + return `${minutes}分钟后`; + } + + if (diff >= 0 && diff < 24 * 60 * 60 * 1000) { const hours = Math.floor(diff / (60 * 60 * 1000)); return `${hours}小时前`; } + if (diff < 0 && absDiff < 24 * 60 * 60 * 1000) { + const hours = Math.floor(absDiff / (60 * 60 * 1000)); + return `${hours}小时后`; + } + if (date.getFullYear() === now.getFullYear()) { return `${date.getMonth() + 1}月${date.getDate()}日 ${padZero(date.getHours())}:${padZero(date.getMinutes())}`; }