提交 de2f183b 编写于 作者: G Granty1

Merge branch 'master' of https://github.com/flipped-aurora/gin-vue-admin into action-ci

### Contributing Guide
#### 1 Issue Guidelines
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
- Before submitting an issue, please check if similar problems have already been issued.
#### 2 Pull Request Guidelines
- Fork this repository to your own account. Do not create branches here.
- Commit info should be formatted as `[File Name]: Info about commit.` (e.g. `README.md: Fix xxx bug`)
- <font color=red>Make sure PRs are created to `develop` branch instead of `master` branch.</font>
- If your PR fixes a bug, please provide a description about the related bug.
- Merging a PR takes two maintainers: one approves the changes after reviewing, and then the other reviews and merges.
......@@ -7,7 +7,7 @@
<img src="https://img.shields.io/badge/gin-1.4.0-lightBlue"/>
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen"/>
<img src="https://img.shields.io/badge/element--ui-2.12.0-green"/>
<img src="https://img.shields.io/badge/gorm-1.9.10-red"/>
<img src="https://img.shields.io/badge/gorm-1.9.12-red"/>
</div>
[English](./README.md) | 简体中文
......@@ -50,9 +50,9 @@ Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-adm
### 1.3 版本列表
- master: 2.0 dev code, for prod
- master: 2.0, 用于生产环境
- develop: 2.0 dev code, for test
- develop: 2.0, 用于测试环境
- [gin-vue-admin_v2.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v2_dev) (v2.0 不再兼容 v1.0)
......@@ -61,8 +61,6 @@ Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-adm
- [gin-vue-admin_v1.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v1_dev) (v1.0 稳定版,会持续更新和维护)
## 2. 使用说明
```
......@@ -101,7 +99,7 @@ go list (go mod tidy)
go build
```
### 2.3 生成swagger自动化API文档
### 2.3 swagger自动化API文档
#### 2.3.1 安装 swagger
......@@ -132,30 +130,6 @@ swag init
````
执行上面的命令后,server目录下会出现docs文件夹,登录http://localhost:8888/swagger/index.html,即可查看swagger文档
### 2.4 docker镜像
感谢 [@chenlinzhong](https://github.com/chenlinzhong)提供的docker镜像.
```
# 启动容器
docker run -itd --net=host --name=go_container shareclz/go_node /bin/bash;
# 进入容器
docker exec -it go_container /bin/bash;
git clone https://github.com/piexlmax/gin-vue-admin.git /data1/www/htdocs/go/admin;
# 启动前端
cd /data1/www/htdocs/go/admin/QMPlusVuePage;
cnpm i ;
npm run serve;
# 修改数据库配置
vi /data1/www/htdocs/go/admin/QMPlusServer/static/dbconfig/config.json;
# 启动后端
cd /data1/www/htdocs/go/admin/QMPlusServer;z
go run main.go;
```
## 3. 技术选型
......@@ -168,7 +142,16 @@ go run main.go;
- 日志:使用`go-logging`实现日志记录。
## 4. 项目目录
## 4. 项目架构
### 4.1 系统架构图
![系统架构图](./docs/gin-vue-admin.png)
### 4.2 前端详细设计图 (提供者:<a href="https://github.com/baobeisuper">baobeisuper</a>)
![前端详细设计图](http://qmplusimg.henrongyi.top/naotu.png)
### 4.3 目录结构
```
├─server (后端文件夹)
......@@ -228,55 +211,41 @@ go run main.go;
- [ ] 工作流,任务交接功能开发
- [ ] 单独前端使用模式以及数据模拟
## 7. 更新日志
| 日期 | 日志 |
| :---: | --- |
|2020/01/07| 角色增加数据资源功能 增加数据资源关联返回 演示环境代码已同步 开启了多点登录拦截 可能会被其他人挤掉 |
|2020/01/13| 增加了配置管理功能 此功能不发表至测试环境 待保护机制以及服务重启机制发开完成后才会发表值测试环境 请自行clone且导入sql体验 |
|2020/02/21| 修改了casbin的自定义鉴权方法,使其完全支持RESTFUL的/:params以及?query= 的接口模式 |
|2020/03/17| 增加了验证码功能 使用了 [@dchest/captcha](https://github.com/dchest/captcha)库 |
|2020/03/30| 代码生成器开发完成 表单生成器开发完成 使用了[@form-generator](https://github.com/JakHuang/form-generator) 库 |
|2020/04/01| 增加前端历史页签功能,增加(修改)条件查询示例,前端背景色调修改为白色。(如不需要此功能可以在`web/src/view/layout/index.vue`中屏蔽`HistoryComponent`背景色调,为本页260行&.el-main中的`background`属性) |
|2020/04/04| 启动2.x版本,项目文档规范化,日志功能改造,方法增加英文注释 |
|2020/04/24|1.增加了角色拷贝功能(目前只支持单角色拷贝)<br>2.增加了首页音频播放器示例 增加了 dotolist工具<br>3.增加了docker支持<br>4.修复了部分total返回0的bug<br>5.修复了首页会发送一次无用404请求的bug<br>6.修复了swagger不能携带token的bug<br>7.修复菜单展示下级只有一个隐藏菜单时候的交互错误<br>8.修复了config从前端控制变化时候导致yaml内部的key名称错误的bug<br>9.数据库添加拷贝角色相关api和权限|
## 8. 团队博客
## 7. 知识库
## 7.1 团队博客
> https://blog.henrongyi.top
> https://www.yuque.com/flipped-aurora
>
>内有前端框架教学视频。如果觉得项目对您有所帮助可以添加我的个人微信:shouzi_1994,欢迎您提出宝贵的需求。
## 9. 教学视频
### 9.1 环境搭建
## 7.2 教学视频
(1)环境搭建
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/ (v1.0版本视频,v2.0操作相同目录不同)
### 9.2 模板使用
(2)模板使用
> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/ (v1.0版本视频,v2.0操作相同目录不同)
### 9.3 golang基础教学视频录制中...
(3)2.0目录以及开发体验
> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
> 地址:https://space.bilibili.com/322210472/channel/detail?cid=108884
## 10. 联系方式
(4)golang基础教学视频录制中...
> https://space.bilibili.com/322210472/channel/detail?cid=108884
## 8. 联系方式
### 8.1 技术群
| QQ群 |
| :---: |
| <img src="http://qmplusimg.henrongyi.top/qq.jpg" width="180"/> |
### QQ交流群:622360840
### 微信交流群:可以添加上面任意一位开发者,备注"加入gin-vue-admin交流群"
### 8.2 项目组成员
| 蒋 | 尹 | 严 | 杜 | 印 | 宋 |
| :---: | :---: | :---: | :---: | :---: | :---: |
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryx.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryr.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrdjl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrygl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrsong.png"> |
### - QQ交流群:622360840
### - 微信交流群:可以添加上面任意一位开发者,备注"加入gin-vue-admin交流群"
## 11. 开发者列表
| 昵称 | 项目职务 | 姓 |
| ---- | ---- | ---- |
| [@piexlmax](https://github.com/piexlmax) | 项目发起者 | 蒋 |
......@@ -286,6 +255,6 @@ go run main.go;
| [@krank666](https://github.com/krank666) | 前端开发 | 尹 |
| [@chen-chen-up](https://github.com/chen-chen-up) | 新手开发 | 宋 |
## 12. 捐赠
## 9. 捐赠
如果你觉得这个项目对你有帮助,你可以请作者喝饮料 :tropical_drink:
......@@ -7,7 +7,7 @@
<img src="https://img.shields.io/badge/gin-1.4.0-lightBlue"/>
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen"/>
<img src="https://img.shields.io/badge/element--ui-2.12.0-green"/>
<img src="https://img.shields.io/badge/gorm-1.9.10-red"/>
<img src="https://img.shields.io/badge/gorm-1.9.12-red"/>
</div>
English | [简体中文](./README-zh_CN.md)
......@@ -53,9 +53,9 @@ We are excited that you are interested in contributing to gin-vue-admin. Before
### 1.3 Version list
- master: 2.0 开发版代码,生产环境
- master: 2.0 dev code, for prod
- develop: 2.0 开发版代码,测试环境
- develop: 2.0 dev code, for test
- [gin-vue-admin_v2.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v2_dev) (v2.0 is no longer compatible with v1.0)
......@@ -131,29 +131,6 @@ swag init
````
After executing the above command,`docs` will show in `server/`,then open your browser, jump into `http://localhost:8888/swagger/index.html` to see the swagger APIs.
### 2.4 Docker image
Thanks [@chenlinzhong](https://github.com/chenlinzhong) for providing docker image.
```
# start docker
docker run -itd --net=host --name=go_container shareclz/go_node /bin/bash;
# come into docker
docker exec -it go_container /bin/bash;
git clone https://github.com/piexlmax/gin-vue-admin.git /data1/www/htdocs/go/admin;
# run web
cd /data1/www/htdocs/go/admin/QMPlusVuePage;
cnpm i ;
npm run serve;
# update db config
vi /data1/www/htdocs/go/admin/QMPlusServer/static/dbconfig/config.json;
# run server
cd /data1/www/htdocs/go/admin/QMPlusServer;z
go run main.go;
```
## 3. Technical selection
......@@ -165,7 +142,17 @@ go run main.go;
- Config: using `fsnotify` and `viper` to implement `yaml` config file。
- Log: using `go-logging` record logs。
## 4. Project layout
## 4. Project Architecture
### 4.1 Architecture Diagram
![Architecture diagram](./docs/gin-vue-admin.png)
### 4.2 Front-end Detailed Design Diagram (Contributor: <a href="https://github.com/baobeisuper">baobeisuper</a>)
![Front-end Detailed Design Diagram](http://qmplusimg.henrongyi.top/naotu.png)
### 4.3 Project Layout
```
├─server (backend)
......@@ -226,57 +213,43 @@ backend code file: model\dnModel\api.go
- [ ] workflow, task transfer function
- [ ] frontend independent mode, mock
## 7. Changelog
| Date | Log |
| :---: | --- |
|2020/01/07| Added data resource function to Role, added the return of data resource association, the demo code was synchronized, and the multi-point login interception has been turned on, which may prevent being crowded out by others |
|2020/01/13| Added configuration management function. This function is not published to the test environment. The test environment will not be published until the protection mechanism and the service restart mechanism are released. Please clone and import the sql scripts into your own database |
|2020/02/21| Modified `casbin` custom authentication method to fully support `/:params and?Query=` interface modes in RESTful API |
|2020/03/17| Added verification code function with [@dchest/captcha](https://github.com/dchest/captcha) |
|2020/03/30| Code generator implementation, form generator implementation with[@form-generator](https://github.com/JakHuang/form-generator) |
|2020/04/01| Add frontend history tab function, add (modify) condition query example, and change the frontend background to white. (If you don't need this feature, you can change `background` in `&.el-main` to shield background color of `HistoryComponent`, which is located at line 260 of the code `web/src/view/layout/index.vue`) |
|2020/04/04| Starting version 2.x, standardize the project documentation, reconstructing the log function, and adding English comments to all methods |
## 7. Knowledge base
## 8. Team blog
### 7.1 Team blog
> https://blog.henrongyi.top
> https://www.yuque.com/flipped-aurora
>
>
There are video courses about frontend framework in our blo. If you think the project is helpful to you, you can add my personal WeChat:shouzi_1994,your comments is welcomed。
## 9. Video courses
>There are video courses about frontend framework in our blo. If you think the project is helpful to you, you can add my personal WeChat:shouzi_1994,your comments is welcomed。
### 9.1 Development environment course
### 7.2 Video courses
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/ (coming soon)
(1) Development environment course
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/
### 9.2 Template course
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/ (coming soon)
(2) Template course
> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/
### 9.3 Golang basic course (coming soon)
(3)2.0 version introduction and development experience
> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
> URL: https://space.bilibili.com/322210472/channel/detail?cid=108884
(4) Golang basic course (coming soon)
## 10. Contacts
> https://space.bilibili.com/322210472/channel/detail?cid=108884
## 8. Contacts
### 8.1 Groups
| QQ group |
| :---: |
| <img src="http://qmplusimg.henrongyi.top/qq.jpg" width="180"/> |
### QQ group: 622360840
### Wechat group: add anyone above, comment "加入gin-vue-admin交流群"
### 8.2 Team members
| Jiang | Yin | Yan | Du | Yin | Song |
| :---: | :---: | :---: | :---: | :---: | :---: |
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryx.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryr.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrdjl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrygl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrsong.png"> |
### QQ group: 622360840
### Wechat group: add anyone above, comment "加入gin-vue-admin交流群"
## 11. Developers
| Nick name | Project position | First name |
| ---- | ---- | ---- |
| [@piexlmax](https://github.com/piexlmax) | Project sponsor | Jiang |
......@@ -286,7 +259,7 @@ There are video courses about frontend framework in our blo. If you think the pr
| [@krank666](https://github.com/krank666) | Frontend developer | Yin |
| [@chen-chen-up](https://github.com/chen-chen-up) | Novice developer | Song |
## 12. Donate
## 9. Donate
If you find this project useful, you can buy author a glass of juice :tropical_drink:
{
"lockfileVersion": 1
}
FROM centos:7.6.1810
FROM golang:alpine as builder
# 设置go mod proxy 国内代理
# 设置golang path
ENV GOPROXY=https://goproxy.io GOPATH=/gopath PATH="${PATH}:/usr/local/go/bin"
# 定义使用的Golang 版本
ARG GO_VERSION=1.13.3
# 安装 golang 1.13.3
RUN yum install -y wget && \
yum install -y wqy-microhei-fonts wqy-zenhei-fonts && \
wget "https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz" && \
rm -rf /usr/local/go && \
tar -C /usr/local -xzf "go$GO_VERSION.linux-amd64.tar.gz" && \
rm -rf *.tar.gz && \
go version && go env;
WORKDIR $GOPATH
COPY . gin-vue
RUN cd server && go build -o app;
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
GO111MODULE=on \
CGO_ENABLED=1
WORKDIR /ginvue
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
COPY . .
RUN go env && go list && go build -o app main.go
EXPOSE 8888
ENTRYPOINT /ginvue/app
CMD ["gin-vue/app"]
\ No newline at end of file
# 根据Dockerfile生成Docker镜像
# docker build -t ginvue .
# 根据Docker镜像启动Docker容器
# docker run -itd -p 8888:8888 --name ginvue ginvue
......@@ -7,6 +7,7 @@ import (
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -21,6 +22,15 @@ import (
func CreateExaCustomer(c *gin.Context) {
var cu model.ExaCustomer
_ = c.ShouldBindJSON(&cu)
CustomerVerify := utils.Rules{
"CustomerName": {utils.NotEmpty()},
"CustomerPhoneData": {utils.NotEmpty()},
}
CustomerVerifyErr := utils.Verify(cu, CustomerVerify)
if CustomerVerifyErr != nil {
response.FailWithMessage(CustomerVerifyErr.Error(), c)
return
}
claims, _ := c.Get("claims")
waitUse := claims.(*request.CustomClaims)
cu.SysUserID = waitUse.ID
......@@ -44,6 +54,14 @@ func CreateExaCustomer(c *gin.Context) {
func DeleteExaCustomer(c *gin.Context) {
var cu model.ExaCustomer
_ = c.ShouldBindJSON(&cu)
CustomerVerify := utils.Rules{
"ID": {utils.NotEmpty()},
}
CustomerVerifyErr := utils.Verify(cu.Model, CustomerVerify)
if CustomerVerifyErr != nil {
response.FailWithMessage(CustomerVerifyErr.Error(), c)
return
}
err := service.DeleteExaCustomer(cu)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败:%v", err), c)
......@@ -63,6 +81,23 @@ func DeleteExaCustomer(c *gin.Context) {
func UpdateExaCustomer(c *gin.Context) {
var cu model.ExaCustomer
_ = c.ShouldBindJSON(&cu)
IdCustomerVerify := utils.Rules{
"ID": {utils.NotEmpty()},
}
IdCustomerVerifyErr := utils.Verify(cu.Model, IdCustomerVerify)
if IdCustomerVerifyErr != nil {
response.FailWithMessage(IdCustomerVerifyErr.Error(), c)
return
}
CustomerVerify := utils.Rules{
"CustomerName": {utils.NotEmpty()},
"CustomerPhoneData": {utils.NotEmpty()},
}
CustomerVerifyErr := utils.Verify(cu, CustomerVerify)
if CustomerVerifyErr != nil {
response.FailWithMessage(CustomerVerifyErr.Error(), c)
return
}
err := service.UpdateExaCustomer(&cu)
if err != nil {
response.FailWithMessage(fmt.Sprintf("更新失败:%v", err), c)
......@@ -82,6 +117,14 @@ func UpdateExaCustomer(c *gin.Context) {
func GetExaCustomer(c *gin.Context) {
var cu model.ExaCustomer
_ = c.ShouldBindQuery(&cu)
IdCustomerVerify := utils.Rules{
"ID": {utils.NotEmpty()},
}
IdCustomerVerifyErr := utils.Verify(cu.Model, IdCustomerVerify)
if IdCustomerVerifyErr != nil {
response.FailWithMessage(IdCustomerVerifyErr.Error(), c)
return
}
err, customer := service.GetExaCustomer(cu.ID)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
......@@ -103,6 +146,11 @@ func GetExaCustomerList(c *gin.Context) {
waitUse := claims.(*request.CustomClaims)
var pageInfo request.PageInfo
_ = c.ShouldBindQuery(&pageInfo)
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
if PageVerifyErr != nil {
response.FailWithMessage(PageVerifyErr.Error(), c)
return
}
err, customerList, total := service.GetCustomerInfoList(waitUse.AuthorityId, pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
......
......@@ -27,7 +27,7 @@ func UploadFile(c *gin.Context) {
response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
} else {
//文件上传后拿到文件路径
err, filePath, key := utils.Upload(header, USER_HEADER_BUCKET, USER_HEADER_IMG_PATH)
err, filePath, key := utils.Upload(header)
if err != nil {
response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
} else {
......@@ -45,7 +45,6 @@ func UploadFile(c *gin.Context) {
response.FailWithMessage(fmt.Sprintf("修改数据库链接失败,%v", err), c)
} else {
response.OkDetailed(resp.ExaFileResponse{File: file}, "上传成功", c)
}
}
}
......@@ -65,7 +64,7 @@ func DeleteFile(c *gin.Context) {
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
err = utils.DeleteFile(USER_HEADER_BUCKET, f.Key)
err = utils.DeleteFile(f.Key)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
......
......@@ -7,6 +7,7 @@ import (
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -21,6 +22,17 @@ import (
func CreateApi(c *gin.Context) {
var api model.SysApi
_ = c.ShouldBindJSON(&api)
ApiVerify := utils.Rules{
"Path": {utils.NotEmpty()},
"Description": {utils.NotEmpty()},
"ApiGroup": {utils.NotEmpty()},
"Method": {utils.NotEmpty()},
}
ApiVerifyErr := utils.Verify(api, ApiVerify)
if ApiVerifyErr != nil {
response.FailWithMessage(ApiVerifyErr.Error(), c)
return
}
err := service.CreateApi(api)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
......@@ -40,6 +52,14 @@ func CreateApi(c *gin.Context) {
func DeleteApi(c *gin.Context) {
var a model.SysApi
_ = c.ShouldBindJSON(&a)
ApiVerify := utils.Rules{
"ID": {utils.NotEmpty()},
}
ApiVerifyErr := utils.Verify(a.Model, ApiVerify)
if ApiVerifyErr != nil {
response.FailWithMessage(ApiVerifyErr.Error(), c)
return
}
err := service.DeleteApi(a)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
......@@ -62,6 +82,11 @@ func GetApiList(c *gin.Context) {
// 此结构体仅本方法使用
var sp request.SearchApiParams
_ = c.ShouldBindJSON(&sp)
PageVerifyErr := utils.Verify(sp.PageInfo, utils.CustomizeMap["PageVerify"])
if PageVerifyErr != nil {
response.FailWithMessage(PageVerifyErr.Error(), c)
return
}
err, list, total := service.GetAPIInfoList(sp.SysApi, sp.PageInfo, sp.OrderKey, sp.Desc)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
......@@ -86,6 +111,11 @@ func GetApiList(c *gin.Context) {
func GetApiById(c *gin.Context) {
var idInfo request.GetById
_ = c.ShouldBindJSON(&idInfo)
IdVerifyErr := utils.Verify(idInfo, utils.CustomizeMap["IdVerify"])
if IdVerifyErr != nil {
response.FailWithMessage(IdVerifyErr.Error(), c)
return
}
err, api := service.GetApiById(idInfo.Id)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
......@@ -105,6 +135,17 @@ func GetApiById(c *gin.Context) {
func UpdateApi(c *gin.Context) {
var api model.SysApi
_ = c.ShouldBindJSON(&api)
ApiVerify := utils.Rules{
"Path": {utils.NotEmpty()},
"Description": {utils.NotEmpty()},
"ApiGroup": {utils.NotEmpty()},
"Method": {utils.NotEmpty()},
}
ApiVerifyErr := utils.Verify(api, ApiVerify)
if ApiVerifyErr != nil {
response.FailWithMessage(ApiVerifyErr.Error(), c)
return
}
err := service.UpdateApi(api)
if err != nil {
response.FailWithMessage(fmt.Sprintf("修改数据失败,%v", err), c)
......
......@@ -7,6 +7,7 @@ import (
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -21,6 +22,16 @@ import (
func CreateAuthority(c *gin.Context) {
var auth model.SysAuthority
_ = c.ShouldBindJSON(&auth)
AuthorityVerify := utils.Rules{
"AuthorityId": {utils.NotEmpty()},
"AuthorityName": {utils.NotEmpty()},
"ParentId": {utils.NotEmpty()},
}
AuthorityVerifyErr := utils.Verify(auth, AuthorityVerify)
if AuthorityVerifyErr != nil {
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
return
}
err, authBack := service.CreateAuthority(auth)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
......@@ -40,6 +51,24 @@ func CreateAuthority(c *gin.Context) {
func CopyAuthority(c *gin.Context) {
var copyInfo resp.SysAuthorityCopyResponse
_ = c.ShouldBindJSON(&copyInfo)
OldAuthorityVerify := utils.Rules{
"OldAuthorityId": {utils.NotEmpty()},
}
OldAuthorityVerifyErr := utils.Verify(copyInfo, OldAuthorityVerify)
if OldAuthorityVerifyErr != nil {
response.FailWithMessage(OldAuthorityVerifyErr.Error(), c)
return
}
AuthorityVerify := utils.Rules{
"AuthorityId": {utils.NotEmpty()},
"AuthorityName": {utils.NotEmpty()},
"ParentId": {utils.NotEmpty()},
}
AuthorityVerifyErr := utils.Verify(copyInfo.Authority, AuthorityVerify)
if AuthorityVerifyErr != nil {
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
return
}
err, authBack := service.CopyAuthority(copyInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("拷贝失败,%v", err), c)
......@@ -59,6 +88,11 @@ func CopyAuthority(c *gin.Context) {
func DeleteAuthority(c *gin.Context) {
var a model.SysAuthority
_ = c.ShouldBindJSON(&a)
AuthorityIdVerifyErr := utils.Verify(a, utils.CustomizeMap["AuthorityIdVerify"])
if AuthorityIdVerifyErr != nil {
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
return
}
//删除角色之前需要判断是否有用户正在使用此角色
err := service.DeleteAuthority(&a)
if err != nil {
......@@ -79,6 +113,16 @@ func DeleteAuthority(c *gin.Context) {
func UpdateAuthority(c *gin.Context) {
var auth model.SysAuthority
_ = c.ShouldBindJSON(&auth)
AuthorityVerify := utils.Rules{
"AuthorityId": {utils.NotEmpty()},
"AuthorityName": {utils.NotEmpty()},
"ParentId": {utils.NotEmpty()},
}
AuthorityVerifyErr := utils.Verify(auth, AuthorityVerify)
if AuthorityVerifyErr != nil {
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
return
}
err, authority := service.UpdateAuthority(auth)
if err != nil {
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
......@@ -98,6 +142,11 @@ func UpdateAuthority(c *gin.Context) {
func GetAuthorityList(c *gin.Context) {
var pageInfo request.PageInfo
_ = c.ShouldBindJSON(&pageInfo)
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
if PageVerifyErr != nil {
response.FailWithMessage(PageVerifyErr.Error(), c)
return
}
err, list, total := service.GetAuthorityInfoList(pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
......@@ -122,6 +171,11 @@ func GetAuthorityList(c *gin.Context) {
func SetDataAuthority(c *gin.Context) {
var auth model.SysAuthority
_ = c.ShouldBindJSON(&auth)
AuthorityIdVerifyErr := utils.Verify(auth, utils.CustomizeMap["AuthorityIdVerify"])
if AuthorityIdVerifyErr != nil {
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
return
}
err := service.SetDataAuthority(auth)
if err != nil {
response.FailWithMessage(fmt.Sprintf("设置关联失败,%v", err), c)
......
......@@ -5,7 +5,9 @@ import (
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
"net/url"
"os"
)
......@@ -20,6 +22,59 @@ import (
func CreateTemp(c *gin.Context) {
var a model.AutoCodeStruct
_ = c.ShouldBindJSON(&a)
AutoCodeVerify := utils.Rules{
"Abbreviation": {utils.NotEmpty()},
"StructName": {utils.NotEmpty()},
"PackageName": {utils.NotEmpty()},
"Fields": {utils.NotEmpty()},
}
WKVerifyErr := utils.Verify(a, AutoCodeVerify)
if WKVerifyErr!=nil {
response.FailWithMessage(WKVerifyErr.Error(), c)
return
}
if a.AutoCreateApiToSql {
apiList := [5]model.SysApi{
{
Path: "/" + a.Abbreviation + "/" + "create" + a.StructName,
Description: "新增" + a.StructName,
ApiGroup: a.Abbreviation,
Method: "POST",
},
{
Path: "/" + a.Abbreviation + "/" + "delete" + a.StructName,
Description: "删除" + a.StructName,
ApiGroup: a.Abbreviation,
Method: "DELETE",
},
{
Path: "/" + a.Abbreviation + "/" + "update" + a.StructName,
Description: "更新" + a.StructName,
ApiGroup: a.Abbreviation,
Method: "PUT",
},
{
Path: "/" + a.Abbreviation + "/" + "find" + a.StructName,
Description: "根据ID获取" + a.StructName,
ApiGroup: a.Abbreviation,
Method: "GET",
},
{
Path: "/" + a.Abbreviation + "/" + "get" + a.StructName + "List",
Description: "获取" + a.StructName + "列表",
ApiGroup: a.Abbreviation,
Method: "GET",
},
}
for _, v := range apiList {
errC := service.CreateApi(v)
if errC != nil {
c.Writer.Header().Add("success", "false")
c.Writer.Header().Add("msg", url.QueryEscape(fmt.Sprintf("自动化创建失败,%v,请自行清空垃圾数据", errC)))
return
}
}
}
err := service.CreateTemp(a)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
......
......@@ -6,6 +6,7 @@ import (
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -20,6 +21,11 @@ import (
func UpdateCasbin(c *gin.Context) {
var cmr request.CasbinInReceive
_ = c.ShouldBindJSON(&cmr)
AuthorityIdVerifyErr := utils.Verify(cmr, utils.CustomizeMap["AuthorityIdVerify"])
if AuthorityIdVerifyErr != nil {
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
return
}
err := service.UpdateCasbin(cmr.AuthorityId, cmr.CasbinInfos)
if err != nil {
response.FailWithMessage(fmt.Sprintf("添加规则失败,%v", err), c)
......@@ -39,6 +45,11 @@ func UpdateCasbin(c *gin.Context) {
func GetPolicyPathByAuthorityId(c *gin.Context) {
var cmr request.CasbinInReceive
_ = c.ShouldBindJSON(&cmr)
AuthorityIdVerifyErr := utils.Verify(cmr, utils.CustomizeMap["AuthorityIdVerify"])
if AuthorityIdVerifyErr != nil {
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
return
}
paths := service.GetPolicyPathByAuthorityId(cmr.AuthorityId)
response.OkWithData(resp.PolicyPathResponse{Paths: paths}, c)
}
......
......@@ -7,6 +7,7 @@ import (
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -39,7 +40,12 @@ func GetMenu(c *gin.Context) {
func GetMenuList(c *gin.Context) {
var pageInfo request.PageInfo
_ = c.ShouldBindJSON(&pageInfo)
err, menuList, total := service.GetInfoList(pageInfo)
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
if PageVerifyErr != nil {
response.FailWithMessage(PageVerifyErr.Error(), c)
return
}
err, menuList, total := service.GetInfoList()
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
......@@ -63,6 +69,26 @@ func GetMenuList(c *gin.Context) {
func AddBaseMenu(c *gin.Context) {
var menu model.SysBaseMenu
_ = c.ShouldBindJSON(&menu)
MenuVerify := utils.Rules{
"Path": {"notEmpty"},
"ParentId": {utils.NotEmpty()},
"Name": {utils.NotEmpty()},
"Component": {utils.NotEmpty()},
"Sort": {utils.Ge("0"), "ge=0"},
}
MenuVerifyErr := utils.Verify(menu, MenuVerify)
if MenuVerifyErr != nil {
response.FailWithMessage(MenuVerifyErr.Error(), c)
return
}
MetaVerify := utils.Rules{
"Title": {utils.NotEmpty()},
}
MetaVerifyErr := utils.Verify(menu.Meta, MetaVerify)
if MetaVerifyErr != nil {
response.FailWithMessage(MetaVerifyErr.Error(), c)
return
}
err := service.AddBaseMenu(menu)
if err != nil {
response.FailWithMessage(fmt.Sprintf("添加失败,%v", err), c)
......@@ -98,7 +124,14 @@ func GetBaseMenuTree(c *gin.Context) {
func AddMenuAuthority(c *gin.Context) {
var addMenuAuthorityInfo request.AddMenuAuthorityInfo
_ = c.ShouldBindJSON(&addMenuAuthorityInfo)
MenuVerify := utils.Rules{
"AuthorityId": {"notEmpty"},
}
MenuVerifyErr := utils.Verify(addMenuAuthorityInfo, MenuVerify)
if MenuVerifyErr != nil {
response.FailWithMessage(MenuVerifyErr.Error(), c)
return
}
err := service.AddMenuAuthority(addMenuAuthorityInfo.Menus, addMenuAuthorityInfo.AuthorityId)
if err != nil {
response.FailWithMessage(fmt.Sprintf("添加失败,%v", err), c)
......@@ -118,6 +151,14 @@ func AddMenuAuthority(c *gin.Context) {
func GetMenuAuthority(c *gin.Context) {
var authorityIdInfo request.AuthorityIdInfo
_ = c.ShouldBindJSON(&authorityIdInfo)
MenuVerify := utils.Rules{
"AuthorityId": {"notEmpty"},
}
MenuVerifyErr := utils.Verify(authorityIdInfo, MenuVerify)
if MenuVerifyErr != nil {
response.FailWithMessage(MenuVerifyErr.Error(), c)
return
}
err, menus := service.GetMenuAuthority(authorityIdInfo.AuthorityId)
if err != nil {
response.FailWithDetailed(response.ERROR, resp.SysMenusResponse{Menus: menus}, fmt.Sprintf("添加失败,%v", err), c)
......@@ -137,6 +178,11 @@ func GetMenuAuthority(c *gin.Context) {
func DeleteBaseMenu(c *gin.Context) {
var idInfo request.GetById
_ = c.ShouldBindJSON(&idInfo)
IdVerifyErr := utils.Verify(idInfo, utils.CustomizeMap["IdVerify"])
if IdVerifyErr != nil {
response.FailWithMessage(IdVerifyErr.Error(), c)
return
}
err := service.DeleteBaseMenu(idInfo.Id)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败:%v", err), c)
......@@ -157,6 +203,26 @@ func DeleteBaseMenu(c *gin.Context) {
func UpdateBaseMenu(c *gin.Context) {
var menu model.SysBaseMenu
_ = c.ShouldBindJSON(&menu)
MenuVerify := utils.Rules{
"Path": {"notEmpty"},
"ParentId": {utils.NotEmpty()},
"Name": {utils.NotEmpty()},
"Component": {utils.NotEmpty()},
"Sort": {utils.Ge("0"), "ge=0"},
}
MenuVerifyErr := utils.Verify(menu, MenuVerify)
if MenuVerifyErr != nil {
response.FailWithMessage(MenuVerifyErr.Error(), c)
return
}
MetaVerify := utils.Rules{
"Title": {utils.NotEmpty()},
}
MetaVerifyErr := utils.Verify(menu.Meta, MetaVerify)
if MetaVerifyErr != nil {
response.FailWithMessage(MetaVerifyErr.Error(), c)
return
}
err := service.UpdateBaseMenu(menu)
if err != nil {
response.FailWithMessage(fmt.Sprintf("修改失败:%v", err), c)
......@@ -176,6 +242,14 @@ func UpdateBaseMenu(c *gin.Context) {
func GetBaseMenuById(c *gin.Context) {
var idInfo request.GetById
_ = c.ShouldBindJSON(&idInfo)
MenuVerify := utils.Rules{
"Id": {"notEmpty"},
}
MenuVerifyErr := utils.Verify(idInfo, MenuVerify)
if MenuVerifyErr != nil {
response.FailWithMessage(MenuVerifyErr.Error(), c)
return
}
err, menu := service.GetBaseMenuById(idInfo.Id)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询失败:%v", err), c)
......
......@@ -18,11 +18,6 @@ import (
"time"
)
const (
USER_HEADER_IMG_PATH string = "http://qmplusimg.henrongyi.top"
USER_HEADER_BUCKET string = "qm-plus-img"
)
// @Tags Base
// @Summary 用户注册账号
// @Produce application/json
......@@ -32,6 +27,17 @@ const (
func Register(c *gin.Context) {
var R request.RegisterStruct
_ = c.ShouldBindJSON(&R)
UserVerify := utils.Rules{
"Username": {utils.NotEmpty()},
"NickName": {utils.NotEmpty()},
"Password": {utils.NotEmpty()},
"AuthorityId": {utils.NotEmpty()},
}
UserVerifyErr := utils.Verify(R, UserVerify)
if UserVerifyErr != nil {
response.FailWithMessage(UserVerifyErr.Error(), c)
return
}
user := &model.SysUser{Username: R.Username, NickName: R.NickName, Password: R.Password, HeaderImg: R.HeaderImg, AuthorityId: R.AuthorityId}
err, userReturn := service.Register(*user)
if err != nil {
......@@ -50,6 +56,17 @@ func Register(c *gin.Context) {
func Login(c *gin.Context) {
var L request.RegisterAndLoginStruct
_ = c.ShouldBindJSON(&L)
UserVerify := utils.Rules{
"CaptchaId": {utils.NotEmpty()},
"Captcha": {utils.NotEmpty()},
"Username": {utils.NotEmpty()},
"Password": {utils.NotEmpty()},
}
UserVerifyErr := utils.Verify(L, UserVerify)
if UserVerifyErr != nil {
response.FailWithMessage(UserVerifyErr.Error(), c)
return
}
if captcha.VerifyString(L.CaptchaId, L.Captcha) {
U := &model.SysUser{Username: L.Username, Password: L.Password}
if err, user := service.Login(U); err != nil {
......@@ -139,6 +156,16 @@ func tokenNext(c *gin.Context, user model.SysUser) {
func ChangePassword(c *gin.Context) {
var params request.ChangePasswordStruct
_ = c.ShouldBindJSON(&params)
UserVerify := utils.Rules{
"Username": {utils.NotEmpty()},
"Password": {utils.NotEmpty()},
"NewPassword": {utils.NotEmpty()},
}
UserVerifyErr := utils.Verify(params, UserVerify)
if UserVerifyErr != nil {
response.FailWithMessage(UserVerifyErr.Error(), c)
return
}
U := &model.SysUser{Username: params.Username, Password: params.Password}
if err, _ := service.ChangePassword(U, params.NewPassword); err != nil {
response.FailWithMessage("修改失败,请检查用户名密码", c)
......@@ -172,7 +199,7 @@ func UploadHeaderImg(c *gin.Context) {
response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
} else {
//文件上传后拿到文件路径
err, filePath, _ := utils.Upload(header, USER_HEADER_BUCKET, USER_HEADER_IMG_PATH)
err, filePath, _ := utils.Upload(header)
if err != nil {
response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
} else {
......@@ -198,6 +225,11 @@ func UploadHeaderImg(c *gin.Context) {
func GetUserList(c *gin.Context) {
var pageInfo request.PageInfo
_ = c.ShouldBindJSON(&pageInfo)
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
if PageVerifyErr != nil {
response.FailWithMessage(PageVerifyErr.Error(), c)
return
}
err, list, total := service.GetUserInfoList(pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
......@@ -222,6 +254,15 @@ func GetUserList(c *gin.Context) {
func SetUserAuthority(c *gin.Context) {
var sua request.SetUserAuth
_ = c.ShouldBindJSON(&sua)
UserVerify := utils.Rules{
"UUID": {utils.NotEmpty()},
"AuthorityId": {utils.NotEmpty()},
}
UserVerifyErr := utils.Verify(sua, UserVerify)
if UserVerifyErr != nil {
response.FailWithMessage(UserVerifyErr.Error(), c)
return
}
err := service.SetUserAuthority(sua.UUID, sua.AuthorityId)
if err != nil {
response.FailWithMessage(fmt.Sprintf("修改失败,%v", err), c)
......@@ -235,12 +276,17 @@ func SetUserAuthority(c *gin.Context) {
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SetUserAuth true "删除用户"
// @Param data body request.GetById true "删除用户"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
// @Router /user/deleteUser [delete]
func DeleteUser(c *gin.Context) {
var reqId request.GetById
_ = c.ShouldBindJSON(&reqId)
IdVerifyErr := utils.Verify(reqId, utils.CustomizeMap["IdVerify"])
if IdVerifyErr != nil {
response.FailWithMessage(IdVerifyErr.Error(), c)
return
}
err := service.DeleteUser(reqId.Id)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
......
......@@ -5,6 +5,7 @@ import (
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
)
......@@ -17,6 +18,17 @@ import (
func CreateWorkFlow(c *gin.Context) {
var wk model.SysWorkflow
_ = c.ShouldBindJSON(&wk)
WKVerify := utils.Rules{
"WorkflowNickName": {utils.NotEmpty()},
"WorkflowName": {utils.NotEmpty()},
"WorkflowDescription": {utils.NotEmpty()},
"WorkflowStepInfo": {utils.NotEmpty()},
}
WKVerifyErr := utils.Verify(wk, WKVerify)
if WKVerifyErr!=nil {
response.FailWithMessage(WKVerifyErr.Error(), c)
return
}
err := service.Create(wk)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
......
......@@ -17,17 +17,20 @@ mysql:
config: 'charset=utf8&parseTime=True&loc=Local'
max-idle-conns: 10
max-open-conns: 10
log-mode: true
log-mode: false
#sqlite 配置
sqlite:
path: db.db
log-mode: true
config: 'loc=Asia/Shanghai'
# oss configuration
qiniu:
access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
bucket: 'qm-plus-img'
img-path: 'http://qmplusimg.henrongyi.top'
# redis configuration
redis:
addr: %{redis_address}
......
......@@ -46,6 +46,8 @@ type Redis struct {
type Qiniu struct {
AccessKey string `mapstructure:"access-key" json:"accessKey" yaml:"access-key"`
SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`
Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"`
ImgPath string `mapstructure:"img-path" json:"imgPath" yaml:"img-path"`
}
type Captcha struct {
......
......@@ -23,6 +23,8 @@ func RunWindowsServer() {
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
// 保证文本顺序输出
// In order to ensure that the text order output can be deleted
time.Sleep(10 * time.Microsecond)
global.GVA_LOG.Debug("server run success on ", address)
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -4,13 +4,15 @@ import (
"gin-vue-admin/global"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"os"
)
//初始化数据库并产生数据库全局变量
func Mysql() {
admin := global.GVA_CONFIG.Mysql
if db, err := gorm.Open("mysql", admin.Username+":"+admin.Password+"@("+admin.Path+")/"+admin.Dbname+"?"+admin.Config); err != nil {
global.GVA_LOG.Error("DEFAULTDB数据库启动异常", err)
global.GVA_LOG.Error("MySQL启动异常", err)
os.Exit(0)
} else {
global.GVA_DB = db
global.GVA_DB.DB().SetMaxIdleConns(admin.MaxIdleConns)
......
......@@ -14,7 +14,6 @@ import (
func Routers() *gin.Engine {
var Router = gin.Default()
//Router.Use(middleware.LoadTls()) // 打开就能玩https了
global.GVA_LOG.Debug("use middleware logger")
// 跨域
......
package initialize
import "gin-vue-admin/utils"
func init() {
_ = utils.RegisterRule("PageVerify",
utils.Rules{
"Page": {utils.NotEmpty()},
"PageSize": {utils.NotEmpty()},
},
)
_ = utils.RegisterRule("IdVerify",
utils.Rules{
"Id": {utils.NotEmpty()},
},
)
_ = utils.RegisterRule("AuthorityIdVerify",
utils.Rules{
"AuthorityId": {utils.NotEmpty()},
},
)
}
......@@ -2,15 +2,17 @@ package model
// 初始版本自动化代码工具
type AutoCodeStruct struct {
StructName string `json:"structName"`
PackageName string `json:"packageName"`
Abbreviation string `json:"abbreviation"`
Fields []Field `json:"fields"`
StructName string `json:"structName"`
PackageName string `json:"packageName"`
Abbreviation string `json:"abbreviation"`
AutoCreateApiToSql bool `json:"autoCreateApiToSql"`
Fields []Field `json:"fields"`
}
type Field struct {
FieldName string `json:"fieldName"`
FieldDesc string `json:"fieldDesc"`
FieldType string `json:"fieldType"`
FieldJson string `json:"fieldJson"`
ColumnName string `json:"columnName"`
}
\ No newline at end of file
}
......@@ -5,7 +5,7 @@ import service from '@/utils/request'
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body {{.PackageName}}.{{.StructName}} true "创建{{.StructName}}"
// @Param data body model.{{.StructName}} true "创建{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/create{{.StructName}} [post]
export const create{{.StructName}} = (data) => {
......@@ -22,13 +22,13 @@ export const create{{.StructName}} = (data) => {
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body {{.PackageName}}.{{.StructName}} true "删除{{.StructName}}"
// @Param data body model.{{.StructName}} true "删除{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /{{.Abbreviation}}/delete{{.StructName}} [post]
// @Router /{{.Abbreviation}}/delete{{.StructName}} [delete]
export const delete{{.StructName}} = (data) => {
return service({
url: "/{{.Abbreviation}}/delete{{.StructName}}",
method: 'post',
method: 'delete',
data
})
}
......@@ -38,13 +38,13 @@ export const create{{.StructName}} = (data) => {
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body {{.PackageName}}.{{.StructName}} true "更新{{.StructName}}"
// @Param data body model.{{.StructName}} true "更新{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /{{.Abbreviation}}/update{{.StructName}} [post]
// @Router /{{.Abbreviation}}/update{{.StructName}} [put]
export const update{{.StructName}} = (data) => {
return service({
url: "/{{.Abbreviation}}/update{{.StructName}}",
method: 'post',
method: 'put',
data
})
}
......@@ -55,14 +55,14 @@ export const create{{.StructName}} = (data) => {
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body {{.PackageName}}.{{.StructName}} true "用id查询{{.StructName}}"
// @Param data body model.{{.StructName}} true "用id查询{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /{{.Abbreviation}}/find{{.StructName}} [post]
export const find{{.StructName}} = (data) => {
// @Router /{{.Abbreviation}}/find{{.StructName}} [get]
export const find{{.StructName}} = (params) => {
return service({
url: "/{{.Abbreviation}}/find{{.StructName}}",
method: 'post',
data
method: 'get',
params
})
}
......@@ -74,11 +74,11 @@ export const create{{.StructName}} = (data) => {
// @Produce application/json
// @Param data body request.PageInfo true "分页获取{{.StructName}}列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/get{{.StructName}}List [post]
export const get{{.StructName}}List = (data) => {
// @Router /{{.Abbreviation}}/get{{.StructName}}List [get]
export const get{{.StructName}}List = (params) => {
return service({
url: "/{{.Abbreviation}}/get{{.StructName}}List",
method: 'post',
data
method: 'get',
params
})
}
\ No newline at end of file
<template>
<div>
<div class="search-term">
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
此处请使用表单生成器生成form填充 表单默认绑定 formData 如手动修改过请自行修改key
<el-form-item>
<el-button @click="openDialog" type="primary">新增</el-button>
</el-form-item>
</el-form>
</div>
<el-table
:data="tableData"
border
ref="multipleTable"
stripe
style="width: 100%"
tooltip-effect="dark"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="日期" width="180">
<template slot-scope="scope">{{ "{{scope.row.CreatedAt|formatDate}}" }}</template>
</el-table-column>
{{range .Fields}}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120"></el-table-column>
{{ end }}
<el-table-column label="按钮组">
<template slot-scope="scope">
<el-button @click="update{{.StructName}}(scope.row)" size="small" type="text">变更</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="text" size="mini" slot="reference">删除</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:style="{float:'right',padding:'20px'}"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="弹窗操作">
此处请使用表单生成器生成form填充 表单默认绑定 formData 如手动修改过请自行修改key
<div class="dialog-footer" slot="footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button @click="enterDialog" type="primary">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
create{{.StructName}},
delete{{.StructName}},
update{{.StructName}},
find{{.StructName}},
get{{.StructName}}List
} from "@/api/{{.PackageName}}"; // 此处请自行替换地址
import { formatTimeToStr } from "@/utils/data";
import infoList from "@/components/mixins/infoList";
export default {
name: "{{.StructName}}",
mixins: [infoList],
data() {
return {
listApi: get{{.StructName}}List,
dialogFormVisible: false,
visible: false,
type: "",
formData: {
{{range .Fields}}{{.FieldJson}}:null,{{ end }}
}
};
},
filters: {
formatDate: function(time) {
if (time != null && time != "") {
var date = new Date(time);
return formatTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
} else {
return "";
}
}
},
methods: {
async update{{.StructName}}(row) {
const res = await find{{.StructName}}({ ID: row.ID });
this.type = "update";
if (res.code == 0) {
this.formData = res.data.re{{.Abbreviation}};
this.dialogFormVisible = true;
}
},
closeDialog() {
this.dialogFormVisible = false;
this.formData = {
{{range .Fields}}
{{.FieldJson}}:null,{{ end }}
};
},
async delete{{.StructName}}(row) {
this.visible = false;
const res = await delete{{.StructName}}({ ID: row.ID });
if (res.code == 0) {
this.$message({
type: "success",
message: "删除成功"
});
this.getTableData();
}
},
async enterDialog() {
let res;
switch (this.type) {
case "create":
res = await create{{.StructName}}(this.formData);
break;
case "update":
res = await update{{.StructName}}(this.formData);
break;
default:
res = await create{{.StructName}}(this.formData);
break;
}
if (res.code == 0) {
this.closeDialog();
this.getTableData();
}
},
openDialog() {
this.type = "create";
this.dialogFormVisible = true;
}
},
created() {
this.getTableData();
}
};
</script>
<style>
</style>
\ No newline at end of file
package api
package v1
import (
"fmt"
"gin-vue-admin/global/response"
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"github.com/gin-gonic/gin"
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"github.com/gin-gonic/gin"
)
......@@ -17,13 +20,13 @@ import (
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/create{{.StructName}} [post]
func Create{{.StructName}}(c *gin.Context) {
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
var {{.Abbreviation}} model.{{.StructName}}
_ = c.ShouldBindJSON(&{{.Abbreviation}})
err := {{.Abbreviation}}.Create{{.StructName}}()
err := service.Create{{.StructName}}({{.Abbreviation}})
if err != nil {
response.Result(response.ERROR, gin.H{}, fmt.Sprintf("创建失败,%v", err), c)
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
} else {
response.Result(response.SUCCESS, gin.H{}, "创建成功", c)
response.OkWithMessage("创建成功", c)
}
}
......@@ -35,15 +38,15 @@ func Create{{.StructName}}(c *gin.Context) {
// @Produce application/json
// @Param data body model.{{.StructName}} true "删除{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /{{.Abbreviation}}/delete{{.StructName}} [post]
// @Router /{{.Abbreviation}}/delete{{.StructName}} [delete]
func Delete{{.StructName}}(c *gin.Context) {
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
var {{.Abbreviation}} model.{{.StructName}}
_ = c.ShouldBindJSON(&{{.Abbreviation}})
err := {{.Abbreviation}}.Delete{{.StructName}}()
err := service.Delete{{.StructName}}({{.Abbreviation}})
if err != nil {
response.Result(response.ERROR, gin.H{}, fmt.Sprintf("删除失败,%v", err), c)
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
response.Result(response.SUCCESS, gin.H{}, "删除成功", c)
response.OkWithMessage("删除成功", c)
}
}
......@@ -55,17 +58,15 @@ func Delete{{.StructName}}(c *gin.Context) {
// @Produce application/json
// @Param data body model.{{.StructName}} true "更新{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /{{.Abbreviation}}/update{{.StructName}} [post]
// @Router /{{.Abbreviation}}/update{{.StructName}} [put]
func Update{{.StructName}}(c *gin.Context) {
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
var {{.Abbreviation}} model.{{.StructName}}
_ = c.ShouldBindJSON(&{{.Abbreviation}})
err,re{{.Abbreviation}} := {{.Abbreviation}}.Update{{.StructName}}()
err := service.Update{{.StructName}}(&{{.Abbreviation}})
if err != nil {
response.Result(response.ERROR, gin.H{}, fmt.Sprintf("更新失败,%v", err), c)
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
} else {
response.Result(response.SUCCESS, gin.H{
"re{{.Abbreviation}}":re{{.Abbreviation}},
}, "更新成功", c)
response.OkWithMessage("更新成功", c)
}
}
......@@ -77,17 +78,15 @@ func Update{{.StructName}}(c *gin.Context) {
// @Produce application/json
// @Param data body model.{{.StructName}} true "用id查询{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /{{.Abbreviation}}/find{{.StructName}} [post]
// @Router /{{.Abbreviation}}/find{{.StructName}} [get]
func Find{{.StructName}}(c *gin.Context) {
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
_ = c.ShouldBindJSON(&{{.Abbreviation}})
err,re{{.Abbreviation}} := {{.Abbreviation}}.FindById()
var {{.Abbreviation}} model.{{.StructName}}
_ = c.ShouldBindQuery(&{{.Abbreviation}})
err,re{{.Abbreviation}} := service.Get{{.StructName}}({{.Abbreviation}}.ID)
if err != nil {
response.Result(response.ERROR, gin.H{}, fmt.Sprintf("查询失败,%v", err), c)
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
} else {
response.Result(response.SUCCESS, gin.H{
"re{{.Abbreviation}}":re{{.Abbreviation}},
}, "查询成功", c)
response.OkWithData( gin.H{"re{{.Abbreviation}}":re{{.Abbreviation}},}, c)
}
}
......@@ -99,19 +98,19 @@ func Find{{.StructName}}(c *gin.Context) {
// @Produce application/json
// @Param data body request.PageInfo true "分页获取{{.StructName}}列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/get{{.StructName}}List [post]
// @Router /{{.Abbreviation}}/get{{.StructName}}List [get]
func Get{{.StructName}}List(c *gin.Context) {
var pageInfo request.PageInfo
_ = c.ShouldBindJSON(&pageInfo)
err, list, total := new({{.PackageName}}.{{.StructName}}).GetInfoList(pageInfo)
_ = c.ShouldBindQuery(&pageInfo)
err, list, total := service.Get{{.StructName}}InfoList(pageInfo)
if err != nil {
response.Result(response.ERROR, gin.H{}, fmt.Sprintf("获取数据失败,%v", err), c)
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
response.Result(response.SUCCESS, gin.H{
"{{.PackageName}}List": list,
"total": total,
"page": pageInfo.Page,
"pageSize": pageInfo.PageSize,
}, "获取数据成功", c)
response.OkWithData(resp.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, c)
}
}
\ No newline at end of file
// 自动生成模板{{.StructName}}
package {{.PackageName}}
package model
import (
"gin-vue-admin/global"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
type {{.StructName}} struct {
gorm.Model {{range .Fields}}
{{.FieldName}} {{.FieldType}} `json:"{{.FieldJson}}"{{if .ColumnName}} gorm:"column:{{.ColumnName}}"{{end}}`{{ end }}
}
// 创建{{.StructName}}
func ({{.Abbreviation}} *{{.StructName}})Create{{.StructName}}()(err error){
err = global.GVA_DB.Create({{.Abbreviation}}).Error
return err
}
// 删除{{.StructName}}
func ({{.Abbreviation}} *{{.StructName}})Delete{{.StructName}}()(err error){
err = global.GVA_DB.Delete({{.Abbreviation}}).Error
return err
}
// 更新{{.StructName}}
func ({{.Abbreviation}} *{{.StructName}})Update{{.StructName}}()(err error, re{{.Abbreviation}} {{.StructName}}){
err = global.GVA_DB.Save({{.Abbreviation}}).Error
return err, *{{.Abbreviation}}
}
// 根据ID查看单条{{.StructName}}
func ({{.Abbreviation}} *{{.StructName}})FindById()(err error,re{{.Abbreviation}} {{.StructName}}){
err = global.GVA_DB.Where("id = ?",{{.Abbreviation}}.ID).First(&re{{.Abbreviation}}).Error
return err,re{{.Abbreviation}}
}
// 分页获取{{.StructName}}
func ({{.Abbreviation}} *{{.StructName}})GetInfoList(info PageInfo)(err error, list interface{}, total int){
limit := info.PageSize
offset := info.PageSize * (info.Page - 1)
db:=global.GVA_DB
if err != nil {
return
} else {
var re{{.StructName}}List []{{.StructName}}
err = db.Limit(limit).Offset(offset).Find(&re{{.StructName}}List).Error
return err, re{{.StructName}}List, total
}
}
\ No newline at end of file
......@@ -10,9 +10,9 @@ func Init{{.StructName}}Router(Router *gin.RouterGroup) {
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
{
{{.StructName}}Router.POST("create{{.StructName}}", v1.Create{{.StructName}}) // 新建{{.StructName}}
{{.StructName}}Router.POST("delete{{.StructName}}", v1.Delete{{.StructName}}) //删除{{.StructName}}
{{.StructName}}Router.POST("update{{.StructName}}", v1.Update{{.StructName}}) //更新{{.StructName}}
{{.StructName}}Router.POST("find{{.StructName}}", v1.Find{{.StructName}}) // 根据ID获取{{.StructName}}
{{.StructName}}Router.POST("get{{.StructName}}List", v1.Get{{.StructName}}List) //获取{{.StructName}}列表
{{.StructName}}Router.DELETE("delete{{.StructName}}", v1.Delete{{.StructName}}) //删除{{.StructName}}
{{.StructName}}Router.PUT("update{{.StructName}}", v1.Update{{.StructName}}) //更新{{.StructName}}
{{.StructName}}Router.GET("find{{.StructName}}", v1.Find{{.StructName}}) // 根据ID获取{{.StructName}}
{{.StructName}}Router.GET("get{{.StructName}}List", v1.Get{{.StructName}}List) //获取{{.StructName}}列表
}
}
package service
import (
"gin-vue-admin/global"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
)
// @title Create{{.StructName}}
// @description create a {{.StructName}}
// @param {{.Abbreviation}} model.{{.StructName}}
// @auth (2020/04/05 20:22)
// @return err error
func Create{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
err = global.GVA_DB.Create(&{{.Abbreviation}}).Error
return err
}
// @title Delete{{.StructName}}
// @description delete a {{.StructName}}
// @auth (2020/04/05 20:22)
// @param {{.Abbreviation}} model.{{.StructName}}
// @return error
func Delete{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
err = global.GVA_DB.Delete({{.Abbreviation}}).Error
return err
}
// @title Update{{.StructName}}
// @description update a {{.StructName}}
// @param {{.Abbreviation}} *model.{{.StructName}}
// @auth (2020/04/05 20:22)
// @return error
func Update{{.StructName}}({{.Abbreviation}} *model.{{.StructName}}) (err error) {
err = global.GVA_DB.Save({{.Abbreviation}}).Error
return err
}
// @title Get{{.StructName}}
// @description get the info of a {{.StructName}}
// @auth (2020/04/05 20:22)
// @param id uint
// @return error
// @return {{.StructName}} {{.StructName}}
func Get{{.StructName}}(id uint) (err error, {{.Abbreviation}} model.{{.StructName}}) {
err = global.GVA_DB.Where("id = ?", id).First(&{{.Abbreviation}}).Error
return
}
// @title Get{{.StructName}}InfoList
// @description get {{.StructName}} list by pagination, 分页获取用户列表
// @auth (2020/04/05 20:22)
// @param info PageInfo
// @return error
func Get{{.StructName}}InfoList(info request.PageInfo) (err error, list interface{}, total int) {
limit := info.PageSize
offset := info.PageSize * (info.Page - 1)
db := global.GVA_DB
var {{.Abbreviation}}s []model.{{.StructName}}
err = db.Find(&{{.Abbreviation}}s).Count(&total).Error
err = db.Limit(limit).Offset(offset).Find(&{{.Abbreviation}}s).Error
return err,{{.Abbreviation}}s, total
}
......@@ -2,12 +2,12 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitUserRouter(Router *gin.RouterGroup) {
UserRouter := Router.Group("user")
//.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
UserRouter := Router.Group("user").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
{
UserRouter.POST("changePassword", v1.ChangePassword) // 修改密码
UserRouter.POST("uploadHeaderImg", v1.UploadHeaderImg) //上传头像
......
......@@ -20,7 +20,7 @@ func CreateExaCustomer(e model.ExaCustomer) (err error) {
// @title DeleteFileChunk
// @description delete a customer, 删除用户
// @auth (2020/04/05 20:22)
// @param e *model.ExaCustomer
// @param e model.ExaCustomer
// @return error
func DeleteExaCustomer(e model.ExaCustomer) (err error) {
......
......@@ -3,8 +3,8 @@ package service
import (
"gin-vue-admin/model"
"gin-vue-admin/utils"
"html/template"
"os"
"text/template"
)
// @title CreateTemp
......@@ -27,10 +27,18 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
if err != nil {
return err
}
serviceTmpl, err := template.ParseFiles(basePath + "/te/service.go.tpl")
if err != nil {
return err
}
feapiTmpl, err := template.ParseFiles(basePath + "/fe/api.js.tpl")
if err != nil {
return err
}
feTableTmpl, err := template.ParseFiles(basePath + "/fe/table.vue.tpl")
if err != nil {
return err
}
readmeTmpl, err := template.ParseFiles(basePath + "/readme.txt.tpl")
if err != nil {
return err
......@@ -43,30 +51,41 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
_modeldir := _te + autoCode.PackageName + "/model"
_apidir := _te + autoCode.PackageName + "/api"
_routerdir := _te + autoCode.PackageName + "/router"
_servicedir := _te + autoCode.PackageName + "/service"
//自动化前台代码目录
_fe := "./autoCode/fe/"
_fe_dir := _fe + autoCode.PackageName
_fe_apidir := _fe + autoCode.PackageName + "/api"
err = utils.CreateDir(_autoCode, _te, _dir, _modeldir, _apidir, _routerdir, _fe, _fe_dir, _fe_apidir)
_fe_tabledir := _fe + autoCode.PackageName + "/table"
err = utils.CreateDir(_autoCode, _te, _dir, _modeldir, _apidir, _routerdir, _servicedir, _fe, _fe_dir, _fe_apidir, _fe_tabledir)
if err != nil {
return err
}
model, err := os.OpenFile(_te+autoCode.PackageName+"/model/"+autoCode.PackageName+".go", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
api, err := os.OpenFile(_te+autoCode.PackageName+"/api/"+autoCode.PackageName+".go", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
model, err := os.OpenFile(_te+autoCode.PackageName+"/model/model.go", os.O_CREATE|os.O_WRONLY, 0755)
router, err := os.OpenFile(_te+autoCode.PackageName+"/router/"+autoCode.PackageName+".go", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
api, err := os.OpenFile(_te+autoCode.PackageName+"/api/api.go", os.O_CREATE|os.O_WRONLY, 0755)
service, err := os.OpenFile(_te+autoCode.PackageName+"/service/"+autoCode.PackageName+".go", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
router, err := os.OpenFile(_te+autoCode.PackageName+"/router/router.go", os.O_CREATE|os.O_WRONLY, 0755)
feapi, err := os.OpenFile(_fe+autoCode.PackageName+"/api/"+autoCode.PackageName+".js", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
feapi, err := os.OpenFile(_fe+autoCode.PackageName+"/api/api.js", os.O_CREATE|os.O_WRONLY, 0755)
fetable, err := os.OpenFile(_fe+autoCode.PackageName+"/table/"+autoCode.PackageName+".vue", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
readme, err := os.OpenFile(_autoCode+"readme.txt", os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
......@@ -85,10 +104,18 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
if err != nil {
return err
}
err = serviceTmpl.Execute(service, autoCode)
if err != nil {
return err
}
err = feapiTmpl.Execute(feapi, autoCode)
if err != nil {
return err
}
err = feTableTmpl.Execute(fetable, autoCode)
if err != nil {
return err
}
err = readmeTmpl.Execute(readme, autoCode)
if err != nil {
return err
......@@ -97,13 +124,18 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
_ = model.Close()
_ = api.Close()
_ = router.Close()
_ = service.Close()
_ = feapi.Close()
_ = fetable.Close()
_ = readme.Close()
fileList := []string{
_te + autoCode.PackageName + "/model/model.go",
_te + autoCode.PackageName + "/api/api.go",
_te + autoCode.PackageName + "/router/router.go",
_fe + autoCode.PackageName + "/api/api.js",
_te + autoCode.PackageName + "/model/" + autoCode.PackageName + ".go",
_te + autoCode.PackageName + "/api/" + autoCode.PackageName + ".go",
_te + autoCode.PackageName + "/router/" + autoCode.PackageName + ".go",
_te + autoCode.PackageName + "/service/" + autoCode.PackageName + ".go",
_fe + autoCode.PackageName + "/api/" + autoCode.PackageName + ".js",
_fe + autoCode.PackageName + "/table/" + autoCode.PackageName + ".vue",
_autoCode + "readme.txt",
}
err = utils.ZipFiles("./ginvueadmin.zip", fileList, ".", ".")
......
......@@ -4,9 +4,26 @@ import (
"errors"
"gin-vue-admin/global"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
"strconv"
)
// @title getMenuTreeMap
// @description 获取路由总树map
// @auth qm (2020/05/06 10:26)
// @return err error
// @return menusMsp map{string}[]SysBaseMenu
func getMenuTreeMap(authorityId string)(err error,treeMap map[string][]model.SysMenu){
var allMenus []model.SysMenu
treeMap = make(map[string][]model.SysMenu)
sql := "SELECT authority_menu.keep_alive,authority_menu.default_menu,authority_menu.created_at,authority_menu.updated_at,authority_menu.deleted_at,authority_menu.menu_level,authority_menu.parent_id,authority_menu.path,authority_menu.`name`,authority_menu.hidden,authority_menu.component,authority_menu.title,authority_menu.icon,authority_menu.sort,authority_menu.menu_id,authority_menu.authority_id FROM authority_menu WHERE authority_menu.authority_id = ? ORDER BY authority_menu.sort ASC"
err = global.GVA_DB.Raw(sql,authorityId).Scan(&allMenus).Error
for _,v := range allMenus{
treeMap[v.ParentId] = append(treeMap[v.ParentId], v)
}
return err,treeMap
}
// @title GetMenuTree
// @description 获取动态菜单树
// @auth (2020/04/05 20:22)
......@@ -15,10 +32,10 @@ import (
// @return menus []model.SysMenu
func GetMenuTree(authorityId string) (err error, menus []model.SysMenu) {
sql := "SELECT authority_menu.keep_alive,authority_menu.default_menu,authority_menu.created_at,authority_menu.updated_at,authority_menu.deleted_at,authority_menu.menu_level,authority_menu.parent_id,authority_menu.path,authority_menu.`name`,authority_menu.hidden,authority_menu.component,authority_menu.title,authority_menu.icon,authority_menu.sort,authority_menu.menu_id,authority_menu.authority_id FROM authority_menu WHERE authority_menu.authority_id = ? AND authority_menu.parent_id = ? ORDER BY authority_menu.sort ASC"
err = global.GVA_DB.Raw(sql, authorityId, 0).Scan(&menus).Error
err,menuTree := getMenuTreeMap(authorityId)
menus = menuTree["0"]
for i := 0; i < len(menus); i++ {
err = getChildrenList(&menus[i], sql)
err = getChildrenList(&menus[i], menuTree)
}
return err, menus
}
......@@ -30,10 +47,10 @@ func GetMenuTree(authorityId string) (err error, menus []model.SysMenu) {
// @param sql string
// @return err error
func getChildrenList(menu *model.SysMenu, sql string) (err error) {
err = global.GVA_DB.Raw(sql, menu.AuthorityId, menu.MenuId).Scan(&menu.Children).Error
func getChildrenList(menu *model.SysMenu,treeMap map[string][]model.SysMenu) (err error) {
menu.Children = treeMap[menu.MenuId]
for i := 0; i < len(menu.Children); i++ {
err = getChildrenList(&menu.Children[i], sql)
err = getChildrenList(&menu.Children[i], treeMap)
}
return err
}
......@@ -46,14 +63,12 @@ func getChildrenList(menu *model.SysMenu, sql string) (err error) {
// @return list interface{}
// @return total int
func GetInfoList(info request.PageInfo) (err error, list interface{}, total int) {
limit := info.PageSize
offset := info.PageSize * (info.Page - 1)
db := global.GVA_DB
func GetInfoList() (err error, list interface{}, total int) {
var menuList []model.SysBaseMenu
err = db.Limit(limit).Offset(offset).Where("parent_id = 0").Order("sort", true).Find(&menuList).Error
err,treeMap := getBaseMenuTreeMap()
menuList = treeMap["0"]
for i := 0; i < len(menuList); i++ {
err = getBaseChildrenList(&menuList[i])
err = getBaseChildrenList(&menuList[i],treeMap)
}
return err, menuList, total
}
......@@ -64,10 +79,10 @@ func GetInfoList(info request.PageInfo) (err error, list interface{}, total int)
// @param menu *model.SysBaseMenu
// @return err error
func getBaseChildrenList(menu *model.SysBaseMenu) (err error) {
err = global.GVA_DB.Where("parent_id = ?", menu.ID).Order("sort", true).Find(&menu.Children).Error
func getBaseChildrenList(menu *model.SysBaseMenu ,treeMap map[string][]model.SysBaseMenu) (err error) {
menu.Children = treeMap[strconv.Itoa(int(menu.ID))]
for i := 0; i < len(menu.Children); i++ {
err = getBaseChildrenList(&menu.Children[i])
err = getBaseChildrenList(&menu.Children[i],treeMap)
}
return err
}
......@@ -89,6 +104,22 @@ func AddBaseMenu(menu model.SysBaseMenu) (err error) {
return err
}
// @title getBaseMenuTreeMap
// @description 获取路由总树map
// @auth qm (2020/05/06 10:26)
// @return err error
// @return menusMsp map{string}[]SysBaseMenu
func getBaseMenuTreeMap()(err error,treeMap map[string][]model.SysBaseMenu){
var allMenus []model.SysBaseMenu
treeMap = make(map[string][]model.SysBaseMenu)
err = global.GVA_DB.Order("sort", true).Find(&allMenus).Error
for _,v := range allMenus{
treeMap[v.ParentId] = append(treeMap[v.ParentId], v)
}
return err,treeMap
}
// @title GetBaseMenuTree
// @description 获取基础路由树
// @auth (2020/04/05 20:22)
......@@ -96,9 +127,10 @@ func AddBaseMenu(menu model.SysBaseMenu) (err error) {
// @return menus []SysBaseMenu
func GetBaseMenuTree() (err error, menus []model.SysBaseMenu) {
err = global.GVA_DB.Where(" parent_id = ?", 0).Order("sort", true).Find(&menus).Error
err,treeMap := getBaseMenuTreeMap()
menus = treeMap["0"]
for i := 0; i < len(menus); i++ {
err = getBaseChildrenList(&menus[i])
err = getBaseChildrenList(&menus[i],treeMap)
}
return err, menus
}
......
// 空值校验工具 仅用于检验空字符串 其余类型请勿使用
package utils
import (
"errors"
"fmt"
"reflect"
)
func HasGap(input interface{}) error {
getType := reflect.TypeOf(input)
getValue := reflect.ValueOf(input)
// 获取方法字段
for i := 0; i < getType.NumField(); i++ {
field := getType.Field(i)
value := getValue.Field(i).Interface()
switch value.(type) {
case string:
if value == "" {
fmt.Printf("%s为空", field.Name)
return errors.New(fmt.Sprintf("%s为空", field.Name))
}
default:
if value == nil {
fmt.Printf("%s为空", field.Name)
return errors.New(fmt.Sprintf("%s为空", field.Name))
}
}
}
// 获取方法
// 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历
//for i := 0; i < getType.NumMethod(); i++ {
// m := getType.Method(i)
// fmt.Printf("%s: %v\n", m.Name, m.Type)
//}
return nil
}
......@@ -10,15 +10,12 @@ import (
"time"
)
var accessKey string = global.GVA_CONFIG.Qiniu.AccessKey // 你在七牛云的accessKey 这里是我个人测试号的key 仅供测试使用 恳请大家不要乱传东西
var secretKey string = global.GVA_CONFIG.Qiniu.SecretKey // 你在七牛云的secretKey 这里是我个人测试号的key 仅供测试使用 恳请大家不要乱传东西
// 接收两个参数 一个文件流 一个 bucket 你的七牛云标准空间的名字
func Upload(file *multipart.FileHeader, bucket string, urlPath string) (err error, path string, key string) {
func Upload(file *multipart.FileHeader) (err error, path string, key string) {
putPolicy := storage.PutPolicy{
Scope: bucket,
Scope: global.GVA_CONFIG.Qiniu.Bucket,
}
mac := qbox.NewMac(accessKey, secretKey)
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
upToken := putPolicy.UploadToken(mac)
cfg := storage.Config{}
// 空间对应的机房
......@@ -43,16 +40,15 @@ func Upload(file *multipart.FileHeader, bucket string, urlPath string) (err erro
fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename) // 文件名格式 自己可以改 建议保证唯一性
err = formUploader.Put(context.Background(), &ret, upToken, fileKey, f, dataLen, &putExtra)
if err != nil {
fmt.Println(err)
//qmlog.QMLog.Info(err)
global.GVA_LOG.Error("upload file fail:", err)
return err, "", ""
}
return err, urlPath + "/" + ret.Key, ret.Key
return err, global.GVA_CONFIG.Qiniu.ImgPath + "/" + ret.Key, ret.Key
}
func DeleteFile(bucket string, key string) error {
func DeleteFile(key string) error {
mac := qbox.NewMac(accessKey, secretKey)
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
cfg := storage.Config{
// 是否使用https域名进行资源管理
UseHTTPS: false,
......@@ -61,7 +57,7 @@ func DeleteFile(bucket string, key string) error {
// 如果没有特殊需求,默认不需要指定
//cfg.Zone=&storage.ZoneHuabei
bucketManager := storage.NewBucketManager(mac, &cfg)
err := bucketManager.Delete(bucket, key)
err := bucketManager.Delete(global.GVA_CONFIG.Qiniu.Bucket, key)
if err != nil {
fmt.Println(err)
return err
......
package utils
import (
"errors"
"reflect"
"strconv"
"strings"
)
type Rules map[string][]string
type RulesMap map[string]Rules
var CustomizeMap = make(map[string]Rules)
// 注册自定义规则方案建议在路由初始化层即注册
func RegisterRule(key string, rule Rules) (err error) {
if CustomizeMap[key] != nil {
return errors.New(key + "已注册,无法重复注册")
} else {
CustomizeMap[key] = rule
return nil
}
}
// 非空 不能为其对应类型的0值
func NotEmpty() string {
return "notEmpty"
}
//小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Lt(mark string) string {
return "lt=" + mark
}
//小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Le(mark string) string {
return "le=" + mark
}
//等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Eq(mark string) string {
return "eq=" + mark
}
//不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Ne(mark string) string {
return "ne=" + mark
}
//大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Ge(mark string) string {
return "ge=" + mark
}
//大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
func Gt(mark string) string {
return "gt=" + mark
}
// 校验方法 接收两个参数 入参实例,规则map
func Verify(st interface{}, roleMap Rules) (err error) {
compareMap := map[string]bool{
"lt": true,
"le": true,
"eq": true,
"ne": true,
"ge": true,
"gt": true,
}
typ := reflect.TypeOf(st)
val := reflect.ValueOf(st) //获取reflect.Type类型
kd := val.Kind() //获取到st对应的类别
if kd != reflect.Struct {
return errors.New("expect struct")
}
num := val.NumField()
//遍历结构体的所有字段
for i := 0; i < num; i++ {
tagVal := typ.Field(i)
val := val.Field(i)
if len(roleMap[tagVal.Name]) > 0 {
for _, v := range roleMap[tagVal.Name] {
switch {
case v == "notEmpty":
if isBlank(val) {
return errors.New(tagVal.Name + "值不能为空")
}
case compareMap[strings.Split(v, "=")[0]]:
if !compareVerify(val, v) {
return errors.New(tagVal.Name + "长度或值不在合法范围," + v)
}
}
}
}
}
return nil
}
// 长度和数字的校验方法 根据类型自动校验
func compareVerify(value reflect.Value, VerifyStr string) bool {
switch value.Kind() {
case reflect.String, reflect.Slice, reflect.Array:
return compare(value.Len(), VerifyStr)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return compare(value.Uint(), VerifyStr)
case reflect.Float32, reflect.Float64:
return compare(value.Float(), VerifyStr)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return compare(value.Int(), VerifyStr)
default:
return false
}
}
// 非空校验
func isBlank(value reflect.Value) bool {
switch value.Kind() {
case reflect.String:
return value.Len() == 0
case reflect.Bool:
return !value.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return value.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return value.Uint() == 0
case reflect.Float32, reflect.Float64:
return value.Float() == 0
case reflect.Interface, reflect.Ptr:
return value.IsNil()
}
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
}
func compare(value interface{}, VerifyStr string) bool {
VerifyStrArr := strings.Split(VerifyStr, "=")
val := reflect.ValueOf(value)
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
VInt, VErr := strconv.ParseInt(VerifyStrArr[1], 10, 64)
if VErr != nil {
return false
}
switch {
case VerifyStrArr[0] == "lt":
return val.Int() < VInt
case VerifyStrArr[0] == "le":
return val.Int() <= VInt
case VerifyStrArr[0] == "eq":
return val.Int() == VInt
case VerifyStrArr[0] == "ne":
return val.Int() != VInt
case VerifyStrArr[0] == "ge":
return val.Int() >= VInt
case VerifyStrArr[0] == "gt":
return val.Int() > VInt
default:
return false
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
VInt, VErr := strconv.Atoi(VerifyStrArr[1])
if VErr != nil {
return false
}
switch {
case VerifyStrArr[0] == "lt":
return val.Uint() < uint64(VInt)
case VerifyStrArr[0] == "le":
return val.Uint() <= uint64(VInt)
case VerifyStrArr[0] == "eq":
return val.Uint() == uint64(VInt)
case VerifyStrArr[0] == "ne":
return val.Uint() != uint64(VInt)
case VerifyStrArr[0] == "ge":
return val.Uint() >= uint64(VInt)
case VerifyStrArr[0] == "gt":
return val.Uint() > uint64(VInt)
default:
return false
}
case reflect.Float32, reflect.Float64:
VFloat, VErr := strconv.ParseFloat(VerifyStrArr[1], 64)
if VErr != nil {
return false
}
switch {
case VerifyStrArr[0] == "lt":
return val.Float() < VFloat
case VerifyStrArr[0] == "le":
return val.Float() <= VFloat
case VerifyStrArr[0] == "eq":
return val.Float() == VFloat
case VerifyStrArr[0] == "ne":
return val.Float() != VFloat
case VerifyStrArr[0] == "ge":
return val.Float() >= VFloat
case VerifyStrArr[0] == "gt":
return val.Float() > VFloat
default:
return false
}
default:
return false
}
}
......@@ -2878,7 +2878,8 @@
"version": "4.6.0",
"resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
"dev": true,
"optional": true
},
"coa": {
"version": "2.0.2",
......@@ -5245,7 +5246,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
......@@ -5266,12 +5268,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
......@@ -5286,17 +5290,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
......@@ -5413,7 +5420,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
......@@ -5425,6 +5433,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
......@@ -5439,6 +5448,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
......@@ -5446,12 +5456,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
......@@ -5470,6 +5482,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
......@@ -5550,7 +5563,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
......@@ -5562,6 +5576,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
......@@ -5647,7 +5662,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
......@@ -5683,6 +5699,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
......@@ -5702,6 +5719,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
......@@ -5745,12 +5763,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
......@@ -9872,7 +9892,8 @@
"version": "4.0.8",
"resolved": "https://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
"dev": true,
"optional": true
},
"rx-lite-aggregates": {
"version": "4.0.8",
......@@ -11147,6 +11168,14 @@
"integrity": "sha1-9d9zJFNAewkZHa5z4qjMc/OBqCY=",
"dev": true
},
"timeline-vuejs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/timeline-vuejs/-/timeline-vuejs-1.1.1.tgz",
"integrity": "sha512-jsdr0xNCBH/GBiW7qsOTbBxZuyk7WKD5YmtTGP1sm0su0fy+iBsEJLDyhHhQ4nTAxca8MkSbJhKGUgF5eNoEfA==",
"requires": {
"vue": "^2.5.17"
}
},
"timers-browserify": {
"version": "2.0.11",
"resolved": "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.11.tgz",
......
......@@ -27,7 +27,8 @@
"vue-router": "^3.1.3",
"vuescroll": "^4.14.4",
"vuex": "^3.1.1",
"vuex-persist": "^2.1.0"
"vuex-persist": "^2.1.0",
"timeline-vuejs": "1.1.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.11.0",
......
web/public/favicon.ico

16.6 KB | W: | H:

web/public/favicon.ico

4.2 KB | W: | H:

web/public/favicon.ico
web/public/favicon.ico
web/public/favicon.ico
web/public/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
......@@ -18,5 +18,6 @@ export default {
#app {
background: #eee;
height: 100vh;
overflow: hidden;
}
</style>
import axios from "axios";
import { Loading } from "element-ui";
let loadingInstance;
let service = axios.create();
service.interceptors.request.use((config) => {
loadingInstance = Loading.service({ fullscreen: true });
return config;
});
service.interceptors.response.use((resp) => {
loadingInstance.close();
return resp;
}, (error) => {
loadingInstance.close();
return error;
});
export function Commits(page) {
return service({
url: "https://api.github.com/repos/flipped-aurora/gin-vue-admin/commits?page=" +
page,
method: "get",
});
}
export function Members() {
return service({
url: "https://api.github.com/orgs/FLIPPED-AURORA/members",
method: "get",
});
}
\ No newline at end of file
<svg xmlns='http://www.w3.org/2000/svg' width='100%'><rect fill='#29adff' width='540' height='450'/><defs><linearGradient id='a' gradientUnits='userSpaceOnUse' x1='0' x2='0' y1='0' y2='100%' gradientTransform='rotate(279,720,373)'><stop offset='0' stop-color='#29adff'/><stop offset='1' stop-color='#42b983'/></linearGradient><pattern patternUnits='userSpaceOnUse' id='b' width='300' height='250' x='0' y='0' viewBox='0 0 1080 900'><g fill-opacity='0'><polygon fill='#444' points='90 150 0 300 180 300'/><polygon points='90 150 180 0 0 0'/><polygon fill='#AAA' points='270 150 360 0 180 0'/><polygon fill='#DDD' points='450 150 360 300 540 300'/><polygon fill='#999' points='450 150 540 0 360 0'/><polygon points='630 150 540 300 720 300'/><polygon fill='#DDD' points='630 150 720 0 540 0'/><polygon fill='#444' points='810 150 720 300 900 300'/><polygon fill='#FFF' points='810 150 900 0 720 0'/><polygon fill='#DDD' points='990 150 900 300 1080 300'/><polygon fill='#444' points='990 150 1080 0 900 0'/><polygon fill='#DDD' points='90 450 0 600 180 600'/><polygon points='90 450 180 300 0 300'/><polygon fill='#666' points='270 450 180 600 360 600'/><polygon fill='#AAA' points='270 450 360 300 180 300'/><polygon fill='#DDD' points='450 450 360 600 540 600'/><polygon fill='#999' points='450 450 540 300 360 300'/><polygon fill='#999' points='630 450 540 600 720 600'/><polygon fill='#FFF' points='630 450 720 300 540 300'/><polygon points='810 450 720 600 900 600'/><polygon fill='#DDD' points='810 450 900 300 720 300'/><polygon fill='#AAA' points='990 450 900 600 1080 600'/><polygon fill='#444' points='990 450 1080 300 900 300'/><polygon fill='#222' points='90 750 0 900 180 900'/><polygon points='270 750 180 900 360 900'/><polygon fill='#DDD' points='270 750 360 600 180 600'/><polygon points='450 750 540 600 360 600'/><polygon points='630 750 540 900 720 900'/><polygon fill='#444' points='630 750 720 600 540 600'/><polygon fill='#AAA' points='810 750 720 900 900 900'/><polygon fill='#666' points='810 750 900 600 720 600'/><polygon fill='#999' points='990 750 900 900 1080 900'/><polygon fill='#999' points='180 0 90 150 270 150'/><polygon fill='#444' points='360 0 270 150 450 150'/><polygon fill='#FFF' points='540 0 450 150 630 150'/><polygon points='900 0 810 150 990 150'/><polygon fill='#222' points='0 300 -90 450 90 450'/><polygon fill='#FFF' points='0 300 90 150 -90 150'/><polygon fill='#FFF' points='180 300 90 450 270 450'/><polygon fill='#666' points='180 300 270 150 90 150'/><polygon fill='#222' points='360 300 270 450 450 450'/><polygon fill='#FFF' points='360 300 450 150 270 150'/><polygon fill='#444' points='540 300 450 450 630 450'/><polygon fill='#222' points='540 300 630 150 450 150'/><polygon fill='#AAA' points='720 300 630 450 810 450'/><polygon fill='#666' points='720 300 810 150 630 150'/><polygon fill='#FFF' points='900 300 810 450 990 450'/><polygon fill='#999' points='900 300 990 150 810 150'/><polygon points='0 600 -90 750 90 750'/><polygon fill='#666' points='0 600 90 450 -90 450'/><polygon fill='#AAA' points='180 600 90 750 270 750'/><polygon fill='#444' points='180 600 270 450 90 450'/><polygon fill='#444' points='360 600 270 750 450 750'/><polygon fill='#999' points='360 600 450 450 270 450'/><polygon fill='#666' points='540 600 630 450 450 450'/><polygon fill='#222' points='720 600 630 750 810 750'/><polygon fill='#FFF' points='900 600 810 750 990 750'/><polygon fill='#222' points='900 600 990 450 810 450'/><polygon fill='#DDD' points='0 900 90 750 -90 750'/><polygon fill='#444' points='180 900 270 750 90 750'/><polygon fill='#FFF' points='360 900 450 750 270 750'/><polygon fill='#AAA' points='540 900 630 750 450 750'/><polygon fill='#FFF' points='720 900 810 750 630 750'/><polygon fill='#222' points='900 900 990 750 810 750'/><polygon fill='#222' points='1080 300 990 450 1170 450'/><polygon fill='#FFF' points='1080 300 1170 150 990 150'/><polygon points='1080 600 990 750 1170 750'/><polygon fill='#666' points='1080 600 1170 450 990 450'/><polygon fill='#DDD' points='1080 900 1170 750 990 750'/></g></pattern></defs><rect x='0' y='0' fill='url(#a)' width='100%' height='100%'/><rect x='0' y='0' fill='url(#b)' width='100%' height='100%'/></svg>
\ No newline at end of file
......@@ -14,6 +14,9 @@ import vueParticleLine from 'vue-particle-line'
import 'vue-particle-line/dist/vue-particle-line.css'
Vue.use(vueParticleLine)
// time line css
import '../node_modules/timeline-vuejs/dist/timeline-vuejs.css'
// 富文本插件
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
......
......@@ -18,12 +18,6 @@ const baseRouters = [{
name: 'register',
component: () =>
import ('@/view/login/register.vue')
},
{
path: "/404",
name: "404",
component: () =>
import ('@/view/error/index.vue')
}
]
......
......@@ -6,7 +6,7 @@ import { asyncMenu } from '@/api/menu'
const formatRouter = (routes) => {
routes && routes.map(item => {
item.meta.hidden = item.hidden
if (item.children.length > 0) {
if (item.children && item.children.length > 0) {
formatRouter(item.children)
}
})
......@@ -37,11 +37,20 @@ export const router = {
}]
const asyncRouterRes = await asyncMenu()
const asyncRouter = asyncRouterRes.data.menus
asyncRouter.push({
path: "404",
name: "404",
hidden: true,
meta: {
title: "迷路了*。*",
},
component: 'view/error/index.vue'
})
formatRouter(asyncRouter)
baseRouter[0].children = asyncRouter
baseRouter.push({
path: '*',
redirect: '/404'
redirect: '/layout/404'
})
asyncRouterHandle(baseRouter)
......
......@@ -621,6 +621,9 @@ li {
padding: 0 15px;
border-left: 1px solid #ebeef5;
border-right: 1px solid #ebeef5;
.demo-form-inline {
margin-bottom: 10px;
}
}
// table
......@@ -662,12 +665,7 @@ li {
border-radius: 4px;
}
}
}
// el-form
.el-form {
background-color: #fff;
padding: 10px 0;
padding: 20px 0!important;
}
.el-row {
......@@ -850,4 +848,195 @@ li {
}
}
// 导航*****
\ No newline at end of file
// 导航*****
// add 5.13
.el-container {
.admin-box {
padding: 24px 24px 40px 24px;
margin: 115px 24px 24px 24px;
border-radius: 2px;
.button-box {
border: none;
padding: 0 0 10px 0px;
}
.el-table--border {
border-radius: 4px;
margin-bottom: 15px;
}
.el-table--border {
th {
border-left: 1px solid #e8e8e8;
}
}
.el-table {
th {
padding: 5px 0;
.cell {
min-height: 34px;
line-height: 34px;
}
}
td {
padding: 8px 0;
}
td,
th.is-leaf {
border-bottom: 1px solid #e8e8e8;
}
}
.el-table__body-wrapper {
tr {
td {
padding: 5px 0;
.cell {
height: 34px;
line-height: 34px;
overflow: hidden;
}
}
}
.el-cascader {
line-height: 34px;
}
}
.upload {
.el-table__body-wrapper {
tr {
td {
padding: 5px 0;
.cell {
height: auto;
}
}
}
}
}
.search-term {
border-left: none;
border-right: none;
padding: 0 5px;
.el-form-item {
margin-bottom: 10px;
}
}
.el-pagination {
padding: 20px 0 0 0;
}
.upload-demo,
.upload {
padding: 0;
}
.system {
padding: 0;
}
.el-form.el-form--inline {
.el-form-item:last-child {
margin-bottom: 0;
}
}
.edit_container,
.edit {
padding: 0;
}
}
.admin-box:after,
.admin-box:before {
content: "";
display: block;
clear: both;
}
.tips {
margin-top: 10px;
font-size: 14px;
font-weight: 400;
color: #606266;
}
}
.el-container.layout-cont {
.header-cont,
.breadcrumb {
height: 40px !important;
line-height: 40px !important;
}
.main-cont.el-main {
background-color: #f0f2f5;
.menu-total {
font-size: 22px;
color: #838383;
margin-top: 7px;
}
// background-color: #f0f2f5;
}
}
.el-container.layout-cont {
.main-cont {
.router-history {
padding-bottom: 8px;
padding-top: 5px;
border-color: #f9f9f9;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.el-tabs__header {
margin: 0px 0 0 0;
.el-tabs__item {
line-height: 35px;
height: 35px;
}
}
}
}
}
.el-table__row {
.el-button.el-button--text.el-button--small {
position: relative;
}
.el-button.el-button--text.el-button--small::after {
content: '';
position: absolute;
width: 1px;
height: 50%;
top: 5px;
margin-left: 15px;
background-color: #e8e8e8;
}
.cell {
button:last-child::after {
content: ''!important;
position: absolute!important;
width: 0px!important;
}
}
}
.clear:after,
.clear:before {
content: "";
display: block;
clear: both;
}
.el-table--striped .el-table__body tr.el-table__row--level-1 td:first-child {
.cell {
.el-table__indent {
border-right: 1.5px solid #ccc;
margin-left: 6px;
}
.el-table__placeholder {
width: 10px;
}
}
}
.el-table--striped .el-table__body tr.el-table__row--level-2 td:first-child {
.cell {
.el-table__indent {
border-right: 1.5px solid #ccc;
margin-left: 6px;
}
.el-table__placeholder {
width: 10px;
}
}
}
\ No newline at end of file
......@@ -21,13 +21,13 @@ const showLoading = () => {
}
const closeLoading = () => {
acitveAxios--
if (acitveAxios <= 0) {
clearTimeout(timer)
loadingInstance && loadingInstance.close()
acitveAxios--
if (acitveAxios <= 0) {
clearTimeout(timer)
loadingInstance && loadingInstance.close()
}
}
}
//http request 拦截器
//http request 拦截器
service.interceptors.request.use(
config => {
showLoading()
......@@ -60,14 +60,12 @@ service.interceptors.response.use(
} else {
Message({
showClose: true,
message: response.data.msg,
message: response.data.msg || decodeURI(response.headers.msg),
type: 'error',
onClose: () => {
if (response.data.data && response.data.data.reload) {
store.commit('user/LoginOut')
}
}
})
if (response.data.data && response.data.data.reload) {
store.commit('user/LoginOut')
}
return Promise.reject(response.data.msg)
}
},
......
<template>
<div>
<el-row :gutter="10">
<el-col :span="12">
<el-card>
<div slot="header">gin-vue-admin</div>
<div>
<el-row>
<el-col :span="8" :offset="8">
<a href="https://github.com/flipped-aurora/gin-vue-admin">
<img
class="org-img dom-center"
src="@/assets/logo.png"
alt="gin-vue-admin"
/>
</a>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="8">
<a href="https://github.com/flipped-aurora/gin-vue-admin">
<img
class="dom-center"
src="https://img.shields.io/github/watchers/flipped-aurora/gin-vue-admin.svg?label=Watch"
alt=""
/>
</a>
</el-col>
<el-col :span="8">
<a href="https://github.com/flipped-aurora/gin-vue-admin">
<img
class="dom-center"
src="https://img.shields.io/github/stars/flipped-aurora/gin-vue-admin.svg?style=social"
alt=""/></a
></el-col>
<el-col :span="8">
<a href="https://github.com/flipped-aurora/gin-vue-admin">
<img
class="dom-center"
src="https://img.shields.io/github/forks/flipped-aurora/gin-vue-admin.svg?label=Fork"
alt=""/></a
></el-col>
</el-row>
</div>
</el-card>
<el-card style="margin-top: 20px">
<div slot="header">flipped-aurora团队</div>
<div>
<el-row>
<el-col :span="8" :offset="8">
<a href="https://github.com/flipped-aurora">
<img
class="org-img dom-center"
src="@/assets/flipped-aurora.png"
alt="flipped-aurora"
/>
</a>
</el-col>
</el-row>
<el-row style="margin-left: 40px" :gutter="20">
<template v-for="(item, index) in members">
<el-col :span="8" :key="index">
<a :href="item.html_url">
<img class="avatar-img" :src="item.avatar_url" />
<a class="author-name" style="">{{ item.login }}</a>
</a>
</el-col>
</template>
</el-row>
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<div slot="header">
提交记录
</div>
<div>
<Timeline
:timeline-items="dataTimeline"
:message-when-no-items="messageWhenNoItems"
:uniqueTimeline="true"
:unique-year="true"
:show-day-and-month="true"
order="desc"
dateLocale="zh-CN"
/>
</div>
<el-button class="load-more" @click="loadMore" type="text"
>Load more</el-button
>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import { Commits, Members } from "@/api/github";
import Timeline from "timeline-vuejs";
export default {
name: "Test",
components: {
Timeline,
},
data() {
return {
messageWhenNoItems: "There arent commits",
members: [],
dataTimeline: [],
page: 0,
};
},
created() {
this.loadCommits();
this.loadMembers();
},
methods: {
loadMore() {
this.page++;
this.loadCommits();
},
loadCommits() {
Commits(this.page).then(({ data }) => {
data.forEach((element) => {
if (element.commit.message) {
this.dataTimeline.push({
from: new Date(element.commit.author.date),
title: element.commit.author.name,
showDayAndMonth: true,
description: `<a style="color: #26191b" href="${element.html_url}">${element.commit.message}</a>`,
});
}
});
});
},
loadMembers() {
Members().then(({ data }) => {
this.members = data;
this.members.sort();
});
},
},
};
</script>
<style scoped>
.load-more {
margin-left: 120px;
}
.avatar-img {
float: left;
height: 40px;
width: 40px;
border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
margin-top: 15px;
}
.org-img {
height: 150px;
width: 150px;
}
.author-name {
float: left;
line-height: 65px !important;
margin-left: 10px;
color: darkblue;
line-height: 100px;
font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
"Lucida Sans Unicode", Geneva, Verdana, sans-serif;
}
.dom-center {
margin-left: 50%;
transform: translateX(-50%);
}
</style>
......@@ -168,10 +168,11 @@ export default {
<style lang="scss" scoped>
.big{
width: 100%;
margin:100px 0 0 0;
padding-top: 0;
background-color: rgb(243,243,243);;
.top{
width: 98%;
width: 100%;
height: 360px;
margin-top: 20px;
overflow: hidden;
......@@ -184,7 +185,7 @@ export default {
}
}
.mid{
width: 98%;
width: 100%;
height: 380px;
.chart-wrapper {
height: 340px;
......@@ -194,9 +195,12 @@ export default {
}
}
.bottom{
width: 97%;
width: 100%;
height: 300px;
margin: 20px 0;
.el-row{
margin-right: 4px !important;
}
.chart-player{
width: 100%;
height: 270px;
......
......@@ -4,6 +4,7 @@
<div class="inner">
<img src="../../assets/notFound.png">
<p>页面被神秘力量吸走了,请联系我们修复</p>
<p style="font-size:18px;line-height:40px;">常见问题为菜单未分配仪表盘,可自行分配仪表盘或修改默认路由</p>
<p></p>
<img src="../../assets/qm.png" class="leftPic">
</div>
......@@ -21,7 +22,7 @@ export default {
<style lang="scss">
.big{
width: 100%;
height: 100vh;
height: calc(100vh - 220px);
background-color: rgb(244,244,244);
position: relative;
}
......
......@@ -22,7 +22,7 @@
<!-- <span
v-if="this.file"
>{{Math.floor(((this.formDataList.length-this.waitNum)/this.formDataList.length)*100)}}%</span> -->
<h2 class="tips">此版本为先行体验功能测试版,样式美化和性能优化正在进行中,上传切片文件和合成的完整文件分别再QMPlusserver目录的breakpointDir文件夹和fileDir文件夹</h2>
<div class="tips">此版本为先行体验功能测试版,样式美化和性能优化正在进行中,上传切片文件和合成的完整文件分别再QMPlusserver目录的breakpointDir文件夹和fileDir文件夹</div>
</div>
</template>
<script>
......
<template>
<div>
<div class="search-term">
<div class="search-term">
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
<el-form-item>
<el-button @click="openDialog" type="primary">新增客户</el-button>
......@@ -25,22 +25,19 @@
<el-table-column label="按钮组">
<template slot-scope="scope">
<el-button @click="updateCustomer(scope.row)" size="small" type="text">变更</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="deleteCustomer(scope.row)">确定</el-button>
</div>
<el-button type="text" size="mini" slot="reference">删除</el-button>
</el-popover>
<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="deleteCustomer(scope.row)">确定</el-button>
</div>
<el-button type="text" size="mini" slot="reference">删除</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
<el-pagination
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
......@@ -51,7 +48,7 @@
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="新增Api">
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="客户">
<el-form :inline="true" :model="form" label-width="80px">
<el-form-item label="客户名">
<el-input autocomplete="off" v-model="form.customerName"></el-input>
......@@ -65,107 +62,101 @@
<el-button @click="enterDialog" type="primary">确 定</el-button>
</div>
</el-dialog>
在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示
<div class="tips"> 在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示</div>
</div>
</template>
<script>
import {
createExaCustomer,
updateExaCustomer,
deleteExaCustomer,
getExaCustomer,
getExaCustomerList
} from '@/api/customer'
import { formatTimeToStr } from '@/utils/data'
import infoList from '@/components/mixins/infoList'
import { mapGetters } from 'vuex'
} from "@/api/customer";
import { formatTimeToStr } from "@/utils/data";
import infoList from "@/components/mixins/infoList";
export default {
name: 'Customer',
mixins: [infoList],
data(){
return{
name: "Customer",
mixins: [infoList],
data() {
return {
listApi: getExaCustomerList,
dialogFormVisible:false,
visible:false,
type:"",
form:{
customerName:"",
customerPhoneData:""
dialogFormVisible: false,
visible: false,
type: "",
form: {
customerName: "",
customerPhoneData: ""
}
}
},
computed:{
...mapGetters('user', ['token'])
};
},
filters: {
filters: {
formatDate: function(time) {
if (time != null && time != '') {
var date = new Date(time)
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
if (time != null && time != "") {
var date = new Date(time);
return formatTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
} else {
return ''
return "";
}
}
},
methods:{
async updateCustomer(row){
const res = await getExaCustomer({ID:row.ID})
this.type = "update"
if(res.code == 0){
this.form = res.data.customer
this.dialogFormVisible = true
methods: {
async updateCustomer(row) {
const res = await getExaCustomer({ ID: row.ID });
this.type = "update";
if (res.code == 0) {
this.form = res.data.customer;
this.dialogFormVisible = true;
}
},
closeDialog(){
this.dialogFormVisible = false
closeDialog() {
this.dialogFormVisible = false;
this.form = {
customerName:"",
customerPhoneData:""
}
customerName: "",
customerPhoneData: ""
};
},
async deleteCustomer(row){
this.visible = false
const res = await deleteExaCustomer({ID:row.ID})
if (res.code == 0){
async deleteCustomer(row) {
this.visible = false;
const res = await deleteExaCustomer({ ID: row.ID });
if (res.code == 0) {
this.$message({
type:"success",
message:"删除成功"
})
this.getTableData()
type: "success",
message: "删除成功"
});
this.getTableData();
}
},
async enterDialog(){
let res
async enterDialog() {
let res;
switch (this.type) {
case "create":
res =await createExaCustomer(this.form)
break;
res = await createExaCustomer(this.form);
break;
case "update":
res =await updateExaCustomer(this.form)
break;
res = await updateExaCustomer(this.form);
break;
default:
res =await createExaCustomer(this.form)
break;
res = await createExaCustomer(this.form);
break;
}
if(res.code == 0){
this.closeDialog()
this.getTableData()
if (res.code == 0) {
this.closeDialog();
this.getTableData();
}
},
openDialog() {
this.type = "create"
this.dialogFormVisible = true
openDialog() {
this.type = "create";
this.dialogFormVisible = true;
}
},
created(){
this.getTableData()
created() {
this.getTableData();
}
}
};
</script>
<style>
......
<template>
<div v-loading.fullscreen.lock="fullscreenLoading">
<div class="upload">
<el-upload
:action="`${path}/fileUploadAndDownload/upload`"
:before-upload="checkFile"
:headers="{'x-token':token}"
:on-error="uploadError"
:on-success="uploadSuccess"
:show-file-list="false"
>
<el-button size="small" type="primary">点击上传</el-button>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<el-table :data="tableData" border stripe>
<el-table-column label="预览" width="100">
<template slot-scope="scope">
<img :alt="scope.row.alt" :src="scope.row.url" height="80" width="80" />
</template>
</el-table-column>
<el-table-column label="日期" prop="UpdatedAt" width="180">
<template slot-scope="scope">
<div>{{scope.row.UpdatedAt|formatDate}}</div>
</template>
</el-table-column>
<el-table-column label="文件名" prop="name" width="180"></el-table-column>
<el-table-column label="链接" prop="url"></el-table-column>
<el-table-column label="标签" prop="tag" width="100">
<template slot-scope="scope">
<el-tag
:type="scope.row.tag === 'jpg' ? 'primary' : 'success'"
disable-transitions
>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button @click="downloadFile(scope.row)" size="small" type="text">下载</el-button>
<el-button @click="deleteFile(scope.row)" size="small" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:style="{float:'right',padding:'20px'}"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<el-upload
:action="`${path}/fileUploadAndDownload/upload`"
:before-upload="checkFile"
:headers="{ 'x-token': token }"
:on-error="uploadError"
:on-success="uploadSuccess"
:show-file-list="false"
>
<el-button size="small" type="primary">点击上传</el-button>
<div class="el-upload__tip" slot="tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
<el-table :data="tableData" border stripe>
<el-table-column label="预览" width="100">
<template slot-scope="scope">
<img
:alt="scope.row.alt"
:src="scope.row.url"
height="80"
width="80"
/>
</template>
</el-table-column>
<el-table-column label="日期" prop="UpdatedAt" width="180">
<template slot-scope="scope">
<div>{{ scope.row.UpdatedAt | formatDate }}</div>
</template>
</el-table-column>
<el-table-column
label="文件名"
prop="name"
width="180"
></el-table-column>
<el-table-column label="链接" prop="url"></el-table-column>
<el-table-column label="标签" prop="tag" width="100">
<template slot-scope="scope">
<el-tag
:type="scope.row.tag === 'jpg' ? 'primary' : 'success'"
disable-transitions
>{{ scope.row.tag }}</el-tag
>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button @click="downloadFile(scope.row)" size="small" type="text"
>下载</el-button
>
<el-button @click="deleteFile(scope.row)" size="small" type="text"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
:style="{ float: 'right', padding: '20px' }"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
</div>
</template>
<script>
const path = process.env.VUE_APP_BASE_API
import { mapGetters } from 'vuex'
import infoList from '@/components/mixins/infoList'
import { getFileList, deleteFile } from '@/api/fileUploadAndDownload'
import { downloadImage } from '@/utils/downloadImg'
import { formatTimeToStr } from '@/utils/data'
const path = process.env.VUE_APP_BASE_API;
import { mapGetters } from "vuex";
import infoList from "@/components/mixins/infoList";
import { getFileList, deleteFile } from "@/api/fileUploadAndDownload";
import { downloadImage } from "@/utils/downloadImg";
import { formatTimeToStr } from "@/utils/data";
export default {
name: 'Upload',
name: "Upload",
mixins: [infoList],
data() {
return {
fullscreenLoading:false,
fullscreenLoading: false,
listApi: getFileList,
path: path,
tableData: []
}
tableData: [],
};
},
computed: {
...mapGetters('user', ['userInfo', 'token'])
...mapGetters("user", ["userInfo", "token"]),
},
filters: {
formatDate: function(time) {
if (time != null && time != '') {
var date = new Date(time)
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
if (time != null && time != "") {
var date = new Date(time);
return formatTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
} else {
return ''
return "";
}
}
},
},
methods: {
async deleteFile(row) {
this.$confirm('此操作将永久文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
this.$confirm("此操作将永久文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
const res = await deleteFile(row)
const res = await deleteFile(row);
if (res.code == 0) {
this.$message({
type: 'success',
message: '删除成功!'
})
this.getTableData()
type: "success",
message: "删除成功!",
});
this.getTableData();
}
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
type: "info",
message: "已取消删除",
});
});
},
checkFile(file) {
this.fullscreenLoading = true
const isJPG = file.type === 'image/jpeg'
const isPng = file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
this.fullscreenLoading = true;
const isJPG = file.type === "image/jpeg";
const isPng = file.type === "image/png";
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG && !isPng) {
this.$message.error('上传头像图片只能是 JPG或png 格式!')
this.fullscreenLoading = false
this.$message.error("上传头像图片只能是 JPG或png 格式!");
this.fullscreenLoading = false;
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
this.fullscreenLoading = false
this.$message.error("上传头像图片大小不能超过 2MB!");
this.fullscreenLoading = false;
}
return (isPng || isJPG) && isLt2M
return (isPng || isJPG) && isLt2M;
},
uploadSuccess(res) {
this.$message({
type: 'success',
message: '上传成功'
})
this.fullscreenLoading = false;
if (res.code == 0) {
this.getTableData()
this.$message({
type: "success",
message: "上传成功",
});
if (res.code == 0) {
this.getTableData();
}
} else {
this.$message({
type: "warning",
message: res.msg,
});
}
this.fullscreenLoading = false
},
uploadError() {
this.$message({
type: 'error',
message: '上传失败'
})
this.fullscreenLoading = false
type: "error",
message: "上传失败",
});
this.fullscreenLoading = false;
},
downloadFile(row) {
downloadImage(row.url, row.name)
}
downloadImage(row.url, row.name);
},
},
created() {
this.getTableData();
},
created(){
this.getTableData()
}
}
</script>
\ No newline at end of file
};
</script>
此差异已折叠。
<template>
<component :is="menuComponent" :routerInfo="routerInfo" v-if="!routerInfo.hidden">
<template v-if="routerInfo.children.length">
<template v-if="routerInfo.children&&routerInfo.children.length">
<AsideComponent :key="item.name" :routerInfo="item" v-for="item in routerInfo.children" />
</template>
</component>
......@@ -14,7 +14,7 @@ export default {
name: 'AsideComponent',
computed: {
menuComponent() {
if (this.routerInfo.children.filter(item=>!item.hidden).length) {
if (this.routerInfo.children&&this.routerInfo.children.filter(item=>!item.hidden).length) {
return 'AsyncSubmenu'
} else {
return 'MenuItem'
......
......@@ -2,7 +2,7 @@
<div>
<el-scrollbar style="height:calc(100vh)">
<el-menu
:class="['el-menu-vertical',!isCollapse&&'noCollapse']"
class="el-menu-vertical"
:collapse="isCollapse"
:collapse-transition="true"
:default-active="active"
......@@ -50,9 +50,7 @@ export default {
if(screenWidth<1000){
this.isCollapse = !this.isCollapse
}
this.$bus.on('totalCollapse', () => {
this.isCollapse = !this.isCollapse
})
this.$bus.on('collapse', (item) => {
this.isCollapse = item
})
......@@ -64,7 +62,6 @@ export default {
}
},
beforeDestroy() {
this.$bus.off('totalCollapse')
this.$bus.off('collapse')
}
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -7,6 +7,7 @@
:data="apiTreeData"
:default-checked-keys="apiTreeIds"
:props="apiDefaultProps"
@check="nodeChange"
default-expand-all
highlight-current
node-key="onlyId"
......@@ -32,6 +33,7 @@ export default {
return {
apiTreeData: [],
apiTreeIds: [],
needConfirm:false,
apiDefaultProps: {
children: 'children',
label: 'description'
......@@ -39,6 +41,13 @@ export default {
}
},
methods: {
nodeChange(){
this.needConfirm = true
},
// 暴露给外层使用的切换拦截统一方法
enterAndNext(){
this.authApiEnter()
},
// 创建api树方法
buildApiTree(apis) {
const apiObj = new Object()
......@@ -78,7 +87,7 @@ export default {
casbinInfos
})
if (res.code == 0) {
this.$message({ type: 'success', message: res.msg })
this.$message({ type: 'success', message: "api设置成功" })
}
}
},
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册