0%

递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var data = [
{ id: 1, name: "办公管理", pid: 0 },
{ id: 2, name: "请假申请", pid: 1 },
{ id: 3, name: "出差申请", pid: 1 },
{ id: 4, name: "请假记录", pid: 2 },
{ id: 5, name: "系统设置", pid: 0 },
{ id: 6, name: "权限管理", pid: 5 },
{ id: 7, name: "用户角色", pid: 6 },
{ id: 8, name: "菜单设置", pid: 6 },
];
function toTree(data) {
// 删除 所有 children,以防止多次调用
data.forEach(function (item) {
delete item.children;
});

// 将数据存储为 以 id 为 KEY 的 map 索引数据列
var map = {};
data.forEach(function (item) {
map[item.id] = item;
});
// console.log(map);
var val = [];
data.forEach(function (item) {
// 以当前遍历项,的pid,去map对象中找到索引的id
var parent = map[item.pid];
// 好绕啊,如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中
if (parent) {
(parent.children || (parent.children = [])).push(item);
} else {
//如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中,作为顶级
val.push(item);
}
});
return val;
}
console.time()
console.log(toTree(data))
console.timeEnd();

非递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
console.time()
var nodes = [
{
"id": "12",
"parentId": "0",
"text": "Man",
"level": "1",
},
{
"id": "13",
"parentId": "12",
"text": "Man",
"level": "1",
},
{
"id": "14",
"parentId": "13",
"text": "Man",
"level": "1",
},
{
"id": "15",
"parentId": "15",
"text": "Man",
"level": "1",
},
{
"id": "16",
"parentId": "12",
"text": "Man",
"level": "1",
},];
var map = {}, node, roots = [];
for (var i = 0; i < nodes.length; i += 1) {
node = nodes[i];
node.children = [];
map[node.id] = i; // use map to look-up the parents
if (node.parentId !== "0") {
nodes[map[node.parentId]].children.push(node);
} else {
roots.push(node);
}
}
console.timeEnd();
console.log(roots); // <-- there's your tree

使用 jquery

1
$(window).trigger('resize');

使用 dispatchEvent

