Files
admin-web/src/components/common/CopyButton.vue
T

63 lines
1.6 KiB
Vue

<script setup lang="ts">
import { computed, ref } from 'vue'
import { Copy } from '@lucide/vue'
import { ElMessage } from 'element-plus'
import { copyText } from '@/utils/copyText'
defineOptions({ inheritAttrs: false })
const props = withDefaults(defineProps<{
value: string | number | null | undefined
label?: string
buttonText?: string
successText?: string
errorText?: string
disabled?: boolean
notify?: boolean
}>(), {
label: '内容',
buttonText: '复制',
successText: undefined,
errorText: undefined,
disabled: false,
notify: true,
})
const emit = defineEmits<{
copied: [value: string]
'copy-error': [error: unknown]
}>()
const copying = ref(false)
const copyValue = computed(() => props.value == null ? '' : String(props.value))
const isDisabled = computed(() => props.disabled || copying.value || copyValue.value.length === 0)
async function handleCopy() {
if (isDisabled.value) return
copying.value = true
try {
await copyText(copyValue.value)
if (props.notify) ElMessage.success(props.successText || `${props.label}已复制`)
emit('copied', copyValue.value)
} catch (error) {
if (props.notify) ElMessage.error(props.errorText || `${props.label}复制失败,请手动选择复制`)
emit('copy-error', error)
} finally {
copying.value = false
}
}
</script>
<template>
<el-button
v-bind="$attrs"
:disabled="isDisabled"
:aria-label="`复制${label}`"
:title="`复制${label}`"
@click="handleCopy"
>
<Copy :size="14" aria-hidden="true" />
<slot :copying="copying">{{ buttonText }}</slot>
</el-button>
</template>