jack il y a 2 mois
commit
89d9807ee5
62 fichiers modifiés avec 1240 ajouts et 0 suppressions
  1. 1 0
      .gitattributes
  2. 19 0
      .gitignore
  3. 6 0
      Makefile
  4. 4 0
      README.MD
  5. 17 0
      api/account/account.go
  6. 17 0
      api/account/v1/account.go
  7. 18 0
      api/users/users.go
  8. 24 0
      api/users/v1/users.go
  9. 26 0
      api/words/v1/words.go
  10. 41 0
      go.mod
  11. 112 0
      go.sum
  12. 7 0
      hack/config.yaml
  13. 19 0
      hack/hack-cli.mk
  14. 75 0
      hack/hack.mk
  15. 37 0
      internal/cmd/cmd.go
  16. 5 0
      internal/consts/consts.go
  17. 6 0
      internal/controller/account/account.go
  18. 20 0
      internal/controller/account/account_new.go
  19. 20 0
      internal/controller/account/account_v1_info.go
  20. 6 0
      internal/controller/users/users.go
  21. 20 0
      internal/controller/users/users_new.go
  22. 15 0
      internal/controller/users/users_v1_login.go
  23. 17 0
      internal/controller/users/users_v1_register.go
  24. 0 0
      internal/dao/.gitkeep
  25. 83 0
      internal/dao/internal/users.go
  26. 91 0
      internal/dao/internal/words.go
  27. 27 0
      internal/dao/users.go
  28. 27 0
      internal/dao/words.go
  29. 0 0
      internal/logic/.gitkeep
  30. 22 0
      internal/logic/middleware/auth.go
  31. 14 0
      internal/logic/users/users.go
  32. 68 0
      internal/logic/users/users_account.go
  33. 45 0
      internal/logic/users/users_register.go
  34. 55 0
      internal/logic/words/words.go
  35. 0 0
      internal/model/.gitkeep
  36. 0 0
      internal/model/do/.gitkeep
  37. 21 0
      internal/model/do/users.go
  38. 25 0
      internal/model/do/words.go
  39. 0 0
      internal/model/entity/.gitkeep
  40. 19 0
      internal/model/entity/users.go
  41. 23 0
      internal/model/entity/words.go
  42. 1 0
      internal/packed/packed.go
  43. 0 0
      internal/service/.gitkeep
  44. 35 0
      main.go
  45. 21 0
      manifest/deploy/kustomize/base/deployment.yaml
  46. 8 0
      manifest/deploy/kustomize/base/kustomization.yaml
  47. 12 0
      manifest/deploy/kustomize/base/service.yaml
  48. 14 0
      manifest/deploy/kustomize/overlays/develop/configmap.yaml
  49. 10 0
      manifest/deploy/kustomize/overlays/develop/deployment.yaml
  50. 14 0
      manifest/deploy/kustomize/overlays/develop/kustomization.yaml
  51. 16 0
      manifest/docker/Dockerfile
  52. 8 0
      manifest/docker/docker.sh
  53. 49 0
      manifest/i18n/zh-CN/validation.toml
  54. 0 0
      manifest/protobuf/.keep-if-necessary
  55. 0 0
      resource/i18n/.gitkeep
  56. 0 0
      resource/public/html/.gitkeep
  57. 0 0
      resource/public/plugin/.gitkeep
  58. 0 0
      resource/public/resource/css/.gitkeep
  59. 0 0
      resource/public/resource/image/.gitkeep
  60. 0 0
      resource/public/resource/js/.gitkeep
  61. 0 0
      resource/template/.gitkeep
  62. 0 0
      utility/.gitkeep

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+* linguist-language=GO

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+.buildpath
+.hgignore.swp
+.project
+.orig
+.swp
+.idea/
+.settings/
+.vscode/
+bin/
+**/.DS_Store
+gf
+main
+main.exe
+output/
+manifest/output/
+temp/
+temp.yaml
+bin
+**/config/config.yaml

+ 6 - 0
Makefile

@@ -0,0 +1,6 @@
+ROOT_DIR    = $(shell pwd)
+NAMESPACE   = "default"
+DEPLOY_NAME = "template-single"
+DOCKER_NAME = "template-single"
+
+include ./hack/hack.mk

+ 4 - 0
README.MD

@@ -0,0 +1,4 @@
+# GoFrame Template For SingleRepo
+
+Quick Start: 
+- https://goframe.org/pages/viewpage.action?pageId=1114399

+ 17 - 0
api/account/account.go

@@ -0,0 +1,17 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 
+// =================================================================================
+
+package account
+
+import (
+	"context"
+	
+	"star/api/account/v1"
+)
+
+type IAccountV1 interface {
+	Info(ctx context.Context, req *v1.InfoReq) (res *v1.InfoRes, err error)
+}
+
+

+ 17 - 0
api/account/v1/account.go

