董懂 发布的文章

UPDATE:8/16

天地图的JavaScript3.0 API中提供了一些方法,在4.0的文档中没有,但是仍然可用,比如设置地图的样式:

map.setMapType(...)

1、引入天地图API

按需引入,在需要用到天地图API的时候,动态创建script标签:

//某组件
...
mounted() {
    this.initMap();
},
...
//methods
initMap(){
    let script = document.getElementById('MapDivId');
    if (script) {
        return this._initMap();
    }

    const _this = this;
    script = document.createElement('script');
    script.id = 'MapDivId';
    script.src = 'https://tianditu.gov.cn/xxxxxxxx';
    script.onload = function () {
        _this._initMap();
    };

    document.body.appendChild(script);
}

二、初始化地图

...
_initMap() {
    //添加卫星图层,下面这个url是固定的,我只找到这种默认显示卫星图层的办法
    let satelliteLayerUrl = "http://t0.tianditu.gov.cn/img_w/wmts?" + "SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles" + "&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=您的密钥";
    let layer = new T.TileLayer(satelliteLayerUrl, { minZoom: 3, maxZoom: 18 });
    window.GIS.Map = new T.Map('Map', { layers: [layer] });
    // 定位到一个默认的坐标,例如北京。这里的坐标是虚构的
    window.GIS.Map.centerAndZoom(new T.LngLat(123.45678, 30.1234), 12);

    //添加地图类型控件
    let ctrlMapType = new T.Control.MapType([
        {
            title: '卫星混合',
            icon: 'http://api.tianditu.gov.cn/v4.0/image/map/maptype/satellitepoi.png',
            layer: TMAP_HYBRID_MAP
        },
        {
            title: '地图',
            icon: 'http://api.tianditu.gov.cn/v4.0/image/map/maptype/vector.png',
            layer: TMAP_NORMAL_MAP
        }
    ]);
    window.GIS.Map.addControl(ctrlMapType);

    //添加缩放控件
    let ctrlZoom = new T.Control.Zoom();
    window.GIS.Map.addControl(ctrlZoom);
    ctrlZoom.setPosition(T_ANCHOR_BOTTOM_RIGHT);

    //添加比例尺控件
    let ctrlScale = new T.Control.Scale();
    window.GIS.Map.addControl(ctrlScale);
},
...

三、添加各种标注工具

首先编写HTML结构,定位到地图上的某个位置,并绑定一个click事件,这部分很简单,效果如下:

1.png

然后编写click事件代码:

<span class="icon xxxx" @click="openPolygonTool"></span>
openPolygonTool() {
    if (window.GIS.handler) window.GIS.handler.close();
    let handler = new T.PolygonTool(window.GIS.Map);
    handler.open();
    window.GIS.handler = handler;
}

效果如下:

2.png

四、保存标注数据

一般在打开标注工具的时候,注册一个相关事件,这样,在结束标注的时候,就能获取到标注的数据。多边形的结束事件是draw

openPolygonTool() {
    ...
    handler.addEventListener('draw', function(e){
        console.log(e);
    });
    handler.open();
    ...
}

到这里,就可以把需要的数据存储起来了。

END

还没仔细研究antd vue的代码,所以动态菜单图标的显示机制还没弄明白,时间仓促,临时找到一个解决办法。

1、选好所需图标

iconfont网站上选好要用的图标,放到一个项目中,在项目设置中,把图标前缀改成anticon,更新代码后,选择下载到本地或者复制在线地址。

2、在public/index.html文件中引用图标

如果下载到本地,就把资源复制到public/static/下,然后在index.html中引入,或者直接引入复制的在线网址。

3、在菜单中使用图标

在系统设置-菜单管理中,在图标一栏填入图标的名字,注意不要带前缀。图标的名字可以在iconfont网站上,鼠标放到项目中的图标上,直接点击复制
当然,也可以在页面的任意位置用任意标签使用图标:

<span class="anticon anticon-tubiao"></span>

4、在任意全局的地方(比如index.html中)加入下面的css代码:

<style>
  .anticon:before {
    display: block !important;
  }
</style>

为什么要在iconfont的项目设置中修改图标前缀呢?因为antd vue图标的class就是anticon
重置.anticon:before的样式,目前也没有发现任何副作用。

有更好的方法欢迎留言告诉我。

END

在一个宽度100%,也就是宽度不固定的容器中,里面有横向排列并且会换行的列表项,列表项的宽度固定,所以每行列表项的个数随着容器的宽度变化:

<div class="box">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    ....
</div>
.box{
    display: flex;
    flex-wrap: wrap;
}
.item{
    width: 200px;
    height: 300px;
    margin-bottom: 20px;
}

