diff --git a/server/addons/modules/addons.go b/server/addons/modules/addons.go new file mode 100644 index 0000000..11174d7 --- /dev/null +++ b/server/addons/modules/addons.go @@ -0,0 +1 @@ +package modules diff --git a/server/internal/global/init.go b/server/internal/global/init.go index d619b2e..e946f8a 100644 --- a/server/internal/global/init.go +++ b/server/internal/global/init.go @@ -27,6 +27,9 @@ import ( ) func Init(ctx context.Context) { + // 设置服务日志处理 + g.Log().SetHandlers(LoggingServeLogHandler) + _, err := g.Cfg().Get(ctx, "hotgo.debug") if err != nil { g.Log().Fatal(ctx, "配置读取异常:", err, "\r\n你确定 config/config.yaml 文件存在且格式正确吗?\r\n") @@ -45,9 +48,6 @@ func Init(ctx context.Context) { // 设置缓存适配器 cache.SetAdapter(ctx) - // 设置服务日志处理 - g.Log().SetHandlers(LoggingServeLogHandler) - // 启动服务监控 service.AdminMonitor().StartMonitor(ctx) diff --git a/server/internal/library/hggen/views/column_map.go b/server/internal/library/hggen/views/column_map.go index 010d189..f5e49b0 100644 --- a/server/internal/library/hggen/views/column_map.go +++ b/server/internal/library/hggen/views/column_map.go @@ -232,6 +232,15 @@ func HasColumn(masterFields []*sysin.GenCodesColumnListModel, column string) boo return false } +func HasColumnWithFormMode(masterFields []*sysin.GenCodesColumnListModel, column string) bool { + for _, field := range masterFields { + if field.FormMode == column { + return true + } + } + return false +} + func HasMaxSort(masterFields []*sysin.GenCodesColumnListModel) bool { return HasColumn(masterFields, "Sort") } @@ -247,5 +256,5 @@ func HasSwitch(headOps []string, masterFields []*sysin.GenCodesColumnListModel) if !gstr.InArray(headOps, "switch") { return false } - return HasColumn(masterFields, "Switch") + return HasColumnWithFormMode(masterFields, "Switch") } diff --git a/server/internal/library/hggen/views/curd.go b/server/internal/library/hggen/views/curd.go index 8f73925..bcaf10c 100644 --- a/server/internal/library/hggen/views/curd.go +++ b/server/internal/library/hggen/views/curd.go @@ -30,17 +30,18 @@ var Curd = gCurd{} type gCurd struct{} type CurdStep struct { - HasMaxSort bool `json:"hasMaxSort"` - HasAdd bool `json:"hasAdd"` - HasBatchDel bool `json:"hasBatchDel"` - HasExport bool `json:"hasExport"` - HasEdit bool `json:"hasEdit"` - HasDel bool `json:"hasDel"` - HasView bool `json:"hasView"` - HasStatus bool `json:"hasStatus"` - HasSwitch bool `json:"hasSwitch"` - HasCheck bool `json:"hasCheck"` - HasMenu bool `json:"hasMenu"` + HasMaxSort bool `json:"hasMaxSort"` + HasAdd bool `json:"hasAdd"` + HasBatchDel bool `json:"hasBatchDel"` + HasExport bool `json:"hasExport"` + HasNotFilterAuth bool `json:"hasNotFilterAuth"` + HasEdit bool `json:"hasEdit"` + HasDel bool `json:"hasDel"` + HasView bool `json:"hasView"` + HasStatus bool `json:"hasStatus"` + HasSwitch bool `json:"hasSwitch"` + HasCheck bool `json:"hasCheck"` + HasMenu bool `json:"hasMenu"` } type CurdOptionsJoin struct { @@ -144,6 +145,7 @@ func initStep(in *CurdPreviewInput) { in.options.Step.HasAdd = gstr.InArray(in.options.HeadOps, "add") in.options.Step.HasBatchDel = gstr.InArray(in.options.HeadOps, "batchDel") in.options.Step.HasExport = gstr.InArray(in.options.HeadOps, "export") + in.options.Step.HasNotFilterAuth = gstr.InArray(in.options.ColumnOps, "notFilterAuth") in.options.Step.HasEdit = gstr.InArray(in.options.ColumnOps, "edit") in.options.Step.HasDel = gstr.InArray(in.options.ColumnOps, "del") in.options.Step.HasView = gstr.InArray(in.options.ColumnOps, "view") diff --git a/server/internal/library/hggen/views/curd_generate_logic.go b/server/internal/library/hggen/views/curd_generate_logic.go index 382f52a..788f012 100644 --- a/server/internal/library/hggen/views/curd_generate_logic.go +++ b/server/internal/library/hggen/views/curd_generate_logic.go @@ -21,8 +21,9 @@ const ( LogicListSimpleSelect = "\tfields, err := hgorm.GenSelect(ctx, sysin.%sListModel{}, dao.%s)\n\tif err != nil {\n\t\treturn\n\t}" LogicListJoinSelect = "\t//关联表select\n\tfields, err := hgorm.GenJoinSelect(ctx, %sin.%sListModel{}, dao.%s, []*hgorm.Join{\n%v\t})" LogicListJoinOnRelation = "\t// 关联表%s\n\tmod = mod.%s(hgorm.GenJoinOnRelation(\n\t\tdao.%s.Table(), dao.%s.Columns().%s, // 主表表名,关联字段\n\t\tdao.%s.Table(), \"%s\", dao.%s.Columns().%s, // 关联表表名,别名,关联字段\n\t)...)\n\n" - LogicEditUpdate = "\t\t_, err = s.Model(ctx).\n\t\t\tFieldsEx(\n%s\t\t\t).\n\t\t\tWhere(dao.%s.Columns().%s, in.%s).Data(in).Update()\n\t\treturn " + LogicEditUpdate = "\t\t_, err = s.Model(ctx%s).\n\t\t\tFieldsEx(\n%s\t\t\t).\n\t\t\tWhere(dao.%s.Columns().%s, in.%s).Data(in).Update()\n\t\treturn " LogicEditInsert = "\t_, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFieldsEx(\n%s\t\t).\n\t\tData(in).Insert()" + LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n" LogicSwitchUpdate = "g.Map{\n\t\tin.Key: in.Value,\n%s}" LogicStatusUpdate = "g.Map{\n\t\tdao.%s.Columns().Status: in.Status,\n%s}" ) @@ -66,7 +67,11 @@ func (l *gCurd) generateLogicSwitchUpdate(ctx context.Context, in *CurdPreviewIn func (l *gCurd) generateLogicSwitchFields(ctx context.Context, in *CurdPreviewInput) string { buffer := bytes.NewBuffer(nil) if in.options.Step.HasSwitch { - buffer.WriteString("\t\tdao." + in.In.DaoName + ".Columns().Switch,\n") + for _, field := range in.masterFields { + if field.FormMode == "Switch" { + buffer.WriteString("\t\tdao." + in.In.DaoName + ".Columns()." + field.GoName + ",\n") + } + } } return buffer.String() } @@ -78,6 +83,7 @@ func (l *gCurd) generateLogicEdit(ctx context.Context, in *CurdPreviewInput) g.M updateBuffer = bytes.NewBuffer(nil) insertFieldsEx = "" insertBuffer = bytes.NewBuffer(nil) + uniqueBuffer = bytes.NewBuffer(nil) ) for _, field := range in.masterFields { @@ -96,13 +102,23 @@ func (l *gCurd) generateLogicEdit(ctx context.Context, in *CurdPreviewInput) g.M if field.Index == consts.GenCodesIndexPK || field.GoName == "UpdatedBy" || field.GoName == "DeletedAt" { insertFieldsEx = insertFieldsEx + "\t\t\t\tdao." + in.In.DaoName + ".Columns()." + field.GoName + ",\n" } + + if field.Unique { + uniqueBuffer.WriteString(fmt.Sprintf(LogicEditUnique, field.GoName, in.In.DaoName, in.In.DaoName, field.GoName, field.GoName, field.Dc)) + } } - updateBuffer.WriteString(fmt.Sprintf(LogicEditUpdate, updateFieldsEx, in.In.DaoName, in.pk.GoName, in.pk.GoName)) + notFilterAuth := "" + if gstr.InArray(in.options.ColumnOps, "notFilterAuth") { + notFilterAuth = ", &handler.Option{FilterAuth: false}" + } + + updateBuffer.WriteString(fmt.Sprintf(LogicEditUpdate, notFilterAuth, updateFieldsEx, in.In.DaoName, in.pk.GoName, in.pk.GoName)) insertBuffer.WriteString(fmt.Sprintf(LogicEditInsert, insertFieldsEx)) data["update"] = updateBuffer.String() data["insert"] = insertBuffer.String() + data["unique"] = uniqueBuffer.String() return data } diff --git a/server/internal/library/hggen/views/curd_generate_web_model.go b/server/internal/library/hggen/views/curd_generate_web_model.go index 4ffcc95..c12b351 100644 --- a/server/internal/library/hggen/views/curd_generate_web_model.go +++ b/server/internal/library/hggen/views/curd_generate_web_model.go @@ -135,11 +135,15 @@ func (l *gCurd) generateWebModelRules(ctx context.Context, in *CurdPreviewInput) buffer := bytes.NewBuffer(nil) buffer.WriteString("export const rules = {\n") for _, field := range in.masterFields { - if field.FormRole == "" || field.FormRole == FormRoleNone { + if !field.IsEdit || (!field.Required && (field.FormRole == "" || field.FormRole == FormRoleNone)) { continue } - buffer.WriteString(fmt.Sprintf(" %s: {\n required: %v,\n trigger: ['blur', 'input'],\n message: '请输入%s',\n validator: validate.%v,\n },\n", field.TsName, field.Required, field.Dc, field.FormRole)) + if field.FormRole == "" || field.FormRole == FormRoleNone { + buffer.WriteString(fmt.Sprintf(" %s: {\n required: %v,\n trigger: ['blur', 'input'],\n type: '%s',\n message: '请输入%s',\n },\n", field.TsName, field.Required, field.TsType, field.Dc)) + } else { + buffer.WriteString(fmt.Sprintf(" %s: {\n required: %v,\n trigger: ['blur', 'input'],\n type: '%s',\n message: '请输入%s',\n validator: validate.%v,\n },\n", field.TsName, field.Required, field.TsType, field.Dc, field.FormRole)) + } } buffer.WriteString("};\n") return buffer.String() diff --git a/server/resource/generate/default/curd/logic.go.template b/server/resource/generate/default/curd/logic.go.template index 52b8858..67da6d5 100644 --- a/server/resource/generate/default/curd/logic.go.template +++ b/server/resource/generate/default/curd/logic.go.template @@ -47,7 +47,7 @@ func (s *s@{.servFunName}) Model(ctx context.Context, option ...*handler.Option) // List 获取@{.tableComment}列表 func (s *s@{.servFunName}) List(ctx context.Context, in @{.templateGroup}in.@{.varName}ListInp) (list []*@{.templateGroup}in.@{.varName}ListModel, totalCount int, err error) { - mod := s.Model(ctx) + mod := s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}) @{.listWhere} @{.listJoin.link} totalCount, err = mod.Clone().Count() @@ -89,6 +89,7 @@ func (s *s@{.servFunName}) Export(ctx context.Context, in @{.templateGroup}in.@{ @{ if eq .options.Step.HasEdit true } // Edit 修改/新增@{.tableComment} func (s *s@{.servFunName}) Edit(ctx context.Context, in @{.templateGroup}in.@{.varName}EditInp) (err error) { +@{.edit.unique} // 修改 if in.@{.pk.GoName} > 0 { @{.edit.update} @@ -102,7 +103,7 @@ func (s *s@{.servFunName}) Edit(ctx context.Context, in @{.templateGroup}in.@{.v @{ if eq .options.Step.HasDel true } // Delete 删除@{.tableComment} func (s *s@{.servFunName}) Delete(ctx context.Context, in @{.templateGroup}in.@{.varName}DeleteInp) (err error) { - _, err = s.Model(ctx).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Delete() + _, err = s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Delete() return }@{end} @{ if and (eq .options.Step.HasEdit true) (eq .options.Step.HasMaxSort true) } @@ -123,7 +124,7 @@ func (s *s@{.servFunName}) MaxSort(ctx context.Context, in @{.templateGroup}in.@ @{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } // View 获取@{.tableComment}指定信息 func (s *s@{.servFunName}) View(ctx context.Context, in @{.templateGroup}in.@{.varName}ViewInp) (res *@{.templateGroup}in.@{.varName}ViewModel, err error) { - err = s.Model(ctx).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Scan(&res) + err = s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Scan(&res) return }@{end} @{ if eq .options.Step.HasStatus true } @@ -144,7 +145,7 @@ func (s *s@{.servFunName}) Status(ctx context.Context, in @{.templateGroup}in.@{ return } - _, err = s.Model(ctx).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Data(@{.statusUpdate}).Update() + _, err = s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Data(@{.statusUpdate}).Update() return } @{end} @@ -161,7 +162,7 @@ func (s *s@{.servFunName}) Switch(ctx context.Context, in @{.templateGroup}in.@{ return } - _, err = s.Model(ctx).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Data(@{.switchUpdate}).Update() + _, err = s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}).Where(dao.@{.daoName}.Columns().@{.pk.GoName}, in.@{.pk.GoName}).Data(@{.switchUpdate}).Update() return } @{end} \ No newline at end of file diff --git a/server/resource/generate/default/curd/web.model.ts.template b/server/resource/generate/default/curd/web.model.ts.template index eb39741..ae0d193 100644 --- a/server/resource/generate/default/curd/web.model.ts.template +++ b/server/resource/generate/default/curd/web.model.ts.template @@ -3,7 +3,7 @@ import { NAvatar, NImage, NTag, NSwitch, NRate } from 'naive-ui'; import { cloneDeep } from 'lodash-es'; import { FormSchema } from '@/components/Form'; import { Dicts } from '@/api/dict/dict'; -@{ if eq .options.Step.HasSwitch true }import { Switch } from '@/api/@{.varName | LcFirst}';@{end} +@{ if eq .options.Step.HasSwitch true }import { Switch } from '@{.importWebApi}';@{end} import { isArray, isNullObject } from '@/utils/is'; import { getFileExt } from '@/utils/urlUtils'; import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil'; diff --git a/web/src/views/develop/code/components/BaseInfo.vue b/web/src/views/develop/code/components/BaseInfo.vue index 3757bf0..e6ca57d 100644 --- a/web/src/views/develop/code/components/BaseInfo.vue +++ b/web/src/views/develop/code/components/BaseInfo.vue @@ -104,7 +104,16 @@ - 主表中存在`switch`字段时才会生效 + 表单组件中存在`开关`类型才会生效 + + + + + 系统默认会过滤权限,勾选后强制不开启权限验证 diff --git a/web/src/views/develop/code/components/EditMasterCell.vue b/web/src/views/develop/code/components/EditMasterCell.vue index 2e9c3a5..7de4277 100644 --- a/web/src/views/develop/code/components/EditMasterCell.vue +++ b/web/src/views/develop/code/components/EditMasterCell.vue @@ -82,6 +82,7 @@ const dataSource = ref(formValue.value.masterColumns); async function reloadFields(loading = false) { + dataSource.value = []; if (loading) { show.value = true; } diff --git a/web/src/views/permission/menu/CreateDrawer.vue b/web/src/views/permission/menu/CreateDrawer.vue index e1eda44..8f7612c 100644 --- a/web/src/views/permission/menu/CreateDrawer.vue +++ b/web/src/views/permission/menu/CreateDrawer.vue @@ -115,7 +115,19 @@ + + + + + + + + + + + + + +