独书先生 Menu

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

参考

全网最强攻略《英雄联盟手游》如何申请公测资格及申请方法

《英雄联盟》(简称LOL)是由美国拳头游戏(Riot Games)开发、中国大陆地区腾讯游戏代理运营的英雄对战MOBA竞技网游,而英雄联盟手游是一款根据这款经典端游改编而来的MOBA手游,你可以在这里看到很多有趣的内容和玩法。

介绍

《英雄联盟》(简称LOL)是由美国拳头游戏(Riot Games)开发、中国大陆地区腾讯游戏代理运营的英雄对战MOBA竞技网游,而英雄联盟手游是一款根据这款经典端游改编而来的MOBA手游,你可以在这里看到很多有趣的内容和玩法。
英雄联盟手游内测
最近《英雄联盟手游》开启了大范围公测,遗憾的的是这次公测并没有国服。据悉这次公测并非全球开放,而是分批进行,率先全面开放LOL手游的国家分别是韩国、日本、菲律宾、新加坡、马来西亚、印度尼西亚和泰国。手游全球公测将在12月首周逐步开启,预计开放的新区域为欧洲、中国台湾、大洋洲、越南。没错,成功绕过了中国大陆,真的是环大陆公测!他们是怎么做到的!

那么,大陆不公测,我们就玩不了么?很多朋友问英雄联盟手游公测下载链接是什么?怎么才能申请这次公测的资格呢?

很多玩家还不清楚外服的资格到底要怎么申请,直接去英雄联盟手游预约官网都无疾而终。下面就来为大家分享一下申请外服测试资格的方法教程。

方法一:开放的谷歌商店直接申请

  1. 首先需要确定了,韩国、日本、菲律宾、新加坡、马来西亚、印度尼西亚和泰国这几个国家的谷歌商店可以预约公测
  2. 登入任意一家的谷歌商店,下载英雄联盟手游预约即可!
    英雄联盟手游预约

注意:有同学发现谷歌商店无法注册,因为google.com根本上不去,这里重点提醒下,强烈推荐采用科学的姿势进行操作,详细姿势请参考:

强烈推荐的科学冲浪软件:Express VPN,或者阅读(为什么推荐它

然后再使用google.com搜索谷歌商店就可以了。
修改Google Play国家地区的官网教程:更改您的 Google Play 国家/地区

方法二:UU加速器

  1. 下载并安装:UU加速器
  2. 搜索找到英雄联盟手游快速下载
  3. 同样需要登陆谷歌账户,启动游戏即可

可能出现的问题
1. UU加速器下载英雄联盟手游的时候提示:不支持下载,请至游戏官网下载。这个可能是vivo或者其它手机自带应用商店 的加速器不是最新版本,需要单独去官网下载UU加速器最新版才可以。
2. 有部分同学可以下载安装英雄联盟了,但是启动游戏时提示与Google服务器通信时出现问题,这个就是典型的不科学姿势,请参考方法一的科学操作
3. 首次激活之后,游戏启动界面提示:Failed to verify login info.Please try again 10087 100036,或者相关的错误代码提示。这个问题出现的话,基本就是需要谷歌商店里搜索下载英雄联盟了,然后再配合加速器使用。

方法三:奇游电竞加速器

如果以上两种方法都不适用,还可以尝试下奇游的加速器。

  1. 安卓用户下载并安装:奇游
  2. 打开APP,在非常明显的位置就可以看到预约入口
    英雄联盟手游预约
  3. 从预约入口进去之后,可以看到不同区服的入口,选择相应区服,点击“下载”然后“加速”
    英雄联盟手游加速
  4. 加速成功之后,会弹出一个图片,需要点击图片进行下一步操作。
  5. 接着根据自己是否有谷歌账号,以及谷歌账号的情况来一步步进行就完成预约了。
    英雄联盟预约需要谷歌账号
    Google Play下载英雄联盟

拓展资讯

近日,对外发布公告宣称,10月27日将会开启更大范围的公测。
游戏官方还表示在韩国及日本等大部分地区,玩家可以用拳头账号登陆游戏,并会根据对《英雄联盟》端游的投入获得相应奖励。

10月27日开放公测的同时,还有一些新的英雄加入手游中。分别是诺手、德莱文、瞎子、阿卡丽、寡妇、萨勒芬妮和卡莎,加上之前的已经上线的42位英雄,总计49位英雄供玩家选择。

英雄联盟手游上线时间官方并没有直接给出答案,不过按照现在进度,2021年春季应该差不多了,到时候大家去英雄联盟正版手游官网注册即可。

总结

到这里,大家就不用再问像英雄联盟手游公测入口,LOL手游公测申请方法这样的问题了。等到大陆也开放了英雄联盟手游公测申请,相信是一个压过王者荣耀人气现象级国民手游。

资源列表

  1. 英雄联盟手游官网
  2. 英雄联盟手游预约: 各大谷歌应用商店,及微信游戏
  3. 科学冲浪方法推荐
  4. 更改您的 Google Play 国家/地区
  5. UU加速器

提交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

python处理excel之excel单元格内容首字符去除

需求

excel首列的单元格内容,首字符去除,如何做?

思路

使用 openpyxl 第三方库,打开excel,首字符去除,使用字符串截取方法取得除了第一个字符外的字符str[1:],再赋值回去,保存excel

代码

演示处理 A2:A5 单元格的内容

from openpyxl import Workbook
from openpyxl import load_workbook

wb = load_workbook(filename = 'workbook1.xlsx')

sheet_ranges = wb['Sheet1']

rangeColumn = range(2,6)
for i in rangeColumn:
    cell = "A" + str(i)
    sheet_ranges[cell] = str(sheet_ranges[cell].value)[1:]

wb.save("workbook2.xlsx")

扩展

根据示例代码,可以自行扩展为更通用的方法,比如循环A列单元格的值,一直取到空值停止,这样就可以处理多个不同的excel了。

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