在列表项不超过一行的时候表现很正常,但是在出现换行的情况下,每行最后可能会出现比较大的空白,这是因为虽然这行剩余的空间放不下一个.item了,但可能只比.item的宽度小一点点:

1.png

我们的目的是,让列表两端对齐,每个项的边距一样大,最后一行如果有空缺,那么就左对齐:

3.png

如果给.box设置下面的样式会怎样呢:

.box {
    ......
    justify-content: space-between;
    ......

如果一共5个.item,每行显示3个.item,结果会像这样:

2.png

解决办法就是补齐缺少的.item。因为第二行缺少1个.item,我们可以给它补上一个看不见的、高度是0的.item

<div class="box">
    ......
    <div class="item"></div>
    <div class="item placeholder"></div>
    ....
</div>
.placeholder{
    visibility: hidden;
    height: 0;
}

这时候就达到了最初的目的:

3.png

那如果每行显示4个、5个项,最后一行缺少2个、3个……怎么办?
如果你能知道你的列表最多有几个列,就可以补上几个.placeholder。如果你不确定,那么可以补多一些,保证补的.placeholder数量多于可能会出现最多的列数。因为.placeholder的高度是0,所以不会对垂直方向的布局产生影响。

这样有一个缺点:随着改变窗口大小,会发现.item之间的空隙忽大忽小。这是因为随着.box的宽度变化,行剩余的空间随之变化,行中的.item的间隙是flex动态计算的,所以会不断变化。如果你不能接受这一点,可以继续往下看。

我们设置固定的边距,并且让列表看起来两端对齐:

.box {
    ......
    /* 删掉或注释掉下面一行 */
    /* justify-content: space-between; */
    /* 设置负margin是为了让列表看上去两端对齐,两边不出现空白 */
    margin: 0 -10px 0;
    ......
}

.item可以扩展宽度并设置基本宽度:

.item {
    flex: 1 200px;
    /* 删掉或注释掉下面一行 */
    /* width: 200px */
    margin: 0 10px 20px;
}

这样,随着.box宽度的变化,.item之间的边距不再变化。但是每个.item的宽度又会跟着变化了,道理同上。不过,宽度变化视觉上要好于边距变化,个人倾向于这种方法。

下面是第二种方法的完整代码:

<div class="box">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <!-- 个数根据需要增减 -->
    <div class="item placeholder"></div>
    <div class="item placeholder"></div>
    ....
</div>
.box{
    display: flex;
    flex-wrap: wrap;
    margin: 0 -10px;
}
.item{
    flex: 1 200px;
    height: 300px;
    margin: 0 10px 20px;
}

END

UPDATE: 2024-08-02
国家网络身份认证App已经发布了,这篇文章的设想已经实现了
相关链接:国家网络身份认证公共服务管理办法向社会公开征求意见


现在的各种APP,只要注册,就必须把自己的手机号交给它们,想要使用某些功能,还必须要实名认证,甚至还要刷脸认证,理由是“根据监管……”也不知道是真的还是假托这样的理由。更有甚者,比如支付宝,不仅要你的身份信息、人脸信息,还千方百计引诱你交出车牌号、社保卡号、公积金账户、教育经历、学历、入职公司……等一切有价值的隐私信息,真让人害怕。

现在国内的APP在滥用用户个人信息方面已经不成样子了,用户毫无隐私可言。各大互联网公司互通有无,你在这个平台上浏览了某个商品,另一个APP上马上为你推荐这类商品。这还不算什么,要是有无良公司把你的信息卖给所谓的金融公司、野鸡招聘网……等等,那你就面临被诈骗的风险。

昨天滴滴被国安部查了,事情非常严重。滴滴掌握的这些信息对国家安全都有影响。

既然这样,为什么不让国家牵头,建立一个统一的认证中心呢?这个中心对外提供接口,接受加密的用户验证信息,在此过程中确保互联网公司不能获取到用户信息;验证通过后,只要返回true或者false来告诉互联网公司验证结果。这样一来,互联网公司没理由再收集用户信息了,国家又能提供权威的验证,又掌握了公民的信息安全,技术上难度也不大,这对国家对个人都有好处,唯一不高兴的肯定是那些大公司了。

不过这样做也不能解决所有问题。就比如钉钉,现在小学校都在用它留作业、交作业,家长也需要参与进去。这样,钉钉能获取的信息简直太丰富了:孩子的基本信息、位置信息、家庭信息、父母信息、孩子的学校班级、学习成绩、班级排名,进而分析出学生的学习习惯、生活习惯、性格,学校的基本信息、教学状况等、家长的财务状况、文化水平……,通过关联其他APP还能获得更多的信息,简直取之不尽……

希望国家重视这类信息的监管,这些信息掌握在国家手里我是放心的。

0、前言

vs code市场里面的主题很多。然而数量虽多,却很难找到一个完全符合自己心意的主题,往往总有几个地方是自己不满意,或者无法接受的。市场中主题的预览图因为一些原因无法打开,只能把主题安装后再应用,才能看到效果,这也导致想要找到一个合适的主题非常麻烦。为什么不自己制作一个简单的主题呢?

我们不是vs code扩展的开发者,不可能从头阅读大量的开发手册。我们要做的是,找到一个最简单的办法,制作出自己的主题。

1、生成扩展

首先需要安装扩展生成器,用来生成vs扩展的基本框架。
用管理员身份打开命令提示符,定位到你想要存放代码的位置,输入并运行下面的命令:

npm install -g yo generator-code

安装完毕之后,使用下面的命令来生成扩展的基本结构:

yo code

运行上面的命令,需要你输入或者选择一些内容,大概是:

是否发送反馈
创建扩展类型,这里选择颜色主题
是创建新的还是导入现有的
主题是浅色还是深色、名称、创建者、其他用户在市场中看到的主题名等等
是否初始化git仓库
等等

根据提示和自己的需要,直到提示创建成功。创建好的文件在命令提示符所在的目录。用vs code打开此目录,结构是这样的:

1.png

themes文件夹下的json文件就是我们要编辑的主题文件。

主题的各种配置十分繁琐。为了节省时间,我们首先在主题市场中找到一个看起来比较顺眼的主题,找到主题配置文件,一般在\Users\你的用户名\.vscode\extensions\扩展名称\themes\主题名称.json,打开它,发现它和你的json文件结构是一样的,大概如下:

2.png

其中的colors配置界面的配色,tokenColors配置语法高亮。

如果你需要定制自己独特的配色,当然可以从头配置各项的颜色,具体的配置在这里:

https://code.visualstudio.com/api/extension-guides/color-theme

如果你也只是希望修改一下刚刚下载的那个主题,那就可以先复制粘贴,用那个主题的配置覆盖你的配置,然后在此基础上修改自己不满意的地方。注意不要把自己主题的名字之类的东西覆盖。

保存之后,按F5进入调试模式,此时会打开一个新的vs窗口,你可以在这个窗口中打开任意文件,用来观察效果。修改json文件并保存后,调试窗口立刻显示出修改后的效果。

2、修改界面配色

以修改编辑器的背景颜色为例。

打开一个颜色拾取器,比如微信截图,将鼠标放到编辑器编辑区内,获取其色值。色值需要16进制格式,如果你获取的是RGB格式,还需要转换一下。接下来在你的json文件中查找并替换这个16进制的颜色。
这里介绍一个小技巧。如果你仅仅想修改颜色的深浅,那么你可以打开一个在线LESS编辑器,使用darken或者lighten函数并编译成css来获得新色值。
替换并保存之后,在调试窗口查看效果。
重复上面的过程,直到把自己想要修改的地方都改好。

3、修改语法高亮配色

语法配色当然也可以从头配置,参考这个链接:

https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide

配置也是非常复杂的。这里还是在别人的主题基础上修改。
参照现有配置,发现tokenColors对象是一个数组,数组的每一个项都是一个对象,这就是一个配置项,结构如下:

{
    "name": "xxxx",
    "scope": [
        "variable.language.this.js",
        "support.type.property-name.json.comments"
    ],
    "settings": {
        "fontStyle": "bold",
        "foreground": "#0094f0"
    }
}

我们新建一个配置项,其中的name是任意命名的,settings也好理解,大概就是颜色、粗体、斜体、下划线等有限几个配置,至于scope,就需要使用下面的命令来获取了:

3.png

如果你想要调整JavaScript语法高亮的配色,需要用任意窗口打开任意一个js文件,为了方便观察效果,这里就在调试窗口里打开一个js文件,按Ctrl+Shift+P打开运行输入框,运行图中的命令。运行后,当你在文件中点击代码时,会弹出一个窗口,告诉你你点击的代码所属的scope

4.png

一般第一行就是我们想要的scope。复制这一行,粘贴到上面我们新建的配置项中的scope字段中。如果有多个scope用同一个配置项,需要用逗号隔开不同的scope。

保存查看效果。在关键字、函数名、变量名...之上点击鼠标,查看它们的scope名,并按需建立不同的配置项,来实现不同的代码不同的配色。

满意后,按ESC关闭scope查看窗口。

4、打包主题

扩展编辑完毕后,就需要打包了。因为我们不想发布到市场,所以只打包到本地就可以了。如果你想把你制作的主题发布到市场,请参阅vs相关文档。

用管理员身份打开命令提示符,运行下面的命令安装VSCE:

npm install -g vsce

安装好之后,定位到开发文件夹,运行:

vsce package

如果配置正确,就会输出一个.vsix包到你的开发目录下。拖动这个文件到VS的扩展窗口,就可以安装这个主题,在主题列表里选择并应用这个主题。也可以把这个文件分享给别人使用。

至此,简单的自定义vs code主题开发完成了。下面是我比较喜欢的样式:

HTML,自定义组件粗体显示:
5.png

JavaScript:
6.png

LESS:
7.png

End

以前,删除好友后,只要对方没有把你删除,再把TA添加回来,对方是没有任何提示的。但是事情从今天开始可能就变了。

今天我在实验的时候发现,即使对方没有把你删除,你在添加对方时,如果对方开启了验证,已经需要发送验证请求了,如果对方没有开启验证,那对方还是没有任何提示的。

所以在此提示大家,珍惜友情,谨慎删除好友。本次实验用的是我自己的小号 :-)

