Compare commits
10 Commits
80ca1cd46e
...
9e3638885d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e3638885d | ||
|
|
7598280fc1 | ||
|
|
e58bafd0d3 | ||
|
|
2482141d0f | ||
|
|
28c65b73c3 | ||
|
|
09b8e8e262 | ||
|
|
b92598ecc4 | ||
|
|
22cb5ec61f | ||
|
|
64a820a6df | ||
|
|
fc347a4140 |
1438
docs/docs.go
1438
docs/docs.go
File diff suppressed because it is too large
Load Diff
1426
docs/swagger.json
1426
docs/swagger.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
package config
|
||||
package global
|
||||
|
||||
type ServerConfig struct {
|
||||
Listen string `yaml:"listen"`
|
||||
@@ -11,6 +11,8 @@ type ServerConfig struct {
|
||||
Redis RedisConfig `yaml:"redis"`
|
||||
Jwt JwtConfig `yaml:"jwt"`
|
||||
Email EmailConfig `yaml:"email"`
|
||||
Bos BosConfig `yaml:"bos"`
|
||||
Kafka KafkaCofig `yaml:"kafka"`
|
||||
}
|
||||
|
||||
type MySQLConfig struct {
|
||||
@@ -39,3 +41,15 @@ type EmailConfig struct {
|
||||
Account string `yaml:"account"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type BosConfig struct {
|
||||
AccessKey string `yaml:"accessKey"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
Domain string `yaml:"domain"`
|
||||
}
|
||||
|
||||
type KafkaCofig struct {
|
||||
Servers []string `yaml:"servers"`
|
||||
Topic string `yaml:"topic"`
|
||||
Partition int `yaml:"partition"`
|
||||
}
|
||||
@@ -3,22 +3,22 @@ package global
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"nCovTrack-Backend/config"
|
||||
"net/http"
|
||||
|
||||
"github.com/baidubce/bce-sdk-go/services/bos"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
ServerSettings config.ServerConfig
|
||||
ServerSettings ServerConfig
|
||||
Db *gorm.DB
|
||||
RootRouter *gin.RouterGroup
|
||||
Logger *zap.SugaredLogger
|
||||
HttpClient map[string]*http.Client
|
||||
Redis *redis.Client
|
||||
BosClient *bos.Client
|
||||
)
|
||||
|
||||
func GetListenOn() string {
|
||||
@@ -34,10 +34,46 @@ func GetHttpClient(key string) (*http.Client, error) {
|
||||
}
|
||||
|
||||
const (
|
||||
CHINA_NCOV_STATISTIC_URL = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
|
||||
ENV_NOLOG = "nolog"
|
||||
TOKEN_EXPIRE_DAYS = 15
|
||||
CHINA_NCOV_STATISTIC_URL = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf"
|
||||
CHINA_NCOV_STATISTIC_TREND_URL = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList"
|
||||
ENV_NOLOG = "nolog"
|
||||
TOKEN_EXPIRE_DAYS = 15
|
||||
FACKER_HOST = "http://myhost.fallen-angle.com:5000/"
|
||||
|
||||
REGISTER_REDIS_KEY = "register_key"
|
||||
CHANGEPWD_REDIS_KEY = "changepwd_key"
|
||||
)
|
||||
|
||||
var (
|
||||
ID_ROLE_MAP = map[int]string{
|
||||
0: "SYSTEM",
|
||||
4: "VOLUNTEER",
|
||||
8: "WORKER",
|
||||
12: "ADMIN",
|
||||
}
|
||||
ROLE_ID_MAP = map[string]int{
|
||||
"SYSTEM": 0,
|
||||
"VOLUNTEER": 4,
|
||||
"WORKER": 8,
|
||||
"ADMIN": 12,
|
||||
}
|
||||
HEALTH_SITUATION_ID_MAP = map[string]int{
|
||||
"OTHER": 0,
|
||||
"PATIENT": 1,
|
||||
"CONTACT": 2,
|
||||
"SUB_CONTACT": 3,
|
||||
}
|
||||
MEASURE_SITUATION_ID_MAP = map[string]int{
|
||||
"NO_MEASURE": 0,
|
||||
"NO_RISK": 1,
|
||||
"TREATING": 2,
|
||||
"CENTRALIZED": 3,
|
||||
"HOME": 4,
|
||||
}
|
||||
PCR_RESULT_ID_MAP = map[string]int{
|
||||
"NONE": 0,
|
||||
"NEGATIVE": 1,
|
||||
"POSITIVE": 2,
|
||||
}
|
||||
KafkaProducerChan = make(chan []byte)
|
||||
)
|
||||
|
||||
20
go.mod
20
go.mod
@@ -18,6 +18,12 @@ require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/Shopify/sarama v1.32.0 // indirect
|
||||
github.com/baidubce/bce-sdk-go v0.9.112 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/eapache/go-resiliency v1.2.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
@@ -30,13 +36,21 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.0.0 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.4 // indirect
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.15.2 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
@@ -48,6 +62,8 @@ require (
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.18.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/spf13/afero v1.8.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
@@ -58,8 +74,8 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.9 // indirect
|
||||
|
||||
54
go.sum
54
go.sum
@@ -44,8 +44,13 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/sarama v1.32.0 h1:P+RUjEaRU0GMMbYexGMDyrMkLhbbBVUVISDywi+IlFU=
|
||||
github.com/Shopify/sarama v1.32.0/go.mod h1:+EmJJKZWVT/faR9RcOxJerP+LId4iWdQPBGLy1Y1Njs=
|
||||
github.com/Shopify/toxiproxy/v2 v2.3.0/go.mod h1:KvQTtB6RjCJY4zqNJn7C7JDFgsG5uoHYDirfUfpIm0c=
|
||||
github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
|
||||
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
|
||||
github.com/baidubce/bce-sdk-go v0.9.112 h1:qHzFxG7fwGbXCv+1smcbWFhWl6iwoXDVzPn9TUtrlss=
|
||||
github.com/baidubce/bce-sdk-go v0.9.112/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@@ -61,6 +66,12 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
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/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -69,6 +80,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
@@ -142,6 +155,8 @@ 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.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/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=
|
||||
@@ -155,6 +170,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/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 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -178,6 +194,12 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
@@ -185,6 +207,17 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
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/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/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.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
@@ -201,6 +234,9 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.2 h1:3WH+AG7s2+T8o3nrM/8u2rdqUEcQhmga7smjrT41nAw=
|
||||
github.com/klauspost/compress v1.15.2/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
@@ -258,6 +294,8 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9
|
||||
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -266,6 +304,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR
|
||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@@ -274,6 +314,7 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
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/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60=
|
||||
@@ -311,6 +352,9 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
|
||||
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/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.0/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -338,6 +382,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@@ -345,6 +390,9 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+Wr
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -417,10 +465,13 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8=
|
||||
golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
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/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -454,6 +505,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -496,12 +548,14 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/service/article"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SaveArticleHandler save an article
|
||||
//SaveArticleHandler save an article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
@@ -19,33 +21,64 @@ import (
|
||||
// @Param Token header string true "token"
|
||||
func SaveArticleHandler(c *gin.Context) {
|
||||
jsonMap := bindJson(c)
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
if jsonMap == nil {
|
||||
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||
return
|
||||
}
|
||||
colMap := models.MapJ2c[models.BackArticle](jsonMap, true)
|
||||
if ok := article.SaveArticle(colMap); !ok {
|
||||
if ok := article.SaveArticle(claims, colMap); !ok {
|
||||
ServerErr(c, "Save Failed")
|
||||
return
|
||||
}
|
||||
utils.Succ(c, jsonMap)
|
||||
}
|
||||
|
||||
// GetAllArticlesHandler get all article
|
||||
//ListPublishedArticlesHandler get all article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary get all articles
|
||||
// @Description Admin can get not published article
|
||||
// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle}
|
||||
// @Success 200 {object} utils.GinResponse{data=[]models.ListArticle}
|
||||
// @Router /article/list [get]
|
||||
// @Param Token header string false "token"
|
||||
func GetAllArticlesHandler(c *gin.Context) {
|
||||
// TODO: admin need to show more articles
|
||||
articles := article.ListAllArticles()
|
||||
func ListPublishedArticlesHandler(c *gin.Context) {
|
||||
articles := article.ListPublishedArticles()
|
||||
utils.Succ(c, articles)
|
||||
}
|
||||
|
||||
// DeleteArticleHandler delete article
|
||||
//ListPublishedArticlesHandler get the user's article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary get user's articles
|
||||
// @Success 200 {object} utils.GinResponse{data=[]models.BackArticle}
|
||||
// @Router /article/list/{published} [get]
|
||||
// @Param Token header string false "token"
|
||||
// @Param published path string true "string enums" Enums(published, notpublished)
|
||||
func ListArticlesByUser(c *gin.Context) {
|
||||
published := c.Param("published")
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
var articles *[]models.ListArticle
|
||||
if published == "published" {
|
||||
articles = article.ListPublishedArticlesByUser(claims.ID)
|
||||
} else if published == "notpublished" {
|
||||
articles = article.ListNotPublishedArticlesByUser(claims.ID)
|
||||
} else {
|
||||
UrlNotFound(c)
|
||||
return
|
||||
}
|
||||
utils.Succ(c, articles)
|
||||
}
|
||||
|
||||
//DeleteArticleHandler delete article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
@@ -56,6 +89,11 @@ func GetAllArticlesHandler(c *gin.Context) {
|
||||
// @Param id path string true "id"
|
||||
func DeleteArticleHandler(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||
return
|
||||
@@ -67,15 +105,14 @@ func DeleteArticleHandler(c *gin.Context) {
|
||||
utils.Succ(c, nil)
|
||||
}
|
||||
|
||||
// GetArticleHandler get an article
|
||||
//GetArticleHandler get an article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary get all articles
|
||||
// @Summary get an articles
|
||||
// @Description Admin can get not published article
|
||||
// @Success 200 {object} utils.GinResponse{data=models.BackArticle}
|
||||
// @Router /article/{id} [get]
|
||||
// @Param Token header string false "token"
|
||||
// @Param id path string true "id"
|
||||
func GetArticleHandler(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
@@ -84,7 +121,6 @@ func GetArticleHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
res := article.GetArticleById(id)
|
||||
//TODO: if not admin, will not show not published article
|
||||
if res == nil {
|
||||
DataNotFound(c, nil)
|
||||
return
|
||||
@@ -92,17 +128,22 @@ func GetArticleHandler(c *gin.Context) {
|
||||
utils.Succ(c, res)
|
||||
}
|
||||
|
||||
// PublishArticleHandler publish an article
|
||||
//PublishArticleHandler publish an article
|
||||
// @Tags Article
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary get all articles
|
||||
// @Summary publish an articles
|
||||
// @Success 200 {object} utils.GinResponse{}
|
||||
// @Router /article/{id}/publish [post]
|
||||
// @Param Token header string true "token"
|
||||
// @Param id path string true "id"
|
||||
func PublishArticleHandler(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
RequestErr(c, map[string]interface{}{"URI": c.Request.RequestURI})
|
||||
return
|
||||
|
||||
@@ -9,9 +9,13 @@ import (
|
||||
// This file is define some business error
|
||||
|
||||
const (
|
||||
BAD_REQUEST = "Bad Request"
|
||||
DATA_NOT_FOUND = "Data not Found"
|
||||
STATUS_DATA_NOT_FOUND = 210
|
||||
BAD_REQUEST = "Bad Request"
|
||||
DATA_NOT_FOUND = "Data not Found"
|
||||
STATUS_DATA_NOT_FOUND = 210
|
||||
FORBIDDENT = "FORBIDDENT"
|
||||
PAGE_NOT_FOUND = "404 page not found"
|
||||
STATUS_OPERATION_FAILED = 410
|
||||
OPERATION_FAILED = "operation failed"
|
||||
)
|
||||
|
||||
func RequestError(c *gin.Context, code int, data interface{}) {
|
||||
@@ -31,3 +35,14 @@ func ServerErr(c *gin.Context, msg interface{}) {
|
||||
func DataNotFound(c *gin.Context, data interface{}) {
|
||||
utils.Success(c, http.StatusOK, STATUS_DATA_NOT_FOUND, DATA_NOT_FOUND, data)
|
||||
}
|
||||
func Forbidden(c *gin.Context) {
|
||||
utils.Err(c, http.StatusForbidden, http.StatusForbidden, FORBIDDENT)
|
||||
}
|
||||
|
||||
func UrlNotFound(c *gin.Context) {
|
||||
c.String(http.StatusNotFound, PAGE_NOT_FOUND)
|
||||
}
|
||||
|
||||
func OperationFailed(c *gin.Context) {
|
||||
c.String(STATUS_OPERATION_FAILED, OPERATION_FAILED)
|
||||
}
|
||||
|
||||
234
handler/management.go
Normal file
234
handler/management.go
Normal file
@@ -0,0 +1,234 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/service/management"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//PullContactHandler pull contact from faker
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary pull contact from faker
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/faker/{patientId} [get]
|
||||
// @Param Token header string true "Token"
|
||||
// @Param patientId path int true "Patient Id"
|
||||
func PullContactHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
patientId, _ := strconv.Atoi(c.Param("patientId"))
|
||||
rowsAffected := management.PullFromFaker(claims, patientId)
|
||||
if rowsAffected == -1 {
|
||||
DataNotFound(c, map[string]interface{}{"patientId": patientId})
|
||||
return
|
||||
}
|
||||
utils.Succ(c, map[string]interface{}{"pullAmount": rowsAffected})
|
||||
}
|
||||
|
||||
//GetObservationHandler get observation's info
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary get observation's info
|
||||
// @Success 200 {object} utils.GinResponse{data=models.BackObservation}
|
||||
// @Router /management/observation/{id} [get]
|
||||
// @Param token header string true "token"
|
||||
// @Param id path int true "id"
|
||||
func GetObservationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
utils.Succ(c, management.GetObservation(id))
|
||||
}
|
||||
|
||||
//ListObservationsHandler list observations by query
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary list observations by query
|
||||
// @Success 200 {object} utils.GinResponse{data=[]models.ListObservation}
|
||||
// @Router /management/observation/ [get]
|
||||
// @Param Token header string true "token"
|
||||
// @Param queries query models.BackObservation true "queries"
|
||||
func ListObservationsHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
jsonMap := bindQuery(c)
|
||||
utils.Succ(c, management.ListObservation(jsonMap))
|
||||
}
|
||||
|
||||
//TreeifyObservationHandler get transform chain by user
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary get transform chain by user
|
||||
// @Success 200 {object} utils.GinResponse{data=models.TreeObservation}
|
||||
// @Router /management/observation/tree/{id}/{direction} [get]
|
||||
// @Param Token header string true "token"
|
||||
// @Param id path int true "id"
|
||||
// @Param direction path string true "direction" Enums(up, down, all)
|
||||
func TreeifyObservationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
direction := c.Param("direction")
|
||||
tree := management.TreeifyObservations(id, direction)
|
||||
utils.Succ(c, tree)
|
||||
}
|
||||
|
||||
//InsertObservationHandler insert observation
|
||||
// @Tags Management
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary insert observation
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/observation/ [post]
|
||||
// @Param Observation body models.BackObservation true "observation"
|
||||
// @Param Token header string true "token"
|
||||
func InsertObservationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
observaion := bindJson(c)
|
||||
delete(observaion, "id")
|
||||
ok := management.InsertObservation(claims, observaion)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
//UpdateObservationHandler update observation
|
||||
// @Tags Management
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary update observation
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/observation/ [put]
|
||||
// @Param Observation body models.BackObservation true "observation"
|
||||
// @Param Token header string true "token"
|
||||
func UpdateObservationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
observation := bindJson(c)
|
||||
ok := management.UpdateObservation(claims, observation)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
//ListLocationHandler list locations
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary list locations
|
||||
// @Success 200 {object} utils.GinResponse{data=models.BackLocation}
|
||||
// @Router /management/location/ [get]
|
||||
// @Param queries query models.BackLocation true "queries"
|
||||
// @Param Token header string true "token"
|
||||
func ListLocationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
queryMap := bindQuery(c)
|
||||
utils.Succ(c, management.ListLocation(queryMap))
|
||||
}
|
||||
|
||||
//InsertLocationHandler insert location
|
||||
// @Tags Management
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary insert location
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/location/ [post]
|
||||
// @Param Location body models.BackLocation true "location"
|
||||
// @Param Token header string true "token"
|
||||
func InsertLocationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
locationMap := bindJson(c)
|
||||
ok := management.InsertLocation(claims, locationMap)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
//DeleteLocationHandler delete location
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary delete location
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/location/{id} [delete]
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id path int true "Id"
|
||||
func DeleteLocationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
ok := management.DeleteLocation(id)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
//InsertPcrHandler insert pcr record
|
||||
// @Tags Management
|
||||
// @Produce json
|
||||
// @Summary insert pcr record
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /management/pcr/ [post]
|
||||
// @Param Pcr body models.BackPcr true "Pcr"
|
||||
// @Param Token header string true "token"
|
||||
func InsertPcrHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
|
||||
if !utils.Contains(allowRows, claims.Role) {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
jsonMap := bindJson(c)
|
||||
ok := management.InsertPcr(claims, jsonMap)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
65
handler/notify.go
Normal file
65
handler/notify.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/service/notify"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//InsertNotificationHandler for test
|
||||
func InsertNotificationHandler(c *gin.Context) {
|
||||
sendNotify := models.SendInfo{Region: []string{"江苏 徐州"}, Channel: []int{1, 0}, Notification: models.BackNotification{Time: time.Now(), Kind: "测试", Content: "Test"}}
|
||||
notify.SendNotify(sendNotify)
|
||||
}
|
||||
|
||||
//CountNotificationHandler count the notification
|
||||
// @Tags Notification
|
||||
// @Produce json
|
||||
// @Summary count the notification
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /notify/count/ [get]
|
||||
// @Param Token header string true "token"
|
||||
func CountNotificationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
count := notify.QueryNotificationLen(claims.Region)
|
||||
utils.Succ(c, map[string]interface{}{"count": count})
|
||||
}
|
||||
|
||||
//ListNotificationHandler list the notifications in the range
|
||||
// @Tags Notification
|
||||
// @Produce json
|
||||
// @Summary list the notification in the range
|
||||
// @Success 200 {object} utils.GinResponse{data=[]models.BackNotification}
|
||||
// @Router /notify/{start}/{end} [get]
|
||||
// @Param Token header string true "token"
|
||||
// @Param start path int true "start"
|
||||
// @Param end path int true "end"
|
||||
func ListNotificationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
start, _ := strconv.Atoi(c.Param("start"))
|
||||
end, _ := strconv.Atoi(c.Param("end"))
|
||||
notifications := notify.ListNotifycation(claims.Region, start, end)
|
||||
utils.Succ(c, notifications)
|
||||
}
|
||||
|
||||
//DeleteNotificationHandler delete the notify by index
|
||||
// @Tags Notification
|
||||
// @Produce json
|
||||
// @Summary delete the notify by index, if -1 delete all
|
||||
// @Success 200 {object} utils.GinResponse
|
||||
// @Router /notify/{index} [delete]
|
||||
// @Param Token header string true "token"
|
||||
// @Param index path int true "index"
|
||||
func DeleteNotificationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
index, _ := strconv.Atoi(c.Param("index"))
|
||||
if index == -1 {
|
||||
notify.CleanNotification(claims.Region)
|
||||
}
|
||||
notify.DeleteNotification(claims.Region, index)
|
||||
utils.Succ(c, nil)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// @Param sort path string false "data sorted by" Enums(today, total, now, default)
|
||||
func ProvinceDataHandler(c *gin.Context) {
|
||||
sort := c.Param("sort")
|
||||
data := service.GetAllProvienceData(sort)
|
||||
data := service.GetAllProvinceData(sort)
|
||||
utils.Succ(c, data)
|
||||
}
|
||||
|
||||
@@ -57,3 +57,14 @@ func ChinaDataHandler(c *gin.Context) {
|
||||
data := service.GetChinaNCovStatistic()
|
||||
utils.Succ(c, data)
|
||||
}
|
||||
|
||||
// ChinaTrendHandler Get china data
|
||||
// @Tags Statistics
|
||||
// @Produce json
|
||||
// @Summary china trend
|
||||
// @Success 200 {object} utils.GinResponse{data=models.ChinaTrend}
|
||||
// @Router /statistics/china/trend [get]
|
||||
func ChinaTrendHandler(c *gin.Context) {
|
||||
data := service.GetChinaTrend()
|
||||
utils.Succ(c, data)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/service/user"
|
||||
"nCovTrack-Backend/utils"
|
||||
"regexp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//UserRegisterHandler user register
|
||||
@@ -13,7 +15,7 @@ import (
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Summary user register account
|
||||
// @Success 200 {object} utils.GinResponse{}
|
||||
// @Success 200 {object} utils.GinResponse{data=models.BackUser}
|
||||
// @Router /user/register [post]
|
||||
// @Param json body models.UserRegister true "json"
|
||||
func UserRegisterHandler(c *gin.Context) {
|
||||
@@ -22,11 +24,13 @@ func UserRegisterHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
registered := user.NoDuplicatePhoneOrEmail(jsonMap["phone"].(string), jsonMap["email"].(string))
|
||||
if registered {
|
||||
if !registered {
|
||||
utils.Success(c, 200, 200, "Registered", nil)
|
||||
return
|
||||
}
|
||||
colMap := models.MapJ2c[models.BackUser](jsonMap, true)
|
||||
user.Register(colMap)
|
||||
utils.Succ(c, nil)
|
||||
}
|
||||
|
||||
//UserApproveHandler admin approve account
|
||||
@@ -39,12 +43,16 @@ func UserRegisterHandler(c *gin.Context) {
|
||||
// @Param Token header string true "token"
|
||||
// @Param json body models.UserApprove true "json"
|
||||
func UserApproveHandler(c *gin.Context) {
|
||||
//TODO: auth user is admin or not
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
jsonMap := bindJsonStruct[models.UserApprove](c)
|
||||
if jsonMap == nil {
|
||||
return
|
||||
}
|
||||
if !user.ApproveRegister(jsonMap["email"].(string), jsonMap["pass"].(bool)) {
|
||||
if !user.ApproveRegister(claims, jsonMap["email"].(string), jsonMap["pass"].(bool)) {
|
||||
RequestErr(c, "approve failed")
|
||||
return
|
||||
}
|
||||
@@ -66,7 +74,9 @@ func UserLoginHandler(c *gin.Context) {
|
||||
}
|
||||
token := user.Login(jsonMap)
|
||||
if token == "" {
|
||||
// TODO: change to request error
|
||||
// Login failed reasons as follow:
|
||||
// 1. account or password incorrect
|
||||
// 2. account apply not pass
|
||||
utils.Succ(c, map[string]interface{}{"msg": "failed"})
|
||||
return
|
||||
}
|
||||
@@ -79,10 +89,25 @@ func UserLoginHandler(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Summary list register infos, which is to be approved
|
||||
// @Success 200 {object} utils.GinResponse{}
|
||||
// @Router /user/registers [get]
|
||||
// @Router /user/registers/{approved} [get]
|
||||
// @Param Token header string true "token"
|
||||
// @Param approved path string true "string enums" Enums(approved, notapproved)
|
||||
func ListRegisterUserHandler(c *gin.Context) {
|
||||
registers := user.ListRegister()
|
||||
approved := c.Param("approved")
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
|
||||
Forbidden(c)
|
||||
return
|
||||
}
|
||||
var registers *[]map[string]interface{}
|
||||
if approved == "notapproved" {
|
||||
registers = user.ListRegister(claims)
|
||||
} else if approved == "approved" {
|
||||
registers = user.ListApprovedRegister(claims)
|
||||
} else {
|
||||
UrlNotFound(c)
|
||||
return
|
||||
}
|
||||
utils.Succ(c, registers)
|
||||
}
|
||||
|
||||
@@ -91,7 +116,7 @@ func ListRegisterUserHandler(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Summary send verify code
|
||||
// @Success 200 {object} utils.GinResponse{}
|
||||
// @Router /user/{code} [get]
|
||||
// @Router /user/code/{email} [get]
|
||||
// @Param email path string true "email"
|
||||
func SendEmailCodeHandler(c *gin.Context) {
|
||||
email := c.Param("email")
|
||||
|
||||
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -46,3 +47,12 @@ func bindJsonStruct[T any](c *gin.Context) map[string]interface{} {
|
||||
}
|
||||
return jsonMap
|
||||
}
|
||||
|
||||
func bindQuery(c *gin.Context) map[string]interface{} {
|
||||
jsonMap := map[string]interface{}{}
|
||||
queries := c.Request.URL.Query()
|
||||
for k := range queries {
|
||||
jsonMap[k] = c.Query(k)
|
||||
}
|
||||
return jsonMap
|
||||
}
|
||||
|
||||
20
initialize/bos.go
Normal file
20
initialize/bos.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"github.com/baidubce/bce-sdk-go/services/bos"
|
||||
"nCovTrack-Backend/global"
|
||||
)
|
||||
|
||||
func initBos() {
|
||||
clientConfig := bos.BosClientConfiguration{
|
||||
global.ServerSettings.Bos.AccessKey,
|
||||
global.ServerSettings.Bos.SecretKey,
|
||||
global.ServerSettings.Bos.Domain,
|
||||
false,
|
||||
}
|
||||
bosClient, err := bos.NewClientWithConfig(&clientConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
global.BosClient = bosClient
|
||||
}
|
||||
@@ -2,11 +2,9 @@ package initialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nCovTrack-Backend/config"
|
||||
"nCovTrack-Backend/global"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/viper"
|
||||
"nCovTrack-Backend/global"
|
||||
)
|
||||
|
||||
func initConfig() {
|
||||
@@ -16,7 +14,7 @@ func initConfig() {
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
serverConfig := config.ServerConfig{}
|
||||
serverConfig := global.ServerConfig{}
|
||||
if err := v.Unmarshal(&serverConfig); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@ func initCron() {
|
||||
c := cron.New()
|
||||
//c.AddFunc("@every 10s", func() { global.Redis.Set("OK", time.Now().String(), time.Duration(10*time.Hour)) })
|
||||
c.AddFunc("@every 10m", statistics.CacheNCov)
|
||||
c.AddFunc("@every 8h", statistics.CacheNCovTrend)
|
||||
c.Start()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ func Initialize() *gin.Engine {
|
||||
initHttpClient()
|
||||
initMySQL()
|
||||
initRedis()
|
||||
initBos()
|
||||
initCron()
|
||||
go initProducer()
|
||||
go initConsumer()
|
||||
g := initRouter()
|
||||
initSwagger()
|
||||
return g
|
||||
|
||||
70
initialize/kafka.go
Normal file
70
initialize/kafka.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/service/notify"
|
||||
"time"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
)
|
||||
|
||||
func initProducer() {
|
||||
config := sarama.NewConfig()
|
||||
config.Producer.RequiredAcks = sarama.WaitForAll
|
||||
config.Producer.Partitioner = sarama.NewRandomPartitioner
|
||||
config.Producer.Return.Successes = true
|
||||
config.Producer.Return.Errors = true
|
||||
producer, err := sarama.NewSyncProducer(global.ServerSettings.Kafka.Servers, config)
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
// defer producer.Close()
|
||||
for {
|
||||
select {
|
||||
case value := <-global.KafkaProducerChan:
|
||||
producer.SendMessage(&sarama.ProducerMessage{Topic: global.ServerSettings.Kafka.Topic, Key: nil, Value: sarama.ByteEncoder(value)})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func initConsumer() {
|
||||
config := sarama.NewConfig()
|
||||
config.Consumer.Offsets.CommitInterval = 1 * time.Second
|
||||
client, err := sarama.NewClient(global.ServerSettings.Kafka.Servers, config)
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
defer client.Close()
|
||||
offsetManager, err := sarama.NewOffsetManagerFromClient("", client)
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
defer offsetManager.Close()
|
||||
partitionOffsetManager, err := offsetManager.ManagePartition(global.ServerSettings.Kafka.Topic, int32(global.ServerSettings.Kafka.Partition))
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
defer partitionOffsetManager.Close()
|
||||
offsetNewest, _ := partitionOffsetManager.NextOffset()
|
||||
consumer, err := sarama.NewConsumer(global.ServerSettings.Kafka.Servers, config)
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
defer consumer.Close()
|
||||
partitionConsumer, err := consumer.ConsumePartition(global.ServerSettings.Kafka.Topic, int32(global.ServerSettings.Kafka.Partition), offsetNewest)
|
||||
if err != nil {
|
||||
panic("kafka init failed")
|
||||
}
|
||||
defer partitionConsumer.Close()
|
||||
for {
|
||||
select {
|
||||
case msg := <-partitionConsumer.Messages():
|
||||
ConsumeFunc(msg.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ConsumeFunc(msg []byte) {
|
||||
notify.HandleKafkaNotify(msg)
|
||||
}
|
||||
@@ -9,6 +9,6 @@ import (
|
||||
)
|
||||
|
||||
func initSwagger() {
|
||||
docs.SwaggerInfo_swagger.BasePath = "/api" + global.ServerSettings.UrlPrefix
|
||||
docs.SwaggerInfo.BasePath = "/api" + global.ServerSettings.UrlPrefix
|
||||
global.RootRouter.GET("/swagger/*any", swagger.WrapHandler(swaggerFile.Handler))
|
||||
}
|
||||
|
||||
9
main.go
9
main.go
@@ -3,11 +3,20 @@ package main
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/initialize"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// @title nCov Tracker
|
||||
// @version 1.0
|
||||
func main() {
|
||||
signals := make(chan os.Signal)
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-signals
|
||||
os.Exit(1)
|
||||
}()
|
||||
gin := initialize.Initialize()
|
||||
gin.Run(global.GetListenOn())
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"encoding/json"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
const UNAUTH_MSG = "unauthorized"
|
||||
@@ -24,9 +26,15 @@ func Auth() gin.HandlerFunc {
|
||||
}
|
||||
// Write the field of token to request header
|
||||
claims := utils.ParseClaims(oldToken[0])
|
||||
c.Request.Header.Set("role", fmt.Sprint(claims["role"]))
|
||||
c.Request.Header.Set("email", claims["email"].(string))
|
||||
c.Request.Header.Set("id", fmt.Sprint(claims["id"]))
|
||||
tokenClaims := models.TokenClaims{
|
||||
ID: int(claims["id"].(float64)),
|
||||
Username: claims["username"].(string),
|
||||
Email: claims["email"].(string),
|
||||
Role: int(claims["role"].(float64)),
|
||||
Region: claims["region"].(string),
|
||||
}
|
||||
claimsByte, _ := json.Marshal(tokenClaims)
|
||||
c.Request.Header.Add("claims", string(claimsByte))
|
||||
|
||||
// renew token, and judge the token's iat is expired or not
|
||||
renewToken := utils.RenewToken(oldToken[0])
|
||||
|
||||
@@ -13,7 +13,7 @@ func Cors() gin.HandlerFunc {
|
||||
c.Header("Access-Control-Allow-Origin", origin)
|
||||
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id")
|
||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, X-Token, Access-Control-Allow-Headers, Content-Type")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
if method == "OPTIONS" {
|
||||
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
|
||||
// BackArticle article struct
|
||||
type BackArticle struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // 文章id
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间
|
||||
CreateUser string `gorm:"column:create_user" json:"createUser"` // 文章创建者id
|
||||
CreateUser int `gorm:"column:create_user" json:"createUser"` // 文章创建者id
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间
|
||||
ModifyUser string `gorm:"column:modify_user" json:"modifyUser"` // 文章最后更新者id
|
||||
ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 文章最后更新者id
|
||||
Title string `gorm:"column:title" json:"title"` // 文章标题
|
||||
Tags string `gorm:"column:tags" json:"tags"` // 文章Tag
|
||||
Resume string `gorm:"column:resume" json:"resume"` // 文章简述
|
||||
@@ -20,16 +20,17 @@ type BackArticle struct {
|
||||
IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
}
|
||||
|
||||
type ListArticle struct {
|
||||
ID int `json:"id"`
|
||||
Username string `json:"username"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
ModifyTime time.Time `json:"modifyTime"`
|
||||
Title string `json:"title"`
|
||||
Tags string `json:"tags"`
|
||||
Resume string `json:"resume"`
|
||||
Cover string `json:"cover"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
initJcMap[BackArticle]()
|
||||
}
|
||||
|
||||
//func ArticleMapJ2c(jsonMap map[string]interface{}, ignoreNil bool) map[string]interface{} {
|
||||
// colMap := make(map[string]interface{})
|
||||
// for k, v := range jsonMap {
|
||||
// if colKey := colKey != "" && (!ignoreNil && v == nil) {
|
||||
// colMap[colKey] = v
|
||||
// }
|
||||
// }
|
||||
// return colMap
|
||||
//}
|
||||
|
||||
1
models/kafka.go
Normal file
1
models/kafka.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
177
models/management.go
Normal file
177
models/management.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BackObservation struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // ID
|
||||
Name string `gorm:"column:name" json:"name"` // 姓名
|
||||
Age int `gorm:"column:age" json:"age"` // 年龄
|
||||
Sex int `gorm:"column:sex" json:"sex"` // 性别
|
||||
Phone string `gorm:"column:phone" json:"phone"` // 手机号码
|
||||
Identification string `gorm:"column:identification" json:"identification"` // 身份证号
|
||||
ContactPerson int `gorm:"column:contact_person" json:"contactPerson"` // 接触者id
|
||||
Region string `gorm:"column:region" json:"region"` // 受观察者所在区域
|
||||
Address string `gorm:"column:address" json:"address"` // 受观察者所在具体地点
|
||||
HealthSituation int `gorm:"column:health_situation" json:"healthSituation"` // 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
|
||||
HealthChangeTime time.Time `gorm:"column:health_change_time" json:"healthChangeTime"` // 患者健康状况转化时间
|
||||
MeasureSituation int `gorm:"column:measure_situation" json:"measureSituation"` // 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
|
||||
Trajectory string `gorm:"column:trajectory" json:"trajectory"` // 行程轨迹
|
||||
CreateUser int `gorm:"column:create_user" json:"createUser"` // 创建者
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 创建时间
|
||||
ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 修改时间
|
||||
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
}
|
||||
|
||||
type BackLocation struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // ID
|
||||
Name string `gorm:"column:name" json:"name"` // 地点名
|
||||
Region string `gorm:"column:region" json:"region"` // 地点所在地区
|
||||
Address string `gorm:"column:address" json:"address"` // 地点的精确地址
|
||||
PrincipalName string `gorm:"column:principal_name" json:"principalName"` // 负责人姓名
|
||||
PrincipalPhone string `gorm:"column:principal_phone" json:"principalPhone"` // 负责人电话
|
||||
CreateUser int `gorm:"column:create_user" json:"createUser"` // 创建者
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 创建时间
|
||||
ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 修改时间
|
||||
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
}
|
||||
|
||||
type BackPcr struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // ID
|
||||
Observation int `gorm:"column:observation" json:"observation"` // 观察对象ID
|
||||
DetectTime time.Time `gorm:"column:detect_time" json:"detectTime"` // 核酸检测时间
|
||||
DetectResult int `gorm:"column:detect_result" json:"detectResult"` // 核酸检测结果:0-未检测,1-阴性,2-阳性
|
||||
CreateUser int `gorm:"column:create_user" json:"createUser"` // 创建者
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 创建时间
|
||||
ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 修改时间
|
||||
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
}
|
||||
|
||||
type BackSituationRecord struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // ID
|
||||
Observation int `gorm:"column:observation" json:"observation"` // 观察对象
|
||||
Record string `gorm:"column:record" json:"record"` // 状态转化记录
|
||||
CreateUser int `gorm:"column:create_user" json:"createUser"` // 创建者
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 创建时间
|
||||
ModifyUser int `gorm:"column:modify_user" json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 修改时间
|
||||
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
}
|
||||
|
||||
type ListObservation struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"` // 姓名
|
||||
Age int `json:"age"` // 年龄
|
||||
Sex int `json:"sex"` // 性别
|
||||
Phone string `json:"phone"` // 手机号码
|
||||
Identification string `json:"identification"` // 身份证号
|
||||
ContactPerson int `json:"contactPerson"` // 接触者id
|
||||
Region string `json:"region"` // 受观察者所在区域
|
||||
Address string `json:"address"` // 受观察者所在具体地点
|
||||
HealthSituation int `json:"healthSituation"` // 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
|
||||
HealthChangeTime time.Time `json:"healthChangeTime"` // 患者健康状况转化时间
|
||||
MeasureSituation int `json:"measureSituation"` // 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
|
||||
Trajectory string `json:"trajectory"` // 行程轨迹
|
||||
CreateUser int `json:"createUser"` // 创建者
|
||||
CreateTime time.Time `json:"createTime"` // 创建时间
|
||||
ModifyUser int `json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `json:"modifyTime"` // 修改时间
|
||||
PcrTime time.Time `json:"pcrTime"` // 核酸时间
|
||||
PcrResult int `json:"pcrResult"` // 核酸结果:0-未检测,1-阴性,2-阳性
|
||||
RecordTime time.Time `json:"recordTime"` // 状态转换时间
|
||||
Record string `json:"record"` // 状态转换内容
|
||||
}
|
||||
|
||||
type TreeObservation struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"` // 姓名
|
||||
Age int `json:"age"` // 年龄
|
||||
Sex int `json:"sex"` // 性别
|
||||
Phone string `json:"phone"` // 手机号码
|
||||
Identification string `json:"identification"` // 身份证号
|
||||
ContactPerson int `json:"contactPerson"` // 接触者id
|
||||
Region string `json:"region"` // 受观察者所在区域
|
||||
Address string `json:"address"` // 受观察者所在具体地点
|
||||
HealthSituation int `json:"healthSituation"` // 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
|
||||
HealthChangeTime time.Time `json:"healthChangeTime"` // 患者健康状况转化时间
|
||||
MeasureSituation int `json:"measureSituation"` // 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
|
||||
Trajectory string `json:"trajectory"` // 行程轨迹
|
||||
CreateUser int `json:"createUser"` // 创建者
|
||||
CreateTime time.Time `json:"createTime"` // 创建时间
|
||||
ModifyUser int `json:"modifyUser"` // 修改者
|
||||
ModifyTime time.Time `json:"modifyTime"` // 修改时间
|
||||
Children []*TreeObservation `json:"children"` // 子结点
|
||||
}
|
||||
|
||||
type QueryObservation struct {
|
||||
BackObservation
|
||||
PcrRecord []BackPcr `json:"pcrRecord"`
|
||||
SituationRecord []BackSituationRecord `json:"situationRecord"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
initJcMap[BackObservation]()
|
||||
initJcMap[BackLocation]()
|
||||
initJcMap[BackPcr]()
|
||||
initJcMap[BackSituationRecord]()
|
||||
}
|
||||
|
||||
type FakerDate time.Time
|
||||
|
||||
const (
|
||||
timeFormat = "2006-01-02"
|
||||
)
|
||||
|
||||
func (t *FakerDate) UnmarshalJSON(data []byte) (err error) {
|
||||
newTime, err := time.ParseInLocation(`"`+timeFormat+`"`, string(data), time.Local)
|
||||
*t = FakerDate(newTime)
|
||||
return
|
||||
}
|
||||
|
||||
func (t FakerDate) MarshalJSON() ([]byte, error) {
|
||||
timeStr := fmt.Sprintf("\"%s\"", time.Time(t).Format(timeFormat))
|
||||
return []byte(timeStr), nil
|
||||
}
|
||||
|
||||
func (t FakerDate) String() string {
|
||||
return time.Time(t).Format(timeFormat)
|
||||
}
|
||||
|
||||
type HotelContactRequest struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age,string"`
|
||||
Sex int `json:"sex,string"`
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
HotelCode string `json:"hotel_code"`
|
||||
HotelName string `json:"hotel_name"`
|
||||
LocateCityId string `json:"locate_city_id"`
|
||||
Identification string `json:"identification"`
|
||||
InData FakerDate `json:"in_data"`
|
||||
OutData FakerDate `json:"out_data"`
|
||||
}
|
||||
|
||||
type RailwayContactRequest struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age,string"`
|
||||
Sex int `json:"sex,string"`
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
Train string `json:"train"`
|
||||
Launch FakerDate `json:"launch"`
|
||||
Identification string `json:"identification"`
|
||||
}
|
||||
|
||||
type PatientRequest struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age,string"`
|
||||
Sex int `json:"sex,string"`
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
Identification string `json:"identification"`
|
||||
}
|
||||
15
models/notify.go
Normal file
15
models/notify.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type BackNotification struct {
|
||||
Time time.Time `json:"time"`
|
||||
Kind string `json:"kind"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type SendInfo struct {
|
||||
Region []string `json:"region"`
|
||||
Channel []int `json:"channel"`
|
||||
Notification BackNotification `json:"notification"`
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
type AreaInfo struct {
|
||||
Name string `json:"name"`
|
||||
Parent string `json:"parent"`
|
||||
Today AreaToday `json:"today"`
|
||||
Total AreaTotal `json:"total"`
|
||||
Children []AreaInfo `json:"children"`
|
||||
@@ -58,3 +59,42 @@ type ChinaData struct {
|
||||
ChinaAdd ChinaAdd `json:"chinaAdd"`
|
||||
ChinaTotal ChinaTotal `json:"chinaTotal"`
|
||||
}
|
||||
|
||||
type ChinaDayAdd struct {
|
||||
DeadRate string `json:"deadRate"`
|
||||
HealRate string `json:"healRate"`
|
||||
Date string `json:"date"`
|
||||
Year string `json:"y"`
|
||||
Confirm int `json:"confirm"`
|
||||
Suspect int `json:"suspect"`
|
||||
Dead int `json:"dead"`
|
||||
Infect int `json:"infect"`
|
||||
Heal int `json:"heal"`
|
||||
ImportedCase int `json:"importedCase"`
|
||||
Localinfectionadd int `json:"localinfectionadd"`
|
||||
LocalConfirmadd int `json:"localConfirmadd"`
|
||||
}
|
||||
|
||||
type ChinaDay struct {
|
||||
DeadRate string `json:"deadRate"`
|
||||
NoInfect int `json:"noInfect"`
|
||||
LocalConfirm int `json:"localConfirm"`
|
||||
ImportedCase int `json:"importedCase"`
|
||||
Date string `json:"date"`
|
||||
LocalConfirmH5 int `json:"localConfirmH5"`
|
||||
Suspect int `json:"suspect"`
|
||||
Dead int `json:"dead"`
|
||||
Heal int `json:"heal"`
|
||||
Year string `json:"y"`
|
||||
Confirm int `json:"confirm"`
|
||||
NowConfirm int `json:"nowConfirm"`
|
||||
HealRate string `json:"healRate"`
|
||||
NowSevere int `json:"nowSevere"`
|
||||
NoInfectH5 int `json:"noInfectH5"`
|
||||
LocalAccConfirm int `json:"local_acc_confirm"`
|
||||
}
|
||||
|
||||
type ChinaTrend struct {
|
||||
ChinaDayList []ChinaDay `json:"ChinaDayList"`
|
||||
ChinaDayAddList []ChinaDayAdd `json:"chinaDayAddList"`
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package models
|
||||
import "time"
|
||||
|
||||
type BackUser struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"-"` // 用户ID
|
||||
ID int `gorm:"primaryKey;column:id" json:"id"` // 用户ID
|
||||
Username string `gorm:"column:username" json:"username"` // 用户真实姓名
|
||||
Password string `gorm:"column:password" json:"password"` // 用户密码
|
||||
Role int `gorm:"column:role" json:"role"` // 用户角色
|
||||
@@ -14,6 +14,7 @@ type BackUser struct {
|
||||
Approver int `gorm:"column:approver" json:"approver"` // 注册审核人ID
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"`
|
||||
IsDelete int8 `gorm:"column:is_delete" json:"isDelete"` // 删除标志
|
||||
Region string `gorm:"column:region" json:"region"` // 用户所属地域
|
||||
}
|
||||
|
||||
type UserLogin struct {
|
||||
@@ -27,6 +28,8 @@ type UserRegister struct {
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Aptitude string `json:"aptitude"`
|
||||
Region string `json:"region"`
|
||||
Role int `json:"role"`
|
||||
}
|
||||
|
||||
type UserChangePwd struct {
|
||||
@@ -40,6 +43,14 @@ type UserApprove struct {
|
||||
Pass bool `json:"pass"`
|
||||
}
|
||||
|
||||
type TokenClaims struct {
|
||||
ID int `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Role int `json:"role"`
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
initJcMap[BackUser]()
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"nCovTrack-Backend/global"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var colNameReg, _ = regexp.Compile(".*column:(.*);?")
|
||||
@@ -60,17 +62,60 @@ func MapJ2c[T any](jsonMap map[string]interface{}, ignoreNil bool) (colMap map[s
|
||||
return colMap
|
||||
}
|
||||
|
||||
func MapsJ2c[T any](jsonMaps []map[string]interface{}, ignoreNil bool) (colMaps []map[string]interface{}) {
|
||||
for _, jsonMap := range jsonMaps {
|
||||
colMap := MapJ2c[T](jsonMap, ignoreNil)
|
||||
colMaps = append(colMaps, colMap)
|
||||
}
|
||||
return colMaps
|
||||
}
|
||||
|
||||
func MapC2j[T any](colMap map[string]interface{}, ignoreNil bool) (jsonMap map[string]interface{}) {
|
||||
tName := reflect.TypeOf(new(T)).Elem().Name()
|
||||
tC2jMap := c2jMap[tName]
|
||||
if tC2jMap == nil {
|
||||
panic(tName + " is not init registered int j2cMap")
|
||||
}
|
||||
|
||||
jsonMap = make(map[string]interface{})
|
||||
for k, v := range colMap {
|
||||
//TODO 无法转换
|
||||
if jsonKey := tC2jMap[k]; jsonKey != "" && (!ignoreNil || v != nil) {
|
||||
jsonMap[jsonKey] = v
|
||||
}
|
||||
}
|
||||
return jsonMap
|
||||
}
|
||||
|
||||
func MapsC2j[T any](jsonMaps []map[string]interface{}, ignoreNil bool) (colMaps []map[string]interface{}) {
|
||||
for _, jsonMap := range jsonMaps {
|
||||
colMap := MapC2j[T](jsonMap, ignoreNil)
|
||||
colMaps = append(colMaps, colMap)
|
||||
}
|
||||
return colMaps
|
||||
}
|
||||
|
||||
// BeforeSave need to set some field while insert or update
|
||||
func BeforeSave(colMap map[string]interface{}, user int) {
|
||||
if colMap["id"] == nil {
|
||||
if colMap["id"] == nil || int(colMap["id"].(float64)) == 0 {
|
||||
colMap["create_time"] = time.Now()
|
||||
if user != -1 {
|
||||
colMap["create_user"] = user
|
||||
} else {
|
||||
colMap["create_user"] = 0
|
||||
}
|
||||
}
|
||||
colMap["modify_time"] = time.Now()
|
||||
if user != -1 {
|
||||
colMap["modify_user"] = user
|
||||
} else {
|
||||
colMap["modify_user"] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func BeforeBatchSave(colMaps *[]map[string]interface{}, user int) {
|
||||
for _, colMap := range *colMaps {
|
||||
BeforeSave(colMap, user)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +126,7 @@ func BeforeSave(colMap map[string]interface{}, user int) {
|
||||
|
||||
func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
||||
var tx *gorm.DB
|
||||
if colMap["id"] == nil {
|
||||
if colMap["id"] == nil || getMapId(colMap["id"]) == 0 {
|
||||
tx = global.Db.Model(new(T)).Create(colMap)
|
||||
} else {
|
||||
tx = global.Db.Model(new(T)).Where("id = ?", colMap["id"]).Updates(colMap)
|
||||
@@ -93,13 +138,44 @@ func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64)
|
||||
return true, tx.RowsAffected
|
||||
}
|
||||
|
||||
func BatchInsert[T any](colMaps []map[string]interface{}) (ok bool, rowsAffected int64) {
|
||||
tx := global.Db.Model(new(T)).Create(&colMaps)
|
||||
if tx.Error != nil {
|
||||
fmt.Println(tx.Error)
|
||||
return false, 0
|
||||
}
|
||||
return true, tx.RowsAffected
|
||||
}
|
||||
|
||||
func Update[T any](queryMap []map[string]interface{}, updateMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
||||
tx := global.Db.Model(new(T))
|
||||
for _, e := range queryMap {
|
||||
e[IS_DELETE] = 0
|
||||
tx = tx.Or(e)
|
||||
}
|
||||
return UpdateByOrm(tx, updateMap)
|
||||
}
|
||||
|
||||
func UpdateByOrm(tx *gorm.DB, updateMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
||||
tx.Updates(updateMap)
|
||||
if tx.Error != nil {
|
||||
fmt.Println(tx.Error)
|
||||
return false, 0
|
||||
}
|
||||
return true, tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeleteById will delete by id, not delete the record from database, only set the field "is_delete" as 1
|
||||
func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
|
||||
tx := global.Db.Model(new(T)).Where("id = ?", id).Update("is_delete", 1)
|
||||
if tx.Error != nil {
|
||||
return false, 0
|
||||
}
|
||||
return true, rowsAffected
|
||||
return true, tx.RowsAffected
|
||||
}
|
||||
|
||||
func DropById[T any](id int) {
|
||||
global.Db.Model(new(T)).Delete("id = ?", id)
|
||||
}
|
||||
|
||||
func List[T any](queryMap []map[string]interface{}) *[]map[string]interface{} {
|
||||
@@ -179,3 +255,17 @@ func CountByOrm(tx *gorm.DB) int64 {
|
||||
tx.Count(&count)
|
||||
return count
|
||||
}
|
||||
|
||||
func getMapId(id interface{}) int {
|
||||
switch id.(type) {
|
||||
case int:
|
||||
return id.(int)
|
||||
case string:
|
||||
id, _ := strconv.Atoi(id.(string))
|
||||
return id
|
||||
case float64:
|
||||
return int(id.(float64))
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,17 @@ import (
|
||||
func articlePrivateRouter(router *gin.RouterGroup) {
|
||||
articleRouter := router.Group("/article")
|
||||
{
|
||||
articleRouter.POST("", handler.SaveArticleHandler)
|
||||
articleRouter.DELETE("/:id", handler.DeleteArticleHandler)
|
||||
articleRouter.POST("/:id/publish", handler.PublishArticleHandler)
|
||||
articleRouter.GET("/list/:published", handler.ListArticlesByUser)
|
||||
}
|
||||
}
|
||||
|
||||
func articlePublicRouter(router *gin.RouterGroup) {
|
||||
articleRouter := router.Group("/article")
|
||||
{
|
||||
articleRouter.POST("", handler.SaveArticleHandler)
|
||||
articleRouter.GET("/list", handler.GetAllArticlesHandler)
|
||||
articleRouter.GET("/list", handler.ListPublishedArticlesHandler)
|
||||
articleRouter.GET("/:id", handler.GetArticleHandler)
|
||||
}
|
||||
}
|
||||
|
||||
23
router/management.go
Normal file
23
router/management.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/handler"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func managementPrivateRouter(router *gin.RouterGroup) {
|
||||
managementRouter := router.Group("/management")
|
||||
{
|
||||
managementRouter.GET("/faker/:patientId", handler.PullContactHandler)
|
||||
managementRouter.GET("/observation", handler.ListObservationsHandler)
|
||||
managementRouter.POST("/observation", handler.InsertObservationHandler)
|
||||
managementRouter.GET("/observation/:id", handler.GetObservationHandler)
|
||||
managementRouter.GET("/observation/tree/:id/:direction", handler.TreeifyObservationHandler)
|
||||
managementRouter.PUT("/observation", handler.UpdateObservationHandler)
|
||||
managementRouter.POST("/location/", handler.InsertLocationHandler)
|
||||
managementRouter.GET("/location/", handler.ListLocationHandler)
|
||||
managementRouter.DELETE("/location/", handler.DeleteLocationHandler)
|
||||
managementRouter.POST("/pcr/", handler.InsertPcrHandler)
|
||||
}
|
||||
}
|
||||
17
router/notify.go
Normal file
17
router/notify.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/handler"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func notifyPrivateRouter(router *gin.RouterGroup) {
|
||||
notifyRouter := router.Group("/notify")
|
||||
{
|
||||
notifyRouter.GET("/count", handler.CountNotificationHandler)
|
||||
notifyRouter.POST("/", handler.InsertNotificationHandler)
|
||||
notifyRouter.GET("/:start/:end", handler.ListNotificationHandler)
|
||||
notifyRouter.DELETE("/:index", handler.DeleteNotificationHandler)
|
||||
}
|
||||
}
|
||||
@@ -21,5 +21,7 @@ func BusiRouter() {
|
||||
{
|
||||
articlePrivateRouter(privateRouter)
|
||||
userPrivateRouter(privateRouter)
|
||||
notifyPrivateRouter(privateRouter)
|
||||
managementPrivateRouter(privateRouter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
func statisticRouter(router *gin.RouterGroup) {
|
||||
statisticsRouter := router.Group("/statistics")
|
||||
{
|
||||
statisticsRouter.GET("/provience/:sort", handler.ProvinceDataHandler)
|
||||
statisticsRouter.GET("/province/:sort", handler.ProvinceDataHandler)
|
||||
statisticsRouter.GET("/city/:sort", handler.CityDataHandler)
|
||||
statisticsRouter.GET("/country/child", handler.CountryDataHandler)
|
||||
statisticsRouter.GET("/country", handler.CountryDataHandler)
|
||||
statisticsRouter.GET("/china", handler.ChinaDataHandler)
|
||||
statisticsRouter.GET("/china/trend", handler.ChinaTrendHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ func userPrivateRouter(router *gin.RouterGroup) {
|
||||
userRouter := router.Group("/user")
|
||||
{
|
||||
userRouter.POST("/approve", handler.UserApproveHandler)
|
||||
userRouter.GET("/registers", handler.ListRegisterUserHandler)
|
||||
userRouter.GET("/registers/:approved", handler.ListRegisterUserHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,46 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//ListPublishedArticles list the articles published, use to show the articles to all people
|
||||
func ListPublishedArticles() *[]map[string]interface{} {
|
||||
article := models.ListField[models.BackArticle]([]map[string]interface{}{{"is_publish": 0}}, true, "content")
|
||||
if *article == nil {
|
||||
article = &[]map[string]interface{}{}
|
||||
}
|
||||
return article
|
||||
func ListPublishedArticles() *[]models.ListArticle {
|
||||
return listArticles(1, 0)
|
||||
}
|
||||
|
||||
//ListAllArticles list all articles, will show the articles not published of the user
|
||||
// TODO: need only show the user's not published article
|
||||
func ListAllArticles() *[]map[string]interface{} {
|
||||
article := models.ListField[models.BackArticle]([]map[string]interface{}{{}}, true, "content")
|
||||
if *article == nil {
|
||||
article = &[]map[string]interface{}{}
|
||||
//ListPublishedArticlesByUser list the user's published articles
|
||||
func ListPublishedArticlesByUser(id int) *[]models.ListArticle {
|
||||
return listArticles(1, id)
|
||||
}
|
||||
|
||||
//ListNotPublishedArticlesByUser list the user's not publish articles
|
||||
func ListNotPublishedArticlesByUser(id int) *[]models.ListArticle {
|
||||
return listArticles(0, id)
|
||||
}
|
||||
|
||||
//listArticles complex function need to directly use gorm
|
||||
func listArticles(isPublish int, createUser int) *[]models.ListArticle {
|
||||
queryStr := "back_article.is_delete = 0 AND is_publish = " + strconv.Itoa(isPublish)
|
||||
if createUser != 0 {
|
||||
queryStr += " AND create_user = " + strconv.Itoa(createUser)
|
||||
}
|
||||
return article
|
||||
var res []models.ListArticle
|
||||
global.Db.Table("back_article").
|
||||
Select("back_user.username, back_article.*").
|
||||
Joins("join back_user on back_article.create_user=back_user.id").
|
||||
Where(queryStr).Find(&res)
|
||||
if res == nil {
|
||||
res = []models.ListArticle{}
|
||||
}
|
||||
return &res
|
||||
}
|
||||
|
||||
//SaveArticle save the articles
|
||||
func SaveArticle(article map[string]interface{}) (ok bool) {
|
||||
models.BeforeSave(article, -1)
|
||||
func SaveArticle(claims models.TokenClaims, article map[string]interface{}) (ok bool) {
|
||||
models.BeforeSave(article, claims.ID)
|
||||
ok, rows := models.Upsert[models.BackArticle](article)
|
||||
return ok && rows != 0
|
||||
}
|
||||
|
||||
111
service/management/faker.go
Normal file
111
service/management/faker.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//fakerGetRequest Get data from faker
|
||||
func fakerGetRequest(uri string) string {
|
||||
resStr := utils.GetWhioutHeader(global.FACKER_HOST + uri)
|
||||
var res utils.GinResponse
|
||||
_ = json.Unmarshal([]byte(resStr), &res)
|
||||
dataStr, _ := json.Marshal(res.Data)
|
||||
return string(dataStr)
|
||||
}
|
||||
|
||||
//queryHotelContacts Hotel contacts
|
||||
func queryHotelContacts(identification string) []models.HotelContactRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/hotel/" + identification)
|
||||
var data []models.HotelContactRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
//queryRailwayContacts Railway contacts
|
||||
func queryRailwayContacts(identification string) []models.RailwayContactRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/railway/" + identification)
|
||||
var data []models.RailwayContactRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
//queryPatients Patients
|
||||
func QueryPatients(identification string) []models.PatientRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/railway/" + identification)
|
||||
var data []models.PatientRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
//queryContacts Resolve the diffrent of hotel and railway request
|
||||
func queryContacts(identification string) []models.BackObservation {
|
||||
hotelContacts := queryHotelContacts(identification)
|
||||
railwayContacts := queryRailwayContacts(identification)
|
||||
observations := append(fakerContacts2Observations(hotelContacts), fakerContacts2Observations(railwayContacts)...)
|
||||
return observations
|
||||
}
|
||||
|
||||
//splitFakerAddress Extract the region
|
||||
func splitFakerAddress(fakerAddress string) string {
|
||||
addresses := strings.Split(fakerAddress, " ")
|
||||
return addresses[1] + " " + addresses[2]
|
||||
}
|
||||
|
||||
//fakerContacts2Observations Convvert structs
|
||||
func fakerContacts2Observations(contacts any) []models.BackObservation {
|
||||
var observations []models.BackObservation
|
||||
switch contacts.(type) {
|
||||
case []models.HotelContactRequest:
|
||||
for _, contact := range contacts.([]models.HotelContactRequest) {
|
||||
tranjectory := fmt.Sprintf("在%s-%s期间,与患者同期留宿%s", contact.InData.String(), contact.OutData.String(), contact.HotelName)
|
||||
observation := &models.BackObservation{
|
||||
Name: contact.Name,
|
||||
Age: contact.Age,
|
||||
Sex: contact.Sex,
|
||||
Phone: contact.Phone,
|
||||
Identification: contact.Identification,
|
||||
Region: splitFakerAddress(contact.Address),
|
||||
Address: "",
|
||||
HealthSituation: global.HEALTH_SITUATION_ID_MAP["CONTACT"],
|
||||
HealthChangeTime: time.Now(),
|
||||
MeasureSituation: global.MEASURE_SITUATION_ID_MAP["NOMEASURE"],
|
||||
Trajectory: tranjectory,
|
||||
}
|
||||
observations = append(observations, *observation)
|
||||
}
|
||||
case []models.RailwayContactRequest:
|
||||
for _, contact := range contacts.([]models.RailwayContactRequest) {
|
||||
tranjectory := fmt.Sprintf("在%s,与患者同期乘坐%s", contact.Launch.String(), contact.Train)
|
||||
observation := &models.BackObservation{
|
||||
Name: contact.Name,
|
||||
Age: contact.Age,
|
||||
Sex: contact.Sex,
|
||||
Phone: contact.Phone,
|
||||
Identification: contact.Identification,
|
||||
Region: splitFakerAddress(contact.Address),
|
||||
Address: "",
|
||||
HealthSituation: global.HEALTH_SITUATION_ID_MAP["CONTACT"],
|
||||
HealthChangeTime: time.Now(),
|
||||
MeasureSituation: global.MEASURE_SITUATION_ID_MAP["NOMEASURE"],
|
||||
Trajectory: tranjectory,
|
||||
}
|
||||
observations = append(observations, *observation)
|
||||
}
|
||||
}
|
||||
return observations
|
||||
}
|
||||
25
service/management/location.go
Normal file
25
service/management/location.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/models"
|
||||
)
|
||||
|
||||
//InsertLocation Insert locations
|
||||
func InsertLocation(claims models.TokenClaims, locationJMap map[string]interface{}) bool {
|
||||
locationCMap := models.MapJ2c[models.BackLocation](locationJMap, true)
|
||||
models.BeforeSave(locationCMap, claims.ID)
|
||||
ok, rowsAffected := models.Upsert[models.BackLocation](locationCMap)
|
||||
return (ok && rowsAffected != 0)
|
||||
}
|
||||
|
||||
//ListLocation List locations
|
||||
func ListLocation(queryJMap map[string]any) *[]map[string]any {
|
||||
queryCMap := models.MapJ2c[models.BackLocation](queryJMap, true)
|
||||
return models.ListField[models.BackLocation]([]map[string]any{queryCMap}, true, "is_delete")
|
||||
}
|
||||
|
||||
//DeleteLocation Delete locations
|
||||
func DeleteLocation(id int) bool {
|
||||
ok, rowsAffected := models.DeleteById[models.BackLocation](id)
|
||||
return (ok && rowsAffected != 0)
|
||||
}
|
||||
389
service/management/observation.go
Normal file
389
service/management/observation.go
Normal file
@@ -0,0 +1,389 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/service/notify"
|
||||
"nCovTrack-Backend/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
//PullFromFaker Pull observations from faker system
|
||||
func PullFromFaker(claims models.TokenClaims, patientId int) int64 {
|
||||
// Get patient's identification by id
|
||||
queryMap := []map[string]interface{}{{"id": patientId}}
|
||||
patient := models.GetField[models.BackObservation](queryMap, false, "identification")
|
||||
if patient == nil || patient["identification"] == nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
// Pull contacts form faker
|
||||
observations := queryContacts(patient["identification"].(string))
|
||||
// Set ContactPerson
|
||||
for i := range observations {
|
||||
observations[i].ContactPerson = patientId
|
||||
}
|
||||
// Insert into db
|
||||
var observationsJMap []map[string]interface{}
|
||||
utils.Strcut2Map(observations, &observationsJMap)
|
||||
observationsCMap := models.MapsJ2c[models.BackObservation](observationsJMap, false)
|
||||
models.BeforeBatchSave(&observationsCMap, claims.ID)
|
||||
_, rowsAffected := models.BatchInsert[models.BackObservation](observationsCMap)
|
||||
// Generate situation record and send notify to the region
|
||||
if rowsAffected != 0 {
|
||||
pullSituationRecord(claims, observations)
|
||||
pullNotify(observations)
|
||||
}
|
||||
return rowsAffected
|
||||
}
|
||||
|
||||
//ListObservation list observations with query
|
||||
func ListObservation(jsonMap map[string]interface{}) []models.ListObservation {
|
||||
colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
|
||||
queryMap := []map[string]interface{}{colMap}
|
||||
return listObservation(queryMap)
|
||||
}
|
||||
|
||||
//GetObservation get observation by id
|
||||
func GetObservation(id int) map[string]interface{} {
|
||||
// Obseration
|
||||
observationCMap := models.GetField[models.BackObservation]([]map[string]interface{}{{"id": id}}, true, "is_delete")
|
||||
observationJMap := models.MapC2j[models.BackObservation](observationCMap, true)
|
||||
// Pcr record
|
||||
pcrRecordCMap := models.ListField[models.BackPcr]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
|
||||
pcrRecordJMap := models.MapsC2j[models.BackPcr](*pcrRecordCMap, true)
|
||||
// Situation record
|
||||
situationRecordCMap := models.ListField[models.BackSituationRecord]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
|
||||
situationRecordJMap := models.MapsC2j[models.BackSituationRecord](*situationRecordCMap, true)
|
||||
// Assemble
|
||||
observationJMap["pcrRecord"] = pcrRecordJMap
|
||||
observationJMap["situationRecord"] = situationRecordJMap
|
||||
return observationJMap
|
||||
}
|
||||
|
||||
//InsertObservation add observation
|
||||
func InsertObservation(claims models.TokenClaims, jsonMap map[string]interface{}) bool {
|
||||
colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
|
||||
models.BeforeSave(colMap, claims.ID)
|
||||
ok, rowsAffected := models.Upsert[models.BackObservation](colMap)
|
||||
queryMap := []map[string]interface{}{{"identification": jsonMap["identification"]}}
|
||||
// Get result after insert, assemble record will use it.
|
||||
newObservation := models.GetField[models.BackObservation](queryMap, true)
|
||||
recordOk := insertSituationRecord(claims, map[string]interface{}{}, newObservation)
|
||||
return (ok && recordOk && rowsAffected != 0)
|
||||
}
|
||||
|
||||
func UpdateObservation(claims models.TokenClaims, jsonMap map[string]any) bool {
|
||||
// Pre actions
|
||||
colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
|
||||
models.BeforeSave(colMap, claims.ID)
|
||||
queryMap := []map[string]interface{}{{"id": jsonMap["id"]}}
|
||||
// Get old record
|
||||
oldMap := models.Get[models.BackObservation](queryMap)
|
||||
if oldMap == nil || len(oldMap) == 0 {
|
||||
return false
|
||||
}
|
||||
// Deal with region update
|
||||
if colMap["region"] != nil && oldMap["region"].(string) != colMap["region"].(string) {
|
||||
updateObservationRegion(colMap["region"].(string))
|
||||
}
|
||||
// Deal with situation update
|
||||
if colMap["health_situation"] != nil && int(colMap["health_situation"].(float64)) != oldMap["health_situation"].(int) ||
|
||||
colMap["measure_situation"] != nil && int(colMap["measure_situation"].(float64)) != oldMap["measure_situation"].(int) {
|
||||
updateSituation(claims, oldMap, colMap)
|
||||
}
|
||||
ok, rowsAffected := models.Update[models.BackObservation](queryMap, colMap)
|
||||
return ok && rowsAffected != 0
|
||||
}
|
||||
|
||||
//TreeifyObservations get the transmission chains of observations
|
||||
// Param direction: up, down, all
|
||||
func TreeifyObservations(observationId int, direction string) *models.TreeObservation {
|
||||
// Get arrays form back observation
|
||||
var observations []models.BackObservation
|
||||
if direction != "down" {
|
||||
observations = append(observations, treeifyObservations(observationId, true)...)
|
||||
}
|
||||
if direction != "up" {
|
||||
observations = append(observations, treeifyObservations(observationId, false)...)
|
||||
}
|
||||
// Treeify
|
||||
observationMap := map[int]*models.TreeObservation{}
|
||||
for _, observation := range observations {
|
||||
observationMap[observation.ID] = &models.TreeObservation{
|
||||
ID: observation.ID,
|
||||
Name: observation.Name,
|
||||
Age: observation.Age,
|
||||
Sex: observation.Sex,
|
||||
Phone: observation.Phone,
|
||||
Identification: observation.Identification,
|
||||
ContactPerson: observation.ContactPerson,
|
||||
Region: observation.Region,
|
||||
Address: observation.Address,
|
||||
HealthSituation: observation.HealthSituation,
|
||||
HealthChangeTime: observation.HealthChangeTime,
|
||||
CreateUser: observation.CreateUser,
|
||||
CreateTime: observation.CreateTime,
|
||||
ModifyUser: observation.ModifyUser,
|
||||
ModifyTime: observation.ModifyTime,
|
||||
}
|
||||
}
|
||||
var rootKey int
|
||||
for k := range observationMap {
|
||||
parentId := observationMap[k].ContactPerson
|
||||
parent := observationMap[parentId]
|
||||
if parent == nil {
|
||||
rootKey = k
|
||||
continue
|
||||
}
|
||||
parent.Children = append(parent.Children, observationMap[k])
|
||||
}
|
||||
return observationMap[rootKey]
|
||||
}
|
||||
|
||||
//treeifyObservations query tree data from db
|
||||
// Param direction up: true, down: false
|
||||
func treeifyObservations(observationId int, direction bool) []models.BackObservation {
|
||||
var res []models.BackObservation
|
||||
var directionCond string
|
||||
if direction {
|
||||
directionCond = "p.id = cte.contact_person"
|
||||
} else {
|
||||
directionCond = "cte.id = p.contact_person"
|
||||
}
|
||||
querySql := fmt.Sprintf(`
|
||||
WITH RECURSIVE cte (id, name, age, sex, phone, identification, contact_person, region, address, health_situation, health_change_time, trajectory, create_user, modify_user, create_time, modify_time) AS (
|
||||
SELECT id, name, age, sex, phone, identification, contact_person, region, address, health_situation, health_change_time, trajectory, create_user, modify_user, create_time, modify_time
|
||||
FROM back_observation
|
||||
WHERE contact_person = ?
|
||||
UNION ALL
|
||||
SELECT p.id, p.name, p.age, p.sex, p.phone, p.identification, p.contact_person, p.region, p.address, p.health_situation, p.health_change_time, p.trajectory, p.create_user, p.modify_user, p.create_time, p.modify_time
|
||||
FROM back_observation p
|
||||
INNER JOIN cte ON %s
|
||||
)
|
||||
SELECT * FROM cte
|
||||
`, directionCond)
|
||||
global.Db.Model(models.BackObservation{}).Raw(querySql, observationId).Scan(&res)
|
||||
return res
|
||||
}
|
||||
|
||||
//listObservation the queryMap need with table name
|
||||
// Param queryMap the colMap of models.BackObservation
|
||||
func listObservation(queryMap []map[string]interface{}) []models.ListObservation {
|
||||
var observations []models.ListObservation
|
||||
tx := global.Db.Model(new((models.BackObservation))).
|
||||
Select("back_observation.*, back_pcr.detect_time AS pcr_time, detect_result AS pcr_result," +
|
||||
"back_situation_record.create_time AS record_time, back_situation_record.record AS record").
|
||||
Joins("LEFT JOIN back_pcr ON back_observation.id = back_pcr.observation").
|
||||
Joins("LEFT JOIN back_situation_record ON back_observation.id = back_situation_record.observation")
|
||||
for _, query := range queryMap {
|
||||
query["is_delete"] = 0
|
||||
// Add the table prefix
|
||||
fullQuery := map[string]interface{}{}
|
||||
for k := range query {
|
||||
fullQuery["back_observation."+k] = query[k]
|
||||
}
|
||||
tx = tx.Or(fullQuery)
|
||||
}
|
||||
tx.Find(&observations)
|
||||
return observations
|
||||
}
|
||||
|
||||
//pullSituationRecord push situation record after pull observations
|
||||
func pullSituationRecord(claims models.TokenClaims, observations []models.BackObservation) {
|
||||
// Query observations' id
|
||||
var identifications []string
|
||||
for _, observation := range observations {
|
||||
identifications = append(identifications, observation.Identification)
|
||||
}
|
||||
queryMap := []map[string]interface{}{{"identification": identifications}}
|
||||
observationMaps := models.ListField[models.BackObservation](queryMap, false, "id", "identification")
|
||||
// Assemble records
|
||||
var records []models.BackSituationRecord
|
||||
recordContent := record___20()
|
||||
for _, observationMap := range *observationMaps {
|
||||
record := models.BackSituationRecord{Observation: observationMap["id"].(int), Record: recordContent}
|
||||
records = append(records, record)
|
||||
}
|
||||
// Insert into db
|
||||
var recordsJMaps []map[string]interface{}
|
||||
utils.Strcut2Map(records, &recordsJMaps)
|
||||
recordsCMaps := models.MapsJ2c[models.BackSituationRecord](recordsJMaps, true)
|
||||
models.BeforeBatchSave(&recordsCMaps, claims.ID)
|
||||
models.BatchInsert[models.BackSituationRecord](recordsCMaps)
|
||||
}
|
||||
|
||||
//pullNotify send notify after pull observations
|
||||
func pullNotify(observations []models.BackObservation) {
|
||||
var regions []string
|
||||
for _, observation := range observations {
|
||||
regions = append(regions, observation.Region)
|
||||
}
|
||||
regions = utils.Distinct(regions)
|
||||
notification := models.BackNotification{Time: time.Now(), Kind: "疫情", Content: "出现了新的接触者,请及时登录系统进行处理"}
|
||||
sendInfo := models.SendInfo{Region: regions, Channel: []int{0, 1}, Notification: notification}
|
||||
notify.SendNotify(sendInfo)
|
||||
}
|
||||
|
||||
//updateObservationRegion send notify while update observation's region
|
||||
func updateObservationRegion(region string) {
|
||||
notification := models.BackNotification{Time: time.Now(), Kind: "疫情", Content: "本地有新的接触者,请及时登录系统进行处理"}
|
||||
sendInfo := models.SendInfo{Region: []string{region}, Channel: []int{0, 1}, Notification: notification}
|
||||
notify.SendNotify(sendInfo)
|
||||
}
|
||||
|
||||
//updateSituation make some special resolve while situation update
|
||||
func updateSituation(claims models.TokenClaims, oldObservationMap, newObservationMap map[string]interface{}) {
|
||||
if newObservationMap["health_situation"] != nil {
|
||||
newHealthSituation := int(newObservationMap["health_situation"].(float64))
|
||||
oldHealthSituation := oldObservationMap["health_situation"].(int)
|
||||
// Update health situation change time and measure_situation
|
||||
if newHealthSituation != oldHealthSituation {
|
||||
newObservationMap["health_change_time"] = time.Now()
|
||||
newObservationMap["measure_situation"] = 0
|
||||
}
|
||||
// Deal with contact to patient
|
||||
if oldHealthSituation == 2 && newHealthSituation == 1 {
|
||||
// Query sub contacts
|
||||
queryMap := []map[string]interface{}{{"contact_person": oldObservationMap["id"].(int)}}
|
||||
subContacts := models.ListField[models.BackObservation](queryMap, false, "id", "region")
|
||||
// Get reginos and assemble situation record
|
||||
var regions []string
|
||||
var subContactRecords []models.BackSituationRecord
|
||||
for _, subContact := range *subContacts {
|
||||
regions = append(regions, subContact["region"].(string))
|
||||
subContactRecord := models.BackSituationRecord{
|
||||
Observation: int(newObservationMap["id"].(float64)),
|
||||
Record: record___20(),
|
||||
}
|
||||
subContactRecords = append(subContactRecords, subContactRecord)
|
||||
}
|
||||
// Update sub contact
|
||||
updateMap := map[string]interface{}{
|
||||
"health_situation": 2,
|
||||
"health_change_time": newObservationMap["health_change_time"],
|
||||
"measure_situation": 0,
|
||||
}
|
||||
models.Update[models.BackObservation](queryMap, updateMap)
|
||||
|
||||
// Insert subContacts' record
|
||||
var recordJMaps []map[string]interface{}
|
||||
utils.Strcut2Map(subContactRecords, &recordJMaps)
|
||||
recordCMap := models.MapsJ2c[models.BackSituationRecord](recordJMaps, true)
|
||||
models.BeforeBatchSave(&recordCMap, claims.ID)
|
||||
models.BatchInsert[models.BackSituationRecord](recordCMap)
|
||||
|
||||
// Send nofity
|
||||
regions = utils.Distinct(regions)
|
||||
notification := models.BackNotification{
|
||||
Time: newObservationMap["health_change_time"].(time.Time),
|
||||
Kind: "疫情",
|
||||
Content: "由于密接者转为患者,次密接者状态需要修改",
|
||||
}
|
||||
sendInfo := models.SendInfo{
|
||||
Region: regions,
|
||||
Channel: []int{0, 1},
|
||||
Notification: notification,
|
||||
}
|
||||
notify.SendNotify(sendInfo)
|
||||
}
|
||||
insertSituationRecord(claims, oldObservationMap, newObservationMap)
|
||||
}
|
||||
}
|
||||
|
||||
//insertSituationRecord insert situation record
|
||||
func insertSituationRecord(claims models.TokenClaims, oldObservation, newObservation map[string]interface{}) bool {
|
||||
var oldSituation, newSituation string
|
||||
if oldObservation["id"] == nil {
|
||||
// insert observation
|
||||
oldSituation = "00"
|
||||
} else {
|
||||
// update observation
|
||||
oldSituation = fmt.Sprintf("%d%d", oldObservation["health_situation"], oldObservation["measure_situation"])
|
||||
}
|
||||
if newObservation["health_situation"] == nil || newObservation["measure_situation"] == nil {
|
||||
// Situation not update
|
||||
return true
|
||||
}
|
||||
newSituation = fmt.Sprintf("%d%d", newObservation["health_situation"], newObservation["measure_situation"])
|
||||
|
||||
// Situation not update
|
||||
if oldSituation == newSituation {
|
||||
return true
|
||||
}
|
||||
// Set record content accrodding the situation convertions
|
||||
var recordContent string
|
||||
situationConvert := oldSituation + "_" + newSituation
|
||||
switch situationConvert {
|
||||
case "00_10":
|
||||
recordContent = record00_10()
|
||||
case "00_30":
|
||||
recordContent = record00_30()
|
||||
case "00_12":
|
||||
recordContent = record00_12(newObservation["region"].(string), newObservation["address"].(string))
|
||||
case "10_12":
|
||||
recordContent = record10_12(newObservation["region"].(string), newObservation["address"].(string))
|
||||
case "00_20", "33_20", "34_20":
|
||||
recordContent = record___20()
|
||||
case "12_01", "23_01", "24_01", "33_01", "34_01":
|
||||
recordContent = record___01()
|
||||
case "20_23", "30_33", "24_23", "34_33":
|
||||
recordContent = record____3(newObservation["region"].(string), newObservation["address"].(string))
|
||||
case "20_24", "30_34", "23_24", "33_34":
|
||||
recordContent = record____4(newObservation["region"].(string), newObservation["address"].(string))
|
||||
case "23_10", "24_10", "33_10", "34_10":
|
||||
recordContent = record___10()
|
||||
default:
|
||||
if oldSituation != "00" {
|
||||
models.Upsert[models.BackObservation](oldObservation)
|
||||
} else {
|
||||
models.DropById[models.BackObservation](newObservation["id"].(int))
|
||||
}
|
||||
return false
|
||||
}
|
||||
record := models.BackSituationRecord{Observation: newObservation["id"].(int), Record: recordContent}
|
||||
var recordJMap map[string]interface{}
|
||||
utils.Strcut2Map(record, &recordJMap)
|
||||
recordCMap := models.MapJ2c[models.BackSituationRecord](recordJMap, true)
|
||||
models.BeforeSave(recordCMap, claims.ID)
|
||||
models.Upsert[models.BackSituationRecord](recordCMap)
|
||||
return true
|
||||
}
|
||||
|
||||
func record00_10() string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return date + " 确诊为患者"
|
||||
}
|
||||
func record00_12(region, address string) string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return fmt.Sprintf("%s 于 %s %s 确诊为患者", date, region, address)
|
||||
}
|
||||
func record___20() string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return date + " 转为密接"
|
||||
}
|
||||
func record00_30() string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return date + " 转为次密接"
|
||||
}
|
||||
func record___01() string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return fmt.Sprintf("%s 解除风险", date)
|
||||
}
|
||||
func record10_12(region, address string) string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return fmt.Sprintf("%s 转至医院:%s %s", date, region, address)
|
||||
}
|
||||
func record___10() string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return date + " 确诊为患者"
|
||||
}
|
||||
func record____3(region, address string) string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return fmt.Sprintf("%s 集中隔离至:%s %s", date, region, address)
|
||||
}
|
||||
func record____4(region, address string) string {
|
||||
date := utils.FormatDate(time.Now())
|
||||
return fmt.Sprintf("%s 进行居家隔离:%s %s", date, region, address)
|
||||
}
|
||||
10
service/management/pcr.go
Normal file
10
service/management/pcr.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package management
|
||||
|
||||
import "nCovTrack-Backend/models"
|
||||
|
||||
func InsertPcr(claims models.TokenClaims, jsonMap map[string]interface{}) bool {
|
||||
colMap := models.MapJ2c[models.BackPcr](jsonMap, true)
|
||||
models.BeforeSave(colMap, claims.ID)
|
||||
ok, rowsAffected := models.Upsert[models.BackPcr](colMap)
|
||||
return ok && rowsAffected != 0
|
||||
}
|
||||
89
service/notify/notify.go
Normal file
89
service/notify/notify.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
)
|
||||
|
||||
type NotifyFunc func([]string, models.BackNotification)
|
||||
|
||||
const (
|
||||
NOTIFY_KEY = "notification_"
|
||||
NOTIFY_DEL_VALUE = "notify_del"
|
||||
)
|
||||
|
||||
var (
|
||||
NOTIFY_CHANNEL_FUNC_ARR = []NotifyFunc{notifyNotification, emailNotification}
|
||||
)
|
||||
|
||||
//emailNotification send email
|
||||
func emailNotification(regions []string, notification models.BackNotification) {
|
||||
queryMap := []map[string]interface{}{{"region": regions, "role": global.ROLE_ID_MAP["ADMIN"]}}
|
||||
observations := models.ListField[models.BackUser](queryMap, false, "email")
|
||||
var emails []string
|
||||
for _, observation := range *observations {
|
||||
emails = append(emails, observation["email"].(string))
|
||||
}
|
||||
utils.SendEmail(notification.Kind+"通知邮件", notification.Content, emails...)
|
||||
}
|
||||
|
||||
//notifyNotification add to notify system
|
||||
func notifyNotification(regions []string, notification models.BackNotification) {
|
||||
valueByte, _ := json.Marshal(notification)
|
||||
pipe := global.Redis.TxPipeline()
|
||||
for _, region := range regions {
|
||||
pipe.RPush(NOTIFY_KEY+region, valueByte)
|
||||
}
|
||||
pipe.Exec()
|
||||
}
|
||||
|
||||
//DeleteNotification delete notify by id
|
||||
func DeleteNotification(region string, index int) {
|
||||
key := NOTIFY_KEY + region
|
||||
pipe := global.Redis.TxPipeline()
|
||||
pipe.LSet(key, int64(index), NOTIFY_DEL_VALUE)
|
||||
pipe.LRem(key, 2, NOTIFY_DEL_VALUE)
|
||||
pipe.Exec()
|
||||
}
|
||||
|
||||
//CleanNotification delete all notify
|
||||
func CleanNotification(region string) {
|
||||
key := NOTIFY_KEY + region
|
||||
global.Redis.Del(key)
|
||||
}
|
||||
|
||||
//QueryNotificationLen query the count notification
|
||||
func QueryNotificationLen(region string) int {
|
||||
key := NOTIFY_KEY + region
|
||||
return int(global.Redis.LLen(key).Val())
|
||||
}
|
||||
|
||||
//ListNotifycation list the notifications ny range
|
||||
func ListNotifycation(region string, start, end int) []models.BackNotification {
|
||||
key := NOTIFY_KEY + region
|
||||
var notifications []models.BackNotification
|
||||
notificationStrArr := global.Redis.LRange(key, int64(start), int64(end)).Val()
|
||||
for _, notificationStr := range notificationStrArr {
|
||||
var notification models.BackNotification
|
||||
json.Unmarshal([]byte(notificationStr), ¬ification)
|
||||
notifications = append(notifications, notification)
|
||||
}
|
||||
return notifications
|
||||
}
|
||||
|
||||
//SendNotify send notify to kafka
|
||||
func SendNotify(send models.SendInfo) {
|
||||
sendInfo, _ := json.Marshal(send)
|
||||
global.KafkaProducerChan <- sendInfo
|
||||
}
|
||||
|
||||
//HandleKafkaNotify handle kafka info
|
||||
func HandleKafkaNotify(sendInfoByte []byte) {
|
||||
var sendInfo models.SendInfo
|
||||
json.Unmarshal(sendInfoByte, &sendInfo)
|
||||
for _, channel := range sendInfo.Channel {
|
||||
NOTIFY_CHANNEL_FUNC_ARR[channel](sendInfo.Region, sendInfo.Notification)
|
||||
}
|
||||
}
|
||||
@@ -12,26 +12,28 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
rds_NCOV_STATISTIC_KEY = "nCovStatistic"
|
||||
rds_CHINA_TOTAL_KEY = "chinaTotal"
|
||||
rds_CHINA_ADD_KEY = "chinaAdd"
|
||||
rds_COUNTRY_LEVEL_KEY = "countryLevel"
|
||||
rds_COUNTRY_LEVEL_CHILD_KEY = "countryLevelChild"
|
||||
rds_PROVIENCE_LEVEL_CHILD_KEY = "provienceLevelChild"
|
||||
rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY = "provienceLevelNowConfirm"
|
||||
rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY = "provienceLevelTodayConfirm"
|
||||
rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY = "provienceLevelTotalConfirm"
|
||||
rds_CITY_LEVEL_CHILD_KEY = "cityLevelChild"
|
||||
rds_CITY_LEVEL_NOW_CONFIRM_KEY = "cityLevelNowConfirm"
|
||||
rds_CITY_LEVEL_TODAY_CONFIRM_KEY = "cityLevelTodayConfirm"
|
||||
rds_CITY_LEVEL_TOTAL_CONFIRM_KEY = "cityLevelTotalConfirm"
|
||||
rds_LAST_UPDATE_TIME = "statisticsLastUpdateTime"
|
||||
rds_LAST_CACHE_TIME = "statisticsLastCacheTime"
|
||||
rds_NCOV_STATISTIC_KEY = "nCovStatistic"
|
||||
rds_CHINA_TOTAL_KEY = "chinaTotal"
|
||||
rds_CHINA_ADD_KEY = "chinaAdd"
|
||||
rds_COUNTRY_LEVEL_KEY = "countryLevel"
|
||||
rds_COUNTRY_LEVEL_CHILD_KEY = "countryLevelChild"
|
||||
rds_PROVINCE_LEVEL_CHILD_KEY = "provinceLevelChild"
|
||||
rds_PROVINCE_LEVEL_NOW_CONFIRM_KEY = "provinceLevelNowConfirm"
|
||||
rds_PROVINCE_LEVEL_TODAY_CONFIRM_KEY = "provinceLevelTodayConfirm"
|
||||
rds_PROVINCE_LEVEL_TOTAL_CONFIRM_KEY = "provinceLevelTotalConfirm"
|
||||
rds_CITY_LEVEL_CHILD_KEY = "cityLevelChild"
|
||||
rds_CITY_LEVEL_NOW_CONFIRM_KEY = "cityLevelNowConfirm"
|
||||
rds_CITY_LEVEL_TODAY_CONFIRM_KEY = "cityLevelTodayConfirm"
|
||||
rds_CITY_LEVEL_TOTAL_CONFIRM_KEY = "cityLevelTotalConfirm"
|
||||
rds_LAST_UPDATE_TIME = "statisticsLastUpdateTime"
|
||||
rds_LAST_CACHE_TIME = "statisticsLastCacheTime"
|
||||
rds_CHINA_DAY_ADD_LIST_KEY = "chinaDayAdd"
|
||||
rds_CHINA_DAY_LIST_KEY = "chinaDay"
|
||||
|
||||
SORT_TODAY_CONFIRM = "today"
|
||||
SORT_TOTAL_CONFIRM = "total"
|
||||
SORT_NOW_CONFIRM = "now"
|
||||
|
||||
D
|
||||
json_FOREIGN_COUNTRY = "境外"
|
||||
json_FOREIGN_CITY = "外地"
|
||||
json_TO_BE_CONFIRM = "待确认"
|
||||
@@ -45,16 +47,31 @@ type AreaSlice []models.AreaInfo
|
||||
|
||||
func cacheNCovStatistics() {
|
||||
resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL)
|
||||
var nCovRes map[string]string
|
||||
var nCovRes map[string]interface{}
|
||||
json.Unmarshal([]byte(resp), &nCovRes)
|
||||
var nCovResData map[string]interface{}
|
||||
json.Unmarshal([]byte(nCovRes["data"]), &nCovResData)
|
||||
nCovResData := (nCovRes["data"].(map[string]interface{}))["diseaseh5Shelf"].(map[string]interface{})
|
||||
if !needToRecache(nCovResData) {
|
||||
return
|
||||
}
|
||||
cacheChinaInfo(nCovResData)
|
||||
cacheLevelInfo(nCovResData)
|
||||
cacheLastUpdateTime(nCovResData)
|
||||
resp = utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_TREND_URL)
|
||||
}
|
||||
|
||||
func CacheNCovTrend() {
|
||||
resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_TREND_URL)
|
||||
var nCovRes map[string]interface{}
|
||||
json.Unmarshal([]byte(resp), &nCovRes)
|
||||
nCovResData := nCovRes["data"].(map[string]interface{})
|
||||
cacheChinaTrend(nCovResData)
|
||||
}
|
||||
|
||||
func cacheChinaTrend(data map[string]interface{}) {
|
||||
chinaDayAdd, _ := json.Marshal(data["chinaDayAddList"])
|
||||
chinaDay, _ := json.Marshal(data["chinaDayList"])
|
||||
global.Redis.Set(rds_CHINA_DAY_ADD_LIST_KEY, chinaDayAdd, 0)
|
||||
global.Redis.Set(rds_CHINA_DAY_LIST_KEY, chinaDay, 0)
|
||||
}
|
||||
|
||||
func cacheChinaInfo(data map[string]interface{}) {
|
||||
@@ -81,8 +98,8 @@ func cacheLevelInfo(data map[string]interface{}) {
|
||||
// Get Every Level's Info
|
||||
var countryLevels []models.AreaInfo
|
||||
json.Unmarshal(areaTree, &countryLevels)
|
||||
provienceLevels := children(countryLevels)
|
||||
cityLevels := children(provienceLevels)
|
||||
provinceLevels := children(countryLevels)
|
||||
cityLevels := children(provinceLevels)
|
||||
|
||||
// Country Level Area Info With Child
|
||||
cacheList(rds_COUNTRY_LEVEL_CHILD_KEY, areaInfoToJson(countryLevels)...)
|
||||
@@ -90,34 +107,34 @@ func cacheLevelInfo(data map[string]interface{}) {
|
||||
areaInfoChildNil(&countryLevels)
|
||||
cacheList(rds_COUNTRY_LEVEL_KEY, areaInfoToJson(countryLevels)...)
|
||||
|
||||
// Provience Level Area Info With Child
|
||||
cacheList(rds_PROVIENCE_LEVEL_CHILD_KEY, areaInfoToJson(provienceLevels)...)
|
||||
areaInfoChildNil(&provienceLevels)
|
||||
// Province Level Area Info With Child
|
||||
cacheList(rds_PROVINCE_LEVEL_CHILD_KEY, areaInfoToJson(provinceLevels)...)
|
||||
areaInfoChildNil(&provinceLevels)
|
||||
// City Level Area Info With Child
|
||||
cacheList(rds_CITY_LEVEL_CHILD_KEY, areaInfoToJson(cityLevels)...)
|
||||
areaInfoChildNil(&provienceLevels)
|
||||
areaInfoChildNil(&provinceLevels)
|
||||
|
||||
// Provience Level Area Info Sorted by Now Confirm
|
||||
provienceLevelsSlice := AreaSlice(provienceLevels)
|
||||
sort.Sort(provienceLevelsSlice)
|
||||
cacheList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
|
||||
// Province Level Area Info Sorted by Now Confirm
|
||||
provinceLevelsSlice := AreaSlice(provinceLevels)
|
||||
sort.Sort(provinceLevelsSlice)
|
||||
cacheList(rds_PROVINCE_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
|
||||
// City Level Area Info Sorted By Now Confirm
|
||||
cityLevelsSlice := AreaSlice(cityLevels)
|
||||
sort.Sort(cityLevelsSlice)
|
||||
cacheList(rds_CITY_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
|
||||
|
||||
sortBy = SORT_TODAY_CONFIRM
|
||||
// Provience Level Area Info Sorted by Today Confirm
|
||||
sort.Sort(provienceLevelsSlice)
|
||||
cacheList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
|
||||
// Province Level Area Info Sorted by Today Confirm
|
||||
sort.Sort(provinceLevelsSlice)
|
||||
cacheList(rds_PROVINCE_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
|
||||
// City Level Area Info Sorted by Today Confirm
|
||||
sort.Sort(cityLevelsSlice)
|
||||
cacheList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
|
||||
|
||||
sortBy = SORT_TOTAL_CONFIRM
|
||||
// Provience Level Area Info Sorted by Total Confirm
|
||||
sort.Sort(provienceLevelsSlice)
|
||||
cacheList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
|
||||
// Province Level Area Info Sorted by Total Confirm
|
||||
sort.Sort(provinceLevelsSlice)
|
||||
cacheList(rds_PROVINCE_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
|
||||
// City Level Area Info Sorted by Total Confirm
|
||||
sort.Sort(cityLevelsSlice)
|
||||
cacheList(rds_CITY_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
|
||||
@@ -137,6 +154,7 @@ func children(parents []models.AreaInfo) []models.AreaInfo {
|
||||
}
|
||||
for _, item := range parent.Children {
|
||||
name := item.Name
|
||||
item.Parent = parent.Name
|
||||
if !strings.Contains(name, json_FOREIGN_CITY) && !strings.Contains(name, json_FOREIGN_COUNTRY) && !strings.Contains(name, json_TO_BE_CONFIRM) {
|
||||
areaInfos = append(areaInfos, item)
|
||||
}
|
||||
|
||||
@@ -7,18 +7,18 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetAllProvienceData(sort string) []interface{} {
|
||||
func GetAllProvinceData(sort string) []interface{} {
|
||||
checkCache()
|
||||
if sort == SORT_TODAY_CONFIRM {
|
||||
return getEntireRedisList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY)
|
||||
return getEntireRedisList(rds_PROVINCE_LEVEL_TODAY_CONFIRM_KEY)
|
||||
}
|
||||
if sort == SORT_TOTAL_CONFIRM {
|
||||
return getEntireRedisList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY)
|
||||
return getEntireRedisList(rds_PROVINCE_LEVEL_TOTAL_CONFIRM_KEY)
|
||||
}
|
||||
if sort == SORT_NOW_CONFIRM {
|
||||
return getEntireRedisList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY)
|
||||
return getEntireRedisList(rds_PROVINCE_LEVEL_NOW_CONFIRM_KEY)
|
||||
}
|
||||
return getEntireRedisList(rds_PROVIENCE_LEVEL_CHILD_KEY)
|
||||
return getEntireRedisList(rds_PROVINCE_LEVEL_CHILD_KEY)
|
||||
}
|
||||
|
||||
func GetAllCityData(sort string) []interface{} {
|
||||
@@ -36,6 +36,7 @@ func GetAllCityData(sort string) []interface{} {
|
||||
}
|
||||
|
||||
func GetCountryData(child bool) []interface{} {
|
||||
checkCache()
|
||||
if child {
|
||||
return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY)
|
||||
}
|
||||
@@ -43,12 +44,39 @@ func GetCountryData(child bool) []interface{} {
|
||||
}
|
||||
|
||||
func GetChinaNCovStatistic() models.ChinaData {
|
||||
checkCache()
|
||||
data := models.ChinaData{}
|
||||
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_ADD_KEY).Val()), &data.ChinaAdd)
|
||||
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_TOTAL_KEY).Val()), &data.ChinaTotal)
|
||||
return data
|
||||
}
|
||||
|
||||
func GetChinaDayAdd() []models.ChinaDayAdd {
|
||||
chinaDayAddStr := global.Redis.Get(rds_CHINA_DAY_ADD_LIST_KEY).Val()
|
||||
if chinaDayAddStr == "" {
|
||||
CacheNCovTrend()
|
||||
chinaDayAddStr = global.Redis.Get(rds_CHINA_DAY_ADD_LIST_KEY).Val()
|
||||
}
|
||||
var chinaDayAddList []models.ChinaDayAdd
|
||||
json.Unmarshal([]byte(chinaDayAddStr), &chinaDayAddList)
|
||||
return chinaDayAddList
|
||||
}
|
||||
|
||||
func GetChinaDay() []models.ChinaDay {
|
||||
chinaDayStr := global.Redis.Get(rds_CHINA_DAY_LIST_KEY).Val()
|
||||
if chinaDayStr == "" {
|
||||
CacheNCovTrend()
|
||||
chinaDayStr = global.Redis.Get(rds_CHINA_DAY_LIST_KEY).Val()
|
||||
}
|
||||
var chinaDayList []models.ChinaDay
|
||||
json.Unmarshal([]byte(chinaDayStr), &chinaDayList)
|
||||
return chinaDayList
|
||||
}
|
||||
|
||||
func GetChinaTrend() models.ChinaTrend {
|
||||
return models.ChinaTrend{ChinaDayAddList: GetChinaDayAdd(), ChinaDayList: GetChinaDay()}
|
||||
}
|
||||
|
||||
func getEntireRedisList(key string) []interface{} {
|
||||
var data []interface{}
|
||||
dataStrArr := global.Redis.LRange(key, 0, -1).Val()
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/google/uuid"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/service/notify"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,64 +30,88 @@ func Login(user map[string]interface{}) (token string) {
|
||||
if userInfo == nil {
|
||||
return ""
|
||||
}
|
||||
if userInfo["approver"].(int) <= 0 {
|
||||
return ""
|
||||
}
|
||||
if !utils.PasswordCompare(user["password"].(string), userInfo["password"].(string)) {
|
||||
return ""
|
||||
}
|
||||
claims := jwt.MapClaims{
|
||||
"id": userInfo["id"],
|
||||
"username": userInfo["username"],
|
||||
"role": userInfo["role"],
|
||||
"email": userInfo["email"],
|
||||
"region": userInfo["region"],
|
||||
"role": userInfo["role"],
|
||||
}
|
||||
return utils.GenerateToken(claims)
|
||||
}
|
||||
|
||||
// Register user register, user can use account after approved
|
||||
func Register(user map[string]interface{}) {
|
||||
func Register(user map[string]interface{}) bool {
|
||||
user["password"] = utils.PasswordEncrypt(user["password"].(string))
|
||||
userStr, _ := json.Marshal(user)
|
||||
// insert into redis, wait for approve
|
||||
cmd := global.Redis.HMSet(global.REGISTER_REDIS_KEY, map[string]interface{}{user["email"].(string): userStr})
|
||||
if cmd.Err() != nil {
|
||||
panic(cmd.Err())
|
||||
user["approver"] = 0
|
||||
colMap := models.MapJ2c[models.BackUser](user, false)
|
||||
ok, rowsAffected := models.Upsert[models.BackUser](colMap)
|
||||
var sendRegion string
|
||||
if int(user["role"].(float64)) == global.ROLE_ID_MAP["ADMIN"] {
|
||||
sendRegion = strings.Split(user["region"].(string), " ")[0]
|
||||
} else {
|
||||
sendRegion = user["region"].(string)
|
||||
}
|
||||
notification := models.BackNotification{Time: time.Now(), Kind: "审批", Content: "有新的注册待审批"}
|
||||
sendInfo := models.SendInfo{Region: []string{sendRegion}, Channel: []int{0}, Notification: notification}
|
||||
notify.SendNotify(sendInfo)
|
||||
if !ok || rowsAffected == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ListRegister list the registers in the redis to be approved
|
||||
func ListRegister() *[]map[string]interface{} {
|
||||
applyStrMap := global.Redis.HGetAll(global.REGISTER_REDIS_KEY).Val()
|
||||
var applies []map[string]interface{}
|
||||
for _, v := range applyStrMap {
|
||||
var apply map[string]interface{}
|
||||
_ = json.Unmarshal([]byte(v), &apply)
|
||||
applies = append(applies, apply)
|
||||
func ListRegister(claims models.TokenClaims) *[]map[string]interface{} {
|
||||
registers := []map[string]interface{}{}
|
||||
tx := global.Db.Model(new(models.BackUser)).Omit("password")
|
||||
if claims.Region == "" {
|
||||
// do nothing
|
||||
} else if !strings.Contains(claims.Region, " ") {
|
||||
// Province Admin approve city admin
|
||||
tx.Where("approver = 0 AND is_delete = 0 AND region LIKE ? AND role = ?", claims.Region+" %", global.ROLE_ID_MAP["ADMIN"])
|
||||
registers = *models.ListByOrm(tx)
|
||||
} else {
|
||||
// City Admin approve workers and volunteers
|
||||
tx.Where("approver = 0 AND is_delete = 0 AND region = ? AND role in ?", claims.Region, []int{global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]})
|
||||
registers = *models.ListByOrm(tx)
|
||||
}
|
||||
if applies == nil {
|
||||
applies = []map[string]interface{}{}
|
||||
}
|
||||
return &applies
|
||||
return ®isters
|
||||
}
|
||||
|
||||
// ListApprovedRegister list registers approved by the admin
|
||||
func ListApprovedRegister(claims models.TokenClaims) *[]map[string]interface{} {
|
||||
approvedRegisters := []map[string]interface{}{}
|
||||
tx := global.Db.Model(new(models.BackUser)).Omit("password").Where("approver in ? and is_delete = 0", []int{claims.ID, -claims.ID})
|
||||
approvedRegisters = *models.ListByOrm(tx)
|
||||
return &approvedRegisters
|
||||
}
|
||||
|
||||
// ApproveRegister approve a register
|
||||
func ApproveRegister(email string, pass bool) bool {
|
||||
if !pass {
|
||||
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
|
||||
return rowsAffected != 0
|
||||
func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool {
|
||||
queryMap := []map[string]interface{}{{"email": email}}
|
||||
var approver int
|
||||
// Approver field status:
|
||||
// = 0: not approved
|
||||
// > 0: approver id, and registe successful
|
||||
// < 0: approver id, and registe failed
|
||||
if pass {
|
||||
approver = claims.ID
|
||||
} else {
|
||||
approver = -claims.ID
|
||||
}
|
||||
// if pass, will get the register info from redis, and the insert into mysql, this mean user is register success
|
||||
applyStr := global.Redis.HGet(global.REGISTER_REDIS_KEY, email).Val()
|
||||
rowsAffected := global.Redis.HDel(global.REGISTER_REDIS_KEY, email).Val()
|
||||
if rowsAffected == 0 {
|
||||
updateMap := map[string]interface{}{"approver": approver, "modify_time": time.Now()}
|
||||
ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap)
|
||||
if !ok || rowsAffected == 0 {
|
||||
return false
|
||||
}
|
||||
var apply map[string]interface{}
|
||||
_ = json.Unmarshal([]byte(applyStr), &apply)
|
||||
if !NoDuplicatePhoneOrEmail(apply["phone"].(string), apply["email"].(string)) {
|
||||
return false
|
||||
}
|
||||
colMap := models.MapJ2c[models.BackUser](apply, true)
|
||||
ok, rowsAffected := models.Upsert[models.BackUser](colMap)
|
||||
return ok && rowsAffected != 0
|
||||
return true
|
||||
}
|
||||
|
||||
// ChangePassword user change password, or user forgot password
|
||||
@@ -97,11 +122,12 @@ func ChangePassword(changePwd map[string]interface{}) bool {
|
||||
}
|
||||
newPassword := utils.PasswordEncrypt(changePwd["newPassword"].(string))
|
||||
colMap := map[string]interface{}{
|
||||
"id": 1,
|
||||
"id": 1.0,
|
||||
"password": newPassword,
|
||||
}
|
||||
models.BeforeSave(colMap, -1)
|
||||
delete(colMap, "id")
|
||||
delete(colMap, "modify_user")
|
||||
rowAffected := global.Db.Model(models.BackUser{}).Where("email = ?", changePwd["email"]).Updates(colMap).RowsAffected
|
||||
if rowAffected == 0 {
|
||||
return false
|
||||
|
||||
@@ -27,3 +27,14 @@ email:
|
||||
port: 587
|
||||
account: fallen-angle@foxmail.com
|
||||
password: hxrisxltxsjvieec
|
||||
|
||||
bos:
|
||||
accessKey: 90dbff87c5aa4bdbb0d7a29e130b2808
|
||||
secretKey: e53a672a10294abc8ecabe1ef92625b1
|
||||
domain: bj.bcebos.com
|
||||
|
||||
kafka:
|
||||
servers:
|
||||
- myhost.fallen-angle.com:9092
|
||||
topic: ncov_track
|
||||
partition: 0
|
||||
|
||||
15
utils/bos.go
Normal file
15
utils/bos.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import "nCovTrack-Backend/global"
|
||||
|
||||
func UploadFile() string {
|
||||
etag, err := global.BosClient.PutObjectFromFile("ncovtrack", "test.jpg", "/home/fallen-angle/Pictures/Anime/pic-w-000003.jpg", nil)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return etag
|
||||
}
|
||||
|
||||
func DownloadLink() string {
|
||||
return global.BosClient.BasicGeneratePresignedUrl("ncovtrack", "test.jpg", 1800)
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
)
|
||||
|
||||
func SendEmail(subject string, text string, to ...string) bool {
|
||||
//TODO: add logs
|
||||
e := email.Email{
|
||||
From: "nCovTrack Server<1853633282@qq.com>",
|
||||
To: to,
|
||||
@@ -20,6 +19,7 @@ func SendEmail(subject string, text string, to ...string) bool {
|
||||
smtp.PlainAuth("", global.ServerSettings.Email.Account, global.ServerSettings.Email.Password, global.ServerSettings.Email.Host),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println("Send failed")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -31,7 +31,11 @@ func GetWithHeader(url string, header map[string]string) string {
|
||||
cost := time.Since(startTime)
|
||||
var logParams []interface{}
|
||||
logParams = append(logParams,
|
||||
"reqest", req,
|
||||
"reqest", map[string]interface{}{
|
||||
"url": req.URL,
|
||||
"method": req.Method,
|
||||
"header": req.Header,
|
||||
},
|
||||
"cost", cost.String(),
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
10
utils/json.go
Normal file
10
utils/json.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func Strcut2Map[S any, T *map[string]interface{} | *[]map[string]interface{}](source S, target T) {
|
||||
jsonByte, _ := json.Marshal(source)
|
||||
json.Unmarshal(jsonByte, target)
|
||||
}
|
||||
12
utils/jwt.go
12
utils/jwt.go
@@ -1,10 +1,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
@@ -56,7 +58,7 @@ func RenewToken(tokenStr string) string {
|
||||
if expireDuration.Hours() > float64(global.ServerSettings.Jwt.RenewAheadDays*24) {
|
||||
return tokenStr
|
||||
}
|
||||
fmt.Println(expireDuration)
|
||||
//fmt.Println(expireDuration)
|
||||
|
||||
claims["exp"] = time.Now().Add(global.TOKEN_EXPIRE_DAYS * 24 * time.Hour).Unix()
|
||||
token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
@@ -81,3 +83,9 @@ func ParseClaims(tokenStr string) jwt.MapClaims {
|
||||
}
|
||||
return token.Claims.(jwt.MapClaims)
|
||||
}
|
||||
|
||||
func ClaimsFromHeader(c *gin.Context) models.TokenClaims {
|
||||
var claims models.TokenClaims
|
||||
json.Unmarshal([]byte(c.Request.Header.Get("claims")), &claims)
|
||||
return claims
|
||||
}
|
||||
|
||||
@@ -15,3 +15,24 @@ func Map[T any, V any](arr []T, fun func(item T) V) []V {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func Distinct[T comparable](arr []T) []T {
|
||||
set := map[T]interface{}{}
|
||||
for _, item := range arr {
|
||||
set[item] = nil
|
||||
}
|
||||
var res []T
|
||||
for k := range set {
|
||||
res = append(res, k)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func Contains[T comparable](arr []T, item T) bool {
|
||||
for _, a := range arr {
|
||||
if a == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
40
utils/set.go
40
utils/set.go
@@ -1,40 +0,0 @@
|
||||
package utils
|
||||
|
||||
type void struct{}
|
||||
|
||||
// This is set with generic
|
||||
|
||||
type Set[T comparable] struct {
|
||||
setMap map[T]void
|
||||
}
|
||||
|
||||
func NewSet[T comparable](eles ...T) *Set[T] {
|
||||
set := &Set[T]{setMap: make(map[T]void)}
|
||||
set.AddAll(eles...)
|
||||
return set
|
||||
}
|
||||
|
||||
func (set *Set[T]) Add(ele T) *Set[T] {
|
||||
set.setMap[ele] = void{}
|
||||
return set
|
||||
}
|
||||
|
||||
func (set *Set[T]) AddAll(eles ...T) *Set[T] {
|
||||
for _, ele := range eles {
|
||||
set.Add(ele)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (set *Set[T]) Delete(ele T) *Set[T] {
|
||||
delete(set.setMap, ele)
|
||||
return set
|
||||
}
|
||||
|
||||
func (set *Set[T]) ToSlice() []T {
|
||||
var s []T
|
||||
for k, _ := range set.setMap {
|
||||
s = append(s, k)
|
||||
}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user