zoie 1 سال پیش
کامیت
5390fc81fb
100فایلهای تغییر یافته به همراه11518 افزوده شده و 0 حذف شده
  1. 41 0
      .gitignore
  2. 39 0
      app/admin/controller/captcha.go
  3. 182 0
      app/admin/controller/serv_api.go
  4. 330 0
      app/admin/controller/serv_menu.go
  5. 315 0
      app/admin/controller/sys_config.go
  6. 248 0
      app/admin/controller/sys_dept.go
  7. 221 0
      app/admin/controller/sys_dict_data_controller.go
  8. 211 0
      app/admin/controller/sys_dict_type_controller.go
  9. 123 0
      app/admin/controller/sys_login_log_controller.go
  10. 210 0
      app/admin/controller/sys_menu.go
  11. 128 0
      app/admin/controller/sys_opera_log_controller.go
  12. 203 0
      app/admin/controller/sys_post.go
  13. 188 0
      app/admin/controller/sys_register_auth.go
  14. 400 0
      app/admin/controller/sys_role.go
  15. 263 0
      app/admin/controller/sys_service.go
  16. 536 0
      app/admin/controller/sys_user.go
  17. 26 0
      app/admin/model/serv_api.go
  18. 43 0
      app/admin/model/serv_menu.go
  19. 25 0
      app/admin/model/serv_role_api.go
  20. 29 0
      app/admin/model/sys_config.go
  21. 47 0
      app/admin/model/sys_dept.go
  22. 34 0
      app/admin/model/sys_dict_data.go
  23. 28 0
      app/admin/model/sys_dict_type.go
  24. 72 0
      app/admin/model/sys_login_log.go
  25. 45 0
      app/admin/model/sys_menu.go
  26. 88 0
      app/admin/model/sys_opera_log.go
  27. 28 0
      app/admin/model/sys_post.go
  28. 29 0
      app/admin/model/sys_register_auth.go
  29. 35 0
      app/admin/model/sys_role.go
  30. 71 0
      app/admin/model/sys_role_menu.go
  31. 30 0
      app/admin/model/sys_service.go
  32. 77 0
      app/admin/model/sys_user.go
  33. 19 0
      app/admin/router/captcha.go
  34. 87 0
      app/admin/router/init_router.go
  35. 41 0
      app/admin/router/router.go
  36. 27 0
      app/admin/router/serv_api.go
  37. 28 0
      app/admin/router/serv_menu.go
  38. 43 0
      app/admin/router/sys_config.go
  39. 29 0
      app/admin/router/sys_dept.go
  40. 38 0
      app/admin/router/sys_dict.go
  41. 25 0
      app/admin/router/sys_login_log.go
  42. 32 0
      app/admin/router/sys_menu.go
  43. 24 0
      app/admin/router/sys_opera_log.go
  44. 25 0
      app/admin/router/sys_post.go
  45. 25 0
      app/admin/router/sys_register_auth.go
  46. 39 0
      app/admin/router/sys_role.go
  47. 35 0
      app/admin/router/sys_service.go
  48. 48 0
      app/admin/router/sys_user.go
  49. 110 0
      app/admin/service/dto/serv_api.go
  50. 149 0
      app/admin/service/dto/serv_menu.go
  51. 107 0
      app/admin/service/dto/sys_config.go
  52. 100 0
      app/admin/service/dto/sys_dept.go
  53. 120 0
      app/admin/service/dto/sys_dict_data_dto.go
  54. 99 0
      app/admin/service/dto/sys_dict_type_dto.go
  55. 58 0
      app/admin/service/dto/sys_login_log_dto.go
  56. 163 0
      app/admin/service/dto/sys_menu.go
  57. 103 0
      app/admin/service/dto/sys_opera_log_dto.go
  58. 107 0
      app/admin/service/dto/sys_post.go
  59. 115 0
      app/admin/service/dto/sys_register_auth.go
  60. 157 0
      app/admin/service/dto/sys_role.go
  61. 143 0
      app/admin/service/dto/sys_service.go
  62. 247 0
      app/admin/service/dto/sys_user.go
  63. 118 0
      app/admin/service/serv_api.go
  64. 356 0
      app/admin/service/serv_menu.go
  65. 178 0
      app/admin/service/sys_config.go
  66. 443 0
      app/admin/service/sys_dept.go
  67. 116 0
      app/admin/service/sys_dict_data_service.go
  68. 117 0
      app/admin/service/sys_dict_type_service.go
  69. 72 0
      app/admin/service/sys_login_log_service.go
  70. 467 0
      app/admin/service/sys_menu.go
  71. 84 0
      app/admin/service/sys_opera_log_service.go
  72. 106 0
      app/admin/service/sys_post.go
  73. 121 0
      app/admin/service/sys_register_auth.go
  74. 487 0
      app/admin/service/sys_role.go
  75. 182 0
      app/admin/service/sys_service.go
  76. 371 0
      app/admin/service/sys_user.go
  77. 72 0
      app/jobs/controller/sys_job.go
  78. 205 0
      app/jobs/jobbase.go
  79. 75 0
      app/jobs/jobs.go
  80. 62 0
      app/jobs/model/sys_job.go
  81. 35 0
      app/jobs/router/int_router.go
  82. 42 0
      app/jobs/router/router.go
  83. 39 0
      app/jobs/router/sys_job.go
  84. 108 0
      app/jobs/service/dto/sys_job.go
  85. 92 0
      app/jobs/service/sys_job.go
  86. 16 0
      app/jobs/type.go
  87. 8 0
      cmd/api/jobs.go
  88. 201 0
      cmd/api/server.go
  89. 51 0
      cmd/cobra.go
  90. 62 0
      cmd/config/server.go
  91. 63 0
      cmd/migrate/initdb.go
  92. 41 0
      cmd/migrate/server.go
  93. 49 0
      common/actions/create.go
  94. 61 0
      common/actions/delete.go
  95. 58 0
      common/actions/index.go
  96. 128 0
      common/actions/permission.go
  97. 5 0
      common/actions/type.go
  98. 59 0
      common/actions/update.go
  99. 67 0
      common/actions/view.go
  100. 13 0
      common/middleware/handler/dept.go

+ 41 - 0
.gitignore

@@ -0,0 +1,41 @@
+# ---> Go
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
+
+# local
+.idea
+/_
+/.cache
+.vscode/
+/logs/logx
+lastupdate.tmp
+main
+nohup.out
+/bin
+Makefile
+ofile
+./setting.yml
+./settings.yml
+

+ 39 - 0
app/admin/controller/captcha.go

@@ -0,0 +1,39 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/captcha"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type SystemController struct {
+	api.Api
+}
+
+// GenerateCaptchaHandler 获取验证码
+// @Summary 获取验证码
+// @Description 获取验证码
+// @Tags 登录
+// @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}"
+// @Router /api/captcha [get]
+func (e SystemController) GenerateCaptchaHandler(c *gin.Context) {
+	err := e.MakeContext(c).Errors
+	if err != nil {
+		e.Error(500, err, "服务初始化失败!")
+		return
+	}
+	id, b64s, err := captcha.DriverDigitFunc()
+	if err != nil {
+		e.Logger.Errorf("DriverDigitFunc error, %s", err.Error())
+		e.Error(500, err, "验证码获取失败")
+		return
+	}
+	e.Custom(gin.H{
+		"code": 200,
+		"data": b64s,
+		"id":   id,
+		"msg":  "success",
+	})
+}

+ 182 - 0
app/admin/controller/serv_api.go