@@ -0,0 +1,17 @@
+package v1
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+type InfoReq struct {
+	g.Meta `path:"/account/info" method:"get" sm:"获取账户信息" tags:"账户"`
+}
+
+type InfoRes struct {
+	Username  string      `json:"username" dc:"用户名"`
+	Email     string      `json:"email" dc:"邮箱"`
+	CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
+	UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
+}

+ 18 - 0
api/users/users.go

@@ -0,0 +1,18 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 
+// =================================================================================
+
+package users
+
+import (
+	"context"
+	
+	"star/api/users/v1"
+)
+
+type IUsersV1 interface {
+	Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error)
+	Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error)
+}
+
+

+ 24 - 0
api/users/v1/users.go

@@ -0,0 +1,24 @@
+package v1
+
+import "github.com/gogf/gf/v2/frame/g"
+
+type RegisterReq struct {
+	g.Meta   `path:"/users/register" method:"post" tags:"用户"`
+	Username string `json:"username" v:"required|length:6,12" dc:"用户名"`
+	Password string `json:"password" v:"required|length:6,16" dc:"密码"`
+	Email    string `json:"email" v:"required|email" dc:"邮箱"`
+}
+
+type RegisterRes struct {
+	Token string `json:"token" dc:"在需要鉴权的接口中header加入Authorization: token"`
+}
+
+type LoginReq struct {
+	g.Meta   `path:"users/login" method:"post" sm:"登录" tags:"用户"`
+	Username string `json:"username" v:"required|length:3,12"`
+	Password string `json:"password" v:"required|length:6,16"`
+}
+
+type LoginRes struct {
+	Token string `json:"token" dc:"在需要鉴权的接口中header加入Authorization: token"`
+}

+ 26 - 0
api/words/v1/words.go

@@ -0,0 +1,26 @@
+package v1
+
+import "github.com/gogf/gf/v2/frame/g"
+
+type ProficiencyLevel uint
+
+const (
+	ProficiencyLevel1 ProficiencyLevel = iota + 1
+	ProficiencyLevel2
+	ProficiencyLevel3
+	ProficiencyLevel4
+	ProficiencyLevel5
+)
+
+type CreateReq struct {
+	g.Meta             `path:"words" method:"post" sm:"创建" tags:"单词"`
+	Word               string           `json:"word" v:"required|length:1,100" dc:"单词"`
+	Definition         string           `json:"definition" v:"required|length:1,300" dc:"单词定义"`
+	ExampleSentence    string           `json:"example_sentence" v:"required|length:1,300" dc:"例句"`
+	ChineseTranslation string           `json:"chinese_translation" v:"required|length:1,300" dc:"中文翻译"`
+	Pronunciation      string           `json:"pronunciation" v:"required|length:1,100" dc:"发音"`
+	ProficiencyLevel   ProficiencyLevel `json:"proficiency_level" v:"required|between:1,5" dc:"熟练度,1最低,5最高"`
+}
+
+type CreateRes struct {
+}

+ 41 - 0
go.mod

