This commit is contained in:
fallen-angle
2022-05-16 19:55:59 +08:00
parent 7598280fc1
commit 9e3638885d
34 changed files with 3623 additions and 115 deletions
+1059
View File
File diff suppressed because it is too large Load Diff
+1059
View File
File diff suppressed because it is too large Load Diff
+710
View File
@@ -54,6 +54,9 @@ definitions:
createUser:
description: 文章创建者id
type: integer
id:
description: 文章id
type: integer
isDelete:
description: 删除标志
type: integer
@@ -76,6 +79,138 @@ definitions:
description: 文章标题
type: string
type: object
models.BackLocation:
properties:
address:
description: 地点的精确地址
type: string
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
id:
description: ID
type: integer
isDelete:
description: 删除标志
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 地点名
type: string
principalName:
description: 负责人姓名
type: string
principalPhone:
description: 负责人电话
type: string
region:
description: 地点所在地区
type: string
type: object
models.BackNotification:
properties:
content:
type: string
kind:
type: string
time:
type: string
type: object
models.BackObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
type: integer
id:
description: ID
type: integer
identification:
description: 身份证号
type: string
isDelete:
description: 删除标志
type: integer
measureSituation:
description: 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
phone:
description: 手机号码
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.BackPcr:
properties:
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
detectResult:
description: 核酸检测结果:0-未检测,1-阴性,2-阳性
type: integer
detectTime:
description: 核酸检测时间
type: string
id:
description: ID
type: integer
isDelete:
description: 删除标志
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
observation:
description: 观察对象ID
type: integer
type: object
models.BackUser:
properties:
approver:
@@ -256,6 +391,8 @@ definitions:
type: string
createTime:
type: string
id:
type: integer
modifyTime:
type: string
resume:
@@ -267,6 +404,129 @@ definitions:
username:
type: string
type: object
models.ListObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
type: integer
id:
type: integer
identification:
description: 身份证号
type: string
measureSituation:
description: 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
pcrResult:
description: 核酸结果:0-未检测,1-阴性,2-阳性
type: integer
pcrTime:
description: 核酸时间
type: string
phone:
description: 手机号码
type: string
record:
description: 状态转换内容
type: string
recordTime:
description: 状态转换时间
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.TreeObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
children:
description: 子结点
items:
$ref: '#/definitions/models.TreeObservation'
type: array
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
type: integer
id:
type: integer
identification:
description: 身份证号
type: string
measureSituation:
description: 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
phone:
description: 手机号码
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.UserApprove:
properties:
email:
@@ -480,6 +740,456 @@ paths:
summary: get user's articles
tags:
- Article
/management/faker/{patientId}:
get:
parameters:
- description: Token
in: header
name: Token
required: true
type: string
- description: Patient Id
in: path
name: patientId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: pull contact from faker
tags:
- Management
/management/location/:
get:
parameters:
- description: 地点的精确地址
in: query
name: address
type: string
- description: 创建时间
in: query
name: createTime
type: string
- description: 创建者
in: query
name: createUser
type: integer
- description: ID
in: query
name: id
type: integer
- description: 删除标志
in: query
name: isDelete
type: integer
- description: 修改时间
in: query
name: modifyTime
type: string
- description: 修改者
in: query
name: modifyUser
type: integer
- description: 地点名
in: query
name: name
type: string
- description: 负责人姓名
in: query
name: principalName
type: string
- description: 负责人电话
in: query
name: principalPhone
type: string
- description: 地点所在地区
in: query
name: region
type: string
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.BackLocation'
type: object
summary: list locations
tags:
- Management
post:
consumes:
- application/json
parameters:
- description: location
in: body
name: Location
required: true
schema:
$ref: '#/definitions/models.BackLocation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert location
tags:
- Management
/management/location/{id}:
delete:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: Id
in: path
name: Id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: delete location
tags:
- Management
/management/observation/:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: 受观察者所在具体地点
in: query
name: address
type: string
- description: 年龄
in: query
name: age
type: integer
- description: 接触者id
in: query
name: contactPerson
type: integer
- description: 创建时间
in: query
name: createTime
type: string
- description: 创建者
in: query
name: createUser
type: integer
- description: 患者健康状况转化时间
in: query
name: healthChangeTime
type: string
- description: 被观察者的疫情状况:0- 其他,1-患者,2-密接,3-次密接
in: query
name: healthSituation
type: integer
- description: ID
in: query
name: id
type: integer
- description: 身份证号
in: query
name: identification
type: string
- description: 删除标志
in: query
name: isDelete
type: integer
- description: 受观察者被采取措施状况 :0-未采取措施,1-解除风险,2-正在治疗,3-集中隔离,4-居家隔离
in: query
name: measureSituation
type: integer
- description: 修改时间
in: query
name: modifyTime
type: string
- description: 修改者
in: query
name: modifyUser
type: integer
- description: 姓名
in: query
name: name
type: string
- description: 手机号码
in: query
name: phone
type: string
- description: 受观察者所在区域
in: query
name: region
type: string
- description: 性别
in: query
name: sex
type: integer
- description: 行程轨迹
in: query
name: trajectory
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
items:
$ref: '#/definitions/models.ListObservation'
type: array
type: object
summary: list observations by query
tags:
- Management
post:
consumes:
- application/json
parameters:
- description: observation
in: body
name: Observation
required: true
schema:
$ref: '#/definitions/models.BackObservation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert observation
tags:
- Management
put:
consumes:
- application/json
parameters:
- description: observation
in: body
name: Observation
required: true
schema:
$ref: '#/definitions/models.BackObservation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: update observation
tags:
- Management
/management/observation/{id}:
get:
parameters:
- description: token
in: header
name: token
required: true
type: string
- description: id
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.BackObservation'
type: object
summary: get observation's info
tags:
- Management
/management/observation/tree/{id}/{direction}:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: id
in: path
name: id
required: true
type: integer
- description: direction
enum:
- up
- down
- all
in: path
name: direction
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.TreeObservation'
type: object
summary: get transform chain by user
tags:
- Management
/management/pcr/:
post:
parameters:
- description: Pcr
in: body
name: Pcr
required: true
schema:
$ref: '#/definitions/models.BackPcr'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert pcr record
tags:
- Management
/notify/{index}:
delete:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: index
in: path
name: index
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: delete the notify by index, if -1 delete all
tags:
- Notification
/notify/{start}/{end}:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: start
in: path
name: start
required: true
type: integer
- description: end
in: path
name: end
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
items:
$ref: '#/definitions/models.BackNotification'
type: array
type: object
summary: list the notification in the range
tags:
- Notification
/notify/count/:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: count the notification
tags:
- Notification
/statistics/china:
get:
produces:
+7
View File
@@ -12,6 +12,7 @@ type ServerConfig struct {
Jwt JwtConfig `yaml:"jwt"`
Email EmailConfig `yaml:"email"`
Bos BosConfig `yaml:"bos"`
Kafka KafkaCofig `yaml:"kafka"`
}
type MySQLConfig struct {
@@ -46,3 +47,9 @@ type BosConfig struct {
SecretKey string `yaml:"secretKey"`
Domain string `yaml:"domain"`
}
type KafkaCofig struct {
Servers []string `yaml:"servers"`
Topic string `yaml:"topic"`
Partition int `yaml:"partition"`
}
+2 -2
View File
@@ -4,12 +4,11 @@ import (
"errors"
"fmt"
"github.com/baidubce/bce-sdk-go/services/bos"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis"
"go.uber.org/zap"
"gorm.io/gorm"
"net/http"
)
var (
@@ -76,4 +75,5 @@ var (
"NEGATIVE": 1,
"POSITIVE": 2,
}
KafkaProducerChan = make(chan []byte)
)
+17 -2
View File
@@ -18,7 +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
@@ -31,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
@@ -49,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
@@ -59,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
+52
View File
@@ -44,6 +44,9 @@ 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=
@@ -63,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=
@@ -71,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=
@@ -144,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=
@@ -157,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=
@@ -180,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=
@@ -187,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=
@@ -203,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=
@@ -260,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=
@@ -268,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=
@@ -276,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=
@@ -313,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=
@@ -340,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=
@@ -347,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=
@@ -419,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=
@@ -456,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=
@@ -498,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=
+3 -3
View File
@@ -31,7 +31,7 @@ func SaveArticleHandler(c *gin.Context) {
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
}
@@ -90,7 +90,7 @@ func ListArticlesByUser(c *gin.Context) {
func DeleteArticleHandler(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
claims := utils.ClaimsFromHeader(c)
if claims.Role == global.ROLE_ID_MAP["ADMIN"] {
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c)
return
}
@@ -140,7 +140,7 @@ func GetArticleHandler(c *gin.Context) {
func PublishArticleHandler(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
claims := utils.ClaimsFromHeader(c)
if claims.Role == global.ROLE_ID_MAP["ADMIN"] {
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c)
return
}
+169 -3
View File
@@ -1,6 +1,7 @@
package handler
import (
"nCovTrack-Backend/global"
"nCovTrack-Backend/service/management"
"nCovTrack-Backend/utils"
"strconv"
@@ -8,8 +9,20 @@ import (
"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 {
@@ -19,13 +32,82 @@ func PullContactHandler(c *gin.Context) {
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)
@@ -36,18 +118,65 @@ func InsertObservationHandler(c *gin.Context) {
}
}
func GetObservationHandler(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
utils.Succ(c, management.GetObservation(id))
//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 {
@@ -57,7 +186,20 @@ func InsertLocationHandler(c *gin.Context) {
}
}
//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 {
@@ -66,3 +208,27 @@ func DeleteLocationHandler(c *gin.Context) {
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
View 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)
}
+3 -1
View File
@@ -24,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
+2
View File
@@ -10,6 +10,8 @@ func Initialize() *gin.Engine {
initRedis()
initBos()
initCron()
go initProducer()
go initConsumer()
g := initRouter()
initSwagger()
return g
+70
View 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
View File
@@ -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())
}
+2 -12
View File
@@ -6,7 +6,7 @@ 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 int `gorm:"column:create_user" json:"createUser"` // 文章创建者id
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间
@@ -21,7 +21,7 @@ type BackArticle struct {
}
type ListArticle struct {
ID int `json:"-"`
ID int `json:"id"`
Username string `json:"username"`
CreateTime time.Time `json:"createTime"`
ModifyTime time.Time `json:"modifyTime"`
@@ -34,13 +34,3 @@ type ListArticle struct {
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
View File
@@ -0,0 +1 @@
package models
+23 -2
View File
@@ -63,7 +63,7 @@ type BackSituationRecord struct {
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
}
type ListObeservation struct {
type ListObservation struct {
ID int `json:"id"`
Name string `json:"name"` // 姓名
Age int `json:"age"` // 年龄
@@ -82,11 +82,32 @@ type ListObeservation struct {
ModifyUser int `json:"modifyUser"` // 修改者
ModifyTime time.Time `json:"modifyTime"` // 修改时间
PcrTime time.Time `json:"pcrTime"` // 核酸时间
PcrResult int `json:"pcrResult"` //核酸结果
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"`
+7 -1
View File
@@ -4,6 +4,12 @@ import "time"
type BackNotification struct {
Time time.Time `json:"time"`
Kind int `json:"kind"`
Kind string `json:"kind"`
Content string `json:"content"`
}
type SendInfo struct {
Region []string `json:"region"`
Channel []int `json:"channel"`
Notification BackNotification `json:"notification"`
}
+19 -3
View File
@@ -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:(.*);?")
@@ -124,7 +126,7 @@ func BeforeBatchSave(colMaps *[]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 || int(colMap["id"].(float64)) == 0 {
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)
@@ -169,7 +171,7 @@ func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
if tx.Error != nil {
return false, 0
}
return true, rowsAffected
return true, tx.RowsAffected
}
func DropById[T any](id int) {
@@ -253,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 -2
View File
@@ -6,12 +6,18 @@ import (
"github.com/gin-gonic/gin"
)
func managementPublicRouter(router *gin.RouterGroup) {
func managementPrivateRouter(router *gin.RouterGroup) {
managementRouter := router.Group("/management")
{
managementRouter.GET("/observation/contact/pull/:patientId", handler.PullContactHandler)
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
View 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)
}
}
+2 -1
View File
@@ -15,12 +15,13 @@ func BusiRouter() {
statisticRouter(publicRouter)
articlePublicRouter(publicRouter)
userPublicRouter(publicRouter)
managementPublicRouter(publicRouter)
}
// Private
{
articlePrivateRouter(privateRouter)
userPrivateRouter(privateRouter)
notifyPrivateRouter(privateRouter)
managementPrivateRouter(privateRouter)
}
}
+2 -2
View File
@@ -39,8 +39,8 @@ func listArticles(isPublish int, createUser int) *[]models.ListArticle {
}
//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
}
+8 -1
View File
@@ -10,6 +10,7 @@ import (
"time"
)
//fakerGetRequest Get data from faker
func fakerGetRequest(uri string) string {
resStr := utils.GetWhioutHeader(global.FACKER_HOST + uri)
var res utils.GinResponse
@@ -18,6 +19,7 @@ func fakerGetRequest(uri string) string {
return string(dataStr)
}
//queryHotelContacts Hotel contacts
func queryHotelContacts(identification string) []models.HotelContactRequest {
dataStr := fakerGetRequest("query/contacts/hotel/" + identification)
var data []models.HotelContactRequest
@@ -28,6 +30,7 @@ func queryHotelContacts(identification string) []models.HotelContactRequest {
return data
}
//queryRailwayContacts Railway contacts
func queryRailwayContacts(identification string) []models.RailwayContactRequest {
dataStr := fakerGetRequest("query/contacts/railway/" + identification)
var data []models.RailwayContactRequest
@@ -38,7 +41,8 @@ func queryRailwayContacts(identification string) []models.RailwayContactRequest
return data
}
func queryPatients(identification string) []models.PatientRequest {
//queryPatients Patients
func QueryPatients(identification string) []models.PatientRequest {
dataStr := fakerGetRequest("query/contacts/railway/" + identification)
var data []models.PatientRequest
err := json.Unmarshal([]byte(dataStr), &data)
@@ -48,6 +52,7 @@ func queryPatients(identification string) []models.PatientRequest {
return data
}
//queryContacts Resolve the diffrent of hotel and railway request
func queryContacts(identification string) []models.BackObservation {
hotelContacts := queryHotelContacts(identification)
railwayContacts := queryRailwayContacts(identification)
@@ -55,11 +60,13 @@ func queryContacts(identification string) []models.BackObservation {
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) {
+3
View File
@@ -4,6 +4,7 @@ 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)
@@ -11,11 +12,13 @@ func InsertLocation(claims models.TokenClaims, locationJMap map[string]interface
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)
+184 -18
View File
@@ -4,10 +4,12 @@ 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}}
@@ -28,31 +30,39 @@ func PullFromFaker(claims models.TokenClaims, patientId int) int64 {
observationsCMap := models.MapsJ2c[models.BackObservation](observationsJMap, false)
models.BeforeBatchSave(&observationsCMap, claims.ID)
_, rowsAffected := models.BatchInsert[models.BackObservation](observationsCMap)
// Generate situation record
// Generate situation record and send notify to the region
if rowsAffected != 0 {
pullSituationRecord(claims, observations)
pullNotify(observations)
}
return rowsAffected
}
func ListObservation(jsonMap map[string]interface{}) []models.ListObeservation {
//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)
@@ -65,17 +75,103 @@ func InsertObservation(claims models.TokenClaims, jsonMap map[string]interface{}
}
func UpdateObservation(claims models.TokenClaims, jsonMap map[string]any) bool {
// Pre actions
colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
models.BeforeSave(colMap, claims.ID)
oldMap := models.Get[models.BackObservation]([]map[string]interface{}{{"id": jsonMap["id"]}})
insertSituationRecord(claims, oldMap, colMap)
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.ListObeservation {
var observations []models.ListObeservation
// 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").
@@ -94,6 +190,7 @@ func listObservation(queryMap []map[string]interface{}) []models.ListObeservatio
return observations
}
//pullSituationRecord push situation record after pull observations
func pullSituationRecord(claims models.TokenClaims, observations []models.BackObservation) {
// Query observations' id
var identifications []string
@@ -104,7 +201,7 @@ func pullSituationRecord(claims models.TokenClaims, observations []models.BackOb
observationMaps := models.ListField[models.BackObservation](queryMap, false, "id", "identification")
// Assemble records
var records []models.BackSituationRecord
recordContent := record00_20()
recordContent := record___20()
for _, observationMap := range *observationMaps {
record := models.BackSituationRecord{Observation: observationMap["id"].(int), Record: recordContent}
records = append(records, record)
@@ -115,20 +212,87 @@ func pullSituationRecord(claims models.TokenClaims, observations []models.BackOb
recordsCMaps := models.MapsJ2c[models.BackSituationRecord](recordsJMaps, true)
models.BeforeBatchSave(&recordsCMaps, claims.ID)
models.BatchInsert[models.BackSituationRecord](recordsCMaps)
// Notify the admin of pull region
// Send email to the region admin
}
//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) {
// Add to notify
// Send email to the target region amdin
notification := models.BackNotification{Time: time.Now(), Kind: "疫情", Content: "本地有新的接触者,请及时登录系统进行处理"}
sendInfo := models.SendInfo{Region: []string{region}, Channel: []int{0, 1}, Notification: notification}
notify.SendNotify(sendInfo)
}
func updateWhileDiagnosis(claims models.TokenClaims, patientId int) {
// Update sub contact to contact and nomeasure
// Add to notify
//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 {
@@ -154,20 +318,22 @@ func insertSituationRecord(claims models.TokenClaims, oldObservation, newObserva
switch situationConvert {
case "00_10":
recordContent = record00_10()
case "00_20":
recordContent = record00_20()
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)
@@ -193,7 +359,7 @@ func record00_12(region, address string) string {
date := utils.FormatDate(time.Now())
return fmt.Sprintf("%s 于 %s %s 确诊为患者", date, region, address)
}
func record00_20() string {
func record___20() string {
date := utils.FormatDate(time.Now())
return date + " 转为密接"
}
+10
View 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
}
+56 -11
View File
@@ -4,35 +4,65 @@ import (
"encoding/json"
"nCovTrack-Backend/global"
"nCovTrack-Backend/models"
"strconv"
"nCovTrack-Backend/utils"
)
type NotifyFunc func([]string, models.BackNotification)
const (
NOTIFY_KEY = "notification_"
NOTIFY_DEL_VALUE = "notify_del"
)
func InsertNotification(userId int, notification models.BackNotification) {
key := NOTIFY_KEY + strconv.Itoa(userId)
valueStr, _ := json.Marshal(notification)
global.Redis.RPush(key, valueStr)
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...)
}
func DeleteNotification(userId int, index int) {
key := NOTIFY_KEY + strconv.Itoa(userId)
//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()
}
func QueryNotificationLen(userId int) int {
key := NOTIFY_KEY + strconv.Itoa(userId)
//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())
}
func ListNotifycation(userId int, start, end int) []models.BackNotification {
key := NOTIFY_KEY + strconv.Itoa(userId)
//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 {
@@ -42,3 +72,18 @@ func ListNotifycation(userId int, start, end int) []models.BackNotification {
}
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)
}
}
+16 -4
View File
@@ -2,13 +2,15 @@ package user
import (
"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 (
@@ -50,6 +52,15 @@ func Register(user map[string]interface{}) bool {
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
}
@@ -95,7 +106,7 @@ func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool {
} else {
approver = -claims.ID
}
updateMap := map[string]interface{}{"approver": approver}
updateMap := map[string]interface{}{"approver": approver, "modify_time": time.Now()}
ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap)
if !ok || rowsAffected == 0 {
return false
@@ -111,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
+6
View File
@@ -32,3 +32,9 @@ bos:
accessKey: 90dbff87c5aa4bdbb0d7a29e130b2808
secretKey: e53a672a10294abc8ecabe1ef92625b1
domain: bj.bcebos.com
kafka:
servers:
- myhost.fallen-angle.com:9092
topic: ncov_track
partition: 0
+1 -1
View File
@@ -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
+5 -1
View File
@@ -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 {
+21
View File
@@ -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
View File
@@ -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
}