Browse Source

ADD:首页数据统计

zoie 10 months ago
parent
commit
8791301874

+ 37 - 0
app/admin/controller/waybill.go

@@ -61,6 +61,37 @@ func (e WaybillController) GetPage(c *gin.Context) {
 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
 }
 
+// Home 首页统计
+// @Summary 首页统计
+// @Description 首页统计
+// @Tags 运单
+// @Param no query string false "运单号"
+// @Param pageSize query int false "页条数"
+// @Param page query int false "页码"
+// @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
+// @Router /api/waybill [get]
+// @Security Bearer
+func (e WaybillController) Home(c *gin.Context) {
+	s := service.Waybill{}
+	req := dto.WaybillStatsReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.Query).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+
+	res := s.GetBasicsStats(&req, p)
+	e.OK(res, "查询成功")
+}
+
 // GetPage 获取运单列表
 // @Summary 获取运单列表
 // @Description 获取运单列表
@@ -645,9 +676,15 @@ func (e WaybillController) Import(c *gin.Context) {
 		if indexRow == 0 {
 			continue
 		}
+		if len(row) < 10 {
+			for i := 0; i < 10-len(row); i++ {
+				row = append(row, "")
+			}
+		}
 		for i, colCell := range row {
 			fmt.Println(i, ":", colCell)
 		}
+
 		obj := dto.WaybillInsertReq{
 			Status:                  1,
 			SenderAddressName:       row[0],

+ 26 - 0
app/admin/model/sys_dept.go

@@ -3,9 +3,14 @@ package model
 import (
 	model2 "cold-logistics/common/model"
 	"errors"
+	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk"
+	"gogs.baozhida.cn/zoie/OAuth-core/sdk/config"
 	"gorm.io/gorm"
 )
 
+var GetCompanyKeyErr = errors.New("获取公司秘钥失败")
+
 type SysDept struct {
 	model2.Model
 	ParentId int    `json:"parentId" gorm:""`                        // 上级部门
@@ -14,6 +19,7 @@ type SysDept struct {
 	Sort     int    `json:"-" gorm:"size:4;"`                        // 排序
 	Status   int    `json:"-" gorm:"size:4;"`                        // 状态 1-停用 2-正常
 	Remark   string `json:"remark"  gorm:"size:1024;"`               // 备注
+	ColdKey  string `json:"coldKey"  gorm:"size:128;"`               // 冷链3.0key
 	model2.ControlBy
 	model2.ModelTime
 }
@@ -47,3 +53,23 @@ func (e *SysDept) BeforeDelete(_ *gorm.DB) (err error) {
 	}
 	return
 }
+
+func GetCompanyById(id int) (SysDept, error) {
+	var err error
+	var deptModel SysDept
+	//准备db
+	db := sdk.Runtime.GetDbByKey(config.ApplicationConfig.Host)
+	if db == nil {
+		err = errors.New("db not exist")
+		log.Errorf("host[%s]'s %s", err.Error())
+		return deptModel, err
+	}
+	err = db.First(&deptModel, id).Error
+	if err != nil {
+		log.Errorf("db error: %s", err)
+		err = errors.New("获取企业信息失败")
+		return deptModel, err
+	}
+
+	return deptModel, nil
+}

+ 14 - 13
app/admin/model/waybill.go

@@ -32,19 +32,20 @@ type Waybill struct {
 	SenderAddressDetails string `json:"senderAddressDetails"  gorm:"size:128"` //发货地址详情
 	SenderAddressName    string `json:"senderAddressName"  gorm:"size:128"`    //发货地址名称
 	SenderAddressPhone   string `json:"senderAddressPhone"  gorm:"size:128"`   //发货地址电话
-	//ConsigneeAddressId      int         `json:"consigneeAddressId"  gorm:"size:128"`      //收货地址id
-	ConsigneeAddressDetails string      `json:"consigneeAddressDetails"  gorm:"size:128"` //收发货地址详情
-	ConsigneeAddressName    string      `json:"consigneeAddressName"  gorm:"size:128"`    //收发货地址名称
-	ConsigneeAddressPhone   string      `json:"consigneeAddressPhone"  gorm:"size:128"`   //收发货地址电话
-	CargoType               string      `json:"cargoType"  gorm:"size:128"`               //货物类型
-	TemperatureInterval     string      `json:"temperatureInterval"  gorm:"size:128"`     //温度要求
-	DeliveryCondition       string      `json:"deliveryCondition"  gorm:"size:128"`       //配送要求
-	Remark                  string      `json:"remark"  gorm:"size:128"`                  //运输备注
-	CustomerId              int         `json:"customerId" gorm:"size:4"`                 //下单客户id
-	CustomerName            string      `json:"customerName" gorm:"size:128"`             //下单客户名称
-	OrderTime               model2.Time `json:"orderTime"  gorm:"size:128"`               //签收时间
-	PrintUserId             int         `json:"printUserId"  gorm:"size:128"`             //打印人id
-	ReceiptTime             model2.Time `json:"receiptTime"  gorm:"size:128"`             //签收时间
+	//ConsigneeAddressId      int         `json:"consigneeAddressId"  gorm:"size:128"`      // 收货地址id
+	ConsigneeAddressDetails string      `json:"consigneeAddressDetails"  gorm:"size:128"` // 收发货地址详情
+	ConsigneeAddressName    string      `json:"consigneeAddressName"  gorm:"size:128"`    // 收发货地址名称
+	ConsigneeAddressPhone   string      `json:"consigneeAddressPhone"  gorm:"size:128"`   // 收发货地址电话
+	CargoType               string      `json:"cargoType"  gorm:"size:128"`               // 货物类型
+	TemperatureInterval     string      `json:"temperatureInterval"  gorm:"size:128"`     // 温度要求
+	DeliveryCondition       string      `json:"deliveryCondition"  gorm:"size:128"`       // 配送要求
+	Remark                  string      `json:"remark"  gorm:"size:128"`                  // 运输备注
+	CustomerId              int         `json:"customerId" gorm:"size:4"`                 // 下单客户id
+	CustomerName            string      `json:"customerName" gorm:"size:128"`             // 下单客户名称
+	OrderTime               model2.Time `json:"orderTime"  gorm:"size:128"`               // 下单时间
+	DeliveryTime            model2.Time `json:"deliveryTime"  gorm:"size:128"`            // 发货时间 入库/装车时间
+	PrintUserId             int         `json:"printUserId"  gorm:"size:128"`             // 打印人id
+	ReceiptTime             model2.Time `json:"receiptTime"  gorm:"size:128"`             // 签收时间
 	WarehouseId             int         `json:"warehouseId"  gorm:"size:128"`             // 仓库id
 	CarId                   int         `json:"carId"  gorm:"size:128"`                   // 仓库id
 	ReceiptImg              string      `json:"ReceiptImg"  gorm:"size:128"`              // 签收图片

+ 13 - 1
app/admin/model/waybill_logistics.go

@@ -1,6 +1,10 @@
 package model
 
-import model2 "cold-logistics/common/model"
+import (
+	amap "cold-logistics/common/amap"
+	model2 "cold-logistics/common/model"
+	"gorm.io/gorm"
+)
 
 // 运单物流
 type WaybillLogistics struct {
@@ -12,6 +16,7 @@ type WaybillLogistics struct {
 	UserId      int           `json:"userId"  gorm:"size:128"`      // 司机/仓管id
 	Lng         string        `json:"lng" gorm:"size:128;"`         // 经度
 	Lat         string        `json:"lat" gorm:"size:128;"`         // 纬度
+	Address     string        `json:"address" gorm:"size:128;"`     // 地址
 	Warehouse   WarehouseOmit `json:"warehouse" gorm:"->;foreignkey:WarehouseId;references:Id"`
 	Car         CarOmit       `json:"car" gorm:"->;foreignkey:CarId;references:Id"`
 	model2.ControlBy
@@ -22,3 +27,10 @@ type WaybillLogistics struct {
 func (WaybillLogistics) TableName() string {
 	return "waybill_logistics"
 }
+
+func (u *WaybillLogistics) BeforeCreate(tx *gorm.DB) (err error) {
+	address := amap.GeocodeRegeo(u.Lng, u.Lat)
+	ac := address.Regeocode.AddressComponent
+	u.Address = ac.City + ac.District
+	return
+}

+ 1 - 0
app/admin/router/waybill.go

@@ -34,5 +34,6 @@ func registerWaybillRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
 		r.GET("/applet", cont.GetAppletPage)           // app 运单列表
 		r.POST("/import", cont.Import)                 // 导入运单
 		r.GET("/export-template", cont.ExportTemplate) // 导出运单模板
+		r.GET("/home", cont.Home)                      // 首页统计
 	}
 }

+ 13 - 1
app/admin/service/car.go

@@ -15,6 +15,16 @@ type Car struct {
 	service.Service
 }
 
+func CarIsBindUserScopes(isBind bool) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		// 未发货
+		if isBind {
+			return db.Where("user_id > 0")
+		}
+		return db
+	}
+}
+
 // GetPage 获取Car列表
 func (e *Car) GetPage(c *dto.CarGetPageReq, list *[]model.Car, count *int64, p *actions.DataPermission) error {
 	var err error
@@ -25,8 +35,10 @@ func (e *Car) GetPage(c *dto.CarGetPageReq, list *[]model.Car, count *int64, p *
 			cDto.MakeCondition(c.GetNeedSearch()),
 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
 			actions.Permission(data.TableName(), p),
+			CarIsBindUserScopes(c.IsBind),
 		).
-		Preload("User").
+		Joins("User").
+		Where("car_no like ? or User.nick_name like ?", "%"+c.Name+"%", "%"+c.Name+"%").
 		Find(list).Limit(-1).Offset(-1).
 		Count(count).Error
 	if err != nil {

+ 6 - 1
app/admin/service/device.go

@@ -41,7 +41,12 @@ func (e *Device) GetSensorList(p *actions.DataPermission) (list []nats_server.De
 		return list, count, nil
 	}
 
-	list, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(sn)
+	company, err := model.GetCompanyById(p.DeptId)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return list, count, model.GetCompanyKeyErr
+	}
+	list, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(sn, company.ColdKey)
 	if err != nil {
 		e.Log.Errorf("db error: %s", err)
 		return list, count, err

+ 3 - 2
app/admin/service/dto/car.go

@@ -8,8 +8,9 @@ import (
 
 type CarGetPageReq struct {
 	dto.Pagination `search:"-"`
-	CarNo          string `form:"carNo" search:"type:contains;column:car_no;table:car"` // 车牌号
-	Sn             string `form:"sn" search:"type:contains;column:sn;table:car"`        // sn
+	Name           string `form:"name" search:"-"`                               // 车牌号
+	Sn             string `form:"sn" search:"type:contains;column:sn;table:car"` // sn
+	IsBind         bool   `form:"isBind" search:"-"`                             // 是否绑定司机
 	CarOrder
 }
 

+ 7 - 3
app/admin/service/dto/company.go

@@ -31,9 +31,10 @@ func (m *CompanyGetAllReq) GetNeedSearch() interface{} {
 }
 
 type CompanyInsertReq struct {
-	Id     int    `json:"id" swaggerignore:"true"`
-	Name   string `json:"name" example:"名称" vd:"len($)>0;msg:'公司名称不能为空'"` //名称
-	Remark string `json:"remark"`                                         // 备注
+	Id      int    `json:"id" swaggerignore:"true"`
+	Name    string `json:"name" example:"名称" vd:"len($)>0;msg:'公司名称不能为空'"` //名称
+	Remark  string `json:"remark"`                                         // 备注
+	ColdKey string `json:"coldKey"`                                        // 冷链3.0key
 
 	common.ControlBy `swaggerignore:"true"`
 }
@@ -45,6 +46,7 @@ func (s *CompanyInsertReq) Generate(model *model.SysDept) {
 	model.Name = s.Name
 	model.ParentId = 0
 	model.Remark = s.Remark
+	model.ColdKey = s.ColdKey
 }
 
 // GetId 获取数据对应的ID
@@ -56,6 +58,7 @@ type CompanyUpdateReq struct {
 	Id               int    `json:"id" comment:"编码"`   // 编码
 	Name             string `json:"name" example:"名称"` //名称
 	Remark           string `json:"remark"`            // 备注
+	ColdKey          string `json:"coldKey"`           // 冷链3.0key
 	common.ControlBy `swaggerignore:"true"`
 }
 
@@ -66,6 +69,7 @@ func (s *CompanyUpdateReq) Generate(model *model.SysDept) {
 	}
 	model.Name = s.Name
 	model.Remark = s.Remark
+	model.ColdKey = s.ColdKey
 }
 
 // GetId 获取数据对应的ID

+ 4 - 2
app/admin/service/dto/warehouse.go

@@ -8,8 +8,10 @@ import (
 
 type WarehouseGetPageReq struct {
 	dto.Pagination `search:"-"`
-	Name           string `form:"name" search:"type:contains;column:name;table:warehouse"` // 仓库名称
-	Sn             string `form:"sn" search:"type:contains;column:sn;table:warehouse"`     // sn
+	//Name           string `form:"name" search:"type:contains;column:name;table:warehouse"` // 仓库名称
+	Name   string `form:"name" search:"-"`                                     // 仓库名称
+	Sn     string `form:"sn" search:"type:contains;column:sn;table:warehouse"` // sn
+	IsBind bool   `form:"isBind" search:"-"`                                   // 是否绑定司机
 	WarehouseOrder
 }
 

+ 21 - 0
app/admin/service/dto/waybill.go

@@ -196,3 +196,24 @@ func (m *WaybillGetAppletPageReq) GetNeedSearch() interface{} {
 type WaybillImportReq struct {
 	CustomerName string `form:"customerName"` //下单客户名称
 }
+
+type WaybillStatsReq struct {
+	Date string `form:"date"` // 日期
+	Type string `form:"type"` // 类型 month-月 year-年
+}
+
+type WaybillStatsRes struct {
+	TodayNum       int64 `json:"todayNum"`       // 今日总运单数
+	WaitTruckNum   int64 `json:"waitTruckNum"`   // 未装车
+	WaitStorageNum int64 `json:"waitStorageNum"` // 未入库
+	InDeliveryNum  int64 `json:"inDeliveryNum"`  // 运送中
+	ThisMonthNum   int64 `json:"thisMonthNum"`   // 本月运单数
+	LastMonthNum   int64 `json:"lastMonthNum"`   // 上月运单数
+	ThisYearNum    int64 `json:"thisYearNum"`    // 本年运单数
+	LastYearNum    int64 `json:"lastYearNum"`    // 上年运单数
+
+	Stats []struct {
+		Date string `json:"date"` // 日期 2024-01-01
+		Num  int64  `json:"num"`  // 数量
+	} `json:"stats"`
+}

+ 13 - 2
app/admin/service/warehouse.go

@@ -15,18 +15,29 @@ type Warehouse struct {
 	service.Service
 }
 
+func WarehouseIsBindUserScopes(isBind bool) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		// 未发货
+		if isBind {
+			return db.Where("user_id > 0")
+		}
+		return db
+	}
+}
+
 // GetPage 获取Warehouse列表
 func (e *Warehouse) GetPage(c *dto.WarehouseGetPageReq, list *[]model.Warehouse, count *int64, p *actions.DataPermission) error {
 	var err error
 	var data model.Warehouse
-
 	err = e.Orm.Model(&data).
 		Scopes(
 			cDto.MakeCondition(c.GetNeedSearch()),
 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
 			actions.Permission(data.TableName(), p),
+			WarehouseIsBindUserScopes(c.IsBind),
 		).
-		Preload("User").
+		Joins("User").
+		Where("name like ? or User.nick_name like ?", "%"+c.Name+"%", "%"+c.Name+"%").
 		Find(list).Limit(-1).Offset(-1).
 		Count(count).Error
 	if err != nil {

+ 152 - 81
app/admin/service/waybill.go

@@ -13,6 +13,7 @@ import (
 	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
 	"gogs.baozhida.cn/zoie/OAuth-core/service"
 	"gorm.io/gorm"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -503,24 +504,13 @@ func (e *Waybill) WarehouseIn(c *dto.WaybillInOutReq, p *actions.DataPermission)
 			e.Log.Errorf("db error: %s", err)
 			return errors.New(fmt.Sprintf("保存运单信息失败:%s", err))
 		}
-		// 获取传感器信息
-		// 获取传感器信息
-		var deviceSensorList = []nats_server.DeviceSensor_R{}
-		var count int64
-		deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(warehouse.Sn)
-		if err != nil || count == 0 {
-			err = errors.New("查询设备定位信息失败")
+
+		var lng, lat string
+		lng, lat, err = e.GetSite(p.DeptId, warehouse.Sn, c.StartTime.String())
+		if err != nil {
+			e.Log.Errorf("获取定位信息失败: %s", err)
 			return err
 		}
-		var lng, Lat string
-		if len(deviceSensorList[0].T_DeviceSensorData.T_site) > 0 {
-			site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
-			if len(site) == 2 {
-				lng = site[0]
-				Lat = site[1]
-			}
-		}
-
 		// 添加物流
 		Logistics := model.WaybillLogistics{
 			WaybillNo:   waybillNo,
@@ -528,7 +518,7 @@ func (e *Waybill) WarehouseIn(c *dto.WaybillInOutReq, p *actions.DataPermission)
 			WarehouseId: warehouse.Id,
 			UserId:      p.UserId,
 			Lng:         lng,
-			Lat:         Lat,
+			Lat:         lat,
 			ControlBy: model2.ControlBy{
 				CreateBy: p.UserId,
 			},
@@ -615,6 +605,9 @@ func (e *Waybill) WarehouseOut(c *dto.WaybillInOutReq, p *actions.DataPermission
 			err = errors.New(fmt.Sprintf("运单号%s状态为%s,无法出库!", waybillNo, model.WaybillStatusMap[waybillModel.Status]))
 			return err
 		}
+		if waybillModel.Status == model.WaybillStatusWaitStorage {
+			waybillModel.DeliveryTime = c.StartTime
+		}
 		waybillModel.Status = model.WaybillStatusStorageOut
 		waybillModel.WarehouseId = warehouse.Id
 		err = tx.Save(&waybillModel).Error
@@ -622,22 +615,13 @@ func (e *Waybill) WarehouseOut(c *dto.WaybillInOutReq, p *actions.DataPermission
 			e.Log.Errorf("db error: %s", err)
 			return errors.New(fmt.Sprintf("保存运单信息失败:%s", err))
 		}
-		// 获取传感器信息
-		var deviceSensorList = []nats_server.DeviceSensor_R{}
-		var count int64
-		deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(warehouse.Sn)
-		if err != nil || count == 0 {
-			err = errors.New("查询设备定位信息失败")
+
+		var lng, lat string
+		lng, lat, err = e.GetSite(p.DeptId, warehouse.Sn, c.StartTime.String())
+		if err != nil {
+			e.Log.Errorf("获取定位信息失败: %s", err)
 			return err
 		}
-		var lng, Lat string
-		if len(deviceSensorList[0].T_DeviceSensorData.T_site) > 0 {
-			site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
-			if len(site) == 2 {
-				lng = site[0]
-				Lat = site[1]
-			}
-		}
 
 		// 添加物流
 		Logistics := model.WaybillLogistics{
@@ -646,7 +630,7 @@ func (e *Waybill) WarehouseOut(c *dto.WaybillInOutReq, p *actions.DataPermission
 			WarehouseId: warehouse.Id,
 			UserId:      p.UserId,
 			Lng:         lng,
-			Lat:         Lat,
+			Lat:         lat,
 			ControlBy: model2.ControlBy{
 				CreateBy: p.UserId,
 			},
@@ -701,7 +685,7 @@ func (e *Waybill) CarIn(c *dto.WaybillInOutReq, p *actions.DataPermission) error
 		First(&car).Error
 	if err != nil {
 		e.Log.Errorf("db error: %s", err)
-		return errors.New("获取车辆信息失败")
+		return errors.New("获取车辆绑定信息失败")
 	}
 
 	for _, waybillNo := range c.WaybillNoList {
@@ -724,29 +708,24 @@ func (e *Waybill) CarIn(c *dto.WaybillInOutReq, p *actions.DataPermission) error
 			err = errors.New(fmt.Sprintf("运单号%s状态为%s,无法装车!", waybillNo, model.WaybillStatusMap[waybillModel.Status]))
 			return err
 		}
+		if waybillModel.Status == model.WaybillStatusWaitTruck {
+			waybillModel.DeliveryTime = c.StartTime
+		}
 		waybillModel.Status = model.WaybillStatusTruck
 		waybillModel.CarId = car.Id
+
 		err = tx.Save(&waybillModel).Error
 		if err != nil {
 			e.Log.Errorf("db error: %s", err)
 			return errors.New(fmt.Sprintf("保存运单信息失败:%s", err))
 		}
-		// 获取传感器信息
-		var deviceSensorList = []nats_server.DeviceSensor_R{}
-		var count int64
-		deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(car.Sn)
-		if err != nil || count == 0 {
-			err = errors.New("查询设备定位信息失败")
+
+		var lng, lat string
+		lng, lat, err = e.GetSite(p.DeptId, car.Sn, c.StartTime.String())
+		if err != nil {
+			e.Log.Errorf("获取定位信息失败: %s", err)
 			return err
 		}
-		var lng, Lat string
-		if len(deviceSensorList[0].T_DeviceSensorData.T_site) > 0 {
-			site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
-			if len(site) == 2 {
-				lng = site[0]
-				Lat = site[1]
-			}
-		}
 
 		// 添加物流
 		Logistics := model.WaybillLogistics{
@@ -755,7 +734,7 @@ func (e *Waybill) CarIn(c *dto.WaybillInOutReq, p *actions.DataPermission) error
 			CarId:     car.Id,
 			UserId:    p.UserId,
 			Lng:       lng,
-			Lat:       Lat,
+			Lat:       lat,
 			ControlBy: model2.ControlBy{
 				CreateBy: p.UserId,
 			},
@@ -814,7 +793,7 @@ func (e *Waybill) CarOut(c *dto.WaybillInOutReq, p *actions.DataPermission) erro
 		First(&car).Error
 	if err != nil {
 		e.Log.Errorf("db error: %s", err)
-		return errors.New("获取车辆信息失败")
+		return errors.New("获取车辆绑定信息失败")
 	}
 
 	for _, waybillNo := range c.WaybillNoList {
@@ -849,22 +828,13 @@ func (e *Waybill) CarOut(c *dto.WaybillInOutReq, p *actions.DataPermission) erro
 			e.Log.Errorf("db error: %s", err)
 			return errors.New(fmt.Sprintf("保存运单信息失败:%s", err))
 		}
-		// 获取传感器信息
-		var deviceSensorList = []nats_server.DeviceSensor_R{}
-		var count int64
-		deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(car.Sn)
-		if err != nil || count == 0 {
-			err = errors.New("查询设备定位信息失败")
+
+		var lng, lat string
+		lng, lat, err = e.GetSite(p.DeptId, car.Sn, c.StartTime.String())
+		if err != nil {
+			e.Log.Errorf("获取定位信息失败: %s", err)
 			return err
 		}
-		var lng, Lat string
-		if len(deviceSensorList[0].T_DeviceSensorData.T_site) > 0 {
-			site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
-			if len(site) == 2 {
-				lng = site[0]
-				Lat = site[1]
-			}
-		}
 
 		// 添加物流
 		Logistics := model.WaybillLogistics{
@@ -873,7 +843,7 @@ func (e *Waybill) CarOut(c *dto.WaybillInOutReq, p *actions.DataPermission) erro
 			CarId:     car.Id,
 			UserId:    p.UserId,
 			Lng:       lng,
-			Lat:       Lat,
+			Lat:       lat,
 			ControlBy: model2.ControlBy{
 				CreateBy: p.UserId,
 			},
@@ -956,23 +926,13 @@ func (e *Waybill) Receipt(c *dto.WaybillReceiptReq, p *actions.DataPermission) e
 		e.Log.Errorf("db error: %s", err)
 		return errors.New(fmt.Sprintf("保存运单信息失败:%s", err))
 	}
-	// 获取传感器信息
-	// 获取传感器信息
-	var deviceSensorList = []nats_server.DeviceSensor_R{}
-	var count int64
-	deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(car.Sn)
-	if err != nil || count == 0 {
-		err = errors.New("查询设备定位信息失败")
+
+	var lng, lat string
+	lng, lat, err = e.GetSite(p.DeptId, car.Sn, c.StartTime.String())
+	if err != nil {
+		e.Log.Errorf("获取定位信息失败: %s", err)
 		return err
 	}
-	var lng, Lat string
-	if len(deviceSensorList[0].T_DeviceSensorData.T_site) > 0 {
-		site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
-		if len(site) == 2 {
-			lng = site[0]
-			Lat = site[1]
-		}
-	}
 
 	// 查询任务
 	var task model.WaybillTask
@@ -998,7 +958,7 @@ func (e *Waybill) Receipt(c *dto.WaybillReceiptReq, p *actions.DataPermission) e
 			CarId:     car.Id,
 			UserId:    p.UserId,
 			Lng:       lng,
-			Lat:       Lat,
+			Lat:       lat,
 			ControlBy: model2.ControlBy{
 				CreateBy: p.UserId,
 			},
@@ -1023,7 +983,7 @@ func (e *Waybill) Receipt(c *dto.WaybillReceiptReq, p *actions.DataPermission) e
 		CarId:     car.Id,
 		UserId:    p.UserId,
 		Lng:       lng,
-		Lat:       Lat,
+		Lat:       lat,
 		ControlBy: model2.ControlBy{
 			CreateBy: p.UserId,
 		},
@@ -1042,3 +1002,114 @@ func (e *Waybill) Receipt(c *dto.WaybillReceiptReq, p *actions.DataPermission) e
 
 	return nil
 }
+
+// 获取入库 出库 上车 下车 定位信息
+func (e *Waybill) GetSite(companyId int, sn string, time string) (lng, lat string, err error) {
+	// 获取公司秘钥
+	var company model.SysDept
+	company, err = model.GetCompanyById(companyId)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return lng, lat, model.GetCompanyKeyErr
+	}
+	// 获取传感器信息
+	var deviceSensorList = []nats_server.DeviceSensor_R{}
+	var count int64
+	deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(sn, company.ColdKey)
+	if err != nil || count == 0 {
+		err = errors.New("查询设备定位信息失败")
+		return lng, lat, err
+	}
+	var deviceData nats_server.DeviceData_
+	deviceData, err = nats_server.Cold_ReadDeviceDataBy_T_snid_T_time(deviceSensorList[0].T_sn, deviceSensorList[0].T_id, time)
+	if err != nil {
+		err = errors.New("查询设备定位信息失败")
+		return lng, lat, err
+	}
+	if len(deviceData.T_site) > 0 {
+		site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
+		if len(site) == 2 {
+			lng = site[0]
+			lat = site[1]
+		}
+	}
+	return lng, lat, nil
+}
+
+// 获取今日运单数 未派单 未装车 未入库 运送中
+// 本月运单总数 上月运单总数 本年运单总数 上年运单总数
+func (e *Waybill) GetBasicsStats(c *dto.WaybillStatsReq, p *actions.DataPermission) dto.WaybillStatsRes {
+	var res dto.WaybillStatsRes
+	var data model.Waybill
+	type DateCount struct {
+		Date  string
+		Count int64
+	}
+	yearCount := make([]DateCount, 0)
+	monthCount := make([]DateCount, 0)
+	now := time.Now()
+	todayStartTime := now.Format("2006-01-02") + " 00:00:00"
+	todayEndTime := now.Format("2006-01-02") + " 23:59:59"
+
+	// 获取上个月第一天
+	firstDayOfLastMonth := time.Date(now.Year(), now.Month()-1, 1, 0, 0, 0, 0, now.Location())
+
+	// 获取去年的第一天
+	firstDayOfLastYear := time.Date(now.Year()-1, time.January, 1, 0, 0, 0, 0, now.Location())
+	monthStartTime := firstDayOfLastMonth.Format("2006-01-02") + " 00:00:00"
+	yearStartTime := firstDayOfLastYear.Format("2006-01-02") + " 00:00:00"
+
+	// 今日总运单数
+	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("order_time between ? and ?", todayStartTime, todayEndTime).Count(&res.TodayNum)
+	// 未装车
+	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusWaitTruck).Count(&res.WaitTruckNum)
+	// 未入库
+	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusWaitStorage).Count(&res.WaitStorageNum)
+	// 获取本月,上月数据
+	e.Orm.Model(&data).Select("date_format(order_time,'%Y%m') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p)).
+		Where("order_time between ? and ?", monthStartTime, now).Group("date").Find(&monthCount)
+
+	for _, month := range monthCount {
+		if month.Date == now.Format("200601") {
+			res.ThisMonthNum = month.Count
+		}
+		if month.Date == firstDayOfLastMonth.Format("200601") {
+			res.LastMonthNum = month.Count
+		}
+	}
+
+	// 获取本年,上年数据
+	e.Orm.Model(&data).Select("date_format(order_time,'%Y') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p)).
+		Where("order_time between ? and ?", yearStartTime, now).Group("date").Find(&yearCount)
+
+	for _, month := range yearCount {
+		if month.Date == now.Format("2006") {
+			res.ThisYearNum = month.Count
+		}
+		if month.Date == firstDayOfLastYear.Format("2006") {
+			res.LastYearNum = month.Count
+		}
+	}
+
+	if c.Type == "year" {
+		// 获取上个月第一天
+		year, _ := strconv.Atoi(c.Date)
+		firstDayOfyear := time.Date(year, 1, 1, 0, 0, 0, 0, now.Location())
+		lastDayOfyear := time.Date(year, 12, 31, 23, 59, 59, 0, now.Location())
+
+		// 年度数据统计
+		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p)).
+			Where("order_time between ? and ?", firstDayOfyear, lastDayOfyear).Group("date").Find(&res.Stats)
+	}
+
+	if c.Type == "month" {
+		// 获取上个月第一天
+		month, _ := time.Parse("2006-01", c.Date)
+		firstDayOfMonth := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, now.Location())
+		lastDayOfMonth := time.Date(month.Year(), month.Month()+1, 1, 23, 59, 59, 0, now.Location()).Add(-time.Hour * 24)
+		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m-%d') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p)).
+			Where("order_time between ? and ?", firstDayOfMonth, lastDayOfMonth).Group("date").Find(&res.Stats)
+	}
+
+	return res
+}

+ 29 - 2
app/admin/service/waybill_task.go

@@ -32,6 +32,12 @@ func WaybillTaskTimeScopes(startTime, endTime string) func(db *gorm.DB) *gorm.DB
 func (e *WaybillTask) GetPage(c *dto.WaybillTaskGetPageReq, list *[]model.WaybillTask, count *int64) error {
 	var err error
 	var data model.WaybillTask
+	var waybill model.Waybill
+	err = e.Orm.Model(&waybill).Where("waybill_no = ?", c.WaybillNo).First(&waybill).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return errors.New("获取运单信息失败")
+	}
 
 	err = e.Orm.Model(&data).
 		Scopes(
@@ -44,9 +50,16 @@ func (e *WaybillTask) GetPage(c *dto.WaybillTaskGetPageReq, list *[]model.Waybil
 		e.Log.Errorf("db error: %s", err)
 		return global.GetFailedErr
 	}
+	// 获取公司秘钥
+	var company model.SysDept
+	company, err = model.GetCompanyById(waybill.DeptId)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return model.GetCompanyKeyErr
+	}
 	for i := 0; i < len(*list); i++ {
 		// 获取传感器信息
-		deviceSensorList, _, _ := nats_server.Cold_CompanyDeviceSensor_List_ByKey((*list)[i].Sn)
+		deviceSensorList, _, _ := nats_server.Cold_CompanyDeviceSensor_List_ByKey((*list)[i].Sn, company.ColdKey)
 		(*list)[i].DeviceSensorList = deviceSensorList
 	}
 	return nil
@@ -100,9 +113,23 @@ func (e *WaybillTask) GetDataPage(c *dto.WaybillTaskGetDataPageReq) (list []nats
 func (e *WaybillTask) GetLocus(c *dto.WaybillGetLocusReq) ([]nats_server.DeviceData_R2, error) {
 	var err error
 	var data model.WaybillTask
+	var waybill model.Waybill
 	var taskList []model.WaybillTask
 	locusList := make([]nats_server.DeviceData_R2, 0)
 
+	err = e.Orm.Model(&waybill).Where("waybill_no = ?", c.WaybillNo).First(&waybill).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return locusList, errors.New("获取运单信息失败")
+	}
+	// 获取公司秘钥
+	var company model.SysDept
+	company, err = model.GetCompanyById(waybill.DeptId)
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return locusList, model.GetCompanyKeyErr
+	}
+
 	err = e.Orm.Model(&data).
 		Scopes(
 			cDto.MakeCondition(c.GetNeedSearch()),
@@ -115,7 +142,7 @@ func (e *WaybillTask) GetLocus(c *dto.WaybillGetLocusReq) ([]nats_server.DeviceD
 
 	for i := 0; i < len(taskList); i++ {
 		// 获取传感器信息
-		deviceSensorList, _, _ := nats_server.Cold_CompanyDeviceSensor_List_ByKey(taskList[i].Sn)
+		deviceSensorList, _, _ := nats_server.Cold_CompanyDeviceSensor_List_ByKey(taskList[i].Sn, company.ColdKey)
 		if len(deviceSensorList) > 0 {
 			T_snid := fmt.Sprintf("%s,%d|", taskList[i].Sn, deviceSensorList[0].T_id)
 			dataList, _, err := nats_server.Cold_ReadDeviceDataListBy_T_snidForLocus(T_snid, taskList[i].StartTime.String(), taskList[i].EndTime.String(), 0, 9999)

+ 75 - 0
common/amap/amap.go

@@ -0,0 +1,75 @@
+package amap
+
+import (
+	"cold-logistics/conf"
+	"encoding/json"
+	"fmt"
+	"github.com/go-resty/resty/v2"
+	"strconv"
+)
+
+type Address struct {
+	Status    string    `json:"status"`
+	Regeocode Regeocode `json:"regeocode"`
+	Info      string    `json:"info"`
+	Infocode  string    `json:"infocode"`
+}
+
+type Regeocode struct {
+	AddressComponent AddressComponent `json:"addressComponent"`
+	FormattedAddress string           `json:"formatted_address"`
+}
+
+type AddressComponent struct {
+	City         string       `json:"city"`
+	Province     string       `json:"province"`
+	Adcode       string       `json:"adcode"`
+	District     string       `json:"district"`
+	Township     string       `json:"township"`
+	StreetNumber StreetNumber `json:"streetNumber"`
+	Country      string       `json:"country"`
+	Citycode     string       `json:"citycode"`
+}
+
+type StreetNumber struct {
+	Number    string `json:"number"`
+	Location  string `json:"location"`
+	Direction string `json:"direction"`
+	Distance  string `json:"distance"`
+	Street    string `json:"street"`
+}
+
+// 高德-逆地址解析
+func GeocodeRegeo(lng, lat string) (address Address) {
+	if len(lng) == 0 || len(lat) == 0 {
+		return
+	}
+
+	lngFloat64, err := strconv.ParseFloat(lng, 64)
+	if err != nil {
+		return
+	}
+	lngStr := fmt.Sprintf("%.6f", lngFloat64)
+
+	latFloat64, err := strconv.ParseFloat(lat, 64)
+	if err != nil {
+		return
+	}
+	latStr := fmt.Sprintf("%.6f", latFloat64)
+
+	client := resty.New()
+
+	resp, err := client.R().SetQueryParams(map[string]string{
+		"key":      conf.ExtConfig.Amap.Key,
+		"location": lngStr + "," + latStr,
+	}).Get("https://restapi.amap.com/v3/geocode/regeo")
+
+	if err != nil {
+		return
+	}
+	err = json.Unmarshal(resp.Body(), &address)
+	if err != nil {
+		return
+	}
+	return address
+}

+ 54 - 4
common/nats/nats_server/NatsColdApi.go

@@ -2,13 +2,13 @@ package nats_server
 
 import (
 	"cold-logistics/common/nats"
-	"cold-logistics/conf"
 	"errors"
 	"github.com/vmihailenco/msgpack/v5"
+	"sort"
 	"time"
 )
 
-func Cold_CompanyDeviceSensor_List_ByKey(T_sn string) (data []DeviceSensor_R, count int64, err error) {
+func Cold_CompanyDeviceSensor_List_ByKey(T_sn, T_key string) (data []DeviceSensor_R, count int64, err error) {
 
 	type T_Req struct {
 		T_sn  string `xml:"T_sn"`
@@ -16,7 +16,7 @@ func Cold_CompanyDeviceSensor_List_ByKey(T_sn string) (data []DeviceSensor_R, co
 	}
 	t_Req := T_Req{
 		T_sn:  T_sn,
-		T_key: conf.ExtConfig.Nats.Key,
+		T_key: T_key,
 	}
 	b, _ := msgpack.Marshal(&t_Req)
 
@@ -39,6 +39,7 @@ func Cold_CompanyDeviceSensor_List_ByKey(T_sn string) (data []DeviceSensor_R, co
 	}
 	if t_R.Code != 200 {
 		err = errors.New(t_R.Msg)
+		return
 	}
 
 	return t_R.Data, t_R.Count, nil
@@ -80,10 +81,58 @@ func Cold_ReadDeviceDataListBy_T_snid(T_snid, startTime, endTime string, page, p
 	}
 	if t_R.Code != 200 {
 		err = errors.New(t_R.Msg)
+		return
 	}
+	list := t_R.Data
+	sort.Slice(list, func(i, j int) bool {
+		// 先按 T_time 字段排序,如果 T_time 相同则按 T_id 字段排序
+		if list[i].T_time == list[j].T_time {
+			return list[i].T_id < list[j].T_id
+		}
+		return list[i].T_time > list[j].T_time
+	})
 
-	return t_R.Data, t_R.Count, nil
+	return list, t_R.Count, nil
+}
+func Cold_ReadDeviceDataBy_T_snid_T_time(T_sn string, T_id int, Time string) (data DeviceData_, err error) {
+
+	type T_Req struct {
+		T_sn string `xml:"T_sn"`
+		T_id int    `xml:"T_id"`
+		Time string `xml:"Time"`
+	}
+	t_Req := T_Req{
+		T_sn: T_sn,
+		T_id: T_id,
+		Time: Time,
+	}
+	b, _ := msgpack.Marshal(&t_Req)
+
+	msg, err := nats.Nats.Request("Cold_ReadDeviceDataBy_T_snid_T_time", b, 3*time.Second)
+	if err != nil {
+		return
+	}
+
+	type T_R struct {
+		Code int16       `xml:"Code"`
+		Msg  string      `xml:"Msg"`
+		Data DeviceData_ `xml:"Data"` // 泛型
+	}
+	var t_R T_R
+
+	err = msgpack.Unmarshal(msg.Data, &t_R)
+	if err != nil {
+		return
+	}
+	if t_R.Code != 200 {
+		err = errors.New(t_R.Msg)
+		return
+	}
+
+	return t_R.Data, nil
 }
+
+// 查询轨迹信息
 func Cold_ReadDeviceDataListBy_T_snidForLocus(T_snid, startTime, endTime string, page, page_z int) (data []DeviceData_R2, count int64, err error) {
 
 	type T_Req struct {
@@ -121,6 +170,7 @@ func Cold_ReadDeviceDataListBy_T_snidForLocus(T_snid, startTime, endTime string,
 	}
 	if t_R.Code != 200 {
 		err = errors.New(t_R.Msg)
+		return
 	}
 
 	return t_R.Data, t_R.Count, nil

+ 8 - 0
common/nats/nats_server/models.go

@@ -61,6 +61,14 @@ type DeviceData_R2 struct {
 	T_site string  // GPS
 	T_time string  // 采集时间
 }
+type DeviceData_ struct {
+	T_id   int       // 传感器id
+	T_sp   int       // 传感器参数id
+	T_t    float32   // 温度
+	T_rh   float32   // 湿度
+	T_site string    // GPS
+	T_time time.Time // 采集时间
+}
 
 type DeviceData_R struct {
 	T_sn   string  // sn

+ 4 - 0
conf/extend.go

@@ -14,6 +14,7 @@ type Extend struct {
 	Qiniu   Qiniu   `yaml:"qiniu"`
 	Applet  Applet  `yaml:"applet"`
 	Nats    Nats    `yaml:"nats"`
+	Amap    Amap    `yaml:"amap"`
 }
 
 type SubMail struct {
@@ -40,3 +41,6 @@ type Nats struct {
 	Url string `json:"url"`
 	Key string `json:"key"`
 }
+type Amap struct {
+	Key string `json:"key"`
+}