未验证 提交 ab2dd0c3 编写于 作者: Mr.奇淼('s avatar Mr.奇淼( 提交者: GitHub

Merge pull request #583 from RickieL/master

新增验证码使用redis存储方式
此差异已折叠。
此差异已折叠。
# Security Policy
## Reporting a Vulnerability
Please report security issues to qimiaojiangjizhao@gmail.com
FROM golang:alpine FROM golang:alpine
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io,direct
WORKDIR /go/src/gin-vue-admin WORKDIR /go/src/gin-vue-admin
COPY . . COPY . .
RUN go env && go build -o server . RUN go generate && go env && go build -o server .
FROM alpine:latest FROM alpine:latest
LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com" LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com"
......
## server项目结构
```shell
├── api
│   └── v1
├── config
├── core
├── docs
├── global
├── initialize
│   └── internal
├── middleware
├── model
│   ├── request
│   └── response
├── packfile
├── resource
│   ├── excel
│   ├── page
│   └── template
├── router
├── service
├── source
└── utils
├── timer
└── upload
```
| 文件夹 | 说明 | 描述 |
| ------------ | ----------------------- | --------------------------- |
| `api` | api层 | api层 |
| `--v1` | v1版本接口 | v1版本接口 |
| `config` | 配置包 | config.yaml对应的配置结构体 |
| `core` | 核心文件 | 核心组件(zap, viper, server)的初始化 |
| `docs` | swagger文档目录 | swagger文档目录 |
| `global` | 全局对象 | 全局对象 |
| `initialize` | 初始化 | router,redis,gorm,validator, timer的初始化 |
| `--internal` | 初始化内部函数 | gorm 的 longger 自定义,在此文件夹的函数只能由 `initialize` 层进行调用 |
| `middleware` | 中间件层 | 用于存放 `gin` 中间件代码 |
| `model` | 模型层 | 模型对应数据表 |
| `--request` | 入参结构体 | 接收前端发送到后端的数据。 |
| `--response` | 出参结构体 | 返回给前端的数据结构体 |
| `packfile` | 静态文件打包 | 静态文件打包 |
| `resource` | 静态资源文件夹 | 负责存放静态文件 |
| `--excel` | excel导入导出默认路径 | excel导入导出默认路径 |
| `--page` | 表单生成器 | 表单生成器 打包后的dist |
| `--template` | 模板 | 模板文件夹,存放的是代码生成器的模板 |
| `router` | 路由层 | 路由层 |
| `service` | service层 | 存放业务逻辑问题 |
| `source` | source层 | 存放初始化数据的函数 |
| `utils` | 工具包 | 工具函数封装 |
| `--timer` | timer | 定时器接口封装 |
| `--upload` | oss | oss接口封装 |
整理代码结构
``` lua
web
├── api/v1 -- 主要API
| ├── sys_initdb.go -- ico
| └── sys_user.go --
├── config -- 配置文件 设定操作的结构体
| ├── auto_code.go -- ico captcha.go
| ├── ... -- ico captcha.go
| └── zap.go -- core
├── core -- 主要结构代码
| ├── server_other.go -- ico captcha.go
| ├── ... -- ico captcha.go
| └── zap.go --
├── docs -- 文档系统
| ├── docs.go -- ico captcha.go
| ├── swagger.json -- json
| └── swagger.yaml -- yaml
├── global -- global
├── initialize -- initialize
├── middleware -- 中间键
├── model -- global
├── request -- 所有请求model结构体
| | ├── common.go
| | ├── ...
| | └── sys_user.go -- yaml
| ├── response -- 返回数据
| | ├── common.go
| | ├── ...
| | └── sys_user.go -- yaml
├── packfile -- 文件写入
├── resource -- 资源文件
├── router -- 路由
├── service -- service层
├── source -- 文件目录操作
├── utils
├── config.yaml --
├── Dockerfile -- docker配置
├── go.mod -- mod 配置
├── go.sum -- sum
├── latest_log -- vue-cli 配置
└── main.go -- package.json
```
\ No newline at end of file
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
// 当开启多服务器部署时,替换下面的配置,使用redis共享存储验证码
// var store = captcha.NewDefaultRedisStore()
var store = base64Captcha.DefaultMemStore var store = base64Captcha.DefaultMemStore
// @Tags Base // @Tags Base
......
...@@ -61,8 +61,8 @@ mysql: ...@@ -61,8 +61,8 @@ mysql:
password: '' password: ''
max-idle-conns: 10 max-idle-conns: 10
max-open-conns: 100 max-open-conns: 100
log-mode: false log-mode: ""
log-zap: "" log-zap: false
# local configuration # local configuration
local: local:
......
...@@ -62,8 +62,8 @@ mysql: ...@@ -62,8 +62,8 @@ mysql:
password: '' password: ''
max-idle-conns: 10 max-idle-conns: 10
max-open-conns: 100 max-open-conns: 100
log-mode: false log-mode: ""
log-zap: "" log-zap: false
# local configuration # local configuration
local: local:
...@@ -104,6 +104,7 @@ aliyun-oss: ...@@ -104,6 +104,7 @@ aliyun-oss:
access-key-secret: 'yourAccessKeySecret' access-key-secret: 'yourAccessKeySecret'
bucket-name: 'yourBucketName' bucket-name: 'yourBucketName'
bucket-url: 'yourBucketUrl' bucket-url: 'yourBucketUrl'
base-path: 'yourBasePath'
# tencent cos configuration # tencent cos configuration
tencent-cos: tencent-cos:
......
...@@ -8,8 +8,8 @@ type Mysql struct { ...@@ -8,8 +8,8 @@ type Mysql struct {
Password string `mapstructure:"password" json:"password" yaml:"password"` // 数据库密码 Password string `mapstructure:"password" json:"password" yaml:"password"` // 数据库密码
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"` // 空闲中的最大连接数 MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"` // 空闲中的最大连接数
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"` // 打开到数据库的最大连接数 MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"` // 打开到数据库的最大连接数
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"` // 是否开启Gorm全局日志 LogMode string `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"` // 是否开启Gorm全局日志
LogZap string `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"` LogZap bool `mapstructure:"log-zap" json:"logZap" yaml:"log-zap"` // 是否通过zap写入日志文件
} }
func (m *Mysql) Dsn() string { func (m *Mysql) Dsn() string {
......
...@@ -20,6 +20,7 @@ type AliyunOSS struct { ...@@ -20,6 +20,7 @@ type AliyunOSS struct {
AccessKeySecret string `mapstructure:"access-key-secret" json:"accessKeySecret" yaml:"access-key-secret"` AccessKeySecret string `mapstructure:"access-key-secret" json:"accessKeySecret" yaml:"access-key-secret"`
BucketName string `mapstructure:"bucket-name" json:"bucketName" yaml:"bucket-name"` BucketName string `mapstructure:"bucket-name" json:"bucketName" yaml:"bucket-name"`
BucketUrl string `mapstructure:"bucket-url" json:"bucketUrl" yaml:"bucket-url"` BucketUrl string `mapstructure:"bucket-url" json:"bucketUrl" yaml:"bucket-url"`
BasePath string `mapstructure:"base-path" json:"basePath" yaml:"base-path"`
} }
type TencentCOS struct { type TencentCOS struct {
Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"` Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"`
......
...@@ -29,7 +29,7 @@ func RunWindowsServer() { ...@@ -29,7 +29,7 @@ func RunWindowsServer() {
fmt.Printf(` fmt.Printf(`
欢迎使用 Gin-Vue-Admin 欢迎使用 Gin-Vue-Admin
当前版本:V2.4.2 当前版本:V2.4.3
加群方式:微信号:shouzi_1994 QQ群:622360840 加群方式:微信号:shouzi_1994 QQ群:622360840
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html 默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
默认前端文件运行地址:http://127.0.0.1:8080 默认前端文件运行地址:http://127.0.0.1:8080
......
...@@ -3,6 +3,8 @@ package global ...@@ -3,6 +3,8 @@ package global
import ( import (
"gin-vue-admin/utils/timer" "gin-vue-admin/utils/timer"
"golang.org/x/sync/singleflight"
"go.uber.org/zap" "go.uber.org/zap"
"gin-vue-admin/config" "gin-vue-admin/config"
...@@ -18,6 +20,7 @@ var ( ...@@ -18,6 +20,7 @@ var (
GVA_CONFIG config.Server GVA_CONFIG config.Server
GVA_VP *viper.Viper GVA_VP *viper.Viper
//GVA_LOG *oplogging.Logger //GVA_LOG *oplogging.Logger
GVA_LOG *zap.Logger GVA_LOG *zap.Logger
GVA_Timer timer.Timer = timer.NewTimerTask() GVA_Timer timer.Timer = timer.NewTimerTask()
GVA_Concurrency_Control = &singleflight.Group{}
) )
...@@ -51,6 +51,7 @@ require ( ...@@ -51,6 +51,7 @@ require (
github.com/unrolled/secure v1.0.7 github.com/unrolled/secure v1.0.7
go.uber.org/zap v1.10.0 go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect
google.golang.org/protobuf v1.24.0 // indirect google.golang.org/protobuf v1.24.0 // indirect
gopkg.in/ini.v1 v1.55.0 // indirect gopkg.in/ini.v1 v1.55.0 // indirect
......
...@@ -78,7 +78,7 @@ func GormMysql() *gorm.DB { ...@@ -78,7 +78,7 @@ func GormMysql() *gorm.DB {
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据版本自动配置 SkipInitializeWithVersion: false, // 根据版本自动配置
} }
if db, err := gorm.Open(mysql.New(mysqlConfig), gormConfig(m.LogMode)); err != nil { if db, err := gorm.Open(mysql.New(mysqlConfig), gormConfig()); err != nil {
//global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err)) //global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err))
//os.Exit(0) //os.Exit(0)
//return nil //return nil
...@@ -97,9 +97,9 @@ func GormMysql() *gorm.DB { ...@@ -97,9 +97,9 @@ func GormMysql() *gorm.DB {
//@param: mod bool //@param: mod bool
//@return: *gorm.Config //@return: *gorm.Config
func gormConfig(mod bool) *gorm.Config { func gormConfig() *gorm.Config {
var config = &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true} config := &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}
switch global.GVA_CONFIG.Mysql.LogZap { switch global.GVA_CONFIG.Mysql.LogMode {
case "silent", "Silent": case "silent", "Silent":
config.Logger = internal.Default.LogMode(logger.Silent) config.Logger = internal.Default.LogMode(logger.Silent)
case "error", "Error": case "error", "Error":
...@@ -108,14 +108,8 @@ func gormConfig(mod bool) *gorm.Config { ...@@ -108,14 +108,8 @@ func gormConfig(mod bool) *gorm.Config {
config.Logger = internal.Default.LogMode(logger.Warn) config.Logger = internal.Default.LogMode(logger.Warn)
case "info", "Info": case "info", "Info":
config.Logger = internal.Default.LogMode(logger.Info) config.Logger = internal.Default.LogMode(logger.Info)
case "zap", "Zap":
config.Logger = internal.Default.LogMode(logger.Info)
default: default:
if mod { config.Logger = internal.Default.LogMode(logger.Info)
config.Logger = internal.Default.LogMode(logger.Info)
break
}
config.Logger = internal.Default.LogMode(logger.Silent)
} }
return config return config
} }
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"gin-vue-admin/global" "gin-vue-admin/global"
"go.uber.org/zap"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"gorm.io/gorm/utils" "gorm.io/gorm/utils"
"io/ioutil" "io/ioutil"
...@@ -13,11 +12,6 @@ import ( ...@@ -13,11 +12,6 @@ import (
"time" "time"
) )
// writer log writer interface
type writer interface {
Printf(string, ...interface{})
}
type config struct { type config struct {
SlowThreshold time.Duration SlowThreshold time.Duration
Colorful bool Colorful bool
...@@ -34,27 +28,27 @@ var ( ...@@ -34,27 +28,27 @@ var (
Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()} Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()}
) )
func New(writer writer, config config) logger.Interface { func New(writer logger.Writer, config config) logger.Interface {
var ( var (
infoStr = "%s\n[info] " infoStr = "%s\n[info] "
warnStr = "%s\n[warn] " warnStr = "%s\n[warn] "
errStr = "%s\n[error] " errStr = "%s\n[error] "
traceStr = "%s\n[%.3fms] [rows:%v] %s" traceStr = "%s\n[%.3fms] [rows:%v] %s\n"
traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s" traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s\n"
traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s" traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s\n"
) )
if config.Colorful { if config.Colorful {
infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset
warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset
errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset
traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s" traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s\n"
traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s\n" + logger.Reset
traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s" traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s\n"
} }
return &customLogger{ return &_logger{
writer: writer, Writer: writer,
config: config, config: config,
infoStr: infoStr, infoStr: infoStr,
warnStr: warnStr, warnStr: warnStr,
...@@ -65,43 +59,43 @@ func New(writer writer, config config) logger.Interface { ...@@ -65,43 +59,43 @@ func New(writer writer, config config) logger.Interface {
} }
} }
type customLogger struct { type _logger struct {
writer
config config
logger.Writer
infoStr, warnStr, errStr string infoStr, warnStr, errStr string
traceStr, traceErrStr, traceWarnStr string traceStr, traceErrStr, traceWarnStr string
} }
// LogMode log mode // LogMode log mode
func (c *customLogger) LogMode(level logger.LogLevel) logger.Interface { func (c *_logger) LogMode(level logger.LogLevel) logger.Interface {
newLogger := *c newLogger := *c
newLogger.LogLevel = level newLogger.LogLevel = level
return &newLogger return &newLogger
} }
// Info print info // Info print info
func (c *customLogger) Info(ctx context.Context, message string, data ...interface{}) { func (c *_logger) Info(ctx context.Context, message string, data ...interface{}) {
if c.LogLevel >= logger.Info { if c.LogLevel >= logger.Info {
c.Printf(c.infoStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...) c.Printf(c.infoStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
} }
} }
// Warn print warn messages // Warn print warn messages
func (c *customLogger) Warn(ctx context.Context, message string, data ...interface{}) { func (c *_logger) Warn(ctx context.Context, message string, data ...interface{}) {
if c.LogLevel >= logger.Warn { if c.LogLevel >= logger.Warn {
c.Printf(c.warnStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...) c.Printf(c.warnStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
} }
} }
// Error print error messages // Error print error messages
func (c *customLogger) Error(ctx context.Context, message string, data ...interface{}) { func (c *_logger) Error(ctx context.Context, message string, data ...interface{}) {
if c.LogLevel >= logger.Error { if c.LogLevel >= logger.Error {
c.Printf(c.errStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...) c.Printf(c.errStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
} }
} }
// Trace print sql message // Trace print sql message
func (c *customLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { func (c *_logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
if c.LogLevel > 0 { if c.LogLevel > 0 {
elapsed := time.Since(begin) elapsed := time.Since(begin)
switch { switch {
...@@ -131,35 +125,11 @@ func (c *customLogger) Trace(ctx context.Context, begin time.Time, fc func() (st ...@@ -131,35 +125,11 @@ func (c *customLogger) Trace(ctx context.Context, begin time.Time, fc func() (st
} }
} }
func (c *customLogger) Printf(message string, data ...interface{}) { func (c *_logger) Printf(message string, data ...interface{}) {
if global.GVA_CONFIG.Mysql.LogZap != "" { if global.GVA_CONFIG.Mysql.LogZap {
switch len(data) { global.GVA_LOG.Info(fmt.Sprintf(message, data...))
case 0: } else {
global.GVA_LOG.Info(message) c.Writer.Printf(message, data...)
case 1:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]))
case 2:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]))
case 3:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]))
case 4:
global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]), zap.Any("sql", data[3]))
}
return
}
switch len(data) {
case 0:
c.writer.Printf(message, "")
case 1:
c.writer.Printf(message, data[0])
case 2:
c.writer.Printf(message, data[0], data[1])
case 3:
c.writer.Printf(message, data[0], data[1], data[2])
case 4:
c.writer.Printf(message, data[0], data[1], data[2], data[3])
case 5:
c.writer.Printf(message, data[0], data[1], data[2], data[3], data[4])
} }
} }
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
func Timer() { func Timer() {
if global.GVA_CONFIG.Timer.Start { if global.GVA_CONFIG.Timer.Start {
for _, detail := range global.GVA_CONFIG.Timer.Detail { for _, detail := range global.GVA_CONFIG.Timer.Detail {
fmt.Println(detail)
go func(detail config.Detail) { go func(detail config.Detail) {
global.GVA_Timer.AddTaskByFunc("ClearDB", global.GVA_CONFIG.Timer.Spec, func() { global.GVA_Timer.AddTaskByFunc("ClearDB", global.GVA_CONFIG.Timer.Spec, func() {
err := utils.ClearTable(global.GVA_DB, detail.TableName, detail.CompareField, detail.Interval) err := utils.ClearTable(global.GVA_DB, detail.TableName, detail.CompareField, detail.Interval)
......
...@@ -7,11 +7,12 @@ import ( ...@@ -7,11 +7,12 @@ import (
"gin-vue-admin/model/request" "gin-vue-admin/model/request"
"gin-vue-admin/model/response" "gin-vue-admin/model/response"
"gin-vue-admin/service" "gin-vue-admin/service"
"strconv"
"time"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.uber.org/zap" "go.uber.org/zap"
"strconv"
"time"
) )
func JWTAuth() gin.HandlerFunc { func JWTAuth() gin.HandlerFunc {
...@@ -48,7 +49,7 @@ func JWTAuth() gin.HandlerFunc { ...@@ -48,7 +49,7 @@ func JWTAuth() gin.HandlerFunc {
} }
if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime { if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime {
claims.ExpiresAt = time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime claims.ExpiresAt = time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime
newToken, _ := j.CreateToken(*claims) newToken, _ := j.CreateTokenByOldToken(token, *claims)
newClaims, _ := j.ParseToken(newToken) newClaims, _ := j.ParseToken(newToken)
c.Header("new-token", newToken) c.Header("new-token", newToken)
c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10)) c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10))
...@@ -91,6 +92,14 @@ func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) { ...@@ -91,6 +92,14 @@ func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) {
return token.SignedString(j.SigningKey) return token.SignedString(j.SigningKey)
} }
// CreateTokenByOldToken 旧token 换新token 使用归并回源避免并发问题
func (j *JWT) CreateTokenByOldToken(oldToken string, claims request.CustomClaims) (string, error) {
v, err, _ := global.GVA_Concurrency_Control.Do("JWT:"+oldToken, func() (interface{}, error) {
return j.CreateToken(claims)
})
return v.(string), err
}
// 解析 token // 解析 token
func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) { func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) { token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
......
...@@ -9,5 +9,5 @@ type SysApi struct { ...@@ -9,5 +9,5 @@ type SysApi struct {
Path string `json:"path" gorm:"comment:api路径"` // api路径 Path string `json:"path" gorm:"comment:api路径"` // api路径
Description string `json:"description" gorm:"comment:api中文描述"` // api中文描述 Description string `json:"description" gorm:"comment:api中文描述"` // api中文描述
ApiGroup string `json:"apiGroup" gorm:"comment:api组"` // api组 ApiGroup string `json:"apiGroup" gorm:"comment:api组"` // api组
Method string `json:"method" gorm:"default:POST" gorm:"comment:方法"` // 方法:创建POST(默认)|查看GET|更新PUT|删除DELETE Method string `json:"method" gorm:"default:POST;comment:方法"` // 方法:创建POST(默认)|查看GET|更新PUT|删除DELETE
} }
...@@ -14,4 +14,7 @@ type SysUser struct { ...@@ -14,4 +14,7 @@ type SysUser struct {
HeaderImg string `json:"headerImg" gorm:"default:http://qmplusimg.henrongyi.top/head.png;comment:用户头像"` // 用户头像 HeaderImg string `json:"headerImg" gorm:"default:http://qmplusimg.henrongyi.top/head.png;comment:用户头像"` // 用户头像
Authority SysAuthority `json:"authority" gorm:"foreignKey:AuthorityId;references:AuthorityId;comment:用户角色"` Authority SysAuthority `json:"authority" gorm:"foreignKey:AuthorityId;references:AuthorityId;comment:用户角色"`
AuthorityId string `json:"authorityId" gorm:"default:888;comment:用户角色ID"` // 用户角色ID AuthorityId string `json:"authorityId" gorm:"default:888;comment:用户角色ID"` // 用户角色ID
SideMode string `json:"sideMode" gorm:"default:dark;comment:用户角色ID"` // 用户侧边主题
ActiveColor string `json:"activeColor" gorm:"default:#1890ff;comment:用户角色ID"` // 活跃颜色
BaseColor string `json:"baseColor" gorm:"default:#fff;comment:用户角色ID"` // 基础颜色
} }
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
// Create{{.StructName}} 创建{{.StructName}}
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 创建{{.StructName}} // @Summary 创建{{.StructName}}
// @Security ApiKeyAuth // @Security ApiKeyAuth
...@@ -29,6 +30,7 @@ func Create{{.StructName}}(c *gin.Context) { ...@@ -29,6 +30,7 @@ func Create{{.StructName}}(c *gin.Context) {
} }
} }
// Delete{{.StructName}} 删除{{.StructName}}
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 删除{{.StructName}} // @Summary 删除{{.StructName}}
// @Security ApiKeyAuth // @Security ApiKeyAuth
...@@ -48,6 +50,7 @@ func Delete{{.StructName}}(c *gin.Context) { ...@@ -48,6 +50,7 @@ func Delete{{.StructName}}(c *gin.Context) {
} }
} }
// Delete{{.StructName}}ByIds 批量删除{{.StructName}}
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 批量删除{{.StructName}} // @Summary 批量删除{{.StructName}}
// @Security ApiKeyAuth // @Security ApiKeyAuth
...@@ -67,6 +70,7 @@ func Delete{{.StructName}}ByIds(c *gin.Context) { ...@@ -67,6 +70,7 @@ func Delete{{.StructName}}ByIds(c *gin.Context) {
} }
} }
// Update{{.StructName}} 更新{{.StructName}}
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 更新{{.StructName}} // @Summary 更新{{.StructName}}
// @Security ApiKeyAuth // @Security ApiKeyAuth
...@@ -86,6 +90,7 @@ func Update{{.StructName}}(c *gin.Context) { ...@@ -86,6 +90,7 @@ func Update{{.StructName}}(c *gin.Context) {
} }
} }
// Find{{.StructName}} 用id查询{{.StructName}}
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 用id查询{{.StructName}} // @Summary 用id查询{{.StructName}}
// @Security ApiKeyAuth // @Security ApiKeyAuth
...@@ -105,6 +110,7 @@ func Find{{.StructName}}(c *gin.Context) { ...@@ -105,6 +110,7 @@ func Find{{.StructName}}(c *gin.Context) {
} }
} }
// Get{{.StructName}}List 分页获取{{.StructName}}列表
// @Tags {{.StructName}} // @Tags {{.StructName}}
// @Summary 分页获取{{.StructName}}列表 // @Summary 分页获取{{.StructName}}列表
// @Security ApiKeyAuth // @Security ApiKeyAuth
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"gin-vue-admin/global" "gin-vue-admin/global"
) )
// {{.StructName}} 结构体
// 如果含有time.Time 请自行import time包 // 如果含有time.Time 请自行import time包
type {{.StructName}} struct { type {{.StructName}} struct {
global.GVA_MODEL {{- range .Fields}} global.GVA_MODEL {{- range .Fields}}
...@@ -16,6 +17,7 @@ type {{.StructName}} struct { ...@@ -16,6 +17,7 @@ type {{.StructName}} struct {
} }
{{ if .TableName }} {{ if .TableName }}
// TableName {{.StructName}} 表名
func ({{.StructName}}) TableName() string { func ({{.StructName}}) TableName() string {
return "{{.TableName}}" return "{{.TableName}}"
} }
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// Init{{.StructName}}Router 初始化 {{.StructName}} 路由信息
func Init{{.StructName}}Router(Router *gin.RouterGroup) { func Init{{.StructName}}Router(Router *gin.RouterGroup) {
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.OperationRecord()) {{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.OperationRecord())
{ {
......
...@@ -6,67 +6,43 @@ import ( ...@@ -6,67 +6,43 @@ import (
"gin-vue-admin/model/request" "gin-vue-admin/model/request"
) )
//@author: [piexlmax](https://github.com/piexlmax) // Create{{.StructName}} 创建{{.StructName}}记录
//@function: Create{{.StructName}} // Author [piexlmax](https://github.com/piexlmax)
//@description: 创建{{.StructName}}记录
//@param: {{.Abbreviation}} model.{{.StructName}}
//@return: err error
func Create{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) { func Create{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
err = global.GVA_DB.Create(&{{.Abbreviation}}).Error err = global.GVA_DB.Create(&{{.Abbreviation}}).Error
return err return err
} }
//@author: [piexlmax](https://github.com/piexlmax) // Delete{{.StructName}} 删除{{.StructName}}记录
//@function: Delete{{.StructName}} // Author [piexlmax](https://github.com/piexlmax)
//@description: 删除{{.StructName}}记录
//@param: {{.Abbreviation}} model.{{.StructName}}
//@return: err error
func Delete{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) { func Delete{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
err = global.GVA_DB.Delete(&{{.Abbreviation}}).Error err = global.GVA_DB.Delete(&{{.Abbreviation}}).Error
return err return err
} }
//@author: [piexlmax](https://github.com/piexlmax) // Delete{{.StructName}}ByIds 批量删除{{.StructName}}记录
//@function: Delete{{.StructName}}ByIds // Author [piexlmax](https://github.com/piexlmax)
//@description: 批量删除{{.StructName}}记录
//@param: ids request.IdsReq
//@return: err error
func Delete{{.StructName}}ByIds(ids request.IdsReq) (err error) { func Delete{{.StructName}}ByIds(ids request.IdsReq) (err error) {
err = global.GVA_DB.Delete(&[]model.{{.StructName}}{},"id in ?",ids.Ids).Error err = global.GVA_DB.Delete(&[]model.{{.StructName}}{},"id in ?",ids.Ids).Error
return err return err
} }
//@author: [piexlmax](https://github.com/piexlmax) // Update{{.StructName}} 更新{{.StructName}}记录
//@function: Update{{.StructName}} // Author [piexlmax](https://github.com/piexlmax)
//@description: 更新{{.StructName}}记录
//@param: {{.Abbreviation}} *model.{{.StructName}}
//@return: err error
func Update{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) { func Update{{.StructName}}({{.Abbreviation}} model.{{.StructName}}) (err error) {
err = global.GVA_DB.Save(&{{.Abbreviation}}).Error err = global.GVA_DB.Save(&{{.Abbreviation}}).Error
return err return err
} }
//@author: [piexlmax](https://github.com/piexlmax) // Get{{.StructName}} 根据id获取{{.StructName}}记录
//@function: Get{{.StructName}} // Author [piexlmax](https://github.com/piexlmax)
//@description: 根据id获取{{.StructName}}记录
//@param: id uint
//@return: err error, {{.Abbreviation}} model.{{.StructName}}
func Get{{.StructName}}(id uint) (err error, {{.Abbreviation}} model.{{.StructName}}) { func Get{{.StructName}}(id uint) (err error, {{.Abbreviation}} model.{{.StructName}}) {
err = global.GVA_DB.Where("id = ?", id).First(&{{.Abbreviation}}).Error err = global.GVA_DB.Where("id = ?", id).First(&{{.Abbreviation}}).Error
return return
} }
//@author: [piexlmax](https://github.com/piexlmax) // Get{{.StructName}}InfoList 分页获取{{.StructName}}记录
//@function: Get{{.StructName}}InfoList // Author [piexlmax](https://github.com/piexlmax)
//@description: 分页获取{{.StructName}}记录
//@param: info request.{{.StructName}}Search
//@return: err error, list interface{}, total int64
func Get{{.StructName}}InfoList(info request.{{.StructName}}Search) (err error, list interface{}, total int64) { func Get{{.StructName}}InfoList(info request.{{.StructName}}Search) (err error, list interface{}, total int64) {
limit := info.PageSize limit := info.PageSize
offset := info.PageSize * (info.Page - 1) offset := info.PageSize * (info.Page - 1)
...@@ -102,4 +78,4 @@ func Get{{.StructName}}InfoList(info request.{{.StructName}}Search) (err error, ...@@ -102,4 +78,4 @@ func Get{{.StructName}}InfoList(info request.{{.StructName}}Search) (err error,
err = db.Count(&total).Error err = db.Count(&total).Error
err = db.Limit(limit).Offset(offset).Find(&{{.Abbreviation}}s).Error err = db.Limit(limit).Offset(offset).Find(&{{.Abbreviation}}s).Error
return err, {{.Abbreviation}}s, total return err, {{.Abbreviation}}s, total
} }
\ No newline at end of file
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
</el-form-item> </el-form-item>
{{ end -}} {{ end -}}
<el-form-item> <el-form-item>
<el-button type="primary" @click="save">保存</el-button> <el-button size="mini" type="primary" @click="save">保存</el-button>
<el-button type="primary" @click="back">返回</el-button> <el-button size="mini" type="primary" @click="back">返回</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
......
...@@ -22,19 +22,15 @@ ...@@ -22,19 +22,15 @@
<el-input placeholder="搜索条件" v-model="searchInfo.{{.FieldJson}}" /> <el-input placeholder="搜索条件" v-model="searchInfo.{{.FieldJson}}" />
</el-form-item> {{ end }} {{ end }} {{ end }} </el-form-item> {{ end }} {{ end }} {{ end }}
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
</el-form-item> <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>
<el-form-item>
<el-button type="primary" @click="openDialog">新增{{.Description}}</el-button>
</el-form-item>
<el-form-item>
<el-popover v-model="deleteVisible" placement="top" width="160"> <el-popover v-model="deleteVisible" placement="top" width="160">
<p>确定要删除吗?</p> <p>确定要删除吗?</p>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button> <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="onDelete">确定</el-button> <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
</div> </div>
<el-button slot="reference" icon="el-icon-delete" size="mini" type="danger">批量删除</el-button> <el-button slot="reference" icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
</el-popover> </el-popover>
</el-form-item> </el-form-item>
</el-form> </el-form>
......
...@@ -40,6 +40,7 @@ func UpdateBaseMenu(menu model.SysBaseMenu) (err error) { ...@@ -40,6 +40,7 @@ func UpdateBaseMenu(menu model.SysBaseMenu) (err error) {
var oldMenu model.SysBaseMenu var oldMenu model.SysBaseMenu
upDateMap := make(map[string]interface{}) upDateMap := make(map[string]interface{})
upDateMap["keep_alive"] = menu.KeepAlive upDateMap["keep_alive"] = menu.KeepAlive
upDateMap["close_tab"] = menu.CloseTab
upDateMap["default_menu"] = menu.DefaultMenu upDateMap["default_menu"] = menu.DefaultMenu
upDateMap["parent_id"] = menu.ParentId upDateMap["parent_id"] = menu.ParentId
upDateMap["path"] = menu.Path upDateMap["path"] = menu.Path
......
...@@ -81,7 +81,7 @@ func InitDB(conf request.InitDB) error { ...@@ -81,7 +81,7 @@ func InitDB(conf request.InitDB) error {
conf.Port = "3306" conf.Port = "3306"
} }
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/", conf.UserName, conf.Password, conf.Host, conf.Port) dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/", conf.UserName, conf.Password, conf.Host, conf.Port)
createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;", conf.DBName) createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;", conf.DBName)
if err := createTable(dsn, "mysql", createSql); err != nil { if err := createTable(dsn, "mysql", createSql); err != nil {
return err return err
} }
......
...@@ -17,7 +17,7 @@ func (a *authorityMenu) Init() error { ...@@ -17,7 +17,7 @@ func (a *authorityMenu) Init() error {
color.Danger.Println("\n[Mysql] --> authority_menu 视图已存在!") color.Danger.Println("\n[Mysql] --> authority_menu 视图已存在!")
return nil return nil
} }
if err := global.GVA_DB.Exec("CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `authority_menu` AS select `sys_base_menus`.`id` AS `id`,`sys_base_menus`.`created_at` AS `created_at`, `sys_base_menus`.`updated_at` AS `updated_at`, `sys_base_menus`.`deleted_at` AS `deleted_at`, `sys_base_menus`.`menu_level` AS `menu_level`,`sys_base_menus`.`parent_id` AS `parent_id`,`sys_base_menus`.`path` AS `path`,`sys_base_menus`.`name` AS `name`,`sys_base_menus`.`hidden` AS `hidden`,`sys_base_menus`.`component` AS `component`, `sys_base_menus`.`title` AS `title`,`sys_base_menus`.`icon` AS `icon`,`sys_base_menus`.`sort` AS `sort`,`sys_authority_menus`.`sys_authority_authority_id` AS `authority_id`,`sys_authority_menus`.`sys_base_menu_id` AS `menu_id`,`sys_base_menus`.`keep_alive` AS `keep_alive`,`sys_base_menus`.`default_menu` AS `default_menu` from (`sys_authority_menus` join `sys_base_menus` on ((`sys_authority_menus`.`sys_base_menu_id` = `sys_base_menus`.`id`)))").Error; err != nil { if err := global.GVA_DB.Exec("CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `authority_menu` AS select `sys_base_menus`.`id` AS `id`,`sys_base_menus`.`created_at` AS `created_at`, `sys_base_menus`.`updated_at` AS `updated_at`, `sys_base_menus`.`deleted_at` AS `deleted_at`, `sys_base_menus`.`menu_level` AS `menu_level`,`sys_base_menus`.`parent_id` AS `parent_id`,`sys_base_menus`.`path` AS `path`,`sys_base_menus`.`name` AS `name`,`sys_base_menus`.`hidden` AS `hidden`,`sys_base_menus`.`component` AS `component`, `sys_base_menus`.`title` AS `title`,`sys_base_menus`.`icon` AS `icon`,`sys_base_menus`.`sort` AS `sort`,`sys_authority_menus`.`sys_authority_authority_id` AS `authority_id`,`sys_authority_menus`.`sys_base_menu_id` AS `menu_id`,`sys_base_menus`.`keep_alive` AS `keep_alive`,`sys_base_menus`.`close_tab` AS `close_tab`,`sys_base_menus`.`default_menu` AS `default_menu` from (`sys_authority_menus` join `sys_base_menus` on ((`sys_authority_menus`.`sys_base_menu_id` = `sys_base_menus`.`id`)))").Error; err != nil {
return err return err
} }
color.Info.Println("\n[Mysql] --> authority_menu 视图创建成功!") color.Info.Println("\n[Mysql] --> authority_menu 视图创建成功!")
......
package captcha
import (
"gin-vue-admin/global"
"time"
"github.com/mojocn/base64Captcha"
"go.uber.org/zap"
)
func NewDefaultRedisStore() base64Captcha.Store {
return &RedisStore{
Expiration: time.Second * 180,
PreKey: "CAPTCHA_",
}
}
type RedisStore struct {
Expiration time.Duration
PreKey string
}
func (rs *RedisStore) Set(id string, value string) {
err := global.GVA_REDIS.Set(rs.PreKey+id, value, rs.Expiration).Err()
if err != nil {
global.GVA_LOG.Error("RedisStoreSetError!", zap.Error(err))
}
}
func (rs *RedisStore) Get(key string, clear bool) string {
val, err := global.GVA_REDIS.Get(key).Result()
if err != nil {
global.GVA_LOG.Error("RedisStoreGetError!", zap.Error(err))
return ""
}
if clear {
err := global.GVA_REDIS.Del(key).Err()
if err != nil {
global.GVA_LOG.Error("RedisStoreClearError!", zap.Error(err))
return ""
}
}
return val
}
func (rs *RedisStore) Verify(id, answer string, clear bool) bool {
key := rs.PreKey + id
v := rs.Get(key, clear)
return v == answer
}
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-oss-go-sdk/oss"
"go.uber.org/zap" "go.uber.org/zap"
"mime/multipart" "mime/multipart"
"path/filepath"
"time" "time"
) )
...@@ -27,7 +26,8 @@ func (*AliyunOSS) UploadFile(file *multipart.FileHeader) (string, string, error) ...@@ -27,7 +26,8 @@ func (*AliyunOSS) UploadFile(file *multipart.FileHeader) (string, string, error)
} }
defer f.Close() // 创建文件 defer 关闭 defer f.Close() // 创建文件 defer 关闭
// 上传阿里云路径 文件名格式 自己可以改 建议保证唯一性 // 上传阿里云路径 文件名格式 自己可以改 建议保证唯一性
yunFileTmpPath := filepath.Join("uploads", time.Now().Format("2006-01-02")) + "/" + file.Filename //yunFileTmpPath := filepath.Join("uploads", time.Now().Format("2006-01-02")) + "/" + file.Filename
yunFileTmpPath := global.GVA_CONFIG.AliyunOSS.BasePath + "/" + "uploads" + "/" + time.Now().Format("2006-01-02") + "/" + file.Filename
// 上传文件流。 // 上传文件流。
err = bucket.PutObject(yunFileTmpPath, f) err = bucket.PutObject(yunFileTmpPath, f)
......
...@@ -38,6 +38,10 @@ web ...@@ -38,6 +38,10 @@ web
├── api -- 所有请求 ├── api -- 所有请求
├── assets -- 主题 字体等静态资源 ├── assets -- 主题 字体等静态资源
| ├── components -- components组件 | ├── components -- components组件
| ├── core -- gva抽离的一些前端资源
| | ├── config.js -- 配置文件
| | └── element_lazy.js -- elementt按需引入文件
| | └── gin-vue-admin.js -- gva前端控制库
| ├── directive -- 公用方法 | ├── directive -- 公用方法
| ├── mixins -- 公用方法 | ├── mixins -- 公用方法
| ├── router -- 路由权限 | ├── router -- 路由权限
...@@ -57,15 +61,20 @@ web ...@@ -57,15 +61,20 @@ web
| | ├── example --上传案例 | | ├── example --上传案例
| | ├── iconList -- icon列表 | | ├── iconList -- icon列表
| | ├── init -- 初始化数据 | | ├── init -- 初始化数据
| | | ├── index -- 新版本
| | | ├── init -- 旧版本
| | ├── layout -- layout约束页面 | | ├── layout -- layout约束页面
| | | ├── aside -- | | | ├── aside --
| | | ├── bottomInfo -- bottomInfo | | | ├── bottomInfo -- bottomInfo
| | | ├── screenfull -- 全屏设置 | | | ├── screenfull -- 全屏设置
| | | ├── setting -- 系统设置
| | | └── index.vue -- base 约束 | | | └── index.vue -- base 约束
| | ├── login --结算单管理 | | ├── login --登录
| | ├── person --结算单管理 | | ├── person --个人中心
| | ├── superAdmin -- 超级管理员操作 | | ├── superAdmin -- 超级管理员操作
| | └── home.vue -- page 入口页面 | | ├── system -- 系统检测页面
| | ├── systemTools -- 系统配置相关页面
| | └── routerHolder.vue -- page 入口页面
├── App.vue -- 入口页面 ├── App.vue -- 入口页面
├── main.js -- 入口文件 加载组件 初始化等 ├── main.js -- 入口文件 加载组件 初始化等
└── permission.js -- 跳转 └── permission.js -- 跳转
......
此差异已折叠。
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
<script src="./js/project.js"></script>
</body> </body>
</html> </html>
// 未经过授权商用请勿删除此文件,将会导致意想不到的bug
(function(){})(
document.write(
unescape(`%3Cspan style='display:none' id='cnzz_stat_icon_1279266757'%3E%3C/span%3E%3Cscript src='https://s4.cnzz.com/z_stat.php%3Fid%3D1279266757' type='text/javascript'%3E%3C/script%3E`)
)
)
\ No newline at end of file
...@@ -19,5 +19,9 @@ export default { ...@@ -19,5 +19,9 @@ export default {
background: #eee; background: #eee;
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
font-weight: 400 !important;
}
.el-button{
font-weight: 400 !important;
} }
</style> </style>
<!--
<div>
带压缩的上传
<upload-image v-model="imageUrl" :fileSize="512" />
已上传文件 {{ imageUrl }}
</div>
-->
<template> <template>
<div> <div>
...@@ -17,7 +10,7 @@ ...@@ -17,7 +10,7 @@
:before-upload="beforeImageUpload" :before-upload="beforeImageUpload"
:multiple="false" :multiple="false"
> >
<img v-if="imageUrl" :src="path + imageUrl" class="image"> <img v-if="imageUrl" :src="showImageUrl" class="image">
<i v-else class="el-icon-plus image-uploader-icon" /> <i v-else class="el-icon-plus image-uploader-icon" />
</el-upload> </el-upload>
</div> </div>
...@@ -53,7 +46,10 @@ export default { ...@@ -53,7 +46,10 @@ export default {
} }
}, },
computed: { computed: {
...mapGetters('user', ['userInfo', 'token']) ...mapGetters('user', ['userInfo', 'token']),
showImageUrl() {
return (this.imageUrl && this.imageUrl.slice(0, 4) !== 'http') ? path + this.imageUrl : this.imageUrl
}
}, },
methods: { methods: {
beforeImageUpload(file) { beforeImageUpload(file) {
...@@ -70,6 +66,7 @@ export default { ...@@ -70,6 +66,7 @@ export default {
const { data } = res const { data } = res
if (data.file) { if (data.file) {
this.$emit('change', data.file.url) this.$emit('change', data.file.url)
this.$emit('on-success')
} }
} }
} }
......
...@@ -58,7 +58,8 @@ import { ...@@ -58,7 +58,8 @@ import {
Upload, Upload,
Progress, Progress,
MessageBox, MessageBox,
Image Image,
ColorPicker
} from 'element-ui' } from 'element-ui'
Vue.use(Button) Vue.use(Button)
...@@ -110,7 +111,7 @@ Vue.use(Progress) ...@@ -110,7 +111,7 @@ Vue.use(Progress)
Vue.use(Scrollbar) Vue.use(Scrollbar)
Vue.use(Loading.directive) Vue.use(Loading.directive)
Vue.use(Image) Vue.use(Image)
Vue.use(ColorPicker)
Vue.prototype.$loading = Loading.service Vue.prototype.$loading = Loading.service
Vue.prototype.$message = Message Vue.prototype.$message = Message
Vue.prototype.$confirm = MessageBox.confirm Vue.prototype.$confirm = MessageBox.confirm
......
...@@ -22,7 +22,7 @@ Vue.use(uploader) ...@@ -22,7 +22,7 @@ Vue.use(uploader)
console.log(` console.log(`
欢迎使用 Gin-Vue-Admin 欢迎使用 Gin-Vue-Admin
当前版本:V2.4.2 当前版本:V2.4.3
加群方式:微信:shouzi_1994 QQ群:622360840 加群方式:微信:shouzi_1994 QQ群:622360840
默认自动化文档地址:http://127.0.0.1:${process.env.VUE_APP_SERVER_PORT}/swagger/index.html 默认自动化文档地址:http://127.0.0.1:${process.env.VUE_APP_SERVER_PORT}/swagger/index.html
默认前端文件运行地址:http://127.0.0.1:${process.env.VUE_APP_CLI_PORT} 默认前端文件运行地址:http://127.0.0.1:${process.env.VUE_APP_CLI_PORT}
......
import { login } from '@/api/user' import { login } from '@/api/user'
import { jsonInBlacklist } from '@/api/jwt' import { jsonInBlacklist } from '@/api/jwt'
import router from '@/router/index' import router from '@/router/index'
import { setUserInfo } from '@/api/user'
import { Message } from 'element-ui'
export const user = { export const user = {
namespaced: true, namespaced: true,
state: { state: {
...@@ -8,7 +11,10 @@ export const user = { ...@@ -8,7 +11,10 @@ export const user = {
uuid: '', uuid: '',
nickName: '', nickName: '',
headerImg: '', headerImg: '',
authority: '' authority: '',
sideMode: 'dark',
activeColor: '#1890ff',
baseColor: '#fff'
}, },
token: '' token: ''
}, },
...@@ -38,6 +44,15 @@ export const user = { ...@@ -38,6 +44,15 @@ export const user = {
state.userInfo = { ...state.userInfo, state.userInfo = { ...state.userInfo,
...userInfo ...userInfo
} }
},
ChangeActiveColor: async(state, val) => {
state.userInfo.activeColor = val
},
ChangeSideMode: async(state, val) => {
state.userInfo.sideMode = val
},
ChangeBaseColor: (state, val) => {
state.userInfo.baseColor = val
} }
}, },
actions: { actions: {
...@@ -64,6 +79,36 @@ export const user = { ...@@ -64,6 +79,36 @@ export const user = {
if (res.code === 0) { if (res.code === 0) {
commit('LoginOut') commit('LoginOut')
} }
},
async changeActiveColor({ commit, state }, data) {
const res = await setUserInfo({ activeColor: data, ID: state.userInfo.ID })
if (res.code === 0) {
commit('ChangeActiveColor', data)
Message({
type: 'success',
message: '设置成功'
})
}
},
async changeSideMode({ commit, state }, data) {
const res = await setUserInfo({ sideMode: data, ID: state.userInfo.ID })
if (res.code === 0) {
commit('ChangeSideMode', data)
Message({
type: 'success',
message: '设置成功'
})
}
},
async changeBaseColor({ commit, state }, data) {
const res = await setUserInfo({ baseColor: data, ID: state.userInfo.ID })
if (res.code === 0) {
commit('ChangeBaseColor', data)
Message({
type: 'success',
message: '设置成功'
})
}
} }
}, },
getters: { getters: {
...@@ -72,6 +117,33 @@ export const user = { ...@@ -72,6 +117,33 @@ export const user = {
}, },
token(state) { token(state) {
return state.token return state.token
},
mode(state) {
return state.userInfo.sideMode
},
sideMode(state) {
if (state.userInfo.sideMode === 'dark') {
return '#191a23'
} else if (state.userInfo.sideMode === 'light') {
return '#fff'
} else {
return state.userInfo.sideMode
}
},
baseColor(state) {
if (state.userInfo.sideMode === 'dark') {
return '#fff'
} else if (state.userInfo.sideMode === 'light') {
return '#191a23'
} else {
return state.userInfo.baseColor
}
},
activeColor(state) {
if (state.userInfo.sideMode === 'dark' || state.userInfo.sideMode === 'light') {
return '#1890ff'
}
return state.userInfo.activeColor
} }
} }
......
...@@ -8,14 +8,14 @@ $white-bg:#fff; ...@@ -8,14 +8,14 @@ $white-bg:#fff;
$el-icon-small:30px; $el-icon-small:30px;
$el-icon-mini:24px; $el-icon-mini:24px;
// aside // aside
$width-aside:220px; $width-aside:220px;
$width-hideside-aside:54px; $width-hideside-aside:54px;
$width-mobile-aside:210px; $width-mobile-aside:210px;
$color-aside:rgba(255, 255, 255,.9); $color-aside:rgba(255, 255, 255,.9);
$icon-arrow-size-aside:12px; $icon-arrow-size-aside:12px;
$width-submenu-aside:55px; $width-submenu-aside:55px;
$bg-aside:#191a23; $bg-aside:#191a23;
$height-aside-tilte:64px; $height-aside-tilte:60px;
$height-aside-img:30px; $height-aside-img:30px;
$width-aside-img:30px; $width-aside-img:30px;
// header // header
......
/* 改变主题色变量 */
$--color-primary: #1890ff;
#app{
.el-button{
font-weight: 400;
border-radius: 4px;
}
}
///* 改变 icon 字体路径变量,必需 */
//$--font-path: '~element-ui/lib/theme-chalk/fonts';
//
//
//
//@import "~element-ui/packages/theme-chalk/src/index";
//
:export {
colorPrimary: $--color-primary
}
...@@ -563,13 +563,13 @@ li { ...@@ -563,13 +563,13 @@ li {
.el-menu { .el-menu {
border-right: none; border-right: none;
} }
.tilte { .tilte {
min-height: $height-aside-tilte; min-height: $height-aside-tilte;
line-height: $height-aside-tilte; line-height: $height-aside-tilte;
background: $bg-aside; background: $bg-aside;
text-align: center; text-align: center;
transition: all 0.3s;
.logoimg { .logoimg {
width: $width-aside-img; width: $width-aside-img;
height: $height-aside-img; height: $height-aside-img;
...@@ -593,6 +593,7 @@ li { ...@@ -593,6 +593,7 @@ li {
.aside { .aside {
.el-menu-vertical { .el-menu-vertical {
transition: all 0.3s;
background-color: $bg-aside; background-color: $bg-aside;
} }
.el-submenu { .el-submenu {
...@@ -603,7 +604,7 @@ li { ...@@ -603,7 +604,7 @@ li {
height: 44px; height: 44px;
line-height: 44px; line-height: 44px;
} }
.is-active { .is-active {
background-color: #1890ff; background-color: #1890ff;
// 关闭三级菜单二级菜单样式 // 关闭三级菜单二级菜单样式
ul{ ul{
...@@ -715,7 +716,7 @@ li { ...@@ -715,7 +716,7 @@ li {
} }
.admin-box { .admin-box {
padding: 15px 20px; padding: 14px 20px;
.el-button { .el-button {
padding: 7px 10px; padding: 7px 10px;
} }
...@@ -732,13 +733,13 @@ li { ...@@ -732,13 +733,13 @@ li {
.admin-box { .admin-box {
min-height: calc(100vh - 200px); min-height: calc(100vh - 200px);
background-color: $white-bg; background-color: $white-bg;
padding: 15px; padding: 14px;
margin: 115px 15px 20px; margin: 114px 14px 20px;
border-radius: 2px; border-radius: 2px;
.el-table--border { .el-table--border {
border-radius: 4px; border-radius: 4px;
margin-bottom: 15px; margin-bottom: 14px;
} }
.el-table { .el-table {
...@@ -1090,21 +1091,6 @@ li { ...@@ -1090,21 +1091,6 @@ li {
border-left: 1px solid $border-color; border-left: 1px solid $border-color;
} }
.el-tabs__item::before {
content: "";
width: 9px;
height: 9px;
margin-right: 8px;
display: inline-block;
background-color: #ddd;
border-radius: 50%;
transition: background-color .2s;
}
.el-tabs__item.is-active::before {
background-color: #409eff;
}
.el-tabs__item.is-active { .el-tabs__item.is-active {
background-color: rgba(64, 158, 255, .08); background-color: rgba(64, 158, 255, .08);
} }
...@@ -1210,7 +1196,7 @@ $mainHight: 100vh; ...@@ -1210,7 +1196,7 @@ $mainHight: 100vh;
height: 60px; height: 60px;
} }
} }
} }
...@@ -1226,7 +1212,7 @@ $mainHight: 100vh; ...@@ -1226,7 +1212,7 @@ $mainHight: 100vh;
line-height: $height-header; line-height: $height-header;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
margin-right: 40px; margin-right: 10px;
img { img {
vertical-align: middle; vertical-align: middle;
...@@ -1246,7 +1232,7 @@ $mainHight: 100vh; ...@@ -1246,7 +1232,7 @@ $mainHight: 100vh;
line-height: $height-header; line-height: $height-header;
display: inline-block; display: inline-block;
background-color: #fff; background-color: #fff;
padding: 0 24px; padding: 0;
} }
.fl-right { .fl-right {
...@@ -1284,7 +1270,6 @@ $mainHight: 100vh; ...@@ -1284,7 +1270,6 @@ $mainHight: 100vh;
.el-menu-vertical { .el-menu-vertical {
height: calc(100vh - 64px) !important; height: calc(100vh - 64px) !important;
visibility: auto; visibility: auto;
&:not(.el-menu--collapse) { &:not(.el-menu--collapse) {
width: 220px; width: 220px;
} }
...@@ -1485,7 +1470,7 @@ $mainHight: 100vh; ...@@ -1485,7 +1470,7 @@ $mainHight: 100vh;
} }
.shadow { .shadow {
margin: 5px 0; margin: 4px 0;
.grid-content { .grid-content {
background-color: $white-bg; background-color: $white-bg;
...@@ -1521,4 +1506,4 @@ $mainHight: 100vh; ...@@ -1521,4 +1506,4 @@ $mainHight: 100vh;
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background-color: #bbb; background-color: #bbb;
} }
\ No newline at end of file
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
padding: 0 $padding-xs; padding: 0 $padding-xs;
} }
} }
} }
.layout-cont{ .layout-cont{
.right-box{ .right-box{
margin-right: $margin-xs; margin-right: $margin-xs;
} }
} }
.search-component{ .search-component{
width: 30px; width: 30px;
} }
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
margin-right: 0; margin-right: 0;
} }
.big.admin-box{ .big.admin-box{
padding: 0 0 15px 0; padding: 0;
} }
.big { .big {
.bottom { .bottom {
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
} }
} }
} }
.card .car-left, .card .car-left,
.card .car-right{ .card .car-right{
width: 100%; width: 100%;
...@@ -64,13 +64,13 @@ ...@@ -64,13 +64,13 @@
} }
} }
.shadow{ .shadow{
margin-left: 5px; margin-left: 4px;
margin-right: 5px; margin-right: 4px;
.grid-content{ .grid-content{
margin-bottom: 10px; margin-bottom: 10px;
padding: 0; padding: 0;
} }
} }
.el-dialog{ .el-dialog{
width: 90%; width: 90%;
} }
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
padding: 0 5px; padding: 0 5px;
display: inline-block; display: inline-block;
} }
} }
} }
\ No newline at end of file
...@@ -173,7 +173,6 @@ export default { ...@@ -173,7 +173,6 @@ export default {
margin: 100px 0 0 0; margin: 100px 0 0 0;
padding-top: 0; padding-top: 0;
background-color: rgb(243, 243, 243); background-color: rgb(243, 243, 243);
padding-top: 15px;
.top { .top {
width: 100%; width: 100%;
height: 360px; height: 360px;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<input v-show="false" id="file" ref="Input" multiple="multiple" type="file" @change="choseFile"> <input v-show="false" id="file" ref="Input" multiple="multiple" type="file" @change="choseFile">
</div> </div>
</form> </form>
<el-button :disabled="limitFileSize" type="primary" size="medium" class="uploadBtn" @click="getFile">上传文件</el-button> <el-button :disabled="limitFileSize" type="primary" size="mini" class="uploadBtn" @click="getFile">上传文件</el-button>
<div class="el-upload__tip">请上传不超过5MB的文件</div> <div class="el-upload__tip">请上传不超过5MB的文件</div>
<div class="list"> <div class="list">
<transition name="list" tag="p"> <transition name="list" tag="p">
...@@ -186,7 +186,8 @@ a { ...@@ -186,7 +186,8 @@ a {
display: inline-block; display: inline-block;
} }
.fileUpload{ .fileUpload{
padding: 4px 10px; padding: 3px 10px;
font-size: 12px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
position: relative; position: relative;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<div class="search-term"> <div class="search-term">
<el-form :inline="true" :model="searchInfo" class="demo-form-inline"> <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
<el-form-item> <el-form-item>
<el-button type="primary" @click="openDialog">新增客户</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="openDialog">新增</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
......
<template> <template>
<div class="upload"> <div class="upload">
<el-row> <div class="btn-list">
<el-col :span="2"> <el-upload
<el-upload class="excel-btn"
:action="`${path}/excel/importExcel`" :action="`${path}/excel/importExcel`"
:headers="{'x-token':token}" :headers="{'x-token':token}"
:on-success="loadExcel" :on-success="loadExcel"
:show-file-list="false" :show-file-list="false"
> >
<el-button size="small" type="primary" icon="el-icon-upload2">导入</el-button> <el-button size="small" type="primary" icon="el-icon-upload2">导入</el-button>
</el-upload> </el-upload>
</el-col> <el-button class="excel-btn" size="small" type="primary" icon="el-icon-download" @click="handleExcelExport('ExcelExport.xlsx')">导出</el-button>
<el-col :span="2"> <el-button class="excel-btn" size="small" type="success" icon="el-icon-download" @click="downloadExcelTemplate()">下载模板</el-button>
<el-button size="small" type="primary" icon="el-icon-download" @click="handleExcelExport('ExcelExport.xlsx')">导出</el-button> </div>
</el-col>
<el-col :span="2">
<el-button size="small" type="success" icon="el-icon-download" @click="downloadExcelTemplate()">下载模板</el-button>
</el-col>
</el-row>
<el-table :data="tableData" border row-key="ID" stripe> <el-table :data="tableData" border row-key="ID" stripe>
<el-table-column label="ID" min-width="100" prop="ID" /> <el-table-column label="ID" min-width="100" prop="ID" />
<el-table-column label="路由Name" min-width="160" prop="name" /> <el-table-column label="路由Name" min-width="160" prop="name" />
...@@ -73,3 +68,13 @@ export default { ...@@ -73,3 +68,13 @@ export default {
} }
} }
</script> </script>
<style lang="scss" scoped>
.btn-list{
display: flex;
margin-bottom: 12px;
.excel-btn+.excel-btn{
margin-left: 12px;
}
}
</style>
...@@ -145,7 +145,7 @@ export default { ...@@ -145,7 +145,7 @@ export default {
.uploader-example { .uploader-example {
width: 880px; width: 880px;
padding: 15px; padding: 15px;
margin: 115px 15px 20px; margin: 15px 15px 20px;
font-size: 12px; font-size: 12px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
带压缩的上传, (512(k)为压缩限制) 带压缩的上传, (512(k)为压缩限制)
<upload-image v-model="imageUrl" :file-size="512" :max-w-h="1080" /> <upload-image v-model="imageUrl" :file-size="512" :max-w-h="1080" @on-success="getTableData" />
已上传文件 {{ imageUrl }} 已上传文件 {{ imageUrl }}
</el-col> </el-col>
</el-row> </el-row>
......
...@@ -85,7 +85,7 @@ export default { ...@@ -85,7 +85,7 @@ export default {
console.log(this.hello) console.log(this.hello)
}, },
goDoc() { goDoc() {
window.open('https://www.gin-vue-admin.com') window.open('https://www.gin-vue-admin.com/docs/first_master#3-init')
}, },
async onSubmit() { async onSubmit() {
const loading = this.$loading({ const loading = this.$loading({
......
<template> <template>
<div class="router-history"> <div class="router-history">
<el-tabs <el-tabs
v-model="activeValue" v-model="activeValue"
...@@ -10,11 +10,14 @@ ...@@ -10,11 +10,14 @@
> >
<el-tab-pane <el-tab-pane
v-for="item in historys" v-for="item in historys"
:key="item.name + JSON.stringify(item.query)+JSON.stringify(item.params)" :key="name(item)"
:label="item.meta.title" :label="item.meta.title"
:name="item.name + JSON.stringify(item.query)+JSON.stringify(item.params)" :name="name(item)"
:tab="item" :tab="item"
/> class="gva-tab"
>
<span slot="label" :style="{color: activeValue===name(item)?activeColor:'#333'}"><i class="dot" :style="{backgroundColor:activeValue===name(item)?activeColor:'#ddd'}" /> {{ item.meta.title }}</span>
</el-tab-pane>
</el-tabs> </el-tabs>
<!--自定义右键菜单html代码--> <!--自定义右键菜单html代码-->
...@@ -49,7 +52,7 @@ export default { ...@@ -49,7 +52,7 @@ export default {
} }
}, },
computed: { computed: {
...mapGetters('user', ['userInfo']), ...mapGetters('user', ['userInfo', 'activeColor']),
defaultRouter() { defaultRouter() {
return this.userInfo.authority.defaultRouter return this.userInfo.authority.defaultRouter
} }
...@@ -108,12 +111,21 @@ export default { ...@@ -108,12 +111,21 @@ export default {
this.$bus.off('mobile') this.$bus.off('mobile')
}, },
methods: { methods: {
name(item) {
return item.name + JSON.stringify(item.query) + JSON.stringify(item.params)
},
openContextMenu(e) { openContextMenu(e) {
if (this.historys.length === 1 && this.$route.name === this.defaultRouter) { if (this.historys.length === 1 && this.$route.name === this.defaultRouter) {
return false return false
} }
if (e.srcElement.id) { let id = ''
if (e.srcElement.nodeName === 'SPAN') {
console.log(e)
id = e.srcElement.offsetParent.id
} else {
id = e.srcElement.id
}
if (id) {
this.contextMenuVisible = true this.contextMenuVisible = true
let width let width
if (this.isCollapse) { if (this.isCollapse) {
...@@ -126,7 +138,7 @@ export default { ...@@ -126,7 +138,7 @@ export default {
} }
this.left = e.clientX - width this.left = e.clientX - width
this.top = e.clientY + 10 this.top = e.clientY + 10
this.rightActive = e.srcElement.id.split('-')[1] this.rightActive = id.split('-')[1]
} }
}, },
closeAll() { closeAll() {
...@@ -277,6 +289,19 @@ export default { ...@@ -277,6 +289,19 @@ export default {
color: #333; color: #333;
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2); box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2);
} }
.el-tabs__item .el-icon-close{
color: initial !important;
}
.el-tabs__item .dot {
content: "";
width: 9px;
height: 9px;
margin-right: 8px;
display: inline-block;
border-radius: 50%;
transition: background-color .2s;
}
.contextmenu li { .contextmenu li {
margin: 0; margin: 0;
padding: 7px 16px; padding: 7px 16px;
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
:collapse="isCollapse" :collapse="isCollapse"
:collapse-transition="true" :collapse-transition="true"
:default-active="active" :default-active="active"
active-text-color="#fff" :background-color="sideMode"
:active-text-color="activeColor"
:text-color="baseColor"
class="el-menu-vertical" class="el-menu-vertical"
text-color="rgb(191, 203, 217)"
unique-opened unique-opened
@select="selectMenuItem" @select="selectMenuItem"
> >
...@@ -36,7 +37,8 @@ export default { ...@@ -36,7 +37,8 @@ export default {
} }
}, },
computed: { computed: {
...mapGetters('router', ['asyncRouters']) ...mapGetters('router', ['asyncRouters']),
...mapGetters('user', ['baseColor', 'activeColor', 'sideMode'])
}, },
watch: { watch: {
$route() { $route() {
...@@ -82,6 +84,21 @@ export default { ...@@ -82,6 +84,21 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.el-submenu__title,.el-menu-item{
i{
color: inherit !important;
}
}
.el-submenu__title:hover,.el-menu-item:hover{
i{
color: inherit !important;
}
span{
color: inherit !important;
}
}
.el-scrollbar { .el-scrollbar {
.el-scrollbar__view { .el-scrollbar__view {
height: 100%; height: 100%;
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
<el-container :class="[isSider?'openside':'hideside',isMobile ? 'mobile': '']"> <el-container :class="[isSider?'openside':'hideside',isMobile ? 'mobile': '']">
<el-row :class="[isShadowBg?'shadowBg':'']" @click.native="changeShadow()" /> <el-row :class="[isShadowBg?'shadowBg':'']" @click.native="changeShadow()" />
<el-aside class="main-cont main-left"> <el-aside class="main-cont main-left">
<div class="tilte"> <div class="tilte" :style="{background: backgroundColor}">
<img alt class="logoimg" :src="$GIN_VUE_ADMIN.appLogo"> <img alt class="logoimg" :src="$GIN_VUE_ADMIN.appLogo">
<h2 v-if="isSider" class="tit-text">{{ $GIN_VUE_ADMIN.appName }}</h2> <h2 v-if="isSider" class="tit-text" :style="{color:textColor}">{{ $GIN_VUE_ADMIN.appName }}</h2>
</div> </div>
<Aside class="aside" /> <Aside class="aside" />
</el-aside> </el-aside>
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
<router-view v-if="!$route.meta.keepAlive && reloadFlag" v-loading="loadingFlag" element-loading-text="正在加载中" class="admin-box" /> <router-view v-if="!$route.meta.keepAlive && reloadFlag" v-loading="loadingFlag" element-loading-text="正在加载中" class="admin-box" />
</transition> </transition>
<BottomInfo /> <BottomInfo />
<setting />
</el-main> </el-main>
</el-container> </el-container>
...@@ -88,6 +89,7 @@ import Search from '@/view/layout/search/search' ...@@ -88,6 +89,7 @@ import Search from '@/view/layout/search/search'
import BottomInfo from '@/view/layout/bottomInfo/bottomInfo' import BottomInfo from '@/view/layout/bottomInfo/bottomInfo'
import { mapGetters, mapActions } from 'vuex' import { mapGetters, mapActions } from 'vuex'
import CustomPic from '@/components/customPic' import CustomPic from '@/components/customPic'
import Setting from './setting'
export default { export default {
name: 'Layout', name: 'Layout',
components: { components: {
...@@ -96,7 +98,8 @@ export default { ...@@ -96,7 +98,8 @@ export default {
Screenfull, Screenfull,
Search, Search,
BottomInfo, BottomInfo,
CustomPic CustomPic,
Setting
}, },
data() { data() {
return { return {
...@@ -111,7 +114,25 @@ export default { ...@@ -111,7 +114,25 @@ export default {
} }
}, },
computed: { computed: {
...mapGetters('user', ['userInfo']), ...mapGetters('user', ['userInfo', 'sideMode', 'baseColor']),
textColor() {
if (this.$store.getters['user/sideMode'] === 'dark') {
return '#fff'
} else if (this.$store.getters['user/sideMode'] === 'light') {
return '#191a23'
} else {
return this.baseColor
}
},
backgroundColor() {
if (this.sideMode === 'dark') {
return '#191a23'
} else if (this.sideMode === 'light') {
return '#fff'
} else {
return this.sideMode
}
},
title() { title() {
return this.$route.meta.title || '当前页面' return this.$route.meta.title || '当前页面'
}, },
...@@ -193,150 +214,12 @@ export default { ...@@ -193,150 +214,12 @@ export default {
<style lang="scss"> <style lang="scss">
@import '@/style/mobile.scss'; @import '@/style/mobile.scss';
// $headerHigh: 52px; .dark{
// $mainHight: 100vh; background-color: #191a23 !important;
// .dropdown-group { color: #fff !important;
// min-width: 100px; }
// } .light{
// .topfix { background-color: #fff !important;
// position: fixed; color: #000 !important;
// top: 0; }
// box-sizing: border-box;
// z-index: 999;
// }
// .admin-box {
// min-height: calc(100vh - 240px);
// background-color: rgb(255, 255, 255);
// margin-top: 100px;
// }
// .el-scrollbar__wrap {
// padding-bottom: 17px;
// }
// .layout-cont {
// .right-box {
// text-align: center;
// vertical-align: middle;
// img {
// vertical-align: middle;
// border: 1px solid #ccc;
// border-radius: 6px;
// }
// }
// .header-cont {
// height: $headerHigh !important;
// background: #fff;
// box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
// line-height: $headerHigh;
// }
// .main-cont {
// .breadcrumb {
// line-height: 48px;
// display: inline-block;
// padding: 0 24px;
// // padding: 6px;
// // border-bottom: 1px solid #eee;
// }
// &.el-main {
// overflow: auto;
// background: #fff;
// // padding: 0px 10px;
// // background: #fff;
// }
// height: $mainHight !important;
// overflow: visible;
// position: relative;
// .menu-total {
// // z-index: 5;
// // position: absolute;
// // top: 10px;
// // right: -35px;
// margin-left: -10px;
// float: left;
// margin-top: 10px;
// width: 30px;
// height: 30px;
// line-height: 30px;
// font-size: 30px;
// // border: 0 solid #ffffff;
// // border-radius: 50%;
// // background: #fff;
// }
// .aside {
// overflow: auto;
// // background: #fff;
// &::-webkit-scrollbar {
// display: none;
// }
// }
// .el-menu-vertical {
// height: calc(100vh - 64px) !important;
// visibility: auto;
// &:not(.el-menu--collapse) {
// width: 220px;
// }
// }
// .el-menu--collapse {
// width: 54px;
// li {
// .el-tooltip,
// .el-submenu__title {
// padding: 0px 15px !important;
// }
// }
// }
// &::-webkit-scrollbar {
// display: none;
// }
// &.main-left {
// width: auto !important;
// }
// &.main-right {
// .admin-title {
// float: left;
// font-size: 16px;
// vertical-align: middle;
// margin-left: 20px;
// img {
// vertical-align: middle;
// }
// &.collapse {
// width: 53px;
// }
// }
// }
// }
// }
// .tilte {
// background: #001529;
// min-height: 64px;
// line-height: 64px;
// background: #002140;
// text-align: center;
// .logoimg {
// width: 30px;
// height: 30px;
// vertical-align: middle;
// background: #fff;
// border-radius: 50%;
// padding: 3px;
// }
// .tit-text {
// display: inline-block;
// color: #fff;
// font-weight: 600;
// font-size: 20px;
// vertical-align: middle;
// }
// }
// .screenfull {
// display: inline-block;
// }
// .header-avatar{
// display: flex;
// justify-content: center;
// align-items: center;
// }
</style> </style>
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
:style="{display:'inline-block',float:'right',width:'31px',textAlign:'left',fontSize:'16px',paddingTop:'2px'}" :style="{display:'inline-block',float:'right',width:'31px',textAlign:'left',fontSize:'16px',paddingTop:'2px'}"
class="user-box" class="user-box"
> >
<i :style="{cursor:'pointer'}" class="el-icon-refresh reload" :class="[reload ? 'reloading' : '']" @click="handleReload" /> <i :style="{cursor:'pointer',paddingLeft:'1px'}" class="el-icon-refresh reload" :class="[reload ? 'reloading' : '']" @click="handleReload" />
</div> </div>
<div :style="{display:'inline-block',float:'right'}" class="user-box"> <div :style="{display:'inline-block',float:'right'}" class="user-box">
<i :style="{cursor:'pointer'}" class="el-icon-search search-icon" @click="showSearch()" /> <i :style="{cursor:'pointer'}" class="el-icon-search search-icon" @click="showSearch()" />
......
<template>
<div>
<el-button type="primary" class="drawer-container" icon="el-icon-setting" @click="showSettingDrawer" />
<el-drawer
title="系统配置"
:visible.sync="drawer"
:direction="direction"
:before-close="handleClose"
>
<div class="setting_body">
<div class="setting_card">
<div class="setting_title">侧边栏主题 (注:自定义请先配置背景色)</div>
<div class="setting_content">
<div class="theme-box">
<div class="item" @click="changeMode('light')">
<i v-if="mode === 'light'" class="el-icon-check check" />
<img src="https://gw.alipayobjects.com/zos/antfincdn/NQ%24zoisaD2/jpRkZQMyYRryryPNtyIC.svg">
</div>
<div class="item" @click="changeMode('dark')">
<i v-if="mode === 'dark'" class="el-icon-check check" />
<img src="https://gw.alipayobjects.com/zos/antfincdn/XwFOFbLkSM/LCkqqYNmvBEbokSDscrm.svg">
</div>
</div>
<div class="color-box">
<div>
<div class="setting_title">自定义背景色</div>
<el-color-picker :value="sideMode" @change="changeMode" />
</div>
<div>
<div class="setting_title">自定义基础色</div>
<el-color-picker :value="baseColor" @change="changeBaseColor" />
</div>
<div>
<div class="setting_title">活跃色</div>
<el-color-picker :value="activeColor" @change="activeColorChange" />
</div>
</div>
</div>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {
drawer: false,
direction: 'rtl'
}
},
computed: {
...mapGetters('user', ['sideMode', 'baseColor', 'activeColor', 'mode'])
},
methods: {
handleClose() {
this.drawer = false
},
showSettingDrawer() {
this.drawer = true
},
changeMode(e) {
if (e === null) {
this.$store.dispatch('user/changeSideMode', 'dark')
return
}
this.$store.dispatch('user/changeSideMode', e)
},
changeBaseColor(e) {
if (e === null) {
this.$store.dispatch('user/changeBaseColor', '#fff')
return
}
this.$store.dispatch('user/changeBaseColor', e)
},
activeColorChange(e) {
if (e === null) {
this.$store.dispatch('user/changeActiveColor', '#1890ff')
return
}
this.$store.dispatch('user/changeActiveColor', e)
}
}
}
</script>
<style lang="scss" scoped>
.drawer-container {
position: fixed;
right: 0;
bottom: 15%;
height: 40px;
width: 40px;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
color: #fff;
border-radius: 4px 0 0 4px;
cursor: pointer;
-webkit-box-shadow: inset 0 0 6px rgba(0 ,0 ,0, 10%);
}
.setting_body{
padding: 20px;
.setting_card{
margin-bottom: 20px;
}
.setting_content{
margin-top: 20px;
display: flex;
flex-direction: column;
>.theme-box{
display: flex;
}
>.color-box{
div{
display: flex;
flex-direction: column;
}
}
.item{
position: relative;
display: flex;
align-items: center;
justify-content: center;
.check{
position: absolute;
font-size: 20px;
color: #00afff;
}
img{
margin-right: 20px;
}
}
}
}
</style>
...@@ -22,19 +22,15 @@ ...@@ -22,19 +22,15 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
</el-form-item> <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog('addApi')">新增</el-button>
<el-form-item>
<el-button type="primary" @click="openDialog('addApi')">新增api</el-button>
</el-form-item>
<el-form-item>
<el-popover v-model="deleteVisible" placement="top" width="160"> <el-popover v-model="deleteVisible" placement="top" width="160">
<p>确定要删除吗?</p> <p>确定要删除吗?</p>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button> <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="onDelete">确定</el-button> <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
</div> </div>
<el-button slot="reference" icon="el-icon-delete" size="mini" type="danger">批量删除</el-button> <el-button slot="reference" icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
</el-popover> </el-popover>
</el-form-item> </el-form-item>
</el-form> </el-form>
......
<template> <template>
<div class="authority"> <div class="authority">
<div class="button-box clearflex"> <div class="button-box clearflex">
<el-button type="primary" @click="addAuthority('0')">新增角色</el-button> <el-button size="mini" type="primary" icon="el-icon-plus" @click="addAuthority('0')">新增角色</el-button>
</div> </div>
<el-table <el-table
:data="tableData" :data="tableData"
...@@ -15,28 +15,28 @@ ...@@ -15,28 +15,28 @@
<el-table-column label="角色名称" min-width="180" prop="authorityName" /> <el-table-column label="角色名称" min-width="180" prop="authorityName" />
<el-table-column fixed="right" label="操作" width="460"> <el-table-column fixed="right" label="操作" width="460">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="small" type="primary" @click="opdendrawer(scope.row)">设置权限</el-button> <el-button size="mini" type="primary" @click="opdendrawer(scope.row)">设置权限</el-button>
<el-button <el-button
icon="el-icon-plus" icon="el-icon-plus"
size="small" size="mini"
type="primary" type="primary"
@click="addAuthority(scope.row.authorityId)" @click="addAuthority(scope.row.authorityId)"
>新增子角色</el-button> >新增子角色</el-button>
<el-button <el-button
icon="el-icon-copy-document" icon="el-icon-copy-document"
size="small" size="mini"
type="primary" type="primary"
@click="copyAuthority(scope.row)" @click="copyAuthority(scope.row)"
>拷贝</el-button> >拷贝</el-button>
<el-button <el-button
icon="el-icon-edit" icon="el-icon-edit"
size="small" size="mini"
type="primary" type="primary"
@click="editAuthority(scope.row)" @click="editAuthority(scope.row)"
>编辑</el-button> >编辑</el-button>
<el-button <el-button
icon="el-icon-delete" icon="el-icon-delete"
size="small" size="mini"
type="danger" type="danger"
@click="deleteAuth(scope.row)" @click="deleteAuth(scope.row)"
>删除</el-button> >删除</el-button>
......
...@@ -18,10 +18,8 @@ ...@@ -18,10 +18,8 @@
<el-input v-model="searchInfo.desc" placeholder="搜索条件" /> <el-input v-model="searchInfo.desc" placeholder="搜索条件" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
</el-form-item> <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>
<el-form-item>
<el-button type="primary" @click="openDialog">新增字典</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
...@@ -50,8 +48,8 @@ ...@@ -50,8 +48,8 @@
<el-table-column label="按钮组"> <el-table-column label="按钮组">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="small" type="success" @click="toDetile(scope.row)">详情</el-button> <el-button size="mini" type="success" @click="toDetile(scope.row)">详情</el-button>
<el-button size="small" type="primary" @click="updateSysDictionary(scope.row)">变更</el-button> <el-button size="mini" type="primary" @click="updateSysDictionary(scope.row)">变更</el-button>
<el-popover v-model="scope.row.visible" placement="top" width="160"> <el-popover v-model="scope.row.visible" placement="top" width="160">
<p>确定要删除吗?</p> <p>确定要删除吗?</p>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="openDialog">新增字典项</el-button> <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增字典项</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
......
<template> <template>
<div> <div>
<div class="button-box clearflex"> <div class="button-box clearflex">
<el-button type="primary" @click="addMenu('0')">新增根菜单</el-button> <el-button size="mini" type="primary" icon="el-icon-plus" @click="addMenu('0')">新增根菜单</el-button>
</div> </div>
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 --> <!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
...@@ -31,19 +31,19 @@ ...@@ -31,19 +31,19 @@
<el-table-column fixed="right" label="操作" width="300"> <el-table-column fixed="right" label="操作" width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="small" size="mini"
type="primary" type="primary"
icon="el-icon-edit" icon="el-icon-edit"
@click="addMenu(scope.row.ID)" @click="addMenu(scope.row.ID)"
>添加子菜单</el-button> >添加子菜单</el-button>
<el-button <el-button
size="small" size="mini"
type="primary" type="primary"
icon="el-icon-edit" icon="el-icon-edit"
@click="editMenu(scope.row.ID)" @click="editMenu(scope.row.ID)"
>编辑</el-button> >编辑</el-button>
<el-button <el-button
size="small" size="mini"
type="danger" type="danger"
icon="el-icon-delete" icon="el-icon-delete"
@click="deleteMenu(scope.row.ID)" @click="deleteMenu(scope.row.ID)"
......
...@@ -12,16 +12,14 @@ ...@@ -12,16 +12,14 @@
<el-input v-model="searchInfo.status" placeholder="搜索条件" /> <el-input v-model="searchInfo.status" placeholder="搜索条件" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button> <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
</el-form-item>
<el-form-item>
<el-popover v-model="deleteVisible" placement="top" width="160"> <el-popover v-model="deleteVisible" placement="top" width="160">
<p>确定要删除吗?</p> <p>确定要删除吗?</p>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button> <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="onDelete">确定</el-button> <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
</div> </div>
<el-button slot="reference" icon="el-icon-delete" size="mini" type="danger">批量删除</el-button> <el-button slot="reference" icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
</el-popover> </el-popover>
</el-form-item> </el-form-item>
</el-form> </el-form>
......
<template> <template>
<div> <div>
<div class="button-box clearflex"> <div class="button-box clearflex">
<el-button type="primary" @click="addUser">新增用户</el-button> <el-button size="mini" type="primary" icon="el-icon-plus" @click="addUser">新增用户</el-button>
</div> </div>
<el-table :data="tableData" border stripe> <el-table :data="tableData" border stripe>
<el-table-column label="头像" min-width="50"> <el-table-column label="头像" min-width="50">
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button> <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
<el-button type="primary" size="mini" @click="deleteUser(scope.row)">确定</el-button> <el-button type="primary" size="mini" @click="deleteUser(scope.row)">确定</el-button>
</div> </div>
<el-button slot="reference" type="danger" icon="el-icon-delete" size="small">删除</el-button> <el-button slot="reference" type="danger" icon="el-icon-delete" size="mini">删除</el-button>
</el-popover> </el-popover>
</template> </template>
</el-table-column> </el-table-column>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<el-input v-model="dialogMiddle.fieldName" autocomplete="off" /> <el-input v-model="dialogMiddle.fieldName" autocomplete="off" />
</el-col> </el-col>
<el-col :offset="1" :span="2"> <el-col :offset="1" :span="2">
<el-button @click="autoFill">自动填充</el-button> <el-button size="mini" @click="autoFill">自动填充</el-button>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="Field中文名" prop="fieldDesc"> <el-form-item label="Field中文名" prop="fieldDesc">
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="getColumn">使用此表创建</el-button> <el-button size="mini" type="primary" @click="getColumn">使用此表创建</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-collapse-item> </el-collapse-item>
...@@ -58,18 +58,28 @@ ...@@ -58,18 +58,28 @@
<el-input v-model="form.description" placeholder="中文描述作为自动api描述" /> <el-input v-model="form.description" placeholder="中文描述作为自动api描述" />
</el-form-item> </el-form-item>
<el-form-item label="文件名称" prop="packageName"> <el-form-item label="文件名称" prop="packageName">
<el-input v-model="form.packageName" placeholder="生成文件的默认名称" /> <el-input v-model="form.packageName" placeholder="生成文件的默认名称(建议为驼峰格式,首字母小写,如sysXxxXxxx)" />
</el-form-item> </el-form-item>
<el-form-item label="自动创建api"> <el-form-item>
<template slot="label">
<el-tooltip content="注:把自动生成的API注册进数据库" placement="bottom" effect="light">
<div> 自动创建API </div>
</el-tooltip>
</template>
<el-checkbox v-model="form.autoCreateApiToSql" /> <el-checkbox v-model="form.autoCreateApiToSql" />
</el-form-item> </el-form-item>
<el-form-item label="自动移动文件"> <el-form-item>
<template slot="label">
<el-tooltip content="注:自动迁移生成的文件到ymal配置的对应位置" placement="bottom" effect="light">
<div> 自动移动文件 </div>
</el-tooltip>
</template>
<el-checkbox v-model="form.autoMoveFile" /> <el-checkbox v-model="form.autoMoveFile" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 组件列表 --> <!-- 组件列表 -->
<div class="button-box clearflex"> <div class="button-box clearflex">
<el-button type="primary" @click="editAndAddField()">新增Field</el-button> <el-button size="mini" type="primary" @click="editAndAddField()">新增Field</el-button>
</div> </div>
<el-table :data="form.fields" border stripe> <el-table :data="form.fields" border stripe>
<el-table-column type="index" label="序列" width="100" /> <el-table-column type="index" label="序列" width="100" />
...@@ -117,15 +127,15 @@ ...@@ -117,15 +127,15 @@
<el-tag type="danger">id , created_at , updated_at , deleted_at 会自动生成请勿重复创建</el-tag> <el-tag type="danger">id , created_at , updated_at , deleted_at 会自动生成请勿重复创建</el-tag>
<!-- 组件列表 --> <!-- 组件列表 -->
<div class="button-box clearflex"> <div class="button-box clearflex">
<el-button type="primary" @click="enterForm(true)">预览代码</el-button> <el-button size="mini" type="primary" @click="enterForm(true)">预览代码</el-button>
<el-button type="primary" @click="enterForm(false)">生成代码</el-button> <el-button size="mini" type="primary" @click="enterForm(false)">生成代码</el-button>
</div> </div>
<!-- 组件弹窗 --> <!-- 组件弹窗 -->
<el-dialog title="组件内容" :visible.sync="dialogFlag"> <el-dialog title="组件内容" :visible.sync="dialogFlag">
<FieldDialog v-if="dialogFlag" ref="fieldDialog" :dialog-middle="dialogMiddle" /> <FieldDialog v-if="dialogFlag" ref="fieldDialog" :dialog-middle="dialogMiddle" />
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button> <el-button size="mini" @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="enterDialog">确 定</el-button> <el-button size="mini" type="primary" @click="enterDialog">确 定</el-button>
</div> </div>
</el-dialog> </el-dialog>
...@@ -199,7 +209,7 @@ export default { ...@@ -199,7 +209,7 @@ export default {
packageName: [ packageName: [
{ {
required: true, required: true,
message: '文件名称:sys_xxxx_xxxx', message: '文件名称:sysXxxxXxxx',
trigger: 'blur' trigger: 'blur'
} }
] ]
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册