{"id":13600278,"url":"https://github.com/snowlyg/iris-admin","last_synced_at":"2025-05-14T23:07:40.792Z","repository":{"id":39866115,"uuid":"159309090","full_name":"snowlyg/iris-admin","owner":"snowlyg","description":"Web admin  for go framework [gin/iris]","archived":false,"fork":false,"pushed_at":"2025-05-09T10:02:59.000Z","size":6536,"stargazers_count":691,"open_issues_count":2,"forks_count":166,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-09T10:42:19.773Z","etag":null,"topics":["apidoc","casbin","docker","docker-compose","excel","gin","go","golang","gorm","httptest","iris","iris-api","redis"],"latest_commit_sha":null,"homepage":"https://github.com/snowlyg/iris-admin","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snowlyg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-11-27T09:23:51.000Z","updated_at":"2025-05-01T05:02:17.000Z","dependencies_parsed_at":"2023-02-10T03:01:36.216Z","dependency_job_id":"61cf850c-5ae5-4d66-9c52-5ecd5d48fa28","html_url":"https://github.com/snowlyg/iris-admin","commit_stats":{"total_commits":848,"total_committers":10,"mean_commits":84.8,"dds":"0.29127358490566035","last_synced_commit":"6e57f32651791c7c49976f5b4054f3d056229c5b"},"previous_names":["snowlyg/irisadminapi","snowlyg/irisapiproject"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowlyg%2Firis-admin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowlyg%2Firis-admin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowlyg%2Firis-admin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowlyg%2Firis-admin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snowlyg","download_url":"https://codeload.github.com/snowlyg/iris-admin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254243362,"owners_count":22038046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apidoc","casbin","docker","docker-compose","excel","gin","go","golang","gorm","httptest","iris","iris-api","redis"],"created_at":"2024-08-01T18:00:34.312Z","updated_at":"2025-05-14T23:07:35.783Z","avatar_url":"https://github.com/snowlyg.png","language":"Go","funding_links":["https://paypal.me/snowlyg?country.x=C2\u0026locale.x=zh_XC"],"categories":["Go"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eIrisAdmin\u003c/h1\u003e\n\n[![Build Status](https://app.travis-ci.com/snowlyg/iris-admin.svg?branch=master)](https://app.travis-ci.com/snowlyg/iris-admin)\n[![LICENSE](https://img.shields.io/github/license/snowlyg/iris-admin)](https://github.com/snowlyg/iris-admin/blob/master/LICENSE)\n[![go doc](https://godoc.org/github.com/snowlyg/iris-admin?status.svg)](https://godoc.org/github.com/snowlyg/iris-admin)\n[![go report](https://goreportcard.com/badge/github.com/snowlyg/iris-admin)](https://goreportcard.com/badge/github.com/snowlyg/iris-admin)\n[![Build Status](https://codecov.io/gh/snowlyg/iris-admin/branch/master/graph/badge.svg)](https://codecov.io/gh/snowlyg/iris-admin)\n\n简体中文 | [English](./README_EN.md)\n\n#### 项目地址\n\n[GITHUB](https://github.com/snowlyg/iris-admin)\n\n\u003e 简单项目仅供学习，欢迎指点！\n\n#### 相关文档\n\n- [IRIS-ADMIN-DOC](https://doc.snowlyg.com)\n- [IRIS V12 中文文档](https://github.com/snowlyg/iris/wiki)\n- [godoc](https://pkg.go.dev/github.com/snowlyg/iris-admin?utm_source=godoc)\n\n\u003ca href=\"https://gitter.im/iris-go-tenancy/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\"\u003e\u003cimg src=\"https://badges.gitter.im/iris-go-tenancy/community.svg\" alt=\"e9939a7e92f32337871feb22e06bd05a.jpeg\" border=\"0\" width=120 /\u003e\u003c/a\u003e\n\u003ca href=\"https://discord.gg/pytCGMSBgA\"\u003e \u003cimg src=\"https://www.svgrepo.com/show/353655/discord-icon.svg\" alt=\"e9939a7e92f32337871feb22e06bd05a.jpeg\" border=\"0\" width=30 /\u003e\u003c/a\u003e\n\n#### iris 学习记录分享\n\n- [Iris-go 项目登陆 API 构建细节实现过程](https://snowlyg.github.io/iris-go-api-1/)\n\n- [iris + casbin 从陌生到学会使用的过程](https://snowlyg.github.io/iris-go-api-2/)\n\n---\n\n#### 简单使用\n\n- 获取依赖包,注意必须带上 `master` 版本\n\n```sh\n go get github.com/snowlyg/iris-admin@master\n```\n\n#### 项目介绍\n\n##### 项目由多个插件构成,每个插件有不同的功能\n\n- [viper_server]\n  - 插件配置初始化,并生成本地配置文件\n  - 使用 [github.com/spf13/viper](https://github.com/spf13/viper) 第三方包实现\n  - 需要实现 `func getViperConfig() viper_server.ViperConfig` 方法\n\n```go\npackage cache\n\nimport (\n  \"fmt\"\n\n  \"github.com/fsnotify/fsnotify\"\n  \"github.com/snowlyg/iris-admin/g\"\n  \"github.com/snowlyg/iris-admin/server/viper_server\"\n  \"github.com/spf13/viper\"\n)\n\nvar CONFIG Redis\n\ntype Redis struct {\n  DB       int    `mapstructure:\"db\" json:\"db\" yaml:\"db\"`\n  Addr     string `mapstructure:\"addr\" json:\"addr\" yaml:\"addr\"`\n  Password string `mapstructure:\"password\" json:\"password\" yaml:\"password\"`\n  PoolSize int    `mapstructure:\"pool-size\" json:\"poolSize\" yaml:\"pool-size\"`\n}\n\n// getViperConfig get viper config\nfunc getViperConfig() viper_server.ViperConfig {\n  configName := \"redis\"\n  db := fmt.Sprintf(\"%d\", CONFIG.DB)\n  poolSize := fmt.Sprintf(\"%d\", CONFIG.PoolSize)\n  return viper_server.ViperConfig{\n    Directory: g.ConfigDir,\n    Name:      configName,\n    Type:      g.ConfigType,\n    Watch: func(vi *viper.Viper) error {\n      if err := vi.Unmarshal(\u0026CONFIG); err != nil {\n        return fmt.Errorf(\"get Unarshal error: %v\", err)\n      }\n      // watch config file change\n      vi.SetConfigName(configName)\n      return nil\n    },\n    //\n    Default: []byte(`\ndb: ` + db + `\naddr: \"` + CONFIG.Addr + `\"\npassword: \"` + CONFIG.Password + `\"\npool-size: ` + poolSize),\n  }\n}\n```\n\n- [zap_server]\n  - 插件日志记录\n  - 使用 [go.uber.org/zap](https://pkg.go.dev/go.uber.org/zap) 第三方包实现\n  - 通过全局变量 `zap_server.ZAPLOG` 记录对应级别的日志\n\n```go\n  zap_server.ZAPLOG.Info(\"注册数据表错误\", zap.Any(\"err\", err))\n  zap_server.ZAPLOG.Debug(\"注册数据表错误\", zap.Any(\"err\", err))\n  zap_server.ZAPLOG.Error(\"注册数据表错误\", zap.Any(\"err\", err))\n  ...\n```\n\n- [database]\n  - 数据插件 [目前仅支持 mysql]\n  - 使用 [gorm.io/gorm](https://github.com/go-gorm/gorm) 第三方包实现\n  - 通过单列 `database.Instance()` 操作数据\n\n```go\n  database.Instance().Model(\u0026User{}).Where(\"name = ?\",\"name\").Find(\u0026user)\n  ...\n```\n\n- [casbin]\n  - 权限控制管理插件\n  - 使用 [casbin](github.com/casbin/casbin/v2) 第三方包实现\n  - 并通过 `casbin.Instance()` 使用中间件,实现接口权限认证\n\n```go\n\t_, err := casbin.Instance().AddRoleForUser(\"1\", \"999\")\n\tuids, err := casbin.Instance().GetRolesForUser(\"1\")\n\t_, err := casbin.Instance().RemoveFilteredPolicy(v, p...)\n  ...\n```\n\n- [cache]\n  - 缓存驱动插件\n  - 使用 [github.com/go-redis/redis](https://github.com/go-redis/redis) 第三方包实现\n  - 通过单列 `cache.Instance()` 操作数据\n\n```go\n  \terr := cache.Instance().Set(context.Background(), \"key\", \"value\", expiration).Err()\n    cache.Instance().Del(context.Background(), \"key\").Result()\n    cache.Instance().Get(context.Background(), \"key\")\n  ...\n```\n\n- [operation]\n\n  - 系统操作日志插件\n  - 并通过 `index.Use(operation.OperationRecord())` 使用中间件,实现接口自动生成操作日志\n\n- [cron_server]\n  - 任务插件\n  - 使用 [robfig/cron](https://github.com/robfig/cron) 第三方包实现\n  - 通过单列 `cron_server.CronInstance()` 操作数据\n\n```go\n  cron_server.CronInstance().AddJob(\"@every 1m\",YourJob)\n  // 或者\n  cron_server.CronInstance().AddFunc(\"@every 1m\",YourFunc)\n  ...\n```\n\n- [web]\n  - web_iris [Go-Iris](https://github.com/kataras/iris) web 框架插件\n  - web_gin [Go-gin web](https://github.com/gin-gonic/gin) web 框架插件\n  - web 框架插件需要实现 `type WebFunc interface {}` 接口\n\n```go\ntype WebBaseFunc interface {\n  AddWebStatic(staticAbsPath, webPrefix string, paths ...string)\n  AddUploadStatic(staticAbsPath, webPrefix string)\n  InitRouter() error\n  Run()\n}\n\n// WebFunc 框架插件接口\n// - GetTestClient 测试客户端\n// - GetTestLogin 测试登录\n// - AddWebStatic 添加静态页面\n// - AddUploadStatic 上传文件路径\n// - Run 启动\ntype WebFunc interface {\n  WebBaseFunc\n}\n```\n\n- [mongodb]\n  - mongodb\n  - 使用 [mongodb](https://www.mongodb.com/) 第三方包实现.\n\n---\n\n#### 数据初始化\n\n##### 简单初始化\n\n- 使用原生方法 `AutoMigrate()` 自动迁移初始化数据表\n\n```go\npackage main\n\nimport (\n  \"github.com/snowlyg/iris-admin/server/web\"\n  \"github.com/snowlyg/iris-admin/server/web/web_iris\"\n  \"github.com/snowlyg/iris-admin-rbac/iris/perm\"\n  \"github.com/snowlyg/iris-admin-rbac/iris/role\"\n  \"github.com/snowlyg/iris-admin/server/database\"\n  \"github.com/snowlyg/iris-admin/server/operation\"\n)\n\nfunc main() {\n    database.Instance().AutoMigrate(\u0026perm.Permission{},\u0026role.Role{},\u0026user.User{},\u0026operation.Oplog{})\n}\n```\n\n##### 自定义迁移工具初始化\n\n- 使用 `gormigrate` 第三方依赖包实现数据的迁移控制，方便后续的升级和开发\n- 使用方法详情见 [iris-admin-cmd](https://github.com/snowlyg/iris-admin-example/blob/main/iris/cmd/main.go)\n\n---\n\n- 添加 main.go 文件\n\n```go\npackage main\n\nimport (\n  \"github.com/snowlyg/iris-admin/server/web\"\n  \"github.com/snowlyg/iris-admin/server/web/web_iris\"\n)\n\nfunc main() {\n  wi := web_iris.Init()\n  web.Start(wi)\n}\n```\n\n#### 启动项目\n\n- 第一次启动项目后,配置文件会自动生成到 `config` 目录下.\n- 同时会生成一个 `rbac_model.conf` 文件到项目根目录,该文件用于 casbin 权鉴的规则.\n\n```sh\ngo run main.go\n```\n\n#### 添加模块\n\n- 如果需要权鉴管理，可以使用 [iris-admin-rbac](https://github.com/snowlyg/iris-admin-rbac) 项目快速集成权鉴功能\n- 可以使用 AddModule() 增加其他 admin 模块\n\n```go\npackage main\n\nimport (\n  rbac \"github.com/snowlyg/iris-admin-rbac/iris\"\n  \"github.com/snowlyg/iris-admin/server/web\"\n  \"github.com/snowlyg/iris-admin/server/web/web_iris\"\n)\n\nfunc main() {\n  wi := web_iris.Init()\n  rbacParty := web_iris.Party{\n    Perfix:    \"/api/v1\",\n    PartyFunc: rbac.Party(),\n  }\n  wi.AddModule(rbacParty)\n  web.Start(web_iris.Init())\n}\n```\n\n#### 设置静态文件路径\n\n- 已经默认内置了一个静态文件访问路径\n- 静态文件将会上传到 `/static/upload` 目录\n- 可以修改配置项 `static-path` 修改默认目录\n\n-\n\n```yaml\nsystem:\n  addr: \"127.0.0.1:8085\"\n  db-type: \"\"\n  level: debug\n  static-prefix: /upload\n  time-format: \"2006-01-02 15:04:05\"\n  web-prefix: /admin\n  web-path: ./dist\n```\n\n#### 配合前端使用\n\n- 编译前端页面默认 `dist` 目录\n- 可以修改配置项 `web-path` 修改默认目录\n\n-\n\n```go\npackage main\n\nimport (\n  \"github.com/kataras/iris/v12\"\n  \"github.com/snowlyg/iris-admin/server/web\"\n)\n\nfunc main() {\n  webServer := web_iris.Init()\n  wi.AddUploadStatic(\"/upload\", \"/var/static\")\n  wi.AddWebStatic(\"/\", \"/var/static\")\n  webServer.Run()\n}\n```\n\n- 前端页面参考/借用：【前端只简单实现预览效果】\n- [gin-vue-admin](https://github.com/flipped-aurora/gin-vue-admin/tree/master/web)\n- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)\n\n#### 简单用例\n\n- [iris](https://github.com/snowlyg/iris-admin-example/tree/main/iris)\n- [gin](https://github.com/snowlyg/iris-admin-example/tree/main/gin)\n\n#### RBAC\n\n- [iris-admin-rbac](https://github.com/snowlyg/iris-admin-rbac)\n\n#### 接口单元测试和接口文档\n\n- 测试前,需要设置 `mysqlPwd`, `mysqlAddr` 系统环境变量，运行测试实例的时候将会使用到它们。\n- 测试使用依赖库 [helper/tests](https://github.com/snowlyg/helper/tree/main/tests) 是基于 [httpexpect/v2](https://github.com/gavv/httpexpect) 的简单封装\n- [接口单元测试例子](https://github.com/snowlyg/iris-admin-rbac/tree/main/iris/perm/tests)\n- [接口单元测试例子](https://github.com/snowlyg/iris-admin-rbac/tree/main/gin/authority/test)\n\n接口单元测试需要新建 `main_test.go` 文件,该文件定义了单元测试的一些通用基础步骤：\n**_建议采用 docker 部署 mysql,否则测试错误失败后会有大量测试数据遗留_**\n\n- 1.测试数据库的数据库的创建和摧毁\n- 2.数据表的新建和表数据的填充\n- 3. `PartyFunc` , `SeedFunc` 方法需要根据对应的测试模块自定义\n     内容如下所示:\n\n**_main_test.go_**\n\n```go\npackage test\n\nimport (\n  \"os\"\n  \"testing\"\n\n  \"github.com/snowlyg/httptest\"\n  rbac \"github.com/snowlyg/iris-admin-rbac/gin\"\n  \"github.com/snowlyg/iris-admin/server/web/common\"\n  \"github.com/snowlyg/iris-admin/server/web/web_gin\"\n)\n\nvar TestServer *web_gin.WebServer\nvar TestClient *httptest.Client\n\nfunc TestMain(m *testing.M) {\n\n  var uuid string\n  uuid, TestServer = common.BeforeTestMainGin(rbac.PartyFunc, rbac.SeedFunc)\n  code := m.Run()\n  common.AfterTestMain(uuid, true)\n\n  os.Exit(code)\n}\n\n```\n\n**_index_test.go_**\n\n```go\npackage test\n\nimport (\n  \"fmt\"\n  \"net/http\"\n  \"path/filepath\"\n  \"testing\"\n\n  \"github.com/snowlyg/helper/str\"\n  \"github.com/snowlyg/httptest\"\n  rbac \"github.com/snowlyg/iris-admin-rbac/gin\"\n  \"github.com/snowlyg/iris-admin/g\"\n  \"github.com/snowlyg/iris-admin/server/web\"\n  \"github.com/snowlyg/iris-admin/server/web/web_gin/response\"\n)\n\nvar (\n  url = \"/api/v1/admin\"\n)\n\nfunc TestList(t *testing.T) {\n  TestClient = httptest.Instance(t, str.Join(\"http://\", web.CONFIG.System.Addr), TestServer.GetEngine())\n  TestClient.Login(rbac.LoginUrl, nil)\n  if TestClient == nil {\n    return\n  }\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n    {Key: \"data\", Value: httptest.Responses{\n      {Key: \"pageSize\", Value: 10},\n      {Key: \"page\", Value: 1},\n      {Key: \"list\", Value: []httptest.Responses{\n        {\n          {Key: \"id\", Value: 1, Type: \"ge\"},\n          {Key: \"nickName\", Value: \"超级管理员\"},\n          {Key: \"username\", Value: \"admin\"},\n          {Key: \"headerImg\", Value: \"http://xxxx/head.png\"},\n          {Key: \"status\", Value: g.StatusTrue},\n          {Key: \"isShow\", Value: g.StatusFalse},\n          {Key: \"phone\", Value: \"13800138000\"},\n          {Key: \"email\", Value: \"admin@admin.com\"},\n          {Key: \"authorities\", Value: []string{\"超级管理员\"}},\n          {Key: \"updatedAt\", Value: \"\", Type: \"notempty\"},\n          {Key: \"createdAt\", Value: \"\", Type: \"notempty\"},\n        },\n      }},\n      {Key: \"total\", Value: 0, Type: \"ge\"},\n    }},\n  }\n  TestClient.GET(fmt.Sprintf(\"%s/getAll\", url), pageKeys, httptest.RequestParams)\n}\n\nfunc TestCreate(t *testing.T) {\n  TestClient = httptest.Instance(t, str.Join(\"http://\", web.CONFIG.System.Addr), TestServer.GetEngine())\n  TestClient.Login(rbac.LoginUrl, nil)\n  if TestClient == nil {\n    return\n  }\n\n  data := map[string]interface{}{\n    \"nickName\":     \"测试名称\",\n    \"username\":     \"create_test_username\",\n    \"authorityIds\": []uint{web.AdminAuthorityId},\n    \"email\":        \"get@admin.com\",\n    \"phone\":        \"13800138001\",\n    \"password\":     \"123456\",\n  }\n  id := Create(TestClient, data)\n  if id == 0 {\n    t.Fatalf(\"测试添加用户失败 id=%d\", id)\n  }\n  defer Delete(TestClient, id)\n}\n\nfunc TestUpdate(t *testing.T) {\n\n  TestClient = httptest.Instance(t, str.Join(\"http://\", web.CONFIG.System.Addr), TestServer.GetEngine())\n  TestClient.Login(rbac.LoginUrl, nil)\n  if TestClient == nil {\n    return\n  }\n  data := map[string]interface{}{\n    \"nickName\":     \"测试名称\",\n    \"username\":     \"create_test_username_for_update\",\n    \"authorityIds\": []uint{web.AdminAuthorityId},\n    \"email\":        \"get@admin.com\",\n    \"phone\":        \"13800138001\",\n    \"password\":     \"123456\",\n  }\n  id := Create(TestClient, data)\n  if id == 0 {\n    t.Fatalf(\"测试添加用户失败 id=%d\", id)\n  }\n  defer Delete(TestClient, id)\n\n  update := map[string]interface{}{\n    \"nickName\": \"测试名称\",\n    \"email\":    \"get@admin.com\",\n    \"phone\":    \"13800138003\",\n    \"password\": \"123456\",\n  }\n\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n  }\n  TestClient.PUT(fmt.Sprintf(\"%s/updateAdmin/%d\", url, id), pageKeys, update)\n}\n\nfunc TestGetById(t *testing.T) {\n  TestClient = httptest.Instance(t, str.Join(\"http://\", web.CONFIG.System.Addr), TestServer.GetEngine())\n  TestClient.Login(rbac.LoginUrl, nil)\n  if TestClient == nil {\n    return\n  }\n  data := map[string]interface{}{\n    \"nickName\":     \"测试名称\",\n    \"username\":     \"create_test_username_for_get\",\n    \"email\":        \"get@admin.com\",\n    \"phone\":        \"13800138001\",\n    \"authorityIds\": []uint{web.AdminAuthorityId},\n    \"password\":     \"123456\",\n  }\n  id := Create(TestClient, data)\n  if id == 0 {\n    t.Fatalf(\"测试添加用户失败 id=%d\", id)\n  }\n  defer Delete(TestClient, id)\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n    {Key: \"data\", Value: httptest.Responses{\n      {Key: \"id\", Value: 1, Type: \"ge\"},\n      {Key: \"nickName\", Value: data[\"nickName\"].(string)},\n      {Key: \"username\", Value: data[\"username\"].(string)},\n      {Key: \"status\", Value: g.StatusTrue},\n      {Key: \"email\", Value: data[\"email\"].(string)},\n      {Key: \"phone\", Value: data[\"phone\"].(string)},\n      {Key: \"isShow\", Value: g.StatusTrue},\n      {Key: \"headerImg\", Value: \"http://xxxx/head.png\"},\n      {Key: \"updatedAt\", Value: \"\", Type: \"notempty\"},\n      {Key: \"createdAt\", Value: \"\", Type: \"notempty\"},\n      {Key: \"createdAt\", Value: \"\", Type: \"notempty\"},\n      {Key: \"authorities\", Value: []string{\"超级管理员\"}},\n    },\n    },\n  }\n  TestClient.GET(fmt.Sprintf(\"%s/getAdmin/%d\", url, id), pageKeys)\n}\n\nfunc TestChangeAvatar(t *testing.T) {\n  TestClient = httptest.Instance(t, str.Join(\"http://\", web.CONFIG.System.Addr), TestServer.GetEngine())\n  TestClient.Login(rbac.LoginUrl, nil)\n  if TestClient == nil {\n    return\n  }\n  data := map[string]interface{}{\n    \"headerImg\": \"/avatar.png\",\n  }\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n  }\n  TestClient.POST(fmt.Sprintf(\"%s/changeAvatar\", url), pageKeys, data)\n\n  profile := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n    {Key: \"data\", Value: httptest.Responses{\n      {Key: \"id\", Value: 1, Type: \"ge\"},\n      {Key: \"nickName\", Value: \"超级管理员\"},\n      {Key: \"username\", Value: \"admin\"},\n      {Key: \"headerImg\", Value: filepath.ToSlash(web.ToStaticUrl(\"/avatar.png\"))},\n      {Key: \"status\", Value: g.StatusTrue},\n      {Key: \"isShow\", Value: g.StatusFalse},\n      {Key: \"phone\", Value: \"13800138000\"},\n      {Key: \"email\", Value: \"admin@admin.com\"},\n      {Key: \"authorities\", Value: []string{\"超级管理员\"}},\n      {Key: \"updatedAt\", Value: \"\", Type: \"notempty\"},\n      {Key: \"createdAt\", Value: \"\", Type: \"notempty\"},\n    },\n    },\n  }\n  TestClient.GET(fmt.Sprintf(\"%s/profile\", url), profile)\n}\n\nfunc Create(TestClient *httptest.Client, data map[string]interface{}) uint {\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n    {Key: \"data\", Value: httptest.Responses{\n      {Key: \"id\", Value: 1, Type: \"ge\"},\n    },\n    },\n  }\n  return TestClient.POST(fmt.Sprintf(\"%s/createAdmin\", url), pageKeys, data).GetId()\n}\n\nfunc Delete(TestClient *httptest.Client, id uint) {\n  pageKeys := httptest.Responses{\n    {Key: \"status\", Value: http.StatusOK},\n    {Key: \"message\", Value: response.ResponseOkMessage},\n  }\n  TestClient.DELETE(fmt.Sprintf(\"%s/deleteAdmin/%d\", url, id), pageKeys)\n}\n\n```\n\n## 🔋 JetBrains 开源证书支持\n\n[JetBrains](https://www.jetbrains.com/?from=iris-admin) 对本项目的支持。\n\n\u003ca href=\"https://www.jetbrains.com/?from=iris-admin\" target=\"_blank\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/snowlyg/illustrations/master/jetbrains/jetbrains-variant-4.png\" width=\"230\" align=\"middle\"/\u003e\u003c/a\u003e\n\n#### 打赏\n\n\u003e 您的打赏将用于支付网站运行，会在项目介绍中特别鸣谢您\n\n\u003cdiv\u003e\n\t\u003cimg src=\"https://ice.frostsky.com/2023/09/19/469c2727cb1a4f9cc0d819a18059c7ab.jpeg\" alt=\"469c2727cb1a4f9cc0d819a18059c7ab.jpeg\" border=\"0\" width=150 /\u003e\n \t\u003cimg src=\"https://ice.frostsky.com/2023/09/19/e9939a7e92f32337871feb22e06bd05a.jpeg\" alt=\"e9939a7e92f32337871feb22e06bd05a.jpeg\" border=\"0\" width=150 /\u003e\n\u003c/div\u003e\n\n- [为爱发电](https://afdian.net/@snowlyg/plan)\n- [donating](https://paypal.me/snowlyg?country.x=C2\u0026locale.x=zh_XC)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowlyg%2Firis-admin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnowlyg%2Firis-admin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowlyg%2Firis-admin/lists"}