@@ -0,0 +1,41 @@
+module star
+
+go 1.24.0
+
+require github.com/gogf/gf/v2 v2.9.3
+
+require (
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/BurntSushi/toml v1.5.0 // indirect
+	github.com/clbanning/mxj/v2 v2.7.0 // indirect
+	github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
+	github.com/emirpasic/gods v1.18.1 // indirect
+	github.com/fatih/color v1.18.0 // indirect
+	github.com/fsnotify/fsnotify v1.9.0 // indirect
+	github.com/go-logr/logr v1.4.3 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-sql-driver/mysql v1.9.3 // indirect
+	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.3 // indirect
+	github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/gorilla/websocket v1.5.3 // indirect
+	github.com/grokify/html-strip-tags-go v0.1.0 // indirect
+	github.com/magiconair/properties v1.8.10 // indirect
+	github.com/mattn/go-colorable v0.1.14 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/mattn/go-runewidth v0.0.19 // indirect
+	github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
+	github.com/olekukonko/errors v1.1.0 // indirect
+	github.com/olekukonko/ll v0.1.1 // indirect
+	github.com/olekukonko/tablewriter v1.1.0 // indirect
+	github.com/rivo/uniseg v0.4.7 // indirect
+	go.opentelemetry.io/auto/sdk v1.2.1 // indirect
+	go.opentelemetry.io/otel v1.38.0 // indirect
+	go.opentelemetry.io/otel/metric v1.38.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.38.0 // indirect
+	go.opentelemetry.io/otel/trace v1.38.0 // indirect
+	golang.org/x/net v0.45.0 // indirect
+	golang.org/x/sys v0.36.0 // indirect
+	golang.org/x/text v0.29.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 112 - 0
go.sum

@@ -0,0 +1,112 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
+github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
+github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
+github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
+github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
+github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.3 h1:P4jrnp+Vmh3kDeaH/kyHPI6rfoMmQD+sPJa716aMbS0=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.3/go.mod h1:yEhfx78wgpxUJhH9C9bWJ7I3JLcVCzUg11A4ORYTKeg=
+github.com/gogf/gf/v2 v2.9.3 h1:qjN4s55FfUzxZ1AE8vUHNDX3V0eIOUGXhF2DjRTVZQ4=
+github.com/gogf/gf/v2 v2.9.3/go.mod h1:w6rcfD13SmO7FKI80k9LSLiSMGqpMYp50Nfkrrc2sEE=
+github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
+github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
+github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
+github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
+github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
+github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
+github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
+github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
+github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
+github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
+github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
+github.com/olekukonko/ll v0.1.1 h1:9Dfeed5/Mgaxb9lHRAftLK9pVfYETvHn+If6lywVhJc=
+github.com/olekukonko/ll v0.1.1/go.mod h1:2dJo+hYZcJMLMbKwHEWvxCUbAOLc/CXWS9noET22Mdo=
+github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
+github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
+github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
+github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
+go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
+go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
+go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
+go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
+go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
+go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
+go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
+golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
+golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 7 - 0
hack/config.yaml

@@ -0,0 +1,7 @@
+
+# CLI tool, only in development environment.
+# https://goframe.org/pages/viewpage.action?pageId=3673173
+gfcli:
+  gen:
+    dao:
+      - link: "mysql:root:aaaAAA111@tcp(127.0.0.1:3306)/star"

+ 19 - 0
hack/hack-cli.mk

@@ -0,0 +1,19 @@
+
+# Install/Update to the latest CLI tool.
+.PHONY: cli
+cli:
+	@set -e; \
+	wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
+	chmod +x gf && \
+	./gf install -y && \
+	rm ./gf
+
+
+# Check and install CLI tool.
+.PHONY: cli.install
+cli.install:
+	@set -e; \
+	gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
+  		echo "GoFame CLI is not installed, start proceeding auto installation..."; \
+		make cli; \
+	fi;

+ 75 - 0
hack/hack.mk

@@ -0,0 +1,75 @@
+include ./hack/hack-cli.mk
+
+# Update GoFrame and its CLI to latest stable version.
+.PHONY: up
+up: cli.install
+	@gf up -a
+
+# Build binary using configuration from hack/config.yaml.
+.PHONY: build
+build: cli.install
+	@gf build -ew
+
+# Parse api and generate controller/sdk.
+.PHONY: ctrl
+ctrl: cli.install
+	@gf gen ctrl
+
+# Generate Go files for DAO/DO/Entity.
+.PHONY: dao
+dao: cli.install
+	@gf gen dao
+
+# Parse current project go files and generate enums go file.
+.PHONY: enums
+enums: cli.install
+	@gf gen enums
+
+# Generate Go files for Service.
+.PHONY: service
+service: cli.install
+	@gf gen service
+
+
+# Build docker image.
+.PHONY: image
+image: cli.install
+	$(eval _TAG  = $(shell git describe --dirty --always --tags --abbrev=8 --match 'v*' | sed 's/-/./2' | sed 's/-/./2'))
+ifneq (, $(shell git status --porcelain 2>/dev/null))
+	$(eval _TAG  = $(_TAG).dirty)
+endif
+	$(eval _TAG  = $(if ${TAG},  ${TAG}, $(_TAG)))
+	$(eval _PUSH = $(if ${PUSH}, ${PUSH}, ))
+	@gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG};
+
+
+# Build docker image and automatically push to docker repo.
+.PHONY: image.push
+image.push:
+	@make image PUSH=-p;
+
+
+# Deploy image and yaml to current kubectl environment.
+.PHONY: deploy
+deploy:
+	$(eval _TAG = $(if ${TAG},  ${TAG}, develop))
+
+	@set -e; \
+	mkdir -p $(ROOT_DIR)/temp/kustomize;\
+	cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\
+	kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\
+	kubectl   apply -f $(ROOT_DIR)/temp/kustomize.yaml; \
+	if [ $(DEPLOY_NAME) != "" ]; then \
+		kubectl   patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \
+	fi;
+
+
+# Parsing protobuf files and generating go files.
+.PHONY: pb
+pb: cli.install
+	@gf gen pb
+
+# Generate protobuf files for database tables.
+.PHONY: pbentity
+pbentity: cli.install
+	@gf gen pbentity

+ 37 - 0
internal/cmd/cmd.go

@@ -0,0 +1,37 @@
+package cmd
+
+import (
+	"context"
+	"star/internal/controller/account"
+	"star/internal/controller/users"
+
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/net/ghttp"
+	"github.com/gogf/gf/v2/os/gcmd"
+)
+
+var (
+	Main = gcmd.Command{
+		Name:  "main",
+		Usage: "main",
+		Brief: "start http server",
+		Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
+			s := g.Server()
+			s.Group("/", func(group *ghttp.RouterGroup) {
+				group.Middleware(ghttp.MiddlewareHandlerResponse)
+				group.Group("/v1", func(group *ghttp.RouterGroup) {
+					group.Bind(
+						users.NewV1(),
+					)
+					group.Group("/", func(group *ghttp.RouterGroup) {
+						group.Bind(
+							account.NewV1(),
+						)
+					})
+				})
+			})
+			s.Run()
+			return nil
+		},
+	}
+)

