) {
+ return request.post({ url: '/{{{.ModuleName}}}/del', params })
+}
diff --git a/server/generator/templates/vue/edit.vue.tpl b/server/generator/templates/vue/edit.vue.tpl
new file mode 100644
index 0000000..a79cad0
--- /dev/null
+++ b/server/generator/templates/vue/edit.vue.tpl
@@ -0,0 +1,252 @@
+
+
+
+
diff --git a/server/generator/templates/vue/index-tree.vue.tpl b/server/generator/templates/vue/index-tree.vue.tpl
new file mode 100644
index 0000000..a401d5d
--- /dev/null
+++ b/server/generator/templates/vue/index-tree.vue.tpl
@@ -0,0 +1,222 @@
+
+
+
+
+ {{{- range .Columns }}}
+ {{{- if eq .IsQuery 1 }}}
+ {{{- if eq .HtmlType "datetime" }}}
+
+
+
+ {{{- else if or (eq .HtmlType "select") (eq .HtmlType "radio") }}}
+
+
+ {{{- if eq .DictType "" }}}
+
+ {{{- else }}}
+
+
+ {{{- end }}}
+
+
+ {{{- else if eq .HtmlType "input" }}}
+
+
+
+ {{{- end }}}
+ {{{- end }}}
+ {{{- end }}}
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+ 新增
+
+ 展开/折叠
+
+
+ {{{- range .Columns }}}
+ {{{- if .IsList }}}
+ {{{- if and (ne .DictType "") (or (eq .HtmlType "select") (eq .HtmlType "radio") (eq .HtmlType "checkbox")) }}}
+
+
+
+
+
+ {{{- else if eq .HtmlType "imageUpload" }}}
+
+
+
+
+
+ {{{- else }}}
+
+ {{{- end }}}
+ {{{- end }}}
+ {{{- end }}}
+
+
+
+ 新增
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
diff --git a/server/generator/templates/vue/index.vue.tpl b/server/generator/templates/vue/index.vue.tpl
new file mode 100644
index 0000000..65261fa
--- /dev/null
+++ b/server/generator/templates/vue/index.vue.tpl
@@ -0,0 +1,183 @@
+
+
+
+
+ {{{- range .Columns }}}
+ {{{- if eq .IsQuery 1 }}}
+ {{{- if eq .HtmlType "datetime" }}}
+
+
+
+ {{{- else if or (eq .HtmlType "select") (eq .HtmlType "radio") }}}
+
+
+ {{{- if eq .DictType "" }}}
+
+ {{{- else }}}
+
+
+ {{{- end }}}
+
+
+ {{{- else if eq .HtmlType "input" }}}
+
+
+
+ {{{- end }}}
+ {{{- end }}}
+ {{{- end }}}
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+ 新增
+
+
+
+ {{{- range .Columns }}}
+ {{{- if .IsList }}}
+ {{{- if and (ne .DictType "") (or (eq .HtmlType "select") (eq .HtmlType "radio") (eq .HtmlType "checkbox")) }}}
+
+
+
+
+
+ {{{- else if eq .HtmlType "imageUpload" }}}
+
+
+
+
+
+ {{{- else }}}
+
+ {{{- end }}}
+ {{{- end }}}
+ {{{- end }}}
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
diff --git a/server/generator/tpl_utils/constants.go b/server/generator/tpl_utils/constants.go
new file mode 100644
index 0000000..fe11c64
--- /dev/null
+++ b/server/generator/tpl_utils/constants.go
@@ -0,0 +1,93 @@
+package tpl_utils
+
+//GenConstants 代码生成常量
+var GenConstants = genConstants{
+ UTF8: "utf-8", //编码
+ TplCrud: "crud", //单表 (增删改查)
+ TplTree: "tree", //树表 (增删改查)
+ QueryLike: "LIKE", //模糊查询
+ QueryEq: "=", //相等查询
+ Require: 1, //需要的
+}
+
+//GoConstants Go相关常量
+var GoConstants = goConstants{
+ TypeString: "string", //字符串类型
+ TypeFloat: "float64", //浮点型
+ TypeInt: "int", //整型
+ TypeDate: "core.TsTime", //时间类型
+}
+
+//SqlConstants 数据库相关常量
+var SqlConstants = sqlConstants{
+ //数据库字符串类型
+ ColumnTypeStr: []string{"char", "varchar", "nvarchar", "varchar2"},
+ //数据库文本类型
+ ColumnTypeText: []string{"tinytext", "text", "mediumtext", "longtext"},
+ //数据库时间类型
+ ColumnTypeTime: []string{"datetime", "time", "date", "timestamp"},
+ //数据库数字类型
+ ColumnTypeNumber: []string{"tinyint", "smallint", "mediumint", "int", "integer", "bit", "bigint",
+ "float", "double", "decimal"},
+ //时间日期字段名
+ ColumnTimeName: []string{"create_time", "update_time", "delete_time", "start_time", "end_time"},
+ //页面不需要插入字段
+ ColumnNameNotAdd: []string{"id", "is_delete", "create_time", "update_time", "delete_time"},
+ //页面不需要编辑字段
+ ColumnNameNotEdit: []string{"is_delete", "create_time", "update_time", "delete_time"},
+ //页面不需要列表字段
+ ColumnNameNotList: []string{"id", "intro", "content", "is_delete", "delete_time"},
+ //页面不需要查询字段
+ ColumnNameNotQuery: []string{"is_delete", "create_time", "update_time", "delete_time"},
+}
+
+//HtmlConstants HTML相关常量
+var HtmlConstants = htmlConstants{
+ HtmlInput: "input", //文本框
+ HtmlTextarea: "textarea", //文本域
+ HtmlSelect: "select", //下拉框
+ HtmlRadio: "radio", //单选框
+ HtmlDatetime: "datetime", //日期控件
+ HtmlImageUpload: "imageUpload", //图片上传控件
+ HtmlFileUpload: "fileUpload", //文件上传控件
+ HtmlEditor: "editor", //富文本控件
+}
+
+type genConstants struct {
+ UTF8 string
+ TplCrud string
+ TplTree string
+ QueryLike string
+ QueryEq string
+ Require uint8
+}
+
+type goConstants struct {
+ TypeString string
+ TypeFloat string
+ TypeInt string
+ TypeDate string
+}
+
+type sqlConstants struct {
+ ColumnTypeStr []string
+ ColumnTypeText []string
+ ColumnTypeTime []string
+ ColumnTypeNumber []string
+ ColumnTimeName []string
+ ColumnNameNotAdd []string
+ ColumnNameNotEdit []string
+ ColumnNameNotList []string
+ ColumnNameNotQuery []string
+}
+
+type htmlConstants struct {
+ HtmlInput string
+ HtmlTextarea string
+ HtmlSelect string
+ HtmlRadio string
+ HtmlDatetime string
+ HtmlImageUpload string
+ HtmlFileUpload string
+ HtmlEditor string
+}
diff --git a/server/generator/tpl_utils/tpl.go b/server/generator/tpl_utils/tpl.go
new file mode 100644
index 0000000..362ed5b
--- /dev/null
+++ b/server/generator/tpl_utils/tpl.go
@@ -0,0 +1,279 @@
+package tpl_utils
+
+import (
+ "archive/zip"
+ "bytes"
+ "io"
+ "os"
+ "path"
+ "strings"
+ "text/template"
+ "x_admin/config"
+ "x_admin/core/response"
+ "x_admin/model/gen"
+ "x_admin/util"
+)
+
+var TemplateUtil = templateUtil{
+ basePath: "generator/templates",
+ tpl: template.New("").Delims("{{{", "}}}").Funcs(
+ template.FuncMap{
+ "sub": sub,
+ "slice": slice,
+ "title": strings.Title,
+ "toSnakeCase": util.StringUtil.ToSnakeCase,
+ "toCamelCase": util.StringUtil.ToCamelCase,
+ "contains": util.ToolsUtil.Contains,
+ }),
+}
+
+// sub 模板-减函数
+func sub(a, b int) int {
+ return a - b
+}
+
+// slice 模板-创建切片
+func slice(items ...interface{}) []interface{} {
+ return items
+}
+
+// zFile 待加入zip的文件
+type zFile struct {
+ Name string
+ Body string
+}
+
+// TplVars 模板变量
+type TplVars struct {
+ GenTpl string
+ TableName string
+ AuthorName string
+ PackageName string
+ EntityName string
+ EntitySnakeName string
+ ModuleName string
+ FunctionName string
+ JavaCamelField string
+ DateFields []string
+ PrimaryKey string
+ PrimaryField string
+ AllFields []string
+ SubPriCol gen.GenTableColumn
+ SubPriField string
+ SubTableFields []string
+ ListFields []string
+ DetailFields []string
+ DictFields []string
+ IsSearch bool
+ ModelOprMap map[string]string
+ Table gen.GenTable
+ Columns []gen.GenTableColumn
+ SubColumns []gen.GenTableColumn
+ //ModelTypeMap map[string]string
+}
+
+// genUtil 模板工具
+type templateUtil struct {
+ basePath string
+ tpl *template.Template
+}
+
+// PrepareVars 获取模板变量信息
+func (tu templateUtil) PrepareVars(table gen.GenTable, columns []gen.GenTableColumn,
+ oriSubPriCol gen.GenTableColumn, oriSubCols []gen.GenTableColumn) TplVars {
+ subPriField := "id"
+ isSearch := false
+ primaryKey := "id"
+ primaryField := "id"
+ functionName := "【请填写功能名称】"
+ var allFields []string
+ var subTableFields []string
+ var listFields []string
+ var detailFields []string
+ var dictFields []string
+ var subColumns []gen.GenTableColumn
+ var oriSubColNames []string
+ for _, column := range oriSubCols {
+ oriSubColNames = append(oriSubColNames, column.ColumnName)
+ }
+ if oriSubPriCol.ID > 0 {
+ subPriField = oriSubPriCol.ColumnName
+ subColumns = append(subColumns, oriSubPriCol)
+ }
+ for _, column := range columns {
+ allFields = append(allFields, column.ColumnName)
+ if util.ToolsUtil.Contains(oriSubColNames, column.ColumnName) {
+ subTableFields = append(subTableFields, column.ColumnName)
+ subColumns = append(subColumns, column)
+ }
+ if column.IsList == 1 {
+ listFields = append(listFields, column.ColumnName)
+ }
+ if column.IsEdit == 1 {
+ detailFields = append(detailFields, column.ColumnName)
+ }
+ if column.IsQuery == 1 {
+ isSearch = true
+ }
+ if column.IsPk == 1 {
+ primaryKey = column.GoField
+ primaryField = column.ColumnName
+ }
+ if column.DictType != "" && !util.ToolsUtil.Contains(dictFields, column.DictType) {
+ dictFields = append(dictFields, column.DictType)
+ }
+ }
+ //QueryType转换查询比较运算符
+ modelOprMap := map[string]string{
+ "=": "==",
+ "LIKE": "like",
+ }
+ if table.FunctionName != "" {
+ functionName = table.FunctionName
+ }
+ return TplVars{
+ GenTpl: table.GenTpl,
+ TableName: table.TableName,
+ AuthorName: table.AuthorName,
+ PackageName: table.ModuleName, //config.GenConfig.PackageName,
+ EntityName: table.EntityName,
+ EntitySnakeName: util.StringUtil.ToSnakeCase(table.EntityName),
+ ModuleName: table.ModuleName,
+ FunctionName: functionName,
+ DateFields: SqlConstants.ColumnTimeName,
+ PrimaryKey: primaryKey,
+ PrimaryField: primaryField,
+ AllFields: allFields,
+ SubPriCol: oriSubPriCol,
+ SubPriField: subPriField,
+ SubTableFields: subTableFields,
+ ListFields: listFields,
+ DetailFields: detailFields,
+ DictFields: dictFields,
+ IsSearch: isSearch,
+ ModelOprMap: modelOprMap,
+ Columns: columns,
+ SubColumns: subColumns,
+ }
+}
+
+// GetTemplatePaths 获取模板路径
+func (tu templateUtil) GetTemplatePaths(genTpl string) []string {
+ tplPaths := []string{
+ "gocode/model.go.tpl",
+ "gocode/schema.go.tpl",
+ "gocode/service.go.tpl",
+ "gocode/route.go.tpl",
+ "gocode/controller.go.tpl",
+ "vue/api.ts.tpl",
+ "vue/edit.vue.tpl",
+ }
+ if genTpl == GenConstants.TplCrud {
+ tplPaths = append(tplPaths, "vue/index.vue.tpl")
+ } else if genTpl == GenConstants.TplTree {
+ tplPaths = append(tplPaths, "vue/index-tree.vue.tpl")
+ }
+ return tplPaths
+}
+
+// Render 渲染模板
+func (tu templateUtil) Render(tplPath string, tplVars TplVars) (res string, e error) {
+ tpl, err := tu.tpl.ParseFiles(path.Join(config.Config.RootPath, tu.basePath, tplPath))
+ if e = response.CheckErr(err, "TemplateUtil.Render ParseFiles err"); e != nil {
+ return "", e
+ }
+ buf := &bytes.Buffer{}
+ err = tpl.ExecuteTemplate(buf, path.Base(tplPath), tplVars)
+ if e = response.CheckErr(err, "TemplateUtil.Render Execute err"); e != nil {
+ return "", e
+ }
+ return buf.String(), nil
+}
+
+// GetGenPath 获取生成路径
+func (tu templateUtil) GetGenPath(table gen.GenTable) string {
+ if table.GenPath == "/" {
+ //return path.Join(config.Config.RootPath, config.GenConfig.GenRootPath)
+ return config.GenConfig.GenRootPath
+ }
+ return table.GenPath
+}
+
+// GetFilePaths 获取生成文件相对路径
+func (tu templateUtil) GetFilePaths(tplCodeMap map[string]string, TableName string) map[string]string {
+ //模板文件对应的输出文件
+ fmtMap := map[string]string{
+ "gocode/model.go.tpl": strings.Join([]string{"server/model/", TableName, ".go"}, ""),
+ "gocode/route.go.tpl": strings.Join([]string{"server/admin/", TableName, "_route.go"}, ""),
+ "gocode/schema.go.tpl": strings.Join([]string{"server/admin/", TableName, "/", TableName, "_schema.go"}, ""), //"server/admin/%s/%s_schema.go"
+ "gocode/service.go.tpl": strings.Join([]string{"server/admin/", TableName, "/", TableName, "_service.go"}, ""), //"server/admin/%s/%s_service.go",
+ // "server/admin/%s_route.go",
+ "gocode/controller.go.tpl": strings.Join([]string{"server/admin/", TableName, "/", TableName, "_ctl.go"}, ""), //"server/admin/%s/%s_ctl.go",
+
+ "vue/api.ts.tpl": strings.Join([]string{"admin/src/api/", TableName, ".ts"}, ""), // "admin/src/api/%s.ts",
+ "vue/edit.vue.tpl": strings.Join([]string{"admin/src/views/", TableName, "/edit.vue"}, ""), // "admin/src/views/%s/edit.vue",
+ "vue/index.vue.tpl": strings.Join([]string{"admin/src/views/", TableName, "/index.vue"}, ""), // "admin/src/views/%s/index.vue",
+ "vue/index-tree.vue.tpl": strings.Join([]string{"admin/src/views/", TableName, "/index-tree.vue"}, ""), // "admin/src/views/%s/index-tree.vue",
+ }
+ filePath := make(map[string]string)
+ for tplPath, tplCode := range tplCodeMap {
+ file := fmtMap[tplPath]
+ filePath[file] = tplCode
+ }
+ return filePath
+}
+
+// GenCodeFiles 生成代码文件
+func (tu templateUtil) GenCodeFiles(tplCodeMap map[string]string, TableName string, basePath string) error {
+ filePaths := tu.GetFilePaths(tplCodeMap, TableName)
+ for file, tplCode := range filePaths {
+ filePath := path.Join(basePath, file)
+ dir := path.Dir(filePath)
+ if !util.ToolsUtil.IsFileExist(dir) {
+ err := os.MkdirAll(dir, 0755)
+ if err != nil {
+ return response.CheckErr(err, "TemplateUtil.GenCodeFiles MkdirAll err")
+ }
+ }
+ err := os.WriteFile(filePath, []byte(tplCode), 0644)
+ if err != nil {
+ return response.CheckErr(err, "TemplateUtil.GenCodeFiles WriteFile err")
+ }
+ }
+ return nil
+}
+
+func addFileToZip(zipWriter *zip.Writer, file zFile) error {
+ header := &zip.FileHeader{
+ Name: file.Name,
+ Method: zip.Deflate,
+ }
+ writer, err := zipWriter.CreateHeader(header)
+ if err != nil {
+ return response.CheckErr(err, "TemplateUtil.addFileToZip CreateHeader err")
+ }
+ _, err = io.WriteString(writer, file.Body)
+ if err != nil {
+ return response.CheckErr(err, "TemplateUtil.addFileToZip WriteString err")
+ }
+ return nil
+}
+
+// GenZip 生成代码压缩包
+func (tu templateUtil) GenZip(zipWriter *zip.Writer, tplCodeMap map[string]string, TableName string) error {
+ filePaths := tu.GetFilePaths(tplCodeMap, TableName)
+ files := make([]zFile, 0)
+ for file, tplCode := range filePaths {
+ files = append(files, zFile{
+ Name: file,
+ Body: tplCode,
+ })
+ }
+ for _, file := range files {
+ err := addFileToZip(zipWriter, file)
+ if err != nil {
+ return response.CheckErr(err, "TemplateUtil.GenZip zipFiles err")
+ }
+ }
+ return nil
+}
diff --git a/server/generator/tpl_utils/utils.go b/server/generator/tpl_utils/utils.go
new file mode 100644
index 0000000..db15596
--- /dev/null
+++ b/server/generator/tpl_utils/utils.go
@@ -0,0 +1,214 @@
+package tpl_utils
+
+import (
+ "strconv"
+ "strings"
+ "time"
+ "x_admin/config"
+ "x_admin/model/gen"
+ "x_admin/util"
+
+ "gorm.io/gorm"
+)
+
+var GenUtil = genUtil{}
+
+// genUtil 代码生成工具
+type genUtil struct{}
+
+// GetDbTablesQuery 查询库中的数据表
+func (gu genUtil) GetDbTablesQuery(db *gorm.DB, tableName string, tableComment string) *gorm.DB {
+ whereStr := ""
+ if tableName != "" {
+ whereStr += `and lower(table_name) like lower("%` + tableName + `%")`
+ }
+ if tableComment != "" {
+ whereStr += `and lower(table_comment) like lower("%` + tableComment + `%")`
+ }
+ query := db.Table("information_schema.tables").Where(
+ `table_schema = (SELECT database())
+ AND table_name NOT LIKE "qrtz_%"
+ AND table_name NOT LIKE "gen_%"
+ AND table_name NOT IN (select table_name from x_gen_table) ` + whereStr).Select(
+ "table_name, table_comment, create_time, update_time")
+ return query
+}
+
+// GetDbTablesQueryByNames 根据表名集查询表
+func (gu genUtil) GetDbTablesQueryByNames(db *gorm.DB, tableNames []string) *gorm.DB {
+ query := db.Table("information_schema.tables").Where(
+ `table_schema = (SELECT database())
+ AND table_name NOT LIKE "qrtz_%"
+ AND table_name NOT LIKE "gen_%"
+ AND table_name IN ?`, tableNames).Select(
+ "table_name, table_comment, create_time, update_time")
+ return query
+}
+
+// GetDbTableColumnsQueryByName 根据表名查询列信息
+func (gu genUtil) GetDbTableColumnsQueryByName(db *gorm.DB, tableName string) *gorm.DB {
+ query := db.Table("information_schema.columns").Where(
+ `table_schema = (SELECT database())
+ AND table_name = ?`, tableName).Order("ordinal_position").Select(
+ `column_name,
+ (CASE WHEN (is_nullable = "no" && column_key != "PRI") THEN "1" ELSE NULL END) AS is_required,
+ (CASE WHEN column_key = "PRI" THEN "1" ELSE "0" END) AS is_pk,
+ ordinal_position AS sort, column_comment,
+ (CASE WHEN extra = "auto_increment" THEN "1" ELSE "0" END) AS is_increment, column_type`)
+ return query
+}
+
+// InitTable 初始化表
+func (gu genUtil) InitTable(table gen.GenTable) gen.GenTable {
+ return gen.GenTable{
+ TableName: table.TableName,
+ TableComment: table.TableComment,
+ AuthorName: "",
+ EntityName: gu.ToClassName(table.TableName),
+ ModuleName: gu.ToModuleName(table.TableName),
+ FunctionName: strings.Replace(table.TableComment, "表", "", -1),
+ CreateTime: time.Now().Unix(),
+ UpdateTime: time.Now().Unix(),
+ }
+}
+
+// InitColumn 初始化字段列
+func (gu genUtil) InitColumn(tableId uint, column gen.GenTableColumn) gen.GenTableColumn {
+ columnType := gu.GetDbType(column.ColumnType)
+ columnLen := gu.GetColumnLength(column.ColumnType)
+ col := gen.GenTableColumn{
+ TableID: tableId,
+ ColumnName: column.ColumnName,
+ ColumnComment: column.ColumnComment,
+ ColumnType: columnType,
+ ColumnLength: columnLen,
+ GoField: column.ColumnName,
+ GoType: GoConstants.TypeString,
+ QueryType: GenConstants.QueryEq,
+ Sort: column.Sort,
+ IsPk: column.IsPk,
+ IsIncrement: column.IsIncrement,
+ IsRequired: column.IsRequired,
+ CreateTime: time.Now().Unix(),
+ UpdateTime: time.Now().Unix(),
+ }
+ if util.ToolsUtil.Contains(append(SqlConstants.ColumnTypeStr, SqlConstants.ColumnTypeText...), columnType) {
+ //文本域组
+ if columnLen >= 500 || util.ToolsUtil.Contains(SqlConstants.ColumnTypeText, columnType) {
+ col.HtmlType = HtmlConstants.HtmlTextarea
+ } else {
+ col.HtmlType = HtmlConstants.HtmlInput
+ }
+ } else if util.ToolsUtil.Contains(SqlConstants.ColumnTypeTime, columnType) {
+ //日期字段
+ col.GoType = GoConstants.TypeDate
+ col.HtmlType = HtmlConstants.HtmlDatetime
+ } else if util.ToolsUtil.Contains(SqlConstants.ColumnTimeName, col.ColumnName) {
+ //时间字段
+ col.GoType = GoConstants.TypeDate
+ col.HtmlType = HtmlConstants.HtmlDatetime
+ } else if util.ToolsUtil.Contains(SqlConstants.ColumnTypeNumber, columnType) {
+ //数字字段
+ col.HtmlType = HtmlConstants.HtmlInput
+ if strings.Contains(columnType, ",") {
+ col.GoType = GoConstants.TypeFloat
+ } else {
+ col.GoType = GoConstants.TypeInt
+ }
+ }
+ //非必填字段
+ if util.ToolsUtil.Contains(SqlConstants.ColumnNameNotEdit, col.ColumnName) {
+ col.IsRequired = 0
+ }
+ //需插入字段
+ if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotAdd, col.ColumnName) {
+ col.IsInsert = GenConstants.Require
+ }
+ //需编辑字段
+ if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotEdit, col.ColumnName) {
+ col.IsEdit = GenConstants.Require
+ col.IsRequired = GenConstants.Require
+ }
+ //需列表字段
+ if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotList, col.ColumnName) && col.IsPk == 0 {
+ col.IsList = GenConstants.Require
+ }
+ //需查询字段
+ if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotQuery, col.ColumnName) && col.IsPk == 0 {
+ col.IsQuery = GenConstants.Require
+ }
+ lowerColName := strings.ToLower(col.ColumnName)
+ //模糊查字段
+ if strings.HasSuffix(lowerColName, "name") || util.ToolsUtil.Contains([]string{"title", "mobile"}, lowerColName) {
+ col.QueryType = GenConstants.QueryLike
+ }
+ //根据字段设置
+ if strings.HasSuffix(lowerColName, "status") || util.ToolsUtil.Contains([]string{"is_show", "is_disable"}, lowerColName) {
+ //状态字段设置单选框
+ col.HtmlType = HtmlConstants.HtmlRadio
+ } else if strings.HasSuffix(lowerColName, "type") || strings.HasSuffix(lowerColName, "sex") {
+ //类型&性别字段设置下拉框
+ col.HtmlType = HtmlConstants.HtmlSelect
+ } else if strings.HasSuffix(lowerColName, "image") {
+ //图片字段设置图片上传
+ col.HtmlType = HtmlConstants.HtmlImageUpload
+ } else if strings.HasSuffix(lowerColName, "file") {
+ //文件字段设置文件上传
+ col.HtmlType = HtmlConstants.HtmlFileUpload
+ } else if strings.HasSuffix(lowerColName, "content") {
+ //富文本字段设置富文本编辑器
+ col.HtmlType = HtmlConstants.HtmlEditor
+ }
+ return col
+}
+
+// ToModuleName 表名转业务名
+func (gu genUtil) ToModuleName(name string) string {
+ names := strings.Split(name, config.Config.DbTablePrefix)
+ return names[len(names)-1]
+}
+
+// ToClassName 表名转类名
+func (gu genUtil) ToClassName(name string) string {
+ tablePrefix := config.Config.DbTablePrefix
+ name = strings.TrimPrefix(name, tablePrefix)
+ // if config.GenConfig.IsRemoveTablePrefix && tablePrefix != "" {
+ // if strings.HasPrefix(name, tablePrefix) {
+ // name = name[len(tablePrefix):]
+ // }
+ // }
+ return util.StringUtil.ToCamelCase(name)
+}
+
+// GetDbType 获取数据库类型字段
+func (gu genUtil) GetDbType(columnType string) string {
+ index := strings.IndexRune(columnType, '(')
+ if index < 0 {
+ return columnType
+ }
+ return columnType[:index]
+}
+
+// GetColumnLength 获取字段长度
+func (gu genUtil) GetColumnLength(columnType string) int {
+ index := strings.IndexRune(columnType, '(')
+ if index < 0 {
+ return 0
+ }
+ length, err := strconv.Atoi(columnType[index+1 : strings.IndexRune(columnType, ')')])
+ if err != nil {
+ return 0
+ }
+ return length
+}
+
+// GetTablePriCol 获取主键列名称
+func (gu genUtil) GetTablePriCol(columns []gen.GenTableColumn) (res gen.GenTableColumn) {
+ for _, col := range columns {
+ if col.IsPk == 1 {
+ res = col
+ return
+ }
+ }
+ return
+}
diff --git a/server/go.mod b/server/go.mod
new file mode 100644
index 0000000..d3cd30f
--- /dev/null
+++ b/server/go.mod
@@ -0,0 +1,74 @@
+module x_admin
+
+go 1.21
+
+require (
+ github.com/fatih/structs v1.1.0
+ github.com/gin-contrib/cors v1.4.0
+ github.com/gin-gonic/gin v1.9.1
+ github.com/go-redis/redis/v9 v9.0.0-rc.2
+ github.com/google/uuid v1.4.0
+ github.com/jinzhu/copier v0.4.0
+ github.com/shirou/gopsutil v3.21.11+incompatible
+ github.com/spf13/viper v1.17.0
+ github.com/ua-parser/uap-go v0.0.0-20230823213814-f77b3e91e9dc
+ go.uber.org/zap v1.26.0
+ gorm.io/driver/mysql v1.5.2
+ gorm.io/gorm v1.25.5
+)
+
+require (
+ github.com/bytedance/sonic v1.10.2 // indirect
+ github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
+ github.com/chenzhuoyu/iasm v0.9.1 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+ github.com/frankban/quicktest v1.14.6 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+ github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/go-playground/locales v0.14.1 // indirect
+ github.com/go-playground/universal-translator v0.18.1 // indirect
+ github.com/go-playground/validator/v10 v10.16.0 // indirect
+ github.com/go-sql-driver/mysql v1.7.1 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
+ github.com/google/go-cmp v0.6.0 // indirect
+ github.com/hashicorp/golang-lru v1.0.2 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.6 // indirect
+ github.com/leodido/go-urn v1.2.4 // indirect
+ github.com/magiconair/properties v1.8.7 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/pelletier/go-toml/v2 v2.1.0 // indirect
+ github.com/rogpeppe/go-internal v1.11.0 // indirect
+ github.com/sagikazarmark/locafero v0.3.0 // indirect
+ github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+ github.com/sourcegraph/conc v0.3.0 // indirect
+ github.com/spf13/afero v1.10.0 // indirect
+ github.com/spf13/cast v1.5.1 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ github.com/subosito/gotenv v1.6.0 // indirect
+ github.com/tklauser/go-sysconf v0.3.12 // indirect
+ github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+ github.com/ugorji/go/codec v1.2.11 // indirect
+ github.com/yusufpapurcu/wmi v1.2.3 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
+ golang.org/x/arch v0.6.0 // indirect
+ golang.org/x/crypto v0.15.0 // indirect
+ golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
+ golang.org/x/net v0.18.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+ gopkg.in/ini.v1 v1.67.0 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/server/go.sum b/server/go.sum
new file mode 100644
index 0000000..efdd1d4
--- /dev/null
+++ b/server/go.sum
@@ -0,0 +1,647 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
+cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
+cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
+github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
+github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
+github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
+github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
+github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
+github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
+github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
+github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
+github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-redis/redis/v9 v9.0.0-rc.2 h1:IN1eI8AvJJeWHjMW/hlFAv2sAfvTun2DVksDDJ3a6a0=
+github.com/go-redis/redis/v9 v9.0.0-rc.2/go.mod h1:cgBknjwcBJa2prbnuHH/4k/Mlj4r0pWNV2HBanHujfY=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
+github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
+github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
+github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
+github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
+github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
+github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
+github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
+github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
+github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
+github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
+github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
+github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
+github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
+github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
+github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
+github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ua-parser/uap-go v0.0.0-20230823213814-f77b3e91e9dc h1:iT5lwxf894PiMq7cnMMQg/7VOD1pxmu//gQuHWAFy4s=
+github.com/ua-parser/uap-go v0.0.0-20230823213814-f77b3e91e9dc/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E=
+github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
+github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
+golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
+golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w=
+golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
+golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
+gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
+gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
+gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/server/main.go b/server/main.go
new file mode 100644
index 0000000..8046ebf
--- /dev/null
+++ b/server/main.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "log"
+ "net/http"
+ "strconv"
+ "time"
+ "x_admin/config"
+ "x_admin/core"
+ "x_admin/core/response"
+ "x_admin/middleware"
+ "x_admin/routers"
+
+ "github.com/gin-gonic/gin"
+)
+
+// initRouter 初始化router
+func initRouter() *gin.Engine {
+ // 初始化gin
+ gin.SetMode(config.Config.GinMode)
+ router := gin.New()
+ // 设置静态路径
+ router.Static(config.Config.PublicPrefix, config.Config.UploadDirectory)
+ router.Static(config.Config.StaticPath, config.Config.StaticDirectory)
+ // 设置中间件
+ router.Use(gin.Logger(), middleware.Cors(), middleware.ErrorRecover())
+ // 演示模式
+ if config.Config.DisallowModify {
+ router.Use(middleware.ShowMode())
+ }
+ // 特殊异常处理
+ router.NoMethod(response.NoMethod)
+ router.NoRoute(response.NoRoute)
+ // 注册路由
+ group := router.Group("/api")
+
+ routers.RegisterGroup(group)
+
+ return router
+}
+
+// initServer 初始化server
+func initServer(router *gin.Engine) *http.Server {
+ return &http.Server{
+ Addr: ":" + strconv.Itoa(config.Config.ServerPort),
+ Handler: router,
+ ReadTimeout: 10 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ MaxHeaderBytes: 1 << 20,
+ }
+}
+
+func main() {
+ // 刷新日志缓冲
+ defer core.Logger.Sync()
+ // 程序结束前关闭数据库连接
+ if core.GetDB() != nil {
+ db, _ := core.GetDB().DB()
+ defer db.Close()
+ }
+ // 初始化DI
+ // initDI()
+ // 初始化router
+ router := initRouter()
+ // 初始化server
+ s := initServer(router)
+ // 运行服务
+ log.Fatalln(s.ListenAndServe().Error())
+}
diff --git a/server/middleware/auth.go b/server/middleware/auth.go
new file mode 100644
index 0000000..14ab426
--- /dev/null
+++ b/server/middleware/auth.go
@@ -0,0 +1,149 @@
+package middleware
+
+import (
+ "strconv"
+ "strings"
+ "x_admin/admin/system/admin"
+ "x_admin/admin/system/role"
+ "x_admin/config"
+ "x_admin/core"
+ "x_admin/core/response"
+ sysModel "x_admin/model/system"
+ "x_admin/util"
+
+ "github.com/gin-gonic/gin"
+)
+
+var (
+ permSrv = role.NewSystemAuthPermService(core.GetDB())
+ roleSrv = role.NewSystemAuthRoleService(core.GetDB(), permSrv)
+ adminSrv = admin.NewSystemAuthAdminService(core.GetDB(), permSrv, roleSrv)
+)
+
+// TokenAuth Token认证中间件
+func TokenAuth() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ // 路由转权限
+ auths := strings.ReplaceAll(strings.Replace(c.Request.URL.Path, "/api/", "", 1), "/", ":")
+
+ // 免登录接口
+ if util.ToolsUtil.Contains(config.AdminConfig.NotLoginUri, auths) {
+ c.Next()
+ return
+ }
+
+ // Token是否为空
+ token := c.Request.Header.Get("token")
+ if token == "" {
+ response.Fail(c, response.TokenEmpty)
+ c.Abort()
+ return
+ }
+
+ // Token是否过期
+ token = config.AdminConfig.BackstageTokenKey + token
+ existCnt := util.RedisUtil.Exists(token)
+ if existCnt < 0 {
+ response.Fail(c, response.SystemError)
+ c.Abort()
+ return
+ } else if existCnt == 0 {
+ response.Fail(c, response.TokenInvalid)
+ c.Abort()
+ return
+ }
+
+ // 用户信息缓存
+ uidStr := util.RedisUtil.Get(token)
+ var uid uint
+ if uidStr != "" {
+ i, err := strconv.ParseUint(uidStr, 10, 32)
+ if err != nil {
+ core.Logger.Errorf("TokenAuth Atoi uidStr err: err=[%+v]", err)
+ response.Fail(c, response.TokenInvalid)
+ c.Abort()
+ return
+ }
+ uid = uint(i)
+ }
+
+ if !util.RedisUtil.HExists(config.AdminConfig.BackstageManageKey, uidStr) {
+ err := adminSrv.CacheAdminUserByUid(uid)
+ if err != nil {
+ core.Logger.Errorf("TokenAuth CacheAdminUserByUid err: err=[%+v]", err)
+ response.Fail(c, response.SystemError)
+ c.Abort()
+ return
+ }
+ }
+
+ // 校验用户被删除
+ var mapping sysModel.SystemAuthAdmin
+ err := util.ToolsUtil.JsonToObj(util.RedisUtil.HGet(config.AdminConfig.BackstageManageKey, uidStr), &mapping)
+ if err != nil {
+ core.Logger.Errorf("TokenAuth Unmarshal err: err=[%+v]", err)
+ response.Fail(c, response.SystemError)
+ c.Abort()
+ return
+ }
+ if mapping.IsDelete == 1 {
+ util.RedisUtil.Del(token)
+ util.RedisUtil.HDel(config.AdminConfig.BackstageManageKey + uidStr)
+ response.Fail(c, response.TokenInvalid)
+ c.Abort()
+ return
+ }
+
+ // 校验用户被禁用
+ if mapping.IsDisable == 1 {
+ response.Fail(c, response.LoginDisableError)
+ c.Abort()
+ return
+ }
+
+ // 令牌剩余30分钟自动续签
+ if util.RedisUtil.TTL(token) < 1800 {
+ util.RedisUtil.Expire(token, 7200)
+ }
+
+ // 单次请求信息保存
+ c.Set(config.AdminConfig.ReqAdminIdKey, uid)
+ c.Set(config.AdminConfig.ReqRoleIdKey, mapping.Role)
+ c.Set(config.AdminConfig.ReqUsernameKey, mapping.Username)
+ c.Set(config.AdminConfig.ReqNicknameKey, mapping.Nickname)
+
+ // 免权限验证接口
+ if util.ToolsUtil.Contains(config.AdminConfig.NotAuthUri, auths) || uid == 1 {
+ c.Next()
+ return
+ }
+
+ // 校验角色的权限,redis没有就重新查询
+ roleId := mapping.Role
+ if !util.RedisUtil.HExists(config.AdminConfig.BackstageRolesKey, roleId) {
+ i, err := strconv.ParseUint(roleId, 10, 32)
+ if err != nil {
+ core.Logger.Errorf("TokenAuth Atoi roleId err: err=[%+v]", err)
+ response.Fail(c, response.SystemError)
+ c.Abort()
+ return
+ }
+ err = permSrv.CacheRoleMenusByRoleId(uint(i))
+ if err != nil {
+ core.Logger.Errorf("TokenAuth CacheRoleMenusByRoleId err: err=[%+v]", err)
+ response.Fail(c, response.SystemError)
+ c.Abort()
+ return
+ }
+ }
+
+ // 验证是否有权限操作
+ menus := util.RedisUtil.HGet(config.AdminConfig.BackstageRolesKey, roleId)
+ if !(menus != "" && util.ToolsUtil.Contains(strings.Split(menus, ","), auths)) {
+ response.Fail(c, response.NoPermission)
+ c.Abort()
+ return
+ }
+ c.Next()
+ }
+}
diff --git a/server/middleware/cors.go b/server/middleware/cors.go
new file mode 100644
index 0000000..aafbeee
--- /dev/null
+++ b/server/middleware/cors.go
@@ -0,0 +1,17 @@
+package middleware
+
+import (
+ "github.com/gin-contrib/cors"
+ "github.com/gin-gonic/gin"
+ "time"
+)
+
+//Cors CORS(跨域资源共享)中间件
+func Cors() gin.HandlerFunc {
+ return cors.New(cors.Config{
+ AllowOrigins: []string{"*"},
+ AllowHeaders: []string{"*"},
+ AllowMethods: []string{"OPTIONS", "GET", "POST", "POST", "DELETE", "PUT"},
+ MaxAge: 1 * time.Hour,
+ })
+}
diff --git a/server/middleware/error.go b/server/middleware/error.go
new file mode 100644
index 0000000..f797b34
--- /dev/null
+++ b/server/middleware/error.go
@@ -0,0 +1,37 @@
+package middleware
+
+import (
+ "runtime/debug"
+ "x_admin/core"
+ "x_admin/core/response"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+// ErrorRecover 异常恢复中间件
+func ErrorRecover() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch v := r.(type) {
+ // 自定义类型
+ case response.RespType:
+ core.Logger.WithOptions(zap.AddCallerSkip(2)).Warnf(
+ "Request Fail by recover: url=[%s], resp=[%+v]", c.Request.URL.Path, v)
+ var data interface{}
+ if v.Data() == nil {
+ data = []string{}
+ }
+ response.Result(c, v, data)
+ // 其他类型
+ default:
+ core.Logger.Errorf("stacktrace from panic: %+v\n%s", r, string(debug.Stack()))
+ response.Fail(c, response.SystemError)
+ }
+ c.Abort()
+ }
+ }()
+ c.Next()
+ }
+}
diff --git a/server/middleware/log.go b/server/middleware/log.go
new file mode 100644
index 0000000..1e25754
--- /dev/null
+++ b/server/middleware/log.go
@@ -0,0 +1,129 @@
+package middleware
+
+import (
+ "fmt"
+ "net/url"
+ "strings"
+ "time"
+ "x_admin/config"
+ "x_admin/core"
+ "x_admin/core/response"
+ "x_admin/model/system"
+ "x_admin/util"
+
+ "github.com/gin-gonic/gin"
+ "github.com/gin-gonic/gin/binding"
+ "go.uber.org/zap"
+)
+
+// requestType 请求参数类
+type requestType string
+
+const (
+ RequestFile requestType = "file" // 文件类型
+ RequestDefault requestType = "default" // 默认数据类型
+)
+
+// RecordLog 记录系统日志信息中间件
+func RecordLog(title string, reqTypes ...requestType) gin.HandlerFunc {
+ reqType := RequestDefault
+ if len(reqTypes) > 0 {
+ reqType = reqTypes[0]
+ }
+ return func(c *gin.Context) {
+ // 开始时间
+ startTime := time.Now().UnixMilli()
+ // 异常信息
+ errStr := ""
+ var status uint8 = 1 // 1=成功, 2=失败
+ args := ""
+ // 请求方式
+ reqMethod := c.Request.Method
+ // 获取请求参数
+ if reqMethod == "POST" {
+ // POST请求
+ if reqType == RequestFile {
+ // 文件类型
+ var filenames []string
+ form, err := c.MultipartForm()
+ // 校验错误
+ if response.IsFailWithResp(c, response.CheckErr(err, "RecordLog MultipartForm err")) {
+ c.Abort()
+ return
+ }
+ // 获取文件列表
+ for _, files := range form.File {
+ for _, file := range files {
+ filenames = append(filenames, file.Filename)
+ }
+ }
+ args = strings.Join(filenames, ",")
+ } else {
+ //默认类型
+ var formParams map[string]interface{}
+ err := c.ShouldBindBodyWith(&formParams, binding.JSON)
+ if err == nil {
+ val, err := util.ToolsUtil.ObjToJson(&formParams)
+ // 校验错误
+ if response.IsFailWithResp(c, response.CheckErr(err, "RecordLog POST Marshal err")) {
+ c.Abort()
+ return
+ }
+ args = val
+ }
+ }
+ } else if reqMethod == "GET" {
+ // GET请求
+ query := c.Request.URL.RawQuery
+ if query != "" {
+ args, _ = url.QueryUnescape(query)
+ }
+ }
+ // 处理异常
+ defer func() {
+ if r := recover(); r != nil {
+ errStr = fmt.Sprintf("%+v", r)
+ status = 2
+ // 结束时间
+ endTime := time.Now().UnixMilli()
+ // 执行时间(毫秒)
+ taskTime := endTime - startTime
+ // 获取当前的用户
+ adminId := config.AdminConfig.GetAdminId(c)
+ urlPath := c.Request.URL.Path
+ ip := c.ClientIP()
+ method := c.HandlerName()
+ err := core.GetDB().Create(&system.SystemLogOperate{
+ AdminId: adminId, Type: reqMethod, Title: title, Ip: ip,
+ Url: urlPath, Method: method, Args: args, Error: errStr, Status: status,
+ StartTime: startTime / 1000, EndTime: endTime / 1000, TaskTime: taskTime,
+ }).Error
+ response.CheckErr(err, "RecordLog recover Create err")
+ core.Logger.WithOptions(zap.AddCallerSkip(2)).Infof(
+ "RecordLog recover: err=[%+v]", r)
+ panic(r)
+ }
+ }()
+ // 执行方法
+ c.Next()
+ if len(c.Errors) > 0 {
+ errStr = c.Errors.String()
+ status = 2
+ }
+ // 结束时间
+ endTime := time.Now().UnixMilli()
+ // 执行时间(毫秒)
+ taskTime := endTime - startTime
+ // 获取当前的用户
+ adminId := config.AdminConfig.GetAdminId(c)
+ urlPath := c.Request.URL.Path
+ ip := c.ClientIP()
+ method := c.HandlerName()
+ err := core.GetDB().Create(&system.SystemLogOperate{
+ AdminId: adminId, Type: reqMethod, Title: title, Ip: ip,
+ Url: urlPath, Method: method, Args: args, Error: errStr, Status: status,
+ StartTime: startTime / 1000, EndTime: endTime / 1000, TaskTime: taskTime,
+ }).Error
+ response.CheckErr(err, "RecordLog Create err")
+ }
+}
diff --git a/server/middleware/show.go b/server/middleware/show.go
new file mode 100644
index 0000000..4036243
--- /dev/null
+++ b/server/middleware/show.go
@@ -0,0 +1,24 @@
+package middleware
+
+import (
+ "strings"
+ "x_admin/config"
+ "x_admin/core/response"
+ "x_admin/util"
+
+ "github.com/gin-gonic/gin"
+)
+
+// ShowMode 演示模式中间件,演示模式禁止POST
+func ShowMode() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ // 路由转权限
+ auths := strings.ReplaceAll(strings.Replace(c.Request.URL.Path, "/api/", "", 1), "/", ":")
+ // 禁止修改操作 (演示功能,限制POST请求)
+ if c.Request.Method == "POST" && !util.ToolsUtil.Contains(config.AdminConfig.ShowWhitelistUri, auths) {
+ response.FailWithMsg(c, response.NoPermission, "演示环境不支持修改数据,请下载源码本地部署体验!")
+ c.Abort()
+ return
+ }
+ }
+}
diff --git a/server/model/article_collect.go b/server/model/article_collect.go
new file mode 100644
index 0000000..67043e5
--- /dev/null
+++ b/server/model/article_collect.go
@@ -0,0 +1,12 @@
+package model
+
+//ArticleCollect 文章收藏实体
+type ArticleCollect struct {
+ Id int `gorm:"primarykey;comment:'主键'"` // 主键
+ UserId int `gorm:"comment:'用户ID'"` // 用户ID
+ ArticleId int `gorm:"comment:'文章ID'"` // 文章ID
+ IsDelete int `gorm:"comment:'是否删除'"` // 是否删除
+ CreateTime int64 `gorm:"comment:'创建时间'"` // 创建时间
+ UpdateTime int64 `gorm:"comment:'更新时间'"` // 更新时间
+ DeleteTime int64 `gorm:"comment:'是否删除'"` // 是否删除
+}
diff --git a/server/model/common/album.go b/server/model/common/album.go
new file mode 100644
index 0000000..07ad2c8
--- /dev/null
+++ b/server/model/common/album.go
@@ -0,0 +1,30 @@
+package common
+
+//Album 相册实体
+type Album struct {
+ ID uint `gorm:"primarykey;comment:'主键ID'"`
+ Cid uint `gorm:"not null;default:0;comment:'类目ID'"`
+ Aid uint `gorm:"not null;default:0;comment:'管理ID'"`
+ Uid uint `gorm:"not null;default:0;comment:'用户ID'"`
+ Type int `gorm:"not null;default:10;comment:'文件类型: [10=图片, 20=视频]''"`
+ Name string `gorm:"not null;default:'';comment:'文件名称''"`
+ Uri string `gorm:"not null;comment:'文件路径'"`
+ Ext string `gorm:"not null;default:'';comment:'文件扩展'"`
+ Size int64 `gorm:"not null;default:0;comment:文件大小"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
+
+//AlbumCate 相册分类实体
+type AlbumCate struct {
+ ID uint `gorm:"primarykey;comment:'主键ID'"`
+ Pid uint `gorm:"not null;default:0;comment:'父级ID'"`
+ Type int `gorm:"not null;default:10;comment:'文件类型: [10=图片, 20=视频]''"`
+ Name string `gorm:"not null;default:'';comment:'分类名称''"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
diff --git a/server/model/gen/gen.go b/server/model/gen/gen.go
new file mode 100644
index 0000000..25df580
--- /dev/null
+++ b/server/model/gen/gen.go
@@ -0,0 +1,48 @@
+package gen
+
+//GenTable 代码生成业务实体
+type GenTable struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ TableName string `gorm:"not null;default:'';comment:'表名称''"`
+ TableComment string `gorm:"not null;default:'';comment:'表描述'"`
+ SubTableName string `gorm:"not null;default:'';comment:'关联表名称'"`
+ SubTableFk string `gorm:"not null;default:'';comment:'关联表外键'"`
+ AuthorName string `gorm:"not null;default:'';comment:'作者的名称'"`
+ EntityName string `gorm:"not null;default:'';comment:'实体的名称'"`
+ ModuleName string `gorm:"not null;default:'';comment:'生成模块名'"`
+ FunctionName string `gorm:"not null;default:'';comment:'生成功能名'"`
+ TreePrimary string `gorm:"not null;default:'';comment:'树主键字段'"`
+ TreeParent string `gorm:"not null;default:'';comment:'树父级字段'"`
+ TreeName string `gorm:"not null;default:'';comment:'树显示字段'"`
+ GenTpl string `gorm:"not null;default:'crud';comment:'生成模板方式: [crud=单表, tree=树表]'"`
+ GenType int `gorm:"not null;default:0;comment:'生成代码方式: [0=zip压缩包, 1=自定义路径]'"`
+ GenPath string `gorm:"not null;default:'/';comment:'生成代码路径: [不填默认项目路径]'"`
+ Remarks string `gorm:"not null;default:'';comment:'备注信息'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+}
+
+//GenTableColumn 代码生成表列实体
+type GenTableColumn struct {
+ ID uint `gorm:"primarykey;comment:'列主键'"`
+ TableID uint `gorm:"not null;default:0;comment:'表外键'"`
+ ColumnName string `gorm:"not null;default:'';comment:'列名称'"`
+ ColumnComment string `gorm:"not null;default:'';comment:'列描述'"`
+ ColumnLength int `gorm:"not null;default:0;comment:'列长度'"`
+ ColumnType string `gorm:"not null;default:'';comment:'列类型'"`
+ GoType string `gorm:"not null;default:'';comment:'类型'"`
+ GoField string `gorm:"not null;default:'';comment:'字段名'"`
+ IsPk uint8 `gorm:"not null;default:0;comment:'是否主键: [1=是, 0=否]'"`
+ IsIncrement uint8 `gorm:"not null;default:0;comment:'是否自增: [1=是, 0=否]'"`
+ IsRequired uint8 `gorm:"not null;default:0;comment:'是否必填: [1=是, 0=否]'"`
+ IsInsert uint8 `gorm:"not null;default:0;comment:'是否为插入字段: [1=是, 0=否]'"`
+ IsEdit uint8 `gorm:"not null;default:0;comment:'是否编辑字段: [1=是, 0=否]'"`
+ IsList uint8 `gorm:"not null;default:0;comment:'是否列表字段: [1=是, 0=否]'"`
+ IsQuery uint8 `gorm:"not null;default:0;comment:'是否查询字段: [1=是, 0=否]'"`
+ QueryType string `gorm:"not null;default:'=';comment:'查询方式: [等于、不等于、大于、小于、范围]'"`
+ HtmlType string `gorm:"not null;default:'';comment:'显示类型: [文本框、文本域、下拉框、复选框、单选框、日期控件]'"`
+ DictType string `gorm:"not null;default:'';comment:'字典类型'"`
+ Sort int `gorm:"not null;default:0;comment:'排序编号'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+}
diff --git a/server/model/setting/dict_data.go b/server/model/setting/dict_data.go
new file mode 100644
index 0000000..7cffe98
--- /dev/null
+++ b/server/model/setting/dict_data.go
@@ -0,0 +1,16 @@
+package setting
+
+//DictData 字典数据实体
+type DictData struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ TypeId uint `gorm:"not null;default:0;comment:'类型'"`
+ Name string `gorm:"not null;default:'';comment:'键名''"`
+ Value string `gorm:"not null;default:'';comment:'数值'"`
+ Remark string `gorm:"not null;default:'';comment:'备注'"`
+ Sort uint16 `gorm:"not null;default:0;comment:'排序'"`
+ Status uint8 `gorm:"not null;default:1;comment:'字典状态: 0=停用, 1=正常'"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
diff --git a/server/model/setting/dict_type.go b/server/model/setting/dict_type.go
new file mode 100644
index 0000000..f066482
--- /dev/null
+++ b/server/model/setting/dict_type.go
@@ -0,0 +1,14 @@
+package setting
+
+//DictType 字典类型实体
+type DictType struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ DictName string `gorm:"not null;default:'';comment:'字典名称''"`
+ DictType string `gorm:"not null;default:'';comment:'字典类型'"`
+ DictRemark string `gorm:"not null;default:'';comment:'字典备注'"`
+ DictStatus uint8 `gorm:"not null;default:1;comment:'字典状态: 0=停用, 1=正常'"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
diff --git a/server/model/system/system.go b/server/model/system/system.go
new file mode 100644
index 0000000..30c352f
--- /dev/null
+++ b/server/model/system/system.go
@@ -0,0 +1,130 @@
+package system
+
+//SystemConfig 系统配置实体
+type SystemConfig struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ Type string `gorm:"default:'';comment:'类型''"`
+ Name string `gorm:"not null;default:'';comment:'键'"`
+ Value string `gorm:"type:text;not null;default:'';comment:'值'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+}
+
+//SystemAuthAdmin 系统管理员实体
+type SystemAuthAdmin struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ DeptId uint `gorm:"not null;default:0;comment:'部门ID'"`
+ PostId uint `gorm:"not null;default:0;comment:'岗位ID'"`
+ Username string `gorm:"not null;default:'';comment:'用户账号''"`
+ Nickname string `gorm:"not null;default:'';comment:'用户昵称'"`
+ Password string `gorm:"not null;default:'';comment:'用户密码'"`
+ Avatar string `gorm:"not null;default:'';comment:'用户头像'"`
+ Role string `gorm:"not null;default:'';comment:'角色主键'"`
+ Salt string `gorm:"not null;default:'';comment:'加密盐巴'"`
+ Sort uint16 `gorm:"not null;default:0;comment:'排序编号'"`
+ IsMultipoint uint8 `gorm:"not null;default:0;comment:'多端登录: 0=否, 1=是''"`
+ IsDisable uint8 `gorm:"not null;default:0;comment:'是否禁用: 0=否, 1=是'"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ LastLoginIp string `gorm:"not null;default:'';comment:'最后登录IP'"`
+ LastLoginTime int64 `gorm:"not null;default:0;comment:'最后登录时间'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
+
+//SystemAuthMenu 系统菜单实体
+type SystemAuthMenu struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ Pid uint `gorm:"not null;default:0;comment:'上级菜单'"`
+ MenuType string `gorm:"not null;default:'';comment:'权限类型: M=目录,C=菜单,A=按钮''"`
+ MenuName string `gorm:"not null;default:'';comment:'菜单名称'"`
+ MenuIcon string `gorm:"not null;default:'';comment:'菜单图标'"`
+ MenuSort uint16 `gorm:"not null;default:0;comment:'菜单排序'"`
+ Perms string `gorm:"not null;default:'';comment:'权限标识'"`
+ Paths string `gorm:"not null;default:'';comment:'路由地址'"`
+ Component string `gorm:"not null;default:'';comment:'前端组件'"`
+ Selected string `gorm:"not null;default:'';comment:'选中路径'"`
+ Params string `gorm:"not null;default:'';comment:'路由参数'"`
+ IsCache uint8 `gorm:"not null;default:0;comment:'是否缓存: 0=否, 1=是''"`
+ IsShow uint8 `gorm:"not null;default:1;comment:'是否显示: 0=否, 1=是'"`
+ IsDisable uint8 `gorm:"not null;default:0;comment:'是否禁用: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+}
+
+//SystemAuthPerm 系统角色菜单实体
+type SystemAuthPerm struct {
+ ID string `gorm:"primarykey;comment:'主键'"`
+ RoleId uint `gorm:"not null;default:0;comment:'角色ID'"`
+ MenuId uint `gorm:"not null;default:0;comment:'菜单ID'"`
+}
+
+//SystemAuthRole 系统角色实体
+type SystemAuthRole struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ Name string `gorm:"not null;default:'';comment:'角色名称''"`
+ Remark string `gorm:"not null;default:'';comment:'备注信息'"`
+ IsDisable uint8 `gorm:"not null;default:0;comment:'是否禁用: 0=否, 1=是'"`
+ Sort uint16 `gorm:"not null;default:0;comment:'角色排序'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+}
+
+//SystemAuthDept 系统部门实体
+type SystemAuthDept struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ Pid uint `gorm:"not null;default:0;comment:'上级主键'"`
+ Name string `gorm:"not null;default:'';comment:'部门名称''"`
+ Duty string `gorm:"not null;default:'';comment:'负责人名'"`
+ Mobile string `gorm:"not null;default:'';comment:'联系电话'"`
+ Sort uint16 `gorm:"not null;default:0;comment:'排序编号'"`
+ IsStop uint8 `gorm:"not null;default:0;comment:'是否停用: 0=否, 1=是'"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
+
+//SystemAuthPost 系统岗位管理
+type SystemAuthPost struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ Code string `gorm:"not null;default:'';comment:'岗位编码''"`
+ Name string `gorm:"not null;default:'';comment:'岗位名称''"`
+ Remarks string `gorm:"not null;default:'';comment:'岗位备注''"`
+ Sort uint16 `gorm:"not null;default:0;comment:'岗位排序'"`
+ IsStop uint8 `gorm:"not null;default:0;comment:'是否停用: 0=否, 1=是'"`
+ IsDelete uint8 `gorm:"not null;default:0;comment:'是否删除: 0=否, 1=是'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+ UpdateTime int64 `gorm:"autoUpdateTime;not null;comment:'更新时间'"`
+ DeleteTime int64 `gorm:"not null;default:0;comment:'删除时间'"`
+}
+
+//SystemLogLogin 系统登录日志实体
+type SystemLogLogin struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ AdminId uint `gorm:"not null;default:0;comment:'管理员ID'"`
+ Username string `gorm:"not null;default:'';comment:'登录账号'"`
+ Ip string `gorm:"not null;default:'';comment:'登录地址'"`
+ Os string `gorm:"not null;default:'';comment:'操作系统'"`
+ Browser string `gorm:"not null;default:'';comment:'浏览器'"`
+ Status uint8 `gorm:"not null;default:0;comment:'操作状态: 1=成功, 0=失败'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+}
+
+//SystemLogOperate 系统操作日志实体
+type SystemLogOperate struct {
+ ID uint `gorm:"primarykey;comment:'主键'"`
+ AdminId uint `gorm:"not null;default:0;comment:'操作人ID'"`
+ Type string `gorm:"not null;default:'';comment:'请求类型: GET/POST/PUT'"`
+ Title string `gorm:"default:'';comment:'操作标题'"`
+ Ip string `gorm:"not null;default:'';comment:'请求IP'"`
+ Url string `gorm:"not null;default:'';comment:'请求接口'"`
+ Method string `gorm:"not null;default:'';comment:'请求方法'"`
+ Args string `gorm:"comment:'请求参数'"`
+ Error string `gorm:"comment:'错误信息'"`
+ Status uint8 `gorm:"not null;default:0;comment:'执行状态: 1=成功, 2=失败'"`
+ StartTime int64 `gorm:"not null;default:0;comment:'开始时间'"`
+ EndTime int64 `gorm:"not null;default:0;comment:'结束时间'"`
+ TaskTime int64 `gorm:"not null;default:0;comment:'执行耗时'"`
+ CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`
+}
diff --git a/server/plugin/storage.go b/server/plugin/storage.go
new file mode 100644
index 0000000..ef6685b
--- /dev/null
+++ b/server/plugin/storage.go
@@ -0,0 +1,134 @@
+package plugin
+
+import (
+ "fmt"
+ "io"
+ "mime/multipart"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+ "x_admin/config"
+ "x_admin/core"
+ "x_admin/core/response"
+ "x_admin/util"
+)
+
+var StorageDriver = storageDriver{}
+
+// UploadFile 文件对象
+type UploadFile struct {
+ Name string // 文件名称
+ Type int // 文件类型
+ Size int64 // 文件大小
+ Ext string // 文件扩展
+ Uri string // 文件路径
+ Path string // 访问地址
+}
+
+// storageDriver 存储引擎
+type storageDriver struct{}
+
+// Upload 根据引擎类型上传文件
+func (sd storageDriver) Upload(file *multipart.FileHeader, folder string, fileType int) (uf *UploadFile, e error) {
+ // TODO: engine默认local
+ if e = sd.checkFile(file, fileType); e != nil {
+ return
+ }
+ key := sd.buildSaveName(file)
+ engine := "local"
+ if engine == "local" {
+ if e = sd.localUpload(file, key, folder); e != nil {
+ return
+ }
+ } else {
+ core.Logger.Errorf("storageDriver.Upload engine err: err=[unsupported engine]")
+ return nil, response.Failed.Make(fmt.Sprintf("engine:%s 暂时不支持", engine))
+ }
+ fileRelPath := path.Join(folder, key)
+ return &UploadFile{
+ Name: file.Filename,
+ Type: fileType,
+ Size: file.Size,
+ Ext: strings.ToLower(strings.Replace(path.Ext(file.Filename), ".", "", 1)),
+ Uri: fileRelPath,
+ Path: util.UrlUtil.ToAbsoluteUrl(fileRelPath),
+ }, nil
+}
+
+// localUpload 本地上传 (临时方法)
+func (sd storageDriver) localUpload(file *multipart.FileHeader, key string, folder string) (e error) {
+ // TODO: 临时方法,后续调整
+ // 映射目录
+ directory := config.Config.UploadDirectory
+ // 打开源文件
+ src, err := file.Open()
+ if err != nil {
+ core.Logger.Errorf("storageDriver.localUpload Open err: err=[%+v]", err)
+ return response.Failed.Make("打开文件失败!")
+ }
+ defer src.Close()
+ // 文件信息
+ savePath := path.Join(directory, folder, path.Dir(key))
+ saveFilePath := path.Join(directory, folder, key)
+ // 创建目录
+ err = os.MkdirAll(savePath, 0755)
+ if err != nil && !os.IsExist(err) {
+ core.Logger.Errorf(
+ "storageDriver.localUpload MkdirAll err: path=[%s], err=[%+v]", savePath, err)
+ return response.Failed.Make("创建上传目录失败!")
+ }
+ // 创建目标文件
+ out, err := os.Create(saveFilePath)
+ if err != nil {
+ core.Logger.Errorf(
+ "storageDriver.localUpload Create err: file=[%s], err=[%+v]", saveFilePath, err)
+ return response.Failed.Make("创建文件失败!")
+ }
+ defer out.Close()
+ // 写入目标文件
+ _, err = io.Copy(out, src)
+ if err != nil {
+ core.Logger.Errorf(
+ "storageDriver.localUpload Copy err: file=[%s], err=[%+v]", saveFilePath, err)
+ return response.Failed.Make("上传文件失败: " + err.Error())
+ }
+ return nil
+}
+
+// checkFile 生成文件名称
+func (sd storageDriver) buildSaveName(file *multipart.FileHeader) string {
+ name := file.Filename
+ ext := strings.ToLower(path.Ext(name))
+ date := time.Now().Format("20060201")
+ return path.Join(date, util.ToolsUtil.MakeUuid()+ext)
+}
+
+// checkFile 文件验证
+func (sd storageDriver) checkFile(file *multipart.FileHeader, fileType int) (e error) {
+ fileName := file.Filename
+ fileExt := strings.ToLower(strings.Replace(path.Ext(fileName), ".", "", 1))
+ fileSize := file.Size
+ if fileType == 10 {
+ // 图片文件
+ if !util.ToolsUtil.Contains(config.Config.UploadImageExt, fileExt) {
+ return response.Failed.Make("不被支持的图片扩展: " + fileExt)
+ }
+ if fileSize > config.Config.UploadImageSize {
+ return response.Failed.Make("上传图片不能超出限制: " + strconv.FormatInt(config.Config.UploadImageSize/1024/1024, 10) + "M")
+ }
+ } else if fileType == 20 {
+ // 视频文件
+ if !util.ToolsUtil.Contains(config.Config.UploadVideoExt, fileExt) {
+ return response.Failed.Make("不被支持的视频扩展: " + fileExt)
+ }
+ if fileSize > config.Config.UploadVideoSize {
+ return response.Failed.Make("上传视频不能超出限制: " + strconv.FormatInt(config.Config.UploadVideoSize/1024/1024, 10) + "M")
+ }
+ } else {
+ core.Logger.Errorf("storageDriver.checkFile fileType err: err=[unsupported fileType]")
+ return response.Failed.Make("上传文件类型错误")
+ }
+ return nil
+}
diff --git a/server/routers/enter.go b/server/routers/enter.go
new file mode 100644
index 0000000..53798e8
--- /dev/null
+++ b/server/routers/enter.go
@@ -0,0 +1,13 @@
+package routers
+
+import (
+ "x_admin/admin"
+ "x_admin/generator"
+
+ "github.com/gin-gonic/gin"
+)
+
+func RegisterGroup(rg *gin.RouterGroup) {
+ admin.RegisterGroup(rg)
+ generator.RegisterGroup(rg)
+}
diff --git a/server/static/backend_avatar.png b/server/static/backend_avatar.png
new file mode 100644
index 0000000..2051719
Binary files /dev/null and b/server/static/backend_avatar.png differ
diff --git a/server/static/backend_backdrop.png b/server/static/backend_backdrop.png
new file mode 100644
index 0000000..a302011
Binary files /dev/null and b/server/static/backend_backdrop.png differ
diff --git a/server/static/backend_favicon.ico b/server/static/backend_favicon.ico
new file mode 100644
index 0000000..7c00219
Binary files /dev/null and b/server/static/backend_favicon.ico differ
diff --git a/server/static/backend_logo.png b/server/static/backend_logo.png
new file mode 100644
index 0000000..cb2f6d5
Binary files /dev/null and b/server/static/backend_logo.png differ
diff --git a/server/util/array.go b/server/util/array.go
new file mode 100644
index 0000000..28da4a5
--- /dev/null
+++ b/server/util/array.go
@@ -0,0 +1,38 @@
+package util
+
+var ArrayUtil = arrayUtil{}
+
+//arrayUtil 数组工具类
+type arrayUtil struct{}
+
+//ListToTree 字典列表转树形结构
+func (au arrayUtil) ListToTree(arr []map[string]interface{}, id string, pid string, child string) (mapList []interface{}) {
+ mapList = []interface{}{}
+ // 遍历以id_为key生成map
+ idValMap := make(map[uint]interface{})
+ for _, m := range arr {
+ if idVal, ok := m[id]; ok {
+ idValMap[idVal.(uint)] = m
+ }
+ }
+ // 遍历
+ for _, m := range arr {
+ // 获取父节点
+ if pidVal, ok := m[pid]; ok {
+ if pNode, pok := idValMap[pidVal.(uint)]; pok {
+ // 有父节点则添加到父节点子集
+ if cVal, cok := pNode.(map[string]interface{})[child]; cok {
+ if cVal == nil {
+ cVal = []interface{}{m}
+ } else {
+ cVal = append(cVal.([]interface{}), m)
+ }
+ pNode.(map[string]interface{})[child] = cVal
+ continue
+ }
+ }
+ }
+ mapList = append(mapList, m)
+ }
+ return
+}
diff --git a/server/util/config.go b/server/util/config.go
new file mode 100644
index 0000000..05c1254
--- /dev/null
+++ b/server/util/config.go
@@ -0,0 +1,75 @@
+package util
+
+import (
+ "errors"
+ "x_admin/model/system"
+
+ "gorm.io/gorm"
+)
+
+var ConfigUtil = configUtil{}
+
+// convertUtil 数据库配置操作工具
+type configUtil struct{}
+
+// Get 根据类型和名称获取配置字典
+func (cu configUtil) Get(db *gorm.DB, cnfType string, names ...string) (data map[string]string, err error) {
+ chain := db.Where("type = ?", cnfType)
+ if len(names) > 0 {
+ chain.Where("name = ?", names[0])
+ }
+ var configs []system.SystemConfig
+ err = chain.Find(&configs).Error
+ if err != nil {
+ return nil, err
+ }
+ data = make(map[string]string)
+ for i := 0; i < len(configs); i++ {
+ data[configs[i].Name] = configs[i].Value
+ }
+ return data, nil
+}
+
+// GetVal 根据类型和名称获取配置值
+func (cu configUtil) GetVal(db *gorm.DB, cnfType string, name string, defaultVal string) (data string, err error) {
+ config, err := cu.Get(db, cnfType, name)
+ if err != nil {
+ return data, err
+ }
+ data, ok := config[name]
+ if !ok {
+ data = defaultVal
+ }
+ return data, nil
+}
+
+// GetMap 根据类型和名称获取配置值(Json字符串转dict)
+func (cu configUtil) GetMap(db *gorm.DB, cnfType string, name string) (data map[string]string, err error) {
+ val, err := cu.GetVal(db, cnfType, name, "")
+ if err != nil {
+ return data, err
+ }
+ if val == "" {
+ return map[string]string{}, nil
+ }
+ err = ToolsUtil.JsonToObj(val, &data)
+ return data, err
+}
+
+// Set 设置配置的值
+func (cu configUtil) Set(db *gorm.DB, cnfType string, name string, val string) (err error) {
+ var config system.SystemConfig
+ err = db.Where("type = ? AND name = ?", cnfType, name).First(&config).Error
+ if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
+ if err = db.Create(&config).Error; err != nil {
+ return err
+ }
+ return nil
+ } else if err != nil {
+ return err
+ }
+ if err = db.Model(&config).Update("value", val).Error; err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/server/util/convert.go b/server/util/convert.go
new file mode 100644
index 0000000..4256395
--- /dev/null
+++ b/server/util/convert.go
@@ -0,0 +1,27 @@
+package util
+
+import (
+ "x_admin/core"
+
+ "github.com/fatih/structs"
+ "github.com/jinzhu/copier"
+)
+
+var ConvertUtil = convertUtil{}
+
+// convertUtil 转换工具
+type convertUtil struct{}
+
+// StructsToMaps 将结构体转换成Map列表
+func (cu convertUtil) StructsToMaps(objs interface{}) (data []map[string]interface{}) {
+ var objList []interface{}
+ err := copier.Copy(&objList, objs)
+ if err != nil {
+ core.Logger.Errorf("convertUtil.StructsToMaps err: err=[%+v]", err)
+ return nil
+ }
+ for _, v := range objList {
+ data = append(data, structs.Map(v))
+ }
+ return data
+}
diff --git a/server/util/ip.go b/server/util/ip.go
new file mode 100644
index 0000000..502ac15
--- /dev/null
+++ b/server/util/ip.go
@@ -0,0 +1,23 @@
+package util
+
+import (
+ "net"
+ "x_admin/core"
+)
+
+var IpUtil = ipUtil{}
+
+// serverUtil IP工具类
+type ipUtil struct{}
+
+// GetHostIp 获取本地主机名
+func (su ipUtil) GetHostIp() (ip string) {
+ conn, err := net.Dial("udp", "114.114.114.114:80")
+ if err != nil {
+ core.Logger.Errorf("GetHostIp Dial err: err=[%+v]", err)
+ return
+ }
+ defer conn.Close()
+ localAddr := conn.LocalAddr().(*net.UDPAddr)
+ return localAddr.IP.String()
+}
diff --git a/server/util/redis.go b/server/util/redis.go
new file mode 100644
index 0000000..0708baf
--- /dev/null
+++ b/server/util/redis.go
@@ -0,0 +1,214 @@
+package util
+
+import (
+ "bufio"
+ "context"
+ "strings"
+ "time"
+ "x_admin/config"
+ "x_admin/core"
+
+ "github.com/go-redis/redis/v9"
+)
+
+var RedisUtil = redisUtil{redis: core.Redis}
+
+// redisUtil Redis操作工具类
+type redisUtil struct {
+ redis *redis.Client
+}
+
+// stringToLines string拆分多行
+func stringToLines(s string) (lines []string, err error) {
+ scanner := bufio.NewScanner(strings.NewReader(s))
+ for scanner.Scan() {
+ lines = append(lines, scanner.Text())
+ }
+ err = scanner.Err()
+ return
+}
+
+// stringToKV string拆分key和val
+func stringToKV(s string) (string, string) {
+ ss := strings.Split(s, ":")
+ if len(ss) < 2 {
+ return s, ""
+ }
+ return ss[0], ss[1]
+}
+
+// Info Redis服务信息
+func (ru redisUtil) Info(sections ...string) (res map[string]string) {
+ infoStr, err := ru.redis.Info(context.Background(), sections...).Result()
+ res = map[string]string{}
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Info err: err=[%+v]", err)
+ return res
+ }
+ // string拆分多行
+ lines, err := stringToLines(infoStr)
+ if err != nil {
+ core.Logger.Errorf("stringToLines err: err=[%+v]", err)
+ return res
+ }
+ // 解析成Map
+ for i := 0; i < len(lines); i++ {
+ if lines[i] == "" || strings.HasPrefix(lines[i], "# ") {
+ continue
+ }
+ k, v := stringToKV(lines[i])
+ res[k] = v
+ }
+ return res
+}
+
+// DBSize 当前数据库key数量
+func (ru redisUtil) DBSize() int64 {
+ size, err := ru.redis.DBSize(context.Background()).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.DBSize err: err=[%+v]", err)
+ return 0
+ }
+ return size
+}
+
+// Set 设置键值对
+func (ru redisUtil) Set(key string, value interface{}, timeSec int) bool {
+ err := ru.redis.Set(context.Background(),
+ config.Config.RedisPrefix+key, value, time.Duration(timeSec)*time.Second).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Set err: err=[%+v]", err)
+ return false
+ }
+ return true
+}
+
+// Get 获取key的值
+func (ru redisUtil) Get(key string) string {
+ res, err := ru.redis.Get(context.Background(), config.Config.RedisPrefix+key).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Get err: err=[%+v]", err)
+ return ""
+ }
+ return res
+}
+
+// SSet 将数据放入set缓存
+func (ru redisUtil) SSet(key string, values ...interface{}) bool {
+ err := ru.redis.SAdd(context.Background(), config.Config.RedisPrefix+key, values...).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.SSet err: err=[%+v]", err)
+ return false
+ }
+ return true
+}
+
+// SGet 根据key获取Set中的所有值
+func (ru redisUtil) SGet(key string) []string {
+ res, err := ru.redis.SMembers(context.Background(), config.Config.RedisPrefix+key).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.SGet err: err=[%+v]", err)
+ return []string{}
+ }
+ return res
+}
+
+// HMSet 设置key, 通过字典的方式设置多个field, value对
+func (ru redisUtil) HMSet(key string, mapping map[string]string, timeSec int) bool {
+ err := ru.redis.HSet(context.Background(), config.Config.RedisPrefix+key, mapping).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.HMSet err: err=[%+v]", err)
+ return false
+ }
+ if timeSec > 0 {
+ if !ru.Expire(key, timeSec) {
+ return false
+ }
+ }
+ return true
+}
+
+// HSet 向hash表中放入数据,如果不存在将创建
+func (ru redisUtil) HSet(key string, field string, value string, timeSec int) bool {
+ return ru.HMSet(key, map[string]string{field: value}, timeSec)
+}
+
+// HGet 获取key中field域的值
+func (ru redisUtil) HGet(key string, field string) string {
+ res, err := ru.redis.HGet(context.Background(), config.Config.RedisPrefix+key, field).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.HGet err: err=[%+v]", err)
+ return ""
+ }
+ return res
+}
+
+// HExists 判断key中有没有field域名
+func (ru redisUtil) HExists(key string, field string) bool {
+ res, err := ru.redis.HExists(context.Background(), config.Config.RedisPrefix+key, field).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.HExists err: err=[%+v]", err)
+ return false
+ }
+ return res
+}
+
+// HDel 删除hash表中的值
+func (ru redisUtil) HDel(key string, fields ...string) bool {
+ err := ru.redis.HDel(context.Background(), config.Config.RedisPrefix+key, fields...).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.HDel err: err=[%+v]", err)
+ return false
+ }
+ return true
+}
+
+// Exists 判断多项key是否存在
+func (ru redisUtil) Exists(keys ...string) int64 {
+ fullKeys := ru.toFullKeys(keys)
+ cnt, err := ru.redis.Exists(context.Background(), fullKeys...).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Exists err: err=[%+v]", err)
+ return -1
+ }
+ return cnt
+}
+
+// Expire 指定缓存失效时间
+func (ru redisUtil) Expire(key string, timeSec int) bool {
+ err := ru.redis.Expire(context.Background(), config.Config.RedisPrefix+key, time.Duration(timeSec)*time.Second).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Expire err: err=[%+v]", err)
+ return false
+ }
+ return true
+}
+
+// TTL 根据key获取过期时间
+func (ru redisUtil) TTL(key string) int {
+ td, err := ru.redis.TTL(context.Background(), config.Config.RedisPrefix+key).Result()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.TTL err: err=[%+v]", err)
+ return 0
+ }
+ return int(td / time.Second)
+}
+
+// Del 删除一个或多个键
+func (ru redisUtil) Del(keys ...string) bool {
+ fullKeys := ru.toFullKeys(keys)
+ err := ru.redis.Del(context.Background(), fullKeys...).Err()
+ if err != nil {
+ core.Logger.Errorf("redisUtil.Del err: err=[%+v]", err)
+ return false
+ }
+ return true
+}
+
+// toFullKeys 为keys批量增加前缀
+func (ru redisUtil) toFullKeys(keys []string) (fullKeys []string) {
+ for _, k := range keys {
+ fullKeys = append(fullKeys, config.Config.RedisPrefix+k)
+ }
+ return
+}
diff --git a/server/util/server.go b/server/util/server.go
new file mode 100644
index 0000000..a330646
--- /dev/null
+++ b/server/util/server.go
@@ -0,0 +1,171 @@
+package util
+
+import (
+ "fmt"
+ "math"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+ "x_admin/core"
+
+ "github.com/shirou/gopsutil/cpu"
+ "github.com/shirou/gopsutil/disk"
+ "github.com/shirou/gopsutil/host"
+ "github.com/shirou/gopsutil/mem"
+ "github.com/shirou/gopsutil/process"
+)
+
+var ServerUtil = serverUtil{}
+
+// serverUtil 服务器信息获取工具
+type serverUtil struct{}
+
+// GetFmtSize 按照正确的格式缩放字节
+func (su serverUtil) GetFmtSize(data uint64) string {
+ var factor float64 = 1024
+ res := float64(data)
+ for _, unit := range []string{"", "K", "M", "G", "T", "P"} {
+ if res < factor {
+ return fmt.Sprintf("%.2f%sB", res, unit)
+ }
+ res /= factor
+ }
+ return fmt.Sprintf("%.2f%sB", res, "P")
+}
+
+// GetFmtTime 格式化显示时间 (毫秒)
+func (su serverUtil) GetFmtTime(ms int64) (res string) {
+ rem := ms / 1000
+ days, rem := rem/86400, rem%86400
+ hours, rem := rem/3600, rem%3600
+ minutes := rem / 60
+ res = strconv.FormatInt(minutes, 10) + "分钟"
+ if hours > 0 {
+ res = strconv.FormatInt(hours, 10) + "小时" + res
+ }
+ if days > 0 {
+ res = strconv.FormatInt(days, 10) + "天" + res
+ }
+ return res
+}
+
+// GetCpuInfo 获取CPU信息
+func (su serverUtil) GetCpuInfo() (data map[string]interface{}) {
+ cnt, err := cpu.Counts(true)
+ if err != nil {
+ core.Logger.Errorf("GetCpuInfo Counts err: err=[%+v]", err)
+ return data
+ }
+ tss, err := cpu.Times(false)
+ if err != nil {
+ core.Logger.Errorf("GetCpuInfo Times err: err=[%+v]", err)
+ return data
+ }
+ ts := tss[0]
+ return map[string]interface{}{
+ "cpu_num": cnt,
+ "total": ToolsUtil.Round(ts.Total(), 2),
+ "sys": ToolsUtil.Round(ts.System/ts.Total(), 2),
+ "used": ToolsUtil.Round(ts.User/ts.Total(), 2),
+ "wait": ToolsUtil.Round(ts.Iowait/ts.Total(), 2),
+ "free": ToolsUtil.Round(ts.Idle/ts.Total(), 2),
+ }
+}
+
+// GetMemInfo 获取内存信息
+func (su serverUtil) GetMemInfo() (data map[string]interface{}) {
+ number := math.Pow(1024, 3)
+ vm, err := mem.VirtualMemory()
+ if err != nil {
+ core.Logger.Errorf("GetMemInfo VirtualMemory err: err=[%+v]", err)
+ return data
+ }
+ return map[string]interface{}{
+ "total": ToolsUtil.Round(float64(vm.Total)/number, 2),
+ "used": ToolsUtil.Round(float64(vm.Used)/number, 2),
+ "free": ToolsUtil.Round(float64(vm.Available)/number, 2),
+ "usage": ToolsUtil.Round(vm.UsedPercent, 2),
+ }
+}
+
+// GetSysInfo 获取服务器信息
+func (su serverUtil) GetSysInfo() (data map[string]interface{}) {
+ infoStat, err := host.Info()
+ if err != nil {
+ core.Logger.Errorf("GetSysInfo Info err: err=[%+v]", err)
+ return data
+ }
+ pwd, err := os.Getwd()
+ if err != nil {
+ core.Logger.Errorf("GetSysInfo Getwd err: err=[%+v]", err)
+ return data
+ }
+ return map[string]interface{}{
+ "computerName": infoStat.Hostname,
+ "computerIp": IpUtil.GetHostIp(),
+ "userDir": pwd,
+ "osName": infoStat.OS,
+ "osArch": infoStat.KernelArch,
+ }
+}
+
+// GetDiskInfo 获取磁盘信息
+func (su serverUtil) GetDiskInfo() (data []map[string]interface{}) {
+ partStats, err := disk.Partitions(false)
+ if err != nil {
+ core.Logger.Errorf("GetDiskInfo Partitions err: err=[%+v]", err)
+ return data
+ }
+ for i := 0; i < len(partStats); i++ {
+ part := partStats[i]
+ usage, uErr := disk.Usage(part.Mountpoint)
+ if uErr != nil {
+ core.Logger.Errorf("GetDiskInfo Usage err: err=[%+v]", err)
+ continue
+ }
+ data = append(data, map[string]interface{}{
+ "dirName": part.Mountpoint,
+ "sysTypeName": part.Fstype,
+ "typeName": part.Device,
+ "total": su.GetFmtSize(usage.Total),
+ "free": su.GetFmtSize(usage.Free),
+ "used": su.GetFmtSize(usage.Used),
+ "usage": ToolsUtil.Round(usage.UsedPercent, 2),
+ })
+ }
+ return data
+}
+
+// GetGoInfo 获取Go环境及服务信息
+func (su serverUtil) GetGoInfo() (data map[string]interface{}) {
+ number := math.Pow(1024, 2)
+ curProc, err := process.NewProcess(int32(os.Getpid()))
+ if err != nil {
+ core.Logger.Errorf("GetGoInfo NewProcess err: err=[%+v]", err)
+ return data
+ }
+ memInfo, err := curProc.MemoryInfo()
+ if err != nil {
+ core.Logger.Errorf("GetGoInfo MemoryInfo err: err=[%+v]", err)
+ return data
+ }
+ startTime, err := curProc.CreateTime()
+ if err != nil {
+ core.Logger.Errorf("GetGoInfo CreateTime err: err=[%+v]", err)
+ return data
+ }
+ return map[string]interface{}{
+ "name": "Go",
+ "version": runtime.Version(),
+ "home": os.Args[0],
+ "inputArgs": fmt.Sprintf("[%s]", strings.Join(os.Args[1:], ", ")),
+ "total": ToolsUtil.Round(float64(memInfo.VMS)/number, 2),
+ "max": ToolsUtil.Round(float64(memInfo.VMS)/number, 2),
+ "free": ToolsUtil.Round((float64(memInfo.VMS-memInfo.RSS))/number, 2),
+ "usage": ToolsUtil.Round(float64(memInfo.RSS)/number, 2),
+ "runTime": su.GetFmtTime(time.Now().UnixMilli() - startTime),
+ "startTime": time.UnixMilli(startTime).Format(core.TimeFormat),
+ }
+}
diff --git a/server/util/string.go b/server/util/string.go
new file mode 100644
index 0000000..208acc8
--- /dev/null
+++ b/server/util/string.go
@@ -0,0 +1,34 @@
+package util
+
+import (
+ "bytes"
+ "strings"
+ "unicode"
+)
+
+var StringUtil = stringUtil{}
+
+//arrayUtil 数组工具类
+type stringUtil struct{}
+
+func (su stringUtil) ToSnakeCase(s string) string {
+ buf := bytes.Buffer{}
+ for i, r := range s {
+ if unicode.IsUpper(r) {
+ if i > 0 {
+ buf.WriteRune('_')
+ }
+ buf.WriteRune(unicode.ToLower(r))
+ } else {
+ buf.WriteRune(r)
+ }
+ }
+ return buf.String()
+}
+func (su stringUtil) ToCamelCase(s string) string {
+ words := strings.Split(s, "_")
+ for i := 1; i < len(words); i++ {
+ words[i] = strings.Title(words[i])
+ }
+ return strings.Join(words, "")
+}
diff --git a/server/util/tools.go b/server/util/tools.go
new file mode 100644
index 0000000..b57611f
--- /dev/null
+++ b/server/util/tools.go
@@ -0,0 +1,97 @@
+package util
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+ "encoding/json"
+ "math"
+ "math/rand"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+ "x_admin/config"
+
+ "github.com/google/uuid"
+)
+
+var (
+ ToolsUtil = toolsUtil{}
+ allRandomStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+)
+
+// toolsUtil 常用工具集合类
+type toolsUtil struct{}
+
+// RandomString 返回随机字符串
+func (tu toolsUtil) RandomString(length int) string {
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ byteList := make([]byte, length)
+ for i := 0; i < length; i++ {
+ byteList[i] = allRandomStr[r.Intn(62)]
+ }
+ return string(byteList)
+}
+
+// MakeUuid 制作UUID
+func (tu toolsUtil) MakeUuid() string {
+ return strings.ReplaceAll(uuid.New().String(), "-", "")
+}
+
+// MakeMd5 制作MD5
+func (tu toolsUtil) MakeMd5(data string) string {
+ sum := md5.Sum([]byte(data))
+ return hex.EncodeToString(sum[:])
+}
+
+// MakeToken 生成唯一Token
+func (tu toolsUtil) MakeToken() string {
+ ms := time.Now().UnixMilli()
+ token := tu.MakeMd5(tu.MakeUuid() + strconv.FormatInt(ms, 10) + tu.RandomString(8))
+ tokenSecret := token + config.Config.Secret
+ return tu.MakeMd5(tokenSecret) + tu.RandomString(6)
+}
+
+// Contains 判断src是否包含elem元素
+func (tu toolsUtil) Contains(src interface{}, elem interface{}) bool {
+ srcArr := reflect.ValueOf(src)
+ if srcArr.Kind() == reflect.Ptr {
+ srcArr = srcArr.Elem()
+ }
+ if srcArr.Kind() == reflect.Slice {
+ for i := 0; i < srcArr.Len(); i++ {
+ if srcArr.Index(i).Interface() == elem {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// Round float四舍五入
+func (tu toolsUtil) Round(val float64, n int) float64 {
+ base := math.Pow(10, float64(n))
+ return math.Round(base*val) / base
+}
+
+// JsonToObj JSON转Obj
+func (tu toolsUtil) JsonToObj(jsonStr string, toVal interface{}) (err error) {
+ return json.Unmarshal([]byte(jsonStr), &toVal)
+}
+
+// ObjToJson Obj转JSON
+func (tu toolsUtil) ObjToJson(data interface{}) (res string, err error) {
+ b, err := json.Marshal(data)
+ if err != nil {
+ return res, err
+ }
+ res = string(b)
+ return res, nil
+}
+
+// IsFileExist 判断文件或目录是否存在
+func (tu toolsUtil) IsFileExist(path string) bool {
+ _, err := os.Stat(path)
+ return err == nil || os.IsExist(err)
+}
diff --git a/server/util/url.go b/server/util/url.go
new file mode 100644
index 0000000..7727cde
--- /dev/null
+++ b/server/util/url.go
@@ -0,0 +1,63 @@
+package util
+
+import (
+ "net/url"
+ "path"
+ "strings"
+ "x_admin/config"
+ "x_admin/core"
+)
+
+var (
+ UrlUtil = urlUtil{}
+ publicUrl = config.Config.PublicUrl
+ publicPrefix = config.Config.PublicPrefix
+)
+
+// urlUtil 文件路径处理工具
+type urlUtil struct{}
+
+// ToAbsoluteUrl 转绝对路径
+func (uu urlUtil) ToAbsoluteUrl(u string) string {
+ // TODO: engine默认local
+ if u == "" {
+ return ""
+ }
+ up, err := url.Parse(publicUrl)
+ if err != nil {
+ core.Logger.Errorf("ToAbsoluteUrl Parse err: err=[%+v]", err)
+ return u
+ }
+ if strings.HasPrefix(u, "/api/static/") {
+ up.Path = path.Join(up.Path, u)
+ return up.String()
+ }
+ engine := "local"
+ if engine == "local" {
+ up.Path = path.Join(up.Path, publicPrefix, u)
+ return up.String()
+ }
+ // TODO: 其他engine
+ return u
+}
+
+func (uu urlUtil) ToRelativeUrl(u string) string {
+ // TODO: engine默认local
+ if u == "" {
+ return ""
+ }
+ up, err := url.Parse(u)
+ if err != nil {
+ core.Logger.Errorf("ToRelativeUrl Parse err: err=[%+v]", err)
+ return u
+ }
+ engine := "local"
+ if engine == "local" {
+ lu := up.String()
+ return strings.Replace(
+ strings.Replace(lu, publicUrl, "", 1),
+ publicPrefix, "", 1)
+ }
+ // TODO: 其他engine
+ return u
+}
diff --git a/server/util/verify.go b/server/util/verify.go
new file mode 100644
index 0000000..9b98eb3
--- /dev/null
+++ b/server/util/verify.go
@@ -0,0 +1,71 @@
+package util
+
+import (
+ "encoding/json"
+ "io"
+ "mime/multipart"
+ "x_admin/core/response"
+
+ "github.com/gin-gonic/gin"
+ "github.com/gin-gonic/gin/binding"
+)
+
+var VerifyUtil = verifyUtil{}
+
+// verifyUtil 参数验证工具类
+type verifyUtil struct{}
+
+func (vu verifyUtil) VerifyJSON(c *gin.Context, obj any) (e error) {
+ if err := c.ShouldBindBodyWith(obj, binding.JSON); err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
+
+func (vu verifyUtil) VerifyJSONArray(c *gin.Context, obj any) (e error) {
+ body, err := io.ReadAll(c.Request.Body)
+ if err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ err = json.Unmarshal(body, &obj)
+ if err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
+
+func (vu verifyUtil) VerifyBody(c *gin.Context, obj any) (e error) {
+ if err := c.ShouldBind(obj); err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
+
+func (vu verifyUtil) VerifyHeader(c *gin.Context, obj any) (e error) {
+ if err := c.ShouldBindHeader(obj); err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
+
+func (vu verifyUtil) VerifyQuery(c *gin.Context, obj any) (e error) {
+ if err := c.ShouldBindQuery(obj); err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
+
+func (vu verifyUtil) VerifyFile(c *gin.Context, name string) (file *multipart.FileHeader, e error) {
+ file, err := c.FormFile(name)
+ if err != nil {
+ e = response.ParamsValidError.MakeData(err.Error())
+ return
+ }
+ return
+}
diff --git a/sql/x_admin.sql b/sql/x_admin.sql
new file mode 100644
index 0000000..946aeab
--- /dev/null
+++ b/sql/x_admin.sql
@@ -0,0 +1,826 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server : likeadmin
+ Source Server Type : MySQL
+ Source Server Version : 50726 (5.7.26-log)
+ Source Host : localhost:3306
+ Source Schema : likeadmin
+
+ Target Server Type : MySQL
+ Target Server Version : 50726 (5.7.26-log)
+ File Encoding : 65001
+
+ Date: 21/11/2023 10:12:07
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for x_album
+-- ----------------------------
+DROP TABLE IF EXISTS `x_album`;
+CREATE TABLE `x_album` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `cid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '类目ID',
+ `aid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '管理员ID',
+ `uid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `type` tinyint(2) UNSIGNED NOT NULL DEFAULT 10 COMMENT '文件类型: [10=图片, 20=视频]',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件名称',
+ `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件路径',
+ `ext` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件扩展',
+ `size` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '文件大小',
+ `is_delete` int(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_cid`(`cid`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '相册管理表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_album
+-- ----------------------------
+INSERT INTO `x_album` VALUES (1, 0, 1, 0, 10, 'Alx_gp73pq.png', 'image/20230911/34a557325c004f498b1da01bb068f919.png', 'png', 7138309, 0, 1699499781, 1699499781, 0);
+INSERT INTO `x_album` VALUES (2, 0, 1, 0, 20, '素材中心 和另外 1 个页面 - 个人 - Microsoft Edge 2023-11-20 15-37-39.mp4', 'video/20232011/e5f53b824e314ab7992ef4b6e7595b86.mp4', 'mp4', 4053956, 0, 1700465870, 1700465870, 0);
+
+-- ----------------------------
+-- Table structure for x_album_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `x_album_cate`;
+CREATE TABLE `x_album_cate` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '父级ID',
+ `type` tinyint(2) UNSIGNED NOT NULL DEFAULT 10 COMMENT '类型: [10=图片, 20=视频]',
+ `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '分类名称',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: [0=否, 1=是]',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '相册分类表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_album_cate
+-- ----------------------------
+INSERT INTO `x_album_cate` VALUES (1, 0, 10, '1', 0, 1699519913, 1699519913, 0);
+
+-- ----------------------------
+-- Table structure for x_article
+-- ----------------------------
+DROP TABLE IF EXISTS `x_article`;
+CREATE TABLE `x_article` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `cid` int(10) UNSIGNED NOT NULL COMMENT '分类',
+ `title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '标题',
+ `intro` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '简介',
+ `summary` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '摘要',
+ `image` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '封面',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '内容',
+ `author` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '作者',
+ `visit` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '浏览',
+ `sort` int(10) UNSIGNED NOT NULL DEFAULT 50 COMMENT '排序',
+ `is_show` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否显示: 0=否, 1=是',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `cid_idx`(`cid`) USING BTREE COMMENT '分类索引'
+) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章资讯表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_article
+-- ----------------------------
+INSERT INTO `x_article` VALUES (1, 1, '让生活更精致!五款居家好物推荐,实用性超高', '##好物推荐🔥', '随着当代生活节奏的忙碌,很多人在闲暇之余都想好好的享受生活。随着科技的发展,也出现了越来越多可以帮助我们提升幸福感,让生活变得更精致的产品,下面周周就给大家盘点五款居家必备的好物,都是实用性很高的产品,周周可以保证大家买了肯定会喜欢。', '/api/static/article01.png', '
拥有一台投影仪,闲暇时可以在家里直接看影院级别的大片,光是想想都觉得超级爽。市面上很多投影仪大几千,其实周周觉得没必要,选泰捷这款一千多的足够了,性价比非常高。
泰捷的专业度很高,在电视TV领域研发已经十年,有诸多专利和技术创新,荣获国内外多项技术奖项,拿下了腾讯创新工场投资,打造的泰捷视频TV端和泰捷电视盒子都获得了极高评价。
这款投影仪的分辨率在3000元内无敌,做到了真1080P高分辨率,也就是跟市场售价三千DLP投影仪一样的分辨率,真正做到了分毫毕现,像桌布的花纹、天空的云彩等,这些细节都清晰可见。
亮度方面,泰捷达到了850ANSI流明,同价位一般是200ANSI。这是因为泰捷为了提升亮度和LCD技术透射率低的问题,首创高功率LED灯源,让其亮度做到同价位最好。专业媒体也进行了多次对比,效果与3000元价位投影仪相当。
操作系统周周也很喜欢,完全不卡。泰捷作为资深音视频品牌,在系统优化方面有十年的研发经验,打造出的“零极”系统是业内公认效率最高、速度最快的系统,用户也评价它流畅度能一台顶三台,而且为了解决行业广告多这一痛点,系统内不植入任何广告。
', '红花', 9, 0, 1, 0, 1663317759, 1663322726, 0);
+INSERT INTO `x_article` VALUES (2, 1, '埋葬UI设计师的坟墓不是内卷,而是免费模式', '', '本文从另外一个角度,聊聊作者对UI设计师职业发展前景的担忧,欢迎从事UI设计的同学来参与讨论,会有赠书哦', '/api/static/article02.jpeg', '
一个职业,卷,根本就没什么大不了的,尤其是成熟且收入高的职业,不卷才不符合事物发展的规律。何况 UI 设计师的人力市场到今天也和 5 年前一样,还是停留在大型菜鸡互啄的场面。远不能和医疗、证券、教师或者演艺练习生相提并论。
真正会让我对 UI 设计师发展前景觉得悲观的事情就只有一件 —— 国内的互联网产品免费机制。这也是一个我一直以来想讨论的话题,就在这次写一写。
国内互联网市场的发展,是一部浩瀚的 “免费经济” 发展史。虽然今天免费已经是深入国内民众骨髓的认知,但最早的中文互联网也是需要付费的,网游也都是要花钱的。
只是自有国情在此,付费确实阻碍了互联网行业的扩张和普及,一批创业家就开始通过免费的模式为用户提供服务,从而扩大了自己的产品覆盖面和普及程度。
印象最深的就是免费急先锋周鸿祎,和现在鲜少出现在公众视野不同,一零年前他是当之无愧的互联网教主,因为他开发出了符合中国国情的互联网产品 “打法”,让 360 的发展如日中天。
就是他在自传中提到:
只要是在互联网上每个人都需要的服务,我们就认为它是基础服务,基础服务一定是免费的,这样的话不会形成价值歧视。就是说,只要这种服务是每个人都一定要用的,我一定免费提供,而且是无条件免费。增值服务不是所有人都需要的,这个比例可能会相当低,它只是百分之几甚至更少比例的人需要,所以这种服务一定要收费……
这就是互联网的游戏规则,它决定了要想建立一个有效的商业模式,就一定要有海量的用户基数……
', '一一', 23, 0, 1, 0, 1663320938, 1663322854, 0);
+INSERT INTO `x_article` VALUES (3, 2, '金山电池公布“沪广深市民绿色生活方式”调查结果', '', '60%以上受访者认为高质量的10分钟足以完成“自我充电”', '/api/static/article03.png', '深圳,2021年10月22日)生活在一线城市的沪广深市民一向以效率见称,工作繁忙和快节奏的生活容易缺乏充足的休息。近日,一项针对沪广深市民绿色生活方式而展开的网络问卷调查引起了大家的注意。问卷的问题设定集中于市民对休息时间的看法,以及从对循环充电电池的使用方面了解其对绿色生活方式的态度。该调查采用随机抽样的模式,并对最终收集的1,500份有效问卷进行专业分析后发现,超过60%的受访者表示,在每天的工作时段能拥有10分钟高质量的休息时间,就可以高效“自我充电”。该调查结果反映出,在快节奏时代下,人们需要高质量的休息时间,也要学会利用高效率的休息方式和工具来应对快节奏的生活,以时刻保持“满电”状态。
60%以上受访者认为高质量的10分钟足以完成“自我充电”
这次调查超过1,500人,主要聚焦18至85岁的沪广深市民,了解他们对于休息时间的观念及使用充电电池的习惯,结果发现:
· 90%以上有工作受访者每天工作时间在7小时以上,平均工作时间为8小时,其中43%以上的受访者工作时间超过9小时
· 70%受访者认为在工作期间拥有10分钟“自我充电”时间不是一件困难的事情
· 60%受访者认为在工作期间有10分钟休息时间足以为自己快速充电
临床心理学家黄咏诗女士在发布会上分享为自己快速充电的实用技巧,她表示:“事实上,只要选择正确的休息方法,10分钟也足以为自己充电。以喝咖啡为例,我们可以使用心灵休息法 ── 静观呼吸,慢慢感受咖啡的温度和气味,如果能配合着聆听流水或海洋的声音,能够有效放松大脑及心灵。”
这次调查结果反映出沪广深市民的希望在繁忙的工作中适时停下来,抽出10分钟喝杯咖啡、聆听音乐或小睡片刻,为自己充电。金山电池全新推出的“绿再十分充”超快速充电器仅需10分钟就能充好电,喝一杯咖啡的时间既能完成“自我充电”,也满足设备使用的用电需求,为提升工作效率和放松身心注入新能量。
金山电池推出10分钟超快电池充电器*绿再十分充,以创新科技为市场带来革新体验
该问卷同时从沪广深市民对循环充电电池的使用方面进行了调查,以了解其对绿色生活方式的态度:
· 87%受访者目前没有使用充电电池,其中61%表示会考虑使用充电电池
· 58%受访者过往曾使用过充电电池,却只有20%左右市民仍在使用
· 60%左右受访者认为充电电池尚未被广泛使用,主要障碍来自于充电时间过长、缺乏相关教育
· 90%以上受访者认为充电电池充满电需要1小时或更长的时间
金山电池一直致力于为大众提供安全可靠的充电电池,并与消费者的需求和生活方式一起演变及进步。今天,金山电池宣布推出10分钟超快电池充电器*绿再十分充,只需10分钟*即可将4粒绿再十分充充电电池充好电,充电速度比其他品牌提升3倍**。充电器的LED灯可以显示每粒电池的充电状态和模式,并提示用户是否错误插入已损坏电池或一次性电池。尽管其体型小巧,却具备多项创新科技 ,如拥有独特的充电算法以优化充电电流,并能根据各个电池类型、状况和温度用最短的时间为充电电池充好电;绿再十分充内置横流扇,有效防止电池温度过热和提供低噪音的充电环境等。
', '中网资讯科技', 3, 0, 1, 0, 1663322665, 1663322665, 0);
+
+-- ----------------------------
+-- Table structure for x_article_category
+-- ----------------------------
+DROP TABLE IF EXISTS `x_article_category`;
+CREATE TABLE `x_article_category` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '名称',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 50 COMMENT '排序',
+ `is_show` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否显示: 0=否, 1=是',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章分类表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_article_category
+-- ----------------------------
+INSERT INTO `x_article_category` VALUES (1, '文章资讯', 0, 1, 0, 1663317280, 1663317282, 0);
+INSERT INTO `x_article_category` VALUES (2, '社会热点', 0, 1, 0, 1663321464, 1663321494, 0);
+
+-- ----------------------------
+-- Table structure for x_article_collect
+-- ----------------------------
+DROP TABLE IF EXISTS `x_article_collect`;
+CREATE TABLE `x_article_collect` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `article_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '文章ID',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章收藏表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_article_collect
+-- ----------------------------
+INSERT INTO `x_article_collect` VALUES (1, 0, 0, 1, 0, 0, 0);
+INSERT INTO `x_article_collect` VALUES (5, 1, 1, 1, 0, 0, 0);
+
+-- ----------------------------
+-- Table structure for x_decorate_page
+-- ----------------------------
+DROP TABLE IF EXISTS `x_decorate_page`;
+CREATE TABLE `x_decorate_page` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `page_type` tinyint(2) UNSIGNED NOT NULL DEFAULT 10 COMMENT '页面类型',
+ `page_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '页面名称',
+ `page_data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '页面数据',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '页面装修表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_decorate_page
+-- ----------------------------
+INSERT INTO `x_decorate_page` VALUES (1, 1, '商城首页', '[{\"title\":\"搜索\",\"name\":\"search\",\"disabled\":1,\"content\":{},\"styles\":{}},{\"title\":\"首页轮播图\",\"name\":\"banner\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"/api/static/banner01.png\",\"name\":\"\",\"link\":{\"path\":\"/pages/index/index\",\"name\":\"商城首页\",\"type\":\"shop\"}},{\"image\":\"/api/static/banner02.png\",\"name\":\"\",\"link\":{}}]},\"styles\":{}},{\"title\":\"导航菜单\",\"name\":\"nav\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"/api/static/nav01.png\",\"name\":\"资讯中心\",\"link\":{\"path\":\"/pages/news/news\",\"name\":\"文章资讯\",\"type\":\"shop\"}},{\"image\":\"/api/static/nav02.png\",\"name\":\"我的收藏\",\"link\":{\"path\":\"/pages/collection/collection\",\"name\":\"我的收藏\",\"type\":\"shop\"}},{\"image\":\"/api/static/nav03.png\",\"name\":\"个人设置\",\"link\":{\"path\":\"/pages/user_set/user_set\",\"name\":\"个人设置\",\"type\":\"shop\"}},{\"image\":\"/api/static/nav04.png\",\"name\":\"联系客服\",\"link\":{\"path\":\"/pages/customer_service/customer_service\",\"name\":\"联系客服\",\"type\":\"shop\"}},{\"image\":\"/api/static/nav05.png\",\"name\":\"关于我们\",\"link\":{\"path\":\"/pages/as_us/as_us\",\"name\":\"关于我们\",\"type\":\"shop\"}}]},\"styles\":{}},{\"id\":\"l84almsk2uhyf\",\"title\":\"资讯\",\"name\":\"news\",\"disabled\":1,\"content\":{},\"styles\":{}}]', 1661757188, 1663321380);
+INSERT INTO `x_decorate_page` VALUES (2, 2, '个人中心', '[{\"title\":\"用户信息\",\"name\":\"user-info\",\"disabled\":1,\"content\":{},\"styles\":{}},{\"title\":\"我的服务\",\"name\":\"my-service\",\"content\":{\"style\":2,\"title\":\"服务中心\",\"data\":[{\"image\":\"/api/static/user_collect.png\",\"name\":\"我的收藏\",\"link\":{\"path\":\"/pages/collection/collection\",\"name\":\"我的收藏\",\"type\":\"shop\"}},{\"image\":\"/api/static/user_setting.png\",\"name\":\"个人设置\",\"link\":{\"path\":\"/pages/user_set/user_set\",\"name\":\"个人设置\",\"type\":\"shop\"}},{\"image\":\"/api/static/user_kefu.png\",\"name\":\"联系客服\",\"link\":{\"path\":\"/pages/customer_service/customer_service\",\"name\":\"联系客服\",\"type\":\"shop\"}}]},\"styles\":{}},{\"title\":\"个人中心广告图\",\"name\":\"user-banner\",\"content\":{\"enabled\":1,\"data\":[{\"image\":\"/api/static/ad01.jpg\",\"name\":\"\",\"link\":{}}]},\"styles\":{}}]', 1661757188, 1663320728);
+INSERT INTO `x_decorate_page` VALUES (3, 3, '客服设置', '[{\"title\":\"客服设置\",\"name\":\"customer-service\",\"content\":{\"title\":\"添加客服二维码\",\"time\":\"早上 9:00 - 22:00\",\"mobile\":\"13800138000\",\"qrcode\":\"\"},\"styles\":{}}]', 1661757188, 1662689155);
+
+-- ----------------------------
+-- Table structure for x_decorate_tabbar
+-- ----------------------------
+DROP TABLE IF EXISTS `x_decorate_tabbar`;
+CREATE TABLE `x_decorate_tabbar` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '导航名称',
+ `selected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '未选图标',
+ `unselected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '已选图标',
+ `link` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '链接地址',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '底部装修表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_decorate_tabbar
+-- ----------------------------
+INSERT INTO `x_decorate_tabbar` VALUES (13, '首页', '/api/static/tabbar_home_sel.png', '/api/static/tabbar_home.png', '{\"path\":\"/pages/index/index\",\"name\":\"商城首页\",\"type\":\"shop\"}', 1662688157, 1662688157);
+INSERT INTO `x_decorate_tabbar` VALUES (14, '资讯', '/api/static/tabbar_text_sel.png', '/api/static/tabbar_text.png', '{\"path\":\"/pages/news/news\",\"name\":\"文章资讯\",\"type\":\"shop\"}', 1662688157, 1662688157);
+INSERT INTO `x_decorate_tabbar` VALUES (15, '我的', '/api/static/tabbar_me_sel.png', '/api/static/tabbar_me.png', '{\"path\":\"/pages/user/user\",\"name\":\"个人中心\",\"type\":\"shop\"}', 1662688157, 1662688157);
+
+-- ----------------------------
+-- Table structure for x_dict_data
+-- ----------------------------
+DROP TABLE IF EXISTS `x_dict_data`;
+CREATE TABLE `x_dict_data` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `type_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '类型',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '键名',
+ `value` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数值',
+ `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '备注',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序',
+ `status` tinyint(1) NOT NULL COMMENT '状态: 0=停用, 1=正常',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_dict_data
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_dict_type
+-- ----------------------------
+DROP TABLE IF EXISTS `x_dict_type`;
+CREATE TABLE `x_dict_type` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `dict_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字典名称',
+ `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字典类型',
+ `dict_remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字典备注',
+ `dict_status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '字典状态: 0=停用, 1=正常',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_dict_type
+-- ----------------------------
+INSERT INTO `x_dict_type` VALUES (1, 'a', 'a', 'a', 1, 0, 1699343341, 1699343341, 0);
+
+-- ----------------------------
+-- Table structure for x_gen_table
+-- ----------------------------
+DROP TABLE IF EXISTS `x_gen_table`;
+CREATE TABLE `x_gen_table` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '表名称',
+ `table_comment` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '表描述',
+ `sub_table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '关联表名称',
+ `sub_table_fk` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '关联表外键',
+ `author_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '作者的名称',
+ `entity_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '实体的名称',
+ `module_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '生成模块名',
+ `function_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '生成功能名',
+ `tree_primary` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '树主键字段',
+ `tree_parent` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '树父级字段',
+ `tree_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '树显示字段',
+ `gen_tpl` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'crud' COMMENT '生成模板方式: [crud=单表, tree=树表]',
+ `gen_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '生成代码方式: [0=zip压缩包, 1=自定义路径]',
+ `gen_path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '/' COMMENT '生成代码路径: [不填默认项目路径]',
+ `remarks` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注信息',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '代码生成业务表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_gen_table
+-- ----------------------------
+INSERT INTO `x_gen_table` VALUES (10, 'x_article_collect', '文章收藏表', '', '', '', 'articleCollect', 'article_collect', '文章收藏', '', '', '', 'crud', 0, '/', '', 1700321456, 1700449469);
+
+-- ----------------------------
+-- Table structure for x_gen_table_column
+-- ----------------------------
+DROP TABLE IF EXISTS `x_gen_table_column`;
+CREATE TABLE `x_gen_table_column` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '列主键',
+ `table_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '表外键',
+ `column_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '列名称',
+ `column_comment` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '列描述',
+ `column_length` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '列长度',
+ `column_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '列类型 ',
+ `go_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT 'JAVA类型',
+ `go_field` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'JAVA字段',
+ `is_pk` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否主键: [1=是, 0=否]',
+ `is_increment` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否自增: [1=是, 0=否]',
+ `is_required` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否必填: [1=是, 0=否]',
+ `is_insert` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否插入字段: [1=是, 0=否]',
+ `is_edit` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否编辑字段: [1=是, 0=否]',
+ `is_list` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否列表字段: [1=是, 0=否]',
+ `is_query` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否查询字段: [1=是, 0=否]',
+ `query_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'EQ' COMMENT '查询方式: [等于、不等于、大于、小于、范围]',
+ `html_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '显示类型: [文本框、文本域、下拉框、复选框、单选框、日期控件]',
+ `dict_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字典类型',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序编号',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 91 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '代码生成字段表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_gen_table_column
+-- ----------------------------
+INSERT INTO `x_gen_table_column` VALUES (84, 10, 'id', '主键', '10', 'int', 'int', 'id', 1, 1, 0, 0, 0, 0, 0, '=', 'input', '', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (85, 10, 'user_id', '用户ID', '10', 'int', 'int', 'user_id', 0, 0, 1, 1, 1, 1, 1, '=', 'select', 'a', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (86, 10, 'article_id', '文章ID', '10', 'int', 'int', 'article_id', 0, 0, 1, 1, 1, 1, 1, '=', 'input', '', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (87, 10, 'is_delete', '是否删除', '1', 'tinyint', 'int', 'is_delete', 0, 0, 0, 0, 0, 0, 0, '=', 'input', '', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (88, 10, 'create_time', '创建时间', '10', 'int', 'core.TsTime', 'create_time', 0, 0, 0, 0, 0, 1, 0, '=', 'datetime', '', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (89, 10, 'update_time', '更新时间', '10', 'int', 'core.TsTime', 'update_time', 0, 0, 0, 0, 0, 1, 0, '=', 'datetime', '', 0, 0, 1700449469);
+INSERT INTO `x_gen_table_column` VALUES (90, 10, 'delete_time', '是否删除', '10', 'int', 'core.TsTime', 'delete_time', 0, 0, 0, 0, 0, 0, 0, '=', 'datetime', '', 0, 0, 1700449469);
+
+-- ----------------------------
+-- Table structure for x_hot_search
+-- ----------------------------
+DROP TABLE IF EXISTS `x_hot_search`;
+CREATE TABLE `x_hot_search` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '关键词',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序号',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '热门搜索配置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_hot_search
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_notice_setting
+-- ----------------------------
+DROP TABLE IF EXISTS `x_notice_setting`;
+CREATE TABLE `x_notice_setting` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `scene` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '场景编号',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '场景名称',
+ `remarks` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '场景描述',
+ `recipient` tinyint(1) NOT NULL DEFAULT 1 COMMENT '接收人员: [1=用户, 2=平台]',
+ `type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '通知类型: [1=业务, 2=验证]',
+ `system_notice` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '系统的通知设置',
+ `sms_notice` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '短信的通知设置',
+ `oa_notice` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '公众号通知设置',
+ `mnp_notice` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '小程序通知设置',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '消息通知设置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_notice_setting
+-- ----------------------------
+INSERT INTO `x_notice_setting` VALUES (1, 101, '登录验证码', '用户手机号码登录时发送', 1, 2, '{}', '{\"type\":\"sms\",\"templateId\":\"SMS_222458159\",\"content\":\"您正在登录,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"tips\":[\"可选变量 验证码:code\",\"示例:您正在登录,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"生效条件:1、管理后台完成短信设置。2、第三方短信平台申请模板。\"],\"status\":\"1\"}', '{}', '{}', 0, 1648696695, 1648696695, 0);
+INSERT INTO `x_notice_setting` VALUES (2, 102, '绑定手机验证码', '用户绑定手机号码时发送', 1, 2, '{}', '{\"type\":\"sms\",\"templateId\":\"SMS_175615069\",\"content\":\"您正在绑定手机号,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"tips\":[\"可选变量 验证码:code\",\"示例:您正在绑定手机号,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"生效条件:1、管理后台完成短信设置。2、第三方短信平台申请模板。\"],\"status\":\"1\"}', '{}', '{}', 0, 1648696695, 1648696695, 0);
+INSERT INTO `x_notice_setting` VALUES (3, 103, '变更手机验证码', '用户变更手机号码时发送', 1, 2, '{}', '{\"type\":\"sms\",\"templateId\":\"SMS_207952628\",\"content\":\"您正在变更手机号,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"tips\":[\"可选变量 验证码:code\",\"示例:您正在变更手机号,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"生效条件:1、管理后台完成短信设置。2、第三方短信平台申请模板。\"],\"status\":\"1\"}', '{}', '{}', 0, 1648696695, 1648696695, 0);
+INSERT INTO `x_notice_setting` VALUES (4, 104, '找回登录密码验证码', '用户找回登录密码号码时发送', 1, 2, '{}', '{\"type\":\"sms\",\"templateId\":\"SMS_175615069\",\"content\":\"您正在找回登录密码,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"tips\":[\"可选变量 验证码:code\",\"示例:您正在找回登录密码,验证码${code},切勿将验证码泄露于他人,本条验证码有效期5分钟。\",\"条验证码有效期5分钟。\"],\"status\":\"1\"}', '{}', '{}', 0, 1648696695, 1648696695, 0);
+
+-- ----------------------------
+-- Table structure for x_official_reply
+-- ----------------------------
+DROP TABLE IF EXISTS `x_official_reply`;
+CREATE TABLE `x_official_reply` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '规则名',
+ `keyword` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '关键词',
+ `reply_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '回复类型: [1=关注回复 2=关键字回复, 3=默认回复]',
+ `matching_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '匹配方式: [1=全匹配, 2=模糊匹配]',
+ `content_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '内容类型: [1=文本]',
+ `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '启动状态: [1=启动, 0=关闭]',
+ `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '回复内容',
+ `sort` int(11) UNSIGNED NOT NULL DEFAULT 50 COMMENT '排序编号',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除',
+ `create_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '公众号的回复表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_official_reply
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_product
+-- ----------------------------
+DROP TABLE IF EXISTS `x_product`;
+CREATE TABLE `x_product` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '产品名称',
+ `category` int(11) UNSIGNED NOT NULL COMMENT '产品分类',
+ `pics` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ FULLTEXT INDEX `name`(`name`)
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '产品表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of x_product
+-- ----------------------------
+INSERT INTO `x_product` VALUES (1, 'aaa', 2, '11');
+INSERT INTO `x_product` VALUES (2, 'a', 0, '3');
+
+-- ----------------------------
+-- Table structure for x_system_auth_admin
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_admin`;
+CREATE TABLE `x_system_auth_admin` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `dept_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '部门ID',
+ `post_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '岗位ID',
+ `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户账号',
+ `nickname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
+ `password` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
+ `avatar` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户头像',
+ `role` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色主键',
+ `salt` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '加密盐巴',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序编号',
+ `is_multipoint` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '多端登录: 0=否, 1=是',
+ `is_disable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁用: 0=否, 1=是',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `last_login_ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最后登录IP',
+ `last_login_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后登录',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统管理成员表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_admin
+-- ----------------------------
+INSERT INTO `x_system_auth_admin` VALUES (1, 1, 0, 'admin', 'admin', '7fac2474740becfaf1ecbdd6cc8fb076', '/api/static/backend_avatar.png', '0', '5Xar0', 0, 1, 0, 0, '127.0.0.1', 1700462131, 1642321599, 1700462131, 0);
+
+-- ----------------------------
+-- Table structure for x_system_auth_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_dept`;
+CREATE TABLE `x_system_auth_dept` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '上级主键',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门名称',
+ `duty` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '负责人名',
+ `mobile` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '联系电话',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序编号',
+ `is_stop` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁用: 0=否, 1=是',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统部门管理表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_dept
+-- ----------------------------
+INSERT INTO `x_system_auth_dept` VALUES (1, 0, '默认部门', '康明', '18327647788', 10, 0, 0, 1649841995, 1660190949, 0);
+
+-- ----------------------------
+-- Table structure for x_system_auth_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_menu`;
+CREATE TABLE `x_system_auth_menu` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '上级菜单',
+ `menu_type` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '权限类型: M=目录,C=菜单,A=按钮',
+ `menu_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '菜单名称',
+ `menu_icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '菜单图标',
+ `menu_sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '菜单排序',
+ `perms` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '权限标识',
+ `paths` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '路由地址',
+ `component` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '前端组件',
+ `selected` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '选中路径',
+ `params` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '路由参数',
+ `is_cache` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否缓存: 0=否, 1=是',
+ `is_show` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否显示: 0=否, 1=是',
+ `is_disable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁用: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 778 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统菜单管理表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_menu
+-- ----------------------------
+INSERT INTO `x_system_auth_menu` VALUES (1, 0, 'C', '工作台', 'el-icon-Monitor', 50, 'common:index:console', 'workbench', 'workbench/index', '', '', 1, 1, 0, 1650341765, 1668672757);
+INSERT INTO `x_system_auth_menu` VALUES (100, 0, 'M', '权限管理', 'el-icon-Lock', 44, '', 'permission', '', '', '', 0, 1, 0, 1650341765, 1662626201);
+INSERT INTO `x_system_auth_menu` VALUES (101, 100, 'C', '管理员', 'local-icon-wode', 0, 'system:admin:list', 'admin', 'permission/admin/index', '', '', 1, 1, 0, 1650341765, 1663301404);
+INSERT INTO `x_system_auth_menu` VALUES (102, 101, 'A', '管理员详情', '', 0, 'system:admin:detail', '', '', '', '', 0, 1, 0, 1650341765, 1660201785);
+INSERT INTO `x_system_auth_menu` VALUES (103, 101, 'A', '管理员新增', '', 0, 'system:admin:add', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (104, 101, 'A', '管理员编辑', '', 0, 'system:admin:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (105, 101, 'A', '管理员删除', '', 0, 'system:admin:del', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (106, 101, 'A', '管理员状态', '', 0, 'system:admin:disable', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (110, 100, 'C', '角色管理', 'el-icon-Female', 0, 'system:role:list', 'role', 'permission/role/index', '', '', 1, 1, 0, 1650341765, 1663301451);
+INSERT INTO `x_system_auth_menu` VALUES (111, 110, 'A', '角色详情', '', 0, 'system:role:detail', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (112, 110, 'A', '角色新增', '', 0, 'system:role:add', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (113, 110, 'A', '角色编辑', '', 0, 'system:role:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (114, 110, 'A', '角色删除', '', 0, 'system:role:del', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (120, 100, 'C', '菜单管理', 'el-icon-Operation', 0, 'system:menu:list', 'menu', 'permission/menu/index', '', '', 1, 1, 0, 1650341765, 1663301388);
+INSERT INTO `x_system_auth_menu` VALUES (121, 120, 'A', '菜单详情', '', 0, 'system:menu:detail', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (122, 120, 'A', '菜单新增', '', 0, 'system:menu:add', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (123, 120, 'A', '菜单编辑', '', 0, 'system:menu:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (124, 120, 'A', '菜单删除', '', 0, 'system:menu:del', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (130, 0, 'M', '组织管理', 'el-icon-OfficeBuilding', 45, '', 'organization', '', '', '', 0, 1, 0, 1650341765, 1664416715);
+INSERT INTO `x_system_auth_menu` VALUES (131, 130, 'C', '部门管理', 'el-icon-Coordinate', 0, 'system:dept:list', 'department', 'organization/department/index', '', '', 1, 1, 0, 1650341765, 1660201994);
+INSERT INTO `x_system_auth_menu` VALUES (132, 131, 'A', '部门详情', '', 0, 'system:dept:detail', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (133, 131, 'A', '部门新增', '', 0, 'system:dept:add', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (134, 131, 'A', '部门编辑', '', 0, 'system:dept:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (135, 131, 'A', '部门删除', '', 0, 'system:dept:del', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (140, 130, 'C', '岗位管理', 'el-icon-PriceTag', 0, 'system:post:list', 'post', 'organization/post/index', '', '', 1, 1, 0, 1650341765, 1660202057);
+INSERT INTO `x_system_auth_menu` VALUES (141, 140, 'A', '岗位详情', '', 0, 'system:post:detail', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (142, 140, 'A', '岗位新增', '', 0, 'system:post:add', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (143, 140, 'A', '岗位编辑', '', 0, 'system:post:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (144, 140, 'A', '岗位删除', '', 0, 'system:post:del', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (200, 0, 'M', '其它管理', '', 0, '', '', '', '', '', 0, 0, 0, 1650341765, 1660636870);
+INSERT INTO `x_system_auth_menu` VALUES (201, 200, 'M', '图库管理', '', 0, '', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (202, 201, 'A', '文件列表', '', 0, 'albums:albumList', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (203, 201, 'A', '文件命名', '', 0, 'albums:albumRename', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (204, 201, 'A', '文件移动', '', 0, 'albums:albumMove', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (205, 201, 'A', '文件删除', '', 0, 'albums:albumDel', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (206, 201, 'A', '分类列表', '', 0, 'albums:cateList', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (207, 201, 'A', '分类新增', '', 0, 'albums:cateAdd', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (208, 201, 'A', '分类命名', '', 0, 'albums:cateRename', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (209, 201, 'A', '分类删除', '', 0, 'albums:cateDel', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (215, 200, 'M', '上传管理', '', 0, '', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (216, 215, 'A', '上传图片', '', 0, 'upload:image', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (217, 215, 'A', '上传视频', '', 0, 'upload:video', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (500, 0, 'M', '系统设置', 'el-icon-Setting', 0, '', 'setting', '', '', '', 0, 1, 0, 1650341765, 1662626322);
+INSERT INTO `x_system_auth_menu` VALUES (501, 500, 'M', '网站设置', 'el-icon-Basketball', 10, '', 'website', '', '', '', 0, 1, 0, 1650341765, 1663233572);
+INSERT INTO `x_system_auth_menu` VALUES (502, 501, 'C', '网站信息', '', 0, 'setting:website:detail', 'information', 'setting/website/information', '', '', 0, 1, 0, 1650341765, 1660202218);
+INSERT INTO `x_system_auth_menu` VALUES (503, 502, 'A', '保存配置', '', 0, 'setting:website:save', '', '', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (505, 501, 'C', '网站备案', '', 0, 'setting:copyright:detail', 'filing', 'setting/website/filing', '', '', 0, 1, 0, 1650341765, 1660202294);
+INSERT INTO `x_system_auth_menu` VALUES (506, 505, 'A', '备案保存', '', 0, 'setting:copyright:save', '', 'setting/website/protocol', '', '', 0, 0, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (510, 501, 'C', '政策协议', '', 0, 'setting:protocol:detail', 'protocol', 'setting/website/protocol', '', '', 0, 1, 0, 1660027606, 1660202312);
+INSERT INTO `x_system_auth_menu` VALUES (511, 510, 'A', '协议保存', '', 0, 'setting:protocol:save', '', '', '', '', 0, 0, 0, 1660027606, 1663670865);
+INSERT INTO `x_system_auth_menu` VALUES (515, 600, 'C', '字典管理', 'el-icon-Box', 0, 'setting:dict:type:list', 'dict', 'setting/dict/type/index', '', '', 0, 1, 0, 1660035436, 1663226087);
+INSERT INTO `x_system_auth_menu` VALUES (516, 515, 'A', '字典类型新增', '', 0, 'setting:dict:type:add', '', '', '', '', 0, 1, 0, 1660202761, 1660202761);
+INSERT INTO `x_system_auth_menu` VALUES (517, 515, 'A', '字典类型编辑', '', 0, 'setting:dict:type:edit', '', '', '', '', 0, 1, 0, 1660202842, 1660202842);
+INSERT INTO `x_system_auth_menu` VALUES (518, 515, 'A', '字典类型删除', '', 0, 'setting:dict:type:del', '', '', '', '', 0, 1, 0, 1660202903, 1660202903);
+INSERT INTO `x_system_auth_menu` VALUES (519, 600, 'C', '字典数据管理', '', 0, 'setting:dict:data:list', 'dict/data', 'setting/dict/data/index', '/dev_tools/dict', '', 0, 0, 0, 1660202948, 1663309252);
+INSERT INTO `x_system_auth_menu` VALUES (520, 515, 'A', '字典数据新增', '', 0, 'setting:dict:data:add', '', '', '', '', 0, 1, 0, 1660203117, 1660203117);
+INSERT INTO `x_system_auth_menu` VALUES (521, 515, 'A', '字典数据编辑', '', 0, 'setting:dict:data:edit', '', '', '', '', 0, 1, 0, 1660203142, 1660203142);
+INSERT INTO `x_system_auth_menu` VALUES (522, 515, 'A', '字典数据删除', '', 0, 'setting:dict:data:del', '', '', '', '', 0, 1, 0, 1660203159, 1660203159);
+INSERT INTO `x_system_auth_menu` VALUES (550, 500, 'M', '系统维护', 'el-icon-SetUp', 0, '', 'system', '', '', '', 0, 1, 0, 1650341765, 1660202466);
+INSERT INTO `x_system_auth_menu` VALUES (551, 550, 'C', '系统环境', '', 0, 'monitor:server', 'environment', 'setting/system/environment', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (552, 550, 'C', '系统缓存', '', 0, 'monitor:cache', 'cache', 'setting/system/cache', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (553, 550, 'C', '系统日志', '', 0, 'system:log:operate', 'journal', 'setting/system/journal', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (555, 500, 'C', '存储设置', 'el-icon-FolderOpened', 6, 'setting:storage:list', 'storage', 'setting/storage/index', '', '', 0, 1, 0, 1650341765, 1663312996);
+INSERT INTO `x_system_auth_menu` VALUES (556, 555, 'A', '保存配置', '', 0, 'setting:storage:edit', '', '', '', '', 0, 1, 0, 1650341765, 1650341765);
+INSERT INTO `x_system_auth_menu` VALUES (600, 0, 'M', '开发工具', 'el-icon-EditPen', 0, '', 'dev_tools', '', '', '', 0, 1, 0, 1660027606, 1664335701);
+INSERT INTO `x_system_auth_menu` VALUES (610, 600, 'C', '代码生成器', 'el-icon-DocumentAdd', 0, 'gen:list', 'code', 'dev_tools/code/index', '', '', 0, 1, 0, 1660028954, 1660532510);
+INSERT INTO `x_system_auth_menu` VALUES (611, 610, 'A', '导入数据表', '', 0, 'gen:importTable', '', '', '', '', 0, 1, 0, 1660532389, 1660532389);
+INSERT INTO `x_system_auth_menu` VALUES (612, 610, 'A', '生成代码', '', 0, 'gen:genCode', '', '', '', '', 0, 1, 0, 1660532421, 1660532421);
+INSERT INTO `x_system_auth_menu` VALUES (613, 610, 'A', '下载代码', '', 0, 'gen:downloadCode', '', '', '', '', 0, 1, 0, 1660532437, 1660532437);
+INSERT INTO `x_system_auth_menu` VALUES (614, 610, 'A', '预览代码', '', 0, 'gen:previewCode', '', '', '', '', 0, 1, 0, 1660532549, 1660532549);
+INSERT INTO `x_system_auth_menu` VALUES (616, 610, 'A', '同步表结构', '', 0, 'gen:syncTable', '', '', '', '', 0, 1, 0, 1660532781, 1660532781);
+INSERT INTO `x_system_auth_menu` VALUES (617, 610, 'A', '删除数据表', '', 0, 'gen:delTable', '', '', '', '', 0, 1, 0, 1660532800, 1660532800);
+INSERT INTO `x_system_auth_menu` VALUES (618, 610, 'A', '数据表详情', '', 0, 'gen:detail', '', '', '', '', 0, 1, 0, 1660532964, 1660532977);
+INSERT INTO `x_system_auth_menu` VALUES (700, 0, 'M', '素材管理', 'el-icon-Picture', 43, '', 'material', '', '', '', 0, 1, 0, 1660203293, 1663300847);
+INSERT INTO `x_system_auth_menu` VALUES (701, 700, 'C', '素材中心', 'el-icon-PictureRounded', 0, '', 'index', 'material/index', '', '', 0, 1, 0, 1660203402, 1663301493);
+INSERT INTO `x_system_auth_menu` VALUES (775, 600, 'C', '代码生成器编辑', 'el-icon-EditPen', 0, 'gen:editTable', 'dev_tools/code/edit', 'dev_tools/code/edit', '', '', 0, 0, 0, 1699344389, 1699344389);
+INSERT INTO `x_system_auth_menu` VALUES (776, 0, 'C', '产品', 'el-icon-Aim', 0, '', 'product/index', 'product/index', '', '', 1, 1, 0, 1699719599, 1699719599);
+INSERT INTO `x_system_auth_menu` VALUES (777, 0, 'C', 'article_collect', '', 0, 'article_collect:list', 'article_collect/index', 'article_collect/index', '', '', 1, 1, 0, 1700329092, 1700329092);
+
+-- ----------------------------
+-- Table structure for x_system_auth_perm
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_perm`;
+CREATE TABLE `x_system_auth_perm` (
+ `id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '主键',
+ `role_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '角色ID',
+ `menu_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '菜单ID',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统角色菜单表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_perm
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_system_auth_post
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_post`;
+CREATE TABLE `x_system_auth_post` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `code` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '岗位编码',
+ `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '岗位名称',
+ `remarks` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '岗位备注',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '岗位排序',
+ `is_stop` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否停用: 0=否, 1=是',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统岗位管理表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_post
+-- ----------------------------
+INSERT INTO `x_system_auth_post` VALUES (1, 'a', '啊', 'aa', 0, 0, 1, 1699718138, 1699718141, 0);
+
+-- ----------------------------
+-- Table structure for x_system_auth_role
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_auth_role`;
+CREATE TABLE `x_system_auth_role` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色名称',
+ `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注信息',
+ `sort` smallint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '角色排序',
+ `is_disable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁用: 0=否, 1=是',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统角色管理表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_auth_role
+-- ----------------------------
+INSERT INTO `x_system_auth_role` VALUES (1, '审核员', '审核数据', 0, 0, 1668679451, 1699458583);
+
+-- ----------------------------
+-- Table structure for x_system_config
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_config`;
+CREATE TABLE `x_system_config` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '类型',
+ `name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '键',
+ `value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '值',
+ `create_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 81 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统全局配置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_config
+-- ----------------------------
+INSERT INTO `x_system_config` VALUES (1, 'storage', 'default', 'local', 1660620367, 1662620927);
+INSERT INTO `x_system_config` VALUES (2, 'storage', 'local', '{\"name\":\"本地存储\"}', 1660620367, 1662620927);
+INSERT INTO `x_system_config` VALUES (3, 'storage', 'qiniu', '{\"name\":\"七牛云存储\",\"bucket\":\"\",\"secretKey\":\"\",\"accessKey\":\"\",\"domain\":\"\"}', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (4, 'storage', 'aliyun', '{\"name\":\"阿里云存储\",\"bucket\":\"\",\"secretKey\":\"\",\"accessKey\":\"\",\"domain\":\"\"}', 1660620367, 1662620071);
+INSERT INTO `x_system_config` VALUES (5, 'storage', 'qcloud', '{\"name\":\"腾讯云存储\",\"bucket\":\"\",\"secretKey\":\"\",\"accessKey\":\"\",\"domain\":\"\",\"region\":\"\"}', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (6, 'sms', 'default', 'aliyun', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (7, 'sms', 'aliyun', '{\"name\":\"阿里云短信\",\"alias\":\"aliyun\",\"sign\":\"\",\"appKey\":\"\",\"secretKey\":\"\"}', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (8, 'sms', 'tencent', '{\"name\":\"腾讯云短信\",\"alias\":\"tencent\",\"sign\":\"\",\"appId\":\"\",\"secretId\":\"\",\"secretKey\":\"\"}', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (9, 'sms', 'huawei', '{\"name\":\"华为云短信\",\"alias\":\"huawei\"}', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (10, 'website', 'name', 'Admin开源后台', 1660620367, 1699524151);
+INSERT INTO `x_system_config` VALUES (11, 'website', 'logo', '/api/static/backend_logo.png', 1660620367, 1699524151);
+INSERT INTO `x_system_config` VALUES (12, 'website', 'favicon', '/api/static/backend_favicon.ico', 1660620367, 1699524151);
+INSERT INTO `x_system_config` VALUES (13, 'website', 'backdrop', '/api/static/backend_backdrop.png', 1660620367, 1699524151);
+INSERT INTO `x_system_config` VALUES (14, 'website', 'copyright', '[{\"name\":\"LikeAdmin开源系统\",\"link\":\"http://www.beian.gov.cn\"}]', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (15, 'website', 'shopName', 'Admin开源系统', 1631255140, 1699524151);
+INSERT INTO `x_system_config` VALUES (16, 'website', 'shopLogo', '/api/static/shop_logo.png', 1631255140, 1699524151);
+INSERT INTO `x_system_config` VALUES (17, 'protocol', 'service', '{\"name\":\"服务协议\",\"content\":\"\\u003cp\\u003e服务协议\\u003c/p\\u003e\"}', 1660620367, 1699496132);
+INSERT INTO `x_system_config` VALUES (18, 'protocol', 'privacy', '{\"name\":\"隐私协议\",\"content\":\"\\u003cp\\u003e隐私协议\\u003c/p\\u003e\"}', 1660620367, 1699496132);
+INSERT INTO `x_system_config` VALUES (19, 'tabbar', 'style', '{\"defaultColor\":\"#4A5DFF\",\"selectedColor\":\"#EA5455\"}', 1660620367, 1662544900);
+INSERT INTO `x_system_config` VALUES (20, 'search', 'isHotSearch', '0', 1660620367, 1662546997);
+INSERT INTO `x_system_config` VALUES (30, 'h5_channel', 'status', '1', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (31, 'h5_channel', 'close', '0', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (32, 'h5_channel', 'url', '', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (40, 'mp_channel', 'name', '', 1660620367, 1662551403);
+INSERT INTO `x_system_config` VALUES (41, 'mp_channel', 'primaryId', '', 1660620367, 1662551403);
+INSERT INTO `x_system_config` VALUES (42, 'mp_channel', 'appId', '', 1660620367, 1662551403);
+INSERT INTO `x_system_config` VALUES (43, 'mp_channel', 'appSecret', '', 1660620367, 1662551403);
+INSERT INTO `x_system_config` VALUES (44, 'mp_channel', 'qrCode', '', 1660620367, 1662551403);
+INSERT INTO `x_system_config` VALUES (50, 'wx_channel', 'appId', '', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (51, 'wx_channel', 'appSecret', '', 1660620367, 1660620367);
+INSERT INTO `x_system_config` VALUES (55, 'oa_channel', 'name', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (56, 'oa_channel', 'primaryId', ' ', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (57, 'oa_channel', 'qrCode', '', 1662551337, 1662551337);
+INSERT INTO `x_system_config` VALUES (58, 'oa_channel', 'appId', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (59, 'oa_channel', 'appSecret', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (60, 'oa_channel', 'url', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (61, 'oa_channel', 'token', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (62, 'oa_channel', 'encodingAesKey', '', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (63, 'oa_channel', 'encryptionType', '1', 1660620367, 1662551337);
+INSERT INTO `x_system_config` VALUES (64, 'oa_channel', 'menus', '[]', 1631255140, 1663118712);
+INSERT INTO `x_system_config` VALUES (70, 'login', 'loginWay', '1,2', 1660620367, 1662538771);
+INSERT INTO `x_system_config` VALUES (71, 'login', 'forceBindMobile', '0', 1660620367, 1662538771);
+INSERT INTO `x_system_config` VALUES (72, 'login', 'openAgreement', '1', 1660620367, 1662538771);
+INSERT INTO `x_system_config` VALUES (73, 'login', 'openOtherAuth', '1', 1660620367, 1662538771);
+INSERT INTO `x_system_config` VALUES (74, 'login', 'autoLoginAuth', '1,2', 1660620367, 1662538771);
+INSERT INTO `x_system_config` VALUES (80, 'user', 'defaultAvatar', '/api/static/default_avatar.png', 1660620367, 1662535156);
+
+-- ----------------------------
+-- Table structure for x_system_log_login
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_log_login`;
+CREATE TABLE `x_system_log_login` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '注解',
+ `admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '管理员ID',
+ `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登录账号',
+ `ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录地址',
+ `os` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作系统',
+ `browser` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '浏览器',
+ `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '操作状态: 1=成功, 2=失败',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统登录日志表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_log_login
+-- ----------------------------
+INSERT INTO `x_system_log_login` VALUES (1, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699342613);
+INSERT INTO `x_system_log_login` VALUES (2, 0, 'admin', '127.0.0.1', 'Windows', 'Edge', 0, 1699343960);
+INSERT INTO `x_system_log_login` VALUES (3, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 0, 1699343975);
+INSERT INTO `x_system_log_login` VALUES (4, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699343985);
+INSERT INTO `x_system_log_login` VALUES (5, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699454100);
+INSERT INTO `x_system_log_login` VALUES (6, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699454113);
+INSERT INTO `x_system_log_login` VALUES (7, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699456315);
+INSERT INTO `x_system_log_login` VALUES (8, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699493828);
+INSERT INTO `x_system_log_login` VALUES (9, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699507466);
+INSERT INTO `x_system_log_login` VALUES (10, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699547693);
+INSERT INTO `x_system_log_login` VALUES (11, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699705884);
+INSERT INTO `x_system_log_login` VALUES (12, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699706435);
+INSERT INTO `x_system_log_login` VALUES (13, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699707397);
+INSERT INTO `x_system_log_login` VALUES (14, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699715636);
+INSERT INTO `x_system_log_login` VALUES (15, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1699803153);
+INSERT INTO `x_system_log_login` VALUES (16, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700142837);
+INSERT INTO `x_system_log_login` VALUES (17, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700150134);
+INSERT INTO `x_system_log_login` VALUES (18, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700298162);
+INSERT INTO `x_system_log_login` VALUES (19, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700381343);
+INSERT INTO `x_system_log_login` VALUES (20, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700402870);
+INSERT INTO `x_system_log_login` VALUES (21, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700449387);
+INSERT INTO `x_system_log_login` VALUES (22, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700462131);
+INSERT INTO `x_system_log_login` VALUES (23, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700493100);
+INSERT INTO `x_system_log_login` VALUES (24, 1, 'admin', '127.0.0.1', 'Windows', 'Edge', 1, 1700493528);
+
+-- ----------------------------
+-- Table structure for x_system_log_operate
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_log_operate`;
+CREATE TABLE `x_system_log_operate` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作人ID',
+ `type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求类型: GET/POST/PUT',
+ `title` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作标题',
+ `ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求IP',
+ `url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求接口',
+ `method` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '请求方法',
+ `args` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求参数',
+ `error` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '错误信息',
+ `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '执行状态: 1=成功, 2=失败',
+ `start_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '开始时间',
+ `end_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '结束时间',
+ `task_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '执行耗时',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 197 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统操作日志表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_log_operate
+-- ----------------------------
+INSERT INTO `x_system_log_operate` VALUES (1, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/routers/system.roleHandler.list-fm', 'pageNo=1&pageSize=15', '', 1, 1699343137, 1699343138, 4, 1699343138);
+INSERT INTO `x_system_log_operate` VALUES (187, 1, 'POST', '上传图片', '127.0.0.1', '/api/common/upload/image', 'likeadmin/admin/common/upload.uploadHandler.uploadImage-fm', '5c8950e543e8046320.mp3', 'Error #01: 300:不被支持的图片扩展: mp3\n', 2, 1700465126, 1700465126, 161, 1700465126);
+INSERT INTO `x_system_log_operate` VALUES (188, 1, 'POST', '上传图片', '127.0.0.1', '/api/common/upload/image', 'likeadmin/admin/common/upload.uploadHandler.uploadImage-fm', 'hrxz.com-30nsh0dvpby60530.mp3', 'Error #01: 300:不被支持的图片扩展: mp3\n', 2, 1700465176, 1700465176, 1, 1700465176);
+INSERT INTO `x_system_log_operate` VALUES (189, 1, 'POST', '上传图片', '127.0.0.1', '/api/common/upload/image', 'likeadmin/admin/common/upload.uploadHandler.uploadImage-fm', 'yiji.mp3', 'Error #01: 300:不被支持的图片扩展: mp3\n', 2, 1700465204, 1700465204, 10, 1700465204);
+INSERT INTO `x_system_log_operate` VALUES (190, 1, 'POST', '上传视频', '127.0.0.1', '/api/common/upload/video', 'likeadmin/admin/common/upload.uploadHandler.uploadVideo-fm', '素材中心 和另外 1 个页面 - 个人 - Microsoft Edge 2023-11-20 15-37-39.mp4', '', 1, 1700465870, 1700465870, 85, 1700465870);
+INSERT INTO `x_system_log_operate` VALUES (191, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700466101, 1700466101, 26, 1700466101);
+INSERT INTO `x_system_log_operate` VALUES (192, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700466116, 1700466116, 3, 1700466116);
+INSERT INTO `x_system_log_operate` VALUES (193, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700493553, 1700493553, 1, 1700493553);
+INSERT INTO `x_system_log_operate` VALUES (194, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700494088, 1700494088, 2, 1700494088);
+INSERT INTO `x_system_log_operate` VALUES (195, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700494182, 1700494182, 7, 1700494182);
+INSERT INTO `x_system_log_operate` VALUES (196, 1, 'GET', '角色列表', '127.0.0.1', '/api/system/role/list', 'likeadmin/admin/system/role.RoleHandler.List-fm', 'pageNo=1&pageSize=15', '', 1, 1700497573, 1700497573, 2, 1700497573);
+
+-- ----------------------------
+-- Table structure for x_system_log_sms
+-- ----------------------------
+DROP TABLE IF EXISTS `x_system_log_sms`;
+CREATE TABLE `x_system_log_sms` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `scene` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '场景编号',
+ `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号码',
+ `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '发送内容',
+ `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '发送状态:[0=发送中, 1=发送成功, 2=发送失败]',
+ `results` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '短信结果',
+ `send_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '发送时间',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统短信日志表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_system_log_sms
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_user
+-- ----------------------------
+DROP TABLE IF EXISTS `x_user`;
+CREATE TABLE `x_user` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `sn` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '编号',
+ `avatar` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像',
+ `real_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '真实姓名',
+ `nickname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
+ `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户账号',
+ `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
+ `mobile` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户电话',
+ `salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '加密盐巴',
+ `sex` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户性别: [1=男, 2=女]',
+ `channel` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '注册渠道: [1=微信小程序, 2=微信公众号, 3=手机H5, 4=电脑PC, 5=苹果APP, 6=安卓APP]',
+ `is_disable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否禁用: [0=否, 1=是]',
+ `is_delete` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除: [0=否, 1=是]',
+ `last_login_ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最后登录IP',
+ `last_login_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后登录时间',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ `delete_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_user
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for x_user_auth
+-- ----------------------------
+DROP TABLE IF EXISTS `x_user_auth`;
+CREATE TABLE `x_user_auth` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `user_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
+ `openid` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Openid',
+ `unionid` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Unionid',
+ `client` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '客户端类型: [1=微信小程序, 2=微信公众号, 3=手机H5, 4=电脑PC, 5=苹果APP, 6=安卓APP]',
+ `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+ `update_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `openid`(`openid`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户授权表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of x_user_auth
+-- ----------------------------
+
+SET FOREIGN_KEY_CHECKS = 1;