Browse Source

Merge branch 'master' of https://gitee.com/bhikkhu-kosalla/mint

bhikkhu-kosalla-china 4 years ago
parent
commit
47c7c4ef47
63 changed files with 2358 additions and 716 deletions
  1. 7 3
      README.md
  2. 3 2
      api/README.md
  3. 6 7
      api/go.mod
  4. 30 347
      api/go.sum
  5. 64 3
      api/main.go
  6. 153 0
      api/mint/article.go
  7. 94 0
      api/mint/article_list.go
  8. 153 0
      api/mint/collection.go
  9. 155 0
      api/mint/course.go
  10. 90 4
      api/mint/demo.go
  11. 200 0
      api/mint/lesson.go
  12. 0 0
      app/public/images/图标.md
  13. 7 6
      dashboard/src/pages/index.tsx
  14. 2 0
      db/migrations/2021-07-06-125510_create-users/down.sql
  15. 7 0
      db/migrations/2021-07-06-125510_create-users/up.sql
  16. 3 0
      db/migrations/2021-07-09-125349_new_course/down.sql
  17. 42 0
      db/migrations/2021-07-09-125349_new_course/up.sql
  18. 3 0
      db/migrations/2021-07-15-131154_create_article/down.sql
  19. 18 0
      db/migrations/2021-07-15-131154_create_article/up.sql
  20. 3 0
      db/migrations/2021-07-16-010532_create_collection/down.sql
  21. 18 0
      db/migrations/2021-07-16-010532_create_collection/up.sql
  22. 3 0
      db/migrations/2021-07-16-130715_collection_article_list/down.sql
  23. 8 0
      db/migrations/2021-07-16-130715_collection_article_list/up.sql
  24. 0 0
      dicttext/readme.md
  25. 0 225
      documents/development/functions.md
  26. 0 0
      documents/readme.md
  27. 83 0
      documents/zh/api/article.md
  28. 23 0
      documents/zh/api/channel.md
  29. 61 0
      documents/zh/api/course.md
  30. 25 0
      documents/zh/api/deploy.md
  31. 210 0
      documents/zh/api/dict.md
  32. 52 0
      documents/zh/api/group.md
  33. 8 9
      documents/zh/api/palicanon.md
  34. 77 0
      documents/zh/api/readme.md
  35. 0 0
      documents/zh/api/search.md
  36. 65 0
      documents/zh/api/share.md
  37. 22 0
      documents/zh/api/term.md
  38. 122 0
      documents/zh/api/translation.md
  39. 171 0
      documents/zh/api/user.md
  40. 77 0
      documents/zh/api/wbw.md
  41. 0 1
      documents/zh/course.md
  42. 0 0
      documents/zh/dashboard/auth.md
  43. 0 0
      documents/zh/dashboard/collection.md
  44. 1 0
      documents/zh/dashboard/course.md
  45. 0 0
      documents/zh/dashboard/dict.md
  46. 0 0
      documents/zh/dashboard/home.md
  47. 1 0
      documents/zh/dashboard/myzone.md
  48. 23 0
      documents/zh/dashboard/palicanon.md
  49. 5 0
      documents/zh/dashboard/public.md
  50. 231 0
      documents/zh/dashboard/readme.md
  51. 0 0
      documents/zh/dashboard/stu_course.md
  52. 0 0
      documents/zh/dashboard/stu_dict.md
  53. 0 0
      documents/zh/dashboard/stu_doc.md
  54. 0 0
      documents/zh/dashboard/stu_group.md
  55. 0 0
      documents/zh/dashboard/stu_term.md
  56. 0 0
      documents/zh/dashboard/studio.md
  57. 0 0
      documents/zh/dashboard/term.md
  58. 0 61
      documents/zh/database.md
  59. 9 0
      documents/zh/db/readme.md
  60. 0 0
      documents/zh/deploy/语料库.md
  61. 19 1
      documents/zh/readme.md
  62. 4 0
      documents/zh/summary.md
  63. 0 47
      documents/功能完善列表.md

+ 7 - 3
README.md

@@ -28,14 +28,16 @@ cd mint; mkdir tmp; chown -R www:www tmp
 ## 开发
 ### 技术栈
 #### 前端
-- ant design pro
 - react
+- umijs
+- ant design pro
 - Tapescript
 
 #### 后端
 - PostgreSQL
-- PHP
-- Laravel
+- elasticsearch
+- golang
+- Redis
   
 ### 工具
 
