Browse Source

修改公司,查询保温箱所有使用记录,保温箱使用冰排记录,订单转门店

huangyan 1 week ago
parent
commit
b3de26b82d

+ 234 - 0
app/admin/controller/cooler_box.go

@@ -5,11 +5,16 @@ import (
 	"cold-delivery/app/admin/service"
 	"cold-delivery/app/admin/service/dto"
 	"cold-delivery/common/actions"
+	"cold-delivery/common/nats/nats_server"
+	"encoding/json"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin/binding"
 	"gogs.baozhida.cn/zoie/OAuth-core/api"
 	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
 	_ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
+	"sort"
+	"time"
 )
 
 type CoolerBoxController struct {
@@ -232,3 +237,232 @@ func (e CoolerBoxController) BatchInsert(c *gin.Context) {
 	}
 	e.OK(nil, "添加成功")
 }
+
+// GetCollerBoxLocus 获取保温箱历史
+// @Summary 获取保温箱历史轨迹
+// @Description 获取保温箱历史
+// @Tags 保温箱
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.CoolerBoxBatchInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/cooler-box/locus [get]
+// @Security Bearer
+func (e CoolerBoxController) GetCollerBoxLocus(c *gin.Context) {
+	s := service.CoolerBox{}
+	req := dto.CoolerBoxBatchReqSN{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	p := actions.GetPermissionFromContext(c)
+	history, err := s.GetHistory(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	count := req.PageZ / req.Page
+	e.PageOK(history, int(count), req.Page, req.PageZ, "查询成功")
+}
+
+// GetCoolerBoxLocus 获取保温箱历史轨迹
+// @Summary 获取保温箱历史轨迹
+// @Description 获取保温箱历史轨迹
+// @Tags 保温箱
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.CoolerBoxBatchInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/cooler-box/historylocus [post]
+// @Security Bearer
+func (e CoolerBoxController) GetCoolerBoxLocus(c *gin.Context) {
+	s := service.CoolerBox{}
+	req := dto.CoolerBoxBatchReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	data, _, err := nats_server.Cold_ReadDeviceDataListBy_T_snidForLocus(req.SnId+","+req.T_id, req.StartTime, req.EndTime, req.Page, req.PageZ)
+	if err != nil {
+		e.Logger.Error("nats 获取轨迹信息失败:", err)
+		fmt.Println("nats 获取轨迹信息失败: %s", err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	// 倒序排序
+	sort.Slice(data, func(i, j int) bool {
+		if data[i].T_time < data[j].T_time {
+			return true
+		}
+		return false
+	})
+	e.OK(data, "查询成功")
+}
+
+// GetCoolerBoxNewestLocus 获取保温箱最新轨迹
+// @Summary 获取保温箱最新轨迹
+// @Description 获取保温箱最新轨迹
+// @Tags 保温箱
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.CoolerBoxBatchInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/cooler-box/newlocus [post]
+// @Security Bearer
+func (e CoolerBoxController) GetCoolerBoxNewestLocus(c *gin.Context) {
+	s := service.CoolerBox{}
+	req := dto.CoolerBoxReq{}
+	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
+	}
+	if len(req.T_sn) == 0 || req.T_sn == "" {
+		e.Error(500, err, err.Error())
+		return
+	}
+	conn := true
+	// 数据权限检查
+	// p := actions.GetPermissionFromContext(c)
+	list := make([]nats_server.DeviceData_, 0)
+
+	// 设置响应头
+	c.Header("Content-Type", "text/event-stream")
+	c.Header("Cache-Control", "no-cache")
+	c.Header("Connection", "keep-alive")
+
+	// 监听客户端断开连接
+	notify := c.Writer.CloseNotify()
+
+	type Response struct {
+		RequestId string                    `protobuf:"bytes,1,opt,name=requestId,proto3" json:"requestId,omitempty"`
+		Code      int32                     `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"`
+		Msg       string                    `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"`
+		SN        string                    `protobuf:"bytes,3,opt,name=sn,proto3" json:"sn,omitempty"`
+		Data      []nats_server.DeviceData_ `json:"data"`
+	}
+	var response Response
+
+	for conn {
+		select {
+		case <-notify:
+			fmt.Println("断开连接")
+			conn = false
+			return
+		default:
+			err = s.GetNewLocus(&req, &list)
+			if err != nil {
+				e.Logger.Error(err)
+				response.Code = 500
+				response.Msg = err.Error()
+				response.Data = list
+				response.SN = req.T_sn
+				res, _ := json.Marshal(&response)
+				fmt.Fprintf(c.Writer, "data: %s\n\n", string(res))
+				c.Writer.Flush()
+				time.Sleep(20 * time.Second)
+			} else {
+				response.Code = 200
+				response.Msg = "查询成功"
+				response.Data = list
+				response.SN = req.T_sn
+				res, _ := json.Marshal(&response)
+				fmt.Fprintf(c.Writer, "data: %s\n\n", string(res))
+				c.Writer.Flush()
+				time.Sleep(10 * time.Second)
+			}
+		}
+	}
+}
+
+// GetCoolerBoxIce 获取指定保温箱下的所有冰排信息
+// @Summary 获取指定保温箱下的所有冰排信息
+// @Description 获取指定保温箱下的所有冰排信息
+// @Tags 保温箱
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.CoolerBoxBatchInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/cooler-box/getcoolerboxice [post]
+// @Security Bearer
+func (e CoolerBoxController) GetCoolerBoxIce(c *gin.Context) {
+	s := service.CoolerBox{}
+	req := dto.GetCoolerBoxIce{}
+	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
+	}
+	list := make([]model.IceRaftRecord, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetCoolerBoxIce(&req, &list, p, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}
+
+// GetCoolerBoxAll 获取所有保温箱使用记录
+// @Summary 获取所有保温箱使用记录
+// @Description 获取所有保温箱使用记录
+// @Tags 保温箱
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.CoolerBoxBatchInsertReq true "data"
+// @Success 200 {string} string	"{"code": 200, "message": "添加成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "添加失败"}"
+// @Router /api/cooler-box/getcoolerboxall [get]
+// @Security Bearer
+func (e CoolerBoxController) GetCoolerBoxAll(c *gin.Context) {
+	s := service.CoolerBox{}
+	req := dto.GetCoolerBoxIceAll{}
+	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
+	}
+	list := make([]model.IceRaftRecord, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.GetCoolerBoxIceAll(&req, &list, p, &count)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
+}

+ 68 - 0
app/admin/controller/ice_raft.go

@@ -545,3 +545,71 @@ func (e IceRaftRecordController) Delete(c *gin.Context) {
 	}
 	e.OK(req.GetId(), "删除成功")
 }
+
+// EndForCold 保温箱冰排结束适冷
+// @Summary 保温箱冰排结束适冷
+// @Description 保温箱冰排结束适冷
+// @Tags 冰排
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.IceRaftRecordEedReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "提交成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "提交成功"}"
+// @Router /api/end-for-cold [post]
+// @Security Bearer
+func (e IceRaftRecordController) EndForCold(c *gin.Context) {
+	s := service.IceRaftRecord{}
+	req := dto.IceRaftRecordEedReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.EndForCold(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req.Id, "提交成功")
+}
+
+// StartForCold 冰排开始释冷
+// @Summary 冰排开始释冷
+// @Description 冰排开始释冷
+// @Tags 冰排
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.IceRaftRecordEedReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "提交成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "提交成功"}"
+// @Router /api/start-for-cold [post]
+// @Security Bearer
+func (e IceRaftRecordController) StartForCold(c *gin.Context) {
+	s := service.IceRaftRecord{}
+	req := dto.IceStartbleForColfTimReq{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON, nil).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.StartForCold(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req, "提交成功")
+}

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

@@ -827,6 +827,70 @@ func (e WaybillController) CustomerReceipt(c *gin.Context) {
 	e.OK(req.WaybillNo, "签收成功")
 }
 
+// CreateSole 生成唯一订单号
+// @Summary 生成唯一订单号
+// @Description 生成唯一订单号
+// @Tags 运单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.WaybillReceiptReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "生成成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "生成成功"}"
+// @Router /api/waybill/createsole [get]
+// @Security Bearer
+func (e WaybillController) CreateSole(c *gin.Context) {
+	s := service.Waybill{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	sole, err := s.CreateSole()
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(sole, "生成成功")
+}
+
+// Turnarounds 订单转门店
+// @Summary 订单转门店
+// @Description 订单转门店
+// @Tags 运单
+// @Accept  application/json
+// @Product application/json
+// @Param data body dto.WaybillReceiptReq true "body"
+// @Success 200 {string} string	"{"code": 200, "message": "生成成功"}"
+// @Success 200 {string} string	"{"code": -1, "message": "生成成功"}"
+// @Router /api/waybill/turnarounds [put]
+// @Security Bearer
+func (e WaybillController) Turnarounds(c *gin.Context) {
+	s := service.Waybill{}
+	req := dto.WaybillTurnarounds{}
+	err := e.MakeContext(c).
+		MakeOrm().
+		Bind(&req, binding.JSON).
+		MakeService(&s.Service).
+		Errors
+	if err != nil {
+		e.Logger.Error(err)
+		e.Error(500, err, err.Error())
+		return
+	}
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c)
+	err = s.WaybillTurnarounds(&req, p)
+	if err != nil {
+		e.Error(500, err, err.Error())
+		return
+	}
+	e.OK(req, "转门店成功")
+}
+
 // GetCustomerPage 获取客户运单列表
 // @Summary 获取客户运单列表
 // @Description 获取客户运单列表

+ 21 - 6
app/admin/model/cooler_box.go

@@ -13,19 +13,34 @@ const (
 // 保温箱
 type CoolerBox struct {
 	model2.Model
-	Name       string                  `json:"name" gorm:"size:128"`                                   // 商品名称
-	Sn         string                  `json:"sn" gorm:"size:128"`                                     // sn
+	Name       string                  `json:"name" gorm:"size:128"`                                 // 商品名称
+	Sn         string                  `json:"sn" gorm:"size:128"`                                   // sn
 	Status     string                  `json:"status" gorm:"size:4;not null;default:'2';comment:状态"` // 1-停用 2-正常
-	HistorySn  model2.StringList       `json:"historySn"`                                              // 历史绑定的sn
+	HistorySn  model2.StringList       `json:"historySn"`                                            // 历史绑定的sn
+	DeviceData natsModel.DeviceData_R2 `json:"deviceData" gorm:"-"`
+	model2.ControlBy
+	model2.ModelTime
+	model2.DeptBy
+	IceRaft []IceRaft `json:"ice_raft" gorm:"-"`
+}
+type CoolerBoxAndIceRaft struct {
+	model2.Model
+	Name       string                  `json:"name" gorm:"size:128"`                                 // 商品名称
+	Sn         string                  `json:"sn" gorm:"size:128"`                                   // sn
+	Status     string                  `json:"status" gorm:"size:4;not null;default:'2';comment:状态"` // 1-停用 2-正常
+	HistorySn  model2.StringList       `json:"historySn"`                                            // 历史绑定的sn
 	DeviceData natsModel.DeviceData_R2 `json:"deviceData" gorm:"-"`
-
 	model2.ControlBy
 	model2.ModelTime
 	model2.DeptBy
+	IceRaft []IceRaft `json:"ice_raft"`
 }
 type CoolerBoxOmit struct {
-	Id   int    `json:"id,omitempty"`   // 主键编码
-	Name string `json:"name,omitempty"` // 商品名称
+	Id        int         `json:"id,omitempty"`       // 主键编码
+	Name      string      `json:"name,omitempty"`     // 商品名称
+	Sn        string      `json:"sn" gorm:"size:128"` // sn
+	StartTime model2.Time `json:"startTime"`
+	EndTime   model2.Time `json:"endTime"`
 }
 
 func (CoolerBox) TableName() string {

+ 38 - 29
app/admin/model/ice_raft.go

@@ -10,12 +10,13 @@ const (
 // 冰排
 type IceRaft struct {
 	model2.Model
-	Code            string            `json:"code" gorm:"size:128"`                                 // 商品名称
-	Status          string            `json:"status" gorm:"size:4;not null;default:'2';comment:状态"` // 1-停用 2-正常
-	IceRaftRecordId int               `json:"iceRaftRecordId" gorm:"size:128"`                      // 最新入库记录
-	FreezeClaim     float32           `json:"freezeClaim" gorm:"type:decimal(10,2);comment:冷冻要求"`   // 冷冻要求 单位小时
-	IceRaftRecord   IceRaftRecordOmit `json:"iceRaftRecord" gorm:"->;foreignkey:IceRaftRecordId;references:Id"`
-	Label           string            `json:"label" gorm:"size:128;comment:标签"` // 标签
+	Code                string            `json:"code" gorm:"size:128"`                                 // 商品名称
+	Status              string            `json:"status" gorm:"size:4;not null;default:'2';comment:状态"` // 1-停用 2-正常
+	IceRaftRecordId     int               `json:"iceRaftRecordId" gorm:"size:128"`                      // 最新入库记录
+	FreezeClaim         float32           `json:"freezeClaim" gorm:"type:decimal(10,2);comment:冷冻要求"`   // 冷冻要求 单位小时
+	IceRaftRecord       IceRaftRecordOmit `json:"iceRaftRecord" gorm:"->;foreignkey:IceRaftRecordId;references:Id"`
+	Label               string            `json:"label" gorm:"size:128;comment:标签"`                 // 标签
+	SuitableForColdTime int               `json:"suitableForColdTime" gorm:"size:128;comment:适冷时间"` // 适冷时间 单位分钟
 	model2.ControlBy
 	model2.ModelTime
 	model2.DeptBy
@@ -37,7 +38,6 @@ const (
 	IceRaftRecordStatusWaitUse  = "2" // 待使用
 	IceRaftRecordStatusUsing    = "3" // 使用中
 	IceRaftRecordStatusFinish   = "4" // 已结束
-
 )
 
 func GetIceRaftRecordStatus(s string) string {
@@ -59,34 +59,43 @@ func GetIceRaftRecordStatus(s string) string {
 // 冰排记录
 type IceRaftRecord struct {
 	model2.Model
-	IceRaftId      int           `json:"iceRaftId" gorm:"size:128;comment:冰排id"`
-	Label          string        `json:"label" gorm:"size:128;comment:标签"`                     // 标签
-	Status         string        `json:"status" gorm:"size:4;not null;default:'2';comment:状态"` // 0未入库 1-冷冻中 2-待使用 3-使用中 4已结束
-	InStorageTime  model2.Time   `json:"inStorageTime"  gorm:"size:128;comment:入库时间"`          // 入库时间
-	OutStorageTime model2.Time   `json:"outStorageTime"  gorm:"size:128;comment:出库时间"`         // 出库时间
-	IceLockerId    int           `json:"iceLockerId" gorm:"size:128;comment:冷冻柜id"`            // 冷冻柜id
-	CoolerBoxId    int           `json:"coolerBoxId" gorm:"size:128;comment:保温箱id"`            // 保温箱id
-	FreezeClaim    float32       `json:"freezeClaim" gorm:"type:decimal(10,2);comment:冷冻要求"`   // 冷冻要求 单位小时
-	FreezeDuration int           `json:"freezeDuration" gorm:"size:128;comment:冷冻时长"`          // 冷冻时长 单位分钟
-	IceLocker      IceLockerOmit `json:"iceLocker" gorm:"->"`
-	CoolerBox      CoolerBoxOmit `json:"coolerBox" gorm:"->"`
+	IceRaftId         int           `json:"iceRaftId" gorm:"size:128;comment:冰排id"`
+	Label             string        `json:"label" gorm:"size:128;comment:标签"`                         // 标签
+	Status            string        `json:"status" gorm:"size:4;not null;default:'2';comment:状态"`     // 0未入库 1-冷冻中 2-待使用 3-使用中 4已结束
+	InStorageTime     model2.Time   `json:"inStorageTime"  gorm:"size:128;comment:入库时间"`              // 入库时间
+	OutStorageTime    model2.Time   `json:"outStorageTime"  gorm:"size:128;comment:出库时间"`             // 出库时间
+	IceLockerId       int           `json:"iceLockerId" gorm:"size:128;comment:冷冻柜id"`                // 冷冻柜id
+	CoolerBoxId       int           `json:"coolerBoxId" gorm:"size:128;comment:保温箱id"`                // 保温箱id
+	FreezeClaim       float32       `json:"freezeClaim" gorm:"type:decimal(10,2);comment:冷冻要求"`       // 冷冻要求 单位小时
+	FreezeDuration    int           `json:"freezeDuration" gorm:"size:128;comment:冷冻时长"`              // 冷冻时长 单位分钟
+	SuitableForCold   float32       `json:"suitableForCold" gorm:"type:decimal(10,2);comment:冰排适冷温度"` // 冰排适冷温度
+	EndForColdTime    model2.Time   `json:"endForColdTime"  gorm:"size:128;comment:适冷结束时间"`           // 适冷结束时间
+	IsSuitableForCold int           `json:"isSuitableForCold" gorm:"size:4;not null;comment:是否结束适冷"`  //0 未适冷 1已适冷
+	CoolerBoxStarTime model2.Time   `json:"coolerBoxStarTime"  gorm:"size:128;comment:保温箱开始记录时间"`     //保温箱开始记录时间
+	CoolerBoxEndTime  model2.Time   `json:"coolerBoxEndTime"  gorm:"size:128;comment:保温箱结束记录时间"`      //保温箱结束记录时间
+	StartIceColdTime  model2.Time   `json:"start_ice_cold_time" gorm:"size:128;comment:释冷开始时间"`       //释冷开始时间
+	IceLocker         IceLockerOmit `json:"iceLocker" gorm:"->"`
+	CoolerBox         CoolerBoxOmit `json:"coolerBox" gorm:"->"`
 	model2.ControlBy
 	model2.ModelTime
 	model2.DeptBy
 }
 
 type IceRaftRecordOmit struct {
-	Id             int           `json:"id,omitempty"`             // 主键编码
-	IceRaftId      int           `json:"iceRaftId,omitempty"`      // 冰排id
-	Status         string        `json:"status"`                   // 1-停用 2-正常
-	InStorageTime  model2.Time   `json:"inStorageTime,omitempty"`  // 入库时间
-	OutStorageTime model2.Time   `json:"outStorageTime,omitempty"` // 出库时间
-	IceLockerId    int           `json:"iceLockerId,omitempty"`    // 冷冻柜id
-	CoolerBoxId    int           `json:"coolerBoxId,omitempty"`    // 保温箱id
-	FreezeClaim    float32       `json:"freezeClaim"`              // 冷冻要求 单位小时
-	FreezeDuration int           `json:"freezeDuration"`           // 冷冻时长 单位分钟
-	IceLocker      IceLockerOmit `json:"iceLocker" gorm:"->"`
-	CoolerBox      CoolerBoxOmit `json:"coolerBox" gorm:"->"`
+	Id                int           `json:"id,omitempty"`             // 主键编码
+	IceRaftId         int           `json:"iceRaftId,omitempty"`      // 冰排id
+	Status            string        `json:"status"`                   // 1-停用 2-正常
+	InStorageTime     model2.Time   `json:"inStorageTime,omitempty"`  // 入库时间
+	OutStorageTime    model2.Time   `json:"outStorageTime,omitempty"` // 出库时间
+	IceLockerId       int           `json:"iceLockerId,omitempty"`    // 冷冻柜id
+	CoolerBoxId       int           `json:"coolerBoxId,omitempty"`    // 保温箱id
+	FreezeClaim       float32       `json:"freezeClaim"`              // 冷冻要求 单位小时
+	FreezeDuration    int           `json:"freezeDuration"`           // 冷冻时长 单位分钟
+	SuitableForCold   float32       `json:"suitableForCold" `         // 冰排适冷温度
+	EndForColdTime    model2.Time   `json:"endForColdTime"  `         // 适冷结束时间
+	IsSuitableForCold int           `json:"isSuitableForCold" `       //0 未适冷 1已适冷
+	IceLocker         IceLockerOmit `json:"iceLocker" gorm:"->"`
+	CoolerBox         CoolerBoxOmit `json:"coolerBox" gorm:"->"`
 }
 
 func (IceRaftRecord) TableName() string {

+ 12 - 9
app/admin/model/sys_dept.go

@@ -13,15 +13,18 @@ var GetCompanyKeyErr = errors.New("获取公司秘钥失败")
 
 type SysDept struct {
 	model2.Model
-	ParentId int       `json:"parentId" gorm:""`                        // 上级部门
-	Path     string    `json:"-" gorm:"size:255;" swaggerignore:"true"` // 路径
-	Name     string    `json:"name"  gorm:"size:128;"`                  // 部门名称
-	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
-	ColdPid  int       `json:"coldPid"  gorm:"size:128;"`               // 冷链3.0公司id
-	Children []SysDept `json:"children" gorm:"-"`
+	ParentId            int       `json:"parentId" gorm:""`                                      // 上级部门
+	Path                string    `json:"-" gorm:"size:255;" swaggerignore:"true"`               // 路径
+	Name                string    `json:"name"  gorm:"size:128;"`                                // 部门名称
+	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
+	ColdPid             int       `json:"coldPid"  gorm:"size:128;"`                             // 冷链3.0公司id
+	IsIceReleaseCold    bool      `json:"isIceReleaseCold" gorm:"type:boolean;default:false"`    //冰排是否释冷
+	IsCoolerReleaseCold bool      `json:"isCoolerReleaseCold" gorm:"type:boolean;default:false"` //保温箱是否释冷
+	Children            []SysDept `json:"children" gorm:"-"`
+	CompanyAddress      string    `json:"companyAddress"` //公司地址
 	model2.ControlBy
 	model2.ModelTime
 }

+ 1 - 1
app/admin/model/waybill.go

@@ -106,7 +106,7 @@ type Waybill struct {
 	PrescriptionIsAudit        int            `json:"prescriptionIssue"   gorm:"size:128;default:1"`        // 处方是否审核 1 未审核 2已审核
 	InvoiceIsAudit             int            `json:"invoiceIssue"   gorm:"size:128;default:1"`             // 发票是否审核 1 未审核 2已审核
 	InspectionReportIsAudit    int            `json:"inspectionReportIssue"   gorm:"size:128;default:1"`    // 检验报告是否审核 1 未审核 2已审核
-	DispensingMedicinesIsAudit int            `json:"dispensingMedicinesIssue"   gorm:"size:128;default:1"` //  调配药品信息是否审核  1 未审核 2已审核
+	DispensingMedicinesIsAudit int            `json:"dispensingMedicinesIssue"   gorm:"size:128;default:1"` // 调配药品信息是否审核  1 未审核 2已审核
 	IsCold                     int            `json:"isCold"   gorm:"size:128;default:1"`                   // 是否冷链 1 否 2 是
 	PaymentStatus              int            `json:"paymentStatus"  gorm:"size:128;default:1"`             //支付状态 1 结清 2 未结清  3 支付完成
 	PaymentType                int            `json:"paymentType"  gorm:"size:128;default:0"`               //支付方式  1现金 2线上支付 3银行卡 4医保 5其他

+ 4 - 0
app/admin/router/cooler_box.go

@@ -22,5 +22,9 @@ func registerCoolerBoxRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd
 		r.POST("/import", cont.BatchInsert)
 		r.PUT("", cont.Update)
 		r.DELETE("", cont.Delete)
+		r.POST("/locus", cont.GetCollerBoxLocus)
+		r.POST("/historylocus", cont.GetCoolerBoxLocus)
+		r.GET("/getcoolerboxice", cont.GetCoolerBoxIce)
+		r.GET("/getcoolerboxall", cont.GetCoolerBoxAll)
 	}
 }

+ 2 - 0
app/admin/router/ice_raft.go

@@ -35,5 +35,7 @@ func registerIceRaftRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
 		r2.GET("", cont2.GetPage)
 		r2.PUT("", cont2.Update)
 		r2.DELETE("", cont2.Delete)
+		r2.POST("/end-for-cold", cont2.EndForCold)
+		r2.POST("/start-for-cold", cont2.StartForCold)
 	}
 }

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

@@ -40,15 +40,18 @@ func registerWaybillRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
 		r.GET("/export", cont.Export)                  // 运单管理-导出
 		r.GET("/customer/export", cont.CustomerExport) // 客户下单
 		r.GET("/temperature-pdf", cont.TemperaturePDF) // 导出温湿度pdf
+		r.GET("/createsole", cont.CreateSole)          // 生成唯一订单编号
+		r.PUT("/turnarounds", cont.Turnarounds)        // 订单转门店
 	}
 }
 
 func registerWaybillRouter2(v1 *gin.RouterGroup) {
 	cont := controller.WaybillController{}
+	test := controller.CoolerBoxController{}
 	r := v1.Group("/waybill")
 	{
 		r.POST("/customer/receipt", cont.CustomerReceipt) // 客户签收
 		r.GET("/no", cont.GetByWaybillNo)
-
+		r.GET("/newlocus", test.GetCoolerBoxNewestLocus)
 	}
 }

+ 265 - 1
app/admin/service/cooler_box.go

@@ -6,10 +6,17 @@ import (
 	"cold-delivery/common/actions"
 	cDto "cold-delivery/common/dto"
 	"cold-delivery/common/global"
+	"cold-delivery/common/lib"
 	"cold-delivery/common/nats/nats_server"
 	"errors"
+	"fmt"
 	"gogs.baozhida.cn/zoie/OAuth-core/service"
 	"gorm.io/gorm"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
 )
 
 type CoolerBox struct {
@@ -20,7 +27,6 @@ type CoolerBox struct {
 func (e *CoolerBox) GetPage(c *dto.CoolerBoxGetPageReq, list *[]model.CoolerBox, count *int64, p *actions.DataPermission) error {
 	var err error
 	var data model.CoolerBox
-
 	if c.PageSize == 9999 {
 		err = e.Orm.Model(&data).
 			Scopes(
@@ -57,6 +63,24 @@ func (e *CoolerBox) GetPage(c *dto.CoolerBoxGetPageReq, list *[]model.CoolerBox,
 			}
 		}
 	}
+	for i, _ := range *list {
+		var dataIce model.IceRaft
+		var dataIces []model.IceRaft
+		err := e.Orm.Model(&dataIce).
+			Scopes(
+				actions.Permission(dataIce.TableName(), p),
+				IceRaftNameRecordStatusScopes(model.IceRaftRecordStatusUsing),
+				IceRaftNameRecordCoolerBoxIdScopes((*list)[i].Id),
+			).
+			Joins("left join ice_raft_record on ice_raft.ice_raft_record_id = ice_raft_record.id").
+			Preload("IceRaftRecord").
+			Find(&dataIces).Error
+		if err != nil {
+			e.Log.Errorf("db error: %s", err)
+			return global.GetFailedErr
+		}
+		(*list)[i].IceRaft = dataIces
+	}
 	return nil
 }
 
@@ -307,3 +331,243 @@ func (e *CoolerBox) Remove(c *dto.CoolerBoxDeleteReq, p *actions.DataPermission)
 
 	return nil
 }
+
+// GetHistory 获取保温箱历史信息
+func (e *CoolerBox) GetHistory(c *dto.CoolerBoxBatchReqSN, p *actions.DataPermission) ([]dto.HistoricalData, error) {
+	var err error
+	var taskList []model.WaybillTask
+	var historical []dto.HistoricalData
+	if c.Page == 0 {
+		c.Page = 1
+	}
+	if c.PageZ == 0 {
+		c.PageZ = 10
+	}
+	// 查询运单任务信息
+	err = e.Orm.Model(&model.WaybillTask{}).
+		Where("cooler_box_id = ?", c.Id).
+		Find(&taskList).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return nil, errors.New("获取运单任务信息失败")
+	}
+	// 获取公司秘钥
+	var dataDept model.SysDept
+	var Depts []model.SysDept
+	err = e.Orm.Model(&dataDept).
+		Scopes(
+			CompanyIdScopesUser(p.DeptId),
+		).
+		Find(&Depts).Limit(-1).Offset(-1).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return nil, model.GetCompanyKeyErr
+	}
+
+	//company, err := model.GetCompanyById(p.DeptId)
+	//if err != nil {
+	//	e.Log.Errorf("db error: %s", err)
+	//	return nil, model.GetCompanyKeyErr
+	//}
+	// 限制并发请求数量
+	const maxConcurrentRequests = 10
+	semaphore := make(chan struct{}, maxConcurrentRequests)
+	var deviceSensorList []nats_server.DeviceSensor_R
+	var wg sync.WaitGroup
+	for _, task := range taskList {
+		wg.Add(1)
+		go func(task model.WaybillTask) {
+			defer wg.Done()
+			semaphore <- struct{}{}
+			defer func() { <-semaphore }()
+			for _, v := range Depts {
+				deviceSensorList, _, _ = nats_server.Cold_CompanyDeviceSensor_List_ByKey(task.Sn, v.ColdKey)
+				if len(deviceSensorList) > 0 {
+					historical = append(historical, dto.HistoricalData{
+						Sn:          task.Sn,
+						T_id:        strconv.Itoa(deviceSensorList[0].T_id) + "|",
+						StartTime:   task.StartTime.String(),
+						EndTime:     task.EndTime.String(),
+						CompanyName: v.Name,
+					})
+					break
+				}
+			}
+			if len(deviceSensorList) == 0 {
+				return
+			}
+			if err != nil {
+				e.Log.Errorf("nats 获取轨迹信息失败: %s", err)
+				return
+			}
+
+		}(task)
+	}
+	wg.Wait()
+	sort.Slice(historical, func(i, j int) bool {
+		if historical[i].StartTime < historical[j].StartTime {
+			return true
+		}
+		return false
+	})
+	startIndex := (c.Page - 1) * c.PageZ
+	endIndex := startIndex + c.PageZ
+	if endIndex > len(historical) {
+		endIndex = len(historical)
+	}
+	pageHistory := historical[startIndex:endIndex]
+	return pageHistory, nil
+}
+
+// GetNewLocus 获取最新轨迹
+func (e *CoolerBox) GetNewLocus(c *dto.CoolerBoxReq, list *[]nats_server.DeviceData_) error {
+	// 获取公司秘钥
+	var dataDept model.SysDept
+	var Depts []model.SysDept
+	atoi, _ := strconv.Atoi(c.Id)
+	err := e.Orm.Model(&dataDept).
+		Scopes(
+			CompanyIdScopesUser(atoi),
+		).
+		Find(&Depts).Limit(-1).Offset(-1).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	var deviceSensorList []nats_server.DeviceSensor_R
+	for _, v := range Depts {
+		deviceSensorList, _, _ = nats_server.Cold_CompanyDeviceSensor_List_ByKey(c.T_sn, v.ColdKey)
+		if len(deviceSensorList) > 0 {
+			break
+		}
+	}
+	if len(deviceSensorList) == 0 {
+		return errors.New("该设备不属于该公司")
+	}
+	data, err := nats_server.Read_DeviceTask_List_By_Condition(c.T_sn)
+	if err != nil {
+		e.Log.Errorf("设备未开启监控: %s", err)
+		return errors.New("设备未开启监控")
+	}
+	// 当最新设备状态为1时,证明设备正在启动中,查询大于开始时间的所有轨迹,设备状态为2时,查询开始时间到结束时间的轨迹
+	if data.T_State == 1 {
+		deviceData, err := nats_server.Read_Start_Time_DeviceData(c.T_sn, deviceSensorList[0].T_id, data.T_Ut_start.Format("2006-01-02 15:04:05"), "")
+		if err != nil {
+			e.Log.Errorf("获取设备轨迹失败: %s", err)
+			return errors.New("获取设备轨迹失败")
+		}
+		*list = appendUniqueDeviceData(*list, deviceData)
+	} else if data.T_State == 2 {
+		deviceData, err := nats_server.Read_Start_Time_DeviceData(c.T_sn, deviceSensorList[0].T_id, data.T_Ut_start.Format("2006-01-02 15:04:05"), data.T_Ut_end.Format("2006-01-02 15:04:05"))
+		if err != nil {
+			e.Log.Errorf("获取设备轨迹失败: %s", err)
+			return errors.New("获取设备轨迹失败")
+		}
+		*list = appendUniqueDeviceData(*list, deviceData)
+	}
+	return nil
+}
+
+// 去重并追加设备数据
+func appendUniqueDeviceData(list []nats_server.DeviceData_, newData []nats_server.DeviceData_) []nats_server.DeviceData_ {
+	uniqueMap := make(map[time.Time]bool)
+	for _, d := range list {
+		//split := strings.Split(list[i].T_site, ",")
+		//defer func() {
+		//	if r := recover(); r != nil {
+		//		fmt.Println("数组下标越界:", r)
+		//	}
+		//}()
+		//Lng := split[0]
+		//Lat := split[1]
+		//Lngs, _ := strconv.ParseFloat(Lng, 64)
+		//Lats, _ := strconv.ParseFloat(Lat, 64)
+		//mLng, mLat := lib.Wgs84ToGcj02(Lngs, Lats)
+		//list[i].T_site = fmt.Sprintf("%v,%v", mLng, mLat)
+		uniqueMap[d.T_time] = true
+	}
+	for _, d := range newData {
+		if !uniqueMap[d.T_time] {
+			split := strings.Split(d.T_site, ",")
+			defer func() {
+				if r := recover(); r != nil {
+					fmt.Println("数组下标越界:", r)
+				}
+			}()
+			Lng := split[0]
+			Lat := split[1]
+			Lngs, _ := strconv.ParseFloat(Lng, 64)
+			Lats, _ := strconv.ParseFloat(Lat, 64)
+			mLng, mLat := lib.Wgs84ToGcj02(Lngs, Lats)
+			d.T_site = fmt.Sprintf("%v,%v", mLng, mLat)
+			list = append(list, d)
+		}
+	}
+	//排序
+	sort.Slice(list, func(i, j int) bool {
+		return list[i].T_time.After(list[j].T_time)
+	})
+	return list
+}
+
+// GetCoolerBoxIce 获取保温箱下的所有历史冰排
+func (e *CoolerBox) GetCoolerBoxIce(c *dto.GetCoolerBoxIce, list *[]model.IceRaftRecord, p *actions.DataPermission, count *int64) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	//查询保温箱是否存在
+	var icerecord model.IceRaftRecord
+	err = e.Orm.Scopes(
+		cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		actions.Permission(icerecord.TableName(), p)).
+		Where("cooler_box_id=?", c.CoolerBoxId).
+		Preload("IceLocker").
+		Preload("CoolerBox").
+		Find(&list).Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetFailedErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}
+
+// GetCoolerBoxIceAll 获取保温箱所有历史记录
+func (e *CoolerBox) GetCoolerBoxIceAll(c *dto.GetCoolerBoxIceAll, list *[]model.IceRaftRecord, p *actions.DataPermission, count *int64) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	//查询保温箱是否存在
+	var icerecord model.IceRaftRecord
+	err = e.Orm.Scopes(
+		cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+		actions.Permission(icerecord.TableName(), p)).
+		Not("cooler_box_id", 0).
+		Preload("IceLocker").
+		Preload("CoolerBox").
+		Find(&list).Count(count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetFailedErr
+		}
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 20 - 12
app/admin/service/dto/company.go

@@ -31,13 +31,15 @@ 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"`                                         // 备注
-	ColdKey  string `json:"coldKey"`                                        // 冷链3.0key
-	ParentId int    `json:"parentId" example:"0" vd:"?"`                    //上级公司
-
-	common.ControlBy `swaggerignore:"true"`
+	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
+	ParentId            int    `json:"parentId" example:"0" vd:"?"`                          //上级公司
+	IsIceReleaseCold    bool   `json:"isIceReleaseCold" gorm:"type:boolean;default:true"`    //冰排是否释冷
+	IsCoolerReleaseCold bool   `json:"isCoolerReleaseCold" gorm:"type:boolean;default:true"` //保温箱是否释冷
+	CompanyAddress      string `json:"companyAddress"`                                       //公司地址
+	common.ControlBy    `swaggerignore:"true"`
 }
 
 func (s *CompanyInsertReq) Generate(model *model.SysDept) {
@@ -48,6 +50,9 @@ func (s *CompanyInsertReq) Generate(model *model.SysDept) {
 	model.ParentId = s.ParentId
 	model.Remark = s.Remark
 	model.ColdKey = s.ColdKey
+	model.CompanyAddress = s.CompanyAddress
+	model.IsIceReleaseCold = s.IsIceReleaseCold
+	model.IsCoolerReleaseCold = s.IsCoolerReleaseCold
 }
 
 // GetId 获取数据对应的ID
@@ -56,11 +61,14 @@ func (s *CompanyInsertReq) GetId() interface{} {
 }
 
 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"`
+	Id                  int    `json:"id" comment:"编码"`                                      // 编码
+	Name                string `json:"name" example:"名称"`                                    //名称
+	Remark              string `json:"remark"`                                               // 备注
+	ColdKey             string `json:"coldKey"`                                              // 冷链3.0key
+	IsIceReleaseCold    bool   `json:"isIceReleaseCold" gorm:"type:boolean;default:true"`    //冰排是否释冷
+	IsCoolerReleaseCold bool   `json:"isCoolerReleaseCold" gorm:"type:boolean;default:true"` //保温箱是否释冷
+	CompanyAddress      string `json:"companyAddress"`                                       //公司地址
+	common.ControlBy    `swaggerignore:"true"`
 }
 
 // Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型

+ 34 - 0
app/admin/service/dto/cooler_box.go

@@ -105,3 +105,37 @@ type CoolerBoxBatchInsertReq struct {
 	common.ControlBy `swaggerignore:"true"`
 	common.DeptBy    `swaggerignore:"true"`
 }
+type CoolerBoxBatchReqSN struct {
+	Id    int `json:"id"`
+	Page  int `json:"page"`
+	PageZ int `json:"page_z"`
+}
+type CoolerBoxBatchReq struct {
+	SnId      string `json:"sn"`
+	T_id      string `json:"t_id"`
+	StartTime string `json:"start_time"`
+	EndTime   string `json:"end_time"`
+	Page      int    `json:"page"`
+	PageZ     int    `json:"page_z"`
+}
+type CoolerBoxReq struct {
+	T_sn string `json:"T_sn"`
+	Id   string `json:"T_id"`
+}
+type HistoricalData struct {
+	Sn          string `json:"sn"`           //设备Sn
+	StartTime   string `json:"start_time"`   //开始时间
+	EndTime     string `json:"end_time"`     //结束时间
+	CompanyName string `json:"company_name"` //公司名称
+	Driver      string `json:"driver"`       //配送员,司机
+	T_id        string `json:"t_id"`
+}
+type GetCoolerBoxIce struct {
+	dto.Pagination `search:"-"`
+	CoolerBoxId    int `form:"cooler_box_id"`
+}
+type GetCoolerBoxIceAll struct {
+	dto.Pagination `search:"-"`
+	Name           string `form:"name" search:"type:contains;column:name;table:ice_locker"`  // 保温箱
+	Status         string `form:"status" search:"type:exact;column:status;table:ice_locker"` // 状态
+}

+ 26 - 14
app/admin/service/dto/ice_raft.go

@@ -38,13 +38,14 @@ func (m *IceRaftGetNewestRecordPageReq) GetNeedSearch() interface{} {
 }
 
 type IceRaftInsertReq struct {
-	Id               int      `json:"id" comment:"编码" swaggerignore:"true"`  // 编码
-	CodeList         []string `json:"codeList" vd:"len($)>0;msg:'冰排编号不能为空'"` // 冰排名称
-	Status           string   `json:"status"`                                // 1-停用 2-正常
-	FreezeClaim      float32  `json:"freezeClaim"`                           // 冷冻要求 单位小时
-	Label            string   `json:"label"`                                 // 标签
-	common.ControlBy `swaggerignore:"true"`
-	common.DeptBy    `swaggerignore:"true"`
+	Id                  int      `json:"id" comment:"编码" swaggerignore:"true"`  // 编码
+	CodeList            []string `json:"codeList" vd:"len($)>0;msg:'冰排编号不能为空'"` // 冰排名称
+	Status              string   `json:"status"`                                // 1-停用 2-正常
+	FreezeClaim         float32  `json:"freezeClaim"`                           // 冷冻要求 单位小时
+	Label               string   `json:"label"`                                 // 标签
+	SuitableForColdTime int      `json:"suitableForColdTime"`                   // 适冷时间 单位分钟
+	common.ControlBy    `swaggerignore:"true"`
+	common.DeptBy       `swaggerignore:"true"`
 }
 
 func (s *IceRaftInsertReq) Generate(model *model.IceRaft, code string) {
@@ -55,6 +56,7 @@ func (s *IceRaftInsertReq) Generate(model *model.IceRaft, code string) {
 	model.Status = s.Status
 	model.FreezeClaim = s.FreezeClaim
 	model.Label = s.Label
+	model.SuitableForColdTime = s.SuitableForColdTime
 	if s.ControlBy.UpdateBy != 0 {
 		model.UpdateBy = s.UpdateBy
 	}
@@ -71,12 +73,13 @@ func (s *IceRaftInsertReq) GetId() interface{} {
 }
 
 type IceRaftUpdateReq struct {
-	Id               int     `json:"id" comment:"编码"`                   // 编码
-	Label            string  `json:"label" gorm:"size:128;comment:标签"`  // 标签
-	Code             string  `json:"code" vd:"len($)>0;msg:'冰排编号不能为空'"` // 冰排名称
-	Status           string  `json:"status"`                            // 1-停用 2-正常
-	FreezeClaim      float32 `json:"freezeClaim"`                       // 冷冻要求 单位小时
-	common.ControlBy `swaggerignore:"true"`
+	Id                  int     `json:"id" comment:"编码"`                   // 编码
+	Label               string  `json:"label" gorm:"size:128;comment:标签"`  // 标签
+	Code                string  `json:"code" vd:"len($)>0;msg:'冰排编号不能为空'"` // 冰排名称
+	Status              string  `json:"status"`                            // 1-停用 2-正常
+	FreezeClaim         float32 `json:"freezeClaim"`                       // 冷冻要求 单位小时
+	SuitableForColdTime int     `json:"suitableForColdTime"`               // 适冷时间 单位分钟
+	common.ControlBy    `swaggerignore:"true"`
 }
 
 func (s *IceRaftUpdateReq) Generate(model *model.IceRaft) {
@@ -87,6 +90,7 @@ func (s *IceRaftUpdateReq) Generate(model *model.IceRaft) {
 	model.Status = s.Status
 	model.FreezeClaim = s.FreezeClaim
 	model.Label = s.Label
+	model.SuitableForColdTime = s.SuitableForColdTime
 	if s.ControlBy.UpdateBy != 0 {
 		model.UpdateBy = s.UpdateBy
 	}
@@ -128,9 +132,13 @@ type IceRaftInStorageReq struct {
 }
 type IceRaftOutStorageReq struct {
 	Code             []string `json:"code"`
-	CoolerBoxId      int      `json:"coolerBoxId"` // 保温箱id
+	CoolerBoxId      int      `json:"coolerBoxId"`     // 保温箱id
+	SuitableForCold  float32  `json:"suitableForCold"` // 冰排适冷温度
 	common.ControlBy `swaggerignore:"true"`
 }
+type IceStartbleForColfTimReq struct {
+	Id []string `json:"id"`
+}
 
 type IceRaftRecordGetPageReq struct {
 	dto.Pagination `search:"-"`
@@ -176,6 +184,10 @@ type IceRaftRecordDeleteReq struct {
 	Id               int `json:"id"`
 	common.ControlBy `swaggerignore:"true"`
 }
+type IceRaftRecordEedReq struct {
+	Id               []int `json:"iceRaftRecordId"`
+	common.ControlBy `swaggerignore:"true"`
+}
 
 func (s *IceRaftRecordDeleteReq) GetId() interface{} {
 	return s.Id

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

@@ -356,3 +356,7 @@ type WaybillGetByWaybillPdfReq struct {
 	HumidityShow bool   `form:"humidityShow" vd:""`                     // 湿度显示
 	//TemplateShow bool   `form:"templateShow" vd:""`                     // 湿度显示
 }
+type WaybillTurnarounds struct {
+	WaybillNo string `json:"waybillNo" vd:"len($)>0;msg:'订单编号不能为空'"` // 运单编号-必填
+	DeptId    int    `json:"deptId"`                                 // 门店id
+}

+ 96 - 10
app/admin/service/ice_raft.go

@@ -89,6 +89,7 @@ func (e *IceRaft) GetRecordPage(c *dto.IceRaftGetNewestRecordPageReq, list *[]mo
 			Joins("left join ice_raft_record on ice_raft.ice_raft_record_id = ice_raft_record.id").
 			Preload("IceRaftRecord.IceLocker").
 			Preload("IceRaftRecord.CoolerBox").
+			Preload("IceRaftRecord").
 			Order("FIELD(ice_raft_record.status,'2','','1','3','4')").
 			Find(list).Limit(-1).Offset(-1).
 			Count(count).Error
@@ -106,6 +107,7 @@ func (e *IceRaft) GetRecordPage(c *dto.IceRaftGetNewestRecordPageReq, list *[]mo
 			Joins("left join ice_raft_record on ice_raft.ice_raft_record_id = ice_raft_record.id").
 			Preload("IceRaftRecord.IceLocker").
 			Preload("IceRaftRecord.CoolerBox").
+			Preload("IceRaftRecord").
 			Order("FIELD(ice_raft_record.status,'2','','1','3','4')").
 			Find(list).Limit(-1).Offset(-1).
 			Count(count).Error
@@ -171,7 +173,8 @@ func (e *IceRaft) Insert(c *dto.IceRaftInsertReq) error {
 		}
 		// 冰排编号已存在
 		if k > 0 {
-			continue
+			err = errors.New("该编号已存在!")
+			return err
 		}
 
 		// 添加冰排
@@ -234,15 +237,19 @@ func (e *IceRaft) Update(c *dto.IceRaftUpdateReq, p *actions.DataPermission) err
 		e.Log.Errorf("db error: %s", err)
 		return global.UpdateFailedErr
 	}
-
+	// 查询冰排记录是否存在
 	var iceRaftRecordModel model.IceRaftRecord
-	iceRaftRecordModel.Id = iceRaftModel.IceRaftRecordId
-	iceRaftRecordModel.FreezeClaim = iceRaftModel.FreezeClaim
-	iceRaftRecordModel.Label = iceRaftModel.Label
-	err = tx.Updates(&iceRaftRecordModel).Error
-	if err != nil {
-		e.Log.Errorf("db error: %s", err)
-		return errors.New("修改冰排记录失败")
+	var count int64
+	e.Orm.Table(iceRaftRecordModel.TableName()).Where("ice_raft_id = ?", c.Id).Count(&count)
+	if count > 0 {
+		iceRaftRecordModel.Id = iceRaftModel.IceRaftRecordId
+		iceRaftRecordModel.FreezeClaim = iceRaftModel.FreezeClaim
+		iceRaftRecordModel.Label = iceRaftModel.Label
+		err = tx.Updates(&iceRaftRecordModel).Error
+		if err != nil {
+			e.Log.Errorf("db error: %s  该冰排未使用", err)
+			return errors.New("修改冰排记录失败")
+		}
 	}
 	c.Id = iceRaftModel.Id
 	return nil
@@ -453,12 +460,22 @@ func (e *IceRaft) OutStorage(c *dto.IceRaftOutStorageReq, p *actions.DataPermiss
 		iceRaftRecordModel.Status = model.IceRaftRecordStatusUsing
 		iceRaftRecordModel.CoolerBoxId = coolerBoxModel.Id
 		iceRaftRecordModel.OutStorageTime = model2.Time(time.Now())
+		iceRaftRecordModel.SuitableForCold = c.SuitableForCold
+		//data, err := nats_server.Read_DeviceTask_List_By_Condition(coolerBoxModel.Sn)
+		//if data.T_State != 1 {
+		//	e.Log.Errorf("该保温箱未启动: %s", err)
+		//	return errors.New("该保温箱未启动,请启动保温箱监控")
+		//}
+		//if err != nil {
+		//	e.Log.Errorf("获取设备任务列表失败: %s", err)
+		//	return errors.New("该保温箱未绑定平台")
+		//}
+		//iceRaftRecordModel.CoolerBoxStarTime = model2.Time(data.T_Ut_start)
 		err = tx.Save(&iceRaftRecordModel).Error
 		if err != nil {
 			e.Log.Errorf("db error: %s", err)
 			return errors.New("保存冰排记录失败")
 		}
-
 	}
 
 	return nil
@@ -621,3 +638,72 @@ func (e *IceRaftRecord) Remove(c *dto.IceRaftRecordDeleteReq, p *actions.DataPer
 	}
 	return nil
 }
+func (e *IceRaftRecord) EndForCold(c *dto.IceRaftRecordEedReq, p *actions.DataPermission) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	// 查询冰排是否存在
+	for _, v := range c.Id {
+		var iceRaftRecordModel model.IceRaftRecord
+		err = e.Orm.Scopes(actions.Permission(iceRaftRecordModel.TableName(), p)).
+			First(&iceRaftRecordModel, v).Error
+		if err != nil {
+			e.Log.Errorf("db error: %s", err)
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return global.UpdateNotFoundOrNoPermissionErr
+			}
+			return global.UpdateFailedErr
+		}
+		iceRaftRecordModel.IsSuitableForCold = 1 // 是否适冷
+		iceRaftRecordModel.EndForColdTime = model2.Time(time.Now())
+		iceRaftRecordModel.Id = v
+		updates := tx.Where("id = ?", iceRaftRecordModel.Id).Updates(&iceRaftRecordModel)
+		if err = updates.Error; err != nil {
+			e.Log.Errorf("db error: %s", err)
+			return global.UpdateFailedErr
+		}
+	}
+	return nil
+}
+
+// StartForCold 冰排开始释冷
+func (e *IceRaftRecord) StartForCold(c *dto.IceStartbleForColfTimReq, p *actions.DataPermission) error {
+	var err error
+
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	//查询冰排是否存在
+	for _, v := range c.Id {
+		var iceRaftRecordModel model.IceRaftRecord
+		err = e.Orm.Scopes(actions.Permission(iceRaftRecordModel.TableName(), p)).
+			First(&iceRaftRecordModel, v).Error
+		if err != nil {
+			e.Log.Errorf("db error: %s", err)
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return global.UpdateNotFoundOrNoPermissionErr
+			}
+			return global.UpdateFailedErr
+		}
+		iceRaftRecordModel.StartIceColdTime = model2.Time(time.Now())
+		updates := tx.Where("id = ?", iceRaftRecordModel.Id).Updates(&iceRaftRecordModel)
+		if err = updates.Error; err != nil {
+			e.Log.Errorf("db error: %s", err)
+			return global.UpdateFailedErr
+		}
+	}
+	return nil
+}

+ 167 - 41
app/admin/service/waybill.go

@@ -121,8 +121,8 @@ func (e *Waybill) GetPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count
 	db := e.Orm.Model(&data).
 		Scopes(
 			cDto.MakeCondition(c.GetNeedSearch()),
-			orStatus(c.Status),
 			actions.Permission(data.TableName(), p),
+			orStatus(c.Status),
 		).
 		Preload("CoolerBox").
 		Preload("Delivery").
@@ -151,7 +151,6 @@ func (e *Waybill) GetPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count
 func (e *Waybill) GetUserPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
 	var err error
 	var data model.Waybill
-
 	// 构建基础查询
 	db := e.Orm.Model(&data).
 		Scopes(
@@ -509,15 +508,45 @@ func (e *Waybill) UpdateStatus(c *dto.UpdateStatusReq, p *actions.DataPermission
 			e.Log.Errorf("db error: %s", err)
 			return global.UpdateFailedErr
 		}
+		// 查询任务
+		//var logistics model.WaybillLogistics
+		//err = tx.Model(&logistics).Where("waybill_no = ? and status = ?", waybillModel.WaybillNo, model.WaybillStatusInDeliverys).
+		//	Last(&logistics).Error
+		//if err != nil {
+		//	if errors.Is(err, gorm.ErrRecordNotFound) {
+		//		// 添加物流
+		//		logisticsObj := model.WaybillLogistics{
+		//			WaybillNo: waybillModel.WaybillNo,
+		//			Status:    waybillModel.Status,
+		//			ControlBy: model2.ControlBy{
+		//				CreateBy: p.UserId,
+		//			},
+		//			DeptBy: model2.DeptBy{
+		//				DeptId: p.DeptId,
+		//			},
+		//		}
+		//		err = tx.Create(&logisticsObj).Error
+		//		if err != nil {
+		//			e.Log.Errorf("db error: %s", err)
+		//			return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+		//		}
+		//	} else {
+		//		e.Log.Errorf("db error: %s", err)
+		//		return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+		//	}
+		//}
+		//err = tx.Save(&logistics).Error
+		//if err != nil {
+		//	e.Log.Errorf("db error: %s", err)
+		//	return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+		//}
 	}
-
 	//err = tx.Save(&waybillModel).Error
 	//if err != nil {
 	//	e.Log.Errorf("db error: %s", err)
 	//	return global.UpdateFailedErr
 	//}
 
-	//c.Id = waybillModel.Id
 	return nil
 }
 
@@ -635,6 +664,46 @@ func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission)
 			waybillModel.IceRaftCode = c.IceRaftCode
 			if c.Status == model.WaybillStatusInShippeds {
 				waybillModel.Status = c.Status
+				// 配送中状态下才发送短信
+				if waybillModeStatus == model.WaybillStatusInShippeds {
+					ss := sms.NewSMS(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature)
+					addr := conf.ExtConfig.Applet.WaybillUrl + url.QueryEscape(lib.AesEncryptCBC(waybillModel.WaybillNo, lib.AesKey))
+					res, err1 := ss.SmsXSend(waybillModel.ConsigneeAddressPhone, addr)
+					if err1 != nil || res.Status != sms.SUCCESS {
+						e.Log.Errorf("派单短信发送失败", zap.Any("res", res), zap.Error(err1))
+						err = errors.New("派单短信发送失败,请检查收件人电话是否正确!")
+						return err
+					}
+					waybillModel.SendLog = model.WaybillSendLog{
+						Phone:   waybillModel.ConsigneeAddressPhone,
+						Content: "【冷链送药追溯平台】您的运单正在派送中,点击查看详情:" + addr,
+					}
+				}
+				// 查询任务
+				var logistics model.WaybillLogistics
+				// 添加物流
+				logisticsObj := model.WaybillLogistics{
+					WaybillNo:   waybillModel.WaybillNo,
+					Status:      waybillModel.Status,
+					CoolerBoxId: coolerBox.Id,
+					ControlBy: model2.ControlBy{
+						CreateBy: p.UserId,
+					},
+					DeptBy: model2.DeptBy{
+						DeptId: p.DeptId,
+					},
+				}
+				err = tx.Create(&logisticsObj).Error
+				if err != nil {
+					e.Log.Errorf("db error: %s", err)
+					return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+				}
+				logistics.CoolerBoxId = coolerBox.Id
+				err = tx.Save(&logistics).Error
+				if err != nil {
+					e.Log.Errorf("db error: %s", err)
+					return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+				}
 			}
 			err = tx.Save(&waybillModel).Error
 			if err != nil {
@@ -644,7 +713,7 @@ func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission)
 
 			// 查询任务
 			var logistics model.WaybillLogistics
-			err = tx.Model(&logistics).Where("waybill_no = ? and status = ?", waybillModel.WaybillNo, model.WaybillStatusInDeliverys).
+			err = tx.Model(&logistics).Where("waybill_no = ?", waybillModel.WaybillNo).
 				Last(&logistics).Error
 			if err != nil {
 				if errors.Is(err, gorm.ErrRecordNotFound) {
@@ -669,14 +738,13 @@ func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission)
 					e.Log.Errorf("db error: %s", err)
 					return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
 				}
+				logistics.CoolerBoxId = coolerBox.Id
+				err = tx.Save(&logistics).Error
+				if err != nil {
+					e.Log.Errorf("db error: %s", err)
+					return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
+				}
 			}
-			logistics.CoolerBoxId = coolerBox.Id
-			err = tx.Save(&logistics).Error
-			if err != nil {
-				e.Log.Errorf("db error: %s", err)
-				return errors.New(fmt.Sprintf("保存运单物流信息失败:%s", err))
-			}
-
 			// 查询任务
 			var task model.WaybillTask
 			err = tx.Model(&task).Where("waybill_no = ? ", waybillModel.WaybillNo).
@@ -706,38 +774,18 @@ func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission)
 					e.Log.Errorf("db error: %s", err)
 					return errors.New(fmt.Sprintf("查询运单任务信息失败:%s", err))
 				}
+				task.StartTime = model2.Time(time.Now())
+				task.UpdateBy = p.UserId
+				task.CoolerBoxId = coolerBox.Id
+				task.Sn = coolerBox.Sn
+				err = tx.Save(&task).Error
+				if err != nil {
+					e.Log.Errorf("db error: %s", err)
+					return errors.New(fmt.Sprintf("保存运单任务信息失败:%s", err))
+				}
 			}
