refactor: 统一剪贴板复制功能到 useClipboard 组合式函数

将各个组件和视图中重复的剪贴板复制逻辑提取到 useClipboard 组合式函数。
增加 showToast 参数支持静默复制,减少代码重复,提高维护性。
This commit is contained in:
fawney19
2025-12-28 20:41:52 +08:00
parent 7d6d262ed3
commit b5c0f85dca
10 changed files with 29 additions and 77 deletions

View File

@@ -700,6 +700,7 @@ import {
} from 'lucide-vue-next'
import { useEscapeKey } from '@/composables/useEscapeKey'
import { useToast } from '@/composables/useToast'
import { useClipboard } from '@/composables/useClipboard'
import Card from '@/components/ui/card.vue'
import Badge from '@/components/ui/badge.vue'
import Button from '@/components/ui/button.vue'
@@ -731,6 +732,7 @@ const emit = defineEmits<{
'refreshProviders': []
}>()
const { success: showSuccess, error: showError } = useToast()
const { copyToClipboard } = useClipboard()
interface Props {
model: GlobalModelResponse | null
@@ -763,16 +765,6 @@ function handleClose() {
}
}
// 复制到剪贴板
async function copyToClipboard(text: string) {
try {
await navigator.clipboard.writeText(text)
showSuccess('已复制')
} catch {
showError('复制失败')
}
}
// 格式化日期
function formatDate(dateStr: string): string {
if (!dateStr) return '-'

View File

@@ -661,6 +661,7 @@ import Button from '@/components/ui/button.vue'
import Badge from '@/components/ui/badge.vue'
import Card from '@/components/ui/card.vue'
import { useToast } from '@/composables/useToast'
import { useClipboard } from '@/composables/useClipboard'
import { getProvider, getProviderEndpoints } from '@/api/endpoints'
import {
KeyFormDialog,
@@ -706,6 +707,7 @@ const emit = defineEmits<{
}>()
const { error: showError, success: showSuccess } = useToast()
const { copyToClipboard } = useClipboard()
const loading = ref(false)
const provider = ref<any>(null)
@@ -1250,16 +1252,6 @@ function getHealthScoreBarColor(score: number): string {
return 'bg-red-500 dark:bg-red-400'
}
// 复制到剪贴板
async function copyToClipboard(text: string) {
try {
await navigator.clipboard.writeText(text)
showSuccess('已复制到剪贴板')
} catch {
showError('复制失败', '错误')
}
}
// 加载 Provider 信息
async function loadProvider() {
if (!props.providerId) return

View File

@@ -224,6 +224,7 @@ import { Box, Edit, Trash2, Layers, Eye, Wrench, Zap, Brain, Power, Copy, Image,
import Card from '@/components/ui/card.vue'
import Button from '@/components/ui/button.vue'
import { useToast } from '@/composables/useToast'
import { useClipboard } from '@/composables/useClipboard'
import { getProviderModels, testModel, type Model } from '@/api/endpoints'
import { updateModel } from '@/api/endpoints/models'
import { parseTestModelError } from '@/utils/errorParser'
@@ -239,6 +240,7 @@ const emit = defineEmits<{
}>()
const { error: showError, success: showSuccess } = useToast()
const { copyToClipboard } = useClipboard()
// 状态
const loading = ref(false)
@@ -257,12 +259,7 @@ const sortedModels = computed(() => {
// 复制模型 ID 到剪贴板
async function copyModelId(modelId: string) {
try {
await navigator.clipboard.writeText(modelId)
showSuccess('已复制到剪贴板')
} catch {
showError('复制失败', '错误')
}
await copyToClipboard(modelId)
}
// 加载模型

View File

@@ -473,6 +473,7 @@
import { ref, watch, computed } from 'vue'
import Button from '@/components/ui/button.vue'
import { useEscapeKey } from '@/composables/useEscapeKey'
import { useClipboard } from '@/composables/useClipboard'
import Card from '@/components/ui/card.vue'
import Badge from '@/components/ui/badge.vue'
import Separator from '@/components/ui/separator.vue'
@@ -505,6 +506,7 @@ const copiedStates = ref<Record<string, boolean>>({})
const viewMode = ref<'compare' | 'formatted' | 'raw'>('compare')
const currentExpandDepth = ref(1)
const dataSource = ref<'client' | 'provider'>('client')
const { copyToClipboard } = useClipboard()
const historicalPricing = ref<{
input_price: string
output_price: string
@@ -784,7 +786,7 @@ function copyJsonToClipboard(tabName: string) {
}
if (data) {
navigator.clipboard.writeText(JSON.stringify(data, null, 2))
copyToClipboard(JSON.stringify(data, null, 2), false)
copiedStates.value[tabName] = true
setTimeout(() => {
copiedStates.value[tabName] = false