@@ -52,7 +54,9 @@ cd mint; mkdir tmp; chown -R www:www tmp
 #### 数据库管理工具
 - [通用数据库管理工具-dbeaver](https://github.com/dbeaver/dbeaver)
 - [redis图形界面工具-RedisDesktopManager](https://github.com/uglide/RedisDesktopManager)
+
 ### Git commit message 规范
+git commit message格式 请参见 https://gitmoji.dev/
 
 -   遵循 git pull request 流程
 -   所有代码必须经过格式化

+ 3 - 2
api/README.md

@@ -1,8 +1,6 @@
 # USAGE
 
 ```bash
-# Install third dependices
-go mod tidy
 # start http server
 go run .
 ```
@@ -12,6 +10,8 @@ go run .
 - [Gin Web Framework](https://github.com/gin-gonic/gin)
 - [PostgreSQL client and ORM for Golang](https://github.com/go-pg/pg)
 - [Introduction to Object-relational mapping](https://pg.uptrace.dev/orm/intro/)
+- [Redis client for Golang](https://github.com/go-redis/redis)
+- [Go Standard library](https://golang.org/pkg/)
 
 ## SOP
 
@@ -20,3 +20,4 @@ go run .
 - Gin: Querystring parameters
 - Gin: Model binding and validation
 - Pg: Quickstart(**ingore createSchema**)
+- Redis: Quickstart

+ 6 - 7
api/go.mod

@@ -3,23 +3,22 @@ module github.com/iapt-platform
 go 1.16
 
 require (
-	github.com/gin-gonic/gin v1.7.2 // indirect
-	github.com/go-pg/pg/v10 v10.10.1 // indirect
-	github.com/go-playground/validator v9.31.0+incompatible // indirect
+	github.com/gin-gonic/gin v1.7.2
+	github.com/go-pg/pg/v10 v10.10.1
 	github.com/go-playground/validator/v10 v10.6.1 // indirect
+	github.com/go-redis/redis/v8 v8.11.0 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/jackc/pgproto3/v2 v2.1.0 // indirect
 	github.com/json-iterator/go v1.1.11 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
-	github.com/lib/pq v1.6.0 // indirect
 	github.com/mattn/go-isatty v0.0.13 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.1 // indirect
 	github.com/ugorji/go v1.2.6 // indirect
 	github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
+	go.opentelemetry.io/otel v0.14.0 // indirect
 	golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
 	golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
 	golang.org/x/text v0.3.6 // indirect
 	google.golang.org/protobuf v1.27.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	gorm.io/driver/postgres v1.1.0
-	gorm.io/gorm v1.21.11
 )

+ 30 - 347
api/go.sum

@@ -1,53 +1,16 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
-github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
-github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
-github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
-github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
-github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
-github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
-github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
-github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
-github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
-github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
@@ -56,34 +19,30 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
 github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
-github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
 github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
 github.com/go-pg/pg/v10 v10.10.1 h1:82lLX4KGs2wOFOvVVIICoU0Si1fLu6Aitniu73HaDuM=
 github.com/go-pg/pg/v10 v10.10.1/go.mod h1:EmoJGYErc+stNN/1Jf+o4csXuprjxcRztBnn6cHe38E=
 github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
 github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
 github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
 github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
+github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
 github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
 github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
 github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
+github.com/go-redis/redis/v8 v8.11.0 h1:O1Td0mQ8UFChQ3N9zFQqo6kTU2cJ+/it88gDB+zg0wo=
+github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7WU5SOQ/r06M=
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
@@ -93,11 +52,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -111,206 +67,52 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
-github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
-github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
-github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
-github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
-github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
-github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
-github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
-github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
-github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
-github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
-github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
-github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
-github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
-github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
-github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
-github.com/jackc/pgconn v1.8.1 h1:ySBX7Q87vOMqKU2bbmKbUvtYhauDFclYbNDYIE1/h6s=
-github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g=
-github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
-github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
-github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
-github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
-github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
-github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
-github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
-github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
-github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
-github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
-github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
-github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
-github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
-github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
-github.com/jackc/pgproto3/v2 v2.1.0 h1:h2yg3kjIyAGSZKDijYn1/gXHlYLCwl9ZjEh2PU0yVxE=
-github.com/jackc/pgproto3/v2 v2.1.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
-github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
-github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
-github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
-github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
-github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
-github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
-github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
-github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
-github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
-github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs=
-github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE=
-github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
-github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
-github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
-github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
-github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
-github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
-github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI=
-github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc=
-github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
-github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
-github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
-github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
-github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
-github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
-github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
-github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
-github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
-github.com/jcmturner/gokrb5/v8 v8.2.0 h1:lzPl/30ZLkTveYsYZPKMcgXc8MbnE6RsTd4F9KgiLtk=
-github.com/jcmturner/gokrb5/v8 v8.2.0/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM=
-github.com/jcmturner/rpc/v2 v2.0.2 h1:gMB4IwRXYsWw4Bc6o/az2HJgFUA1ffSh90i26ZJ6Xl0=
-github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
-github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
-github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.6.0 h1:I5DPxhYJChW9KYc66se+oKFFQX6VuQrKiprsX6ivRZc=
-github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
-github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
-github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
-github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
-github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
 github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
-github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
-github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
-github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
-github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
-github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
 github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
 github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
 github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
@@ -332,61 +134,14 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
-github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
-github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
-github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
-github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
-github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
-github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
 github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
@@ -395,8 +150,6 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
 github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94=
 github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ=
 github.com/vmihailenco/msgpack/v5 v5.3.1/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
@@ -407,12 +160,14 @@ github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq
 github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
 github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@@ -426,85 +181,50 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
@@ -515,48 +235,33 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -571,26 +276,13 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
-gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
-gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
-gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
-gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
-gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
-gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
-gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
-gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -599,16 +291,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/postgres v1.1.0 h1:afBljg7PtJ5lA6YUWluV2+xovIPhS+YiInuL3kUjrbk=
-gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw=
-gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
-gorm.io/gorm v1.21.11 h1:CxkXW6Cc+VIBlL8yJEHq+Co4RYXdSLiMKNvgoZPjLK4=
-gorm.io/gorm v1.21.11/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=
 mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ=
-sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
-sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

+ 64 - 3
api/main.go

@@ -4,22 +4,83 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/go-pg/pg/v10"
 	"github.com/iapt-platform/mint"
+	"fmt"
 )
 
 func main() {
+
 	opt, err := pg.ParseURL("postgres://postgres:@127.0.0.1:5432/mint?sslmode=disable")
 	if err != nil {
 		panic(err)
 	}
-
+	fmt.Println("pg connectd")
 	db := pg.Connect(opt)
 	defer db.Close()
 
 	rt := gin.Default()
 
 	// TODO 在这里进行http mount
-	rt.GET("/demo/get", mint.GetDemo(db))
-	rt.POST("/demo/sign-in", mint.LoginDemo(db))
+
+	rt.GET("/demo/user/:id", mint.GetDemo(db))
+	//rt.POST("/demo/sign-in", mint.LoginDemo(db))
+	rt.POST("/demo/user",mint.PostDemo(db))
+	rt.PUT("/demo/user",mint.PutDemo(db))
+	rt.PATCH("/demo/user/:id",mint.PatchDemo(db))
+	rt.DELETE("/demo/user/:id",mint.DeleteDemo(db))
+
+	//课程
+	//根据id查询课程 
+	rt.GET("/api/course/:cid",mint.GetCourse(db))
+	//输入标题查询符合条件的课程 title% 
+	rt.GET("/api/course/title/:ctitle",mint.GetCourseByTitle(db))
+	//新建课程
+	rt.PUT("/api/course",mint.PutCourse(db)) 
+	//修改
+	rt.POST("/api/course",mint.PostCourse(db))//改
+	//删除
+	rt.DELETE("/api/course/:cid",mint.DeleteCourse(db)) 
+	//修改课程表里的课的数量
+	rt.PATCH("/api/course/lessonnum",mint.PatchLessonNumInCousrse(db))
+
+	//课
+	//根据id查询课程
+	rt.GET("/api/lesson/:lid",mint.GetLesson(db))
+	//输入标题查询符合条件的课程 title% 
+	rt.GET("/api/lesson/title/:ltitle",mint.GetLessonByTitle(db))
+	//新建课
+	rt.PUT("/api/lesson",mint.PutLesson(db)) 
+	//修改
+	rt.POST("/api/lesson",mint.PostLesson(db))//改
+	//删除
+	rt.DELETE("/api/lesson/:lid",mint.DeleteLesson(db)) 
+
+	//文章
+	//根据id查询
+	rt.GET("/api/article/:aid",mint.GetArticle(db))
+	//输入标题查询符合条件的 title% 
+	rt.GET("/api/article/title/:title",mint.GetArticleByTitle(db))
+	//新建课
+	rt.PUT("/api/article",mint.PutArticle(db))
+	//修改
+	rt.POST("/api/article",mint.PostAritcle(db))//改
+	//删除
+	rt.DELETE("/api/article/:aid",mint.DeleteArticle(db))
+
+	//文集
+	//根据id查询
+	rt.GET("/api/collection/:cid",mint.GetCollection(db))
+	//输入标题查询符合条件的 title% 
+	rt.GET("/api/collection/title/:title",mint.GetCollectionByTitle(db))
+	//新建课
+	rt.PUT("/api/collection",mint.PutCollection(db))
+	//修改
+	rt.POST("/api/collection",mint.PostCollection(db))//改
+	//删除
+	rt.DELETE("/api/collection/:cid",mint.DeleteCollection(db))
+
+	rt.GET("/api/article_list/:cid",mint.GetCollectionArticleList(db))//改
+	//修改
+	rt.POST("/api/article_list/article/:aid",mint.PostArticleListByArticle(db))//改
 
 	rt.Run()
 }

+ 153 - 0
api/mint/article.go

@@ -0,0 +1,153 @@
+package mint
+
+import (
+	"net/http"
+	"strconv"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pg/pg/v10"
+	"time"
+)
+/*
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    content      TEXT,
+    owner_id     INTEGER  NOT NULL,
+    owner        VARCHAR (36),
+    setting      JSON,
+    status       INTEGER   NOT NULL DEFAULT (10),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+
+*/
+type Article struct {
+	Id     int `form:"id" json:"id" binding:"required"`
+	Title string `form:"title" json:"title" binding:"required"`
+	Subtitle string `form:"subtitle" json:"subtitle" binding:"required"`
+	Summary string `form:"summary" json:"summary" binding:"required"`
+	Content string `form:"content" json:"content" binding:"required"`
+	OwnerId int
+	Setting string `form:"setting" json:"setting" binding:"required"`
+	Status int `form:"status" json:"status" binding:"required"`
+	Version int
+    DeletedAt time.Time
+    CreatedAt time.Time
+    UpdatedAt time.Time
+}
+//查询
+func GetArticle(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		lid,err := strconv.ParseInt(c.Param("aid"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("get lesson")
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		article := &Article{Id: int(lid)}
+		err = db.Model(article).WherePK().Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": "article-"+article.Title,
+		})
+	}
+}
+
+//查询
+func GetArticleByTitle(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		title:= c.Param("ltitle")
+
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		var articles []Article
+		err := db.Model(&articles).Column("id","title","subtitle").Where("title like ?",title+"%").Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": articles,
+		})
+	}
+}
+
+//新建-
+//PUT http://127.0.0.1:8080/api/lesson?title=lesson-one&status=10
+func PutArticle(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+	
+		title := c.Query("title")
+		status1,err := strconv.ParseInt(c.Query("status"),10,64)
+		if err != nil {
+			panic(err)
+		}
+
+		newArticle := &Article{
+			Title:   title,
+			Status: int(status1),
+			OwnerId:1,
+		}
+		_, err = db.Model(newArticle).Insert()
+		if err != nil {
+			panic(err)
+		}
+
+		//修改完毕
+		c.JSON(http.StatusOK,gin.H{
+			"message":"",
+		})
+	}
+}
+
+
+//修改
+func PostAritcle(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		var form Article
+
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		_,err := db.Model(&form).Column("title","subtitle","summary","status","content").WherePK().Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"update ok",
+		})
+	}
+}
+
+
+//删
+func DeleteArticle(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		id,err := strconv.ParseInt(c.Param("aid"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		article := &Article{
+			Id:int(id),
+		}
+		//删之前获取 course_id
+		_, err = db.Model(article).WherePK().Delete()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK,gin.H{
+			"message":"delete "+c.Param("lid"),
+		})
+	}
+}

+ 94 - 0
api/mint/article_list.go

@@ -0,0 +1,94 @@
+package mint
+
+import (
+	"net/http"
+	"strconv"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pg/pg/v10"
+	"time"
+	"encoding/json"
+
+)
+type ArticleList struct {
+	Id     int `form:"id" json:"id"`
+	CollectionId int `form:"collection_id" json:"collection_id" binding:"required"`
+	ArticleId int `form:"article_id" json:"article_id" binding:"required"`
+    CreatedAt time.Time
+}
+type ArticleListHolder struct{
+	Items []ArticleList
+}
+func (i *ArticleListHolder) UnmarshalJSON(b []byte) error{
+	return json.Unmarshal(b, &i.Items)
+}
+//查询
+func GetCollectionArticleList(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		cid,err:= strconv.Atoi(c.Param("cid"))
+		if err != nil {
+			panic(err)
+		}
+
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		var articles []ArticleList
+		err = db.Model(&articles).Column("collection_id","article_id").Where("collection_id = ?",cid).Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": articles,
+		})
+	}
+}
+
+
+
+//修改
+func PostArticleListByArticle(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		aid,err:= strconv.Atoi(c.Param("aid"))
+		if err != nil {
+			panic(err)
+		}
+		//先删除
+		_, err = db.Model((*ArticleList)(nil)).Where("article_id = ?",aid).Delete()
+		if err != nil {
+			panic(err)
+		}
+
+		var form ArticleListHolder
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		tx, err := db.Begin()
+		if err != nil {
+			panic(err)
+		}
+		defer tx.Rollback()
+		stmt, err := tx.Prepare("INSERT INTO article_lists( collection_id, article_id ) VALUES( $1, $2 )")
+		if err != nil {
+			panic(err)
+		}
+		defer stmt.Close()
+		for _, value := range form.Items{
+			_, err = stmt.Exec(value.CollectionId,aid)
+			if err != nil {
+				panic(err)
+			}
+	
+		}
+		err = tx.Commit()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"update ok",
+		})
+	}
+}
+
+

+ 153 - 0
api/mint/collection.go