-
-			task.StartTime = model2.Time(time.Now())
-			task.UpdateBy = p.UserId
-			task.CoolerBoxId = coolerBox.Id
-			task.Sn = coolerBox.Sn
-			err = tx.Save(&task).Error
-			if err != nil {
-				e.Log.Errorf("db error: %s", err)
-				return errors.New(fmt.Sprintf("保存运单任务信息失败:%s", err))
-			}
-
-		}
-
-		// 待配送时状态下才发送短信 ------目前不需要发送短信
-		if waybillModeStatus == model.WaybillStatusInDeliverys {
-			ss := sms.NewSMS(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature)
-			addr := conf.ExtConfig.Applet.WaybillUrl + url.QueryEscape(lib.AesEncryptCBC(waybillModel.WaybillNo, lib.AesKey))
-			res, err1 := ss.SmsXSend(waybillModel.ConsigneeAddressPhone, addr)
-			if err1 != nil || res.Status != sms.SUCCESS {
-				e.Log.Errorf("派单短信发送失败", zap.Any("res", res), zap.Error(err1))
-				err = errors.New("派单短信发送失败,请检查收件人电话是否正确!")
-				return err
-			}
-			//waybillModel.SendLog = model.WaybillSendLog{
-			//	Phone:   waybillModel.ConsigneeAddressPhone,
-			//	Content: "【冷链送药追溯平台】您的运单正在派送中,点击查看详情:" + addr,
-			//}
 		}
