KevinChen 发表于 2020-7-27 16:51:48

怎样实现内部复制粘贴?如何禁止用户将表格数据粘贴到本地Excel?

近期有几位朋友同时咨询这个需求,本文就这个问题的原理和实现方案在此详细描述一下。
要解释清楚这个问题,需要咱们先了解以下几个前提:

一、JS语言本身访问系统剪贴板的权限
JS语言本身,受语言规则(或是浏览器安全规则)所限,访问、操作系统剪贴板的限制
比较多,具体参考:https://juejin.im/post/5bbb2870e51d450e853050e0

二、SpreadJS无法通过除Ctrl + C / V 之外的方式与本地Excel交互数据。
不难理解,实际上纯JS实现的SpreadJS默认不支持通过右键菜单“复制”、copy命令
或接口实现将内部数据写入系统剪贴板的。那为什么Ctrl + C、Ctrl+V可以实现内外部
数据的相互粘贴呢?这是由于Ctrl+C与Ctrl+V是浏览器留给JS程序的一个“窗口”,而
且这个窗口期很短,且有一些规则限制。
在SpreadJS中,除文件IO接口外,这是与本地数据交互的唯一方式。

三、具体实现
了解了其中原理,我们知道,不想让用户把表格数据导出到本地,除了不给用户提供
IO接口外,只剩下切断与系统剪贴板的交互这一种办法了。
1、禁用SpreadJS所在hostElement的Ctrl+C/V的事件
// 1、禁用ctrl+c ctrl+v功能
                document.getElementById('ss').onkeydown = function(){
                        if (event.ctrlKey && (window.event.keyCode==67 || window.event.keyCode==86)){
                                alert("禁止:" + window.event.keyCode);
                                return false;
                        }
                }SpreadJS默认会监听浏览器的C/V事件,先禁用这里的事件。

2、用自定义copy命令,替换掉默认的copy命令
// 2、重写copy命令
                spread.commandManager().register("myCopy",
            {
                canUndo: true,
                execute: function (context, options, isUndo) {
                                        setTimeout(function(){
                                                options.cmd = "copy";
                                                spread.commandManager().execute(options);
                                                options.cmd = "myCopy";
                                        },10);
                }
            });
                       
                // 设置快捷键Ctrl + C
      spread.commandManager().setShortcutKey(
            "copy", null, false, false, false, false
      );
      spread.commandManager().setShortcutKey(
            "myCopy", GC.Spread.Commands.Key.c, true, false, false, false
      );请注意自定义copy命令中setTimeout的使用,这里实际上是为了规避掉访问系统剪贴板的“窗口”

3、用自定义Paste命令,替换掉默认的paste命令
// 3、重写paste命令
                spread.commandManager().register("myPaste",
            {
                canUndo: true,
                execute: function (context, options, isUndo) {
                                        //内部粘贴逻辑
                                        var innerPaste = "paste";
                                        options.cmd = innerPaste;
                                        // 设置setTimeout,让开时间窗口,否则SpreadJS会自动粘贴外部内容。
                                        setTimeout(function(){
                                                spread.commandManager().execute(options);
                                        },10);
                }
            });
                // 设置快捷键Ctrl + V
      spread.commandManager().setShortcutKey(
            "paste", null, false, false, false, false
      );
      spread.commandManager().setShortcutKey(
            "myPaste", GC.Spread.Commands.Key.v, true, false, false, false
      );

完整的Demo请参考附件【重写CopyPast命令实现内部复制粘贴.html】
页: [1]
查看完整版本: 怎样实现内部复制粘贴?如何禁止用户将表格数据粘贴到本地Excel?