docs: change and add docs
@@ -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
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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' },
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import Theme from 'vitepress/theme'
|
||||
import './index.css'
|
||||
|
||||
export default {
|
||||
...Theme
|
||||
}
|
||||
@@ -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"/>
|
||||
@@ -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
|
||||
---
|
||||
|
||||
---
|
||||
@@ -1,5 +0,0 @@
|
||||
# 更新日志
|
||||
|
||||
### 2023-01-10
|
||||
|
||||
- CRM 开发文档正式发布。
|
||||
@@ -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 服务器上处理跨域请求,好处是跨域请求相关的配置可以由我们自己来决定。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# 用户授权与认证
|
||||
|
||||
Crm 系统采用 JWT 来完成用户授权与认证。
|
||||
|
||||
## 什么是 JWT ?
|
||||
|
||||
JSON Web Token(JWT)是一个开放标准(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``` 的合法性来判断用户是否登录。
|
||||
|
||||
@@ -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
|
||||
@@ -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)。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
# 详细设计
|
||||
|
||||
文档即将发布...
|
||||
@@ -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)。
|
||||
@@ -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)
|
||||
@@ -0,0 +1,10 @@
|
||||
# 更新日志
|
||||
|
||||
### 2023-01-15
|
||||
|
||||
- 项目文档优化。
|
||||
- 新增前端、后端以及运维相关的文档。
|
||||
|
||||
### 2023-01-10
|
||||
|
||||
- CRM 项目文档正式发布。
|
||||
@@ -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)。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,11 +0,0 @@
|
||||
# 简介
|
||||
|
||||
客户关系管理系统,基于 Vue + Go 实现,主要功能有仪表盘、客户管理、合同管理、产品管理,订阅等功能。
|
||||
|
||||
### 项目演示
|
||||
|
||||
https://zocrm.cloud
|
||||
|
||||
### 官方文档
|
||||
|
||||
https://docs.zocrm.cloud
|
||||
@@ -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)。
|
||||
@@ -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 |
|
||||
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 169 KiB |
@@ -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 |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 329 KiB |
|
After Width: | Height: | Size: 773 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 54 KiB |
@@ -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 |
|
||||