白板博客

https://oblank.com


  • 首页

  • 归档

  • 标签

前公司两份PPT分享

发表于 2018-12-10 | 分类于 开发 |

整理电脑时看到之前在公司分享用的两分份PPT,做的挺好看的,记录下来。一份是给市场人员介绍基本IT知识用的,一个是给小组成员总结经验用的。

如下:

图片
图片
图片

PDF版:

《后台开发组会议要点2017.06.13》PDF版
《互联网安全初探_邓羽浩_2017.02.17》PDF版

KeyNote版:

《后台开发组会议要点2017.06.13》KeyNote版
《互联网安全初探_邓羽浩_2017.02.17》KeyNote版

Hypleder Fabric 体验

发表于 2018-06-14 | 分类于 开发 |

推荐选用云服务器,按流量付费,使用后及时销毁

注意选择香港区域的服务器,保证网络的联通,避免额外工作,这算是小小的经验吧,我这里选择的是腾讯云香港服务器(4核8G)。

国内服务器可以使用ProxyChain4配合代理来无障碍安装软件

注意服务器版本选择,因为要用到Docker,而根据经验CentOS最好使用7+的版本,我们这里选择的是7.4

根据文档来看,在Windows、Mac环境下都会多做一些额外工作,建议使用CentOS或Ubuntu这样的系统。

我所用系统内核:

1
Linux VM_***_centos 3.10.0-693.el7.x86_64

按官方文档安装系统环境

http://hyperledger-fabric.readthedocs.io/en/latest/prereqs.html

具体要求如下:

  • Docker version 17.06.2-ce or greater.
  • Docker Compose version 1.14.0 or greater.
  • Go version 1.10.x is required.
  • Node.js - version 8.9.x or greater,9.x is not supported at this time.

安装DockerCE社区版

参考官方文档 https://docs.docker.com/install/linux/docker-ce/centos/

确认Docker正常:

1
2
docker --version
Docker version 18.05.0-ce, build f150324

安装Docker-compose

参考官方文档:https://docs.docker.com/compose/install/#install-compose

确认Docker-compose正常:

1
2
docker-compose --version
docker-compose version 1.21.2, build a133471

安装 Go

Fabric是由Go开发的,智能合约Chaincode也是Go实现的

参考文档:https://golang.org/doc/install?download=go1.10.2.linux-amd64.tar.gz

确定Go正常:

1
2
3
4
5
6
go version
go version go1.10.2 linux/amd64

# test code
go run hello.go
hello, world

Node.js 安装

这里使用NVM进行多版本管理

参考:https://github.com/creationix/nvm/blob/master/README.md

确认安装正常:

1
2
3
4
5
nvm install 8.9.4
nvm use v8.9.4

npm -v
5.6.0

按文档安装Fabric

http://hyperledger-fabric.readthedocs.io/en/latest/install.html

执行:

1
2
3
4
5
# 如果系统没有GIT则先安装GIT
sudo yum install git -y

# 安装 Fabric
curl -sSL https://goo.gl/6wtTN5 | bash -s 1.1.0

没问题的话用docker images命令会看下列结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest e38bc07ac18e 6 weeks ago 1.85kB
hyperledger/fabric-ca latest 72617b4fa9b4 2 months ago 299MB
hyperledger/fabric-ca x86_64-1.1.0 72617b4fa9b4 2 months ago 299MB
hyperledger/fabric-tools latest b7bfddf508bc 2 months ago 1.46GB
hyperledger/fabric-tools x86_64-1.1.0 b7bfddf508bc 2 months ago 1.46GB
hyperledger/fabric-orderer latest ce0c810df36a 2 months ago 180MB
hyperledger/fabric-orderer x86_64-1.1.0 ce0c810df36a 2 months ago 180MB
hyperledger/fabric-peer latest b023f9be0771 2 months ago 187MB
hyperledger/fabric-peer x86_64-1.1.0 b023f9be0771 2 months ago 187MB
hyperledger/fabric-javaenv latest 82098abb1a17 2 months ago 1.52GB
hyperledger/fabric-javaenv x86_64-1.1.0 82098abb1a17 2 months ago 1.52GB
hyperledger/fabric-ccenv latest c8b4909d8d46 2 months ago 1.39GB
hyperledger/fabric-ccenv x86_64-1.1.0 c8b4909d8d46 2 months ago 1.39GB
hyperledger/fabric-zookeeper latest 92cbb952b6f8 3 months ago 1.39GB
hyperledger/fabric-zookeeper x86_64-0.4.6 92cbb952b6f8 3 months ago 1.39GB
hyperledger/fabric-kafka latest 554c591b86a8 3 months ago 1.4GB
hyperledger/fabric-kafka x86_64-0.4.6 554c591b86a8 3 months ago 1.4GB
hyperledger/fabric-couchdb latest 7e73c828fc5b 3 months ago 1.56GB
hyperledger/fabric-couchdb x86_64-0.4.6 7e73c828fc5b 3 months ago 1.56GB

