feat: management && notify
This commit is contained in:
145
docs/docs.go
145
docs/docs.go
@@ -310,6 +310,37 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/statistics/china/trend": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Statistics"
|
||||
],
|
||||
"summary": "china trend",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/utils.GinResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.ChinaTrend"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/statistics/city/{sort}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -741,6 +772,9 @@ const docTemplate = `{
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": "string"
|
||||
},
|
||||
"today": {
|
||||
"$ref": "#/definitions/models.AreaToday"
|
||||
},
|
||||
@@ -939,6 +973,100 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaDay": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
},
|
||||
"dead": {
|
||||
"type": "integer"
|
||||
},
|
||||
"deadRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"heal": {
|
||||
"type": "integer"
|
||||
},
|
||||
"healRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"importedCase": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirmH5": {
|
||||
"type": "integer"
|
||||
},
|
||||
"local_acc_confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"noInfect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"noInfectH5": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nowConfirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nowSevere": {
|
||||
"type": "integer"
|
||||
},
|
||||
"suspect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"y": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaDayAdd": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
},
|
||||
"dead": {
|
||||
"type": "integer"
|
||||
},
|
||||
"deadRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"heal": {
|
||||
"type": "integer"
|
||||
},
|
||||
"healRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"importedCase": {
|
||||
"type": "integer"
|
||||
},
|
||||
"infect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirmadd": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localinfectionadd": {
|
||||
"type": "integer"
|
||||
},
|
||||
"suspect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"y": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaTotal": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -986,6 +1114,23 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaTrend": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ChinaDayList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ChinaDay"
|
||||
}
|
||||
},
|
||||
"chinaDayAddList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ChinaDayAdd"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ListArticle": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -300,6 +300,37 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/statistics/china/trend": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Statistics"
|
||||
],
|
||||
"summary": "china trend",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/utils.GinResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.ChinaTrend"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/statistics/city/{sort}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -731,6 +762,9 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": "string"
|
||||
},
|
||||
"today": {
|
||||
"$ref": "#/definitions/models.AreaToday"
|
||||
},
|
||||
@@ -929,6 +963,100 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaDay": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
},
|
||||
"dead": {
|
||||
"type": "integer"
|
||||
},
|
||||
"deadRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"heal": {
|
||||
"type": "integer"
|
||||
},
|
||||
"healRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"importedCase": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirmH5": {
|
||||
"type": "integer"
|
||||
},
|
||||
"local_acc_confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"noInfect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"noInfectH5": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nowConfirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nowSevere": {
|
||||
"type": "integer"
|
||||
},
|
||||
"suspect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"y": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaDayAdd": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirm": {
|
||||
"type": "integer"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
},
|
||||
"dead": {
|
||||
"type": "integer"
|
||||
},
|
||||
"deadRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"heal": {
|
||||
"type": "integer"
|
||||
},
|
||||
"healRate": {
|
||||
"type": "string"
|
||||
},
|
||||
"importedCase": {
|
||||
"type": "integer"
|
||||
},
|
||||
"infect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localConfirmadd": {
|
||||
"type": "integer"
|
||||
},
|
||||
"localinfectionadd": {
|
||||
"type": "integer"
|
||||
},
|
||||
"suspect": {
|
||||
"type": "integer"
|
||||
},
|
||||
"y": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaTotal": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -976,6 +1104,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ChinaTrend": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ChinaDayList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ChinaDay"
|
||||
}
|
||||
},
|
||||
"chinaDayAddList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ChinaDayAdd"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ListArticle": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -7,6 +7,8 @@ definitions:
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
parent:
|
||||
type: string
|
||||
today:
|
||||
$ref: '#/definitions/models.AreaToday'
|
||||
total:
|
||||
@@ -144,6 +146,68 @@ definitions:
|
||||
chinaTotal:
|
||||
$ref: '#/definitions/models.ChinaTotal'
|
||||
type: object
|
||||
models.ChinaDay:
|
||||
properties:
|
||||
confirm:
|
||||
type: integer
|
||||
date:
|
||||
type: string
|
||||
dead:
|
||||
type: integer
|
||||
deadRate:
|
||||
type: string
|
||||
heal:
|
||||
type: integer
|
||||
healRate:
|
||||
type: string
|
||||
importedCase:
|
||||
type: integer
|
||||
local_acc_confirm:
|
||||
type: integer
|
||||
localConfirm:
|
||||
type: integer
|
||||
localConfirmH5:
|
||||
type: integer
|
||||
noInfect:
|
||||
type: integer
|
||||
noInfectH5:
|
||||
type: integer
|
||||
nowConfirm:
|
||||
type: integer
|
||||
nowSevere:
|
||||
type: integer
|
||||
suspect:
|
||||
type: integer
|
||||
"y":
|
||||
type: string
|
||||
type: object
|
||||
models.ChinaDayAdd:
|
||||
properties:
|
||||
confirm:
|
||||
type: integer
|
||||
date:
|
||||
type: string
|
||||
dead:
|
||||
type: integer
|
||||
deadRate:
|
||||
type: string
|
||||
heal:
|
||||
type: integer
|
||||
healRate:
|
||||
type: string
|
||||
importedCase:
|
||||
type: integer
|
||||
infect:
|
||||
type: integer
|
||||
localConfirmadd:
|
||||
type: integer
|
||||
localinfectionadd:
|
||||
type: integer
|
||||
suspect:
|
||||
type: integer
|
||||
"y":
|
||||
type: string
|
||||
type: object
|
||||
models.ChinaTotal:
|
||||
properties:
|
||||
confirm:
|
||||
@@ -175,6 +239,17 @@ definitions:
|
||||
suspect:
|
||||
type: integer
|
||||
type: object
|
||||
models.ChinaTrend:
|
||||
properties:
|
||||
ChinaDayList:
|
||||
items:
|
||||
$ref: '#/definitions/models.ChinaDay'
|
||||
type: array
|
||||
chinaDayAddList:
|
||||
items:
|
||||
$ref: '#/definitions/models.ChinaDayAdd'
|
||||
type: array
|
||||
type: object
|
||||
models.ListArticle:
|
||||
properties:
|
||||
cover:
|
||||
@@ -422,6 +497,23 @@ paths:
|
||||
summary: china data
|
||||
tags:
|
||||
- Statistics
|
||||
/statistics/china/trend:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/utils.GinResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/models.ChinaTrend'
|
||||
type: object
|
||||
summary: china trend
|
||||
tags:
|
||||
- Statistics
|
||||
/statistics/city/{sort}:
|
||||
get:
|
||||
parameters:
|
||||
|
||||
@@ -36,6 +36,7 @@ func GetHttpClient(key string) (*http.Client, error) {
|
||||
|
||||
const (
|
||||
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/"
|
||||
@@ -57,4 +58,22 @@ var (
|
||||
"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,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -14,6 +14,8 @@ const (
|
||||
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{}) {
|
||||
@@ -40,3 +42,7 @@ func Forbidden(c *gin.Context) {
|
||||
func UrlNotFound(c *gin.Context) {
|
||||
c.String(http.StatusNotFound, PAGE_NOT_FOUND)
|
||||
}
|
||||
|
||||
func OperationFailed(c *gin.Context) {
|
||||
c.String(STATUS_OPERATION_FAILED, OPERATION_FAILED)
|
||||
}
|
||||
|
||||
68
handler/management.go
Normal file
68
handler/management.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/service/management"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func PullContactHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
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})
|
||||
}
|
||||
|
||||
func ListObservationsHandler(c *gin.Context) {
|
||||
jsonMap := bindQuery(c)
|
||||
utils.Succ(c, management.ListObservation(jsonMap))
|
||||
}
|
||||
|
||||
func InsertObservationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
observaion := bindJson(c)
|
||||
delete(observaion, "id")
|
||||
ok := management.InsertObservation(claims, observaion)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
func GetObservationHandler(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
utils.Succ(c, management.GetObservation(id))
|
||||
}
|
||||
|
||||
func ListLocationHandler(c *gin.Context) {
|
||||
queryMap := bindQuery(c)
|
||||
utils.Succ(c, management.ListLocation(queryMap))
|
||||
}
|
||||
|
||||
func InsertLocationHandler(c *gin.Context) {
|
||||
claims := utils.ClaimsFromHeader(c)
|
||||
locationMap := bindJson(c)
|
||||
ok := management.InsertLocation(claims, locationMap)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteLocationHandler(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
ok := management.DeleteLocation(id)
|
||||
if ok {
|
||||
utils.Succ(c, nil)
|
||||
} else {
|
||||
OperationFailed(c)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FakerDate time.Time
|
||||
|
||||
const (
|
||||
timeFormat = "2006-01-02"
|
||||
)
|
||||
|
||||
func (t *FakerDate) UnmarshalJSON(data []byte) (err error) {
|
||||
fmt.Println(string(data))
|
||||
newTime, err := time.ParseInLocation(`"`+timeFormat+`"`, string(data), time.Local)
|
||||
*t = FakerDate(newTime)
|
||||
return
|
||||
}
|
||||
|
||||
func (t FakerDate) MarshalJSON() ([]byte, error) {
|
||||
fmt.Println(time.Time(t).Format(timeFormat))
|
||||
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 int `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"`
|
||||
}
|
||||
156
models/management.go
Normal file
156
models/management.go
Normal file
@@ -0,0 +1,156 @@
|
||||
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 ListObeservation 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"` //核酸结果
|
||||
RecordTime time.Time `json:"recordTime"` //状态转换时间
|
||||
Record string `json:"record"` //状态转换内容
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
9
models/notify.go
Normal file
9
models/notify.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type BackNotification struct {
|
||||
Time time.Time `json:"time"`
|
||||
Kind int `json:"kind"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
@@ -59,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"`
|
||||
}
|
||||
|
||||
@@ -60,17 +60,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 +124,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 || int(colMap["id"].(float64)) == 0 {
|
||||
tx = global.Db.Model(new(T)).Create(colMap)
|
||||
} else {
|
||||
tx = global.Db.Model(new(T)).Where("id = ?", colMap["id"]).Updates(colMap)
|
||||
@@ -93,6 +136,15 @@ 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 {
|
||||
@@ -120,6 +172,10 @@ func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
|
||||
return true, 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{} {
|
||||
tx := global.Db.Model(new(T))
|
||||
for _, e := range queryMap {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"nCovTrack-Backend/service/investigate"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func investigatePublicRouter(router *gin.RouterGroup) {
|
||||
investigateRouter := router.Group("investigate")
|
||||
{
|
||||
investigateRouter.GET("/test", func(c *gin.Context) {
|
||||
investigate.QueryHotelContacts()
|
||||
c.JSON(http.StatusOK, nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
17
router/management.go
Normal file
17
router/management.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/handler"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func managementPublicRouter(router *gin.RouterGroup) {
|
||||
managementRouter := router.Group("/management")
|
||||
{
|
||||
managementRouter.GET("/observation/contact/pull/:patientId", handler.PullContactHandler)
|
||||
managementRouter.GET("/observation", handler.ListObservationsHandler)
|
||||
managementRouter.POST("/observation", handler.InsertObservationHandler)
|
||||
managementRouter.GET("/observation/:id", handler.GetObservationHandler)
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ func BusiRouter() {
|
||||
statisticRouter(publicRouter)
|
||||
articlePublicRouter(publicRouter)
|
||||
userPublicRouter(publicRouter)
|
||||
investigatePublicRouter(publicRouter)
|
||||
managementPublicRouter(publicRouter)
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
@@ -13,5 +13,6 @@ func statisticRouter(router *gin.RouterGroup) {
|
||||
statisticsRouter.GET("/country/child", handler.CountryDataHandler)
|
||||
statisticsRouter.GET("/country", handler.CountryDataHandler)
|
||||
statisticsRouter.GET("/china", handler.ChinaDataHandler)
|
||||
statisticsRouter.GET("/china/trend", handler.ChinaTrendHandler)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package investigate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func QueryHotelContacts() []models.HotelContactRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/hotel/320581199103182689")
|
||||
var data []models.HotelContactRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func QueryRailwayContacts() []models.RailwayContactRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/railway/320581199103182689")
|
||||
var data []models.RailwayContactRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func QueryPatients() []models.PatientRequest {
|
||||
dataStr := fakerGetRequest("query/contacts/railway/320581199103182689")
|
||||
var data []models.PatientRequest
|
||||
err := json.Unmarshal([]byte(dataStr), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package investigate
|
||||
104
service/management/faker.go
Normal file
104
service/management/faker.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func queryContacts(identification string) []models.BackObservation {
|
||||
hotelContacts := queryHotelContacts(identification)
|
||||
railwayContacts := queryRailwayContacts(identification)
|
||||
observations := append(fakerContacts2Observations(hotelContacts), fakerContacts2Observations(railwayContacts)...)
|
||||
return observations
|
||||
}
|
||||
|
||||
func splitFakerAddress(fakerAddress string) string {
|
||||
addresses := strings.Split(fakerAddress, " ")
|
||||
return addresses[1] + " " + addresses[2]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
22
service/management/location.go
Normal file
22
service/management/location.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/models"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
func DeleteLocation(id int) bool {
|
||||
ok, rowsAffected := models.DeleteById[models.BackLocation](id)
|
||||
return (ok && rowsAffected != 0)
|
||||
}
|
||||
223
service/management/observation.go
Normal file
223
service/management/observation.go
Normal file
@@ -0,0 +1,223 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
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
|
||||
if rowsAffected != 0 {
|
||||
pullSituationRecord(claims, observations)
|
||||
}
|
||||
return rowsAffected
|
||||
}
|
||||
|
||||
func ListObservation(jsonMap map[string]interface{}) []models.ListObeservation {
|
||||
colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
|
||||
queryMap := []map[string]interface{}{colMap}
|
||||
return listObservation(queryMap)
|
||||
}
|
||||
|
||||
func GetObservation(id int) map[string]interface{} {
|
||||
observationCMap := models.GetField[models.BackObservation]([]map[string]interface{}{{"id": id}}, true, "is_delete")
|
||||
observationJMap := models.MapC2j[models.BackObservation](observationCMap, true)
|
||||
pcrRecordCMap := models.ListField[models.BackPcr]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
|
||||
pcrRecordJMap := models.MapsC2j[models.BackPcr](*pcrRecordCMap, true)
|
||||
situationRecordCMap := models.ListField[models.BackSituationRecord]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
|
||||
situationRecordJMap := models.MapsC2j[models.BackSituationRecord](*situationRecordCMap, true)
|
||||
observationJMap["pcrRecord"] = pcrRecordJMap
|
||||
observationJMap["situationRecord"] = situationRecordJMap
|
||||
return observationJMap
|
||||
}
|
||||
|
||||
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 {
|
||||
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)
|
||||
return false
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
|
||||
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 := record00_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)
|
||||
// Notify the admin of pull region
|
||||
// Send email to the region admin
|
||||
}
|
||||
|
||||
func updateObservationRegion(region string) {
|
||||
// Add to notify
|
||||
// Send email to the target region amdin
|
||||
}
|
||||
|
||||
func updateWhileDiagnosis(claims models.TokenClaims, patientId int) {
|
||||
// Update sub contact to contact and nomeasure
|
||||
// Add to notify
|
||||
}
|
||||
|
||||
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_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 "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))
|
||||
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 record00_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)
|
||||
}
|
||||
44
service/notify/notify.go
Normal file
44
service/notify/notify.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func DeleteNotification(userId int, index int) {
|
||||
key := NOTIFY_KEY + strconv.Itoa(userId)
|
||||
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)
|
||||
return int(global.Redis.LLen(key).Val())
|
||||
}
|
||||
|
||||
func ListNotifycation(userId int, start, end int) []models.BackNotification {
|
||||
key := NOTIFY_KEY + strconv.Itoa(userId)
|
||||
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
|
||||
}
|
||||
@@ -27,11 +27,13 @@ const (
|
||||
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 = "待确认"
|
||||
@@ -54,6 +56,22 @@ func cacheNCovStatistics() {
|
||||
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{}) {
|
||||
|
||||
@@ -51,6 +51,32 @@ func GetChinaNCovStatistic() models.ChinaData {
|
||||
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()
|
||||
|
||||
@@ -17,7 +17,6 @@ const (
|
||||
|
||||
// Login if login success, will return token
|
||||
func Login(user map[string]interface{}) (token string) {
|
||||
// TODO: need to detect is passed or not
|
||||
account := user["account"].(string)
|
||||
var queryMap []map[string]interface{}
|
||||
if strings.Contains(account, "@") {
|
||||
|
||||
@@ -2,7 +2,6 @@ package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
"time"
|
||||
@@ -59,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)
|
||||
|
||||
Reference in New Issue
Block a user