Browse Source

Merge branch 'flipped-aurora:develop' into develop

main
VUCA 3 years ago
committed by GitHub
parent
commit
8f9d4127c6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      server/api/v1/sys_initdb.go
  2. 24
      server/api/v1/sys_user.go
  3. 1
      server/config.yaml
  4. 1
      server/model/sys_auto_code.go
  5. 4
      server/resource/template/server/model.go.tpl
  6. 85
      server/resource/template/web/api.js.tpl
  7. 157
      server/resource/template/web/form.vue.tpl
  8. 352
      server/resource/template/web/table.vue.tpl
  9. 3
      server/router/sys_base.go
  10. 3
      server/service/jwt_black_list.go
  11. 9
      server/service/sys_auto_code.go
  12. 33
      server/service/sys_initdb.go
  13. 8
      web/.env.development
  14. 8
      web/.env.production
  15. 6
      web/src/App.vue
  16. 15
      web/src/core/config.js
  17. 4
      web/src/core/gin-vue-admin.js
  18. 7
      web/src/utils/page.js
  19. 23
      web/src/utils/request.js
  20. 24
      web/src/view/init/index.vue
  21. 2
      web/src/view/layout/bottomInfo/bottomInfo.vue
  22. 6
      web/src/view/layout/index.vue
  23. 31
      web/src/view/layout/search/search.vue
  24. 25
      web/src/view/login/index.vue
  25. 157
      web/src/view/login/login.vue
  26. 4
      web/src/view/systemTools/autoCode/index.vue
  27. 9916
      web/yarn.lock

7
server/api/v1/sys_initdb.go