@@ -0,0 +1,182 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type ServApi struct {
+	api.Api
+}
+
+// GetPage 获取接口列表
+// @Summary 获取接口列表
+// @Description 获取接口列表
+// @Tags 服务接口
+// @Param serviceId query string true "服务ID"
+// @Param title query string false "接口名称"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.ServApi}} "{"code": 200, "data": [...]}"
+// @Router /api/serv-api [get]
+// @Security Bearer
+func (e ServApi) GetPage(c *gin.Context) {
+	s := service.ServApi{}
+	req := dto.ServApiGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var list = make([]model.ServApi, 0)
+
+	var count int64
+	err = s.GetPage(&req, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取接口
+// @Summary 通过id获取接口
+// @Description 通过id获取接口
+// @Tags 服务接口
+// @Param id path string true "接口id"
+// @Success 200 {object} response.Response{data=model.ServApi} "{"code": 200, "data": [...]}"
+// @Router /api/serv-api/{id} [get]
+// @Security Bearer
+func (e ServApi) Get(c *gin.Context) {
+	req := dto.ServApiGetReq{}
+	s := service.ServApi{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object = model.ServApi{}
+	err = s.Get(&req, &object)
+	if err != nil {
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建接口
+// @Summary 创建接口
+// @Description 创建接口
+// @Tags 服务接口
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ServApiInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-api [post]
+// @Security Bearer
+func (e ServApi) Insert(c *gin.Context) {
+	req := dto.ServApiInsertReq{}
+	s := service.ServApi{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	// 设置创建人
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改接口
+// @Summary 修改接口
+// @Description 修改接口
+// @Tags 服务接口
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "接口id"
+// @Param data body dto.ServApiUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-api/{id} [put]
+// @Security Bearer
+func (e ServApi) Update(c *gin.Context) {
+	s := service.ServApi{}
+	req := dto.ServApiUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除接口
+// @Summary 删除接口
+// @Description 删除接口
+// @Tags 服务接口
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ServApiDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-api [delete]
+// @Security Bearer
+func (e ServApi) Delete(c *gin.Context) {
+	s := service.ServApi{}
+	req := dto.ServApiDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Logger.Errorf("RemoveServApi error, %s", err)
+		e.Error(500, err, "删除失败")
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}

+ 330 - 0
app/admin/controller/serv_menu.go

@@ -0,0 +1,330 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"encoding/json"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"github.com/tealeg/xlsx"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"os"
+)
+
+type ServMenu struct {
+	api.Api
+}
+
+// GetPage 获取菜单列表
+// @Summary 获取菜单列表
+// @Description 获取菜单列表
+// @Tags 服务菜单
+// @Param serviceId query string true "服务ID"
+// @Param name query string false "菜单名称"
+// @Param visible query string false "显示状态"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.ServMenu}} "{"code": 200, "data": [...]}"
+// @Router /api/serv-menu [get]
+// @Security Bearer
+func (e ServMenu) GetPage(c *gin.Context) {
+	s := service.ServMenu{}
+	serv := service.SysService{}
+	req := dto.ServMenuGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	// 查询服务信息
+	var servObject model.SysService
+	servReq := dto.SysServiceGetReq{Id: req.ServiceId}
+	err = serv.Get(&servReq, &servObject, nil)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var list = make([]model.ServMenu, 0)
+
+	if err = s.GetPage(&req, &list).Error; err != nil {
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(list, "查询成功")
+}
+
+// Get 通过id获取菜单
+// @Summary 通过id获取菜单
+// @Description 通过id获取菜单
+// @Tags 服务菜单
+// @Param id path string true "菜单id"
+// @Success 200 {object} response.Response{data=model.ServMenu} "{"code": 200, "data": [...]}"
+// @Router /api/serv-menu/{id} [get]
+// @Security Bearer
+func (e ServMenu) Get(c *gin.Context) {
+	req := dto.ServMenuGetReq{}
+	s := service.ServMenu{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object = model.ServMenu{}
+	err = s.Get(&req, &object).Error
+	if err != nil {
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建菜单
+// @Summary 创建菜单
+// @Description 创建菜单
+// @Tags 服务菜单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ServMenuInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-menu [post]
+// @Security Bearer
+func (e ServMenu) Insert(c *gin.Context) {
+	req := dto.ServMenuInsertReq{}
+	s := service.ServMenu{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	// 设置创建人
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req).Error
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改菜单
+// @Summary 修改菜单
+// @Description 修改菜单
+// @Tags 服务菜单
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "菜单id"
+// @Param data body dto.ServMenuUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-menu/{id} [put]
+// @Security Bearer
+func (e ServMenu) Update(c *gin.Context) {
+	s := service.ServMenu{}
+	req := dto.ServMenuUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req).Error
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除菜单
+// @Summary 删除菜单
+// @Description 删除菜单
+// @Tags 服务菜单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ServMenuDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/serv-menu [delete]
+// @Security Bearer
+func (e ServMenu) Delete(c *gin.Context) {
+	s := service.ServMenu{}
+	req := dto.ServMenuDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req).Error
+	if err != nil {
+		e.Logger.Errorf("RemoveServMenu error, %s", err)
+		e.Error(500, err, "删除失败")
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// Export 导出菜单
+// @Summary 导出菜单
+// @Description 导出菜单
+// @Tags 服务菜单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ServMenuExportReq true "body"
+// @Success 200 {object} response.Response "{"code": 200}"
+// @Router /api/serv-menu/export [get]
+// @Security Bearer
+func (e ServMenu) Export(c *gin.Context) {
+	s := service.ServMenu{}
+	serv := service.SysService{}
+	req := dto.ServMenuExportReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		MakeService(&serv.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	// 查询服务信息
+	var servObject model.SysService
+	servReq := dto.SysServiceGetReq{Id: req.ServiceId}
+	err = serv.Get(&servReq, &servObject, nil)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	if req.Type == "json" {
+		var list = make([]model.ServMenu, 0)
+		jsonReq := dto.ServMenuGetPageReq{
+			ServiceId: req.ServiceId,
+		}
+		if err = s.GetPage(&jsonReq, &list).Error; err != nil {
+			e.Error(500, err, "查询失败")
+			return
+		}
+		jsonBytes, err := json.Marshal(list)
+		if err != nil {
+			e.Error(500, err, err.Error())
+			return
+		}
+
+		filename := fmt.Sprintf("%s菜单.json", servObject.Name)
+		file, err := os.Create(filename)
+		if err != nil {
+			e.Error(500, err, err.Error())
+			return
+		}
+		defer file.Close()
+
+		if _, err := file.Write(jsonBytes); err != nil {
+			e.Error(500, err, err.Error())
+			return
+		}
+		c.Header("Content-Disposition", "attachment; filename="+filename)
+		c.Header("Content-Type", "application/octet-stream")
+		c.FileAttachment(filename, file.Name())
+	}
+
+	if req.Type == "excel" {
+
+		var list = make([]model.ServMenu, 0)
+		jsonReq := dto.ServMenuGetPageReq{
+			ServiceId: req.ServiceId,
+		}
+		if err = s.GetList(&jsonReq, &list); err != nil {
+			e.Error(500, err, "查询失败")
+			return
+		}
+		file := xlsx.NewFile()
+		sheet, err := file.AddSheet("Sheet1")
+		if err != nil {
+			e.Error(500, err, err.Error())
+			return
+		}
+
+		// Add header row
+		headerRow := sheet.AddRow()
+		headerRow.AddCell().SetValue("id")
+		headerRow.AddCell().SetValue("service_id")
+		headerRow.AddCell().SetValue("menu_path")
+		headerRow.AddCell().SetValue("parent_id")
+		headerRow.AddCell().SetValue("name")
+		headerRow.AddCell().SetValue("sort")
+		headerRow.AddCell().SetValue("menu_type")
+		headerRow.AddCell().SetValue("icon")
+		headerRow.AddCell().SetValue("component")
+		headerRow.AddCell().SetValue("is_frame")
+		headerRow.AddCell().SetValue("path")
+		headerRow.AddCell().SetValue("permission")
+		headerRow.AddCell().SetValue("visible")
+
+		// Add data rows
+		for _, v := range list {
+			dataRow := sheet.AddRow()
+			dataRow.AddCell().SetValue(v.Id)
+			dataRow.AddCell().SetValue(v.ServiceId)
+			dataRow.AddCell().SetValue(v.MenuPath)
+			dataRow.AddCell().SetValue(v.ParentId)
+			dataRow.AddCell().SetValue(v.Name)
+			dataRow.AddCell().SetValue(v.Sort)
+			dataRow.AddCell().SetValue(v.MenuType)
+			dataRow.AddCell().SetValue(v.Icon)
+			dataRow.AddCell().SetValue(v.Component)
+			dataRow.AddCell().SetValue(v.IsFrame)
+			dataRow.AddCell().SetValue(v.Path)
+			dataRow.AddCell().SetValue(v.Permission)
+			dataRow.AddCell().SetValue(v.Visible)
+		}
+		filename := fmt.Sprintf("%s菜单.xlsx", servObject.Name)
+
+		// Set content type and headers
+		c.Header("Content-Disposition", "attachment; filename="+filename)
+		c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+
+		// Write file to response
+		err = file.Write(c.Writer)
+		if err != nil {
+			e.Error(500, err, err.Error())
+			return
+		}
+		c.FileAttachment(filename, filename)
+	}
+
+	e.Error(500, err, "类型错误!")
+	return
+}

+ 315 - 0
app/admin/controller/sys_config.go

@@ -0,0 +1,315 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+)
+
+type SysConfig struct {
+	api.Api
+}
+
+// GetPage 获取配置管理列表
+// @Summary 获取配置管理列表
+// @Description 获取配置管理列表
+// @Tags 配置管理
+// @Param configName query string false "名称"
+// @Param configKey query string false "key"
+// @Param configType query string false "类型"
+// @Param isFrontend query int false "是否前端"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysConfig}} "{"code": 200, "data": [...]}"
+// @Router /api/sys-config [get]
+// @Security Bearer
+func (e SysConfig) GetPage(c *gin.Context) {
+	s := service.SysConfig{}
+	req := dto.SysConfigGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysConfig, 0)
+	var count int64
+	err = s.GetPage(&req, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 获取配置管理
+// @Summary 获取配置管理
+// @Description 获取配置管理
+// @Tags 配置管理
+// @Param id path string false "id"
+// @Success 200 {object} response.Response{data=model.SysConfig} "{"code": 200, "data": [...]}"
+// @Router /api/sys-config/{id} [get]
+// @Security Bearer
+func (e SysConfig) Get(c *gin.Context) {
+	req := dto.SysConfigGetReq{}
+	s := service.SysConfig{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysConfig
+
+	err = s.Get(&req, &object)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建配置管理
+// @Summary 创建配置管理
+// @Description 创建配置管理
+// @Tags 配置管理
+// @Accept application/json
+// @Product application/json
+// @Param data body dto.SysConfigControl true "body"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "创建成功"}"
+// @Router /api/sys-config [post]
+// @Security Bearer
+func (e SysConfig) Insert(c *gin.Context) {
+	s := service.SysConfig{}
+	req := dto.SysConfigControl{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetCreateBy(user.GetUserId(c))
+
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改配置管理
+// @Summary 修改配置管理
+// @Description 修改配置管理
+// @Tags 配置管理
+// @Accept application/json
+// @Product application/json
+// @Param data body dto.SysConfigControl true "body"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}"
+// @Router /api/sys-config/{id} [put]
+// @Security Bearer
+func (e SysConfig) Update(c *gin.Context) {
+	s := service.SysConfig{}
+	req := dto.SysConfigControl{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除配置管理
+// @Summary 删除配置管理
+// @Description 删除配置管理
+// @Tags 配置管理
+// @Param ids body []int false "ids"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "删除成功"}"
+// @Router /api/sys-config [delete]
+// @Security Bearer
+func (e SysConfig) Delete(c *gin.Context) {
+	s := service.SysConfig{}
+	req := dto.SysConfigDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// Get2SysApp 获取系统配置信息
+// @Summary 获取系统前台配置信息,主要注意这里不在验证权限
+// @Description 获取系统配置信息,主要注意这里不在验证权限
+// @Tags 配置管理
+// @Success 200 {object} response.Response{data=map[string]string} "{"code": 200, "data": [...]}"
+// @Router /api/app-config [get]
+func (e SysConfig) Get2SysApp(c *gin.Context) {
+	req := dto.SysConfigGetToSysAppReq{}
+	s := service.SysConfig{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		return
+	}
+	// 控制只读前台的数据
+	req.IsFrontend = "1"
+	list := make([]model.SysConfig, 0)
+	err = s.GetWithKeyList(&req, &list)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	mp := make(map[string]string)
+	for i := 0; i < len(list); i++ {
+		key := list[i].ConfigKey
+		if key != "" {
+			mp[key] = list[i].ConfigValue
+		}
+	}
+	e.OK(mp, "查询成功")
+}
+
+// Get2Set 获取配置
+// @Summary 获取配置
+// @Description 界面操作设置配置值的获取
+// @Tags 配置管理
+// @Accept application/json
+// @Product application/json
+// @Success 200 {object} response.Response{data=map[string]interface{}}	"{"code": 200, "message": "获取成功"}"
+// @Router /api/set-config [get]
+// @Security Bearer
+func (e SysConfig) Get2Set(c *gin.Context) {
+	s := service.SysConfig{}
+	req := make([]dto.GetSetSysConfigReq, 0)
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	err = s.GetForSet(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	m := make(map[string]interface{}, 0)
+	for _, v := range req {
+		m[v.ConfigKey] = v.ConfigValue
+	}
+	e.OK(m, "查询成功")
+}
+
+// Update2Set 设置配置
+// @Summary 设置配置
+// @Description 界面操作设置配置值
+// @Tags 配置管理
+// @Accept application/json
+// @Product application/json
+// @Param data body []dto.GetSetSysConfigReq true "body"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}"
+// @Router /api/set-config [put]
+// @Security Bearer
+func (e SysConfig) Update2Set(c *gin.Context) {
+	s := service.SysConfig{}
+	req := make([]dto.GetSetSysConfigReq, 0)
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	err = s.UpdateForSet(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK("", "更新成功")
+}
+
+// GetSysConfigByKEYForService 根据Key获取SysConfig的Service
+// @Summary 根据Key获取SysConfig的Service
+// @Description 根据Key获取SysConfig的Service
+// @Tags 配置管理
+// @Param configKey path string false "configKey"
+// @Success 200 {object} response.Response{data=dto.SysConfigByKeyReq} "{"code": 200, "data": [...]}"
+// @Router /api/configKey/{{configKey}} [get]
+// @Security Bearer
+func (e SysConfig) GetSysConfigByKEYForService(c *gin.Context) {
+	s := service.SysConfig{}
+	req := dto.SysConfigByKeyReq{}
+	resp := dto.GetSysConfigByKEYForServiceResp{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	err = s.GetWithKey(&req, &resp)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(resp, s.Msg)
+}

+ 248 - 0
app/admin/controller/sys_dept.go

@@ -0,0 +1,248 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type SysDeptController struct {
+	api.Api
+}
+
+// GetPage 获取部门列表
+// @Summary 获取部门列表
+// @Description 获取部门列表
+// @Tags 部门
+// @Param deptName query string false "部门名称"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysDept}} "{"code": 200, "data": [...]}"
+// @Router /api/dept [get]
+// @Security Bearer
+func (e SysDeptController) GetPage(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Query).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	p.DeptId = user.GetDeptId(c)
+	req.DeptId = user.GetDeptId(c)
+	list := make([]model.SysDept, 0)
+	list, err = s.SetDeptPage(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(list, "查询成功")
+}
+
+// Get 通过id获取部门
+// @Summary 通过id获取部门
+// @Description 通过id获取部门
+// @Tags 部门
+// @Param id path string true "部门id"
+// @Success 200 {object} response.Response{data=model.SysDept} "{"code": 200, "data": [...]}"
+// @Router /api/dept/{id} [get]
+// @Security Bearer
+func (e SysDeptController) Get(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysDept
+	//数据权限检查
+	err = s.Get(&req, &object)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 添加部门
+// @Summary 添加部门
+// @Description 添加部门
+// @Tags 部门
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysDeptInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/dept [post]
+// @Security Bearer
+func (e SysDeptController) Insert(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	// 设置创建人
+	req.SetCreateBy(user.GetUserId(c))
+	deptId := user.GetDeptId(c)
+	err = s.Insert(&req, deptId)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改部门
+// @Summary 修改部门
+// @Description 修改部门
+// @Tags 部门
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "部门id"
+// @Param data body dto.SysDeptUpdateReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/dept [put]
+// @Security Bearer
+func (e SysDeptController) Update(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除部门
+// @Summary 删除部门
+// @Description 删除部门
+// @Tags 部门
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysDeptDeleteReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "删除成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "删除失败"}"
+// @Router /api/dept [delete]
+// @Security Bearer
+func (e SysDeptController) Delete(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptDeleteReq{}
+	userSvc := service.SysUser{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		MakeService(&userSvc.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var count int64
+	err = userSvc.GetCount(&dto.SysUserGetCountReq{DeptIds: []int{req.Id}}, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	if count > 0 {
+		e.Error(500, err, "有用户关联,禁止删除!")
+		return
+	}
+
+	//数据权限检查
+	//p := actions.GetPermissionFromContext(c)
+	err = s.Remove(&req, nil)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// Enter 进入部门
+// @Summary 删除部门
+// @Description 删除部门
+// @Tags 部门
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysDeptEnterReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "删除成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "删除失败"}"
+// @Router /api/dept/enter [post]
+// @Security Bearer
+func (e SysDeptController) Enter(c *gin.Context) {
+	s := service.SysDept{}
+	req := dto.SysDeptEnterReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var object model.SysDept
+	//数据权限检查
+	err = s.Get(&dto.SysDeptGetReq{
+		Id: req.Id,
+	}, &object)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	err = e.Cache.Set(model.GetEnterDeptCacheKey(user.GetUserId(c)), req.GetId(), -1)
+	err = e.Cache.Set(model.GetEnterDeptNameCacheKey(user.GetUserId(c)), object.DeptName, -1)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, "进入失败")
+		return
+	}
+	e.OK(req.GetId(), "进入成功")
+}

+ 221 - 0
app/admin/controller/sys_dict_data_controller.go

@@ -0,0 +1,221 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+)
+
+type SysDictDataController struct {
+	api.Api
+}
+
+// GetPage 获取字典数据列表
+// @Summary 获取字典数据列表
+// @Description 获取字典数据列表
+// @Tags 字典数据
+// @Param status query string false "status"
+// @Param dictCode query string false "dictCode"
+// @Param dictType query string false "dictType"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysDictData}} "{"code": 200, "data": [...]}"
+// @Router /api/dict/data [get]
+// @Security Bearer
+func (e SysDictDataController) GetPage(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysDictData, 0)
+	var count int64
+	err = s.GetPage(&req, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取字典数据
+// @Summary 通过id获取字典数据
+// @Description 通过id获取字典数据
+// @Tags 字典数据
+// @Param dictCode path int true "字典编码"
+// @Success 200 {object} response.Response{data=model.SysDictData} "{"code": 200, "data": [...]}"
+// @Router /api/dict/data/{dictCode} [get]
+// @Security Bearer
+func (e SysDictDataController) Get(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var object model.SysDictData
+
+	err = s.Get(&req, &object)
+	if err != nil {
+		e.Logger.Warnf("Get error: %s", err.Error())
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 添加字典数据
+// @Summary 添加字典数据
+// @Description 添加字典数据
+// @Tags 字典数据
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysDictDataInsertReq true "data"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "添加成功"}"
+// @Router /api/dict/data [post]
+// @Security Bearer
+func (e SysDictDataController) Insert(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改字典数据
+// @Summary 修改字典数据
+// @Description 修改字典数据
+// @Tags 字典数据
+// @Accept  application/json
+// @Product application/json
+// @Param dictCode path int true "字典编码"
+// @Param data body dto.SysDictDataUpdateReq true "body"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}"
+// @Router /api/dict/data/{dictCode} [put]
+// @Security Bearer
+func (e SysDictDataController) Update(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除字典数据
+// @Summary 删除字典数据
+// @Description 删除字典数据
+// @Tags 字典数据
+// @Param dictCode body dto.SysDictDataDeleteReq true "body"
+// @Success 200 {object} response.Response	"{"code": 200, "message": "删除成功"}"
+// @Router /api/dict/data [delete]
+// @Security Bearer
+func (e SysDictDataController) Delete(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// GetAll 通过key获取数据字典【业务页面使用】
+// @Summary 通过key获取数据字典【业务页面使用】
+// @Description 通过key获取数据字典【业务页面使用】
+// @Tags 字典数据
+// @Param dictType query string true "dictType"
+// @Success 200 {object} response.Response{data=[]dto.SysDictDataGetAllResp}  "{"code": 200, "data": [...]}"
+// @Router /api/dict-data/option-select [get]
+// @Security Bearer
+func (e SysDictDataController) GetAll(c *gin.Context) {
+	s := service.SysDictDataService{}
+	req := dto.SysDictDataGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Query).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	list := make([]model.SysDictData, 0)
+	err = s.GetAll(&req, &list)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	l := make([]dto.SysDictDataGetAllResp, 0)
+	for _, i := range list {
+		d := dto.SysDictDataGetAllResp{}
+		e.Translate(i, &d)
+		l = append(l, d)
+	}
+
+	e.OK(l, "查询成功")
+}

+ 211 - 0
app/admin/controller/sys_dict_type_controller.go

@@ -0,0 +1,211 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysDictTypeController struct {
+	api.Api
+}
+
+// GetPage 获取字典类型列表
+// @Summary 字典类型列表数据
+// @Description 字典类型列表数据
+// @Tags 字典类型
+// @Param dictName query string false "dictName"
+// @Param dictId query string false "dictId"
+// @Param dictType query string false "dictType"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysDictType}} "{"code": 200, "data": [...]}"
+// @Router /api/dict/type [get]
+// @Security Bearer
+func (e SysDictTypeController) GetPage(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	list := make([]model.SysDictType, 0)
+	var count int64
+	err = s.GetPage(&req, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取字典类型
+// @Summary 通过id获取字典类型
+// @Description 通过id获取字典类型
+// @Tags 字典类型
+// @Param id path int true "字典类型id"
+// @Success 200 {object} response.Response{data=model.SysDictType} "{"code": 200, "data": [...]}"
+// @Router /api/dict/type/{id} [get]
+// @Security Bearer
+func (e SysDictTypeController) Get(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysDictType
+	err = s.Get(&req, &object)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建字典类型
+// @Summary 添加字典类型
+// @Description 添加字典类型
+// @Tags 字典类型
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysDictTypeInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/dict/type [post]
+// @Security Bearer
+func (e SysDictTypeController) Insert(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改字典类型
+// @Summary 修改字典类型
+// @Description 修改字典类型
+// @Tags 字典类型
+// @Accept  application/json
+// @Product application/json
+// @Param id path int true "字典类型id"
+// @Param data body dto.SysDictTypeUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/dict/type/{id} [put]
+// @Security Bearer
+func (e SysDictTypeController) Update(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除字典类型
+// @Summary 删除字典类型
+// @Description 删除字典类型
+// @Tags 字典类型
+// @Param dictCode body dto.SysDictTypeDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/dict/type [delete]
+// @Security Bearer
+func (e SysDictTypeController) Delete(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// GetAll 字典类型查询【代码生成】
+// @Summary 字典类型查询【代码生成】
+// @Description 字典类型查询【代码生成】
+// @Tags 字典类型
+// @Param dictName query string false "dictName"
+// @Param dictId query string false "dictId"
+// @Param dictType query string false "dictType"
+// @Success 200 {object} response.Response{data=[]model.SysDictType}  "{"code": 200, "data": [...]}"
+// @Router /api/dict/type-option-select [get]
+// @Security Bearer
+func (e SysDictTypeController) GetAll(c *gin.Context) {
+	s := service.SysDictTypeService{}
+	req := dto.SysDictTypeGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	list := make([]model.SysDictType, 0)
+	err = s.GetAll(&req, &list)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(list, "查询成功")
+}

+ 123 - 0
app/admin/controller/sys_login_log_controller.go

@@ -0,0 +1,123 @@
+package controller
+
+import (
+	"Medical_OAuth/common/actions"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysLoginLogController struct {
+	api.Api
+}
+
+// GetPage 登录日志列表
+// @Summary 登录日志列表
+// @Description 登录日志列表
+// @Tags 登录日志
+// @Param username query string false "用户名"
+// @Param ipaddr query string false "ip地址"
+// @Param loginLocation  query string false "归属地"
+// @Param status query string false "状态"
+// @Param beginTime query string false "开始时间"
+// @Param endTime query string false "结束时间"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysLoginLog}} "{"code": 200, "data": [...]}"
+// @Router /api/sys-login-log [get]
+// @Security Bearer
+func (e SysLoginLogController) GetPage(c *gin.Context) {
+	s := service.SysLoginLogService{}
+	req := dto.SysLoginLogGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	list := make([]model.SysLoginLog, 0)
+	var count int64
+	err = s.GetPage(&req, &list, &count, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取登录日志
+// @Summary 通过id获取登录日志
+// @Description 通过id获取登录日志
+// @Tags 登录日志
+// @Param id path string true "登录日志id"
+// @Success 200 {object} response.Response{data=model.SysLoginLog} "{"code": 200, "data": [...]}"
+// @Router /api/sys-login-log/{id} [get]
+// @Security Bearer
+func (e SysLoginLogController) Get(c *gin.Context) {
+	s := service.SysLoginLogService{}
+	req := dto.SysLoginLogGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	var object model.SysLoginLog
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Delete 删除登录日志
+// @Summary 删除登录日志
+// @Description 删除登录日志
+// @Tags 登录日志
+// @Param data body dto.SysLoginLogDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/sys-login-log [delete]
+// @Security Bearer
+func (e SysLoginLogController) Delete(c *gin.Context) {
+	s := service.SysLoginLogService{}
+	req := dto.SysLoginLogDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}

+ 210 - 0
app/admin/controller/sys_menu.go

@@ -0,0 +1,210 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type SysMenuController struct {
+	api.Api
+}
+
+// GetPage 获取菜单列表
+// @Summary 获取菜单列表
+// @Description 获取菜单列表
+// @Tags 菜单
+// @Param menuName query string false "菜单名称"
+// @Param title query string false "显示名称"
+// @Param visible query string false "显示状态"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysMenu}} "{"code": 200, "data": [...]}"
+// @Router /api/menu [get]
+// @Security Bearer
+func (e SysMenuController) GetPage(c *gin.Context) {
+	s := service.SysMenu{}
+	req := dto.SysMenuGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var list = make([]model.SysMenu, 0)
+	if err = s.GetPage(&req, &list).Error; err != nil {
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(list, "查询成功")
+}
+
+// Get 通过id获取菜单
+// @Summary 通过id获取菜单
+// @Description 通过id获取菜单
+// @Tags 菜单
+// @Param id path string true "菜单id"
+// @Success 200 {object} response.Response{data=model.SysMenu} "{"code": 200, "data": [...]}"
+// @Router /api/menu/{id} [get]
+// @Security Bearer
+func (e SysMenuController) Get(c *gin.Context) {
+	req := dto.SysMenuGetReq{}
+	s := service.SysMenu{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object = model.SysMenu{}
+	err = s.Get(&req, &object).Error
+	if err != nil {
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建菜单
+// @Summary 创建菜单
+// @Description 创建菜单
+// @Tags 菜单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysMenuInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/menu [post]
+// @Security Bearer
+func (e SysMenuController) Insert(c *gin.Context) {
+	req := dto.SysMenuInsertReq{}
+	s := service.SysMenu{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	// 设置创建人
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req).Error
+	if err != nil {
+		e.Error(500, err, "创建失败")
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改菜单
+// @Summary 修改菜单
+// @Description 修改菜单
+// @Tags 菜单
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "菜单id"
+// @Param data body dto.SysMenuUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/menu/{id} [put]
+// @Security Bearer
+func (e SysMenuController) Update(c *gin.Context) {
+	s := service.SysMenu{}
+	req := dto.SysMenuUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Update(&req).Error
+	if err != nil {
+		e.Error(500, err, "更新失败")
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除菜单
+// @Summary 删除菜单
+// @Description 删除菜单
+// @Tags 菜单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysMenuDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/menu [delete]
+// @Security Bearer
+func (e SysMenuController) Delete(c *gin.Context) {
+	s := service.SysMenu{}
+	req := dto.SysMenuDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req).Error
+	if err != nil {
+		e.Logger.Errorf("RemoveSysMenu error, %s", err)
+		e.Error(500, err, "删除失败")
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// GetMenuRole 根据登录角色名称获取菜单列表数据【左菜单使用】
+// @Summary 根据登录角色名称获取菜单列表数据【左菜单使用】
+// @Description 根据登录角色名称获取菜单列表数据【左菜单使用】
+// @Tags 菜单
+// @Success 200 {object} response.Response{data=[]model.SysMenu} "{"code": 200, "data": [...]}"
+// @Router /api/menu-role [get]
+// @Security Bearer
+func (e SysMenuController) GetMenuRole(c *gin.Context) {
+	s := new(service.SysMenu)
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	result, err := s.SetMenuRole(user.GetRoleName(c))
+
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(result, "")
+}

+ 128 - 0
app/admin/controller/sys_opera_log_controller.go

@@ -0,0 +1,128 @@
+package controller
+
+import (
+	"Medical_OAuth/common/actions"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysOperaLogController struct {
+	api.Api
+}
+
+// GetPage 操作日志列表
+// @Summary 操作日志列表
+// @Description 操作日志列表
+// @Tags 操作日志
+// @Param title query string false "title"
+// @Param method query string false "method"
+// @Param requestMethod  query string false "requestMethod"
+// @Param operaUrl query string false "operaUrl"
+// @Param operaIp query string false "operaIp"
+// @Param status query string false "status"
+// @Param beginTime query string false "beginTime"
+// @Param endTime query string false "endTime"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysOperaLog}} "{"code": 200, "data": [...]}"
+// @Router /api/sys-opera-log [get]
+// @Security Bearer
+func (e SysOperaLogController) GetPage(c *gin.Context) {
+	s := service.SysOperaLog{}
+	req := new(dto.SysOperaLogGetPageReq)
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysOperaLog, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetPage(req, &list, &count, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, "查询失败")
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取操作日志
+// @Summary 通过id获取操作日志
+// @Description 通过id获取操作日志
+// @Tags 操作日志
+// @Param id path string true "操作日志id"
+// @Success 200 {object} response.Response{data=model.SysOperaLog} "{"code": 200, "data": [...]}"
+// @Router /api/sys-opera-log/{id} [get]
+// @Security Bearer
+func (e SysOperaLogController) Get(c *gin.Context) {
+	s := new(service.SysOperaLog)
+	req := dto.SysOperaLogGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	var object model.SysOperaLog
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, "查询失败")
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Delete 删除操作日志
+// @Summary 删除操作日志
+// @Description 删除操作日志
+// @Tags 操作日志
+// @Param data body dto.SysOperaLogDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/sys-opera-log [delete]
+// @Security Bearer
+func (e SysOperaLogController) Delete(c *gin.Context) {
+	s := new(service.SysOperaLog)
+	req := dto.SysOperaLogDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Remove(&req, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, fmt.Sprintf("删除失败!错误详情:%s", err.Error()))
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}

+ 203 - 0
app/admin/controller/sys_post.go

@@ -0,0 +1,203 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type SysPostController struct {
+	api.Api
+}
+
+// GetPage 获取岗位列表
+// @Summary 获取岗位列表
+// @Description 获取岗位列表
+// @Tags 岗位
+// @Param postName query string false "岗位名称"
+// @Param status query int false "状态 1-停用 2-正常"
+// @Param sort query int false "排序 ASC-升序 DESC-降序"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysPost}} "{"code": 200, "data": [...]}"
+// @Router /api/post [get]
+// @Security Bearer
+func (e SysPostController) GetPage(c *gin.Context) {
+	s := service.SysPost{}
+	req := dto.SysPostPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysPost, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetPage(&req, &list, &count, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取岗位
+// @Summary 通过id获取岗位
+// @Description 通过id获取岗位
+// @Tags 岗位
+// @Param id path int true "岗位id"
+// @Success 200 {object} response.Response{data=model.SysPost} "{"code": 200, "data": [...]}"
+// @Router /api/post/{id} [get]
+// @Security Bearer
+func (e SysPostController) Get(c *gin.Context) {
+	s := service.SysPost{}
+	req := dto.SysPostGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysPost
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 添加岗位
+// @Summary 添加岗位
+// @Description 添加岗位
+// @Tags 岗位
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysPostInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/post [post]
+// @Security Bearer
+func (e SysPostController) Insert(c *gin.Context) {
+	s := service.SysPost{}
+	req := dto.SysPostInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改岗位
+// @Summary 修改岗位
+// @Description 修改岗位
+// @Tags 岗位
+// @Accept  application/json
+// @Product application/json
+// @Param id path int true "岗位id"
+// @Param data body dto.SysPostUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/post/{id} [put]
+// @Security Bearer
+func (e SysPostController) Update(c *gin.Context) {
+	s := service.SysPost{}
+	req := dto.SysPostUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除岗位
+// @Summary 删除岗位
+// @Description 删除岗位
+// @Tags 岗位
+// @Accept  application/json
+// @Product application/json
+// @Param id body dto.SysPostDeleteReq true "请求参数"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/post [delete]
+// @Security Bearer
+func (e SysPostController) Delete(c *gin.Context) {
+	s := service.SysPost{}
+	req := dto.SysPostDeleteReq{}
+	userSvc := service.SysUser{}
+
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		MakeService(&userSvc.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	userReq := dto.SysUserGetCountReq{PostIds: req.Ids}
+	var count int64
+	err = userSvc.GetCount(&userReq, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	if count > 0 {
+		e.Error(500, err, "有用户关联,禁止删除!")
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}

+ 188 - 0
app/admin/controller/sys_register_auth.go

@@ -0,0 +1,188 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+type SysRegisterAuthController struct {
+	api.Api
+}
+
+// GetPage 获取公开用户注册授权列表
+// @Summary 获取公开用户注册授权列表
+// @Description 获取公开用户注册授权列表
+// @Tags 公开用户注册授权
+// @Param postName query string false "公开用户注册授权名称"
+// @Param status query int false "状态 1-停用 2-正常"
+// @Param sort query int false "排序 ASC-升序 DESC-降序"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysRegisterAuth}} "{"code": 200, "data": [...]}"
+// @Router /api/register-auth [get]
+// @Security Bearer
+func (e SysRegisterAuthController) GetPage(c *gin.Context) {
+	s := service.SysRegisterAuth{}
+	req := dto.SysRegisterAuthPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysRegisterAuth, 0)
+	var count int64
+	err = s.GetPage(&req, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取公开用户注册授权
+// @Summary 通过id获取公开用户注册授权
+// @Description 通过id获取公开用户注册授权
+// @Tags 公开用户注册授权
+// @Param id path int true "公开用户注册授权id"
+// @Success 200 {object} response.Response{data=model.SysRegisterAuth} "{"code": 200, "data": [...]}"
+// @Router /api/register-auth/{id} [get]
+// @Security Bearer
+func (e SysRegisterAuthController) Get(c *gin.Context) {
+	s := service.SysRegisterAuth{}
+	req := dto.SysRegisterAuthGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysRegisterAuth
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 添加公开用户注册授权
+// @Summary 添加公开用户注册授权
+// @Description 添加公开用户注册授权
+// @Tags 公开用户注册授权
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysRegisterAuthInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/register-auth [post]
+// @Security Bearer
+func (e SysRegisterAuthController) Insert(c *gin.Context) {
+	s := service.SysRegisterAuth{}
+	req := dto.SysRegisterAuthInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改公开用户注册授权
+// @Summary 修改公开用户注册授权
+// @Description 修改公开用户注册授权
+// @Tags 公开用户注册授权
+// @Accept  application/json
+// @Product application/json
+// @Param id path int true "公开用户注册授权id"
+// @Param data body dto.SysRegisterAuthUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/register-auth/{id} [put]
+// @Security Bearer
+func (e SysRegisterAuthController) Update(c *gin.Context) {
+	s := service.SysRegisterAuth{}
+	req := dto.SysRegisterAuthUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除公开用户注册授权
+// @Summary 删除公开用户注册授权
+// @Description 删除公开用户注册授权
+// @Tags 公开用户注册授权
+// @Accept  application/json
+// @Product application/json
+// @Param id body dto.SysRegisterAuthDeleteReq true "请求参数"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/register-auth [delete]
+// @Security Bearer
+func (e SysRegisterAuthController) Delete(c *gin.Context) {
+	s := service.SysRegisterAuth{}
+	req := dto.SysRegisterAuthDeleteReq{}
+
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}

+ 400 - 0
app/admin/controller/sys_role.go

@@ -0,0 +1,400 @@
+package controller
+
+import (
+	"Medical_OAuth/common/actions"
+	"Medical_OAuth/common/global"
+	"github.com/gin-gonic/gin"
+	"net/http"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+
+	"github.com/gin-gonic/gin/binding"
+)
+
+type SysRoleController struct {
+	api.Api
+}
+
+// GetPage 获取角色列表
+// @Summary 角色列表数据
+// @Description 获取角色列表
+// @Tags 角色
+// @Param roleName query string false "角色名称"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysRole}} "{"code": 200, "data": [...]}"
+// @Router /api/role [get]
+// @Security Bearer
+func (e SysRoleController) GetPage(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysRole, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetPage(&req, &list, &count, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取角色
+// @Summary 通过id获取角色
+// @Description 通过id获取角色
+// @Tags 角色
+// @Param id path string true "角色Id"
+// @Success 200 {object} response.Response{data=model.SysRole} "{"code": 200, "data": [...]}"
+// @Router /api/role/{id} [get]
+// @Security Bearer
+func (e SysRoleController) Get(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var object model.SysRole
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(http.StatusUnprocessableEntity, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建角色
+// @Summary 创建角色
+// @Description 创建角色
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysRoleInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/role [post]
+// @Security Bearer
+func (e SysRoleController) Insert(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	// 设置创建人
+	req.CreateBy = user.GetUserId(c)
+
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	_, err = global.LoadPolicy(c)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改用户角色
+// @Summary 修改用户角色
+// @Description 修改用户角色
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "角色Id"
+// @Param data body dto.SysRoleUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/role/{id} [put]
+// @Security Bearer
+func (e SysRoleController) Update(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Update(&req, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	_, err = global.LoadPolicy(c)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除用户角色
+// @Summary 删除用户角色
+// @Description 删除用户角色
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysRoleDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/role [delete]
+// @Security Bearer
+func (e SysRoleController) Delete(c *gin.Context) {
+	s := new(service.SysRole)
+	req := dto.SysRoleDeleteReq{}
+	userSvc := service.SysUser{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		MakeService(&userSvc.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	userReq := dto.SysUserGetCountReq{RoleIds: []int{req.Id}}
+	var count int64
+	err = userSvc.GetCount(&userReq, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	if count > 0 {
+		e.Error(500, err, "有用户关联,禁止删除!")
+		return
+	}
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	//cb := sdk.Runtime.GetCasbinKey(c.Request.Host)
+	cb := sdk.Runtime.GetCasbinKey(config.ApplicationConfig.Host)
+	// fixme 删除角色与路由,角色与菜单之间的关联
+	err = s.Remove(&req, p, cb)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "删除成功")
+}
+
+// UpdateRoleApi 修改角色路由权限
+// @Summary 修改角色路由权限
+// @Description 修改角色路由权限
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "角色Id"
+// @Param data body dto.SysRoleUpdateRoleApiReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/role-api/{id} [put]
+// @Security Bearer
+func (e SysRoleController) UpdateRoleApi(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleUpdateRoleApiReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	cb := sdk.Runtime.GetCasbinKey(config.ApplicationConfig.Host)
+	err = s.UpdateRoleApi(&req, cb)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	_, err = global.LoadPolicy(c)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, "更新失败,"+err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "更新角色路由权限成功")
+}
+
+// GetRoleApi 获取角色路由权限
+// @Summary 获取角色路由权限
+// @Description 获取角色路由权限
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "角色Id"
+// @Param service_id query int true "服务id"
+// @Success 200 {object} response.Response{data=dto.SysRoleGetRoleApiListResp} "{"code": 200, "data": [...]}"
+// @Router /api/role-api/{id} [get]
+// @Security Bearer
+func (e SysRoleController) GetRoleApi(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleGetRoleApiListReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var apiList []model.ServApi
+	var apiIds []int
+
+	err = s.GetRoleApiList(&req, &apiIds, &apiList)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(dto.SysRoleGetRoleApiListResp{
+		ApiList: apiList,
+		ApiIds:  apiIds,
+	}, "查询成功")
+}
+
+// UpdateRoleMenu 修改角色菜单权限
+// @Summary 修改角色菜单权限
+// @Description 修改角色菜单权限
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "角色Id"
+// @Param data body dto.SysRoleUpdateRoleMenuReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/role-menu/{id} [put]
+// @Security Bearer
+func (e SysRoleController) UpdateRoleMenu(c *gin.Context) {
+	s := service.SysRole{}
+	req := dto.SysRoleUpdateRoleMenuReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.UpdateRoleMenu(&req)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "更新角色路由权限成功")
+}
+
+// GetRoleMenu 修改角色菜单权限
+// @Summary 修改角色菜单权限
+// @Description 修改角色菜单权限
+// @Tags 角色
+// @Accept  application/json
+// @Product application/json
+// @Param id path string true "角色Id"
+// @Success 200 {object} response.Response{data=dto.SysRoleGetRoleMenuListResp} "{"code": 200, "data": [...]}"
+// @Router /api/role-menu/{id} [get]
+// @Security Bearer
+func (e SysRoleController) GetRoleMenu(c *gin.Context) {
+	req := dto.SysRoleGetRoleMenuListReq{}
+	m := service.SysMenu{}
+	r := service.SysRole{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&m.Service).
+		MakeService(&r.Service).
+		Bind(&req, nil).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	result, err := m.SetLabel()
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	menuIds := make([]int, 0)
+	if req.Id != 0 {
+		menuIds, err = r.GetRoleMenuId(req.Id)
+		if err != nil {
+			e.Error(500, err, "")
+			return
+		}
+	}
+	e.OK(gin.H{
+		"menus":       result,
+		"checkedKeys": menuIds,
+	}, "获取成功")
+}

+ 263 - 0
app/admin/controller/sys_service.go

@@ -0,0 +1,263 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	coreModel "gogs.baozhida.cn/zoie/OAuth-core/model"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"strconv"
+)
+
+type SysService struct {
+	api.Api
+}
+
+// GetPage 获取服务列表
+// @Summary 获取服务列表
+// @Description 获取服务列表
+// @Tags 服务
+// @Param name query string false "服务名称"
+// @Param status query int false "状态 1-停用 2-正常"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysService}} "{"code": 200, "data": [...]}"
+// @Router /api/service [get]
+// @Security Bearer
+func (e SysService) GetPage(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServicePageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Form).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	list := make([]model.SysService, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetPage(&req, &list, &count, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取服务
+// @Summary 通过id获取服务
+// @Description 通过id获取服务
+// @Tags 服务
+// @Param id path int true "服务id"
+// @Success 200 {object} response.Response{data=model.SysService} "{"code": 200, "data": [...]}"
+// @Router /api/service/{id} [get]
+// @Security Bearer
+func (e SysService) Get(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServiceGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var object model.SysService
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.Get(&req, &object, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(object, "查询成功")
+}
+
+// Insert 添加服务
+// @Summary 添加服务
+// @Description 添加服务
+// @Tags 服务
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysServiceInsertReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/service [post]
+// @Security Bearer
+func (e SysService) Insert(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServiceInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改服务
+// @Summary 修改服务
+// @Description 修改服务
+// @Tags 服务
+// @Accept  application/json
+// @Product application/json
+// @Param id path int true "服务id"
+// @Param data body dto.SysServiceUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/service/{id} [put]
+// @Security Bearer
+func (e SysService) Update(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServiceUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	err = s.Update(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 删除服务
+// @Summary 删除服务
+// @Description 删除服务
+// @Tags 服务
+// @Accept  application/json
+// @Product application/json
+// @Param id body dto.SysServiceDeleteReq true "请求参数"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/service [delete]
+// @Security Bearer
+func (e SysService) Delete(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServiceDeleteReq{}
+
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Remove(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// Discovery 服务发现
+// @Summary 服务发现
+// @Description 服务发现,服务主动推送到数据库保存,有则更新,没有则删除。
+// @Tags 服务
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysServiceDiscoveryReq true "data"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/service-disco [post]
+func (e SysService) Discovery(c *gin.Context) {
+	s := service.SysService{}
+	req := dto.SysServiceDiscoveryReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	err = s.Discovery(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "创建成功")
+}
+
+// UserInfo 服务获取用户信息
+// @Summary 服务获取用户信息
+// @Description 服务获取用户信息,验证登录
+// @Tags 服务
+// @Accept  application/json
+// @Product application/json
+// @Success 200 {object} response.Response{data=coreModel.UserInfo} "{"code": 200, "data": [...]}"
+// @Router /api/userinfo [get]
+func (e SysService) UserInfo(c *gin.Context) {
+	s := service.SysService{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	info := coreModel.UserInfo{
+		Uuid:      user.GetUUID(c),
+		UserId:    user.GetUserId(c),
+		RoleId:    user.GetRoleId(c),
+		DeptId:    user.GetDeptId(c),
+		UserName:  user.GetUserName(c),
+		RoleName:  user.GetRoleName(c),
+		RoleKey:   user.GetRoleKey(c),
+		DataScope: user.GetDataScope(c),
+	}
+
+	if deptIdStr, err := e.Cache.Get(model.GetEnterDeptCacheKey(user.GetUserId(c))); err == nil {
+		info.DeptId, _ = strconv.Atoi(deptIdStr)
+	}
+	if deptNameStr, err := e.Cache.Get(model.GetEnterDeptNameCacheKey(user.GetUserId(c))); err == nil {
+		info.DeptName = deptNameStr
+	}
+
+	e.OK(info, "ok")
+}

+ 536 - 0
app/admin/controller/sys_user.go

@@ -0,0 +1,536 @@
+package controller
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	"Medical_OAuth/common/middleware/handler"
+	"Medical_OAuth/conf"
+	"errors"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"go.uber.org/zap"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/sms"
+	"golang.org/x/crypto/bcrypt"
+	"net/http"
+	"strconv"
+)
+
+// SysUser 定义用户控制器
+type SysUser struct {
+	api.Api
+}
+
+// GetPage 获取系统用户列表
+// @Summary 获取系统用户列表
+// @Description 获取系统用户列表
+// @Tags 用户
+// @Param username query string false "用户名"
+// @Param deptId query int false "部门id"
+// @Param roleId query string false "角色id"
+// @Param postId query string false "岗位id"
+// @Param status query string false "状态 1-停用 2-正常"
+// @Param pageSize query int false "页条数"
+// @Param pageIndex query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.SysUser}}  "{"code": 200, "data": [...]}"
+// @Router /api/sys-user [get]
+// @Security Bearer
+func (e SysUser) GetPage(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserGetPageReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Query).
+		MakeService(&s.Service).
+		Errors
+
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	list := make([]model.SysUser, 0)
+	var count int64
+
+	err = s.GetPage(&req, p, &list, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// Get 通过id获取用户
+// @Summary 通过id获取用户
+// @Description 通过id获取用户
+// @Tags 用户
+// @Param id path int true "用户id"
+// @Success 200 {object} response.Response{data=model.SysUser}  "{"code": 200, "data": [...]}"
+// @Router /api/sys-user/{id} [get]
+// @Security Bearer
+func (e SysUser) Get(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserGetReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	var object model.SysUser
+	err = s.Get(&req, p, &object)
+	if err != nil {
+		e.Error(http.StatusUnprocessableEntity, err, err.Error())
+		return
+	}
+	e.OK(object, "查询成功")
+}
+
+// Insert 创建用户
+// @Summary 创建用户
+// @Description 创建用户
+// @Tags 用户
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.SysUserInsertReq true "用户数据"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/sys-user [post]
+// @Security Bearer
+func (e SysUser) Insert(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserInsertReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	deptId := user.GetDeptId(c)
+
+	if deptIdStr, err := e.Cache.Get(model.GetEnterDeptCacheKey(user.GetUserId(c))); err == nil {
+		deptId, _ = strconv.Atoi(deptIdStr)
+	}
+	req.DeptId = deptId
+	req.RoleId = 1
+	req.Status = "2"
+
+	// 设置创建人
+	req.SetCreateBy(user.GetUserId(c))
+	err = s.Insert(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "创建成功")
+}
+
+// Update 修改用户数据
+// @Summary 修改用户数据
+// @Description 修改用户数据
+// @Tags 用户
+// @Accept  application/json
+// @Product application/json
+// @Param id path int true "用户id"
+// @Param data body dto.SysUserUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/sys-user [put]
+// @Security Bearer
+func (e SysUser) Update(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserUpdateReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	err = s.Update(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// Delete 通过id删除用户数据
+// @Summary 通过id删除用户数据
+// @Description 通过id删除用户数据
+// @Tags 用户
+// @Param data body dto.SysUserDeleteReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/sys-user [delete]
+// @Security Bearer
+func (e SysUser) Delete(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserDeleteReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	userId := user.GetUserId(c)
+	if userId == req.Id {
+		err := errors.New("禁止删除自己")
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	// 设置编辑人
+	req.SetUpdateBy(userId)
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	err = s.Remove(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "删除成功")
+}
+
+// UpdateStatus 修改用户状态
+// @Summary 修改用户状态
+// @Description 修改用户状态
+// @Tags 用户
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.UpdateSysUserStatusReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/user/status [put]
+// @Security Bearer
+func (e SysUser) UpdateStatus(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.UpdateSysUserStatusReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	err = s.UpdateStatus(&req, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "更新成功")
+}
+
+// ResetPwd 重置用户密码
+// @Summary 重置用户密码
+// @Description 重置用户密码
+// @Tags 用户
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.ResetSysUserPwdReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/user/pwd/reset [put]
+// @Security Bearer
+func (e SysUser) ResetPwd(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.ResetSysUserPwdReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	err = s.ResetPwd(&req, p)
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	e.OK(req.GetId(), "更新成功")
+
+}
+
+// UpdatePwd 修改密码
+// @Summary 修改密码
+// @Description 修改密码
+// @Tags 个人中心
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.PassWord true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/user/pwd/set [put]
+// @Security Bearer
+func (e SysUser) UpdatePwd(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.PassWord{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	var hash []byte
+	if hash, err = bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost); err != nil {
+		req.NewPassword = string(hash)
+	}
+
+	err = s.UpdatePwd(user.GetUserId(c), req.OldPassword, req.NewPassword)
+	if err != nil {
+		e.Error(http.StatusForbidden, err, err.Error())
+		return
+	}
+
+	e.OK(nil, "密码修改成功")
+
+}
+
+// GetProfile 获取个人中心用户
+// @Summary 获取个人中心用户
+// @Description 获取个人中心用户
+// @Tags 个人中心
+// @Success 200 {object} response.Response{user=model.SysUser,role=model.SysRole}  "{"code": 200, "data": {"user":[...],"role":[...]}}"
+// @Router /api/user/profile [get]
+// @Security Bearer
+func (e SysUser) GetProfile(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserById{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.Id = user.GetUserId(c)
+
+	sysUser := model.SysUser{}
+	err = s.GetProfile(&req, &sysUser)
+	if err != nil {
+		e.Logger.Errorf("get user profile error, %s", err.Error())
+		e.Error(500, err, "获取用户信息失败")
+		return
+	}
+	e.OK(gin.H{
+		"user": sysUser,
+	}, "查询成功")
+}
+
+// GetInfo 获取个人信息
+// @Summary 获取个人信息
+// @Description 获取个人信息
+// @Tags 个人中心
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/user/info [get]
+// @Security Bearer
+func (e SysUser) GetInfo(c *gin.Context) {
+	req := dto.SysUserGetReq{}
+	s := service.SysUser{}
+	r := service.SysRole{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&r.Service).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	var roles = make([]string, 1)
+	roles[0] = user.GetRoleName(c)
+	var permissions = make([]string, 1)
+	permissions[0] = "*:*:*"
+	var buttons = make([]string, 1)
+	buttons[0] = "*:*:*"
+
+	var mp = make(map[string]interface{})
+	mp["roles"] = roles
+	list, _ := r.GetById(user.GetRoleId(c))
+	mp["permissions"] = list
+	mp["buttons"] = list
+
+	sysUser := model.SysUser{}
+	req.Id = user.GetUserId(c)
+
+	err = s.Get(&req, nil, &sysUser)
+	if err != nil {
+		e.Logger.Errorf("get user info error, %s", err.Error())
+		e.Error(http.StatusUnauthorized, err, err.Error())
+		return
+	}
+
+	mp["userName"] = sysUser.Username
+	mp["userId"] = sysUser.Id
+	mp["deptId"] = sysUser.DeptId
+	mp["name"] = sysUser.NickName
+	mp["code"] = 200
+	e.OK(mp, "查询成功")
+}
+
+// Register 公开用户注册
+// @Summary 公开用户注册
+// @Description 公开用户注册
+// @Tags 用户
+// @Accept  application/json
+// @Product application/json
+// @Param id body dto.SysUserRegisterReq true "请求参数"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /api/user/register [post]
+// @Security Bearer
+func (e SysUser) Register(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserRegisterReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	req.SetUpdateBy(user.GetUserId(c))
+	err = s.Register(&req)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.GetId(), "注册成功")
+}
+
+// VerifyCode 获取短信验证码
+// @Summary 获取短信验证码
+// @Description 获取短信验证码
+// @Tags 登录
+// @Accept  application/json
+// @Product application/json
+// @Success 200 {string} string "{"code": 200, "data": "18888888888"}"
+// @Router /verify-code [post]
+// @Security Bearer
+func (e SysUser) VerifyCode(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.SysUserGetSMSVerifyCodeReq{}
+	err := e.MakeContext(c).
+		MakeService(&s.Service).
+		Bind(&req, binding.Query).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	key := model.GetVerifyCodeCacheKey(req.Phone)
+	_, err = e.Cache.Get(key)
+	// 验证吗缓存已存在
+	if err == nil {
+		e.Error(500, err, "验证吗已发送,请注意查收")
+		return
+	}
+
+	code := pkg.GenerateRandomFigureKey6()
+
+	ss := sms.NewSMS(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature)
+	content := fmt.Sprintf("【宝智达统一身份认证】您的短信验证码:%s,请在10分钟内输入", code)
+	res, err := ss.Send(req.Phone, content)
+	if err != nil || res.Status != sms.SUCCESS {
+		e.Logger.Error("发送短信验证码出现异常", zap.Any("res", res), zap.Error(err))
+		e.Error(500, err, "验证吗发送失败,请重试")
+		return
+	}
+	_ = e.Cache.Set(key, code, 600)
+	e.OK(req.Phone, "发送成功")
+
+}
+
+// GetNewestToken 获取最新token
+// @Summary 获取最新token
+// @Description 获取最新token,提供给接入服务访问,用于单一认证检查
+// @Tags 用户
+// @Param serviceId header int true "服务id"
+// @Param userId path int true "用户id"
+// @Success 200 {string} string "{"code": 200, "data": "...token..."}"
+// @Router /newest-token [get]
+func (e SysUser) GetNewestToken(c *gin.Context) {
+	s := service.SysUser{}
+	req := dto.GetNewestTokenReq{}
+	err := e.MakeContext(c).
+		MakeService(&s.Service).
+		Bind(&req, nil).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	key, err := handler.GetNewestToken(c, req.UserId)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(key, "查询成功")
+}

+ 26 - 0
app/admin/model/serv_api.go

@@ -0,0 +1,26 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	coreModel "gogs.baozhida.cn/zoie/OAuth-core/model"
+)
+
+type ServApi struct {
+	model2.Model
+	coreModel.Api
+	model2.ModelTime
+	model2.ControlBy
+}
+
+func (ServApi) TableName() string {
+	return "serv_api"
+}
+
+func (e *ServApi) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *ServApi) GetId() interface{} {
+	return e.Id
+}

+ 43 - 0
app/admin/model/serv_menu.go

@@ -0,0 +1,43 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type ServMenu struct {
+	model2.Model
+	ServiceId  int        `json:"serviceId" gorm:"size:4;not null;comment:服务ID"`  // 服务ID
+	MenuPath   string     `json:"menuPath" gorm:"size:128;" swaggerignore:"true"` //
+	ParentId   int        `json:"parentId" gorm:"size:11;"`                       // 父id
+	Name       string     `json:"name" gorm:"size:128;"`                          // 菜单名称
+	Sort       int        `json:"sort" gorm:"size:4;"`                            // 排序
+	MenuType   string     `json:"menuType" gorm:"size:1;"`                        // 菜单类型
+	Icon       string     `json:"icon" gorm:"size:128;"`                          // 图标
+	Component  string     `json:"component" gorm:"size:255;"`                     // 组件路径
+	IsFrame    string     `json:"isFrame" gorm:"size:1;DEFAULT:0;"`               // 是否外链 1-是 2-否
+	Path       string     `json:"path" gorm:"size:128;"`                          // 外链路由地址
+	Permission string     `json:"permission" gorm:"size:255;"`                    // 权限标识
+	Visible    string     `json:"visible" gorm:"size:1;"`                         // 1-显示 0-隐藏
+	Children   []ServMenu `json:"children,omitempty" gorm:"-"`
+	IsSelect   bool       `json:"is_select" gorm:"-"`
+	model2.ControlBy
+	model2.ModelTime
+}
+
+type ServMenuSlice []ServMenu
+
+func (x ServMenuSlice) Len() int           { return len(x) }
+func (x ServMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort }
+func (x ServMenuSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (ServMenu) TableName() string {
+	return "serv_menu"
+}
+
+func (e *ServMenu) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *ServMenu) GetId() interface{} {
+	return e.Id
+}

+ 25 - 0
app/admin/model/serv_role_api.go

@@ -0,0 +1,25 @@
+package model
+
+import model2 "Medical_OAuth/common/model"
+
+type ServRoleApi struct {
+	model2.Model
+	ServiceId int    `json:"serviceId" gorm:"size:4;not null;comment:服务ID"` // 服务ID
+	RoleKey   string `json:"roleKey" gorm:"size:128;comment:角色编码"`          // 角色编码
+	ApiId     int    `json:"apiId" gorm:"size:128;comment:接口id"`            // 接口id
+	model2.ModelTime
+	model2.ControlBy
+}
+
+func (ServRoleApi) TableName() string {
+	return "serv_role_api"
+}
+
+func (e *ServRoleApi) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *ServRoleApi) GetId() interface{} {
+	return e.Id
+}

+ 29 - 0
app/admin/model/sys_config.go

@@ -0,0 +1,29 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysConfig struct {
+	model2.Model
+	ConfigName  string `json:"configName" gorm:"size:128;comment:ConfigName"`   // 配置名称
+	ConfigKey   string `json:"configKey" gorm:"size:128;comment:ConfigKey"`     //  配置Key
+	ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` //   配置值
+	IsFrontend  string `json:"isFrontend" gorm:"size:64;comment:是否前台"`          //是否前台展示
+	Remark      string `json:"remark" gorm:"size:128;comment:Remark"`           //
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysConfig) TableName() string {
+	return "sys_config"
+}
+
+func (e *SysConfig) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysConfig) GetId() interface{} {
+	return e.Id
+}

+ 47 - 0
app/admin/model/sys_dept.go

@@ -0,0 +1,47 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"errors"
+	"fmt"
+	"gorm.io/gorm"
+)
+
+type SysDept struct {
+	model2.Model
+	ParentId int       `json:"parentId" gorm:""`                               //上级部门
+	DeptPath string    `json:"deptPath" gorm:"size:255;" swaggerignore:"true"` //
+	DeptName string    `json:"deptName"  gorm:"size:128;"`                     //部门名称
+	Sort     int       `json:"sort" gorm:"size:4;"`                            //排序
+	Status   int       `json:"status" gorm:"size:4;"`                          //状态 1-停用 2-正常
+	Children []SysDept `json:"children" gorm:"-"`
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysDept) TableName() string {
+	return "sys_dept"
+}
+
+func (e *SysDept) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysDept) GetId() interface{} {
+	return e.Id
+}
+
+func (e *SysDept) BeforeDelete(_ *gorm.DB) (err error) {
+	if e.Id == 1 {
+		return errors.New("禁止删除系统部门")
+	}
+	return
+}
+
+func GetEnterDeptCacheKey(userId int) string {
+	return fmt.Sprintf("enter-dept-%d", userId)
+}
+func GetEnterDeptNameCacheKey(userId int) string {
+	return fmt.Sprintf("enter-dept-name-%d", userId)
+}

+ 34 - 0
app/admin/model/sys_dict_data.go

@@ -0,0 +1,34 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysDictData struct {
+	DictCode  int    `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"`
+	DictSort  int    `json:"dictSort" gorm:"size:20;comment:DictSort"`
+	DictLabel string `json:"dictLabel" gorm:"size:128;comment:DictLabel"`
+	DictValue string `json:"dictValue" gorm:"size:255;comment:DictValue"`
+	DictType  string `json:"dictType" gorm:"size:64;comment:DictType"`
+	CssClass  string `json:"cssClass" gorm:"size:128;comment:CssClass"`
+	ListClass string `json:"listClass" gorm:"size:128;comment:ListClass"`
+	IsDefault string `json:"isDefault" gorm:"size:8;comment:IsDefault"`
+	Status    int    `json:"status" gorm:"size:4;not null;default:2;comment:状态"` // 1-停用 2-正常
+	Default   string `json:"default" gorm:"size:8;comment:Default"`
+	Remark    string `json:"remark" gorm:"size:255;comment:Remark"`
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysDictData) TableName() string {
+	return "sys_dict_data"
+}
+
+func (e *SysDictData) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysDictData) GetId() interface{} {
+	return e.DictCode
+}

+ 28 - 0
app/admin/model/sys_dict_type.go

@@ -0,0 +1,28 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysDictType struct {
+	ID       int    `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"`
+	DictName string `json:"dictName" gorm:"size:128;comment:DictName"`
+	DictType string `json:"dictType" gorm:"size:128;comment:DictType"`
+	Status   int    `json:"status" gorm:"size:4;not null;default:2;comment:状态"` // 1-停用 2-正常
+	Remark   string `json:"remark" gorm:"size:255;comment:Remark"`
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysDictType) TableName() string {
+	return "sys_dict_type"
+}
+
+func (e *SysDictType) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysDictType) GetId() interface{} {
+	return e.ID
+}

+ 72 - 0
app/admin/model/sys_login_log.go

@@ -0,0 +1,72 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"encoding/json"
+	"errors"
+	"time"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+	"gogs.baozhida.cn/zoie/OAuth-core/storage"
+)
+
+type SysLoginLog struct {
+	model2.Model
+	Username      string    `json:"username" gorm:"size:128;comment:用户名"`
+	Status        string    `json:"status" gorm:"size:4;comment:状态"`
+	Ipaddr        string    `json:"ipaddr" gorm:"size:255;comment:ip地址"`
+	LoginLocation string    `json:"loginLocation" gorm:"size:255;comment:归属地"`
+	Browser       string    `json:"browser" gorm:"size:255;comment:浏览器"`
+	Os            string    `json:"os" gorm:"size:255;comment:系统"`
+	Platform      string    `json:"platform" gorm:"size:255;comment:固件"`
+	LoginTime     time.Time `json:"loginTime" gorm:"comment:登录时间"`
+	Remark        string    `json:"remark" gorm:"size:255;comment:备注"`
+	Msg           string    `json:"msg" gorm:"size:255;comment:信息"`
+	CreatedAt     time.Time `json:"createdAt" gorm:"comment:创建时间"`
+	UpdatedAt     time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
+	model2.ControlBy
+}
+
+func (SysLoginLog) TableName() string {
+	return "sys_login_log"
+}
+
+func (e *SysLoginLog) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysLoginLog) GetId() interface{} {
+	return e.Id
+}
+
+// SaveLoginLog 从队列中获取登录日志
+func SaveLoginLog(message storage.Messager) (err error) {
+	//准备db
+	db := sdk.Runtime.GetDbByKey(config.ApplicationConfig.Host)
+	if db == nil {
+		err = errors.New("db not exist")
+		log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
+		return err
+	}
+	var rb []byte
+	rb, err = json.Marshal(message.GetValues())
+	if err != nil {
+		log.Errorf("json Marshal error, %s", err.Error())
+		return err
+	}
+	var l SysLoginLog
+	err = json.Unmarshal(rb, &l)
+	if err != nil {
+		log.Errorf("json Unmarshal error, %s", err.Error())
+		return err
+	}
+	err = db.Create(&l).Error
+	if err != nil {
+		log.Errorf("db create error, %s", err.Error())
+		return err
+	}
+	return nil
+}

+ 45 - 0
app/admin/model/sys_menu.go

@@ -0,0 +1,45 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysMenu struct {
+	model2.Model
+	ParentId      int    `json:"parentId" gorm:"size:11;"`                            // 父id
+	ServiceMenuId int    `json:"serviceMenuId" gorm:"size:4;not null;comment:服务菜单ID"` //服务菜单ID
+	ServiceId     int    `json:"serviceId" gorm:"size:4;not null;comment:服务ID"`       // 服务ID
+	Sort          int    `json:"sort" gorm:"size:4;"`                                 // 排序
+	Visible       string `json:"visible" gorm:"size:1;"`                              // 1-显示 0-隐藏
+	MenuPath      string `json:"paths" gorm:"size:128;" swaggerignore:"true"`         //
+
+	Name       string `json:"name" gorm:"-"`       // 菜单名称
+	MenuType   string `json:"menuType" gorm:"-"`   // 菜单类型
+	Icon       string `json:"icon" gorm:"-"`       // 图标
+	Component  string `json:"component" gorm:"-"`  // 组件路径
+	IsFrame    string `json:"isFrame" gorm:"-"`    // 是否外链 1-是 2-否
+	Path       string `json:"path" gorm:"-"`       // 外链路由地址
+	Permission string `json:"permission" gorm:"-"` // 权限标识
+
+	Children []SysMenu `json:"children,omitempty" gorm:"-"`
+	model2.ControlBy
+	model2.ModelTime
+}
+
+type SysMenuSlice []SysMenu
+
+func (x SysMenuSlice) Len() int           { return len(x) }
+func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort }
+func (x SysMenuSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (SysMenu) TableName() string {
+	return "sys_menu"
+}
+
+func (e *SysMenu) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysMenu) GetId() interface{} {
+	return e.Id
+}

+ 88 - 0
app/admin/model/sys_opera_log.go

@@ -0,0 +1,88 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"encoding/json"
+	"errors"
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+	"gogs.baozhida.cn/zoie/OAuth-core/storage"
+	"time"
+)
+
+type SysOperaLog struct {
+	model2.Model
+	Title         string    `json:"title" gorm:"size:255;comment:操作模块"`
+	BusinessType  string    `json:"businessType" gorm:"size:128;comment:操作类型"`
+	BusinessTypes string    `json:"businessTypes" gorm:"size:128;comment:BusinessTypes"`
+	Method        string    `json:"method" gorm:"size:128;comment:函数"`
+	RequestMethod string    `json:"requestMethod" gorm:"size:128;comment:请求方式 GET POST PUT DELETE"`
+	OperatorType  string    `json:"operatorType" gorm:"size:128;comment:操作类型"`
+	OperaName     string    `json:"operaName" gorm:"size:128;comment:操作者"`
+	DeptName      string    `json:"deptName" gorm:"size:128;comment:机构名称"`
+	OperaUrl      string    `json:"operaUrl" gorm:"size:255;comment:访问地址"`
+	OperaIp       string    `json:"operaIp" gorm:"size:128;comment:客户端ip"`
+	OperaLocation string    `json:"operaLocation" gorm:"size:128;comment:访问位置"`
+	OperaParam    string    `json:"operaParam" gorm:"text;comment:请求参数"`
+	Status        string    `json:"status" gorm:"size:4;comment:操作状态 1:正常 2:关闭"`
+	OperaTime     time.Time `json:"operaTime" gorm:"comment:操作时间"`
+	JsonResult    string    `json:"jsonResult" gorm:"text;comment:返回数据"`
+	Remark        string    `json:"remark" gorm:"size:255;comment:备注"`
+	LatencyTime   string    `json:"latencyTime" gorm:"size:128;comment:耗时"`
+	UserAgent     string    `json:"userAgent" gorm:"size:255;comment:ua"`
+	CreatedAt     time.Time `json:"createdAt" gorm:"comment:创建时间"`
+	UpdatedAt     time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
+	model2.ControlBy
+}
+
+func (SysOperaLog) TableName() string {
+	return "sys_opera_log"
+}
+
+func (e *SysOperaLog) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysOperaLog) GetId() interface{} {
+	return e.Id
+}
+
+// SaveOperaLog 从队列中获取操作日志
+func SaveOperaLog(message storage.Messager) (err error) {
+	//准备db
+	db := sdk.Runtime.GetDbByKey(config.ApplicationConfig.Host)
+	if db == nil {
+		err = errors.New("db not exist")
+		log.Errorf("host[%s]'s %s", config.ApplicationConfig.Host, err.Error())
+		// Log writing to the database ignores error
+		return nil
+	}
+	var rb []byte
+	rb, err = json.Marshal(message.GetValues())
+	if err != nil {
+		log.Errorf("json Marshal error, %s", err.Error())
+		// Log writing to the database ignores error
+		return nil
+	}
+	var l SysOperaLog
+	err = json.Unmarshal(rb, &l)
+	if err != nil {
+		log.Errorf("json Unmarshal error, %s", err.Error())
+		// Log writing to the database ignores error
+		return nil
+	}
+	// 超出100个字符返回值截断
+	if len(l.JsonResult) > 100 {
+		l.JsonResult = l.JsonResult[:100]
+	}
+	l.OperaTime = time.Now()
+	err = db.Create(&l).Error
+	if err != nil {
+		log.Errorf("db create error, %s", err.Error())
+		// Log writing to the database ignores error
+		return nil
+	}
+	return nil
+}

+ 28 - 0
app/admin/model/sys_post.go

@@ -0,0 +1,28 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysPost struct {
+	model2.Model
+	PostName string `gorm:"size:128;not null;" json:"postName"`                 //岗位名称
+	Sort     int    `gorm:"size:4;" json:"sort"`                                //岗位排序
+	Status   int    `gorm:"size:4;not null;default:2;comment:状态" json:"status"` // 1-停用 2-正常
+	Remark   string `gorm:"size:255;" json:"remark"`                            //描述
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysPost) TableName() string {
+	return "sys_post"
+}
+
+func (e *SysPost) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysPost) GetId() interface{} {
+	return e.Id
+}

+ 29 - 0
app/admin/model/sys_register_auth.go

@@ -0,0 +1,29 @@
+package model
+
+import model2 "Medical_OAuth/common/model"
+
+// 公开用户注册授权
+type SysRegisterAuth struct {
+	model2.Model
+	URKey      string `gorm:"size:128;not null;" json:"URKey"`                         //岗位名称
+	RoleId     int    `gorm:"size:4;" json:"roleId"`                                   //角色id
+	DeptId     int    `gorm:"size:4;" json:"deptId"`                                   // 部门id
+	Status     int    `gorm:"size:4;not null;default:2;comment:状态" json:"status"`      // 状态 1-停用 2-正常
+	SMSVerify  int    `gorm:"size:4;not null;default:2;comment:短信验证" json:"SMSVerify"` // 状态 1-关闭 2-开启
+	InviteCode string `gorm:"size:255;" json:"remark"`                                 //邀请码
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysRegisterAuth) TableName() string {
+	return "sys_register_auth"
+}
+
+func (e *SysRegisterAuth) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysRegisterAuth) GetId() interface{} {
+	return e.Id
+}

+ 35 - 0
app/admin/model/sys_role.go

@@ -0,0 +1,35 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	coreModel "gogs.baozhida.cn/zoie/OAuth-core/model"
+
+	"errors"
+	"gorm.io/gorm"
+)
+
+type SysRole struct {
+	model2.Model
+	coreModel.Role
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysRole) TableName() string {
+	return "sys_role"
+}
+
+func (e *SysRole) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysRole) GetId() interface{} {
+	return e.Id
+}
+func (e *SysRole) BeforeDelete(_ *gorm.DB) (err error) {
+	if e.RoleKey == "admin" {
+		return errors.New("禁止删除系统角色")
+	}
+	return
+}

+ 71 - 0
app/admin/model/sys_role_menu.go

@@ -0,0 +1,71 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"encoding/json"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+)
+
+type SysRoleMenu struct {
+	model2.Model
+	RoleKey string `json:"roleKey" gorm:"size:128;comment:角色编码"` // 角色编码
+	MenuId  int    `json:"menuId" gorm:"size:128;comment:菜单id"`  // 菜单id
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysRoleMenu) TableName() string {
+	return "sys_role_menu"
+}
+
+func (e *SysRoleMenu) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysRoleMenu) GetId() interface{} {
+	return e.Id
+}
+
+func GetRoleMenuCacheKey(roleKey string) string {
+	return "role_menu-" + roleKey
+}
+
+// 添加、修改、删除菜单时删除角色菜单缓存
+func DeleteAllRoleMenuCache() error {
+	//准备db
+	db := sdk.Runtime.GetDbByKey(config.ApplicationConfig.Host)
+	if db == nil {
+		return errors.New("db not exist")
+	}
+	var list []SysRole
+	err := db.Model(SysRole{}).Find(&list).Error
+	if err != nil {
+		return err
+	}
+	for _, role := range list {
+		_ = sdk.Runtime.GetCacheAdapter().Del(GetRoleMenuCacheKey(role.RoleKey))
+	}
+	return nil
+}
+
+func DeleteRoleMenuCache(roleKey string) error {
+	return sdk.Runtime.GetCacheAdapter().Del(GetRoleMenuCacheKey(roleKey))
+}
+
+func SetRoleMenuCache(roleKey string, menuList []SysMenu) error {
+	s, err := json.Marshal(menuList)
+	err = sdk.Runtime.GetCacheAdapter().Set(GetRoleMenuCacheKey(roleKey), s, 24*60*60)
+	return err
+}
+
+func GetRoleMenuCache(roleKey string, menuList *[]SysMenu) error {
+	s, err := sdk.Runtime.GetCacheAdapter().Get(GetRoleMenuCacheKey(roleKey))
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal([]byte(s), &menuList)
+	return err
+}

+ 30 - 0
app/admin/model/sys_service.go

@@ -0,0 +1,30 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysService struct {
+	model2.Model
+	No         string `gorm:"size:8;not null;" json:"no"`                         // 服务编号
+	Name       string `gorm:"size:128;" json:"name"`                              // 服务名称
+	Host       string `gorm:"size:512;not null;comment:服务地址" json:"host"`         // 服务地址
+	AuthCode   string `gorm:"size:32;not null;comment:授权码" json:"authCode"`       // 授权码
+	Status     int    `gorm:"size:4;not null;default:2;comment:状态" json:"status"` // 状态 1-停用 2-正常
+	RoleApiUrl string `gorm:"size:128;" json:"roleApiUrl"`                        // 角色权限回调地址
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysService) TableName() string {
+	return "sys_service"
+}
+
+func (e *SysService) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysService) GetId() interface{} {
+	return e.Id
+}

+ 77 - 0
app/admin/model/sys_user.go

@@ -0,0 +1,77 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"errors"
+	"fmt"
+	"github.com/google/uuid"
+	coreModel "gogs.baozhida.cn/zoie/OAuth-core/model"
+	"golang.org/x/crypto/bcrypt"
+	"gorm.io/gorm"
+)
+
+type SysUser struct {
+	model2.Model
+	coreModel.User
+	Dept SysDept `json:"dept" gorm:"-"` // 部门
+	Role SysRole `json:"role" gorm:"-"` // 角色
+	//Post SysPost `json:"post" gorm:"-"` // 岗位
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (SysUser) TableName() string {
+	return "sys_user"
+}
+
+func (e *SysUser) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysUser) GetId() interface{} {
+	return e.Id
+}
+
+// 加密
+func (e *SysUser) Encrypt() (err error) {
+	if e.Password == "" {
+		return
+	}
+
+	var hash []byte
+	if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil {
+		return
+	} else {
+		e.Password = string(hash)
+		return
+	}
+}
+
+func (e *SysUser) BeforeCreate(_ *gorm.DB) error {
+	e.Uuid = uuid.NewString()
+	return e.Encrypt()
+}
+
+func (e *SysUser) BeforeUpdate(_ *gorm.DB) error {
+	var err error
+	if e.Password != "" {
+		err = e.Encrypt()
+	}
+	return err
+}
+
+func (e *SysUser) BeforeDelete(_ *gorm.DB) error {
+	if e.Username == "admin" {
+		return errors.New("禁止删除系统用户")
+	}
+	return nil
+}
+
+func GetVerifyCodeCacheKey(phone string) string {
+	return fmt.Sprintf("verify-code-%s", phone)
+}
+
+func GetUserCacheKey(id int) string {
+	return fmt.Sprintf("oauth:user:%d", id)
+}

+ 19 - 0
app/admin/router/captcha.go

@@ -0,0 +1,19 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerCaptchaRouter)
+}
+
+func registerCaptchaRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	r1 := v1.Group("")
+	{
+		cont := controller.SystemController{}
+		r1.GET("/captcha", cont.GenerateCaptchaHandler)
+	}
+}

+ 87 - 0
app/admin/router/init_router.go

@@ -0,0 +1,87 @@
+package router
+
+import (
+	"Medical_OAuth/common/middleware"
+	handler2 "Medical_OAuth/common/middleware/handler"
+	"github.com/gin-gonic/gin"
+	swaggerfiles "github.com/swaggo/files"
+	ginSwagger "github.com/swaggo/gin-swagger"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+	"os"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+)
+
+// InitRouter 路由初始化,不要怀疑,这里用到了
+func InitRouter() {
+	var r *gin.Engine
+	h := sdk.Runtime.GetEngine()
+	if h == nil {
+		log.Fatal("not found engine...")
+		os.Exit(-1)
+	}
+	switch h.(type) {
+	case *gin.Engine:
+		r = h.(*gin.Engine)
+	default:
+		log.Fatal("not support other engine")
+		os.Exit(-1)
+	}
+
+	// the jwt middleware
+	authMiddleware, err := middleware.AuthInit()
+	if err != nil {
+		log.Fatalf("JWT Init Error, %s", err.Error())
+	}
+
+	// 注册系统路由
+	InitSysRouter(r, authMiddleware)
+
+}
+
+func InitSysRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.RouterGroup {
+	g := r.Group("")
+	// 静态文件
+	// sysStaticFileRouter(g)
+	// swagger;注意:生产环境可以注释掉
+	if config.ApplicationConfig.Mode != "prod" {
+		sysSwaggerRouter(g)
+	}
+	// 需要认证
+	sysCheckRoleRouterInit(g, authMiddleware)
+
+	return g
+}
+
+func sysSwaggerRouter(r *gin.RouterGroup) {
+	//r.GET("/swagger/admin/*any", ginSwagger.WrapHandler(swaggerfiles.NewHandler(), ginSwagger.InstanceName("admin")))
+	//r.GET("/swagger/*any", func(c *gin.Context) {
+	//	ginSwagger.DisablingWrapHandler(swaggerfiles.Handler, "SWAGGER")(c)
+	//})
+	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
+}
+
+func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+
+	v1 := r.Group("/api/")
+	{
+		v1.POST("/login", authMiddleware.LoginHandler)
+		// Refresh time can be longer than token timeout
+		v1.GET("/refresh_token", authMiddleware.RefreshHandler)
+	}
+
+	for _, f := range routerCheckRole {
+		f(v1, authMiddleware)
+	}
+
+	registerBaseRouter(v1, authMiddleware)
+}
+
+func registerBaseRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		v1auth.POST("/logout", handler2.LogOut)
+	}
+}

+ 41 - 0
app/admin/router/router.go

@@ -0,0 +1,41 @@
+package router
+
+import (
+	"github.com/gin-gonic/gin"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+var (
+	routerNoCheckRole = make([]func(*gin.RouterGroup), 0)
+	routerCheckRole   = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
+)
+
+// 路由示例
+func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
+
+	// 无需认证的路由
+	NoCheckRoleRouter(r)
+	// 需要认证的路由
+	CheckRoleRouter(r, authMiddleware)
+
+	return r
+}
+
+// 无需认证的路由示例
+func NoCheckRoleRouter(r *gin.Engine) {
+	// 可根据业务需求来设置接口版本
+	v1 := r.Group("/api")
+	for _, f := range routerNoCheckRole {
+		f(v1)
+	}
+}
+
+// 需要认证的路由示例
+func CheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) {
+	// 可根据业务需求来设置接口版本
+	v1 := r.Group("/api")
+	for _, f := range routerCheckRole {
+		f(v1, authMiddleware)
+	}
+}

+ 27 - 0
app/admin/router/serv_api.go

@@ -0,0 +1,27 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerServApiRouter)
+}
+
+// 需认证的路由代码 - 统一身份认证菜单
+func registerServApiRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.ServApi{}
+
+	r := v1.Group("/serv-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+
+}

+ 28 - 0
app/admin/router/serv_menu.go

@@ -0,0 +1,28 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerServMenuRouter)
+}
+
+// 需认证的路由代码 - 统一身份认证菜单
+func registerServMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.ServMenu{}
+
+	//r := v1.Group("/serv-menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	r := v1.Group("/serv-menu")
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+		r.GET("/export", cont.Export)
+	}
+
+}

+ 43 - 0
app/admin/router/sys_config.go

@@ -0,0 +1,43 @@
+package router
+
+import (
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysConfigRouter)
+}
+
+// 需认证的路由代码
+func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysConfig{}
+	r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+
+	r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc())
+	{
+		r1.GET("/:configKey", cont.GetSysConfigByKEYForService)
+	}
+
+	r2 := v1.Group("/app-config")
+	{
+		r2.GET("", cont.Get2SysApp)
+	}
+
+	r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc())
+	{
+		r3.PUT("", cont.Update2Set)
+		r3.GET("", cont.Get2Set)
+	}
+
+}

+ 29 - 0
app/admin/router/sys_dept.go

@@ -0,0 +1,29 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/actions"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysDeptRouter)
+}
+
+// 需认证的路由代码
+func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysDeptController{}
+
+	r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("", cont.Update)
+		r.DELETE("", cont.Delete)
+		r.POST("/enter", cont.Enter)
+	}
+
+}

+ 38 - 0
app/admin/router/sys_dict.go

@@ -0,0 +1,38 @@
+package router
+
+import (
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerDictRouter)
+}
+
+func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	dictCont := controller.SysDictTypeController{}
+	dataCont := controller.SysDictDataController{}
+	dicts := v1.Group("/dict").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+
+		dicts.GET("/data", dataCont.GetPage)
+		dicts.GET("/data/:dictCode", dataCont.Get)
+		dicts.POST("/data", dataCont.Insert)
+		dicts.PUT("/data/:dictCode", dataCont.Update)
+		dicts.DELETE("/data", dataCont.Delete)
+
+		dicts.GET("/type-option-select", dictCont.GetAll)
+		dicts.GET("/type", dictCont.GetPage)
+		dicts.GET("/type/:id", dictCont.Get)
+		dicts.POST("/type", dictCont.Insert)
+		dicts.PUT("/type/:id", dictCont.Update)
+		dicts.DELETE("/type", dictCont.Delete)
+	}
+	opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		opSelect.GET("/option-select", dataCont.GetAll)
+	}
+}

+ 25 - 0
app/admin/router/sys_login_log.go

@@ -0,0 +1,25 @@
+package router
+
+import (
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysLoginLogRouter)
+}
+
+// 需认证的路由代码
+func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysLoginLogController{}
+
+	r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.DELETE("", cont.Delete)
+	}
+}

+ 32 - 0
app/admin/router/sys_menu.go

@@ -0,0 +1,32 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysMenuRouter)
+}
+
+// 需认证的路由代码
+func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysMenuController{}
+
+	r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+
+	r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
+	{
+		r1.GET("/menu-role", cont.GetMenuRole)
+	}
+
+}

+ 24 - 0
app/admin/router/sys_opera_log.go

@@ -0,0 +1,24 @@
+package router
+
+import (
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysOperaLogRouter)
+}
+
+// 需认证的路由代码
+func registerSysOperaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysOperaLogController{}
+	r := v1.Group("/sys-opera-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.DELETE("", cont.Delete)
+	}
+}

+ 25 - 0
app/admin/router/sys_post.go

@@ -0,0 +1,25 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSyPostRouter)
+}
+
+// 需认证的路由代码
+func registerSyPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysPostController{}
+	r := v1.Group("/post").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+}

+ 25 - 0
app/admin/router/sys_register_auth.go

@@ -0,0 +1,25 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysRegisterAuthRouter)
+}
+
+// 需认证的路由代码
+func registerSysRegisterAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysRegisterAuthController{}
+	r := v1.Group("/register-auth").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+}

+ 39 - 0
app/admin/router/sys_role.go

@@ -0,0 +1,39 @@
+package router
+
+import (
+	"Medical_OAuth/common/actions"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysRoleRouter)
+}
+
+// 需认证的路由代码
+func registerSysRoleRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysRoleController{}
+	r := v1.Group("/role").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+	// 角色关联的api
+	r1 := v1.Group("/role-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r1.GET("/:id", cont.GetRoleApi)
+		r1.PUT("/:id", cont.UpdateRoleApi)
+	}
+	// 角色关联的菜单
+	r2 := v1.Group("/role-menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r2.GET("/:id", cont.GetRoleMenu)
+		r2.PUT("/:id", cont.UpdateRoleMenu)
+	}
+}

+ 35 - 0
app/admin/router/sys_service.go

@@ -0,0 +1,35 @@
+package router
+
+import (
+	"Medical_OAuth/app/admin/controller"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysServiceRouter)
+}
+
+// 需认证的路由代码
+func registerSysServiceRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysService{}
+	r := v1.Group("/service").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("/:id", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+	r1 := v1.Group("")
+	{
+		// 服务发现
+		r1.POST("/service-disco", cont.Discovery)
+	}
+	r2 := v1.Group("/service").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckService())
+	{
+		// 服务获取用户信息
+		r2.GET("/userinfo", cont.UserInfo)
+	}
+}

+ 48 - 0
app/admin/router/sys_user.go

@@ -0,0 +1,48 @@
+package router
+
+import (
+	"Medical_OAuth/common/actions"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/admin/controller"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysUserRouter)
+}
+
+// 需认证的路由代码
+func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+	cont := controller.SysUser{}
+	r := v1.Group("/sys-user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction())
+	{
+		r.GET("", cont.GetPage)
+		r.GET("/:id", cont.Get)
+		r.POST("", cont.Insert)
+		r.PUT("", cont.Update)
+		r.DELETE("", cont.Delete)
+	}
+
+	user := v1.Group("/user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction())
+	{
+		user.GET("/profile", cont.GetProfile)
+		user.GET("/info", cont.GetInfo)
+		user.PUT("/status", cont.UpdateStatus)
+		user.PUT("/pwd/set", cont.UpdatePwd)
+		user.PUT("/pwd/reset", cont.ResetPwd)
+
+	}
+	r2 := v1.Group("")
+	{
+		r2.POST("/register", cont.Register)
+		r2.GET("/verify-code", cont.VerifyCode)
+	}
+
+	r3 := v1.Group("/newest-token").Use(middleware.AuthCheckService())
+	{
+		r3.GET("/:userId", cont.GetNewestToken)
+	}
+
+}

+ 110 - 0
app/admin/service/dto/serv_api.go

@@ -0,0 +1,110 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// ServApiGetPageReq 列表或者搜索使用结构体
+type ServApiGetPageReq struct {
+	dto.Pagination `search:"-"`
+	ServiceId      int    `form:"serviceId" search:"type:exact;column:service_id;table:serv_api"`                // 服务id
+	Name           string `form:"name" search:"type:orcontains;column:name;table:serv_api"`                      // 名称
+	Path           string `form:"name" search:"type:orcontains;column:path;table:serv_api" swaggerignore:"true"` // 路径
+}
+
+func (m *ServApiGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// ServApiInsertReq 功能创建请求参数
+type ServApiInsertReq struct {
+	Id               int    `json:"id" swaggerignore:"true"`  // 编码
+	ServiceId        int    `json:"ServiceId"`                // 服务id
+	Name             string `json:"name" example:"标题"`        // 标题
+	Path             string `json:"path" example:"/api/list"` // 地址
+	Action           string `json:"type" example:"GET"`       // 请求类型 GET PUT POST DELETE
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServApiInsertReq) Generate(model *model.ServApi) {
+	model.ServiceId = s.ServiceId
+	model.Name = s.Name
+	model.Path = s.Path
+	model.Action = s.Action
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+
+}
+
+func (s *ServApiInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+// ServApiUpdateReq 功能更新请求参数
+type ServApiUpdateReq struct {
+	Id               int    `uri:"id" swaggerignore:"true"`   // 接口ID
+	Name             string `json:"name" example:"标题"`        // 标题
+	Path             string `json:"path" example:"/api/list"` // 地址
+	Action           string `json:"type" example:"GET"`       // 请求类型
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServApiUpdateReq) Generate(model *model.ServApi) {
+	model.Name = s.Name
+	model.Path = s.Path
+	model.Action = s.Action
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *ServApiUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+// ServApiGetReq 功能获取请求参数
+type ServApiGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *ServApiGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// ServApiDeleteReq 功能删除请求参数
+type ServApiDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServApiDeleteReq) GetId() interface{} {
+	return s.Ids
+}
+
+// ServApiListByMenuId 获取菜单关联api列表
+type ServApiListByMenuId struct {
+	MenuId int `search:"type:exact;column:menu_id;table:app_api"`
+}
+
+func (m *ServApiListByMenuId) GetNeedSearch() interface{} {
+	return *m
+}
+
+// ServApiListByIds 功能获取请求参数
+type ServApiListByIds struct {
+	ServiceId int   `search:"type:exact;column:service_id;table:serv_api"` // 服务id
+	Ids       []int `search:"type:in;column:id;table:serv_api"`
+}
+
+func (m *ServApiListByIds) GetNeedSearch() interface{} {
+	return *m
+}

+ 149 - 0
app/admin/service/dto/serv_menu.go

@@ -0,0 +1,149 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// ServMenuGetPageReq 列表或者搜索使用结构体
+type ServMenuGetPageReq struct {
+	dto.Pagination `search:"-"`
+	ServiceId      int    `form:"serviceId" search:"type:exact;column:service_id;table:serv_menu"` // 服务id
+	Name           string `form:"name" search:"type:contains;column:name;table:serv_menu"`         // 菜单名称
+	Visible        int    `form:"visible" search:"type:exact;column:visible;table:serv_menu"`      // 显示状态
+	ServMenuOrder
+}
+
+type ServMenuOrder struct {
+	SortOrder string `search:"type:order;column:sort;table:serv_menu" form:"sort" default:"asc"` //排序 ASC 升序 DESC 降序
+}
+
+func (m *ServMenuGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type ServMenuInsertReq struct {
+	Id               int    `uri:"id" swaggerignore:"true"`                           //编码
+	ServiceId        int    `form:"serviceId" example:"1" vd:"@:$>0; msg:'服务ID不能为空'"` // 服务id
+	Name             string `form:"name" example:"菜单名称"`                              //菜单名称
+	Icon             string `form:"icon" example:"app-group-fill"`                    //图标
+	Path             string `form:"path" example:"/admin"`                            //路径
+	MenuPath         string `form:"paths" swaggerignore:"true"`                       //id路径
+	MenuType         string `form:"menuType" example:"C"`                             //菜单类型 M-目录 C-菜单 F-按钮
+	Permission       string `form:"permission" example:"admin:sysUser:list"`          //权限编码
+	ParentId         int    `form:"parentId" example:"0"`                             //上级菜单
+	Component        string `form:"component" example:"/admin/sys-user/index"`        //组件名称
+	Sort             int    `form:"sort" example:"0"`                                 //排序
+	Visible          string `form:"visible" example:"1"`                              //是否显示 1-显示 2-隐藏
+	IsFrame          string `form:"isFrame" example:"0"`                              //是否frame 1-是 2-否
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServMenuInsertReq) Generate(model *model.ServMenu) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.ServiceId = s.ServiceId
+	model.Name = s.Name
+	model.Icon = s.Icon
+	model.Path = s.Path
+	model.MenuPath = s.MenuPath
+	model.MenuType = s.MenuType
+	model.Permission = s.Permission
+	model.ParentId = s.ParentId
+	model.Component = s.Component
+	model.Sort = s.Sort
+	model.Visible = s.Visible
+	model.IsFrame = s.IsFrame
+	if s.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+	if s.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+}
+
+func (s *ServMenuInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type ServMenuUpdateReq struct {
+	Id               int    `uri:"id" swaggerignore:"true"`                    //编码
+	Name             string `form:"name" example:"菜单名称"`                       //菜单名称
+	Icon             string `form:"icon" example:"app-group-fill"`             //图标
+	Path             string `form:"path" example:"/admin"`                     //路径
+	MenuPath         string `form:"paths" swaggerignore:"true"`                //id路径
+	MenuType         string `form:"menuType" example:"C"`                      //菜单类型 M-目录 C-菜单 F-按钮
+	Permission       string `form:"permission" example:"admin:sysUser:list"`   //权限编码
+	ParentId         int    `form:"parentId" example:"0"`                      //上级菜单
+	Component        string `form:"component" example:"/admin/sys-user/index"` //组件名称
+	Sort             int    `form:"sort" example:"0"`                          //排序
+	Visible          string `form:"visible" example:"1"`                       //是否显示 1-显示 2-隐藏
+	IsFrame          string `form:"isFrame" example:"0"`                       //是否frame 1-是 2-否
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServMenuUpdateReq) Generate(model *model.ServMenu) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.Name = s.Name
+	model.Icon = s.Icon
+	model.Path = s.Path
+	model.MenuPath = s.MenuPath
+	model.MenuType = s.MenuType
+	model.Permission = s.Permission
+	model.ParentId = s.ParentId
+	model.Component = s.Component
+	model.Sort = s.Sort
+	model.Visible = s.Visible
+	model.IsFrame = s.IsFrame
+	if s.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+	if s.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+}
+
+func (s *ServMenuUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type ServMenuGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *ServMenuGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type ServMenuDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ServMenuDeleteReq) GetId() interface{} {
+	return s.Ids
+}
+
+type ServMenuLabel struct {
+	Id       int         `json:"id,omitempty" gorm:"-"`
+	Label    string      `json:"label,omitempty" gorm:"-"`
+	Children []MenuLabel `json:"children,omitempty" gorm:"-"`
+}
+
+type ServMenuRole struct {
+	model.ServMenu
+	IsSelect bool `json:"is_select" gorm:"-"`
+}
+
+type AppSelectRole struct {
+	RoleId int `uri:"roleId"`
+}
+
+type ServMenuExportReq struct {
+	ServiceId int    `form:"serviceId" example:"1"`
+	Type      string `form:"type" example:"json"` // json excel
+}

+ 107 - 0
app/admin/service/dto/sys_config.go

@@ -0,0 +1,107 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// SysConfigGetPageReq 列表或者搜索使用结构体
+type SysConfigGetPageReq struct {
+	dto.Pagination `search:"-"`
+	ConfigName     string `form:"configName" search:"type:contains;column:config_name;table:sys_config"`
+	ConfigKey      string `form:"configKey" search:"type:contains;column:config_key;table:sys_config"`
+	IsFrontend     string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"`
+	SysConfigOrder
+}
+
+type SysConfigOrder struct {
+	IdOrder         string `search:"type:order;column:id;table:sys_config" form:"idOrder"`
+	ConfigNameOrder string `search:"type:order;column:config_name;table:sys_config" form:"configNameOrder"`
+	ConfigKeyOrder  string `search:"type:order;column:config_key;table:sys_config" form:"configKeyOrder"`
+	CreatedAtOrder  string `search:"type:order;column:created_at;table:sys_config" form:"createdAtOrder"`
+}
+
+func (m *SysConfigGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysConfigGetToSysAppReq struct {
+	IsFrontend string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"`
+}
+
+func (m *SysConfigGetToSysAppReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// SysConfigControl 增、改使用的结构体
+type SysConfigControl struct {
+	Id               int    `uri:"id" swaggerignore:"true"` // 编码
+	ConfigName       string `json:"configName" example:"单-登录"`
+	ConfigKey        string `uri:"configKey" example:"sys_single_login"`
+	ConfigValue      string `json:"configValue" example:"是"`
+	IsFrontend       string `json:"isFrontend" example:"1"` // 1 是 2 否
+	Remark           string `json:"remark" example:"备注"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+// Generate 结构体数据转化 从 SysConfigControl 至 system.SysConfig 对应的模型
+func (s *SysConfigControl) Generate(model *model.SysConfig) {
+	if s.Id == 0 {
+		model.Model = common.Model{Id: s.Id}
+	}
+	model.ConfigName = s.ConfigName
+	model.ConfigKey = s.ConfigKey
+	model.ConfigValue = s.ConfigValue
+	model.IsFrontend = s.IsFrontend
+	model.Remark = s.Remark
+}
+
+// GetId 获取数据对应的ID
+func (s *SysConfigControl) GetId() interface{} {
+	return s.Id
+}
+
+// GetSetSysConfigReq 增、改使用的结构体
+type GetSetSysConfigReq struct {
+	ConfigKey   string `json:"configKey" comment:""`
+	ConfigValue string `json:"configValue" comment:""`
+}
+
+// Generate 结构体数据转化 从 SysConfigControl 至 system.SysConfig 对应的模型
+func (s *GetSetSysConfigReq) Generate(model *model.SysConfig) {
+	model.ConfigValue = s.ConfigValue
+}
+
+type UpdateSetSysConfigReq map[string]string
+
+// SysConfigByKeyReq 根据Key获取配置
+type SysConfigByKeyReq struct {
+	ConfigKey string `uri:"configKey" search:"type:contains;column:config_key;table:sys_config"`
+}
+
+func (m *SysConfigByKeyReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type GetSysConfigByKEYForServiceResp struct {
+	ConfigKey   string `json:"configKey" comment:""`
+	ConfigValue string `json:"configValue" comment:""`
+}
+
+type SysConfigGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysConfigGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysConfigDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysConfigDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 100 - 0
app/admin/service/dto/sys_dept.go

@@ -0,0 +1,100 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	common "Medical_OAuth/common/model"
+)
+
+// SysDeptGetPageReq 列表或者搜索使用结构体
+type SysDeptGetPageReq struct {
+	DeptName string `form:"deptName" search:"type:exact;column:dept_name;table:sys_dept" example:"部门名称"` //部门名称
+	DeptId   int    `form:"deptId" search:"-" swaggerignore:"true"`                                      //部门名称
+	SysDeptOrder
+}
+
+type SysDeptOrder struct {
+	SortOrder string `search:"type:order;column:sort;table:sys_dept" form:"sort" default:"asc"` //排序 ASC 升序 DESC 降序
+}
+
+func (m *SysDeptGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysDeptInsertReq struct {
+	Id               int    `json:"id" swaggerignore:"true"`
+	ParentId         int    `json:"parentId" example:"0" vd:"?"`           //上级部门
+	DeptName         string `json:"deptName" example:"部门名称" vd:"len($)>0"` //部门名称
+	Sort             int    `json:"sort" swaggerignore:"true"`             //排序
+	Status           int    `json:"status"  swaggerignore:"true"`          //状态 1-停用 2-正常
+	DeptPath         string `swaggerignore:"true"`                         //路径
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDeptInsertReq) Generate(model *model.SysDept) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.DeptName = s.DeptName
+	model.ParentId = s.ParentId
+	model.Sort = 0
+	model.Status = 2
+}
+
+// GetId 获取数据对应的ID
+func (s *SysDeptInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDeptUpdateReq struct {
+	Id               int    `json:"id" comment:"编码"`                       // 编码
+	DeptName         string `json:"deptName" example:"部门名称" vd:"len($)>0"` //部门名称
+	Status           int    `json:"status" swaggerignore:"true"`           //状态 1-停用 2-正常
+	Sort             int    `json:"sort" swaggerignore:"true"`             //排序
+	DeptPath         string `swaggerignore:"true"`                         //路径
+	common.ControlBy `swaggerignore:"true"`
+}
+
+// Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型
+func (s *SysDeptUpdateReq) Generate(model *model.SysDept) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.DeptName = s.DeptName
+	model.Sort = 0
+	model.Status = 2
+}
+
+// GetId 获取数据对应的ID
+func (s *SysDeptUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDeptGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysDeptGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDeptDeleteReq struct {
+	Id int `json:"id"`
+}
+
+func (s *SysDeptDeleteReq) GetId() interface{} {
+	return s.Id
+}
+
+type DeptLabel struct {
+	Id       int         `gorm:"-" json:"id"`
+	Label    string      `gorm:"-" json:"label"`
+	Children []DeptLabel `gorm:"-" json:"children"`
+}
+
+type SysDeptEnterReq struct {
+	Id int `json:"id"`
+}
+
+func (s *SysDeptEnterReq) GetId() interface{} {
+	return s.Id
+}

+ 120 - 0
app/admin/service/dto/sys_dict_data_dto.go

@@ -0,0 +1,120 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+type SysDictDataGetPageReq struct {
+	dto.Pagination `search:"-"`
+	Id             int    `form:"id" search:"type:exact;column:dict_code;table:sys_dict_data" comment:""`
+	DictLabel      string `form:"dictLabel" search:"type:contains;column:dict_label;table:sys_dict_data" comment:""`
+	DictValue      string `form:"dictValue" search:"type:contains;column:dict_value;table:sys_dict_data" comment:""`
+	DictType       string `form:"dictType" search:"type:contains;column:dict_type;table:sys_dict_data" comment:""`
+	Status         string `form:"status" search:"type:exact;column:status;table:sys_dict_data" comment:""`
+}
+
+func (m *SysDictDataGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysDictDataGetAllResp struct {
+	DictLabel string `json:"label"`
+	DictValue string `json:"value"`
+}
+
+type SysDictDataInsertReq struct {
+	Id               int    `json:"-" comment:"" swaggerignore:"true"`
+	DictSort         int    `json:"dictSort" comment:""`
+	DictLabel        string `json:"dictLabel" comment:""`
+	DictValue        string `json:"dictValue" comment:""`
+	DictType         string `json:"dictType" comment:""`
+	CssClass         string `json:"cssClass" comment:""`
+	ListClass        string `json:"listClass" comment:""`
+	IsDefault        string `json:"isDefault" comment:""`
+	Status           int    `json:"status" comment:""`
+	Default          string `json:"default" comment:""`
+	Remark           string `json:"remark" comment:""`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictDataInsertReq) Generate(model *model.SysDictData) {
+	model.DictCode = s.Id
+	model.DictSort = s.DictSort
+	model.DictLabel = s.DictLabel
+	model.DictValue = s.DictValue
+	model.DictType = s.DictType
+	model.CssClass = s.CssClass
+	model.ListClass = s.ListClass
+	model.IsDefault = s.IsDefault
+	model.Status = s.Status
+	model.Default = s.Default
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysDictDataInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictDataUpdateReq struct {
+	Id               int    `uri:"dictCode" comment:""`
+	DictSort         int    `json:"dictSort" comment:""`
+	DictLabel        string `json:"dictLabel" comment:""`
+	DictValue        string `json:"dictValue" comment:""`
+	DictType         string `json:"dictType" comment:""`
+	CssClass         string `json:"cssClass" comment:""`
+	ListClass        string `json:"listClass" comment:""`
+	IsDefault        string `json:"isDefault" comment:""`
+	Status           int    `json:"status" comment:""`
+	Default          string `json:"default" comment:""`
+	Remark           string `json:"remark" comment:""`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictDataUpdateReq) Generate(model *model.SysDictData) {
+	model.DictCode = s.Id
+	model.DictSort = s.DictSort
+	model.DictLabel = s.DictLabel
+	model.DictValue = s.DictValue
+	model.DictType = s.DictType
+	model.CssClass = s.CssClass
+	model.ListClass = s.ListClass
+	model.IsDefault = s.IsDefault
+	model.Status = s.Status
+	model.Default = s.Default
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysDictDataUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictDataGetReq struct {
+	Id int `uri:"dictCode"`
+}
+
+func (s *SysDictDataGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictDataDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictDataDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 99 - 0
app/admin/service/dto/sys_dict_type_dto.go

@@ -0,0 +1,99 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+type SysDictTypeGetPageReq struct {
+	dto.Pagination `search:"-"`
+	DictId         []int  `form:"dictId" search:"type:in;column:dict_id;table:sys_dict_type"`
+	DictName       string `form:"dictName" search:"type:contains;column:dict_name;table:sys_dict_type"`
+	DictType       string `form:"dictType" search:"type:contains;column:dict_type;table:sys_dict_type"`
+	Status         int    `form:"status" search:"type:exact;column:status;table:sys_dict_type"`
+}
+
+type SysDictTypeOrder struct {
+	DictIdOrder string `search:"type:order;column:dict_id;table:sys_dict_type" form:"dictIdOrder"`
+}
+
+func (m *SysDictTypeGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysDictTypeInsertReq struct {
+	Id               int    `uri:"id"`
+	DictName         string `json:"dictName"`
+	DictType         string `json:"dictType"`
+	Status           int    `json:"status"`
+	Remark           string `json:"remark"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictTypeInsertReq) Generate(model *model.SysDictType) {
+	if s.Id != 0 {
+		model.ID = s.Id
+	}
+	model.DictName = s.DictName
+	model.DictType = s.DictType
+	model.Status = s.Status
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+
+}
+
+func (s *SysDictTypeInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictTypeUpdateReq struct {
+	Id               int    `uri:"id"`
+	DictName         string `json:"dictName"`
+	DictType         string `json:"dictType"`
+	Status           int    `json:"status"`
+	Remark           string `json:"remark"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictTypeUpdateReq) Generate(model *model.SysDictType) {
+	if s.Id != 0 {
+		model.ID = s.Id
+	}
+	model.DictName = s.DictName
+	model.DictType = s.DictType
+	model.Status = s.Status
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysDictTypeUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictTypeGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysDictTypeGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysDictTypeDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysDictTypeDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 58 - 0
app/admin/service/dto/sys_login_log_dto.go

@@ -0,0 +1,58 @@
+package dto
+
+import (
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+	"time"
+)
+
+type SysLoginLogGetPageReq struct {
+	dto.Pagination `search:"-"`
+	Username       string `form:"username" search:"type:exact;column:username;table:sys_error: %s_log" comment:"用户名"`
+	Status         string `form:"status" search:"type:exact;column:status;table:sys_error: %s_log" comment:"状态"`
+	Ipaddr         string `form:"ipaddr" search:"type:exact;column:ipaddr;table:sys_login_log" comment:"ip地址"`
+	LoginLocation  string `form:"loginLocation" search:"type:exact;column:login_location;table:sys_login_log" comment:"归属地"`
+	BeginTime      string `form:"beginTime" search:"type:gte;column:ctime;table:sys_login_log" comment:"创建时间"`
+	EndTime        string `form:"endTime" search:"type:lte;column:ctime;table:sys_login_log" comment:"结束时间"`
+	SysLoginLogOrder
+}
+
+type SysLoginLogOrder struct {
+	CreatedAtOrder string `search:"type:order;column:created_at;table:sys_login_log" form:"createdAtOrder"`
+}
+
+func (m *SysLoginLogGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysLoginLogControl struct {
+	ID            int       `uri:"Id" comment:"主键"` // 主键
+	Username      string    `json:"username" comment:"用户名"`
+	Status        string    `json:"status" comment:"状态"`
+	Ipaddr        string    `json:"ipaddr" comment:"ip地址"`
+	LoginLocation string    `json:"loginLocation" comment:"归属地"`
+	Browser       string    `json:"browser" comment:"浏览器"`
+	Os            string    `json:"os" comment:"系统"`
+	Platform      string    `json:"platform" comment:"固件"`
+	LoginTime     time.Time `json:"loginTime" comment:"登录时间"`
+	Remark        string    `json:"remark" comment:"备注"`
+	Msg           string    `json:"msg" comment:"信息"`
+}
+
+type SysLoginLogGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysLoginLogGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysLoginLogDeleteReq 功能删除请求参数
+type SysLoginLogDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysLoginLogDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 163 - 0
app/admin/service/dto/sys_menu.go

@@ -0,0 +1,163 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	common "Medical_OAuth/common/model"
+)
+
+// SysMenuGetPageReq 列表或者搜索使用结构体
+type SysMenuGetPageReq struct {
+	Name    string `form:"name" search:"-"`                                           // 菜单名称
+	Visible int    `form:"visible" search:"type:exact;column:visible;table:sys_menu"` // 显示状态
+	SysMenuOrder
+}
+
+type SysMenuOrder struct {
+	SortOrder string `search:"type:order;column:sort;table:sys_menu" form:"sort" default:"asc"` //排序 ASC 升序 DESC 降序
+}
+
+func (m *SysMenuGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysMenuInsertReq struct {
+	Id            int    `uri:"id" comment:"编码" swaggerignore:"true"`                  // 编码
+	ParentId      int    `form:"parentId" example:"0"`                                   //上级菜单
+	ServiceMenuId int    `uri:"id"`                                                      //编码
+	ServiceId     int    `form:"serviceId" example:"1" vd:"@:$>0; msg:'服务ID不能为空'"` // 服务id
+	Sort          int    `form:"sort" example:"0"`                                       //排序
+	Visible       string `form:"visible" example:"1"`                                    //是否显示 1-显示 2-隐藏
+
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysMenuInsertReq) Generate(model *model.SysMenu) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.ParentId = s.ParentId
+	model.ServiceMenuId = s.ServiceMenuId
+	model.ServiceId = s.ServiceId
+	model.Sort = s.Sort
+	model.Visible = s.Visible
+	if s.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+	if s.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+}
+
+func (s *SysMenuInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysMenuUpdateReq struct {
+	Id               int    `uri:"id" comment:"编码"`           // 编码
+	Sort             int    `form:"sort" comment:"排序"`        //排序
+	Visible          string `form:"visible" comment:"是否显示"` //是否显示
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysMenuUpdateReq) Generate(model *model.SysMenu) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.Sort = s.Sort
+	model.Visible = s.Visible
+	if s.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+	if s.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+}
+
+func (s *SysMenuUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysMenuGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysMenuGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysMenuDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysMenuDeleteReq) GetId() interface{} {
+	return s.Ids
+}
+
+type SysMenu struct {
+	Id            int    `json:"id"`            //编码
+	ParentId      int    `json:"parentId"`      // 父id
+	ServiceMenuId int    `json:"serviceMenuId"` //服务菜单ID
+	ServiceId     int    `json:"serviceId"`     // 服务ID
+	Sort          int    `json:"sort"`          // 排序
+	Visible       string `json:"visible"`       // 1-显示 0-隐藏
+	MenuPath      string `json:"paths"`         //
+
+	Name       string `json:"name"`       // 菜单名称
+	MenuType   string `json:"menuType"`   // 菜单类型
+	Icon       string `json:"icon"`       // 图标
+	Component  string `json:"component"`  // 组件路径
+	IsFrame    string `json:"isFrame"`    // 是否外链 1-是 2-否
+	Path       string `json:"path"`       // 外链路由地址
+	Permission string `json:"permission"` // 权限标识
+	common.ControlBy
+	common.ModelTime
+}
+
+func (s SysMenu) Generate() (model model.SysMenu) {
+
+	model.Id = s.Id
+	model.ParentId = s.ParentId
+	model.ServiceMenuId = s.ServiceMenuId
+	model.ServiceId = s.ServiceId
+	model.Sort = s.Sort
+	model.Visible = s.Visible
+	model.MenuPath = s.MenuPath
+
+	model.Name = s.Name
+	model.MenuType = s.MenuType
+	model.Icon = s.Icon
+	model.Component = s.Component
+	model.IsFrame = s.IsFrame
+	model.Path = s.Path
+	model.Permission = s.Permission
+
+	if s.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+	if s.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if !s.CreatedAt.IsZero() {
+		model.CreatedAt = s.CreatedAt
+	}
+	if !s.UpdatedAt.IsZero() {
+		model.UpdatedAt = s.UpdatedAt
+	}
+	return
+}
+
+type MenuLabel struct {
+	Id       int         `json:"id,omitempty" gorm:"-"`
+	Label    string      `json:"label,omitempty" gorm:"-"`
+	Children []MenuLabel `json:"children,omitempty" gorm:"-"`
+}
+
+type MenuRole struct {
+	model.SysMenu
+	IsSelect bool `json:"is_select" gorm:"-"`
+}
+
+type SelectRole struct {
+	RoleId int `uri:"roleId"`
+}

+ 103 - 0
app/admin/service/dto/sys_opera_log_dto.go

@@ -0,0 +1,103 @@
+package dto
+
+import (
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+	"time"
+
+	"Medical_OAuth/app/admin/model"
+)
+
+const (
+	OperaStatusEnabel  = "1" // 状态-正常
+	OperaStatusDisable = "2" // 状态-关闭
+)
+
+type SysOperaLogGetPageReq struct {
+	dto.Pagination `search:"-"`
+	Title          string `form:"title" search:"type:contains;column:title;table:sys_opera_log" comment:"操作模块"`
+	Method         string `form:"method" search:"type:contains;column:method;table:sys_opera_log" comment:"函数"`
+	RequestMethod  string `form:"requestMethod" search:"type:contains;column:request_method;table:sys_opera_log" comment:"请求方式: GET POST PUT DELETE"`
+	OperaUrl       string `form:"operaUrl" search:"type:contains;column:opera_url;table:sys_opera_log" comment:"访问地址"`
+	OperaIp        string `form:"operaIp" search:"type:exact;column:opera_ip;table:sys_opera_log" comment:"客户端ip"`
+	Status         int    `form:"status" search:"type:exact;column:status;table:sys_opera_log" comment:"状态 1:正常 2:关闭"`
+	BeginTime      string `form:"beginTime" search:"type:gte;column:created_at;table:sys_opera_log" comment:"创建时间"`
+	EndTime        string `form:"endTime" search:"type:lte;column:created_at;table:sys_opera_log" comment:"更新时间"`
+	SysOperaLogOrder
+}
+
+type SysOperaLogOrder struct {
+	CreatedAtOrder string `search:"type:order;column:created_at;table:sys_opera_log" form:"createdAtOrder"`
+}
+
+func (m *SysOperaLogGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysOperaLogControl struct {
+	ID            int       `uri:"Id" comment:"编码"` // 编码
+	Title         string    `json:"title" comment:"操作模块"`
+	BusinessType  string    `json:"businessType" comment:"操作类型"`
+	BusinessTypes string    `json:"businessTypes" comment:""`
+	Method        string    `json:"method" comment:"函数"`
+	RequestMethod string    `json:"requestMethod" comment:"请求方式"`
+	OperatorType  string    `json:"operatorType" comment:"操作类型"`
+	OperaName     string    `json:"operaName" comment:"操作者"`
+	DeptName      string    `json:"organName" comment:"机构名称"`
+	OperaUrl      string    `json:"operaUrl" comment:"访问地址"`
+	OperaIp       string    `json:"operaIp" comment:"客户端ip"`
+	OperaLocation string    `json:"operaLocation" comment:"访问位置"`
+	OperaParam    string    `json:"operaParam" comment:"请求参数"`
+	Status        string    `json:"status" comment:"操作状态"`
+	OperaTime     time.Time `json:"operaTime" comment:"操作时间"`
+	JsonResult    string    `json:"jsonResult" comment:"返回数据"`
+	Remark        string    `json:"remark" comment:"备注"`
+	LatencyTime   string    `json:"latencyTime" comment:"耗时"`
+	UserAgent     string    `json:"userAgent" comment:"ua"`
+}
+
+func (s *SysOperaLogControl) Generate() (*model.SysOperaLog, error) {
+	return &model.SysOperaLog{
+		Model:         common.Model{Id: s.ID},
+		Title:         s.Title,
+		BusinessType:  s.BusinessType,
+		BusinessTypes: s.BusinessTypes,
+		Method:        s.Method,
+		RequestMethod: s.RequestMethod,
+		OperatorType:  s.OperatorType,
+		OperaName:     s.OperaName,
+		DeptName:      s.DeptName,
+		OperaUrl:      s.OperaUrl,
+		OperaIp:       s.OperaIp,
+		OperaLocation: s.OperaLocation,
+		OperaParam:    s.OperaParam,
+		Status:        s.Status,
+		OperaTime:     s.OperaTime,
+		JsonResult:    s.JsonResult,
+		Remark:        s.Remark,
+		LatencyTime:   s.LatencyTime,
+		UserAgent:     s.UserAgent,
+	}, nil
+}
+
+func (s *SysOperaLogControl) GetId() interface{} {
+	return s.ID
+}
+
+type SysOperaLogGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysOperaLogGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysOperaLogDeleteReq 功能删除请求参数
+type SysOperaLogDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysOperaLogDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 107 - 0
app/admin/service/dto/sys_post.go

@@ -0,0 +1,107 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// SysPostPageReq 列表或者搜索使用结构体
+type SysPostPageReq struct {
+	dto.Pagination `search:"-"`
+	PostName       string `form:"postName" search:"type:contains;column:post_name;table:sys_post"` // 名称
+	Status         int    `form:"status" search:"type:exact;column:status;table:sys_post"`         // 状态
+	SysPostOrder
+}
+
+type SysPostOrder struct {
+	SortOrder string `search:"type:order;column:sort;table:sys_post" form:"sort" default:"asc"` //排序 ASC 升序 DESC 降序
+}
+
+func (m *SysPostPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// SysPostInsertReq 增使用的结构体
+type SysPostInsertReq struct {
+	Id               int    `json:"id" comment:"id" swaggerignore:"true"`
+	PostName         string `json:"postName" example:"岗位名称" vd:"@:len($)>0; msg:'岗位名称不能为空'"` //岗位名称
+	Sort             int    `json:"sort" example:"0"`                                        //排序
+	Status           int    `json:"status" vd:"$>0" example:"2"`                             //状态 1-停用 2-正常
+	Remark           string `json:"remark" example:"备注"`                                     //备注
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysPostInsertReq) Generate(model *model.SysPost) {
+	model.PostName = s.PostName
+	model.Sort = s.Sort
+	model.Status = s.Status
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+// GetId 获取数据对应的ID
+func (s *SysPostInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysPostUpdateReq 改使用的结构体
+type SysPostUpdateReq struct {
+	Id               int    `uri:"id"  swaggerignore:"true"`
+	PostName         string `json:"postName"  example:"岗位名称"` // 岗位名称
+	Sort             int    `json:"sort" example:"0"`         //排序
+	Status           int    `json:"status"   example:"2"`     //状态
+	Remark           string `json:"remark"   example:"备注"`    // 备注
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysPostUpdateReq) Generate(model *model.SysPost) {
+	model.Id = s.Id
+	model.PostName = s.PostName
+	model.Sort = s.Sort
+	model.Status = s.Status
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysPostUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysPostGetReq 获取单个的结构体
+type SysPostGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysPostGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysPostDeleteReq 删除的结构体
+type SysPostDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysPostDeleteReq) Generate(model *model.SysPost) {
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysPostDeleteReq) GetId() interface{} {
+	return s.Ids
+}

+ 115 - 0
app/admin/service/dto/sys_register_auth.go

@@ -0,0 +1,115 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// SysRegisterAuthPageReq 列表或者搜索使用结构体
+type SysRegisterAuthPageReq struct {
+	dto.Pagination `search:"-"`
+	URKey          string `form:"URKey" search:"type:contains;column:ur_key;table:sys_register_auth"` // 名称
+	Status         int    `form:"status" search:"type:exact;column:status;table:sys_register_auth"`   // 状态
+}
+
+func (m *SysRegisterAuthPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// SysRegisterAuthInsertReq 增使用的结构体
+type SysRegisterAuthInsertReq struct {
+	Id         int    `json:"id" swaggerignore:"true"`
+	URKey      string `swaggerignore:"true"`
+	RoleId     int    `json:"roleId" vd:"$>0" example:"2"`    //角色id
+	DeptId     int    `json:"deptId" vd:"$>0" example:"2"`    // 部门id
+	Status     int    `json:"status" vd:"$>0" example:"2"`    // 状态 1-停用 2-正常
+	SMSVerify  int    `json:"SMSVerify" vd:"$>0" example:"2"` // 短信验证 1-关闭 2-开启
+	InviteCode string `json:"inviteCode"  example:"HnhsqMls"` // 邀请码,可以为空
+
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRegisterAuthInsertReq) Generate(model *model.SysRegisterAuth) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	if len(s.URKey) > 0 {
+		model.URKey = s.URKey
+	}
+	model.RoleId = s.RoleId
+	model.DeptId = s.DeptId
+	model.Status = s.Status
+	model.SMSVerify = s.SMSVerify
+	model.InviteCode = s.InviteCode
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+// GetId 获取数据对应的ID
+func (s *SysRegisterAuthInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysRegisterAuthUpdateReq 改使用的结构体
+type SysRegisterAuthUpdateReq struct {
+	Id         int    `uri:"id" swaggerignore:"true"`
+	RoleId     int    `json:"roleId" vd:"$>0" example:"2"`    //角色id
+	DeptId     int    `json:"deptId" vd:"$>0" example:"2"`    // 部门id
+	Status     int    `json:"status" vd:"$>0" example:"2"`    // 状态 1-停用 2-正常
+	SMSVerify  int    `json:"SMSVerify" vd:"$>0" example:"2"` // 短信验证 1-关闭 2-开启
+	InviteCode string `json:"inviteCode"  example:"HnhsqMls"` // 邀请码,可以为空
+
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRegisterAuthUpdateReq) Generate(model *model.SysRegisterAuth) {
+	model.Id = s.Id
+	model.RoleId = s.RoleId
+	model.DeptId = s.DeptId
+	model.Status = s.Status
+	model.SMSVerify = s.SMSVerify
+	model.InviteCode = s.InviteCode
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysRegisterAuthUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysRegisterAuthGetReq 获取单个的结构体
+type SysRegisterAuthGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysRegisterAuthGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysRegisterAuthDeleteReq 删除的结构体
+type SysRegisterAuthDeleteReq struct {
+	Id               int `json:"id"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRegisterAuthDeleteReq) Generate(model *model.SysRegisterAuth) {
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysRegisterAuthDeleteReq) GetId() interface{} {
+	return s.Id
+}

+ 157 - 0
app/admin/service/dto/sys_role.go

@@ -0,0 +1,157 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+type SysRoleGetPageReq struct {
+	dto.Pagination `search:"-"`
+	Name           string `form:"name" search:"type:contains;column:name;table:sys_role"` // 角色名称
+	SysRoleOrder
+}
+
+type SysRoleOrder struct {
+	SortOrder string `form:"sort" search:"type:order;column:sort;table:sys_role" default:"asc"`
+}
+
+func (m *SysRoleGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysRoleInsertReq struct {
+	Id               int    `uri:"id" swaggerignore:"true" swaggerignore:"true"` // 角色编码
+	Name             string `form:"roleName" example:"管理员"`                      // 角色名称
+	Status           string `form:"status" example:"2"`                          // 状态 1-停用 2-正常
+	RoleKey          string `form:"roleKey" swaggerignore:"true"`                // 角色代码
+	Sort             int    `form:"roleSort" example:"0"`                        // 角色排序
+	DataScope        int    `form:"dataScope" example:"1"`                       // 数据权限 1-全部数据权限 3-本机构数据权限 4-本机构及以下数据权限 5-仅本人数据权限
+	Remark           string `form:"remark" example:"备注"`                         // 备注
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRoleInsertReq) Generate(model *model.SysRole) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.Name = s.Name
+	model.Status = s.Status
+	model.RoleKey = s.RoleKey
+	model.Sort = s.Sort
+	model.DataScope = s.DataScope
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysRoleInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleUpdateReq struct {
+	Id               int    `uri:"id" comment:"角色编码" swaggerignore:"true"` // 角色编码
+	Name             string `form:"roleName" example:"管理员"`                // 角色名称
+	Status           string `form:"status" example:"2"`                    // 状态 1-停用 2-正常
+	Sort             int    `form:"roleSort" example:"0"`                  // 角色排序
+	DataScope        int    `form:"dataScope" example:"1"`                 // 数据权限 1-全部数据权限 3-本机构数据权限 4-本机构及以下数据权限 5-仅本人数据权限
+	Remark           string `form:"remark" example:"备注"`                   // 备注
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRoleUpdateReq) Generate(model *model.SysRole) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	model.Name = s.Name
+	model.Status = s.Status
+	model.Sort = s.Sort
+	model.DataScope = s.DataScope
+	model.Remark = s.Remark
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysRoleUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleByName struct {
+	RoleName string `form:"role"` // 角色编码
+}
+
+type SysRoleGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysRoleGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleDeleteReq struct {
+	Id               int `json:"id"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRoleDeleteReq) GetId() interface{} {
+	return s.Id
+}
+
+type DeptIdList struct {
+	DeptId int `json:"Id"`
+}
+
+type SysRoleUpdateRoleApiReq struct {
+	Id               int   `uri:"id" comment:"角色编码" swaggerignore:"true"` // 角色编码
+	ServiceId        int   `json:"serviceId" example:"1"`                 // 服务id
+	ApiIds           []int `json:"apiIds" example:"1,2,3"`                // api路由 id
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRoleUpdateRoleApiReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleGetRoleApiListReq struct {
+	Id        int `uri:"id" comment:"角色编码" swaggerignore:"true"` // 角色编码
+	ServiceId int `form:"serviceId" example:"1"`                 // 服务id
+}
+
+func (s *SysRoleGetRoleApiListReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleGetRoleApiListResp struct {
+	ApiList []model.ServApi `json:"apiList"`
+	ApiIds  []int           `json:"apiIds"`
+}
+
+type SysRoleUpdateRoleMenuReq struct {
+	Id               int   `uri:"id" comment:"角色编码" swaggerignore:"true"` // 角色编码
+	MenuIds          []int `json:"menuIds" example:"1,2,3"`               // 系统菜单id
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysRoleUpdateRoleMenuReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleGetRoleMenuListReq struct {
+	Id int `uri:"id" comment:"角色编码" swaggerignore:"true"` // 角色编码
+}
+
+func (s *SysRoleGetRoleMenuListReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysRoleGetRoleMenuListResp struct {
+	MenuIds []int `json:"menuIds"`
+}

+ 143 - 0
app/admin/service/dto/sys_service.go

@@ -0,0 +1,143 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+)
+
+// SysServicePageReq 列表或者搜索使用结构体
+type SysServicePageReq struct {
+	dto.Pagination `search:"-"`
+	Name           string `form:"name" search:"type:orcontains;column:name;table:sys_service"` // 服务名称
+	No             string `form:"no" search:"type:orcontains;column:no;table:sys_service"`     // 服务编号
+	Status         int    `form:"status" search:"type:exact;column:status;table:sys_service"`  // 状态
+	SysServiceOrder
+}
+
+type SysServiceOrder struct {
+	IdOrder string `form:"id" search:"type:order;column:id;table:sys_service" default:"desc"` //排序 ASC 升序 DESC 降序
+}
+
+func (m *SysServicePageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// SysServiceInsertReq 增使用的结构体
+type SysServiceInsertReq struct {
+	Id               int    `json:"id" comment:"id" swaggerignore:"true"`
+	No               string `json:"serviceNo" swaggerignore:"true"`                                                     // 服务编号
+	Name             string `json:"name" example:"用户系统" vd:"@:len($)>0; msg:'服务名称不能为空'"`                                // 服务名称
+	Host             string `json:"host" example:"http://127.0.0.1:8080/user" vd:"@:len($)>0; msg:'服务地址不能为空'"`          // 服务地址
+	AuthCode         string `json:"authCode" example:"3EDJRaagFTVVo2Ilo80nHJfLVN1OgN8d" vd:"@:len($)>0; msg:'授权码不能为空'"` // 授权码
+	Status           int    `json:"status" vd:"$>0" example:"1" default:"1"`                                            // 状态 1-停用 2-正常
+	RoleApiUrl       string `json:"roleApiUrl" example:"/role/api"`                                                     // 角色api回调地址
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysServiceInsertReq) Generate(model *model.SysService) {
+	model.No = s.No
+	model.Name = s.Name
+	model.Host = s.Host
+	model.Status = s.Status
+	model.AuthCode = s.AuthCode
+	model.RoleApiUrl = s.RoleApiUrl
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+// GetId 获取数据对应的ID
+func (s *SysServiceInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysServiceUpdateReq 改使用的结构体
+type SysServiceUpdateReq struct {
+	Id               int    `uri:"id"  swaggerignore:"true"`
+	Name             string `json:"name" example:"用户系统" vd:"@:len($)>0; msg:'服务名称不能为空'"`                                // 服务名称
+	Host             string `json:"host" example:"http://127.0.0.1:8080/user" vd:"@:len($)>0; msg:'服务地址不能为空'"`          // 服务地址
+	AuthCode         string `json:"authCode" example:"3EDJRaagFTVVo2Ilo80nHJfLVN1OgN8d" vd:"@:len($)>0; msg:'授权码不能为空'"` // 授权码
+	Status           int    `json:"status" vd:"$>0" example:"1" default:"1"`
+	RoleApiUrl       string `json:"roleApiUrl" example:"/role/api"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysServiceUpdateReq) Generate(model *model.SysService) {
+	model.Id = s.Id
+	model.Name = s.Name
+	model.Host = s.Host
+	model.AuthCode = s.AuthCode
+	model.Status = s.Status
+	model.RoleApiUrl = s.RoleApiUrl
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysServiceUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysServiceGetReq 获取单个的结构体
+type SysServiceGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysServiceGetReq) GetId() interface{} {
+	return s.Id
+}
+
+// SysServiceDeleteReq 删除的结构体
+type SysServiceDeleteReq struct {
+	Ids              []int `json:"ids"`
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysServiceDeleteReq) Generate(model *model.SysService) {
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysServiceDeleteReq) GetId() interface{} {
+	return s.Ids
+}
+
+// SysServiceDiscoveryReq 增使用的结构体
+type SysServiceDiscoveryReq struct {
+	Id         int    `swaggerignore:"true"`
+	No         string `swaggerignore:"true"`                                                                      // 服务编号
+	Name       string `json:"name" example:"用户系统" vd:"@:len($)>0; msg:'服务名称不能为空'"`                                // 服务名称
+	Host       string `json:"host" example:"http://127.0.0.1:8080/user" vd:"@:len($)>0; msg:'服务地址不能为空'"`          // 服务地址
+	AuthCode   string `json:"authCode" example:"3EDJRaagFTVVo2Ilo80nHJfLVN1OgN8d" vd:"@:len($)>0; msg:'授权码不能为空'"` // 授权码
+	RoleApiUrl string `json:"roleApiUrl" example:"/api/role-api-test"`                                            // 授权码
+	Status     int    `swaggerignore:"true"`                                                                      // 状态 1-停用 2-正常
+}
+
+func (s *SysServiceDiscoveryReq) Generate(model *model.SysService) {
+	if s.Id != 0 {
+		model.Id = s.Id
+	}
+	if len(s.No) > 0 {
+		model.No = s.No
+	}
+	model.Name = s.Name
+	model.Host = s.Host
+	model.AuthCode = s.AuthCode
+	model.RoleApiUrl = s.RoleApiUrl
+}
+
+// GetId 获取数据对应的ID
+func (s *SysServiceDiscoveryReq) GetId() interface{} {
+	return s.Id
+}

+ 247 - 0
app/admin/service/dto/sys_user.go

@@ -0,0 +1,247 @@
+package dto
+
+import (
+	"Medical_OAuth/app/admin/model"
+	dto2 "Medical_OAuth/common/dto"
+	model2 "Medical_OAuth/common/model"
+)
+
+type SysUserGetPageReq struct {
+	dto2.Pagination `search:"-"`
+	Username        string `form:"username" search:"type:contains;column:username;table:sys_user" comment:"用户名"`
+	NickName        string `form:"nickName" search:"type:contains;column:nick_name;table:sys_user" comment:"昵称"`
+	RoleId          int    `form:"roleId" search:"type:exact;column:role_id;table:sys_user" comment:"角色ID"`
+	DeptId          int    `form:"deptId" search:"type:exact;column:dept_id;table:sys_user" comment:"部门ID"`
+	PostId          int    `form:"postId" search:"type:exact;column:post_id;table:sys_user" comment:"岗位ID"`
+	Status          string `form:"status" search:"type:exact;column:status;table:sys_user" comment:"状态"`
+	SysUserOrder
+}
+type SysUserOrder struct {
+	//UserIdOrder    string `search:"type:order;column:id;table:sys_user" form:"userIdOrder"`
+	//UsernameOrder  string `search:"type:order;column:username;table:sys_user" form:"usernameOrder"`
+	//StatusOrder    string `search:"type:order;column:status;table:sys_user" form:"statusOrder"`
+	CreatedAtOrder string `search:"type:order;column:created_at;table:sys_user" form:"createdAtOrder" default:"desc"`
+}
+
+func (m *SysUserGetPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type SysUserGetCountReq struct {
+	RoleIds []int `form:"roleId" search:"type:in;column:role_id;table:sys_user" comment:"角色ID"`
+	DeptIds []int `form:"deptId" search:"type:in;column:dept_id;table:sys_user" comment:"部门ID"`
+	PostIds []int `form:"postId" search:"type:in;column:post_id;table:sys_user" comment:"岗位ID"`
+}
+
+func (m *SysUserGetCountReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+type ResetSysUserPwdReq struct {
+	Id               int    `json:"id" example:"1" vd:"$>0"`                 // 用户ID
+	Password         string `json:"password" example:"123456" vd:"len($)>0"` // 密码
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *ResetSysUserPwdReq) GetId() interface{} {
+	return s.Id
+}
+
+func (s *ResetSysUserPwdReq) Generate(userModel *model.SysUser) {
+	if s.Id != 0 {
+		userModel.Id = s.Id
+	}
+	userModel.Password = s.Password
+	if s.ControlBy.UpdateBy != 0 {
+		userModel.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		userModel.CreateBy = s.CreateBy
+	}
+}
+
+type UpdateSysUserStatusReq struct {
+	Id               int    `json:"id" example:"1" vd:"$>0"`          // 用户ID
+	Status           string `json:"status" example:"2" vd:"len($)>0"` // 状态 1-停用 2-正常
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *UpdateSysUserStatusReq) GetId() interface{} {
+	return s.Id
+}
+
+func (s *UpdateSysUserStatusReq) Generate(userModel *model.SysUser) {
+	if s.Id != 0 {
+		userModel.Id = s.Id
+	}
+	userModel.Status = s.Status
+	if s.ControlBy.UpdateBy != 0 {
+		userModel.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		userModel.CreateBy = s.CreateBy
+	}
+}
+
+type SysUserInsertReq struct {
+	Id               int    `json:"id" swaggerignore:"true" comment:"用户ID"`                    // 用户ID
+	Username         string `json:"username" example:"username" vd:"@:len($)>0 msg:'用户名不能为空'"` //用户名
+	Password         string `json:"password" example:"123456" vd:"@:len($)>5 msg:'密码格式不正确'"`   //密码
+	NickName         string `json:"nickName" example:"姓名"`                                     //姓名
+	Phone            string `json:"phone" example:"13912345678" swaggerignore:"true"`          //手机号
+	RoleId           int    `json:"roleId" example:"1" swaggerignore:"true" `                  //角色id
+	DeptId           int    `json:"deptId" example:"1" swaggerignore:"true"`                   //部门id
+	PostId           int    `json:"postId" example:"1" swaggerignore:"true"`                   //岗位id
+	Remark           string `json:"remark" example:"备注" swaggerignore:"true"`                  // 备注
+	Status           string `json:"status" example:"2" swaggerignore:"true"`                   // 状态
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysUserInsertReq) Generate(userModel *model.SysUser) {
+	if s.Id != 0 {
+		userModel.Id = s.Id
+	}
+	userModel.Username = s.Username
+	userModel.Password = s.Password
+	userModel.NickName = s.NickName
+	userModel.Phone = s.Phone
+	userModel.RoleId = s.RoleId
+	userModel.DeptId = s.DeptId
+	userModel.Remark = s.Remark
+	userModel.Status = s.Status
+	if s.ControlBy.UpdateBy != 0 {
+		userModel.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		userModel.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysUserInsertReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysUserUpdateReq struct {
+	Id               int    `json:"id"`                                               // 用户id
+	NickName         string `json:"nickName" example:"昵称"`                            // 昵称
+	Phone            string `json:"phone" example:"13988888888" swaggerignore:"true"` // 手机号
+	RoleId           int    `json:"roleId" example:"1" swaggerignore:"true"`          //角色id
+	DeptId           int    `json:"deptId" example:"1" swaggerignore:"true"`          //部门id
+	PostId           int    `json:"postId" example:"1" swaggerignore:"true"`          //岗位id
+	Remark           string `json:"remark" example:"备注" swaggerignore:"true"`         // 备注
+	Status           string `json:"status" example:"2" swaggerignore:"true"`          // 状态
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysUserUpdateReq) Generate(userModel *model.SysUser) {
+	if s.Id != 0 {
+		userModel.Id = s.Id
+	}
+	userModel.NickName = s.NickName
+	userModel.Phone = s.Phone
+	userModel.RoleId = s.RoleId
+	userModel.DeptId = s.DeptId
+	userModel.Remark = s.Remark
+	userModel.Status = s.Status
+	if s.ControlBy.UpdateBy != 0 {
+		userModel.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		userModel.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysUserUpdateReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysUserGetReq struct {
+	Id int `uri:"id"`
+}
+
+func (s *SysUserGetReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysUserDeleteReq struct {
+	Id               int `json:"id"`
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysUserDeleteReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysUserById struct {
+	dto2.ObjectById
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysUserById) GetIds() interface{} {
+	return s.Ids
+}
+
+func (s *SysUserById) GetId() interface{} {
+	if len(s.Ids) > 0 {
+		s.Ids = append(s.Ids, s.Id)
+		return s.Ids
+	}
+	return s.Id
+}
+
+func (s *SysUserById) GenerateM() (model2.ActiveRecord, error) {
+	return &model.SysUser{}, nil
+}
+
+// PassWord 密码
+type PassWord struct {
+	NewPassword string `json:"newPassword" example:"123456" vd:"len($)>0"`   // 新密码
+	OldPassword string `json:"oldPassword" example:"12345678" vd:"len($)>0"` // 旧密码
+}
+
+type SysUserRegisterReq struct {
+	Id               int    `json:"id" swaggerignore:"true" comment:"用户ID"`                         // 用户ID
+	URKey            string `json:"URKey" example:"jKEnYWNXyrOvTofU" vd:"@:len($)>0 msg:'注册码不能为空'"` //注册码
+	Username         string `json:"username" example:"username" vd:"@:len($)>0 msg:'用户名不能为空'"`      //用户名
+	Password         string `json:"password" example:"123456" vd:"@:len($)>5 msg:'密码格式不正确'"`        //密码
+	NickName         string `json:"nickName" swaggerignore:"true"`                                  //昵称
+	Phone            string `json:"phone" example:"13912345678"`                                    //手机号
+	Code             string `json:"code" example:"125478"`                                          //短信验证码
+	RoleId           int    `json:"roleId" swaggerignore:"true"`                                    //角色id
+	DeptId           int    `json:"deptId" swaggerignore:"true"`                                    //部门id
+	PostId           int    `json:"postId" swaggerignore:"true"`                                    //岗位id
+	Remark           string `json:"remark" swaggerignore:"true"`                                    // 备注
+	Status           string `json:"status" swaggerignore:"true"`                                    // 状态
+	model2.ControlBy `swaggerignore:"true"`
+}
+
+func (s *SysUserRegisterReq) Generate(userModel *model.SysUser) {
+	if s.Id != 0 {
+		userModel.Id = s.Id
+	}
+	userModel.Username = s.Username
+	userModel.Password = s.Password
+	userModel.NickName = s.NickName
+	userModel.Phone = s.Phone
+	userModel.RoleId = s.RoleId
+	userModel.DeptId = s.DeptId
+	userModel.Remark = s.Remark
+	userModel.Status = s.Status
+	if s.ControlBy.UpdateBy != 0 {
+		userModel.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		userModel.CreateBy = s.CreateBy
+	}
+}
+
+func (s *SysUserRegisterReq) GetId() interface{} {
+	return s.Id
+}
+
+type SysUserGetSMSVerifyCodeReq struct {
+	Phone string `form:"phone" example:"13912345678"` //手机号
+}
+type GetNewestTokenReq struct {
+	UserId int64 `uri:"userId" example:"1"` //手机号
+}

+ 118 - 0
app/admin/service/serv_api.go

@@ -0,0 +1,118 @@
+package service
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gorm.io/gorm"
+
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+)
+
+type ServApi struct {
+	service.Service
+}
+
+// GetPage 获取ServApi列表
+
+func (e *ServApi) GetPage(c *dto.ServApiGetPageReq, list *[]model.ServApi, count *int64) error {
+	var err error
+	var data model.ServApi
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s \r", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取ServApi对象
+func (e *ServApi) Get(d *dto.ServApiGetReq, servApiModel *model.ServApi) error {
+	err := e.Orm.First(servApiModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建AppMenu对象
+func (e *ServApi) Insert(c *dto.ServApiInsertReq) error {
+	var err error
+	var data model.ServApi
+	err = e.Orm.Where("service_id = ? and path = ? and action = ?", c.ServiceId, c.Path, c.Action).First(&data).Error
+	if err == nil {
+		return errors.New("数据已存在")
+	}
+	c.Generate(&data)
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+	return nil
+}
+
+// Update 修改ServApi对象
+func (e *ServApi) Update(c *dto.ServApiUpdateReq) error {
+	var servModel = model.ServApi{}
+	err := e.Orm.First(&servModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&servModel)
+
+	err = e.Orm.Save(&servModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除ServApi
+func (e *ServApi) Remove(d *dto.ServApiDeleteReq) error {
+	var data model.ServApi
+
+	db := e.Orm.Model(&data).Delete(&data, d.GetId())
+	if err := db.Error; err != nil {
+		e.Log.Errorf("Service RemoveServApi error: %s", err)
+		return global.DeleteFailedErr
+	}
+	return nil
+}
+
+func (e *ServApi) GetList(c *dto.ServApiListByIds, list *[]model.ServApi) error {
+	var err error
+	var data model.ServApi
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Error
+	if err != nil {
+		e.Log.Errorf("db error: %s \r", err)
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 356 - 0
app/admin/service/serv_menu.go

@@ -0,0 +1,356 @@
+package service
+
+import (
+	dto2 "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	cModel "Medical_OAuth/common/model"
+	"encoding/json"
+	"fmt"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"strings"
+
+	"github.com/pkg/errors"
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+)
+
+type ServMenu struct {
+	service.Service
+}
+
+// GetPage 获取ServMenu列表
+func (e *ServMenu) GetPage(c *dto.ServMenuGetPageReq, menus *[]model.ServMenu) *ServMenu {
+	var menu = make([]model.ServMenu, 0)
+	err := e.getPage(c, &menu).Error
+	if err != nil {
+		_ = e.AddError(global.GetFailedErr)
+		return e
+	}
+	for i := 0; i < len(menu); i++ {
+		if menu[i].ParentId != 0 {
+			continue
+		}
+		menusInfo := servMenuCall(&menu, menu[i])
+		*menus = append(*menus, menusInfo)
+	}
+
+	if len(*menus) == 0 {
+		parentMap, flag := getServMenuParent(&menu)
+		if flag {
+			for i := 0; i < len(menu); i++ {
+				if parentMap[menu[i].ParentId] {
+					continue
+				}
+				menusInfo := servMenuCall(&menu, menu[i])
+				*menus = append(*menus, menusInfo)
+			}
+		} else {
+			for i := 0; i < len(menu); i++ {
+				menusInfo := servMenuCall(&menu, menu[i])
+				*menus = append(*menus, menusInfo)
+			}
+		}
+	}
+
+	return e
+}
+
+// 获取搜索出来的菜单的父菜单
+func getServMenuParent(menuList *[]model.ServMenu) (map[int]bool, bool) {
+	list := *menuList
+	var flag = false
+	var parentMap = map[int]bool{}
+	for j := 0; j < len(list); j++ {
+		parentMap[list[j].ParentId] = false
+	}
+
+	for j := 0; j < len(list); j++ {
+		if _, ok := parentMap[list[j].Id]; !ok {
+			continue
+		}
+		parentMap[list[j].Id] = true
+		flag = true
+	}
+	return parentMap, flag
+}
+
+// getPage 菜单分页列表
+func (e *ServMenu) getPage(c *dto.ServMenuGetPageReq, list *[]model.ServMenu) *ServMenu {
+	var err error
+	var data model.ServMenu
+	var tempList []model.ServMenu
+	err = e.Orm.Model(&data).
+		Scopes(dto2.MakeCondition(c.GetNeedSearch())).
+		Find(&tempList).Error
+	if err != nil {
+		e.Log.Errorf("getServMenuPage error: %s", err)
+		_ = e.AddError(err)
+		return e
+	}
+
+	// 获取菜单及其子菜单下ID
+	for _, menu := range tempList {
+		var menuList = make([]model.ServMenu, 0)
+		err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Order(fmt.Sprintf("sort %s", c.SortOrder)).Find(&menuList).Error
+		*list = append(*list, menuList...)
+	}
+
+	*list = DeduplicateServMenu(*list)
+
+	return e
+}
+
+// Get 获取ServMenu对象
+func (e *ServMenu) Get(d *dto.ServMenuGetReq, menuModel *model.ServMenu) *ServMenu {
+	err := e.Orm.First(menuModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.GetNotFoundOrNoPermissionErr
+		} else {
+			err = global.GetFailedErr
+		}
+		_ = e.AddError(err)
+		return e
+	}
+	return e
+}
+
+// Insert 创建ServMenu对象
+func (e *ServMenu) Insert(c *dto.ServMenuInsertReq) *ServMenu {
+	var err error
+	var data model.ServMenu
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	c.Generate(&data)
+	err = tx.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(global.CreateFailedErr)
+		return e
+	}
+	c.Id = data.Id
+
+	menuPath, err := e.initPaths(&data)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(err)
+		return e
+	}
+	err = tx.Model(&data).Where("id = ?", data.Id).Update("menu_path", menuPath).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(global.CreateFailedErr)
+		return e
+	}
+
+	return e
+}
+
+func (e *ServMenu) initPaths(menu *model.ServMenu) (menuPath string, err error) {
+	var data model.ServMenu
+	parentMenu := new(model.ServMenu)
+	if menu.ParentId != 0 {
+		e.Orm.Model(&data).Where("service_id = ?", menu.ServiceId).First(parentMenu, menu.ParentId)
+		if parentMenu.MenuPath == "" {
+			err = errors.New("父级menu_path异常,请尝试对当前节点父级菜单进行更新操作!")
+			return menuPath, err
+		}
+		menuPath = parentMenu.MenuPath + "/" + pkg.IntToString(menu.Id)
+	} else {
+		menuPath = "/0/" + pkg.IntToString(menu.Id)
+	}
+	return menuPath, nil
+}
+
+// Update 修改ServMenu对象
+func (e *ServMenu) Update(c *dto.ServMenuUpdateReq) *ServMenu {
+	var err error
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	var menuModel = model.ServMenu{}
+	err = tx.First(&menuModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.UpdateNotFoundOrNoPermissionErr
+		} else {
+			err = global.UpdateFailedErr
+		}
+		_ = e.AddError(err)
+		return e
+	}
+	oldPath := menuModel.MenuPath
+	oldParentId := menuModel.ParentId
+	c.Generate(&menuModel)
+
+	// 替换旧的path
+	if c.ParentId != oldParentId {
+		menuPath, err := e.initPaths(&menuModel)
+		if err != nil {
+			e.Log.Errorf("db error: %s", err)
+			_ = e.AddError(err)
+			return e
+		}
+		menuModel.MenuPath = menuPath
+	}
+	// 更新菜单信息
+	err = tx.Model(&menuModel).Save(&menuModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(global.UpdateFailedErr)
+		return e
+	}
+	// 替换旧的path
+	if oldPath != menuModel.MenuPath {
+		var menuList []model.ServMenu
+		tx.Where("menu_path like ?", oldPath+"%").Find(&menuList)
+		for _, v := range menuList {
+			v.MenuPath = strings.Replace(v.MenuPath, oldPath, menuModel.MenuPath, 1)
+			err := tx.Model(&v).Update("menu_path", v.MenuPath).Error
+			if err != nil {
+				e.Log.Errorf("db error: %s", err)
+				_ = e.AddError(global.CreateFailedErr)
+				return e
+			}
+		}
+	}
+
+	// 修改服务菜单后删除角色菜单缓存,防止系统菜单与服务菜单不同步
+	err = model.DeleteAllRoleMenuCache()
+	if err != nil {
+		_ = e.AddError(err)
+		return e
+	}
+
+	return e
+}
+
+// Remove 删除ServMenu
+func (e *ServMenu) Remove(d *dto.ServMenuDeleteReq) *ServMenu {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	var menuList = make([]model.ServMenu, 0)
+	tx.Where("id in (?)", d.GetId(), d.GetId()).Find(&menuList)
+	if len(menuList) == 0 {
+		return e
+	}
+
+	for _, menu := range menuList {
+		err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Delete(&model.ServMenu{}).Error
+		if err != nil {
+			e.Log.Errorf("Delete error: %s", err)
+			_ = e.AddError(global.DeleteFailedErr)
+			return e
+		}
+	}
+
+	// 删除服务菜单后删除角色菜单缓存,防止系统菜单与服务菜单不同步
+	err = model.DeleteAllRoleMenuCache()
+	if err != nil {
+		e.Log.Errorf("删除角色菜单缓存失败 %s", err)
+		_ = e.AddError(err)
+		return e
+	}
+	return e
+}
+
+// GetList 获取菜单数据
+func (e *ServMenu) GetList(c *dto.ServMenuGetPageReq, list *[]model.ServMenu) error {
+	var err error
+	var data model.ServMenu
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			dto2.MakeCondition(c.GetNeedSearch()),
+		).
+		Find(list).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// servMenuCall 构建菜单树
+func servMenuCall(menuList *[]model.ServMenu, menu model.ServMenu) model.ServMenu {
+	list := *menuList
+
+	min := make([]model.ServMenu, 0)
+	for j := 0; j < len(list); j++ {
+
+		if menu.Id != list[j].ParentId {
+			continue
+		}
+		mi := model.ServMenu{}
+		mi.Id = list[j].Id
+		mi.Name = list[j].Name
+		mi.Icon = list[j].Icon
+		mi.Path = list[j].Path
+		mi.MenuType = list[j].MenuType
+		mi.Permission = list[j].Permission
+		mi.ParentId = list[j].ParentId
+		mi.Component = list[j].Component
+		mi.Sort = list[j].Sort
+		mi.Visible = list[j].Visible
+		mi.CreatedAt = list[j].CreatedAt
+		mi.Children = []model.ServMenu{}
+
+		if mi.MenuType != cModel.Button {
+			ms := servMenuCall(menuList, mi)
+			min = append(min, ms)
+		} else {
+			min = append(min, mi)
+		}
+	}
+	menu.Children = min
+	return menu
+}
+
+// DeduplicateServMenu 菜单列表去重
+func DeduplicateServMenu(list []model.ServMenu) []model.ServMenu {
+	seen := make(map[string]bool)
+	deduplicated := []model.ServMenu{}
+
+	for _, v := range list {
+		// 将结构体编码为 JSON 字符串
+		key, err := json.Marshal(v)
+		if err != nil {
+			// 处理错误
+			continue
+		}
+		// 将 JSON 字符串作为键插入到 map 中
+		if _, ok := seen[string(key)]; !ok {
+			seen[string(key)] = true
+			deduplicated = append(deduplicated, v)
+		}
+	}
+
+	return deduplicated
+}

+ 178 - 0
app/admin/service/sys_config.go

@@ -0,0 +1,178 @@
+package service
+
+import (
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysConfig struct {
+	service.Service
+}
+
+// GetPage 获取SysConfig列表
+func (e *SysConfig) GetPage(c *dto.SysConfigGetPageReq, list *[]model.SysConfig, count *int64) error {
+	err := e.Orm.
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("Service GetSysConfigPage error: %s", err)
+		return err
+	}
+	return nil
+}
+
+// Get 获取SysConfig对象
+func (e *SysConfig) Get(d *dto.SysConfigGetReq, model *model.SysConfig) error {
+	err := e.Orm.First(model, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysConfig对象
+func (e *SysConfig) Insert(c *dto.SysConfigControl) error {
+	var err error
+	var data model.SysConfig
+	c.Generate(&data)
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("Service InsertSysConfig error: %s", err)
+		return global.CreateFailedErr
+	}
+	return nil
+}
+
+// Update 修改SysConfig对象
+func (e *SysConfig) Update(c *dto.SysConfigControl) error {
+	var err error
+	var confModel = model.SysConfig{}
+	err = e.Orm.First(&confModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+	c.Generate(&confModel)
+	err = e.Orm.Save(&confModel).Error
+	if err != nil {
+		e.Log.Errorf("Service UpdateSysConfig error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// SetSysConfig 修改SysConfig对象
+func (e *SysConfig) SetSysConfig(c *[]dto.GetSetSysConfigReq) error {
+	for _, req := range *c {
+		var confModel = model.SysConfig{}
+		err := e.Orm.Where("config_key = ?", req.ConfigKey).First(&confModel).Error
+		if err != nil {
+			e.Log.Errorf("db error: %s", err)
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return global.UpdateNotFoundOrNoPermissionErr
+			}
+			return global.UpdateFailedErr
+		}
+	}
+	return nil
+}
+
+func (e *SysConfig) GetForSet(c *[]dto.GetSetSysConfigReq) error {
+	var err error
+	var data model.SysConfig
+
+	err = e.Orm.Model(&data).Find(c).Error
+	if err != nil {
+		e.Log.Errorf("Service GetSysConfigPage error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+func (e *SysConfig) UpdateForSet(c *[]dto.GetSetSysConfigReq) error {
+	m := *c
+	for _, req := range m {
+		var data model.SysConfig
+		if err := e.Orm.Where("config_key = ?", req.ConfigKey).
+			First(&data).Error; err != nil {
+			e.Log.Errorf("Service GetSysConfigPage error: %s", err)
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return global.UpdateNotFoundOrNoPermissionErr
+			}
+			return global.UpdateFailedErr
+		}
+		if data.ConfigValue != req.ConfigValue {
+			data.ConfigValue = req.ConfigValue
+
+			if err := e.Orm.Save(&data).Error; err != nil {
+				e.Log.Errorf("Service GetSysConfigPage error: %s", err)
+				return global.UpdateFailedErr
+			}
+		}
+
+	}
+
+	return nil
+}
+
+// Remove 删除SysConfig
+func (e *SysConfig) Remove(d *dto.SysConfigDeleteReq) error {
+	var err error
+	var data model.SysConfig
+
+	db := e.Orm.Delete(&data, d.Ids)
+	if err = db.Error; err != nil {
+		err = db.Error
+		e.Log.Errorf("Service RemoveSysConfig error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}
+
+// GetWithKey 根据Key获取SysConfig
+func (e *SysConfig) GetWithKey(c *dto.SysConfigByKeyReq, resp *dto.GetSysConfigByKEYForServiceResp) error {
+	var err error
+	var data model.SysConfig
+	err = e.Orm.Table(data.TableName()).Where("config_key = ?", c.ConfigKey).First(resp).Error
+	if err != nil {
+		e.Log.Errorf("At Service GetSysConfigByKEY error: %s", err)
+		return global.GetFailedErr
+	}
+
+	return nil
+}
+
+func (e *SysConfig) GetWithKeyList(c *dto.SysConfigGetToSysAppReq, list *[]model.SysConfig) error {
+	var err error
+	err = e.Orm.
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+		).
+		Find(list).Error
+	if err != nil {
+		e.Log.Errorf("Service GetSysConfigByKey error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 443 - 0
app/admin/service/sys_dept.go

@@ -0,0 +1,443 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+)
+
+type SysDept struct {
+	service.Service
+}
+
+// Get 获取SysDept对象
+func (e *SysDept) Get(d *dto.SysDeptGetReq, deptModel *model.SysDept) error {
+	err := e.Orm.
+		First(deptModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysDept对象
+func (e *SysDept) Insert(c *dto.SysDeptInsertReq, deptId int) error {
+	var err error
+	var data model.SysDept
+	c.Generate(&data)
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	if deptId != 0 && c.ParentId == 0 {
+		data.ParentId = deptId
+	}
+	err = tx.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+
+	c.Id = data.Id
+	deptPath := pkg.IntToString(data.Id) + "/"
+	if data.ParentId != 0 {
+		var deptP model.SysDept
+		tx.First(&deptP, data.ParentId)
+		deptPath = deptP.DeptPath + deptPath
+	} else {
+		deptPath = "/0/" + deptPath
+	}
+	var mp = map[string]string{}
+	mp["dept_path"] = deptPath
+
+	err = tx.Model(&data).Update("dept_path", deptPath).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	return nil
+}
+
+// Update 修改SysDept对象
+func (e *SysDept) Update(c *dto.SysDeptUpdateReq) error {
+	var err error
+	var deptModel = model.SysDept{}
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	err = tx.First(&deptModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&deptModel)
+
+	DeptPath := pkg.IntToString(deptModel.Id) + "/"
+	if deptModel.ParentId != 0 {
+		var DeptP model.SysDept
+		tx.First(&DeptP, deptModel.ParentId)
+		DeptPath = DeptP.DeptPath + DeptPath
+	} else {
+		DeptPath = "/0/" + DeptPath
+	}
+	deptModel.DeptPath = DeptPath
+	db := tx.Save(&deptModel)
+	if err = db.Error; err != nil {
+		e.Log.Errorf("UpdateSysDept error: %s", err)
+		return err
+	}
+	return nil
+}
+
+// Remove 删除SysDept
+// 删除部门 同时删除其子部门、部门下的用户
+func (e *SysDept) Remove(d *dto.SysDeptDeleteReq, p *actions.DataPermission) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	var dept model.SysDept
+	err = e.Orm.
+		First(&dept, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.DeleteFailedErr
+	}
+
+	var deptList = make([]model.SysDept, 0)
+	var deptIds = make([]int, 0)
+	tx.Where("dept_path like ?", dept.DeptPath+"%").Find(&deptList)
+
+	// 获取部门及其子部门下ID
+	for _, v := range deptList {
+		deptIds = append(deptIds, v.Id)
+	}
+
+	db := tx.Select(clause.Associations).Delete(&deptList)
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	// 删除部门下的用户
+	dbUser := tx.Where("dept_id in (?)", deptIds).Delete(&model.SysUser{})
+	if err = dbUser.Error; err != nil {
+		e.Log.Errorf("Delete User error: %s", err)
+		return global.DeleteFailedErr
+	}
+
+	return nil
+}
+
+// getList 获取组织数据
+func (e SysDept) getList(c *dto.SysDeptGetPageReq, list *[]model.SysDept, p *actions.DataPermission) error {
+	var err error
+	var data model.SysDept
+	if len(c.DeptName) == 0 && c.DeptId == 0 {
+		err = e.Orm.Model(&data).
+			Scopes(
+				cDto.MakeCondition(c.GetNeedSearch()),
+			).
+			Find(list).Error
+		if err != nil {
+			e.Log.Errorf("db error:%s", err)
+			return err
+		}
+
+		return nil
+	}
+
+	var tempList []model.SysDept
+	err = e.Orm.Model(&data).Where("id in (select id from sys_dept where dept_path like ? )", "%/"+pkg.IntToString(p.DeptId)+"/%").
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+		).
+		Find(&tempList).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+
+	// 获取部门及其子部门下ID
+	for _, dept := range tempList {
+		var deptList = make([]model.SysDept, 0)
+		err = e.Orm.Where("dept_path like ?", dept.DeptPath+"%").Order(fmt.Sprintf("sort %s", c.SortOrder)).Find(&deptList).Error
+		*list = append(*list, deptList...)
+	}
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+
+	*list = DeduplicateDept(*list)
+
+	return nil
+}
+
+// SetDeptTree 设置组织数据
+func (e *SysDept) SetDeptTree(c *dto.SysDeptGetPageReq, p *actions.DataPermission) (m []dto.DeptLabel, err error) {
+	var list []model.SysDept
+	err = e.getList(c, &list, p)
+
+	m = make([]dto.DeptLabel, 0)
+	for i := 0; i < len(list); i++ {
+		if list[i].ParentId != 0 {
+			continue
+		}
+		e := dto.DeptLabel{}
+		e.Id = list[i].Id
+		e.Label = list[i].DeptName
+		DeptInfo := DeptTreeCall(&list, e)
+
+		m = append(m, DeptInfo)
+	}
+	return
+}
+
+// DeptTreeCall 递归构造组织数据
+func DeptTreeCall(DeptList *[]model.SysDept, Dept dto.DeptLabel) dto.DeptLabel {
+	list := *DeptList
+	min := make([]dto.DeptLabel, 0)
+	for j := 0; j < len(list); j++ {
+		if Dept.Id != list[j].ParentId {
+			continue
+		}
+		mi := dto.DeptLabel{Id: list[j].Id, Label: list[j].DeptName, Children: []dto.DeptLabel{}}
+		ms := DeptTreeCall(DeptList, mi)
+		min = append(min, ms)
+	}
+	Dept.Children = min
+	return Dept
+}
+
+// SetDeptPage 设置dept页面数据
+//func (e *SysDept) SetDeptPage(c *dto.SysDeptGetPageReq, p *actions.DataPermission) (m []model.SysDept, err error) {
+//	var list []model.SysDept
+//	err = e.getList(c, &list, p)
+//	for i := 0; i < len(list); i++ {
+//		if list[i].ParentId != 0 {
+//			continue
+//		}
+//		info := e.deptPageCall(&list, list[i])
+//		m = append(m, info)
+//	}
+//	return
+//}
+//
+//func (e *SysDept) deptPageCall(deptlist *[]model.SysDept, dept model.SysDept) model.SysDept {
+//	list := *deptlist
+//	min := make([]model.SysDept, 0)
+//	for j := 0; j < len(list); j++ {
+//		if dept.Id != list[j].ParentId {
+//			continue
+//		}
+//		mi := model.SysDept{}
+//		mi.Id = list[j].Id
+//		mi.ParentId = list[j].ParentId
+//		mi.DeptPath = list[j].DeptPath
+//		mi.DeptName = list[j].DeptName
+//		mi.Sort = list[j].Sort
+//		mi.Status = list[j].Status
+//		mi.CreatedAt = list[j].CreatedAt
+//		mi.Children = []model.SysDept{}
+//		ms := e.deptPageCall(deptlist, mi)
+//		min = append(min, ms)
+//	}
+//	dept.Children = min
+//	return dept
+//}
+
+// SetDeptPage 设置Dept页面数据
+func (e *SysDept) SetDeptPage(c *dto.SysDeptGetPageReq, p *actions.DataPermission) (m []model.SysDept, err error) {
+	var list []model.SysDept
+	err = e.getList(c, &list, p)
+	for i := 0; i < len(list); i++ {
+		if list[i].ParentId != 0 {
+			continue
+		}
+		info := e.DeptPageCall(&list, list[i])
+		m = append(m, info)
+	}
+
+	if len(m) == 0 {
+		parentMap, flag := getDeptParent(list)
+		if flag {
+			for i := 0; i < len(list); i++ {
+				if parentMap[list[i].ParentId] {
+					continue
+				}
+				info := e.DeptPageCall(&list, list[i])
+				m = append(m, info)
+			}
+		} else {
+			for i := 0; i < len(list); i++ {
+				info := e.DeptPageCall(&list, list[i])
+				m = append(m, info)
+			}
+		}
+	}
+
+	return
+}
+
+func getDeptParent(deptList []model.SysDept) (map[int]bool, bool) {
+	list := deptList
+	var flag = false
+	var parentMap = map[int]bool{}
+	for j := 0; j < len(list); j++ {
+		parentMap[list[j].ParentId] = false
+	}
+
+	for j := 0; j < len(list); j++ {
+		if _, ok := parentMap[list[j].Id]; !ok {
+			continue
+		}
+		parentMap[list[j].Id] = true
+		flag = true
+	}
+	return parentMap, flag
+}
+
+func (e *SysDept) DeptPageCall(deptList *[]model.SysDept, menu model.SysDept) model.SysDept {
+	list := *deptList
+	min := make([]model.SysDept, 0)
+	for j := 0; j < len(list); j++ {
+		if menu.Id != list[j].ParentId {
+			continue
+		}
+		mi := model.SysDept{}
+		mi.Id = list[j].Id
+		mi.ParentId = list[j].ParentId
+		mi.DeptPath = list[j].DeptPath
+		mi.DeptName = list[j].DeptName
+		mi.Sort = list[j].Sort
+		mi.Status = list[j].Status
+		mi.CreatedAt = list[j].CreatedAt
+		mi.Children = []model.SysDept{}
+		ms := e.DeptPageCall(deptList, mi)
+		min = append(min, ms)
+	}
+	menu.Children = min
+	return menu
+}
+
+// GetWithRoleId 获取角色的部门ID集合
+func (e *SysDept) GetWithRoleId(roleId int) ([]int, error) {
+	DeptIds := make([]int, 0)
+	DeptList := make([]dto.DeptIdList, 0)
+	if err := e.Orm.Table("sys_role_dept").
+		Select("sys_role_dept.dept_id").
+		Joins("LEFT JOIN sys_dept on sys_dept.id=sys_role_dept.dept_id").
+		Where("role_id = ? ", roleId).
+		Where(" sys_role_dept.dept_id not in(select sys_dept.parent_id from sys_role_dept LEFT JOIN sys_dept on sys_dept.id=sys_role_dept.dept_id where role_id =? )", roleId).
+		Find(&DeptList).Error; err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return nil, global.GetFailedErr
+	}
+	for i := 0; i < len(DeptList); i++ {
+		DeptIds = append(DeptIds, DeptList[i].DeptId)
+	}
+	return DeptIds, nil
+}
+
+func (e *SysDept) SetDeptLabel() (m []dto.DeptLabel, err error) {
+	list := make([]model.SysDept, 0)
+	err = e.Orm.Find(&list).Error
+	if err != nil {
+		e.Log.Error("find Dept list error, %s", err)
+		err = global.GetFailedErr
+		return
+	}
+	m = make([]dto.DeptLabel, 0)
+	var item dto.DeptLabel
+	for i := range list {
+		if list[i].ParentId != 0 {
+			continue
+		}
+		item = dto.DeptLabel{}
+		item.Id = list[i].Id
+		item.Label = list[i].DeptName
+		DeptInfo := DeptLabelCall(&list, item)
+		m = append(m, DeptInfo)
+	}
+	return
+}
+
+// DeptLabelCall
+func DeptLabelCall(DeptList *[]model.SysDept, Dept dto.DeptLabel) dto.DeptLabel {
+	list := *DeptList
+	var mi dto.DeptLabel
+	min := make([]dto.DeptLabel, 0)
+	for j := 0; j < len(list); j++ {
+		if Dept.Id != list[j].ParentId {
+			continue
+		}
+		mi = dto.DeptLabel{Id: list[j].Id, Label: list[j].DeptName, Children: []dto.DeptLabel{}}
+		ms := DeptLabelCall(DeptList, mi)
+		min = append(min, ms)
+	}
+	Dept.Children = min
+	return Dept
+}
+
+func DeduplicateDept(list []model.SysDept) []model.SysDept {
+	seen := make(map[string]bool)
+	deduplicated := []model.SysDept{}
+
+	for _, v := range list {
+		// 将结构体编码为 JSON 字符串
+		key, err := json.Marshal(v)
+		if err != nil {
+			// 处理错误
+			continue
+		}
+		// 将 JSON 字符串作为键插入到 map 中
+		if _, ok := seen[string(key)]; !ok {
+			seen[string(key)] = true
+			deduplicated = append(deduplicated, v)
+		}
+	}
+
+	return deduplicated
+}

+ 116 - 0
app/admin/service/sys_dict_data_service.go

@@ -0,0 +1,116 @@
+package service
+
+import (
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysDictDataService struct {
+	service.Service
+}
+
+// GetPage 获取列表
+func (e *SysDictDataService) GetPage(c *dto.SysDictDataGetPageReq, list *[]model.SysDictData, count *int64) error {
+	var err error
+	var data model.SysDictData
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取对象
+func (e *SysDictDataService) Get(d *dto.SysDictDataGetReq, sysDictModel *model.SysDictData) error {
+	err := e.Orm.First(sysDictModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建对象
+func (e *SysDictDataService) Insert(c *dto.SysDictDataInsertReq) error {
+	var err error
+	var data = new(model.SysDictData)
+	c.Generate(data)
+	err = e.Orm.Create(data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	return nil
+}
+
+// Update 修改对象
+func (e *SysDictDataService) Update(c *dto.SysDictDataUpdateReq) error {
+	var err error
+	var dictDataModel = model.SysDictData{}
+	err = e.Orm.First(&dictDataModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+	c.Generate(&dictDataModel)
+	err = e.Orm.Save(dictDataModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除
+func (e *SysDictDataService) Remove(c *dto.SysDictDataDeleteReq) error {
+	var err error
+	var data model.SysDictData
+
+	db := e.Orm.Delete(&data, c.GetId())
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}
+
+// GetAll 获取所有
+func (e *SysDictDataService) GetAll(c *dto.SysDictDataGetPageReq, list *[]model.SysDictData) error {
+	var err error
+	var data model.SysDictData
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+		).
+		Find(list).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 117 - 0
app/admin/service/sys_dict_type_service.go

@@ -0,0 +1,117 @@
+package service
+
+import (
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"fmt"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysDictTypeService struct {
+	service.Service
+}
+
+// GetPage 获取列表
+func (e *SysDictTypeService) GetPage(c *dto.SysDictTypeGetPageReq, list *[]model.SysDictType, count *int64) error {
+	var err error
+	var data model.SysDictType
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取对象
+func (e *SysDictTypeService) Get(d *dto.SysDictTypeGetReq, model *model.SysDictType) error {
+	err := e.Orm.First(model, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建对象
+func (e *SysDictTypeService) Insert(c *dto.SysDictTypeInsertReq) error {
+	var err error
+	var data model.SysDictType
+	c.Generate(&data)
+	var count int64
+	e.Orm.Model(&data).Where("dict_type = ?", data.DictType).Count(&count)
+	if count > 0 {
+		return errors.New(fmt.Sprintf("当前字典类型[%s]已经存在!", data.DictType))
+	}
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	return nil
+}
+
+// Update 修改对象
+func (e *SysDictTypeService) Update(c *dto.SysDictTypeUpdateReq) error {
+	var err error
+	var dictTypeModel = model.SysDictType{}
+	e.Orm.First(&dictTypeModel, c.GetId())
+	c.Generate(&dictTypeModel)
+	db := e.Orm.Save(&dictTypeModel)
+	if db.Error != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.UpdateNotFoundOrNoPermissionErr
+	}
+	return nil
+}
+
+// Remove 删除
+func (e *SysDictTypeService) Remove(d *dto.SysDictTypeDeleteReq) error {
+	var err error
+	var data model.SysDictType
+
+	db := e.Orm.Delete(&data, d.GetId())
+	err = db.Error
+	if err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}
+
+// GetAll 获取所有
+func (e *SysDictTypeService) GetAll(c *dto.SysDictTypeGetPageReq, list *[]model.SysDictType) error {
+	var err error
+	var data model.SysDictType
+
+	err = e.Orm.Model(&data).
+		Scopes(cDto.MakeCondition(c.GetNeedSearch())).
+		Find(list).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 72 - 0
app/admin/service/sys_login_log_service.go

@@ -0,0 +1,72 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysLoginLogService struct {
+	service.Service
+}
+
+// GetPage 获取SysLoginLog列表
+func (e *SysLoginLogService) GetPage(c *dto.SysLoginLogGetPageReq, list *[]model.SysLoginLog, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data model.SysLoginLog
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysLoginLog对象
+func (e *SysLoginLogService) Get(d *dto.SysLoginLogGetReq, loginLogModel *model.SysLoginLog, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(loginLogModel.TableName(), p)).
+		First(loginLogModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysLoginLog
+func (e *SysLoginLogService) Remove(c *dto.SysLoginLogDeleteReq, p *actions.DataPermission) error {
+	var err error
+	var data model.SysLoginLog
+
+	db := e.Orm.
+		Scopes(actions.Permission(data.TableName(), p)).
+		Delete(&data, c.GetId())
+	if db.Error != nil {
+		err = db.Error
+		e.Log.Errorf("Delete error: %s", err)
+		return err
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}

+ 467 - 0
app/admin/service/sys_menu.go

@@ -0,0 +1,467 @@
+package service
+
+import (
+	dto2 "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"encoding/json"
+	"fmt"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"sort"
+	"strings"
+
+	"github.com/pkg/errors"
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+)
+
+type SysMenu struct {
+	service.Service
+}
+
+// GetPage 获取SysMenu列表
+func (e *SysMenu) GetPage(c *dto.SysMenuGetPageReq, menus *[]model.SysMenu) *SysMenu {
+	var menu = make([]model.SysMenu, 0)
+	err := e.getPage(c, &menu).Error
+	if err != nil {
+		_ = e.AddError(global.GetFailedErr)
+		return e
+	}
+	for i := 0; i < len(menu); i++ {
+		if menu[i].ParentId != 0 {
+			continue
+		}
+		menusInfo := menuCall(&menu, menu[i])
+		*menus = append(*menus, menusInfo)
+	}
+
+	if len(*menus) == 0 {
+		parentMap, flag := getMenuParent(&menu)
+		if flag {
+			for i := 0; i < len(menu); i++ {
+				if parentMap[menu[i].ParentId] {
+					continue
+				}
+				menusInfo := menuCall(&menu, menu[i])
+				*menus = append(*menus, menusInfo)
+			}
+		} else {
+			for i := 0; i < len(menu); i++ {
+				menusInfo := menuCall(&menu, menu[i])
+				*menus = append(*menus, menusInfo)
+			}
+		}
+	}
+
+	return e
+}
+
+func getMenuParent(menuList *[]model.SysMenu) (map[int]bool, bool) {
+	list := *menuList
+	var flag = false
+	var parentMap = map[int]bool{}
+	for j := 0; j < len(list); j++ {
+		parentMap[list[j].ParentId] = false
+	}
+
+	for j := 0; j < len(list); j++ {
+		if _, ok := parentMap[list[j].Id]; !ok {
+			continue
+		}
+		parentMap[list[j].Id] = true
+		flag = true
+	}
+	return parentMap, flag
+}
+
+// getPage 菜单分页列表
+func (e *SysMenu) getPage(c *dto.SysMenuGetPageReq, list *[]model.SysMenu) *SysMenu {
+	var err error
+	var data model.SysMenu
+	var tempList []model.SysMenu
+	var temp2List []model.SysMenu
+	var temp3List []dto.SysMenu
+	err = e.Orm.Model(&data).
+		Scopes(dto2.MakeCondition(c.GetNeedSearch())).
+		Find(&tempList).Error
+	if err != nil {
+		e.Log.Errorf("getSysMenuPage error: %s", err)
+		_ = e.AddError(err)
+		return e
+	}
+
+	// 获取菜单及其子菜单下ID
+	for _, menu := range tempList {
+		var menuList = make([]model.SysMenu, 0)
+		err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Order(fmt.Sprintf("sort %s", c.SortOrder)).Find(&menuList).Error
+		temp2List = append(temp2List, menuList...)
+	}
+
+	ids := DeduplicateSysMenuIds(temp2List)
+	err = e.Orm.Table("sys_menu").
+		Select("*,sys_menu.id as id,sys_menu.parent_id as parent_id,sys_menu.visible as visible").
+		Joins("left join serv_menu on sys_menu.service_menu_id=serv_menu.id and sys_menu.service_id=serv_menu.service_id").
+		Where("sys_menu.id in (?) and serv_menu.name like ?", ids, "%"+c.Name+"%").
+		Scan(&temp3List).Error
+	for _, menu := range temp3List {
+		*list = append(*list, menu.Generate())
+	}
+	return e
+}
+
+// DeduplicateSysMenuIds  去掉重复的ID
+func DeduplicateSysMenuIds(list []model.SysMenu) (deduplicated []int) {
+	seen := make(map[string]bool)
+
+	for _, v := range list {
+		// 将结构体编码为 JSON 字符串
+		key, err := json.Marshal(v)
+		if err != nil {
+			// 处理错误
+			continue
+		}
+		// 将 JSON 字符串作为键插入到 map 中
+		if _, ok := seen[string(key)]; !ok {
+			seen[string(key)] = true
+			deduplicated = append(deduplicated, v.Id)
+		}
+	}
+
+	return deduplicated
+}
+
+// Get 获取SysMenu对象
+func (e *SysMenu) Get(d *dto.SysMenuGetReq, menuModel *model.SysMenu) *SysMenu {
+	err := e.Orm.First(menuModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.GetNotFoundErr
+		} else {
+			err = global.GetFailedErr
+		}
+		_ = e.AddError(err)
+		return e
+	}
+	var servMenu model.ServMenu
+	_ = e.Orm.Where("id = ? and service_id = ?", menuModel.ServiceMenuId, menuModel.ServiceId).First(&servMenu).Error
+	menuModel.Name = servMenu.Name
+	menuModel.MenuType = servMenu.MenuType
+	menuModel.Icon = servMenu.Icon
+	menuModel.Component = servMenu.Component
+	menuModel.IsFrame = servMenu.IsFrame
+	menuModel.Path = servMenu.Path
+	menuModel.Permission = servMenu.Permission
+	return e
+}
+
+// Insert 创建SysMenu对象
+func (e *SysMenu) Insert(c *dto.SysMenuInsertReq) *SysMenu {
+	var err error
+	var data model.SysMenu
+	c.Generate(&data)
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(global.CreateFailedErr)
+	}
+	c.Id = data.Id
+	err = e.initPaths(&data)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(err)
+	}
+	return e
+}
+
+// initPaths 初始化菜单paths
+func (e *SysMenu) initPaths(menu *model.SysMenu) error {
+	var err error
+	var data model.SysMenu
+	parentMenu := new(model.SysMenu)
+	if menu.ParentId != 0 {
+		e.Orm.Model(&data).First(parentMenu, menu.ParentId)
+		if parentMenu.MenuPath == "" {
+			err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!")
+			return err
+		}
+		menu.MenuPath = parentMenu.MenuPath + "/" + pkg.IntToString(menu.Id)
+	} else {
+		menu.MenuPath = "/0/" + pkg.IntToString(menu.Id)
+	}
+	e.Orm.Model(&data).Where("id = ?", menu.Id).Update("menu_path", menu.MenuPath)
+	return err
+}
+
+// Update 修改SysMenu对象
+func (e *SysMenu) Update(c *dto.SysMenuUpdateReq) *SysMenu {
+	var err error
+	tx := e.Orm.Debug().Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	var menuModel = model.SysMenu{}
+	err = tx.First(&menuModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.UpdateNotFoundOrNoPermissionErr
+		} else {
+			err = global.UpdateFailedErr
+		}
+		_ = e.AddError(err)
+		return e
+	}
+	oldPath := menuModel.MenuPath
+
+	c.Generate(&menuModel)
+	err = tx.Model(&menuModel).Save(&menuModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		_ = e.AddError(global.UpdateFailedErr)
+		return e
+	}
+	var menuList []model.SysMenu
+	tx.Where("paths like ?", oldPath+"%").Find(&menuList)
+	for _, v := range menuList {
+		v.MenuPath = strings.Replace(v.MenuPath, oldPath, menuModel.MenuPath, 1)
+		tx.Model(&v).Update("paths", v.MenuPath)
+	}
+	return e
+}
+
+// Remove 删除SysMenu
+func (e *SysMenu) Remove(d *dto.SysMenuDeleteReq) *SysMenu {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	var menuList = make([]model.SysMenu, 0)
+	tx.Where("id in (?)", d.GetId(), d.GetId()).Find(&menuList)
+	if len(menuList) == 0 {
+		return e
+	}
+
+	for _, menu := range menuList {
+		err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Delete(&model.SysMenu{}).Error
+		if err != nil {
+			e.Log.Errorf("Delete error: %s", err)
+			_ = e.AddError(global.DeleteFailedErr)
+			return e
+		}
+	}
+	return e
+}
+
+// GetList 获取菜单数据
+func (e *SysMenu) GetList(c *dto.SysMenuGetPageReq, list *[]model.SysMenu) error {
+	var err error
+
+	var tempList []dto.SysMenu
+	err = e.Orm.Table("sys_menu").
+		Select("sys_menu.id as id,sys_menu.parent_id as parent_id,sys_menu.visible as visible,name").
+		Joins("left join serv_menu on sys_menu.service_menu_id=serv_menu.id and sys_menu.service_id=serv_menu.service_id").
+		Where("serv_menu.name like ?", "%"+c.Name+"%").
+		Scan(&tempList).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	for _, menu := range tempList {
+		*list = append(*list, menu.Generate())
+	}
+	return nil
+}
+
+// SetLabel 修改角色中 设置菜单基础数据
+func (e *SysMenu) SetLabel() (m []dto.MenuLabel, err error) {
+	var list []model.SysMenu
+	err = e.GetList(&dto.SysMenuGetPageReq{}, &list)
+	if err != nil {
+		return
+	}
+
+	m = make([]dto.MenuLabel, 0)
+	for i := 0; i < len(list); i++ {
+		if list[i].ParentId != 0 {
+			continue
+		}
+		e := dto.MenuLabel{}
+		e.Id = list[i].Id
+		e.Label = list[i].Name
+		menuInfo := menuLabelCall(&list, e)
+
+		m = append(m, menuInfo)
+	}
+	return
+}
+
+// menuLabelCall 递归构造组织数据
+func menuLabelCall(eList *[]model.SysMenu, organ dto.MenuLabel) dto.MenuLabel {
+	list := *eList
+
+	min := make([]dto.MenuLabel, 0)
+	for j := 0; j < len(list); j++ {
+
+		if organ.Id != list[j].ParentId {
+			continue
+		}
+		mi := dto.MenuLabel{}
+		mi.Id = list[j].Id
+		mi.Label = list[j].Name
+		mi.Children = []dto.MenuLabel{}
+		if list[j].MenuType != "F" {
+			ms := menuLabelCall(eList, mi)
+			min = append(min, ms)
+		} else {
+			min = append(min, mi)
+		}
+	}
+	if len(min) > 0 {
+		organ.Children = min
+	} else {
+		organ.Children = nil
+	}
+	return organ
+}
+
+// menuCall 构建菜单树
+func menuCall(menuList *[]model.SysMenu, menu model.SysMenu) model.SysMenu {
+	list := *menuList
+
+	min := make([]model.SysMenu, 0)
+	for j := 0; j < len(list); j++ {
+
+		if menu.Id != list[j].ParentId {
+			continue
+		}
+		mi := model.SysMenu{}
+		mi.Id = list[j].Id
+		mi.Name = list[j].Name
+		mi.Icon = list[j].Icon
+		mi.Path = list[j].Path
+		mi.MenuType = list[j].MenuType
+		mi.Permission = list[j].Permission
+		mi.ParentId = list[j].ParentId
+		mi.Component = list[j].Component
+		mi.Sort = list[j].Sort
+		mi.Visible = list[j].Visible
+		mi.CreatedAt = list[j].CreatedAt
+		mi.Children = []model.SysMenu{}
+		ms := menuCall(menuList, mi)
+		min = append(min, ms)
+	}
+	menu.Children = min
+	return menu
+}
+
+// 去掉重复菜单
+func menuDistinct(menuList []model.SysMenu) (result []model.SysMenu) {
+	distinctMap := make(map[int]struct{}, len(menuList))
+	for _, menu := range menuList {
+		if _, ok := distinctMap[menu.Id]; !ok {
+			distinctMap[menu.Id] = struct{}{}
+			result = append(result, menu)
+		}
+	}
+	return result
+}
+
+func recursiveSetMenu(orm *gorm.DB, mIds []int, menus *[]model.SysMenu) error {
+	if len(mIds) == 0 || menus == nil {
+		return nil
+	}
+	var subMenus []model.SysMenu
+	err := orm.Where("id in ?", mIds).Find(&subMenus).Error
+	if err != nil {
+		return err
+	}
+
+	subIds := make([]int, 0)
+	for _, menu := range subMenus {
+		if menu.ParentId != 0 {
+			subIds = append(subIds, menu.ParentId)
+		}
+		//if menu.MenuType != cModel.Button {
+		//	*menus = append(*menus, menu)
+		//}
+		*menus = append(*menus, menu)
+	}
+	return recursiveSetMenu(orm, subIds, menus)
+}
+
+// SetMenuRole 获取左侧菜单树使用
+func (e *SysMenu) SetMenuRole(roleName string) (m []model.SysMenu, err error) {
+	// 从缓存获取角色关联的菜单
+	if err := model.GetRoleMenuCache(roleName, &m); err == nil {
+		return m, nil
+	}
+	menus, err := e.getByRoleName(roleName)
+	if err != nil {
+		return m, global.GetFailedErr
+	}
+	menuIds := make([]int, 0)
+	for _, menu := range menus {
+		menuIds = append(menuIds, menu.Id)
+	}
+	var tempList []dto.SysMenu
+	var menuList []model.SysMenu
+	err = e.Orm.Table("sys_menu").
+		Select("*,sys_menu.id as id,sys_menu.parent_id as parent_id,sys_menu.visible as visible").
+		Joins("left join serv_menu on sys_menu.service_menu_id=serv_menu.id and sys_menu.service_id=serv_menu.service_id").
+		Where("sys_menu.id in (?) and sys_menu.visible = 1", menuIds).
+		Order("sys_menu.sort").
+		Scan(&tempList).Error
+	for _, menu := range tempList {
+		menuList = append(menuList, menu.Generate())
+	}
+	sort.Sort(model.SysMenuSlice(menuList))
+	m = make([]model.SysMenu, 0)
+	for i := 0; i < len(menuList); i++ {
+		if menuList[i].ParentId != 0 {
+			continue
+		}
+		menusInfo := menuCall(&menuList, menuList[i])
+		m = append(m, menusInfo)
+	}
+	// 保存角色菜单到缓存
+	_ = model.SetRoleMenuCache(roleName, m)
+	return
+}
+
+// 通过roleName获取菜单列表
+func (e *SysMenu) getByRoleName(roleName string) ([]model.SysMenu, error) {
+	var err error
+
+	data := make([]model.SysMenu, 0)
+
+	if roleName == "admin" {
+		err = e.Orm.Find(&data).Error
+	} else {
+		roleMenuIds := make([]int, 0)
+		err = e.Orm.Model(&model.SysRoleMenu{}).Select("menu_id").Where("role_key = ? ", roleName).Scan(&roleMenuIds).Error
+
+		if len(roleMenuIds) > 0 {
+			if err = recursiveSetMenu(e.Orm, roleMenuIds, &data); err != nil {
+				return nil, err
+			}
+			// 菜单id及父id 去重
+			data = menuDistinct(data)
+		}
+	}
+
+	return data, err
+}

+ 84 - 0
app/admin/service/sys_opera_log_service.go

@@ -0,0 +1,84 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysOperaLog struct {
+	service.Service
+}
+
+// GetPage 获取SysOperaLog列表
+func (e *SysOperaLog) GetPage(c *dto.SysOperaLogGetPageReq, list *[]model.SysOperaLog, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data model.SysOperaLog
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("Service GetSysOperaLogPage error: %s", err.Error())
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysOperaLog对象
+func (e *SysOperaLog) Get(d *dto.SysOperaLogGetReq, operaLogModel *model.SysOperaLog, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(operaLogModel.TableName(), p)).
+		First(operaLogModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysOperaLog对象
+func (e *SysOperaLog) Insert(operaLogModel *model.SysOperaLog) error {
+	var err error
+	var data model.SysOperaLog
+
+	err = e.Orm.Model(&data).
+		Create(operaLogModel).Error
+	if err != nil {
+		e.Log.Errorf("Service InsertSysOperaLog error: %s", err.Error())
+		return global.CreateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysOperaLog
+func (e *SysOperaLog) Remove(d *dto.SysOperaLogDeleteReq, p *actions.DataPermission) error {
+	var err error
+	var data model.SysOperaLog
+
+	db := e.Orm.
+		Scopes(actions.Permission(data.TableName(), p)).
+		Delete(&data, d.GetId())
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Service RemoveSysOperaLog error: %s", err.Error())
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}

+ 106 - 0
app/admin/service/sys_post.go

@@ -0,0 +1,106 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysPost struct {
+	service.Service
+}
+
+// GetPage 获取SysPost列表
+func (e *SysPost) GetPage(c *dto.SysPostPageReq, list *[]model.SysPost, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data model.SysPost
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s \r", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysPost对象
+func (e *SysPost) Get(d *dto.SysPostGetReq, postModel *model.SysPost, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(postModel.TableName(), p)).
+		First(postModel, d.GetId()).Error
+
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysPost对象
+func (e *SysPost) Insert(c *dto.SysPostInsertReq) error {
+	var err error
+	var data model.SysPost
+	c.Generate(&data)
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+	return nil
+}
+
+// Update 修改SysPost对象
+func (e *SysPost) Update(c *dto.SysPostUpdateReq) error {
+	var postModel = model.SysPost{}
+	err := e.Orm.First(&postModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&postModel)
+
+	err = e.Orm.Save(&postModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysPost
+func (e *SysPost) Remove(d *dto.SysPostDeleteReq) error {
+	var err error
+	var data model.SysPost
+
+	db := e.Orm.Model(&data).Delete(&data, d.GetId())
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}

+ 121 - 0
app/admin/service/sys_register_auth.go

@@ -0,0 +1,121 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysRegisterAuth struct {
+	service.Service
+}
+
+// GetPage 获取SysRegisterAuth列表
+func (e *SysRegisterAuth) GetPage(c *dto.SysRegisterAuthPageReq, list *[]model.SysRegisterAuth, count *int64) error {
+	var err error
+	var data model.SysRegisterAuth
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s \r", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysRegisterAuth对象
+func (e *SysRegisterAuth) Get(d *dto.SysRegisterAuthGetReq, postModel *model.SysRegisterAuth, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(postModel.TableName(), p)).
+		First(postModel, d.GetId()).Error
+
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysRegisterAuth对象
+func (e *SysRegisterAuth) Insert(c *dto.SysRegisterAuthInsertReq) error {
+	var err error
+	var data model.SysRegisterAuth
+
+	var URKey string
+	for {
+		URKey = utils.GetRandString(16, "", 0)
+		var j int64
+		err = e.Orm.Model(&data).Where("ur_key = ?", URKey).Count(&j).Error
+		if err != nil {
+			continue
+		}
+		if j == 0 {
+			break
+		}
+	}
+
+	c.Generate(&data)
+	data.URKey = URKey
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+	return nil
+}
+
+// Update 修改SysRegisterAuth对象
+func (e *SysRegisterAuth) Update(c *dto.SysRegisterAuthUpdateReq) error {
+	var postModel = model.SysRegisterAuth{}
+	err := e.Orm.First(&postModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&postModel)
+
+	err = e.Orm.Save(&postModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysRegisterAuth
+func (e *SysRegisterAuth) Remove(d *dto.SysRegisterAuthDeleteReq) error {
+	var err error
+	var data model.SysRegisterAuth
+
+	db := e.Orm.Model(&data).Delete(&data, d.GetId())
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}

+ 487 - 0
app/admin/service/sys_role.go

@@ -0,0 +1,487 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"Medical_OAuth/conf"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/casbin/casbin/v2"
+	"github.com/go-resty/resty/v2"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"strconv"
+	"strings"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	"gorm.io/gorm"
+)
+
+type SysRole struct {
+	service.Service
+}
+
+// GetPage 获取SysRole列表
+func (e *SysRole) GetPage(c *dto.SysRoleGetPageReq, list *[]model.SysRole, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data model.SysRole
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysRole对象
+func (e *SysRole) Get(d *dto.SysRoleGetReq, roleModel *model.SysRole, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(roleModel.TableName(), p)).
+		First(roleModel, d.GetId()).Error
+
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	//roleModel.MenuIds, err = e.GetRoleMenuId(roleModel.Id)
+	if err != nil {
+		e.Log.Errorf("get menuIds error, %s", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysRole对象
+func (e *SysRole) Insert(c *dto.SysRoleInsertReq) error {
+	var err error
+	var data model.SysRole
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	var roleKey string
+	for {
+		var count int64
+		roleKey = utils.GetRandString(8, "", 0)
+		var i int64
+		err = tx.Model(&data).Where("role_key = ?", roleKey).Count(&count).Error
+		if err != nil {
+			continue
+		}
+		if i == 0 {
+			break
+		}
+	}
+
+	c.Generate(&data)
+	data.RoleKey = roleKey
+	err = tx.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+
+	return nil
+}
+
+// Update 修改SysRole对象
+func (e *SysRole) Update(c *dto.SysRoleUpdateReq, p *actions.DataPermission) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	var roleModel = model.SysRole{}
+	// 查询角色是否存在
+	err = e.Orm.Scopes(actions.Permission(roleModel.TableName(), p)).
+		First(&roleModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&roleModel)
+	err = tx.Save(&roleModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+
+	c.Id = roleModel.Id
+
+	return nil
+}
+
+// Remove 删除SysRole
+func (e *SysRole) Remove(c *dto.SysRoleDeleteReq, p *actions.DataPermission, cb *casbin.SyncedEnforcer) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	var userList = make([]model.SysUser, 0)
+	var roleModel model.SysRole
+	err = e.Orm.Where("role_id = ?", c.Id).Find(&userList).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.DeleteFailedErr
+	}
+
+	// 统计与用户关联的角色名
+	if len(userList) > 0 {
+		var roleNameStr string
+		for i := 0; i < len(userList); i++ {
+			roleNameStr += fmt.Sprintf(" %s,", userList[i].Username)
+		}
+		if !pkg.IsEmptyStr(roleNameStr) {
+			// eg: role1,role2有用户关联,禁止删除!
+			return errors.New(strings.TrimRight(roleNameStr, ",") + "有用户关联,禁止删除!")
+		}
+	}
+
+	// 查询角色是否存在
+	err = e.Orm.Scopes(actions.Permission(roleModel.TableName(), p)).
+		First(&roleModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.DeleteNotFoundOrNoPermissionErr
+		}
+		return global.DeleteFailedErr
+	}
+	db := tx.Delete(&roleModel)
+
+	if err = db.Error; err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+
+	// 删除之前的角色关联的api
+	var roleApi model.ServRoleApi
+	err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleApi).Error
+	if err != nil {
+		return global.UpdateFailedErr
+	}
+
+	// 删除之前的角色关联的菜单
+	var roleMenu model.SysRoleMenu
+	err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleMenu).Error
+	if err != nil {
+		return global.UpdateFailedErr
+	}
+
+	// 清除 sys_casbin_rule 权限表里 当前角色的所有记录
+	_, _ = cb.RemoveFilteredPolicy(0, roleModel.RoleKey)
+
+	return nil
+}
+
+// GetRoleMenuId 获取角色对应的菜单ids
+func (e *SysRole) GetRoleMenuId(roleId int) ([]int, error) {
+	var err error
+	var roleModel model.SysRole
+	var menuIds []int
+	err = e.Orm.Where("id = ?", roleId).First(&roleModel).Error
+	if err != nil {
+		return []int{}, global.GetFailedErr
+	}
+
+	err = e.Orm.Model(&model.SysRoleMenu{}).Select("menu_id").Where("role_key = ? ", roleModel.RoleKey).Scan(&menuIds).Error
+	if err != nil {
+		return []int{}, global.GetFailedErr
+	}
+	return menuIds, nil
+}
+
+// GetWithName 获取SysRole对象
+func (e *SysRole) GetWithName(d *dto.SysRoleByName, roleModel *model.SysRole) *SysRole {
+	err := e.Orm.Where("name = ?", d.RoleName).First(roleModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.GetNotFoundOrNoPermissionErr
+		} else {
+			err = global.GetFailedErr
+		}
+		_ = e.AddError(err)
+		return e
+	}
+
+	//roleModel.MenuIds, err = e.GetRoleMenuId(roleModel.Id)
+	if err != nil {
+		e.Log.Errorf("get menuIds error, %s", err.Error())
+		_ = e.AddError(global.GetFailedErr)
+		return e
+	}
+	return e
+}
+
+// GetById 获取SysRole对象
+func (e *SysRole) GetById(roleId int) ([]string, error) {
+	permissions := make([]string, 0)
+	roleModel := model.SysRole{}
+	roleModel.Id = roleId
+	err := e.Orm.Model(&roleModel).First(&roleModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = global.GetNotFoundOrNoPermissionErr
+		} else {
+			err = global.GetFailedErr
+		}
+		return nil, err
+	}
+	//l := *roleModel.SysMenu
+	//for i := 0; i < len(l); i++ {
+	//	permissions = append(permissions, l[i].Permission)
+	//}
+	return permissions, nil
+}
+
+func (e *SysRole) SaveRoleApiCache(roleKey string, serviceId int, apiList []model.ServApi) {
+	key := "role_api-" + roleKey + strconv.Itoa(serviceId)
+	s, err := json.Marshal(apiList)
+	err = e.Cache.Set(key, s, 24*60*60)
+	if err != nil {
+		e.Log.Errorf("save apiIds error to redis, %s", err)
+	}
+}
+
+func (e *SysRole) GetRoleApiCache(roleKey string, serviceId int, apiList *[]model.ServApi) (err error) {
+	key := "role_api-" + roleKey + strconv.Itoa(serviceId)
+	s, err := e.Cache.Get(key)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal([]byte(s), &apiList)
+	return err
+}
+
+// UpdateRoleApi
+func (e *SysRole) UpdateRoleApi(d *dto.SysRoleUpdateRoleApiReq, cb *casbin.SyncedEnforcer) error {
+	var err error
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	var roleModel model.SysRole
+	err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+	var serviceModel model.SysService
+	err = e.Orm.Where("id = ?", d.ServiceId).First(&serviceModel).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+
+	var apiList []model.ServApi
+	err = e.Orm.Where("service_id = ? and id in (?)", d.ServiceId, d.ApiIds).Find(&apiList).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+	if len(apiList) == 0 {
+		return errors.New("api接口不存在!")
+	}
+	// 发送api权限回调
+	if serviceModel.No != conf.ExtConfig.Service.Number {
+		// 调用回调地址
+		client := resty.New()
+		resp, err := client.R().
+			SetHeader("Content-Type", "application/json").
+			SetHeader("AuthCode", serviceModel.AuthCode).
+			SetBody(map[string]interface{}{
+				"roleKey": roleModel.RoleKey,
+				"apiList": apiList,
+			}).
+			Post(serviceModel.Host + serviceModel.RoleApiUrl)
+
+		if err != nil {
+			return err
+		}
+		if resp.RawResponse.StatusCode != 200 {
+			return errors.New("请求服务角色授权接口失败!")
+		}
+	}
+
+	// 删除之前的角色关联的api
+	var roleApi model.ServRoleApi
+	err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleApi).Error
+	if err != nil {
+		return global.UpdateFailedErr
+	}
+	var roleApiList []model.ServRoleApi
+	// 添加新增的角色关联的api
+	for _, v := range apiList {
+		roleApiObj := model.ServRoleApi{
+			ServiceId: serviceModel.Id,
+			RoleKey:   roleModel.RoleKey,
+			ApiId:     v.Id,
+		}
+		roleApiObj.SetCreateBy(d.CreateBy)
+		roleApiList = append(roleApiList, roleApiObj)
+
+	}
+	err = tx.Save(&roleApiList).Error
+	if err != nil {
+		e.Log.Errorf("save apiIds error, %s", err)
+		return global.UpdateFailedErr
+	}
+
+	e.SaveRoleApiCache(roleModel.RoleKey, serviceModel.Id, apiList)
+
+	polices := make([][]string, 0)
+
+	for _, api := range apiList {
+		sub, dom, obj, act := FormatRoutePolicyForRole(roleModel.RoleKey, &api)
+		polices = append(polices, []string{sub, dom, obj, act})
+	}
+
+	// 清除 sys_casbin_rule 权限表里 当前角色的所有记录
+	_, err = cb.RemoveFilteredPolicy(0, roleModel.RoleKey)
+	_, err = cb.AddNamedPolicies("p", polices)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// GetRoleApiList
+func (e *SysRole) GetRoleApiList(d *dto.SysRoleGetRoleApiListReq, apiIds *[]int, apiList *[]model.ServApi) error {
+	var err error
+	var roleModel model.SysRole
+	err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+	var serviceModel model.SysService
+	err = e.Orm.Where("id = ?", d.ServiceId).First(&serviceModel).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+	e.Orm.Model(&model.ServRoleApi{}).Select("api_id").Where("role_key = ? and service_id = ?", roleModel.RoleKey, serviceModel.Id).Scan(apiIds)
+	// 从redis获取角色对应的api列表
+	err = e.GetRoleApiCache(roleModel.RoleKey, serviceModel.Id, apiList)
+	if err == nil {
+		return nil
+	}
+	err = e.Orm.Where("id in (?)", *apiIds).Find(&apiList).Error
+	if err != nil {
+		e.Log.Errorf("get apiIds error, %s", err)
+		return global.GetFailedErr
+	}
+	e.SaveRoleApiCache(roleModel.RoleKey, serviceModel.Id, *apiList)
+	return nil
+}
+
+func FormatRoutePolicyForRole(roleKey string, servApi *model.ServApi) (sub, dom, obj, act string) {
+	sub = fmt.Sprintf("role:%s", roleKey)                  // 希望访问资源的角色
+	dom = fmt.Sprintf("service:%d:api", servApi.ServiceId) // 域/域租户,这里以资源为单位
+	obj = servApi.Path                                     // 要访问的资源
+	act = servApi.Action                                   // 用户对资源执行的操作
+	return
+}
+
+func FormatRoutePolicyForScope(roleKey string, servApi *model.ServApi) (sub, dom, obj, act string) {
+	sub = fmt.Sprintf("scope:%s", roleKey)                 // 希望访问资源的范围
+	dom = fmt.Sprintf("service:%d:api", servApi.ServiceId) // 域/域租户,这里以资源为单位
+	obj = servApi.Path                                     // 要访问的资源
+	act = servApi.Action                                   // 用户对资源执行的操作
+	return
+}
+
+// UpdateRoleMenu 修改角色绑定的菜单
+func (e *SysRole) UpdateRoleMenu(d *dto.SysRoleUpdateRoleMenuReq) error {
+	var err error
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	var roleModel model.SysRole
+	err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+
+	var menuList []model.SysMenu
+	err = e.Orm.Where("id in (?)", d.MenuIds).Find(&menuList).Error
+	if err != nil {
+		return global.GetFailedErr
+	}
+	if len(menuList) == 0 {
+		return errors.New("菜单不存在!")
+	}
+
+	// 删除之前的角色关联的菜单
+	var roleMenu model.SysRoleMenu
+	err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleMenu).Error
+	if err != nil {
+		return global.UpdateFailedErr
+	}
+	var roleMenuList []model.SysRoleMenu
+	// 添加角色关联的菜单
+	for _, v := range menuList {
+		roleMenuObj := model.SysRoleMenu{
+			RoleKey: roleModel.RoleKey,
+			MenuId:  v.Id,
+		}
+		roleMenuObj.SetCreateBy(d.CreateBy)
+		roleMenuList = append(roleMenuList, roleMenuObj)
+
+	}
+	err = tx.Save(&roleMenuList).Error
+	if err != nil {
+		e.Log.Errorf("save menuIds error, %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}

+ 182 - 0
app/admin/service/sys_service.go

@@ -0,0 +1,182 @@
+package service
+
+import (
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+
+	"gorm.io/gorm"
+
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+)
+
+type SysService struct {
+	service.Service
+}
+
+// GetPage 获取SysService列表
+func (e *SysService) GetPage(c *dto.SysServicePageReq, list *[]model.SysService, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data model.SysService
+	c.No = c.Name
+
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s \r", err)
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Get 获取SysService对象
+func (e *SysService) Get(d *dto.SysServiceGetReq, postModel *model.SysService, p *actions.DataPermission) error {
+	err := e.Orm.
+		Scopes(actions.Permission(postModel.TableName(), p)).
+		First(postModel, d.GetId()).Error
+
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// Insert 创建SysService对象
+func (e *SysService) Insert(c *dto.SysServiceInsertReq) error {
+	var err error
+	var data model.SysService
+	err = e.Orm.Model(&data).Where("name = ?", c.Name).First(&data).Error
+	if err == nil {
+		e.Log.Errorf("db error: %s", err)
+		return errors.New("服务名称已存在")
+	}
+
+	var no string
+	for {
+		no = utils.GetRandString(8, "", 0)
+		var i int64
+		err = e.Orm.Model(&data).Where("no = ?", no).Count(&i).Error
+		if err != nil {
+			continue
+		}
+		if i == 0 {
+			break
+		}
+	}
+
+	c.Generate(&data)
+	data.No = no
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+	return nil
+}
+
+// Update 修改SysService对象
+func (e *SysService) Update(c *dto.SysServiceUpdateReq) error {
+	var postModel = model.SysService{}
+	var data = model.SysService{}
+	err := e.Orm.First(&postModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+	err = e.Orm.Model(&data).Where("name = ?", c.Name).First(&data).Error
+	if err == nil && postModel.Name != c.Name {
+		e.Log.Errorf("db error: %s", err)
+		return errors.New("服务名称已存在")
+	}
+
+	c.Generate(&postModel)
+
+	err = e.Orm.Save(&postModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysService
+func (e *SysService) Remove(d *dto.SysServiceDeleteReq) error {
+	var err error
+	var data model.SysService
+
+	db := e.Orm.Model(&data).Delete(&data, d.GetId())
+	if err = db.Error; err != nil {
+		e.Log.Errorf("Delete error: %s", err)
+		return global.DeleteFailedErr
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+	return nil
+}
+
+// Remove 删除SysService
+func (e *SysService) Discovery(d *dto.SysServiceDiscoveryReq) error {
+	var err error
+	var data model.SysService
+
+	err = e.Orm.Model(&data).Where("name = ?", d.Name).First(&data).Error
+	if err != nil {
+		if err == gorm.ErrRecordNotFound {
+			var no string
+			for {
+				no = utils.GetRandString(8, "", 0)
+				var i int64
+				err = e.Orm.Model(&data).Where("no = ?", no).Count(&i).Error
+				if err != nil {
+					continue
+				}
+				if i == 0 {
+					break
+				}
+			}
+
+			d.Generate(&data)
+			data.No = no
+			data.Status = 1
+			err = e.Orm.Create(&data).Error
+			if err != nil {
+				e.Log.Errorf("db error: %s", err)
+				return global.CreateFailedErr
+			}
+			d.Id = data.Id
+			return nil
+		}
+		e.Log.Errorf("Delete error: %s", err)
+		return global.CreateFailedErr
+	}
+
+	// 有则更新
+	d.Generate(&data)
+
+	err = e.Orm.Save(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	d.Id = data.Id
+	return nil
+}

+ 371 - 0
app/admin/service/sys_user.go

@@ -0,0 +1,371 @@
+package service
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/admin/service/dto"
+	"Medical_OAuth/common/actions"
+	cDto "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/global"
+	"errors"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"gorm.io/gorm"
+)
+
+type SysUser struct {
+	service.Service
+}
+
+// GetPage 获取SysUser列表
+func (e *SysUser) GetPage(c *dto.SysUserGetPageReq, p *actions.DataPermission, list *[]model.SysUser, count *int64) error {
+	var err error
+	var data model.SysUser
+	var userList []model.SysUser
+
+	err = e.Orm.
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.UserPermission(data.TableName(), p),
+		).
+		Find(&userList).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+
+	for i := 0; i < len(userList); i++ {
+		var dept model.SysDept
+		var role model.SysRole
+		//var post model.SysPost
+		err = e.Orm.First(&dept, userList[i].DeptId).Error
+		userList[i].Dept = dept
+
+		err = e.Orm.First(&role, userList[i].RoleId).Error
+		userList[i].Role = role
+
+		//err = e.Orm.First(&post, userList[i].PostId).Error
+		//userList[i].Post = post
+	}
+	*list = userList
+	return nil
+}
+
+func (e *SysUser) GetCount(c *dto.SysUserGetCountReq, count *int64) error {
+	var err error
+	var data model.SysUser
+	err = e.Orm.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+		).Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+
+	return nil
+}
+
+// Get 获取SysUser对象
+func (e *SysUser) Get(d *dto.SysUserGetReq, p *actions.DataPermission, userModel *model.SysUser) error {
+	var data model.SysUser
+	var dept model.SysDept
+	var role model.SysRole
+	//var post model.SysPost
+	err := e.Orm.Model(&data).
+		Scopes(actions.UserPermission(data.TableName(), p)).
+		First(userModel, d.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	err = e.Orm.First(&dept, userModel.DeptId).Error
+	userModel.Dept = dept
+
+	err = e.Orm.First(&role, userModel.RoleId).Error
+	userModel.Role = role
+
+	//err = e.Orm.First(&post, userModel.PostId).Error
+	//userModel.Post = post
+
+	return nil
+}
+
+// Insert 创建SysUser对象
+func (e *SysUser) Insert(c *dto.SysUserInsertReq) error {
+	var err error
+	var data model.SysUser
+	var i int64
+	err = e.Orm.Model(&data).Where("username = ?", c.Username).Count(&i).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	if i > 0 {
+		err = errors.New("用户名已存在!")
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+
+	var uuid string
+	for {
+		uuid = utils.GetUUID()
+		var j int64
+		err = e.Orm.Model(&data).Where("uuid = ?", uuid).Count(&j).Error
+		if err != nil {
+			continue
+		}
+		if j == 0 {
+			break
+		}
+	}
+
+	c.Generate(&data)
+	data.Uuid = uuid
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+
+	return nil
+}
+
+// Update 修改SysUser对象
+func (e *SysUser) Update(c *dto.SysUserUpdateReq, p *actions.DataPermission) error {
+	var err error
+	var userModel model.SysUser
+	err = e.Orm.
+		Scopes(actions.UserPermission(userModel.TableName(), p)).
+		First(&userModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+
+	c.Generate(&userModel)
+	err = e.Orm.Model(&userModel).Where("id = ?", &userModel.Id).
+		Omit("password", "salt").Updates(&userModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// UpdateStatus 更新用户状态
+func (e *SysUser) UpdateStatus(c *dto.UpdateSysUserStatusReq, p *actions.DataPermission) error {
+	var userModel model.SysUser
+	err := e.Orm.
+		Scopes(actions.UserPermission(userModel.TableName(), p)).
+		First(&userModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+	err = e.Orm.Table(userModel.TableName()).Where("id = ? ", c.Id).Updates(c).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// ResetPwd 重置用户密码
+func (e *SysUser) ResetPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPermission) error {
+	var userModel model.SysUser
+	err := e.Orm.
+		Scopes(actions.UserPermission(userModel.TableName(), p)).
+		First(&userModel, c.GetId()).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return global.UpdateFailedErr
+	}
+	c.Generate(&userModel)
+	err = e.Orm.Omit("username", "nick_name", "phone", "role_id", "avatar", "sex").Save(&userModel).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+// Remove 删除SysUser
+func (e *SysUser) Remove(c *dto.SysUserDeleteReq, p *actions.DataPermission) error {
+	var data model.SysUser
+
+	db := e.Orm.Model(&data).
+		Scopes(actions.UserPermission(data.TableName(), p)).
+		Find(&data, c.GetId())
+
+	if err := db.Error; err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+	if db.RowsAffected == 0 {
+		return global.DeleteNotFoundOrNoPermissionErr
+	}
+
+	if err := e.Orm.Delete(&data, c.GetId()).Error; err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+	return nil
+}
+
+// UpdatePwd 修改SysUser对象密码
+func (e *SysUser) UpdatePwd(id int, oldPassword, newPassword string) error {
+	var err error
+
+	if newPassword == "" {
+		return nil
+	}
+	c := &model.SysUser{}
+
+	err = e.Orm.Model(c).
+		Select("id", "password", "salt").
+		First(c, id).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.UpdateNotFoundOrNoPermissionErr
+		}
+		return errors.New("密码修改失败")
+	}
+	var ok bool
+	ok, err = pkg.CompareHashAndPassword(c.Password, oldPassword)
+	if err != nil {
+		e.Log.Errorf("CompareHashAndPassword error, %s", err.Error())
+		return errors.New("密码修改失败")
+	}
+	if !ok {
+		err = errors.New("incorrect Password")
+		e.Log.Warnf("user[%d] %s", id, err.Error())
+		return err
+	}
+	c.Password = newPassword
+	db := e.Orm.Model(c).Where("id = ?", id).
+		Select("Password", "Salt").
+		Updates(c)
+	if err = db.Error; err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return errors.New("密码修改失败")
+	}
+	return nil
+}
+
+func (e *SysUser) GetProfile(c *dto.SysUserById, user *model.SysUser) error {
+	err := e.Orm.First(user, c.GetId()).Error
+	if err != nil {
+		return err
+	}
+	var dept model.SysDept
+	var role model.SysRole
+	//var post model.SysPost
+
+	err = e.Orm.First(&dept, user.DeptId).Error
+	if err != nil {
+		return err
+	}
+	user.Dept = dept
+
+	err = e.Orm.First(&role, user.RoleId).Error
+	if err != nil {
+		return err
+	}
+	user.Role = role
+
+	//err = e.Orm.First(&post, user.PostId).Error
+	//if err != nil {
+	//	return err
+	//}
+	//user.Post = post
+
+	return nil
+}
+
+// 公开用户注册
+func (e *SysUser) Register(c *dto.SysUserRegisterReq) error {
+
+	var err error
+	var registerAuth model.SysRegisterAuth
+	err = e.Orm.Where("ur_key = ?", c.URKey).First(&registerAuth).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return errors.New("URKey不存在!")
+		}
+		return global.CreateFailedErr
+	}
+	if registerAuth.Status == 1 {
+		return errors.New("URKey已停用!")
+	}
+
+	if registerAuth.SMSVerify == 2 {
+		if len(c.Phone) == 0 {
+			return errors.New("手机号码不能为空!")
+		}
+		if len(c.Code) == 0 {
+			return errors.New("短信验证码不能为空!")
+		}
+		code, err := e.Cache.Get(model.GetVerifyCodeCacheKey(c.Phone))
+		if err != nil || code != c.Code {
+			return errors.New("短信验证码错误")
+		}
+	}
+
+	var data model.SysUser
+	var i int64
+	err = e.Orm.Model(&data).Where("username = ?", c.Username).Count(&i).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	if i > 0 {
+		err = errors.New("用户名已存在!")
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+
+	var uuid string
+	for {
+		uuid = utils.GetUUID()
+		var j int64
+		err = e.Orm.Model(&data).Where("uuid = ?", uuid).Count(&j).Error
+		if err != nil {
+			continue
+		}
+		if j == 0 {
+			break
+		}
+	}
+
+	c.Generate(&data)
+	data.Uuid = uuid
+	data.RoleId = registerAuth.RoleId
+	data.DeptId = registerAuth.DeptId
+	data.Status = "2"
+	err = e.Orm.Create(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.CreateFailedErr
+	}
+	c.Id = data.Id
+
+	return nil
+}

+ 72 - 0
app/jobs/controller/sys_job.go

@@ -0,0 +1,72 @@
+package controller
+
+import (
+	"Medical_OAuth/common/dto"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	toolsConfig "gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/jobs/service"
+	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+)
+
+type SysJob struct {
+	api.Api
+}
+
+// RemoveJobForService 调用service实现
+func (e SysJob) RemoveJobForService(c *gin.Context) {
+	v := dto.GeneralDelDto{}
+	s := service.SysJob{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&v, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, "")
+		return
+	}
+
+	s.Cron = sdk.Runtime.GetCrontabKey(toolsConfig.ApplicationConfig.Host)
+	err = s.RemoveJob(&v)
+	if err != nil {
+		e.Logger.Errorf("RemoveJob error, %s", err.Error())
+		e.Error(500, err, "")
+		return
+	}
+	e.OK(nil, s.Msg)
+}
+
+// StartJobForService 启动job service实现
+func (e SysJob) StartJobForService(c *gin.Context) {
+	e.MakeContext(c)
+	log := e.GetLogger()
+	db, err := e.GetOrm()
+	if err != nil {
+		log.Error(err)
+		return
+	}
+	var v dto.GeneralGetDto
+	err = c.BindUri(&v)
+	if err != nil {
+		log.Warnf("参数验证错误, error: %s", err)
+		e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
+		return
+	}
+	s := service.SysJob{}
+	s.Orm = db
+	s.Log = log
+	s.Cron = sdk.Runtime.GetCrontabKey(toolsConfig.ApplicationConfig.Host)
+	err = s.StartJob(&v)
+	if err != nil {
+		log.Errorf("GetCrontabKey error, %s", err.Error())
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(nil, s.Msg)
+}

+ 205 - 0
app/jobs/jobbase.go

@@ -0,0 +1,205 @@
+package jobs
+
+import (
+	"fmt"
+	"github.com/robfig/cron/v3"
+	"gorm.io/gorm"
+	"sync"
+	"time"
+
+	models2 "Medical_OAuth/app/jobs/model"
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/cronjob"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+)
+
+var timeFormat = "2006-01-02 15:04:05"
+var retryCount = 3
+
+var jobList map[string]JobsExec
+var lock sync.Mutex
+
+type JobCore struct {
+	InvokeTarget   string
+	Name           string
+	JobId          int
+	EntryId        int
+	CronExpression string
+	Args           string
+}
+
+// 任务类型 http
+type HttpJob struct {
+	JobCore
+}
+
+type ExecJob struct {
+	JobCore
+}
+
+func (e *ExecJob) Run() {
+	startTime := time.Now()
+	var obj = jobList[e.InvokeTarget]
+	if obj == nil {
+		log.Warn("[Job] ExecJob Run job nil")
+		return
+	}
+	err := CallExec(obj.(JobsExec), e.Args)
+	if err != nil {
+		// 如果失败暂停一段时间重试
+		fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err)
+	}
+	// 结束时间
+	endTime := time.Now()
+
+	// 执行时间
+	latencyTime := endTime.Sub(startTime)
+	//TODO: 待完善部分
+	//str := time.Now().Format(timeFormat) + " [INFO] JobCore " + string(e.EntryId) + "exec success , spend :" + latencyTime.String()
+	//ws.SendAll(str)
+	log.Infof("[Job] JobCore %s exec success , spend :%v", e.Name, latencyTime)
+	return
+}
+
+// http 任务接口
+func (h *HttpJob) Run() {
+
+	startTime := time.Now()
+	var count = 0
+	var err error
+	var str string
+	/* 循环 */
+LOOP:
+	if count < retryCount {
+		/* 跳过迭代 */
+		str, err = pkg.Get(h.InvokeTarget)
+		if err != nil {
+			// 如果失败暂停一段时间重试
+			fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err)
+			fmt.Printf(time.Now().Format(timeFormat)+" [INFO] Retry after the task fails %d seconds! %s \n", (count+1)*5, str)
+			time.Sleep(time.Duration(count+1) * 5 * time.Second)
+			count = count + 1
+			goto LOOP
+		}
+	}
+	// 结束时间
+	endTime := time.Now()
+
+	// 执行时间
+	latencyTime := endTime.Sub(startTime)
+	//TODO: 待完善部分
+
+	log.Infof("[Job] JobCore %s exec success , spend :%v", h.Name, latencyTime)
+	return
+}
+
+// 初始化
+func Setup(dbs map[string]*gorm.DB) {
+
+	fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore Starting...")
+
+	for k, db := range dbs {
+		sdk.Runtime.SetCrontab(k, cronjob.NewWithSeconds())
+		setup(k, db)
+	}
+}
+
+func setup(key string, db *gorm.DB) {
+	crontab := sdk.Runtime.GetCrontabKey(key)
+	sysJob := models2.SysJob{}
+	jobs := make([]models2.SysJob, 0)
+	err := sysJob.GetList(db, &jobs)
+	if err != nil {
+		fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore init error", err)
+	}
+	if len(jobs) == 0 {
+		fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore total:0")
+	}
+
+	_, err = sysJob.RemoveAllEntryID(db)
+	if err != nil {
+		fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore remove entry_id error", err)
+	}
+
+	for i := 0; i < len(jobs); i++ {
+		if !jobs[i].Auto {
+			continue
+		}
+		if jobs[i].JobType == 1 {
+			j := &HttpJob{}
+			j.InvokeTarget = jobs[i].InvokeTarget
+			j.CronExpression = jobs[i].CronExpression
+			j.JobId = jobs[i].JobId
+			j.Name = jobs[i].JobName
+
+			sysJob.EntryId, err = AddJob(crontab, j)
+		} else if jobs[i].JobType == 2 {
+			j := &ExecJob{}
+			j.InvokeTarget = jobs[i].InvokeTarget
+			j.CronExpression = jobs[i].CronExpression
+			j.JobId = jobs[i].JobId
+			j.Name = jobs[i].JobName
+			j.Args = jobs[i].Args
+			sysJob.EntryId, err = AddJob(crontab, j)
+		}
+		err = sysJob.Update(db, jobs[i].JobId)
+	}
+
+	// 启动任务
+	crontab.Start()
+	fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore start success.")
+	// 关闭任务
+	defer crontab.Stop()
+	select {}
+}
+
+// 添加任务 AddJob(invokeTarget string, jobId int, jobName string, cronExpression string)
+func AddJob(c *cron.Cron, job Job) (int, error) {
+	if job == nil {
+		fmt.Println("unknown")
+		return 0, nil
+	}
+	return job.addJob(c)
+}
+
+func (h *HttpJob) addJob(c *cron.Cron) (int, error) {
+	id, err := c.AddJob(h.CronExpression, h)
+	if err != nil {
+		fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore AddJob error", err)
+		return 0, err
+	}
+	EntryId := int(id)
+	return EntryId, nil
+}
+
+func (h *ExecJob) addJob(c *cron.Cron) (int, error) {
+	id, err := c.AddJob(h.CronExpression, h)
+	if err != nil {
+		fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore AddJob error", err)
+		return 0, err
+	}
+	EntryId := int(id)
+	return EntryId, nil
+}
+
+// 移除任务
+func Remove(c *cron.Cron, entryID int) chan bool {
+	ch := make(chan bool)
+	go func() {
+		c.Remove(cron.EntryID(entryID))
+		fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore Remove success ,info entryID :", entryID)
+		ch <- true
+	}()
+	return ch
+}
+
+// 任务停止
+//func Stop() chan bool {
+//	ch := make(chan bool)
+//	go func() {
+//		global.GADMCron.Stop()
+//		ch <- true
+//	}()
+//	return ch
+//}

+ 75 - 0
app/jobs/jobs.go

@@ -0,0 +1,75 @@
+package jobs
+
+import (
+	"fmt"
+	"time"
+)
+
+// 需要将定义的struct 添加到字典中;
+// 字典 key 可以配置到 自动任务 调用目标 中;
+func InitJob() {
+	jobList = map[string]JobsExec{
+		"ExamplesOne": ExamplesOne{},
+		//"CheckDeptSigned": CheckDeptSigned{},
+		// ...
+	}
+}
+
+// 新添加的job 必须按照以下格式定义,并实现Exec函数
+type ExamplesOne struct {
+}
+
+func (t ExamplesOne) Exec(arg interface{}) error {
+	str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success"
+	// TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string);请根据对应的类型进行转化;
+	switch arg.(type) {
+
+	case string:
+		if arg.(string) != "" {
+			fmt.Println("string", arg.(string))
+			fmt.Println(str, arg.(string))
+		} else {
+			fmt.Println("arg is nil")
+			fmt.Println(str, "arg is nil")
+		}
+		break
+	}
+
+	return nil
+}
+
+type CheckDeptSigned struct {
+}
+
+//// 检查机构签约是否过期
+//func (t CheckDeptSigned) Exec(arg interface{}) error {
+//
+//	organList := make([]sysModel.SysDept, 0)
+//	// GetOrm 获取orm连接
+//	orm, _ := db.GetOrm(&gin.Context{})
+//
+//	err := orm.Find(&organList).Error
+//	if err != nil {
+//		log.Errorf("db error: %s", err)
+//		return global.GetFailedErr
+//	}
+//
+//	for _, organ := range organList {
+//		// 未签约或已过期不处理
+//		if organ.IsSigned == cmodel.DeptNotSigned || organ.IsSigned == cmodel.DeptExpired {
+//			continue
+//		}
+//		expiredDate, _ := time.Parse("2006-01-02 15:04:05", organ.ExpiredDate+" 23:59:59")
+//		// 已过期
+//		if time.Now().After(expiredDate) {
+//			organ.IsSigned = cmodel.DeptExpired
+//			if err := orm.Save(&organ).Error; err != nil {
+//				log.Errorf("db error: %s", err)
+//				return global.UpdateFailedErr
+//			}
+//		}
+//	}
+//
+//	return nil
+//
+//}

+ 62 - 0
app/jobs/model/sys_job.go

@@ -0,0 +1,62 @@
+package model
+
+import (
+	model2 "Medical_OAuth/common/model"
+	"gorm.io/gorm"
+)
+
+type SysJob struct {
+	JobId          int    `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码
+	JobName        string `json:"jobName" gorm:"size:255;"`              // 名称
+	JobGroup       string `json:"jobGroup" gorm:"size:255;"`             // 任务分组
+	JobType        int    `json:"jobType" gorm:"size:1;"`                // 任务类型
+	CronExpression string `json:"cronExpression" gorm:"size:255;"`       // cron表达式
+	InvokeTarget   string `json:"invokeTarget" gorm:"size:255;"`         // 调用目标
+	Args           string `json:"args" gorm:"size:255;"`                 // 目标参数
+	MisfirePolicy  int    `json:"misfirePolicy" gorm:"size:255;"`        // 执行策略
+	Concurrent     int    `json:"concurrent" gorm:"size:1;"`             // 是否并发
+	Status         int    `json:"status" gorm:"size:1;"`                 // 状态
+	EntryId        int    `json:"entry_id" gorm:"size:11;"`              // job启动时返回的id
+	Auto           bool   `json:"auto" gorm:"size:4;"`                   // 是否开机自启动
+	model2.ControlBy
+	model2.ModelTime
+
+	DataScope string `json:"dataScope" gorm:"-"`
+}
+
+func (SysJob) TableName() string {
+	return "sys_job"
+}
+
+func (e *SysJob) Generate() model2.ActiveRecord {
+	o := *e
+	return &o
+}
+
+func (e *SysJob) GetId() interface{} {
+	return e.JobId
+}
+
+func (e *SysJob) SetCreateBy(createBy int) {
+	e.CreateBy = createBy
+}
+
+func (e *SysJob) SetUpdateBy(updateBy int) {
+	e.UpdateBy = updateBy
+}
+
+func (e *SysJob) GetList(tx *gorm.DB, list interface{}) (err error) {
+	return tx.Table(e.TableName()).Where("status = ?", 2).Find(list).Error
+}
+
+// 更新SysJob
+func (e *SysJob) Update(tx *gorm.DB, id interface{}) (err error) {
+	return tx.Table(e.TableName()).Where(id).Updates(&e).Error
+}
+
+func (e *SysJob) RemoveAllEntryID(tx *gorm.DB) (update SysJob, err error) {
+	if err = tx.Table(e.TableName()).Where("entry_id > ?", 0).Update("entry_id", 0).Error; err != nil {
+		return
+	}
+	return
+}

+ 35 - 0
app/jobs/router/int_router.go

@@ -0,0 +1,35 @@
+package router
+
+import (
+	common "Medical_OAuth/common/middleware"
+	"os"
+
+	"github.com/gin-gonic/gin"
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+)
+
+// InitRouter 路由初始化,不要怀疑,这里用到了
+func InitRouter() {
+	var r *gin.Engine
+	h := sdk.Runtime.GetEngine()
+	if h == nil {
+		log.Fatal("not found engine...")
+		os.Exit(-1)
+	}
+	switch h.(type) {
+	case *gin.Engine:
+		r = h.(*gin.Engine)
+	default:
+		log.Fatal("not support other engine")
+		os.Exit(-1)
+	}
+
+	authMiddleware, err := common.AuthInit()
+	if err != nil {
+		log.Fatalf("JWT Init Error, %s", err.Error())
+	}
+
+	// 注册业务路由
+	initRouter(r, authMiddleware)
+}

+ 42 - 0
app/jobs/router/router.go

@@ -0,0 +1,42 @@
+package router
+
+import (
+	"github.com/gin-gonic/gin"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+var (
+	routerNoCheckRole = make([]func(*gin.RouterGroup), 0)
+	routerCheckRole   = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
+)
+
+// initRouter 路由示例
+func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
+
+	// 无需认证的路由
+	noCheckRoleRouter(r)
+	// 需要认证的路由
+	checkRoleRouter(r, authMiddleware)
+
+	return r
+}
+
+// noCheckRoleRouter 无需认证的路由示例
+func noCheckRoleRouter(r *gin.Engine) {
+	// 可根据业务需求来设置接口版本
+	v1 := r.Group("/api")
+
+	for _, f := range routerNoCheckRole {
+		f(v1)
+	}
+}
+
+// checkRoleRouter 需要认证的路由示例
+func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) {
+	// 可根据业务需求来设置接口版本
+	v1 := r.Group("/api")
+
+	for _, f := range routerCheckRole {
+		f(v1, authMiddleware)
+	}
+}

+ 39 - 0
app/jobs/router/sys_job.go

@@ -0,0 +1,39 @@
+package router
+
+import (
+	actions2 "Medical_OAuth/common/actions"
+	"Medical_OAuth/common/middleware"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/jobs/controller"
+	"Medical_OAuth/app/jobs/model"
+	"Medical_OAuth/app/jobs/service/dto"
+	jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth"
+)
+
+func init() {
+	routerCheckRole = append(routerCheckRole, registerSysJobRouter)
+}
+
+// 需认证的路由代码
+func registerSysJobRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
+
+	r := v1.Group("/sys-job").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
+	{
+		sysJob := &model.SysJob{}
+		r.GET("", actions2.PermissionAction(), actions2.IndexAction(sysJob, new(dto.SysJobSearch), func() interface{} {
+			list := make([]model.SysJob, 0)
+			return &list
+		}))
+		r.GET("/:id", actions2.PermissionAction(), actions2.ViewAction(new(dto.SysJobById), func() interface{} {
+			return &dto.SysJobItem{}
+		}))
+		r.POST("", actions2.CreateAction(new(dto.SysJobControl)))
+		r.PUT("", actions2.PermissionAction(), actions2.UpdateAction(new(dto.SysJobControl)))
+		r.DELETE("", actions2.PermissionAction(), actions2.DeleteAction(new(dto.SysJobById)))
+	}
+	sysJob := controller.SysJob{}
+
+	v1.GET("/job/remove/:id", sysJob.RemoveJobForService)
+	v1.GET("/job/start/:id", sysJob.StartJobForService)
+}

+ 108 - 0
app/jobs/service/dto/sys_job.go

@@ -0,0 +1,108 @@
+package dto
+
+import (
+	dto2 "Medical_OAuth/common/dto"
+	common "Medical_OAuth/common/model"
+	"github.com/gin-gonic/gin"
+
+	"Medical_OAuth/app/jobs/model"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+)
+
+type SysJobSearch struct {
+	dto2.Pagination `search:"-"`
+	JobId           int    `form:"jobId" search:"type:exact;column:job_id;table:sys_job"`
+	JobName         string `form:"jobName" search:"type:icontains;column:job_name;table:sys_job"`
+	JobGroup        string `form:"jobGroup" search:"type:exact;column:job_group;table:sys_job"`
+	CronExpression  string `form:"cronExpression" search:"type:exact;column:cron_expression;table:sys_job"`
+	InvokeTarget    string `form:"invokeTarget" search:"type:exact;column:invoke_target;table:sys_job"`
+	Status          int    `form:"status" search:"type:exact;column:status;table:sys_job"`
+}
+
+func (m *SysJobSearch) GetNeedSearch() interface{} {
+	return *m
+}
+
+func (m *SysJobSearch) Bind(ctx *gin.Context) error {
+	log := api.GetRequestLogger(ctx)
+	err := ctx.ShouldBind(m)
+	if err != nil {
+		log.Errorf("Bind error: %s", err)
+	}
+	return err
+}
+
+func (m *SysJobSearch) Generate() dto2.Index {
+	o := *m
+	return &o
+}
+
+type SysJobControl struct {
+	JobId          int    `json:"jobId"`
+	JobName        string `json:"jobName" validate:"required"` // 名称
+	JobGroup       string `json:"jobGroup"`                    // 任务分组
+	JobType        int    `json:"jobType"`                     // 任务类型
+	CronExpression string `json:"cronExpression"`              // cron表达式
+	InvokeTarget   string `json:"invokeTarget"`                // 调用目标
+	Args           string `json:"args"`                        // 目标参数
+	MisfirePolicy  int    `json:"misfirePolicy"`               // 执行策略
+	Concurrent     int    `json:"concurrent"`                  // 是否并发
+	Status         int    `json:"status"`                      // 状态
+	EntryId        int    `json:"entryId"`                     // job启动时返回的id
+}
+
+func (s *SysJobControl) Bind(ctx *gin.Context) error {
+	return ctx.ShouldBind(s)
+}
+
+func (s *SysJobControl) Generate() dto2.Control {
+	cp := *s
+	return &cp
+}
+
+func (s *SysJobControl) GenerateM() (common.ActiveRecord, error) {
+	return &model.SysJob{
+		JobId:          s.JobId,
+		JobName:        s.JobName,
+		JobGroup:       s.JobGroup,
+		JobType:        s.JobType,
+		CronExpression: s.CronExpression,
+		InvokeTarget:   s.InvokeTarget,
+		Args:           s.Args,
+		MisfirePolicy:  s.MisfirePolicy,
+		Concurrent:     s.Concurrent,
+		Status:         s.Status,
+		EntryId:        s.EntryId,
+	}, nil
+}
+
+func (s *SysJobControl) GetId() interface{} {
+	return s.JobId
+}
+
+type SysJobById struct {
+	dto2.ObjectById
+}
+
+func (s *SysJobById) Generate() dto2.Control {
+	cp := *s
+	return &cp
+}
+
+func (s *SysJobById) GenerateM() (common.ActiveRecord, error) {
+	return &model.SysJob{}, nil
+}
+
+type SysJobItem struct {
+	JobId          int    `json:"jobId"`
+	JobName        string `json:"jobName" validate:"required"` // 名称
+	JobGroup       string `json:"jobGroup"`                    // 任务分组
+	JobType        int    `json:"jobType"`                     // 任务类型
+	CronExpression string `json:"cronExpression"`              // cron表达式
+	InvokeTarget   string `json:"invokeTarget"`                // 调用目标
+	Args           string `json:"args"`                        // 目标参数
+	MisfirePolicy  int    `json:"misfirePolicy"`               // 执行策略
+	Concurrent     int    `json:"concurrent"`                  // 是否并发
+	Status         int    `json:"status"`                      // 状态
+	EntryId        int    `json:"entryId"`                     // job启动时返回的id
+}

+ 92 - 0
app/jobs/service/sys_job.go

@@ -0,0 +1,92 @@
+package service
+
+import (
+	"Medical_OAuth/common/dto"
+	"errors"
+	"github.com/robfig/cron/v3"
+	"gogs.baozhida.cn/zoie/OAuth-core/service"
+	"time"
+
+	"Medical_OAuth/app/jobs"
+	"Medical_OAuth/app/jobs/model"
+)
+
+type SysJob struct {
+	service.Service
+	Cron *cron.Cron
+}
+
+// RemoveJob 删除job
+func (e *SysJob) RemoveJob(c *dto.GeneralDelDto) error {
+	var err error
+	var data model.SysJob
+	err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+	cn := jobs.Remove(e.Cron, data.EntryId)
+
+	select {
+	case res := <-cn:
+		if res {
+			err = e.Orm.Table(data.TableName()).Where("entry_id = ?", data.EntryId).Update("entry_id", 0).Error
+			if err != nil {
+				e.Log.Errorf("db error: %s", err)
+			}
+			return err
+		}
+	case <-time.After(time.Second * 1):
+		e.Msg = "操作超时!"
+		return nil
+	}
+	return nil
+}
+
+// StartJob 启动任务
+func (e *SysJob) StartJob(c *dto.GeneralGetDto) error {
+	var data model.SysJob
+	var err error
+	err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return err
+	}
+
+	if data.Status == 1 {
+		err = errors.New("当前Job是关闭状态不能被启动,请先启用。")
+		return err
+	}
+
+	if data.JobType == 1 {
+		var j = &jobs.HttpJob{}
+		j.InvokeTarget = data.InvokeTarget
+		j.CronExpression = data.CronExpression
+		j.JobId = data.JobId
+		j.Name = data.JobName
+		data.EntryId, err = jobs.AddJob(e.Cron, j)
+		if err != nil {
+			e.Log.Errorf("jobs AddJob[HttpJob] error: %s", err)
+		}
+	} else {
+		var j = &jobs.ExecJob{}
+		j.InvokeTarget = data.InvokeTarget
+		j.CronExpression = data.CronExpression
+		j.JobId = data.JobId
+		j.Name = data.JobName
+		j.Args = data.Args
+		data.EntryId, err = jobs.AddJob(e.Cron, j)
+		if err != nil {
+			e.Log.Errorf("jobs AddJob[ExecJob] error: %s", err)
+		}
+	}
+	if err != nil {
+		return err
+	}
+
+	err = e.Orm.Table(data.TableName()).Where(c.Id).Updates(&data).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+	}
+	return err
+}

+ 16 - 0
app/jobs/type.go

@@ -0,0 +1,16 @@
+package jobs
+
+import "github.com/robfig/cron/v3"
+
+type Job interface {
+	Run()
+	addJob(*cron.Cron) (int, error)
+}
+
+type JobsExec interface {
+	Exec(arg interface{}) error
+}
+
+func CallExec(e JobsExec, arg interface{}) error {
+	return e.Exec(arg)
+}

+ 8 - 0
cmd/api/jobs.go

@@ -0,0 +1,8 @@
+package api
+
+import "Medical_OAuth/app/jobs/router"
+
+func init() {
+	//注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法
+	AppRouters = append(AppRouters, router.InitRouter)
+}

+ 201 - 0
cmd/api/server.go

@@ -0,0 +1,201 @@
+package api
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"Medical_OAuth/app/jobs"
+	global2 "Medical_OAuth/common/global"
+	"Medical_OAuth/common/middleware"
+	"Medical_OAuth/common/middleware/handler"
+	"Medical_OAuth/common/storage"
+	"context"
+	"fmt"
+	"gorm.io/gorm"
+	"log"
+	"net/http"
+	"os"
+	"os/signal"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"github.com/spf13/cobra"
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/config/source/file"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/runtime"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+
+	"Medical_OAuth/app/admin/router"
+	ext "Medical_OAuth/conf"
+	database "Medical_OAuth/db"
+)
+
+var (
+	configYml string
+	StartCmd  = &cobra.Command{
+		Use:          "server",
+		Short:        "Start API server",
+		Example:      "Medical_OAuth server -c conf/settings.yml",
+		SilenceUsage: true,
+		PreRun: func(cmd *cobra.Command, args []string) {
+			setup()
+		},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return run()
+		},
+	}
+)
+
+var AppRouters = make([]func(), 0)
+
+func init() {
+	StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file")
+
+	//注册路由
+	AppRouters = append(AppRouters, router.InitRouter)
+}
+
+func setup() {
+	// 注入配置扩展项
+	config.ExtendConfig = &ext.ExtConfig
+	//1. 读取配置
+	config.Setup(
+		file.NewSource(file.WithPath(configYml)),
+		database.Setup,
+		storage.Setup,
+	)
+	database.AutoMigrateDB()
+	//注册监听函数
+	queue := sdk.Runtime.GetMemoryQueue("")
+	queue.Register(global2.LoginLog, model.SaveLoginLog)
+	queue.Register(global2.OperateLog, model.SaveOperaLog)
+	//queue.Register(global2.ApiCheck, model.SaveSysApi)
+	go queue.Run()
+
+	usageStr := `starting api server...`
+	log.Println(usageStr)
+}
+
+func run() error {
+	if config.ApplicationConfig.Mode == pkg.ModeProd.String() {
+		gin.SetMode(gin.ReleaseMode)
+	}
+	initRouter()
+
+	for _, f := range AppRouters {
+		f()
+	}
+
+	srv := &http.Server{
+		Addr:    fmt.Sprintf("%s:%d", config.ApplicationConfig.Host, config.ApplicationConfig.Port),
+		Handler: sdk.Runtime.GetEngine(),
+	}
+
+	// fixme 新加的服务在这里配置
+	//go func() {
+	//	otherSvc.InitJob()
+	//	otherSvc.Setup(sdk.Runtime.GetDb())
+	//
+	//}()
+
+	go func() {
+		jobs.InitJob()
+		jobs.Setup(sdk.Runtime.GetDb())
+	}()
+
+	go func() {
+		// 服务连接
+		if config.SslConfig.Enable {
+			if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
+				log.Fatal("listen: ", err)
+			}
+		} else {
+			if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+				log.Fatal("listen: ", err)
+			}
+		}
+	}()
+
+	go func() {
+		InitService()
+	}()
+
+	tip()
+	fmt.Println(pkg.Green("Server run at:"))
+	fmt.Printf("-  Local:   http://localhost:%d/ \r\n", config.ApplicationConfig.Port)
+	fmt.Printf("-  Network: http://%s:%d/ \r\n", pkg.GetLocalHost(), config.ApplicationConfig.Port)
+	fmt.Println(pkg.Green("Swagger run at:"))
+	fmt.Printf("-  Local:   http://localhost:%d/swagger/index.html \r\n", config.ApplicationConfig.Port)
+	fmt.Printf("-  Network: http://%s:%d/swagger/index.html \r\n", pkg.GetLocalHost(), config.ApplicationConfig.Port)
+	fmt.Printf("%s Enter Control + C Shutdown Server \r\n", pkg.GetCurrentTimeStr())
+	// 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)
+	quit := make(chan os.Signal)
+	signal.Notify(quit, os.Interrupt)
+	<-quit
+
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
+	fmt.Printf("%s Shutdown Server ... \r\n", pkg.GetCurrentTimeStr())
+
+	if err := srv.Shutdown(ctx); err != nil {
+		log.Fatal("Server Shutdown:", err)
+	}
+	log.Println("Server exiting")
+
+	return nil
+}
+
+var Router runtime.Router
+
+func tip() {
+	usageStr := `欢迎使用 ` + pkg.Green(`OAuth `+global2.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
+	fmt.Printf("%s \n\n", usageStr)
+}
+
+func initRouter() {
+	var r *gin.Engine
+	h := sdk.Runtime.GetEngine()
+	if h == nil {
+		h = gin.New()
+		sdk.Runtime.SetEngine(h)
+	}
+	switch h.(type) {
+	case *gin.Engine:
+		r = h.(*gin.Engine)
+	default:
+		log.Fatal("not support other engine")
+		os.Exit(-1)
+	}
+	if config.SslConfig.Enable {
+		r.Use(handler.TlsHandler())
+	}
+	r.Use(middleware.Sentinel()).
+		Use(middleware.RequestId(pkg.TrafficKey)).
+		Use(api.SetRequestLogger)
+
+	middleware.InitMiddleware(r)
+
+}
+
+func InitService() {
+	// gorm 创建或更新
+	obj := model.SysService{}
+	service := model.SysService{
+		No:       ext.ExtConfig.Service.Number,
+		Name:     ext.ExtConfig.Service.Name,
+		Host:     config.ApplicationConfig.Host,
+		AuthCode: ext.ExtConfig.Service.AuthCode,
+	}
+	db := database.DB
+
+	err := db.Where("name = ?", ext.ExtConfig.Service.Name).First(&obj).Error
+	if err != nil {
+		if gorm.ErrRecordNotFound == err {
+			db.Create(&service)
+		}
+	} else {
+		db.Model(&service).Where("name = ?", ext.ExtConfig.Service.Name).Updates(&service)
+	}
+
+}

+ 51 - 0
cmd/cobra.go

@@ -0,0 +1,51 @@
+package cmd
+
+import (
+	"Medical_OAuth/common/global"
+	"errors"
+	"fmt"
+	"os"
+
+	"github.com/spf13/cobra"
+
+	"Medical_OAuth/cmd/api"
+	"Medical_OAuth/cmd/config"
+	"Medical_OAuth/cmd/migrate"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+)
+
+var rootCmd = &cobra.Command{
+	Use:          "Medical_OAuth",
+	Short:        "Medical_OAuth",
+	SilenceUsage: true,
+	Long:         `OAuth`,
+	Args: func(cmd *cobra.Command, args []string) error {
+		if len(args) < 1 {
+			tip()
+			return errors.New(pkg.Red("requires at least one arg"))
+		}
+		return nil
+	},
+	PersistentPreRunE: func(*cobra.Command, []string) error { return nil },
+	Run: func(cmd *cobra.Command, args []string) {
+		tip()
+	},
+}
+
+func tip() {
+	usageStr := `欢迎使用 ` + pkg.Green(`OAuth `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
+	fmt.Printf("%s\n", usageStr)
+}
+
+func init() {
+	rootCmd.AddCommand(api.StartCmd)
+	rootCmd.AddCommand(config.StartCmd)
+	rootCmd.AddCommand(migrate.StartCmd)
+}
+
+// Execute : apply commands
+func Execute() {
+	if err := rootCmd.Execute(); err != nil {
+		os.Exit(-1)
+	}
+}

+ 62 - 0
cmd/config/server.go

@@ -0,0 +1,62 @@
+package config
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/spf13/cobra"
+
+	"gogs.baozhida.cn/zoie/OAuth-core/config/source/file"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+)
+
+var (
+	configYml string
+	StartCmd  = &cobra.Command{
+		Use:     "config",
+		Short:   "Get Application config info",
+		Example: "Medical_OAuth config -c conf/settings.yml",
+		Run: func(cmd *cobra.Command, args []string) {
+			run()
+		},
+	}
+)
+
+func init() {
+	StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file")
+}
+
+func run() {
+	config.Setup(file.NewSource(file.WithPath(configYml)))
+
+	application, errs := json.MarshalIndent(config.ApplicationConfig, "", "   ") //转换成JSON返回的是byte[]
+	if errs != nil {
+		fmt.Println(errs.Error())
+	}
+	fmt.Println("application:", string(application))
+
+	jwt, errs := json.MarshalIndent(config.JwtConfig, "", "   ") //转换成JSON返回的是byte[]
+	if errs != nil {
+		fmt.Println(errs.Error())
+	}
+	fmt.Println("jwt:", string(jwt))
+
+	database, errs := json.MarshalIndent(config.DatabasesConfig, "", "   ") //转换成JSON返回的是byte[]
+	if errs != nil {
+		fmt.Println(errs.Error())
+	}
+	fmt.Println("database:", string(database))
+
+	gen, errs := json.MarshalIndent(config.GenConfig, "", "   ") //转换成JSON返回的是byte[]
+	if errs != nil {
+		fmt.Println(errs.Error())
+	}
+	fmt.Println("gen:", string(gen))
+
+	loggerConfig, errs := json.MarshalIndent(config.LoggerConfig, "", "   ") //转换成JSON返回的是byte[]
+	if errs != nil {
+		fmt.Println(errs.Error())
+	}
+	fmt.Println("logger:", string(loggerConfig))
+
+}

+ 63 - 0
cmd/migrate/initdb.go

@@ -0,0 +1,63 @@
+package migrate
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"strings"
+
+	"gorm.io/gorm"
+)
+
+func InitDb(db *gorm.DB) (err error) {
+	filePath := "conf/db.sql"
+	if err = ExecSql(db, filePath); err != nil {
+		return err
+	}
+	return err
+}
+
+func ExecSql(db *gorm.DB, filePath string) error {
+	sql, err := IoUtil(filePath)
+	if err != nil {
+		fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error())
+		return err
+	}
+
+	tx := db.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	sqlList := strings.Split(sql, ";")
+	for i := 0; i < len(sqlList)-1; i++ {
+		if strings.Contains(sqlList[i], "--") {
+			fmt.Println(sqlList[i])
+			continue
+		}
+		sql := strings.Replace(sqlList[i]+";", "\n", "", -1)
+		sql = strings.TrimSpace(sql)
+		if err = tx.Exec(sql).Error; err != nil {
+			log.Printf("error sql: %s", sql)
+			if !strings.Contains(err.Error(), "Query was empty") {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func IoUtil(filePath string) (string, error) {
+	if contents, err := os.ReadFile(filePath); err == nil {
+		//因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符
+		result := strings.Replace(string(contents), "\n", "", 1)
+		fmt.Println("Use ioUtil.ReadFile to read a file:", result)
+		return result, nil
+	} else {
+		return "", err
+	}
+}

+ 41 - 0
cmd/migrate/server.go

@@ -0,0 +1,41 @@
+package migrate
+
+import (
+	"github.com/spf13/cobra"
+
+	"Medical_OAuth/db"
+	"gogs.baozhida.cn/zoie/OAuth-core/config/source/file"
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+)
+
+var (
+	configYml string
+	StartCmd  = &cobra.Command{
+		Use:     "migrate",
+		Short:   "初始化数据库基础数据",
+		Example: "Medical_OAuth migrate -c conf/settings.yml",
+		PreRunE: func(cmd *cobra.Command, args []string) error {
+			//1. 读取配置
+			config.Setup(
+				file.NewSource(file.WithPath(configYml)),
+				db.Setup,
+			)
+			db.AutoMigrateDB()
+
+			return nil
+		},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			if err := InitDb(db.DB); err != nil {
+				log.Error("数据库基础数据初始化失败", err.Error())
+			} else {
+				log.Info("数据库基础数据初始化成功")
+			}
+			return nil
+		},
+	}
+)
+
+func init() {
+	StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file")
+}

+ 49 - 0
common/actions/create.go

@@ -0,0 +1,49 @@
+package actions
+
+import (
+	"Medical_OAuth/common/dto"
+	"Medical_OAuth/common/model"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	"gogs.baozhida.cn/zoie/OAuth-core/api"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+// CreateAction 通用新增动作
+func CreateAction(control dto.Control) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		log := api.GetRequestLogger(c)
+		db, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		//新增操作
+		req := control.Generate()
+		err = req.Bind(c)
+		if err != nil {
+			response.Error(c, http.StatusUnprocessableEntity, err, err.Error())
+			return
+		}
+		var object model.ActiveRecord
+		object, err = req.GenerateM()
+		if err != nil {
+			response.Error(c, 500, err, "模型生成失败")
+			return
+		}
+		object.SetCreateBy(user.GetUserId(c))
+		err = db.WithContext(c).Create(object).Error
+		if err != nil {
+			log.Errorf("Create error: %s", err)
+			response.Error(c, 500, err, "创建失败")
+			return
+		}
+		response.OK(c, object.GetId(), "创建成功")
+		c.Next()
+	}
+}

+ 61 - 0
common/actions/delete.go

@@ -0,0 +1,61 @@
+package actions
+
+import (
+	"Medical_OAuth/common/dto"
+	"Medical_OAuth/common/model"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+// DeleteAction 通用删除动作
+func DeleteAction(control dto.Control) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		db, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		msgID := pkg.GenerateMsgIDFromContext(c)
+		//删除操作
+		req := control.Generate()
+		err = req.Bind(c)
+		if err != nil {
+			log.Errorf("MsgID[%s] Bind error: %s", msgID, err)
+			response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败")
+			return
+		}
+		var object model.ActiveRecord
+		object, err = req.GenerateM()
+		if err != nil {
+			response.Error(c, 500, err, "模型生成失败")
+			return
+		}
+
+		object.SetUpdateBy(user.GetUserId(c))
+
+		//数据权限检查
+		p := GetPermissionFromContext(c)
+
+		db = db.WithContext(c).Scopes(
+			Permission(object.TableName(), p),
+		).Where(req.GetId()).Delete(object)
+		if db.Error != nil {
+			log.Errorf("MsgID[%s] Delete error: %s", msgID, err)
+			response.Error(c, 500, err, "删除失败")
+			return
+		}
+		if db.RowsAffected == 0 {
+			response.Error(c, http.StatusForbidden, nil, "无权删除该数据")
+			return
+		}
+		response.OK(c, object.GetId(), "删除成功")
+		c.Next()
+	}
+}

+ 58 - 0
common/actions/index.go

@@ -0,0 +1,58 @@
+package actions
+
+import (
+	dto2 "Medical_OAuth/common/dto"
+	"Medical_OAuth/common/model"
+	"errors"
+	"gorm.io/gorm"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+// IndexAction 通用查询动作
+func IndexAction(m model.ActiveRecord, d dto2.Index, f func() interface{}) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		db, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		msgID := pkg.GenerateMsgIDFromContext(c)
+		list := f()
+		object := m.Generate()
+		req := d.Generate()
+		var count int64
+
+		//查询列表
+		err = req.Bind(c)
+		if err != nil {
+			response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败")
+			return
+		}
+
+		//数据权限检查
+		p := GetPermissionFromContext(c)
+
+		err = db.WithContext(c).Model(object).
+			Scopes(
+				dto2.MakeCondition(req.GetNeedSearch()),
+				dto2.Paginate(req.GetPageSize(), req.GetPageIndex()),
+				Permission(object.TableName(), p),
+			).
+			Find(list).Limit(-1).Offset(-1).
+			Count(&count).Error
+		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+			log.Errorf("MsgID[%s] Index error: %s", msgID, err)
+			response.Error(c, 500, err, "查询失败")
+			return
+		}
+		response.PageOK(c, list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+		c.Next()
+	}
+}

+ 128 - 0
common/actions/permission.go

@@ -0,0 +1,128 @@
+package actions
+
+import (
+	"Medical_OAuth/app/admin/model"
+	"errors"
+	"github.com/gin-gonic/gin"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gorm.io/gorm"
+	"strconv"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
+)
+
+type DataPermission struct {
+	DataScope string
+	UserId    int
+	DeptId    int
+	RoleId    int
+}
+
+func PermissionAction() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		ormDB, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		msgID := pkg.GenerateMsgIDFromContext(c)
+		var p = new(DataPermission)
+		if userId := user.GetUserIdStr(c); userId != "" {
+			p, err = newDataPermission(ormDB, userId)
+			if err != nil {
+				log.Errorf("MsgID[%s] PermissionAction error: %s", msgID, err)
+				response.Error(c, 500, err, "权限范围鉴定错误")
+				c.Abort()
+				return
+			}
+		}
+		c.Set(PermissionKey, p)
+		c.Next()
+	}
+}
+
+func newDataPermission(tx *gorm.DB, userId interface{}) (*DataPermission, error) {
+	var err error
+	p := &DataPermission{}
+
+	err = tx.Table("sys_user").
+		Select("sys_user.id as user_id", "sys_role.id as role_id", "sys_user.dept_id", "sys_role.data_scope").
+		Joins("left join sys_role on sys_role.id = sys_user.role_id").
+		Where("sys_user.id = ?", userId).
+		Scan(p).Error
+	if err != nil {
+		err = errors.New("获取用户数据出错 msg:" + err.Error())
+		return nil, err
+	}
+	return p, nil
+}
+
+func UserPermission(tableName string, p *DataPermission) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		if !config.ApplicationConfig.EnableDP {
+			return db
+		}
+		if p == nil {
+			return db
+		}
+		switch p.DataScope {
+		//case "2":
+		//	return db.Where(tableName+".create_by in (select sys_user.id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?) id = ?", p.RoleId, p.UserId)
+		case "3":
+			return db.Where(tableName+".dept_id = ? ", p.DeptId)
+		case "4":
+			return db.Where(tableName+".create_by in (SELECT id from sys_user where sys_user.dept_id in(select id from sys_dept where dept_path like ? )) or id = ?", "%/"+pkg.IntToString(p.DeptId)+"/%", p.UserId)
+		case "5":
+			return db.Where(tableName+".id = ?", p.UserId)
+		default:
+			return db
+		}
+	}
+}
+
+func Permission(tableName string, p *DataPermission) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		if !config.ApplicationConfig.EnableDP {
+			return db
+		}
+		if p == nil {
+			return db
+		}
+		switch p.DataScope {
+		//case "2":
+		//	return db.Where(tableName+".create_by in (select sys_user.id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", p.RoleId)
+		case "3":
+			return db.Where(tableName+".create_by in (SELECT id from sys_user where dept_id = ? )", p.DeptId)
+		case "4":
+			return db.Where(tableName+".create_by in (SELECT id from sys_user where sys_user.dept_id in (select id from sys_dept where dept_path like ? ))", "%/"+pkg.IntToString(p.DeptId)+"/%")
+		case "5":
+			return db.Where(tableName+".create_by = ?", p.UserId)
+		default:
+			return db
+		}
+	}
+}
+
+func getPermissionFromContext(c *gin.Context) *DataPermission {
+	p := new(DataPermission)
+	if pm, ok := c.Get(PermissionKey); ok {
+		switch pm.(type) {
+		case *DataPermission:
+			p = pm.(*DataPermission)
+		}
+	}
+	if deptIdStr, err := sdk.Runtime.GetCacheAdapter().Get(model.GetEnterDeptCacheKey(user.GetUserId(c))); err == nil {
+		p.DeptId, _ = strconv.Atoi(deptIdStr)
+	}
+	return p
+}
+
+// GetPermissionFromContext 提供非action写法数据范围约束
+func GetPermissionFromContext(c *gin.Context) *DataPermission {
+	return getPermissionFromContext(c)
+}

+ 5 - 0
common/actions/type.go

@@ -0,0 +1,5 @@
+package actions
+
+const (
+	PermissionKey = "dataPermission"
+)

+ 59 - 0
common/actions/update.go

@@ -0,0 +1,59 @@
+package actions
+
+import (
+	"Medical_OAuth/common/dto"
+	"Medical_OAuth/common/model"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+// UpdateAction 通用更新动作
+func UpdateAction(control dto.Control) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		db, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		msgID := pkg.GenerateMsgIDFromContext(c)
+		req := control.Generate()
+		//更新操作
+		err = req.Bind(c)
+		if err != nil {
+			response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败")
+			return
+		}
+		var object model.ActiveRecord
+		object, err = req.GenerateM()
+		if err != nil {
+			response.Error(c, 500, err, "模型生成失败")
+			return
+		}
+		object.SetUpdateBy(user.GetUserId(c))
+
+		//数据权限检查
+		p := GetPermissionFromContext(c)
+
+		db = db.WithContext(c).Scopes(
+			Permission(object.TableName(), p),
+		).Where(req.GetId()).Updates(object)
+		if db.Error != nil {
+			log.Errorf("MsgID[%s] Update error: %s", msgID, err)
+			response.Error(c, 500, err, "更新失败")
+			return
+		}
+		if db.RowsAffected == 0 {
+			response.Error(c, http.StatusForbidden, nil, "无权更新该数据")
+			return
+		}
+		response.OK(c, object.GetId(), "更新成功")
+		c.Next()
+	}
+}

+ 67 - 0
common/actions/view.go

@@ -0,0 +1,67 @@
+package actions
+
+import (
+	"Medical_OAuth/common/dto"
+	"Medical_OAuth/common/model"
+	"errors"
+	"gorm.io/gorm"
+	"net/http"
+
+	"github.com/gin-gonic/gin"
+
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+)
+
+// ViewAction 通用详情动作
+func ViewAction(control dto.Control, f func() interface{}) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		db, err := pkg.GetOrm(c)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		msgID := pkg.GenerateMsgIDFromContext(c)
+		//查看详情
+		req := control.Generate()
+		err = req.Bind(c)
+		if err != nil {
+			response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败")
+			return
+		}
+		var object model.ActiveRecord
+		object, err = req.GenerateM()
+		if err != nil {
+			response.Error(c, 500, err, "模型生成失败")
+			return
+		}
+
+		var rsp interface{}
+		if f != nil {
+			rsp = f()
+		} else {
+			rsp, _ = req.GenerateM()
+		}
+
+		//数据权限检查
+		p := GetPermissionFromContext(c)
+
+		err = db.Model(object).WithContext(c).Scopes(
+			Permission(object.TableName(), p),
+		).Where(req.GetId()).First(rsp).Error
+
+		if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
+			response.Error(c, http.StatusNotFound, nil, "查看对象不存在或无权查看")
+			return
+		}
+		if err != nil {
+			log.Errorf("MsgID[%s] View error: %s", msgID, err)
+			response.Error(c, 500, err, "查看失败")
+			return
+		}
+		response.OK(c, rsp, "查询成功")
+		c.Next()
+	}
+}

+ 13 - 0
common/middleware/handler/dept.go

@@ -0,0 +1,13 @@
+package handler
+
+import (
+	model2 "Medical_OAuth/common/model"
+	coreModel "gogs.baozhida.cn/zoie/OAuth-core/model"
+)
+
+type SysDept struct {
+	model2.Model
+	coreModel.Dept
+	model2.ControlBy
+	model2.ModelTime
+}