解决方案已经发布成了npm包,需要的话直接下载就好了(目前还暂时不支持自定义样式,后续可以集成)
https://www.npmjs.com/package/copy-and-paste-kiko
需要源码的话可以访问我的仓库
https://gitee.com/yangdan1028/copy-and-paste
问题描述
公司目前的协作管理平台用到的是飞书,然后公司内部的一些业务系统也是用的是在飞书里面嵌套网页的形式。但是在飞书里面嵌套网页,由于飞书禁用了右键,因此不能够用右键来进行复制粘贴,可是老板又必须要使用右键来复制粘贴(让他cv他不干)。所以只能去询问了飞书的开发人员有没有相应的解决方案,得到的回应是让我们cv…

没办法,飞书没有这个功能,那么我们只能手动写一个复制粘贴的功能。
解决思路
首先在开始写代码前,先捋一下要完成这个功能需要实现的功能点。
- 首先需要在项目初始化的时候监听鼠标右键。
- 在鼠标右键的位置展示复制和粘贴的弹窗。
- 右键的时候获取当前页面存不存在拖蓝的文本,存在拖蓝的时候需要展示复制按钮。
- 如果是在文本输入框里右键需要获取当前的光标的位置(在指定的位置粘贴),并且如果是在输入框里面右键需要展示粘贴按钮。
- 点击复制的时候需要复制拖蓝的文本。
- 点击粘贴的时候,如果文本框里存在拖蓝的文本,需要删除后再在光标的位置输入文本。
- 粘贴的时候,不能直接给文本框赋值,必须要模拟键盘的输入事件,因为在vue或react等项目里,直接给文本框赋值不能给输入框的双向绑定对象绑定上值,此时需要模拟键盘的输入事件。
解决方案
知道了问题的解决步骤后,就一步一步的根据步骤来解决问题。
监听鼠标右键
window.oncontextmenu=()=>{
console.log('鼠标点击了右键')}
展示复制和粘贴的弹窗
要在鼠标右键的位置展示弹窗,首先就需要获取当前鼠标右键的位置,我们可以根据事件对象里面的pageX和pageY拿到鼠标当前右击的位置
window.oncontextmenu=(e)=>{
console.log(e.pageX) //右击鼠标的x坐标
console.log(e.pageY) //右击鼠标的y坐标
}
拿到位置后,我们需要在这个位置展示复制粘贴的弹窗,步骤是创建一个div,然后给这个div添加样式,然后apend到指定(鼠标右击)的位置上面去。
window.oncontextmenu = (e) => {
let div = document.createElement('div') //创建复制粘贴大盒子
// 给复制粘贴盒子配置样式
div.style.transform = 'scale(0)'
div.className = 'sniPaste'
div.id = 'sniPaste'
div.style.position = 'fixed'
div.style.width = '190px'
div.style.backgroundColor = '#fff'
div.style.left = e.pageX + 3 + 'px'
div.style.top = e.pageY + 3 + 'px'
div.style.borderRadius = '4px'
div.style.boxShadow = ' 5px 5px 10px #bebebe'
div.style.zIndex = '99999999'
div.style.transformOrigin = '0 0'
div.style.transition = 'all 0.2s'
div.style.overflow = 'hidden'
div.style.border = '1px solid #d9dbdf'
div.style.borderTop = 'none'
div.style.height = '50px'
document.body.appendChild(div)
setTimeout(() => {
div.style.transform = 'scale(1)'
}, 20)
}
然后我们右击页面看一下效果,可以看到页面上浏览器自带的右击弹窗出现了,并且覆盖住了我们的弹窗,因此为了便于测试我们先把这个弹窗给禁用掉,只保留我们自己的弹窗

我们可以用阻止默认行为的方式禁用掉弹窗
e.preventDefault();
e.stopPropagation();
再来看一下效果,可以看到我们自己的弹窗已经出现了,并且是可以固定出现在鼠标右键的位置。

但是发现在多次点击右键的时候会出现多个弹窗,因此在点右键哈唤出弹窗前,需要先把之前的弹窗删除。

let sniPaste = document.getElementById("sniPaste"); //获取复制粘贴大盒子
if (sniPaste) {
sniPaste.remove(); //先移除一次
}
再次测试发现始终只会出现一个弹窗了
添加复制按钮
能够展示弹窗后接下来就是向这个弹窗里添加复制和粘贴按钮,首先先添加复制按钮,并且在鼠标移入和移除按钮的时候加上一个样式反馈。
let copy = document.createElement("div");
copy.style.borderTop = "1px solid #d9dbdf";
copy.innerHTML = `<div class="my_copy_box" style="display:flex;justify-content: space-between;align-items: center"><span style="display:flex;align-items: center">复制</span><span style="color:gray"></span></div>`;
copy.style.fontSize = "14px";
copy.style.padding = "10px 15px";
copy.style.cursor = "pointer";
copy.addEventListener("mouseover", () => {
copy.style.backgroundColor = "rgb(232, 235, 234)";
});
copy.addEventListener("mouseout", () => {
copy.style.backgroundColor = "#fff";
});
div.appendChild(copy);
加上后,效果如下所示

但是在实际的使用过程中,右键能不能复制,应该是根据当前是否存在选中的文本(以下称为拖蓝)来决定的。那么如何获取当前页面是否存在选中的文本呢?
获取当前的拖蓝的文本
可以根据window.getSelection()获取当前拖蓝的文本
//获取拖蓝的文本
let text = window.getSelection().toString()? window.getSelection().toString(): ""
获取到了拖蓝的文本后,再次点击右键唤出复制粘贴的弹出框的时候需要先增加一个判断(当前是否存在拖蓝的文本)
//获取拖蓝的文本
let text = window.getSelection().toString()? window.getSelection().toString(): ""
//存在拖蓝的情况下展示copy按钮
if (text) {
let copy = document.createElement("div");
copy.style.borderTop = "1px solid #d9dbdf";
copy.innerHTML = `<div class="my_copy_box" style="display:flex;justify-content: space-between;align-items: center"><span style="display:flex;align-items: center">复制</span><span style="color:gray"></span></div>`;
copy.style.fontSize = "14px"



5756

被折叠的 条评论
为什么被折叠?