End

应该有挺多人遇到了这一问题,就是formidableparse无论如何也不执行,找了很多原因,尝试了很多方法,都不管用。

const formidable = require('formidable');

const form = new formidable({
    multiples: true,
    uploadDir: path.join(__dirname, '../ ', '../', '../', 'public', 'uploads'),
    keepExtensions: true
});

form.parse(req, (err, fields, files) => {
    console.log(0); // 不执行
})

我也遇到了这种情况。在parse上选择转到定义,在formidable - parse的源码中添加console,可以看到实际上parse是执行了的,但是浏览器一直在转圈,node端也没有反应,说明这时node不知道怎么处理这个请求,一直处在等待状态。

既然不是formidable的问题,那肯定是请求有问题。
这是一个POST请求,请求由submitbutton触发,由HTML的form发出。
既然是由form发出的请求,那我们来检查一下form的配置是否正确。form如下:

<form method="POST" action="user/add">
  <file/>
</form>

问题就在这里了。这里的form好像缺少一个常用的属性:enctype。这个属性有3个取值,其中有一个值是multipart/form-data,它的描述是:不对字符编码。当使用有文件上传控件的表单时,该值是必需的,而我们的form里面恰恰有一个file
所以,给form加上这个属性试试:

<form method="POST" action="user/add" enctype="multipart/form-data">
......