1
2
3
4
5
6
7
if (Event.prototype.initEvent) {
const evt = window.document.createEvent('UIEvents');
evt.initUIEvent('resize', true, false, window, 0);
window.dispatchEvent(evt);
else {
window.dispatchEvent(new Event('resize'));
}

说明

由于 window 的 resize 事件属于高频操作,需要进行 debounce 等方式来限制执行频率。

1
2
3
4
import _ from 'lodash';

// Avoid costly calculations while the window size is in flux.
jQuery(window).on('resize', _.debounce(calculateLayout, 150));

另外,还有一个类似 debounce 的函数 throttle,两者的区别可以参考这篇文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
handleSubmit(e) {
e.preventDefault();

const { name, password, department, gender } = this.state;
fetch('http://localhost:8080/api/user', {
mode: "cors",
method: 'POST',
// 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
body: JSON.stringify({
name,
password,
department,
gender
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
}
})
.then((res) => res.json())
.then((res) => {
// 当添加成功时,返回的json对象中应包含一个有效的id字段
// 所以可以使用res.id来判断添加是否成功
if (res.id) {
alert('添加用户成功');
this.setState({
name: '',
password: 0,
gender: ''
});
} else {
alert('添加失败');
}
})
.catch((err) => console.error(err));
}
1
2
3
4
5
6
7
8
9
10
11
12
func userAdd(w http.ResponseWriter, r *http.Request) {
body, readErr := ioutil.ReadAll(r.Body)
if readErr != nil {
log.Fatal(readErr)
}
user := User{}
jsonErr := json.Unmarshal(body, &user)
if jsonErr != nil {
log.Fatal(jsonErr)
}
fmt.Println(string(body), user)
}

参考:https://blog.alexellis.io/golang-json-api-client/

资料来源是这里, 脚本如下:

1
2
3
4
date=$(date +"%Y_%m_%d")
DESCRIPTION="vps_"$date
API_KEY="API_KEY"
curl -X POST --data "SUBID=12345&description=$DESCRIPTION" https://api.vultr.com/v1/snapshot/create?api_key=$API_KEY

其中API_key在设置里可以看到, SUBID是进入主机之后网页后面那一串的主机编号
来自:[https://blog.liuwm.work/2017/10/06/使用vultr的snapshot api实现自动备份VPS/](https://blog.liuwm.work/2017/10/06/使用vultr的snapshot api实现自动备份VPS/)

indows2008根据用户权限显示共享文件夹,叫做“ 基于访问权限的枚举 ”,即Access Based Enumeration。

环境要求:域环境+Windows2008
新建一个文件夹ShareFile,权限就设置为everyone可读取就可以了。

打开##管理工具##中的“共享和存储管理”

右键ShareFile共享文件夹,点击属性

点击高级

勾选“启用基于访问权限的枚举”

在ShareFile中新建test1、test2两个文件夹。

右键文件夹test1,属性,安全

点击高级,编辑,去掉“从父项继承的权限”,点击复制

回到 安全 ,点击编辑,删除everyone,添加用户test1。

不能从资源管理器访问的话,从dos登录。
net use * /del /y
net use \计算机名 /user:用户名 回车提示输入密码

`[运行CMD,在窗口中输入NET USE命令,会列出当前的所有共享连接:
删除远程共享连接,使用如下命令:
net use \10.10.2.122\ipc$ /delete
其中”\10.10.2.122\ipc$”是你需要删除的

Windows共享文件夹设置了局域网文件夹共享,我设置了2个用户专门用来共享访问,一个用户只拥有对文件夹的只读访问权限,另外一个用户则对文件夹拥有完全权限。
但是用其中一个用户登陆之后,要用另外一个用户名来进行登陆更换不了。
对于文件更换用户名进行登陆必须先切断默认用户名的登陆,命令就是
net use \计算机名 /delete
选定某个用户名登陆的命令是
net use \计算机名 /user:用户名

net use \ip\ipc$ “ “ /user:” “ 建立IPC空链接
net use \ip\ipc$ “密码” /user:”用户名” 建立IPC非空链接
net use h: \ip\c$ “密码” /user:”用户名” 直接登陆后映射对方C:到本地为H:
net use h: \ip\c$ 登陆后映射对方C:到本地为H:
net use \ip\ipc$ /del 删除IPC链接
net use h: /del 删除映射对方到本地的为H:的映射
net user 用户名 密码 /add 建立用户
net user guest /active:yes 激活guest用户
net user 查看有哪些用户
net user 帐户名 查看帐户的属性

然后再输入密码就可以实现用户名的更换登陆了。
在删除了后再重新连接还有可能会出现一些其他问题,例如不能多用户连接的问题。这时用以后命令来一次清空就可以了!
net use * /del /y
net use \计算机名 /user:用户名

此SVN部署主要是在家和单位都会做一些活儿!所以这儿做个笔记,可能你在部署的时候未必会和我的一样,但思路差不多!
服务器配置:
centos 6.x
lnmp,openresty,
web目录:/home/wwwroot/你的项目名

1
2
3
4
# 安装
yum install -y subversion
# 测试是否安装成功 如果显示了版本信息则表示安装成功
svnserve --version;

我习惯使用home目录,你可以根据自己的情况做以下调整。

新建一个版本库目录

1
2
mkdir -p /home/wwwroot/svn/repos
cd /home/wwwroot/svn/repos

建立svn版本库:

1
svnadmin create /home/wwwroot/svn/repos/版本库名称(www.xxx.com)

进入创建的这个版本库,里面有个conf的目录,目录下的几个文件不多介绍,挨个儿来。先设置账号和密码

1
2
3
vim passwd
[users]
root = lvtao

接着配置权限

1
2
3
4
5
vim authz
[groups] #用户组
admin = root
[/] #/仓库权限
@admin = rw

再配置svnserve.conf

1
2
3
4
5
6
7
8
9
10
11
12
vim svnserve.conf
[general]
# 使非授权用户无法访问
anon-access = none
# 使授权用户有写权限
auth-access = write
# 用户密码文件
password-db = /home/wwwroot/svn/repos/你的项目/conf/passwd
# 访问控制文件
# authz-db = /home/svn/web/conf/authz //这个开启会遇到认证失败,所以继续注释吧。
# 认证命名空间,subversion会在认证提示里显示,并且作为凭证缓存的关键字。
realm = my frist project.

如果有防火墙,请检查相关端口,并设置启动

启动 默认端口 3690

1
2
killall svnserve
svnserve -d -r /home/wwwroot/svn/repos

加入开机启动

1
echo svnserve -d -r /home/wwwroot/svn/repos >> /etc/rc.local

到这儿安装就结束了!客户端的使用不讲!我们来继续下面的,提交应用后自动更新到WEB站点的目录
第一步进入目录

1
cd /home/wwwroot/svn/repos/你的项目/hooks

#创建文件 post-commit

1
2
3
4
5
6
7
8
vi post-commit
如下内容,相关参数自己修改
#!/bin/sh
export LANG=zh_CN.UTF-8 #文件的编码,自己看着办啦
SVN_PATH=/usr/bin/svn #svn的执行文件目录,默认滴
WEB_PATH=/home/wwwroot/你的项目 #网站的根目录

$SVN_PATH export --username 用户名 --password 密码 svn://127.0.0.1/你的项目名 $WEB_PATH --no-auth-cache --non-interactive --force

那有时候我们开发中,会有数据库的修改操作,肿么办!我在刚才的post-commit下加了一个小判断,如果有数据更新,我就将数据库导出一个db.sql并更新到服务器上,然后提交后如果有这个文件,就执行一次数据库导入!O了!!

1
2
3
4
5
if [ -f "$WEB_PATH/db.sql" ]; then 
#mysql还原数据库的操作!希望你懂的
mysql -hlocalhost -uroot -plvtao demo > $WEB_PATH/db.sql
rm -r $WEB_PATH/db.sql #删掉WEB目录下的那个.SQL文件!
fi

最后,给这个post-commit执行权限

1
chmod 777 ./post-commit

好了,至此就结束了!

转自:https://www.lvtao.net/config/svn-web-mysql.html

1
2
3
4
wget https://nchc.dl.sourceforge.net/project/p7zip/p7zip/16.02/p7zip_16.02_src_all.tar.bz2
tar -xjvf p7zip_16.02_src_all.tar.bz2
cd p7zip_16.02
make && make install

用法:

1
2
7za x xxx.7z
7za a xxx.7z /home/wwwroot/www.xxx.com

apache php 开发微信公众号, curl 下载语音,图片,视频 是https 开头的。遇到curl_init() 返回 bool(false)。就是这个问题。
PHP通过cURL访问https时出现SSL certificate problem: unable to get local issuer certificate的解决方法:只要设置以下两个属性就可以解决。
将 CURLOPT_SSL_VERIFYPEER 设置为 false,
将 CURLOPT_SSL_VERIFYHOST 设置为 false.
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function saveImg($url)
{
$ch = curl_init($url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0); //对body进行输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$package = curl_exec($ch);
$httpinfo = curl_getinfo($ch);

curl_close($ch);
$media = array_merge(array('mediaBody' => $package), $httpinfo);

//文件格式
preg_match('/\w\/(\w+)/i', $media["content_type"], $extmatches);
$fileExt = $extmatches[1];
$filename = $this->com_create_guid() . $this->get_total_millisecond() . ".{$fileExt}";
$dirname = public_path() .DIRECTORY_SEPARATOR. "uploads".DIRECTORY_SEPARATOR."img".DIRECTORY_SEPARATOR;
if (!file_exists($dirname)) {
mkdir($dirname, 0777, true);
}
file_put_contents($dirname . $filename, $media['mediaBody']);
return $filename;
}