@@ -0,0 +1,153 @@
+package mint
+
+import (
+	"net/http"
+	"strconv"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pg/pg/v10"
+	"time"
+)
+/*
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    article_list TEXT,
+    status       INTEGER   NOT NULL DEFAULT (10),
+    creator_id   INTEGER,
+    owner        VARCHAR (36),
+    lang         CHAR (8),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+
+*/
+type Collection struct {
+	Id     int `form:"id" json:"id" binding:"required"`
+	Title string `form:"title" json:"title" binding:"required"`
+	Subtitle string `form:"subtitle" json:"subtitle" binding:"required"`
+	Summary string `form:"summary" json:"summary" binding:"required"`
+	ArticleList string `form:"article_list" json:"article_list" binding:"required"`
+	CreatorId int
+	Lang string `form:"lang" json:"lang" binding:"required"`
+	Status int `form:"status" json:"status" binding:"required"`
+	Version int
+    DeletedAt time.Time
+    CreatedAt time.Time
+    UpdatedAt time.Time
+}
+//查询
+func GetCollection(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		lid,err := strconv.Atoi(c.Param("cid"))
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("get lesson")
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		collection := &Collection{Id: int(lid)}
+		err = db.Model(collection).Column("title","subtitle","summary","status").WherePK().Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": collection,
+		})
+	}
+}
+
+//查询
+func GetCollectionByTitle(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		title:= c.Param("ctitle")
+
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		var collections []Collection
+		err := db.Model(&collections).Column("id","title","subtitle").Where("title like ?",title+"%").Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": collections,
+		})
+	}
+}
+
+//新建-
+//PUT http://127.0.0.1:8080/api/lesson?title=lesson-one&course_id=1&status=10
+func PutCollection(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+	
+		title := c.Query("title")
+		status1,err := strconv.Atoi(c.Query("status"))
+		if err != nil {
+			panic(err)
+		}
+
+		newOne := &Collection{
+			Title:   title,
+			Status: int(status1),
+			CreatorId:1,
+		}
+		_, err = db.Model(newOne).Insert()
+		if err != nil {
+			panic(err)
+		}
+
+		//修改完毕
+		c.JSON(http.StatusOK,gin.H{
+			"message":"insert ok",
+		})
+	}
+}
+
+
+//改
+func PostCollection(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		var form Collection
+
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		_,err := db.Model(&form).Column("title","subtitle","summary","status","article_list").WherePK().Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"update ok",
+		})
+	}
+}
+
+
+//删
+func DeleteCollection(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		id,err := strconv.Atoi(c.Param("cid"))
+		if err != nil {
+			panic(err)
+		}
+		collection := &Collection{
+			Id:int(id),
+		}
+		//删之前获取 course_id
+		_, err = db.Model(collection).WherePK().Delete()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK,gin.H{
+			"message":"deleted "+c.Param("cid"),
+		})
+	}
+}

+ 155 - 0
api/mint/course.go

@@ -0,0 +1,155 @@
+package mint
+
+import (
+	"net/http"
+	"strconv"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pg/pg/v10"
+	"time"
+)
+
+
+type Course struct {
+	Id     int `form:"id" json:"id" binding:"required"`
+	Cover string
+	Title string `form:"title" json:"title"`
+	Subtitle string `form:"subtitle" json:"subtitle"`
+	Summary string `form:"summary" json:"summary"`
+	Teacher int `form:"teacher" json:"teacher"`
+	Lang string `form:"lang" json:"lang"`
+	Speech_lang string `form:"speech_lang" json:"speech_lang"`
+	Status int `form:"status" json:"status"`
+	Content string `form:"content" json:"content"`
+	Creator int
+    LessonNum int `form:"lesson_num" json:"lesson_num"`
+    Version int
+    CreatedAt time.Time
+    UpdatedAt time.Time
+}
+//查询
+func GetCourse(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		cid,err := strconv.Atoi(c.Param("cid"))
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("get course")
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		course := &Course{Id: cid}
+		err = db.Model(course).WherePK().Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": "course-"+course.Title,
+		})
+	}
+}
+
+//查询
+func GetCourseByTitle(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		ctitle:= c.Param("ctitle")
+
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		var courses []Course
+		err := db.Model(&courses).Column("id","title","subtitle").Where("title like ?",ctitle+"%").Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": courses,
+		})
+	}
+}
+
+//新建
+func PutCourse(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		title := c.Query("title")
+		status1,err := strconv.ParseInt(c.Query("status"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("title:"+title)
+
+		newCouse := &Course{
+			Title:   title,
+			Status: int(status1),
+			Teacher:1,
+			Creator:1,
+		}
+		_, err = db.Model(newCouse).Insert()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"new-Ok- hello "+title,
+		})
+	}
+}
+
+//改
+func PostCourse(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		var form Course
+
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		_,err := db.Model(&form).Table("courses").Column("title","subtitle","summary","teacher","lang","speech_lang","status","content").WherePK().Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"update ok",
+		})
+	}
+}
+
+
+//补
+func PatchLessonNumInCousrse(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		var form Course
+
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		_, err := db.Model(&form).Column("lesson_num").WherePK().Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"patch ok",
+		})
+	}
+}
+//删
+func DeleteCourse(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		id,err := strconv.Atoi(c.Param("cid"))
+		if err != nil {
+			panic(err)
+		}
+		course := &Course{
+			Id:   id,
+		}
+		_, err = db.Model(course).WherePK().Delete()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"delete "+c.Param("cid"),
+		})
+	}
+}

+ 90 - 4
api/mint/demo.go

@@ -2,7 +2,8 @@ package mint
 
 import (
 	"net/http"
-
+	"strconv"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/go-pg/pg/v10"
 )
@@ -12,15 +13,21 @@ type Login struct {
 	Password string `form:"password" json:"password" binding:"required"`
 }
 
+type User struct{
+    Id     int64
+    Name   string
+    Emails []string
+}
 func LoginDemo(_db *pg.DB) gin.HandlerFunc {
+		
 	return func(c *gin.Context) {
 		// TODO 在这里进行db操作
 		var form Login
+
 		if err := c.ShouldBindJSON(&form); err != nil {
 			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
 			return
 		}
-
 		if form.User != "manu" || form.Password != "123" {
 			c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
 			return
@@ -32,15 +39,94 @@ func LoginDemo(_db *pg.DB) gin.HandlerFunc {
 	}
 }
 
+//查询
 func GetDemo(db *pg.DB) gin.HandlerFunc {
 	return func(c *gin.Context) {
+		userid,err := strconv.ParseInt(c.Param("id"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("get demo")
 		// TODO 在这里进行db操作
-		_, err := db.Exec("SELECT CURRENT_TIMESTAMP")
+		// Select user by primary key.
+		user := &User{Id: userid}
+		err = db.Model(user).WherePK().Select()
 		if err != nil {
 			panic(err)
 		}
+		
 		c.JSON(http.StatusOK, gin.H{
-			"message": "pong",
+			"message": "user-"+user.Name,
+		})
+	}
+}
+func PostDemo(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		name := c.DefaultQuery("name","guest")
+		password := c.Query("password")
+		c.JSON(http.StatusOK,gin.H{
+			"message": "name="+name+" password="+password,
+		})
+	}
+}
+
+//增加
+func PutDemo(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		name := c.Query("name")
+		email := c.Query("emails")
+
+		user1 := &User{
+			Name:   name,
+			Emails: []string{email},
+		}
+		_, err := db.Model(user1).Insert()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"new-Ok- hello "+name,
 		})
 	}
 }
+//改
+func PatchDemo(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		userid,err := strconv.ParseInt(c.Param("id"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		email := c.Query("emails")
+		user1 := &User{
+			Id:   userid,
+			Emails: []string{email},
+		}
+		//_, err = db.Model(user1).WherePK().Update()
+		_, err = db.Model(user1).Set("emails = ?emails").Where("id = ?id").Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"-patch="+email,
+		})
+	}
+}
+//删
+func DeleteDemo(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		userid,err := strconv.ParseInt(c.Param("id"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		user1 := &User{
+			Id:   userid,
+		}
+		_, err = db.Model(user1).Where("id = ?", userid).Delete()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"delete "+c.Param("id"),
+		})
+	}
+}

+ 200 - 0
api/mint/lesson.go

