1.1.4 校验码
码距
两个合法编码对应位之间比较,有多少位编码不同,又称为海明距离。比如 10101 和 00110 就是(从高到低 1,4,5 位不同,码距为 3)
计算海明距离的一种方法,就是对两个位串进行异或(xor)运算,并计算出异或运算结果中 1 的个数。例如 110 和 011 这两个位串,对它们进行异或运算,其结果是:
两个合法编码对应位之间比较,有多少位编码不同,又称为海明距离。比如 10101 和 00110 就是(从高到低 1,4,5 位不同,码距为 3)
计算海明距离的一种方法,就是对两个位串进行异或(xor)运算,并计算出异或运算结果中 1 的个数。例如 110 和 011 这两个位串,对它们进行异或运算,其结果是:
之前入手了一台miniPC安装好了Ubuntu,并通过frp内网穿透部署好了gitlab。现在决定重拾荒废的Blog,并做成自动部署。
本文想达到的目的是在任意一台主机编写Blog,并能够做到提交后自动部署。
当前hexo版本5.0以上(安装主题的方式有所不同)
npm install -g hexo-cli
hexo init myblog
cd myblog
npm install
一般我们需要专门为服务创建不同用户及用户组,以便做好权限管理。 当前是以root用户登录服务器的
useradd blog
passwd blog #设置用户密码
usermod -a -G root blog #设置组
为了方便,直接将blog用户加到了root组里面
届时会通过git的钩子方法自动将文件复制到静态文件夹
mkdir /home/blog/repo/
chown -R blog:root /home/blog/repo/
chmod -R 755 /home/blog/repo/
cd /home/blog/repo/
git init --bare hexo_static.git
既然创建了专用的用户账号,就把相应的资源放在用户目录下/home/blog/就是用户home目录,我们将文件都放到home目录的repo目录中
柯里化(Currying)是函数式编程里最常被提起、也最常被误解的概念之一。面试喜欢问,但很多人只背得住一句「把多参函数变成单参函数的链式调用」,说不清它从哪来、为什么存在、以及它到底划算不划算。
这篇文章把三件事讲透:它是谁发明的、它解决什么问题、它的代价是什么。
手写系列的意义不是「记住答案」,而是把 API 背后那句被藏起来的话重新说出来:「改变 this」本质是什么?「异步」到底是怎么串起来的? 顺着 apply → call → bind → Promise 这条线写下来,你会发现它们是一脉相承的——前面三个解决的是一件事(函数调用时的 this 和参数),最后一个把「回调」正式升级成了「一等公民」。
如果想要实现input输入Number类型,又不想用难看的type='number'怎么处理
<el-input style="width:200px" :maxlength="4" @keyup.native="isNumber(form,'recruitsCount')" v-model.number="form.recruitsCount" placeholder="请输入数字,不能为空"></el-input>
isNumber(obj,key) {
let isnumber = new RegExp('^[0-9]\\d*$')
if (!isnumber.test(obj[key])) {
obj[key] = null
} else {
return true
}
},
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
<input style="width:200px" :maxlength="4" @keyup="isNumber(form,'count')" v-model.number="form.count" placeholder="请输入数字,不能为空"></input>
</div>
</body>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
form: {
count: null
}
},
methods: {
isNumber(obj, key) {
let isnumber = new RegExp('^[0-9]\\d*$')
if (!isnumber.test(obj[key])) {
obj[key] = null
} else {
return true
}
}
}
})
</script>
</html>
<!-- plupload封装 -->
<template>
<div class="supload">
<div class="clearfix list-picture" v-if="fileList.length>0&&listType=='picture'">
<div v-for="ff,index in fileList" class="pic-bx small">
<img :src="ff.showUrl">
<div class="cl-bx">
<i class="el-icon-close" @click="deleteFile(ff,index)"></i>
</div>
</div>
</div>
<div class="plupload clearfix" v-show="fileList.length<maxFile">
<template v-if="listType=='text'">
<div class="text_trigger">
<div :id="trigger_id" >
<i class="el-icon-document" ></i>
<span>{{triggerText}}(小于{{maxSize}}Mb)</span>
</div>
</div>
</template>
<template v-if="listType=='picture'">
<div class="fm-up" :id="trigger_id">
<div class="cc">
<i class="el-icon-circle-plus-outline"></i>
<p>点击选择</p>
<span>支持jpg/png格式</span>
<span>560px×400px</span>
</div>
</div>
</template>
</div>
<div class="pgs" v-if="progress>0&&listType=='text'">
<el-progress :text-inside="true" :stroke-width="20" :percentage="progress" status="success"></el-progress>
</div>
<div class="list-text" v-if="listType=='text'">
<template v-for="ff,index in fileList">
<div class="clearfix item-text">
<!-- <div class="progress" :style="{'width':ff.progress+'%'}"></div> -->
<div class="title">{{ff.name}}</div>
<div class="close" @click="deleteFile(ff,index)">删除</div>
</div>
</template>
</div>
</div>
</template>
<script>
/**
* 强制multi_selection为false使其只能逐个上传
*
*/
/**
* tip:
* 为了操作方便fileList以数组形式传入props,直接操作fileList可以实现数据双向绑定
* 并不建议这样去做,父子组件之间尽量保持单向数据流
* 因此可以暂不向外提供文件删除上传的回调入口
*/
/*
xlsx等文档可以在拓展过滤为zip的情况下可选的bug是因为xlsx本质是个压缩包,将xlsx拓展名改成zip再看看
*/
import plupload from 'plupload'
import {guid,getExtName} from '../../lib/util.js'
import config from '../../config/config.js'
export default {
data() {
return {
trigger_id:null, //触发按钮的ID属性
plup:null, // plupload实例对象
progress: 0, // 单文件上传进度
option: null
};
},
props: {
accept: {
type: String,
default: 'image/png,image/jpeg,audio/mp3'
},
// 支持的拓展名以逗号隔开jpg,gif,png,bmp,mp4
extensions:{
type: String,
default: 'mp4'
},
maxFile: {
type: Number,
default: 1
},
maxSize: {
type: Number,
default: 512 //mb
},
// 文件列表
fileList: {
default(){
return []
}
},
// text,picture 以picture形式呈现时,如果超过可上传数量,上传界面将消失
listType:{
default: 'text'
},
params:{
type:Object,
required:true
},
triggerText:{
default:'选择文件'
}
},
computed:{
},
components: {
},
methods: {
transGetUrl(url) {
return config.imgHost + url
},
deleteFile(ff,index){
this.fileList.splice(index,1)
},
},
watch:{
extensions(ne,olg){
this.option.filters.mime_types=[{
title: 'files', extensions: ne
}]
this.plup.destroy()
this.plup = new plupload.Uploader(this.option);
this.plup.init()
}
},
mounted(){
const $this = this;
this.option = {
runtimes: 'html5,flash,silverlight,html4',
url: config.downloadHost+'upload/pluploadUpload',
//url: '/preschool/upload/pluploadUpload',
browse_button: this.trigger_id,
chunk_size: '2048kb',
multi_selection:false,
filters: {
mime_types: [{ title: 'files', extensions: this.extensions }],
max_file_size: this.maxSize+'mb',
prevent_duplicates: true
},
multipart:true,
multipart_params:this.params,
init: {
FilesAdded: function(up, files) {
up.start();
},
UploadProgress: function(up, file) {
$this.progress = file.percent;
},
BeforeUpload: function(up,file) {},
FileUploaded: function(uploader,file,res){
// response,responseHeaders,status
if (res.status==200){
let result = JSON.parse(res.response);
if (result.code==0){
setTimeout(function(){
$this.progress = 0;
$this.fileList.push({
name:file.name,
// url: result.data.replace(/(.*)(pluploadDir)/g,config.imgHost),
url: result.data,
showUrl: $this.transGetUrl(result.data),
type: getExtName(result.data)
});
},500);
}
} else {
}
},
Error:function(up,err){},
Refresh: function(up){},
Destroy(up){},
OptionChanged:function(up,option_name,new_value,old_value){}
// Error: this.error
}
}
this.plup = new plupload.Uploader(this.option);
this.plup.init();
},
beforeMount(){
this.trigger_id = guid();
}
};
/**
* 额外参数传递:
* 1.设置multipart为true
* 为true时将以multipart/form-data的形式来上传文件,为false时则以二进制的格式来上传文件。
* 2. 设置multipart_params:{userId:1024}
* 方式二
* 设置init的BeforeUpload(up,file){up.setOption("multipart_params",{userId:1024})}
* 也可以up.setOption({'multipart_params':{userId:1030}});这样可以方便设置多个参数
* 像 up.setOption({'multipart':true,'multipart_params':{userId:1032}})
* 在某些情况下可能更方便
*/
</script>
<plup-vue :file-list="fileListForAttach" list-type="text" :params="extendParamsForUploadComponent" :extensions="format" :maxSize="1024">
</plup-vue>
/*上传组件*/
.supload{
line-height: 30px;
.pgs{
line-height:20px;width:600px;
}
.list-text{
line-height:20px;width:600px;
.item-text{
line-height: 30px;
height: 30px;
background: #ededed;
position: relative;
margin: 5px auto;
.progress{
position: absolute;
height: 100%;
width: 1%;
background: green;
top: 0;left: 0;
opacity: 0.2;
transition: width 0.5s;
-moz-transition: width 0.5s;
-webkit-transition: width 0.5s;
-o-transition: width 0.5s;
}
.title{
float: left;height: inherit;line-height: inherit;padding: 0 10px;
width: 500px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.close{
float: right;height: inherit;
line-height: inherit;padding: 0 10px;
cursor: pointer;
color:$colorRed
}
}
}
.list-picture {
.pic-bx{
float: left;
margin: 10px 10px 10px 0;
border:1px dashed #ededed;
img{width: 100%; }
position: relative;
}
.cl-bx{
width: 100%;height: 25px;background: rgba(1,1,1,0.5);
position: absolute;right: 0;top: 0;
text-align: right;
line-height: 25px;
i{
font-size: 15px;
color:#fff;
margin-right: 3px;
cursor: pointer;
}
}
.small{
width: 240px;height: 180px;overflow: hidden;
border-radius: 4px
}
}
.plupload{
.text_trigger{
display: inline-block;
position: relative;
color:$colorBlue;
cursor: pointer;
}
}
}
.fm-up{
width: 240px;height: 180px;
text-align: center;
cursor: pointer;
// border: 1px solid #03A9F4;
.cc{
height: 100px;width: 200px;
line-height: 20px;
margin: auto;
margin-top: 40px;
}
color:#dcdcdc;
border: 1px solid #dcdcdc;
i{font-size: 25px;}
border-radius: 4px;
p{line-height: 20px;}
span{font-size: 12px;line-height: 20px;}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<style>
* {
margin: 0;
padding: 0
}
body {
min-width: 550px;
font-weight: bold;
font-size: 20px;
}
#header,
#footer {
background: rgba(29, 27, 27, 0.726);
text-align: center;
height: 60px;
line-height: 60px;
}
#container {
overflow: hidden;
}
.column {
text-align: center;
}
#left,
#right,
#center {
float: left;
/*三列高度撑开对齐,关键步*/
padding-bottom: 10000px;
margin-bottom: -10000px;
}
#center {
width: 100%;
background: rgb(206, 201, 201);
}
#left {
width: 200px;
margin-left: -100%;
background: rgba(95, 179, 235, 0.972);
}
#right {
width: 150px;
margin-left: -150px;
background: rgb(231, 105, 2);
}
.content {
margin: 0 150px 0 200px;
height: 400px;
}
</style>
<body>
<div id="header">#header</div>
<div id="container">
<div id="center" class="column">
<div class="content">
#center
</div>
</div>
<div id="left" class="column">#left</div>
<div id="right" class="column">#right</div>
</div>
<div id="footer">#footer</div>
</body>
</html>

最近在研发基于electron的桌面应用,其中涉及到外设交互部分需要使用dll实现,在经历了艰难的环境配置之后,最后由于electron内存管理问题导致应用崩溃使得electron+ffi实现动态链接库调用这条路无法走通。当时还剩下两种方案可以尝试:
为什么坚持了两个星期还不放弃是因为node+ffi这条路已经走通了,证明第三方的dll是没有问题的。所以试着能不能解决electron中出现的问题。
当electron不能实现的事实逐渐明朗,我开始转移方向。首先想到的是nwjs+ffi的方案,随后迅速想到为什么不使用node自己实现呢?将此部分功能单独分割成为第三方应用,通过某种通信方式实现(写缓存、数据库、http等)。最不济的情况是我为每台终端部署node服务(此应用是B2B,需要实施,不需要自己安装,这一点帮了大忙)
最好的方式是不需要安装node等一堆东西,直接是可执行文件。因此我开始寻找node打包成可执行文件的方法。
在后端程序中,往往将session和成功登录的用户id进行绑定来保持登录状态,这样前后端交互时就不用显示传递用户ID来判断是哪个用户,并通过设置session过期时间来保障账户的安全。
session的值会被后端设置在cookie,前端无需做什么特别操作,正常请求接口即可。由于session就相当于用户id,当同一个浏览器存在多个标签页,A页是A用户,B页是B用户,那么session绑定的其实是后登陆的那一个用户的id,因为这种绑定是在登陆接口处理的。这样的话假如请求的数据(比如查看个人信息)是基于session拿用户id的,就会导致A用户拿到B用户的数据。
cocosCreator版本:2.0.7
在游戏场景中少不了要使用网络交互,在以往的编程中,用jQuery实现或者axios实现并不是很难,从论坛的反馈来看,cocos对ES6的支持尤其是promise,经过长时间的更新似乎依然没有很好地完善,由于开发时间限制,这里就没有去体验这些说法直接使用回调函数避免兼容性问题原始实现ajax请求。