diff --git a/docs/docs/deploy_prepare_appoint.md b/docs/docs/deploy_prepare_appoint.md
new file mode 100644
index 0000000..26853b5
--- /dev/null
+++ b/docs/docs/deploy_prepare_appoint.md
@@ -0,0 +1,8 @@
+---
+url: deploy_prepare_appoint
+---
+
+# 约定
+
+- 部署文档以源源客官方平台作为例子, 域名为: yuanyuanke.cn
+-
diff --git a/docs/docs/deploy_prepare_domain.md b/docs/docs/deploy_prepare_domain.md
new file mode 100644
index 0000000..099a7dc
--- /dev/null
+++ b/docs/docs/deploy_prepare_domain.md
@@ -0,0 +1,44 @@
+---
+url: deploy_prepare_domain
+---
+
+# 域名
+
+
+## SSL证书
+> ssl证书, 对网站传输的数据可以进行SSL加密,包括用户名,密码等等,防止窃取和篡改。并且网站安装SSL证书后,在浏览器地址栏可以显示一个安全锁,告诉用户你的网站是安全的。SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。
+
+
+
+
+> **ECShopX需要购买通配型ssl证书(泛域名型ssl证书).
+
+**
+
+
+## 域名规划域名规划
+
+为了表述方便, 以域名_b.yuanyuanke.cn_做例子.
+
+- https://b.yuanyuanke.cn api/商家后台域名
+- https://h5.yuanyuanke.cn h5访问域名
+- https://pc.yuanyuanke.cn pc访问域名
+- https://b-import-cdn.yuanyuanke.cn 上传文件cdn域名
+- https://b-cdn.yuanyuanke.cn 后台前端的相关 css js 资源cdn域名
+- https://b-img-cdn.yuanyuanke.cn 图片cdn域名
+
+
+## FAQ
+
+- 为什么必须要使用SSL证书
+
其一SSL证书作为电商领域保证客户信息安全的重要手段. 其二微信小程序 公众号 苹果商店等对于安全性的要求越来越高, 微信小程序是必须SSL才可以, 其它场景也陆续增加限制. 其三, C端用户对于安全的意识也越来越强, 有些客户对于没有小锁头的电商网站有抵触.
+- 是否可以选择免费的SSL?
+
尽量避免使用免费的SSL, 免费的SSL通常不支持**通配符型SSL证书**/**泛域名SSL证书**, 本文档相关部署以支持_通配符型SSL证书_为准.
+- 对于收费的SSL证书应该如何选择?
+- 云盾证书服务
+- SSL去哪里买?
+
主流的云供应商都有, 阿里的云盾
+
+
+##
+
diff --git a/docs/docs/deploy_prepare_domain_record.md b/docs/docs/deploy_prepare_domain_record.md
new file mode 100644
index 0000000..480eecd
--- /dev/null
+++ b/docs/docs/deploy_prepare_domain_record.md
@@ -0,0 +1,35 @@
+---
+url: deploy_prepare_domain_record
+---
+
+# 域名备案
+
+根据 《互联网信息服务管理办法》 以及 《非经营性互联网信息服务备案管理办法》 ,国家对非经营性互联网信息服务实行备案制度,对经营性互联网信息服务实行许可制度。未取得许可或者未履行备案手续的,不得从事互联网信息服务。即所有对中国大陆提供服务的网站都必须先进行 ICP 备案,才可开通服务。阿里云ICP代备案系统为您提供申请备案、修改注销备案信息、认领备案等功能。
+
+> **如果由商派提供采购阿里云服务器, 可以选用我们的备案服务.**
+
+
+
+## 阿里云备案
+
+[阿里云备案](https://beian.aliyun.com)
+
+
+## 腾讯云备案
+
+[腾讯云备案](https://cloud.tencent.com/product/ba)
+
+
+## 微软云(中国)
+
+[微软云备案](https://www.azure.cn/zh-cn/support/icp/icp-new/)
+
+
+## 华为云备案
+
+[华为云备案](https://support.huaweicloud.com/pi-icp/zh-cn_topic_0115820080.html)
+
+
+## 网易云备案
+
+[网易云备案](https://www.163yun.com/help/documents/15588222030344192)
diff --git a/docs/docs/deploy_prepare_implementation.md b/docs/docs/deploy_prepare_implementation.md
new file mode 100644
index 0000000..71a6abe
--- /dev/null
+++ b/docs/docs/deploy_prepare_implementation.md
@@ -0,0 +1,256 @@
+---
+url: deploy_prepare_implementation
+---
+
+# ECShopX初始化
+
+> **本文档引自ECShopX操作手册. 前半部分为数据初始化及上线前准备工作, 因此罗列在此处.**
+>
+
+> **目前本文档仅有Word版, 如需要可向售后人员索要.**
+
+
+### 开通EcshopX
+
+
+
+### 注册开放平台以及创建第三方平台
+
+
+
+### 申请服务号并且认证
+> 不能是订阅号
+
+
+
+
+### 申请小程序并且认证
+> 可以通过服务号快速申请小程序,这样可以避免主体不一致带来的麻烦
+
+
+
+
+### 申请微信支付
+> 小程序支付、JSAPI支付、h5支付
+> 按您的业务需求申请,如果只有小程序则只需要开通小程序支付即可
+
+
+
+> 在接入微信支付过程中,会出现APPID、MCH_ID、公众平台、开放平台、商户平台等概念,下面仅从微信支付的角度来做简单分析:
+>
+
+> 
+
+>
+
+
+> **● 公众平台([mp.weixin.qq.com](https://mp.weixin.qq.com/)):**注册、配置服务号、订阅号、小程序的入口,注册成功后系统就会下发一个与之一一对应的APPID(其中订阅号的APPID不支持申请和使用微信支付)。
+
+>
+
+
+> **● 商户平台([ pay.weixin.qq.com](https://pay.weixin.qq.com/)):**微信支付业务管理中心,商户可以在商户平台进行所有支付业务相关操作,例如退款、下载对账单、查询订单、提现、账号绑定、API证书下载、API密钥设置、查看证书序列号等操作。
+
+>
+
+
+> **● 开放平台([open.weixin.qq.com](https://open.weixin.qq.com/)):**注册、配置APP移动应用、网站应用的入口,注册成功后系统就会下发一个与之一一对应的APPID。
+
+>
+
+
+> **● APPID:**在公众平台或开放平台申请注册之后由平台下发,在支付接口中通常作为配置参数,必须上传。
+
+>
+
+
+> **● MCH_ID:**在公众平台、开放平台申请微信支付成功后由微信支付下发,或者直接在商户平台注册也可获得MCH_ID,在支付接口中通常作为配置参数,必须上传。
+
+>
+
+
+> 注意: 支付接口要求APPID与MCH_ID必须有绑定关系,在商户平台注册获得的MCH_ID需要在【商户平台—>产品中心—>APPID授权管理】菜单下与APPID进行绑定后方可使用。
+
+
+###
+
+### ECShopX授权绑定服务号
+> 管理员才能授权
+
+
+
+
+### ECShopX授权绑定小程序
+> 管理员才能授权
+
+
+
+### 小程序模板开发
+> 与开发普通小程序一致,开发者在开发工具上开发好相关的业务逻辑之后,在项目页卡中提交预览即可以在微信中查看小程序的真实表现。
+
+> 有所不同的是,第三方平台小程序的提交上传是上传至该第三方平台的 open 帐号下的模板草稿箱中,该平台的管理员需要自行对该模板进行相应的设置,更多请参考 [开放平台的文档](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489144594_DhNoV&token=&lang=zh_CN) 。
+
+
+### 上架小程序须知
+> 第三方平台帮助旗下已授权的小程序进行代码管理时,需先开发完成小程序模板,再将小程序模板部署到旗下小程序帐号中,具体流程如下:
+
+> **第一步:绑定开发小程序**
+
+> (1)第三方平台的开发人员需先到微信公众平台(mp.weixin.qq.com)申请一个普通的小程序并完善小程序的头像、昵称、简介、服务类目等信息。
+
+> (2)进入微信开放平台,在第三方平台详情中,将该小程序添加为**开发小程序**。
+
+> **注意:** 绑定为开发小程序后,该小程序的在开发工具中上传,代码会直接上传到开放平台,不会上传到公众平台。
+
+> **第二步:小程序模板的开发和上传**
+
+> 使用开发小程序的开发者微信号登录[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html),开发者工具中按照正常的小程序开发流程进行代码开发和调试。开发完成后,在开发工具中点击上传。使用详见:[**第三方平台代开发小程序**](https://developers.weixin.qq.com/miniprogram/dev/devtools/ext.html)
+
+> **第三步:添加到小程序模板库,获得模板 ID**
+
+> 从开发者工具中上传的代码,会先存在草稿箱中,每个开发小程序只保留最新一份上传记录。开发者可将草稿箱中的代码添加到小程序模板库中,小程序模板库中的模板不会被覆盖。最多可以有200个代码模板,添加后可以获得模板 ID(TemplateID)。
+
+> **第四步:调用接口,为旗下授权的小程序部署代码**
+
+> 具体接口详见“代码管理”文档中的接口。
+
+> **重点提示:**
+
+> 小程序授权托管之后,只能使用第三方平台的在微信开放平台登记的服务器地址。所以第三方平台在帮助旗下公众号发布代码之前,需先把服务器地址设置到小程序的服务器地址中,设置接口详见“修改服务器地址”文档中的接口。
+
+
diff --git a/docs/docs/deploy_prepare_lbs.md b/docs/docs/deploy_prepare_lbs.md
new file mode 100644
index 0000000..cab0db5
--- /dev/null
+++ b/docs/docs/deploy_prepare_lbs.md
@@ -0,0 +1,7 @@
+---
+url: deploy_prepare_lbs
+---
+
+# 腾讯位置服务
+
+[接入步骤](https://lbs.qq.com/guides/startup.html)
diff --git a/docs/docs/deploy_prepare_license.md b/docs/docs/deploy_prepare_license.md
new file mode 100644
index 0000000..0ef0a76
--- /dev/null
+++ b/docs/docs/deploy_prepare_license.md
@@ -0,0 +1,17 @@
+---
+url: deploy_prepare_license
+---
+
+# 域名备案
+
+如果由商派提供采购阿里云服务器, 可以选用我们的备案服务.
+
+
+## 阿里云备案
+
+[阿里云备案](https://beian.aliyun.com)
+
+
+## 腾讯云备案
+
+[腾讯云备案](https://cloud.tencent.com/product/ba)
diff --git a/docs/docs/deploy_prepare_open_weixin.md b/docs/docs/deploy_prepare_open_weixin.md
new file mode 100644
index 0000000..273a53b
--- /dev/null
+++ b/docs/docs/deploy_prepare_open_weixin.md
@@ -0,0 +1,168 @@
+---
+url: deploy_prepare_open_weixin
+---
+
+# 微信开放平台第三方平台申请
+
+
+## 注册微信开放平台账号
+
+
[注册微信平台注册](https://open.weixin.qq.com/cgi-bin/readtemplate?t=regist/regist_tmpl&lang=zh_CN)
+
+
+## 开发者资质认证
+
+
[第三方平台申请流程](https://open.weixin.qq.com/cgi-bin/frame?t=home/wx_plugin_tmpl&lang=zh_CN)
+

+
点击_`开发者资质认证`_, 并进行认证.
+
+> 开发者资质认证介绍
+> 微信开放平台帐号的开发者资质认证提供更安全、更严格的真实性认证、也能够更好的保护企业及用户的合法权益
开发者资质认证通过后,微信开放平台帐号下的应用,将获得微信登录、智能接口、第三方平台开发等高级能力
审核费用:中国大陆地区:300元,非中国大陆地区:99美元
+
+
+
认证时间大概2-3天, 已微信实际认证时间为准
+
+
+## 创建第三方平台
+
+
管理中心->第三方平台
+

+
点击_`创建第三方平台`_
+
+
+## 输入基本信息
+
+
平台类型选择_**`平台型服务商`**_
+

+
+
+## 选择权限
+
+
公众号权限
+


+
小程序权限
+

+
+
+## 填写开发资料
+
+
为了表述方便, 下文将以主域名_yuanyuanke.cn_为例。实际部署时根据您的域名进行修改,并且您的域名是要https的。
+
+
+#### 授权流程相关
+
+
+- 登录授权的发起页域名:_ b.yuanyuanke.cn_
+
+
+
+> 必须从本域名内网页跳转到登录授权页,才可完成登录授权。无需填写`https://等域名协议前缀`。
+
+
+
+- 授权测试公众号列表: gh_************
+
+
+
+> 在全网发布之前,仅该列表内公众号才可进行授权(包含测试小程序),以便测试。请填写公众号的原始ID(可在公众平台网站的公众号设置页找到),最多10个,以英文“;”隔开。
+
+
+
+- 授权事件接收URL: _b.yuanyuanke.cn/wechatAuth/events_
+
+
+
+> 用于接收取消授权通知、授权成功通知、授权更新通知,也用于接收ticket,ticket是验证平台方的重要凭据。
+> 并且选择https协议头。
+
+
+
+
+#### 授权后实现业务
+
+
+- 消息校验Token: qwn2891ktj024
+
+
+
+> 开发者在代替公众号或小程序接收到消息时,用此Token来校验消息。可以自定义。
+> **消息校验Token前后, 绝不能有空格**
+
+
+
+- 消息加解密Key: sklfjkfgeiawwwqvn65997wlj01ndnfoqoe8x2k0nck
+
+
+
+> 在代替公众号或小程序收发消息过程中使用。必须是长度为43位的字符串,只能是字母和数字。可以自定义。
+> **消息加解密Key前后, 绝不能有空格. 长度必须43位
**
+
+
+
+- 消息与事件接收URL: _b.yuanyuanke.cn/wechatAuth/callback/$APPID$_
+
+
+
+> 通过该URL接收公众号或小程序消息和事件推送,该参数按规则填写(需包含/$APPID$,如www.abc.com/$APPID$/callback),实际接收消息时$APPID$将被替换为公众号或小程序AppId。
+
+
+
+- 公众号开发域名: _b.yuanyuanke.cn_
+
+
+
+> 第三方平台在代公众号做网页授权、调用JS SDK等网页开发工作时所用的域名,以;隔开。为了满足开发者管理需要,符合以下要求的下级域名也将生效:$APPID$.wx.abc.com($APPID$为公众号的AppID的替换符)
请**下载校验文件**,并将文件放置在域名根目录下,例如wx.qq.com,并确保可以访问该文件。
每月可提交修改申请3次,本月有3次机会。不需要填写https协议头。
+
+
+
+- 小程序服务器域名: _b.yuanyuanke.cn;b-websocket.yuanyuanke.cn;mmbiz.qpic.cn;wx.qlogo.cn;b-img-cdn.yuanyuanke.cn;up.qiniup.com;up-z1.qiniup.com;up-z2.qiniup.com;up-na0.qiniup.com;up-as0.qiniup.com;thirdwx.qlogo.cn_
+
+
+
+> 第三方平台旗下授权的小程序,只可配置本平台服务器域名列表中的域名,以;隔开。
每月可提交修改申请3次,本月有2次机会。
+
+
+
+> **需要访问的小程序服务器域名, 同时需要后端接口b.yuanyuanke.cn 和 websocket服务: b-websocket.yuanyuanke.cn。这里主要就是您的网站域名,其他还有图片相关域名(七牛,阿里OSS的相关域名,原始域名或者cdn域名),websocket域名(如果用到),微信官方素材域名**
+
+
+
+- 小程序业务域名: **无需填写**
+
+
+
+> 请**下载校验文件**,并将文件放置在域名根目录下,例如wx.qq.com,并确保可以访问该文件。
每月可提交修改申请3次,本月有3次机会
+
+
+
+
+#### 其他
+
+
+- 白名单IP地址列表: 47.115.75.92;
+
+
+
+> 仅当开发者IP地址在该列表中时,才被允许调用相关接口。最多填写100个IP地址,以英文“;”隔开。
+
+
+
+> **服务器出口ip地址, 如果是vpc. 否则访问微信接口会被拒**
+
+**
+
+#### 开发资料综合截图
+
+
+
+## 获取APPSECRET
+
+
获取appsecret(微信开放平台管理中心的第三方平台详情页中的AppID和AppSecret)。
示例:

+
+## 绑定开发者小程序
+
+
微信开放平台管理中心的**第三方平台详情页**的**开发配置**里添加开发小程序。
同时在对应的小程序**添加开发者**。
**建议开发小程序和您的实际授权小程序用同一个**,避免一些异常问题。
示例:

+
+## 开放平台绑定小程序
+
+
微信开放平台管理中心的小程序中去绑定小程序。用于保证unionid一致。

diff --git a/docs/docs/deploy_prepare_qiniu.md b/docs/docs/deploy_prepare_qiniu.md
new file mode 100644
index 0000000..c59f6ac
--- /dev/null
+++ b/docs/docs/deploy_prepare_qiniu.md
@@ -0,0 +1,64 @@
+---
+url: deploy_prepare_qiniu
+---
+
+# 七牛
+
+
+## 概念
+
+
+### cdn
+
+> CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
+
+
+
+### 开放存储服务 OSS
+
+> 开放存储服务(OpenStorageService,简称OSS),是云对外提供的海量,安全,低成本,高可靠的云存储服务。用户可以通过简单的API(REST方式的接口),在任何时间、任何地点、任何互联网设备上进行数据上传和下载 保存js, ccs, 图片等静态资源
+
+
+
+### 七牛云
+
+[七牛云](https://www.qiniu.com)
+
+> 七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化PaaS服务。围绕富媒体场景,七牛先后推出了对象存储,融合CDN加速,数据通用处理,内容反垃圾服务,以及直播云服务等。目前,七牛云已经在为 50多万家企业提供服务, 亲历互联网创新创业发展的同时,也深入理解传统企业转型过程中的云服务需求场景,推出了有针对性的一系列行业解决方案
+
+
+
+## 创建存储空间
+
+
+### espier-vue
+
+用来存储前端的 css js 及静态图片等
+
+- 存储空间(bucket): espier-vue
+- 融合 CDN 加速域名: [https://b-cdn.yuanyuanke.cn](https://b-cdn.yuanyuanke.cn)
+- 访问控制: 公开空间
+
+
+### espier-import-files
+
+用来存储系统导入 导出的相关数据
+
+- 存储空间(bucket): espier-import-files
+- 融合 CDN 加速域名: [https://b-import-cdn.yuanyuanke.cn](https://b-import-cdn.yuanyuanke.cn)
+- 访问控制: 私有空间
+
+
+### espier-images
+
+用来存储商品图片, video等资源
+
+- 存储空间(bucket): espier-images
+- 融合 CDN 加速域名: [https://b-img-cdn.yuanyuanke.cn](https://b-img-cdn.yuanyuanke.cn)
+- 访问控制: 公开空间
+
+
+## FAQ
+
+- 怎么获取或者找到 Access Key 和 Secret Key
+
[怎么获取或者找到 Access Key 和 Secret Key](https://developer.qiniu.com/af/kb/1479/how-to-access-or-locate-the-access-key-and-secret-key)
diff --git a/docs/docs/deploy_prepare_readme.md b/docs/docs/deploy_prepare_readme.md
new file mode 100644
index 0000000..414c4da
--- /dev/null
+++ b/docs/docs/deploy_prepare_readme.md
@@ -0,0 +1,14 @@
+---
+url: deploy_prepare_readme
+---
+
+# README.md
+
+---
+
+
+
+## description: Shortcut keys allows an easy and quick method for navigating or editing con
+
+
+# 准备工作
diff --git a/docs/docs/deploy_prepare_solution.md b/docs/docs/deploy_prepare_solution.md
new file mode 100644
index 0000000..f4a11ed
--- /dev/null
+++ b/docs/docs/deploy_prepare_solution.md
@@ -0,0 +1,120 @@
+---
+url: deploy_prepare_solution
+---
+
+# 服务器方案
+
+
+## 独立部署服务器方案
+
+
+
+- 角色定义
+ - 负载均衡: Load Balance
+ - Web服务:
+API服务
+ - 队列:
+可使用redis/rabbitmq
+ - scheduler:
+定时任务, 例如凌晨1点产生统计任务, 加入队列.
+ - job:
+处理队列中的任务
+ - neo4j:
+图数据库
+ - redis:
+Key-Value数据库
+ - OSS:
+对象存储, 存储文件/图片/视频
+ - CDN:
+CDN的全称是Content Delivery Network,即内容分发网络
+
+
+### 声明
+
+- 本文方案所指皆为以阿里云, 其它云方方案可以此为基准.
+- 数据库建议使用RDS. 如果不使用RDS, 请做好备份方案, 以免误操作造成数据丢失.
+
+
+### 入门级方案
+
+- ECS1台 4核8g 100g高速硬盘
+部署 redis/neo4j/ecshopX(web/Job/scheduler)
+- RDS 2核4g
+- 七牛云 cdn 及 图片
+
+方案简描述:
+
+```
+入门级方案, 不考虑高可用, 仅作为业务刚刚开始, 初始量级不大的情况下.
+```
+
+
+### 标准方案
+
+
+
+- 负载均衡
+- ECS3台 4核8g 100g高速硬盘
+ - Web服务: ecs*2
+ - 定时任务/job/redis/neo4j ecs*1
+- RDS: 2核4g
+
+方案简描述:
+
+```
+优点
+Web端提供两台服务器做负载均衡, 保证高可用. 队列任务分开部署, 将可异步处理的业务从前端业务中剥离, 后端的任务处理不影响API业务正常的相应. 一旦业务发生瓶颈, 可以方便增加Web机的数量, 提高RDS的配置. 以快速相应业务.
+
+缺点
+任务机上部署了过多的服务, 当任务服务器负载过重时, 快速扩展不易.
+```
+
+
+### 进阶方案(根据业务侧重点调整方案配置)
+
+- 负载均衡
+- ecs 4核8g 40g ssd硬盘 * 6
+ - Web: ecs * 3
+ - Job: ecs * 2
+ - Scheduler/redis/neo4j: ecs * 1
+- RDS 2核4g 100g * 1 集群版 便于扩展主从
+- 七牛云 cdn 及 图片
+- 日志服务
+
+
+### Kubernetes方案
+
+
+
+- kubernetes 主节点: ecs 2核4g * 3
+- kubernetes node 工作节点: ecs 4核8g * 3
+- RDS 2核4g 100g * 1 集群版 便于扩展主从
+
+
+## 私有云方案(kubernetes)
+
+服务器托管在商派集群. 使用kubernetes集群方案.
+
+
+### 入门方案(默认)
+
+- 共享负载均衡
+- 5核5g 容器资源
+- RDS 2核4g 100g * 1
+- 七牛云 cdn 及 图片
+
+
+### 标准方案
+
+- 独享负载均衡
+- ECS 4核8g 100g高速硬盘 * 2 (独享)
+- RDS 2核4g
+- 七牛云 cdn 及 图片
+
+
+### 进阶方案(根据业务侧重点调整方案配置)
+
+- 独享负载均衡
+- ECS 4核8g 100g高速硬盘 * 6 (独享)
+- RDS 2核4g 100g * 1 集群版 便于扩展主从
+- 七牛云 cdn 及 图片
diff --git a/docs/docs/deploy_prepare_wxa.md b/docs/docs/deploy_prepare_wxa.md
new file mode 100644
index 0000000..c759a9d
--- /dev/null
+++ b/docs/docs/deploy_prepare_wxa.md
@@ -0,0 +1,77 @@
+---
+url: deploy_prepare_wxa
+---
+
+# 小程序
+
+> **本文档引自ECShopX操作手册. 前半部分为数据初始化及上线前准备工作, 因此罗列在此处.**
+
+
+
+> **需确认好小程序的**_**管理员**_**。****后续很多其它操作员的操作都需要管理员微信扫码。例如添加开发者,小程序授权等**
+
+
+
+
+#### 申请小程序
+
+
+> [https://kf.qq.com/faq/170109iQBJ3Q170109JbQfiu.html](https://kf.qq.com/faq/170109iQBJ3Q170109JbQfiu.html)
+>
+
+> 如果您有服务号,建议直接从服务号后台走快速注册并认证小程序,避免主体搞错的情况发生
+> 
+
+
+####
+
+#### 小程序认证
+
+
+> [https://kf.qq.com/faq/170109F7ZVzq170109MnQRNN.html](https://kf.qq.com/faq/170109F7ZVzq170109MnQRNN.html)
+
+
+####
+
+#### 添加开发者或者体验者
+
+
+> 登录小程序后。开发的时候都是在小程序开发者工具中进行开发,所以必须要开发者权限才能运行。体验成员则可以看小程序体验版。
+> 
+
+
+
+
+#### 获取小程序的APPID(小程序ID),原始ID
+
+
+> - 登录小程序后,点 _设置->基本设置_
+>
+__
+> - 拉到页面底部
+>
+
+
+
+
+
+### 小程序模板开发
+> 与开发普通小程序一致,开发者在开发工具上开发好相关的业务逻辑之后,在项目页卡中提交预览即可以在微信中查看小程序的真实表现。
+> 有所不同的是,第三方平台小程序的提交上传是上传至该第三方平台的 open 帐号下的模板草稿箱中,该平台的管理员需要自行对该模板进行相应的设置,更多请参考 [开放平台的文档](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1489144594_DhNoV&token=&lang=zh_CN) 。
+
+
+### 上架小程序须知
+> 第三方平台帮助旗下已授权的小程序进行代码管理时,需先开发完成小程序模板,再将小程序模板部署到旗下小程序帐号中,具体流程如下:
+> **第一步:绑定开发小程序**
+> (1)第三方平台的开发人员需先到微信公众平台(mp.weixin.qq.com)申请一个普通的小程序并完善小程序的头像、昵称、简介、服务类目等信息。
+> (2)进入微信开放平台,在第三方平台详情中,将该小程序添加为**开发小程序**。
+> **注意:** 绑定为开发小程序后,该小程序的在开发工具中上传,代码会直接上传到开放平台,不会上传到公众平台。
+> **第二步:小程序模板的开发和上传**
+> 使用开发小程序的开发者微信号登录[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html),开发者工具中按照正常的小程序开发流程进行代码开发和调试。开发完成后,在开发工具中点击上传。使用详见:[**第三方平台代开发小程序**](https://developers.weixin.qq.com/miniprogram/dev/devtools/ext.html)
+> **第三步:添加到小程序模板库,获得模板 ID**
+> 从开发者工具中上传的代码,会先存在草稿箱中,每个开发小程序只保留最新一份上传记录。开发者可将草稿箱中的代码添加到小程序模板库中,小程序模板库中的模板不会被覆盖。最多可以有200个代码模板,添加后可以获得模板 ID(TemplateID)。
+> **第四步:调用接口,为旗下授权的小程序部署代码**
+> 具体接口详见“代码管理”文档中的接口。
+> **重点提示:**
+> 小程序授权托管之后,只能使用第三方平台的在微信开放平台登记的服务器地址。所以第三方平台在帮助旗下公众号发布代码之前,需先把服务器地址设置到小程序的服务器地址中,设置接口详见“修改服务器地址”文档中的接口。
+
diff --git a/docs/docs/dicucx.md b/docs/docs/dicucx.md
new file mode 100644
index 0000000..df43383
--- /dev/null
+++ b/docs/docs/dicucx.md
@@ -0,0 +1,6 @@
+---
+url: dicucx
+---
+
+# php的readme
+
diff --git a/docs/docs/el5sfv.md b/docs/docs/el5sfv.md
new file mode 100644
index 0000000..ad15be5
--- /dev/null
+++ b/docs/docs/el5sfv.md
@@ -0,0 +1,1343 @@
+---
+url: el5sfv
+---
+
+# 单机部署方案
+
+
+## 约定
+
+
+- 操作系统:Centos 7.x x64
+- 域名: 文档内域名规划参见 [系统部署/准备/域名](deploy_prepare_domain)
+- 操作权限: root
+
+
+
+
+## 服务清单
+
+
+- supervisorctl > 3.0
+- neo4j 3.5.x
+- mysql 5.7
+- nginx + php-fpm
+- npm > 6.0
+- redis ~ 4.x
+- php 7.2
+
+
+
+
+## 基础服务部署
+
+
+
+### 调整时间
+
+
+```
+timedatectl set-timezone Asia/Shanghai
+```
+
+
+
+### 安装sudo
+
+
+```
+yum install sudo
+```
+
+
+
+### 安装PHP
+
+
+```bash
+yum -y install epel-release
+yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
+yum install yum-utils
+yum-config-manager --enable remi-php72
+
+yum install php72 \
+ php72-php-gd \
+ php72-php-json \
+ php72-php-mbstring \
+ php72-php-mysqlnd \
+ php72-php-xml \
+ php72-php-opcache \
+ php72-php-bcmath \
+ php72-php-pecl-swoole \
+ php72-php-pecl-mongodb \
+ php72-php-pecl-zip \
+ php72-php-pecl-redis4 \
+ php72-php-pcntl \
+ php72-php-pecl-apcu
+
+ln /opt/remi/php72/root/usr/bin/php /usr/bin/php
+```
+
+
验证
+
+```
+php --version
+php --modules
+```
+
+
+
+### 安装composer
+
+
+```
+curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
+/usr/bin/composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
+```
+
+
+
+### 安装supervisor
+
+
版本基于3.0
+
安装supervisor
+
+```
+yum install -y epel-release
+yum install -y supervisor
+```
+
+
开启supervisorctl
+
+```
+systemctl enable supervisord.service
+```
+
+
+
+### 创建用户和组
+
+
+```
+groupadd www
+useradd --shell /sbin/nologin -g www www
+```
+
+
+
+### 安装php-fpm
+
+
安装php-fpm
+
+```
+yum install php72-php-fpm
+```
+
+
开启php-fpm
+
+```
+systemctl enable php72-php-fpm.service
+```
+
+
修改用户权限, 将用户和组从apache 改为www
+
+```
+/etc/opt/remi/php72/php-fpm.d/www.conf
+```
+
+
+```
+user = www
+group = www
+```
+
+
+
+### 安装npm
+
+
+1. 添加**Node.js** **Yum**仓库```
+curl -sL https://rpm.nodesource.com/setup_12.x | bash -
+```
+
+2. 安装**Node.js**```
+yum install -y nodejs
+```
+
+3. 检查**Node.js**和**NPM**版本```
+node -v
+
+v12.6.0
+Also, check the version of npm.
+
+npm -v
+
+6.9.0
+```
+
+
+
+
参考: [How To Install Latest Nodejs on CentOS/RHEL 7/6](https://tecadmin.net/install-latest-nodejs-and-npm-on-centos/)
+
+
+### 安装nginx
+
+
安装nginx
+
+```bash
+yum install nginx
+```
+
+
开启nginx
+
+```bash
+systemctl enable nginx.service
+```
+
+
+
+### 安装crontabs
+> 如果已经安装,请忽略
+
+
+
+```bash
+yum install crontabs
+```
+
+
+```bash
+systemctl enable crond.service
+```
+
+
+```bash
+systemctl start crond.service
+```
+
+
+
+### 安装redis
+> 如果使用阿里云的redis,安装请忽略
+
+安装redis
+
+```bash
+yum install -y redis
+```
+
+
开启redis
+
+```bash
+yum enable redis
+```
+
+
修改配置文件**/etc/redis.conf**
+
+```bash
+# requirepass foobared
+requirepass #指定密码为 redis1234
+```
+
+
启动redis
+
+```bash
+systemctl start redis
+```
+
+
测试
+
+```bash
+redis-cli -h 127.0.0.1 -a redis1234
+keys *
+```
+
+
+
+### 安装neo4j
+
+
+1. 导入签名并且添加neo4j的源到本地centos源中
+```bash
+rpm --import https://debian.neo4j.org/neotechnology.gpg.key
+cat < /etc/yum.repos.d/neo4j.repo
+[neo4j]
+name=Neo4j RPM Repository
+baseurl=https://yum.neo4j.org/stable
+enabled=1
+gpgcheck=1
+EOF
+```
+
+
+2. 安装neo4j
+ - 用**root**权限安装neo4j社区版
+```bash
+yum install neo4j-3.5.7
+```
+
+
+
+3. 运行以下命令会返回已安装的Neo4j的版本:
+
+```bash
+rpm -qa | grep neo4j
+```
+
+
+
+3. 修改默认**密码
**生产环境使用时需要修改初始密码, 否则会安装使用时报错.**
**
+```bash
+# neo4j-admin set-initial-password
+neo4j-admin set-initial-password neo4j1234
+```
+
+
+
+3. 启动neo4j
+```bash
+systemctl start neo4j
+```
+
+### 安装mysql
+
+
+> **如果使用云方提供的RDS, 请忽略安装**
+
+添加mysql7的源到本地centos源中
+
+```
+yum install -y https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
+```
+
+
安装mysql
+
+```
+yum install -y mysql-server
+```
+
+
修改配置文件**/etc/my.conf**(配置位置取决于安装方式)
+
+**
+> **如果使用阿里云的RDS可以忽略此步骤**
+
+
+
+```
+sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
+```
+
+
开启mysql
+
+```
+systemctl enable mysqld
+```
+
+
启动mysql
+
+```
+systemctl start mysqld
+```
+
+
在安装过程中,为MySQL**root**用户生成一个临时密码
+
+```
+grep 'temporary password' /var/log/mysqld.log
+```
+
+
输出:
+
+```
+2016-12-01T00:22:31.416107Z 1 [Note] A temporary password is generated for root@localhost: mqRfBU_3Xk>r
+```
+
+
请记录下密码, 在此例里中为**mqRfBU_3Xk>r**
+
+```
+mysql_secure_installation
+```
+
+
会提示你输入默认的**root**密码, 输入好后, 会被要求改掉密码.
+
输出
+
+```
+The existing password for the user account root has expired. Please set a new password.
+
+New password:
+```
+
+
输入一个新的12个字符的密码,该密码至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符。在提示时重新输入.
+
在此例中设置为, **Wka25ijklmng0ada-x**
+
您将收到关于新密码强度的反馈,然后您将立即被提示再次更改密码.
+
输出
+
+```
+Estimated strength of the password: 100
+Change the password for root ? (Press y|Y for Yes, any other key for No) :
+```
+
+
我们将按下**Y**,然后进入所有后续问题,以便删除匿名用户、禁止远程根登录、删除测试数据库并访问它,并重新加载特权表.
+
命令行连接**mysql**
+
+```
+mysql -uroot -p"Wka25ijklmng0ada-x"
+```
+
+
创建应用数据库
+> 请使用编码 utf8mb4
+
+
+
+```
+CREATE DATABASE espier_bloated CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+```
+
+
参考: [How To Install MySQL on CentOS 7](https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-centos-7)
+
+
+## 系统应用部署
+
+
部署几部分
+
+> 系统是前后端分离的。所以分为商家端(VUE开发,后台管理页面),API端(PHP开发,提供api服务)
+
+
+
+
+### 配置授权
+
+
安装swoole-loader,用于解密。下载地址如果变化,请自行验证一下
+
确认PHP扩展目录
+
+```
+# php -r 'phpinfo();' | grep -i '^extension_dir'
+
+extension_dir => /opt/remi/php72/root/usr/lib64/php/modules => /opt/remi/php72/root/usr/lib64/php/modules
+```
+
+
本例中为**/opt/remi/php72/root/usr/lib64/php/modules**
+
+```bash
+curl https://business.swoole.com/static/loader2.0.0/swoole_loader72.so > /opt/remi/php72/root/usr/lib64/php/modules/swoole_loader72.so
+```
+
+
php扩展配置文件位置
+
+```
+# php -r 'phpinfo();' | grep -i 'Scan this dir for additional'
+
+Scan this dir for additional .ini files => /etc/opt/remi/php72/php.d
+```
+
+
设置授权
+> 注意配置license的正确位置, 默认license.zl在代码包(espier-bloated)根目录下
+
+```
+{ \
+ echo "extension=swoole_loader72.so"; \
+ echo "swoole_license_files=/var/www/html/license.zl"; \
+} > /etc/opt/remi/php72/php.d/60-swoole_loader.ini
+```
+
+
重启fpm
+
+```
+systemctl enable php72-php-fpm.service
+```
+
+
+
+### 部署API服务(php)
+
+
+
+#### 配置
+
+
后端代码
+
+```
+mkdir -p /var/www/espier-bloated
+chown -R www:www /var/www/espier-bloated
+```
+
+
放置代码到**/var/www/espier-bloated**目录中
+
修改配置**.env**, 拷贝**.env.production**文件做为模版.
+
+1. 配置数据库```
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=espier_bloated
+DB_USERNAME=root
+DB_PASSWORD=Wka25ijklmng0ada-x
+```
+
+
+
+1. 配置REDIS```bash
+# REDIS配置
+REDIS_CLIENT=predis
+REDIS_HOST=
+# 必须要设置密码
+REDIS_PASSWORD=redis1234
+REDIS_PORT=6379
+```
+
+1. 配置队列```bash
+QUEUE_DRIVER=redis
+```
+
+1. 配置neo4j```
+NEO4J_DEFAULT_PROTOCOL=bolt
+NEO4J_DEFAULT_HOST=127.0.0.1
+NEO4J_DEFAULT_PORT=7687
+NEO4J_DEFAULT_USERNAME=neo4j
+NEO4J_DEFAULT_PASSWORD=neo4j1234
+```
+
+1. 配置缓存```bash
+CACHE_DRIVER=redis
+```
+
+1. 配置七牛
[如何获取Access Key和Secret Key](https://developer.qiniu.com/af/kb/1479/how-to-access-or-locate-the-access-key-and-secret-key)
```bash
+# 图片CDN域名
+QINIU_IMAGE_DOMAIN=b-img-cdn.yuanyuanke.cn
+# 图片bucket
+QINIU_IMAGE_NAME=espier-images
+# 导入导出文件CDN域名
+QINIU__FILE_DOMAIN=https://b-import-cdn.yuanyuanke.cn
+导入导出bucket
+QINIU_FILE_NAME=espier-import-files
+# 七牛Access Key
+QINIU_ACCESS_KEY=
+# 七牛Secret Key
+QINIU_SECRET_KEY=
+```
+
+1. 配置阿里OSS选七牛就不用配了
+```bash
+# OSS配置
+## OSS密钥配置
+OSS_ACCESS_KEY=
+OSS_SECRET_KEY=
+## OSS文件配置
+### 不通地区域名不一样,文件类的不需要cdn
+OSS_FILE_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_FILE_BUCKET=oss-cdn
+OSS_FILE_IS_CNAME=false
+## OSS图片配置
+OSS_IMAGE_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_IMAGE_BUCKET=oss-cdn
+### 是否开启cdn
+OSS_IMAGE_IS_CNAME=false
+### 图片cdn,开启cdn则该配置必填
+OSS_IMAGE_DOMAIN=
+## OSS视频配置
+OSS_VIDEO_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_VIDEO_BUCKET=oss-cdn
+OSS_VIDEO_IS_CNAME=flase
+### 视频cdn,开启cdn则该配置必填
+OSS_VIDEO_DOMAIN=
+```
+
+
+8. 配置微信开放平台第三方平台相关配置
+```bash
+# 微信开放平台对应第三方平台APPID
+WECHAT_APPID=
+# 微信开放平台对应第三方平台APPSECRET
+WECHAT_SECRET=
+# 微信开放平台对应第三方平台 消息校验Token
+WECHAT_TOKEN=
+# 微信开放平台对应第三方平台 消息加解密Key
+WECHAT_AES_KEY=
+WECHAT_DEBUG=true
+```
+9.配置商城小程序模版
模版ID, 需要添加到小程序模版库,获得模版ID, 参考:[开发者平台小程序模板](https://developers.weixin.qq.com/community/develop/doc/000c6c3524cff06575466ccd35ec00)
+```bash
+# 微商城小程序配置
+## 微信模板id
+YYKWEISHOP_TEMPLATE_ID=1
+## 微信模板id(小程序支持直播,一般可不填)
+YYKWEISHOP_TEMPLATE_ID_2=1
+## 小程序自定义版本
+YYKWEISHOP_VERSION=v1.0.0
+## request合法域名,逗号分割
+YYKWEISHOP_REQUESTDOMAIN=https://b.test.cn
+## socket合法域名,逗号分割
+YYKWEISHOP_WSREQUESTDOMAIN=wss://b-websocket.test.cn
+## uploadFile合法域名,逗号分割,七牛,根据自己实际情况填
+YYKWEISHOP_UPLOADDOMAIN=https://up.qiniup.com,https://up-as0.qiniup.com,https://up-na0.qiniup.com,https://up-z1.qiniup.com,https://up-z2.qiniup.com
+## uploadFile合法域名,逗号分割,阿里OSS,根据自己实际情况填
+#YYKWEISHOP_UPLOADDOMAIN=https://oss-cn-hangzhou.aliyuncs.com
+## downloadFile合法域名,逗号分割,七牛,根据自己实际情况填
+YYKWEISHOP_DOWNLOADDOMAIN=https://mmbiz.qpic.cn,https://wx.qlogo.cn,https://up.qiniup.com,https://up-as0.qiniup.com,https://up-na0.qiniup.com,https://up-z1.qiniup.com,https://up-z2.qiniup.com
+## downloadFile合法域名,逗号分割,阿里OSS,根据自己实际情况填
+#YYKWEISHOP_DOWNLOADDOMAIN=https://mmbiz.qpic.cn,https://wx.qlogo.cn,https://oss-cn-hangzhou.aliyuncs.com
+## 业务域名,逗号分割
+YYKWEISHOP_WEBVIEWDOMAIN=
+```
+10.配置腾讯位置服务
腾讯位置服务需要申请账号配置KEY, KEY对接口的访问是有配额的, 配额内是免费的.
在[腾讯位置服务Key管理](https://lbs.qq.com/console/mykey.html?console=mykey), 可以查询到Key, 并且可以查询到配额.
为了开发环境方便, 提供只为开发环境公用的免费KEY. 因为是公共的, 无法保证一定可用
+```bash
+QQMAP_KEY=PSPBZ-KQ5CW-CSGRF-ON2S4-K2HQJ-XEBQG
+```
+
+11. 配置支付通知接口
+```bash
+WECHAT_PAYMENT_NOTIFY=https://b.yuanyuanke.cn/wechatAuth/wxpay/notify
+```
+
+12. 生成api密钥
+```bash
+php artisan jwt:secret
+```
+
+13. 修改业务版本
+
+standard:标准连锁版,后台界面有“店铺”菜单
platform:平台版,后台界面有“商家”菜单,并且有独立的店铺后台
+```bash
+# 系统版本,standard|platform
+PRODUCT_MODEL=standard
+```
+
+
完整的例子
+
+```bash
+# 标识应用环境, 本地环境设置为local,生产环境为production
+APP_ENV=production
+# 调试模式, 正式环境可以关闭(true,false)
+APP_DEBUG=true
+# 时区不要修改
+APP_TIMEZONE=PRC
+
+# 数据库相关配置
+## DB_CONNECTION默认不需要改
+DB_CONNECTION=default
+DB_HOST=
+DB_PORT=3306
+DB_DATABASE=
+DB_USERNAME=
+DB_PASSWORD=
+
+# REDIS配置
+REDIS_CLIENT=predis
+REDIS_HOST=
+REDIS_PASSWORD=redis1234
+REDIS_PORT=6379
+
+# 数据库主从配置
+#DB_DRIVER=master_slave
+#DB_MASTER={"user":"root","password":"123455","host":"localhost","dbname":"ecx"}
+#DB_SLAVES=[{"user":"root","password":"123455","host":"localhost2","dbname":"ecx"},{"user":"root","password":"123455","host":"localhost3","dbname":"ecx"}]
+
+# 缓存驱动, 默认使用redis
+CACHE_DRIVER=redis
+# 队列驱动, 默认使用redis
+QUEUE_DRIVER=redis
+
+# 文件存储。oss或者qiniu
+DISK_DRIVER=qiniu
+
+# 七牛相关配置
+## 七牛密钥配置
+QINIU_ACCESS_KEY=
+QINIU_SECRET_KEY=
+## 七牛图片配置
+QINIU_IMAGE_DOMAIN=
+QINIU_IMAGE_NAME=espier-image
+QINIU_IMAGE_REGION=z2
+## 七牛视频配置
+QINIU_VIDEO_DOMAIN=
+QINIU_VIDEO_NAME=espier-videos
+QINIU_VIDEO_REGION=z2
+## 七牛文件配置
+QINIU__FILE_DOMAIN=
+QINIU_FILE_NAME=espier-file
+
+# OSS配置
+## OSS密钥配置
+OSS_ACCESS_KEY=
+OSS_SECRET_KEY=
+## OSS文件配置
+### 不通地区域名不一样,文件类的不需要cdn
+OSS_FILE_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_FILE_BUCKET=oss-cdn
+OSS_FILE_IS_CNAME=false
+## OSS图片配置
+OSS_IMAGE_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_IMAGE_BUCKET=oss-cdn
+### 是否开启cdn
+OSS_IMAGE_IS_CNAME=false
+### 图片cdn,开启cdn则该配置必填
+OSS_IMAGE_DOMAIN=
+## OSS视频配置
+OSS_VIDEO_ENDPOINT=https://oss-cn-shanghai.aliyuncs.com
+OSS_VIDEO_BUCKET=oss-cdn
+OSS_VIDEO_IS_CNAME=flase
+### 视频cdn,开启cdn则该配置必填
+OSS_VIDEO_DOMAIN=
+
+# JWT 相关配置, 通过php artisan jwt:secret生成密钥,线上务必修改
+JWT_SECRET=ker4H1Gp4TsddddWJMaB2SMA8Zsh3drv
+JWT_TTL=7200
+JWT_REFRESH_TTL=20160
+
+# 微信第三方平台配置。本地开发环境不配置, 会影响到调用微信的相关页面, 整体不影响后台开发。
+## 第三方平台APPID
+WECHAT_APPID=
+## 第三方平台SECRET
+WECHAT_SECRET=
+## 消息校验Token
+WECHAT_TOKEN=
+## 消息加解密Key
+WECHAT_AES_KEY=
+## 开启微信接口debug模式
+WECHAT_DEBUG=true
+
+# 微信支付通知回调地址
+WECHAT_PAYMENT_NOTIFY=https://域名/wechatAuth/wxpay/notify
+
+# 支付宝配置
+ALIPAY_PAYMENT_NOTIFY=
+ALIPAY_PAYMENT_RETURN=
+ALIPAY_PAYMENT_RETURN_PC=
+ALIPAY_PAYMENT_RETURN_H5=
+ALIPAY_MODE=normal
+
+# SWOOLE 配置
+SERVER_HOST=0.0.0.0
+SERVER_PORT=9058
+
+# 好像没用
+SERVER_OPTIONS_USER=www-data
+SERVER_OPTIONS_GROUP=www-data
+SERVER_OPTIONS_DAEMONIZE=false
+SERVER_OPTIONS_WORKER_NUM=4
+
+# dingo api标准配置, 根据实际场景进行配置,token需要修改
+API_PREFIX=api
+API_NAME="Espier API"
+API_STANDARDS_TREE=vnd
+API_STRICT=false
+API_DEBUG=false
+API_VERSION=v1
+API_SUBTYPE=espier
+API_CONDITIONAL_REQUEST=false
+API_TOKEN=Os6Bass1oT5vig2Yod0yiT8dU0as5cIn
+
+# RABBITMQ配置
+RABBITMQ_HOST=
+RABBITMQ_PORT=5672
+RABBITMQ_VHOST=/
+RABBITMQ_LOGIN=guest
+RABBITMQ_PASSWORD=
+RABBITMQ_QUEUE=default
+RABBITMQ_EXCHANGE_DECLARE=true
+RABBITMQ_QUEUE_DECLARE_BIND=true
+RABBITMQ_QUEUE_PASSIVE=false
+RABBITMQ_QUEUE_DURABLE=true
+RABBITMQ_QUEUE_EXCLUSIVE=false
+RABBITMQ_QUEUE_AUTODELETE=false
+RABBITMQ_EXCHANGE_NAME=sweetheart
+RABBITMQ_EXCHANGE_TYPE=direct
+RABBITMQ_EXCHANGE_PASSIVE=false
+RABBITMQ_EXCHANGE_DURABLE=true
+RABBITMQ_EXCHANGE_AUTODELETE=false
+RABBITMQ_ERROR_SLEEP=false
+
+# NEO4J配置
+NEO4J_DEFAULT_PROTOCOL=http
+NEO4J_DEFAULT_HOST=127.0.0.1
+NEO4J_DEFAULT_PORT=7474
+NEO4J_DEFAULT_USERNAME=neo4j
+NEO4J_DEFAULT_PASSWORD=
+
+#默认小程序模板名称
+DEFAULT_WEISHOP_TEMP=yykweishop
+
+# 微商城小程序配置
+## 微信模板id
+YYKWEISHOP_TEMPLATE_ID=1
+## 微信模板id(小程序支持直播,一般可不填)
+YYKWEISHOP_TEMPLATE_ID_2=1
+## 小程序自定义版本
+YYKWEISHOP_VERSION=v1.0.0
+## request合法域名,逗号分割
+YYKWEISHOP_REQUESTDOMAIN=https://b.test.cn
+## socket合法域名,逗号分割
+YYKWEISHOP_WSREQUESTDOMAIN=wss://b-websocket.test.cn
+## uploadFile合法域名,逗号分割,七牛,根据自己实际情况填
+YYKWEISHOP_UPLOADDOMAIN=https://up.qiniup.com,https://up-as0.qiniup.com,https://up-na0.qiniup.com,https://up-z1.qiniup.com,https://up-z2.qiniup.com
+## uploadFile合法域名,逗号分割,阿里OSS,根据自己实际情况填
+#YYKWEISHOP_UPLOADDOMAIN=https://oss-cn-hangzhou.aliyuncs.com
+## downloadFile合法域名,逗号分割,七牛,根据自己实际情况填
+YYKWEISHOP_DOWNLOADDOMAIN=https://mmbiz.qpic.cn,https://wx.qlogo.cn,https://up.qiniup.com,https://up-as0.qiniup.com,https://up-na0.qiniup.com,https://up-z1.qiniup.com,https://up-z2.qiniup.com
+## downloadFile合法域名,逗号分割,阿里OSS,根据自己实际情况填
+#YYKWEISHOP_DOWNLOADDOMAIN=https://mmbiz.qpic.cn,https://wx.qlogo.cn,https://oss-cn-hangzhou.aliyuncs.com
+## 业务域名,逗号分割
+YYKWEISHOP_WEBVIEWDOMAIN=
+
+# 核销小程序配置,没有这个业务不需要填
+YYKZS_APPID=
+YYKZS_APP_SECRET=
+
+# websocket配置
+WEBSOCKET_SERVER_PORT=9051
+WEBSOCKET_SERVER_HOST=域名
+TIPS_WS_URI=https://域名/ws:9051
+TIPS_WS_KEY=
+
+# sentry配置,报错收集
+SENTRY_LARAVEL_DSN=
+
+# 分销配置
+BROKERAGE_URI=
+BROKERAGE_URI_ITEM=
+
+# OMS配置
+OMS_TOKEN=
+OMS_API_URL=
+ERP_GY_TOKEN=
+
+# 默认地址模板
+ADDRESS_TEMPLATE_ID=
+
+# 日志删除时间
+DEL_OPERATOR_LOGS_DATE=
+# 是否saas
+SYSTEM_IS_SAAS=false
+# 主company_id,单账户,不是saas的配置
+SYSTEM_COMPANYS_ID=1
+# 设置系统主要的企业id,用于pc和h5
+SYSTEM_MAIN_COMPANYS_ID=1
+
+# 是否使用系统菜单,false则是固定菜单,true则更新storage/static/目录下的菜单
+USE_SYSTEM_MENU=true
+# 系统版本,starndard|platform
+PRODUCT_MODEL=standard
+
+# 对接saas ERP的配置信息
+STORE_KEY=59887c5ceec36fa1a9d9a72c6cdf3741
+CERTI_BASE_URL=https://您的域名/
+# 矩阵关系绑定API
+MATRIX_REALTION_URL=https://iframe.shopex.cn/?
+# 矩阵API
+MATRIX_API_URL=http://matrix.ecos.shopex.cn/sync
+VERIFY_APP_ID=ecos.ecshopx
+
+# 腾讯地图接口KEY, 建议根据项目进行申请
+QQMAP_KEY=PSPBZ-KQ5CW-CSGRF-ON2S4-K2HQJ-XEBQG
+# 腾讯地图配置
+TENCENT_LBS_KEY=
+TENCENT_LBS_SECERT_KEY=
+
+# 是否需要服务号,false则需要自己绑定到开放平台
+WX_OPEN_THIRD=true
+# 是否需要第三方平台
+WXA_NEED_OPEN_PLATFORM=true
+
+# 内部rpc,不用管
+RPCCALL_DRIVER=dingo
+
+# prism配置,默认不用动
+PRISM_URL=http://openapi.shopex.cn/api
+PRISM_KEY=a4dyatls
+PRISM_SECRET=xescyjbdmzox75cfybab
+
+# license配置,不用管
+LICENSE_PRODUCTION_URL=http://service.ec-os.net/api/yyk/register
+LICENSE_PRODUCT=yyk
+
+# 文档生成配置
+SWAGGER_STORAGE_DIR=apidocs
+SWAGGER_DOCS_ROUTER=api-doc
+SWAGGER_API_HOST=
+SWAGGER_API_BASE_PATH=/index.php/api
+
+# 发票链接
+FAPIAO_HANGXIN_API_URL=
+
+# pc端扫码登录
+PC_WXCODE_LOGIN=
+
+# H5地址
+H5_BASE_URL=
+
+```
+
+
+
+#### 安装
+
+
安装composer扩展包
+
+```
+cd /var/www/espier-blaoted
+composer install
+```
+
+
数据库迁移
+
+```
+cd /var/www/espier-blaoted
+./artisan doctrine:migrations:migrate
+```
+
+
+
+### 部署商家端(vue)
+
+
商家端代码
+
代码build好后build目录里的文件直接copy至此目录
+
+1. 创建项目目录```
+mkdir -p /var/www/espier-retail-manage
+```
+
+1. 放置代码
通常会通过git的方式进行部署及更新
+
+根据业务选择版本。standard:标准版,有“店铺”菜单。platform:平台版,有“商家”菜单
修改**app/config/test.env.js**```bash
+module.exports = {
+ IS_SAAS: '"true"',
+ PRODUCT_MODEL: '"standard"',// standard:标准版;platform:平台版
+ NODE_ENV: '"testing"',
+ BASE_API: '"https://b.yuanyuanke.cn/api"',// 请求的api基础地质
+ //WXIMG_URL: '"https://b.yuanyuanke.cn/image/"',
+ WXIMG_URL: '""',
+ WXAUTHCALL_Url: '"https://b.yuanyuanke.cn/"' // 微信授权回调域名,最后的斜杠别忘记了
+}
+```
+
+3. 安装npm包
+```bash
+cd /var/www/espier-retail-manage/app
+
+npm install
+```
+
+3. 代码编译目录
**/var/www/espier-retail-manage/app/config/index.js**```
+assetsRoot: path.resolve(__dirname, '../test'),
+```
+
编译后的文件在**/var/www/espier-retail-manage/app/test**下
+3. 代码编译```
+npm run build-test
+```
+
+7. 更改权限```
+chown -R www:www /var/www/espier-retail-manage
+```
+
+
+
+
+
+### 配置nginx
+
+
修改/etc/nginx/nginx.conf, 将权限nginx 改为www
+
+```
+use www;
+```
+
+
创建项目nginx配置
+> 以下是通过反向代理的形式配置的服务,您也可以自己按照自己需要配置,只要vue能访问到php就ok了
+
+```
+vim /etc/nginx/conf.d/espier.conf
+```
+
+
需要配置ssl证书, 在下边配置的所有**配置ssl**处。
+```bash
+server
+{
+ listen 443;
+ # 配置ssl
+
+ server_name b.yuanyuanke.cn;
+
+ location /api/ {
+ access_log /var/log/nginx/espier-bloated.log;
+ proxy_pass http://localhost:8080;
+ }
+
+ location /wechatAuth/ {
+ access_log /var/log/nginx/espier-wechatauth.log;
+ proxy_pass http://localhost:8080;
+ }
+
+ location / {
+ proxy_pass http://localhost:8081;
+ }
+}
+
+# 配置API服务(espier-bloated)
+server {
+
+ listen 8080;
+ listen [::]:8080;
+
+ server_name localhost;
+ root /var/www/espier-bloated/public;
+ index index.php index.html index.htm;
+
+ location / {
+ try_files $uri $uri/ /index.php$is_args$args;
+ }
+
+ location ~ \.php$ {
+ add_header Access-Control-Allow-Origin '*' always;
+ add_header Access-Control-Allow-Headers "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With";
+ add_header Access-Control-Expose-Headers "Authorization";
+ add_header Access-Control-Allow-Methods "DELETE, GET, HEAD, POST, PUT, OPTIONS, TRACE, PATCH";
+
+ if ($request_method = OPTIONS ) {
+ return 200;
+ }
+
+ fastcgi_pass localhost:9000;
+ fastcgi_read_timeout 150;
+ fastcgi_index index.php;
+ fastcgi_buffers 16 16k;
+ fastcgi_buffer_size 32k;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ include fastcgi_params;
+ }
+
+ location ~ /\.ht {
+ deny all;
+ }
+}
+
+# 配置商家端(espier-retail-manage)
+# pc端配置,h5配置可以参考这个进行修改
+server {
+ listen 8081;
+ listen [::]:8081;
+
+ server_name localhost;
+
+ location / {
+ root /var/www/espier-retail-manage/app/test;
+ index index.html index.htm;
+ try_files $uri $uri/ /index.html =404;
+ }
+
+ location /wximage/ {
+ set $hostx "";
+ set $addrs "";
+ if ( $uri ~ "^/wximage/http./+([^/]+)/(.+)$") {
+ set $hostx $1;
+ set $addrs $2;
+ }
+ resolver 8.8.8.8;
+ proxy_pass http://$hostx/$addrs;
+ proxy_set_header referer "http://read.html5.qq.com/image";
+ }
+}
+
+配置websocket服务
+server
+{
+ listen 443;
+
+ # 配置ssl
+
+ server_name b-websocket.yuanyuanke.cn;
+
+ location / {
+ proxy_pass http://localhost:9051/;
+
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ }
+}
+```
+
+
+
+### 配置定时任务
+
+
+```
+crontab -e
+```
+
+
+```json
+* * * * * sudo -E -u www php /var/www/espier-bloated/artisan schedule:run >> /var/log/espier-cront.log 2>&1
+```
+
+
+
+### 配置队列服务
+
+
修改队列配置
+
+```
+vim /etc/supervisord.d/super-queue.ini
+```
+
+
+```bash
+[program:bloated-queue-default]
+command=/var/www/espier-bloated/artisan queue:work --queue=default --delay=3 --memory=128 --timeout=30 --sleep=1 --tries=3
+stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-default.log
+redirect_stderr=true
+process_name=%(program_name)s_%(process_num)02d
+autostart=true
+autorestart=true
+numprocs=1
+user=www
+startsecs=3
+startretries=100000
+
+[program:bloated-queue-slow]
+command=/var/www/espier-bloated/artisan queue:work --queue=slow --delay=3 --memory=128 --timeout=1800 --sleep=1 --tries=3
+stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-slow.log
+redirect_stderr=true
+process_name=%(program_name)s_%(process_num)02d
+redirect_stderr=true
+autostart=true
+autorestart=true
+numprocs=1
+user=www
+startsecs=3
+startretries=100000
+
+[program:bloated-queue-sms]
+command=/var/www/espier-bloated/artisan queue:work --queue=sms --delay=3 --memory=128 --timeout=1800 --sleep=1 --tries=3
+stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-sms.log
+redirect_stderr=true
+process_name=%(program_name)s_%(process_num)02d
+redirect_stderr=true
+autostart=true
+autorestart=true
+numprocs=1
+user=www
+startsecs=3
+startretries=100000
+```
+
+
+
+### 配置websocket服务
+
+
配置websocket
+
+```
+vim /etc/supervisord.d/super-websocket.ini
+```
+
+
+```bash
+[program:websocket]
+command=/var/www/espier-bloated/artisan websocket:start
+stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-websocket.log
+redirect_stderr=true
+autostart=true
+autorestart=true
+numprocs=1
+user=www
+startsecs=3
+startretries=100000
+```
+
+
+
+### 小程序编译打包
+
+- .env文件配置信息
+
+
+
+```json
+ {
+ "APP_BASE_URL": "接口访问地址",
+ "APP_WEBSOCKET": "websocket访问地址",
+ "APP_COMPANY_ID": "企业id",
+ "APP_PLATFORM": "打包平台,standard为标准版, platform为平台版",
+ "APP_CUSTOM_SERVER": "域名地址,H5支付回调使用",
+ "APP_HOME_PAGE": "首页访问路径",
+ "APP_MAP_KEY": "H5 腾讯地图使用key",
+ "APP_MAP_NAME": "H5 使用地图name"
+ }
+```
+
+
+- ext.json文件配置
+
+
+
+```json
+{
+ "extEnable": true,
+ "extAppid": "第三方平台绑定的开发小程序id,一般建议与小程序appid相同",
+ "ext": {
+ "company_id": "企业id",
+ "appid": "小程序id",
+ "wxa_name": "通用小程序"
+ }
+}
+```
+
+
+- npm打包指令
+
+
+
+```bash
+# 如遇初始化下载时间过长或者network timeout,可更换npm镜像源
+# npm更换淘宝镜像,使用此命令后,npm指令关键词改为(cnpm),例如:npm i 改为 cnpm i
+# 更换命令:npm install -g cnpm --registry=https://registry.npm.taobao.org
+
+# npm初始化安装
+npm i
+
+# 小程序本地开发编译
+npm run dev:weapp
+
+# 小程序生产打包
+npm run build:weapp
+
+# ----------目前小程序包与H5分离,小程序包暂不支持打包H5,请注意区分-----------------
+
+# H5本地开发编译
+npm run dev:h5
+
+# H5生产打包
+npm run build:h5
+```
+
+
+- 注意事项
+> - 关于小程序预览,dev:weapp本地开发编译模式下因为主包过大无法上传预览,需要使用build:weapp打包后选择小程序开发工具中的详情->本地设置->上传代码时自动压缩混淆
+> - 如果不需要直播插件请在app.js找到_live-player-plugin代码块将其注释掉_
+> - 目前小程序包与H5分离,小程序包暂不支持打包H5,请注意区分
+
+
+##
+
+### H5编译打包
+> 只支持H5打包
+
+
+
+- .env文件配置
+
+
+
+```javascript
+//小程序id
+APP_ID="小程序id"
+//首页路径
+APP_HOME_PAGE="首页路径"
+//企业ID
+APP_COMPANY_ID="企业ID"
+//api访问地址
+APP_API_BASE_URL="api访问地址"
+//域名地址
+APP_HOME_URL="h5访问域名地址"
+//websocket访问地址
+APP_WEBSOCKET_URL="websocket访问地址"
+//cdn地址
+APP_PUBLIC_PATH="cdn地址"
+//cdn地址
+CDN_QINIU_BUCKET="七牛cdn地址BUCKET"
+CDN_QINIU_PATH=h5/
+// 平台判断(standard 标准版 platform平台版)
+APP_PLATFORM="版本参数"
+//地图key
+APP_MAP_KEY="腾讯地图key"
+//地图name
+APP_MAP_NAME="腾讯地图名称"
+```
+
+
+- cdn配置
+> package.json文件配置
+
+
+
+```javascript
+"cdn": {
+ "publicPath": "*host*",
+ "bucket": "***",
+ "path": "h5/"
+}
+```
+
+
+- 打包发布
+
+
+
+```bash
+# 如遇初始化下载时间过长或者network timeout,可更换npm镜像源
+# npm更换淘宝镜像,使用此命令后,npm指令关键词改为(cnpm),例如:npm i 改为 cnpm i
+# 更换命令:npm install -g cnpm --registry=https://registry.npm.taobao.org
+
+# npm初始化安装
+npm i
+
+# H5本地开发编译
+npm run dev:h5
+
+# H5生产打包
+npm run build:h5
+
+# ----------目前小程序包与H5分离,H5包暂不支持打包小程序包,请注意区分-----------------
+# 小程序本地开发编译
+npm run dev:weapp
+
+# 小程序生产打包
+npm run build:weapp
+```
+
+
+- 美洽客服配置
+
+
+
+> 如果配置了美洽客服将客户的美洽配置文件放置在打包生成的/dist/h5中与index.html同级
+>
+
+> 美洽客服配置文件需要客户登录自己的美洽客服平台访问[https://app.meiqia.com/chatlink](https://app.meiqia.com/chatlink) 生成文件下载下来
+
+
+
+- 关于@shopex/sp-mui-app无法安装处理
+
+
+
+```bash
+# 配置npm镜像源
+npm config set registry http://registry.npm.ishopex.cn
+```
+
+##
+
+## 服务启动
+
+
启动队列任务, websocket服务
+
+```bash
+systemctl start supervisord.service
+```
+
+
启动nginx
+
+```
+systemctl start nginx.service
+```
+
+
启动php-fpm
+
+```
+systemctl start php72-php-fpm.service
+```
+
+
diff --git a/docs/docs/fe4lti.md b/docs/docs/fe4lti.md
new file mode 100644
index 0000000..1bfe6ec
--- /dev/null
+++ b/docs/docs/fe4lti.md
@@ -0,0 +1,21 @@
+---
+url: fe4lti
+---
+
+# 架构说明
+
+
+
+
+## 软件架构
+后端开发语言:PHP 8.2
后端技术框架:采用 Lumen 开源框架开发,引入dingo作为接口管理,采用更符合大型项目的 Doctrine ORM 替换系统自带 ORM
前端开发语言:HTML5/CSS3/ES6/小程序开发框架
前端开发框架:VueJS,Taro
数据库:支持 MySQL/MariaDB/SqlServer等数据库
队列:支持 Redis/RabbitMQ/数据库 等方案,默认采用 Redis
缓存:支持 Redis/filesystem/memcached,默认采用 Redis
CDN/OSS:支持阿里云/七牛云
图形数据库:Neo4j(可选)
日志搜集:ELK/Sentry
+
+## 数据处理能力
+支持 MySQL 读写分离模式,支持阿里云PolarDB。
在 5 机集群下支持 2000 每秒并发,其中订单占比 1%,且根据实际业务需求扩容
采用多级缓存机制,可以有效保证API响应时间在 2S 以内
系统具备按照终端,店铺,门店等权限控制
+
+
+## 稳定性
+系统支持集群模式部署,可按照 web/schedule/worker 等不同角色部署,可有效保证系统高可用
支持阿里云 K8S 部署,可以通过HPA实现 POD 自动扩容,可有效保证在突发流量下,系统的高可用
采用事件机制,可以异步处理耗时业务逻辑,保证实时业务稳定性
采用多级缓存机制,nginx+memcache/php+redis 方式,在redis数据库宕机是,可由 nginx 缓存来替代,保证系统高可用。
+
+## 持续集成
+系统采用 PHP 开发,支持二次开发
具备完善的开发环境(docker-compose)和测试环境构建脚本,可以快速搭建环境
采用基于 GitLab-CI/K8S/Helm/Helmfile 的持续集成方案
diff --git a/docs/docs/fiytfx.md b/docs/docs/fiytfx.md
new file mode 100644
index 0000000..87e6e3b
--- /dev/null
+++ b/docs/docs/fiytfx.md
@@ -0,0 +1,51 @@
+---
+url: fiytfx
+---
+
+# 阿里云
+
+进入 [https://oss.console.aliyun.com/bucket](https://oss.console.aliyun.com/bucket) 创建bucket。
+
+
+## 创建 espier-image 和 espier-vue(公共读)
+
+
+
+### 一、创建 Bucket
+
+
+
+### 二、填写详细信息
+
+

+
+
+### 三、进入详情页面配置
+
+

+
+
+### 四、创建跨域规则
+
+

+
创建完成如下:
+

+
+
+### 五、配置 CDN
+进入 cdn 管理界面 [https://cdn.console.aliyun.com/domain/list](https://cdn.console.aliyun.com/domain/list)
+

+
+### 六、域名解析
+CDN添加完成后,会在域名管理界面生成相应的CNAME,然后在域名解析后台添加相应的解析

+
+
+## 创建 espier-import-files (私有)
+
+### 一、创建
+
+
+> 私有存储不需要配置 cdn 和跨域
+
+
+
diff --git a/docs/docs/framework_architecture-repository.md b/docs/docs/framework_architecture-repository.md
new file mode 100644
index 0000000..8bb4c5c
--- /dev/null
+++ b/docs/docs/framework_architecture-repository.md
@@ -0,0 +1,339 @@
+---
+url: framework_architecture-repository
+---
+
+# Repository
+
+> **使用 Repository 辅助 Model**
+
+
+若将数据库逻辑都写在 model,会造成 model 的肥大而难以维护,基于 SOLID 原则,我们应该使用 Repository 模式辅助 model,将相关的数据库逻辑封装在不同的 repository,方便中大型项目的维护。
+
+
+## 数据库逻辑
+
+在 CRUD 中,CUD 比较稳定,但 R 的部分则千变万化,大部分的数据库逻辑都在描述R 的部分,若将数据库逻辑写在 controller 或 model 都不适当,会造成 controller 与 model 肥大,造成日后难以维护。
+
+
+## Model
+
+如果使用 Eloquent ORM 来实现 Repository 模式,需要修改 model 不要包含数据库逻辑,仅保留以下部分:
+
+- Property : 如$table,$fillable…等。
+- Mutator: 包括 mutator 與 accessor。
+- Method : relation 類的 method,如使用 hasMany() 與 belongsTo()。
+
+简化后的Eloquent 的 model 类我们可以称之为`Eloquent Class`,由于继承了`Illuminate\Database\Eloquent\Model` 类,所以`Eloquent Class`仍然有很多方法可以操作数据库。
+
+Eloquent Class 代码结构如下:
+
+```php
+namespace MyBlog;
+
+use Illuminate\Database\Eloquent\Model;
+/**
+ * MyBlog\User
+ *
+ */
+class User extends Model {
+
+ /**
+ * The database table used by the model.
+ *
+ * @var string
+ */
+ protected $table = 'users';
+
+ /**
+ * The attributes that are mass assignable.
+ *
+ * @var array
+ */
+ protected $fillable = ['name', 'email', 'password'];
+
+ /**
+ * The attributes excluded from the model's JSON form.
+ *
+ * @var array
+ */
+ protected $hidden = ['password', 'remember_token'];
+}
+```
+
+而在 ECShopX 中,由于我们采用了 Doctrine ORM,其自带Repository模式。在 Doctrine ORM 中也有简化的 model 类: `Entity Class`。
+
+相比 `Eloquent Class` `Entity Class` 更简单,其只包含 `protected` 或 `private`的属性和`getter` 和 `setter` 方法(在 JAVA 中,这种对象成为值对象)。
+
+Entity Class 代码结构如下:
+
+```php
+
+## Repository
+
+初学者常会在 controller 直接调用 model 写数据库逻辑:
+
+```php
+public function index()
+{
+ $users = User::where('age', '>', 20)
+ ->orderBy('age')
+ ->get();
+
+ return view('users.index', compact('users'));
+}
+```
+
+数据库逻辑是`获取 20 岁以上的用户`。
+
+在中大型项目中,会有几个问题 :
+
+- 将数据库逻辑写在 controller,造成 controller 的肥大难以维护。
+- 违反 SOLID 的单一职责原则 : 数据库逻辑不应该写在 controller。
+- controller 直接相依于model,使得我们无法对 controller 做单元测试。
+
+比较好的方式是使用 repository :
+
+- 将 model 依赖注入到 repository。
+- 将数据库逻辑写在 repository。
+- 将 repository 依赖注入到 service。
+
+以此原则,我们看下,采用 Eloquent ORM 如何使用 Repository 模式。
+
+UserRepository.php
+
+```php
+namespace MyBlog\Repositories;
+
+use Doctrine\Common\Collections\Collection;
+use MyBlog\User;
+
+class UserRepository
+{
+ /** @var User 注入的User model */
+ protected $user;
+
+ /**
+ * UserRepository constructor.
+ * @param User $user
+ */
+ public function __construct(User $user)
+ {
+ $this->user = $user;
+ }
+
+ /**
+ * 返回年龄大于$age的用户
+ * @param integer $age
+ * @return Collection
+ */
+ public function getAgeLargerThan($age)
+ {
+ return $this->user
+ ->where('age', '>', $age)
+ ->orderBy('age')
+ ->get();
+ }
+}
+```
+
+第 8 行
+
+```php
+/** @var User 注入的User model */
+protected $user;
+
+/**
+ * UserRepository constructor.
+ * @param User $user
+ */
+public function __construct(User $user)
+{
+ $this->user = $user;
+}
+```
+
+将依赖的 User model 依赖注入到 UserRepository。
+
+UserController.php
+
+```php
+userRepository = $userRepository;
+ }
+
+ /**
+ * Display a listing of the resource.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index()
+ {
+ $users = $this->userRepository
+ ->getAgeLargerThan(20);
+
+ return view('users.index', compact('users'));
+ }
+}
+```
+
+将依赖的 UserRepository 依赖注入到 UserController。
+
+26行
+
+```php
+/**
+ * Display a listing of the resource.
+ *
+ * @return \Illuminate\Http\Response
+ */
+public function index()
+{
+ $users = $this->userRepository
+ ->getAgeLargerThan(20);
+
+ return view('users.index', compact('users'));
+}
+```
+
+从原本直接依赖 User model,改成依赖注入的 UserRepository。
+
+改用这种写法,有几个优点:
+
+- 将数据库逻辑写在存储库中,解决控制器肥大问题。
+- 符合SOLID的单一职责原则:数据库逻辑写在repository,没写在controller。
+- 符合SOLID的依赖转换原则:controller 并非直接相依于存储库,而是将存储库依赖注入进controller。
+
+>
+
+**实际上建议repository仅依赖注入于service,而不要直接注入在controller,本范例因为还没介绍到servie模式,以便简化起见,所以直接注入于controller**。
+
+
+>
+
+**是否该建立存储库接口?**
+
+
+理论上使用依赖注入时,应该使用接口,不过接口目的在于通过抽象化,方便在后期更换接口的具体实现,以便让程序达到开放封闭的要求,但是实际上要更换存储库的机会不高,除非你有更换资料库的需求,如从MySQL抽换到MongoDB,此时就该建立存储库接口。
+
+不过由于我们使用了依赖注入,将来要从类改成interface也很方便,只要在构造方法的类型提示改成interface即可,维护成本很低,所以在此大可使用的存储库类,用接口反而会造成设计过度,等真正需求来时再重构成接口即可。
+
+采用 Doctrine ORM 如何使用 Repository 模式。
+
+由于 Doctrine ORM 自带 Repository 模式,所以直接使用即可。
+
+UserRepository.php
+
+```php
+user
+ ->where('age', '>', $age)
+ ->orderBy('age')
+ ->get();
+ }
+}
+```
+
+UserController.php
+
+```php
+namespace App\Http\Controllers;
+
+use App\Http\Requests;
+use MyBlog\Repositories\UserRepository;
+
+class UserController extends Controller
+{
+ /** @var UserRepository 注入的UserRepository */
+ protected $userRepository;
+
+ /**
+ * UserController constructor.
+ *
+ * @param UserRepository $userRepository
+ */
+ public function __construct(UserRepository $userRepository)
+ {
+ $this->userRepository = $userRepository;
+ }
+
+ /**
+ * Display a listing of the resource.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index()
+ {
+ $users = $this->userRepository
+ ->getAgeLargerThan(20);
+
+ return view('users.index', compact('users'));
+ }
+}
+```
diff --git a/docs/docs/framework_architecture-service.md b/docs/docs/framework_architecture-service.md
new file mode 100644
index 0000000..fb89853
--- /dev/null
+++ b/docs/docs/framework_architecture-service.md
@@ -0,0 +1,308 @@
+---
+url: framework_architecture-service
+---
+
+# Service
+
+>
+
+**使用 Service 辅助 Controller**
+
+
+若将商业逻辑都写在 controller,会造成 controller 肥大而难以维护,基于SOLID原则,我们应该使用 Service 模式辅助 controller,将相关的商业逻辑封装在不同的 service,方便中大型项目的维护。
+
+
+## 商业逻辑
+
+商业逻辑中,常见的如 :
+
+- 牵涉到外部行为 : 如发送Email,使用外部API…。
+- 使用PHP写的逻辑 : 如促销规则计算、订单创建等。
+
+若将商业逻辑写在 controller,会造成 controller 肥大,日后难以维护。
+
+
+## Service
+
+牵涉到外部行为
+
+如发`送Email`,初学者常会在 controller 直接调用 `Mail::queue()`:
+
+```php
+public function store(Request $request)
+{
+ Mail::queue('email.index', $request->all(), function (Message $message) {
+ $message->sender(env('MAIL_USERNAME'));
+ $message->subject(env('MAIL_SUBJECT'));
+ $message->to(env('MAIL_TO_ADDR'));
+ });
+}
+```
+
+> Mail::queue()只有一行可能无感,但很多外部服务需要一连串 API,甚至还要有 try/catch 处理。
+
+
+在中大型项目,会有几个问题 :
+
+- 将牵涉到外部行为的商业逻辑写在 controller,造成 controller 的肥大难以维护。
+- 违反 SOLID 的单一职责原则 : 外部行为不应该写在 controller。
+- controller 直接相依于外部行为,使得我们无法对 controller 做单元测试。
+
+比较好的方式是使用 service :
+
+- 将外部行为注入到 service。
+- 在 service 使用外部行为。
+- 将 service 注入到 controller。
+
+EmailService.php
+
+```php
+namespace App\Services;
+
+use Illuminate\Mail\Mailer;
+use Illuminate\Mail\Message;
+
+class EmailService
+{
+ /** @var Mailer */
+ private $mail;
+
+ /**
+ * EmailService constructor.
+ * 将依赖的 Mailer 注入到 EmailService。
+ * @param Mailer $mail
+ */
+ public function __construct(Mailer $mail)
+ {
+ $this->mail = $mail;
+ }
+
+ /**
+ * 发送Email
+ * 将发送 Email 的商业逻辑写在 send()。
+ * 不是使用 Mail facade,而是使用注入的 $this->mail。
+ * @param array $request
+ */
+ public function send(array $request)
+ {
+ $this->mail->queue('email.index', $request, function (Message $message) {
+ $message->sender(env('MAIL_USERNAME'));
+ $message->subject(env('MAIL_SUBJECT'));
+ $message->to(env('MAIL_TO_ADDR'));
+ });
+ }
+}
+```
+
+UserController.php
+
+```php
+namespace App\Http\Controllers;
+
+use App\Http\Requests;
+use Illuminate\Http\Request;
+use MyBlog\Services\EmailService;
+
+class UserController extends Controller
+{
+ /** @var EmailService */
+ protected $emailService;
+
+ /**
+ * UserController constructor.
+ * @param EmailService $emailService
+ */
+ public function __construct(EmailService $emailService)
+ {
+ //将依赖的 EmailService 注入到 UserController。
+ $this->emailService = $emailService;
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(Request $request)
+ {
+ //从原本直接依赖于 Mail facade,改成相依于注入的 EmailService。
+ $this->emailService->send($request->all());
+ }
+}
+```
+
+>
+
+**改用这种写法,有几个优点 :**
+
+
+- 将外部行为写在 service,解决 controller 肥大问题。
+- 符合 SOLID 的单一职责原则 : 外部行为写在 service,没写在 controller。
+- 符合 SOLID 的依赖反转原则 : controller 并非直接相依于 service,而是将 service 依赖注入进 controller。
+
+使用 PHP 写的逻辑:
+
+如根据购买的件数,有不同的折扣,初学者常会在 controller 直接写 if...else 逻辑。
+
+```php
+public function store(Request $request)
+{
+ $qty = $request->input('qty');
+
+ $price = 500;
+
+ if ($qty == 1) {
+ $discount = 1.0;
+ } elseif ($qty == 2) {
+ $discount = 0.9;
+ } elseif ($qty == 3) {
+ $discount = 0.8;
+ } else {
+ $discount = 0.7;
+ }
+
+ $total = $price * $qty * $discount;
+
+ echo($total);
+}
+```
+
+在中大型项目,会有几个问题 :
+
+- 将 PHP 写的商业逻辑直接写在 controller,造成 controller 的肥大难以维护。
+- 违反 SOLID的 单一职责原则 : 商业逻辑不应该写在 controller。
+- 违反SOLID的单一职责原则: 若未来想要改变折扣与加总的算法,都需要改到此method,也就是说,此method 同时包含了计算折扣与计算加总的职责,因此违反SOLID 的单一职责原则。
+- 直接写在 controller 的逻辑无法被其他 controller 使用。
+
+比较好的方式是使用 service。
+
+- 将依赖的类注入到 service。
+- 在 service 写 PHP逻辑使用相依物件。
+- 将 service 注入到 controller。
+
+OrderService.php
+
+```php
+namespace App\Services;
+
+class OrderService
+{
+ /**
+ * 計算折扣
+ * @param int $qty
+ * @return float
+ */
+ //为了符合 SOLID 的单一职责原则,将计算折扣独立成 getDiscount(),将PHP写的判断逻辑写在里面。
+ public function getDiscount($qty)
+ {
+ if ($qty == 1) {
+ return 1.0;
+ } elseif ($qty == 2) {
+ return 0.9;
+ } elseif ($qty == 3) {
+ return 0.8;
+ } else {
+ return 0.7;
+ }
+ }
+
+ /**
+ * 计算最后价格
+ * @param integer $qty
+ * @param float $discount
+ * @return float
+ */
+ //为了符合 SOLID 的单一职责原则,将计算加总独立成 getTotal(),将PHP写的计算逻辑写在里面。
+ public function getTotal($qty, $discount)
+ {
+ return 500 * $qty * $discount;
+ }
+}
+```
+
+OrderController.php
+
+```php
+namespace App\Http\Controllers;
+
+use App\Http\Requests;
+use App\MyBlog\Services\OrderService;
+use Illuminate\Http\Request;
+
+class OrderController extends Controller
+{
+ /** @var OrderService */
+ protected $orderService;
+
+ /**
+ * OrderController constructor.
+ * @param OrderService $orderService
+ */
+ public function __construct(OrderService $orderService)
+ {
+ //将依赖的 OrderService 注入到 UserController。
+ $this->orderService = $orderService;
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(Request $request)
+ {
+ $qty = $request->input('qty');
+ //将原本的 if...else 逻辑改成调用 OrderService,
+ //controller 变得非常干净,也达到了controller 接收 HTTP request,调用其他 class 的责任。
+ $discount = $this->orderService->getDiscount($qty);
+ $total = $this->orderService->getTotal($qty, $discount);
+
+ echo($total);
+ }
+}
+```
+
+::: info
+改用这种写法,有几个优点 :
+:::
+
+- 将PHP写的商业逻辑写在 service,解决 controller 肥大问题。
+- 符合 SOLID 的单一职责原则 : 商业逻辑写在 service,没写在 controller。
+- 符合 SOLID 的单一职责原则 : 计算折扣与计算加总价分开在不同 method,且归属于 OrderService,而非 OrderController。
+- 符合 SOLID 的依赖反转原则 : controller 并非直接相依于 service,而是将 service依赖注入进 controller。
+- 其他 controller 也可以重复使用此段商业逻辑。
+
+
+## Controller
+
+涉及到外部行为
+
+```php
+public function store(Request $request)
+{
+ $this->emailService->send($request->all());
+}
+```
+
+使用 PHP 写的逻辑
+
+```php
+public function store(Request $request)
+{
+ $qty = $request->input('qty');
+
+ $discount = $this->orderService->getDiscount($qty);
+ $total = $this->orderService->getTotal($qty, $discount);
+
+ echo($total);
+}
+```
+
+若使用了 service 辅助 controller,再搭配依赖注入与 service container,则 controller 就非常干净,能专心处理`接收HTTP request,调用其他class`的职责了。
+
+
+## Conclusion
+
+- 实际上会有很多 service,须自行依照 SOLID 原则去判断是否该建立 service。
+- Service 使得商业逻辑从 controller 中解放,不仅更容易维护、更容易扩展、更容易重复使用,且更容易测试。
diff --git a/docs/docs/framework_architecture.md b/docs/docs/framework_architecture.md
new file mode 100644
index 0000000..47f7911
--- /dev/null
+++ b/docs/docs/framework_architecture.md
@@ -0,0 +1,109 @@
+---
+url: framework_architecture
+---
+
+# 中大型项目架构
+
+Laravel 的初学者分为两种:
+
+- 一种是乖乖的将程序在写 MVC 架构内,这将导致 Controller 和 Model 非常臃肿,日后代码很难维护。
+- 一种是不知道将程序写在哪一个Class内而犹豫不决。
+
+本文整理出最适合 Laravel 的中大型项目架构,兼具易维护、易扩展、易复用和易测试的特点。
+
+
+## Controller 过于肥大
+
+受RoR的影响,初学者常认为 MVC 架构就是 Model,View,Controller:
+
+- Model 就是数据库。
+- Controller 负责与 HTTP 通信,调用 Model 与 View。
+- View 就是 HTML。
+
+假如按照此定义,以下需求应该写在哪里呢?
+
+1.发送 Email,使用外部 API。
+
+2.使用 PHP 写的逻辑。
+
+3.依需求将显示格式作转换。
+
+4.依需求是否显示某些资料。
+
+5.依需求显示不同资料。
+
+其中1, 2 属于商业逻辑,而3, 4, 5 属于显示逻辑,若依照一般人对 MVC 的定义,Model 是数据库,而 View 是HTML,以上这些需求都不能写在Model 与View,只能勉强写在Controller。
+
+因此初学者开始将大量程序写在 Controller,造成 Controller 的肥大难以维护。
+
+
+## Model 过于肥大
+
+>
+
+**既然逻辑写在 Controller 不方便维护,那我将逻辑都写在 Model 就好了?**
+
+
+当你将逻辑从 Controller 搬到 Model 后,虽然 Controller 变瘦了,但却肥了 Model,Model 从原本只处理数据库逻辑,现在变成还要负担商业逻辑与显示逻辑,结果更惨。
+
+Model 代表数据库吗?把它想成是 Eloquent class就好,数据库逻辑应该写在 repository 里,这也是为什么 Laravel(Lumen) 已经没有 Models目录,Eloquent class 仅仅是放在 app 根目录下而已。
+
+
+## 中大型项目架构
+
+那我们该怎么写呢?别将我们的思维局限在 MVC 内 :
+
+- Model : 仅当成 Eloquent class。
+- Repository : 辅助 Model,处理数据库逻辑,然后注入到 service。
+- Service : 辅助 Controller,处理商业逻辑,然后注入到 Controller。
+- Controller : 接收 HTTP request,调用其他 service。
+- Presenter : 处理显示逻辑,然后注入到 View。
+- View : 使用 blade 将资料 binding 到 HTML。
+
+其中蓝色为原本的 MVC,而紫色为本文要介绍的的重点 : Repository 模式,Service 模式与 Presenter 模式。
+
+
+
+> 箭头表示物件依赖注入的方向。
+
+
+我们可以发现 MVC 架构还在,由于 SOLID 的单一职责原则与依赖反转原则 :
+
+- 我们将数据库逻辑从 Model 分离出来,由 repository 辅助 Model,将 Model 依赖注入进 repository。
+- 我们将商业逻辑从 Controller 分离出来,由 service 辅助 Controller,将 service 依赖注入进 Controller。
+- 我们将显示逻辑从 View 分离出来,由 presenter 辅助 View,将 presenter 依赖注入进 View。
+
+建立目录在 src 的 Bundle 目录下建立 Repositories,Services 与 Presenters 目录。
+
+别害怕在 Laravel 预设目录以外建立的其他目录,根据 SOLID 的单一职责原则,class 功能越多,责任也越多,因此越违反单一职责原则。
+
+所以你应该将你的程序分割成更小的部分,每个部分都有它专属的功能,而不是一个 class 功能包山包海,也就是所谓的`万能类`。
+
+所以整个项目不应该只有 MVC 三个部分,放手根据你的需求建立适当的目录,并将适当的 class 放到该目录下,只要我们的class 有namespace 帮我们分类即可。
+
+
+## Repository
+
+由于篇幅的关系,将 repository 独立成专文讨论,请参考[如何使用 Repository 模式](framework_architecture-repository) ?
+
+
+## Service
+
+由于篇幅的关系,将 service 独立成专文讨论,请参考如何使用 Service 模式?
+
+
+## 单元测试
+
+由于现在Model、View、Controller 的依赖都已经拆开,也都使用依赖注入,因此每个部分都可以单独的做单元测试,如要测试service,就将repository 加以 mock,也可以将其他 service 加以 mock。
+
+
+## 结论
+
+本文谈到的架构只是开始,你可以依照实际需求增加更多的目录与 class,当你发现你的 MVC 违反 SOLID原则时,就大胆的将 class 从 MVC 拆开重构,然后依照以下手法 :
+
+- 建立新的 class 或 interface。
+- 将依赖类依赖注入到 class。
+- 在 class 内处理他的职责。
+- 将 class 或 interface 注入到 Controller 或 View。
+
+最后搭配单元测试,测试重构后的架构是否与原来的需求结果相同。