@@ -0,0 +1,200 @@
+package mint
+
+import (
+	"net/http"
+	"io/ioutil"
+	/*"strings"*/
+	"bytes"
+	"encoding/json"
+	"strconv"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pg/pg/v10"
+	"time"
+)
+
+type Lesson struct {
+	Id     int `form:"id" json:"id" binding:"required"`
+	CourseId     int `form:"course_id" json:"course_id" binding:"required"`
+	Cover string
+	Title string `form:"title" json:"title" binding:"required"`
+	Subtitle string `form:"subtitle" json:"subtitle" binding:"required"`
+	Summary string `form:"summary" json:"summary" binding:"required"`
+	Teacher int `form:"teacher" json:"teacher" binding:"required"`
+	Lang string `form:"lang" json:"lang" binding:"required"`
+	Speech_lang string `form:"speech_lang" json:"speech_lang" binding:"required"`
+	Status int `form:"status" json:"status" binding:"required"`
+	Content string `form:"content" json:"content" binding:"required"`
+	Creator int
+	StartDate time.Time `form:"date" json:"date" binding:"required"`
+    Duration int64 `form:"duration" json:"duration" binding:"required"` 
+	Version int64
+    CreatedAt time.Time
+    UpdatedAt time.Time
+}
+//查询
+func GetLesson(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		lid,err := strconv.ParseInt(c.Param("lid"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		fmt.Println("get lesson")
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		lesson := &Lesson{Id: int(lid)}
+		err = db.Model(lesson).WherePK().Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": "lesson-"+lesson.Title,
+		})
+	}
+}
+
+//查询
+func GetLessonByTitle(db *pg.DB) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		title:= c.Param("ltitle")
+
+		// TODO 在这里进行db操作
+		// Select user by primary key.
+		var lessons []Lesson
+		err := db.Model(&lessons).Column("id","title","subtitle").Where("title like ?",title+"%").Select()
+		if err != nil {
+			panic(err)
+		}
+		
+		c.JSON(http.StatusOK, gin.H{
+			"message": lessons,
+		})
+	}
+}
+
+/*新建
+新建课以后,查询这个course 里有几个lesson 然后更新 courese 的 lesson_num
+*/
+//PUT http://127.0.0.1:8080/api/lesson?title=lesson-one&course_id=1&status=10
+func PutLesson(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+	
+		title := c.Query("title")
+		courseId,err := strconv.Atoi(c.Query("course_id"))
+		status1,err := strconv.Atoi(c.Query("status"))
+		if err != nil {
+			panic(err)
+		}
+
+		newLesson := &Lesson{
+			Title:   title,
+			CourseId: courseId,
+			Status: status1,
+			Teacher:0,
+			Creator:1,
+		}
+		_, err = db.Model(newLesson).Insert()
+		if err != nil {
+			panic(err)
+		}
+		//修改 course 的 lesson_num
+		courseMessage := _updateLessonCount(db,courseId)
+		
+		c.JSON(http.StatusOK,gin.H{
+			"message":courseMessage,
+		})
+	}
+}
+
+func _updateLessonCount(db *pg.DB,courseId int) string{
+			//查询这个course 里面有几个课程
+			countLesson, err := db.Model((*Lesson)(nil)).Where("course_id = ?",courseId).Count()
+			if err != nil {
+				panic(err)
+			}		
+	
+			//修改course lesson number
+			url := "http://127.0.0.1:8080/api/course/lessonnum"
+			values := Course{
+				Id : courseId,
+				LessonNum : countLesson,
+			}
+			json_data, err := json.Marshal(values);
+			if err != nil {
+				panic(err)
+			}
+	
+			client := &http.Client{}
+			req, err := http.NewRequest("PATCH",url, bytes.NewBuffer(json_data))
+			if err != nil {
+				panic(err)
+			}
+			req.Header.Set("Content-Type","application/json")
+			resp,err := client.Do(req)
+			if err != nil {
+				panic(err)
+			}
+			 defer resp.Body.Close()
+			b, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				panic(err)
+			}
+	
+		return(string(b))
+}
+
+//改
+func PostLesson(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		var form Lesson
+
+		if err := c.ShouldBindJSON(&form); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+			return
+		}
+
+		_,err := db.Model(&form).Table("lessons").Column("title","subtitle","summary","teacher","tag","lang","speech_lang","status","content","start_date","duration").WherePK().Update()
+		if err != nil {
+			panic(err)
+		}
+		c.JSON(http.StatusOK,gin.H{
+			"message":"update ok",
+		})
+	}
+}
+
+
+//删
+func DeleteLesson(db *pg.DB) gin.HandlerFunc{
+	return func(c *gin.Context){
+		id,err := strconv.ParseInt(c.Param("lid"),10,64)
+		if err != nil {
+			panic(err)
+		}
+		lesson := &Lesson{
+			Id:int(id),
+			CourseId: int(0) ,
+		}
+		//删之前获取 course_id
+		err = db.Model(lesson).Column("course_id").WherePK().Select()
+		if err != nil {
+			panic(err)
+		}
+		course_id := lesson.CourseId
+
+		_, err = db.Model(lesson).WherePK().Delete()
+		if err != nil {
+			panic(err)
+		}
+
+		//修改 course 的 lesson_num
+		courseMessage := _updateLessonCount(db,course_id)
+
+	
+		c.JSON(http.StatusOK,gin.H{
+			"message":"delete "+c.Param("lid"),
+			"lesson_num":courseMessage,
+		})
+	}
+}

+ 0 - 0
documents/图标.md → app/public/images/图标.md


+ 7 - 6
dashboard/src/pages/index.tsx

