docs: change and add docs

This commit is contained in:
zchengo
2023-01-15 18:29:31 +08:00
parent 84a105a3d8
commit 74fcfedaec
41 changed files with 1706 additions and 316 deletions
-41
View File
@@ -1,41 +0,0 @@
// node_modules/vitepress/dist/client/theme-default/index.js
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/base.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
import "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
import VPBadge from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
import Layout from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/Layout.vue";
import NotFound from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/NotFound.vue";
import { default as default2 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
import { default as default3 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
import { default as default4 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
import { default as default5 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
import { default as default6 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
import { default as default7 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
import { default as default8 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
import { default as default9 } from "/Users/xuzc/crm/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
var theme = {
Layout,
NotFound,
enhanceApp: ({ app }) => {
app.component("Badge", VPBadge);
}
};
var theme_default_default = theme;
export {
default5 as VPDocAsideSponsors,
default3 as VPHomeFeatures,
default2 as VPHomeHero,
default4 as VPHomeSponsors,
default9 as VPTeamMembers,
default6 as VPTeamPage,
default8 as VPTeamPageSection,
default7 as VPTeamPageTitle,
theme_default_default as default
};
//# sourceMappingURL=@theme_index.js.map
-7
View File
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/vitepress/dist/client/theme-default/index.js"],
"sourcesContent": ["import './styles/fonts.css';\r\nimport './styles/vars.css';\r\nimport './styles/base.css';\r\nimport './styles/utils.css';\r\nimport './styles/components/custom-block.css';\r\nimport './styles/components/vp-code.css';\r\nimport './styles/components/vp-code-group.css';\r\nimport './styles/components/vp-doc.css';\r\nimport './styles/components/vp-sponsor.css';\r\nimport VPBadge from './components/VPBadge.vue';\r\nimport Layout from './Layout.vue';\r\nimport NotFound from './NotFound.vue';\r\nexport { default as VPHomeHero } from './components/VPHomeHero.vue';\r\nexport { default as VPHomeFeatures } from './components/VPHomeFeatures.vue';\r\nexport { default as VPHomeSponsors } from './components/VPHomeSponsors.vue';\r\nexport { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue';\r\nexport { default as VPTeamPage } from './components/VPTeamPage.vue';\r\nexport { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';\r\nexport { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';\r\nexport { default as VPTeamMembers } from './components/VPTeamMembers.vue';\r\nconst theme = {\r\n Layout,\r\n NotFound,\r\n enhanceApp: ({ app }) => {\r\n app.component('Badge', VPBadge);\r\n }\r\n};\r\nexport default theme;\r\n"],
"mappings": ";AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,cAAc;AACrB,SAAoB,WAAXA,gBAA6B;AACtC,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAqC;AAC9C,SAAoB,WAAXA,gBAA6B;AACtC,SAAoB,WAAXA,gBAAkC;AAC3C,SAAoB,WAAXA,gBAAoC;AAC7C,SAAoB,WAAXA,gBAAgC;AACzC,IAAM,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,EACA,YAAY,CAAC,EAAE,IAAI,MAAM;AACrB,QAAI,UAAU,SAAS,OAAO;AAAA,EAClC;AACJ;AACA,IAAO,wBAAQ;",
"names": ["default"]
}
+3 -9
View File
@@ -1,17 +1,11 @@
{
"hash": "769566c1",
"browserHash": "06c6ce40",
"hash": "3520588e",
"browserHash": "76e04641",
"optimized": {
"vue": {
"src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "8ba1b9d6",
"needsInterop": false
},
"@theme/index": {
"src": "../../../../node_modules/vitepress/dist/client/theme-default/index.js",
"file": "@theme_index.js",
"fileHash": "5e9b16a0",
"fileHash": "bef91d7b",
"needsInterop": false
}
},
+40 -11
View File
@@ -1,11 +1,15 @@
export default {
title: 'CRM DOCS',
description: 'CRM Docs',
title: 'CrmDocs',
description: 'CrmDocs',
themeConfig: {
siteTitle: 'CRM DOCS',
logo: '/logo.svg',
siteTitle: 'CrmDocs',
algolia: {
apiKey: 'your_api_key',
indexName: 'index_name'
},
nav: [
{ text: '文档', link: '/project/introduction' },
{ text: '更新日志', link: '/logs/update-log' },
{ text: '文档', link: '/project/docs/introduction' },
{ text: '关于', link: '/about/about' },
{ text: '赞赏', link: '/sponsor/sponsor' }
],
@@ -18,12 +22,37 @@ export default {
text: '文档',
collapsible: true,
items: [
{ text: '简介', link: '/project/introduction' },
{ text: '技术栈', link: '/project/technology-stack' },
{ text: '快速运行', link: '/project/getting-started' },
{ text: '部署指南', link: '/project/deploy-guide' },
{ text: '许可证', link: '/project/open-license' }
],
{ text: '简介', link: '/project/docs/introduction' },
{ text: '快速开始', link: '/project/docs/getting-started' },
{ text: '部署指南', link: '/project/docs/deploy-guide' },
{ text: '详细设计', link: '/project/docs/detailed-design' },
{ text: '问题反馈', link: '/project/docs/problem-feedback' },
{ text: '更新日志', link: '/project/docs/update-log' },
]
},
{
text: '前端',
collapsible: true,
items: [
{ text: '封装 axios 请求库', link: '/project/frontend/axios-package' },
{ text: '页面中的加载进度条', link: '/project/frontend/nprogress' },
]
},
{
text: '后端',
collapsible: true,
items: [
{ text: '跨域请求处理', link: '/project/backend/cors-handle' },
{ text: '用户授权与认证', link: '/project/backend/jwt-handle' },
]
},
{
text: '运维',
collapsible: true,
items: [
{ text: '部署到云服务器', link: '/project/devops/deploy-cloudserver' },
{ text: '持续集成与交付 (CI/CD)', link: '/project/devops/ci-cd' },
]
},
]
},
+26
View File
@@ -0,0 +1,26 @@
:root {
/* 标题 */
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: linear-gradient( 135deg, #93a9fa 5%, #476FFF 100%);
/* 图标背景 */
--vp-home-hero-image-background-image: linear-gradient( 135deg, #97abf5 10%, #476FFF 100%);
--vp-home-hero-image-filter: blur(150px);
/* brand按钮 */
--vp-button-brand-border: #476FFF;
--vp-button-brand-text: #FFFFFF;
--vp-button-brand-bg: #476FFF;
--vp-button-brand-border-radius: 10px;
--vp-button-brand-hover-border: #476FFF;
--vp-button-brand-hover-text: #FFFFFF;
--vp-button-brand-hover-bg: #476FFF;
--vp-button-brand-active-border: #476FFF;
/* 主题基色 */
--vp-c-brand: #476FFF;
--vp-c-brand-light: #476FFF;
--vp-c-brand-dark: #476FFF;
}
+6
View File
@@ -0,0 +1,6 @@
import Theme from 'vitepress/theme'
import './index.css'
export default {
...Theme
}
+17 -3
View File
@@ -1,5 +1,19 @@
# 公众号
# 关于
关注公众号「**GoCode**」,本公众号专注Go语言技术分享!
Crm(英文全称 Customer relationship management )是一个免费、开源的客户关系管理系统,主要功能有仪表盘、客户管理、合同管理、产品管理、订阅等功能。
<img src="https://zocrm.cloud/gzh_qrcode.jpg" style="width: 240px; height: 240px;border-radius: 10px;border: 1px solid #e9e9eb;" alt="gzh qrcode"/>
项目基于 Vue + Golang 实现,采用[MIT 许可证](https://github.com/zchengo/crm/blob/main/LICENSE),使用完全免费。
## 为何要开源
做项目的同时把项目开源了,既能提升自己,又能帮助别人,岂不美哉!本项目会持续更新优化,希望这个项目能够给大家带来更多的学习参考价值。
## 作者简介
程序员,Go 开发工程师,喜欢 Go 语言、Vue.js、区块链、开源。
## 关注作者
欢迎关注公众号「**GoCode**」,本公众号专注Go语言技术分享!
<img src="/gzh_qrcode.jpg" style="width: 240px; height: 240px;border-radius: 8px;border: 1px solid #e9e9eb;" alt="gzh_qrcode"/>
+6 -2
View File
@@ -5,6 +5,11 @@ hero:
name: CrmSystem
text: Use Golang & Vue
tagline: 一个免费开源的客户关系管理系统。
image:
src: /logo.svg
alt: VitePress
width: 200
height: 200
actions:
- theme: brand
text: 在线预览
@@ -12,5 +17,4 @@ hero:
- theme: alt
text: 查看代码库
link: https://github.com/zchengo/crm
---
---
-5
View File
@@ -1,5 +0,0 @@
# 更新日志
### 2023-01-10
- CRM 开发文档正式发布。
+112
View File
@@ -0,0 +1,112 @@
# 跨域请求处理
您可以在前端、服务端或者 Nginx 服务器上处理跨域请求。
## 什么是跨域请求?
当您在浏览器中从一个域名的网页去请求另一个域名的资源时,域名、端口、协议中的任一不同,就会出现请求跨域。只要协议、域名和端口中的任何一个不同,都会被当作是不同的域,之间的请求就是跨域请求。
## 在服务端处理跨域请求
请参考如下代码:
```go
// Cors 处理跨域请求
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin")
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id, Uid, Ver")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
// 放行所有OPTIONS方法
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
// 处理请求
c.Next()
}
}
```
将 Cors 作为 Gin 的中间件,用户每次发送 API 请求时,都会经过此中间件(即每个跨域请求都会被处理)。
处理跨域请求的方式是在这个请求中设置跨域相关的请求头:
| 跨域相关的请求头 | 说明 |
| --- | -- |
| Access-Control-Allow-Origin | 允许跨域的域名,指定了该响应的资源是否被允许与给定的来源(origin)共享。 |
| Access-Control-Allow-Headers | 允许跨域的请求头, 用于预检请求中,列出了将会在正式请求的 ```Access-Control-Request-Headers``` 字段中出现的首部信息。 |
| Access-Control-Allow-Methods | 允许跨域请求的方法,在对预检请求的应答中明确了客户端所要访问的资源允许使用的方法或方法列表。 |
| Access-Control-Expose-Headers | 允许服务器指示那些响应标头可以暴露给浏览器中运行的脚本,以响应跨域请求。 |
| Access-Control-Allow-Credentials | 允许客户端携带验证信息,用于在请求要求包含 ```credentials``` 时,告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。Credentials 可以是 cookies 或 authorization headers。 |
## 在 Vue + Vite 项目中配置允许跨域请求
在 ```vite.config.js``` 配置文件中添加请求代理配置,请参考如下配置:
```js
export default defineConfig({
server: {
host: '127.0.0.1',
port: 8060,
proxy: {
'/api': {
target: 'http://127.0.0.1:8000/',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
},
plugins: [vue()],
})
```
## 在 Nginx 中配置允许跨域请求
修改 ```nginx.conf``` 配置文件,请参考如下:
```bash
server {
listen 80;
server_name zocrm.cloud;
location / {
root html/dist;
index index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# api proxy
location /api {
# 配置跨域
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' *;
add_header 'Access-Control-Allow-Headers' *;
proxy_pass http://127.0.0.1:8000;
}
}
```
## 如何选择?
以上三种跨域请求处理方式,比较推荐在服务端或者 Nginx 服务器上处理跨域请求,好处是跨域请求相关的配置可以由我们自己来决定。
+124
View File
@@ -0,0 +1,124 @@
# 用户授权与认证
Crm 系统采用 JWT 来完成用户授权与认证。
## 什么是 JWT
JSON Web TokenJWT)是一个开放标准(RFC 7519),它定义了一种紧凑和自包含的方式,用于作为JSON对象在各方之间安全地传输信息。
这些信息可以被验证和信任,因为它是数字签名的。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
以下是一些 JSON Web Token 应用场景:
- 授权:这是使用 JWT 最常见的场景。一旦用户登录,每个后续请求都将包括 JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且可以轻松地在不同领域使用。
- 信息交换:JWT 是各方之间安全传输信息的好方法。因为JWT可以签名,例如,使用公钥或私钥对,您可以确定发件人就是他们所说的那个人。此外,由于签名是使用标头和有效负载计算的,您还可以验证内容是否未被篡改。
想了解有关 JWT 的更多信息,请访问[jwt.io](https://jwt.io)。
## 安装
添加 ```golang-jwt``` 作为Go程序中的依赖项,请执行诶下命令:
```bash
go get -u github.com/golang-jwt/jwt/v4
```
## 封装成方法
请参考如下代码:
```go
import (
"crm/global"
"time"
"github.com/golang-jwt/jwt/v4"
)
type Claims struct {
Uid int64 `json:"uid"`
jwt.RegisteredClaims
}
// 生成Token
func GenToken(uid int64) (string, error) {
var signingKey = []byte(global.Config.Jwt.SigningKey)
var expiredTime = global.Config.Jwt.ExpiredTime
claims := Claims{uid, jwt.RegisteredClaims{
ExpiresAt: &jwt.NumericDate{Time: time.Now().Add(time.Duration(expiredTime) * time.Second)},
Issuer: "crm",
}}
token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(signingKey)
return token, err
}
// 校验Token
func VerifyToken(tokens string) (int64, error) {
token, err := jwt.ParseWithClaims(tokens, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(global.Config.Jwt.SigningKey), nil
})
claims, ok := token.Claims.(*Claims)
if ok && token.Valid {
return claims.Uid, nil
}
return 0, err
}
```
想要了解有关 golang-jwt 的更多信息,请访问[golang-jwt](https://github.com/golang-jwt/jwt)。
## 当用户登录成功后生成 Token 信息
请参考 ```crm/server/service/user.go``` 中的 ```Login``` 方法,部分代码如下:
```go
// 用户登录
func (u *UserService) Login(param *models.UserLoginParam) (*models.UserInfo, int) {
...
// 生成Token
token, err := common.GenToken(user.Id)
if err != nil {
log.Printf("[error]Login:GenerateToken:%s", err)
return nil, response.ErrCodeFailed
}
userInfo := models.UserInfo{
Uid: user.Id,
Token: token,
}
...
}
```
## 使用 JWT 中间件校验 Token
请参考如下代码:
```go
// JWT认证中间件
func JwtAuth() gin.HandlerFunc {
return func(c *gin.Context) {
uid, _ := strconv.Atoi(c.Request.Header.Get("uid"))
token := c.Request.Header.Get("token")
if token == "" {
response.Result(response.ErrCodeNoLogin, nil, c)
c.Abort()
return
}
userid, err := common.VerifyToken(token)
if userid != int64(uid) || err != nil {
response.Result(response.ErrCodeTokenExpire, nil, c)
c.Abort()
return
}
c.Next()
}
}
```
前端发送请求时会携带 ```uid``` 和 ```token```JWT 认证中间件会校验 ```token``` 的合法性来判断用户是否登录。
-106
View File
@@ -1,106 +0,0 @@
# 部署指南
本地部署的主要流程:环境安装、运行服务端、运行Web端。
## 环境安装
在你自己的电脑上,安装如下运行环境:
| 环境 | 版本 | 下载地址 |
|---|---|---|
| go | >= 1.19.2 | https://golang.google.cn/dl |
| mysql | >= 8.0.31 | https://www.mysql.com/downloads |
| redis | >= 7.0.5 | https://redis.io/download |
| node | >= 18.12.0 | https://nodejs.org/en/download |
## 运行服务端
::: info
前提条件:Go 环境正常、MySQL 服务正常启动、Redis 服务正常启动。
:::
第一步,导入数据库文件,你需要把 crm/server/db/crm.sql 文件导入到本地的数据库中,你可以在数据库开发工具 Navicat 中直接导入 SQL 文件。
第二步,修改配置文件,你需要修改 crm/server/config.yaml 配置文件,你可以保持默认配置,但是你必须修改邮件服务配置和支付宝支付配置,否则你无法正常使用注册、密码找回、获取验证码、订阅、支付等功能。
邮件服务配置如下:
```yaml
# 邮件服务
mail:
smtp: smtp.qq.com
secret: dhsepilzlvoaceij // 改成自己的QQ邮箱SMTP服务的授权码
sender: 1655064994@qq.com // 改成自己的QQ邮箱
```
**如何开启邮箱的 SMTP 服务并获取授权码?**
请参考官方文档:https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=10000&&no=1001607
支付宝支付服务配置如下:
```yaml
# 支付宝支付服务配置
alipay:
appId: 2022003122606990
privateKey: MIIEpQIBAAKCAQEAkR0YofR...2sDd6uIy9rkpk8azj/rLmetW5r+tqTZgxcPWKeSz4=
appPublicCert: /home/ubuntu/crm/cert/appPublicCert.crt
alipayRootCert: /home/ubuntu/crm/cert/alipayRootCert.crt
alipayPublicCert: /home/ubuntu/crm/cert/alipayPublicCert.crt
returnURL: http://127.0.0.1:8000/api/subscribe/callback
notifyURL: http://127.0.0.1:8000/api/subscribe/notify
paySuccessURL: http://127.0.0.1:8060/#/subscribe
```
**如何获取 appId、privateKey、appPublicCert、alipayRootCert、alipayPublicCert **
你需要登录到支付宝开放平台:https://open.alipay.com
登录到支付宝开放平台后,点击控制台->开发工具推荐->沙箱->沙箱应用,在基本信息中可看到 APPID,然后在开发信息中选择系统默认秘钥->启用证书模式->查看,即可看到复制私钥和下载证书,1个私钥和3个证书。
**如何获取支付账号?**
点击控制台->开发工具推荐->沙箱->沙箱账号,里面有商家信息和买家信息,买家信息中的买家账号就是支付账号。
第三步,初始化并运行,使用电脑自带的终端执行执行如下命令,也可以使用 VS Code 或者 Goland 等开发工具,打开 crm 目录,找到 Terminal 终端。
执行如下命令:
```bash
$ cd server
$ go mod tidy
$ go build -o server main.go (windows编译命令为 go build -o server.exe main.go )
# 运行二进制
$ ./server (windows运行命令为 server.exe)
```
运行二进制文件后,如果控制台没有出现报错信息,就说明服务端启动成功。
## 运行Web端
::: info
前提条件:Node 环境正常。
:::
使用电脑自带的终端执行执行如下命令,也可以使用 VSCode 或者 WebStom 等开发工具,打开 crm 目录,找到 Terminal 终端。
执行如下命令:
```bash
$ cd web
$ npm install
$ npm run dev
```
当你使用 npm install 命令安装依赖时,如果出现下载缓慢、卡住等问题,你需要修改 npm 默认的镜像源。
要修改镜像源,请执行如下命令:
```bash
npm install -g cnpm --registry=https://registry.npmmirror.com
```
想要了解有关 Npm Mirror 中国镜像站的更多信息,请访问 npmmirror.com
当 Web 端启动成功后,打开浏览器访问 http://127.0.0.1:8060
+168
View File
@@ -0,0 +1,168 @@
# 持续集成与交付 (CI/CD)
Crm 系统使用 GitHub Actions 作为持续集成和持续交付 (CI/CD) 平台,自动执行生成、测试和部署,通过创建工作流程来自动构建和部署项目到生产环境。
想要了解有关 GitHub Actions 的更多信息,请访问[GitHub Actions](https://docs.github.com/en/actions)。
## 创建工作流
在您的 Github 存储库中创建 ```.github/workflows``` 目录,在该目录下创建一个 ```Ymal``` 文件(如 deploy.ymal)。
## 编写配置文件
配置文件 ```deploy.ymal``` 请参考如下:
```yaml
name: CRM CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.12.0'
- name: Build Web
run: cd web && npm install && npm run build
- name: Build Docs
run: cd docs && npm install && npm run docs:build
- name: Use Go
uses: actions/setup-go@v3
with:
go-version: 1.19
- name: Build Server
run: cd server && go mod tidy && go build -o crmserver main.go
- name: Deploy CRM
env:
KEY: ${{ secrets.SSH_PRIVATE_KEY }}
HOST: ${{ secrets.REMOTE_HOST }}
run: |
mkdir -p ~/.ssh/ && echo "$KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
scp -o StrictHostKeyChecking=no -r web/dist ubuntu@${HOST}:/usr/local/nginx/html/
scp -o StrictHostKeyChecking=no -r docs/docs/.vitepress/dist ubuntu@${HOST}:/usr/local/nginx/html/docs/
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /usr/local/nginx/sbin/nginx -s reload"
scp -o StrictHostKeyChecking=no -r server/crmserver ubuntu@${HOST}:/home/ubuntu/
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /home/ubuntu/crmapi/restart.sh > /dev/null 2>&1 &"
```
## 配置文件说明
### 使用 Ubuntu 系统构建应用
```yaml
jobs:
build:
runs-on: ubuntu-latest
```
### 构建Web端与项目文档
```yaml
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.12.0'
- name: Build Web
run: cd web && npm install && npm run build
- name: Build Docs
run: cd docs && npm install && npm run docs:build
```
### 构建服务端
```yaml
- name: Use Go
uses: actions/setup-go@v3
with:
go-version: 1.19
- name: Build Server
run: cd server && go mod tidy && go build -o crmserver main.go
```
### 部署到服务器
```yaml
- name: Deploy CRM
env:
KEY: ${{ secrets.SSH_PRIVATE_KEY }}
HOST: ${{ secrets.REMOTE_HOST }}
run: |
mkdir -p ~/.ssh/ && echo "$KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
scp -o StrictHostKeyChecking=no -r web/dist ubuntu@${HOST}:/usr/local/nginx/html/
scp -o StrictHostKeyChecking=no -r docs/docs/.vitepress/dist ubuntu@${HOST}:/usr/local/nginx/html/docs/
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /usr/local/nginx/sbin/nginx -s reload"
scp -o StrictHostKeyChecking=no -r server/crmserver ubuntu@${HOST}:/home/ubuntu/
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /home/ubuntu/crmapi/restart.sh > /dev/null 2>&1 &"
```
设置 ```SSH_PRIVATE_KEY``` 和 ```REMOTE_HOST```
```SSH_PRIVATE_KEY``` 指的是你在自己电脑上生成的 SSH 私钥(与服务器关联的那个秘钥),```REMOTE_HOST``` 指的是服务器的IP地址。
由于这两个变量属于敏感信息,不方便直接写在配置文件中,所以需要在您的 ```代码库``` -> ```Settings``` -> ```secrets``` -> ```Actions``` 中设置。设置后,可通过 ```secrets``` 来调用。
在虚拟机环境中配置 ```SSH```
```bash
mkdir -p ~/.ssh/ && echo "$KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
```
将构建的页面资源上传到服务器的特定目录:
```bash
scp -o StrictHostKeyChecking=no -r web/dist ubuntu@${HOST}:/usr/local/nginx/html/
scp -o StrictHostKeyChecking=no -r docs/docs/.vitepress/dist ubuntu@${HOST}:/usr/local/nginx/html/docs/
```
连接到服务器、重启 Nginx 服务:
```bash
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /usr/local/nginx/sbin/nginx -s reload"
```
将构建的Go可执行文件上传到服务器的特定目录:
```bash
scp -o StrictHostKeyChecking=no -r server/crmserver ubuntu@${HOST}:/home/ubuntu/
```
使用 Shell 脚本重启Go服务:
```bash
ssh -o StrictHostKeyChecking=no ubuntu@${HOST} "sudo /home/ubuntu/crmapi/restart.sh > /dev/null 2>&1 &"
```
Shell 重启Go服务脚本 ```restart.sh```,请参考如下:
```shell
#!/bin/bash
sudo pkill crmserver
sudo cp /home/ubuntu/crmserver /home/ubuntu/crmapi/
sudo nohup /home/ubuntu/crmapi/crmserver > /home/ubuntu/crmapi/crmserver.log 2>&1 &
```
## 常见问题
遇到问题,请访问[GitHub Actions](https://docs.github.com/en/actions)查看更多信息。
@@ -0,0 +1,696 @@
# 部署到云服务器
如果您打算将 Crm 系统部署到您自己的云服务器,您需要先注册一个域名和购买一台云服务器,然后在云服务器上进行环境安装、服务启动与配置、项目的构建与部署。
## 注册域名
您可以选择以下任意云厂商提供的域名注册,完成域名注册。
- [阿里云-域名注册](https://wanwang.aliyun.com)
- [腾讯云-域名注册](https://dnspod.cloud.tencent.com/)
- [百度智能云-域名服务](https://cloud.baidu.com/product/bcd.html)
## 购买云服务器
您可以选择以下任意云厂商提供的云服务器,完成云服务器购买。
- [阿里云-云服务器ECS](https://www.aliyun.com/product/ecs)
- [腾讯云-云服务器CVM](https://cloud.tencent.com/product/cvm)
- [华为云-弹性云服务器ECS](https://www.huaweicloud.com/product/ecs.html)
- [亚马逊云-Amazon EC2](https://aws.amazon.com/cn/ec2/?nc2=h_ql_prod_fs_ec2)
- [百度智能云-云服务器BCC](https://cloud.baidu.com/product/bcc.html)
::: tip 友情提示
亚马逊云新用户可以免费体验12个月云服务器以及其他基础设施产品和服务,[前往免费体验](https://aws.amazon.com/cn/campaigns/freecenter-select-region)。
:::
## 创建云服务器实例
以亚马逊云 Amazon EC2(其他云服务器类似)为例,创建与配置云服务器实例。
第一步,登录到亚马逊云控制台,点击 ```EC2```。
<img src="/amazon_console.png" style="border-radius: 5px;" alt="amazon console"/>
第二步,选择 ```实例```,点击 ```启动新实例```。
<img src="/amazon_ec2.png" style="border-radius: 5px;" alt="amazon ec2"/>
第三步,填写实例名称 ```crm```(可填写任意名称),操作系统选择 ```Ubuntu```(比较推荐),其他按默认设置即可,然后点击 ```启动实例```。
<img src="/start_instance.png" style="border-radius: 5px;" alt="start instance"/>
第四步,实例启动成功后,您需要连接到您的实例,请点击 ```连接到实例```。
<img src="/start_instance_success.png" style="border-radius: 5px;" alt="start instance success"/>
第五步,连接到实例的方式有四种,推荐使用 ```SSH 客户端``` 来连接实例,您需要先关联密钥对,请根据如下提示进行操作。
<img src="/ssh_connect_ec2.png" style="border-radius: 5px;" alt="ssh connect ec2"/>
::: details 如何将密钥对与 EC2 实例(云服务器)进行关联?
1. 在您自己的电脑中,执行如下命令来生成密钥对:
```bash
ssh-keygen -t rsa -C "xxxx@qq.com"
```
生成密钥对后,会在 ```~/.ssh/``` 目录下生成私钥文件 ```id_rsa``` 和公钥文件 ```id_rsa.pub```,复制公钥文件中的内容。
2. 查看实例列表,选中您创建的实例,点击 ```连接```。
<img src="/instance_list.png" style="border-radius: 5px;" alt="instance list"/>
3. 在连接到实例页面中,选择 ```EC2 Instance Connect```,点击 ```连接```,即可连接到服务器。
4. 将自己电脑中生成的公钥文件的内容,复制到云服务器的 ```~/.ssh/authorized_keys``` 文件中。
完成以上步骤,即可完成密钥对与 EC2 实例(云服务器)的关联。
:::
密钥对与 EC2 实例(云服务器)关联成功后,您就可以使用 SSH 连接到您创建的 EC2 实例),您可以执行如下命令:
```bash
ssh 用户名@ip地址 // 比如 ssh ubuntu@52.223.50.216
```
进入到云服务器后,即可搭建系统的运行环境。
## 环境搭建
您需要安装以下运行环境:
| 环境 | 版本 | 下载地址 |
|---|---|---|
| go | >= 1.19.2 | https://golang.google.cn/dl |
| mysql | >= 8.0.31 | https://www.mysql.com/downloads |
| redis | >= 7.0.5 | https://redis.io/download |
| node | >= 18.12.0 | https://nodejs.org/en/download |
| nginx | >= 1.22.1 | http://nginx.org/en/download.html |
::: tip 提示
以下安装操作适用于 Ubuntu 操作系统,安装版本均为 Linux 版本。
:::
### 安装 Go 环境
安装 Go 语言压缩包,请执行如下命令:
```bash
$ wget https://golang.google.cn/dl/go1.19.5.linux-amd64.tar.gz
```
压缩包下载完成后,建议解压到 ```/usr/local/``` 目录下,您可以执行如下命令:
```bash
$ sudo tar -zxvf go1.19.5.linux-amd64.tar.gz -C /usr/local/
```
配置 Go 环境变量,使用 ```vi``` 命令打开 ```~/.profile``` 文件,添加如下配置:
```bash
# golang
export PATH="$PATH:/usr/local/go/bin"
```
添加完成后,执行 ```source .profile```。
查看 Go 环境是否安装成功:
```bash
$ go version
go version go1.19.5 linux/amd64
```
### 安装 Node 环境
下载 Node For Linux Binaries (x64) 并解压到 ```/usr/local/``` 目录下,请执行如下命令:
```bash
$ wget https://nodejs.org/dist/v18.13.0/node-v18.13.0-linux-x64.tar.xz
$ sudo tar -xvf node-v18.13.0-linux-x64.tar.xz -C /usr/local/
```
配置 Node 环境变量,使用 ```vi``` 命令打开 ```~/.profile``` 文件,添加如下配置:
```bash
# nodejs
export PATH="$PATH:/usr/local/node-v18.13.0-linux-x64/bin"
```
添加完成后,执行 ```source .profile```。
查看 Node 环境是否安装成功:
```bash
$ node -v
v18.13.0
$ npm -v
8.19.3
```
### 安装 MySQL
使用 ```apt install``` 安装,请执行如下命令:
```bash
$ sudo apt install mysql-server
```
查看是否安装成功:
```bash
$ mysql --version
mysql Ver 8.0.31-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu))
```
默认用户名 ```root```, 默认密码 ``` ```,修改默认密码为 ```123456```,请执行如下命令:
```bash
# mysqladmin -u用户名 -p旧密码 password 新密码
$ sudo mysqladmin -uroot -p password 123456
```
登录到 MySQl,请执行如下命令:
```bash
$ sudo mysql -uroot -p123456
```
### 安装 Redis
安装 redis-stable 源码,请执行如下命令:
```bash
wget https://download.redis.io/redis-stable.tar.gz
```
编译和安装 redis,默认会安装到 ```/usr/local/bin``` 目录下,请执行如下命令:
```bash
$ sudo tar -xzvf redis-stable.tar.gz
$ cd redis-stable
$ sudo make
$ sudo make install
```
启动 redis 服务,请执行如下命令:
```bash
$ redis-server
```
### 安装 Nginx
安装 Nginx 源码包,请执行如下命令:
```bash
$ wget http://nginx.org/download/nginx-1.22.1.tar.gz
```
解压 ```nginx-1.22.1.tar.gz``` 到当前目录,请执行如下命令:
```bash
$ sudo tar -zxvf nginx-1.22.1.tar.gz
```
编译和安装 Nginx,请执行如下命令:
```bash
$ cd nginx-1.22.1
$ sudo ./configure --prefix=/usr/local/nginx --without-http_rewrite_module
```
::: danger 您可能会遇到如下报错:
```bash
./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.
```
:::
需要先安装 ```zlib library```, 请执行如下命令:
```bash
$ wget http://www.zlib.net/zlib-1.2.13.tar.gz
$ tar -zxvf zlib-1.2.13.tar.gz
$ cd zlib-1.2.13
$ sudo ./configure
$ sudo make
$ sudo make install
```
了解 zlib 的更多信息,请访问[zlib.net](http://www.zlib.net/)。
安装完 ```zlib library``` 后,重新安装 Nginx,请执行如下命令:
```bash
$ cd nginx-1.22.1
$ sudo ./configure --prefix=/usr/local/nginx --without-http_rewrite_module
$ sudo make
$ sudo make install
```
查看是否安装成功,请执行如下命令:
```bash
$ nginx -v
nginx version: nginx/1.22.1
```
修改 Nginx 配置文件 ```/usr/local/nginx/conf/nginx.conf```,请参考如下配置:
```bash
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name zocrm.cloud;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html/dist;
index index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# api proxy
location /api {
proxy_pass http://127.0.0.1:8000;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
server {
listen 443 ssl;
server_name zocrm.cloud;
ssl_certificate cert/8913125_zocrm.cloud.pem;
ssl_certificate_key cert/8913125_zocrm.cloud.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
root html/dist;
index index.html;
}
location /api {
proxy_pass http://127.0.0.1:8000;
}
}
server {
listen 443 ssl;
server_name docs.zocrm.cloud;
ssl_certificate cert/9129982_docs.zocrm.cloud.pem;
ssl_certificate_key cert/9129982_docs.zocrm.cloud.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
root html/docs/dist;
index index.html;
}
}
}
```
启动 Nginx 服务,请执行如下命令:
```bash
$ cd /usr/local/nginx/sbin/
$ sudo ./nginx -c /usr/local/nginx/conf/nginx.conf
# 或者
$ sudo nginx
```
当 Nginx 服务成功启动后,您可以尝试在浏览器中访问服务器的 ```IP地址```,查看是否能访问到 Nginx 的默认页面。
::: details 访问不到 Nginx 默认页面?
您可能需要配置服务器实例的安全组,进入到 ```Amazon EC2 控制台``` -> ```EC2``` -> ```安全组``` -> ```入站规则``` -> ```编辑入站规则信息``` -> ```添加规则```,请参考如下:
<img src="/incoming_rules.png" style="border-radius: 5px;" alt="incoming rules"/>
点击 ```保存规则```,在浏览器中访问 ```IP地址```,即可看到如下页面:
<img src="/nginx_home.png" style="border-radius: 5px;" alt="nginx home page"/>
:::
到这里,系统运行环境的搭建基本已经完成。
## 构建与部署
您需要先下载 Crm 项目代码到服务器。
如果您的系统中已经安装了 ```Git```,您可以使用如下方式安装(推荐):
```bash
git clone https://github.com/zchengo/crm.git
```
您也可以使用 ```wget``` 命令下载压缩包,使用 ```unzip``` 解压,请执行如下命令:
```bash
wget https://github.com/zchengo/crm/archive/refs/heads/main.zip
unzip main.zip
```
### 部署服务端
::: tip 前提条件:
Go 环境正常、MySQL 服务正常启动、Redis 服务正常启动。
:::
#### 导入数据库文件
请先登录到 MySQl,请执行如下命令:
```bash
$ sudo mysql -uroot -p123456
```
再把 ```crm/server/db/crm.sql``` 文件导入到 MySQL 数据库中,执行如下 SQL 语句:
```bash
mysql> source SQL文件路径
```
#### 修改配置文件
您需要修改 ```crm/server/config.yaml``` 配置文件,必须修改文件存储配置、邮件服务配置和支付宝支付服务配置,否则您将无法正常使用文件导出、注册、密码找回、获取验证码、订阅、支付等功能。
文件存储配置如下:
```yaml
file:
path: /home/ubuntu/crm/source/
```
把路径改成自己的系统路径,建议使用绝对路径。
邮件服务配置如下:
```yaml
# 邮件服务
mail:
smtp: smtp.qq.com
secret: dhsepilzlvoaceij // 改成自己的QQ邮箱SMTP服务的授权码
sender: 1655064994@qq.com // 改成自己的QQ邮箱
```
**如何开启邮箱的 SMTP 服务并获取授权码?**
请参考官方文档[service.mail.qq.com](https://service.mail.qq.com)。
支付宝支付服务配置如下:
```yaml
# 支付宝支付服务配置
alipay:
appId: 2022003122606990
privateKey: MIIEpQIBAAKCAQEAkR0YofR...2sDd6uIy9rkpk8azj/rLmetW5r+tqTZgxcPWKeSz4=
appPublicCert: /home/ubuntu/crm/cert/appPublicCert.crt
alipayRootCert: /home/ubuntu/crm/cert/alipayRootCert.crt
alipayPublicCert: /home/ubuntu/crm/cert/alipayPublicCert.crt
returnURL: http://127.0.0.1:8000/api/subscribe/callback
notifyURL: http://127.0.0.1:8000/api/subscribe/notify
paySuccessURL: http://127.0.0.1:8060/#/subscribe
```
**如何获取支付宝支付服务的 appId、privateKey、appPublicCert、alipayRootCert、alipayPublicCert **
您需要登录到支付宝开放平台,请访问[open.alipay.com](https://open.alipay.com)。
登录到支付宝开放平台后,点击 ```控制台``` -> ```开发工具推荐``` -> ```沙箱``` -> ```沙箱应用```,在基本信息中可看到 ```APPID``` ,然后在开发信息中选择 ```系统默认秘钥``` -> ````启用证书模式``` -> ```查看```,即可看到复制私钥和下载证书,1个私钥和3个证书。
**如何获取支付账号?**
点击 ```控制台``` -> ```开发工具推荐``` -> ```沙箱``` -> ```沙箱账号```,里面有商家信息和买家信息,买家信息中的买家账号就是支付账号。
将 ```returnURL```、```notifyURL```、```paySuccessURL``` 中的 ```IP地址```改成您的服务器的 ```IP地址``` 或 ```域名```。
#### 初始化和运行
服务端初始化和运行,请执行如下命令:
```bash
$ cd crm
$ cd server
$ go mod tidy
$ go build -o crmserver main.go (windows编译命令为 go build -o crmserver.exe main.go )
# 运行二进制
$ ./crmserver (windows运行命令为 crmserver.exe)
# 或者在后台运行
$ sudo nohup ./crmserver > /home/ubuntu/crmserver.log 2>&1 &
```
### 部署Web端
::: tip 前提条件:
Node 环境正常。
:::
Web端初始化和打包,请执行如下命令:
```bash
$ cd crm
$ cd web
$ npm install
$ npm run build
```
::: details 使用 ```npm install``` 命令安装依赖时,出现下载缓慢、卡住等问题?
您可能需要修改 npm 默认的镜像源,请执行如下命令:
```bash
$ npm install -g cnpm --registry=https://registry.npmmirror.com
```
想要了解有关 Npm Mirror 中国镜像站的更多信息,请访问[npmmirror.com](https://npmmirror.com)。
:::
打包完成后,会在 ```crm/web/dist/``` 目录下生成页面资源文件,您需要复制这些文件到 ```/usr/local/nginx/html/``` 目录下,请执行如下命令:
```bash
sudo cp ./crm/web/dist /usr/local/nginx/html/
```
您可能需要适当的修改 Nginx 配置文件 ```/usr/local/nginx/conf/nginx.conf```,以确保能够访问到页面,您可能需要修改这个部分:
```bash
http {
...
server {
...
location / {
root html/dist;
index index.html;
}
}
}
```
然后您就可以通过 ```IP地址``` 或 ```域名``` 来访问 Crm 系统的页面了。
### 部署Docs文档
如果您有需要,您也可以部署 Docs 项目文档,部署方式与部署Web端类似。
请参考如下命令:
```bash
$ cd crm/docs
$ npm install
$ npm run docs:build
$ sudo cp ./docs/docs/.vitepress/dist /usr/local/nginx/html/docs
```
修改 Nginx 配置文件请参考:
```bash
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
...
# HTTPS server
# Web
server {
listen 443 ssl;
server_name zocrm.cloud;
ssl_certificate cert/8913125_zocrm.cloud.pem;
ssl_certificate_key cert/8913125_zocrm.cloud.key;
location / {
root html/dist;
index index.html;
}
location /api {
proxy_pass http://127.0.0.1:8000;
}
}
# Docs
server {
listen 443 ssl;
server_name docs.zocrm.cloud;
ssl_certificate cert/9129982_docs.zocrm.cloud.pem;
ssl_certificate_key cert/9129982_docs.zocrm.cloud.key;
location / {
root html/docs/dist;
index index.html;
}
}
}
```
当然,如果你使用域名来替换 ```html/``` 目录下的 ```dist``` 目录名称,或许会更优雅。
比如您可以这样命名:
```text
/usr/local/nginx/html/www/zocrm/com
/usr/local/nginx/html/www/docs/zocrm/com
```
### 测试
在浏览器访问您部署的项目,比如 http://3.83.115.236 或者 http://zocrm.cloud。
如果您配置了 SSL 证书,您可以使用 HTTPS 来访问。
## 持续集成与交付
当有新版本发布时,即可自动部署到服务器,请参考[持续集成与交付 (CI/CD)](/project/devops/ci-cd)。
## 常见问题
如果您在部署过程中遇到了问题,您可以通过以下方式反馈:
- [在公众号后台反馈](/about/about)
- [New Issues In Github](https://github.com/zchengo/crm/issues)
## 支持作者
此文档对您有帮助的话,您可以[支持作者](/sponsor/sponsor)。
+134
View File
@@ -0,0 +1,134 @@
# 部署指南
::: tip 提示
请先安装运行环境,再运行服务端和Web端。
:::
## 环境安装
在您自己的电脑上,安装如下运行环境:
| 环境 | 版本 | 下载地址 |
|---|---|---|
| go | >= 1.19.2 | https://golang.google.cn/dl |
| mysql | >= 8.0.31 | https://www.mysql.com/downloads |
| redis | >= 7.0.5 | https://redis.io/download |
| node | >= 18.12.0 | https://nodejs.org/en/download |
## 运行服务端
::: tip 前提条件:
Go 环境正常、MySQL 服务正常启动、Redis 服务正常启动。
:::
### 导入数据库文件
您需要把 ```crm/server/db/crm.sql``` 文件导入到本地的数据库中,您可以在数据库开发工具 Navicat 中直接导入 SQL 文件。
或者使用 MySQL 自带的命令行工具导入 SQL 文件:
```bash
mysql> source 文件路径
```
### 修改配置文件
您需要修改 ```crm/server/config.yaml``` 配置文件,您可以保持默认配置,但是您必须修改文件存储配置、邮件服务配置和支付宝支付服务配置,否则您将无法正常使用文件导出、注册、密码找回、获取验证码、订阅、支付等功能。
文件存储配置如下:
```yaml
file:
path: /home/ubuntu/crm/source/
```
把路径改成自己的系统路径,建议使用绝对路径。
邮件服务配置如下:
```yaml
# 邮件服务
mail:
smtp: smtp.qq.com
secret: dhsepilzlvoaceij // 改成自己的QQ邮箱SMTP服务的授权码
sender: 1655064994@qq.com // 改成自己的QQ邮箱
```
**如何开启邮箱的 SMTP 服务并获取授权码?**
请参考官方文档[service.mail.qq.com](https://service.mail.qq.com)。
支付宝支付服务配置如下:
```yaml
# 支付宝支付服务配置
alipay:
appId: 2022003122606990
privateKey: MIIEpQIBAAKCAQEAkR0YofR...2sDd6uIy9rkpk8azj/rLmetW5r+tqTZgxcPWKeSz4=
appPublicCert: /home/ubuntu/crm/cert/appPublicCert.crt
alipayRootCert: /home/ubuntu/crm/cert/alipayRootCert.crt
alipayPublicCert: /home/ubuntu/crm/cert/alipayPublicCert.crt
returnURL: http://127.0.0.1:8000/api/subscribe/callback
notifyURL: http://127.0.0.1:8000/api/subscribe/notify
paySuccessURL: http://127.0.0.1:8060/#/subscribe
```
**如何获取支付宝支付服务的 appId、privateKey、appPublicCert、alipayRootCert、alipayPublicCert **
您需要登录到支付宝开放平台,请访问[open.alipay.com](https://open.alipay.com)。
登录到支付宝开放平台后,点击 ```控制台``` -> ```开发工具推荐``` -> ```沙箱``` -> ```沙箱应用```,在基本信息中可看到 ```APPID``` ,然后在开发信息中选择 ```系统默认秘钥``` -> ````启用证书模式``` -> ```查看```,即可看到复制私钥和下载证书,1个私钥和3个证书。
**如何获取支付账号?**
点击 ```控制台``` -> ```开发工具推荐``` -> ```沙箱``` -> ```沙箱账号```,里面有商家信息和买家信息,买家信息中的买家账号就是支付账号。
### 初始化并运行
使用电脑自带的终端执行执行如下命令,也可以使用 VS Code 或者 Goland 等开发工具,打开 crm 目录,找到 Terminal 终端。
执行如下命令:
```bash
$ cd server
$ go mod tidy
$ go build -o server main.go (windows编译命令为 go build -o server.exe main.go )
# 运行二进制
$ ./server (windows运行命令为 server.exe)
```
运行二进制文件后,如果控制台没有出现报错信息,就说明服务端启动成功。
## 运行Web端
::: tip 前提条件:
Node 环境正常。
:::
使用电脑自带的终端执行执行如下命令,也可以使用 VSCode 或者 WebStom 等开发工具,打开 crm 目录,找到 Terminal 终端。
执行如下命令:
```bash
$ cd web
$ npm install
$ npm run dev
```
当您使用 ```npm install``` 命令安装依赖时,如果出现下载缓慢、卡住等问题,您可能需要修改 npm 默认的镜像源。
要修改镜像源,请执行如下命令:
```bash
$ npm install -g cnpm --registry=https://registry.npmmirror.com
```
想要了解有关 Npm Mirror 中国镜像站的更多信息,请访问[npmmirror.com](https://npmmirror.com)。
当 Web 端启动成功后,打开浏览器访问http://127.0.0.1:8060。
## 部署到云服务器
以上是把项目部署到本地,如果您想部署到云服务器,请参考[部署到云服务器](/project/devops/deploy-cloudserver)。
@@ -0,0 +1,3 @@
# 详细设计
文档即将发布...
+45
View File
@@ -0,0 +1,45 @@
# 快速开始
## 安装
如果你的系统中已经安装了 ```Git```,你可以使用如下方式安装:
```bash
git clone https://github.com/zchengo/crm.git
```
你也可以通过下载压缩包的方式安装[Download ZIP](https://github.com/zchengo/crm/archive/refs/heads/main.zip)。
## 部署
你需要在你的系统中,安装如下运行环境:
| 环境 | 版本 | 下载地址 |
|---|---|---|
| go | >= 1.19.2 | https://golang.google.cn/dl |
| mysql | >= 8.0.31 | https://www.mysql.com/downloads |
| redis | >= 7.0.5 | https://redis.io/download |
| node | >= 18.12.0 | https://nodejs.org/en/download |
::: tip 初始化和运行的前提条件
Go 环境正常、Node 环境正常、MySQL 和 Redis 能正常启动。
:::
然后在终端中,执行如下命令:
```bash
$ cd server
$ go mod tidy
$ go build -o server main.go (windows编译命令为 go build -o server.exe main.go )
# 运行二进制
$ ./server (windows运行命令为 server.exe)
$ cd web
$ npm install
$ npm run dev
```
项目初始化并运行成功后,打开浏览器访问http://127.0.0.1:8060。
详细部署,请参考[部署指南](/project/docs/deploy-guide)。
+106
View File
@@ -0,0 +1,106 @@
# 简介
::: tip 提示
你正在阅读的是 Crm 最新版的[项目文档](https://docs.zocrm.cloud)。
:::
## 什么是 Crm
Crm(英文全称 Customer relationship management )是一个客户关系管理系统,主要功能有仪表盘、客户管理、合同管理、产品管理、订阅等功能。
- 在线演示:[zocrm.cloud](https://zocrm.cloud)
- 项目文档:[docs.zocrm.cloud](https://docs.zocrm.cloud)
## 技术栈
### 前端技术
| 技术 | 说明 | 相关文档 |
|---|---|---|
| Vue.js | 前端框架 | https://v3.cn.vuejs.org |
| Vue Router | 页面路由 | https://router.vuejs.org |
| Axios | 网络请求库 | https://axios-http.com |
| Pinia | 状态管理 | https://pinia.vuejs.org |
| Vite | 构建工具 | https://vitejs.dev |
| Ant Design Vue | 前端UI组件库 | https://www.antdv.com |
| Apache ECharts | 可视化图表库 | https://echarts.apache.org |
| Moment | 日期库 | https://momentjs.com |
### 后端技术
| 技术 | 说明 | 相关文档 |
|---|---|---|
| Gin | Web框架 | https://gin-gonic.com |
| Gorm | ORM框架 | https://gorm.io |
| Jwt | 用户认证 | https://github.com/golang-jwt/jwt |
| Viper | 配置管理 | https://github.com/spf13/viper |
| Redis | 数据缓存 | https://github.com/go-redis/redis |
| Mail | 邮件服务SDK | https://github.com/go-gomail/gomail |
## 目录结构
Crm 的目录结构如下:
```text
crm
├── .github/workflows // 工作流
├── deploy.yaml // 自动部署配置文件
├── docs // 项目文档
├── docs // 项目文档
├── .vitepress // VitePress配置
├── logs // 更新日志
├── project // Markdown文档
├── sponsor // 赞赏
├── index.md // 文档首页
├── package-lock.json // Npm依赖管理
├── package.json // Npm依赖管理
├── server // 服务端
├── api // API层
├── common // 通用的工具
├── config // 配置文件
├── db // 数据库 SQL 文件
├── global // 全局对象
├── initialize // 初始化
├── middleware // 中间件
├── models // 数据模型
├── response // 数据响应封装
├── service // service层
├── config.yaml // Yaml配置文件
├── go.mod // Go模块
├── go.sum // Go模块相关
├── main.go // 程序启动的入口
├── web // Web端
├── public // 公共的资源
├── src // 源代码
|── api // API接口
├── assets // 资源
├── axios // 网络请求
├── router // 页面路由
├── store // 状态管理
├── views // 页面
├── App.vue // 组件入口
├── main.js // 程序启动的入口
├── index.html // 首页
├── package-lock.json // Npm依赖管理
├── package.json // Npm依赖管理
├── vite.config.js // Vite配置文件
├── .gitattributes // Git描述
├── .gitignore // Git文件忽略
├── LICENSE // 许可证
├── README.md // 项目简介文档
```
想要了解有关 Crm 目录结构中的文件,请访问[github.com/zchengo/crm](https://github.com/zchengo/crm)代码库。
## 系统架构
Crm 系统采用前后端分离架构,前端与后端分开部署,且部署到同一台服务器。
系统架构图:
<img src="/sys_structure.png" style="border-radius: 5px;" alt="system tructure"/>
## 许可证
Crm 是采用 MIT 许可的开源项目,使用完全免费。要了解有关 MIT 许可证的更多信息,请访问[MIT License](https://github.com/zchengo/crm/blob/main/LICENSE)。
@@ -0,0 +1,6 @@
# 问题反馈
在使用过程中遇到了问题,您可以通过以下方式反馈:
- [在公众号后台反馈](/about/about#关注作者)
- [New Issues In Github](https://github.com/zchengo/crm/issues)
+10
View File
@@ -0,0 +1,10 @@
# 更新日志
### 2023-01-15
- 项目文档优化。
- 新增前端、后端以及运维相关的文档。
### 2023-01-10
- CRM 项目文档正式发布。
+121
View File
@@ -0,0 +1,121 @@
# 封装 axios 请求库
## 什么是 axios
axios 是浏览器和 node.js 的一个简单的基于 promise 的 HTTP 客户端。axios 在一个具有非常可扩展界面的小软件包中提供了一个简单易用的库。
了解有关 axios 的更多信息,请访问[axios](https://github.com/axios/axios)。
## 封装 axios
封装 axios 请求库,请参考如下:
```js
import axios from 'axios';
import router from '../router/index';
import { message } from 'ant-design-vue';
const host = window.location.hostname
switch (host) {
case 'zocrm.cloud':
axios.defaults.baseURL = 'https://zocrm.cloud/api'
break;
default:
axios.defaults.baseURL = 'http://127.0.0.1:8000/api'
break;
}
const request = axios.create({
timeout: 5000,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
});
request.interceptors.request.use(config => {
config.headers['uid'] = localStorage.getItem('uid')
config.headers['token'] = localStorage.getItem('token')
return config
})
request.interceptors.response.use(response => {
console.log(response)
if (response.data.code == 1) {
message.error('服务器异常!')
}
return response;
}, error => {
console.log(error)
router.push('/error');
return Promise.reject(error)
})
export default request;
```
### 初始化请求的 baseURL
```js
const host = window.location.hostname
switch (host) {
case 'zocrm.cloud':
axios.defaults.baseURL = 'https://zocrm.cloud/api'
break;
default:
axios.defaults.baseURL = 'http://127.0.0.1:8000/api'
break;
}
```
通过 ```window.location.hostname``` 获取主机名(不包含端口号),主机名指的是 ```IP地址``` 或 ```域名```,然后根据不同的主机名,设置不同的 ```axios.defaults.baseURL```。
### 设置请求超时时间与请求头
```js
const request = axios.create({
timeout: 5000,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
});
```
### 请求拦截与响应拦截
请求拦截,请参考如下:
```js
request.interceptors.request.use(config => {
config.headers['uid'] = localStorage.getItem('uid')
config.headers['token'] = localStorage.getItem('token')
return config
})
```
前端每次发送请求时,都会被 axios 拦截。axios 会先给这个请求设置请求头 ```uid``` 和 ```token```,然后再向服务端发送请求。
响应拦截,请参考如下:
```js
request.interceptors.response.use(response => {
console.log(response)
if (response.data.code == 1) {
message.error('服务器异常!')
}
return response;
}, error => {
console.log(error)
router.push('/error');
return Promise.reject(error)
})
```
后端响应的数据会先被 axios 拦截,如果响应的结果是正确的,会直接返回响应结果,然后将数据渲染到指定的页面;如果响应的结果是错误的,会路由到错误页面。
了解有关 axios 请求拦截与响应拦截的更多信息,请访问[axios interceptors](https://github.com/axios/axios#interceptors)。
+54
View File
@@ -0,0 +1,54 @@
# 页面中的加载进度条
Crm 系统使用 NProgress 作为页面中的加载进度条。
## 什么是 NProgress
NProgress 是一个适用于应用程序的超薄进度条,灵感来自谷歌、YouTube和媒体。了解有关 NProgress 的更多信息,请访问[NProgress](https://github.com/rstacruz/nprogress)。
## 安装 NProgress
添加 ```nprogress.js``` 和 ```nprogress.css``` 到您的项目。
```html
<script src='nprogress.js'></script>
<link rel='stylesheet' href='nprogress.css'/>
```
或者使用 ```npm``` 安装:
```bash
$ npm install --save nprogress
```
## 在 Vue Router 中使用
在 Vue Router 中使用 nprogress,请参考如下:
```js
const router = createRouter({
history: createWebHashHistory(), routes
})
NProgress.configure({ easing: 'ease', speed: 500, showSpinner: false });
router.beforeEach((to, from, next) => {
NProgress.start() // 进度条开始
next()
})
router.afterEach(() => {
NProgress.done() // 进度条结束
})
```
查看完整代码,请访问[crm/web/src/router/index.js](https://github.com/zchengo/crm/blob/main/web/src/router/index.js)。
想要了解有关 NProgress 的更多信息,请访问[NProgress](https://github.com/rstacruz/nprogress)。
-28
View File
@@ -1,28 +0,0 @@
# 快速运行
系统运行环境:
| 环境 | 版本 | 下载地址 |
|---|---|---|
| go | >= 1.19.2 | https://golang.google.cn/dl |
| mysql | >= 8.0.31 | https://www.mysql.com/downloads |
| redis | >= 7.0.5 | https://redis.io/download |
| node | >= 18.12.0 | https://nodejs.org/en/download |
在终端中,执行如下命令,初始化并运行。
```bash
$ cd server
$ go mod tidy
$ go build -o server main.go (windows编译命令为 go build -o server.exe main.go )
# 运行二进制
$ ./server (windows运行命令为 server.exe)
$ cd web
$ npm install
$ npm run dev
```
项目运行成功后,打开浏览器访问 http://127.0.0.1:8060
-11
View File
@@ -1,11 +0,0 @@
# 简介
客户关系管理系统,基于 Vue + Go 实现,主要功能有仪表盘、客户管理、合同管理、产品管理,订阅等功能。
### 项目演示
https://zocrm.cloud
### 官方文档
https://docs.zocrm.cloud
-26
View File
@@ -1,26 +0,0 @@
# 许可证
```
MIT License
Copyright (c) 2022 zchengo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
要了解有关 MIT License 许可证的更多信息,请访问 [MIT License](https://github.com/zchengo/crm/blob/main/LICENSE)。
-25
View File
@@ -1,25 +0,0 @@
# 技术栈
### 前端技术
| 技术 | 说明 | 相关文档 |
|---|---|---|
| Vue.js | 前端框架 | https://v3.cn.vuejs.org |
| Vue Router | 页面路由 | https://router.vuejs.org |
| Axios | 网络请求库 | https://axios-http.com |
| Pinia | 状态管理 | https://pinia.vuejs.org |
| Vite | 构建工具 | https://vitejs.cn |
| Ant Design Vue | 前端UI组件库 | https://www.antdv.com |
| Apache ECharts | 可视化图表库 | https://echarts.apache.org |
| Moment | 日期库 | https://momentjs.com |
### 后端技术
| 技术 | 说明 | 相关文档 |
|---|---|---|
| Gin | Web框架 | https://gin-gonic.com |
| Gorm | ORM框架 | https://gorm.io |
| Jwt | 用户认证 | https://github.com/golang-jwt/jwt |
| Viper | 配置管理 | https://github.com/spf13/viper |
| Redis | 数据缓存 | https://github.com/go-redis/redis |
| Mail | 邮件服务SDK | https://github.com/go-gomail/gomail |
Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="181.88px" viewBox="0 0 1126 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M904.3968 585.0624l-362.0352-361.984-362.0352 361.984 325.7856 325.8368a51.2 51.2 0 0 0 72.448 0l325.8368-325.8368z" fill="#476FFF" fill-opacity=".5" /><path d="M343.9616 96.256L54.272 385.8944a76.8 76.8 0 0 0 0 108.5952l434.432 434.432a76.8 76.8 0 0 0 108.5952 0l289.6384-289.5872a76.8 76.8 0 0 0 0-108.6464L452.608 96.256a76.8 76.8 0 0 0-108.5952 0z m-253.44 325.8368l289.6384-289.6384a25.6 25.6 0 0 1 36.1984 0l434.432 434.432a25.6 25.6 0 0 1 0 36.2496l-289.6384 289.5872a25.6 25.6 0 0 1-36.1984 0L90.5216 458.2912a25.6 25.6 0 0 1 0-36.1984z" fill="#476FFF" /><path d="M942.6432 297.472a25.6 25.6 0 0 0-39.168 32.7168l2.9696 3.5328 88.4224 88.4224a25.6 25.6 0 0 1 2.9696 32.6656l-2.9696 3.584-434.432 434.432a25.6 25.6 0 0 1-32.6656 2.9696l-3.5328-2.9696-289.6384-289.6384a25.6 25.6 0 0 1-2.9696-32.6656l2.9696-3.584 434.432-434.432a25.6 25.6 0 0 1 32.6656-2.9184l3.584 2.9184 79.8208 79.872a25.6 25.6 0 0 0 39.168-32.6656l-2.9696-3.584-79.872-79.8208a76.8 76.8 0 0 0-103.1168-4.9664l-5.4784 4.9664-434.432 434.4832a76.8 76.8 0 0 0-4.9664 103.1168l4.9664 5.4784 289.6384 289.6384a76.8 76.8 0 0 0 103.1168 4.9664l5.4784-4.9664 434.4832-434.4832a76.8 76.8 0 0 0 4.9664-103.1168l-4.9664-5.4784-88.4736-88.4224z" fill="#476FFF" /><path d="M542.3616 186.88l398.2336 398.1824-343.9616 343.9616a76.8 76.8 0 0 1-108.5952 0l-343.9616-343.9616 398.2848-398.2336z m-307.712 416.256l289.5872 289.6896 3.584 2.9696a25.6 25.6 0 0 0 32.6144-2.9696l289.6896-289.6384a25.6 25.6 0 0 0 0-36.2496l-307.712-307.712-307.712 307.712a25.6 25.6 0 0 0 0 36.2496z" fill="#476FFF" /></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+4 -4
View File
@@ -2,10 +2,10 @@
打开微信扫一扫,扫描下方赞赏码,请作者喝咖啡!
<img src="https://zocrm.cloud/sponsor.png" style="width: 240px; height: 240px;border-radius: 10px;border: 1px solid #e9e9eb;" alt="sponsor qrcode"/>
<img src="/sponsor.png" style="width: 240px; height: 240px;border-radius: 8px;border: 1px solid #e9e9eb;" alt="sponsor qrcode"/>
### 赞赏记录
| 用户昵称 | 金额 | 备注 |
| ---- | -- | -- |
| 空空如也 | ¥0 | 无备注 |
| 用户昵称 | 金额 | 备注 | 赞赏日期 |
| ---- | -- | -- | -- |
| 空空如也 | ¥0 | 无备注 | 2023.01.10 |