-
 	}
-
 	return nil
 }
 
@@ -1460,3 +1508,81 @@ func (e *Waybill) InsertByOrderId(c *dto.WeianGetWaybillNoReq) error {
 	return nil
 
 }
+
+// CreateSole 生成唯一订单编号
+func (e *Waybill) CreateSole() (string, error) {
+	var waybill model.Waybill
+	var err error
+	var count int64
+	format := time.Now().Format("20060102")
+	un := time.Now().Unix()
+	waybillno := fmt.Sprintf("%v%v", format, un)
+	err = e.Orm.Model(&waybill).Where("waybill_no = ?", waybillno).Count(&count).Error
+	if count > 0 {
+		return e.CreateSole()
+	}
+	if err != nil {
+		e.Log.Errorf("生成订单号错误: %s", err)
+		err = errors.New("生成订单号错误,请重新生成")
+		return "", err
+	}
+	return waybillno, nil
+}
+
+// WaybillTurnarounds 订单转门店
+func (e *Waybill) WaybillTurnarounds(c *dto.WaybillTurnarounds, p *actions.DataPermission) error {
+	var err error
+	var waybillModel model.Waybill
+	var count int64
+	//查询订单是否存在
+	tx := e.Orm.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
+		Where("waybill_no = ?", c.WaybillNo).
+		First(&waybillModel).Count(&count).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundOrNoPermissionErr
+		}
+		return global.GetFailedErr
+	}
+	if count == 0 {
+		return errors.New("订单不存在")
+	}
+	//查询门店是否存在可以转换
+	var data model.SysDept
+	var Depts []model.SysDept
+	err = e.Orm.Model(&data).
+		Scopes(
+			CompanyIdScopesUser(p.DeptId),
+		).Find(&Depts).Error
+	if err != nil {
+		e.Log.Errorf("db error: %s", err)
+		return global.GetFailedErr
+	}
+	contains := false
+	for _, v := range Depts {
+		if v.Id == c.DeptId {
+			contains = true
+		} else {
+			contains = false
+		}
+	}
+	if !contains {
+		return errors.New("转门店不存在")
+	}
+	waybillModel.DeptId = c.DeptId
+	update := tx.Updates(&waybillModel)
+	if update.Error != nil {
+		e.Log.Errorf("db error: %s", update.Error)
+		return global.UpdateFailedErr
+	}
+	return nil
+}

