Compare commits

..

No commits in common. "a130e0d3f5f020c5cfd67bd72230b3b4232fd773" and "b93178ec8535a1ee64f89a35e887b179f46ba722" have entirely different histories.

7 changed files with 79 additions and 3 deletions

2
.gitignore vendored
View File

@ -41,6 +41,4 @@ skills-lock.json
*.db
server/data/*.db
scripts/deploy-frontend-standalone.sh
tsconfig.tsbuildinfo

View File

@ -96,6 +96,8 @@
import { ref } from "vue";
import { storeToRefs } from "pinia";
import {
Menu,
Trash2,
ExternalLink,
Pin,
Archive,
@ -139,6 +141,12 @@ const showMoreMenu = ref(false);
const settingsStore = useSettingsStore();
const { settings } = storeToRefs(settingsStore);
function handleClear() {
if (confirm("确定要清空当前对话吗?此操作不可恢复。")) {
emit("clear");
}
}
function handleShare() {
showMoreMenu.value = false;
emit("share");

View File

@ -49,7 +49,16 @@
<script setup lang="ts">
import { computed } from "vue";
import {
MessageSquare,
Code,
Image,
FileText,
ChevronRight,
Keyboard,
Zap,
Globe,
Lightbulb,
PenTool,
} from "@/components/icons";
import promptData from "@/assets/prompt.json";
import type { Suggestion } from "@/types/chat";

View File

@ -178,7 +178,8 @@ 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(() =>
attachments.value.some((a) => a.uploading || a.deleting),
);

View File

@ -160,6 +160,8 @@ import { ref } from "vue";
import MarkdownRender from "markstream-vue";
import { setCustomComponents } from "markstream-vue";
import {
Bot,
User,
AlertCircle,
RefreshCw,
Zap,
@ -168,6 +170,7 @@ import {
Check,
} from "@/components/icons";
import { NImage, NImageGroup } from "naive-ui";
import MessageActions from "./MessageActions.vue";
import { formatFileSize, getFileIcon } from "@/utils/helpers";
import type { Message, Suggestion, Attachment, VideoInfo } from "@/types/chat";
import ThinkingNode from "./components/ThinkingNode.vue";
@ -220,6 +223,11 @@ function handleToggleSelect() {
emit("toggle-select");
}
//
function handleShareClick() {
emit("enter-select-mode");
}
function getFileEmoji(mimeType?: string) {
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", {
think: ThinkingNode,
vmr_container: EChartsContainerNode,

View File

@ -135,10 +135,12 @@ import { useChatStore } from "@/stores/chat";
import { useSettingsStore } from "@/stores/settings";
import { chatApi } from "@/services/api.ts";
import ConversationItem from "./ConversationItem.vue";
import ShareButton from "./ShareButton.vue";
import {
Plus,
Pin,
ChevronDown,
Check,
ChevronUp,
} from "@/components/icons";

View File

@ -55,10 +55,48 @@ const defaultColors = [
'#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) {
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) {
if (card.icon) return card.icon