diff --git a/README.md b/README.md index 8d8cf02..7710710 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ HuLa is an instant messaging system developed with Tauri, Vite 5, Vue 3, and Typ ![img_3.png](preview/img_3.png) +![img_4.png](preview/img_4.png) + HuLa adopts a modular architecture design, with the front end built using Vue 3 for the user interface, enhanced by TypeScript for better code readability and maintainability. On the backend, we use the Tauri framework for packaging and distributing the application, leveraging its native integration with the operating system to offer users more functionality and higher performance. ## Installation and Running diff --git a/README.zh-CN.md b/README.zh-CN.md index b87eca7..9d6a486 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -47,6 +47,8 @@ HuLa 是一个基于 Tauri、Vite 5、Vue 3 和 TypeScript 构建的即时通讯 ![img_3.png](preview/img_3.png) +![img_4.png](preview/img_4.png) + ## 安装与运行 ```bash diff --git a/preview/img_4.png b/preview/img_4.png new file mode 100644 index 0000000..b87f821 Binary files /dev/null and b/preview/img_4.png differ diff --git a/src/components/rightBox/chatBox/ChatMain.vue b/src/components/rightBox/chatBox/ChatMain.vue index c4607b2..15bb444 100644 --- a/src/components/rightBox/chatBox/ChatMain.vue +++ b/src/components/rightBox/chatBox/ChatMain.vue @@ -186,15 +186,6 @@ const { createWebviewWindow } = useWindow() const selectKey = ref() const activeBubble = ref(-1) const userId = ref(10086) -const copyright = ref('-HuLa©-版权所有') -const copyrightComputed = computed(() => { - const copy = (index: number) => { - items.value[index].content.endsWith(copyright.value) - ? navigator.clipboard.writeText(items.value[index].content) - : navigator.clipboard.writeText(items.value[index].content + copyright.value) - } - return { copy } -}) /* 提醒框标题 */ const tips = ref() const modalShow = ref(false) @@ -242,13 +233,14 @@ const activeItemRef = ref({ ...activeItem }) // }) // const message = computed(() => msg.value) /* 右键消息菜单列表 */ +// 复制内容到剪贴板的通用函数 const menuList = ref([ { label: '复制', icon: 'copy', click: (item: any) => { - // 复制内容到剪贴板 - copyrightComputed.value.copy(item.key) + const content = items.value[item.key].content + handleCopy(content) } }, { @@ -295,6 +287,39 @@ watchEffect(() => { activeItemRef.value = { ...activeItem } }) +/** + * 处理复制事件 + * @param content 复制的内容 + */ +const handleCopy = (content: string) => { + // 如果是图片 + // TODO 文件类型的在右键菜单中不设置复制 (nyh -> 2024-04-14 01:14:56) + if (content.includes('data:image')) { + // 创建一个新的图片标签 + const img = new Image() + img.src = content + // 监听图片加载完成事件 + img.onload = () => { + const canvas = document.createElement('canvas') + canvas.width = img.width + canvas.height = img.height + const ctx = canvas.getContext('2d') + ctx?.drawImage(img, 0, 0, img.width, img.height) + // 将 base64 图片数据复制到剪贴板 + canvas.toBlob((blob) => { + const item = new ClipboardItem({ 'image/png': blob! }) + navigator.clipboard.write([item]) + }) + } + } else { + // 如果是纯文本 + navigator.clipboard.writeText(removeTag(content)) + } +} + +/* 去除字符串中的元素标记 */ +const removeTag = (fragment: any) => new DOMParser().parseFromString(fragment, 'text/html').body.textContent || '' + /* 处理滚动事件(用于页脚显示功能) */ const handleScroll = (e: Event) => { const target = e.target as HTMLElement @@ -332,7 +357,8 @@ const handleMsgClick = (item: any) => { // 启用键盘监听 const handleKeyPress = (e: KeyboardEvent) => { if (e.ctrlKey && e.key === 'c') { - copyrightComputed.value.copy(item.key) + const content = items.value[item.key].content + handleCopy(content) // 取消监听键盘事件,以免多次绑定 document.removeEventListener('keydown', handleKeyPress) } diff --git a/src/components/rightBox/emoji/index.vue b/src/components/rightBox/emoji/index.vue index 38e0060..b5e390f 100644 --- a/src/components/rightBox/emoji/index.vue +++ b/src/components/rightBox/emoji/index.vue @@ -1,5 +1,5 @@