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' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
NButton: typeof import('naive-ui')['NButton']
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NIcon: typeof import('naive-ui')['NIcon']
NInput: typeof import('naive-ui')['NInput'] NInput: typeof import('naive-ui')['NInput']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NTable: typeof import('naive-ui')['NTable'] NTable: typeof import('naive-ui')['NTable']
} }
} }

View File

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

View File

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

View File

@ -3,6 +3,13 @@ import { ref, computed } from 'vue'
import { codecs } from '@/utils/codecs.ts' import { codecs } from '@/utils/codecs.ts'
import { EncodingConverter } from '@/utils/converter' import { EncodingConverter } from '@/utils/converter'
import { useOsTheme, darkTheme } from 'naive-ui' 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 osThemeRef = useOsTheme()
const theme = computed(() => (osThemeRef.value === 'dark' ? darkTheme : undefined)) 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> </script>
<template> <template>
<n-config-provider :theme="theme"> <n-config-provider :theme="theme">
<div class="container"> <n-message-provider>
<n-input <div class="container">
v-model:value="content" <n-input
type="textarea" v-model:value="content"
placeholder="请输入待恢复的乱码文本" type="textarea"
clearable placeholder="请输入待恢复的乱码文本"
class="input" clearable
@input="handleTextInput" class="input"
/> @input="handleTextInput"
<n-table :single-line="false" striped class="table"> />
<thead> <n-table :single-line="false" striped class="table">
<tr> <thead>
<th class="encode title">原来编码</th> <tr>
<th class="encode title">目标编码</th> <th class="encode title">原来编码</th>
<th class="result title">结果</th> <th class="encode title">目标编码</th>
</tr> <th class="result title">结果</th>
</thead> </tr>
<tbody> </thead>
<tr v-for="(item, index) in codecs" :key="index"> <tbody>
<td>{{ item.origin }}</td> <tr v-for="(item, index) in codecs" :key="index">
<td>{{ item.target }}</td> <td>{{ item.origin }}</td>
<td>{{ result[index] }}</td> <td>{{ item.target }}</td>
</tr> <td>
</tbody> {{ result[index] }}
</n-table> <n-button
</div> 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> </n-config-provider>
</template> </template>