问题解决了。

End

0、前言

首先,建议直接上传设计稿到蓝湖之类的网站自动生成标注。地址:https://lanhuapp.com/,设计稿上传上去之后,直接把蓝湖的地址发给程序员就行了。

如果无法使用以上的方法,请继续往下看。

使用Sketch Measure插件来标注和切图非常方便。
首先肯定要安装Sketch。

1、下载Sketch Measure插件

安装好Sketch,接下来下载Sketch Measure插件。下载地址:https://github.com/utom/sketch-measure,点击绿色的“download zip”按钮下载,或者直接点击这个链接:https://github.com/ellunium/sketch-measure/archive/master.zip(不保证是最新版本)

2、安装Sketch Measure

解压下载的文件,双击Sketch Measure.sketchplugin完成安装。

3、使用Sketch Measure

点击Sketch的Plugins - Sketch Measure,可以看到Sketch Measure提供的功能,点击Plugins - Sketch Measure - 工具栏,可以显示出快捷工具栏,不用再一次次从菜单中选择功能。

工具栏如下:

sketch-measure-2@2x.jpg

接下来就是使用这个插件了。

标记尺寸、颜色、字体等一般操作步骤是

  • 选中要操作的图层(根据需要,选中1个或多个图层,比如标记两个图层之间的距离,就要选中两个图层)
  • 根据需要点击工具栏上相应的按钮

4、其他

如你所见,这个插件一共只有上图中那些按钮和功能,使用起来也非常简单。只要尝试几遍就能掌握,重要的就是要敢于尝试。

End

想要通过事件冒泡,获取到.item的data,WXML如下:

<view class="toolbar" catchtouchend="format">
    <view class="item" data-name="list" data-value="ordered">
      <text class="iconfont icon-youxuliebiao"></text>
      <text class="name">有序列表</text>
    </view>
</view>

上面的结构是无法在js中通过e.target.dataset获取到data-namedata-value的:

- 阅读剩余部分 -