添加PATH环境变理:

1
2
# 具体路径以你实际情况为准
export PATH=$PATH:/root/go/src/fabric-samples/bin

运行第一个测试网络

参考:http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html

在fabric-samples/first-network目录下执行:

1
2
3
4
5
6
7
8
9
10
11
12
./byfn.sh generate
./byfn.sh up

# 直到出现下面的提示
========= All GOOD, BYFN execution completed ===========


_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/

这个时候再使用使用docker ps,会出现如下结果:

1
2
3
4
5
6
7
8
9
10
11
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61be9101c099 dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab "chaincode -peer.add…" 3 minutes ago Up 3 minutes dev-peer1.org2.example.com-mycc-1.0
eda8b0fd85ff dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 3 minutes ago Up 3 minutes dev-peer0.org1.example.com-mycc-1.0
6107fb4406fc dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 4 minutes ago Up 4 minutes dev-peer0.org2.example.com-mycc-1.0
b8204bfc0734 hyperledger/fabric-tools:latest "/bin/bash" 4 minutes ago Up 4 minutes cli
83ff712ca3bd hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
677a3fc1c6c7 hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
193de4b51d5a hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
ebafff254a5b hyperledger/fabric-orderer:latest "orderer" 4 minutes ago Up 4 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
ebe3b1c8f9e8 hyperledger/fabric-peer:latest "peer node start" 4 minutes ago Up 4 minutes 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com

简洁模式

1
2
3
4
5
6
7
8
9
10
11
# docker ps --format "{{.ID}}\t{{.Names}}"

61be9101c099 dev-peer1.org2.example.com-mycc-1.0
eda8b0fd85ff dev-peer0.org1.example.com-mycc-1.0
6107fb4406fc dev-peer0.org2.example.com-mycc-1.0
b8204bfc0734 cli
83ff712ca3bd peer1.org1.example.com
677a3fc1c6c7 peer0.org1.example.com
193de4b51d5a peer0.org2.example.com
ebafff254a5b orderer.example.com
ebe3b1c8f9e8 peer1.org2.example.com

这样就模拟了一个简单的区块链网络,它有1个排序机构(order org),2个节点组织(peer org)每个组织有2个节点(peer)。

上面的组织机构定义在configtx.yaml文件中,而各个容器的拓扑关系定义在crypto-config.yaml文件中,使用 ./byfn.sh down 可以关闭这个网络。

用Nginx代理解决一些问题总结

发表于 2018-04-09 | 分类于 开发 |

总结一下用Nginx代理解决的一些问题的思路。

小程序校验domain

docker暴露端口不够

WFG墙翻(反),外网不可以

websockt:ws变wss

IPV6不支持的情况

阿里云、腾讯云都不支持IPV6,如果代理时返回的IPV6将会报错:

1
Address family not supported by protocol

解决办法是在DNS后指定不返回IPV6地址

1
resolver 8.8.8.8 ipv6=off;

React Native 入门问题集

发表于 2018-04-09 | 分类于 开发 |

记录一些自己入门遇到的问题与解决方法

怎么将navigation传递到子级组件?

