optimize copy feedback
This commit is contained in:
57
src/App.vue
57
src/App.vue
@@ -88,14 +88,6 @@ const deleteHistoryItem = (id: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const copyHistoryText = async (text: string) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy history text: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
// Logs Management
|
||||
const selectedLogId = ref<string | null>(null);
|
||||
const selectedLogItem = computed(() =>
|
||||
@@ -116,6 +108,23 @@ const getLogSummary = (log: any) => {
|
||||
return 'JSON Data';
|
||||
};
|
||||
|
||||
// Universal Copy with Feedback
|
||||
const activeCopyId = ref<string | null>(null);
|
||||
|
||||
const copyWithFeedback = async (text: string, id: string) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
activeCopyId.value = id;
|
||||
setTimeout(() => {
|
||||
if (activeCopyId.value === id) {
|
||||
activeCopyId.value = null;
|
||||
}
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
// Profile Management
|
||||
const newProfileName = ref('');
|
||||
const isSavingProfile = ref(false);
|
||||
@@ -197,7 +206,6 @@ const sourceText = ref('');
|
||||
const context = ref('');
|
||||
const targetText = ref('');
|
||||
const isTranslating = ref(false);
|
||||
const showCopyFeedback = ref(false);
|
||||
|
||||
interface Suggestion {
|
||||
id: number;
|
||||
@@ -287,18 +295,6 @@ const clearSource = () => {
|
||||
evaluationResult.value = null;
|
||||
};
|
||||
|
||||
const copyTarget = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(targetText.value);
|
||||
showCopyFeedback.value = true;
|
||||
setTimeout(() => {
|
||||
showCopyFeedback.value = false;
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
const evaluateTranslation = async () => {
|
||||
if (!targetText.value) return;
|
||||
|
||||
@@ -776,8 +772,8 @@ const translate = async () => {
|
||||
</div>
|
||||
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<button @click="copyTarget" class="p-1.5 hover:bg-slate-200 dark:hover:bg-slate-700 rounded-md transition-colors relative" title="复制结果">
|
||||
<Check v-if="showCopyFeedback" class="w-4 h-4 text-green-600" />
|
||||
<button @click="copyWithFeedback(targetText, 'main-target')" class="p-1.5 hover:bg-slate-200 dark:hover:bg-slate-700 rounded-md transition-colors relative" title="复制结果">
|
||||
<Check v-if="activeCopyId === 'main-target'" class="w-4 h-4 text-green-600" />
|
||||
<Copy v-else class="w-4 h-4 text-slate-500 dark:text-slate-400" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -1008,10 +1004,11 @@ const translate = async () => {
|
||||
<h3 class="text-xs font-black text-slate-400 uppercase tracking-widest">{{ selectedHistoryItem.sourceLang.displayName }} (原文)</h3>
|
||||
</div>
|
||||
<button
|
||||
@click="copyHistoryText(selectedHistoryItem.sourceText)"
|
||||
@click="copyWithFeedback(selectedHistoryItem.sourceText, `history-source-${selectedHistoryItem.id}`)"
|
||||
class="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg text-slate-400 transition-colors"
|
||||
>
|
||||
<Copy class="w-4 h-4" />
|
||||
<Check v-if="activeCopyId === `history-source-${selectedHistoryItem.id}`" class="w-4 h-4 text-green-600" />
|
||||
<Copy v-else class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-slate-50 dark:bg-slate-800/30 p-6 rounded-2xl border border-slate-100 dark:border-slate-800 text-lg leading-relaxed text-slate-700 dark:text-slate-200 whitespace-pre-wrap">
|
||||
@@ -1038,10 +1035,11 @@ const translate = async () => {
|
||||
<h3 class="text-xs font-black text-blue-500/60 uppercase tracking-widest">{{ selectedHistoryItem.targetLang.displayName }} (译文)</h3>
|
||||
</div>
|
||||
<button
|
||||
@click="copyHistoryText(selectedHistoryItem.targetText)"
|
||||
@click="copyWithFeedback(selectedHistoryItem.targetText, `history-target-${selectedHistoryItem.id}`)"
|
||||
class="p-2 bg-blue-50 dark:bg-blue-900/30 hover:bg-blue-100 dark:hover:bg-blue-900/50 rounded-lg text-blue-600 dark:text-blue-400 transition-colors"
|
||||
>
|
||||
<Copy class="w-4 h-4" />
|
||||
<Check v-if="activeCopyId === `history-target-${selectedHistoryItem.id}`" class="w-4 h-4 text-green-600" />
|
||||
<Copy v-else class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-blue-50/20 dark:bg-blue-900/10 p-6 rounded-2xl border border-blue-100/50 dark:border-blue-900/20 text-xl leading-relaxed font-medium text-slate-800 dark:text-slate-100 whitespace-pre-wrap shadow-sm">
|
||||
@@ -1385,10 +1383,11 @@ const translate = async () => {
|
||||
>{{ selectedLogItem.type === 'request' ? 'Request' : selectedLogItem.type === 'response' ? 'Response' : 'Error' }}</span>
|
||||
</div>
|
||||
<button
|
||||
@click="copyHistoryText(typeof selectedLogItem.content === 'object' ? JSON.stringify(selectedLogItem.content, null, 2) : String(selectedLogItem.content))"
|
||||
@click="copyWithFeedback(typeof selectedLogItem.content === 'object' ? JSON.stringify(selectedLogItem.content, null, 2) : String(selectedLogItem.content), `log-${selectedLogItem.id}`)"
|
||||
class="flex items-center gap-2 px-3 py-2 text-xs font-medium text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800 rounded-lg transition-colors border border-slate-200 dark:border-slate-700"
|
||||
>
|
||||
<Copy class="w-4 h-4" />
|
||||
<Check v-if="activeCopyId === `log-${selectedLogItem.id}`" class="w-4 h-4 text-green-600" />
|
||||
<Copy v-else class="w-4 h-4" />
|
||||
复制内容
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user