@ -5,6 +5,7 @@ import (
"gin-vue-admin/model/request"
"gin-vue-admin/model/response"
"gin-vue-admin/service"
"go.uber.org/zap"
"github.com/gin-gonic/gin"
@ -18,8 +19,8 @@ import (
// @Router /init/initdb [post]
func InitDB(c *gin.Context) {
if global.GVA_DB != nil {
global.GVA_LOG.Error("非法访问!")
response.FailWithMessage("非法访问", c)
global.GVA_LOG.Error("已存在数据库配置!")
response.FailWithMessage("已存在数据库配置", c)
return
}
var dbInfo request.InitDB
@ -30,7 +31,7 @@ func InitDB(c *gin.Context) {
}
if err := service.InitDB(dbInfo); err != nil {
global.GVA_LOG.Error("自动创建数据库失败!", zap.Any("err", err))
response.FailWithMessage("自动创建数据库失败,请查看后台日志", c)
response.FailWithMessage("自动创建数据库失败,请查看后台日志,检查后在进行初始化", c)
return
}
response.OkWithData("自动创建数据库成功", c)

24
server/api/v1/sys_user.go

@ -23,15 +23,15 @@ import (
// @Success 200 {string} string "{"success":true,"data":{},"msg":"登陆成功"}"
// @Router /base/login [post]
func Login(c *gin.Context) {
var L request.Login
_ = c.ShouldBindJSON(&L)
if err := utils.Verify(L, utils.LoginVerify); err != nil {
var l request.Login
_ = c.ShouldBindJSON(&l)
if err := utils.Verify(l, utils.LoginVerify); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if store.Verify(L.CaptchaId, L.Captcha, true) {
U := &model.SysUser{Username: L.Username, Password: L.Password}
if err, user := service.Login(U); err != nil {
if store.Verify(l.CaptchaId, l.Captcha, true) {
u := &model.SysUser{Username: l.Username, Password: l.Password}
if err, user := service.Login(u); err != nil {
global.GVA_LOG.Error("登陆失败! 用户名不存在或者密码错误!", zap.Any("err", err))
response.FailWithMessage("用户名不存在或者密码错误", c)
} else {
@ -112,13 +112,13 @@ func tokenNext(c *gin.Context, user model.SysUser) {
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
// @Router /user/register [post]
func Register(c *gin.Context) {
var R request.Register
_ = c.ShouldBindJSON(&R)
if err := utils.Verify(R, utils.RegisterVerify); err != nil {
var r request.Register
_ = c.ShouldBindJSON(&r)
if err := utils.Verify(r, utils.RegisterVerify); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
user := &model.SysUser{Username: R.Username, NickName: R.NickName, Password: R.Password, HeaderImg: R.HeaderImg, AuthorityId: R.AuthorityId}
user := &model.SysUser{Username: r.Username, NickName: r.NickName, Password: r.Password, HeaderImg: r.HeaderImg, AuthorityId: r.AuthorityId}
err, userReturn := service.Register(*user)
if err != nil {
global.GVA_LOG.Error("注册失败!", zap.Any("err", err))
@ -142,8 +142,8 @@ func ChangePassword(c *gin.Context) {
response.FailWithMessage(err.Error(), c)
return
}
U := &model.SysUser{Username: user.Username, Password: user.Password}
if err, _ := service.ChangePassword(U, user.NewPassword); err != nil {
u := &model.SysUser{Username: user.Username, Password: user.Password}
if err, _ := service.ChangePassword(u, user.NewPassword); err != nil {
global.GVA_LOG.Error("修改失败!", zap.Any("err", err))
response.FailWithMessage("修改失败,原密码与当前账户不符", c)
} else {

1
server/config.yaml

@ -53,6 +53,7 @@ captcha:
img-height: 80
# mysql connect configuration
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://www.gin-vue-admin.com/docs/first)
mysql:
path: ''
config: ''

1
server/model/sys_auto_code.go

@ -7,6 +7,7 @@ type AutoCodeStruct struct {
StructName string `json:"structName"` // Struct名称
TableName string `json:"tableName"` // 表名
PackageName string `json:"packageName"` // 文件名称
HumpPackageName string `json:"humpPackageName"` // go文件名称
Abbreviation string `json:"abbreviation"` // Struct简称
Description string `json:"description"` // Struct中文名称
AutoCreateApiToSql bool `json:"autoCreateApiToSql"` // 是否自动创建api

4
server/resource/template/server/model.go.tpl

@ -9,9 +9,9 @@ import (
type {{.StructName}} struct {
global.GVA_MODEL {{- range .Fields}}
{{- if eq .FieldType "bool" }}
{{.FieldName}} *{{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- if eq .FieldType "string" -}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}}{{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
{{.FieldName}} *{{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- end }}"`
{{- else }}
{{.FieldName}} {{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- if eq .FieldType "string" -}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}}{{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
{{.FieldName}} {{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- if eq .FieldType "string" -}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}}{{- end -}};{{- if ne .FieldType "string" -}}{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}{{- end -}}"`
{{- end }} {{- end }}
}

85
server/resource/template/web/api.js.tpl

@ -9,13 +9,12 @@ import service from '@/utils/request'
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/create{{.StructName}} [post]
export const create{{.StructName}} = (data) => {
return service({
url: "/{{.Abbreviation}}/create{{.StructName}}",
method: 'post',
data
})
}
return service({
url: '/{{.Abbreviation}}/create{{.StructName}}',
method: 'post',
data
})
}
// @Tags {{.StructName}}
// @Summary 删除{{.StructName}}
@ -25,13 +24,13 @@ export const create{{.StructName}} = (data) => {
// @Param data body model.{{.StructName}} true "删除{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /{{.Abbreviation}}/delete{{.StructName}} [delete]
export const delete{{.StructName}} = (data) => {
return service({
url: "/{{.Abbreviation}}/delete{{.StructName}}",
method: 'delete',
data
})
}
export const delete{{.StructName}} = (data) => {
return service({
url: '/{{.Abbreviation}}/delete{{.StructName}}',
method: 'delete',
data
})
}
// @Tags {{.StructName}}
// @Summary 删除{{.StructName}}
@ -41,13 +40,13 @@ export const create{{.StructName}} = (data) => {
// @Param data body request.IdsReq true "批量删除{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /{{.Abbreviation}}/delete{{.StructName}} [delete]
export const delete{{.StructName}}ByIds = (data) => {
return service({
url: "/{{.Abbreviation}}/delete{{.StructName}}ByIds",
method: 'delete',
data
})
}
export const delete{{.StructName}}ByIds = (data) => {
return service({
url: '/{{.Abbreviation}}/delete{{.StructName}}ByIds',
method: 'delete',
data
})
}
// @Tags {{.StructName}}
// @Summary 更新{{.StructName}}
@ -57,14 +56,13 @@ export const create{{.StructName}} = (data) => {
// @Param data body model.{{.StructName}} true "更新{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /{{.Abbreviation}}/update{{.StructName}} [put]
export const update{{.StructName}} = (data) => {
return service({
url: "/{{.Abbreviation}}/update{{.StructName}}",
method: 'put',
data
})
}
export const update{{.StructName}} = (data) => {
return service({
url: '/{{.Abbreviation}}/update{{.StructName}}',
method: 'put',
data
})
}
// @Tags {{.StructName}}
// @Summary 用id查询{{.StructName}}
@ -74,14 +72,13 @@ export const create{{.StructName}} = (data) => {
// @Param data body model.{{.StructName}} true "用id查询{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /{{.Abbreviation}}/find{{.StructName}} [get]
export const find{{.StructName}} = (params) => {
return service({
url: "/{{.Abbreviation}}/find{{.StructName}}",
method: 'get',
params
})
}
export const find{{.StructName}} = (params) => {
return service({
url: '/{{.Abbreviation}}/find{{.StructName}}',
method: 'get',
params
})
}
// @Tags {{.StructName}}
// @Summary 分页获取{{.StructName}}列表
@ -91,10 +88,10 @@ export const create{{.StructName}} = (data) => {
// @Param data body request.PageInfo true "分页获取{{.StructName}}列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /{{.Abbreviation}}/get{{.StructName}}List [get]
export const get{{.StructName}}List = (params) => {
return service({
url: "/{{.Abbreviation}}/get{{.StructName}}List",
method: 'get',
params
})
}
export const get{{.StructName}}List = (params) => {
return service({
url: '/{{.Abbreviation}}/get{{.StructName}}List',
method: 'get',
params
})
}

157
server/resource/template/web/form.vue.tpl

@ -1,124 +1,121 @@
<template>
<div>
<div>
<el-form :model="formData" label-position="right" label-width="80px">
{{- range .Fields}}
<el-form-item label="{{.FieldDesc}}:">
{{- if eq .FieldType "bool" }}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
{{ end -}}
{{- if eq .FieldType "string" }}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" ></el-input>
{{ end -}}
{{- if eq .FieldType "int" }}
{{- if .DictType}}
<el-select v-model="formData.{{ .FieldJson }}" placeholder="请选择" clearable>
<el-option v-for="(item,key) in {{ .DictType }}Options" :key="key" :label="item.label" :value="item.value"></el-option>
</el-select>
{{ else -}}
<el-input v-model.number="formData.{{ .FieldJson }}" clearable placeholder="请输入"></el-input>
{{ end -}}
{{ end -}}
{{- if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable></el-date-picker>
{{ end -}}
{{- if eq .FieldType "float64" }}
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable></el-input-number>
{{ end -}}
</el-form-item>
{{ end -}}
<el-form-item>
<el-button @click="save" type="primary">保存</el-button>
<el-button @click="back" type="primary">返回</el-button>
</el-form-item>
{{- range .Fields}}
<el-form-item label="{{.FieldDesc}}:">
{{ if eq .FieldType "bool" -}}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
{{ end -}}
{{ if eq .FieldType "string" -}}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" />
{{ end -}}
{{ if eq .FieldType "int" -}}
{{ if .DictType -}}
<el-select v-model="formData.{{ .FieldJson }}" placeholder="请选择" clearable>
<el-option v-for="(item,key) in {{ .DictType }}Options" :key="key" :label="item.label" :value="item.value"></el-option>
</el-select>
{{ else -}}
<el-input v-model.number="formData.{{ .FieldJson }}" clearable placeholder="请输入"/>
{{ end -}}
{{ end -}}
{{ if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable></el-date-picker>
{{ end -}}
{{ if eq .FieldType "float64" }}
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable></el-input-number>
{{ end -}}
</el-form-item>
{{ end -}}
<el-form-item>
<el-button type="primary" @click="save">保存</el-button>
<el-button type="primary" @click="back">返回</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {
create{{.StructName}},
update{{.StructName}},
find{{.StructName}}
} from "@/api/{{.PackageName}}"; // 此处请自行替换地址
import infoList from "@/mixins/infoList";
create{{.StructName}},
update{{.StructName}},
find{{.StructName}}
} from '@/api/{{.PackageName}}' // 此处请自行替换地址
import infoList from '@/mixins/infoList'
export default {
name: "{{.StructName}}",
name: '{{.StructName}}',
mixins: [infoList],
data() {
return {
type: "",
{{- range .Fields}}
type: '',
{{range .Fields}}
{{- if .DictType }}
{{ .DictType }}Options:[],
{{ .DictType }}Options: [],
{{ end -}}
{{end -}}
formData: {
{{range .Fields}}
{{- if eq .FieldType "bool" -}}
{{.FieldJson}}:false,
{{.FieldJson}}: false,
{{ end -}}
{{- if eq .FieldType "string" -}}
{{.FieldJson}}:"",
{{.FieldJson}}: '',
{{ end -}}
{{- if eq .FieldType "int" -}}
{{.FieldJson}}:0,
{{.FieldJson}}: 0,
{{ end -}}
{{- if eq .FieldType "time.Time" -}}
{{.FieldJson}}:new Date(),
{{.FieldJson}}: new Date(),
{{ end -}}
{{- if eq .FieldType "float64" -}}
{{.FieldJson}}:0,
{{.FieldJson}}: 0,
{{ end -}}
{{ end }}
}
};
}
},
async created() {
// 建议通过url传参获取目标数据ID 调用 find方法进行查询数据操作 从而决定本页面是create还是update 以下为id作为url参数示例
if (this.$route.query.id) {
const res = await find{{.StructName}}({ ID: this.$route.query.id })
if (res.code === 0) {
this.formData = res.data.re{{.Abbreviation}}
this.type = 'update'
}
} else {
this.type = 'create'
}
{{ range .Fields -}}
{{- if .DictType }}
await this.getDict("{{.DictType}}")
{{ end -}}
{{- end }}
},
methods: {
async save() {
let res;
let res
switch (this.type) {
case "create":
res = await create{{.StructName}}(this.formData);
break;
case "update":
res = await update{{.StructName}}(this.formData);
break;
case 'create':
res = await create{{.StructName}}(this.formData)
break
case 'update':
res = await update{{.StructName}}(this.formData)
break
default:
res = await create{{.StructName}}(this.formData);
break;
res = await create{{.StructName}}(this.formData)
break
}
if (res.code == 0) {
if (res.code === 0) {
this.$message({
type:"success",
message:"创建/更改成功"
type: 'success',
message: '创建/更改成功'
})
}
},
back(){
this.$router.go(-1)
back() {
this.$router.go(-1)
}
},
async created() {
// 建议通过url传参获取目标数据ID 调用 find方法进行查询数据操作 从而决定本页面是create还是update 以下为id作为url参数示例
if(this.$route.query.id){
const res = await find{{.StructName}}({ ID: this.$route.query.id })
if(res.code == 0){
this.formData = res.data.re{{.Abbreviation}}
this.type = "update"
}
}else{
this.type = "create"
}
{{ range .Fields -}}
{{- if .DictType }}
await this.getDict("{{.DictType}}");
{{ end -}}
{{- end }}
}
}
};
</script>
<style>

352
server/resource/template/web/table.vue.tpl

@ -19,61 +19,61 @@
</el-form-item>
{{- else }}
<el-form-item label="{{.FieldDesc}}">
<el-input placeholder="搜索条件" v-model="searchInfo.{{.FieldJson}}"></el-input>
<el-input placeholder="搜索条件" v-model="searchInfo.{{.FieldJson}}" />
</el-form-item> {{ end }} {{ end }} {{ end }}
<el-form-item>
<el-button @click="onSubmit" type="primary">查询</el-button>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
<el-form-item>
<el-button @click="openDialog" type="primary">新增{{.Description}}</el-button>
<el-button type="primary" @click="openDialog">新增{{.Description}}</el-button>
</el-form-item>
<el-form-item>
<el-popover placement="top" v-model="deleteVisible" width="160">
<el-popover v-model="deleteVisible" placement="top" width="160">
<p>确定要删除吗?</p>
<div style="text-align: right; margin: 0">
<el-button @click="deleteVisible = false" size="mini" type="text">取消</el-button>
<el-button @click="onDelete" size="mini" type="primary">确定</el-button>
</div>
<el-button icon="el-icon-delete" size="mini" slot="reference" type="danger">批量删除</el-button>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="onDelete">确定</el-button>
</div>
<el-button slot="reference" icon="el-icon-delete" size="mini" type="danger">批量删除</el-button>
</el-popover>
</el-form-item>
</el-form>
</div>
<el-table
:data="tableData"
@selection-change="handleSelectionChange"
border
ref="multipleTable"
border
stripe
style="width: 100%"
tooltip-effect="dark"
:data="tableData"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="日期" width="180">
<template slot-scope="scope">{{ "{{scope.row.CreatedAt|formatDate}}" }}</template>
</el-table-column>
{{range .Fields}}
{{- if .DictType}}
<el-table-column type="selection" width="55" />
<el-table-column label="日期" width="180">
<template slot-scope="scope">{{ "{{ scope.row.CreatedAt|formatDate }}" }}</template>
</el-table-column>
{{- range .Fields}}
{{- if .DictType}}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120">
<template slot-scope="scope">
{{"{{"}}filterDict(scope.row.{{.FieldJson}},"{{.DictType}}"){{"}}"}}
</template>
</el-table-column>
{{- else if eq .FieldType "bool" }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120">
<template slot-scope="scope">{{ "{{scope.row."}}{{.FieldJson}}{{"|formatBoolean}}" }}</template>
</el-table-column> {{- else }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120"></el-table-column> {{ end }}
{{ end }}
{{- else if eq .FieldType "bool" }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120">
<template slot-scope="scope">{{ "{{scope.row."}}{{.FieldJson}}{{"|formatBoolean}}" }}</template>
</el-table-column> {{- else }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120" /> {{ end -}}
{{ end -}}
<el-table-column label="按钮组">
<template slot-scope="scope">
<el-button class="table-button" @click="update{{.StructName}}(scope.row)" size="small" type="primary" icon="el-icon-edit">变更</el-button>
<el-button size="small" type="primary" icon="el-icon-edit" class="table-button" @click="update{{.StructName}}(scope.row)">变更</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
layout="total, sizes, prev, pager, next, jumper"
:current-page="page"
:page-size="pageSize"
:page-sizes="[10, 30, 50, 100]"
@ -81,40 +81,38 @@
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
/>
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="弹窗操作">
<el-form :model="formData" label-position="right" label-width="80px">
{{- range .Fields}}
<el-form-item label="{{.FieldDesc}}:">
{{- if eq .FieldType "bool" }}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
<el-form-item label="{{.FieldDesc}}:">
{{ if eq .FieldType "bool" }}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
{{ end -}}
{{- if eq .FieldType "string" }}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" ></el-input>
{{ if eq .FieldType "string" }}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" />
{{ end -}}
{{- if eq .FieldType "int" }}
{{ if eq .FieldType "int" }}
{{- if .DictType}}
<el-select v-model="formData.{{ .FieldJson }}" placeholder="请选择" clearable>
<el-option v-for="(item,key) in {{ .DictType }}Options" :key="key" :label="item.label" :value="item.value"></el-option>
</el-select>
{{ else -}}
<el-input v-model.number="formData.{{ .FieldJson }}" clearable placeholder="请输入"></el-input>
<el-select v-model="formData.{{ .FieldJson }}" placeholder="请选择" clearable>
<el-option v-for="(item,key) in {{ .DictType }}Options" :key="key" :label="item.label" :value="item.value" />
</el-select>
{{ else }}
<el-input v-model.number="formData.{{ .FieldJson }}" clearable placeholder="请输入" />
{{ end -}}
{{ end -}}
{{- if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable></el-date-picker>
{{ if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable />
{{ end -}}
{{- if eq .FieldType "float64" }}
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable></el-input-number>
{{ end -}}
</el-form-item>
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable />
{{ end -}}
</el-form>
<div class="dialog-footer" slot="footer">
</el-form-item>
{{- end }}
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button @click="enterDialog" type="primary">确 定</el-button>
<el-button type="primary" @click="enterDialog">确 定</el-button>
</div>
</el-dialog>
</div>
@ -122,198 +120,196 @@
<script>
import {
create{{.StructName}},
delete{{.StructName}},
delete{{.StructName}}ByIds,
update{{.StructName}},
find{{.StructName}},
get{{.StructName}}List
} from "@/api/{{.PackageName}}"; // 此处请自行替换地址
import { formatTimeToStr } from "@/utils/date";
import infoList from "@/mixins/infoList";
create{{.StructName}},
delete{{.StructName}},
delete{{.StructName}}ByIds,
update{{.StructName}},
find{{.StructName}},
get{{.StructName}}List
} from '@/api/{{.PackageName}}' // 此处请自行替换地址
import { formatTimeToStr } from '@/utils/date'
import infoList from '@/mixins/infoList'
export default {
name: "{{.StructName}}",
name: '{{.StructName}}',
mixins: [infoList],
data() {
return {
listApi: get{{ .StructName }}List,
dialogFormVisible: false,
type: "",
type: '',
deleteVisible: false,
multipleSelection: [],
{{- range .Fields}}
{{ range .Fields}}
{{- if .DictType }}
{{ .DictType }}Options:[],
{{ .DictType }}Options: [],
{{ end -}}
{{end -}}
{{ end }}
formData: {
{{range .Fields}}
{{- if eq .FieldType "bool" -}}
{{.FieldJson}}:false,
{{ end -}}
{{- if eq .FieldType "string" -}}
{{.FieldJson}}:"",
{{ end -}}
{{- if eq .FieldType "int" -}}
{{.FieldJson}}:0,
{{ end -}}
{{- if eq .FieldType "time.Time" -}}
{{.FieldJson}}:new Date(),
{{ end -}}
{{- if eq .FieldType "float64" -}}
{{.FieldJson}}:0,
{{ end -}}
{{ end }}
{{range .Fields}}
{{- if eq .FieldType "bool" -}}
{{.FieldJson}}: false,
{{ end -}}
{{- if eq .FieldType "string" -}}
{{.FieldJson}}: '',
{{ end -}}
{{- if eq .FieldType "int" -}}
{{.FieldJson}}: 0,
{{ end -}}
{{- if eq .FieldType "time.Time" -}}
{{.FieldJson}}: new Date(),
{{ end -}}
{{- if eq .FieldType "float64" -}}
{{.FieldJson}}: 0,
{{ end -}}
{{ end }}
}
};
}
},
filters: {
formatDate: function(time) {
if (time != null && time != "") {
if (time !== null && time !== '') {
var date = new Date(time);
return formatTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss');
} else {
return "";
return ''
}
},
formatBoolean: function(bool) {
if (bool != null) {
return bool ? "是" :"否";
return bool ? '是' : '否'
} else {
return "";
return ''
}
}
},
async created() {
await this.getTableData()
{{ range .Fields -}}
{{- if .DictType }}
await this.getDict('{{.DictType}}')
{{ end -}}
{{- end }}
},
methods: {
//条件搜索前端看此方法
onSubmit() {
this.page = 1
this.pageSize = 10
{{- range .Fields}} {{- if eq .FieldType "bool" }}
if (this.searchInfo.{{.FieldJson}}==""){
this.searchInfo.{{.FieldJson}}=null
} {{ end }} {{ end }}
this.getTableData()
},
handleSelectionChange(val) {
this.multipleSelection = val
},
deleteRow(row){
this.$confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.delete{{.StructName}}(row);
});
},
async onDelete() {
const ids = []
if(this.multipleSelection.length == 0){
this.$message({
type: 'warning',
message: '请选择要删除的数据'
})
return
}
this.multipleSelection &&
this.multipleSelection.map(item => {
ids.push(item.ID)
})
const res = await delete{{.StructName}}ByIds({ ids })
if (res.code == 0) {
this.$message({
type: 'success',
message: '删除成功'
})
if (this.tableData.length == ids.length && this.page > 1) {
this.page--;
}
this.deleteVisible = false
this.getTableData()
// 条件搜索前端看此方法
onSubmit() {
this.page = 1
this.pageSize = 10
{{- range .Fields}} {{- if eq .FieldType "bool" }}
if (this.searchInfo.{{.FieldJson}} === ""){
this.searchInfo.{{.FieldJson}}=null
} {{ end }} {{ end }}
this.getTableData()
},
handleSelectionChange(val) {
this.multipleSelection = val
},
deleteRow(row) {
this.$confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.delete{{.StructName}}(row)
})
},
async onDelete() {
const ids = []
if (this.multipleSelection.length === 0) {
this.$message({
type: 'warning',
message: '请选择要删除的数据'
})
return
}
this.multipleSelection &&
this.multipleSelection.map(item => {
ids.push(item.ID)
})
const res = await delete{{.StructName}}ByIds({ ids })
if (res.code === 0) {
this.$message({
type: 'success',
message: '删除成功'
})
if (this.tableData.length === ids.length && this.page > 1) {
this.page--
}
},
this.deleteVisible = false
this.getTableData()
}
},
async update{{.StructName}}(row) {
const res = await find{{.StructName}}({ ID: row.ID });
this.type = "update";
if (res.code == 0) {
this.formData = res.data.re{{.Abbreviation}};
this.dialogFormVisible = true;
const res = await find{{.StructName}}({ ID: row.ID })
this.type = 'update'
if (res.code === 0) {
this.formData = res.data.re{{.Abbreviation}}
this.dialogFormVisible = true
}
},
closeDialog() {
this.dialogFormVisible = false;
this.dialogFormVisible = false
this.formData = {
{{range .Fields}}
{{range .Fields}}
{{- if eq .FieldType "bool" -}}
{{.FieldJson}}:false,
{{.FieldJson}}: false,
{{ end -}}
{{- if eq .FieldType "string" -}}
{{.FieldJson}}:"",
{{.FieldJson}}: '',
{{ end -}}
{{- if eq .FieldType "int" -}}
{{.FieldJson}}:0,
{{.FieldJson}}: 0,
{{ end -}}
{{- if eq .FieldType "time.Time" -}}
{{.FieldJson}}:new Date(),
{{.FieldJson}}: new Date(),
{{ end -}}
{{- if eq .FieldType "float64" -}}
{{.FieldJson}}:0,
{{.FieldJson}}: 0,
{{ end -}}
{{ end }}
};
{{ end }}
}
},
async delete{{.StructName}}(row) {
const res = await delete{{.StructName}}({ ID: row.ID });
if (res.code == 0) {
const res = await delete{{.StructName}}({ ID: row.ID })
if (res.code === 0) {
this.$message({
type: "success",
message: "删除成功"
});
if (this.tableData.length == 1 && this.page > 1 ) {
this.page--;
type: 'success',
message: '删除成功'
})
if (this.tableData.length === 1 && this.page > 1 ) {
this.page--
}
this.getTableData();
this.getTableData()
}
},
async enterDialog() {
let res;
let res
switch (this.type) {
case "create":
res = await create{{.StructName}}(this.formData);
break;
res = await create{{.StructName}}(this.formData)
break
case "update":
res = await update{{.StructName}}(this.formData);
break;
res = await update{{.StructName}}(this.formData)
break
default:
res = await create{{.StructName}}(this.formData);
break;
res = await create{{.StructName}}(this.formData)
break
}
if (res.code == 0) {
if (res.code === 0) {
this.$message({
type:"success",
message:"创建/更改成功"
type: 'success',
message: '创建/更改成功'
})
this.closeDialog();
this.getTableData();
this.closeDialog()
this.getTableData()
}
},
openDialog() {
this.type = "create";
this.dialogFormVisible = true;
this.type = 'create'
this.dialogFormVisible = true
}
},
async created() {
await this.getTableData();
{{ range .Fields -}}
{{- if .DictType }}
await this.getDict("{{.DictType}}");
{{ end -}}
{{- end }}
}
};
</script>
<style>

3
server/router/sys_base.go

@ -2,12 +2,11 @@ package router
import (
"gin-vue-admin/api/v1"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
)
func InitBaseRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
BaseRouter := Router.Group("base").Use(middleware.NeedInit())
BaseRouter := Router.Group("base")
{
BaseRouter.POST("login", v1.Login)
BaseRouter.POST("captcha", v1.Captcha)

3
server/service/jwt_black_list.go

@ -26,7 +26,8 @@ func JsonInBlacklist(jwtList model.JwtBlacklist) (err error) {
//@return: bool
func IsBlacklist(jwt string) bool {
isNotFound := errors.Is(global.GVA_DB.Where("jwt = ?", jwt).First(&model.JwtBlacklist{}).Error, gorm.ErrRecordNotFound)
err := global.GVA_DB.Where("jwt = ?", jwt).First(&model.JwtBlacklist{}).Error
isNotFound := errors.Is(err, gorm.ErrRecordNotFound)
return !isNotFound
}

9
server/service/sys_auto_code.go

@ -360,8 +360,15 @@ func getNeedList(autoCode *model.AutoCodeStruct) (dataList []tplData, fileList [
origFileName := strings.TrimSuffix(trimBase[lastSeparator+1:], ".tpl")
firstDot := strings.Index(origFileName, ".")
if firstDot != -1 {
var fileName string
if origFileName[firstDot:] !=".go"{
fileName = autoCode.PackageName+origFileName[firstDot:]
}else{
fileName = autoCode.HumpPackageName+origFileName[firstDot:]
}
dataList[index].autoCodePath = filepath.Join(autoPath, trimBase[:lastSeparator], autoCode.PackageName,
origFileName[:firstDot], autoCode.PackageName+origFileName[firstDot:])
origFileName[:firstDot], fileName)
}
}

33
server/service/sys_initdb.go

@ -9,10 +9,11 @@ import (
"gin-vue-admin/model/request"
"gin-vue-admin/source"
"gin-vue-admin/utils"
"path/filepath"
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"path/filepath"
)
//@author: [songzhibin97](https://github.com/songzhibin97)
@ -71,13 +72,6 @@ func initDB(InitDBFunctions ...model.InitDBFunc) (err error) {
//@return: error
func InitDB(conf request.InitDB) error {
BaseMysql := config.Mysql{
Path: "",
Dbname: "",
Username: "",
Password: "",
Config: "charset=utf8mb4&parseTime=True&loc=Local",
}
if conf.Host == "" {
conf.Host = "127.0.0.1"
@ -100,15 +94,11 @@ func InitDB(conf request.InitDB) error {
Config: "charset=utf8mb4&parseTime=True&loc=Local",
}
if err := writeConfig(global.GVA_VP, MysqlConfig); err != nil {
return err
}
m := global.GVA_CONFIG.Mysql
if m.Dbname == "" {
if MysqlConfig.Dbname == "" {
return nil
}
linkDns := m.Username + ":" + m.Password + "@tcp(" + m.Path + ")/" + m.Dbname + "?" + m.Config
linkDns := MysqlConfig.Username + ":" + MysqlConfig.Password + "@tcp(" + MysqlConfig.Path + ")/" + MysqlConfig.Dbname + "?" + MysqlConfig.Config
mysqlConfig := mysql.Config{
DSN: linkDns, // DSN data source name
DefaultStringSize: 191, // string 类型字段的默认长度
@ -118,15 +108,11 @@ func InitDB(conf request.InitDB) error {
SkipInitializeWithVersion: false, // 根据版本自动配置
}
if db, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}); err != nil {
//global.GVA_LOG.Error("MySQL启动异常!", zap.Any("err", err))
//os.Exit(0)
//return nil
_ = writeConfig(global.GVA_VP, BaseMysql)
return nil
} else {
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(m.MaxIdleConns)
sqlDB.SetMaxOpenConns(m.MaxOpenConns)
sqlDB.SetMaxIdleConns(MysqlConfig.MaxIdleConns)
sqlDB.SetMaxOpenConns(MysqlConfig.MaxOpenConns)
global.GVA_DB = db
}
@ -147,7 +133,7 @@ func InitDB(conf request.InitDB) error {
model.SysOperationRecord{},
)
if err != nil {
_ = writeConfig(global.GVA_VP, BaseMysql)
global.GVA_DB = nil
return err
}
err = initDB(
@ -163,7 +149,10 @@ func InitDB(conf request.InitDB) error {
source.File,
source.BaseMenu)
if err != nil {
_ = writeConfig(global.GVA_VP, BaseMysql)
global.GVA_DB = nil
return err
}
if err = writeConfig(global.GVA_VP, MysqlConfig); err != nil {
return err
}
global.GVA_CONFIG.AutoCode.Root, _ = filepath.Abs("..")

8
web/.env.development

@ -1,6 +1,6 @@
ENV = 'development'
VUE_APP_CLI_PORT = '8080'
VUE_APP_SERVER_PORT = '8888'
VUE_APP_BASE_API = '/api'
VUE_APP_BASE_PATH = 'http://127.0.0.1'
VUE_APP_CLI_PORT = 8080
VUE_APP_SERVER_PORT = 8888
VUE_APP_BASE_API = /api
VUE_APP_BASE_PATH = http://127.0.0.1

8
web/.env.production

@ -1,7 +1,7 @@
ENV = 'production'
VUE_APP_CLI_PORT = '8080'
VUE_APP_SERVER_PORT = '8888'
VUE_APP_BASE_API = '/api'
VUE_APP_CLI_PORT = 8080
VUE_APP_SERVER_PORT = 8888
VUE_APP_BASE_API = /api
#下方修改为你的线上ip
VUE_APP_BASE_PATH = 'http://8.141.61.63'
VUE_APP_BASE_PATH = http://8.141.61.63

6
web/src/App.vue

@ -5,12 +5,8 @@
</template>
<script>
import { checkDB } from '@/api/initdb'
export default {
name: 'App',
async created() {
await checkDB()
}
name: 'App'
}
</script>

15
web/src/core/config.js

@ -0,0 +1,15 @@
/*
* 网站配置文件
* */
const config ={
appName : 'Gin-Vue-Admin',
appLogo : 'https://www.gin-vue-admin.com/img/logo.png'
}
export default config

4
web/src/core/gin-vue-admin.js

@ -10,6 +10,10 @@ import APlayer from '@moefe/vue-aplayer'
import '../../node_modules/timeline-vuejs/dist/timeline-vuejs.css'
// 路由守卫
import Bus from '@/utils/bus'
//加载网站配置文件夹
import config from './config'
Vue.prototype.$GIN_VUE_ADMIN = config
console.log(config)
Vue.use(Bus)
Vue.use(APlayer, {
defaultCover: 'https://github.com/u3u.png',

7
web/src/utils/page.js

@ -1,8 +1,7 @@
const title = 'GIN-VUE-ADMIN'
import config from '@/core/config'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle} - ${title}`
return `${pageTitle} - ${config.appName}`
}
return `${title}`
return `${config.appName}`
}

23
web/src/utils/request.js

@ -2,7 +2,7 @@ import axios from 'axios' // 引入axios
import { Message } from 'element-ui'
import { store } from '@/store'
import context from '@/main'
import router from '@/router/index'
import { MessageBox } from 'element-ui'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
@ -64,16 +64,6 @@ service.interceptors.response.use(
if (response.headers['new-token']) {
store.commit('user/setToken', response.headers['new-token'])
}
if (response.data.code === 0) {
if (response.data.data?.needInit) {
Message({
type: 'info',
message: '您是第一次使用,请初始化'
})
store.commit('user/NeedInit')
router.push({ name: 'Init' })
}
}
if (response.data.code === 0 || response.headers.success === 'true') {
return response.data
} else {
@ -90,11 +80,14 @@ service.interceptors.response.use(
},
error => {
closeLoading()
Message({
showClose: true,
message: error,
type: 'error'
MessageBox.confirm(`检测到接口错误${error},此类错误内容常见于后台panic,如果影响您正常使用可强制登出清理缓存`, '接口报错', {
distinguishCancelAndClose: true,
confirmButtonText: '清理缓存',
cancelButtonText: '取消'
})
.then(() => {
store.commit('user/LoginOut')
})
return error
}
)

24
web/src/view/init/index.vue

@ -1,11 +1,21 @@
<template>
<div class="init_page">
<div class="init_page_panle">
<div v-if="hello < 2" id="hello" :class="[hello < 1 ? 'slide-in-fwd-top' : 'slide-out-right']" class="hello " @click="showNext">
<div v-if="hello < 2" id="hello" :class="[hello < 1 ? 'slide-in-fwd-top' : 'slide-out-right']" class="hello ">
<div>
<div class="hello_title">GIN-VUE-ADMIN</div>
<p class="in-two a-fadeinT">您需要初始化您的数据库并且填充初始数据</p>
<p class="init_p">点击进入初始化</p>
<p class="in-two a-fadeinT">初始化须知</p>
<p class="init_p">1.您需有用一定的VUE和golang基础</p>
<p class="init_p">2.请您确认是否已经阅读过官方文档</p>
<p class="init_p">3.请您确认是否了解后续的配置流程</p>
<p class="init_btn">
<el-button type="primary" @click="goDoc">
阅读文档
</el-button>
<el-button type="primary" @click="showNext">
我已确认
</el-button>
</p>
</div>
</div>
<div v-if="hello > 0 " :class="[(hello > 0 && !out)? 'slide-in-left' : '' , out ? 'slide-out-right' : '']" class=" form">
@ -73,8 +83,10 @@ export default {
this.hello = this.hello + 1
console.log(this.hello)
},
goDoc() {
window.open('https://www.gin-vue-admin.com')
},
async onSubmit() {
this.out = true
const loading = this.$loading({
lock: true,
text: '正在初始化数据库,请稍候',
@ -84,6 +96,7 @@ export default {
try {
const res = await initDB(this.form)
if (res.code === 0) {
this.out = true
this.$message({
type: 'success',
message: res.msg
@ -141,6 +154,9 @@ export default {
margin-top: 20px;
color: #777777;
}
.init_btn{
margin-top: 20px;
}
}
.form{
position: absolute;

2
web/src/view/layout/bottomInfo/bottomInfo.vue

@ -3,7 +3,7 @@
<div>
<span>Powered by</span>
<span>
<a href="https://github.com/flipped-aurora/gin-vue-admin">gin-vue-admin</a>
<a href="https://github.com/flipped-aurora/gin-vue-admin">{{ $GIN_VUE_ADMIN.appName }}</a>
</span>
<el-divider direction="vertical" />
<span>Copyright</span>

6
web/src/view/layout/index.vue

@ -4,8 +4,8 @@
<el-row :class="[isShadowBg?'shadowBg':'']" @click.native="changeShadow()" />
<el-aside class="main-cont main-left">
<div class="tilte">
<img alt class="logoimg" src="~@/assets/nav_logo.png">
<h2 v-if="isSider" class="tit-text">Gin-Vue-Admin</h2>
<img alt class="logoimg" :src="$GIN_VUE_ADMIN.appLogo">
<h2 v-if="isSider" class="tit-text">{{ $GIN_VUE_ADMIN.appName }}</h2>
</div>
<Aside class="aside" />
</el-aside>
@ -38,7 +38,7 @@
<Search />
<Screenfull class="screenfull" :style="{cursor:'pointer'}" />
<el-dropdown>
<span class="header-avatar">
<span class="header-avatar" style="cursor: pointer">
<CustomPic />
<span style="margin-left: 5px">{{ userInfo.nickName }}</span>
<i class="el-icon-arrow-down" />

31
web/src/view/layout/search/search.vue

@ -23,7 +23,7 @@
:style="{display:'inline-block',float:'right',width:'31px',textAlign:'left',fontSize:'16px',paddingTop:'2px'}"
class="user-box"
>
<i :style="{cursor:'pointer'}" class="el-icon-refresh" @click="$bus.$emit('reload')" />
<i :style="{cursor:'pointer'}" class="el-icon-refresh reload" :class="[reload ? 'reloading' : '']" @click="handleReload" />
</div>
<div :style="{display:'inline-block',float:'right'}" class="user-box">
<i :style="{cursor:'pointer'}" class="el-icon-search search-icon" @click="showSearch()" />
@ -39,7 +39,8 @@ export default {
data() {
return {
value: '',
show: false
show: false,
reload: false
}
},
computed: {
@ -58,7 +59,33 @@ export default {
this.$nextTick(() => {
this.$refs['search-input'].focus()
})
},
handleReload() {
this.reload = true
this.$bus.$emit('reload')
setTimeout(() => {
this.reload = false
}, 500)
}
}
}
</script>
<style scoped lang="scss">
.reload{
font-size: 17px;
&:hover{
transform: scale(1.02)
}
}
.reloading{
animation:turn 0.5s linear infinite;
}
@keyframes turn {
0%{-webkit-transform:rotate(0deg);}
25%{-webkit-transform:rotate(90deg);}
50%{-webkit-transform:rotate(180deg);}
75%{-webkit-transform:rotate(270deg);}
100%{-webkit-transform:rotate(360deg);}
}
</style>

25
web/src/view/login/index.vue

@ -3,7 +3,7 @@
<div class="login_panle">
<div class="login_panle_form">
<div class="login_panle_form_title">
<img class="login_panle_form_title_logo" src="@/assets/logo_login.png" alt=""><p class="login_panle_form_title_p">GIN-VUE-ADMIN</p>
<img class="login_panle_form_title_logo" :src="$GIN_VUE_ADMIN.appLogo" alt=""><p class="login_panle_form_title_p">{{ $GIN_VUE_ADMIN.appName }}</p>
</div>
<el-form
ref="loginForm"
@ -47,10 +47,16 @@
>
</div>
</el-form-item>
<div />
<el-form-item>
<el-button
type="primary"
style="width: 100%"
style="width: 46%"
@click="checkInit"
>前往初始化</el-button>
<el-button
type="primary"
style="width: 46%;margin-left:8%"
@click="submitForm"
> </el-button>
</el-form-item>
@ -73,6 +79,7 @@
<script>
import { mapActions } from 'vuex'
import { captcha } from '@/api/user'
import { checkDB } from '@/api/initdb'
export default {
name: 'Login',
data() {
@ -113,6 +120,20 @@ export default {
},
methods: {
...mapActions('user', ['LoginIn']),
async checkInit() {
const res = await checkDB()
if (res.code === 0) {
if (res.data?.needInit) {
this.$store.commit('user/NeedInit')
this.$router.push({ name: 'Init' })
} else {
this.$message({
type: 'info',
message: '已配置数据库信息,无法初始化'
})
}
}
},
async login() {
return await this.LoginIn(this.loginForm)
},

157
web/src/view/login/login.vue

@ -1,157 +0,0 @@
<template>
<div id="userLayout" class="user-layout-wrapper">
<div class="container">
<div class="top">
<div class="desc">
<img class="logo_login" src="@/assets/logo_login.png" alt="">
</div>
<div class="header">
<a href="/"><span class="title">Gin-Vue-Admin</span></a>
</div>
</div>
<div class="main">
<el-form
ref="loginForm"
:model="loginForm"
:rules="rules"
@keyup.enter.native="submitForm"
>
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入用户名">
<i slot="suffix" class="el-input__icon el-icon-user" />
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
:type="lock === 'lock' ? 'password' : 'text'"
placeholder="请输入密码"
>
<i
slot="suffix"
:class="'el-input__icon el-icon-' + lock"
@click="changeLock"
/>
</el-input>
</el-form-item>
<el-form-item style="position: relative">
<el-input
v-model="loginForm.captcha"
name="logVerify"
placeholder="请输入验证码"
style="width: 60%"
/>
<div class="vPic">
<img
v-if="picPath"
:src="picPath"
width="100%"
height="100%"
alt="请输入验证码"
@click="loginVerify()"
>
</div>
</el-form-item>
<el-form-item>
<el-button
type="primary"
style="width: 100%"
@click="submitForm"
> </el-button>
</el-form-item>
</el-form>
</div>
<div class="footer">
<div class="links">
<a href="http://doc.henrongyi.top/"><img src="@/assets/docs.png" class="link-icon"></a>
<a href="https://www.yuque.com/flipped-aurora/"><img src="@/assets/yuque.png" class="link-icon"></a>
<a href="https://github.com/flipped-aurora/gin-vue-admin"><img src="@/assets/github.png" class="link-icon"></a>
<a href="https://space.bilibili.com/322210472"><img src="@/assets/video.png" class="link-icon"></a>
</div>
<div class="copyright">Copyright &copy; {{ curYear }} 💖flipped-aurora</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex'
import { captcha } from '@/api/user'
export default {
name: 'Login',
data() {
const checkUsername = (rule, value, callback) => {
if (value.length < 5) {
return callback(new Error('请输入正确的用户名'))
} else {
callback()
}
}
const checkPassword = (rule, value, callback) => {
if (value.length < 6) {
return callback(new Error('请输入正确的密码'))
} else {
callback()
}
}
return {
curYear: 0,
lock: 'lock',
loginForm: {
username: 'admin',
password: '123456',
captcha: '',
captchaId: ''
},
rules: {
username: [{ validator: checkUsername, trigger: 'blur' }],
password: [{ validator: checkPassword, trigger: 'blur' }]
},
logVerify: '',
picPath: ''
}
},
created() {
this.loginVerify()
this.curYear = new Date().getFullYear()
},
methods: {
...mapActions('user', ['LoginIn']),
async login() {
return await this.LoginIn(this.loginForm)
},
async submitForm() {
this.$refs.loginForm.validate(async(v) => {
if (v) {
const flag = await this.login()
if (!flag) {
this.loginVerify()
}
} else {
this.$message({
type: 'error',
message: '请正确填写登录信息',
showClose: true
})
this.loginVerify()
return false
}
})
},
changeLock() {
this.lock = this.lock === 'lock' ? 'unlock' : 'lock'
},
loginVerify() {
captcha({}).then((ele) => {
this.picPath = ele.data.picPath
this.loginForm.captchaId = ele.data.captchaId
})
}
}
}
</script>
<style scoped lang="scss">
@import "@/style/login.scss";
</style>

4
web/src/view/systemTools/autoCode/index.vue

@ -154,7 +154,7 @@ const fieldTemplate = {
import FieldDialog from '@/view/systemTools/autoCode/component/fieldDialog.vue'
import PreviewCodeDialg from '@/view/systemTools/autoCode/component/previewCodeDialg.vue'
import { toUpperCase, toHump } from '@/utils/stringFun'
import { toUpperCase, toHump, toSQLLine } from '@/utils/stringFun'
import { createTemp, getDB, getTable, getColumn, preview } from '@/api/autoCode'
import { getDict } from '@/utils/dictionary'
@ -294,6 +294,8 @@ export default {
})
return false
}
this.form.humpPackageName = toSQLLine(this.form.packageName)
debugger
if (isPreview) {
const data = await preview(this.form)
this.preViewCode = data.data.autoCode

9916
web/yarn.lock
File diff suppressed because it is too large
View File

Loading…
Cancel
Save