mirror of
https://github.com/flipped-aurora/gin-vue-admin.git
synced 2026-09-25 05:50:19 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5efcd251a | ||
|
|
b74ea58172 | ||
|
|
707dbac2ca | ||
|
|
184b1a903f | ||
|
|
4a995a1c56 | ||
|
|
e6768d5e17 | ||
|
|
e3057c4bd9 | ||
|
|
87f101a7bf | ||
|
|
ab435d131c | ||
|
|
674ae4c4a0 | ||
|
|
f3a84e2ca8 | ||
|
|
835dd15c47 | ||
|
|
c983370162 | ||
|
|
00b5024f20 | ||
|
|
ae0af55d17 | ||
|
|
f19b398c93 | ||
|
|
8743b63869 | ||
|
|
4af1627116 | ||
|
|
5d4c4d53fc | ||
|
|
62bc8092e2 | ||
|
|
4cea6f9f5d | ||
|
|
decee13bf1 | ||
|
|
60bfe48307 | ||
|
|
bca54282c9 | ||
|
|
db933cecb6 | ||
|
|
3f06c8ba7d | ||
|
|
f7fb34ec16 | ||
|
|
b691d53523 | ||
|
|
5396aa40cb | ||
|
|
1a43b89674 | ||
|
|
fb570acf7c | ||
|
|
8c5d0ad64b | ||
|
|
74a92b08d8 | ||
|
|
3e6a3d97bb | ||
|
|
b3e4666108 | ||
|
|
a344f2bdb7 | ||
|
|
4b6eb80ddb | ||
|
|
5226a2a26f | ||
|
|
e8bb532cdc | ||
|
|
171be652eb | ||
|
|
c410125c8f | ||
|
|
0f6613c4a1 | ||
|
|
d278344dd4 | ||
|
|
c47b3eee2c | ||
|
|
162b8df569 | ||
|
|
55e2109091 | ||
|
|
11efbe7699 | ||
|
|
329d094e2a | ||
|
|
414766001b | ||
|
|
e05e16dce4 | ||
|
|
3549f4cf1f | ||
|
|
bedbd3c872 | ||
|
|
296110f969 | ||
|
|
f60b0f1750 | ||
|
|
6ad13c5930 | ||
|
|
6a1b53e3d4 | ||
|
|
21ef7bdcc0 | ||
|
|
718574cdf3 | ||
|
|
18571ca224 | ||
|
|
41c164a8ef | ||
|
|
f82acdb478 | ||
|
|
40b56b6bf5 | ||
|
|
f259d69910 | ||
|
|
3952d5ec14 | ||
|
|
c1745f6f40 | ||
|
|
0940a70d86 | ||
|
|
7abe6987a5 | ||
|
|
7baa2c84a3 | ||
|
|
6867eb2c05 | ||
|
|
3d01706fb6 | ||
|
|
7707d4c99d | ||
|
|
b66d7a4e7a | ||
|
|
8a67795faf | ||
|
|
64299e6912 | ||
|
|
fdd522e56a | ||
|
|
1c257fa830 | ||
|
|
3d9fbbac63 | ||
|
|
f83332b2c8 | ||
|
|
b8d187bb35 | ||
|
|
9567564bf4 | ||
|
|
d05bf07db8 | ||
|
|
5adb89694b | ||
|
|
e21146d048 | ||
|
|
4c7f04536d | ||
|
|
71d0883c3d | ||
|
|
ee9022f9e3 | ||
|
|
cc0a894162 | ||
|
|
d27f2ec966 | ||
|
|
83b7927c4b | ||
|
|
e1975682a9 | ||
|
|
f914f96b9a | ||
|
|
35a21d4e24 | ||
|
|
3e58190112 | ||
|
|
39150b2b2b | ||
|
|
f2b287f933 | ||
|
|
e458e583ee | ||
|
|
74c1fd5b7d | ||
|
|
2547ba88ae | ||
|
|
5c78ecc2d3 | ||
|
|
9c934917d0 | ||
|
|
1132723355 | ||
|
|
26261001f5 | ||
|
|
2e3a1582ab | ||
|
|
5d1bcb3575 | ||
|
|
6c7d49b323 | ||
|
|
843a585b7f | ||
|
|
8df6fa6a33 | ||
|
|
9ccb5439df | ||
|
|
928d816c68 | ||
|
|
27df9862ea | ||
|
|
d428ed6876 | ||
|
|
72fd7beec0 | ||
|
|
7613b85271 | ||
|
|
23eac98551 | ||
|
|
8bd245b1f1 | ||
|
|
b13bbfced1 | ||
|
|
645c788512 | ||
|
|
9f6c8f5e22 | ||
|
|
9a4667fa46 | ||
|
|
338d81e101 | ||
|
|
336d7473f7 | ||
|
|
265cd4d885 | ||
|
|
cab8de721f | ||
|
|
4030cd325c | ||
|
|
d796a39aa7 | ||
|
|
04d8303f28 | ||
|
|
5eec28a964 | ||
|
|
a5e5c588ba | ||
|
|
34e6ccc6e2 | ||
|
|
6a028e13cb | ||
|
|
176e9d09b6 | ||
|
|
7ddcf97efd | ||
|
|
e19bda949b | ||
|
|
b09d142091 | ||
|
|
e102f820c1 | ||
|
|
36627e4ca5 | ||
|
|
9c6e6ca1b2 | ||
|
|
f32fdbf543 | ||
|
|
7342788339 | ||
|
|
15d6ff0144 | ||
|
|
9718b16e39 | ||
|
|
e80842207f | ||
|
|
58585afdf6 | ||
|
|
a3eee91cef | ||
|
|
9098eaf22e | ||
|
|
2d3b039f71 | ||
|
|
864c468440 | ||
|
|
cc295fad32 | ||
|
|
b4e0dc800d | ||
|
|
5e7078e3a6 | ||
|
|
2829d7b653 | ||
|
|
ba834592a7 | ||
|
|
1607e6a0a9 | ||
|
|
f936029d59 | ||
|
|
9f1552f508 | ||
|
|
c00d465709 | ||
|
|
c2a55931bb | ||
|
|
e957e5ebc9 | ||
|
|
1357e22330 | ||
|
|
8a282cd743 | ||
|
|
6ca7f62ce6 | ||
|
|
6ee7ad8069 | ||
|
|
307b1bf496 | ||
|
|
61f50980e1 | ||
|
|
5293222ac0 | ||
|
|
411a21d0f7 | ||
|
|
8a5d788e73 | ||
|
|
3e48fa55c7 | ||
|
|
cd735e727e | ||
|
|
1eb69c696a | ||
|
|
8208ccf5a3 | ||
|
|
1591944756 | ||
|
|
8e87ae55a9 | ||
|
|
1ddd6dac4f | ||
|
|
a487266f5b | ||
|
|
0286d56e9c | ||
|
|
5bb840c1ce | ||
|
|
8f221b6b0b | ||
|
|
ac4398873b | ||
|
|
2fad9035d3 | ||
|
|
4863b2c5be | ||
|
|
86afc0ddf4 | ||
|
|
f4709f00ab | ||
|
|
b12bbc74ff | ||
|
|
d3dbca0e00 | ||
|
|
4828dc3dae | ||
|
|
8413f0e8d3 | ||
|
|
5bfc5563b3 | ||
|
|
d6bc0572c2 | ||
|
|
32abd69c16 | ||
|
|
02f155f497 | ||
|
|
c570c095b9 | ||
|
|
0e1a820c3a | ||
|
|
bf21fec50e | ||
|
|
4e514dc83e | ||
|
|
3f52783b30 | ||
|
|
16bab848e1 | ||
|
|
b710f6a5df | ||
|
|
840723c592 | ||
|
|
6f63290e74 | ||
|
|
10b009bb7e | ||
|
|
8350dfe2c9 | ||
|
|
e9c5ac6ec0 | ||
|
|
247487529b | ||
|
|
5ef5af4723 | ||
|
|
2188f79e77 | ||
|
|
dc1cc2ec10 | ||
|
|
e394a3afdf | ||
|
|
28dbad6c1f | ||
|
|
84e35753cf | ||
|
|
cebb9b3002 | ||
|
|
4abcbeb420 | ||
|
|
77aea09d5f | ||
|
|
c56e0416f2 | ||
|
|
9865d53ea7 | ||
|
|
213d1a700f | ||
|
|
e18f0cae1a | ||
|
|
973da4df7e | ||
|
|
b9f7783878 |
@@ -10,6 +10,8 @@ cat>"${filename}"<<EOF
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
expires-time: 604800
|
||||
buffer-time: 86400
|
||||
|
||||
# zap logger configuration
|
||||
zap:
|
||||
@@ -65,8 +67,9 @@ mysql:
|
||||
username: 'root'
|
||||
password: 'Aa@6447985'
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: false
|
||||
log-zap: ""
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
open_collective: gin-vue-admin
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
|
||||
[English](./README-en.md) | 简体中文
|
||||
|
||||
[gitee地址](https://gitee.com/pixelmax/gin-vue-admin)|
|
||||
[github地址](https://github.com/flipped-aurora/gin-vue-admin)
|
||||
[gitee地址:https://gitee.com/pixelmax/gin-vue-admin](https://gitee.com/pixelmax/gin-vue-admin)
|
||||
|
||||
[github地址:https://github.com/flipped-aurora/gin-vue-admin](https://github.com/flipped-aurora/gin-vue-admin)
|
||||
|
||||
[vue3版本分支地址:https://github.com/flipped-aurora/gin-vue-admin/tree/vue3Develop](https://github.com/flipped-aurora/gin-vue-admin/tree/vue3Develop)
|
||||
|
||||
# 项目文档
|
||||
[在线文档](https://www.gin-vue-admin.com/) : https://www.gin-vue-admin.com/
|
||||
@@ -72,7 +75,7 @@ Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-adm
|
||||
- node版本 > v8.6.0
|
||||
- golang版本 >= v1.14
|
||||
- IDE推荐:Goland
|
||||
- gormv2版本初始化数据库可以利用批量创建功能,这里已经写好初始化代码,需要在main.go内打开 initialize.Data() 的注释即可
|
||||
- 初始化项目: 不同版本数据库初始化不通 参见https://www.gin-vue-admin.com/docs/server#1-%E5%88%9D%E5%A7%8B%E5%8C%96server%E9%A1%B9%E7%9B%AE
|
||||
- 替换掉项目中的七牛云公钥,私钥,仓名和默认url地址,以免发生测试文件数据错乱
|
||||
```
|
||||
|
||||
@@ -160,6 +163,8 @@ npm run serve
|
||||
|
||||
### 2.2 server端
|
||||
|
||||
使用 goland等编辑工具,打开server目录,不可以打开 gin-vue-admin跟目录
|
||||
|
||||
```bash
|
||||
# 使用 go.mod
|
||||
|
||||
@@ -320,7 +325,6 @@ swag init
|
||||
|
||||
- [ ] 导入,导出Excel
|
||||
- [ ] Echart图表支持
|
||||
- [ ] 工作流,任务交接功能开发
|
||||
- [ ] 单独前端使用模式以及数据模拟
|
||||
|
||||
## 7. 知识库
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
.PHONY: all build run gotool clean help
|
||||
|
||||
BINARY="server"
|
||||
GVA = "gva"
|
||||
|
||||
all: check gva initdb run
|
||||
|
||||
gva:
|
||||
go build -o ${GVA} cmd/main.go
|
||||
|
||||
initdb:
|
||||
@if [ -f ${GVA} ] ; then ./gva initdb && rm ${GVA} ; fi
|
||||
|
||||
linux-build:
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
|
||||
|
||||
windows-build:
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ${BINARY}.exe
|
||||
|
||||
mac-build:
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ${BINARY}
|
||||
|
||||
run:
|
||||
@go run main.go
|
||||
|
||||
check:
|
||||
go fmt ./
|
||||
go vet ./
|
||||
|
||||
clean:
|
||||
@if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
|
||||
@if [ -f ${GVA} ] ; then rm ${GVA} ; fi
|
||||
|
||||
help:
|
||||
@echo "make - 构建gva终端工具并初始化数据,初始化数据后删除gva终端工具,启动server项目"
|
||||
@echo "make gva - 构建gva终端工具"
|
||||
@echo "make initdb - 如果有gva终端工具就初始化数据,初始化数据后删除gva终端工具,没有则不会执行"
|
||||
@echo "make linux-build - 编译 Go 代码, 生成Linux系统的二进制文件"
|
||||
@echo "make windows-build - 编译 Go 代码, 生成Windows系统的exe文件"
|
||||
@echo "make mac-build - 编译 Go 代码, 生成Mac系统的二进制文件"
|
||||
@echo "make run - 直接运行 main.go"
|
||||
@echo "make clean - 移除二进制文件"
|
||||
@echo "make check - 运行 Go 工具 'fmt' and 'vet'"
|
||||
@@ -0,0 +1,99 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// /excel/importExcel 接口,与upload接口作用类似,只是把文件存到resource/excel目录下,用于导入Excel时存放Excel文件(ExcelImport.xlsx)
|
||||
// /excel/loadExcel接口,用于读取resource/excel目录下的文件((ExcelImport.xlsx)并加载为[]model.SysBaseMenu类型的示例数据
|
||||
// /excel/exportExcel 接口,用于读取前端传来的tableData,生成Excel文件并返回
|
||||
// /excel/downloadTemplate 接口,用于下载resource/excel目录下的 ExcelTemplate.xlsx 文件,作为导入的模板
|
||||
|
||||
// @Tags excel
|
||||
// @Summary 导出Excel
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/octet-stream
|
||||
// @Param data body model.ExcelInfo true "导出Excel文件信息"
|
||||
// @Success 200
|
||||
// @Router /excel/exportExcel [post]
|
||||
func ExportExcel(c *gin.Context) {
|
||||
var excelInfo model.ExcelInfo
|
||||
_ = c.ShouldBindJSON(&excelInfo)
|
||||
filePath := global.GVA_CONFIG.Excel.Dir + excelInfo.FileName
|
||||
err := service.ParseInfoList2Excel(excelInfo.InfoList, filePath)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("转换Excel失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("转换Excel失败", c)
|
||||
return
|
||||
}
|
||||
c.Writer.Header().Add("success", "true")
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Tags excel
|
||||
// @Summary 导入Excel文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "导入Excel文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"导入成功"}"
|
||||
// @Router /excel/importExcel [post]
|
||||
func ImportExcel(c *gin.Context) {
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("接收文件失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
_ = c.SaveUploadedFile(header, global.GVA_CONFIG.Excel.Dir+"ExcelImport.xlsx")
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
|
||||
// @Tags excel
|
||||
// @Summary 加载Excel数据
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"加载数据成功"}"
|
||||
// @Router /excel/loadExcel [get]
|
||||
func LoadExcel(c *gin.Context) {
|
||||
menus, err := service.ParseExcel2InfoList()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("加载数据失败", zap.Any("err", err))
|
||||
response.FailWithMessage("加载数据失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: menus,
|
||||
Total: int64(len(menus)),
|
||||
Page: 1,
|
||||
PageSize: 999,
|
||||
}, "加载数据成功", c)
|
||||
}
|
||||
|
||||
// @Tags excel
|
||||
// @Summary 下载模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param fileName query fileName true "模板名称"
|
||||
// @Success 200
|
||||
// @Router /excel/downloadTemplate [get]
|
||||
func DownloadTemplate(c *gin.Context) {
|
||||
fileName := c.Query("fileName")
|
||||
filePath := global.GVA_CONFIG.Excel.Dir + fileName
|
||||
ok, err := utils.PathExists(filePath)
|
||||
if !ok || err != nil {
|
||||
global.GVA_LOG.Error("文件不存在", zap.Any("err", err))
|
||||
response.FailWithMessage("文件不存在", c)
|
||||
return
|
||||
}
|
||||
c.Writer.Header().Add("success", "true")
|
||||
c.File(filePath)
|
||||
}
|
||||
@@ -75,6 +75,6 @@ func GetFileList(c *gin.Context) {
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
},"获取成功", c)
|
||||
}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,44 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// @Tags AutoCode
|
||||
// @Summary 预览创建后的代码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.AutoCodeStruct true "预览创建代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/preview [post]
|
||||
func PreviewTemp(c *gin.Context) {
|
||||
var a model.AutoCodeStruct
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
if err := utils.Verify(a, utils.AutoCodeVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
autoCode, err := service.PreviewTemp(a)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("预览失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("预览失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(gin.H{"autoCode": autoCode}, "预览成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags AutoCode
|
||||
// @Summary 自动代码模板
|
||||
// @Security ApiKeyAuth
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/request"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags InitDB
|
||||
// @Summary 初始化用户数据库
|
||||
// @Produce application/json
|
||||
// @Param data body request.InitDB true "初始化数据库参数"
|
||||
// @Success 200 {string} string "{"code":0,"data":{},"msg":"自动创建数据库成功"}"
|
||||
// @Router /init/initdb [post]
|
||||
func InitDB(c *gin.Context) {
|
||||
if global.GVA_DB != nil {
|
||||
global.GVA_LOG.Error("非法访问")
|
||||
response.FailWithMessage("非法访问", c)
|
||||
return
|
||||
}
|
||||
var dbInfo request.InitDB
|
||||
if err := c.ShouldBindJSON(&dbInfo); err != nil {
|
||||
global.GVA_LOG.Error("参数校验不通过", zap.Any("err", err))
|
||||
response.FailWithMessage("参数校验不通过", c)
|
||||
return
|
||||
}
|
||||
if err := service.InitDB(dbInfo); err != nil {
|
||||
global.GVA_LOG.Error("自动创建数据库失败", zap.Any("err", err))
|
||||
response.FailWithMessage("自动创建数据库失败,请查看后台日志", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData("自动创建数据库成功", c)
|
||||
}
|
||||
|
||||
// @Tags CheckDB
|
||||
// @Summary 初始化用户数据库
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"code":0,"data":{},"msg":"探测完成"}"
|
||||
// @Router /init/checkdb [post]
|
||||
func CheckDB(c *gin.Context) {
|
||||
if global.GVA_DB != nil {
|
||||
global.GVA_LOG.Info("数据库无需初始化")
|
||||
response.OkWithDetailed(gin.H{
|
||||
"needInit": false,
|
||||
}, "数据库无需初始化", c)
|
||||
return
|
||||
} else {
|
||||
global.GVA_LOG.Info("前往初始化数据库")
|
||||
response.OkWithDetailed(gin.H{
|
||||
"needInit": true,
|
||||
}, "前往初始化数据库", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@ import (
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -42,23 +47,27 @@ func SetSystemConfig(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 本方法开发中 开发者windows系统 缺少linux系统所需的包 因此搁置
|
||||
// @Tags System
|
||||
// @Summary 重启系统
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body model.System true "重启系统"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"重启系统成功"}"
|
||||
// @Router /system/ReloadSystem [post]
|
||||
// @Success 200 {string} string "{"code":0,"data":{},"msg":"重启系统成功"}"
|
||||
// @Router /system/reloadSystem [post]
|
||||
func ReloadSystem(c *gin.Context) {
|
||||
var sys model.System
|
||||
_ = c.ShouldBindJSON(&sys)
|
||||
if err := service.SetSystemConfig(sys); err != nil {
|
||||
if runtime.GOOS == "windows" {
|
||||
response.FailWithMessage("系统不支持", c)
|
||||
return
|
||||
}
|
||||
pid := os.Getpid()
|
||||
cmd := exec.Command("kill", "-1", strconv.Itoa(pid))
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("重启系统失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("重启系统失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("重启系统成功", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("重启系统成功", c)
|
||||
return
|
||||
}
|
||||
|
||||
// @Tags System
|
||||
|
||||
@@ -50,11 +50,11 @@ func tokenNext(c *gin.Context, user model.SysUser) {
|
||||
NickName: user.NickName,
|
||||
Username: user.Username,
|
||||
AuthorityId: user.AuthorityId,
|
||||
BufferTime: 60 * 60 * 24, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
|
||||
BufferTime: global.GVA_CONFIG.JWT.BufferTime, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
NotBefore: time.Now().Unix() - 1000, // 签名生效时间
|
||||
ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 7天
|
||||
Issuer: "qmPlus", // 签名的发行者
|
||||
NotBefore: time.Now().Unix() - 1000, // 签名生效时间
|
||||
ExpiresAt: time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime, // 过期时间 7天 配置文件
|
||||
Issuer: "qmPlus", // 签名的发行者
|
||||
},
|
||||
}
|
||||
token, err := j.CreateToken(claims)
|
||||
@@ -240,7 +240,7 @@ func DeleteUser(c *gin.Context) {
|
||||
func SetUserInfo(c *gin.Context) {
|
||||
var user model.SysUser
|
||||
_ = c.ShouldBindJSON(&user)
|
||||
if err := utils.Verify(user, utils.SetUserVerify); err != nil {
|
||||
if err := utils.Verify(user, utils.IdVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// @Tags workflow
|
||||
// @Summary 注册工作流
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysWorkflow true "注册工作流接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
|
||||
// @Router /workflow/createWorkFlow [post]
|
||||
func CreateWorkFlow(c *gin.Context) {
|
||||
var wk model.SysWorkflow
|
||||
_ = c.ShouldBindJSON(&wk)
|
||||
if err := utils.Verify(wk, utils.WorkFlowVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := service.Create(wk); err != nil {
|
||||
global.GVA_LOG.Error("注册失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("注册失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("注册成功", c)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
"gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 创建WorkflowProcess
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.WorkflowProcess true "创建WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/createWorkflowProcess [post]
|
||||
func CreateWorkflowProcess(c *gin.Context) {
|
||||
var workflowProcess model.WorkflowProcess
|
||||
_ = c.ShouldBindJSON(&workflowProcess)
|
||||
err := service.CreateWorkflowProcess(workflowProcess)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 删除WorkflowProcess
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.WorkflowProcess true "删除WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /workflowProcess/deleteWorkflowProcess [delete]
|
||||
func DeleteWorkflowProcess(c *gin.Context) {
|
||||
var workflowProcess model.WorkflowProcess
|
||||
_ = c.ShouldBindJSON(&workflowProcess)
|
||||
err := service.DeleteWorkflowProcess(workflowProcess)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 批量删除WorkflowProcess
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "批量删除WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /workflowProcess/deleteWorkflowProcessByIds [delete]
|
||||
func DeleteWorkflowProcessByIds(c *gin.Context) {
|
||||
var IDS request.IdsReq
|
||||
_ = c.ShouldBindJSON(&IDS)
|
||||
err := service.DeleteWorkflowProcessByIds(IDS)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 更新WorkflowProcess
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.WorkflowProcess true "更新WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /workflowProcess/updateWorkflowProcess [put]
|
||||
func UpdateWorkflowProcess(c *gin.Context) {
|
||||
var workflowProcess model.WorkflowProcess
|
||||
_ = c.ShouldBindJSON(&workflowProcess)
|
||||
err := service.UpdateWorkflowProcess(&workflowProcess)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 用id查询WorkflowProcess
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.WorkflowProcess true "用id查询WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /workflowProcess/findWorkflowProcess [get]
|
||||
func FindWorkflowProcess(c *gin.Context) {
|
||||
var workflowProcess model.WorkflowProcess
|
||||
_ = c.ShouldBindQuery(&workflowProcess)
|
||||
err, reworkflowProcess := service.GetWorkflowProcess(workflowProcess.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"reworkflowProcess": reworkflowProcess}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 用id查询工作流步骤
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.WorkflowProcess true "用id查询WorkflowProcess"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /workflowProcess/findWorkflowStep [get]
|
||||
func FindWorkflowStep(c *gin.Context) {
|
||||
var workflowProcess model.WorkflowProcess
|
||||
_ = c.ShouldBindQuery(&workflowProcess)
|
||||
err, workflow := service.FindWorkflowStep(workflowProcess.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"workflow": workflow}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 分页获取WorkflowProcess列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.WorkflowProcessSearch true "分页获取WorkflowProcess列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/getWorkflowProcessList [get]
|
||||
func GetWorkflowProcessList(c *gin.Context) {
|
||||
var pageInfo request.WorkflowProcessSearch
|
||||
_ = c.ShouldBindQuery(&pageInfo)
|
||||
err, list, total := service.GetWorkflowProcessInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 开启工作流
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/startWorkflow [post]
|
||||
func StartWorkflow(c *gin.Context) {
|
||||
business := c.Query("businessType")
|
||||
wfInfo := model.WorkflowBusinessStruct[business]()
|
||||
c.ShouldBindJSON(wfInfo)
|
||||
err := service.StartWorkflow(wfInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("启动成功", c)
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 提交工作流
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/completeWorkflowMove [post]
|
||||
func CompleteWorkflowMove(c *gin.Context) {
|
||||
business := c.Query("businessType")
|
||||
wfInfo := model.WorkflowBusinessStruct[business]()
|
||||
c.ShouldBindJSON(wfInfo)
|
||||
err := service.CompleteWorkflowMove(wfInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("启动成功", c)
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 我发起的工作流
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/getMyStated [get]
|
||||
func GetMyStated(c *gin.Context) {
|
||||
if claims, exists := c.Get("claims"); !exists {
|
||||
errStr := "从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件"
|
||||
global.GVA_LOG.Error(errStr)
|
||||
response.FailWithMessage(errStr, c)
|
||||
} else {
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
err, wfms := service.GetMyStated(waitUse.ID)
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
global.GVA_LOG.Error(errStr)
|
||||
response.FailWithMessage(errStr, c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{"wfms": wfms}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 我的待办
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/getMyNeed [get]
|
||||
func GetMyNeed(c *gin.Context) {
|
||||
if claims, exists := c.Get("claims"); !exists {
|
||||
errStr := "从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件"
|
||||
global.GVA_LOG.Error(errStr)
|
||||
response.FailWithMessage(errStr, c)
|
||||
} else {
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
err, wfms := service.GetMyNeed(waitUse.ID, waitUse.AuthorityId)
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
global.GVA_LOG.Error(errStr)
|
||||
response.FailWithMessage(errStr, c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{"wfms": wfms}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags WorkflowProcess
|
||||
// @Summary 根据id获取当前节点详情和历史
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "根据id获取当前节点详情和过往"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /workflowProcess/getWorkflowMoveByID [get]
|
||||
func GetWorkflowMoveByID(c *gin.Context) {
|
||||
var req request.GetById
|
||||
_ = c.ShouldBindQuery(&req)
|
||||
err, move, moves, business := service.GetWorkflowMoveByID(req.Id)
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
global.GVA_LOG.Error(errStr)
|
||||
response.FailWithMessage(errStr, c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{"move": move, "moves": moves, "business": business}, c)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitAuthorityMenu(db *gorm.DB) {
|
||||
if err := db.Exec("CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `authority_menu` AS select `sys_base_menus`.`id` AS `id`,`sys_base_menus`.`created_at` AS `created_at`, `sys_base_menus`.`updated_at` AS `updated_at`, `sys_base_menus`.`deleted_at` AS `deleted_at`, `sys_base_menus`.`menu_level` AS `menu_level`,`sys_base_menus`.`parent_id` AS `parent_id`,`sys_base_menus`.`path` AS `path`,`sys_base_menus`.`name` AS `name`,`sys_base_menus`.`hidden` AS `hidden`,`sys_base_menus`.`component` AS `component`, `sys_base_menus`.`title` AS `title`,`sys_base_menus`.`icon` AS `icon`,`sys_base_menus`.`sort` AS `sort`,`sys_authority_menus`.`sys_authority_authority_id` AS `authority_id`,`sys_authority_menus`.`sys_base_menu_id` AS `menu_id`,`sys_base_menus`.`keep_alive` AS `keep_alive`,`sys_base_menus`.`default_menu` AS `default_menu` from (`sys_authority_menus` join `sys_base_menus` on ((`sys_authority_menus`.`sys_base_menu_id` = `sys_base_menus`.`id`)))").Error; err != nil {
|
||||
color.Danger.Println("authority_menu视图已存在!")
|
||||
return
|
||||
}
|
||||
color.Info.Println("authority_menu视图创建成功!")
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Authorities = []model.SysAuthority{
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "888", AuthorityName: "普通用户", ParentId: "0"},
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "8881", AuthorityName: "普通用户子角色", ParentId: "888"},
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "9528", AuthorityName: "测试角色", ParentId: "0"},
|
||||
}
|
||||
|
||||
func InitSysAuthority(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("authority_id IN ? ", []string{"888", "9528"}).Find(&[]model.SysAuthority{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_authorities表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Authorities).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_authorities 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
)
|
||||
|
||||
type SysDataAuthorityId struct {
|
||||
SysAuthorityAuthorityId string
|
||||
DataAuthorityIdAuthorityId string
|
||||
}
|
||||
|
||||
var DataAuthorityId = []SysDataAuthorityId{
|
||||
{"888", "888"},
|
||||
{"888", "8881"},
|
||||
{"888", "9528"},
|
||||
{"9528", "8881"},
|
||||
{"9528", "9528"},
|
||||
}
|
||||
|
||||
func InitSysDataAuthorityId(db *gorm.DB) {
|
||||
if err := db.Table("sys_data_authority_id").Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("sys_authority_authority_id IN ?", []string{"888", "9528"}).Find(&[]SysDataAuthorityId{}).RowsAffected == 5 {
|
||||
color.Danger.Println("sys_data_authority_id表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&DataAuthorityId).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_data_authority_id 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
)
|
||||
|
||||
type SysAuthorityMenus struct {
|
||||
SysAuthorityAuthorityId string
|
||||
SysBaseMenuId uint
|
||||
}
|
||||
|
||||
var AuthorityMenus = []SysAuthorityMenus{
|
||||
{"888", 1},
|
||||
{"888", 2},
|
||||
{"888", 3},
|
||||
{"888", 4},
|
||||
{"888", 5},
|
||||
{"888", 6},
|
||||
{"888", 7},
|
||||
{"888", 8},
|
||||
{"888", 9},
|
||||
{"888", 10},
|
||||
{"888", 11},
|
||||
{"888", 12},
|
||||
{"888", 13},
|
||||
{"888", 14},
|
||||
{"888", 15},
|
||||
{"888", 16},
|
||||
{"888", 17},
|
||||
{"888", 18},
|
||||
{"888", 19},
|
||||
{"888", 20},
|
||||
{"888", 21},
|
||||
{"888", 22},
|
||||
{"888", 23},
|
||||
{"888", 24},
|
||||
{"888", 25},
|
||||
{"888", 26},
|
||||
{"888", 27},
|
||||
{"8881", 1},
|
||||
{"8881", 2},
|
||||
{"8881", 8},
|
||||
{"8881", 17},
|
||||
{"8881", 18},
|
||||
{"8881", 19},
|
||||
{"8881", 20},
|
||||
{"9528", 1},
|
||||
{"9528", 2},
|
||||
{"9528", 3},
|
||||
{"9528", 4},
|
||||
{"9528", 5},
|
||||
{"9528", 6},
|
||||
{"9528", 7},
|
||||
{"9528", 8},
|
||||
{"9528", 9},
|
||||
{"9528", 10},
|
||||
{"9528", 11},
|
||||
{"9528", 12},
|
||||
{"9528", 13},
|
||||
{"9528", 14},
|
||||
{"9528", 15},
|
||||
{"9528", 17},
|
||||
{"9528", 18},
|
||||
{"9528", 19},
|
||||
{"9528", 20},
|
||||
}
|
||||
|
||||
func InitSysAuthorityMenus(db *gorm.DB) {
|
||||
if err := db.Table("sys_authority_menus").Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("sys_authority_authority_id IN ?", []string{"888", "8881", "9528"}).Find(&[]SysAuthorityMenus{}).RowsAffected == 53 {
|
||||
color.Danger.Println("sys_authority_menus表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&AuthorityMenus).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_authority_menus 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Customers = []model.ExaCustomer{
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, CustomerName: "测试客户", CustomerPhoneData: "1761111111", SysUserID: 1, SysUserAuthorityID: "888"},
|
||||
}
|
||||
|
||||
func InitExaCustomer(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ? ", []int{1}).Find(&[]model.ExaCustomer{}).RowsAffected == 1 {
|
||||
color.Danger.Println("exa_customers表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Customers).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> exa_customers 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package datas
|
||||
|
||||
import (
|
||||
"gin-vue-admin/model"
|
||||
gormadapter "github.com/casbin/gorm-adapter/v3"
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
)
|
||||
|
||||
func InitMysqlData(db *gorm.DB) {
|
||||
InitSysApi(db)
|
||||
InitSysUser(db)
|
||||
InitExaCustomer(db)
|
||||
InitCasbinModel(db)
|
||||
InitSysAuthority(db)
|
||||
InitSysBaseMenus(db)
|
||||
InitAuthorityMenu(db)
|
||||
InitSysDictionary(db)
|
||||
InitSysAuthorityMenus(db)
|
||||
InitSysDataAuthorityId(db)
|
||||
InitSysDictionaryDetail(db)
|
||||
InitExaFileUploadAndDownload(db)
|
||||
}
|
||||
|
||||
func InitMysqlTables(db *gorm.DB) {
|
||||
var err error
|
||||
if !db.Migrator().HasTable("casbin_rule") {
|
||||
err = db.Migrator().CreateTable(&gormadapter.CasbinRule{})
|
||||
}
|
||||
err = db.AutoMigrate(
|
||||
model.SysApi{},
|
||||
model.SysUser{},
|
||||
model.ExaFile{},
|
||||
model.ExaCustomer{},
|
||||
model.SysBaseMenu{},
|
||||
model.SysWorkflow{},
|
||||
model.SysAuthority{},
|
||||
model.JwtBlacklist{},
|
||||
model.ExaFileChunk{},
|
||||
model.SysDictionary{},
|
||||
model.ExaSimpleUploader{},
|
||||
model.SysOperationRecord{},
|
||||
model.SysWorkflowStepInfo{},
|
||||
model.SysDictionaryDetail{},
|
||||
model.SysBaseMenuParameter{},
|
||||
model.ExaFileUploadAndDownload{},
|
||||
)
|
||||
if err != nil {
|
||||
color.Warn.Printf("[Mysql]-->初始化数据表失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
color.Info.Println("[Mysql]-->初始化数据表成功")
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020 SliverHorn
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package gva
|
||||
|
||||
import (
|
||||
"gin-vue-admin/cmd/datas"
|
||||
"gin-vue-admin/core"
|
||||
"gin-vue-admin/initialize"
|
||||
|
||||
"github.com/gookit/color"
|
||||
|
||||
_ "gin-vue-admin/core"
|
||||
"gin-vue-admin/global"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// initdbCmd represents the initdb command
|
||||
var initdbCmd = &cobra.Command{
|
||||
Use: "initdb",
|
||||
Short: "gin-vue-admin初始化数据",
|
||||
Long: `gin-vue-admin初始化数据适配数据库情况:
|
||||
1. mysql完美适配,
|
||||
2. postgresql不能保证完美适配,
|
||||
3. sqlite未适配,
|
||||
4. sqlserver未适配`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
path, _ := cmd.Flags().GetString("path")
|
||||
global.GVA_VP = core.Viper(path)
|
||||
global.GVA_LOG = core.Zap() // 初始化zap日志库
|
||||
db := initialize.GormMysql()
|
||||
switch global.GVA_CONFIG.System.DbType {
|
||||
case "mysql":
|
||||
datas.InitMysqlTables(db)
|
||||
datas.InitMysqlData(db)
|
||||
case "postgresql":
|
||||
color.Info.Println("postgresql功能开发中")
|
||||
case "sqlite":
|
||||
color.Info.Println("sqlite功能开发中")
|
||||
case "sqlserver":
|
||||
color.Info.Println("sqlserver功能开发中")
|
||||
default:
|
||||
datas.InitMysqlTables(db)
|
||||
datas.InitMysqlData(db)
|
||||
}
|
||||
frame, _ := cmd.Flags().GetString("frame")
|
||||
if frame == "gf" {
|
||||
color.Info.Println("gf功能开发中")
|
||||
return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(initdbCmd)
|
||||
initdbCmd.Flags().StringP("path", "p", "./config.yaml", "自定配置文件路径(绝对路径)")
|
||||
initdbCmd.Flags().StringP("frame", "f", "gin", "可选参数为gin,gf")
|
||||
initdbCmd.Flags().StringP("type", "t", "mysql", "可选参数为mysql,postgresql,sqlite,sqlserver")
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020 SliverHorn
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package gva
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"os"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "gva",
|
||||
Short: "这是一款amazing的终端工具",
|
||||
Long: `欢迎使用gva终端工具
|
||||
________ ____ ____ _____
|
||||
/ _____/ \ \ / / / _ \
|
||||
/ \ ___ \ Y / / /_\ \
|
||||
\ \_\ \ \ / / | \
|
||||
\______ / \___/ \____|__ /
|
||||
\/ \/
|
||||
`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
color.Warn.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.gva.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
func initConfig() {
|
||||
if cfgFile != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
// Find home directory.
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
color.Warn.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Search config in home directory with name ".gva" (without extension).
|
||||
viper.AddConfigPath(home)
|
||||
viper.SetConfigName(".gva")
|
||||
}
|
||||
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
color.Warn.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package gva
|
||||
|
||||
import (
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
// runCmd represents the run command
|
||||
var runCmd = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "running go codes with hot-compiled-like feature",
|
||||
Long: `
|
||||
The "run" command is used for running go codes with hot-compiled-like feature,
|
||||
which compiles and runs the go codes asynchronously when codes change.
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
w := utils.NewWatch()
|
||||
t := utils.NewT()
|
||||
path, _ := os.Getwd()
|
||||
go w.Watch(path, t)
|
||||
t.RunTask()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(runCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// runCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// runCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020 SliverHorn
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package gva
|
||||
|
||||
import (
|
||||
"github.com/gookit/color"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "版本信息",
|
||||
Long: `版本的长信息`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
color.Green.Println("v0.0.3")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020 SliverHorn
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package main
|
||||
|
||||
import "gin-vue-admin/cmd/gva"
|
||||
|
||||
func main() {
|
||||
gva.Execute()
|
||||
}
|
||||
+32
-7
@@ -3,6 +3,8 @@
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
expires-time: 604800
|
||||
buffer-time: 86400
|
||||
|
||||
# zap logger configuration
|
||||
zap:
|
||||
@@ -41,7 +43,7 @@ system:
|
||||
env: 'public' # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: 'mysql'
|
||||
oss-type: 'local'
|
||||
oss-type: 'local' # 控制oss选择走本期还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-multipoint: false
|
||||
|
||||
# captcha configuration
|
||||
@@ -52,14 +54,15 @@ captcha:
|
||||
|
||||
# mysql connect configuration
|
||||
mysql:
|
||||
path: '127.0.0.1:3306'
|
||||
config: 'charset=utf8mb4&parseTime=True&loc=Local'
|
||||
db-name: 'qmPlus'
|
||||
username: 'root'
|
||||
password: 'Aa@6447985'
|
||||
path: ''
|
||||
config: ''
|
||||
db-name: ''
|
||||
username: ''
|
||||
password: ''
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: false
|
||||
log-zap: ""
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
@@ -73,4 +76,26 @@ qiniu:
|
||||
use-https: false
|
||||
access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
|
||||
secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
|
||||
use-cdn-domains: false
|
||||
use-cdn-domains: false
|
||||
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: 'yourEndpoint'
|
||||
access-key-id: 'yourAccessKeyId'
|
||||
access-key-secret: 'yourAccessKeySecret'
|
||||
bucket-name: 'yourBucketName'
|
||||
bucket-url: 'yourBucketUrl'
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: 'xxxxx-10005608'
|
||||
region: 'ap-shanghai'
|
||||
secret-id: 'xxxxxxxx'
|
||||
secret-key: 'xxxxxxxx'
|
||||
base-url: 'https://gin.vue.admin'
|
||||
path-prefix: 'gin-vue-admin'
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: './resource/excel/'
|
||||
@@ -9,8 +9,11 @@ type Server struct {
|
||||
System System `mapstructure:"system" json:"system" yaml:"system"`
|
||||
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
|
||||
// gorm
|
||||
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
|
||||
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
|
||||
// oss
|
||||
Local Local `mapstructure:"local" json:"local" yaml:"local"`
|
||||
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
|
||||
Local Local `mapstructure:"local" json:"local" yaml:"local"`
|
||||
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
|
||||
AliyunOSS AliyunOSS `mapstructure:"aliyun-oss" json:"aliyunOSS" yaml:"aliyun-oss"`
|
||||
TencentCOS TencentCOS `mapstructure:"tencent-cos" json:"tencentCOS" yaml:"tencent-cos"`
|
||||
Excel Excel `mapstructure:"excel" json:"excel" yaml:"excel"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
type Excel struct {
|
||||
Dir string `mapstructure:"dir" json:"dir" yaml:"dir"`
|
||||
}
|
||||
@@ -9,4 +9,9 @@ type Mysql struct {
|
||||
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
|
||||
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
|
||||
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
|
||||
LogZap string `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"`
|
||||
}
|
||||
|
||||
func (m *Mysql) Dsn() string {
|
||||
return m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package config
|
||||
|
||||
type JWT struct {
|
||||
SigningKey string `mapstructure:"signing-key" json:"signingKey" yaml:"signing-key"`
|
||||
SigningKey string `mapstructure:"signing-key" json:"signingKey" yaml:"signing-key"`
|
||||
ExpiresTime int64 `mapstructure:"expires-time" json:"expiresTime" yaml:"expires-time"`
|
||||
BufferTime int64 `mapstructure:"buffer-time" json:"bufferTime" yaml:"buffer-time"`
|
||||
}
|
||||
|
||||
@@ -13,3 +13,19 @@ type Qiniu struct {
|
||||
SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`
|
||||
UseCdnDomains bool `mapstructure:"use-cdn-domains" json:"useCdnDomains" yaml:"use-cdn-domains"`
|
||||
}
|
||||
|
||||
type AliyunOSS struct {
|
||||
Endpoint string `mapstructure:"endpoint" json:"endpoint" yaml:"endpoint"`
|
||||
AccessKeyId string `mapstructure:"access-key-id" json:"accessKeyId" yaml:"access-key-id"`
|
||||
AccessKeySecret string `mapstructure:"access-key-secret" json:"accessKeySecret" yaml:"access-key-secret"`
|
||||
BucketName string `mapstructure:"bucket-name" json:"bucketName" yaml:"bucket-name"`
|
||||
BucketUrl string `mapstructure:"bucket-url" json:"bucketUrl" yaml:"bucket-url"`
|
||||
}
|
||||
type TencentCOS struct {
|
||||
Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"`
|
||||
Region string `mapstructure:"region" json:"region" yaml:"region"`
|
||||
SecretID string `mapstructure:"secret-id" json:"secretID" yaml:"secret-id"`
|
||||
SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`
|
||||
BaseURL string `mapstructure:"base-url" json:"baseURL" yaml:"base-url"`
|
||||
PathPrefix string `mapstructure:"path-prefix" json:"pathPrefix" yaml:"path-prefix"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package constant
|
||||
|
||||
//定义clazz常量
|
||||
|
||||
const (
|
||||
USER_TASK string = "userTask" // 审批节点
|
||||
//SCRIPT_TASK string = "scriptTask" //脚本节点
|
||||
//RECEIVE_TASK string = "receiveTask"
|
||||
//MAIL_TASK string = "mailTask" //邮件节点
|
||||
//TIMER_START string = "timerStart" // 定时节点
|
||||
//MESSAGE_START string = "messageStart" // 消息节点
|
||||
EXCLUSIVE_GATEWAY string = "exclusiveGateway" // 排他网关
|
||||
INCLUSIVE_GATEWAY string = "inclusiveGateway" // 包容网关
|
||||
PARELLEL_GATEWAY string = "parallelGateway" // 并行网关
|
||||
FLOW string = "flow" // 连线
|
||||
START string = "start" // 开始节点
|
||||
END string = "end" // 结束节点
|
||||
//PROCESS string = "process" // 基础节点
|
||||
)
|
||||
@@ -17,6 +17,7 @@ func RunWindowsServer() {
|
||||
// 初始化redis服务
|
||||
initialize.Redis()
|
||||
}
|
||||
initialize.InitWkMode()
|
||||
Router := initialize.Routers()
|
||||
Router.Static("/form-generator", "./resource/page")
|
||||
|
||||
@@ -29,7 +30,8 @@ func RunWindowsServer() {
|
||||
|
||||
fmt.Printf(`
|
||||
欢迎使用 Gin-Vue-Admin
|
||||
当前版本:V2.3.7
|
||||
当前版本:V2.4.0
|
||||
加群方式:微信号:shouzi_1994 QQ群:622360840
|
||||
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
|
||||
默认前端文件运行地址:http://127.0.0.1:8080
|
||||
如果项目让您获得了收益,希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/docs/coffee
|
||||
|
||||
+9
-6
@@ -3,8 +3,11 @@ module gin-vue-admin
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.2
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/casbin/casbin v1.9.1
|
||||
github.com/casbin/casbin/v2 v2.11.0
|
||||
github.com/casbin/gorm-adapter/v3 v3.0.2
|
||||
@@ -33,10 +36,10 @@ require (
|
||||
github.com/onsi/ginkgo v1.7.0 // indirect
|
||||
github.com/onsi/gomega v1.4.3 // indirect
|
||||
github.com/pelletier/go-toml v1.6.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/qiniu/api.v7/v7 v7.4.1
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/shirou/gopsutil v2.20.8+incompatible
|
||||
github.com/shirou/gopsutil v3.21.1+incompatible
|
||||
github.com/spf13/afero v1.2.2 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/cobra v1.1.1
|
||||
@@ -45,16 +48,16 @@ require (
|
||||
github.com/swaggo/gin-swagger v1.2.0
|
||||
github.com/swaggo/swag v1.6.7
|
||||
github.com/tebeka/strftime v0.1.3 // indirect
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.19
|
||||
github.com/unrolled/secure v1.0.7
|
||||
go.uber.org/zap v1.10.0
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
|
||||
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
||||
golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect
|
||||
google.golang.org/protobuf v1.24.0 // indirect
|
||||
gopkg.in/ini.v1 v1.55.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
gorm.io/driver/mysql v0.3.0
|
||||
gorm.io/gorm v1.20.5
|
||||
gorm.io/gorm v1.20.9
|
||||
)
|
||||
|
||||
replace github.com/casbin/gorm-adapter/v3 => github.com/casbin/gorm-adapter/v3 v3.0.2
|
||||
replace github.com/casbin/gorm-adapter/v3 => github.com/casbin/gorm-adapter/v3 v3.0.2
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
@echo ##########Formatting code#########################################
|
||||
go fmt ./ && go vet ./
|
||||
@echo ##########Format the code successfully############################
|
||||
@echo ##########Compiling gva.exe#######################################
|
||||
go build -o gva.exe cmd/main.go
|
||||
@echo ##########Successfully compiled gva.exe###########################
|
||||
@echo ##########Initializing data using gva.exe#########################
|
||||
gva.exe initdb
|
||||
@echo ##########Use gva.exe to initialize data successfully#############
|
||||
@echo ##########Deleting gva.exe########################################
|
||||
del gva.exe
|
||||
@echo ##########Deleting gva.exe successfully###########################
|
||||
+58
-19
@@ -2,15 +2,21 @@ package initialize
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/initialize/internal"
|
||||
"gin-vue-admin/model"
|
||||
"os"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Gorm 初始化数据库并产生数据库全局变量
|
||||
//@author: SliverHorn
|
||||
//@function: Gorm
|
||||
//@description: 初始化数据库并产生数据库全局变量
|
||||
//@return: *gorm.DB
|
||||
|
||||
func Gorm() *gorm.DB {
|
||||
switch global.GVA_CONFIG.System.DbType {
|
||||
case "mysql":
|
||||
@@ -20,7 +26,12 @@ func Gorm() *gorm.DB {
|
||||
}
|
||||
}
|
||||
|
||||
// MysqlTables 注册数据库表专用
|
||||
// MysqlTables
|
||||
//@author: SliverHorn
|
||||
//@function: MysqlTables
|
||||
//@description: 注册数据库表专用
|
||||
//@param: db *gorm.DB
|
||||
|
||||
func MysqlTables(db *gorm.DB) {
|
||||
err := db.AutoMigrate(
|
||||
model.SysUser{},
|
||||
@@ -29,8 +40,6 @@ func MysqlTables(db *gorm.DB) {
|
||||
model.SysBaseMenu{},
|
||||
model.SysBaseMenuParameter{},
|
||||
model.JwtBlacklist{},
|
||||
model.SysWorkflow{},
|
||||
model.SysWorkflowStepInfo{},
|
||||
model.SysDictionary{},
|
||||
model.SysDictionaryDetail{},
|
||||
model.ExaFileUploadAndDownload{},
|
||||
@@ -39,6 +48,13 @@ func MysqlTables(db *gorm.DB) {
|
||||
model.ExaSimpleUploader{},
|
||||
model.ExaCustomer{},
|
||||
model.SysOperationRecord{},
|
||||
model.WorkflowProcess{},
|
||||
model.WorkflowNode{},
|
||||
model.WorkflowEdge{},
|
||||
model.WorkflowStartPoint{},
|
||||
model.WorkflowEndPoint{},
|
||||
model.WorkflowMove{},
|
||||
model.ExaWfLeave{},
|
||||
)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("register table failed", zap.Any("err", err))
|
||||
@@ -47,9 +63,17 @@ func MysqlTables(db *gorm.DB) {
|
||||
global.GVA_LOG.Info("register table success")
|
||||
}
|
||||
|
||||
// GormMysql 初始化Mysql数据库
|
||||
//
|
||||
//@author: SliverHorn
|
||||
//@function: GormMysql
|
||||
//@description: 初始化Mysql数据库
|
||||
//@return: *gorm.DB
|
||||
|
||||
func GormMysql() *gorm.DB {
|
||||
m := global.GVA_CONFIG.Mysql
|
||||
if m.Dbname == "" {
|
||||
return nil
|
||||
}
|
||||
dsn := m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config
|
||||
mysqlConfig := mysql.Config{
|
||||
DSN: dsn, // DSN data source name
|
||||
@@ -60,8 +84,9 @@ func GormMysql() *gorm.DB {
|
||||
SkipInitializeWithVersion: false, // 根据版本自动配置
|
||||
}
|
||||
if db, err := gorm.Open(mysql.New(mysqlConfig), gormConfig(m.LogMode)); err != nil {
|
||||
global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err))
|
||||
os.Exit(0)
|
||||
//global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err))
|
||||
//os.Exit(0)
|
||||
//return nil
|
||||
return nil
|
||||
} else {
|
||||
sqlDB, _ := db.DB()
|
||||
@@ -71,17 +96,31 @@ func GormMysql() *gorm.DB {
|
||||
}
|
||||
}
|
||||
|
||||
// gormConfig 根据配置决定是否开启日志
|
||||
//@author: SliverHorn
|
||||
//@function: gormConfig
|
||||
//@description: 根据配置决定是否开启日志
|
||||
//@param: mod bool
|
||||
//@return: *gorm.Config
|
||||
|
||||
func gormConfig(mod bool) *gorm.Config {
|
||||
if mod {
|
||||
return &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
}
|
||||
} else {
|
||||
return &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
var config = &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}
|
||||
switch global.GVA_CONFIG.Mysql.LogZap {
|
||||
case "silent", "Silent":
|
||||
config.Logger = internal.Default.LogMode(logger.Silent)
|
||||
case "error", "Error":
|
||||
config.Logger = internal.Default.LogMode(logger.Error)
|
||||
case "warn", "Warn":
|
||||
config.Logger = internal.Default.LogMode(logger.Warn)
|
||||
case "info", "Info":
|
||||
config.Logger = internal.Default.LogMode(logger.Info)
|
||||
case "zap", "Zap":
|
||||
config.Logger = internal.Default.LogMode(logger.Info)
|
||||
default:
|
||||
if mod {
|
||||
config.Logger = internal.Default.LogMode(logger.Info)
|
||||
break
|
||||
}
|
||||
config.Logger = internal.Default.LogMode(logger.Silent)
|
||||
}
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/utils"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// writer log writer interface
|
||||
type writer interface {
|
||||
Printf(string, ...interface{})
|
||||
}
|
||||
|
||||
type config struct {
|
||||
SlowThreshold time.Duration
|
||||
Colorful bool
|
||||
LogLevel logger.LogLevel
|
||||
}
|
||||
|
||||
var (
|
||||
Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), config{})
|
||||
Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), config{
|
||||
SlowThreshold: 200 * time.Millisecond,
|
||||
LogLevel: logger.Warn,
|
||||
Colorful: true,
|
||||
})
|
||||
Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()}
|
||||
)
|
||||
|
||||
func New(writer writer, config config) logger.Interface {
|
||||
var (
|
||||
infoStr = "%s\n[info] "
|
||||
warnStr = "%s\n[warn] "
|
||||
errStr = "%s\n[error] "
|
||||
traceStr = "%s\n[%.3fms] [rows:%v] %s"
|
||||
traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
|
||||
traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
|
||||
)
|
||||
|
||||
if config.Colorful {
|
||||
infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset
|
||||
warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset
|
||||
errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset
|
||||
traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
|
||||
traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset
|
||||
traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
|
||||
}
|
||||
|
||||
return &customLogger{
|
||||
writer: writer,
|
||||
config: config,
|
||||
infoStr: infoStr,
|
||||
warnStr: warnStr,
|
||||
errStr: errStr,
|
||||
traceStr: traceStr,
|
||||
traceWarnStr: traceWarnStr,
|
||||
traceErrStr: traceErrStr,
|
||||
}
|
||||
}
|
||||
|
||||
type customLogger struct {
|
||||
writer
|
||||
config
|
||||
infoStr, warnStr, errStr string
|
||||
traceStr, traceErrStr, traceWarnStr string
|
||||
}
|
||||
|
||||
// LogMode log mode
|
||||
func (c *customLogger) LogMode(level logger.LogLevel) logger.Interface {
|
||||
newLogger := *c
|
||||
newLogger.LogLevel = level
|
||||
return &newLogger
|
||||
}
|
||||
|
||||
// Info print info
|
||||
func (c *customLogger) Info(ctx context.Context, message string, data ...interface{}) {
|
||||
if c.LogLevel >= logger.Info {
|
||||
c.Printf(c.infoStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warn print warn messages
|
||||
func (c *customLogger) Warn(ctx context.Context, message string, data ...interface{}) {
|
||||
if c.LogLevel >= logger.Warn {
|
||||
c.Printf(c.warnStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error print error messages
|
||||
func (c *customLogger) Error(ctx context.Context, message string, data ...interface{}) {
|
||||
if c.LogLevel >= logger.Error {
|
||||
c.Printf(c.errStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Trace print sql message
|
||||
func (c *customLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||
if c.LogLevel > 0 {
|
||||
elapsed := time.Since(begin)
|
||||
switch {
|
||||
case err != nil && c.LogLevel >= logger.Error:
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
c.Printf(c.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
c.Printf(c.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case elapsed > c.SlowThreshold && c.SlowThreshold != 0 && c.LogLevel >= logger.Warn:
|
||||
sql, rows := fc()
|
||||
slowLog := fmt.Sprintf("SLOW SQL >= %v", c.SlowThreshold)
|
||||
if rows == -1 {
|
||||
c.Printf(c.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
c.Printf(c.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case c.LogLevel >= logger.Info:
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
c.Printf(c.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
c.Printf(c.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *customLogger) Printf(message string, data ...interface{}) {
|
||||
if global.GVA_CONFIG.Mysql.LogZap != "" {
|
||||
switch len(data) {
|
||||
case 0:
|
||||
global.GVA_LOG.Info(message)
|
||||
case 1:
|
||||
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]))
|
||||
case 2:
|
||||
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]))
|
||||
case 3:
|
||||
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]))
|
||||
case 4:
|
||||
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]), zap.Any("sql", data[3]))
|
||||
}
|
||||
return
|
||||
}
|
||||
switch len(data) {
|
||||
case 0:
|
||||
c.writer.Printf(message, "")
|
||||
case 1:
|
||||
c.writer.Printf(message, data[0])
|
||||
case 2:
|
||||
c.writer.Printf(message, data[0], data[1])
|
||||
case 3:
|
||||
c.writer.Printf(message, data[0], data[1], data[2])
|
||||
case 4:
|
||||
c.writer.Printf(message, data[0], data[1], data[2], data[3])
|
||||
case 5:
|
||||
c.writer.Printf(message, data[0], data[1], data[2], data[3], data[4])
|
||||
}
|
||||
}
|
||||
|
||||
type traceRecorder struct {
|
||||
logger.Interface
|
||||
BeginAt time.Time
|
||||
SQL string
|
||||
RowsAffected int64
|
||||
Err error
|
||||
}
|
||||
|
||||
func (t traceRecorder) New() *traceRecorder {
|
||||
return &traceRecorder{Interface: t.Interface, BeginAt: time.Now()}
|
||||
}
|
||||
|
||||
func (t *traceRecorder) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||
t.BeginAt = begin
|
||||
t.SQL, t.RowsAffected = fc()
|
||||
t.Err = err
|
||||
}
|
||||
@@ -5,10 +5,11 @@ import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/middleware"
|
||||
"gin-vue-admin/router"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/swaggo/gin-swagger"
|
||||
"github.com/swaggo/gin-swagger/swaggerFiles"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// 初始化总路由
|
||||
@@ -19,7 +20,7 @@ func Routers() *gin.Engine {
|
||||
// Router.Use(middleware.LoadTls()) // 打开就能玩https了
|
||||
global.GVA_LOG.Info("use middleware logger")
|
||||
// 跨域
|
||||
Router.Use(middleware.Cors())
|
||||
//Router.Use(middleware.Cors()) // 如需跨域可以打开
|
||||
global.GVA_LOG.Info("use middleware cors")
|
||||
Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
global.GVA_LOG.Info("register swagger handler")
|
||||
@@ -27,6 +28,7 @@ func Routers() *gin.Engine {
|
||||
PublicGroup := Router.Group("")
|
||||
{
|
||||
router.InitBaseRouter(PublicGroup) // 注册基础功能路由 不做鉴权
|
||||
router.InitInitRouter(PublicGroup) // 自动初始化相关
|
||||
}
|
||||
PrivateGroup := Router.Group("")
|
||||
PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
@@ -38,7 +40,6 @@ func Routers() *gin.Engine {
|
||||
router.InitEmailRouter(PrivateGroup) // 邮件相关路由
|
||||
router.InitSystemRouter(PrivateGroup) // system相关路由
|
||||
router.InitCasbinRouter(PrivateGroup) // 权限相关路由
|
||||
router.InitWorkflowRouter(PrivateGroup) // 工作流相关路由
|
||||
router.InitCustomerRouter(PrivateGroup) // 客户路由
|
||||
router.InitAutoCodeRouter(PrivateGroup) // 创建自动化代码
|
||||
router.InitAuthorityRouter(PrivateGroup) // 注册角色路由
|
||||
@@ -47,6 +48,8 @@ func Routers() *gin.Engine {
|
||||
router.InitSysOperationRecordRouter(PrivateGroup) // 操作记录
|
||||
router.InitSysDictionaryDetailRouter(PrivateGroup) // 字典详情管理
|
||||
router.InitFileUploadAndDownloadRouter(PrivateGroup) // 文件上传下载功能路由
|
||||
router.InitWorkflowProcessRouter(PrivateGroup) // 工作流相关接口
|
||||
router.InitExcelRouter(PrivateGroup) // 表格导入导出
|
||||
}
|
||||
global.GVA_LOG.Info("router register success")
|
||||
return Router
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package initialize
|
||||
|
||||
import "gin-vue-admin/model"
|
||||
|
||||
func initWorkflowModel() {
|
||||
model.WorkflowBusinessStruct = make(map[string]func() model.GVA_Workflow)
|
||||
model.WorkflowBusinessStruct["leave"] = func() model.GVA_Workflow {
|
||||
return new(model.ExaWfLeaveWorkflow)
|
||||
}
|
||||
}
|
||||
|
||||
func initWorkflowTable() {
|
||||
model.WorkflowBusinessTable = make(map[string]func() interface{})
|
||||
model.WorkflowBusinessTable["leave"] = func() interface{} {
|
||||
return new(model.ExaWfLeave)
|
||||
}
|
||||
}
|
||||
|
||||
func InitWkMode() {
|
||||
initWorkflowModel()
|
||||
initWorkflowTable()
|
||||
}
|
||||
+9
-8
@@ -14,13 +14,14 @@ import (
|
||||
// @name x-token
|
||||
// @BasePath /
|
||||
func main() {
|
||||
global.GVA_VP = core.Viper() // 初始化Viper
|
||||
global.GVA_LOG = core.Zap() // 初始化zap日志库
|
||||
global.GVA_DB = initialize.Gorm() // gorm连接数据库
|
||||
initialize.MysqlTables(global.GVA_DB) // 初始化表
|
||||
// 程序结束前关闭数据库链接
|
||||
db, _ := global.GVA_DB.DB()
|
||||
defer db.Close()
|
||||
|
||||
global.GVA_VP = core.Viper() // 初始化Viper
|
||||
global.GVA_LOG = core.Zap() // 初始化zap日志库
|
||||
global.GVA_DB = initialize.Gorm() // gorm连接数据库
|
||||
if global.GVA_DB != nil {
|
||||
initialize.MysqlTables(global.GVA_DB) // 初始化表
|
||||
// 程序结束前关闭数据库链接
|
||||
db, _ := global.GVA_DB.DB()
|
||||
defer db.Close()
|
||||
}
|
||||
core.RunWindowsServer()
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func JWTAuth() gin.HandlerFunc {
|
||||
c.Abort()
|
||||
}
|
||||
if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime {
|
||||
claims.ExpiresAt = time.Now().Unix() + 60*60*24*7
|
||||
claims.ExpiresAt = time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime
|
||||
newToken, _ := j.CreateToken(*claims)
|
||||
newClaims, _ := j.ParseToken(newToken)
|
||||
c.Header("new-token", newToken)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 处理跨域请求,支持options访问
|
||||
func NeedInit() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if global.GVA_DB == nil {
|
||||
response.OkWithDetailed(gin.H{
|
||||
"needInit": true,
|
||||
}, "前往初始化数据库", c)
|
||||
c.Abort()
|
||||
} else {
|
||||
c.Next()
|
||||
}
|
||||
// 处理请求
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
type ExcelInfo struct {
|
||||
FileName string `json:"fileName"`
|
||||
InfoList []SysBaseMenu `json:"infoList"`
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// 自动生成模板ExaWfLeave
|
||||
package model
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 如果含有time.Time 请自行import time包
|
||||
type ExaWfLeave struct {
|
||||
global.GVA_MODEL
|
||||
Cause string `json:"cause" form:"cause" gorm:"column:cause;comment:"`
|
||||
StartTime time.Time `json:"startTime" form:"startTime" gorm:"column:start_time;comment:"`
|
||||
EndTime time.Time `json:"endTime" form:"endTime" gorm:"column:end_time;comment:"`
|
||||
}
|
||||
|
||||
type ExaWfLeaveWorkflow struct {
|
||||
// 工作流操作结构体
|
||||
WorkflowBase `json:"wf"`
|
||||
ExaWfLeave `json:"business"`
|
||||
}
|
||||
|
||||
func (ExaWfLeave) TableName() string {
|
||||
return "exa_wf_leaves"
|
||||
}
|
||||
@@ -20,4 +20,4 @@ type GetAuthorityId struct {
|
||||
AuthorityId string
|
||||
}
|
||||
|
||||
type Empty struct {}
|
||||
type Empty struct{}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package request
|
||||
|
||||
type InitDB struct {
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
UserName string `json:"userName" binding:"required"`
|
||||
Password string `json:"password"`
|
||||
DBName string `json:"dbName" binding:"required"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package request
|
||||
|
||||
import "gin-vue-admin/model"
|
||||
|
||||
type WorkflowProcessSearch struct {
|
||||
model.WorkflowProcess
|
||||
PageInfo
|
||||
}
|
||||
@@ -14,4 +14,5 @@ type SysAuthority struct {
|
||||
DataAuthorityId []SysAuthority `json:"dataAuthorityId" gorm:"many2many:sys_data_authority_id"`
|
||||
Children []SysAuthority `json:"children" gorm:"-"`
|
||||
SysBaseMenus []SysBaseMenu `json:"menus" gorm:"many2many:sys_authority_menus;"`
|
||||
DefaultRouter string `json:"defaultRouter" gorm:"comment:默认菜单;default:dashboard"`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type Meta struct {
|
||||
DefaultMenu bool `json:"defaultMenu" gorm:"comment:是否是基础路由(开发中)"`
|
||||
Title string `json:"title" gorm:"comment:菜单名"`
|
||||
Icon string `json:"icon" gorm:"comment:菜单图标"`
|
||||
CloseTab bool `json:"closeTab" gorm:"comment:自动关闭tab"`
|
||||
}
|
||||
|
||||
type SysBaseMenuParameter struct {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package model
|
||||
|
||||
type InitDBFunc interface {
|
||||
Init() (err error)
|
||||
}
|
||||
+145
-15
@@ -2,24 +2,154 @@ package model
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 工作流属性表
|
||||
type SysWorkflow struct {
|
||||
global.GVA_MODEL
|
||||
WorkflowNickName string `json:"workflowNickName" gorm:"comment:工作流中文名称"` // 工作流名称
|
||||
WorkflowName string `json:"workflowName" gorm:"comment:工作流英文名称"` // 工作流英文id
|
||||
WorkflowDescription string `json:"workflowDescription" gorm:"comment:工作流描述"` // 工作流描述
|
||||
WorkflowStepInfo []SysWorkflowStepInfo `json:"workflowStep" gorm:"comment:工作流步骤"` // 工作流步骤
|
||||
var WorkflowBusinessStruct map[string]func() GVA_Workflow
|
||||
var WorkflowBusinessTable map[string]func() interface{}
|
||||
|
||||
type GVA_Workflow interface {
|
||||
CreateWorkflowMove() *WorkflowMove
|
||||
GetBusinessType() string
|
||||
GetBusinessID() uint
|
||||
GetWorkflowBase() WorkflowBase
|
||||
}
|
||||
|
||||
// 工作流状态表
|
||||
type SysWorkflowStepInfo struct {
|
||||
type WorkflowBase struct {
|
||||
WorkflowMoveID uint `json:"workflowMoveID" gorm:"-"`
|
||||
BusinessID uint `json:"businessID" gorm:"<-:false;column:id"` // 业务对应ID(businessID)的返回
|
||||
BusinessType string `json:"businessType" gorm:"-"`
|
||||
PromoterID uint `json:"promoterID" gorm:"-"`
|
||||
OperatorID uint `json:"operatorID" gorm:"-"`
|
||||
WorkflowProcessID string `json:"workflowProcessID" gorm:"-"`
|
||||
WorkflowNodeID string `json:"workflowNodeID" gorm:"-"`
|
||||
Param string `json:"param" gorm:"-"`
|
||||
Action string `json:"action" gorm:"-"`
|
||||
}
|
||||
|
||||
func (w WorkflowBase) CreateWorkflowMove() (businessModel *WorkflowMove) {
|
||||
return &WorkflowMove{
|
||||
GVA_MODEL: global.GVA_MODEL{ID: w.WorkflowMoveID},
|
||||
BusinessType: w.BusinessType,
|
||||
PromoterID: w.PromoterID,
|
||||
OperatorID: w.OperatorID,
|
||||
Param: w.Param,
|
||||
WorkflowProcessID: w.WorkflowProcessID,
|
||||
WorkflowNodeID: w.WorkflowNodeID,
|
||||
BusinessID: w.BusinessID,
|
||||
Action: w.Action,
|
||||
IsActive: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (w WorkflowBase) GetBusinessType() (businessType string) {
|
||||
return w.BusinessType
|
||||
}
|
||||
|
||||
func (w WorkflowBase) GetBusinessID() (businessID uint) {
|
||||
return w.BusinessID
|
||||
}
|
||||
|
||||
func (w WorkflowBase) GetWorkflowBase() (workflowBase WorkflowBase) {
|
||||
return w
|
||||
}
|
||||
|
||||
type WorkflowMove struct {
|
||||
global.GVA_MODEL
|
||||
SysWorkflowID uint `json:"workflowID" gorm:"comment:所属工作流ID"` // 所属工作流ID
|
||||
IsStart bool `json:"isStart" gorm:"comment:是否是开始流节点"` // 是否是开始流节点
|
||||
StepName string `json:"stepName" gorm:"comment:工作流节点名称"` // 工作流名称
|
||||
StepNo float64 `json:"stepNo" gorm:"comment:步骤id (第几步)"` // 步骤id (第几步)
|
||||
StepAuthorityID string `json:"stepAuthorityID" gorm:"comment:操作者级别id"` // 操作者级别id
|
||||
IsEnd bool `json:"isEnd" gorm:"comment:是否是完结流节点"` // 是否是完结流节点
|
||||
WorkflowProcessID string `json:"workflowProcessID" gorm:"comment:工作流模板ID"`
|
||||
WorkflowProcess WorkflowProcess `gorm:"<-:false" json:"workflowProcess" gorm:"comment:工作流模板具体信息"`
|
||||
WorkflowNodeID string `json:"workflowNodeID" gorm:"comment:工作流节点ID"`
|
||||
WorkflowNode WorkflowNode `gorm:"<-:false" json:"workflowNode" gorm:"comment:工作流节点具体信息"`
|
||||
BusinessType string `json:"businessType" gorm:"comment:业务标记"`
|
||||
BusinessID uint `json:"businessID" gorm:"comment:业务ID"`
|
||||
PromoterID uint `json:"promoterID" gorm:"comment:当前流转发起人"`
|
||||
Promoter SysUser `gorm:"<-:false" json:"promoter" gorm:"comment:当前流转发起人信息"`
|
||||
OperatorID uint `json:"operatorID" gorm:"comment:当前流转操作人"`
|
||||
Operator SysUser `gorm:"<-:false" json:"operator" gorm:"comment:当前流转操作人信息"`
|
||||
Action string `json:"action" gorm:"comment:工作流驱动事件"`
|
||||
Param string `json:"param" gorm:"comment:工作流驱动参数"`
|
||||
IsActive bool `json:"isActive" gorm:"comment:是否是活跃节点 "`
|
||||
}
|
||||
|
||||
type WorkflowProcess struct {
|
||||
ID string `json:"id" form:"id" gorm:"comment:流程标识;primaryKey;unique;not null"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
Name string `json:"name" gorm:"comment:流程名称"`
|
||||
Category string `json:"category" gorm:"comment:分类"`
|
||||
Clazz string `json:"clazz" gorm:"comment:类型"`
|
||||
Label string `json:"label" gorm:"comment:流程标题"`
|
||||
HideIcon bool `json:"hideIcon" gorm:"comment:是否隐藏图标"`
|
||||
Description string `json:"description" gorm:"comment:详细介绍"`
|
||||
View string `json:"view" gorm:"comment:前端视图文件"`
|
||||
Nodes []WorkflowNode `json:"nodes"` // 流程节点数据
|
||||
Edges []WorkflowEdge `json:"edges"` // 流程链接数据
|
||||
}
|
||||
|
||||
type WorkflowNode struct {
|
||||
ID string `json:"id" form:"id" gorm:"comment:节点id;primaryKey;unique;not null"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
WorkflowProcessID string `json:"workflowProcessID" gorm:"comment:流程标识"`
|
||||
Clazz string `json:"clazz" gorm:"comment:节点类型"`
|
||||
Label string `json:"label" gorm:"comment:节点名称"`
|
||||
Type string `json:"type" gorm:"comment:图标类型"`
|
||||
Shape string `json:"shape" gorm:"comment:形状"`
|
||||
Description string `json:"description" gorm:"comment:详细介绍"`
|
||||
View string `json:"view" gorm:"comment:前端视图文件"`
|
||||
X float64 `json:"y" gorm:"comment:x位置"`
|
||||
Y float64 `json:"x" gorm:"comment:y位置"`
|
||||
WaitState string `json:"waitState" gorm:"comment:等待属性"`
|
||||
StateValue string `json:"stateValue" gorm:"comment:等待值"`
|
||||
To string `json:"to" gorm:"comment:收件人"`
|
||||
Subject string `json:"subject" gorm:"comment:标题"`
|
||||
Content string `json:"content" gorm:"comment:内容"`
|
||||
Cycle string `json:"cycle" gorm:"comment:循环时间"`
|
||||
Duration string `json:"duration" gorm:"comment:持续时间"`
|
||||
HideIcon bool `json:"hideIcon" gorm:"comment:是否隐藏图标"`
|
||||
DueDate *time.Time `json:"dueDate" gorm:"comment:到期时间"`
|
||||
AssignType string `json:"assignType" gorm:"comment:审批类型"`
|
||||
AssignValue string `json:"assignValue" gorm:"comment:审批类型值"`
|
||||
Success bool `json:"success" gorm:"comment:是否成功"`
|
||||
}
|
||||
|
||||
type WorkflowEdge struct {
|
||||
ID string `json:"id" form:"id" gorm:"comment:唯一标识;primaryKey;unique;not null"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
WorkflowProcessID string `json:"-" gorm:"comment:流程标识"`
|
||||
Clazz string `json:"clazz" gorm:"comment:类型(线)"`
|
||||
Source string `json:"source" gorm:"comment:起点节点"`
|
||||
Target string `json:"target" gorm:"comment:目标节点"`
|
||||
SourceAnchor int `json:"sourceAnchor" gorm:"comment:起点"`
|
||||
TargetAnchor int `json:"targetAnchor" gorm:"comment:目标点"`
|
||||
Description string `json:"description" gorm:"comment:详细介绍"`
|
||||
Shape string `json:"shape" gorm:"comment:形状"`
|
||||
StartPoint WorkflowStartPoint `json:"startPoint"` // 起点信息
|
||||
EndPoint WorkflowEndPoint `json:"endPoint"` // 终点信息
|
||||
Label string `json:"label" gorm:"comment:标题"`
|
||||
HideIcon bool `json:"hideIcon" gorm:"comment:隐藏图标"`
|
||||
ConditionExpression string `json:"conditionExpression" gorm:"comment:条件标识"`
|
||||
Seq string `json:"seq" gorm:"comment:序号"`
|
||||
Reverse bool `json:"reverse" gorm:"comment:是否反向"`
|
||||
}
|
||||
|
||||
type WorkflowStartPoint struct {
|
||||
WorkflowEdgeID string
|
||||
global.GVA_MODEL
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
Index int `json:"index"`
|
||||
}
|
||||
|
||||
type WorkflowEndPoint struct {
|
||||
WorkflowEdgeID string
|
||||
global.GVA_MODEL
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
Index int `json:"index"`
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
)
|
||||
|
||||
// 工作流流转表
|
||||
type SysWorkFlowProcess struct {
|
||||
global.GVA_MODEL
|
||||
ApplicationID uint `json:"applicationID" gorm:"comment:当前工作流所属申请的ID"` // 当前工作流所属申请的ID
|
||||
CurrentNode string `json:"currentNode" gorm:"comment:当前进度节点"` // 当前进度节点
|
||||
HistoricalNode string `json:"historicalNode" gorm:"comment:上一个进度节点"` // 上一个进度节点
|
||||
CurrentUser string `json:"currentUser" gorm:"comment:当前进度操作人"` // 当前进度操作人
|
||||
HistoricalUser string `json:"historicalUser" gorm:"comment:上一个进度的操作人"` // 上一个进度的操作人
|
||||
State bool `json:"state" gorm:"comment:是否是正在进行的状态"` // 状态 是否是正在进行的状态
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -78,7 +78,7 @@ func Delete{{.StructName}}ByIds(c *gin.Context) {
|
||||
func Update{{.StructName}}(c *gin.Context) {
|
||||
var {{.Abbreviation}} model.{{.StructName}}
|
||||
_ = c.ShouldBindJSON(&{{.Abbreviation}})
|
||||
if err := service.Update{{.StructName}}(&{{.Abbreviation}}); err != nil {
|
||||
if err := service.Update{{.StructName}}({{.Abbreviation}}); err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
} else {
|
||||
|
||||
@@ -19,4 +19,27 @@ type {{.StructName}} struct {
|
||||
func ({{.StructName}}) TableName() string {
|
||||
return "{{.TableName}}"
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
// 如果使用工作流功能 需要打开下方注释 并到initialize的workflow中进行注册 且必须指定TableName
|
||||
// type {{.StructName}}Workflow struct {
|
||||
// // 工作流操作结构体
|
||||
// WorkflowBase `json:"wf"`
|
||||
// {{.StructName}} `json:"business"`
|
||||
// }
|
||||
|
||||
// func ({{.StructName}}) TableName() string {
|
||||
// return "{{.TableName}}"
|
||||
// }
|
||||
|
||||
// 工作流注册代码
|
||||
|
||||
// initWorkflowModel内部注册
|
||||
// model.WorkflowBusinessStruct["{{.Abbreviation}}"] = func() model.GVA_Workflow {
|
||||
// return new(model.{{.StructName}}Workflow)
|
||||
// }
|
||||
|
||||
// initWorkflowTable内部注册
|
||||
// model.WorkflowBusinessTable["{{.Abbreviation}}"] = func() interface{} {
|
||||
// return new(model.{{.StructName}})
|
||||
// }
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func Init{{.StructName}}Router(Router *gin.RouterGroup) {
|
||||
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()).Use(middleware.OperationRecord())
|
||||
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.OperationRecord())
|
||||
{
|
||||
{{.StructName}}Router.POST("create{{.StructName}}", v1.Create{{.StructName}}) // 新建{{.StructName}}
|
||||
{{.StructName}}Router.DELETE("delete{{.StructName}}", v1.Delete{{.StructName}}) // 删除{{.StructName}}
|
||||
|
||||
@@ -24,7 +24,7 @@ func Create{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error)
|
||||
//@return: err error
|
||||
|
||||
func Delete{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
|
||||
err = global.GVA_DB.Delete({{.Abbreviation}}).Error
|
||||
err = global.GVA_DB.Delete(&{{.Abbreviation}}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ func Delete{{.StructName}}ByIds(ids request.IdsReq) (err error) {
|
||||
//@param: {{.Abbreviation}} *model.{{.StructName}}
|
||||
//@return: err error
|
||||
|
||||
func Update{{.StructName}}({{.Abbreviation}} *model.{{.StructName}}) (err error) {
|
||||
err = global.GVA_DB.Save({{.Abbreviation}}).Error
|
||||
func Update{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
|
||||
err = global.GVA_DB.Save(&{{.Abbreviation}}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -68,14 +68,7 @@
|
||||
<el-table-column label="按钮组">
|
||||
<template slot-scope="scope">
|
||||
<el-button class="table-button" @click="update{{.StructName}}(scope.row)" size="small" type="primary" icon="el-icon-edit">变更</el-button>
|
||||
<el-popover placement="top" width="160" v-model="scope.row.visible">
|
||||
<p>确定要删除吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" @click="delete{{.StructName}}(scope.row)">确定</el-button>
|
||||
</div>
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini" slot="reference">删除</el-button>
|
||||
</el-popover>
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -145,7 +138,6 @@ export default {
|
||||
return {
|
||||
listApi: get{{ .StructName }}List,
|
||||
dialogFormVisible: false,
|
||||
visible: false,
|
||||
type: "",
|
||||
deleteVisible: false,
|
||||
multipleSelection: [],
|
||||
@@ -208,6 +200,15 @@ export default {
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val
|
||||
},
|
||||
deleteRow(row){
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.delete{{.StructName}}(row);
|
||||
});
|
||||
},
|
||||
async onDelete() {
|
||||
const ids = []
|
||||
if(this.multipleSelection.length == 0){
|
||||
@@ -227,6 +228,9 @@ export default {
|
||||
type: 'success',
|
||||
message: '删除成功'
|
||||
})
|
||||
if (this.tableData.length == ids.length) {
|
||||
this.page--;
|
||||
}
|
||||
this.deleteVisible = false
|
||||
this.getTableData()
|
||||
}
|
||||
@@ -262,13 +266,15 @@ export default {
|
||||
};
|
||||
},
|
||||
async delete{{.StructName}}(row) {
|
||||
this.visible = false;
|
||||
const res = await delete{{.StructName}}({ ID: row.ID });
|
||||
if (res.code == 0) {
|
||||
this.$message({
|
||||
type: "success",
|
||||
message: "删除成功"
|
||||
});
|
||||
if (this.tableData.length == 1) {
|
||||
this.page--;
|
||||
}
|
||||
this.getTableData();
|
||||
}
|
||||
},
|
||||
@@ -311,4 +317,4 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="formData" label-position="right" label-width="80px">
|
||||
{{- range .Fields}}
|
||||
<el-form-item label="{{.FieldDesc}}:">
|
||||
{{- if eq .FieldType "bool" }}
|
||||
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "string" }}
|
||||
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" ></el-input>
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "int" }}
|
||||
{{- if .DictType}}
|
||||
<el-select v-model="formData.{{ .FieldJson }}" placeholder="请选择" clearable>
|
||||
<el-option v-for="(item,key) in {{ .DictType }}Options" :key="key" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
{{ else -}}
|
||||
<el-input v-model.number="formData.{{ .FieldJson }}" clearable placeholder="请输入"></el-input>
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "time.Time" }}
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable></el-date-picker>
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "float64" }}
|
||||
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable></el-input-number>
|
||||
{{ end -}}
|
||||
</el-form-item>
|
||||
{{ end -}}
|
||||
|
||||
<el-form-item>
|
||||
<el-button v-if="this.wf.clazz == 'start'" @click="start" type="primary">启动</el-button>
|
||||
<!-- complete传入流转参数 决定下一步会流转到什么位置 此处可以设置多个按钮来做不同的流转 -->
|
||||
<el-button v-if="canShow" @click="complete('yes')" type="primary">提交</el-button>
|
||||
<el-button v-if="showSelfNode" @click="complete('')" type="primary">确认</el-button>
|
||||
<el-button @click="back" type="primary">返回</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
startWorkflow,
|
||||
completeWorkflowMove
|
||||
} from "@/api/workflowProcess";
|
||||
import infoList from "@/mixins/infoList";
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
name: "{{.StructName}}",
|
||||
mixins: [infoList],
|
||||
props:{
|
||||
business:{
|
||||
type:Object,
|
||||
default:function(){return null}
|
||||
},
|
||||
wf:{
|
||||
type:Object,
|
||||
default:function(){return{}}
|
||||
},
|
||||
move:{
|
||||
type:Object,
|
||||
default:function(){return{}}
|
||||
},
|
||||
workflowMoveID:{
|
||||
type:[Number,String],
|
||||
default:0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
{{- range .Fields}}
|
||||
{{- if .DictType }}
|
||||
{{ .DictType }}Options:[],
|
||||
{{ end -}}
|
||||
{{end -}}
|
||||
|
||||
formData: {
|
||||
{{range .Fields}}
|
||||
{{- if eq .FieldType "bool" -}}
|
||||
{{.FieldJson}}:false,
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "string" -}}
|
||||
{{.FieldJson}}:"",
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "int" -}}
|
||||
{{.FieldJson}}:0,
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "time.Time" -}}
|
||||
{{.FieldJson}}:new Date(),
|
||||
{{ end -}}
|
||||
{{- if eq .FieldType "float64" -}}
|
||||
{{.FieldJson}}:0,
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
}
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
showSelfNode(){
|
||||
if(this.wf.assignType == "self" && this.move.promoterID == this.userInfo.ID){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
},
|
||||
canShow(){
|
||||
if(this.wf.assignType == "user"){
|
||||
if(this.wf.assignValue.indexOf(","+this.userInfo.ID+",")>-1 && this.wf.clazz == 'userTask'){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}else if(this.wf.assign_type == "authority"){
|
||||
if(this.wf.assignValue.indexOf(","+this.userInfo.authorityId+",")>-1 && this.wf.clazz == 'userTask'){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
...mapGetters("user", ["userInfo"])
|
||||
},
|
||||
methods: {
|
||||
async start() {
|
||||
const res = await startWorkflow({
|
||||
business:this.formData,
|
||||
wf:{
|
||||
workflowMoveID:this.workflowMoveID,
|
||||
businessId:0,
|
||||
businessType:"{{.Abbreviation}}",
|
||||
workflowProcessID:this.wf.workflowProcessID,
|
||||
workflowNodeID:this.wf.id,
|
||||
promoterID:this.userInfo.ID,
|
||||
operatorID:this.userInfo.ID,
|
||||
action:"create",
|
||||
param:""
|
||||
}
|
||||
});
|
||||
if (res.code == 0) {
|
||||
this.$message({
|
||||
type:"success",
|
||||
message:"启动成功"
|
||||
})
|
||||
this.back()
|
||||
}
|
||||
},
|
||||
async complete(param){
|
||||
const res = await completeWorkflowMove({
|
||||
business:this.formData,
|
||||
wf:{
|
||||
workflowMoveID:this.workflowMoveID,
|
||||
businessID:this.formData.ID,
|
||||
businessType:"{{.Abbreviation}}",
|
||||
workflowProcessID:this.wf.workflowProcessID,
|
||||
workflowNodeID:this.wf.id,
|
||||
promoterID:this.userInfo.ID,
|
||||
operatorID:this.userInfo.ID,
|
||||
action:"complete",
|
||||
param:param
|
||||
}
|
||||
})
|
||||
if(res.code == 0){
|
||||
this.$message({
|
||||
type:"success",
|
||||
message:"提交成功"
|
||||
})
|
||||
this.back()
|
||||
}
|
||||
},
|
||||
back(){
|
||||
this.$router.go(-1)
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
if(this.business){
|
||||
this.formData = this.business
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,16 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/api/v1"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitExcelRouter(Router *gin.RouterGroup) {
|
||||
FileUploadAndDownloadGroup := Router.Group("excel")
|
||||
{
|
||||
FileUploadAndDownloadGroup.POST("/importExcel", v1.ImportExcel) // 导入Excel
|
||||
FileUploadAndDownloadGroup.GET("/loadExcel", v1.LoadExcel) // 加载Excel数据
|
||||
FileUploadAndDownloadGroup.POST("/exportExcel", v1.ExportExcel) // 导出Excel
|
||||
FileUploadAndDownloadGroup.GET("/downloadTemplate", v1.DownloadTemplate) // 下载模板文件
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
func InitAutoCodeRouter(Router *gin.RouterGroup) {
|
||||
AutoCodeRouter := Router.Group("autoCode")
|
||||
{
|
||||
AutoCodeRouter.POST("preview", v1.PreviewTemp) // 获取自动创建代码预览
|
||||
AutoCodeRouter.POST("createTemp", v1.CreateTemp) // 创建自动化代码
|
||||
AutoCodeRouter.GET("getTables", v1.GetTables) // 获取对应数据库的表
|
||||
AutoCodeRouter.GET("getDB", v1.GetDB) // 获取数据库
|
||||
|
||||
@@ -2,11 +2,12 @@ package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/api/v1"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitBaseRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
|
||||
BaseRouter := Router.Group("base")
|
||||
BaseRouter := Router.Group("base").Use(middleware.NeedInit())
|
||||
{
|
||||
BaseRouter.POST("login", v1.Login)
|
||||
BaseRouter.POST("captcha", v1.Captcha)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/api/v1"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitInitRouter(Router *gin.RouterGroup) {
|
||||
ApiRouter := Router.Group("init")
|
||||
{
|
||||
ApiRouter.POST("initdb", v1.InitDB) // 创建Api
|
||||
ApiRouter.POST("checkdb", v1.CheckDB) // 创建Api
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,6 @@ func InitSystemRouter(Router *gin.RouterGroup) {
|
||||
SystemRouter.POST("getSystemConfig", v1.GetSystemConfig) // 获取配置文件内容
|
||||
SystemRouter.POST("setSystemConfig", v1.SetSystemConfig) // 设置配置文件内容
|
||||
SystemRouter.POST("getServerInfo", v1.GetServerInfo) // 获取服务器信息
|
||||
SystemRouter.POST("reloadSystem", v1.ReloadSystem) // 重启服务
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,20 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitWorkflowRouter(Router *gin.RouterGroup) {
|
||||
WorkflowRouter := Router.Group("workflow").Use(middleware.OperationRecord())
|
||||
func InitWorkflowProcessRouter(Router *gin.RouterGroup) {
|
||||
WorkflowProcessRouter := Router.Group("workflowProcess").Use(middleware.OperationRecord())
|
||||
{
|
||||
WorkflowRouter.POST("createWorkFlow", v1.CreateWorkFlow) // 创建工作流
|
||||
WorkflowProcessRouter.POST("createWorkflowProcess", v1.CreateWorkflowProcess) // 新建WorkflowProcess
|
||||
WorkflowProcessRouter.DELETE("deleteWorkflowProcess", v1.DeleteWorkflowProcess) // 删除WorkflowProcess
|
||||
WorkflowProcessRouter.DELETE("deleteWorkflowProcessByIds", v1.DeleteWorkflowProcessByIds) // 批量删除WorkflowProcess
|
||||
WorkflowProcessRouter.PUT("updateWorkflowProcess", v1.UpdateWorkflowProcess) // 更新WorkflowProcess
|
||||
WorkflowProcessRouter.GET("findWorkflowProcess", v1.FindWorkflowProcess) // 根据ID获取WorkflowProcess
|
||||
WorkflowProcessRouter.GET("findWorkflowStep", v1.FindWorkflowStep) // 根据ID获取工作流步骤
|
||||
WorkflowProcessRouter.GET("getWorkflowProcessList", v1.GetWorkflowProcessList) // 获取WorkflowProcess列表
|
||||
WorkflowProcessRouter.POST("startWorkflow", v1.StartWorkflow) // 开启工作流
|
||||
WorkflowProcessRouter.POST("completeWorkflowMove", v1.CompleteWorkflowMove) // 提交工作流
|
||||
WorkflowProcessRouter.GET("getMyStated", v1.GetMyStated) // 获取我发起的工作流
|
||||
WorkflowProcessRouter.GET("getMyNeed", v1.GetMyNeed) // 获取我的待办
|
||||
WorkflowProcessRouter.GET("getWorkflowMoveByID", v1.GetWorkflowMoveByID) // 获取我的待办
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func CreateExaCustomer(e model.ExaCustomer) (err error) {
|
||||
//@return: err error
|
||||
|
||||
func DeleteExaCustomer(e model.ExaCustomer) (err error) {
|
||||
err = global.GVA_DB.Delete(e).Error
|
||||
err = global.GVA_DB.Delete(&e).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/360EntSecGroup-Skylar/excelize/v2"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ParseInfoList2Excel(infoList []model.SysBaseMenu, filePath string) error {
|
||||
excel := excelize.NewFile()
|
||||
excel.SetSheetRow("Sheet1","A1",&[]string{"ID","路由Name","路由Path","是否隐藏","父节点","排序","文件名称"})
|
||||
for i, menu := range infoList {
|
||||
axis := fmt.Sprintf("A%d",i+2)
|
||||
excel.SetSheetRow("Sheet1",axis,&[]interface{}{
|
||||
menu.ID,
|
||||
menu.Name,
|
||||
menu.Path,
|
||||
menu.Hidden,
|
||||
menu.ParentId,
|
||||
menu.Sort,
|
||||
menu.Component,
|
||||
})
|
||||
}
|
||||
excel.SaveAs(filePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseExcel2InfoList() ([]model.SysBaseMenu, error) {
|
||||
skipHeader := true
|
||||
fixedHeader := []string{"ID","路由Name","路由Path","是否隐藏","父节点","排序","文件名称"}
|
||||
file, err := excelize.OpenFile(global.GVA_CONFIG.Excel.Dir+"ExcelImport.xlsx")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
menus := make([]model.SysBaseMenu, 0)
|
||||
rows, err := file.Rows("Sheet1")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
row, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if skipHeader {
|
||||
if compareStrSlice(row, fixedHeader) {
|
||||
skipHeader = false
|
||||
continue
|
||||
} else {
|
||||
return nil, errors.New("Excel格式错误")
|
||||
}
|
||||
}
|
||||
if len(row) != len(fixedHeader) {
|
||||
continue
|
||||
}
|
||||
id, _ := strconv.Atoi(row[0])
|
||||
hidden, _ := strconv.ParseBool(row[3])
|
||||
sort, _ := strconv.Atoi(row[5])
|
||||
menu := model.SysBaseMenu{
|
||||
GVA_MODEL: global.GVA_MODEL{
|
||||
ID: uint(id),
|
||||
},
|
||||
Name: row[1],
|
||||
Path: row[2],
|
||||
Hidden: hidden,
|
||||
ParentId: row[4],
|
||||
Sort: sort,
|
||||
Component: row[6],
|
||||
}
|
||||
menus = append(menus, menu)
|
||||
}
|
||||
return menus, nil
|
||||
}
|
||||
|
||||
func compareStrSlice(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
if (b == nil) != (a == nil) {
|
||||
return false
|
||||
}
|
||||
for key, value := range a {
|
||||
if value != b[key] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -42,10 +42,10 @@ func DeleteFile(file model.ExaFileUploadAndDownload) (err error) {
|
||||
var fileFromDb model.ExaFileUploadAndDownload
|
||||
err, fileFromDb = FindFile(file.ID)
|
||||
oss := upload.NewOss()
|
||||
if err = oss.DeleteFile(fileFromDb.Key); err != nil{
|
||||
if err = oss.DeleteFile(fileFromDb.Key); err != nil {
|
||||
return errors.New("文件删除失败")
|
||||
}
|
||||
err = global.GVA_DB.Where("id = ?", file.ID).Unscoped().Delete(file).Error
|
||||
err = global.GVA_DB.Where("id = ?", file.ID).Unscoped().Delete(&file).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,12 @@ func MergeFileMd5(md5 string, fileName string) (err error) {
|
||||
rd, err := ioutil.ReadDir(dir)
|
||||
_ = os.MkdirAll(finishDir, os.ModePerm)
|
||||
//创建目标文件
|
||||
fd, _ := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
fd, err := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//关闭文件
|
||||
defer fd.Close()
|
||||
//将切片文件按照顺序写入
|
||||
for k := range rd {
|
||||
content, _ := ioutil.ReadFile(dir + "/" + fileName + strconv.Itoa(k+1))
|
||||
@@ -60,8 +65,6 @@ func MergeFileMd5(md5 string, fileName string) (err error) {
|
||||
_ = os.Remove(finishDir + fileName)
|
||||
}
|
||||
}
|
||||
//关闭文件
|
||||
defer fd.Close()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -49,7 +49,7 @@ func GetRedisJWT(userName string) (err error, redisJWT string) {
|
||||
|
||||
func SetRedisJWT(jwt string, userName string) (err error) {
|
||||
// 此处过期时间等于jwt过期时间
|
||||
timer := 60 * 60 * 24 * 7 * time.Second
|
||||
timer := time.Duration(global.GVA_CONFIG.JWT.ExpiresTime) * time.Second
|
||||
err = global.GVA_REDIS.Set(userName, jwt, timer).Err()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func CreateApi(api model.SysApi) (err error) {
|
||||
//@return: err error
|
||||
|
||||
func DeleteApi(api model.SysApi) (err error) {
|
||||
err = global.GVA_DB.Delete(api).Error
|
||||
err = global.GVA_DB.Delete(&api).Error
|
||||
ClearCasbin(1, api.Path, api.Method)
|
||||
return err
|
||||
}
|
||||
|
||||
+140
-55
@@ -7,12 +7,18 @@ import (
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
"gin-vue-admin/utils"
|
||||
"gorm.io/gorm"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
autoPath = "autoCode/"
|
||||
basePath = "resource/template"
|
||||
)
|
||||
|
||||
type tplData struct {
|
||||
@@ -22,6 +28,71 @@ type tplData struct {
|
||||
autoMoveFilePath string
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: PreviewTemp
|
||||
//@description: 预览创建代码
|
||||
//@param: model.AutoCodeStruct
|
||||
//@return: map[string]string, error
|
||||
|
||||
func PreviewTemp(autoCode model.AutoCodeStruct) (map[string]string, error) {
|
||||
dataList, _, needMkdir, err := getNeedList(&autoCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 写入文件前,先创建文件夹
|
||||
if err = utils.CreateDir(needMkdir...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建map
|
||||
ret := make(map[string]string)
|
||||
|
||||
// 生成map
|
||||
for _, value := range dataList {
|
||||
ext := ""
|
||||
if ext = filepath.Ext(value.autoCodePath); ext == ".txt" {
|
||||
continue
|
||||
}
|
||||
f, err := os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = value.template.Execute(f, autoCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = f.Close()
|
||||
f, err = os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_RDONLY, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder := strings.Builder{}
|
||||
builder.WriteString("```")
|
||||
|
||||
if ext != "" && strings.Contains(ext, ".") {
|
||||
builder.WriteString(strings.Replace(ext, ".", "", -1))
|
||||
}
|
||||
builder.WriteString("\n\n")
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.Write(data)
|
||||
builder.WriteString("\n\n```")
|
||||
|
||||
pathArr := strings.Split(value.autoCodePath, string(os.PathSeparator))
|
||||
ret[pathArr[1]+"-"+pathArr[3]] = builder.String()
|
||||
_ = f.Close()
|
||||
|
||||
}
|
||||
defer func() { // 移除中间文件
|
||||
if err := os.RemoveAll(autoPath); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateTemp
|
||||
//@description: 创建代码
|
||||
@@ -29,52 +100,10 @@ type tplData struct {
|
||||
//@return: error
|
||||
|
||||
func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
|
||||
basePath := "resource/template"
|
||||
// 获取 basePath 文件夹下所有tpl文件
|
||||
tplFileList, err := GetAllTplFile(basePath, nil)
|
||||
dataList, fileList, needMkdir, err := getNeedList(&autoCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dataList := make([]tplData, 0, len(tplFileList))
|
||||
fileList := make([]string, 0, len(tplFileList))
|
||||
needMkdir := make([]string, 0, len(tplFileList)) // 当文件夹下存在多个tpl文件时,改为map更合理
|
||||
// 根据文件路径生成 tplData 结构体,待填充数据
|
||||
for _, value := range tplFileList {
|
||||
dataList = append(dataList, tplData{locationPath: value})
|
||||
}
|
||||
// 生成 *Template, 填充 template 字段
|
||||
for index, value := range dataList {
|
||||
dataList[index].template, err = template.ParseFiles(value.locationPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 生成文件路径,填充 autoCodePath 字段,readme.txt.tpl不符合规则,需要特殊处理
|
||||
// resource/template/web/api.js.tpl -> autoCode/web/autoCode.PackageName/api/autoCode.PackageName.js
|
||||
// resource/template/readme.txt.tpl -> autoCode/readme.txt
|
||||
autoPath := "autoCode/"
|
||||
for index, value := range dataList {
|
||||
trimBase := strings.TrimPrefix(value.locationPath, basePath+"/")
|
||||
if trimBase == "readme.txt.tpl" {
|
||||
dataList[index].autoCodePath = autoPath + "readme.txt"
|
||||
continue
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(trimBase, "/"); lastSeparator != -1 {
|
||||
origFileName := strings.TrimSuffix(trimBase[lastSeparator+1:], ".tpl")
|
||||
firstDot := strings.Index(origFileName, ".")
|
||||
if firstDot != -1 {
|
||||
dataList[index].autoCodePath = autoPath + trimBase[:lastSeparator] + "/" + autoCode.PackageName + "/" +
|
||||
origFileName[:firstDot] + "/" + autoCode.PackageName + origFileName[firstDot:]
|
||||
}
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(dataList[index].autoCodePath, "/"); lastSeparator != -1 {
|
||||
needMkdir = append(needMkdir, dataList[index].autoCodePath[:lastSeparator])
|
||||
}
|
||||
}
|
||||
|
||||
// 写入文件前,先创建文件夹
|
||||
if err = utils.CreateDir(needMkdir...); err != nil {
|
||||
return err
|
||||
@@ -82,7 +111,6 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
|
||||
|
||||
// 生成文件
|
||||
for _, value := range dataList {
|
||||
fileList = append(fileList, value.autoCodePath)
|
||||
f, err := os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -186,24 +214,31 @@ func GetColumn(tableName string, dbName string) (err error, Columns []request.Co
|
||||
func addAutoMoveFile(data *tplData) {
|
||||
dir := filepath.Base(filepath.Dir(data.autoCodePath))
|
||||
base := filepath.Base(data.autoCodePath)
|
||||
if strings.Contains(data.autoCodePath, "server") {
|
||||
if strings.Contains(data.autoCodePath, "router") {
|
||||
fileSlice := strings.Split(data.autoCodePath, string(os.PathSeparator))
|
||||
n := len(fileSlice)
|
||||
if n <= 2 {
|
||||
return
|
||||
}
|
||||
if strings.Contains(fileSlice[1], "server") {
|
||||
if strings.Contains(fileSlice[n-2], "router") {
|
||||
data.autoMoveFilePath = filepath.Join(dir, base)
|
||||
} else if strings.Contains(data.autoCodePath, "api") {
|
||||
} else if strings.Contains(fileSlice[n-2], "api") {
|
||||
data.autoMoveFilePath = filepath.Join(dir, "v1", base)
|
||||
} else if strings.Contains(data.autoCodePath, "service") {
|
||||
} else if strings.Contains(fileSlice[n-2], "service") {
|
||||
data.autoMoveFilePath = filepath.Join(dir, base)
|
||||
} else if strings.Contains(data.autoCodePath, "model") {
|
||||
} else if strings.Contains(fileSlice[n-2], "model") {
|
||||
data.autoMoveFilePath = filepath.Join(dir, base)
|
||||
} else if strings.Contains(data.autoCodePath, "request") {
|
||||
} else if strings.Contains(fileSlice[n-2], "request") {
|
||||
data.autoMoveFilePath = filepath.Join("model", dir, base)
|
||||
}
|
||||
} else if strings.Contains(data.autoCodePath, "web") {
|
||||
if strings.Contains(data.autoCodePath, "js") {
|
||||
} else if strings.Contains(fileSlice[1], "web") {
|
||||
if strings.Contains(fileSlice[n-1], "js") {
|
||||
data.autoMoveFilePath = filepath.Join("../", "web", "src", dir, base)
|
||||
} else if strings.Contains(data.autoCodePath, "form") {
|
||||
} else if strings.Contains(fileSlice[n-2], "workflowForm") {
|
||||
data.autoMoveFilePath = filepath.Join("../", "web", "src", "view", filepath.Base(filepath.Dir(filepath.Dir(data.autoCodePath))), strings.TrimSuffix(base, filepath.Ext(base))+"WorkflowForm.vue")
|
||||
} else if strings.Contains(fileSlice[n-2], "form") {
|
||||
data.autoMoveFilePath = filepath.Join("../", "web", "src", "view", filepath.Base(filepath.Dir(filepath.Dir(data.autoCodePath))), strings.TrimSuffix(base, filepath.Ext(base))+"Form.vue")
|
||||
} else if strings.Contains(data.autoCodePath, "table") {
|
||||
} else if strings.Contains(fileSlice[n-2], "table") {
|
||||
data.autoMoveFilePath = filepath.Join("../", "web", "src", "view", filepath.Base(filepath.Dir(filepath.Dir(data.autoCodePath))), base)
|
||||
}
|
||||
}
|
||||
@@ -268,3 +303,53 @@ func AutoCreateApi(a *model.AutoCodeStruct) (err error) {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func getNeedList(autoCode *model.AutoCodeStruct) (dataList []tplData, fileList []string, needMkdir []string, err error) {
|
||||
// 获取 basePath 文件夹下所有tpl文件
|
||||
tplFileList, err := GetAllTplFile(basePath, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
dataList = make([]tplData, 0, len(tplFileList))
|
||||
fileList = make([]string, 0, len(tplFileList))
|
||||
needMkdir = make([]string, 0, len(tplFileList)) // 当文件夹下存在多个tpl文件时,改为map更合理
|
||||
// 根据文件路径生成 tplData 结构体,待填充数据
|
||||
for _, value := range tplFileList {
|
||||
dataList = append(dataList, tplData{locationPath: value})
|
||||
}
|
||||
// 生成 *Template, 填充 template 字段
|
||||
for index, value := range dataList {
|
||||
dataList[index].template, err = template.ParseFiles(value.locationPath)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
// 生成文件路径,填充 autoCodePath 字段,readme.txt.tpl不符合规则,需要特殊处理
|
||||
// resource/template/web/api.js.tpl -> autoCode/web/autoCode.PackageName/api/autoCode.PackageName.js
|
||||
// resource/template/readme.txt.tpl -> autoCode/readme.txt
|
||||
autoPath := "autoCode/"
|
||||
for index, value := range dataList {
|
||||
trimBase := strings.TrimPrefix(value.locationPath, basePath+"/")
|
||||
if trimBase == "readme.txt.tpl" {
|
||||
dataList[index].autoCodePath = autoPath + "readme.txt"
|
||||
continue
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(trimBase, "/"); lastSeparator != -1 {
|
||||
origFileName := strings.TrimSuffix(trimBase[lastSeparator+1:], ".tpl")
|
||||
firstDot := strings.Index(origFileName, ".")
|
||||
if firstDot != -1 {
|
||||
dataList[index].autoCodePath = filepath.Join(autoPath, trimBase[:lastSeparator], autoCode.PackageName,
|
||||
origFileName[:firstDot], autoCode.PackageName+origFileName[firstDot:])
|
||||
}
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(dataList[index].autoCodePath, string(os.PathSeparator)); lastSeparator != -1 {
|
||||
needMkdir = append(needMkdir, dataList[index].autoCodePath[:lastSeparator])
|
||||
}
|
||||
}
|
||||
for _, value := range dataList {
|
||||
fileList = append(fileList, value.autoCodePath)
|
||||
}
|
||||
return dataList, fileList, needMkdir, err
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func CreateSysDictionary(sysDictionary model.SysDictionary) (err error) {
|
||||
//@return: err error
|
||||
|
||||
func DeleteSysDictionary(sysDictionary model.SysDictionary) (err error) {
|
||||
err = global.GVA_DB.Delete(sysDictionary).Delete(&sysDictionary.SysDictionaryDetails).Error
|
||||
err = global.GVA_DB.Delete(&sysDictionary).Delete(&sysDictionary.SysDictionaryDetails).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ func CreateSysDictionaryDetail(sysDictionaryDetail model.SysDictionaryDetail) (e
|
||||
//@return: err error
|
||||
|
||||
func DeleteSysDictionaryDetail(sysDictionaryDetail model.SysDictionaryDetail) (err error) {
|
||||
err = global.GVA_DB.Delete(sysDictionaryDetail).Error
|
||||
err = global.GVA_DB.Delete(&sysDictionaryDetail).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
"gin-vue-admin/source"
|
||||
"github.com/spf13/viper"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: writeConfig
|
||||
//@description: 回写配置
|
||||
//@param:
|
||||
//@return: error
|
||||
|
||||
func writeConfig(viper *viper.Viper, conf map[string]interface{}) error {
|
||||
for k, v := range conf {
|
||||
viper.Set(k, v)
|
||||
}
|
||||
return viper.WriteConfig()
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: createTable
|
||||
//@description: 创建数据库(mysql)
|
||||
//@param: dsn string, driver string, createSql
|
||||
//@return: error
|
||||
|
||||
func createTable(dsn string, driver string, createSql string) error {
|
||||
db, err := sql.Open(driver, dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
if err = db.Ping(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.Exec(createSql)
|
||||
return err
|
||||
}
|
||||
|
||||
func initDB(InitDBFunctions ...model.InitDBFunc) (err error) {
|
||||
for _, v := range InitDBFunctions {
|
||||
err = v.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: InitDB
|
||||
//@description: 创建数据库并初始化
|
||||
//@param: authorityId string
|
||||
//@return: err error, treeMap map[string][]model.SysMenu
|
||||
|
||||
func InitDB(conf request.InitDB) error {
|
||||
if conf.Host == "" {
|
||||
conf.Host = "127.0.0.1"
|
||||
}
|
||||
|
||||
if conf.Port == "" {
|
||||
conf.Port = "3306"
|
||||
}
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/", conf.UserName, conf.Password, conf.Host, conf.Port)
|
||||
fmt.Println(dsn)
|
||||
createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;", conf.DBName)
|
||||
if err := createTable(dsn, "mysql", createSql); err != nil {
|
||||
return err
|
||||
}
|
||||
setting := map[string]interface{}{
|
||||
"mysql.path": fmt.Sprintf("%s:%s", conf.Host, conf.Port),
|
||||
"mysql.db-name": conf.DBName,
|
||||
"mysql.username": conf.UserName,
|
||||
"mysql.password": conf.Password,
|
||||
"mysql.config": "charset=utf8mb4&parseTime=True&loc=Local",
|
||||
}
|
||||
if err := writeConfig(global.GVA_VP, setting); err != nil {
|
||||
return err
|
||||
}
|
||||
m := global.GVA_CONFIG.Mysql
|
||||
if m.Dbname == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
linkDns := m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config
|
||||
mysqlConfig := mysql.Config{
|
||||
DSN: linkDns, // DSN data source name
|
||||
DefaultStringSize: 191, // string 类型字段的默认长度
|
||||
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
|
||||
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
|
||||
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
|
||||
SkipInitializeWithVersion: false, // 根据版本自动配置
|
||||
}
|
||||
if db, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}); err != nil {
|
||||
//global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err))
|
||||
//os.Exit(0)
|
||||
//return nil
|
||||
return nil
|
||||
} else {
|
||||
sqlDB, _ := db.DB()
|
||||
sqlDB.SetMaxIdleConns(m.MaxIdleConns)
|
||||
sqlDB.SetMaxOpenConns(m.MaxOpenConns)
|
||||
global.GVA_DB = db
|
||||
}
|
||||
|
||||
err := global.GVA_DB.AutoMigrate(
|
||||
model.SysUser{},
|
||||
model.SysAuthority{},
|
||||
model.SysApi{},
|
||||
model.SysBaseMenu{},
|
||||
model.SysBaseMenuParameter{},
|
||||
model.JwtBlacklist{},
|
||||
model.SysDictionary{},
|
||||
model.SysDictionaryDetail{},
|
||||
model.ExaFileUploadAndDownload{},
|
||||
model.ExaFile{},
|
||||
model.ExaFileChunk{},
|
||||
model.ExaSimpleUploader{},
|
||||
model.ExaCustomer{},
|
||||
model.SysOperationRecord{},
|
||||
model.WorkflowProcess{},
|
||||
model.WorkflowNode{},
|
||||
model.WorkflowEdge{},
|
||||
model.WorkflowStartPoint{},
|
||||
model.WorkflowEndPoint{},
|
||||
model.WorkflowMove{},
|
||||
model.ExaWfLeave{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = initDB(
|
||||
source.Admin,
|
||||
source.Api,
|
||||
source.AuthorityMenu,
|
||||
source.Authority,
|
||||
source.AuthoritiesMenus,
|
||||
source.Casbin,
|
||||
source.DataAuthorities,
|
||||
source.Dictionary,
|
||||
source.DictionaryDetail,
|
||||
source.File,
|
||||
source.BaseMenu,
|
||||
source.Workflow)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -89,12 +89,11 @@ func getBaseChildrenList(menu *model.SysBaseMenu, treeMap map[string][]model.Sys
|
||||
//@param: menu model.SysBaseMenu
|
||||
//@return: err error
|
||||
|
||||
func AddBaseMenu(menu model.SysBaseMenu) (err error) {
|
||||
func AddBaseMenu(menu model.SysBaseMenu) error {
|
||||
if !errors.Is(global.GVA_DB.Where("name = ?", menu.Name).First(&model.SysBaseMenu{}).Error, gorm.ErrRecordNotFound) {
|
||||
err = errors.New("存在重复name,请修改name")
|
||||
return errors.New("存在重复name,请修改name")
|
||||
}
|
||||
err = global.GVA_DB.Create(&menu).Error
|
||||
return err
|
||||
return global.GVA_DB.Create(&menu).Error
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
|
||||
@@ -36,7 +36,7 @@ func DeleteSysOperationRecordByIds(ids request.IdsReq) (err error) {
|
||||
//@return: err error
|
||||
|
||||
func DeleteSysOperationRecord(sysOperationRecord model.SysOperationRecord) (err error) {
|
||||
err = global.GVA_DB.Delete(sysOperationRecord).Error
|
||||
err = global.GVA_DB.Delete(&sysOperationRecord).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,445 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/constant"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Create
|
||||
//@description: 创建工作流
|
||||
//@param: wk model.SysWorkflow
|
||||
//@return: error
|
||||
func getTable(businessType string) interface{} {
|
||||
return model.WorkflowBusinessTable[businessType]()
|
||||
}
|
||||
|
||||
func Create(wk model.SysWorkflow) error {
|
||||
err := global.GVA_DB.Create(&wk).Error
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateWorkflowProcess
|
||||
//@description: 创建工作流相关信息
|
||||
//@param: workflowProcess model.WorkflowProcess
|
||||
//@return: err error
|
||||
|
||||
func CreateWorkflowProcess(workflowProcess model.WorkflowProcess) (err error) {
|
||||
err = global.GVA_DB.Create(&workflowProcess).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteWorkflowProcess
|
||||
//@description: 删除工作流相关信息
|
||||
//@param: workflowProcess model.WorkflowProcess
|
||||
//@return: err error
|
||||
|
||||
func DeleteWorkflowProcess(workflowProcess model.WorkflowProcess) (err error) {
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
txErr = tx.Delete(&workflowProcess).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
var edges []model.WorkflowEdge
|
||||
txErr = tx.Delete(&model.WorkflowNode{}, "workflow_process_id = ?", workflowProcess.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Find(&edges, "workflow_process_id = ?", workflowProcess.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
if len(edges) > 0 {
|
||||
txErr = tx.Select("StartPoint", "EndPoint").Delete(&edges).Error
|
||||
}
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateWorkflowProcess
|
||||
//@description: 批量删除工作流信息(暂未启用)
|
||||
//@param: ids request.IdsReq
|
||||
//@return: err error
|
||||
|
||||
func DeleteWorkflowProcessByIds(ids request.IdsReq) (err error) {
|
||||
err = global.GVA_DB.Delete(&[]model.WorkflowProcess{}, "id in ?", ids.Ids).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateWorkflowProcess
|
||||
//@description: 更新工作流相关信息
|
||||
//@param: workflowProcess *model.WorkflowProcess
|
||||
//@return: err error
|
||||
|
||||
func UpdateWorkflowProcess(workflowProcess *model.WorkflowProcess) (err error) {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
var edges []model.WorkflowEdge
|
||||
var edgesIds []string
|
||||
txErr = tx.Unscoped().Delete(workflowProcess).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Unscoped().Delete(&model.WorkflowNode{}, "workflow_process_id = ?", workflowProcess.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Unscoped().Find(&edges, "workflow_process_id = ?", workflowProcess.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Unscoped().Delete(&edges).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
for _, v := range edges {
|
||||
edgesIds = append(edgesIds, v.ID)
|
||||
}
|
||||
txErr = tx.Unscoped().Delete(&model.WorkflowStartPoint{}, "workflow_edge_id in ?", edgesIds).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Unscoped().Delete(&model.WorkflowEndPoint{}, "workflow_edge_id in ?", edgesIds).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Create(&workflowProcess).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetWorkflowProcess
|
||||
//@description: 获取工作流相关信息
|
||||
//@param: id string
|
||||
//@return: err error,workflowProcess model.WorkflowProcess
|
||||
|
||||
func GetWorkflowProcess(id string) (err error, workflowProcess model.WorkflowProcess) {
|
||||
err = global.GVA_DB.Preload("Nodes").Preload("Edges").Where("id = ?", id).First(&workflowProcess).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetWorkflowCreateStep
|
||||
//@description: 获取工作流步骤信息
|
||||
//@param: id string
|
||||
//@return: err error, workflowNodes []model.WorkflowNode
|
||||
|
||||
func FindWorkflowStep(id string) (err error, workflowNode model.WorkflowProcess) {
|
||||
err = global.GVA_DB.Preload("Nodes", "clazz = ?", constant.START).Where("id = ?", id).First(&workflowNode).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetWorkflowProcessInfoList
|
||||
//@description: 获取工作流列表
|
||||
//@param: info request.WorkflowProcessSearch
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func GetWorkflowProcessInfoList(info request.WorkflowProcessSearch) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
// 创建db
|
||||
db := global.GVA_DB.Model(&model.WorkflowProcess{})
|
||||
var workflowProcesss []model.WorkflowProcess
|
||||
// 如果有条件搜索 下方会自动创建搜索语句
|
||||
if info.Name != "" {
|
||||
db = db.Where("`name` LIKE ?", "%"+info.Name+"%")
|
||||
}
|
||||
if info.Label != "" {
|
||||
db = db.Where("`label` LIKE ?", "%"+info.Label+"%")
|
||||
}
|
||||
err = db.Count(&total).Error
|
||||
err = db.Limit(limit).Offset(offset).Find(&workflowProcesss).Error
|
||||
return err, workflowProcesss, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: StartWorkflow
|
||||
//@description: 开启一个工作流
|
||||
//@param: wfInterface model.GVA_Workflow
|
||||
//@return: err error
|
||||
|
||||
func StartWorkflow(wfInterface model.GVA_Workflow) (err error) {
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
tableName := getTable(wfInterface.GetBusinessType()).(schema.Tabler).TableName()
|
||||
txErr = tx.Table(tableName).Create(wfInterface).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
wfm := wfInterface.CreateWorkflowMove()
|
||||
txErr = tx.Create(wfm).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = complete(tx, wfm)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func CompleteWorkflowMove(wfInterface model.GVA_Workflow) (err error) {
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
tableName := getTable(wfInterface.GetBusinessType()).(schema.Tabler).TableName()
|
||||
txErr = tx.Table(tableName).Where("id = ?", wfInterface.GetBusinessID()).Updates(wfInterface).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
nowWorkflowMove := wfInterface.CreateWorkflowMove()
|
||||
txErr = complete(tx, nowWorkflowMove)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func complete(tx *gorm.DB, wfm *model.WorkflowMove) (err error) {
|
||||
var returnWfm model.WorkflowMove
|
||||
var nodeInfo model.WorkflowNode
|
||||
var Edges []model.WorkflowEdge
|
||||
txErr := tx.First(&returnWfm, "id = ? AND is_active = ?", wfm.ID, true).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.First(&nodeInfo, "id = ?", wfm.WorkflowNodeID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
|
||||
if nodeInfo.Clazz == constant.START || nodeInfo.Clazz == constant.USER_TASK {
|
||||
txErr = tx.Find(&Edges, "workflow_process_id = ? and source = ?", wfm.WorkflowProcessID, wfm.WorkflowNodeID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
if len(Edges) == 0 {
|
||||
return errors.New("不存在当前节点为起点的后续流程")
|
||||
}
|
||||
if len(Edges) == 1 {
|
||||
txErr = tx.Model(&returnWfm).Update("param", wfm.Param).Update("is_active", false).Update("action", wfm.Action).Update("operator_id", wfm.OperatorID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr, newWfm := createNewWorkflowMove(tx, &returnWfm, Edges[0].Target)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
if len(newWfm) > 0 {
|
||||
txErr = tx.Create(&newWfm).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
}
|
||||
// 当target为自动节点时候 需要做一些事情 这里暂时先不处理 后续慢慢完善
|
||||
}
|
||||
if len(Edges) > 1 {
|
||||
var needUseTargetNodeID string
|
||||
|
||||
txErr = tx.Model(&returnWfm).Update("param", wfm.Param).Update("is_active", false).Update("action", wfm.Action).Update("operator_id", wfm.OperatorID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
for _, v := range Edges {
|
||||
if v.ConditionExpression == wfm.Param {
|
||||
needUseTargetNodeID = v.Target
|
||||
break
|
||||
}
|
||||
}
|
||||
if needUseTargetNodeID == "" {
|
||||
return errors.New("未发现流转参数,流转失败")
|
||||
}
|
||||
txErr, newWfm := createNewWorkflowMove(tx, &returnWfm, needUseTargetNodeID)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
if len(newWfm) > 0 {
|
||||
txErr = tx.Create(&newWfm).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if nodeInfo.Clazz == constant.EXCLUSIVE_GATEWAY {
|
||||
return errors.New("目前只支持start节点和userTask功能,其他功能正在开发中")
|
||||
} else if nodeInfo.Clazz == constant.INCLUSIVE_GATEWAY {
|
||||
return errors.New("目前只支持start节点和userTask功能,其他功能正在开发中")
|
||||
} else if nodeInfo.Clazz == constant.PARELLEL_GATEWAY {
|
||||
return errors.New("目前只支持start节点和userTask功能,其他功能正在开发中")
|
||||
} else {
|
||||
return errors.New("目前只支持start节点和userTask功能,其他功能正在开发中")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createNewWorkflowMove(tx *gorm.DB, oldWfm *model.WorkflowMove, targetNodeID string) (err error, newWfm []model.WorkflowMove) {
|
||||
// 以下所有非 default的节点的下一步流转均应该处理为递归形式
|
||||
var nodeInfo model.WorkflowNode
|
||||
var edge model.WorkflowEdge
|
||||
var edges []model.WorkflowEdge
|
||||
var wfms []model.WorkflowMove
|
||||
txErr := tx.First(&nodeInfo, "id = ?", targetNodeID).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
switch nodeInfo.Clazz {
|
||||
case constant.EXCLUSIVE_GATEWAY:
|
||||
// 当为排他网关时候 选择一个参数进行排他线路选择
|
||||
txErr := tx.First(&edge, "workflow_process_id = ? and source = ? and condition_expression = ?", oldWfm.WorkflowProcessID, nodeInfo.ID, oldWfm.Param).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
newWfm = append(newWfm, model.WorkflowMove{
|
||||
BusinessID: oldWfm.BusinessID,
|
||||
BusinessType: oldWfm.BusinessType,
|
||||
PromoterID: oldWfm.PromoterID,
|
||||
OperatorID: 0,
|
||||
WorkflowNodeID: edge.Target,
|
||||
WorkflowProcessID: oldWfm.WorkflowProcessID,
|
||||
Param: "",
|
||||
Action: "",
|
||||
IsActive: true})
|
||||
return nil, newWfm
|
||||
case constant.INCLUSIVE_GATEWAY:
|
||||
// 当为包容网关时,需要等待其他网关执行结束才进行创建
|
||||
txErr := tx.Find(&edges, "workflow_process_id = ? and target = ?", oldWfm.WorkflowProcessID, nodeInfo.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
var sourceIds []string
|
||||
for _, v := range edges {
|
||||
sourceIds = append(sourceIds, v.Source)
|
||||
}
|
||||
txErr = tx.Find(&wfms, "workflow_process_id = ? and business_id = ? and workflow_node_id in (?) and is_active = ?", oldWfm.WorkflowProcessID, oldWfm.BusinessID, sourceIds, false).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
if len(wfms) != len(edges) {
|
||||
return nil, []model.WorkflowMove{}
|
||||
}
|
||||
if len(wfms) == len(edges) {
|
||||
params := make(map[string]int)
|
||||
var param string
|
||||
var temp int
|
||||
for _, v := range wfms {
|
||||
params[v.Param]++
|
||||
}
|
||||
for k, v := range params {
|
||||
if temp < v {
|
||||
temp = v
|
||||
param = k
|
||||
}
|
||||
}
|
||||
//参数携带模式暂时未定 暂时为少数服从多数原则 后续会增加原则配置 (少数服从多数,仅一关键字即为关键字,所有关键字才为关键字 三种方案)
|
||||
txErr := tx.First(&edge, "workflow_process_id = ? and source = ? and condition_expression = ?", oldWfm.WorkflowProcessID, nodeInfo.ID, param).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
newWfm = append(newWfm, model.WorkflowMove{
|
||||
BusinessID: oldWfm.BusinessID,
|
||||
BusinessType: oldWfm.BusinessType,
|
||||
PromoterID: oldWfm.PromoterID,
|
||||
OperatorID: 0,
|
||||
WorkflowNodeID: edge.Target,
|
||||
WorkflowProcessID: oldWfm.WorkflowProcessID,
|
||||
Param: "",
|
||||
Action: "",
|
||||
IsActive: true})
|
||||
}
|
||||
return nil, newWfm
|
||||
|
||||
case constant.PARELLEL_GATEWAY:
|
||||
// 当为并行网关时候 找出所有线路创建并行节点
|
||||
txErr := tx.Find(&edges, "workflow_process_id = ? and source = ?", oldWfm.WorkflowProcessID, nodeInfo.ID).Error
|
||||
if txErr != nil {
|
||||
return txErr, []model.WorkflowMove{}
|
||||
}
|
||||
for _, v := range edges {
|
||||
newWfm = append(newWfm, model.WorkflowMove{
|
||||
BusinessID: oldWfm.BusinessID,
|
||||
BusinessType: oldWfm.BusinessType,
|
||||
PromoterID: oldWfm.PromoterID,
|
||||
OperatorID: 0,
|
||||
WorkflowNodeID: v.Target,
|
||||
WorkflowProcessID: oldWfm.WorkflowProcessID,
|
||||
Param: "",
|
||||
Action: "",
|
||||
IsActive: true})
|
||||
}
|
||||
|
||||
return nil, newWfm
|
||||
case constant.END:
|
||||
newWfm = append(newWfm, model.WorkflowMove{
|
||||
BusinessID: oldWfm.BusinessID,
|
||||
BusinessType: oldWfm.BusinessType,
|
||||
PromoterID: oldWfm.PromoterID,
|
||||
OperatorID: oldWfm.OperatorID,
|
||||
WorkflowNodeID: targetNodeID,
|
||||
WorkflowProcessID: oldWfm.WorkflowProcessID,
|
||||
Param: "",
|
||||
Action: "",
|
||||
IsActive: false})
|
||||
return nil, newWfm
|
||||
default:
|
||||
newWfm = append(newWfm, model.WorkflowMove{
|
||||
BusinessID: oldWfm.BusinessID,
|
||||
BusinessType: oldWfm.BusinessType,
|
||||
PromoterID: oldWfm.PromoterID,
|
||||
OperatorID: 0,
|
||||
WorkflowNodeID: targetNodeID,
|
||||
WorkflowProcessID: oldWfm.WorkflowProcessID,
|
||||
Param: "",
|
||||
Action: "",
|
||||
IsActive: true})
|
||||
return nil, newWfm
|
||||
}
|
||||
}
|
||||
|
||||
func GetMyStated(userID uint) (err error, wfms []model.WorkflowMove) {
|
||||
err = global.GVA_DB.Preload("Promoter").Preload("Operator").Preload("WorkflowNode").Preload("WorkflowProcess").Joins("INNER JOIN workflow_nodes as node ON workflow_moves.workflow_node_id = node.id").Find(&wfms, "promoter_id = ? and ( is_active = ? OR node.clazz = ?)", userID, true, "end").Error
|
||||
return err, wfms
|
||||
}
|
||||
|
||||
func GetMyNeed(userID uint, AuthorityID string) (err error, wfms []model.WorkflowMove) {
|
||||
user := "%," + strconv.Itoa(int(userID)) + ",%"
|
||||
auth := "%," + AuthorityID + ",%"
|
||||
err = global.GVA_DB.Preload("Promoter").Preload("Operator").Preload("WorkflowNode").Preload("WorkflowProcess").Joins("INNER JOIN workflow_nodes as node ON workflow_moves.workflow_node_id = node.id").Where("is_active = ? AND ((node.assign_type = ? AND node.assign_value LIKE ? ) OR (node.assign_type = ? AND node.assign_value LIKE ? ) OR (node.assign_type = ? AND promoter_id = ? ))", true, "user", user, "authority", auth, "self", userID).Find(&wfms).Error
|
||||
return err, wfms
|
||||
}
|
||||
|
||||
func GetWorkflowMoveByID(id float64) (err error, move model.WorkflowMove, moves []model.WorkflowMove, business interface{}) {
|
||||
var result interface{}
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
var txErr error
|
||||
txErr = tx.Preload("Promoter").Preload("Operator").Preload("WorkflowNode").Preload("WorkflowProcess").First(&move, "id = ?", id).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = tx.Preload("Promoter").Preload("Operator").Preload("WorkflowNode").Preload("WorkflowProcess").Find(&moves, "business_id = ? AND business_type = ?", move.BusinessID, move.BusinessType).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
result = getTable(move.BusinessType)
|
||||
fmt.Println(result)
|
||||
txErr = tx.First(result, "id = ?", move.BusinessID).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err, move, moves, result
|
||||
}
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Users = []model.SysUser{
|
||||
var Admin = new(admin)
|
||||
|
||||
type admin struct{}
|
||||
|
||||
var admins = []model.SysUser{
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, UUID: uuid.NewV4(), Username: "admin", Password: "e10adc3949ba59abbe56e057f20f883e", NickName: "超级管理员", HeaderImg: "http://qmplusimg.henrongyi.top/gva_header.jpg", AuthorityId: "888"},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, UUID: uuid.NewV4(), Username: "a303176530", Password: "3ec063004a6f31642261936a379fde3d", NickName: "QMPlusUser", HeaderImg: "http://qmplusimg.henrongyi.top/1572075907logo.png", AuthorityId: "9528"},
|
||||
}
|
||||
|
||||
func InitSysUser(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_users 表数据初始化
|
||||
func (a *admin) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 2}).Find(&[]model.SysUser{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_users表的初始数据已存在!")
|
||||
color.Danger.Println("\n[Mysql] --> sys_users 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Users).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&admins).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_users 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_users 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Apis = []model.SysApi{
|
||||
var Api = new(api)
|
||||
|
||||
type api struct{}
|
||||
|
||||
var apis = []model.SysApi{
|
||||
{global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/base/login", "用户登录", "base", "POST"},
|
||||
{global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/user/register", "用户注册", "user", "POST"},
|
||||
{global.GVA_MODEL{ID: 3, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/api/createApi", "创建api", "api", "POST"},
|
||||
@@ -39,7 +42,7 @@ var Apis = []model.SysApi{
|
||||
{global.GVA_MODEL{ID: 27, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/casbin/updateCasbin", "更改角色api权限", "casbin", "POST"},
|
||||
{global.GVA_MODEL{ID: 28, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/casbin/getPolicyPathByAuthorityId", "获取权限列表", "casbin", "POST"},
|
||||
{global.GVA_MODEL{ID: 29, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/fileUploadAndDownload/deleteFile", "删除文件", "fileUploadAndDownload", "POST"},
|
||||
{global.GVA_MODEL{ID: 30, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/jwt/jsonInBlacklist", "jwt加入黑名单", "jwt", "POST"},
|
||||
{global.GVA_MODEL{ID: 30, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/jwt/jsonInBlacklist", "jwt加入黑名单(退出)", "jwt", "POST"},
|
||||
{global.GVA_MODEL{ID: 31, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/authority/setDataAuthority", "设置角色资源权限", "authority", "POST"},
|
||||
{global.GVA_MODEL{ID: 32, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/system/getSystemConfig", "获取配置文件内容", "system", "POST"},
|
||||
{global.GVA_MODEL{ID: 33, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/system/setSystemConfig", "设置配置文件内容", "system", "POST"},
|
||||
@@ -77,20 +80,37 @@ var Apis = []model.SysApi{
|
||||
{global.GVA_MODEL{ID: 65, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/user/setUserInfo", "设置用户信息", "user", "PUT"},
|
||||
{global.GVA_MODEL{ID: 66, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/system/getServerInfo", "获取服务器信息", "system", "POST"},
|
||||
{global.GVA_MODEL{ID: 67, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/email/emailTest", "发送测试邮件", "email", "POST"},
|
||||
{global.GVA_MODEL{ID: 68, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/createWorkflowProcess", "新建工作流", "workflowProcess", "POST"},
|
||||
{global.GVA_MODEL{ID: 69, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/deleteWorkflowProcess", "删除工作流", "workflowProcess", "DELETE"},
|
||||
{global.GVA_MODEL{ID: 70, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/deleteWorkflowProcessByIds", "批量删除工作流", "workflowProcess", "DELETE"},
|
||||
{global.GVA_MODEL{ID: 71, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/updateWorkflowProcess", "更新工作流", "workflowProcess", "PUT"},
|
||||
{global.GVA_MODEL{ID: 72, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/findWorkflowProcess", "根据ID获取工作流", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 73, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getWorkflowProcessList", "获取工作流", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 74, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/findWorkflowStep", "获取工作流步骤", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 75, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/startWorkflow", "启动工作流", "workflowProcess", "POST"},
|
||||
{global.GVA_MODEL{ID: 76, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getMyStated", "获取我发起的工作流", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 77, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getMyNeed", "获取我的待办", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 78, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getWorkflowMoveByID", "根据id获取当前节点详情和历史", "workflowProcess", "GET"},
|
||||
{global.GVA_MODEL{ID: 79, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/completeWorkflowMove", "提交工作流", "workflowProcess", "POST"},
|
||||
{global.GVA_MODEL{ID: 80, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/autoCode/preview", "预览自动化代码", "autoCode", "POST"},
|
||||
{global.GVA_MODEL{ID: 81, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/excel/importExcel", "导入excel", "excel", "POST"},
|
||||
{global.GVA_MODEL{ID: 82, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/excel/loadExcel", "下载excel", "excel", "GET"},
|
||||
{global.GVA_MODEL{ID: 83, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/excel/exportExcel", "导出excel", "excel", "POST"},
|
||||
{global.GVA_MODEL{ID: 84, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/excel/downloadTemplate", "下载excel模板", "excel", "GET"},
|
||||
}
|
||||
|
||||
func InitSysApi(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_apis 表数据初始化
|
||||
func (a *api) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 67}).Find(&[]model.SysApi{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_apis表的初始数据已存在!")
|
||||
color.Danger.Println("\n[Mysql] --> sys_apis 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Apis).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&apis).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_apis 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_apis 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var AuthoritiesMenus = new(authoritiesMenus)
|
||||
|
||||
type authoritiesMenus struct{}
|
||||
|
||||
type AuthorityMenus struct {
|
||||
AuthorityId string `gorm:"column:sys_authority_authority_id"`
|
||||
BaseMenuId uint `gorm:"column:sys_base_menu_id"`
|
||||
}
|
||||
|
||||
var authorityMenus = []AuthorityMenus{
|
||||
{"888", 1},
|
||||
{"888", 2},
|
||||
{"888", 3},
|
||||
{"888", 4},
|
||||
{"888", 5},
|
||||
{"888", 6},
|
||||
{"888", 7},
|
||||
{"888", 8},
|
||||
{"888", 9},
|
||||
{"888", 10},
|
||||
{"888", 11},
|
||||
{"888", 12},
|
||||
{"888", 13},
|
||||
{"888", 14},
|
||||
{"888", 15},
|
||||
{"888", 16},
|
||||
{"888", 17},
|
||||
{"888", 18},
|
||||
{"888", 19},
|
||||
{"888", 20},
|
||||
{"888", 21},
|
||||
{"888", 22},
|
||||
{"888", 23},
|
||||
{"888", 24},
|
||||
{"888", 25},
|
||||
{"888", 26},
|
||||
{"888", 27},
|
||||
{"888", 28},
|
||||
{"888", 29},
|
||||
{"8881", 1},
|
||||
{"8881", 2},
|
||||
{"8881", 8},
|
||||
{"9528", 1},
|
||||
{"9528", 2},
|
||||
{"9528", 3},
|
||||
{"9528", 4},
|
||||
{"9528", 5},
|
||||
{"9528", 6},
|
||||
{"9528", 7},
|
||||
{"9528", 8},
|
||||
{"9528", 9},
|
||||
{"9528", 10},
|
||||
{"9528", 11},
|
||||
{"9528", 12},
|
||||
{"9528", 14},
|
||||
{"9528", 15},
|
||||
{"9528", 16},
|
||||
{"9528", 17},
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_authority_menus 表数据初始化
|
||||
func (a *authoritiesMenus) Init() error {
|
||||
return global.GVA_DB.Table("sys_authority_menus").Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("sys_authority_authority_id IN ('888', '8881', '9528')").Find(&[]AuthorityMenus{}).RowsAffected == 48 {
|
||||
color.Danger.Println("\n[Mysql] --> sys_authority_menus 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&authorityMenus).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_authority_menus 表初始数据成功!")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Authority = new(authority)
|
||||
|
||||
type authority struct{}
|
||||
|
||||
var authorities = []model.SysAuthority{
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "888", AuthorityName: "普通用户", ParentId: "0", DefaultRouter: "dashboard"},
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "8881", AuthorityName: "普通用户子角色", ParentId: "888", DefaultRouter: "dashboard"},
|
||||
{CreatedAt: time.Now(), UpdatedAt: time.Now(), AuthorityId: "9528", AuthorityName: "测试角色", ParentId: "0", DefaultRouter: "dashboard"},
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_authorities 表数据初始化
|
||||
func (a *authority) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("authority_id IN ? ", []string{"888", "9528"}).Find(&[]model.SysAuthority{}).RowsAffected == 2 {
|
||||
color.Danger.Println("\n[Mysql] --> sys_authorities 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&authorities).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_authorities 表初始数据成功!")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
var AuthorityMenu = new(authorityMenu)
|
||||
|
||||
type authorityMenu struct{}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: authority_menu 视图数据初始化
|
||||
func (a *authorityMenu) Init() error {
|
||||
if global.GVA_DB.Find(&[]model.SysMenu{}).RowsAffected > 0 {
|
||||
color.Danger.Println("\n[Mysql] --> authority_menu 视图已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := global.GVA_DB.Exec("CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `authority_menu` AS select `sys_base_menus`.`id` AS `id`,`sys_base_menus`.`created_at` AS `created_at`, `sys_base_menus`.`updated_at` AS `updated_at`, `sys_base_menus`.`deleted_at` AS `deleted_at`, `sys_base_menus`.`menu_level` AS `menu_level`,`sys_base_menus`.`parent_id` AS `parent_id`,`sys_base_menus`.`path` AS `path`,`sys_base_menus`.`name` AS `name`,`sys_base_menus`.`hidden` AS `hidden`,`sys_base_menus`.`component` AS `component`, `sys_base_menus`.`title` AS `title`,`sys_base_menus`.`icon` AS `icon`,`sys_base_menus`.`sort` AS `sort`,`sys_authority_menus`.`sys_authority_authority_id` AS `authority_id`,`sys_authority_menus`.`sys_base_menu_id` AS `menu_id`,`sys_base_menus`.`keep_alive` AS `keep_alive`,`sys_base_menus`.`default_menu` AS `default_menu` from (`sys_authority_menus` join `sys_base_menus` on ((`sys_authority_menus`.`sys_base_menu_id` = `sys_base_menus`.`id`)))").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> authority_menu 视图创建成功!")
|
||||
return nil
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
gormadapter "github.com/casbin/gorm-adapter/v3"
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Carbines = []gormadapter.CasbinRule{
|
||||
var Casbin = new(casbin)
|
||||
|
||||
type casbin struct{}
|
||||
|
||||
var carbines = []gormadapter.CasbinRule{
|
||||
{PType: "p", V0: "888", V1: "/base/login", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/user/register", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/api/createApi", V2: "POST"},
|
||||
@@ -51,6 +55,7 @@ var Carbines = []gormadapter.CasbinRule{
|
||||
{PType: "p", V0: "888", V1: "/customer/customer", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/customer/customerList", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/autoCode/createTemp", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/autoCode/preview", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/autoCode/getTables", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/autoCode/getDB", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/autoCode/getColumn", V2: "GET"},
|
||||
@@ -75,6 +80,22 @@ var Carbines = []gormadapter.CasbinRule{
|
||||
{PType: "p", V0: "888", V1: "/simpleUploader/upload", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/simpleUploader/checkFileMd5", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/simpleUploader/mergeFileMd5", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/createWorkflowProcess", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/deleteWorkflowProcess", V2: "DELETE"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/deleteWorkflowProcessByIds", V2: "DELETE"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/updateWorkflowProcess", V2: "PUT"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/findWorkflowProcess", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/getWorkflowProcessList", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/findWorkflowStep", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/startWorkflow", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/completeWorkflowMove", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/getMyStated", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/getMyNeed", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/workflowProcess/getWorkflowMoveByID", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/excel/importExcel", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/excel/loadExcel", V2: "GET"},
|
||||
{PType: "p", V0: "888", V1: "/excel/exportExcel", V2: "POST"},
|
||||
{PType: "p", V0: "888", V1: "/excel/downloadTemplate", V2: "GET"},
|
||||
{PType: "p", V0: "8881", V1: "/base/login", V2: "POST"},
|
||||
{PType: "p", V0: "8881", V1: "/user/register", V2: "POST"},
|
||||
{PType: "p", V0: "8881", V1: "/api/createApi", V2: "POST"},
|
||||
@@ -152,18 +173,19 @@ var Carbines = []gormadapter.CasbinRule{
|
||||
{PType: "p", V0: "9528", V1: "/autoCode/createTemp", V2: "POST"},
|
||||
}
|
||||
|
||||
func InitCasbinModel(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("p_type = ? AND v0 IN ?", "p", []string{"888", "8881", "9528"}).Find(&[]gormadapter.CasbinRule{}).RowsAffected == 142 {
|
||||
color.Danger.Println("casbin_rule表的初始数据已存在!")
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: casbin_rule 表数据初始化
|
||||
func (c *casbin) Init() error {
|
||||
global.GVA_DB.AutoMigrate(gormadapter.CasbinRule{})
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Find(&[]gormadapter.CasbinRule{}).RowsAffected == 154 {
|
||||
color.Danger.Println("\n[Mysql] --> casbin_rule 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Carbines).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&carbines).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> casbin_rule 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> casbin_rule 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var DataAuthorities = new(dataAuthorities)
|
||||
|
||||
type dataAuthorities struct{}
|
||||
|
||||
type DataAuthority struct {
|
||||
AuthorityId string `gorm:"column:sys_authority_authority_id"`
|
||||
DataAuthority string `gorm:"column:data_authority_id_authority_id"`
|
||||
}
|
||||
|
||||
var infos = []DataAuthority{
|
||||
{"888", "888"},
|
||||
{"888", "8881"},
|
||||
{"888", "9528"},
|
||||
{"9528", "8881"},
|
||||
{"9528", "9528"},
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_data_authority_id 表数据初始化
|
||||
func (d *dataAuthorities) Init() error {
|
||||
return global.GVA_DB.Table("sys_data_authority_id").Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("sys_authority_authority_id IN ('888', '9528') ").Find(&[]DataAuthority{}).RowsAffected == 5 {
|
||||
color.Danger.Println("\n[Mysql] --> sys_data_authority_id 表初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&infos).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_data_authority_id 表初始数据成功!")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1,19 +1,25 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitSysDictionary(db *gorm.DB) {
|
||||
var status = new(bool)
|
||||
var Dictionary = new(dictionary)
|
||||
|
||||
type dictionary struct{}
|
||||
|
||||
var status = new(bool)
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_dictionaries 表数据初始化
|
||||
func (d *dictionary) Init() error {
|
||||
*status = true
|
||||
Dictionaries := []model.SysDictionary{
|
||||
var dictionaries = []model.SysDictionary{
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, Name: "性别", Type: "sex", Status: status, Desc: "性别字典"},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, Name: "数据库int类型", Type: "int", Status: status, Desc: "int类型对应的数据库类型"},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 3, CreatedAt: time.Now(), UpdatedAt: time.Now()}, Name: "数据库时间日期类型", Type: "time.Time", Status: status, Desc: "数据库时间日期类型"},
|
||||
@@ -21,17 +27,15 @@ func InitSysDictionary(db *gorm.DB) {
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 5, CreatedAt: time.Now(), UpdatedAt: time.Now()}, Name: "数据库字符串", Type: "string", Status: status, Desc: "数据库字符串"},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 6, CreatedAt: time.Now(), UpdatedAt: time.Now()}, Name: "数据库bool类型", Type: "bool", Status: status, Desc: "数据库bool类型"},
|
||||
}
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 6}).Find(&[]model.SysDictionary{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_dictionaries表的初始数据已存在!")
|
||||
color.Danger.Println("\n[Mysql] --> sys_dictionaries 表初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Dictionaries).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&dictionaries).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_dictionaries 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_dictionaries 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,19 +1,22 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func InitSysDictionaryDetail(db *gorm.DB) {
|
||||
status := new(bool)
|
||||
*status = true
|
||||
DictionaryDetail := []model.SysDictionaryDetail{
|
||||
var DictionaryDetail = new(dictionaryDetail)
|
||||
|
||||
type dictionaryDetail struct{}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: dictionary_details 表数据初始化
|
||||
func (d *dictionaryDetail) Init() error {
|
||||
var details = []model.SysDictionaryDetail{
|
||||
{global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "smallint", 1, status, 1, 2},
|
||||
{global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "mediumint", 2, status, 2, 2},
|
||||
{global.GVA_MODEL{ID: 3, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "int", 3, status, 3, 2},
|
||||
@@ -38,17 +41,15 @@ func InitSysDictionaryDetail(db *gorm.DB) {
|
||||
{global.GVA_MODEL{ID: 22, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "longtext", 9, status, 9, 5},
|
||||
{global.GVA_MODEL{ID: 23, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "tinyint", 0, status, 0, 6},
|
||||
}
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 23}).Find(&[]model.SysDictionaryDetail{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_dictionary_details表的初始数据已存在!")
|
||||
color.Danger.Println("\n[Mysql] --> sys_dictionary_details 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&DictionaryDetail).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&details).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_dictionary_details 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_dictionary_details 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,33 +1,34 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Files = []model.ExaFileUploadAndDownload{
|
||||
var File = new(file)
|
||||
|
||||
type file struct{}
|
||||
|
||||
var files = []model.ExaFileUploadAndDownload{
|
||||
{global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "10.png", "http://qmplusimg.henrongyi.top/gvalogo.png", "png", "158787308910.png"},
|
||||
{global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "logo.png", "http://qmplusimg.henrongyi.top/1576554439myAvatar.png", "png", "1587973709logo.png"},
|
||||
}
|
||||
|
||||
func InitExaFileUploadAndDownload(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: exa_file_upload_and_downloads 表初始化数据
|
||||
func (f *file) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 2}).Find(&[]model.ExaFileUploadAndDownload{}).RowsAffected == 2 {
|
||||
color.Danger.Println("exa_file_upload_and_downloads表的初始数据已存在!")
|
||||
color.Danger.Println("\n[Mysql] --> exa_file_upload_and_downloads 表初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&Files).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&files).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("[Mysql]-->初始化数据成功")
|
||||
color.Info.Println("\n[Mysql] --> exa_file_upload_and_downloads 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> exa_file_upload_and_downloads 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
package datas
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"github.com/gookit/color"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gin-vue-admin/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var BaseMenus = []model.SysBaseMenu{
|
||||
var BaseMenu = new(menu)
|
||||
|
||||
type menu struct{}
|
||||
|
||||
var menus = []model.SysBaseMenu{
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "dashboard", Name: "dashboard", Hidden: false, Component: "view/dashboard/index.vue", Sort: 1, Meta: model.Meta{Title: "仪表盘", Icon: "setting"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "about", Name: "about", Component: "view/about/index.vue", Sort: 7, Meta: model.Meta{Title: "关于我们", Icon: "info"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 3, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "admin", Name: "superAdmin", Component: "view/superAdmin/index.vue", Sort: 3, Meta: model.Meta{Title: "超级管理员", Icon: "user-solid"}},
|
||||
@@ -20,38 +23,40 @@ var BaseMenus = []model.SysBaseMenu{
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 7, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "user", Name: "user", Component: "view/superAdmin/user/user.vue", Sort: 4, Meta: model.Meta{Title: "用户管理", Icon: "coordinate"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 8, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: true, ParentId: "0", Path: "person", Name: "person", Component: "view/person/person.vue", Sort: 4, Meta: model.Meta{Title: "个人信息", Icon: "message-solid"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 9, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "example", Name: "example", Component: "view/example/index.vue", Sort: 6, Meta: model.Meta{Title: "示例文件", Icon: "s-management"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 10, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "table", Name: "table", Component: "view/example/table/table.vue", Sort: 1, Meta: model.Meta{Title: "表格示例", Icon: "s-order"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 11, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "form", Name: "form", Component: "view/example/form/form.vue", Sort: 2, Meta: model.Meta{Title: "表单示例", Icon: "document"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 12, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "rte", Name: "rte", Component: "view/example/rte/rte.vue", Sort: 3, Meta: model.Meta{Title: "富文本编辑器", Icon: "reading"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 13, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "excel", Name: "excel", Component: "view/example/excel/excel.vue", Sort: 4, Meta: model.Meta{Title: "excel导入导出", Icon: "s-marketing"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 14, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "upload", Name: "upload", Component: "view/example/upload/upload.vue", Sort: 5, Meta: model.Meta{Title: "上传下载", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 15, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "breakpoint", Name: "breakpoint", Component: "view/example/breakpoint/breakpoint.vue", Sort: 6, Meta: model.Meta{Title: "断点续传", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 16, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "customer", Name: "customer", Component: "view/example/customer/customer.vue", Sort: 7, Meta: model.Meta{Title: "客户列表(资源示例)", Icon: "s-custom"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 17, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "systemTools", Name: "systemTools", Component: "view/systemTools/index.vue", Sort: 5, Meta: model.Meta{Title: "系统工具", Icon: "s-cooperation"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 18, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "17", Path: "autoCode", Name: "autoCode", Component: "view/systemTools/autoCode/index.vue", Sort: 1, Meta: model.Meta{Title: "代码生成器", Icon: "cpu", KeepAlive: true}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 19, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "17", Path: "formCreate", Name: "formCreate", Component: "view/systemTools/formCreate/index.vue", Sort: 2, Meta: model.Meta{Title: "表单生成器", Icon: "magic-stick", KeepAlive: true}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 20, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "17", Path: "system", Name: "system", Component: "view/systemTools/system/system.vue", Sort: 3, Meta: model.Meta{Title: "系统配置", Icon: "s-operation"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 21, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "iconList", Name: "iconList", Component: "view/iconList/index.vue", Sort: 2, Meta: model.Meta{Title: "图标集合", Icon: "star-on"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 22, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "dictionary", Name: "dictionary", Component: "view/superAdmin/dictionary/sysDictionary.vue", Sort: 5, Meta: model.Meta{Title: "字典管理", Icon: "notebook-2"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 23, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: true, ParentId: "3", Path: "dictionaryDetail/:id", Name: "dictionaryDetail", Component: "view/superAdmin/dictionary/sysDictionaryDetail.vue", Sort: 1, Meta: model.Meta{Title: "字典详情", Icon: "s-order"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 24, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "operation", Name: "operation", Component: "view/superAdmin/operation/sysOperationRecord.vue", Sort: 6, Meta: model.Meta{Title: "操作历史", Icon: "time"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 25, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "simpleUploader", Name: "simpleUploader", Component: "view/example/simpleUploader/simpleUploader", Sort: 6, Meta: model.Meta{Title: "断点续传(插件版)", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 26, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "https://www.gin-vue-admin.com", Name: "https://www.gin-vue-admin.com", Hidden: false, Component: "/", Sort: 0, Meta: model.Meta{Title: "官方网站", Icon: "s-home"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 27, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "state", Name: "state", Hidden: false, Component: "view/system/state.vue", Sort: 6, Meta: model.Meta{Title: "服务器状态", Icon: "cloudy"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 10, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "excel", Name: "excel", Component: "view/example/excel/excel.vue", Sort: 4, Meta: model.Meta{Title: "excel导入导出", Icon: "s-marketing"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 11, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "upload", Name: "upload", Component: "view/example/upload/upload.vue", Sort: 5, Meta: model.Meta{Title: "媒体库(上传下载)", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 12, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "breakpoint", Name: "breakpoint", Component: "view/example/breakpoint/breakpoint.vue", Sort: 6, Meta: model.Meta{Title: "断点续传", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 13, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "customer", Name: "customer", Component: "view/example/customer/customer.vue", Sort: 7, Meta: model.Meta{Title: "客户列表(资源示例)", Icon: "s-custom"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 14, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "0", Path: "systemTools", Name: "systemTools", Component: "view/systemTools/index.vue", Sort: 5, Meta: model.Meta{Title: "系统工具", Icon: "s-cooperation"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 15, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "14", Path: "autoCode", Name: "autoCode", Component: "view/systemTools/autoCode/index.vue", Sort: 1, Meta: model.Meta{Title: "代码生成器", Icon: "cpu", KeepAlive: true}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 16, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "14", Path: "formCreate", Name: "formCreate", Component: "view/systemTools/formCreate/index.vue", Sort: 2, Meta: model.Meta{Title: "表单生成器", Icon: "magic-stick", KeepAlive: true}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 17, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "14", Path: "system", Name: "system", Component: "view/systemTools/system/system.vue", Sort: 3, Meta: model.Meta{Title: "系统配置", Icon: "s-operation"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 18, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "dictionary", Name: "dictionary", Component: "view/superAdmin/dictionary/sysDictionary.vue", Sort: 5, Meta: model.Meta{Title: "字典管理", Icon: "notebook-2"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 19, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: true, ParentId: "3", Path: "dictionaryDetail/:id", Name: "dictionaryDetail", Component: "view/superAdmin/dictionary/sysDictionaryDetail.vue", Sort: 1, Meta: model.Meta{Title: "字典详情", Icon: "s-order"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 20, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "operation", Name: "operation", Component: "view/superAdmin/operation/sysOperationRecord.vue", Sort: 6, Meta: model.Meta{Title: "操作历史", Icon: "time"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 21, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "simpleUploader", Name: "simpleUploader", Component: "view/example/simpleUploader/simpleUploader", Sort: 6, Meta: model.Meta{Title: "断点续传(插件版)", Icon: "upload"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 22, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "https://www.gin-vue-admin.com", Name: "https://www.gin-vue-admin.com", Hidden: false, Component: "/", Sort: 0, Meta: model.Meta{Title: "官方网站", Icon: "s-home"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 23, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "state", Name: "state", Hidden: false, Component: "view/system/state.vue", Sort: 6, Meta: model.Meta{Title: "服务器状态", Icon: "cloudy"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 24, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "workflow", Name: "workflow", Hidden: false, Component: "view/workflow/index.vue", Sort: 5, Meta: model.Meta{Title: "工作流功能", Icon: "phone"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 25, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "24", Path: "workflowCreate", Name: "workflowCreate", Hidden: false, Component: "view/workflow/workflowCreate/workflowCreate.vue", Sort: 0, Meta: model.Meta{Title: "工作流绘制", Icon: "circle-plus"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 26, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "24", Path: "workflowProcess", Name: "workflowProcess", Hidden: false, Component: "view/workflow/workflowProcess/workflowProcess.vue", Sort: 0, Meta: model.Meta{Title: "工作流列表", Icon: "s-cooperation"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 27, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "24", Path: "workflowUse", Name: "workflowUse", Hidden: true, Component: "view/workflow/workflowUse/workflowUse.vue", Sort: 0, Meta: model.Meta{Title: "使用工作流", Icon: "video-play"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 28, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "24", Path: "started", Name: "started", Hidden: false, Component: "view/workflow/userList/started.vue", Sort: 0, Meta: model.Meta{Title: "我发起的", Icon: "s-order"}},
|
||||
{GVA_MODEL: global.GVA_MODEL{ID: 29, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "24", Path: "need", Name: "need", Hidden: false, Component: "view/workflow/userList/need.vue", Sort: 0, Meta: model.Meta{Title: "我的待办", Icon: "s-platform"}},
|
||||
}
|
||||
|
||||
func InitSysBaseMenus(db *gorm.DB) {
|
||||
if err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 27}).Find(&[]model.SysBaseMenu{}).RowsAffected == 2 {
|
||||
color.Danger.Println("sys_base_menus表的初始数据已存在!")
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: sys_base_menus 表数据初始化
|
||||
func (m *menu) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []int{1, 29}).Find(&[]model.SysBaseMenu{}).RowsAffected == 2 {
|
||||
color.Danger.Println("\n[Mysql] --> sys_base_menus 表的初始数据已存在!")
|
||||
return nil
|
||||
}
|
||||
if err := tx.Create(&BaseMenus).Error; err != nil { // 遇到错误时回滚事务
|
||||
if err := tx.Create(&menus).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> sys_base_menus 表初始数据成功!")
|
||||
return nil
|
||||
}); err != nil {
|
||||
color.Warn.Printf("[Mysql]--> sys_base_menus 表的初始数据失败,err: %v\n", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Workflow = new(workflow)
|
||||
|
||||
type workflow struct{}
|
||||
|
||||
var WorkflowProcess = []model.WorkflowProcess{
|
||||
{ID: "leaveFlow", CreatedAt: time.Now(), UpdatedAt: time.Now(), Name: "leaveFlow", Clazz: "process", Label: "请假流程(演示)", HideIcon: false, Description: "请假流程演示", View: "view/iconList/index.vue"},
|
||||
}
|
||||
|
||||
var WorkflowNodes = []model.WorkflowNode{
|
||||
{ID: "end1603681358043", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "end", Label: "请假失败", Type: "end-node", Shape: "end-node", Description: "", View: "view/exa_wf_leave/exa_wf_leaveFrom.vue", X: 302, Y: 545.5, HideIcon: false, AssignType: "", AssignValue: "", Success: false},
|
||||
{ID: "end1603681360882", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "end", Label: "请假成功", Type: "end-node", Shape: "end-node", Description: "请假完成,具体结果等待提交", View: "view/exa_wf_leave/exa_wf_leaveFrom.vue", X: 83.5, Y: 546, HideIcon: false, AssignType: "", AssignValue: "", Success: true},
|
||||
{ID: "start1603681292875", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "start", Label: "发起请假", Type: "start-node", Shape: "start-node", Description: "发起一个请假流程", View: "view/exa_wf_leave/exa_wf_leaveFrom.vue", X: 201, Y: 109, HideIcon: false, AssignType: "", AssignValue: "", Success: false},
|
||||
{ID: "userTask1603681299962", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "userTask", Label: "审批", Type: "user-task-node", Shape: "user-task-node", Description: "审批会签", View: "view/exa_wf_leave/exa_wf_leaveFrom.vue", X: 202, Y: 320.5, HideIcon: false, AssignType: "user", AssignValue: ",1,2,", Success: false},
|
||||
}
|
||||
var WorkflowEdge = []model.WorkflowEdge{
|
||||
{ID: "flow1604985849039", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "flow", Source: "start1603681292875", Target: "userTask1603681299962", SourceAnchor: 1, TargetAnchor: 3, Shape: "flow-polyline-round", Label: "", HideIcon: false, ConditionExpression: "", Reverse: false},
|
||||
{ID: "flow1604985879574", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "flow", Source: "userTask1603681299962", Target: "end1603681360882", SourceAnchor: 0, TargetAnchor: 2, Shape: "flow-polyline-round", Label: "同意", HideIcon: false, ConditionExpression: "yes", Reverse: false},
|
||||
{ID: "flow1604985881207", CreatedAt: time.Now(), UpdatedAt: time.Now(), WorkflowProcessID: "leaveFlow", Clazz: "flow", Source: "userTask1603681299962", Target: "end1603681358043", SourceAnchor: 2, TargetAnchor: 2, Shape: "flow-polyline-round", Label: "不同意", HideIcon: false, ConditionExpression: "no", Reverse: false},
|
||||
}
|
||||
var WorkflowStartPoint = []model.WorkflowStartPoint{
|
||||
{WorkflowEdgeID: "flow1604985849039", GVA_MODEL: global.GVA_MODEL{ID: 31, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 137, Y: 201, Index: 1},
|
||||
{WorkflowEdgeID: "flow1604985879574", GVA_MODEL: global.GVA_MODEL{ID: 32, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 320.5, Y: 174, Index: 0},
|
||||
{WorkflowEdgeID: "flow1604985881207", GVA_MODEL: global.GVA_MODEL{ID: 33, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 320.5, Y: 230, Index: 2},
|
||||
}
|
||||
|
||||
var WorkflowEndPoint = []model.WorkflowEndPoint{
|
||||
{WorkflowEdgeID: "flow1604985849039", GVA_MODEL: global.GVA_MODEL{ID: 31, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 270, Y: 202, Index: 3},
|
||||
{WorkflowEdgeID: "flow1604985879574", GVA_MODEL: global.GVA_MODEL{ID: 32, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 518, Y: 83.5, Index: 2},
|
||||
{WorkflowEdgeID: "flow1604985881207", GVA_MODEL: global.GVA_MODEL{ID: 33, CreatedAt: time.Now(), UpdatedAt: time.Now()}, X: 517.5, Y: 302, Index: 2},
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@description: 工作流相关 表数据初始化
|
||||
func (w *workflow) Init() error {
|
||||
return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
if tx.Where("id IN ?", []string{"leaveFlow"}).Find(&[]model.WorkflowProcess{}).RowsAffected == 1 {
|
||||
// continue
|
||||
} else if err := tx.Create(&WorkflowProcess).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
|
||||
if tx.Where("id IN ?", []string{"end1603681358043", "end1603681360882", "start1603681292875", "userTask1603681299962"}).Find(&[]model.WorkflowNode{}).RowsAffected == 4 {
|
||||
// continue
|
||||
} else if err := tx.Create(&WorkflowNodes).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
|
||||
if tx.Where("id IN ?", []string{"flow1604985849039", "flow1604985879574", "flow1604985881207"}).Find(&[]model.WorkflowEdge{}).RowsAffected == 3 {
|
||||
|
||||
} else if err := tx.Create(&WorkflowEdge).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
|
||||
if tx.Where("workflow_edge_id IN ?", []string{"flow1604985849039", "flow1604985879574", "flow1604985881207"}).Find(&[]model.WorkflowStartPoint{}).RowsAffected == 3 {
|
||||
|
||||
} else if err := tx.Create(&WorkflowStartPoint).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
|
||||
if tx.Where("workflow_edge_id IN ?", []string{"flow1604985849039", "flow1604985879574", "flow1604985881207"}).Find(&[]model.WorkflowEndPoint{}).RowsAffected == 3 {
|
||||
|
||||
} else if err := tx.Create(&WorkflowEndPoint).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
}
|
||||
color.Info.Println("\n[Mysql] --> 工作流相关 表初始数据成功!")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -55,7 +55,6 @@ func CheckMd5(content []byte, chunkMd5 string) (CanUpload bool) {
|
||||
func makeFileContent(content []byte, fileName string, FileDir string, contentNumber int) (error, string) {
|
||||
path := FileDir + fileName + "_" + strconv.Itoa(contentNumber)
|
||||
f, err := os.Create(path)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
return err, path
|
||||
} else {
|
||||
@@ -64,6 +63,7 @@ func makeFileContent(content []byte, fileName string, FileDir string, contentNum
|
||||
return err, path
|
||||
}
|
||||
}
|
||||
defer f.Close()
|
||||
return nil, path
|
||||
}
|
||||
|
||||
@@ -79,7 +79,11 @@ func MakeFile(fileName string, FileMd5 string) (error, string) {
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
_ = os.MkdirAll(finishDir, os.ModePerm)
|
||||
fd, _ := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
fd, err := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
defer fd.Close()
|
||||
for k := range rd {
|
||||
content, _ := ioutil.ReadFile(breakpointDir + FileMd5 + "/" + fileName + "_" + strconv.Itoa(k))
|
||||
_, err = fd.Write(content)
|
||||
@@ -88,7 +92,7 @@ func MakeFile(fileName string, FileMd5 string) (error, string) {
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
return nil, finishDir + fileName
|
||||
}
|
||||
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@interface_name: RunTask
|
||||
//@description: Task接口
|
||||
|
||||
type RunTask interface {
|
||||
AddTask()
|
||||
RunTask()
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@struct_name: T
|
||||
//@description: Task任务
|
||||
|
||||
type T struct {
|
||||
sync.Mutex
|
||||
|
||||
// 获取事件channel
|
||||
ch chan struct{}
|
||||
|
||||
closeChan chan struct{}
|
||||
|
||||
// 记录process对象
|
||||
p *os.Process
|
||||
|
||||
// 执行任务
|
||||
f func(chan struct{}) error
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: NewT
|
||||
//@description: T的实例化方法
|
||||
//@return: *T
|
||||
|
||||
func NewT() *T {
|
||||
return newT(nil)
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: newT
|
||||
//@description:
|
||||
//@param: f func(chan struct{}) error
|
||||
//@return: *T
|
||||
|
||||
func newT(f func(chan struct{}) error) *T {
|
||||
t := &T{
|
||||
Mutex: sync.Mutex{},
|
||||
ch: make(chan struct{}, 1),
|
||||
closeChan: make(chan struct{}),
|
||||
f: f,
|
||||
}
|
||||
if f == nil {
|
||||
t.f = t.DefaultF
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: *T
|
||||
//@function: AddTask
|
||||
//@description: 添加任务
|
||||
|
||||
func (t *T) AddTask() {
|
||||
if len(t.ch) == 1 {
|
||||
return
|
||||
}
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
if len(t.ch) == 1 {
|
||||
// 代表已经有任务了
|
||||
// 直接丢弃这次任务
|
||||
return
|
||||
}
|
||||
t.ch <- struct{}{}
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: *T
|
||||
//@function: RunTask
|
||||
//@description: 启动任务
|
||||
|
||||
func (t *T) RunTask() {
|
||||
fmt.Println("进入")
|
||||
// 这里做的make 是用于关闭上一个执行的任务
|
||||
ch := make(chan struct{})
|
||||
// 先run服务
|
||||
go t.f(ch)
|
||||
for {
|
||||
_, ok := <-t.ch
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- struct{}{}
|
||||
// 等待上一个关闭
|
||||
<-t.closeChan
|
||||
go t.f(ch)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: t *T
|
||||
//@function: DefaultF
|
||||
//@description: 默认的StartFunction
|
||||
//@param: ch chan struct{}
|
||||
//@return: error
|
||||
|
||||
func (t *T) DefaultF(ch chan struct{}) error {
|
||||
var buildCmd *exec.Cmd
|
||||
var cmd *exec.Cmd
|
||||
|
||||
// 检测系统是否有编译环境
|
||||
_, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// build
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
buildCmd = exec.Command("go", "build", "-o", "server.exe", "main.go")
|
||||
default:
|
||||
buildCmd = exec.Command("go", "build", "-o", "server", "main.go")
|
||||
}
|
||||
//cmd = exec.Command("go", "run", "main.go")
|
||||
err = buildCmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("build 执行完成")
|
||||
// 执行
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
cmd = exec.Command("server.exe")
|
||||
default:
|
||||
cmd = exec.Command("./server")
|
||||
}
|
||||
|
||||
// 开始执行任务
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
err = t.echo(cmd, ctx)
|
||||
<-ch
|
||||
// 回收资源
|
||||
fmt.Println("pid:", t.p.Pid, "->Kill")
|
||||
err = t.p.Kill()
|
||||
cancel()
|
||||
// 发送关闭完成信号
|
||||
t.closeChan <- struct{}{}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: t *T
|
||||
//@function: echo
|
||||
//@description: 封装回显
|
||||
//@param: cmd *exec.Cmd, ctx context.Context
|
||||
//@return: error
|
||||
|
||||
func (t *T) echo(cmd *exec.Cmd, ctx context.Context) error {
|
||||
var stdoutBuf bytes.Buffer
|
||||
stdoutIn, _ := cmd.StdoutPipe()
|
||||
var errStdout error
|
||||
stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func(ctx context.Context) {
|
||||
_, errStdout = io.Copy(stdout, stdoutIn)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
}(ctx)
|
||||
t.p = cmd.Process
|
||||
fmt.Println("pid", t.p.Pid)
|
||||
go func() {
|
||||
_ = cmd.Wait()
|
||||
if errStdout != nil {
|
||||
fmt.Printf("failed to capture stdout or stderr\n")
|
||||
}
|
||||
fmt.Printf("%s\n", string(stdoutBuf.Bytes()))
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
//_ = os.Stdout.Close()
|
||||
return
|
||||
default:
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@struct_name: Watch
|
||||
//@description: 监控对象
|
||||
|
||||
type Watch struct {
|
||||
*fsnotify.Watcher
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: NewWatch
|
||||
//@description: Watch的实例化方法
|
||||
//@return: *Watch
|
||||
|
||||
func NewWatch() *Watch {
|
||||
obj, _ := fsnotify.NewWatcher()
|
||||
return &Watch{obj}
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: Watch
|
||||
//@description: 监控对象
|
||||
//@param: path string, t *T
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) Watch(path string, t *T) error {
|
||||
// 先转化为绝对路径
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断是单个文件还是目录文件
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断是否是目录 添加监控
|
||||
if fileInfo.IsDir() {
|
||||
// dir
|
||||
err = w.watchDir(path)
|
||||
|
||||
} else {
|
||||
err = w.watchFile(path)
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c := make(chan error)
|
||||
// 启动监控
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case even, ok := <-w.Events:
|
||||
if !ok {
|
||||
// close
|
||||
fmt.Println("Errors close")
|
||||
c <- errors.New("errors close")
|
||||
return
|
||||
}
|
||||
// 判断事件
|
||||
switch {
|
||||
case even.Op&fsnotify.Create == fsnotify.Create:
|
||||
//这里获取新创建文件的信息,如果是目录,则加入监控中
|
||||
fmt.Println("创建文件 : ", even.Name)
|
||||
//t.AddTask()
|
||||
_ = w.Add(even.Name)
|
||||
case even.Op&fsnotify.Write == fsnotify.Write:
|
||||
fmt.Println("修改文件 : ", even.Name)
|
||||
w.addTask(t, even.Name)
|
||||
case even.Op&fsnotify.Remove == fsnotify.Remove || even.Op&fsnotify.Rename == fsnotify.Rename:
|
||||
fmt.Println("删除或重命名文件 : ", even.Name)
|
||||
_ = w.Remove(even.Name)
|
||||
w.addTask(t, even.Name)
|
||||
}
|
||||
case err = <-w.Errors:
|
||||
fmt.Println("even Error:", err)
|
||||
c <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return <-c
|
||||
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: watchDir
|
||||
//@description: 处理监控目录
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) watchDir(path string) error {
|
||||
// 先将自己添加到监控
|
||||
err := w.Add(path)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileSlice, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range fileSlice {
|
||||
fPath := filepath.Join(path, f.Name())
|
||||
if !f.IsDir() {
|
||||
// 判断是否可监控的文件
|
||||
if chickPower(fPath) {
|
||||
err = w.watchFile(fPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := w.watchDir(fPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: watchDir
|
||||
//@description: 处理监控单文件
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) watchFile(path string) error {
|
||||
var err error
|
||||
if chickPower(path) {
|
||||
err = w.Add(path)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: chickPower
|
||||
//@description: 判断是否在可控范围内
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func chickPower(name string) bool {
|
||||
name = filepath.Ext(name)
|
||||
return name == ".go" || name == ".yaml"
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: addTask
|
||||
//@description: 偏函数 简化发送任务
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) addTask(t *T, name string) {
|
||||
if chickPower(name) {
|
||||
fmt.Println("Add Task->>>>>>")
|
||||
t.AddTask()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"go.uber.org/zap"
|
||||
"mime/multipart"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AliyunOSS struct{}
|
||||
|
||||
func (*AliyunOSS) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
bucket, err := NewBucket()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error()))
|
||||
return "", "", errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
// 读取本地文件。
|
||||
f, openError := file.Open()
|
||||
if openError != nil {
|
||||
global.GVA_LOG.Error("function file.Open() Failed", zap.Any("err", openError.Error()))
|
||||
return "", "", errors.New("function file.Open() Failed, err:" + openError.Error())
|
||||
}
|
||||
|
||||
//上传阿里云路径 文件名格式 自己可以改 建议保证唯一性
|
||||
yunFileTmpPath := filepath.Join("uploads", time.Now().Format("2006-01-02")) + "/" + file.Filename
|
||||
|
||||
// 上传文件流。
|
||||
err = bucket.PutObject(yunFileTmpPath, f)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("function formUploader.Put() Failed", zap.Any("err", err.Error()))
|
||||
return "", "", errors.New("function formUploader.Put() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
return global.GVA_CONFIG.AliyunOSS.BucketUrl + "/" + yunFileTmpPath, yunFileTmpPath, nil
|
||||
}
|
||||
|
||||
func (*AliyunOSS) DeleteFile(key string) error {
|
||||
bucket, err := NewBucket()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error()))
|
||||
return errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
// 删除单个文件。objectName表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
|
||||
// 如需删除文件夹,请将objectName设置为对应的文件夹名称。如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。
|
||||
err = bucket.DeleteObject(key)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error()))
|
||||
return errors.New("function bucketManager.Delete() Filed, err:" + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewBucket() (*oss.Bucket, error) {
|
||||
// 创建OSSClient实例。
|
||||
client, err := oss.New(global.GVA_CONFIG.AliyunOSS.Endpoint, global.GVA_CONFIG.AliyunOSS.AccessKeyId, global.GVA_CONFIG.AliyunOSS.AccessKeySecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取存储空间。
|
||||
bucket, err := client.Bucket(global.GVA_CONFIG.AliyunOSS.BucketName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bucket, nil
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/tencentyun/cos-go-sdk-v5"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type TencentCOS struct{}
|
||||
|
||||
// UploadFile upload file to COS
|
||||
func (*TencentCOS) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
client := NewClient()
|
||||
f, openError := file.Open()
|
||||
if openError != nil {
|
||||
global.GVA_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
|
||||
return "", "", errors.New("function file.Open() Filed, err:" + openError.Error())
|
||||
}
|
||||
fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename)
|
||||
|
||||
_, err := client.Object.Put(context.Background(), global.GVA_CONFIG.TencentCOS.PathPrefix+"/"+fileKey, f, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return global.GVA_CONFIG.TencentCOS.BaseURL + "/" + global.GVA_CONFIG.TencentCOS.PathPrefix + "/" + fileKey, fileKey, nil
|
||||
}
|
||||
|
||||
// DeleteFile delete file form COS
|
||||
func (*TencentCOS) DeleteFile(key string) error {
|
||||
client := NewClient()
|
||||
name := global.GVA_CONFIG.TencentCOS.PathPrefix + "/" + key
|
||||
_, err := client.Object.Delete(context.Background(), name)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error()))
|
||||
return errors.New("function bucketManager.Delete() Filed, err:" + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewClient init COS client
|
||||
func NewClient() *cos.Client {
|
||||
urlStr, _ := url.Parse("https://" + global.GVA_CONFIG.TencentCOS.Bucket + ".cos." + global.GVA_CONFIG.TencentCOS.Region + ".myqcloud.com")
|
||||
baseURL := &cos.BaseURL{BucketURL: urlStr}
|
||||
client := cos.NewClient(baseURL, &http.Client{
|
||||
Transport: &cos.AuthorizationTransport{
|
||||
SecretID: global.GVA_CONFIG.TencentCOS.SecretID,
|
||||
SecretKey: global.GVA_CONFIG.TencentCOS.SecretKey,
|
||||
},
|
||||
})
|
||||
return client
|
||||
}
|
||||
@@ -28,7 +28,11 @@ func NewOss() OSS {
|
||||
return &Local{}
|
||||
case "qiniu":
|
||||
return &Qiniu{}
|
||||
case "tencent-cos":
|
||||
return &TencentCOS{}
|
||||
case "aliyun-oss":
|
||||
return &AliyunOSS{}
|
||||
default:
|
||||
return &Local{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,10 @@ var (
|
||||
MenuVerify = Rules{"Path": {NotEmpty()}, "ParentId": {NotEmpty()}, "Name": {NotEmpty()}, "Component": {NotEmpty()}, "Sort": {Ge("0")}}
|
||||
MenuMetaVerify = Rules{"Title": {NotEmpty()}}
|
||||
LoginVerify = Rules{"CaptchaId": {NotEmpty()}, "Captcha": {NotEmpty()}, "Username": {NotEmpty()}, "Password": {NotEmpty()}}
|
||||
SetUserVerify = Rules{"ID": {NotEmpty()}, "Username": {NotEmpty()}, "NickName": {NotEmpty()}, "HeaderImg": {NotEmpty()}}
|
||||
RegisterVerify = Rules{"Username": {NotEmpty()}, "NickName": {NotEmpty()}, "Password": {NotEmpty()}, "AuthorityId": {NotEmpty()}}
|
||||
PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}}
|
||||
CustomerVerify = Rules{"CustomerName": {NotEmpty()}, "CustomerPhoneData": {NotEmpty()}}
|
||||
AutoCodeVerify = Rules{"Abbreviation": {NotEmpty()}, "StructName": {NotEmpty()}, "PackageName": {NotEmpty()}, "Fields": {NotEmpty()}}
|
||||
WorkFlowVerify = Rules{"WorkflowNickName": {NotEmpty()}, "WorkflowName": {NotEmpty()}, "WorkflowDescription": {NotEmpty()}, "WorkflowStepInfo": {NotEmpty()}}
|
||||
AuthorityVerify = Rules{"AuthorityId": {NotEmpty()}, "AuthorityName": {NotEmpty()}, "ParentId": {NotEmpty()}}
|
||||
AuthorityIdVerify = Rules{"AuthorityId": {NotEmpty()}}
|
||||
OldAuthorityVerify = Rules{"OldAuthorityId": {NotEmpty()}}
|
||||
|
||||
+40
-31
@@ -13,51 +13,60 @@ import (
|
||||
//@param: filename string, files []string, oldform, newform string
|
||||
//@return: error
|
||||
|
||||
func ZipFiles(filename string, files []string, oldform, newform string) error {
|
||||
func ZipFiles(filename string, files []string, oldForm, newForm string) error {
|
||||
|
||||
newZipFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer newZipFile.Close()
|
||||
defer func() {
|
||||
_ = newZipFile.Close()
|
||||
}()
|
||||
|
||||
zipWriter := zip.NewWriter(newZipFile)
|
||||
defer zipWriter.Close()
|
||||
defer func() {
|
||||
_ = zipWriter.Close()
|
||||
}()
|
||||
|
||||
// 把files添加到zip中
|
||||
for _, file := range files {
|
||||
|
||||
zipfile, err := os.Open(file)
|
||||
err = func(file string) error {
|
||||
zipFile, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
// 获取file的基础信息
|
||||
info, err := zipFile.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 使用上面的FileInforHeader() 就可以把文件保存的路径替换成我们自己想要的了,如下面
|
||||
header.Name = strings.Replace(file, oldForm, newForm, -1)
|
||||
|
||||
// 优化压缩
|
||||
// 更多参考see http://golang.org/pkg/archive/zip/#pkg-constants
|
||||
header.Method = zip.Deflate
|
||||
|
||||
writer, err := zipWriter.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.Copy(writer, zipFile); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipfile.Close()
|
||||
|
||||
// 获取file的基础信息
|
||||
info, err := zipfile.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 使用上面的FileInforHeader() 就可以把文件保存的路径替换成我们自己想要的了,如下面
|
||||
header.Name = strings.Replace(file, oldform, newform, -1)
|
||||
|
||||
// 优化压缩
|
||||
// 更多参考see http://golang.org/pkg/archive/zip/#pkg-constants
|
||||
header.Method = zip.Deflate
|
||||
|
||||
writer, err := zipWriter.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.Copy(writer, zipfile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user