@@ -1,9 +1,10 @@
 
 
-export default function IndexPage() {
-  return (
-    <div>
-      <h1>Page index</h1>
-    </div>
-  );
+export default function IndexPage(props) {
+	console.log(props.location)
+	return (
+		<div>
+			<h1>Page index</h1>
+		</div>
+	);
 }

+ 2 - 0
db/migrations/2021-07-06-125510_create-users/down.sql

@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+DROP TABLE users

+ 7 - 0
db/migrations/2021-07-06-125510_create-users/up.sql

@@ -0,0 +1,7 @@
+-- Your SQL goes here
+CREATE TABLE users
+(
+id int,
+name varchar(255),
+emails varchar(255)
+)

+ 3 - 0
db/migrations/2021-07-09-125349_new_course/down.sql

@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+DROP TABLE courses ;
+DROP TABLE lessons ;

+ 42 - 0
db/migrations/2021-07-09-125349_new_course/up.sql

@@ -0,0 +1,42 @@
+-- Your SQL goes here
+
+CREATE TABLE courses
+( 
+    id SERIAL PRIMARY KEY, 
+    cover VARCHAR(255), 
+    title VARCHAR(32) NOT NULL, 
+    subtitle VARCHAR(32),
+    summary VARCHAR(255),
+    teacher INTEGER NOT NULL, 
+    lang VARCHAR (8), 
+    speech_lang VARCHAR (8), 
+    status INTEGER NOT NULL DEFAULT(0), 
+    lesson_num INTEGER NOT NULL DEFAULT(0), 
+    content TEXT ,  
+    creator INTEGER NOT NULL, 
+    version INTEGER,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TABLE lessons
+(
+    id SERIAL PRIMARY KEY, 
+    course_id INTEGER NOT NULL,
+    course_uuid VARCHAR(36),
+    title VARCHAR(32) NOT NULL, 
+    subtitle VARCHAR(32), 
+    summary VARCHAR(255), 
+    status INTEGER  NOT NULL DEFAULT(0), 
+    cover VARCHAR(255), 
+    teacher INTEGER, 
+    lang VARCHAR(8), 
+    speech_lang VARCHAR(8), 
+    start_date TIMESTAMP, 
+    duration INTEGER, 
+    content TEXT,
+    creator INTEGER  NOT NULL,    
+    version INTEGER,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);

+ 3 - 0
db/migrations/2021-07-15-131154_create_article/down.sql

@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+
+DROP TABLE articles

+ 18 - 0
db/migrations/2021-07-15-131154_create_article/up.sql

@@ -0,0 +1,18 @@
+-- Your SQL goes here
+
+CREATE TABLE articles (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    content      TEXT,
+    owner_id     INTEGER  NOT NULL,
+    owner        VARCHAR (36),
+    setting      JSON,
+    status       INTEGER   NOT NULL DEFAULT (10),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);

+ 3 - 0
db/migrations/2021-07-16-010532_create_collection/down.sql

@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+
+DROP TABLE collections

+ 18 - 0
db/migrations/2021-07-16-010532_create_collection/up.sql

@@ -0,0 +1,18 @@
+-- Your SQL goes here
+
+CREATE TABLE collections (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    article_list TEXT,
+    status       INTEGER   NOT NULL DEFAULT (10),
+    creator_id   INTEGER,
+    owner        VARCHAR (36),
+    lang         CHAR (8),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);

+ 3 - 0
db/migrations/2021-07-16-130715_collection_article_list/down.sql

@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+
+DROP TABLE collection_article_lists

+ 8 - 0
db/migrations/2021-07-16-130715_collection_article_list/up.sql

@@ -0,0 +1,8 @@
+-- article 关联表
+CREATE TABLE article_lists (
+    id SERIAL PRIMARY KEY,
+    collection_id    INTEGER NOT NULL ,
+    article_id    INTEGER  NOT NULL ,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+

+ 0 - 0
dicttext/readme.md


+ 0 - 225
documents/development/functions.md

@@ -1,225 +0,0 @@
-# 说明
-
-本文档是网站页面的功能介绍。每个功能模块包含四个部分的描述:
-
-- 已经实现的功能能
-- 需要完善的功能
-- 尚未实现的功能(目前的需求)
-- 未来可能的发展(后续版本可能添加的功能)
-
-紧迫程度由低到高。
-
-# PCD Suite 设计原则
-
-- **可重用的数据** 从逐词解析到整篇译文。所有的数据应该是可重用的。可重用意味着在技术层面应该存储计算机可辨识的格式的数据。
-
-```
-应该存储
-{
-    word:"citta",
-    grammar:"nt.",
-    meaning:['心','缤纷']
-}
-
-不应存储
-citta:中性 心;缤纷;
-```
-
-- **智能重用** 程序应根据经文类型(经藏或律藏)或其他特征,提供提供不同的数据给用户。或将数据列表按信心指数排序。以减少不必要的人工劳动。
-- **公共版权** 有版权的信息与前两条原则违背。所以,一切在本平台公开的数据都应使用公共版权。
-- **平等的发言权** 每个平台的使用者都有权发表自己的观点。平台不应以官方的角度用人工的方式评价观点的正确性或给予排名靠前或靠后的操作。但是平台应该记录和向所有人提供统计数据,如:信息发布者的使用经验数值(使用平台时间,发表信息量,被点赞量等),阅读者的阅读数据(阅读量,收藏量)供阅读者自己判断信息的可用性。没有实质内容的信息(如:“很好”;“太差了”等)将对读者造成困扰,增加读者搜寻有用信息的时间。管理员应根据判定规则,将信息隐藏。在读者选择“查看隐藏的内容”时展示。
-
-# 程序架构设计
-
-- 除了对安全性和性能要求较高的部分以外。业务逻辑应尽量放在前端。
-- 所有前端业务逻辑功能应该由扩展(extension)提供。
-- 系统应提供可扩展的内核框架。供扩展调用。以实现相关功能及业务逻辑。
-- 扩展可由本软件的编写者或其他人创建和维护。
-- 任何人创建的扩展无需通过 pr 挂接系统。
-- 任何人创建的扩展应该由创建者在平台上注册和上传,供用户自行选择使用。
-- 平台的创建者应提供最基本的扩展。
-- 所有后端功能不使用公开上传的方式扩展功能。应使用 pr and review 方式。
-- 扩展程序只能包含 js css setting.json 和少量图片
-
-# 平台结构 map
-
-- 藏经阁-Libray
-  - 首页
-  - 课程
-  - 三藏
-  - 字典
-  - 搜索
-  - 个人空间
-- 译经楼-Studio
-  - 三藏分类
-  - 我的文档(最近打开)
-  - 协作文档
-  - 群组管理
-  - 课程管理
-  - 单词本
-  - 百科词条
-  - 统计数据
-- 用户中心- User Center
-  - 注册
-  - 登陆
-  - 个性化设置
-- 实用工具
-  - 佛历
-  - 圣典编码转换
-- 后台管理
-  - 栏目管理
-  - 用户管理
-  - 数据表管理
-
-# 藏经阁-Libray
-
-## 首页
-
-www.wikipali.org
-
-### 已经实现的功能能
-
-- 最新课程列表
-- 最新百科词条列表
-
-### 需要完善的功能
-
-#### 最新课程列表
-
-- 返回数量是写死的。应该在栏目后台里可以设置。
-
-### 尚未实现的功能(目前的需求)
-
-- **最新课程列表**-报名数字显示和报名功能
-
-- 最新三藏译文列表
-
-- 手机版 css
-  - 写不同的 css 在手机端和 pc 看到不同的页面。
-  - 不一定用 css 切换,可以使用不同的技术实现方式。
-
-### 未来可能的发展
-
-- 实现类似 tweet 的文章推荐功能。根据用户阅读行为推荐不同类型和内容的文章。
-- 文章类型
-  - 逐词解析单词
-  - 词典词条
-  - 百科词条
-  - 句子
-  - 段落
-  - 章节
-- 文章属性标签
-  - 译文
-  - 新手试验田
-  - 雅正(希望大家提修改意见)
-  - 求助
-- 应用场景
-  - 当有学习者不知道某个词的拆分,他在编辑器(studio)中单词的位置选择“求助”按钮。会发布一个带有“求助”标签的“逐词解析”类型的文章。某老师或网友看到求助文章,可以以跟帖的方式回答。
-  - 某人翻译了一篇经文。希望大家给个修改意见。他在编辑器(studio)中标题的位置选择“发布”按钮,发布带有“雅正;译文;”标签的“段落”类型的文章。某老师或网友看到文章,可以以跟帖的方式回答。
-
-## 三藏分类
-
-www.wikipali.org/palicanon
-
-### 已经实现的功能能
-
-- 章节标签过滤
-- 在阅读器中打开章节
-
-### 需要完善的功能
-
-### 尚未实现的功能(目前的需求)
-
-### 未来可能的发展
-
-## 课程
-
-### 已经实现的功能能
-
-### 需要完善的功能
-
-### 尚未实现的功能(目前的需求)
-
-### 未来可能的发展
-
-## 百科
-
-### 已经实现的功能能
-
-### 需要完善的功能
-
-### 尚未实现的功能(目前的需求)
-
-### 未来可能的发展
-
-## 字典
-
-## 标题搜索
-
-## 全文搜索
-
-## 黑体字搜索
-
-## 经典阅读器
-
-# 译经楼 Studio
-
-## 欢迎页
-
-## 经文选择
-
-## 最近打开
-
-## 协作
-
-## 课程管理
-
-## 用户字典管理
-
-## 百科字典管理
-
-## 工作组管理
-
-# 用户中心
-
-## 登录
-
-## 注册
-
-## 用户设置
-
-# 网站后台管理
-
-## 栏目管理
-
-### 首页
-
-### 三藏
-
-### 课程
-
-### 百科
-
-### 字典
-
-### 搜索
-
-### 阅读器
-
-### 用户管理
-
-#### 修改权限
-
-#### 禁用账号
-
-### 数据表管理
-
-#### 查看
-
-#### 统计
-
-#### 添加
-
-#### 删除
-
-# 数据表与模块关系

+ 0 - 0
documents/about.md → documents/readme.md


+ 83 - 0
documents/zh/api/article.md

@@ -0,0 +1,83 @@
+# article
+
+## article 文章
+
+```table
+CREATE TABLE articles (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    content      TEXT,
+    owner_id     INTEGER  NOT NULL,
+    owner        VARCHAR (36),
+    setting      JSON,
+    status       INTEGER   NOT NULL DEFAULT (10),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+```
+
+`uuid` 旧表中的主键
+
+`setting` json 格式。文章设置
+
+### API
+	
+`GET /api/article/:aid`
+根据id查询
+	
+`GET /api/article/title/:title`
+输入标题查询符合条件的 title% 
+	
+`PUT /api/article`
+
+新建文章
+`POST /api/article`
+修改
+
+`DELETE /api/article/:aid`
+删除
+
+## article_list 关联表
+
+```table
+CREATE TABLE collection_article_lists (
+    id SERIAL PRIMARY KEY,
+    collect_id    INTEGER NOT NULL REFERENCES collections (id),
+    article_id    INTEGER  NOT NULL REFERENCES articles (id),
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+);
+```
+
+article 和 collect 的关联表
+
+
+## 文集
+
+```table
+CREATE TABLE collections (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36) ,
+    title        VARCHAR (32) NOT NULL,
+    subtitle     VARCHAR (32),
+    summary      VARCHAR (255),
+    article_list TEXT,
+    status       INTEGER   NOT NULL DEFAULT (10),
+    creator_id   INTEGER,
+    owner        VARCHAR (36),
+    lang         CHAR (8),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+`uuid` 旧表中的主键
+
+`creator_id` 创建者。原来的表中是 owner uuid 导入后更新为int 然后删除owner

+ 23 - 0
documents/zh/api/channel.md

@@ -0,0 +1,23 @@
+# channel
+
+```table
+CREATE TABLE channal (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36),
+    owner_id     INTEGER NOT NULL,
+    owner        VARCHAR (36) NOT NULL,
+    name         VARCHAR (32),
+    summary      VARCHAR (255),
+    status       INTEGER,
+    lang         VARCHAR (8),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+`owner` VARCHAR (36) NOT NULL
+
+最初的创建者。
+旧表中的用户 id uuid。新表中改用 owner_id(int)。

+ 61 - 0
documents/zh/api/course.md

@@ -0,0 +1,61 @@
+# Course 课程
+
+## Table
+
+```
+CREATE TABLE courses
+(
+    id SERIAL PRIMARY KEY,
+    cover VARCHAR(255),
+    title VARCHAR(32) NOT NULL,
+    subtitle VARCHAR(32),
+    summary VARCHAR(255),
+    teacher INTEGER NOT NULL,
+    lang VARCHAR (8),
+    speech_lang VARCHAR (8),
+    status INTEGER NOT NULL DEFAULT(0),
+    lesson_num INTEGER NOT NULL DEFAULT(0),
+    content TEXT ,
+    creator INTEGER NOT NULL,
+    version INTEGER,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+```
+CREATE TABLE lessons
+(
+    id SERIAL PRIMARY KEY,
+    course_id INTEGER NOT NULL,
+    course_uuid VARCHAR(36),
+    title VARCHAR(32) NOT NULL,
+    subtitle VARCHAR(32),
+    summary VARCHAR(255),
+    status INTEGER  NOT NULL DEFAULT(0),
+    cover VARCHAR(255),
+    teacher INTEGER,
+    lang VARCHAR(8),
+    speech_lang VARCHAR(8),
+    start_date TIMESTAMP,
+    duration INTEGER,
+    content TEXT,
+    creator INTEGER  NOT NULL,
+    version INTEGER,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+## API
+
+GET /api/course/:cid
+PUT /api/course/?data=data
+POST /api/course/:cid/?data=data
+DELETE /api/course/:cid
+
+GET /api/lesson/:lid
+GET /api/lessons/:cid
+PUT /api/lesson/?data=data
+POST /api/lesson/:lid/?data=data
+DELETE /api/lesson/:lid

+ 25 - 0
documents/zh/api/deploy.md

@@ -0,0 +1,25 @@
+# 运维
+
+```table
+CREATE TABLE setting (
+    [key]     VARCHAR(32) PRIMARY KEY,
+    value     VARCHAR(64) NOT NULL,
+    [default] VARCHAR(64)
+);
+```
+## 逐词解析编辑消息message
+```table
+CREATE TABLE message (
+    id        INTEGER   PRIMARY KEY AUTOINCREMENT,
+    sender    TEXT      NOT NULL,
+    user_id    INTEGER      NOT NULL,
+    type      INTEGER   NOT NULL,
+    book      INTEGER,
+    paragraph INTEGER,
+    data      TEXT,
+    doc_id    VARCHAR (36),
+    time      BIGINT
+);
+```
+
+`time` 消息发送时间

+ 210 - 0
documents/zh/api/dict.md

@@ -0,0 +1,210 @@
+# 用户逐词解析字典
+```table
+CREATE TABLE user_wbw_dicts (
+    id SERIAL PRIMARY KEY,
+    pali        TEXT    NOT NULL,
+    type        TEXT,
+    gramma      TEXT,
+    parent      TEXT,
+    mean        TEXT,
+    note        TEXT,
+    factors     TEXT,
+    factormean  TEXT,
+    status      INTEGER,
+    lang    VARCHAR(8),
+    confidence  INTEGER DEFAULT (100),
+    creator     INTEGER NOT NULL,
+    ref_counter INTEGER DEFAULT (1) 
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+    updated_at TIMESTAMP NOT NULL
+
+);
+
+//引用索引
+CREATE TABLE user_wbw_dict_indexs (
+    id SERIAL PRIMARY KEY,
+    word_index  INTEGER NOT NULL,
+    user_id     INTEGER NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+);
+
+```
+
+
+## API
+### 存储一个单词
+`PUT /api/dict/user`
+
+body
+```
+{
+    "pali":string
+    "type":string
+    gramma:string
+    parent:string
+    mean:string
+    note:string
+    parts:string
+    partmean:string
+    lang:string
+    confidence:int (1-10)
+}
+```
+>提交时查重。如果    pali:
+    type:
+    gramma:
+    parent:
+    mean:
+    note:
+    factors:
+    factormean:
+合在一起有重复,就、改变引用次数,并更新引用索引。没有重复,添加新纪录。
+
+### 查社区字典
+`GET /api/dict/wbw/word/:word`
+返回值:
+```json
+[
+    {
+        "id":int,
+        "word":string,
+        "type":string,
+        "gramma":string,
+        "mean":string,
+        "parent":string,
+        "parts":string,
+        "creator":string,
+        "ref_count":int,
+    }
+]
+```
+
+# 系统字典+第三方字典
+
+字段同逐词解析字典。原始数据[csv文件](/dicttext/readme.md)。全部导入redis。
+
+# 参考字典
+
+>PCED 中的字典
+
+```table
+CREATE TABLE dict_ref (
+    id SERIAL PRIMARY KEY,
+    lang VARCHAR(8),
+    dict_id  INTEGER,
+    eword    VARCHAR(255),
+    word     VARCHAR(255),
+    mean     TEXT
+);
+```
+字典名称表
+
+```table
+CREATE TABLE dict_ref_name (
+    id SERIAL PRIMARY KEY,
+    lang VARCHAR(8),
+    shortname VARCHAR(16),
+    name      VARCHAR(255)
+);
+```
+## API
+
+### 词头列表
+`GET /api/dict/ref/head/:word`
+返回值:
+```json
+[
+    {
+        "id":int,
+        "word":string,
+        "count"int,
+    }
+]
+```
+### 简要意思列表
+`GET /api/dict/ref/firstmean`
+参数:?lang=en word=word1,word2……wordn
+
+返回值:
+```json
+[
+    {
+        "id":int,
+        "word":string,
+        "count"int,
+    }
+]
+```
+
+### 单词查询
+
+`GET /api/dict/ref/word/:word`
+
+返回值:
+```json
+[
+    {
+        "id":int,
+        "word":string,
+        "dict_id":int,
+        "mean":string,
+    }
+]
+```
+
+### 内文查询
+
+`GET /api/dict/ref/content/:word`
+
+返回值:
+```json
+[
+    {
+        "id":int,
+        "word":string,
+        "dict_id":int,
+        "mean":string,
+    }
+]
+```
+
+# 逐词解析自动查字典
+>逐词解析以两种方式查字典。按照段落,和单个单词。段落匹配用于逐词解析批量查词填充。查单个单词用于鼠标移入单词区域或拆分改变。
+
+## API
+
+### 以段落为单位查词
+
+`GET /api/dict/wbw/para/:book/:para`
+
+返回:
+```json
+[
+    {
+        "pali":"value",
+        "type":"value",
+        "gramma":"value",
+        "mean":"value",
+        "parts":"value",
+        "partmean":"value",
+        "note":"value",
+        "lang":"value",
+        "pali":"value",
+        "pali":"value",
+        "pali":"value",
+    }
+]
+```
+
+### 以单词为单位查
+
+`GET /api/dict/wbw/word`
+
+参数:?word=word1,word2……wordn
+
+返回:
+
+与以段落为单位查词相同
+
+
+

+ 52 - 0
documents/zh/api/group.md

@@ -0,0 +1,52 @@
+# group
+
+## group_info
+
+```table
+CREATE TABLE group_info (
+    id          int    PRIMARY KEY,
+    uuid        VARCHAR (36) ,
+    name        VARCHAR (32)    NOT NULL,
+    description TEXT,
+    status      INTEGER,
+    owner_id    INTEGER,
+    owner       VARCHAR (36),
+    create_at BIGINT      NOT NULL,
+    update_at BIGINT NOT NULL,
+    delete_at BIGINT 
+);
+```
+
+`owner`       VARCHAR (36),
+
+最初创建者
+旧表中用uuid 新表用 int 取代。数据迁移后删除。
+
+`uuid`        VARCHAR (36) ,
+
+旧表中的主键用uuid 新表用 int 取代。新表中保留此uuid。
+
+## group_member
+```table
+CREATE TABLE group_member (
+    id         INTEGER   PRIMARY KEY AUTOINCREMENT,
+    user_id    CHAR (36) NOT NULL,
+    group_id   INTEGER   NOT NULL,
+    power      INTEGER   NOT NULL
+                         DEFAULT (1),
+    group_name CHAR (32),
+    level      INTEGER   DEFAULT (0),
+    status     INTEGER   DEFAULT (1) 
+);
+```
+`user_id` 原表中用uuid  新表替换为 int
+
+`group_name` 与 group_info中的name相同
+
+`power` 目前没有使用
+
+`level` 目前没有使用
+
+`status` 
+- 0-禁用
+- 1-正常

+ 8 - 9
documents/zh/palicanon.md → documents/zh/api/palicanon.md

@@ -1,20 +1,18 @@
-# 主题:Palicanon-巴利三藏 
+# 主题:语料库
 
-## API
-
-### book_tag.php
-
-#### 功能
+## 用标签查段落
+> 参照:book_tag.php
+### 功能
 根据输入标签,输出符合这个标签的标题
-#### 参数
+### 参数
 - GET
 - `tag` 以逗号分隔的标签字符串
 - `lang`  语言 如 en, zh-hans
   
-#### rest api
+### rest api
     api/palicanon/[lang]/[tag]
 
-#### 返回
+### 返回
 
 格式:json
 ```
@@ -37,3 +35,4 @@
 - `progress`: int 章节译文完成度  0-100
 - `trans_title` string, 根据lang查找对应的标题 如果没有查询到 无该变量
 
+## 

+ 77 - 0
documents/zh/api/readme.md

@@ -0,0 +1,77 @@
+# 后端开发文档
+
+## 开发环境
+
+-   golang
+-   PostgreSQL
+-   Redis
+-   ES
+
+给 vscode 用的 go
+
+```
+sudo apt install yarnpkg golang-go
+```
+
+## 文档资源
+
+## 依赖
+
+https://github.com/go-redis/redis
+
+## 目录
+
+-   [版本](channel.md)
+-   [课程](course.md)
+-   [字典](dict.md)
+-   [工作组](group.md)
+-   [语料库](palicanon.md)
+-   [术语](term.md)
+-   [译文](translation.md)
+-   [文章文集](article.md)
+-   [用户](user.md)
+-   [逐词解析](wbw.md)
+-   [全文搜索](search.md)
+-   [其他工具表](others.md)
+
+```mermaid
+graph LR
+subgraph 后端
+    subgraph channel版本
+    channel[("channel")]
+    end
+    subgraph article文章
+    article[("article")]
+    article_list[("article_list")]
+    collection[("collection")]
+    end
+end
+
+subgraph 前端
+    subgraph 文集
+    collection_home("著作首页")
+    article_reader("文章阅读")
+    collection_edit("著作编辑")
+    article_edit("文章编辑")
+    end
+end
+collection_home --> collection
+collection_home --> article
+article_reader --> article
+article_reader --> collection
+article_reader --> article_list
+collection_edit --> collection
+article_edit  --> article
+```
+
+## 数据表设计
+
+数据表应包含如下字段
+
+```
+    id SERIAL PRIMARY KEY,
+    version     INTEGER NOT NULL DEFAULT (1),
+    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    deleted_at  TIMESTAMP //可选
+```

+ 0 - 0
documents/zh/api/search.md


+ 65 - 0
documents/zh/api/share.md

@@ -0,0 +1,65 @@
+# share
+
+```table
+CREATE TABLE share_cooperator (
+    id SERIAL PRIMARY KEY,
+    res_id          INTEGER NOT NULL,
+    res_uuid          VARCHAR (36),
+    res_type        INTEGER,
+    cooperator_id   INTEGER NOT NULL,
+    cooperator_uuid   VARCHAR (36),
+    cooperator_type INTEGER NOT NULL,
+    right           INTEGER NOT NULL DEFAULT 0,
+    version INTEGER NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL
+);
+```
+分享资源给用户或者群组。
+
+`res_id` 资源id 原来的表中是uuid 导入后改为 int
+
+`res_type` 资源类型 
+1. channel
+2. wbw doc
+3. article
+4. collection
+   
+`cooperator_id` 用户或工作组id
+
+`cooperator_type` 
+1. 用户
+2. 工作组
+
+`right` 权限
+1. 只读
+2. 可写
+3. 拥有者
+
+
+
+
+```table
+CREATE TABLE share_link (
+    id SERIAL PRIMARY KEY,
+    link_id     VARCHAR (36) UNIQUE,
+    res_id      INTEGER NOT NULL,
+    res_type    INTEGER,
+    right       INTEGER,
+    version INTEGER NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL
+);
+```
+
+分享资源链接
+
+`link_id` uuid
+
+`res_id` 资源id 原来的表中是uuid 导入后改为 int
+
+`res_type` 资源类型 
+1. channel
+2. wbw doc
+3. article
+4. collection

+ 22 - 0
documents/zh/api/term.md

@@ -0,0 +1,22 @@
+# 术语
+
+```table
+CREATE TABLE terms (
+    id SERIAL PRIMARY KEY,
+    uuid          VARCHAR (36),
+    word          VARCHAR (256),
+    word_en       VARCHAR (256),
+    tag           VARCHAR (128),
+    meaning       TEXT,
+    other_meaning TEXT,
+    note          TEXT,
+    channal       VARCHAR (36),
+    owner         VARCHAR (36),
+    lang          VARCHAR (8),
+    hit           INTEGER  DEFAULT (0),
+	version     INTEGER NOT NULL DEFAULT (1),
+    deleted_at  TIMESTAMP,
+    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```

+ 122 - 0
documents/zh/api/translation.md

@@ -0,0 +1,122 @@
+# 译文
+
+## 句子块 sent_block
+
+```table
+CREATE TABLE sent_block (
+    id SERIAL PRIMARY KEY,
+    uuid         VARCHAR (36),
+    parent_id    VARCHAR (36),
+    book         INTEGER,
+    paragraph    INTEGER,
+    owner_id     INTEGER NOT NULL,
+    owner        VARCHAR (36) NOT NULL,
+    lang         VARCHAR (8),
+    author       VARCHAR (50),
+    editor_id    INTEGER,
+    editor       TEXT,
+    status       INTEGER,
+    create_at  BIGINT,
+    update_at  BIGINT,
+    delete_at  BIGINT
+);
+```
+
+`book` 书号
+
+`paragraph` 书号
+
+`author`
+
+编辑者列表。还没设计好。 可能是这样
+
+```
+[
+    {"creater":"bhikkhu bodhi"},
+    {"translater":"bhikkhu kosalla"},
+]
+```
+
+`editor` 数据提交者 旧表中用 user_name 新表用 editor_id
+
+`owner` 记录的创建者
+
+## sentence
+
+```table
+CREATE TABLE sentence (
+    id           int PRIMARY KEY,
+    uuid           CHAR (36) ,
+    parent       CHAR (36),
+    block_id     CHAR (36),
+    channel_id      CHAR (36),
+    book         INTEGER   NOT NULL,
+    paragraph    INTEGER   NOT NULL,
+    start      INTEGER   NOT NULL,
+    end        INTEGER   NOT NULL,
+    author       TEXT,
+    editor_id       CHAR (36),
+    text         TEXT,
+    language     CHAR (8),
+    version      INTEGER,
+    status       INTEGER,
+    strlen       INTEGER,
+    create_at    BIGINT  NOT NULL,
+    update_at    BIGINT   NOT NULL,
+    delete_at    BIGINT,
+
+);
+```
+
+`uuid` 原表的主键 新表中用 int 代替
+
+`channel_id` 外键 原表 channal uuid 导入后应改为 int
+
+`editor_id` 记录的上传者 外键 原表用 uuid 现在改用 int
+
+`text` 句子文本
+
+`version` 用于乐观锁 每次更新+1
+
+`strlen` 句子字符数
+
+```table
+CREATE TABLE sent_pr (
+    id           INTEGER      PRIMARY KEY AUTOINCREMENT,
+    book         INTEGER      NOT NULL,
+    paragraph    INTEGER      NOT NULL,
+    start      INTEGER      NOT NULL,
+    end        INTEGER      NOT NULL,
+    channel_id      VARCHAR (36),
+    author       VARCHAR (40),
+    editor_id       VARCHAR (36),
+    text         TEXT,
+    language     VARCHAR (8),
+    status       INTEGER,
+    strlen       INTEGER,
+    create_at    BIGINT  NOT NULL,
+    update_at    BIGINT   NOT NULL,
+    delete_at    BIGINT,
+);
+
+```
+
+# 修改历史
+
+```table
+CREATE TABLE sent_historay (
+    sent_id  CHAR (36),
+    user_id  CHAR (36),
+    text     TEXT,
+    create_at     BIGINT NOT NULL,
+    landmark VARCHAR(32)
+);
+```
+
+`sent_id` 外键 导入后改为 int
+
+`user_id` 外键 导入后改为 int
+
+`text` 句子文本
+
+`landmark` 里程碑标记

+ 171 - 0
documents/zh/api/user.md

@@ -0,0 +1,171 @@
+# 用户
+
+## users
+
+用户信息
+
+旧表:user_info
+
+```
+CREATE TABLE users (
+    id           INTEGER    PRIMARY KEY AUTOINCREMENT,
+    userid       TEXT       UNIQUE,
+    path         CHAR (36),
+    username     TEXT (64)  NOT NULL,
+    password     TEXT       NOT NULL,
+    nickname     TEXT (64)  NOT NULL,
+    email        TEXT (256),
+    create_time  INTEGER,
+    modify_time  INTEGER,
+    receive_time INTEGER,
+    setting      TEXT
+);
+```
+
+#### `id`
+
+INTEGER 唯一自增 id
+
+#### `userid`
+
+CHAR (36) uuid
+
+#### `path`
+
+CHAR (36) 用户在服务器上私有文件的路径
+
+#### `username`
+
+TEXT (64) 用户登录名
+
+#### `password`
+
+TEXT 密码 md5 加密
+
+#### `nickname`
+
+TEXT (64) 昵称
+
+#### `email`
+
+TEXT (256) 电邮地址
+
+#### create_time
+
+INTEGER 账户建立时间
+
+#### `modify_time`
+
+INTEGER 数据修改时间
+
+#### `receive_time`
+
+INTEGER 服务器收到此数据时间
+
+#### `setting`
+
+TEXT 用户设置 json 数据
+
+## profile
+
+用户简历
+
+```
+CREATE TABLE user_profile (
+    id SERIAL PRIMARY KEY,
+    user_id   CHAR (36),
+    bio       TEXT,
+    lang      CHAR (8),
+    isdefault INTEGER,
+    email     TEXT
+);
+```
+
+#### `id`
+
+INTEGER 唯一自增 id
+
+#### `user_id`
+
+CHAR (36) uuid
+
+#### `bio`
+
+TEXT
+
+#### `lang`
+
+简介语言,一个用户可以建立多个语言版本的简历。用户的显示与用户的语言设置有关。不能匹配到相同语言时,匹配相同语族,还是不行,就显示默认记录。
+
+#### `isdefault`
+
+是否是默认记录。
+
+#### `email`
+
+电邮地址
+
+## 编辑记录索引 active_index
+
+用户行为记录。以日期计算的使用与编辑有关功能的时间和操作次数
+
+```table
+CREATE TABLE active_index (
+    id SERIAL PRIMARY KEY,
+    user_id  INTEGER NOT NULL,
+    user_uuid  VARCHAR (36),
+    date     TIMESTAMP NOT NULL,
+    duration INTEGER NOT NULL,
+    hit      INTEGER NOT NULL
+);
+```
+
+`date` 日期
+
+`duration` 持续时间 毫秒
+
+`hit` 操作次数
+
+## 编辑记录 edit_records
+
+```table
+CREATE TABLE edit_records (
+    id SERIAL PRIMARY KEY,
+    user_id  INTEGER NOT NULL,
+    user_uuid  VARCHAR (36),
+    start_at    TIMESTAMP,
+    end_at    TIMESTAMP,
+    duration INTEGER,
+    hit      INTEGER   DEFAULT (0),
+    timezone INTEGER   DEFAULT (0)
+);
+```
+
+## 编辑行为记录
+
+```table
+CREATE TABLE active_log (
+    id SERIAL PRIMARY KEY,
+    user_id  INTEGER NOT NULL,
+    active   INTEGER NOT NULL,
+    content  TEXT,
+    timezone INTEGER,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+```
+
+只添加不删除
+
+### api
+
+`PUT /api/useractive/log`
+
+body:
+
+```
+{
+    active:aid,
+    content:text,
+    timezone:timezone,
+}
+```

+ 77 - 0
documents/zh/api/wbw.md

@@ -0,0 +1,77 @@
+## 逐词解析
+### wbw_block
+```
+CREATE TABLE wbw_block (
+    id SERIAL PRIMARY KEY,
+    uuid           VARCHAR(36),
+    parent_id      UUID,
+    channal_id     INTEGER NOT NULL,
+    channal        UUID,
+    parent_channel_id INTEGER NOT NULL,
+    parent_channel UUID,
+    owner_id       INTEGER NOT NULL,
+    owner          UUID,
+    book           INTEGER  NOT NULL  DEFAULT 0,
+    paragraph      INTEGER  NOT NULL  DEFAULT 0,
+    style          VARCHAR (16),
+    lang           VARCHAR (8),
+    status         INTEGER,
+    deleted_at TIMESTAMP,
+    version INTEGER NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL
+);
+```
+#### `parent_id`
+上游id
+#### `channal`
+channel
+#### `parent_channel`
+从哪个channel 复制的
+#### `owner`
+最初拥有者
+#### `book`
+书号
+#### 'paragraph'
+段落号
+
+
+### 逐词解析数据 wbw-data
+```
+CREATE TABLE wbw_datas (
+    id SERIAL PRIMARY KEY,
+    block_id     INTEGER NOT NULL,
+    block_uuid     VARCHAR(36),
+    book         INTEGER NOT NULL,
+    paragraph    INTEGER NOT NULL,
+    wid          INTEGER NOT NULL,
+    word         TEXT,
+    data         TEXT,
+    status       INTEGER,
+    owner_id     INTEGER NOT NULL,
+    owner        VARCHAR(36),
+    deleted_at TIMESTAMP,
+    version INTEGER NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at TIMESTAMP NOT NULL
+);
+
+```
+
+`id` 原表uuid 不需要导入因为没有其他表链接到这个id
+
+`block_id`
+与wbw_block表关联的字段
+
+`data`
+单词数据 xml格式
+
+
+### API
+GET api/wbw/:channel/:book/:para/
+
+PUT api/wbw/:channel/:book/:para/
+
+POST api/wbw/:channel/:book/:para/
+
+DELETE api/wbw/:channel/:book/:para/

+ 0 - 1
documents/zh/course.md

@@ -1 +0,0 @@
-# API

+ 0 - 0
documents/zh/dashboard/auth.md


+ 0 - 0
documents/zh/dashboard/collection.md


+ 1 - 0
documents/zh/dashboard/course.md

@@ -0,0 +1 @@
+# 课程栏目前端设计

+ 0 - 0
documents/zh/dashboard/dict.md


+ 0 - 0
documents/zh/dashboard/home.md


+ 1 - 0
documents/zh/dashboard/myzone.md

@@ -0,0 +1 @@
+# 个人空间

+ 23 - 0
documents/zh/dashboard/palicanon.md

@@ -0,0 +1,23 @@
+# 三藏经文选择
+
+## 功能一览
+- 利用标签选择三藏经文
+- 根据用户界面语言设定显示相应的标题语言
+- 在服务器端记录用户浏览历史并在页面显示
+- 点击书或章节名称打开[经文阅读界面](reader.md)
+- 显示最新更新列表
+- 作者过滤
+
+> 注意:章节只显示到第一个层级
+
+## 公共组件
+- 网站导航
+- 网站页脚
+
+## 标签选择三藏经文
+以列表和书封面两种模式显示所选择的经文。
+
+## 阅读历史记录
+## 最新更新
+以列表
+## 贡献者列表

+ 5 - 0
documents/zh/dashboard/public.md

@@ -0,0 +1,5 @@
+# 公共组件与资源
+
+## 网站导航组件
+
+## 网站页脚组件

+ 231 - 0
documents/zh/dashboard/readme.md

@@ -0,0 +1,231 @@
+# 说明
+
+本文档是网站页面的前端设计文档
+
+
+# 开发环境
+- React
+- Umijs
+- Ant Design
+- Type Script
+
+
+# 网站地图
+```mermaid
+graph LR;
+
+subgraph 藏经阁
+home(藏经阁首页) --> palicanon(圣典)
+home --> course(课程)
+home --> dict(字典)
+home --> collection(文集)
+home --> term(术语百科)
+collection --> article(文章)
+article --> article-reader(文章阅读器)
+dict -->|嵌入| reader
+dict -->|嵌入| article-reader
+palicanon --> reader(阅读器)
+term -->|嵌入| reader
+
+end
+
+subgraph 译经楼
+studio(译经楼首页) --> pali(经文选择)
+studio --> filelist("逐词解析<br>编辑历史记录")
+filelist --> wbw(逐词解析)
+studio --> course1(课程管理)
+studio --> channel(版本管理)
+studio --> group(群组)
+studio --> article1(文章管理)
+studio --> collection1(文集管理)
+end
+
+home -->studio
+dict -->|嵌入| wbw
+reader -->wbw
+term -->|嵌入| wbw
+```
+- 藏经阁-Libray
+  - [首页](home.md)
+  - [三藏](palicanon.md)  
+  - [课程](course.md)
+  - [字典](dict.md)
+  - [搜索](search.md)
+  - [个人空间](myzone.md)
+- 译经楼-Studio
+  - [首页](stu_home.md) 
+  - [三藏分类](stu_pali.md)
+  - [我的文档(最近打开)](stu_doc.md)
+  - [逐词解析编辑](stu_wbw.md)
+  - [协作文档](stu_coop.md)
+  - [群组管理](stu_group.md)
+  - [版本管理](stu_channel.md)
+  - [课程管理](stu_course.md)
+  - [单词本](stu_dict.md)
+  - [百科词条](stu_term.md)
+  - 统计数据
+- 用户中心- User Center
+  - [注册](sign_up.md)
+  - [登陆](sign_in.md)
+  - 找回密码
+  - 个性化设置
+- 实用工具
+  - 佛历
+  - 圣典编码转换
+- 后台管理
+  - 栏目内容管理
+  - 用户管理
+  - 数据表管理
+
+# 藏经阁-Libray
+
+## 首页
+
+www.wikipali.org
+
+### 已经实现的功能能
+
+- 最新课程列表
+- 最新百科词条列表
+
+### 需要完善的功能
+
+#### 最新课程列表
+
+- 返回数量是写死的。应该在栏目后台里可以设置。
+
+### 尚未实现的功能(目前的需求)
+
+- **最新课程列表**-报名数字显示和报名功能
+
+- 最新三藏译文列表
+
+- 手机版 css
+  - 写不同的 css 在手机端和 pc 看到不同的页面。
+  - 不一定用 css 切换,可以使用不同的技术实现方式。
+
+### 未来可能的发展
+
+- 实现类似 tweet 的文章推荐功能。根据用户阅读行为推荐不同类型和内容的文章。
+- 文章类型
+  - 逐词解析单词
+  - 词典词条
+  - 百科词条
+  - 句子
+  - 段落
+  - 章节
+- 文章属性标签
+  - 译文
+  - 新手试验田
+  - 雅正(希望大家提修改意见)
+  - 求助
+- 应用场景
+  - 当有学习者不知道某个词的拆分,他在编辑器(studio)中单词的位置选择“求助”按钮。会发布一个带有“求助”标签的“逐词解析”类型的文章。某老师或网友看到求助文章,可以以跟帖的方式回答。
+
+
+## 三藏分类
+
+www.wikipali.org/palicanon
+
+### 已经实现的功能能
+
+- 章节标签过滤
+- 在阅读器中打开章节
+
+### 需要完善的功能
+
+### 尚未实现的功能(目前的需求)
+
+### 未来可能的发展
+
+## 课程
+
+### 已经实现的功能能
+
+### 需要完善的功能
+
+### 尚未实现的功能(目前的需求)
+
+### 未来可能的发展
+
+## 百科
+
+### 已经实现的功能能
+
+### 需要完善的功能
+
+### 尚未实现的功能(目前的需求)
+
+### 未来可能的发展
+
+## 字典
+
+## 标题搜索
+
+## 全文搜索
+
+## 黑体字搜索
+
+## 经典阅读器
+
+# 译经楼 Studio
+
+## 欢迎页
+
+## 经文选择
+
+## 最近打开
+
+## 协作
+
+## 课程管理
+
+## 用户字典管理
+
+## 百科字典管理
+
+## 工作组管理
+
+# 用户中心
+
+## 登录
+
+## 注册
+
+## 用户设置
+
+# 网站后台管理
+
+## 栏目管理
+
+### 首页
+
+### 三藏
+
+### 课程
+
+### 百科
+
+### 字典
+
+### 搜索
+
+### 阅读器
+
+### 用户管理
+
+#### 修改权限
+
+#### 禁用账号
+
+### 数据表管理
+
+#### 查看
+
+#### 统计
+
+#### 添加
+
+#### 删除
+
+# 数据表与模块关系

+ 0 - 0
documents/zh/dashboard/stu_course.md


+ 0 - 0
documents/zh/dashboard/stu_dict.md


+ 0 - 0
documents/zh/dashboard/stu_doc.md


+ 0 - 0
documents/zh/dashboard/stu_group.md


+ 0 - 0
documents/zh/dashboard/stu_term.md


+ 0 - 0
documents/zh/dashboard/studio.md


+ 0 - 0
documents/zh/dashboard/term.md


+ 0 - 61
documents/zh/database.md

@@ -1,61 +0,0 @@
-# 数据库指南
-
-## 语料库
-
-## 字典
-
-
-## 用户认证
-### userinfo
-
-#### `id`
-INTEGER 唯一自增id 
-#### `userid`
-CHAR (36)  uuid
-#### `path`
-CHAR (36) 用户在服务器上私有文件的路径
-#### `username`
-TEXT (64) 用户登录名
-#### `password`
-TEXT 密码 md5加密
-#### `nickname`
-TEXT (64) 昵称
-#### `email`
-TEXT (256) 电邮地址
-#### create_time
-INTEGER 账户建立时间
-#### `modify_time`
-INTEGER 数据修改时间
-#### `receive_time`
-INTEGER 服务器收到此数据时间
-#### `setting`
-TEXT 用户设置 json 数据
-
-### projile
-用户简历
-#### `id`
-INTEGER 唯一自增id 
-#### `user_id`
-CHAR (36)  uuid
-#### `bio`
-TEXT 
-
-## 用户字典
-
-## 逐词解析
-
-## 译文
-
-
-## 工作组
-
-
-## Channel
-
-
-## 文章
-
-
-## 权限管理
-
-

+ 9 - 0
documents/zh/db/readme.md

@@ -0,0 +1,9 @@
+# 数据库
+
+## 语料库
+
+## 字典
+
+
+
+

+ 0 - 0
documents/zh/deploy/语料库.md


+ 19 - 1
documents/zh/readme.md

@@ -1 +1,19 @@
-# 欢迎来到 wikipali
+# wikipali 开发文档
+
+## 概述
+## 价值观
+- **可重用的数据** 从逐词解析到整篇译文。所有的数据应该是可重用的。可重用意味着在技术层面应该存储计算机可辨识的格式的数据。
+- **智能重用** 程序应根据经文类型(经藏或律藏)或其他特征,提供提供不同的数据给用户。或将数据列表按信心指数排序。以减少不必要的人工劳动。
+- **公共版权** 有版权的信息与前两条原则违背。所以,一切在本平台公开的数据都应使用公共版权。
+- **平等的发言权** 每个平台的使用者都有权发表自己的观点。平台不应以官方的角度用人工的方式评价观点的正确性或给予排名靠前或靠后的操作。但是平台应该记录和向所有人提供统计数据,如:信息发布者的使用经验数值(使用平台时间,发表信息量,被点赞量等),阅读者的阅读数据(阅读量,收藏量)供阅读者自己判断信息的可用性。没有实质内容的信息(如:“很好”;“太差了”等)将对读者造成困扰,增加读者搜寻有用信息的时间。管理员应根据判定规则,将信息隐藏。在读者选择“查看隐藏的内容”时展示。
+
+## 开发文档包含
+
+* [API 接口](api/readme.md)
+* [前端文档](dashboard/readme.md)
+* [数据库设计](db/readme.md)
+* [运维](deploy/readme.md)
+
+git commit message格式 请参见https://gitmoji.dev/
+
+用户手册请参考https://github.com/iapt-platform/help.zh-hans

+ 4 - 0
documents/zh/summary.md

@@ -0,0 +1,4 @@
+* [API 接口](api/readme.md)
+* [前端文档]](dashboard/readme.md)
+* [数据库设计]](db/readme.md)
+* [运维]](deploy/readme.md)

+ 0 - 47
documents/功能完善列表.md

@@ -1,47 +0,0 @@
-# 功能列表
-
-```mermaid
-graph LR;
-subgraph 首页
-A(帮助页面);
-end
-subgraph 逐词译
-B1(查词结果智能排序)
-B2(计算公式)-->B1
-B3(拼写)-->B2
-B4(值)-->B2
-B5(类型)-->B2
-B6(书号)-->B2
-B7(段落号)-->B2
-B8(贡献者)-->B2
-
-B11(编辑框bug)
-B11(编辑框bug)-->B12(拆分意思联动)
-end
-subgraph studio译文
-C1(历史功能)
-C2(译文隐私状态)-->C3
-C3(公开)
-C2-->C4(链接)
-C2-->C5(私密)
-C4-->C6(可见范围)
-C7(默认前N个channal)
-C8(消息收发)
-C9(自动术语)
-end
-subgraph 术语
-D1(外部添加)
-D2(外部修改)
-end
-subgraph 文章文集
-F1(协作)-->F2(历史)
-F3(优化导入操作)
-F4(拖拽混排)
-end
-subgraph 阅读器
-E1(添加字典功能)
-E2(加载范围)
-E2-->E3(黑体数字)
-end
-
-```