Dolphin web后台开发框架

2637309949 · · 905 次点击 · 开始浏览    置顶

# Dolphin, Go code generate Framework Dolphin是一个Golang代码生成工具, 及ERP基础架构平台, 内部提供多种基本功能, 适合k8s中构建微服务 使用Dolphin-ui作为前端与基于Dolphin构建的后台rest交互, 部分截图 <img align="center" width="400px" src="https://img-blog.csdnimg.cn/2021043013451981.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1NzEyNDM=,size_16,color_FFFFFF,t_70"> <img align="center" width="400px" src="https://img-blog.csdnimg.cn/20210430134858440.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1NzEyNDM=,size_16,color_FFFFFF,t_70"> <img align="center" width="400px" src="https://img-blog.csdnimg.cn/20210430134623869.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1NzEyNDM=,size_16,color_FFFFFF,t_70"> # Features ``` - 基于XML配置生成代码 - 基于XML配置生成DOC文档 - 基于XML配置生成SQL - 默认处理NULL空值问题 - 支持多租户分库 - 登录/退出, 或者单点登录 - 支持路由权限认证 - 快速EXCEL报表和EXCEL解析 - 支持路由缓存 - 支持数据权限控制 - 支持日子记录 - 支持RPC远程服务 - 默认生成K8s部署配置 - 支持基于数据库生成XML配置 ``` ## 可以前往github查看更多功能, 开源不易, 有兴趣就给个star吧 ^_^ https://github.com/2637309949/dolphin ## Quick start <img width="580px" src="https://img-blog.csdnimg.cn/20210430135242138.gif"/> 1. The first need [Go](https://golang.org/) installed, then you can use the below Go command to install Dolphin. ```shell $ go get -u github.com/2637309949/dolphin/cmd/dolphin ``` 2. Create project dir and run dolphin ```shell $ mkdir example && cd example && dolphin init && dolphin build && go run main.go ``` Output: ```shell time="2020/06/13 11:55:58" level=info msg="grpc listen on port:9081" time="2020/06/13 11:55:58" level=info msg="http listen on port:8082" ``` ## Directory structure > The quasi-directory structure of the project is shown below, The project structure has been simplified as a guideline, such as managing large-scale projects and recommending new sub-projects ```shell . ├── app │ ├── app.auto.go │ ├── app.go │ ├── article.go │ └── article.go.new ├── app.properties ├── doc │ └── swagger.yaml ├── go.mod ├── go.sum ├── log │ └── demo.2020071400 ├── main.go ├── model │ ├── article.auto.go │ └── article_info.auto.go ├── rpc │ ├── message.cli.go │ ├── message.go │ ├── message.go.new │ └── proto │ ├── message.pb.go │ ├── message.proto │ └── message.proto.new ├── script │ ├── apis │ │ ├── article.js │ │ └── index.js │ └── axios.js ├── sql │ ├── article │ │ ├── article_page_count.tpl │ │ └── article_page_select.tpl │ └── sqlmap │ └── article.xml ├── srv │ ├── article.go │ └── worker_hello.go ├── static │ ├── files │ │ ├── 6b7ead55-f663-4340-a594-d282d5baf753.xlsx │ │ └── 6dc88052-54e0-4aa9-a344-fb2b3c30f9b6.xlsx │ └── web │ ├── affirm.html │ └── login.html ├── util │ └── tool.go └── xml ├── application.xml ├── bean │ └── article_info.xml ├── controller │ └── article.xml ├── rpc │ └── message.xml └── table └── article.xml ``` ## CMD Command options ```shell dolphin, a cli tools for generate golang code Usage: dolphin [command] Available Commands: build Build project from xml clean Removing intermediate files help Help about any command init Initialize a empty project Flags: -h, --help help for dolphin Use "dolphin [command] --help" for more information about a command. ``` ### build The build command generates the preset function by executing the built-in Pipeline function, You can specify that only a pipeline will be executed via the @ symbol ```shell dolphin build @table xml/test ``` Existing built-in Pipeline function: | Function | Action | |----------|:-------------:| | main | create main file source | | app | create engine template source | | ctr | create controller source | | proto | create proto3 source | | srv | create server source | | model | create model source | | bean | create bean source | | auto | create register source | | tool | create tool source | | sql | create sql source, .sql to .go | | sqlmap | create table sqlmap | | oauth | create oauth h5 template | | script | create js api | | deploy | create k8s template | | doc | create swagger api doc | | table | create table from datasource | ### clean The clean command clears temporary files ```shell dolphin clean ``` ### init The init command, as stated, generates a series of initialization files ```shell mkdir demo && cd demo && dolphin init ``` ## API Examples ### dolphin-ui > An erp template that uses dolphin background support. You can find a number of ready-to-run examples at [dolphin examples repository.](https://github.com/2637309949/dolphin-ui) ## XML Label ### application > application label contain app infomation, such as name, package Example: ```xml <?xml version="1.0" encoding="utf-8" ?> <application name="demo" desc="template" packagename="demo"/> ``` application | LabelName | LabelMeaning | |----------|:-------------:| | name | required, application name | | desc | application desc | | packagename | required, application packagename | ### bean > bean, you can declare object in bean, just like spring bean. all bean and model will be placed in the model directory, so you needs another name if the conflict Example: ```xml <bean name="activity_info" desc="desc" packages="xxx" extends="$applet_activity"> <prop name="code" desc="编码" type="xx.String" /> <prop name="name" desc="名称" type="xx.String" /> </bean> ``` Generate code: ```go // Code generated by dol build. DO NOT EDIT. package model import ( "github.com/2637309949/dolphin/packages/null" ) // ArticleInfo defined 文章信息 type ArticleInfo struct { *Article // 地址 URL null.String `json:"url" xml:"url"` } ``` bean | LabelName | LabelMeaning | |----------|:-------------:| | name | bean name | | desc | bean desc | | packagename | third party package name,use "," to split | | extends | bean extends | prop | LabelName | LabelMeaning | |----------|:-------------:| | name | prop name | | desc | prop desc | | type | prop type | ### controller > controller, a collect api, you can declare api prefix Example: ```xml <controller name="activity" desc="微信活动" /> ``` controller | LabelName | LabelMeaning | |----------|:-------------:| | name | controller name | | desc | controller desc | | prefix | controller desc | ### api example > api, api func in controller. we has some built-in func such as 'add', 'delete', 'update', 'page', 'get', 'tree', or you can refined if you need. #### add ##### one ```xml <api name="add" func="add" table="sys_client" desc="添加客户端" method="post"> <param name="user" type="$sys_client" desc="客户端信息" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysClientAdd api implementation // @Summary 添加客户端 // @Tags 客户端 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param user body model.SysClient false "客户端信息" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/client/add [post] func SysClientAdd(ctx *Context) { var payload model.SysClient if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { ctx.Fail(err) return } payload.ID = null.StringFromUUID() payload.CreateTime = null.TimeFrom(time.Now().Value()) payload.Creater = null.StringFrom(ctx.GetToken().GetUserID()) payload.UpdateTime = null.TimeFrom(time.Now().Value()) payload.Updater = null.StringFrom(ctx.GetToken().GetUserID()) payload.IsDelete = null.IntFrom(0) payload.AppName = null.StringFrom(viper.GetString("app.name")) ret, err := ctx.PlatformDB.Insert(&payload) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` ##### batch > Of course, you can also specify array parameters, which will automatically generate batch added templates. ```xml <api name="batch_add" func="add" table="sys_role_menu" method="post" desc="添加角色菜单"> <param name="role_menu" type="[]$sys_role_menu" desc="角色菜单信息" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysRoleMenuBatchAdd api implementation // @Summary 添加角色菜单 // @Tags 角色菜单 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param role_menu body []model.SysRoleMenu false "角色菜单信息" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/role/menu/batch_add [post] func SysRoleMenuBatchAdd(ctx *Context) { var payload []*model.SysRoleMenu if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { logrus.Error(err) ctx.Fail(err) return } funk.ForEach(payload, func(form *model.SysRoleMenu) { form.ID = null.StringFromUUID() form.CreateTime = null.TimeFrom(time.Now().Value()) form.Creater = null.StringFrom(ctx.GetToken().GetUserID()) form.UpdateTime = null.TimeFrom(time.Now().Value()) form.Updater = null.StringFrom(ctx.GetToken().GetUserID()) form.IsDelete = null.IntFrom(0) }) payload = funk.Filter(payload, func(form *model.SysRoleMenu) bool { ext, _ := ctx.DB.Where("role_id=? and menu_id=?", form.RoleId.String, form.MenuId.String).Exist(new(model.SysRoleMenu)) return !ext }).([]*model.SysRoleMenu) ret, err := ctx.DB.Insert(&payload) if err != nil { logrus.Error(err) ctx.Fail(err) return } ctx.Success(ret) } ``` #### delete ##### one > The system default templates are soft delete logic, this is also highly recommended. If you need hard delete, please do it yourself ```xml <api name="del" func="delete" table="sys_client" desc="删除客户端" method="delete"> <param name="sys_client" type="$sys_client" desc="客户端" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysClientDel api implementation // @Summary 删除客户端 // @Tags 客户端 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param sys_client body model.SysClient false "客户端" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/client/del [delete] func SysClientDel(ctx *Context) { var payload model.SysClient if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { ctx.Fail(err) return } ret, err := ctx.PlatformDB.In("id", payload.ID.String).Update(&model.SysClient{ UpdateTime: null.TimeFrom(time.Now().Value()), Updater: null.StringFrom(ctx.GetToken().GetUserID()), IsDelete: null.IntFrom(1), }) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` ##### batch > Of course, you can also specify array parameters, which will automatically generate batch deleted templates. ```xml <api name="batch_del" func="delete" table="sys_optionset" method="delete" desc="删除字典"> <param name="user" type="[]$sys_optionset" desc="字典" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysOptionsetBatchDel api implementation // @Summary 删除字典 // @Tags 字典 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param user body []model.SysOptionset false "字典" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/optionset/batch_del [delete] func SysOptionsetBatchDel(ctx *Context) { var payload []*model.SysOptionset var ids []string if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { logrus.Error(err) ctx.Fail(err) return } funk.ForEach(payload, func(form model.SysOptionset) { ids = append(ids, form.ID.String) }) ret, err := ctx.DB.In("id", ids).Update(&model.SysOptionset{ UpdateTime: null.TimeFrom(time.Now().Value()), Updater: null.StringFrom(ctx.GetToken().GetUserID()), IsDelete: null.IntFrom(1), }) if err != nil { logrus.Error(err) ctx.Fail(err) return } ctx.Success(ret) } ``` #### update ##### one > The entire model field definition is null type, so don't worry about the default value types, as long as you reference packages/ xormplus (native xorm has been modified to fit null packages) ```xml <api name="update" func="update" table="sys_client" desc="更新客户端" method="put"> <param name="user" type="$sys_role" desc="客户端信息" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysClientUpdate api implementation // @Summary 更新客户端 // @Tags 客户端 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param user body model.SysRole false "客户端信息" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/client/update [put] func SysClientUpdate(ctx *Context) { var payload model.SysRole if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { ctx.Fail(err) return } payload.Updater = null.StringFrom(ctx.GetToken().GetUserID()) payload.UpdateTime = null.TimeFrom(time.Now().Value()) ret, err := ctx.PlatformDB.ID(payload.ID).Update(&payload) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` ##### batch > Of course, you can also specify array parameters, which will automatically generate batch updated templates. ```xml <api name="batch_update" func="update" table="article" desc="更新文章" method="put"> <param name="article" type="[]$article" desc="文章信息" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // ArticleBatchUpdate api implementation // @Summary 更新文章 // @Tags 文章 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param article body []model.Article false "文章信息" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/article/batch_update [put] func ArticleBatchUpdate(ctx *Context) { var payload []*model.Article var err error var ret []int64 var r int64 if err = ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { logrus.Error(err) ctx.Fail(err) return } s := ctx.DB.NewSession() s.Begin() defer s.Close() funk.ForEach(payload, func(form model.Article) { form.Updater = null.StringFrom(ctx.GetToken().GetUserID()) form.UpdateTime = null.TimeFrom(time.Now().Value()) r, err = s.ID(form.ID.String).Update(&form) ret = append(ret, r) }) if err != nil { s.Rollback() logrus.Error(err) ctx.Fail(err) return } ctx.Success(ret) } ``` #### page > The most basic paging interface template is also supported by default. ```xml <api name="page" func="page" table="sys_client" desc="客户端分页查询" method="get"> <param name="page" type="int" value="1" desc="页码"/> <param name="size" type="int" value="10" desc="单页数"/> <param name="app_name" type="string" desc="所属应用"/> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysClientPage api implementation // @Summary 客户端分页查询 // @Tags 客户端 // @Param Authorization header string false "认证令牌" // @Param page query int false "页码" // @Param size query int false "单页数" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/client/page [get] func SysClientPage(ctx *Context) { q := ctx.TypeQuery() q.SetInt("page", 1) q.SetInt("size", 10) q.SetString("app_name", viper.GetString("app.name")) q.SetTags() ret, err := ctx.PageSearch(ctx.PlatformDB, "sys_client", "page", "sys_client", q.Value()) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` #### tree > Tree structure is also a common algorithm. The framework integrates a TreeSearch interface for tree retrieval. ```xml <api name="page" func="page" table="sys_menu" desc="菜单分页查询" method="get"> <param name="page" type="int" value="1" desc="页码"/> <param name="size" type="int" value="10" desc="单页数"/> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysMenuTree api implementation // @Summary 菜单树形结构 // @Tags 菜单 // @Param Authorization header string false "认证令牌" // @Failure 403 {object} model.Fail // @Router /api/sys/menu/tree [get] func SysMenuTree(ctx *Context) { q := ctx.TypeQuery() q.SetString("name") q.SetRule("sys_menu_tree") q.SetTags() ret, err := ctx.TreeSearch(ctx.DB, "sys_menu", "tree", "sys_menu", q.Value()) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` > TreeSearch: > Detailed instructions can be found in the TreeSearch source code ```go // platform/app/app.ctx.go#TreeSearch func (ctx *Context) TreeSearch(db *xorm.Engine, controller, api, table string, q map[string]interface{}) (interface{}, error) ``` #### one > Find a single piece of data by unique key. ```xml <api name="get" func="one" table="sys_client" desc="获取客户端信息" method="get"> <param name="id" type="string" desc="客户端id" /> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // SysClientGet api implementation // @Summary 获取客户端信息 // @Tags 客户端 // @Param Authorization header string false "认证令牌" // @Param id query string false "客户端id" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/sys/client/get [get] func SysClientGet(ctx *Context) { var entity model.SysClient id := ctx.Query("id") _, err := ctx.PlatformDB.ID(id).Get(&entity) if err != nil { ctx.Fail(err) return } ctx.Success(entity) } ``` #### other > In addition to the default interface, custom interfaces are also supported. ```xml <api name="payment" method="post" desc="文章付费"> <param name="article" type="$article_info" desc="文章"/> <return> <success type="$success"/> <failure type="$fail"/> </return> </api> ``` Generate code: ```go // ArticlePayment api implementation // @Summary 文章分页查询 // @Tags 文章 // @Accept application/json // @Param Authorization header string false "认证令牌" // @Param article body model.ArticleInfo false "文章" // @Failure 403 {object} model.Fail // @Success 200 {object} model.Success // @Failure 500 {object} model.Fail // @Router /api/article/payment [post] func ArticlePayment(ctx *Context) { var payload model.ArticleInfo if err := ctx.ShouldBindBodyWith(&payload, binding.JSON); err != nil { ctx.Fail(err) return } ret, err := srv.ArticleAction(payload) if err != nil { ctx.Fail(err) return } ctx.Success(ret) } ``` 可以前往github查看更多功能, 有兴趣就给个star吧 ^_^ https://github.com/2637309949/dolphin

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

905 次点击  ∙  2 赞  
加入收藏 微博
2 回复  |  直到 2021-05-01 09:02:35
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传