当需要在子组件中使用navigation导航时,一种方法是直接在引入组件时将 navigation 作为props传递,另一种是使用 withNavigation,后者更优雅。

方法一:引用时传递

1
<Component navigation={this.props.navigation} ...otherProps />

方法二:使用 withNavigation, 参见官方文档

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';  
import { Button } from 'react-native';
import { withNavigation } from 'react-navigation';

class Component extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}

// 用withNavigation包一下
export default withNavigation(Component);

然后在引入时更直接:

1
<Component ...otherProps />

RN在iOS真机、模拟器调试时网络兼容问题

在RN生成的XCode项目里,默认是通过远程方式调试,只要手机、模拟器处于同一网络即可,但我们的手机极有可能会切换网络(譬如上下班、吃饭、上厕所…等等),而这会导到远程调试的应用无法打开,可以兼容处理。

打开XCode项目,修改 AppDelegate.m,将原有的

1
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

修改成

1
2
3
4
5
6
7
#if TARGET_IPHONE_SIMULATOR
// remote debug
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
// release
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif

这会将真机像发布时一样把文件打包进APP,不受网络切换影响

获取组件的屏幕位置

当使用react-native-modal-popover组件时,有一个参数fromRect用来指明组件的位置,这时候我们取要获取组件的位置,使用NativeModules.UIManager.measure

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
import React, { Component } from 'react'; 
import {
StyleSheet,
Text,
View,
TouchableOpacity,
findNodeHandle,
NativeModules
} from 'react-native';
import Popover, { PopoverTouchable } from 'react-native-modal-popover';

....

const handle = findNodeHandle(this.refs[ 'popoverAnchor' ]);
if (handle) {
NativeModules.UIManager.measure(handle, (x0, y0, width, height, x, y) => {
this.setState({
popoverAnchor: { x, y, width, height },
});
});
}

....

<SimpleLineIcons
name="options"
ref="popoverAnchor"
...otherProps
/>
<Popover
visible={this.state.showPopover}
fromRect={this.state.popoverAnchor}
...otherProps
>
{children}
</Popover>

基于webview实现简易浏览器

在APP内经常需要打开一些URL链接,如果通过外部浏览器打开、返回体验不好,一般会做一个内部的导航,用RN的WebView组件很容易实现,主要是利用onNavigationStateChange获得各种状态并处理各导航菜单的表现,同时利用navigation.setParams动态设置浏览器的标题栏。

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...
goBack() {
this.refs[ WEB_VIEW_REF ].goBack(); }

goForward() {
this.refs[ WEB_VIEW_REF ].goForward(); }

reload() {
self.refs[ WEB_VIEW_REF ].reload(); }

openShare() {
Share.share({ message: 'content', title: 'testshare' })
.catch((error) => console.error(error)); }

openWithSafari() {
Linking.openURL(this.state.currentUrl)
.catch(err => console.error('An error occurred', err)); }

onNavigationStateChange(navState) {
this.setState({
backButtonEnabled : navState.canGoBack,
forwardButtonEnabled: navState.canGoForward,
currentUrl : navState.url,
status : navState.title,
loading : navState.loading,
scalesPageToFit : true
});

// 动态更新 headerTitle
if (navState.title) {
this.props.navigation.setParams({ title: navState.title })
}
}

...

<WebView
ref={WEB_VIEW_REF}
source={{ uri: url }}
style={styles.webView}
scalesPageToFit={true}
startInLoadingState={true}
onNavigationStateChange={(e) => this.onNavigationStateChange(e)}
/>
<View style={styles.toolbar}>
{/*退回*/}
{
!this.state.backButtonEnabled && (
<View style={[ styles.toolBtn ]}>
<SimpleLineIcons name='arrow-left' size={18} style={[ styles.headerIcon, styles.headerIconDisable ]}/>
</View> )
}
{
this.state.backButtonEnabled && (
<TouchableOpacity style={styles.toolBtn} onPress={() => this.goBack()}>
<SimpleLineIcons name='arrow-left' size={18} style={[ styles.headerIcon ]}/>
</TouchableOpacity> )
}
...other buttons
</View>

