643104191

643104191 查看完整档案

深圳编辑  |  填写毕业院校  |  填写所在公司/组织 segmentfault.com/u/643104191 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

643104191 赞了回答 · 9月9日

解决有赞vant组件库在vue-cli创建项目中自定义全局样式问题(修改var.css)

vue-cli@3中处理全局SASS/SCSS变量的方法(亲测可用):
2020年9月6日 12:01:24

# 主流的两种方法 :
  • 使用 sass-resources-loader
  • vue.config.js 中配置 sass-loader

    // vue.config.js
    
    module.exports = {
      // sass-loader
      // https://vue-loader.vuejs.org/zh/guide/pre-processors.html#sass
      css: {
        loaderOptions: {
          sass: {
            // webpack.docschina.org/loaders/sass-loader/#options
            // webpack.docschina.org/loaders/sass-loader/#additionaldata
            // cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
            additionalData: '@import "~@/style/variables.scss";'
          }
        }
      },
    }
# 注意:
  • vue.config.js 中引入了 variables.scss 后,不要再在 main.js 中引入,否则报错SassError: An @import loop has been found:
# 参考:

关注 2 回答 3

643104191 发布了文章 · 2019-11-22

快速无脑创建一个使用typescript开发&使用eslint代码风格校验的uni-app开发框架

1.目前已知信息

  1. 在vue-cli里使用dcloud预设的uni-app开发配置,可以创建使用typescript开发但是没有eslint校验uni-app开发框架

      vue create -p dcloudio/uni-preset-vue my-project
  2. 在vue-cli里直接创建项目,可以创建使用typescript开发并且有eslint校验vue开发框架

      vue create my-project

2.整合信息

目前得到A,B两个项目


A.使用typescript开发但是没有eslint校验uni-app开发框架

B.使用typescript开发并且有eslint校验vue开发框架

很容易想到将以上两个项目的package.json结合起来就能得到

使用typescript开发并且有eslint代码校验uni-app开发框架

3.结合package.json注意事项

各种依赖的版本需要以A项目中的为准
否则可能会出现期望之外的错误

4.eslint校验注意事项

在对no-unused-vars这条规则进行校验时
eslint并不能正常校验typescript的type/interface的使用情况
需要按照这个issues去修改eslint配置

5.最终成果

点我查看

觉得有用的可以在github上点个星
或者给这篇文章点个收藏或者点个赞

6.挖坑

下次抽个时间写个从0开始的分解步骤

查看原文

赞 1 收藏 1 评论 0

643104191 赞了文章 · 2019-11-01

CSS3 border-image 彻底明白

border-image用于给border(边框)贴上背景图像

类似于CSS中的background(背景)属性。 例如:background:url(xx.jpg) 27px no-repeat;指的是图片(url(xx.jpg)),位置(27px),重复性(no-repeat)。

border-image与此类似,border-image包括图片,剪裁位置(与background位置一样,也是数值,也支持百分值),重复性。
例如:border-image:url(border.png) 27 repeat; 指的就是图片(url(border.png)),剪裁位置(27),重复方式(repeat)。
图片描述

下面我们将border-image的复合写法分解描述,

border-image的主要参数就是上面提到的三个:图片,剪裁位置,重复性。
其实还有另外两个,文章最后面再讲。更好理解

1、图片(border-image-source)

  • border-image的背景图使用url()调用,图片可以是相对路径或是绝对路径,也可以不使用图片,即border-image:none;

2、图片剪裁位置(border-image-slice)

  • 没有单位,默认单位就是像素(px)。例如:border-image:url(border.png) 27 repeat;这里的27专指27px。

  • 支持百分比值,百分比值大小是相对于边框图片的大小,假设边框图片大小为400px*300px,则20%的实际效果就是剪裁了图片的60px 80px 60px 80px的四边大小。

  • 剪裁特性。类似于CSS中的clip属性。其有1~4个参数,代表上右下左四个方位的剪裁,符合CSS普遍的方位规则(与margin,padding等或border-width一致),举个简单的例子,前面提到,支持百分比宽度,所以这里“30% 35% 40% 30%”的示意可以用下图表示:
    clipboard.png

距离图片上部30%的地方,距离右边35%,距离底部40%,左边30%的地方各剪裁一下。也就是对图片进行了“四刀切”,形成了九个分离的区域,这就是九宫格,这是下面深入讲解border-image的基础。

3、重复性(border-image-repeat)

取值为repeat(重复)只是其中之一,其余两个是round(平铺)和stretch(拉伸)。其中,stretch是默认值。

参数0~2个,0则使用默认值 – stretch,例如:border-image:url(border.png) 30% 40%;就等同于border-image:url(border.png) 30% 40% stretch stretch;;1则表示水平方向及垂直方向均使用此参数;2个参数的话则第一个参数表水平方向,第二个参数表示垂直方向。例如:border-image:url(border.png) 30% 40% round repeat;表示水平方向round(平铺),垂直方向repeat(重复)。

关于round 和repeat 的区别。
round会凑整填充(进行了适度的拉伸)。repeat不进行拉伸,不凑整。 具体效果看文章后边的例子。

4、实际渲染规则

通过裁切属性值,将边框背景图切出了“九宫格”的模型,那这张背景图怎么对应地贴在div的边框上呢?

clipboard.png <————————> 图片描述

图片描述

  • 如图 在border-image中的橙红色的四个边角只会呆在border的四个角,并且水平和垂直方向均被拉伸来填充border的四个角。
  • 如图 上下区域即border-top-image和border-bottom-image受到第一个参数——水平方向效果影响:如果为repeat,则此区域被水平重复(round水平平铺,stretch水平拉伸)来填充对应的上下border【该区域在垂直方向上首先会按所对应的border-image-width的值等比缩放,然后再按参数设置在边框水平方向上进行重复或平铺或拉伸】
  • 左右区域border-left-image和border-right-image 的作用效果亦然【该区域在水平方向上首先会按所对应的border-image-width的值等比缩放,然后再按参数设置在边框垂直方向上进行重复或平铺或拉伸】

图片描述



我们用下图(27×3)px *(27×3)pxpng 做实验,我给不同部位加了一个序号做标志,便于观察。
图片描述

    // 加一个蓝色背景的父级,便于我们分析效果。
    .border_image {
        width: 400px;
        height: 115px;
        border: 3em double orange;
        -webkit-border-image: url(border.png) 27 round;
        border-image: url(border.png) 27 round;
    }
    .box {
        background: blue;
    }

    <div class="box">
        <div class="border_image"></div>
    </div>

效果如下
clipboard.png


   //去掉重复属性,即默认都为stretch
   border-image: url(border.png) 27;

效果如下
clipboard.png


  //使用repeat
  border-image: url(border.png) 27 repeat;

效果如下
clipboard.png



    //边框宽度改变
    border-image: url(border.png) 27 repeat stretch;
    border-width: 3rem 1rem;

效果如下

clipboard.png



5、(边框背景宽度)border-image-width

这个属性默认是边框的宽度,用来限制相应区域背景图的范围,
首先相应背景区域的图像会根据这个属性值进行缩放。然后再重复或平铺或拉伸。

在复合写法中应该位于 slice属性 和repeat属性中间 用“/”间隔
如:border-image:url(border.png) 27 / 6rem / repeat;

语法:border-image-width: [ <length> | <percentage> | <number> | auto ]{1,4}

length 带 px, em, in … 单位的尺寸值
percentage 百分比
number 不带单位的数字;它表示 border-width 的倍数
auto 使用 auto, border-image-width 将会使用 border-image-slice 的值
    border: 3em double orange;
    border-image: url(border.png) 27 round;
    border-image-width: 6rem;

效果如下
(白框为border)
图片描述

    border-image-width: 1.5rem;

效果如下
(白框为border)
图片描述


    border: 3em double orange;
    border-image: url(border.png) 27 round;
    border-image-width: 6rem 1.5rem;

效果如下
(白框为border)
图片描述

6、(边框背景扩散)border-image-outset

语法:border-image-outset: [ <length> | <number> ]{1,4}
相当于把原来的贴图位置向外延伸。不能为负值,试一下就知道。

在复合写法中应该位于 border-image-width 后面,用“/”间隔
如:border-image:url(border.png) 27 / 6rem / 1.5rem /repeat;
向外延伸1.5rem再贴图。。
    border: 3em double orange;
    border-image: url(border.png) 27 round;
    border-image-width: 1.5rem;
    border-image-outset: 1.5rem;

效果如下:
(白框为border)
图片描述
ps 部分资料来源网络

亲们,看懂没?不懂请留言,帮你解答。。保会。。

查看原文

赞 41 收藏 30 评论 4

643104191 关注了问题 · 2019-10-16

微信静态资源公共库的地址是什么?

就比如
http://mat1.gtimg.com/libs/jquery/1.12.0/jquery.js
的资源库首页是
https://libs.qq.com/


http://res.wx.qq.com/open/js/jweixin-1.4.0.js
所在的资源库首页是啥????


我记得我之前访问过一次
里面资源还挺多的
比如有weui,vconsole....
但是没保存书签
现在就找不到了

关注 1 回答 0

643104191 提出了问题 · 2019-10-16

微信静态资源公共库的地址是什么?

就比如
http://mat1.gtimg.com/libs/jquery/1.12.0/jquery.js
的资源库首页是
https://libs.qq.com/


http://res.wx.qq.com/open/js/jweixin-1.4.0.js
所在的资源库首页是啥????


我记得我之前访问过一次
里面资源还挺多的
比如有weui,vconsole....
但是没保存书签
现在就找不到了

关注 1 回答 0

643104191 回答了问题 · 2019-08-30

解决vscode在tsconfig.json中指定了types选项,却找不到相关的声明

我之前自己给tsconfig.json加了个include
然后types就失效了
不知道为啥
我把include删掉就行了

关注 1 回答 1

643104191 提出了问题 · 2019-08-30

解决vscode在tsconfig.json中指定了types选项,却找不到相关的声明

项目创建方式

vue create -p dcloudio/uni-preset-vue my-project

在创建的过程中选择了默认的 Typescript模板

问题步骤

直接在.ts文件中写Page下的interface

function foo(options: Page.CustomShareContent){
// ...
}

然后就报错了(见下图)

图片描述

请问这个问题应该如何解决?

关注 1 回答 1

643104191 赞了回答 · 2019-04-08

video标签如何只把全屏按钮给去掉????

微信浏览器控制不了视频是否全屏显示的

全凭微信的心情。

关注 4 回答 4

643104191 赞了回答 · 2019-02-15

vuerouter $route watch无效了?

你注释打开的那几个路由跟user组件也没关系啊,虽然你名字起的是Userxxx。
全是独立的路由,每次跳转都被销毁,watch来不及执行。


补充,不是说/user/a就一定是/user的子路由,在定义router的时候必须有明确的children关系才是。况且你的代码里连路径的层级关系都没有。


再补充。不会,你可以在router-view外加个keep-alive,然后这种情况下路由组件不会被销毁,你能看到watch:"$route"是能执行的。然后简单看了下源代码:

Vue.prototype.$destroy = function () {
    // teardown watchers
    if (vm._watcher) {
      vm._watcher.teardown();
    }
    while (i--) {
      vm._watchers[i].teardown();
    }
}

Vue的$destory里有一步是.teardown(),此方法会将watcherthis.active = falseactive属性置为false,当watcher执行时发现activefalse会直接跳过。
watcher的队列里,watch对应的watcher是在destory对应的watcher之后的,所以destory后,当前销毁组件的所有watcher就会被全部跳过不再执行。至于为什么是这个顺序,没看。

watch和watcher是两个东西,watch是监听api,watcher是所有相关操作的一个对象,包括watch的回调,计算属性,render等操作。

关注 1 回答 1

643104191 收藏了文章 · 2019-01-26

利用网页版微信API做一个微信机器人

本文不涉及到 AI 的知识,如果你是冲着 AI 来的,那么可能会让你失望了.

前一阵子一个朋友找我,问我能不能搞一个微信自动加好友的软件,(在普通人眼里,程序员就是专门写木马病毒外挂软件的三流黑客.不会写那就连三流都不是.

所以为了证明我是三流黑客,我随便百度了两个现成的给他.本来事情到这里应该结束了的,不过本着探索的精神,想顺便了解一下这种外挂的原理,于是百歌谷度了一下,
最终原理没找到,倒是找到几个有意思的 github 仓库,利用网页版的微信 API 做第三方微信.

先看个效果?

<img data-original="https://raw.githubusercontent...; width="300" />
<img data-original="https://raw.githubusercontent...; width="300" />

步骤

我们看看大致步骤

  1. 获取 UUID
  2. 根据 UUID 获取二维码
  3. 扫码登陆, 获取登陆信息
  4. 拿登陆信息换初始化数据
  5. 拿数据初始化
  6. 获取好友列表和消息列表
  7. 发送消息

以下为具体过程,不感兴趣的可以直接拉到末尾查看源码仓库

需要注意的是,每一步的请求所使用的方法(POST/GET) 和 Content-Type 都是不一样的,下面我都有标注,如果有请求不通的请参考 gtihub 源码.

一、获取 UUID

接口地址 https://wx.qq.com/jslogin

请求方法 POST

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    appid: 'wx782c26e4c19acffb',
    fun: 'new',
    lang: 'zh_CN',
     _: new Date().valueOf()
}

除了最后一个当前时间戳不是固定的,其他的3个参数都是写死的,照抄即可,调用成功的话,会到一个字符串 window.QRLogin.code = 200; window.QRLogin.uuid = "obizONtqZA==";, 需要自己想办法截取到 window.QRLogin.uuid = 后面的那串字符,即 UUID.

二、获取二维码

这一步很简单,有了 UUID 后,我们可以直接请求 'https://wx.qq.com/qrcode/' + UUID 获取到二维码. 获取到二维码以后,先别急着去扫描二维码,因为我们要先去监听二维码的扫描状态,这样我们才能知道什么时候被登陆.

请求方式 GET 无需参数

三、监听二维码的扫描结果

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 GET

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    tip: 0,
    uuid: 'obizONtqZA==',
    _: new Date().valueOf(),
    loginicon: true
}

tip 取值 0 或 1, 监听分2个阶段,第一阶段,监听用户是否扫码,tip 为 0,第二阶段,监听用户是否在微信上点确认登陆,tip 为 1.

uuid 就是第一步获取到的那个 UUID

_ 当前时间戳

loginicon 我猜应该是否扫码完返回用户头像,都填 true 即可.

返回结果,当你扫描二维码的时候,接口会返回你一个这样的对象

{
    'window.code': 201,
    'window.userAvatar': 头像的 base64 地址
}

得到的 code 是 201, 说明已扫码,但并不代表已登陆,还需要继续监听是否在手机微信上点击 确认登陆 按钮(重复上面步骤,把 参数里的 tip 改为 1 即可)

这步如果成功的话,会返回一个如下对象

{
    'window.code': '200',
    'window.redirect_uri': 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ARD37_ikx-Kakd2i0W-f-E7q@qrticket_0&uuid=4f6yOkV4AA==&lang=zh_CN&scan=1548300672' }
}

四、获取初始化数据(敏感数据)

上一步获取到的数据里面的 window.redirect_uri 里包含了一个 url 和一些 查询参数,直接请求这个地址好像没办法成功,需要将 url 和 参数拆分,然后加入其他参数

接口地址 就是上面的 url

请求方法 GET

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    ticket: 上面得到的 ticket,
    uuid: 上面得到的 uuid,
    lang: 'zh_CN',  // 固定
    scan: 上面得到的 scan,
    fun: 'new' // 固定
}

这一步的返回的头部里面,会有个 cookie ,需要存起来,接来来得到请求头里面要带上这个 cookie,另外就是一个 xml 格式的 敏感的信息,也是要存起来.

tip: xml 格式可以用 xml2js 转换成 json.

五、初始化

呼,到这一步,终于接近登陆成功了,只需再调用以下接口,初始化以下

接口地址 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=${~(new Date().valueOf())}

请求方法 POST

参数类型(content-type) application/json

参数

{
    BaseRequest: {
        DeviceID: 'e747337466044216', // 这个好像随便填都可以
        Sid: 上一步获取到的 wxsid,
        Uin: 上一步获取到的 wxuin,
        Skey: 上一步获取到的 skey
    }
}

这里有 2 个地方跟之前不同的,第一是地址后面要跟一个时间戳,而且这个时间戳还要按位取反,第二个是请求参数是放在 BaseRequest 下面,而不是对象的一级属性下面.

返回的数据里面有 2 个数据需要保存起来,一个是 data.SyncKey, 一个是 res.data.User.UserName,后面都会用到

到此才真正完成登陆,下面如果你不需要好友列表的话,可以直接收取消息了

六、检测新消息

接口地址 https://webpush.wx.qq.com/cgi...

请求方法 GET

参数类型(content-type) application/json

参数

let time = new Date().getTime()

let synckey = ''

let sk = data.SyncKey.List || []   // data.SyncKey 就是上一步获取到的那个

for (let i = 0; i < sk.length; i++) {
    synckey += `${sk[i].Key}_${sk[i].Val}`
    if (i !== sk.length - 1) synckey += '|'
}

// 传递的参数
{
    r: time,
    sid: 第四步拿到的 wxsid,
    uin: 第四步拿到的 wxuin,
    skey: 第四步拿到的 skey,
    deviceid: 'e747337466044216', // 同上一步
    synckey: synckey,
    _: time
}

返回内容的 data 里面 包含如下内容

window.synccheck={retcode:"0",selector:"2"}

如果 selector 是 2, 说明有新消息,走下一步,获取消息内容

七、获取消息内容

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 POST

参数类型(content-type) application/json

参数

{
    BaseRequest: {
        Uin: 第四步拿到的 wxuin,
        Sid: 第四步拿到的 wxsid,
        Skey: 第四步拿到的 skey,
        DeviceID: 'e747337466044216', // 同上一步
    },
    SyncKey: data.SyncKey, // 还记得上一步我们费尽千辛万苦转换这个数据吗? 你没看错,这里不需要转换,就是这么神奇
    rr: ~(new Date().valueOf())
}

返回结果里面有个 data.AddMsgList 就是消息列表了,还有个 data.SyncCheckKey 就是下次请求的时候用的 SyncKey, 每次都会变的.

AddMsgList 是一个数组,里面可能包含多条消息,消息的自动比较多,就不一一说明了,这里说说 2 个比较重要的字段,其他的字段有兴趣的可以自己打印出来看一下.

FromUserName 对方的微信名,说是微信名,其实是一个 @ 或 @@ 开头的内部的id, 完全不可读,据我猜测 @ 开头的应该是普通好友, @@ 开头的是群或者公众号之类的

Content 消息内容

有了消息内容,和发消息的人,我们就可以回复对方,不过回复什么? 当然不可能写一大堆 if else 或者 switch case 去适应各种情况,不妨网上搜索一下 价值一个亿的ai代码 哈哈哈

八、获取自动回复内容

这边我用的是图灵机器人的 API 地址,当然你也可以用其他的.

接口地址 http://openapi.tuling123.com/...

请求方法 POST

参数类型(content-type) application/json

参数

{

perception: {
    inputText: {
        text: '待回复的消息'
    }
},
userInfo: {
    apiKey: tulingApiKey,  // 在图灵官网申请
    userId: tulingUserId   // 同上

}

你要是懒得去申请的话,可以在我的项目里面复制, 在 src/global.js 里面,在返回的内容里面 data.results[0].values.text 下面可以看到图灵给你生成的自动回复内容(results是一个数组,支持一次回复多条)

九、回复消息

拿到自动回复以后,我们只需要把它发给你的好友,即完成一次自动对话.

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 POST

参数类型(content-type) application/json

参数

let timeStamp = new Date().getTime() + '' + (9000 * Math.random() + 1000)
{
    BaseRequest: {
      Uin: 同上,
      Sid: 同上,
      Skey: 同上,
      DeviceID: 同上
    },
    Msg: {
      Type: 1,  // 消息类型 1 是文字消息,其他的暂时没用过
      Content: '回复的内容',
      FromUserName: '你的用户名,在第五步有拿到',
      ToUserName: '对方的微信名 第七步的 FromUserName',
      LocalID: timeStamp,
      ClientMsgId: timeStamp
}

发送成功的话,会返回如下内容

{
    BaseResponse: { Ret: 0, ErrMsg: '' },
    MsgID: '2033517278669301361',
    LocalID: ''
}

好了,这样我们的一个自动回复机器人就完成了.完整的代码在这里

广告时间

我们40人的前端团队常年招兵买马中,在厦门的和想来厦门的童鞋们,不要吝惜你的简历,使劲砸过来 邮箱:atob('bnVveWFAZ2FvZGluZy5jb20='), 期待你一起来稿

对本文有意见或者建议,请尽量在 github 上提 issue, 最近比较忙,比较不怎么逛社区

查看原文

认证与成就

  • 获得 17 次点赞
  • 获得 16 枚徽章 获得 1 枚金徽章, 获得 3 枚银徽章, 获得 12 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-09-08
个人主页被 537 人浏览