前言
上一篇文章低代码平台(一)-远程组件打包(ESModule)已经可以把组件打包成可远程加载的zip包,接下来就是对组件进行管理,考虑到组件有迭代的过程,所以需要有个版本管理,后台对接的是腾讯云的云开发,腾讯云有一整套的后台服务,使用便利。
思路
把打包好的组件zip包解压上传到云端存储空间,并在数据库记录相应的组件信息(组件名/标识/缩略图/分类)和关联的版本列表
技术栈
- vue3 + ts 项目基础框架
- elementplus ui框架
- jszip 前端zip解压插件
- 腾讯云 提供后台能力(数据库/云存储)
添加分类
添加组件的时候关联分类,便于后面组件的使用。
组件分类集合assembly_classify
- name 分类名称
添加组件
组件集合assembly_sort
- classify_id 分类集合id
- icon 组件缩略图
- name 组件名称
- name_es 组件标识,有唯一性,添加时需校验
- version 当前最新版本,上传/删除版本的时候更新为最新的版本号
校验组件标识
js
// 查询集合assembly_sort是否村在name_es标识的记录
/**
**name_es 组件标识
**/
const isExistName_es = async (name_es) => {
const res = await db.collection('assembly_sort')
.where({
name_es
}).get()
return res.data.length > 0
}
添加版本
版本集合assembly
- assembly_sort_id 组件集合id window.JSZip.loadAsync(evt.raw) {
}
- createTime 创建时间,用于排序
- version 版本号,新的版本号必须大于已有的版本,如此保证了版本的顺序从大到小
判断版本是否已存在
js
/**
**assembly_sort_id 组件集合id
**version 版本号
**/
const isExistVersion = (assembly_sort_id, version) => {
const res = await db.collection('assembly')
.where({
assembly_sort_id,
version
}).get()
return res.data.length > 0
}
上传文件到云空间
js
/**
**dir 文件路径
**file 文件
**/
const uploadFile = (dir, file) => {
return app.uploadFile({
// 云存储的路径
cloudPath: dir,
// 需要上传的文件,File 类型
filePath: file,
})
}
插入版本记录
js
/**
**data 版本信息 {verison: 'xx'}
**/
const insertAssembly = (data) => {
return db.collection('assembly').add({
...data,
createTime: Date.now()
})
}
更新组件最新版本
js
/**
**assembly_sort_id 组件集合id
**/
const updateAssembly_sort_version = (assembly_sort_id) => {
// 查询当前最新版本
const res = await db.collection('assembly')
.where({
assembly_sort_id
}).get()
// 设置最新版本
const version = res.data.length > 0 ? res.data[0].version : ''
db.collection('assembly_sort').doc(assembly_sort_id).update({
version
})
}
上传zip包
通过elementplus的el-upload组件选择zip包,在on-change回调函数读取,通过jszip插件解压,逐个文件上传到腾讯云存储。
js
// 读取版本号
const readVersion = async (content) => {
const f = new FileReader()
f.readAsText(content)
const cardJson = await new Promise((r) => {
f.onload = (e) => {
r(JSON.parse(e.target?.result))
}
})
return cardJson.version
}
const onChange = (evt) => {
window.JSZip.loadAsync(evt.raw)
.then(
async (zip) => {
const bolbArr = []
// 组件标识,点击上传版本按钮时获取
const name_es = 'xx'
// 组件id,点击上传版本按钮时获取
const assembly_sort_id = 'xx'
// 版本是否已存在
let isUpdate = false
// 遍历解压的文件
for (let key in zip.files) {
// 排除文件夹
if (zip.files[key].dir) continue
// 读取内容
const content = await zip.file(key).async('blob')
// 获取版本号
if(key === 'card.json') {
const version = await readVersion(content)
isUpdate = await isExistVersion(assembly_sort_id, version)
}
// 记录要上传的文件和路径
// 云端路径格式 环境id/cards/组件标识/版本号/组件文件
bolbArr.push({
dir: `cards/${name_es}/${version}/${key}`,
version,
file: new File([content], name_es, { type: content.type }),
})
}
// 上传文件
let count = 0
const l = bolbArr.length
bolbArr.forEach(item => {
uploadFile(item.dir, item.file).then(async () => {
count++
if (count === l) {
// 上传结束
if (!isUpdate) {
// 新增版本
await insertAssembly({
assembly_sort_id,
version: item.version,
})
// 更新最新版本
await updateAssembly_sort_version(assembly_sort_id)
}
}
})
})
}
)
}
删除版本
删除版本的时候,删除数据库的同时要把云空间相关的文件删除,删除文件的操作通过云函数实现。
批量删除数据库记录
js
/**
assembly_sort_id 组件集合id
versionArr 版本数组 ['1.0.0', '1.0.1']
*/
const delAssembly = (assembly_sort_id, versionArr) => {
await db.collection('assembly').where({
assembly_sort_id,
version: db.command.in(versionArr)
}).remove()
}
批量删除文件夹(云函数)
js
'use strict';
const CloudBase = require("@cloudbase/manager-node");
const { storage } = new CloudBase({
secretId: "xxx",
secretKey: "xxx",
envId: "xxx" // 云开发环境ID,可在腾讯云云开发控制台获取
});
async function deleteDirectory(dir) {
await storage.deleteDirectory(dir);
}
exports.main = async (event, context) => {
const {dir = []} = event
for(let i=0; i<dir.length; i++) {
await deleteDirectory(dir[i])
}
return {
code: 200,
msg: 'success'
}
};