使用react-navigation的TabNavigator时Tab之间跳转不能正常返回的情况

如果TabA、TabB同时是StackNavigator,当从一个TabA跳到另一个TabB里的某个路由时,返回时常常会处于TabB中而无法正常返回到TabA,一种方法是修改顶部左侧菜单自定义实现返回逻辑,但这种情况下右滑返回手势仍然不能正常返回到TabA。

换种思维,直接将TabA要跳转的页面引入到相应的Tab路由中,代码仍然是一套,只是配了两个路由,路由名字略微不同即可:

1
2
3
4
5
6
7
8
9
10
11
export const RouteHome = StackNavigator({
Home : { screen: Views.Home },
HBrowser: { screen: Views.Browser },
Scanner : { screen: Views.Scanner },
})

export const RouteSetting = StackNavigator({
Setting : { screen: Views.Home },
Browser: { screen: Views.Browser },
ScannerB : { screen: Views.Scanner },
})

上面的 HBrowser、Browser用了相同的组件,但路由名不同,在Home路由中按需跳转HBrowser,在Setting中就按需跳转Browser,这样兼顾了代码复用与交互的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
......
<Hyperlink
onPress={ (url, text) => {
if (navigation.state && navigation.state.routeName === 'Home') {
this.props.navigation.navigate('HBrowser', {url: url, text: text})
} else {
this.props.navigation.navigate('Browser', {url: url, text: text})
}
}}
linkStyle={styles.url}
>
<Text style={styles.content} selectable={true} selectable={true}>
{item.content}
</Text>
</Hyperlink>
......

UPDATE: 经测试,不同StackNavigator里可以包含同名路由,导航时会优先从该Stack里寻找路由,所以上面的路由在取名时不需要刻意规避,简化如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const BaseRoutes = {
Browser: { screen: Views.Browser },
Scanner : { screen: Views.Scanner },
};

export const RouteHome = StackNavigator({
Home : { screen: Views.Home },
...BaseRoutes,
})

export const RouteSetting = StackNavigator({
Setting : { screen: Views.Home },
...BaseRoutes,
})

导航时不再区分路由名:

1
2
3
4
5
6
7
8
9
10
11
12
......
<Hyperlink
onPress={ (url, text) => {
this.props.navigation.navigate('Browser', {url: url, text: text})
}}
linkStyle={styles.url}
>
<Text style={styles.content} selectable={true} selectable={true}>
{item.content}
</Text>
</Hyperlink>
......

StackNavigator里嵌套了TabNavigator

如果TabNavigator里的Views是根据程序动态生成的,那边多半面临导航找不到路由的问题

同时如果组件既在TabNavigator里使用,也有可能直接在StackNavigator里使用,这个时候 navigation指向不同,需要特殊处理才能兼容

具体方法,参考:https://github.com/react-navigation/react-navigation/issues/335

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Community   : CommunityTabs, // 这个方法不能让子级最高层级的 TabBar的情况,譬如按需隐藏 
Community : { screen: ({ navigation }) => <TabsNavigator screenProps={{ navigation }}/> },

...

// 调用时做一些处理
navigate = (route, payload) => {
if (this.props.screenProps) {
this.props.screenProps.navigation.navigate(route, payload)
} else {
this.props.navigation.navigate(route, payload)
}
}
...

读书笔记一:增长黑客

发表于 2016-04-11 | 分类于 运营 |

最近读了几本运营营销相关的书籍,国内国外的作者都有,书里提到了不少案例,十分精彩,学习了不少新的观点理论,虽然还没读完但总觉得有必要记录一下。

一些新概念

MVP:最小化可行产品(Minimum Viable Product)

Idea is cheap,show me the product。

MVP要求的是在一个点子变成完整的产品之前,应该借助于现有一些平台或工具做出最基本的产品,然后投放给市场进行检验,经过市场反馈有效后再投入更多资源进行开发。MVP并不意味着主体功能的缺失或是体验上的粗糙。