+ 5 - 0
internal/consts/consts.go

@@ -0,0 +1,5 @@
+package consts
+
+const (
+	JwtKey = "db03d23b03ec405793b38f10592a2f34"
+)

+ 6 - 0
internal/controller/account/account.go

@@ -0,0 +1,6 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package account
+

+ 20 - 0
internal/controller/account/account_new.go

@@ -0,0 +1,20 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package account
+
+import (
+	"star/api/account"
+	"star/internal/logic/users"
+)
+
+type ControllerV1 struct {
+	users *users.Users
+}
+
+func NewV1() account.IAccountV1 {
+	return &ControllerV1{
+		users: users.New(),
+	}
+}

+ 20 - 0
internal/controller/account/account_v1_info.go

@@ -0,0 +1,20 @@
+package account
+
+import (
+	"context"
+
+	v1 "star/api/account/v1"
+)
+
+func (c *ControllerV1) Info(ctx context.Context, req *v1.InfoReq) (res *v1.InfoRes, err error) {
+	user, err := c.users.Info(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return &v1.InfoRes{
+		Username:  user.Username,
+		Email:     user.Email,
+		CreatedAt: user.CreatedAt,
+		UpdatedAt: user.UpdatedAt,
+	}, nil
+}

+ 6 - 0
internal/controller/users/users.go

@@ -0,0 +1,6 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package users
+

+ 20 - 0
internal/controller/users/users_new.go

@@ -0,0 +1,20 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package users
+
+import (
+	"star/api/users"
+	userLogic "star/internal/logic/users"
+)
+
+type ControllerV1 struct {
+	users *userLogic.Users
+}
+
+func NewV1() users.IUsersV1 {
+	return &ControllerV1{
+		users: userLogic.New(),
+	}
+}

+ 15 - 0
internal/controller/users/users_v1_login.go

@@ -0,0 +1,15 @@
+package users
+
+import (
+	"context"
+
+	v1 "star/api/users/v1"
+)
+
+func (c *ControllerV1) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) {
+	token, err := c.users.Login(ctx, req.Username, req.Password)
+	if err != nil {
+		return
+	}
+	return &v1.LoginRes{Token: token}, nil
+}

+ 17 - 0
internal/controller/users/users_v1_register.go

@@ -0,0 +1,17 @@
+package users
+
+import (
+	"context"
+
+	v1 "star/api/users/v1"
+	"star/internal/logic/users"
+)
+
+func (c *ControllerV1) Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) {
+	err = c.users.Register(ctx, users.RegisterInput{
+		Username: req.Username,
+		Password: req.Password,
+		Email:    req.Email,
+	})
+	return nil, err
+}

+ 0 - 0
internal/dao/.gitkeep


+ 83 - 0
internal/dao/internal/users.go

@@ -0,0 +1,83 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+
+	"github.com/gogf/gf/v2/database/gdb"
+	"github.com/gogf/gf/v2/frame/g"
+)
+
+// UsersDao is the data access object for table users.
+type UsersDao struct {
+	table   string       // table is the underlying table name of the DAO.
+	group   string       // group is the database configuration group name of current DAO.
+	columns UsersColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// UsersColumns defines and stores column names for table users.
+type UsersColumns struct {
+	Id        string //
+	Username  string //
+	Password  string //
+	Email     string //
+	CreatedAt string //
+	UpdatedAt string //
+}
+
+// usersColumns holds the columns for table users.
+var usersColumns = UsersColumns{
+	Id:        "id",
+	Username:  "username",
+	Password:  "password",
+	Email:     "email",
+	CreatedAt: "created_at",
+	UpdatedAt: "updated_at",
+}
+
+// NewUsersDao creates and returns a new DAO object for table data access.
+func NewUsersDao() *UsersDao {
+	return &UsersDao{
+		group:   "default",
+		table:   "users",
+		columns: usersColumns,
+	}
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *UsersDao) DB() gdb.DB {
+	return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *UsersDao) Table() string {
+	return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *UsersDao) Columns() UsersColumns {
+	return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *UsersDao) Group() string {
+	return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *UsersDao) Ctx(ctx context.Context) *gdb.Model {
+	return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *UsersDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
+	return dao.Ctx(ctx).Transaction(ctx, f)
+}

+ 91 - 0
internal/dao/internal/words.go

@@ -0,0 +1,91 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+
+	"github.com/gogf/gf/v2/database/gdb"
+	"github.com/gogf/gf/v2/frame/g"
+)
+
+// WordsDao is the data access object for table words.
+type WordsDao struct {
+	table   string       // table is the underlying table name of the DAO.
+	group   string       // group is the database configuration group name of current DAO.
+	columns WordsColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// WordsColumns defines and stores column names for table words.
+type WordsColumns struct {
+	Id                 string //
+	Uid                string //
+	Word               string //
+	Definition         string //
+	ExampleSentence    string //
+	ChineseTranslation string //
+	Pronunciation      string //
+	ProficiencyLevel   string //
+	CreatedAt          string //
+	UpdatedAt          string //
+}
+
+// wordsColumns holds the columns for table words.
+var wordsColumns = WordsColumns{
+	Id:                 "id",
+	Uid:                "uid",
+	Word:               "word",
+	Definition:         "definition",
+	ExampleSentence:    "example_sentence",
+	ChineseTranslation: "chinese_translation",
+	Pronunciation:      "pronunciation",
+	ProficiencyLevel:   "proficiency_level",
+	CreatedAt:          "created_at",
+	UpdatedAt:          "updated_at",
+}
+
+// NewWordsDao creates and returns a new DAO object for table data access.
+func NewWordsDao() *WordsDao {
+	return &WordsDao{
+		group:   "default",
+		table:   "words",
+		columns: wordsColumns,
+	}
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *WordsDao) DB() gdb.DB {
+	return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *WordsDao) Table() string {
+	return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *WordsDao) Columns() WordsColumns {
+	return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *WordsDao) Group() string {
+	return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *WordsDao) Ctx(ctx context.Context) *gdb.Model {
+	return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *WordsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
+	return dao.Ctx(ctx).Transaction(ctx, f)
+}

+ 27 - 0
internal/dao/users.go

@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+	"star/internal/dao/internal"
+)
+
+// internalUsersDao is internal type for wrapping internal DAO implements.
+type internalUsersDao = *internal.UsersDao
+
+// usersDao is the data access object for table users.
+// You can define custom methods on it to extend its functionality as you wish.
+type usersDao struct {
+	internalUsersDao
+}
+
+var (
+	// Users is globally public accessible object for table users operations.
+	Users = usersDao{
+		internal.NewUsersDao(),
+	}
+)
+
+// Fill with you ideas below.

