Compare commits
No commits in common. "a130e0d3f5f020c5cfd67bd72230b3b4232fd773" and "b93178ec8535a1ee64f89a35e887b179f46ba722" have entirely different histories.
a130e0d3f5
...
b93178ec85
|
|
@ -41,6 +41,4 @@ skills-lock.json
|
||||||
*.db
|
*.db
|
||||||
server/data/*.db
|
server/data/*.db
|
||||||
|
|
||||||
scripts/deploy-frontend-standalone.sh
|
|
||||||
|
|
||||||
tsconfig.tsbuildinfo
|
tsconfig.tsbuildinfo
|
||||||
|
|
@ -96,6 +96,8 @@
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import {
|
import {
|
||||||
|
Menu,
|
||||||
|
Trash2,
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
Pin,
|
Pin,
|
||||||
Archive,
|
Archive,
|
||||||
|
|
@ -139,6 +141,12 @@ const showMoreMenu = ref(false);
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const { settings } = storeToRefs(settingsStore);
|
const { settings } = storeToRefs(settingsStore);
|
||||||
|
|
||||||
|
function handleClear() {
|
||||||
|
if (confirm("确定要清空当前对话吗?此操作不可恢复。")) {
|
||||||
|
emit("clear");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleShare() {
|
function handleShare() {
|
||||||
showMoreMenu.value = false;
|
showMoreMenu.value = false;
|
||||||
emit("share");
|
emit("share");
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import {
|
import {
|
||||||
|
MessageSquare,
|
||||||
Code,
|
Code,
|
||||||
|
Image,
|
||||||
|
FileText,
|
||||||
|
ChevronRight,
|
||||||
|
Keyboard,
|
||||||
|
Zap,
|
||||||
|
Globe,
|
||||||
|
Lightbulb,
|
||||||
|
PenTool,
|
||||||
} from "@/components/icons";
|
} from "@/components/icons";
|
||||||
import promptData from "@/assets/prompt.json";
|
import promptData from "@/assets/prompt.json";
|
||||||
import type { Suggestion } from "@/types/chat";
|
import type { Suggestion } from "@/types/chat";
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,7 @@ function showThrottledToast(message: string, type: "error" = "error") {
|
||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const charCount = computed(() => inputText.value.length);
|
const charCount = computed(() => inputText.value.length);
|
||||||
|
const isUploading = computed(() => attachments.value.some((a) => a.uploading));
|
||||||
const isProcessingAttachments = computed(() =>
|
const isProcessingAttachments = computed(() =>
|
||||||
attachments.value.some((a) => a.uploading || a.deleting),
|
attachments.value.some((a) => a.uploading || a.deleting),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,8 @@ import { ref } from "vue";
|
||||||
import MarkdownRender from "markstream-vue";
|
import MarkdownRender from "markstream-vue";
|
||||||
import { setCustomComponents } from "markstream-vue";
|
import { setCustomComponents } from "markstream-vue";
|
||||||
import {
|
import {
|
||||||
|
Bot,
|
||||||
|
User,
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
Zap,
|
Zap,
|
||||||
|
|
@ -168,6 +170,7 @@ import {
|
||||||
Check,
|
Check,
|
||||||
} from "@/components/icons";
|
} from "@/components/icons";
|
||||||
import { NImage, NImageGroup } from "naive-ui";
|
import { NImage, NImageGroup } from "naive-ui";
|
||||||
|
import MessageActions from "./MessageActions.vue";
|
||||||
import { formatFileSize, getFileIcon } from "@/utils/helpers";
|
import { formatFileSize, getFileIcon } from "@/utils/helpers";
|
||||||
import type { Message, Suggestion, Attachment, VideoInfo } from "@/types/chat";
|
import type { Message, Suggestion, Attachment, VideoInfo } from "@/types/chat";
|
||||||
import ThinkingNode from "./components/ThinkingNode.vue";
|
import ThinkingNode from "./components/ThinkingNode.vue";
|
||||||
|
|
@ -220,6 +223,11 @@ function handleToggleSelect() {
|
||||||
emit("toggle-select");
|
emit("toggle-select");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理分享按钮点击(进入选择模式)
|
||||||
|
function handleShareClick() {
|
||||||
|
emit("enter-select-mode");
|
||||||
|
}
|
||||||
|
|
||||||
function getFileEmoji(mimeType?: string) {
|
function getFileEmoji(mimeType?: string) {
|
||||||
return getFileIcon(mimeType || "");
|
return getFileIcon(mimeType || "");
|
||||||
}
|
}
|
||||||
|
|
@ -240,6 +248,18 @@ function textCopy(data: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCopy() {
|
||||||
|
emit("copy");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLike() {
|
||||||
|
emit("like");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDislike() {
|
||||||
|
emit("dislike");
|
||||||
|
}
|
||||||
|
|
||||||
setCustomComponents("playground-demo", {
|
setCustomComponents("playground-demo", {
|
||||||
think: ThinkingNode,
|
think: ThinkingNode,
|
||||||
vmr_container: EChartsContainerNode,
|
vmr_container: EChartsContainerNode,
|
||||||
|
|
|
||||||
|
|
@ -135,10 +135,12 @@ import { useChatStore } from "@/stores/chat";
|
||||||
import { useSettingsStore } from "@/stores/settings";
|
import { useSettingsStore } from "@/stores/settings";
|
||||||
import { chatApi } from "@/services/api.ts";
|
import { chatApi } from "@/services/api.ts";
|
||||||
import ConversationItem from "./ConversationItem.vue";
|
import ConversationItem from "./ConversationItem.vue";
|
||||||
|
import ShareButton from "./ShareButton.vue";
|
||||||
import {
|
import {
|
||||||
Plus,
|
Plus,
|
||||||
Pin,
|
Pin,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
|
Check,
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
} from "@/components/icons";
|
} from "@/components/icons";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,48 @@ const defaultColors = [
|
||||||
'#ec4899', // pink
|
'#ec4899', // pink
|
||||||
]
|
]
|
||||||
|
|
||||||
|
function formatFileSize(size?: number) {
|
||||||
|
if (!size || size <= 0) return ''
|
||||||
|
const units = ['B', 'KB', 'MB', 'GB']
|
||||||
|
let value = size
|
||||||
|
let unitIndex = 0
|
||||||
|
|
||||||
|
while (value >= 1024 && unitIndex < units.length - 1) {
|
||||||
|
value /= 1024
|
||||||
|
unitIndex += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const display = value >= 10 || unitIndex === 0 ? Math.round(value) : value.toFixed(1)
|
||||||
|
return `${display} ${units[unitIndex]}`
|
||||||
|
}
|
||||||
|
|
||||||
function getCardTitle(card: CardItem, index: number) {
|
function getCardTitle(card: CardItem, index: number) {
|
||||||
return card.title || card.name || `Card ${index + 1}`
|
return card.title || card.name || `Card ${index + 1}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCardDescription(card: CardItem) {
|
||||||
|
if (card.description) return card.description
|
||||||
|
|
||||||
|
const labels: Record<string, string> = {
|
||||||
|
image: '图片',
|
||||||
|
file: '文件',
|
||||||
|
video: '视频',
|
||||||
|
}
|
||||||
|
|
||||||
|
const kind = labels[card.type || ''] || '附件'
|
||||||
|
const size = formatFileSize(card.size)
|
||||||
|
|
||||||
|
if (card.uploading) {
|
||||||
|
return size ? `${kind} · 上传中 · ${size}` : `${kind} · 上传中`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card.deleting) {
|
||||||
|
return size ? `${kind} · 删除中 · ${size}` : `${kind} · 删除中`
|
||||||
|
}
|
||||||
|
|
||||||
|
return size ? `${kind} · ${size}` : kind
|
||||||
|
}
|
||||||
|
|
||||||
function getCardIcon(card: CardItem) {
|
function getCardIcon(card: CardItem) {
|
||||||
if (card.icon) return card.icon
|
if (card.icon) return card.icon
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue