独书先生 Menu

js倒计时自定义小时分钟

需求

实现一个倒计时一小时的网页应用

代码







Document

小时
分钟
<p class="count"></p>

<button id="start">START</button>
<script>
  window.onload = function () {
    // countDown();

    document.querySelector("#start").addEventListener("click", () => {
      function addZero(i) {
        return i < 10 ? "0" + i : i + "";
      }

      var hour = document.querySelector("#hour");
      var min = document.querySelector("#min");
      var countTimeHour = parseInt(hour.value === "" ? "1" : hour.value);
      var countTimeMin = parseInt(min.value === "" ? "0" : min.value);

      var nowtime = new Date(); //你已知的时间
      var t_s = nowtime.getTime(); //转化为时间戳毫秒数
      var endtime = new Date(); //定义一个新时间
      t_s = t_s + 1000 * 60 * countTimeMin; //设置新时间比旧时间多一分钟
      t_s = t_s + 1000 * 60 * 60 * countTimeHour; //设置新时间比旧时间多一小时;
      endtime.setTime(t_s);
      // nt.setTime(t_s+1000*60*60*24);//设置新时间比旧时间多一天

      countDown();

      function countDown() {
        var nowtime = new Date(); //你已知的时间
        //   var endtime = new Date("2019/03/16,17:57:00");
        var lefttime = parseInt(
          (endtime.getTime() - nowtime.getTime()) / 1000
        );
        var d = parseInt(lefttime / (24 * 60 * 60));
        var h = parseInt((lefttime / (60 * 60)) % 24);
        var m = parseInt((lefttime / 60) % 60);
        var s = parseInt(lefttime % 60);
        d = addZero(d);
        h = addZero(h);
        m = addZero(m);
        s = addZero(s);
        document.querySelector(
          ".count"
        ).innerHTML = `活动倒计时  ${d}天 ${h} 时 ${m} 分 ${s} 秒`;
        if (lefttime <= 0) {
          document.querySelector(".count").innerHTML = "Time Over!";
          var isShow = false;
          setInterval(() => {
            isShow = !isShow;
            if (isShow) {
              document.title = "😆Time Over!";
            } else {
              document.title = "";
            }
          }, 1000);
          return;
        }
        setTimeout(countDown, 1000);
      }
    });
    // window.countDown = function () {

    // };
  };
</script>



Typescript CSS module 问题,VSCODE提示 cannot find module ‘XXX.scss’ or its corresponding type declarations

问题

在Typescript + Webpack + Sass项目中使用CSS Module,可以正常引入CSS模块使用,但是vscode总是提示 cannot find module ‘XXX.scss’ or its corresponding type declarations。

解决方案

方案一

1、首先要确保webpack和sass已经能够识别CSS Module,参考webpack官网配置即可 Separating Interoperable CSS-only and CSS Module features

2、配置d.ts
重点来了,这里要注意配置两个d.ts文件
一、主文件index.d.ts

    declare module '*.scss' {
        const content: { [key: string]: any }
        export = content
    }
    

二、同级目录再新增一个typings.d.ts文件

    declare module '*.scss';
    

这样配置后,已经解决了笔者的问题,VSCODE和Node命令行界面都不会报错,而且能正常匹配

方案二

网络推荐的解决方案是在css文件同级目录编写d.ts文件,通常使用插件来自动完成

以下插件选择其一即可
1. webpack插件 typings-for-css-modules-loader
2. webpacl插件 css-modules-typescript-loader
3. 可能需要的插件,Typescript插件 typescript-plugin-css-modules(笔者用了没有效果)

通常安装完插件自动生成每个css的声明文件后,就不会报错了,但是有两个缺点,一是项目文件太多,二是路径别名还是无法被VSCODE识别(Node命令行正常),这个必须是如上配置两个d.ts才能让VSCODE不提示错误。

参考

一些可能的scss文件声明写法

//写法一
declare module '*.scss';

//写法二
declare module '*.scss' {
    const content: any;
    export default content;
}

//写法三
declare module '*.scss' {
    const content: Record;
    export default content;
}

//写法三
declare module '*.scss' {
    const content: { [key: string]: any }
    export = content
}

一些回答 cant-import-css-scss-modules-typescript-says-cannot-find-module

master提交PR到main分支出现There isn’t anything to compare

master提交PR到main分支出现:There isn't anything to compare.main and master are entirely different commit histories.

解决方案

以下操作会强制覆盖原有代码,所以需要将要保留的内容提前存下来,覆盖后再手动更新上去。

git checkout master
git branch main master -f
git checkout main
git push origin main -f

为何不能合并?

在git checkout main之后会提示你执行git pull,试验发现合并失败,提示:fatal: refusing to merge unrelated histories,应该是和master不允许提交PR到main分支一个意思,没有相同的关联记录,即使代码差不多。

删除不需要的分支

删除本地master分支

git branch -D master

删除远程master分支

git push origin --delete master

如何github commit记录全部清除?

解决

  1. 新建orphan分支
git checkout --orphan latest_branch
  1. 将需要的文件添加到暂存区
git add -A
  1. Commit
git commit -m "..."
  1. 删除main分支
git branch -D main
  1. 将当前latest_branch分支重命名为main分支
git branch -m main
  1. 最后,推送到远程仓库
git push -f origin main

参考

  • https://stackoverflow.com/questions/23344320/there-isnt-anything-to-compare-nothing-to-compare-branches-are-entirely-diffe
  • https://github.com/lishuhao/blog/issues/9

github clone很慢,github上不去,github.io无法访问

问题

github 是程序员必备的代码仓库和学习网站,但是当你发现一个开源库并把它clone下来的时候,发现一直卡住不动,及时能下载也只有几k的速度。

并且,虽然能上github,细心的同学可以发现,大多数github站内图片也是打不开的。

还有的项目的博客或者文档是托管在github.io上的,这个网址也经常是访问不了。

有没有什么补救措施?

解决

首先参考众多网友的智慧,马上就有了方案

方案一:设置git config

修改下git的配置

git config --global http.postBuffer 524288000

有同学用了这个配置,速度就提升了,但是小编用了没有效果,可能还是要看网络原因。

方案二:cnpm镜像

国内大型镜像系统cnpm的服务又来啦!

操作很简单,只要我们将原本的网站中的https://github.com 进行替换为https://github.com.cnpmjs.org即可,比如,

git clone https://github.com/openHacking/vuepress-plugin-qrcode

可以改为

git clone https://github.com.cnpmjs.org/openHacking/vuepress-plugin-qrcode

笔者经过试验,速度确实有所提升,快的时候大概有500k的样子。但是因为镜像是有同步周期的,如果是对实时性要求比较高的小伙伴,需要注意下这个问题。

方案三:gitee同步

这是一个利用gitee.com(码云)的github仓库的一键同步服务,来做一个中转,实现快速下载github项目的目的。

具体操作:

1.注册【码云】

2.通过【码云】【从github导入已有项目】

3.git clone【码云】中的项目

注意:笔者试验过确实可以同步,而且码云的速度还挺快。但是有两个缺点:1.每看到一个库就同步再下载,有点麻烦 2.如果仓库太大,是同步不过来的。所以这个方案也不是万能的。

方案四:修改host文件

git clone特别慢是因为github.global.ssl.fastly.net域名被限制了。
只要找到这个域名对应的ip地址,然后在hosts文件中加上ip–>域名的映射,刷新DNS缓存便可。

具体操作:

  1. 在网站 https://www.ipaddress.com/ 分别搜索:
github.global.ssl.fastly.net
github.com

得到对于的ip地址

  1. 打开hosts文件

– Windows上的hosts文件路径在C:\Windows\System32\drivers\etc\hosts
– Linux的hosts文件路径在:sudo vim /etc/hosts

  1. 在hosts文件末尾添加两行(对应上面查到的ip)
151.101.185.194 github.global-ssl.fastly.net
192.30.253.112 github.com
  1. 保存更新DNS

– Winodws系统的做法:打开CMD,输入ipconfig /flushdns
– Linux的做法:在终端输入sudo /etc/init.d/networking restart

  1. 重新git clone试试

注意:建议多试验几家ip地址获取的服务,因为ip也有被污染的情况,通常一个ip不一定靠谱。笔者经过尝试,发现这种方法并不是很奏效,git clone还是龟速。

方案五:代理

通过本地代理软件,将github代理转发到可以高速访问的服务器上,代理技术有很多应用场景,现在就是一个。

大致步骤:
1. 大多数同学会推荐shadowsocks,加上免费白嫖的账户,就可以链接上了
2. 设置github代理

git config --global http.https://github.com.proxy https://127.0.0.1:1080
git config --global https.https://github.com.proxy https://127.0.0.1:1080

注意这是对https的仓库链接有效果。

小编试验完,发现这个代理并没有作用,已经显示连接上了,但是网速依然感人,不知道哪里出了问题。欢迎试验成功的小伙伴留言区告诉小编。

其实小编估摸着大家已经把所有的方案都试过一遍了,效果还是不如人意。饱含着一整个工作日的研究与心酸泪,小编最后终于发现了一个终极大招:EXPRESS

因为小编想通了一件事情,作为一个合格的程(da)序(gong)猿(ren),没有一款能够稳定输出、坚挺硬刚的强力代理软件,是无法正常享受流畅开发体验的,现在都5G时代了,下个github代码还在5k的速度,内心再也不能接受。

可能有小伙伴对这块有所研究,或许已经成为大家的每日必(kan)备(pian)工(shen)具(qi)。如果有小伙伴对此有所疑虑,那么小编推荐大家仔细阅读下面这篇文章。小编仔细阅读了这篇推心置腹的文章之后,就迅速入手了,也解决了小编多年的上网烦恼。

程序员必备姿势

这是小编使用过的最稳定最快的代理服务,没有之一。

动手做起来,你就成功了一半。

彻底解决npm install卡住不动npm安装报错最全指南

问题

在使用npm install安装某个npm依赖包时,比如安装vue

npm install vue

发现进度条一直卡住不动,或者一个包下载很久,相信很多朋友也遇到过。原因应该是国内的网络连接npm速度比较慢,甚至很多的依赖包都无法直接下载下来。那么如何解决这个问题呢?

写在前面:

本文的内容大致为笔者在使用很多方案没有很好的效果之后,还是选择了买付费vpn来解决,如果已经对这个npm安装问题有所了解的,建议直接开始使用VPN。推荐笔者用的一个很稳定的VPN:Express VPN

为什么推荐Express VPN

正文开始:

方案一:淘宝镜像

npm淘宝镜像源是淘宝出品的专为npm安装加速的国内镜像代理站,官方说明是每10分钟同步一次。国内代理也是用淘宝镜像最多,并且服务稳定。

代理的原理很简单,国外的服务器距离我们比较远,连接上去当然比较慢了,国内的淘宝服务器就多了,又近,当然你就比较快了。

使用淘宝的代理镜像有三种具体方案,下面给大家详细说明

  1. 一是当你是单个依赖无法安装的时候,可以简单的在安装命令后面加上--registry=https://registry.npm.taobao.org,将此次安装的npm源切换到淘宝的npm镜像站。比如安装vue
npm install vue --registry=https://registry.npm.taobao.org # 一次性使用淘宝镜像

这个方案的好处是,针对个别的依赖库操作即可,不需要安装额外的依赖或者修改配置。

  1. 二是切换npm源的方式。直接把npm安装时用的来源切换到淘宝npm.taobao.org,就不用每次输入后缀了。设置
npm config set registry https://registry.npm.taobao.org #  设置npm镜像源为淘宝镜像

之后安装依赖还是正常的npm命令就行。

后续如果不想使用npm.taobao.org作为源了,可以重新切换回来

npm config set registry http://registry.npmjs.org # 设置npm镜像源为淘宝镜像

npm config get registry  # 查看npm当前镜像源

  1. 三是采用cnpm的安装方式,本质是也是切换镜像源。先安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org # 目的是安装cnpm这个库,也是采用一次性使用淘宝镜像的方式

再在安装npm包时把npm 改为cnpm即可,比如安装vue

cnpm install vue

这个方法的好处是,同时支持cnpm和npm两种方式安装npm包,而不用像前面两个方法一样,要么加后缀要么重新切换源。

注意点:淘宝镜像源的方案也不是一劳永逸的,因为有小伙伴反馈说用了淘宝镜像安装后的依赖库有问题,但是用npm安装的就没问题,这种情况很少出现,但是一旦遇到,就是大坑,小伙伴们注意防范。

方案二:yarn

yarn是新一代替代npm安装依赖包的方案,更好的处理依赖树,所以有些npm安装失败的问题,换成yarn可能就好了。

这里简要列出各个系统环境下的安装方法,如有疑问,可以访问yarn中文网参考详细教程
1. windows环境下,需要去官网下载yarn软件

yarn下载
2. macOS推荐直接使用brew安装

brew install yarn
  1. CentOS也是命令安装
curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo

sudo yum install yarn

安装完后,使用以下命令测试yarn是否安装成功

yarn --version

然后我们就可以使用yarn来安装npm包了,这里贴出常用的一些命令对比。

npm Yarn
npm install yarn add
npm install [package] –save yarn add [package]
npm install [package] –save-dev yarn add [package] –dev
npm install [package] –global yarn global add [package]
npm update –global yarn global upgrade
npm rebuild yarn add –force
npm uninstall [package] yarn remove [package]
npm cache clean yarn cache clean [package]
rm -rf node_modules && npm install yarn upgrade
npm version major yarn version –major
npm version minor yarn version –minor
npm version patch yarn version –patch

同样的如方案一,yarn可能也需要配合切换镜像源使用。如下可以参考

yarn config get registry  #  查看yarn当前镜像源

yarn config set registry https://registry.npm.taobao.org/  #  设置yarn镜像源为淘宝镜像

另外,现在一些大型第三方库也在推荐使用yarn安装依赖库,比如vue,这个可以作为重要的参考。但也不是绝对,因为也有小伙伴反馈用yarn出了问题,但是用npm是正常的。

因为每个人做的项目不同,npm依赖间的关系错综复杂,很多时候还要看点运气,或者你测出了别人没遇到的bug,毕竟,这些底层工具也是代码写的,代码写的就可能有bug,找到自己最适合的工具就好。

方案三:专线链接

如果前两个方案都不太奏效,小编只能推荐一个终极大招了,彻底解决npm卡住不动,npm下载慢,npm安装报错等各种网络问题–科学上网专线直连。为什么是大招,小编你是不是忽悠我?

理由有两个,

  1. 一是虽然我们用了淘宝镜像源,但是第三方依赖包各种各样,奇葩的是还有的第三方库在下载的时候需要临时去别的网址下载它自己的依赖,而这个它自己的依赖咱们淘宝是没有代理的,或者说即使有的网址可以代理,那么多第三方库的额外网址,你也不可能都能帮你代理下载。最典型的依赖库如node-sassnode-gyp等(node-sass和node-gyp的坑不止一个,这个等小编哪天再出详细教程)
  2. 二是小编之前遇到过这类坑,无论采用cnpm,换镜像源,换yarn,各种删除依赖重新安装,都不行,最后还是采用更科学的方式,才得以节约宝贵的开发时间。毕竟,各种工具要为我们的工作效率服务才行,不然就不是好工具。如果我们为了节省资金,但是耗费了大量的时间研究踩坑而没有结果,那岂不是浪费了更多的资金了,时间比资金更贵。

好了,不卖关子了,明白这类工具的好处的小伙伴,自然明白时间和好工具的重要性,请直接到小编推荐的专业网站操作

排名第一的VPN: Express VPN

专线直连最直接的方案就是购买服务 —鲁迅(误)

如果对此工具还有疑问的小伙伴,请参考这篇解读欣赏下小编的踩坑辛酸泪。。。

为什么我会推荐Express VPN

参考

提交main主分支后接着提交gh-pages分支

需求

我们在github建立的项目,有时候需要发布GitHub pages,有两种方案,1是源码一个仓库,打包后代码放到另一个仓库的gh-pages分支,2是源码一个仓库main分支,打包后代码还是放在本仓库的gh-pages分支。我们这里采用第二种方式

步骤

我们以线上开源项目vuepress-template为例,这一个vuepress 模板项目,打包后生成的dist文件夹在docs/.vuepress文件夹目录下

第一步:打包文件

npm run docs:build

第二步:dist提交git

git add docs/.vuepress/dist
git commit -m "Initial dist subtree commit"

第三步:push dist

git subtree push --prefix docs/.vuepress/dist origin gh-pages

jquery error Uncaught TypeError: ((x.event.special[i.origType] || (intermediate value)).handle || i.handler).apply is not a function

问题

jquery error:

Uncaught TypeError: ((x.event.special[i.origType] || (intermediate value)).handle || i.handler).apply is not a function

思路

可能的问题来源

按照网上的方法一一排查
1. 事件监听的函数没有具体内容

// Not Working
$('#btnClick').click(function(){   //code })
  1. 调用的方法不存在
var foo = {
bar1: function(){
    alert('working');
}
};


// Not Working because bar2 doesn't exist
$('body').on('click', '.my-button', foo.bar2);

// Working
$('body').on('click', '.my-button', foo.bar1);

  1. 手误绑定了两次
// Not Working
$(document).on('change', '#selectInput').on('change', '#selectInput', function () {});

// Working
$(document).off('change', '#selectInput').on('change', '#selectInput', function () {});

  1. 监听写法错误
// Not Working
$('body').click('click','.delete_item',function(e){})

// Working
$('body').on('click','.delete_item',function(e){}) 

  1. 监听事件handler不是function
// Not Working
$('.foo').click($('.bar').trigger('click'));

// Working
$('.foo').click(function () {
  $('.bar').trigger('click');
});
  1. 监听的元素不存在
// Not Working if '.js-test' didn't exist anymore.
$(document).on('click', '.js-test', App.test);

一般情况下,监听写的不多,或者已知最近改了哪几个地方,是可以查出来的。但是如果元素特别多,一眼看不出来的情况,就需要使用点调试手段。

如何调试出问题点?

步骤:
1. 格式化format jquery
2. 找到报错的地方,在后面打印event的console,参考如下打印方法:

((p.event.special[r.origType] || {}).handle || r.handler).apply(o.elem, l) || console.log(t)
  1. 复现bug,在报错出现后,找到报错之前的console日志,点开event找到handleObj.handler,一般情况下这个handler是一个function,你可以看看其他正常的情况,但是在这里,这可能是一个对象或者字符串,所以在这之后绑定的apply会报错,这时候就能根据这里的信息,去代码里搜索定位了。

比如我的错误是这样的,我在这个位置的handler是

{
    guid: 12
    preventScroll: true
}

是一个对象,随机搜索’preventScroll’发现了一段代码

$("#" + selector).attr("tabindex", 0).focus({
    preventScroll: true 
});

但是focus里面是支持这种写法的,所以删除tabindex即可

$("#" + selector).focus({      
    preventScroll: true 
});

参考

https://stackoverflow.com/questions/32231036/uncaught-typeerror-x-event-speciali-origtype-intermediate-value-handl

Luckysheet如何一键导入本地Excel

问题

Luckysheet是一款功能很丰富的在线电子表格插件,但是初始版本暂时不支持excel导入导出.笔者结合身边朋友的经验,给出案例供参考.

解决方案

通过sheetJs将导入的excel文件转换成Luckysheet能够支持的数据格式即可

操作步骤

  1. 参照官网教程,先打包源代码,得到Luckysheet核心文件,并在在项目主页引入Luckysheet依赖的js,css,和sheetJs插件xlsx.full.min.js
<link rel="stylesheet" href="./luckysheet/plugins/css/pluginsCss.min.css">

<link rel="stylesheet" href="./luckysheet/plugins/plugins.min.css">

<link rel="stylesheet" href="./luckysheet/css/main.min.css">

<script src="./luckysheet/plugins/js/plugin.min.js"></script>

<script src="./luckysheet/main.min.js"></script>

<script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.16.2/xlsx.full.min.js"></script>
  1. 页面准备,渲染一个空白的Luckysheet,input file 监听Excel文件上传,通过sheetJs将导入的数据转换成Luckysheet能够识别的格式
// 渲染一个空白的Luckysheet
$(function () {
    luckysheet.create({
        container: 'luckysheet'
    })
})

// 监听文件上传
var input = document.querySelector('input');
input.addEventListener('change', importExcel);
  1. 通过sheetJs将导入的excel数据转换成html table格式数据,使用从luckysheet中抽出来的数据转换方法, 转换为Luckysheet可识别的格式
// 获取excel数据
function importExcel(event) {

    var file = event.target.files[0];
    /* 实例FileReader对象 */
    //other code...
}

// 解析excel数据
function readFile(txtdata) {
    $("#luckysheet-copy-content").html(txtdata);

   //other code...
}

代码参考

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>luckysheet import excel</title>

    <link rel="stylesheet" href="./luckysheet/plugins/css/pluginsCss.min.css">

    <link rel="stylesheet" href="./luckysheet/plugins/plugins.min.css">

    <link rel="stylesheet" href="./luckysheet/css/main.min.css">

    <script src="./luckysheet/plugins/js/plugin.min.js"></script>

    <script src="./luckysheet/main.min.js"></script>

    <script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.16.2/xlsx.full.min.js"></script>

    <style>
        #container {
            position: relative;
        }
    </style>
</head>

<body>
    <div id="container">
        <input type="file" />
        <div id="luckysheet"
            style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 30px;"></div>
    </div>

    <script>
        document.querySelector('#container').style.height = window.innerHeight + 'px';

        // 渲染一个空白的Luckysheet
        $(function () {

            luckysheet.create({
                container: 'luckysheet'
            })
        })

        // 监听文件上传
        var input = document.querySelector('input');
        input.addEventListener('change', importExcel);

        // 获取excel数据
        function importExcel(event) {

            var file = event.target.files[0];
            /* 实例FileReader对象 */
            var reader = new FileReader();
            reader.onload = function (e) {
                /* Parse data */
                var bstr = e.target.result;
                var wb = XLSX.read(bstr, { type: 'binary' });
                /* 获取第一个工作表*/
                var wsname = wb.SheetNames[0];
                var ws = wb.Sheets[wsname];
                /* 将工作表对象转换为JSON对象数组*/
                // var dataArr = XLSX.utils.sheet_to_json(ws, { header: 1 });
                /* 生成HTML输出 */
                var data = XLSX.utils.sheet_to_html(ws);
                /* 调用数据转换方法将数据格式转换成Luckysheet格式*/
                readFile(data);
            };
            /*将文件内容读取为原始二进制字符串*/
            reader.readAsBinaryString(file);
        }

        // 解析excel数据
        function readFile(txtdata) {
            $("#luckysheet-copy-content").html(txtdata);

            var data = new Array($("#luckysheet-copy-content").find("table tr").length);
            var colLen = 0;
            $("#luckysheet-copy-content").find("table tr").eq(0).find("td").each(function () {
                var colspan = parseInt($(this).attr("colspan"));
                if (isNaN(colspan)) {
                    colspan = 1;
                }
                colLen += colspan;
            });

            for (var i = 0; i < data.length; i++) {
                data[i] = new Array(colLen);
            }

            var r = 0;
            var borderInfo = {};
            var luckysheet_select_save = luckysheet.getluckysheet_select_save();

            $("#luckysheet-copy-content").find("table tr").each(function () {
                var $tr = $(this);
                var c = 0;
                $tr.find("td").each(function () {
                    var $td = $(this);
                    var cell = {};
                    var txt = $td.text();

                    if ($.trim(txt).length == 0) {
                        cell.v = null;
                        cell.m = "";
                    }
                    else {
                        var mask = luckysheet.mask.genarate($td.text());
                        cell.v = mask[2];
                        cell.ct = mask[1];
                        cell.m = mask[0];
                    }

                    var bg = $td.css("background-color");
                    if (bg == "rgba(0, 0, 0, 0)") {
                        bg = "rgba(255,255,255)";
                    }

                    cell.bg = bg;

                    var bl = $td.css("font-weight");
                    if (bl == 400 || bl == "normal") {
                        cell.bl = 0;
                    }
                    else {
                        cell.bl = 1;
                    }

                    var it = $td.css("font-style");
                    if (it == "normal") {
                        cell.it = 0;
                    }
                    else {
                        cell.it = 1;
                    }

                    var ff = $td.css("font-family");
                    var ffs = ff.split(",");
                    for (var i = 0; i < ffs.length; i++) {
                        var fa = $.trim(ffs[i].toLowerCase());
                        fa = luckysheet.menuButton.fontjson[fa];
                        if (fa == null) {
                            cell.ff = 0;
                        }
                        else {
                            cell.ff = fa;
                            break;
                        }
                    }

                    var fs = Math.floor(parseInt($td.css("font-size")) * 72 / luckysheet.dpi_y) + 1;
                    cell.fs = fs;

                    var fc = $td.css("color");

                    cell.fc = fc;

                    var ht = $td.css("text-align");
                    if (ht == "center") {
                        cell.ht = 0;
                    }
                    else if (ht == "right") {
                        cell.ht = 2;
                    }
                    else {
                        cell.ht = 1;
                    }

                    var vt = $td.css("vertical-align");
                    if (vt == "middle") {
                        cell.vt = 0;
                    }
                    else if (vt == "top" || vt == "text-top") {
                        cell.vt = 1;
                    }
                    else {
                        cell.vt = 2;
                    }

                    while (c < colLen && data[r] != null) {
                        c++;
                    }

                    if (c == colLen) {
                        return true;
                    }

                    if (data[r] == null) {
                        data[r] = cell;
                        var rowspan = parseInt($td.attr("rowspan"));
                        var colspan = parseInt($td.attr("colspan"));

                        if (isNaN(rowspan)) {
                            rowspan = 1;
                        }

                        if (isNaN(colspan)) {
                            colspan = 1;
                        }


                        var r_ab = luckysheet_select_save[0]["row"][0] + r;
                        var c_ab = luckysheet_select_save[0]["column"][0] + c;
                        for (var rp = 0; rp < rowspan; rp++) {
                            for (var cp = 0; cp < colspan; cp++) {
                                if (rp == 0) {
                                    var bt = $td.css("border-top");
                                    if (bt != null && bt.length > 0 && bt.substr(0, 3).toLowerCase() != "0px") {
                                        var width = $td.css("border-top-width");
                                        var type = $td.css("border-top-style");
                                        var color = $td.css("border-top-color");
                                        var borderconfig = luckysheet.menuButton.getQKBorder(width, type, color);

                                        if (borderInfo[(r + rp) + "_" + (c + cp)] == null) {
                                            borderInfo[(r + rp) + "_" + (c + cp)] = {};
                                        }

                                        borderInfo[(r + rp) + "_" + (c + cp)].t = { "style": borderconfig[0], "color": borderconfig[1] };
                                    }
                                }

                                if (rp == rowspan - 1) {
                                    var bb = $td.css("border-bottom");
                                    if (bb != null && bb.length > 0 && bb.substr(0, 3).toLowerCase() != "0px") {
                                        var width = $td.css("border-bottom-width");
                                        var type = $td.css("border-bottom-style");
                                        var color = $td.css("border-bottom-color");
                                        var borderconfig = luckysheet.menuButton.getQKBorder(width, type, color);

                                        if (borderInfo[(r + rp) + "_" + (c + cp)] == null) {
                                            borderInfo[(r + rp) + "_" + (c + cp)] = {};
                                        }

                                        borderInfo[(r + rp) + "_" + (c + cp)].b = { "style": borderconfig[0], "color": borderconfig[1] };
                                    }
                                }

                                if (cp == 0) {
                                    var bl = $td.css("border-left");
                                    if (bl != null && bl.length > 0 && bl.substr(0, 3).toLowerCase() != "0px") {
                                        var width = $td.css("border-left-width");
                                        var type = $td.css("border-left-style");
                                        var color = $td.css("border-left-color");
                                        var borderconfig = luckysheet.menuButton.getQKBorder(width, type, color);

                                        if (borderInfo[(r + rp) + "_" + (c + cp)] == null) {
                                            borderInfo[(r + rp) + "_" + (c + cp)] = {};
                                        }

                                        borderInfo[(r + rp) + "_" + (c + cp)].l = { "style": borderconfig[0], "color": borderconfig[1] };
                                    }
                                }

                                if (cp == colspan - 1) {
                                    var br = $td.css("border-right");
                                    if (br != null && br.length > 0 && br.substr(0, 3).toLowerCase() != "0px") {
                                        var width = $td.css("border-right-width");
                                        var type = $td.css("border-right-style");
                                        var color = $td.css("border-right-color");
                                        var borderconfig = luckysheet.menuButton.getQKBorder(width, type, color);

                                        if (borderInfo[(r + rp) + "_" + (c + cp)] == null) {
                                            borderInfo[(r + rp) + "_" + (c + cp)] = {};
                                        }

                                        borderInfo[(r + rp) + "_" + (c + cp)].r = { "style": borderconfig[0], "color": borderconfig[1] };
                                    }
                                }

                                if (rp == 0 && cp == 0) {
                                    continue;
                                }
                                data[r + rp] = { "mc": { "r": r_ab, "c": c_ab } };
                            }
                        }

                        if (rowspan > 1 || colspan > 1) {
                            var first = { "rs": rowspan, "cs": colspan, "r": r_ab, "c": c_ab };
                            data[r].mc = first;
                        }
                    }

                    c++;

                    if (c == colLen) {
                        return true;
                    }
                });

                r++;
            });

            var index = luckysheet.sheetmanage.getSheetIndex(luckysheet.currentSheetIndex);
            var file = luckysheet.getluckysheetfile()[index];
            var luckysheet_selection_range = file["luckysheet_selection_range"];

            luckysheet_selection_range = [];
            luckysheet.selection.pasteHandler(data, borderInfo);
            $("#luckysheet-copy-content").empty();
        }

    </script>
</body>

</html>

探讨

仅前端文件导入是不带单元格样式的,但是从excel复制单元格到Luckysheet是带单元格样式的.可以从 在线demo 尝试下.

目前Luckysheet功能正在完善中,可以逐步关注.

The operation was rejected by your operating system.

问题

npm install报错:

The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

解决

  1. 查看是否有程序占用项目文件夹,比如:
    • git bash打开了项目
    • github desktop打开了项目
    • 另外的cmd窗口打开了此文件夹/项目文件夹
    • 开启了本地服务器/vscode等编辑器软件打开了项目
  2. 在项目中已管理员身份运行cmd(如何以管理员身份运行cmd)

node-gyp node-sass安装指南

问题

npm install --global --production windows-build-tools报错

MSI (s) (14:10) [20:36:04:711]: Product: Python 2.7.15 (64-bit) -- Installation failed.

MSI (s) (14:10) [20:36:04:712]: Windows Installer 已安装产品。产品名称: Python 2.7.15 (64-bit)。产品版本: 2.7.15150。产品语言: 1033。制造商: Python Software Foundation。安装成功或错误状态: 1603。

安装时发生严重错误
C:\Users\14145\.windows-build-tools\python-2.7.15.amd64.msi

解决

1.自行下载python2.7.15版本的重装
淘宝镜像站快速下载地址:https://npm.taobao.org/mirrors/python/2.7.15/

2.设置多python
https://blog.csdn.net/qq_27474589/article/details/72583014

3.重新 npm install --global --production windows-build-tools

可能搭配的命令

  1. npm config set msvs_version 2012 --global
  2. npm config set msvs_version 2017
  3. npm install node-pre-gyp -g
  4. 有的依赖比较大,但是国内的网络环境收到了限制,可以参考此篇教程采用更科学的方式
    > 强烈推荐:彻底解决npm下载问题

其他解决思路

一、重新安装
1. npm cache clean --force
2. 删除项目中的 node_modules (如何快速删除node_modules)
3. 删除 package-lock.jsona
4. 重新 npm install

二、node-sass换成sass
1.先卸载node-sass: npm uninstall node-sass -g
2.再安装sass: npm install sass -g

node-gyp

教程链接:https://github.com/nodejs/node-gyp