+ 27 - 0
internal/dao/words.go

@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+	"star/internal/dao/internal"
+)
+
+// internalWordsDao is internal type for wrapping internal DAO implements.
+type internalWordsDao = *internal.WordsDao
+
+// wordsDao is the data access object for table words.
+// You can define custom methods on it to extend its functionality as you wish.
+type wordsDao struct {
+	internalWordsDao
+}
+
+var (
+	// Words is globally public accessible object for table words operations.
+	Words = wordsDao{
+		internal.NewWordsDao(),
+	}
+)
+
+// Fill with you ideas below.

+ 0 - 0
internal/logic/.gitkeep


+ 22 - 0
internal/logic/middleware/auth.go

@@ -0,0 +1,22 @@
+package middleware
+
+import (
+	"net/http"
+
+	"star/internal/consts"
+
+	"github.com/gogf/gf/v2/net/ghttp"
+	"github.com/golang-jwt/jwt/v5"
+)
+
+func Auth(r *ghttp.Request) {
+	var tokenString = r.Header.Get("Authorization")
+	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+		return []byte(consts.JwtKey), nil
+	})
+	if err != nil || !token.Valid {
+		r.Response.WriteStatus(http.StatusForbidden)
+		r.Exit()
+	}
+	r.Middleware.Next()
+}

+ 14 - 0
internal/logic/users/users.go

@@ -0,0 +1,14 @@
+package users
+
+import "github.com/gogf/gf/v2/crypto/gmd5"
+
+type Users struct {
+}
+
+func New() *Users {
+	return &Users{}
+}
+
+func (u *Users) encryptPassword(password string) string {
+	return gmd5.MustEncryptString(password)
+}

+ 68 - 0
internal/logic/users/users_account.go

@@ -0,0 +1,68 @@
+package users
+
+import (
+	"context"
+	"time"
+
+	"github.com/gogf/gf/v2/errors/gerror"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/golang-jwt/jwt/v5"
+
+	"star/internal/consts"
+	"star/internal/dao"
+	"star/internal/model/entity"
+)
+
+type jwtClaims struct {
+	Id       uint
+	Username string
+	jwt.RegisteredClaims
+}
+
+func (u *Users) Login(ctx context.Context, username, password string) (tokenString string, err error) {
+	var user entity.Users
+	err = dao.Users.Ctx(ctx).Where("username", username).Scan(&user)
+	if err != nil {
+		return "", gerror.New("用户名或密码错误")
+	}
+
+	if user.Id == 0 {
+		return "", gerror.New("用户不存在")
+	}
+
+	// 将密码加密后与数据库中的密码进行比对
+	if user.Password != u.encryptPassword(password) {
+		return "", gerror.New("用户名或密码错误")
+	}
+
+	// 生成token
+	uc := &jwtClaims{
+		Id:       user.Id,
+		Username: user.Username,
+		RegisteredClaims: jwt.RegisteredClaims{
+			ExpiresAt: jwt.NewNumericDate(time.Now().Add(6 * time.Hour)),
+		},
+	}
+	token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc)
+	return token.SignedString([]byte(consts.JwtKey))
+}
+
+func (u *Users) Info(ctx context.Context) (user *entity.Users, err error) {
+	tokenString := g.RequestFromCtx(ctx).Request.Header.Get("Authorization")
+	tokenClaims, _ := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) {
+		return []byte(consts.JwtKey), nil
+	})
+
+	if claims, ok := tokenClaims.Claims.(*jwtClaims); ok && tokenClaims.Valid {
+		err = dao.Users.Ctx(ctx).Where("id", claims.Id).Scan(&user)
+	}
+	return
+}
+
+func (u *Users) GetUid(ctx context.Context) (uint, error) {
+	user, err := u.Info(ctx)
+	if err != nil {
+		return 0, err
+	}
+	return user.Id, nil
+}

