未验证 提交 2527251b 编写于 作者: R rainyan 提交者: GitHub

Merge pull request #65 from flipped-aurora/gin-vue-admin_v2_dev

Gin vue admin v2 dev
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.pnp.*
**/node_modules
FROM golang:alpine as builder
RUN apk add --update --no-cache yarn make g++
RUN yarn global add cross-env node-sass
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
GO111MODULE=on \
CGO_ENABLED=1
WORKDIR /go/src/gin-vue-admin
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
COPY server/ ./
RUN go env && go list && go build -v -a -ldflags "-extldflags \"-static\" " -o gvadmin .
WORKDIR /web
COPY web/ ./
RUN yarn install && yarn run build
FROM nginx:alpine
LABEL MAINTAINER="rikugun"
RUN apk add --no-cache gettext tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
date && \
apk del tzdata
COPY docker/etc/nginx/nginx.conf.tpl /etc/nginx/nginx.conf.tpl
WORKDIR /app
#copy web
COPY --from=builder /web/dist/ /var/www/
#copy go app
COPY --from=builder /go/src/gin-vue-admin/gvadmin ./
COPY --from=builder /go/src/gin-vue-admin/db.db ./
COPY --from=builder /go/src/gin-vue-admin/config.yaml ./
COPY --from=builder /go/src/gin-vue-admin/resource ./resource
COPY docker/docker-start.sh ./
ENV API_SERVER="http://localhost:8888/"
EXPOSE 80
ENTRYPOINT ["./docker-start.sh"]
......@@ -68,7 +68,7 @@ Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-adm
```
- node版本 > v8.6.0
- golang版本 >= v1.11
- IDE推荐:Golang
- IDE推荐:Goland
- 各位在clone项目以后,把db文件导入自己创建的库后,最好前往七牛云申请自己的空间地址。
- 替换掉项目中的七牛云公钥,私钥,仓名和默认url地址,以免发生测试文件数据错乱
```
......
#!/bin/sh
envsubst '$API_SERVER' < /etc/nginx/nginx.conf.tpl > /etc/nginx/nginx.conf
env nginx
./gvadmin
daemon on;
worker_processes 50;
#error_log /dev/stdout warn;
error_log /var/log/nginx/error.log error;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# See http://licson.net/post/optimizing-nginx-for-large-file-delivery/ for more detail
# This optimizes the server for HLS fragment delivery
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access_log /dev/stdout combined;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 10m;
server {
listen 80;
# Uncomment these lines to enable SSL.
# Update the ssl paths with your own certificate and private key.
# listen 443 ssl;
# ssl_certificate /opt/certs/example.com.crt;
# ssl_certificate_key /opt/certs/example.com.key;
location / {
root /var/www;
try_files $uri $uri/ /index.html;
index index.html;
}
location /v1/ {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_pass ${API_SERVER} ;
}
}
}
FROM centos:7.6.1810
# 设置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 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;
EXPOSE 8888
CMD ["gin-vue/app"]
\ No newline at end of file
......@@ -29,6 +29,25 @@ func CreateAuthority(c *gin.Context) {
}
}
// @Tags authority
// @Summary 拷贝角色
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body response.SysAuthorityCopyResponse true "拷贝角色"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"拷贝成功"}"
// @Router /authority/copyAuthority [post]
func CopyAuthority(c *gin.Context) {
var copyInfo resp.SysAuthorityCopyResponse
_ = c.ShouldBindJSON(&copyInfo)
err, authBack := service.CopyAuthority(copyInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
} else {
response.OkWithData(resp.SysAuthorityResponse{Authority: authBack}, c)
}
}
// @Tags authority
// @Summary 删除角色
// @Security ApiKeyAuth
......
......@@ -13,14 +13,14 @@ mysql:
username: root
password: 'Aa@6447985'
path: '127.0.0.1:3306'
db-name: 'qmplus'
db-name: 'qmPlus'
config: 'charset=utf8&parseTime=True&loc=Local'
max-idle-conns: 10
max-open-conns: 10
log-mode: true
#sqlite 配置
sqlite:
path: db/db.db
path: db.db
log-mode: true
config: 'loc=Asia/Shanghai'
# oss configuration
......@@ -31,7 +31,7 @@ qiniu:
# redis configuration
redis:
addr: '127.0.0.1:6379'
passwprd: ''
password: ''
db: 0
# system configuration
......@@ -39,7 +39,7 @@ system:
use-multipoint: false
env: 'public' # Change to "develop" to skip authentication for development mode
addr: 8888
db-type: "mysql"
db-type: "mysql" # support mysql/sqlite
# captcha configuration
captcha:
......
package config
type Server struct {
Mysql Mysql `mapstructure:"mysql" json:"mysql"`
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite"`
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu"`
Casbin Casbin `mapstructure:"casbin" json:"casbin"`
Redis Redis `mapstructure:"redis" json:"redis"`
System System `mapstructure:"system" json:"system"`
JWT JWT `mapstructure:"jwt" json:"jwt"`
Captcha Captcha `mapstructure:"captcha" json:"captcha"`
Log Log `mapstructure:"log" json:"log"`
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite" yaml:"sqlite"`
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
System System `mapstructure:"system" json:"system" yaml:"system"`
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
Log Log `mapstructure:"log" json:"log" yaml:"log"`
}
type System struct {
UseMultipoint bool `mapstructure:"use-multipoint" json:"useMultipoint"`
Env string `mapstructure:"env" json:"env"`
Addr int `mapstructure:"addr" json:"addr"`
DbType string `mapstructure:"db-type" json:"dbType"`
UseMultipoint bool `mapstructure:"use-multipoint" json:"useMultipoint" yaml:"use-multipoint"`
Env string `mapstructure:"env" json:"env" yaml:"env"`
Addr int `mapstructure:"addr" json:"addr" yaml:"addr"`
DbType string `mapstructure:"db-type" json:"dbType" yaml:"db-type"`
}
type JWT struct {
SigningKey string `mapstructure:"signing-key" json:"signingKey"`
SigningKey string `mapstructure:"signing-key" json:"signingKey" yaml:"signing-key"`
}
type Casbin struct {
ModelPath string `mapstructure:"model-path" json:"modelPath"`
ModelPath string `mapstructure:"model-path" json:"modelPath" yaml:"model-path"`
}
type Mysql struct {
Username string `mapstructure:"username" json:"username"`
Password string `mapstructure:"password" json:"password"`
Path string `mapstructure:"path" json:"path"`
Dbname string `mapstructure:"db-name" json:"dbname"`
Config string `mapstructure:"config" json:"config"`
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns"`
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns"`
LogMode bool `mapstructure:"log-mode" json:"logMode"`
Username string `mapstructure:"username" json:"username" yaml:"username"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
Path string `mapstructure:"path" json:"path" yaml:"path"`
Dbname string `mapstructure:"db-name" json:"dbname" yaml:"db-name"`
Config string `mapstructure:"config" json:"config" yaml:"config"`
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
}
type Redis struct {
Addr string `mapstructure:"addr" json:"addr"`
Password string `mapstructure:"password" json:"password"`
DB int `mapstructure:"db" json:"db"`
Addr string `mapstructure:"addr" json:"addr" yaml:"addr"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
DB int `mapstructure:"db" json:"db" yaml:"db"`
}
type Qiniu struct {
AccessKey string `mapstructure:"access-key" json:"accessKey"`
SecretKey string `mapstructure:"secret-key" json:"secretKey"`
AccessKey string `mapstructure:"access-key" json:"accessKey" yaml:"access-key"`
SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`
}
type Captcha struct {
KeyLong int `mapstructure:"key-long" json:"keyLong"`
ImgWidth int `mapstructure:"img-width" json:"imgWidth"`
ImgHeight int `mapstructure:"img-height" json:"imgHeight"`
KeyLong int `mapstructure:"key-long" json:"keyLong" yaml:"key-long"`
ImgWidth int `mapstructure:"img-width" json:"imgWidth" yaml:"img-width"`
ImgHeight int `mapstructure:"img-height" json:"imgHeight" yaml:"img-height"`
}
type Log struct {
Prefix string `mapstructure:"prefix" json:"prefix"`
LogFile bool `mapstructure:"log-file" json:"logFile"`
Stdout string `mapstructure:"stdout" json:"stdout"`
File string `mapstructure:"file" json:"file"`
Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
LogFile bool `mapstructure:"log-file" json:"logFile" yaml:"log-file"`
Stdout string `mapstructure:"stdout" json:"stdout" yaml:"stdout"`
File string `mapstructure:"file" json:"file" yaml:"file"`
}
type Sqlite struct {
Username string `mapstructure:"username" json:"username"`
Password string `mapstructure:"password" json:"password"`
Path string `mapstructure:"path" json:"path"`
Config string `mapstructure:"config" json:"config"`
LogMode bool `mapstructure:"log-mode" json:"logMode"`
Username string `mapstructure:"username" json:"username" yaml:"username"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
Path string `mapstructure:"path" json:"path" yaml:"path"`
Config string `mapstructure:"config" json:"config" yaml:"config"`
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
}
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// 2020-04-15 09:37:13.5084762 +0800 CST m=+0.126566601
// 2020-04-20 14:50:58.4141704 +0800 CST m=+0.881639701
package docs
......@@ -248,6 +248,45 @@ var doc = `{
}
}
},
"/authority/copyAuthority": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"authority"
],
"summary": "拷贝角色",
"parameters": [
{
"description": "拷贝角色",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/response.SysAuthorityCopyResponse"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"拷贝成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/authority/createAuthority": {
"post": {
"security": [
......@@ -404,6 +443,45 @@ var doc = `{
}
}
},
"/authority/updateAuthority": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"authority"
],
"summary": "设置角色资源权限",
"parameters": [
{
"description": "设置角色资源权限",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/model.SysAuthority"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"设置成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/autoCode/createTemp": {
"post": {
"security": [
......@@ -1588,6 +1666,45 @@ var doc = `{
}
}
},
"/user/deleteUser": {
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"SysUser"
],
"summary": "删除用户",
"parameters": [
{
"description": "删除用户",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/request.SetUserAuth"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/user/getUserList": {
"post": {
"security": [
......@@ -2072,12 +2189,18 @@ var doc = `{
"component": {
"type": "string"
},
"defaultMenu": {
"type": "boolean"
},
"hidden": {
"type": "boolean"
},
"icon": {
"type": "string"
},
"keepAlive": {
"type": "boolean"
},
"name": {
"type": "string"
},
......@@ -2317,6 +2440,25 @@ var doc = `{
"type": "string"
}
}
},
"response.SysAuthorityCopyResponse": {
"type": "object",
"properties": {
"authority": {
"type": "object",
"$ref": "#/definitions/model.SysAuthority"
},
"oldAuthorityId": {
"type": "integer"
}
}
}
},
"securityDefinitions": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "x-token",
"in": "header"
}
}
}`
......@@ -2332,12 +2474,12 @@ type swaggerInfo struct {
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "",
Version: "0.0.1",
Host: "",
BasePath: "",
BasePath: "/",
Schemes: []string{},
Title: "",
Description: "",
Title: "Swagger Example API",
Description: "This is a sample Server pets",
}
type s struct{}
......
{
"swagger": "2.0",
"info": {
"description": "This is a sample Server pets",
"title": "Swagger Example API",
"contact": {},
"license": {}
"license": {},
"version": "0.0.1"
},
"basePath": "/",
"paths": {
"/api/createApi": {
"post": {
......@@ -227,6 +231,45 @@
}
}
},
"/authority/copyAuthority": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"authority"
],
"summary": "拷贝角色",
"parameters": [
{
"description": "拷贝角色",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/response.SysAuthorityCopyResponse"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"拷贝成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/authority/createAuthority": {
"post": {
"security": [
......@@ -383,6 +426,45 @@
}
}
},
"/authority/updateAuthority": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"authority"
],
"summary": "设置角色资源权限",
"parameters": [
{
"description": "设置角色资源权限",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/model.SysAuthority"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"设置成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/autoCode/createTemp": {
"post": {
"security": [
......@@ -1567,6 +1649,45 @@
}
}
},
"/user/deleteUser": {
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"SysUser"
],
"summary": "删除用户",
"parameters": [
{
"description": "删除用户",
"name": "data",
"in": "body",
"required": true,
"schema": {
"type": "object",
"$ref": "#/definitions/request.SetUserAuth"
}
}
],
"responses": {
"200": {
"description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/user/getUserList": {
"post": {
"security": [
......@@ -2051,12 +2172,18 @@
"component": {
"type": "string"
},
"defaultMenu": {
"type": "boolean"
},
"hidden": {
"type": "boolean"
},
"icon": {
"type": "string"
},
"keepAlive": {
"type": "boolean"
},
"name": {
"type": "string"
},
......@@ -2296,6 +2423,25 @@
"type": "string"
}
}
},
"response.SysAuthorityCopyResponse": {
"type": "object",
"properties": {
"authority": {
"type": "object",
"$ref": "#/definitions/model.SysAuthority"
},
"oldAuthorityId": {
"type": "integer"
}
}
}
},
"securityDefinitions": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "x-token",
"in": "header"
}
}
}
\ No newline at end of file
basePath: /
definitions:
config.Captcha:
properties:
......@@ -217,10 +218,14 @@ definitions:
type: array
component:
type: string
defaultMenu:
type: boolean
hidden:
type: boolean
icon:
type: string
keepAlive:
type: boolean
name:
type: string
parentId:
......@@ -380,9 +385,20 @@ definitions:
uuid:
type: string
type: object
response.SysAuthorityCopyResponse:
properties:
authority:
$ref: '#/definitions/model.SysAuthority'
type: object
oldAuthorityId:
type: integer
type: object
info:
contact: {}
description: This is a sample Server pets
license: {}
title: Swagger Example API
version: 0.0.1
paths:
/api/createApi:
post:
......@@ -520,6 +536,30 @@ paths:
summary: 创建基础api
tags:
- SysApi
/authority/copyAuthority:
post:
consumes:
- application/json
parameters:
- description: 拷贝角色
in: body
name: data
required: true
schema:
$ref: '#/definitions/response.SysAuthorityCopyResponse'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"拷贝成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 拷贝角色
tags:
- authority
/authority/createAuthority:
post:
consumes:
......@@ -616,6 +656,30 @@ paths:
summary: 设置角色资源权限
tags:
- authority
/authority/updateAuthority:
post:
consumes:
- application/json
parameters:
- description: 设置角色资源权限
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysAuthority'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"设置成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 设置角色资源权限
tags:
- authority
/autoCode/createTemp:
post:
consumes:
......@@ -1343,6 +1407,30 @@ paths:
summary: 用户修改密码
tags:
- SysUser
/user/deleteUser:
delete:
consumes:
- application/json
parameters:
- description: 删除用户
in: body
name: data
required: true
schema:
$ref: '#/definitions/request.SetUserAuth'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"修改成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 删除用户
tags:
- SysUser
/user/getUserList:
post:
consumes:
......@@ -1438,4 +1526,9 @@ paths:
summary: 注册工作流
tags:
- workflow
securityDefinitions:
ApiKeyAuth:
in: header
name: x-token
type: apiKey
swagger: "2.0"
......@@ -11,6 +11,7 @@ import (
)
//初始化总路由
func Routers() *gin.Engine {
var Router = gin.Default()
......
......@@ -7,6 +7,13 @@ import (
//"runtime"
)
// @title Swagger Example API
// @version 0.0.1
// @description This is a sample Server pets
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name x-token
// @BasePath /
func main() {
switch global.GVA_CONFIG.System.DbType {
case "mysql":
......
......@@ -5,3 +5,8 @@ import "gin-vue-admin/model"
type SysAuthorityResponse struct {
Authority model.SysAuthority `json:"authority"`
}
type SysAuthorityCopyResponse struct {
Authority model.SysAuthority `json:"authority"`
OldAuthorityId string `json:"oldAuthorityId"`
}
package response
import "gin-vue-admin/model/request"
type PolicyPathResponse struct {
Paths []map[string]string `json:"paths"`
Paths []request.CasbinInfo `json:"paths"`
}
......@@ -12,6 +12,7 @@ func InitAuthorityRouter(Router *gin.RouterGroup) {
AuthorityRouter.POST("createAuthority", v1.CreateAuthority) //创建角色
AuthorityRouter.POST("deleteAuthority", v1.DeleteAuthority) //删除角色
AuthorityRouter.PUT("updateAuthority", v1.UpdateAuthority) //更新角色
AuthorityRouter.POST("copyAuthority", v1.CopyAuthority) //更新角色
AuthorityRouter.POST("getAuthorityList", v1.GetAuthorityList) //获取角色列表
AuthorityRouter.POST("setDataAuthority", v1.SetDataAuthority) //设置角色资源权限
}
......
......@@ -53,6 +53,7 @@ func GetFileRecordInfoList(info request.PageInfo) (err error, list interface{},
offset := info.PageSize * (info.Page - 1)
db := global.GVA_DB
var fileLists []model.ExaFileUploadAndDownload
err = db.Find(&fileLists).Count(&total).Error
err = db.Limit(limit).Offset(offset).Order("updated_at desc").Find(&fileLists).Error
return err, fileLists, total
}
......@@ -5,6 +5,8 @@ import (
"gin-vue-admin/global"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
"gin-vue-admin/model/response"
"strconv"
)
// @title CreateAuthority
......@@ -19,6 +21,33 @@ func CreateAuthority(auth model.SysAuthority) (err error, authority model.SysAut
return err, auth
}
// @title CopyAuthority
// @description 复制一个角色
// @auth (2020/04/05 20:22)
// @param copyInfo response.SysAuthorityCopyResponse
// @return error
// @return authority model.SysAuthority
func CopyAuthority(copyInfo response.SysAuthorityCopyResponse) (err error, authority model.SysAuthority) {
copyInfo.Authority.Children = []model.SysAuthority{}
err, menus := GetMenuAuthority(copyInfo.OldAuthorityId)
var baseMenu []model.SysBaseMenu
for _, v := range menus {
intNum, _ := strconv.Atoi(v.MenuId)
v.SysBaseMenu.ID = uint(intNum)
baseMenu = append(baseMenu, v.SysBaseMenu)
}
copyInfo.Authority.SysBaseMenus = baseMenu
err = global.GVA_DB.Create(&copyInfo.Authority).Error
paths := GetPolicyPathByAuthorityId(copyInfo.OldAuthorityId)
err = UpdateCasbin(copyInfo.Authority.AuthorityId, paths)
if err != nil {
_ = DeleteAuthority(&copyInfo.Authority)
}
return err, copyInfo.Authority
}
// @title UpdateAuthority
// @description 更改一个角色
// @auth (2020/04/05 20:22)
......
......@@ -71,13 +71,13 @@ func UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod
// @param authorityId string
// @return []string
func GetPolicyPathByAuthorityId(authorityId string) (pathMaps []map[string]string) {
func GetPolicyPathByAuthorityId(authorityId string) (pathMaps []request.CasbinInfo) {
e := Casbin()
list := e.GetFilteredPolicy(0, authorityId)
for _, v := range list {
pathMaps = append(pathMaps, map[string]string{
"path": v[1],
"method": v[2],
pathMaps = append(pathMaps, request.CasbinInfo{
Path: v[1],
Method: v[2],
})
}
return pathMaps
......
......@@ -79,6 +79,7 @@ func GetUserInfoList(info request.PageInfo) (err error, list interface{}, total
offset := info.PageSize * (info.Page - 1)
db := global.GVA_DB
var userList []model.SysUser
err = db.Find(&userList).Count(&total).Error
err = db.Limit(limit).Offset(offset).Preload("Authority").Find(&userList).Error
return err, userList, total
}
......
.todoapp {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
color: #4d4d4d;
min-width: 230px;
max-width: 666px;
margin: 0 auto ;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
background: #fff;
z-index: 1;
position: relative;
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
:focus {
outline: 0;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 18px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
padding: 10px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
.toggle-all {
text-align: center;
border: none;
/* Mobile Safari */
opacity: 0;
position: absolute;
}
.toggle-all+label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.toggle-all+label:before {
content: '❯';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked+label:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 12px 16px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none;
/* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle {
opacity: 0;
}
.todo-list li .toggle+label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
background-size: 36px;
}
.todo-list li .toggle:checked+label {
background-size: 36px;
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
.todo-list li label {
word-break: break-all;
padding: 15px 15px 15px 50px;
display: block;
line-height: 1.0;
font-size: 14px;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
transition: color 0.2s ease-out;
cursor: pointer;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
position: relative;
padding: 10px 15px;
height: 40px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 40px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
position: relative;
z-index: 1;
list-style: none;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
font-size: 12px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}
}
......@@ -48,13 +48,8 @@
}
const defalutList = [
{ text: 'star this repository', done: false },
{ text: 'fork this repository', done: false },
{ text: 'follow author', done: false },
{ text: 'vue-element-admin', done: true },
{ text: 'vue', done: true },
{ text: 'element-ui', done: true },
{ text: 'axios', done: true },
{ text: 'webpack', done: true }
{ text: 'vue-element-admin', done: true }
]
export default {
components: { Todo },
......@@ -123,5 +118,5 @@
</script>
<style lang="scss">
/*@import './index.scss';*/
@import './index.scss';
</style>
......@@ -22,7 +22,7 @@
<div class="top">
<div id="main" class="chart-container"></div>
</div>
<!-- <div class="bottom">
<div class="bottom">
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="12">
<div class="chart-player">
......@@ -30,11 +30,12 @@
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="12">
<div style="background:pink;">
<div class="chart-player">
<todo-list />
</div>
</el-col>
</el-row>
</div> -->
</div>
</div>
</template>
......@@ -45,7 +46,9 @@ require('echarts/theme/macarons') // echarts theme
import RaddarChart from "./component/RaddarChart"
import stackMap from "./component/stackMap"
import Sunburst from "./component/Sunburst"
// import musicPlayer from "./component/musicPlayer"
import musicPlayer from "./component/musicPlayer"
import TodoList from "./component/todoList"
export default {
name: 'Dashboard',
data() {
......@@ -57,7 +60,8 @@ export default {
RaddarChart, //雷达图
stackMap, //堆叠图
Sunburst, //旭日图
// musicPlayer //音乐播放器
musicPlayer, //音乐播放器
TodoList //TodoList
},
mounted() {
let myChart = echarts.init(document.getElementById('main'),'macarons');
......@@ -190,13 +194,13 @@ export default {
}
}
.bottom{
width: 98%;
height: 230px;
margin-top: 20px;
width: 97%;
height: 300px;
margin: 20px 0;
.chart-player{
width: 100%;
height: 100%;
padding: 20px;
height: 270px;
padding: 10px;
background-color: #fff;
}
}
......
......@@ -25,7 +25,7 @@
placeholder="请输入验证码"
maxlength="10"
/>
<img :src="path + picPath" alt="请输入验证码" @click="loginVefify()" class="vPic">
<img v-if="picPath" :src="path + picPath" alt="请输入验证码" @click="loginVefify()" class="vPic">
</el-form-item>
<el-form-item>
<el-button @click="submitForm" style="width:100%">登 录</el-button>
......
......@@ -78,11 +78,6 @@
<el-form-item label="secretKey">
<el-input v-model="config.qiniu.secretKey"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="update" type="primary">立即更新</el-button>
<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
</el-form-item>
<h2>验证码配置</h2>
<el-form-item label="keyLong">
<el-input v-model.number="config.captcha.keyLong"></el-input>
......@@ -93,11 +88,6 @@
<el-form-item label="imgHeight">
<el-input v-model.number="config.captcha.imgHeight"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="update" type="primary">立即更新</el-button>
<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
</el-form-item>
<h2>日志配置</h2>
<el-form-item label="prefix">
<el-input v-model.number="config.log.prefix"></el-input>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册