时间大约是三年前,当时我所在的团队是最早接触 PHP 的,而团队其他成员都是用 Java。由于某些项目原因,我们决定全面转向使用 GO 进行开发。在当时,我们并不想花太多时间去折腾 REACT 和 VUE 这些前端框架,我们更倾向于使用 jQuery 来开发,因为我们喜欢它的快感。于是我想到了一个基于 ThinkPHP 和 Bootstrap 的快速后台开发框架,叫做 FastAdmin。我之前使用过它做过项目,发现速度很快,而且学习成本也很低。于是,我们决定将原本用 ThinkPHP 写的后端代码用 Goframe 重新实现了一遍,并且使用 FastAdmin 的前端规范和框架。我们内部把它叫做 FastGoAdmin。原本我想花点时间整理一下代码,将业务逻辑和框架分离,然后开源分享出来。但由于一直忙于产品开发,没有时间进行整理。今天我先在这里留个记录,如果有很多人关注的话,我就会花时间整理代码并开源出来。另外,我也要感谢 FastAdmin 的作者,他提供了一个简单易用的设计思想。

FastGoAdmin 框架支持一键生成 CRUD,根据数据表可以自动产生控制器、模型、视图、JS、语言包、菜单、回收站等。

FastGoAdmin 的目标是为开发者提供一个能够单独完成前后端开发的能力,约定优于配置,配置优于开发,开发优于重复。

主要特性包括:

  • 基于 Auth 验证的权限管理系统
  • 一键生成 CRUD
  • 支持无限级父子级权限继承,父级管理员可以任意增删改子级管理员并设置权限
  • 支持单管理员多角色
  • 支持用户部门管理
  • 支持数据权限,可以对管理员管辖的数据进行权限限制
  • 有插件应用市场,可以进行插件化开发,实现即插即用的应用
  • 支持多语言,内置简体中文、繁体中文和英文
  • 支持多模块的开发

我们修改后的功能界面

我们用goframe重写了FastAdmin的后端,原来这么爽_开发者

我们用goframe重写了FastAdmin的后端,原来这么爽_go语言_02

我们把详细页面修改了一下

我们用goframe重写了FastAdmin的后端,原来这么爽_数据_03

我们用goframe重写了FastAdmin的后端,原来这么爽_go语言_04

添加了插件管理功能

下面的部份代码

我们用goframe重写了FastAdmin的后端,原来这么爽_数据_05

//通用的查询、新增、修改、删除、查看 功能,由代码产生后自带CURD界面
func (a *openAuth) List(ctx context.Context, req *libModel.ApiPageReq) (total int, list []*entity.OpenAuth, err error) {
	boAttachment := &libService.BackendOption{Model: dao.OpenAuth.Table(), Ctx: ctx, DataLimit: true}
	total, err = libService.NewBackend(boAttachment).Index(req, &list)
	return
}

func (a *openAuth) Add(ctx context.Context, req *model.OpenAuthRow) (res *libModel.AdminApiRes, err error) {
	id, err := libService.NewBackend(&libService.BackendOption{Model: dao.OpenAuth.Table(), Ctx: ctx, DataLimit: true}).Add()
	if err != nil {
		return nil, gerror.New("添加失败")
	}
	res = &libModel.AdminApiRes{
		Count: 1,
		Id:    id,
	}
	return
}

func (a *openAuth) Edit(ctx context.Context, req *model.OpenAuthRow, id uint64) (res *libModel.AdminApiRes, err error) {
	count, err := libService.NewBackend(&libService.BackendOption{Model: dao.OpenAuth.Table(), Ctx: ctx, DataLimit: true}).Edit(dao.OpenAuth.Columns().Id, id)
	if err != nil {
		return nil, gerror.New("修改失败")
	}
	res = &libModel.AdminApiRes{
		Count: count,
	}
	return
}

func (a *openAuth) Del(ctx context.Context, req *libModel.ApiDelReq) (res *libModel.AdminApiRes, err error) {
	count, err := libService.NewBackend(&libService.BackendOption{Model: dao.OpenAuth.Table(), Ctx: ctx, DataLimit: true}).Del(dao.OpenAuth.Columns().Id, gstr.Split(req.Ids, ","))
	if err != nil {
		return nil, gerror.New("删除失败")
	}
	res = &libModel.AdminApiRes{
		Count: count,
	}
	return
}

func (a *openAuth) GetDetailById(ctx context.Context, id uint64) (row *entity.OpenAuth, err error) {
	err = libService.NewBackend(&libService.BackendOption{Model: dao.OpenAuth.Table(), Ctx: ctx, DataLimit: true}).GetDetailById(id, &row)
	return
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.