+ 45 - 0
internal/logic/users/users_register.go

@@ -0,0 +1,45 @@
+package users
+
+import (
+	"context"
+
+	"star/internal/dao"
+	"star/internal/model/do"
+
+	"github.com/gogf/gf/v2/errors/gerror"
+)
+
+type RegisterInput struct {
+	Username string
+	Password string
+	Email    string
+}
+
+// Register 注册用户
+func (u *Users) Register(ctx context.Context, in RegisterInput) error {
+	if err := u.checkUser(ctx, in.Username); err != nil {
+		return err
+	}
+
+	_, err := dao.Users.Ctx(ctx).Data(do.Users{
+		Username: in.Username,
+		Password: u.encryptPassword(in.Password), // 加密密码
+		Email:    in.Email,
+	}).Insert()
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// checkUser 检查用户是否存在
+func (u *Users) checkUser(ctx context.Context, username string) error {
+	count, err := dao.Users.Ctx(ctx).Where("username", username).Count()
+	if err != nil {
+		return err
+	}
+	if count > 0 {
+		return gerror.New("用户名已存在")
+	}
+	return nil
+}

+ 55 - 0
internal/logic/words/words.go

@@ -0,0 +1,55 @@
+package words
+
+import (
+	"context"
+	v1 "star/api/words/v1"
+	"star/internal/dao"
+	"star/internal/model/do"
+
+	"github.com/gogf/gf/v2/errors/gerror"
+)
+
+type Words struct {
+}
+
+func New() *Words {
+	return &Words{}
+}
+
+type CreateInput struct {
+	Uid                uint
+	Word               string
+	Definition         string
+	ExampleSentence    string
+	ChineseTranslation string
+	Pronunciation      string
+	ProficiencyLevel   v1.ProficiencyLevel
+}
+
+func (w *Words) Create(ctx context.Context, in CreateInput) error {
+	var cls = dao.Words.Columns()
+
+	count, err := dao.Words.Ctx(ctx).
+		Where(cls.Uid, in.Uid).
+		Where(cls.Word, in.Word).Count()
+	if err != nil {
+		return err
+	}
+	if count > 0 {
+		return gerror.New("单词已存在")
+	}
+
+	_, err = dao.Words.Ctx(ctx).Data(do.Words{
+		Uid:                in.Uid,
+		Word:               in.Word,
+		Definition:         in.Definition,
+		ExampleSentence:    in.ExampleSentence,
+		ChineseTranslation: in.ChineseTranslation,
+		Pronunciation:      in.Pronunciation,
+		ProficiencyLevel:   in.ProficiencyLevel,
+	}).Insert()
+	if err != nil {
+		return err
+	}
+	return nil
+}

+ 0 - 0
internal/model/.gitkeep


+ 0 - 0
internal/model/do/.gitkeep


+ 21 - 0
internal/model/do/users.go

@@ -0,0 +1,21 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Users is the golang structure of table users for DAO operations like Where/Data.
+type Users struct {
+	g.Meta    `orm:"table:users, do:true"`
+	Id        interface{} //
+	Username  interface{} //
+	Password  interface{} //
+	Email     interface{} //
+	CreatedAt *gtime.Time //
+	UpdatedAt *gtime.Time //
+}

+ 25 - 0
internal/model/do/words.go

@@ -0,0 +1,25 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Words is the golang structure of table words for DAO operations like Where/Data.
+type Words struct {
+	g.Meta             `orm:"table:words, do:true"`
+	Id                 interface{} //
+	Uid                interface{} //
+	Word               interface{} //
+	Definition         interface{} //
+	ExampleSentence    interface{} //
+	ChineseTranslation interface{} //
+	Pronunciation      interface{} //
+	ProficiencyLevel   interface{} //
+	CreatedAt          *gtime.Time //
+	UpdatedAt          *gtime.Time //
+}

+ 0 - 0
internal/model/entity/.gitkeep


+ 19 - 0
internal/model/entity/users.go

@@ -0,0 +1,19 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Users is the golang structure for table users.
+type Users struct {
+	Id        uint        `json:"id"        ` //
+	Username  string      `json:"username"  ` //
+	Password  string      `json:"password"  ` //
+	Email     string      `json:"email"     ` //
+	CreatedAt *gtime.Time `json:"createdAt" ` //
+	UpdatedAt *gtime.Time `json:"updatedAt" ` //
+}

+ 23 - 0
internal/model/entity/words.go

@@ -0,0 +1,23 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+// Words is the golang structure for table words.
+type Words struct {
+	Id                 uint        `json:"id"                 ` //
+	Uid                uint        `json:"uid"                ` //
+	Word               string      `json:"word"               ` //
+	Definition         string      `json:"definition"         ` //
+	ExampleSentence    string      `json:"exampleSentence"    ` //
+	ChineseTranslation string      `json:"chineseTranslation" ` //
+	Pronunciation      string      `json:"pronunciation"      ` //
+	ProficiencyLevel   uint        `json:"proficiencyLevel"   ` //
+	CreatedAt          *gtime.Time `json:"createdAt"          ` //
+	UpdatedAt          *gtime.Time `json:"updatedAt"          ` //
+}

+ 1 - 0
internal/packed/packed.go

@@ -0,0 +1 @@
+package packed

+ 0 - 0
internal/service/.gitkeep


+ 35 - 0
main.go

@@ -0,0 +1,35 @@
+package main
+
+import (
+	"errors"
+	_ "star/internal/packed"
+
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gctx"
+
+	"star/internal/cmd"
+
+	_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
+)
+
+func main() {
+	var err error
+
+	g.I18n().SetLanguage("zh-CN")
+
+	// 检查数据库是否能连接
+	err = connDb()
+	if err != nil {
+		panic(err)
+	}
+
+	cmd.Main.Run(gctx.GetInitCtx())
+}
+
+func connDb() error {
+	err := g.DB().PingMaster()
+	if err != nil {
+		return errors.New("数据库连接失败")
+	}
+	return nil
+}

+ 21 - 0
manifest/deploy/kustomize/base/deployment.yaml

@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-single
+  labels:
+    app: template-single
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: template-single
+  template:
+    metadata:
+      labels:
+        app: template-single
+    spec:
+      containers:
+        - name : main
+          image: template-single
+          imagePullPolicy: Always
+

+ 8 - 0
manifest/deploy/kustomize/base/kustomization.yaml

@@ -0,0 +1,8 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- deployment.yaml
+- service.yaml
+
+
+

+ 12 - 0
manifest/deploy/kustomize/base/service.yaml

@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: template-single
+spec:
+  ports:
+  - port: 80
+    protocol: TCP
+    targetPort: 8000
+  selector:
+    app: template-single
+

+ 14 - 0
manifest/deploy/kustomize/overlays/develop/configmap.yaml

@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: template-single-configmap
+data:
+  config.yaml: |
+    server:
+      address:     ":8000"
+      openapiPath: "/api.json"
+      swaggerPath: "/swagger"
+
+    logger:
+      level : "all"
+      stdout: true

+ 10 - 0
manifest/deploy/kustomize/overlays/develop/deployment.yaml

@@ -0,0 +1,10 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-single
+spec:
+  template:
+    spec:
+      containers:
+        - name : main
+          image: template-single:develop

+ 14 - 0
manifest/deploy/kustomize/overlays/develop/kustomization.yaml

@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+- ../../base
+- configmap.yaml
+
+patchesStrategicMerge:
+- deployment.yaml
+
+namespace: default
+
+
+

+ 16 - 0
manifest/docker/Dockerfile

@@ -0,0 +1,16 @@
+FROM loads/alpine:3.8
+
+###############################################################################
+#                                INSTALLATION
+###############################################################################
+
+ENV WORKDIR                 /app
+ADD resource                $WORKDIR/
+ADD ./temp/linux_amd64/main $WORKDIR/main
+RUN chmod +x $WORKDIR/main
+
+###############################################################################
+#                                   START
+###############################################################################
+WORKDIR $WORKDIR
+CMD ./main

+ 8 - 0
manifest/docker/docker.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This shell is executed before docker build.
+
+
+
+
+

+ 49 - 0
manifest/i18n/zh-CN/validation.toml

@@ -0,0 +1,49 @@
+"gf.gvalid.rule.required"             = "{field}字段不能为空"
+"gf.gvalid.rule.required-if"          = "{field}字段不能为空"
+"gf.gvalid.rule.required-unless"      = "{field}字段不能为空"
+"gf.gvalid.rule.required-with"        = "{field}字段不能为空"
+"gf.gvalid.rule.required-with-all"    = "{field}字段不能为空"
+"gf.gvalid.rule.required-without"     = "{field}字段不能为空"
+"gf.gvalid.rule.required-without-all" = "{field}字段不能为空"
+"gf.gvalid.rule.date"                 = "{field}字段值`{value}`日期格式不满足Y-m-d格式,例如: 2001-02-03"
+"gf.gvalid.rule.datetime"             = "{field}字段值`{value}`日期格式不满足Y-m-d H:i:s格式,例如: 2001-02-03 12:00:00"
+"gf.gvalid.rule.date-format"          = "{field}字段值`{value}`日期格式不满足{format}"
+"gf.gvalid.rule.email"                = "{field}字段值`{value}`邮箱地址格式不正确"
+"gf.gvalid.rule.phone"                = "{field}字段值`{value}`手机号码格式不正确"
+"gf.gvalid.rule.phone-loose"          = "{field}字段值`{value}`手机号码格式不正确"
+"gf.gvalid.rule.telephone"            = "{field}字段值`{value}`电话号码格式不正确"
+"gf.gvalid.rule.passport"             = "{field}字段值`{value}`账号格式不合法,必需以字母开头,只能包含字母、数字和下划线,长度在6~18之间"
+"gf.gvalid.rule.password"             = "{field}字段值`{value}`密码格式不合法,密码格式为任意6-18位的可见字符"
+"gf.gvalid.rule.password2"            = "{field}字段值`{value}`密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母和数字"
+"gf.gvalid.rule.password3"            = "{field}字段值`{value}`密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符"
+"gf.gvalid.rule.postcode"             = "{field}字段值`{value}`邮政编码不正确"
+"gf.gvalid.rule.resident-id"          = "{field}字段值`{value}`身份证号码格式不正确"
+"gf.gvalid.rule.bank-card"            = "{field}字段值`{value}`银行卡号格式不正确"
+"gf.gvalid.rule.qq"                   = "{field}字段值`{value}`QQ号码格式不正确"
+"gf.gvalid.rule.ip"                   = "{field}字段值`{value}`IP地址格式不正确"
+"gf.gvalid.rule.ipv4"                 = "{field}字段值`{value}`IPv4地址格式不正确"
+"gf.gvalid.rule.ipv6"                 = "{field}字段值`{value}`IPv6地址格式不正确"
+"gf.gvalid.rule.mac"                  = "{field}字段值`{value}`MAC地址格式不正确"
+"gf.gvalid.rule.url"                  = "{field}字段值`{value}`URL地址格式不正确"
+"gf.gvalid.rule.domain"               = "{field}字段值`{value}`域名格式不正确"
+"gf.gvalid.rule.length"               = "{field}字段值`{value}`字段长度应当为{min}到{max}个字符"
+"gf.gvalid.rule.min-length"           = "{field}字段值`{value}`字段最小长度应当为{min}"
+"gf.gvalid.rule.max-length"           = "{field}字段值`{value}`字段最大长度应当为{max}"
+"gf.gvalid.rule.size"                 = "{field}字段值`{value}`字段长度必须应当为{size}"
+"gf.gvalid.rule.between"              = "{field}字段值`{value}`字段大小应当为{min}到{max}"
+"gf.gvalid.rule.min"                  = "{field}字段值`{value}`字段最小值应当为{min}"
+"gf.gvalid.rule.max"                  = "{field}字段值`{value}`字段最大值应当为{max}"
+"gf.gvalid.rule.json"                 = "{field}字段值`{value}`字段应当为JSON格式"
+"gf.gvalid.rule.xml"                  = "{field}字段值`{value}`字段应当为XML格式"
+"gf.gvalid.rule.array"                = "{field}字段值`{value}`字段应当为数组"
+"gf.gvalid.rule.integer"              = "{field}字段值`{value}`字段应当为整数"
+"gf.gvalid.rule.float"                = "{field}字段值`{value}`字段应当为浮点数"
+"gf.gvalid.rule.boolean"              = "{field}字段值`{value}`字段应当为布尔值"
+"gf.gvalid.rule.same"                 = "{field}字段值`{value}`字段值必须和{field}相同"
+"gf.gvalid.rule.different"            = "{field}字段值`{value}`字段值不能与{field}相同"
+"gf.gvalid.rule.in"                   = "{field}字段值`{value}`字段值应当满足取值范围:{pattern}"
+"gf.gvalid.rule.not-in"               = "{field}字段值`{value}`字段值不应当满足取值范围:{pattern}"
+"gf.gvalid.rule.regex"                = "{field}字段值`{value}`字段值不满足规则:{pattern}"
+"gf.gvalid.rule.__default__"          = "{field}字段值`{value}`字段值不合法"
+"CustomMessage"                       = "自定义错误"
+"project id must between {min}, {max}"  = "项目ID必须大于等于{min}并且要小于等于{max}"

+ 0 - 0
manifest/protobuf/.keep-if-necessary


+ 0 - 0
resource/i18n/.gitkeep


+ 0 - 0
resource/public/html/.gitkeep


+ 0 - 0
resource/public/plugin/.gitkeep


+ 0 - 0
resource/public/resource/css/.gitkeep


+ 0 - 0
resource/public/resource/image/.gitkeep


+ 0 - 0
resource/public/resource/js/.gitkeep


+ 0 - 0
resource/template/.gitkeep


+ 0 - 0
utility/.gitkeep