+ 16 - 0
common/global/websocket.go

@@ -0,0 +1,16 @@
+package global
+
+import (
+	"github.com/gorilla/websocket"
+	"net/http"
+)
+
+// Upgrader WebSocket 升级器
+var Upgrader = websocket.Upgrader{
+	ReadBufferSize:  1024,
+	WriteBufferSize: 1024,
+	// 允许所有来源的连接
+	CheckOrigin: func(r *http.Request) bool {
+		return true
+	},
+}

+ 49 - 0
common/lib/wgs84ToGcj02.go

@@ -0,0 +1,49 @@
+package lib
+
+import "math"
+
+const (
+	a  = 6378245.0          // 长半轴
+	ee = 0.0066934216229659 // 扁率
+)
+
+// 判断是否在中国范围外
+func outOfChina(lng, lat float64) bool {
+	return !(lng > 72.004 && lng < 137.8347 && lat > 0.8293 && lat < 55.8271)
+}
+
+// 计算纬度偏差
+func transformLat(x, y float64) float64 {
+	ret := -100.0 + 2.0*x + 3.0*y + 0.2*y*y + 0.1*x*y + 0.2*math.Sqrt(math.Abs(x))
+	ret += (20.0*math.Sin(6.0*x*(math.Pi)) + 20.0*math.Sin(2.0*x*(math.Pi))) * 2.0 / 3.0
+	ret += (20.0*math.Sin(y*(math.Pi)) + 40.0*math.Sin(y/3.0*(math.Pi))) * 2.0 / 3.0
+	ret += (160.0*math.Sin(y/12.0*(math.Pi)) + 320.0*math.Sin(y/30.0*(math.Pi))) * 2.0 / 3.0
+	return ret
+}
+
+// 计算经度偏差
+func transformLon(x, y float64) float64 {
+	ret := 300.0 + x + 2.0*y + 0.1*x*x + 0.1*x*y + 0.1*math.Sqrt(math.Abs(x))
+	ret += (20.0*math.Sin(6.0*x*(math.Pi)) + 20.0*math.Sin(2.0*x*(math.Pi))) * 2.0 / 3.0
+	ret += (20.0*math.Sin(x*(math.Pi)) + 40.0*math.Sin(x/3.0*(math.Pi))) * 2.0 / 3.0
+	ret += (150.0*math.Sin(x/12.0*(math.Pi)) + 300.0*math.Sin(x/30.0*(math.Pi))) * 2.0 / 3.0
+	return ret
+}
+
+// WGS-84 转 GCJ-02
+func Wgs84ToGcj02(lng, lat float64) (float64, float64) {
+	if outOfChina(lng, lat) {
+		return lng, lat
+	}
+	dLat := transformLat(lng-105.0, lat-35.0)
+	dLng := transformLon(lng-105.0, lat-35.0)
+	radLat := lat / 180.0 * math.Pi
+	magic := math.Sin(radLat)
+	magic = 1 - ee*magic*magic
+	sqrtMagic := math.Sqrt(magic)
+	dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * math.Pi)
+	dLng = (dLng * 180.0) / (a / sqrtMagic * math.Cos(radLat) * math.Pi)
+	mgLat := lat + dLat
+	mgLng := lng + dLng
+	return mgLng, mgLat
+}

