1、增加报表功能;

2、增加服务器端sse;
3、增加任务运行日志;
This commit is contained in:
wangjian 2023-04-24 15:21:17 +08:00
parent e22669ae05
commit adca8e6148
30 changed files with 1387 additions and 34 deletions

View File

@ -43,3 +43,6 @@ functions:
- name: task-request - name: task-request
dataTag : 12 dataTag : 12
mqType: 1 mqType: 1
- name: task-log
dataTag: 28
mqType: 2

25
go.mod
View File

@ -5,7 +5,9 @@ go 1.18
require ( require (
git.hpds.cc/Component/gin_valid v0.0.0-20230104142509-f956bce255b6 git.hpds.cc/Component/gin_valid v0.0.0-20230104142509-f956bce255b6
git.hpds.cc/Component/logging v0.0.0-20230106105738-e378e873921b git.hpds.cc/Component/logging v0.0.0-20230106105738-e378e873921b
git.hpds.cc/pavement/hpds_node v0.0.0-20230402152619-41414aafa930 git.hpds.cc/Component/network v0.0.0-20230405135741-a4ea724bab76
git.hpds.cc/pavement/hpds_node v0.0.0-20230405153516-9403c4d01e12
github.com/360EntSecGroup-Skylar/excelize v1.4.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-contrib/zap v0.1.0 github.com/gin-contrib/zap v0.1.0
github.com/gin-gonic/gin v1.8.2 github.com/gin-gonic/gin v1.8.2
@ -17,6 +19,7 @@ require (
github.com/spf13/cobra v0.0.3 github.com/spf13/cobra v0.0.3
github.com/spf13/viper v1.14.0 github.com/spf13/viper v1.14.0
go.uber.org/zap v1.24.0 go.uber.org/zap v1.24.0
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
xorm.io/xorm v1.3.2 xorm.io/xorm v1.3.2
) )
@ -27,7 +30,6 @@ require (
cloud.google.com/go/compute/metadata v0.2.1 // indirect cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/firestore v1.8.0 // indirect cloud.google.com/go/firestore v1.8.0 // indirect
git.hpds.cc/Component/mq_coder v0.0.0-20221010064749-174ae7ae3340 // indirect git.hpds.cc/Component/mq_coder v0.0.0-20221010064749-174ae7ae3340 // indirect
git.hpds.cc/Component/network v0.0.0-20230326151855-3c157f531d86 // indirect
github.com/armon/go-metrics v0.4.0 // indirect github.com/armon/go-metrics v0.4.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect
@ -45,6 +47,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-cmp v0.5.9 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.6.0 // indirect github.com/googleapis/gax-go/v2 v2.6.0 // indirect
@ -60,10 +63,7 @@ require (
github.com/klauspost/compress v1.15.9 // indirect github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/cpuid/v2 v2.1.0 // indirect github.com/klauspost/cpuid/v2 v2.1.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect
github.com/lucas-clemente/quic-go v0.29.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect github.com/magiconair/properties v1.8.6 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
github.com/matoous/go-nanoid/v2 v2.0.0 // indirect github.com/matoous/go-nanoid/v2 v2.0.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-isatty v0.0.16 // indirect
@ -73,11 +73,15 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxadm/tail v1.4.8 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
github.com/quic-go/quic-go v0.33.0 // indirect
github.com/rs/xid v1.4.0 // indirect github.com/rs/xid v1.4.0 // indirect
github.com/sagikazarmark/crypt v0.8.0 // indirect github.com/sagikazarmark/crypt v0.8.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect
@ -97,16 +101,16 @@ require (
go.opentelemetry.io/otel/trace v1.10.0 // indirect go.opentelemetry.io/otel/trace v1.10.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/crypto v0.4.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.4.0 // indirect golang.org/x/net v0.4.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.3.0 // indirect golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/tools v0.1.12 // indirect golang.org/x/tools v0.2.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.102.0 // indirect google.golang.org/api v0.102.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
@ -115,7 +119,6 @@ require (
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect
) )

View File

@ -63,3 +63,18 @@ func (s HandlerService) ImportDataset(c *gin.Context) (data interface{}, err err
go s.SaveLog("导入数据集", "Dataset", "", "", ToString(data), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("导入数据集", "Dataset", "", "", ToString(data), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
} }
func (s HandlerService) DatasetInfo(c *gin.Context) (data interface{}, err error) {
repo := service.NewDatasetService(s.AppConfig, s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.DatasetItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("DatasetInfo", "Dataset", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.DatasetInfo(c, req)
go s.SaveLog("获取数据集详情", "Dataset", "", "", ToString(data), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}

View File

@ -37,3 +37,27 @@ func (s HandlerService) UploadFile(c *gin.Context) (data interface{}, err error)
go s.SaveLog("文件上传", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("文件上传", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
} }
func (s HandlerService) FileList(c *gin.Context) (data interface{}, err error) {
repo := service.NewFileService(s.AppConfig, s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.DatasetItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("FileList", "FileManage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
if req.Size < 1 {
req.Size = 20
}
if req.Size > 1000 {
req.Size = 1000
}
if req.Page < 1 {
req.Page = 1
}
data, err = repo.FileList(c, req)
go s.SaveLog("获取数据集详情", "FileManage", "", "", ToString(data), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}

View File

@ -122,6 +122,20 @@ func (s HandlerService) ProjectList(c *gin.Context) (data interface{}, err error
return return
} }
func (s HandlerService) ProjectInfo(c *gin.Context) (data interface{}, err error) {
repo := service.NewManageService(s.AppConfig, s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.ProjectItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("ProjectInfo", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.ProjectInfo(c, req)
go s.SaveLog("获取项目信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}
func (s HandlerService) AddProject(c *gin.Context) (data interface{}, err error) { func (s HandlerService) AddProject(c *gin.Context) (data interface{}, err error) {
repo := service.NewManageService(s.AppConfig, s.Engine, s.Logger) repo := service.NewManageService(s.AppConfig, s.Engine, s.Logger)
us, _ := c.Get("operatorUser") us, _ := c.Get("operatorUser")

View File

@ -0,0 +1,47 @@
package handler
import (
"fmt"
"github.com/gin-gonic/gin"
"hpds-iot-web/internal/proto"
"hpds-iot-web/internal/service"
"hpds-iot-web/model"
e "hpds-iot-web/pkg/err"
)
func (s HandlerService) ReportList(c *gin.Context) (data interface{}, err error) {
repo := service.NewReportService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.ReportRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("ReportList", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.ReportList(c, req)
go s.SaveLog("报表列表", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}
func (s HandlerService) GenerateReport(c *gin.Context) (data interface{}, err error) {
repo := service.NewReportService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.ReportRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("GenerateReport", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
xlsx, err := repo.GenerateReport(c, req)
if err != nil {
}
c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
c.Header("Content-Disposition", "attachment; filename=模型报表.xlsx")
//c.Header("")
c.Header("Content-Transfer-Encoding", "binary")
err = xlsx.Write(c.Writer)
return nil, err
}

View File

@ -19,6 +19,15 @@ func (s HandlerService) TaskList(c *gin.Context) (data interface{}, err error) {
go s.SaveLog("TaskList", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("TaskList", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err) return nil, e.NewValidErr(err)
} }
if req.Size < 1 {
req.Size = 20
}
if req.Size > 1000 {
req.Size = 1000
}
if req.Page < 1 {
req.Page = 1
}
data, err = repo.TaskList(c, req) data, err = repo.TaskList(c, req)
go s.SaveLog("任务列表", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("任务列表", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
@ -38,3 +47,71 @@ func (s HandlerService) AddTask(c *gin.Context) (data interface{}, err error) {
go s.SaveLog("新增任务", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("新增任务", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
} }
func (s HandlerService) ReRunTask(c *gin.Context) (data interface{}, err error) {
repo := service.NewTaskService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.TaskItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("ReRunTask", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.ReRunTask(c, req)
go s.SaveLog("重新执行任务", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}
func (s HandlerService) TaskInfo(c *gin.Context) (data interface{}, err error) {
repo := service.NewTaskService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.TaskItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("TaskInfo", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.TaskInfo(c, req)
go s.SaveLog("获取任务信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}
func (s HandlerService) TaskResult(c *gin.Context) (data interface{}, err error) {
repo := service.NewTaskService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.ReportRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("TaskResult", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
if req.Size < 1 {
req.Size = 20
}
if req.Size > 1000 {
req.Size = 1000
}
if req.Page < 1 {
req.Page = 1
}
data, err = repo.TaskResult(c, req)
go s.SaveLog("获取任务结果信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}
func (s HandlerService) TaskLog(c *gin.Context) (data interface{}, err error) {
repo := service.NewTaskService(s.Engine, s.Logger)
us, _ := c.Get("operatorUser")
userInfo := us.(*model.SystemUser)
var req proto.TaskItemRequest
err = c.ShouldBindJSON(&req)
if err != nil {
go s.SaveLog("TaskLog", "Manage", "", "", req.ToString(), fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
data, err = repo.TaskLog(c, req)
go s.SaveLog("获取任务日志信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return
}

View File

@ -33,7 +33,6 @@ func (s HandlerService) AddUser(c *gin.Context) (data interface{}, err error) {
data, err = repo.AddUser(c, req) data, err = repo.AddUser(c, req)
go s.SaveLog("新增用户", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("新增用户", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
return
} }
func (s HandlerService) EditUser(c *gin.Context) (data interface{}, err error) { func (s HandlerService) EditUser(c *gin.Context) (data interface{}, err error) {
@ -49,7 +48,6 @@ func (s HandlerService) EditUser(c *gin.Context) (data interface{}, err error) {
data, err = repo.EditUser(c, req) data, err = repo.EditUser(c, req)
go s.SaveLog("修改用户信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "") go s.SaveLog("修改用户信息", "Manage", "", "", "", fmt.Sprintf("%d", userInfo.UserId), c.Request.RemoteAddr, "")
return return
return
} }
func (s HandlerService) GetUserInfo(c *gin.Context) (data interface{}, err error) { func (s HandlerService) GetUserInfo(c *gin.Context) (data interface{}, err error) {
@ -80,5 +78,10 @@ func (s HandlerService) MenuList(c *gin.Context) (data interface{}, err error) {
us, _ := c.Get("operatorUser") us, _ := c.Get("operatorUser")
userinfo := us.(*model.SystemUser) userinfo := us.(*model.SystemUser)
data, err = repo.MenuList(c, userinfo.UserId) data, err = repo.MenuList(c, userinfo.UserId)
if err != nil {
go s.SaveLog("GetUserList", "Manage", "", "", userinfo.ToString(), fmt.Sprintf("%d", userinfo.UserId), c.Request.RemoteAddr, "")
return nil, e.NewValidErr(err)
}
go s.SaveLog("获取用户菜单列表", "Manage", "", "", "", fmt.Sprintf("%d", userinfo.UserId), c.Request.RemoteAddr, "")
return return
} }

View File

@ -70,7 +70,7 @@ func JwtAuthMiddleware(logger *zap.Logger) gin.HandlerFunc {
) )
token := c.GetHeader("Authorization") token := c.GetHeader("Authorization")
// 这里可以过滤不需要进行验证的接口 // 这里可以过滤不需要进行验证的接口
if path == "/api/user/login" || path == "/api/health" { if path == "/api/user/login" || path == "/api/health" || path == "/api/task/event" {
goto Return goto Return
} }
if len(token) == 0 { if len(token) == 0 {

View File

@ -428,6 +428,11 @@ type UploadFileRequest struct {
Scene string `json:"scene"` Scene string `json:"scene"`
Files []*multipart.FileHeader `json:"files"` Files []*multipart.FileHeader `json:"files"`
DatasetId int64 `json:"datasetId"` DatasetId int64 `json:"datasetId"`
DataType int `json:"dataType"`
}
type FileList struct {
DatasetId int64
} }
type BrandRequest struct { type BrandRequest struct {
@ -514,7 +519,7 @@ func (p OwnerProjectRequest) ToString() string {
type DatasetRequest struct { type DatasetRequest struct {
OwnerId int64 `json:"ownerId"` OwnerId int64 `json:"ownerId"`
ProjectId int64 `json:"projectId"` ProjectId []int64 `json:"projectId"`
DatasetName string `json:"datasetName"` DatasetName string `json:"datasetName"`
StartTime string `json:"startTime"` StartTime string `json:"startTime"`
EndTime string `json:"endTime"` EndTime string `json:"endTime"`
@ -529,6 +534,20 @@ func (p DatasetRequest) ToString() string {
return string(data) return string(data)
} }
type DatasetItemRequest struct {
DatasetId int64 `json:"datasetId"`
DataType int `json:"dataType"`
BasePageList
}
func (p DatasetItemRequest) ToString() string {
data, err := json.Marshal(p)
if err != nil {
return ""
}
return string(data)
}
type ImportDatasetRequest struct { type ImportDatasetRequest struct {
DatasetId int64 `json:"datasetId"` DatasetId int64 `json:"datasetId"`
CategoryId int `json:"categoryId"` CategoryId int `json:"categoryId"`
@ -655,3 +674,17 @@ func (p TaskItemRequest) ToString() string {
} }
return string(data) return string(data)
} }
type ReportRequest struct {
ReportId int64 `json:"reportId,omitempty"`
TaskId int64 `json:"taskId,omitempty"`
BasePageList
}
func (p ReportRequest) ToString() string {
data, err := json.Marshal(p)
if err != nil {
return ""
}
return string(data)
}

View File

@ -121,3 +121,23 @@ type TaskDetail struct {
CreateAt int64 `xorm:"created" json:"createAt"` CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"` UpdateAt int64 `xorm:"updated" json:"updateAt"`
} }
type TaskResultItem struct {
FileId int64 `json:"fileId"`
FileName string `json:"fileName"`
SrcFile string `json:"srcFile"`
DistFile string `json:"distFile"`
DiseaseType int `json:"diseaseType"`
DiseaseTypeName string `json:"diseaseTypeName"`
DiseaseLevel int `json:"diseaseLevel"`
DiseaseLevelName string `json:"diseaseLevelName"`
KPile string `json:"KPile"`
UpDown int `json:"upDown"`
LineNum int `json:"lineNum"`
Length float64 `json:"length"`
Width float64 `json:"width"`
Area float64 `json:"area"`
HorizontalPositions float64 `json:"horizontalPositions"`
Memo string `json:"memo"`
Stat bool `json:"stat"`
}

View File

@ -1,12 +1,15 @@
package router package router
import ( import (
"fmt"
"git.hpds.cc/Component/logging" "git.hpds.cc/Component/logging"
ginzap "github.com/gin-contrib/zap" ginzap "github.com/gin-contrib/zap"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hpds-iot-web/config" "hpds-iot-web/config"
"hpds-iot-web/internal/handler" "hpds-iot-web/internal/handler"
"hpds-iot-web/internal/middleware" "hpds-iot-web/internal/middleware"
"hpds-iot-web/mq"
"net/http"
"xorm.io/xorm" "xorm.io/xorm"
e "hpds-iot-web/pkg/err" e "hpds-iot-web/pkg/err"
@ -48,6 +51,7 @@ func InitRouter(cfg *config.WebConfig, logger *logging.Logger, engine *xorm.Engi
project := manage.Group("/project") project := manage.Group("/project")
{ {
project.POST("/list", e.ErrorWrapper(hs.ProjectList)) project.POST("/list", e.ErrorWrapper(hs.ProjectList))
project.POST("/info", e.ErrorWrapper(hs.ProjectInfo))
project.POST("/add", e.ErrorWrapper(hs.AddProject)) project.POST("/add", e.ErrorWrapper(hs.AddProject))
project.POST("/edit", e.ErrorWrapper(hs.EditProject)) project.POST("/edit", e.ErrorWrapper(hs.EditProject))
project.POST("/delete", e.ErrorWrapper(hs.DelProject)) project.POST("/delete", e.ErrorWrapper(hs.DelProject))
@ -135,6 +139,7 @@ func InitRouter(cfg *config.WebConfig, logger *logging.Logger, engine *xorm.Engi
{ {
file.Use(middleware.JwtAuthMiddleware(logger.Logger)) file.Use(middleware.JwtAuthMiddleware(logger.Logger))
file.POST("/upload", e.ErrorWrapper(hs.UploadFile)) file.POST("/upload", e.ErrorWrapper(hs.UploadFile))
file.POST("/list", e.ErrorWrapper(hs.FileList))
} }
system := r.Group("/system") system := r.Group("/system")
{ {
@ -163,6 +168,34 @@ func InitRouter(cfg *config.WebConfig, logger *logging.Logger, engine *xorm.Engi
task.Use(middleware.JwtAuthMiddleware(logger.Logger)) task.Use(middleware.JwtAuthMiddleware(logger.Logger))
task.POST("/list", e.ErrorWrapper(hs.TaskList)) task.POST("/list", e.ErrorWrapper(hs.TaskList))
task.POST("/add", e.ErrorWrapper(hs.AddTask)) task.POST("/add", e.ErrorWrapper(hs.AddTask))
task.POST("/reRun", e.ErrorWrapper(hs.ReRunTask))
task.POST("/info", e.ErrorWrapper(hs.TaskInfo))
task.POST("/result", e.ErrorWrapper(hs.TaskResult))
task.POST("/log", e.ErrorWrapper(hs.TaskLog))
task.GET("/event", func(c *gin.Context) {
//us, _ := c.Get("operatorUser")
//userInfo := us.(*m.SystemUser)
mq.AddChannel(fmt.Sprintf("%d", 1))
c.Writer.Header().Set("Content-Type", "text/event-stream")
c.Writer.Header().Set("Cache-Control", "no-cache")
c.Writer.Header().Set("Connection", "keep-alive")
w := c.Writer
flusher, _ := w.(http.Flusher)
closeNotify := c.Request.Context().Done()
go func() {
<-closeNotify
delete(mq.ChannelsMap, fmt.Sprintf("%d", 1))
logging.L().Info("SSE close for user = " + fmt.Sprintf("%d", 1))
return
}()
_, _ = fmt.Fprintf(w, "data: %s\n\n", "--ping--")
flusher.Flush()
for msg := range mq.ChannelsMap[fmt.Sprintf("%d", 1)] {
_, _ = fmt.Fprintf(w, "data: %s\n\n", msg)
flusher.Flush()
}
})
} }
disease := r.Group("/disease") disease := r.Group("/disease")
{ {
@ -183,6 +216,15 @@ func InitRouter(cfg *config.WebConfig, logger *logging.Logger, engine *xorm.Engi
dataset.POST("/list", e.ErrorWrapper(hs.DatasetList)) dataset.POST("/list", e.ErrorWrapper(hs.DatasetList))
dataset.POST("/import", e.ErrorWrapper(hs.ImportDataset)) dataset.POST("/import", e.ErrorWrapper(hs.ImportDataset))
dataset.POST("/info", e.ErrorWrapper(hs.DatasetInfo))
}
report := r.Group("/report")
{
report.Use(middleware.JwtAuthMiddleware(logger.Logger))
report.POST("/list", e.ErrorWrapper(hs.ReportList))
report.POST("/generate", e.ErrorWrapper(hs.GenerateReport))
//report.POST("/view", e.ErrorWrapper(hs.ViewReport))
} }
} }
return root return root

View File

@ -16,6 +16,7 @@ type DatasetService interface {
GetOwnerProjectList(ctx context.Context, req proto.OwnerProjectRequest) (rsp *proto.BaseResponse, err error) GetOwnerProjectList(ctx context.Context, req proto.OwnerProjectRequest) (rsp *proto.BaseResponse, err error)
DatasetList(ctx context.Context, req proto.DatasetRequest) (rsp *proto.BaseResponse, err error) DatasetList(ctx context.Context, req proto.DatasetRequest) (rsp *proto.BaseResponse, err error)
ImportDataset(ctx context.Context, req proto.ImportDatasetRequest) (rsp *proto.BaseResponse, err error) ImportDataset(ctx context.Context, req proto.ImportDatasetRequest) (rsp *proto.BaseResponse, err error)
DatasetInfo(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error)
} }
func NewDatasetService(cfg *config.WebConfig, engine *xorm.Engine, logger *logging.Logger) DatasetService { func NewDatasetService(cfg *config.WebConfig, engine *xorm.Engine, logger *logging.Logger) DatasetService {
@ -86,24 +87,27 @@ func (rp *repo) DatasetList(ctx context.Context, req proto.DatasetRequest) (rsp
return rsp, ctx.Err() return rsp, ctx.Err()
default: default:
list := make([]model.Dataset, 0) list := make([]model.Dataset, 0)
count, err := rp.engine.Where("(? = '' or dataset_name like ?)", req.DatasetName, "%"+req.DatasetName+"%"). st := rp.engine.Where("(? = '' or dataset_name like ?)", req.DatasetName, "%"+req.DatasetName+"%").
And("(? = '' or create_at >= ?)", req.StartTime, req.StartTime). And("(? = '' or create_at >= ?)", req.StartTime, req.StartTime).
And("(? = '' or create_at < ?)", req.EndTime, req.EndTime). And("(? = '' or create_at < ?)", req.EndTime, req.EndTime).
And("(? = 0 or owner_id = ?)", req.OwnerId, req.OwnerId). And("(? = 0 or owner_id = ?)", req.OwnerId, req.OwnerId).
And("(? = 0 or project_id = ?)", req.ProjectId, req.ProjectId). And("status = 1")
And("status = 1").FindAndCount(&list) if len(req.ProjectId) > 0 {
st.In("project_id", req.ProjectId)
}
count, err := st.Limit(int(req.Size), int(((req.Page)-1)*req.Size)).FindAndCount(&list)
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
} }
data := make([]proto.DatasetItem, len(list)) data := make([]proto.DatasetItem, len(list))
for k, v := range list { for k, v := range list {
detailList := make([]model.FileManager, 0) detailList := make([]model.FileManager, 0)
datasetCount, err := rp.engine.Where("dataset_id = ?", v.DatasetId).FindAndCount(&detailList) datasetCount, err := rp.engine.Where("dataset_id = ?", v.DatasetId).And("data_type=1").FindAndCount(&detailList)
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
} }
fm := new(model.FileManager) fm := new(model.FileManager)
datasetSize, err := rp.engine.Where("dataset_id = ?", v.DatasetId).SumInt(fm, "file_size") datasetSize, err := rp.engine.Where("dataset_id = ?", v.DatasetId).And("data_type=1").SumInt(fm, "file_size")
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
} }
@ -181,3 +185,42 @@ ReturnPoint:
} }
return rsp, err return rsp, err
} }
func (rp *repo) DatasetInfo(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
item := new(model.Dataset)
var b bool
b, err = rp.engine.ID(req.DatasetId).Get(item)
if err != nil {
goto ReturnPoint
}
if !b {
err = fmt.Errorf("未能找到对应的数据集")
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp.Err = err
rsp.Data = item
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}

View File

@ -22,7 +22,8 @@ import (
type FileService interface { type FileService interface {
UploadFile(ctx context.Context, req proto.UploadFileRequest) (rsp *proto.BaseResponse, err error) UploadFile(ctx context.Context, req proto.UploadFileRequest) (rsp *proto.BaseResponse, err error)
UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64) (data *model.FileManager, err error) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64, dataType int) (data *model.FileManager, err error)
FileList(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error)
} }
func NewFileService(cfg *config.WebConfig, engine *xorm.Engine, logger *logging.Logger) FileService { func NewFileService(cfg *config.WebConfig, engine *xorm.Engine, logger *logging.Logger) FileService {
@ -47,7 +48,7 @@ func (rp *repo) UploadFile(ctx context.Context, req proto.UploadFileRequest) (rs
list := make([]*model.FileManager, len(req.Files)) list := make([]*model.FileManager, len(req.Files))
fileUrl := make([]string, len(req.Files)) fileUrl := make([]string, len(req.Files))
for k := range req.Files { for k := range req.Files {
fileItem, err := rp.UploadFileToMinIo(ctx, req.Files[k], req.Scene, req.DatasetId, req.Creator) fileItem, err := rp.UploadFileToMinIo(ctx, req.Files[k], req.Scene, req.DatasetId, req.Creator, req.DataType)
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
} }
@ -76,7 +77,7 @@ ReturnPoint:
return rsp, err return rsp, err
} }
func (rp *repo) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64) (data *model.FileManager, err error) { func (rp *repo) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHeader, scene string, datasetId, creator int64, dataType int) (data *model.FileManager, err error) {
file, err := srcFile.Open() file, err := srcFile.Open()
defer func(file multipart.File) { defer func(file multipart.File) {
_ = file.Close() _ = file.Close()
@ -126,9 +127,47 @@ func (rp *repo) UploadFileToMinIo(ctx context.Context, srcFile *multipart.FileHe
data.Scene = scene data.Scene = scene
data.AccessUrl = accessUrl data.AccessUrl = accessUrl
data.FileSize = srcFile.Size data.FileSize = srcFile.Size
data.DataType = dataType
data.DatasetId = datasetId
data.Creator = creator data.Creator = creator
data.FileMd5 = hex.EncodeToString(md5hash.Sum(nil)) data.FileMd5 = hex.EncodeToString(md5hash.Sum(nil))
data.CreateAt = time.Now().Unix() data.CreateAt = time.Now().Unix()
data.UpdateAt = time.Now().Unix() data.UpdateAt = time.Now().Unix()
return data, nil return data, nil
} }
func (rp *repo) FileList(ctx context.Context, req proto.DatasetItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
data := make([]model.FileManager, 0)
count, err := rp.engine.Where("(? = 0 or dataset_id = ?)", req.DatasetId, req.DatasetId).
And("(? = 0 or data_type = ?)", req.DataType, req.DataType).
Limit(int(req.Size), int(((req.Page)-1)*req.Size)).
FindAndCount(&data)
if err != nil {
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp = FillPaging(count, req.Page, req.Size, data, rsp)
rsp.Err = err
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}

View File

@ -24,6 +24,7 @@ type ManageService interface {
ProjectList(ctx context.Context, req proto.ProjectRequest) (rsp *proto.BaseResponse, err error) ProjectList(ctx context.Context, req proto.ProjectRequest) (rsp *proto.BaseResponse, err error)
GetLngLat(ctx context.Context, mileagePile string) (lng, lat float64, err error) GetLngLat(ctx context.Context, mileagePile string) (lng, lat float64, err error)
ProjectInfo(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error)
AddProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) AddProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error)
EditProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) EditProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error)
DelProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) DelProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error)
@ -321,6 +322,44 @@ ReturnPoint:
return rsp, err return rsp, err
} }
func (rp *repo) ProjectInfo(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
var h bool
item := new(model.Project)
h, err = rp.engine.ID(req.ProjectId).Get(item)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到对应的项目")
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp.Data = item
rsp.Err = err
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}
func (rp *repo) AddProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) { func (rp *repo) AddProject(ctx context.Context, req proto.ProjectItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse) rsp = new(proto.BaseResponse)
select { select {
@ -378,6 +417,7 @@ ReturnPoint:
} }
return rsp, err return rsp, err
} }
func (rp *repo) GetLngLat(ctx context.Context, mileagePile string) (lng, lat float64, err error) { func (rp *repo) GetLngLat(ctx context.Context, mileagePile string) (lng, lat float64, err error) {
mine := minedata.NewMineData(rp.AppConfig.MineData.AccessKey) mine := minedata.NewMineData(rp.AppConfig.MineData.AccessKey)
//正里程桩 //正里程桩

187
internal/service/report.go Normal file
View File

@ -0,0 +1,187 @@
package service
import (
"context"
"fmt"
"git.hpds.cc/Component/logging"
"hpds-iot-web/internal/proto"
"hpds-iot-web/model"
"net/http"
"xorm.io/xorm"
"github.com/360EntSecGroup-Skylar/excelize"
)
type ReportService interface {
ReportList(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error)
GenerateReport(ctx context.Context, req proto.ReportRequest) (rsp *excelize.File, err error)
}
func NewReportService(engine *xorm.Engine, logger *logging.Logger) ReportService {
return &repo{
engine: engine,
logger: logger,
}
}
func (rp *repo) ReportList(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
data := make([]model.Report, 0)
count, err := rp.engine.
Where("(? = 0 or m.report_id = ?)", req.ReportId, req.ReportId).
And("t.status > 0").Limit(int(req.Size), int(((req.Page)-1)*req.Size)).
FindAndCount(&data)
if err != nil {
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp = FillPaging(count, req.Page, req.Size, data, rsp)
rsp.Err = err
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}
func (rp *repo) GenerateReport(ctx context.Context, req proto.ReportRequest) (rsp *excelize.File, err error) {
//rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
//rsp.Code = http.StatusInternalServerError
//rsp.Status = http.StatusText(http.StatusInternalServerError)
//rsp.Message = "超时/取消"
//rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
//data := make([]model.Report, 0)
//_, err = rp.engine.
// Where("(? = 0 or m.report_id = ?)", req.ReportId, req.ReportId).
// And("t.status > 0").Limit(int(req.Size), int(((req.Page)-1)*req.Size)).
// FindAndCount(&data)
//if err != nil {
// goto ReturnPoint
//}
list := make([]proto.TaskResultItem, 2)
list[0] = proto.TaskResultItem{
FileId: 147,
FileName: "Y016 2.844 I 1 06272008 Color.jpg",
SrcFile: "http://127.0.0.1:9000/jky-data/road/test_dataset/Y016 2.844 I 1 06272008 Color.jpg",
DistFile: "http://127.0.0.1:9000/jky-data/road/test_dataset/Y016 2.844 I 1 06272008 Color.jpg",
DiseaseType: 4,
DiseaseLevel: 2,
KPile: "K229+778",
UpDown: 1,
LineNum: 2,
Length: 0.5,
Width: 1,
Area: 0.5,
HorizontalPositions: 0.5,
Memo: "有裂缝",
}
list[1] = proto.TaskResultItem{
FileId: 149,
FileName: "C279 0.132 I 1 06272008 Color.jpg",
SrcFile: "http://127.0.0.1:9000/jky-data/road/test_dataset/cba/C279 0.132 I 1 06272008 Color.jpg",
DistFile: "http://127.0.0.1:9000/jky-data/road/test_dataset/cba/C279 0.132 I 1 06272008 Color.jpg",
DiseaseType: 0,
DiseaseLevel: 0,
KPile: "",
UpDown: 0,
LineNum: 0,
Length: 0,
Width: 0,
Area: 0,
HorizontalPositions: 0,
}
disTypeList := make([]model.DiseaseType, 0)
err = model.DB.Find(&disTypeList)
if err != nil {
goto ReturnPoint
}
diseaseTypeList := make(map[int64]string)
for _, v := range disTypeList {
diseaseTypeList[v.TypeId] = v.TypeName
}
diseaseLevelList := make(map[int]string)
diseaseLevelList[1] = "一级"
diseaseLevelList[2] = "二级"
diseaseLevelList[3] = "三级"
xlsx := excelize.NewFile()
xlsx.MergeCell("Sheet1", "A1", "L1")
xlsx.MergeCell("Sheet1", "A2", "L2")
xlsx.MergeCell("Sheet1", "A3", "L3")
xlsx.MergeCell("Sheet1", "A4", "L4")
xlsx.SetCellValue("Sheet1", "A4", "病害明细")
//序号 路线编码 方向 桩号 车道 病害名称 程度 长度(m) 宽度(m) 面积(㎡) 横向位置 备注
xlsx.SetCellValue("Sheet1", "A5", "序号")
xlsx.SetCellValue("Sheet1", "B5", "路线编码")
xlsx.SetCellValue("Sheet1", "C5", "方向")
xlsx.SetCellValue("Sheet1", "D5", "桩号")
xlsx.SetCellValue("Sheet1", "E5", "车道")
xlsx.SetCellValue("Sheet1", "F5", "病害名称")
xlsx.SetCellValue("Sheet1", "G5", "程度")
xlsx.SetCellValue("Sheet1", "H5", "长度(m)")
xlsx.SetCellValue("Sheet1", "I5", "宽度(m)")
xlsx.SetCellValue("Sheet1", "J5", "面积(㎡)")
xlsx.SetCellValue("Sheet1", "K5", "横向位置")
xlsx.SetCellValue("Sheet1", "L5", "备注")
for k, v := range list {
xlsx.SetCellValue("Sheet1", fmt.Sprintf("A%d", k+6), k+1)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("B%d", k+6), v.KPile)
switch v.UpDown {
case 1:
xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", k+6), "上行")
case 2:
xlsx.SetCellValue("Sheet1", fmt.Sprintf("C%d", k+6), "下行")
}
xlsx.SetCellValue("Sheet1", fmt.Sprintf("D%d", k+6), v.KPile)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("E%d", k+6), v.LineNum)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("F%d", k+6), diseaseTypeList[int64(v.DiseaseType)])
xlsx.SetCellValue("Sheet1", fmt.Sprintf("G%d", k+6), diseaseLevelList[v.DiseaseLevel])
xlsx.SetCellValue("Sheet1", fmt.Sprintf("H%d", k+6), v.Length)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("I%d", k+6), v.Width)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("J%d", k+6), v.Area)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", k+6), v.HorizontalPositions)
xlsx.SetCellValue("Sheet1", fmt.Sprintf("K%d", k+6), v.Memo)
}
//rsp = xlsx
//rsp.Code = http.StatusOK
//rsp.Status = http.StatusText(http.StatusOK)
//rsp.Message = "成功"
//rsp.Data = xlsx
//rsp.Err = err
return xlsx, err
}
ReturnPoint:
if err != nil {
rsp = nil
//rsp.Code = http.StatusInternalServerError
//rsp.Status = http.StatusText(http.StatusInternalServerError)
//rsp.Err = err
//rsp.Message = "失败"
}
return rsp, err
}

View File

@ -411,7 +411,7 @@ func (rp *repo) NodeState(ctx context.Context, req proto.NodeInfoRequest) (rsp *
return rsp, ctx.Err() return rsp, ctx.Err()
default: default:
list := make([]model.NodeState, 0) list := make([]model.NodeState, 0)
err = rp.engine.Where("node_name = ?", req.NodeGuid). err = rp.engine.Where("node_guid = ?", req.NodeGuid).
And(" uptime > UNIX_TIMESTAMP(DATE_ADD(NOW(),INTERVAL -24 HOUR))"). And(" uptime > UNIX_TIMESTAMP(DATE_ADD(NOW(),INTERVAL -24 HOUR))").
Find(&list) Find(&list)
if err != nil { if err != nil {

View File

@ -1,7 +1,9 @@
package service package service
import ( import (
"bytes"
"context" "context"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.hpds.cc/Component/logging" "git.hpds.cc/Component/logging"
@ -9,15 +11,21 @@ import (
"hpds-iot-web/internal/proto" "hpds-iot-web/internal/proto"
"hpds-iot-web/model" "hpds-iot-web/model"
"hpds-iot-web/mq" "hpds-iot-web/mq"
"image"
"net/http" "net/http"
"strconv"
"time" "time"
"xorm.io/xorm" "xorm.io/xorm"
) )
type TaskService interface { type TaskService interface {
TaskList(ctx context.Context, req proto.TaskRequest) (rsp *proto.BaseResponse, err error) TaskList(ctx context.Context, req proto.TaskRequest) (rsp *proto.BaseResponse, err error)
TaskInfo(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error)
AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error) AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error)
ReRunTask(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error)
//EditTask(ctx context.Context, req proto.ModelItemRequest) (rsp *proto.BaseResponse, err error) //EditTask(ctx context.Context, req proto.ModelItemRequest) (rsp *proto.BaseResponse, err error)
TaskResult(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error)
TaskLog(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error)
} }
func NewTaskService(engine *xorm.Engine, logger *logging.Logger) TaskService { func NewTaskService(engine *xorm.Engine, logger *logging.Logger) TaskService {
@ -48,6 +56,7 @@ func (rp *repo) TaskList(ctx context.Context, req proto.TaskRequest) (rsp *proto
And("t.start_time >= unix_timestamp(?)", req.StartTime). And("t.start_time >= unix_timestamp(?)", req.StartTime).
And("? = 0 or t.start_time <= unix_timestamp(?)", req.FinishTime, req.FinishTime). And("? = 0 or t.start_time <= unix_timestamp(?)", req.FinishTime, req.FinishTime).
And("t.status > 0").Limit(int(req.Size), int(((req.Page)-1)*req.Size)). And("t.status > 0").Limit(int(req.Size), int(((req.Page)-1)*req.Size)).
Desc("start_time").
FindAndCount(&data) FindAndCount(&data)
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
@ -92,7 +101,7 @@ func (rp *repo) AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *pr
} }
ds := new(model.Dataset) ds := new(model.Dataset)
h, err = rp.engine.ID(req.ModelId).Get(ds) h, err = rp.engine.ID(req.DatasetArr).Get(ds)
if err != nil { if err != nil {
goto ReturnPoint goto ReturnPoint
} }
@ -100,6 +109,18 @@ func (rp *repo) AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *pr
err = fmt.Errorf("未能找到对应的数据集") err = fmt.Errorf("未能找到对应的数据集")
goto ReturnPoint goto ReturnPoint
} }
var node *model.Node
if req.NodeId > 0 {
node = new(model.Node)
h, err = rp.engine.ID(req.NodeId).Get(node)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到对应的节点")
goto ReturnPoint
}
}
item := &model.Task{ item := &model.Task{
ModelId: req.ModelId, ModelId: req.ModelId,
@ -143,6 +164,9 @@ func (rp *repo) AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *pr
payload["modelVersion"] = m.ModelVersion payload["modelVersion"] = m.ModelVersion
payload["modelCommand"] = m.ModelCommand payload["modelCommand"] = m.ModelCommand
payload["nodeId"] = item.NodeId payload["nodeId"] = item.NodeId
if item.NodeId > 0 && node != nil {
payload["nodeGuid"] = node.NodeGuid
}
payload["inPath"] = m.InPath payload["inPath"] = m.InPath
payload["outPath"] = m.OutPath payload["outPath"] = m.OutPath
payload["httpUrl"] = m.HttpUrl payload["httpUrl"] = m.HttpUrl
@ -153,6 +177,11 @@ func (rp *repo) AddTask(ctx context.Context, req proto.TaskItemRequest) (rsp *pr
payload["subDataTag"] = item.SubDataTag payload["subDataTag"] = item.SubDataTag
payload["workflow"] = m.Workflow payload["workflow"] = m.Workflow
issue := new(model.IssueModel)
h, _ = model.DB.Where("model_id=? and node_id =?", req.ModelId, item.NodeId).Get(issue)
if h {
payload["issueResult"] = issue.IssueResult
}
mqClient := mq.GetMqClient("task-request", 1) mqClient := mq.GetMqClient("task-request", 1)
mqPayload := &mq.InstructionReq{ mqPayload := &mq.InstructionReq{
Command: mq.TaskAdd, Command: mq.TaskAdd,
@ -176,3 +205,473 @@ ReturnPoint:
} }
return rsp, err return rsp, err
} }
func (rp *repo) ReRunTask(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
item := new(model.Task)
var h bool
h, err = rp.engine.ID(req.TaskId).Get(item)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到任务")
goto ReturnPoint
}
m := new(model.Model)
h, err = rp.engine.ID(item.ModelId).Get(m)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到对应的模型")
goto ReturnPoint
}
ds := new(model.Dataset)
h, err = rp.engine.ID(item.DatasetArr).Get(ds)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到对应的数据集")
goto ReturnPoint
}
var node *model.Node
if item.NodeId > 0 {
node = new(model.Node)
h, err = rp.engine.ID(item.NodeId).Get(node)
if err != nil {
goto ReturnPoint
}
if !h {
err = fmt.Errorf("未能找到对应的节点")
goto ReturnPoint
}
}
payload := make(map[string]interface{})
payload["taskId"] = item.TaskId
payload["modelId"] = item.ModelId
payload["modelVersion"] = m.ModelVersion
payload["modelCommand"] = m.ModelCommand
payload["nodeId"] = item.NodeId
if item.NodeId > 0 && node != nil {
payload["nodeGuid"] = node.NodeGuid
}
payload["inPath"] = m.InPath
payload["outPath"] = m.OutPath
payload["httpUrl"] = m.HttpUrl
payload["datasetArr"] = item.DatasetArr
payload["datasetPath"] = ds.StoreName
payload["datasetName"] = ds.DatasetName
payload["subDataset"] = item.SubDataset
payload["subDataTag"] = item.SubDataTag
payload["workflow"] = m.Workflow
issue := new(model.IssueModel)
h, _ = model.DB.Where("model_id=? and node_id =?", req.ModelId, item.NodeId).Get(issue)
if h {
payload["issueResult"] = issue.IssueResult
}
mqClient := mq.GetMqClient("task-request", 1)
mqPayload := &mq.InstructionReq{
Command: mq.TaskAdd,
Payload: payload,
}
pData, _ := json.Marshal(mqPayload)
err = mq.GenerateAndSendData(mqClient.EndPoint.(hpds_node.AccessPoint), pData, rp.logger)
if err != nil {
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "重新任务成功"
rsp.Err = ctx.Err()
rsp.Data = item
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}
func (rp *repo) TaskInfo(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
item := new(model.Task)
var b bool
b, err = rp.engine.ID(req.TaskId).Get(item)
if err != nil {
goto ReturnPoint
}
if !b {
err = fmt.Errorf("未能找到对应的任务")
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp.Err = err
rsp.Data = item
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}
func (rp *repo) TaskResult(ctx context.Context, req proto.ReportRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
taskResultList := make([]model.TaskResult, 0)
err = rp.engine.Where("task_id = ?", req.TaskId).
Limit(int(req.Size), int(((req.Page)-1)*req.Size)).
Find(&taskResultList)
if err != nil {
err = fmt.Errorf("未能找到对应的结果")
goto ReturnPoint
}
list := make([]proto.TaskResultItem, 0)
for _, v := range taskResultList {
var h bool
file := new(model.FileManager)
h, err = rp.engine.ID(v.FileId).Get(file)
if err != nil || !h {
continue
}
md := new(model.Model)
h, err = rp.engine.ID(v.ModelId).Get(md)
if err != nil || !h {
continue
}
var (
mr mq.ModelResult
mrList []string
fileDiscern string
memo string
diseaseType int64
diseaseLevel int
length float64
area float64
width float64
diseaseTypeName string
diseaseLevelName string
)
if len(v.Result) > 0 && v.Result[0] == '[' {
mrList = make([]string, 0)
if err := json.Unmarshal([]byte(v.Result), &mrList); err != nil {
continue
}
for _, str := range mrList {
if err := json.Unmarshal([]byte(str), &mr); err != nil {
continue
}
switch mr.Code {
case 0: //轻量化模型返回
lr := new(mq.LightweightResult)
if err := json.Unmarshal([]byte(v.Result), lr); err != nil {
continue
}
//for _, val := range lrList {
if lr.Crack || lr.Pothole {
if lr.Crack {
memo = "检测到裂缝"
} else {
memo = "检测到坑洼"
}
fileDiscern = lr.ImgDiscern
diseaseLevel = 3
diseaseLevelName = "重度"
switch md.BizType {
case 2:
diseaseType = 8
diseaseTypeName = "结构裂缝"
case 3:
diseaseType = 15
diseaseTypeName = "衬砌裂缝"
default:
diseaseType = 4
diseaseTypeName = "横向裂缝"
}
}
fn, _ := base64.StdEncoding.DecodeString(fileDiscern)
buff := bytes.NewBuffer(fn)
_, imgType, _ := image.Decode(buff)
fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern)
item := proto.TaskResultItem{
FileId: v.FileId,
FileName: v.SrcPath,
SrcFile: file.AccessUrl,
DistFile: fileDiscern,
DiseaseType: int(diseaseType),
DiseaseTypeName: diseaseTypeName,
DiseaseLevel: diseaseLevel,
DiseaseLevelName: diseaseLevelName,
KPile: "",
UpDown: 0,
LineNum: 0,
Length: length,
Width: width,
Area: area,
HorizontalPositions: 0,
Memo: memo,
Stat: false,
}
list = append(list, item)
//}
case 2000:
ir := new(mq.InsigmaResult)
if err := json.Unmarshal([]byte(str), &ir); err != nil {
continue
}
fileDiscern = ir.Image
fn, _ := base64.StdEncoding.DecodeString(fileDiscern)
buff := bytes.NewBuffer(fn)
_, imgType, _ := image.Decode(buff)
fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern)
item := proto.TaskResultItem{
FileId: v.FileId,
FileName: v.SrcPath,
SrcFile: file.AccessUrl,
DistFile: fileDiscern,
DiseaseType: int(diseaseType),
DiseaseTypeName: diseaseTypeName,
DiseaseLevel: diseaseLevel,
DiseaseLevelName: diseaseLevelName,
KPile: "",
UpDown: 0,
LineNum: 0,
Length: length,
Width: width,
Area: area,
HorizontalPositions: 0,
Memo: memo,
Stat: false,
}
list = append(list, item)
case 2001:
ir := new(mq.InsigmaResult)
if err := json.Unmarshal([]byte(str), &ir); err != nil {
continue
}
fileDiscern = ir.Image
for _, value := range ir.Diseases {
diseaseType = model.GetDiseaseType(value.Type, md.BizType)
if len(value.Param.MaxWidth) > 0 && width == 0 {
width, _ = strconv.ParseFloat(value.Param.MaxWidth, 64)
}
length = value.Param.Length
area = value.Param.Area
diseaseLevelName = value.Level
diseaseTypeName = value.Type
switch value.Level {
case "重度":
diseaseLevel = 3
case "中度":
diseaseLevel = 2
case "轻度":
diseaseLevel = 1
}
memo += fmt.Sprintf("发现[%s],等级[%s],长度[%f],最大宽度[%s],面积[%f];\n", value.Type, value.Level, value.Param.Length, value.Param.MaxWidth, value.Param.Area)
}
fn, _ := base64.StdEncoding.DecodeString(fileDiscern)
buff := bytes.NewBuffer(fn)
_, imgType, _ := image.Decode(buff)
fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern)
item := proto.TaskResultItem{
FileId: v.FileId,
FileName: v.SrcPath,
SrcFile: file.AccessUrl,
DistFile: fileDiscern,
DiseaseType: int(diseaseType),
DiseaseTypeName: diseaseTypeName,
DiseaseLevel: diseaseLevel,
DiseaseLevelName: diseaseLevelName,
KPile: "",
UpDown: 0,
LineNum: 0,
Length: length,
Width: width,
Area: area,
HorizontalPositions: 0,
Memo: memo,
Stat: false,
}
list = append(list, item)
}
}
} else {
if err := json.Unmarshal([]byte(v.Result), &mr); err != nil {
continue
}
switch mr.Code {
case 0: //轻量化模型返回
lr := new(mq.LightweightResult)
if err := json.Unmarshal([]byte(v.Result), &lr); err != nil {
continue
}
if lr.Crack || lr.Pothole {
if lr.Crack {
memo = "检测到裂缝"
} else {
memo = "检测到坑洼"
}
fileDiscern = lr.ImgDiscern
diseaseLevel = 3
diseaseLevelName = "重度"
switch md.BizType {
case 2:
diseaseType = 8
diseaseTypeName = "结构裂缝"
case 3:
diseaseType = 15
diseaseTypeName = "衬砌裂缝"
default:
diseaseType = 4
diseaseTypeName = "横向裂缝"
}
}
//
case 2000: //网新返回没有病害
ir := new(mq.InsigmaResult)
if err := json.Unmarshal([]byte(v.Result), &ir); err != nil {
continue
}
fileDiscern = ir.Image
case 2001: //网新返回有病害
ir := new(mq.InsigmaResult)
if err := json.Unmarshal([]byte(v.Result), &ir); err != nil {
continue
}
fileDiscern = ir.Image
for _, val := range ir.Diseases {
diseaseType = model.GetDiseaseType(val.Type, md.BizType)
if len(val.Param.MaxWidth) > 0 && width == 0 {
width, _ = strconv.ParseFloat(val.Param.MaxWidth, 64)
}
length = val.Param.Length
area = val.Param.Area
diseaseLevelName = val.Level
diseaseTypeName = val.Type
switch val.Level {
case "重度":
diseaseLevel = 3
case "中度":
diseaseLevel = 2
case "轻度":
diseaseLevel = 1
}
memo += fmt.Sprintf("发现[%s],等级[%s],长度[%f],最大宽度[%s],面积[%f];\n", val.Type, val.Level, val.Param.Length, val.Param.MaxWidth, val.Param.Area)
}
}
fn, _ := base64.StdEncoding.DecodeString(fileDiscern)
buff := bytes.NewBuffer(fn)
_, imgType, _ := image.Decode(buff)
fileDiscern = fmt.Sprintf("data:image/%s;base64,%s", imgType, fileDiscern)
item := proto.TaskResultItem{
FileId: v.FileId,
FileName: v.SrcPath,
SrcFile: file.AccessUrl,
DistFile: fileDiscern,
DiseaseType: int(diseaseType),
DiseaseTypeName: diseaseTypeName,
DiseaseLevel: diseaseLevel,
DiseaseLevelName: diseaseLevelName,
KPile: "",
UpDown: 0,
LineNum: 0,
Length: length,
Width: width,
Area: area,
HorizontalPositions: 0,
Memo: memo,
Stat: false,
}
list = append(list, item)
}
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp.Err = err
rsp.Data = list
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}
func (rp *repo) TaskLog(ctx context.Context, req proto.TaskItemRequest) (rsp *proto.BaseResponse, err error) {
rsp = new(proto.BaseResponse)
select {
case <-ctx.Done():
err = fmt.Errorf("超时/取消")
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Message = "超时/取消"
rsp.Err = ctx.Err()
return rsp, ctx.Err()
default:
list := make([]model.TaskLog, 0)
err = rp.engine.Where("task_id = ?", req.TaskId).Find(&list)
if err != nil {
goto ReturnPoint
}
rsp.Code = http.StatusOK
rsp.Status = http.StatusText(http.StatusOK)
rsp.Message = "成功"
rsp.Err = err
rsp.Data = list
return rsp, err
}
ReturnPoint:
if err != nil {
rsp.Code = http.StatusInternalServerError
rsp.Status = http.StatusText(http.StatusInternalServerError)
rsp.Err = err
rsp.Message = "失败"
}
return rsp, err
}

14
model/TaskLog.go Normal file
View File

@ -0,0 +1,14 @@
package model
type TaskLog struct {
TaskLogId int64 `xorm:"not null pk autoincr BIGINT(11)" json:"taskLogId"`
TaskId int64 `xorm:"INT(11) index" json:"taskId"`
NodeId int64 `xorm:"INT(11) index" json:"nodeId"`
Content string `xorm:"LANGTEXT" json:"content"`
CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"`
}
func InsertLog(taskLog *TaskLog) {
_, _ = DB.Insert(taskLog)
}

View File

@ -9,3 +9,15 @@ type DiseaseType struct {
CreateAt int64 `xorm:"created" json:"createAt"` CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"` UpdateAt int64 `xorm:"updated" json:"updateAt"`
} }
func GetDiseaseType(name string, categoryId int) int64 {
item := new(DiseaseType)
h, err := DB.Where("type_name like ?", "%"+name+"%").
And("category_id = ?", categoryId).
And("status = 1").Get(item)
if err != nil || !h {
return 0
}
return item.TypeId
}

View File

@ -5,6 +5,7 @@ type FileManager struct {
FileName string `xorm:"VARCHAR(200)" json:"fileName"` //文件名 FileName string `xorm:"VARCHAR(200)" json:"fileName"` //文件名
AccessUrl string `xorm:"VARCHAR(400)" json:"url"` //访问路径 AccessUrl string `xorm:"VARCHAR(400)" json:"url"` //访问路径
Scene string `xorm:"VARCHAR(40)" json:"scene"` //应用场景0 : 其他, 1: 道路; 2: 桥梁; 3:隧道; 4: 边坡 Scene string `xorm:"VARCHAR(40)" json:"scene"` //应用场景0 : 其他, 1: 道路; 2: 桥梁; 3:隧道; 4: 边坡
DataType int `xorm:"TINYINT index default 0" json:"dataType"` //数据类型1:数据集;2:病害库;3:应用;0:其他
DatasetId int64 `xorm:"INT(11) index default 0" json:"datasetId"` //数据集 DatasetId int64 `xorm:"INT(11) index default 0" json:"datasetId"` //数据集
FileSize int64 `xorm:"BIGINT" json:"fileSize"` //文件大小 FileSize int64 `xorm:"BIGINT" json:"fileSize"` //文件大小
FileMd5 string `xorm:"VARCHAR(64)" json:"fileMd5"` //文件MD5 FileMd5 string `xorm:"VARCHAR(64)" json:"fileMd5"` //文件MD5

View File

@ -59,6 +59,7 @@ func New(driveName, dsn string, showSql bool) {
&SystemUser{}, &SystemUser{},
&SystemUserRole{}, &SystemUserRole{},
&Task{}, &Task{},
&TaskLog{},
&TaskResult{}, &TaskResult{},
) )
if err != nil { if err != nil {

View File

@ -3,7 +3,8 @@ package model
// NodeState 节点状态信息 // NodeState 节点状态信息
type NodeState struct { type NodeState struct {
Uptime uint64 `xorm:"BIGINT pk" json:"uptime,omitempty"` Uptime uint64 `xorm:"BIGINT pk" json:"uptime,omitempty"`
NodeName string `xorm:"varchar(100) pk" json:"nodeName"` NodeGuid string `xorm:"varchar(100) pk" json:"nodeGuid,omitempty"`
NodeName string `xorm:"varchar(100)" json:"nodeName"`
CPU float64 `xorm:"DECIMAL(18,4)" json:"cpu,omitempty"` CPU float64 `xorm:"DECIMAL(18,4)" json:"cpu,omitempty"`
MemUsed uint64 `xorm:"BIGINT" json:"memUsed,omitempty"` MemUsed uint64 `xorm:"BIGINT" json:"memUsed,omitempty"`
SwapUsed uint64 `xorm:"BIGINT" json:"swapUsed,omitempty"` SwapUsed uint64 `xorm:"BIGINT" json:"swapUsed,omitempty"`

9
model/report.go Normal file
View File

@ -0,0 +1,9 @@
package model
type Report struct {
ReportId int64 `xorm:"not null pk autoincr INT(11)" json:"reportId"`
TaskId int64 `xorm:"INT(11) index" json:"taskId"`
Status int `xorm:"TINYINT default 1" json:"status"`
CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"`
}

13
model/reportDetail.go Normal file
View File

@ -0,0 +1,13 @@
package model
type ReportDetail struct {
DetailId int64 `xorm:"not null pk autoincr INT(11)" json:"detailId"`
ReportId int64 `xorm:"INT(11) index" json:"reportId"`
FileId int64 `xorm:"INT(11) index" json:"fileId"`
FieldName string `xorm:"VARCHAR(100)" json:"fieldName"`
FieldValue string `xorm:"LONGTEXT" json:"fieldValue"`
Status int `xorm:"TINYINT default 1" json:"status"`
CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"`
DeleteAt int64 `xorm:"deleted" json:"deleteAt"`
}

View File

@ -12,6 +12,10 @@ type Task struct {
AppointmentTime string `xorm:"VARCHAR(30)" json:"appointmentTime"` AppointmentTime string `xorm:"VARCHAR(30)" json:"appointmentTime"`
StartTime int64 `xorm:"BIGINT" json:"startTime"` StartTime int64 `xorm:"BIGINT" json:"startTime"`
FinishTime int64 `xorm:"BIGINT" json:"finishTime"` FinishTime int64 `xorm:"BIGINT" json:"finishTime"`
TotalCount int64 `xorm:"INT" json:"totalCount"`
FailingCount int64 `xorm:"INT" json:"failingCount"`
CompletedCount int64 `xorm:"INT" json:"completedCount"`
UnfinishedCount int64 `xorm:"INT" json:"unfinishedCount"`
Status int `xorm:"not null SMALLINT default 0" json:"status"` // 1:等待执行; 2:执行中; 3:执行完成; 4:任务分配失败; 5:任务执行失败 Status int `xorm:"not null SMALLINT default 0" json:"status"` // 1:等待执行; 2:执行中; 3:执行完成; 4:任务分配失败; 5:任务执行失败
CreateAt int64 `xorm:"created" json:"createAt"` CreateAt int64 `xorm:"created" json:"createAt"`
UpdateAt int64 `xorm:"updated" json:"updateAt"` UpdateAt int64 `xorm:"updated" json:"updateAt"`

View File

@ -11,5 +11,6 @@ type TaskResult struct {
SubDataset string `xorm:"varchar(200)" json:"subDataset"` SubDataset string `xorm:"varchar(200)" json:"subDataset"`
DatasetId int64 `xorm:"INT(11)" json:"datasetId"` DatasetId int64 `xorm:"INT(11)" json:"datasetId"`
SrcPath string `xorm:"varchar(500)" json:"srcPath"` SrcPath string `xorm:"varchar(500)" json:"srcPath"`
Result string `xorm:"TEXT" json:"result"` Result string `xorm:"LONGTEXT" json:"result"`
FileId int64 `xorm:"BIGINT" json:"fileId"`
} }

View File

@ -1,8 +1,10 @@
package mq package mq
import ( import (
"encoding/json"
"fmt" "fmt"
"git.hpds.cc/Component/logging" "git.hpds.cc/Component/logging"
"git.hpds.cc/Component/network/frame"
"go.uber.org/zap" "go.uber.org/zap"
"hpds-iot-web/config" "hpds-iot-web/config"
"os" "os"
@ -20,6 +22,23 @@ type HpdsMqNode struct {
EndPoint interface{} EndPoint interface{}
} }
var ifChannelsMapInit = false
var ChannelsMap = map[string]chan string{}
func initChannelsMap() {
ChannelsMap = make(map[string]chan string)
}
func AddChannel(userId string) {
if !ifChannelsMapInit {
initChannelsMap()
ifChannelsMapInit = true
}
var newChannel = make(chan string)
ChannelsMap[userId] = newChannel
logging.L().Info("Build SSE connection for user = " + userId)
}
func must(logger *logging.Logger, err error) { func must(logger *logging.Logger, err error) {
if err != nil { if err != nil {
if logger != nil { if logger != nil {
@ -39,7 +58,7 @@ func NewMqClient(funcs []config.FuncConfig, node config.HpdsNode, logger *loggin
sf := hpds_node.NewStreamFunction( sf := hpds_node.NewStreamFunction(
v.Name, v.Name,
hpds_node.WithMqAddr(fmt.Sprintf("%s:%d", node.Host, node.Port)), hpds_node.WithMqAddr(fmt.Sprintf("%s:%d", node.Host, node.Port)),
hpds_node.WithObserveDataTags(v.DataTag), hpds_node.WithObserveDataTags(frame.Tag(v.DataTag)),
hpds_node.WithCredential(node.Token), hpds_node.WithCredential(node.Token),
) )
err = sf.Connect() err = sf.Connect()
@ -50,6 +69,12 @@ func NewMqClient(funcs []config.FuncConfig, node config.HpdsNode, logger *loggin
EndPoint: sf, EndPoint: sf,
} }
must(logger, err) must(logger, err)
switch v.Name {
case "task-log":
_ = sf.SetHandler(TaskLogNotificationHandler)
default:
}
mqList = append(mqList, nodeInfo) mqList = append(mqList, nodeInfo)
default: default:
ap := hpds_node.NewAccessPoint( ap := hpds_node.NewAccessPoint(
@ -65,7 +90,7 @@ func NewMqClient(funcs []config.FuncConfig, node config.HpdsNode, logger *loggin
EndPoint: ap, EndPoint: ap,
} }
must(logger, err) must(logger, err)
ap.SetDataTag(v.DataTag) ap.SetDataTag(frame.Tag(v.DataTag))
mqList = append(mqList, nodeInfo) mqList = append(mqList, nodeInfo)
} }
@ -91,3 +116,23 @@ func GenerateAndSendData(stream hpds_node.AccessPoint, data []byte, logger *logg
time.Sleep(1000 * time.Millisecond) time.Sleep(1000 * time.Millisecond)
return nil return nil
} }
func TaskLogNotificationHandler(data []byte) (frame.Tag, []byte) {
logging.L().Info("任务日志", zap.String("接收数据", string(data)))
cmd := new(InstructionReq)
err := json.Unmarshal(data, cmd)
if err != nil {
return 0x0B, []byte(err.Error())
}
str, _ := json.Marshal(cmd.Payload)
for key := range ChannelsMap {
//if strings.Contains(key, userEmail) {
// channel := channelsMap[key]
// channel <- string(msgBytes)
//}
channel := ChannelsMap[key]
channel <- string(str)
}
return 0x0B, nil
}

View File

@ -9,3 +9,35 @@ type InstructionReq struct {
Command int `json:"command"` Command int `json:"command"`
Payload interface{} `json:"payload"` Payload interface{} `json:"payload"`
} }
type ModelResult struct {
Code int `json:"code"`
}
type LightweightResult struct {
Code int `json:"code"`
Crack bool `json:"crack"`
ImgDiscern string `json:"img_discern"`
ImgSrc string `json:"img_src"`
Pothole bool `json:"pothole"`
}
type InsigmaResult struct {
Code int `json:"code"`
NumOfDiseases int `json:"num_of_diseases"`
Diseases []DiseasesInfo `json:"diseases"`
Image string `json:"image"`
}
type DiseasesInfo struct {
Id int `json:"id"`
Type string `json:"type"`
Level string `json:"level"`
Param DiseasesParam `json:"param"`
}
type DiseasesParam struct {
Length float64 `json:"length"`
Area float64 `json:"area"`
MaxWidth string `json:"max_width"`
}

131
pkg/utils/image.go Normal file
View File

@ -0,0 +1,131 @@
package utils
import (
"bytes"
"encoding/base64"
"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
"image"
"image/color"
"image/jpeg"
"image/png"
)
func BuffToImage(in []byte) image.Image {
buff := bytes.NewBuffer(in)
m, _, _ := image.Decode(buff)
return m
}
// Clip 图片裁剪
func Clip(in []byte, wi, hi int, equalProportion bool) (out image.Image, imageType string, err error) {
buff := bytes.NewBuffer(in)
m, imgType, _ := image.Decode(buff)
rgbImg := m.(*image.YCbCr)
if equalProportion {
w := m.Bounds().Max.X
h := m.Bounds().Max.Y
if w > 0 && h > 0 && wi > 0 && hi > 0 {
wi, hi = fixSize(w, h, wi, hi)
}
}
return rgbImg.SubImage(image.Rect(0, 0, wi, hi)), imgType, nil
}
func fixSize(img1W, img2H, wi, hi int) (new1W, new2W int) {
var ( //为了方便计算,将图片的宽转为 float64
imgWidth, imgHeight = float64(img1W), float64(img2H)
ratio float64
)
if imgWidth >= imgHeight {
ratio = imgWidth / float64(wi)
return int(imgWidth * ratio), int(imgHeight * ratio)
}
ratio = imgHeight / float64(hi)
return int(imgWidth * ratio), int(imgHeight * ratio)
}
func Gray(in []byte) (out image.Image, err error) {
m := BuffToImage(in)
bounds := m.Bounds()
dx := bounds.Dx()
dy := bounds.Dy()
newRgba := image.NewRGBA(bounds)
for i := 0; i < dx; i++ {
for j := 0; j < dy; j++ {
colorRgb := m.At(i, j)
_, g, _, a := colorRgb.RGBA()
gUint8 := uint8(g >> 8)
aUint8 := uint8(a >> 8)
newRgba.SetRGBA(i, j, color.RGBA{R: gUint8, G: gUint8, B: gUint8, A: aUint8})
}
}
r := image.Rect(0, 0, dx, dy)
return newRgba.SubImage(r), nil
}
func Rotate90(in []byte) image.Image {
m := BuffToImage(in)
rotate90 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
// 矩阵旋转
for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
// 设置像素点
rotate90.Set(m.Bounds().Max.Y-x, y, m.At(y, x))
}
}
return rotate90
}
// Rotate180 旋转180度
func Rotate180(in []byte) image.Image {
m := BuffToImage(in)
rotate180 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dx(), m.Bounds().Dy()))
// 矩阵旋转
for x := m.Bounds().Min.X; x < m.Bounds().Max.X; x++ {
for y := m.Bounds().Min.Y; y < m.Bounds().Max.Y; y++ {
// 设置像素点
rotate180.Set(m.Bounds().Max.X-x, m.Bounds().Max.Y-y, m.At(x, y))
}
}
return rotate180
}
// Rotate270 旋转270度
func Rotate270(in []byte) image.Image {
m := BuffToImage(in)
rotate270 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
// 矩阵旋转
for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
// 设置像素点
rotate270.Set(x, m.Bounds().Max.X-y, m.At(y, x))
}
}
return rotate270
}
func ImageToBase64(img image.Image, imgType string) string {
buff := ImageToBuff(img, imgType)
return base64.StdEncoding.EncodeToString(buff.Bytes())
}
func ImageToBuff(img image.Image, imgType string) *bytes.Buffer {
buff := bytes.NewBuffer(nil)
switch imgType {
case "bmp":
imgType = "bmp"
_ = bmp.Encode(buff, img)
case "png":
imgType = "png"
_ = png.Encode(buff, img)
case "tiff":
imgType = "tiff"
_ = tiff.Encode(buff, img, nil)
default:
imgType = "jpeg"
_ = jpeg.Encode(buff, img, nil)
}
return buff
}