feat: copy to clipboard

This commit is contained in:
TaurusXin 2024-04-25 15:11:57 +08:00
parent 07b01270ca
commit 1b758030a9
4 changed files with 103 additions and 27 deletions

3
components.d.ts vendored
View File

@ -7,8 +7,11 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
NButton: typeof import('naive-ui')['NButton']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NIcon: typeof import('naive-ui')['NIcon']
NInput: typeof import('naive-ui')['NInput']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NTable: typeof import('naive-ui')['NTable']
}
}

View File

@ -12,7 +12,8 @@
},
"dependencies": {
"@tauri-apps/api": "^1",
"vue": "^3.3.4"
"vue": "^3.3.4",
"vue-clipboard3": "^2.0.0"
},
"devDependencies": {
"@tauri-apps/cli": "^1",

View File

@ -11,6 +11,9 @@ dependencies:
vue:
specifier: ^3.3.4
version: 3.4.21(typescript@5.4.2)
vue-clipboard3:
specifier: ^2.0.0
version: 2.0.0
devDependencies:
'@tauri-apps/cli':
@ -777,6 +780,14 @@ packages:
fsevents: 2.3.3
dev: true
/clipboard@2.0.11:
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
dependencies:
good-listener: 1.2.2
select: 1.1.2
tiny-emitter: 2.1.0
dev: false
/computeds@0.0.1:
resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
dev: true
@ -832,6 +843,10 @@ packages:
ms: 2.1.2
dev: true
/delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
dev: false
/entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@ -937,6 +952,12 @@ packages:
is-glob: 4.0.3
dev: true
/good-listener@1.2.2:
resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==}
dependencies:
delegate: 3.2.0
dev: false
/graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
requiresBuild: true
@ -1302,6 +1323,10 @@ packages:
resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==}
dev: true
/select@1.1.2:
resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
dev: false
/semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true
@ -1339,6 +1364,10 @@ packages:
engines: {node: '>= 0.4'}
dev: true
/tiny-emitter@2.1.0:
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
dev: false
/to-fast-properties@2.0.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'}
@ -1513,6 +1542,12 @@ packages:
vue: 3.4.21(typescript@5.4.2)
dev: true
/vue-clipboard3@2.0.0:
resolution: {integrity: sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==}
dependencies:
clipboard: 2.0.11
dev: false
/vue-template-compiler@2.7.16:
resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==}
dependencies:

View File

@ -3,6 +3,13 @@ import { ref, computed } from 'vue'
import { codecs } from '@/utils/codecs.ts'
import { EncodingConverter } from '@/utils/converter'
import { useOsTheme, darkTheme } from 'naive-ui'
import { CopyOutline as CopyIcon } from '@vicons/ionicons5'
import useClipboard from 'vue-clipboard3'
import { createDiscreteApi } from "naive-ui";
const { message } = createDiscreteApi(["message"]);
const { toClipboard } = useClipboard()
const osThemeRef = useOsTheme()
const theme = computed(() => (osThemeRef.value === 'dark' ? darkTheme : undefined))
@ -20,36 +27,66 @@ const handleTextInput = (text: string) => {
})
})
}
const copyToClipboard = async (msg: string) => {
try {
await toClipboard(msg)
message.success('复制成功!')
} catch (e) {
message.error('复制失败!')
}
}
const handleCopyResult = (text: string) => {
copyToClipboard(text)
}
</script>
<template>
<n-config-provider :theme="theme">
<div class="container">
<n-input
v-model:value="content"
type="textarea"
placeholder="请输入待恢复的乱码文本"
clearable
class="input"
@input="handleTextInput"
/>
<n-table :single-line="false" striped class="table">
<thead>
<tr>
<th class="encode title">原来编码</th>
<th class="encode title">目标编码</th>
<th class="result title">结果</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in codecs" :key="index">
<td>{{ item.origin }}</td>
<td>{{ item.target }}</td>
<td>{{ result[index] }}</td>
</tr>
</tbody>
</n-table>
</div>
<n-message-provider>
<div class="container">
<n-input
v-model:value="content"
type="textarea"
placeholder="请输入待恢复的乱码文本"
clearable
class="input"
@input="handleTextInput"
/>
<n-table :single-line="false" striped class="table">
<thead>
<tr>
<th class="encode title">原来编码</th>
<th class="encode title">目标编码</th>
<th class="result title">结果</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in codecs" :key="index">
<td>{{ item.origin }}</td>
<td>{{ item.target }}</td>
<td>
{{ result[index] }}
<n-button
icon-placement="left"
strong
size="tiny"
v-if="result[index]"
@click="handleCopyResult(result[index])"
>
<template #icon>
<n-icon>
<copy-icon />
</n-icon>
</template>
</n-button>
</td>
</tr>
</tbody>
</n-table>
</div>
</n-message-provider>
</n-config-provider>
</template>