书中提到就算是Goole大约也只有30%的想法经市场检验后确认是比较靠谱的,大多数人自认为有用的需求不过是一厢情愿。

可以实践的方式:微信公众号,微信企业号;WrodPress博客系统;原型基础上做的模拟体验;做出效果视频看用户是否喜欢。

PMF:产品市场适配度(Product Market Fit)

产品是否有用,有多大用,市场说了算。有些产品有用,但可能是很小的一个受众,能找到那个小众群体才算达到PMF,没找到或是找了一群不相干的用户,基本上也是没用,严重甚至的会对产品的运营策略带来误判。

Growth Hacker:增长黑客

增长黑客指的是那些既有技术,又有产品、营销视觉的跨界人才,他们依靠分析产品的各种数据得出增长或是降低的原因,并提出优化方案,使产品、收入进行可持续的增长。

增长团队一般是工程师、数据科学家、产品、营销组成,是一个综合性团队,有些公司在此之上设立增长官Growth Officer,赋予更大的职责和权限。他们所采用的方法也称之为 Growth Hacking。

基本上这类人才很少,相关岗位的设置也多是大公司才有专门设置。据称 Facebook 的增长团队由CEO直接领导,作出了卓越贡献。

可用的一些工具:Mixpanel,growingio.com,Google Analytics等类似平台

附一段百科的介绍:

增长黑客是介于技术和市场之间的新型团队角色,主要『依靠技术和数据』的力量来达成各种营销目标,而非传统意义上靠砸钱来获取用户的市场推广角色。他们能从单线思维者时常忽略的角度和难以企及的高度通盘考虑影响产品发展的因素,提出基于产品本身的改造和开发策略,以切实的依据、低廉的成本、可控的风险来达成用户增长、活跃度上升、收入额增加等商业目的。简单来说,就是『低成本』甚至零成本地用“技术”来让产品获得有效增长。

噪声用户 / 蝗虫用户

并不是所有用户是有意义的,比如女性社区里的大量爷们,企业应用里的个人用户,他们不是产品的服务对象,但却大量消耗相关的资源,对初创公司是非常不利的,社区类产品尤其不利。

有二次元网站为了过滤掉这些用户需要注册用户回答60多道题目,有的需要邀请,有的需要付费才能注册。

可用的手段包括:邀请注册、付费注册、过滤非目标用户、权限控制等。

关于增长

所谓增长就是在曝光量与转化率两件事上下功夫:SEO、反链、ASO、AD、内容营销、病毒、事件营销等是为了提高曝光量。交互方式、设计美丑、速度、文案等深刻地影响着注册到付费的转化率,不可小视,提高到理论上就是growth hack,细操起来是苦力活,过程与结果往往很有意思。

一般的产品体验的提升是靠观察与琢磨,growth hack更多靠数据+A/B test说话,比起单个营销事件的而言,GH有可持续操作的特点。当然最基本的还是要讲产品的价值。现在流行的社群概念对冷启动、增长、营销、售后关怀…整个流程都有可能全面的介入。

为什么要重建博客?

发表于 2016-02-24 | 分类于 思考 |

缘由

没什么具体的原因,一是想深入学习MarkDown写作,二是想分享一些学习内容,三是GitHub可以免费搭建博客,不再为服务器与长城防火墙发愁。

历史

说起来之前的博客大约存在了6年(2008-2014),好的时候每天都出一篇甚至好几篇,后来微博兴起,博客再也没有以前那么热闹了。再后来服务器过期,数据东挪西腾的,搞乱的有,搞掉的有,也就没什么兴趣再把博客维持下去,索性关掉。

将来

现在有了兴趣,不会写的太频繁,会是真正的想写一点东西的时候更新。

hello world

发表于 2016-02-24 | 分类于 学习 , 思考 , 设计 , 运营 |

tags:

1, ProductHunt
2, HuntNew

categories:

1, 学习
2, 思考
3, 设计
4, 运营

oBlank

oBlank

7 日志
7 分类
19 标签
RSS
© 2018 oBlank
由 Hexo 强力驱动
主题 - NexT.Muse