后台管理系统

架构示意图

​ 前端 后台 小程序云开发

vue-admin-template <—通过 ajax–> 基于 Koa2;HTTP API 或 tcb-admin-node —->云函数、云数据库、云存储

vue-admin-template 构建管理系统前端

vue-element-admin 基于 element 的后台管理系统模板

vue-admin-templatevue-element-admin的简化版

使用方法查看官方文档。

Koa2 构建管理系统后端

官网: https://koa.bootcss.com/

新建空文件夹 wx-music-admin-backend,打开终端:

1
2
3
4
5
6
7
8
9
# 生成package.json文件,-y 表示默认的配置
npm init -y

# 安装koa
npm install koa

# 新建app.js文件 (win10系统命令),作为项目入口文件
type nul > app.js

app.js:

1
2
3
4
5
6
7
8
9
10
11
12
const Koa = require("koa");
const chalk = require("chalk"); // 使console.log打印文字有颜色的插件,需: npm i chalk
const app = new Koa();

app.use(async (ctx) => {
ctx.body = "Hello Wolrd";
});
const port = 3000;
app.listen(port, () => {
// 端口号,开启服务后的回调函数
console.log(chalk.green(`> 服务已开启,访问:http://localhost:${port}`));
});

终端:

1
2
3
4
# node启动项目
node app.js

# 访问:http://localhost:3000

接口调用凭证 access_token 的缓存与更新

access_token,微信的接口调用凭证,详情:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html

回到项目 wx-music-admin-backend,打开终端:

1
2
3
# HTTP 请求 插件
npm i request
npm i request-promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* 获取微信接口调用凭证
* 详情:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
*/

const rp = require("request-promise"); // node发送http请求的插件
const fs = require("fs"); // node文件模块
const path = require("path"); // node 路径模块

//fileName = __dirname 当前文件所在目录的绝对路径, 加上 './access_token.json'
const fileName = path.resolve(__dirname, "./access_token.json");

// 这两个参数的获取:微信公众平台>开发>开发设置
const APPID = "wxc4e0b2d98063b103";
const APPSECRET = "xxx"; //小程序密钥,注意保密!

// 微信 access_token 请求地址
const URL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`;

// 发送请求获取AccessToken
const updateAccessToken = async () => {
const resStr = await rp(URL);
const res = JSON.parse(resStr);

if (res.access_token) {
// node写文件,参数:1 文件路径,2 文件内容, 首次写文件为新建,往后为覆盖
fs.writeFileSync(
fileName,
JSON.stringify({
access_token: res.access_token,
createTime: new Date(),
})
);
} else {
// 如获取不到,再次获取
await updateAccessToken();
}
};

// 读取access_token
const getAccessToken = async () => {
try {
// node读取文件,参数:1 读取的文件,2 字符集
const readRes = fs.readFileSync(fileName, "utf8");
const readObj = JSON.parse(readRes);

// 如果服务器宕机导致setInterval无法定时更新,这里需要再次判断access_token的有效性
const createTime = new Date(readObj.createTime).getTime();
const nowTime = new Date().getTime();
if ((nowTime - createTime) / 1000 / 60 / 60 >= 2) {
await updateAccessToken();
await getAccessToken();
return;
}
return readObj.access_token;
} catch (error) {
//捕获异常,在未创建文件时,先创建文件
await updateAccessToken();
await getAccessToken();
}
};

// access_token有效期为2个小时,定时更新
setInterval(async () => {
await updateAccessToken();
}, (7200 - 300) * 1000);

module.exports = getAccessToken;

后端代码通过 HTTP API 触发云函数获取数据

HTTP API 触发云函数

产生跨域和后端解决跨域问题

管理系统前端向管理系统后端请求数据,产生了跨域问题

1
2
3
4
5
6
7
8
9
10
11
// 产生跨域的几种情况
// http://www.a.com https://www.a.com 协议不同
// http://www.a.com http://www.b.com 域名不同
// http://www.a.com http://news.a.com 主域与子域不同
// http://www.a.com:8080 http://www.a.com:3000 端口不同

// 解决跨域的几种方法
// jsonp
// iframe
// postMessage跨域
// 跨域资源共享(CORS)

管理系统后端,安装

1
2
// 解决跨域问题的koa包
npm i koa2-cors

app.js

1
2
3
4
5
6
7
//处理跨域
app.use(
cors({
origin: ["http://localhost:9528"], // 允许访问本服务的域
credentials: true,
})
);

云数据库的增删改查接口

数据库查询记录

后端获取前端 post 请求传来的数据

get 请求可以直接通过 ctx.request.query 获取,但是 post 请求需要安装 koa-body

1
npm i koa-body

app.js

1
2
3
4
5
6
7
8
const koaBody = require("koa-body"); // 对post请求前端传来的数据的获取,需要此依赖

// 接收post参数解析
app.use(
koaBody({
multipart: true,
})
);

接口.js

1
2
3
router.post("/updatePlaylist", async (ctx, next) => {
const params = ctx.request.body; // post请求获取前端传来的数据,需安装和配置koa-body
});

后端获取云存储图片

云存储中上传图片,云数据库中新建图片的集合,并添加数据字段,字段包含云文件的 fileid。

后端项目通过调用云数据库的方式获取数据

1
2
3
4
5
6
router.get("/list", async (ctx, next) => {
// 接口中读取数据库默认最多10条数据
const query = `db.collection('swiper').get()`;
const res = await callCloudDB(ctx, "databasequery", query);
console.log(res);
});

但获取到的数据为 fileid,并不能用于显示图片,需要通过微信 HTTP API 获取云存储的接口来获取图片地址

获取云存储

后端上传图片到云存储

文件上传