+ 1 - 0
common/middleware/header.go

@@ -23,6 +23,7 @@ func Options(c *gin.Context) {
 	if c.Request.Method != "OPTIONS" {
 		c.Next()
 	} else {
+		c.Header("Access-Control-Allow-Credentials", "true")
 		c.Header("Access-Control-Allow-Origin", "*")
 		c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
 		c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept, X-Token, serviceId")

+ 6 - 2
common/middleware/openapi.go

@@ -6,6 +6,7 @@ import (
 	"crypto/sha256"
 	"encoding/hex"
 	"errors"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
 	"net/http"
@@ -17,7 +18,6 @@ const apiKeyHeader = "X-API-KEY"
 const apiSignatureHeader = "X-API-SIGNATURE"
 const apiTimestampHeader = "X-API-TIMESTAMP"
 
-
 // 验证签名是否有效
 func isValidSignature(apiKey, signature, timestamp string) bool {
 	// 使用提供的 API Key 查找对应的 API Secret
@@ -31,7 +31,11 @@ func isValidSignature(apiKey, signature, timestamp string) bool {
 	mac := hmac.New(sha256.New, []byte(secret))
 	mac.Write([]byte(message))
 	expectedSignature := hex.EncodeToString(mac.Sum(nil))
-
+	fmt.Println("apiKey:", apiKey)
+	fmt.Println("secret:", secret)
+	fmt.Println("时间戳:", timestamp)
+	fmt.Println("生成的签名:", expectedSignature)
+	fmt.Println("传递的签名:", signature)
 	// 验证客户端提供的签名是否与预期签名匹配
 	return hmac.Equal([]byte(signature), []byte(expectedSignature))
 }

+ 108 - 1
common/nats/nats_server/NatsColdApi.go

@@ -159,7 +159,7 @@ func Cold_ReadDeviceDataListBy_T_snidForLocus(T_snid, startTime, endTime string,
 	}
 	b, _ := msgpack.Marshal(&t_Req)
 
-	msg, err := nats.Nats.Request("Cold_ReadDeviceDataListBy_T_snid", b, 3*time.Second)
+	msg, err := nats.Nats.Request("Cold_ReadDeviceDataListBy_T_snid", b, 120*time.Second)
 	if err != nil {
 		return
 	}
@@ -276,3 +276,110 @@ func Cold_ReadDeviceByT_sn(T_sn string) (data Device, err error) {
 
 	return data, nil
 }
+func Read_DeviceTask_List_By_Condition(T_sn string) (data DeviceTask, err error) {
+	type T_R struct {
+		Code int16      `xml:"Code"`
+		Msg  string     `xml:"Msg"`
+		Data DeviceTask `xml:"Data"` // 泛型
+	}
+	type T_Req struct {
+		T_sn string `xml:"T_sn"`
+	}
+	if len(T_sn) == 0 {
+		err = errors.New("sn不能为空!")
+		return
+	}
+	t_req := T_Req{
+		T_sn: T_sn,
+	}
+	b, _ := msgpack.Marshal(&t_req)
+	msg, err := nats.Nats.Request("Read_DeviceTask_List_By_Condition", b, 3*time.Second)
+	if err != nil {
+		return
+	}
+	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
+	}
+	data = t_R.Data
+	return data, nil
+}
+func Read_New_DeviceData(T_sn string, T_id int) (data DeviceSensor, err error) {
+	type T_R struct {
+		Code int16        `xml:"Code"`
+		Msg  string       `xml:"Msg"`
+		Data DeviceSensor `xml:"Data"` // 泛型
+	}
+	type T_Req struct {
+		T_sn string `xml:"T_sn"`
+		T_id int    `xml:"T_id"`
+	}
+	if len(T_sn) == 0 {
+		err = errors.New("sn不能为空!")
+		return
+	}
+	t_req := T_Req{
+		T_sn: T_sn,
+		T_id: T_id,
+	}
+	b, _ := msgpack.Marshal(&t_req)
+	msg, err := nats.Nats.Request("Read_New_DeviceData", b, 3*time.Second)
+	if err != nil {
+		return
+	}
+	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
+	}
+	data = t_R.Data
+	return data, nil
+}
+func Read_Start_Time_DeviceData(T_sn string, T_id int, StartTime, EndTime string) (data []DeviceData_, err error) {
+	type T_R struct {
+		Code int16         `xml:"Code"`
+		Msg  string        `xml:"Msg"`
+		Data []DeviceData_ `xml:"Data"` // 泛型
+	}
+	type T_Req struct {
+		T_sn      string `xml:"T_sn"`
+		T_id      int    `xml:"T_id"`
+		StartTime string `xml:"StartTime"`
+		EndTime   string `xml:"EndTime"`
+	}
+	if len(T_sn) == 0 {
+		err = errors.New("sn不能为空!")
+		return
+	}
+	t_req := T_Req{
+		T_sn:      T_sn,
+		T_id:      T_id,
+		StartTime: StartTime,
+		EndTime:   EndTime,
+	}
+	b, _ := msgpack.Marshal(&t_req)
+	msg, err := nats.Nats.Request("Read_Start_Time_DeviceData", b, 3*time.Second)
+	if err != nil {
+		return
+	}
+	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
+	}
+	data = t_R.Data
+	return data, nil
+}

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

@@ -2,6 +2,7 @@ package nats_server
 
 import (
 	"database/sql/driver"
+	"encoding/json"
 	"fmt"
 	"time"
 )
@@ -70,6 +71,47 @@ type DeviceData_ struct {
 	T_time time.Time // 采集时间
 }
 
+func (ab *DeviceData_) MarshalJSON() ([]byte, error) {
+	loc, _ := time.LoadLocation("Asia/Shanghai")
+	type Alias DeviceData_
+	return json.Marshal(&struct {
+		T_time string `json:"T_time,omitempty"`
+		*Alias
+	}{
+		T_time: ab.T_time.In(loc).Format("2006-01-02 15:04:05"),
+		Alias:  (*Alias)(ab),
+	})
+}
+
+type DeviceSensor struct {
+	Id   int    `orm:"column(ID);size(11);auto;pk"`
+	T_sn string `orm:"index;size(256);null"` // 设备序列号 KF开头,环境监测主机。 YD开头,温途监测主机
+	T_id int    `orm:"index;size(11);null"`  // 传感器编号
+	T_sp int    `orm:"size(11);null"`        // 传感器参数id
+
+	T_name string `orm:"size(256);null"` // 标题
+
+	T_pid      int    `orm:"index;size(256);null"`     // Account.Company 绑定公司
+	T_Class    string `orm:"size(256);null"`           // Device.DeviceClass.Id 设备分类  C1|C2|
+	T_Notice   string `orm:"size(256);null"`           // 通知绑定
+	T_datashow int    `orm:"size(2);default(1)"`       // 0 屏蔽数据展示  1 正常数据展示   (屏蔽后 数据展示无法看到,设备管理中 不受影响)
+	T_sort     int    `orm:"size(200);default(1)"`     // 排序
+	T_3dview   string `orm:"size(256);null"`           // 3D 视图ID
+	T_type     int    `orm:"size(4);null"`             // Device.DeviceSensorType  1库房   2移动
+	T_link     int    `orm:"size(4);default(1)"`       // 0:断开/故障 1连接 实时数据
+	T_State    int    `orm:"index;size(2);default(1)"` // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
+
+	// 设备同步参数
+	T_Dattery  int    `orm:"size(4);null"`       // 电量
+	T_Site     string `orm:"size(200);null"`     // GPS
+	T_monitor  int    `orm:"size(2);null"`       // 监控状态 0 未监控 1 监控
+	T_online   int    `orm:"size(2);default(1)"` // 在线状态 0 未启用  1 在线  2 离线
+	T_online_s int    `orm:"size(2);default(0)"` // 在线状态-备用  0 未启用  1 在线  2 离线
+
+	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
+	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
+}
+
 type DeviceData_R struct {
 	T_sn   string  // sn
 	T_id   int     // 传感器id
@@ -190,3 +232,17 @@ type Device struct {
 	CreateTime time.Time //auto_now_add 第一次保存时才设置时间
 	UpdateTime time.Time //auto_now 每次 model 保存时都会对时间自动更新
 }
+
+// 设备任务
+type DeviceTask struct {
+	Id         int       `orm:"column(ID);size(11);auto;pk"`
+	T_sn       string    `orm:"size(256);null"`        // 设备序列号 KF开头,环境监测主机。 YD开头,温途监测主机
+	T_Ut_start time.Time `orm:"type(timestamp);null;"` // 采集时间
+	T_Ut_end   time.Time `orm:"type(timestamp);null;"` // 采集时间
+
+	T_Ut    time.Time `orm:"type(timestamp);null;"` // 采集时间
+	T_State int       `orm:"size(2);default(1)"`
+	//  1   start:开始监测任务,
+	//  2   stop:结束监测任务,
+	//  3   print:中途打印任务
+}

+ 1 - 0
go.mod

@@ -77,6 +77,7 @@ require (
 	github.com/goccy/go-json v0.10.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/golang/snappy v0.0.1 // indirect
+	github.com/gorilla/websocket v1.5.3 // indirect
 	github.com/henrylee2cn/ameda v1.4.10 // indirect
 	github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect
 	github.com/imdario/mergo v0.3.9 // indirect

+ 2 - 0
go.sum

@@ -311,6 +311,8 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
 github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=

+ 8 - 4
setting.yml

@@ -32,10 +32,10 @@ settings:
     # 数据库类型 mysql
     driver: mysql
     # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms
-    source: cold-delivery:SRxDd5TK3xtPTKxw@tcp(192.168.11.77:3306)/cold-delivery?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
-  cache:
+    source: root:mysql_5xGzBc@tcp(182.43.247.65:3306)/cold_delivery?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
+#    source: cold_delivery:yjwyEckZS7rE5H!@tcp(182.44.114.135:3306)/cold_delivery?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
     redis:
-      addr: 192.168.11.77:6379
+      addr: 182.44.113.60:6379
       password:
       db: 4
     # key存在即可
@@ -55,11 +55,15 @@ settings:
       tokenExpire: 30
       waybillUrl: "https://coldlogistics.coldbaozhida.com/newInquiry?waybillNo="
     nats:
-      url: "127.0.0.1:43422"
+#      url: "182.44.113.60:4222"
+      url: "203.34.49.130:4222"
     amap:
       key: "c3dbf424f12240b2de8ace32893c1aa2"
     apk:
       path: "/Users/zoie/work/bzd_project/cold-delivery/ofile"
     weian:
       orderInfoUrl: "http://127.0.0.1:4523/m2/4530431-0-default/215455750"
+    openapi:
+      apiKey: "01HsBYiG"
+      secret: "A8CDJ1GQW4XNB3SZY7PKT92R6LQV8FW5"