Explorar o código

fit:
1. dtgateway数据接口签名中间件
2. 验证ts的时间窗口为10s,请注意客户端与数据中心的时区问题
3. 增加app_info数据表, 管理app数据及客户端签名key
4. 统一数据响应到commonResponse

gaoyagang hai 1 ano
pai
achega
d4f757cd3c

+ 10 - 9
app/cmd/dtgateway/desc/dtgateway.api

@@ -7,40 +7,41 @@ import (
 @server(
 	prefix: api/dtgateway/v1
 	group: dtgateway
+	middleware: DataSign
 )
 service dtgateway {
 	@doc "查询working uf信息"
 	@handler WorkingUf
 	get /working-uf/info (DcWorkingReq) returns (CommonResponse)
-	
+
 	@doc "查询working ro信息"
 	@handler WorkingRo
 	get /working-ro/info (DcWorkingReq) returns (CommonResponse)
-	
+
 	@doc "查询working chest信息"
 	@handler WorkingChest
 	get /working-chest/info (DcWorkingReq) returns (CommonResponse)
-	
+
 	@doc "查询working pump信息"
 	@handler WorkingPump
 	get /working-pump/info (DcWorkingReq) returns (CommonResponse)
-	
+
 	@doc "查询working valve信息"
 	@handler WorkingValve
 	get /working-valve/info (DcWorkingReq) returns (CommonResponse)
-	
+
 	@doc "秒级单点数据批量入库"
 	@handler ItemHistoryDataMultiAdd
-	post /item-history/multi-add (MultiAddItemHistoryDataReq) returns (MultiAddItemHistoryDataResq)
-	
+	post /item-history/multi-add (MultiAddItemHistoryDataReq) returns (CommonResponse)
+
 	@doc "点位历史数据查询"
 	@handler ItemHistoryDataList
 	get /item-history/list (ItemHistoryDataListReq) returns (CommonResponse)
-	
+
 	@doc "按时间点位历史数据查询"
 	@handler ItemHistoryDataInfo
 	get /item-history/info (ItemHistoryDataByTimeReq) returns (CommonResponse)
-	
+
 	@doc "按时间点位历史数据最大值最小值查询"
 	@handler ItemHistoryDataMaxMin
 	get /item-history/max-min (ItemHistoryDataMaxMinByTimeReq) returns (CommonResponse)

+ 10 - 152
app/cmd/dtgateway/desc/dtgateway/dtgateway.api

@@ -1,126 +1,11 @@
 syntax = "v1"
 
-type DcWorkingUf{
-    Id               int64         `json:"id"`
-    ProjectId        int64         `json:"project_id"`
-    DeviceCode       string        `json:"device_code"`
-    WaterTemperature float64       `json:"water_temperature"` // 水温 摄氏度
-    FeedFlow         float64       `json:"feed_flow"`         // 进水流量
-    ConFlow          float64       `json:"con_flow"`          // 浓水流量
-    ProductFlow      float64       `json:"product_flow"`      // 产水流量
-    FeedPressure     float64       `json:"feed_pressure"`     // 进水压力
-    ConPressure      float64       `json:"con_pressure"`      // 浓水压力
-    ProductPressure  float64       `json:"product_pressure"`  // 产水压力
-    Tmp              float64       `json:"tmp"`               // 跨膜压差
-    Flux             float64       `json:"flux"`              // 膜通量
-    FeedWqTurbidity  float64       `json:"feed_wq_turbidity"` // 进水浊度
-    FeedWqPh         int64         `json:"feed_wq_ph"`        // 进水 PH 值
-    ProductWqPh      int64         `json:"product_wq_ph"`     // 产水 PH 值
-    FeedWqAl         float64       `json:"feed_wq_al"`        // 进水水质:铝
-    ProductWqAl      float64       `json:"product_wq_al"`     // 产水水质:铝
-    FeedWqFe         float64       `json:"feed_wq_fe"`        // 进水水质:铁
-    ProductWqFe      float64       `json:"product_wq_fe"`     // 产水水质:铁
-    FeedWqMn         float64       `json:"feed_wq_mn"`        // 进水水质:锰
-    ProductWqMn      float64       `json:"product_wq_mn"`     // 产水水质:锰
-    FeedWqSio2       float64       `json:"feed_wq_sio2"`      // 进水水质:二氧化硅
-    ProductWqSio2    float64       `json:"product_wq_sio2"`   // 产水水质:二氧化硅
-    FeedWqCod        float64       `json:"feed_wq_cod"`       // 进水水质:COD
-    ProductWqCod     float64       `json:"product_wq_cod"`    // 产水水质:COD
-    FeedWqP          float64       `json:"feed_wq_p"`         // 进水水质:磷
-    ProductWqP       float64       `json:"product_wq_p"`      // 产水水质:磷
-    Step             int64         `json:"step"`              // 设备当前步序值
-    CTime            string        `json:"c_time"`
-}
-
-type DcWorkingRo{
-    Id                 int64         `json:"id"`
-    ProjectId          int64         `json:"project_id"`
-    DeviceCode         string        `json:"device_code"`
-    WaterTemperature   float64       `json:"water_temperature"`    // 水温 摄氏度
-    FeedFlow1St        float64       `json:"feed_flow_1st"`        // 一段进水流量
-    ConFlow1St         float64       `json:"con_flow_1st"`         // 一段浓水流量
-    ProductFlow1St     float64       `json:"product_flow_1st"`     // 一段产水流量
-    FeedPressure1St    float64       `json:"feed_pressure_1st"`    // 一段进水压力
-    ConPressure1St     float64       `json:"con_pressure_1st"`     // 一段浓水压力
-    ProductPressure1St float64       `json:"product_pressure_1st"` // 一段产水压力
-    Tmp1St             float64       `json:"tmp_1st"`              // 一段跨膜压差
-    Flux1St            float64       `json:"flux_1st"`             // 一段膜通量
-    Permeability1St    float64       `json:"permeability_1st"`     // 一段渗透率
-    FeedFlow2Nd        float64       `json:"feed_flow_2nd"`        // 二段进水流量
-    ConFlow2Nd         float64       `json:"con_flow_2nd"`         // 二段浓水流量
-    ProductFlow2Nd     float64       `json:"product_flow_2nd"`     // 二段产水流量
-    FeedPressure2Nd    float64       `json:"feed_pressure_2nd"`    // 二段进水压力
-    ConPressure2Nd     float64       `json:"con_pressure_2nd"`     // 二段浓水压力
-    ProductPressure2Nd float64       `json:"product_pressure_2nd"` // 二段产水压力
-    Tmp2Nd             float64       `json:"tmp_2nd"`              // 二段压差
-    Flux2Nd            float64       `json:"flux_2nd"`             // 二段通量
-    Permeability2Nd    float64       `json:"permeability_2nd"`     // 二段渗透率
-    FeedFlow3Th        float64       `json:"feed_flow_3th"`        // 三段进水流量
-    ConFlow3Th         float64       `json:"con_flow_3th"`         // 三段浓水流量
-    ProductFlow3Th     float64       `json:"product_flow_3th"`     // 三段产水流量
-    FeedPressure3Th    float64       `json:"feed_pressure_3th"`    // 三段进水压力
-    ConPressure3Th     float64       `json:"con_pressure_3th"`     // 三段浓水压力
-    ProductPressure3Th float64       `json:"product_pressure_3th"` // 三段产水压力
-    Tmp3Th             float64       `json:"tmp_3th"`              // 三段压差
-    Flux3Th            float64       `json:"flux_3th"`             // 三段通量
-    Permeability3Th    float64       `json:"permeability_3th"`     // 三段渗透率
-    FeedWqTurbidity    float64       `json:"feed_wq_turbidity"`    // 进水浊度
-    FeedWqPh           int64         `json:"feed_wq_ph"`           // 进水 PH 值
-    ProductWqPh        int64         `json:"product_wq_ph"`        // 产水 PH 值
-    FeedWqAl           float64       `json:"feed_wq_al"`           // 进水水质:铝
-    ProductWqAl        float64       `json:"product_wq_al"`        // 产水水质:铝
-    FeedWqFe           float64       `json:"feed_wq_fe"`           // 进水水质:铁
-    ProductWqFe        float64       `json:"product_wq_fe"`        // 产水水质:铁
-    FeedWqMn           float64       `json:"feed_wq_mn"`           // 进水水质:锰
-    ProductWqMn        float64       `json:"product_wq_mn"`        // 产水水质:锰
-    FeedWqSio2         float64       `json:"feed_wq_sio2"`         // 进水水质:二氧化硅
-    ProductWqSio2      float64       `json:"product_wq_sio2"`      // 产水水质:二氧化硅
-    FeedWqCod          float64       `json:"feed_wq_cod"`          // 进水水质:COD
-    ProductWqCod       float64       `json:"product_wq_cod"`       // 产水水质:COD
-    FeedWqP            float64       `json:"feed_wq_p"`            // 进水水质:磷
-    ProductWqP         float64       `json:"product_wq_p"`         // 产水水质:磷
-    Step               int64         `json:"step"`                 // 设备当前步序值
-    CTime              string        `json:"c_time"`
-}
-
-type DcWorkingChest {
-    Id                  int64     `json:"id"`
-    ProjectId           int64     `json:"project_id"`
-    DeviceCode          string    `json:"device_code"`
-    Switch              int64     `json:"switch"`                // 药箱液位开关 0: 关 1: 开
-    Level               float64   `json:"level"`                 // 液位高度
-    AgitatorStatus      int64     `json:"agitator_status"`       // 搅拌器运行状态 0: 未运行 1:运行中
-    AgitatorDuration    int64     `json:"agitator_duration"`     // 搅拌器运行时长
-    AgitatorFaultStatus int64     `json:"agitator_fault_status"` // 搅拌器故障状态 0:正常 1:故障
-    CTime               string    `json:"c_time"`
-}
-
-type DcWorkingPump {
-    Id           int64     `json:"id"`
-    ProjectId    int64     `json:"project_id"`
-    DeviceCode   string    `json:"device_code"`
-    FeedPressure float64   `json:"feed_pressure"` // 进水压力
-    OutPressure  float64   `json:"out_pressure"`  // 出水压力
-    Duration     int64     `json:"duration"`      // 运行时长 单位 s
-    Current      float64   `json:"current"`       // 运行电流
-    Frequency    float64   `json:"frequency"`     // 运行频率
-    Lift         float64   `json:"lift"`          // 工作扬程
-    Efficiency   float64   `json:"efficiency"`    // 运行效率
-    RunStatus    int64     `json:"run_status"`    // 运行状态 0: 停机 1: 运行正常
-    FaultStatus  int64     `json:"fault_status"`  // 故障状态 0: 正常 1: 故障
-    CTime        string    `json:"c_time"`
-}
-
-type DcWorkingValve {
-    Id          int64     `json:"id"`
-    ProjectId   int64     `json:"project_id"`
-    DeviceCode  string    `json:"device_code"`
-    Adjust      int64     `json:"adjust"`       // 是否为调节阀门 0: 否 1: 是
-    Opening     float64   `json:"opening"`      // 当前阀门的开度
-    Closed      int64     `json:"closed"`       // 关到位 全关  0: 否 1: 是
-    Opened      int64     `json:"opened"`       // 开到位 开到 设置的开度 0: 否 1: 是
-    FaultStatus int64     `json:"fault_status"` // 是否故障 0: 否 1: 是
-    CTime       string    `json:"c_time"`
+type CommonParams {
+    Ts        int64  `form:"ts"`
+    ProjectId int64  `form:"project_id"`
+    Sign      string `form:"sign"`
+    SignFlag  uint8  `form:"sign_flag,optional"`
+    AppName   string `header:"APP-NAME"`
 }
 
 type CommonResponse {
@@ -129,32 +14,14 @@ type CommonResponse {
     Data interface{} `json:"data,omitempty"`
 }
 
-
 type (
     DcWorkingReq{
         ProjectId           int64       `form:"project_id"`
         DeviceCode          string      `form:"device_code"`
     }
-    WorkingUfResp{
-        Info    *DcWorkingUf    `json:"info"`
-    }
-    WorkingRoResp{
-        Info    *DcWorkingRo    `json:"info"`
-    }
-    WorkingChestResp{
-        Info    *DcWorkingChest    `json:"info"`
-    }
-    WorkingValveResp{
-        Info    *DcWorkingValve    `json:"info"`
-    }
-    WorkingPumpResp{
-        Info    *DcWorkingPump    `json:"info"`
-    }
-)
 
-type (
     ItemHistoryData {
-        ProjectId   int64     `json:"project_id"`
+        CommonParams
         ItemName    string    `json:"item_name"`
         Val         float64   `json:"val"`
         HTime       string    `json:"h_time"`
@@ -164,12 +31,8 @@ type (
         List    []*ItemHistoryData  `json:"list"`
     }
 
-    MultiAddItemHistoryDataResq{}
-)
-
-type (
     ItemHistoryDataListReq{
-        ProjectId   int64     `form:"project_id"`
+        CommonParams
         ItemName    string    `form:"item_name"`
         Size        int64     `form:"size"`         //结果间隔
         Interval    string    `form:"interval"`     //时间单位 s,minute,h,day
@@ -179,22 +42,17 @@ type (
     }
 
     ItemHistoryDataByTimeReq{
-        ProjectId   int64     `form:"project_id"`
+        CommonParams
         ItemName    string    `form:"item_name"`
         STime       string    `form:"stime"`
         ETime       string    `form:"etime"`
     }
 
     ItemHistoryDataMaxMinByTimeReq{
-        ProjectId   int64     `form:"project_id"`
+        CommonParams
         ItemName    string    `form:"item_name"`
         STime       string    `form:"stime"`
         ETime       string    `form:"etime"`
     }
-
-    ItemHistoryDataMaxMinByTimeResq{
-        MaxVal    float64     `json:"max_val"`
-        MinVal    float64     `json:"min_val"`
-    }
 )
 

+ 0 - 4
app/cmd/dtgateway/dtgateway.go

@@ -1,7 +1,6 @@
 package main
 
 import (
-	"GtDataStore/common/middleware"
 	"flag"
 	"fmt"
 
@@ -24,9 +23,6 @@ func main() {
 	server := rest.MustNewServer(c.RestConf)
 	defer server.Stop()
 
-	ipWhiteList := []string{"127.0.0.1/32", "47.96.12.136/32", "120.55.44.4/32", "58.214.245.78/32"}
-	server.Use(middleware.WhiteListCheck(ipWhiteList))
-
 	ctx := svc.NewServiceContext(c)
 	handler.RegisterHandlers(server, ctx)
 

+ 4 - 0
app/cmd/dtgateway/etc/dtgateway.test.yaml

@@ -17,6 +17,10 @@ Log:
   Mode: console
   Level: error
 
+DtDataStoreDB:
+  #  DataSource: ws_data:c712f89fc4f8edaf30e41b828f4e3d26@tcp(192.168.60.201:4000)/ws_data?charset=utf8mb4&parseTime=True&loc=&loc=Asia%2FShanghai
+  DataSource: ws_data:c712f89fc4f8edaf30e41b828f4e3d26@tcp(172.16.0.195:4000)/ws_data?charset=utf8mb4&parseTime=True&loc=&loc=Asia%2FShanghai
+
 #rpc service
 OrganizationRpcConf:
   Endpoints:

+ 4 - 0
app/cmd/dtgateway/etc/dtgateway.yaml

@@ -17,6 +17,10 @@ Log:
   Mode: console
   Level: error
 
+DtDataStoreDB:
+  #  DataSource: ws_data:c712f89fc4f8edaf30e41b828f4e3d26@tcp(192.168.60.201:4000)/ws_data?charset=utf8mb4&parseTime=True&loc=&loc=Asia%2FShanghai
+  DataSource: ws_data:c712f89fc4f8edaf30e41b828f4e3d26@tcp(172.16.0.195:4000)/ws_data?charset=utf8mb4&parseTime=True&loc=&loc=Asia%2FShanghai
+
 #rpc service
 #OrganizationRpcConf:
 #  Endpoints:

+ 4 - 0
app/cmd/dtgateway/internal/config/config.go

@@ -12,4 +12,8 @@ type Config struct {
 		AccessExpire int64
 	}
 	OrganizationRpcConf zrpc.RpcClientConf
+
+	DtDataStoreDB struct {
+		DataSource string
+	}
 }

+ 50 - 47
app/cmd/dtgateway/internal/handler/routes.go

@@ -12,53 +12,56 @@ import (
 
 func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	server.AddRoutes(
-		[]rest.Route{
-			{
-				Method:  http.MethodGet,
-				Path:    "/working-uf/info",
-				Handler: dtgateway.WorkingUfHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/working-ro/info",
-				Handler: dtgateway.WorkingRoHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/working-chest/info",
-				Handler: dtgateway.WorkingChestHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/working-pump/info",
-				Handler: dtgateway.WorkingPumpHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/working-valve/info",
-				Handler: dtgateway.WorkingValveHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodPost,
-				Path:    "/item-history/multi-add",
-				Handler: dtgateway.ItemHistoryDataMultiAddHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/item-history/list",
-				Handler: dtgateway.ItemHistoryDataListHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/item-history/info",
-				Handler: dtgateway.ItemHistoryDataInfoHandler(serverCtx),
-			},
-			{
-				Method:  http.MethodGet,
-				Path:    "/item-history/max-min",
-				Handler: dtgateway.ItemHistoryDataMaxMinHandler(serverCtx),
-			},
-		},
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.DataSign},
+			[]rest.Route{
+				{
+					Method:  http.MethodGet,
+					Path:    "/working-uf/info",
+					Handler: dtgateway.WorkingUfHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/working-ro/info",
+					Handler: dtgateway.WorkingRoHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/working-chest/info",
+					Handler: dtgateway.WorkingChestHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/working-pump/info",
+					Handler: dtgateway.WorkingPumpHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/working-valve/info",
+					Handler: dtgateway.WorkingValveHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/item-history/multi-add",
+					Handler: dtgateway.ItemHistoryDataMultiAddHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/item-history/list",
+					Handler: dtgateway.ItemHistoryDataListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/item-history/info",
+					Handler: dtgateway.ItemHistoryDataInfoHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodGet,
+					Path:    "/item-history/max-min",
+					Handler: dtgateway.ItemHistoryDataMaxMinHandler(serverCtx),
+				},
+			}...,
+		),
 		rest.WithPrefix("/api/dtgateway/v1"),
 	)
 }

+ 1 - 1
app/cmd/dtgateway/internal/logic/dtgateway/itemHistoryDataLogic.go

@@ -23,7 +23,7 @@ func NewItemHistoryDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *I
 	}
 }
 
-func (l *ItemHistoryDataLogic) ItemHistoryData(req *types.MultiAddItemHistoryDataReq) (resp *types.MultiAddItemHistoryDataResq, err error) {
+func (l *ItemHistoryDataLogic) ItemHistoryData(req *types.MultiAddItemHistoryDataReq) (resp *types.CommonResponse, err error) {
 	// todo: add your logic here and delete this line
 
 	return

+ 7 - 2
app/cmd/dtgateway/internal/logic/dtgateway/itemHistoryDataMultiAddLogic.go

@@ -4,6 +4,7 @@ import (
 	"GtDataStore/app/cmd/dtgateway/internal/svc"
 	"GtDataStore/app/cmd/dtgateway/internal/types"
 	"GtDataStore/app/cmd/organization/pb"
+	"GtDataStore/common/xerr"
 	"context"
 	"errors"
 
@@ -24,7 +25,7 @@ func NewItemHistoryDataMultiAddLogic(ctx context.Context, svcCtx *svc.ServiceCon
 	}
 }
 
-func (l *ItemHistoryDataMultiAddLogic) ItemHistoryDataMultiAdd(req *types.MultiAddItemHistoryDataReq) (resp *types.MultiAddItemHistoryDataResq, err error) {
+func (l *ItemHistoryDataMultiAddLogic) ItemHistoryDataMultiAdd(req *types.MultiAddItemHistoryDataReq) (resp *types.CommonResponse, err error) {
 	if len(req.List) == 0 {
 		return nil, errors.New("data list is empty")
 	}
@@ -47,5 +48,9 @@ func (l *ItemHistoryDataMultiAddLogic) ItemHistoryDataMultiAdd(req *types.MultiA
 		return nil, err
 	}
 
-	return &types.MultiAddItemHistoryDataResq{}, nil
+	return &types.CommonResponse{
+		Code: xerr.OK,
+		Msg:  xerr.MapErrMsg(xerr.OK),
+		Data: nil,
+	}, nil
 }

+ 1 - 1
app/cmd/dtgateway/internal/logic/dtgateway/workingChestLogic.go

@@ -23,7 +23,7 @@ func NewWorkingChestLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Work
 	}
 }
 
-func (l *WorkingChestLogic) WorkingChest(req *types.DcWorkingReq) (resp *types.WorkingChestResp, err error) {
+func (l *WorkingChestLogic) WorkingChest(req *types.DcWorkingReq) (resp *types.CommonResponse, err error) {
 	// todo: add your logic here and delete this line
 
 	return

+ 1 - 1
app/cmd/dtgateway/internal/logic/dtgateway/workingPumpLogic.go

@@ -23,7 +23,7 @@ func NewWorkingPumpLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Worki
 	}
 }
 
-func (l *WorkingPumpLogic) WorkingPump(req *types.DcWorkingReq) (resp *types.WorkingPumpResp, err error) {
+func (l *WorkingPumpLogic) WorkingPump(req *types.DcWorkingReq) (resp *types.CommonResponse, err error) {
 	// todo: add your logic here and delete this line
 
 	return

+ 1 - 1
app/cmd/dtgateway/internal/logic/dtgateway/workingValveLogic.go

@@ -23,7 +23,7 @@ func NewWorkingValveLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Work
 	}
 }
 
-func (l *WorkingValveLogic) WorkingValve(req *types.DcWorkingReq) (resp *types.WorkingValveResp, err error) {
+func (l *WorkingValveLogic) WorkingValve(req *types.DcWorkingReq) (resp *types.CommonResponse, err error) {
 	// todo: add your logic here and delete this line
 
 	return

+ 201 - 0
app/cmd/dtgateway/internal/middleware/datasignMiddleware.go

@@ -0,0 +1,201 @@
+package middleware
+
+import (
+	"GtDataStore/app/cmd/dtgateway/internal/config"
+	"GtDataStore/app/model"
+	"GtDataStore/common/crypto/md5"
+	"GtDataStore/common/utils"
+	"GtDataStore/common/xerr"
+	"bytes"
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+	"github.com/zeromicro/go-zero/rest/httpx"
+	"io/ioutil"
+	"k8s.io/apimachinery/pkg/util/json"
+	"net/http"
+	"net/url"
+	"sync"
+	"time"
+)
+
+const (
+	TIME_OUT                = 10 // ts时间窗口大小, 单位: 秒
+	S2_MIN_LENGTH           = 2048
+	S2_HEAD_LENGTH          = 200
+	S2_TAIL_LENGTH          = 200
+	APP_SECRET_CACHE_EXPIRE = 600
+)
+
+var (
+	appSecrets     = make(map[string]secretExpire)
+	appSecretsLock sync.Mutex
+)
+
+type (
+	secretExpire struct {
+		Secret string
+		Status int64
+		Expire time.Time
+	}
+
+	DataSignMiddleware struct {
+		AppInfo model.DcAppInfoModel
+	}
+
+	CommonParams struct {
+		Ts        int64  `form:"ts"`
+		ProjectId int64  `form:"project_id"`
+		Sign      string `form:"sign"`
+		SignFlag  uint8  `form:"sign_flag,optional"`
+		AppName   string `header:"APP-NAME"`
+	}
+)
+
+func NewDataSignMiddleware(conf config.Config) *DataSignMiddleware {
+	mysql := sqlx.NewMysql(conf.DtDataStoreDB.DataSource)
+	return &DataSignMiddleware{
+		AppInfo: model.NewDcAppInfoModel(mysql),
+	}
+}
+
+func (m *DataSignMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		cps := CommonParams{}
+		err := httpx.Parse(r, &cps)
+		if err != nil {
+			httpx.WriteJson(w, http.StatusOK, map[string]interface{}{
+				"code": xerr.REUQEST_PARAM_ERROR,
+				"msg":  err.Error(),
+			})
+			return
+		}
+
+		// 验证时间窗口
+		if m.checkTs(cps.Ts) == false {
+			httpx.WriteJson(w, http.StatusOK, map[string]interface{}{
+				"code": xerr.REUQEST_PARAM_TS_ERROR,
+				"msg":  "请求参数错误",
+			})
+			return
+		}
+
+		// 得到secret, 如果发生错误, 则响应失败
+		appSecret, err := m.getAppSecret(cps.AppName)
+		if err != nil {
+			httpx.WriteJson(w, http.StatusOK, map[string]interface{}{
+				"code": xerr.REUQEST_PARAM_APP_NAME_ERROR,
+				"msg":  err.Error(),
+			})
+			return
+		}
+
+		// 解析query, 得到sign和s1
+		s1, err := m.parseQuery(r)
+		if err != nil {
+			fmt.Printf("m.parseQuery(r) error :s\n", err.Error())
+		}
+		s2, err := m.parseBody(r)
+		if err != nil {
+			fmt.Printf("m.parseBody(r) error :s\n", err.Error())
+		}
+
+		s3 := r.ContentLength
+
+		csign := m.calcSign(s1, s2, appSecret, s3, cps.SignFlag)
+		if csign != cps.Sign {
+			httpx.WriteJson(w, http.StatusOK, map[string]interface{}{
+				"code": xerr.REUQEST_PARAM_DATA_SIGN_ERROR,
+				"msg":  "未通过数据认证",
+			})
+			return
+		}
+
+		next(w, r)
+	}
+}
+
+func (m *DataSignMiddleware) calcSign(s1, s2, appSecret string, s3 int64, signFlag uint8) string {
+	// 处理s2
+	if signFlag == 1 {
+		s2 = m.cutS2(s2)
+	} else {
+		s2, _ = m.sortS2(s2)
+	}
+
+	//fmt.Printf("sign data: %s\n", fmt.Sprintf("%s%s%d%s", s1, s2, s3, appSecret))
+	//fmt.Printf("md5: %s\n", md5.Md5([]byte(fmt.Sprintf("%s%s%d%s", s1, s2, s3, appSecret))))
+
+	return md5.Md5([]byte(fmt.Sprintf("%s%s%d%s", s1, s2, s3, appSecret)))
+}
+
+func (m *DataSignMiddleware) cutS2(s2 string) string {
+	s2l := len(s2)
+	if s2l <= S2_MIN_LENGTH {
+		return s2
+	}
+	return fmt.Sprintf("%s%s", s2[:S2_HEAD_LENGTH], s2[s2l-S2_TAIL_LENGTH:])
+}
+
+func (m *DataSignMiddleware) sortS2(s2 string) (string, error) {
+	var mi map[string]interface{}
+	if err := json.Unmarshal([]byte(s2), &mi); err != nil {
+		return "", err
+	}
+
+	smi := utils.SortMapByKey(mi)
+
+	if bs, err := json.Marshal(smi); err != nil {
+		return "", err
+	} else {
+		return string(bs), nil
+	}
+}
+
+func (m *DataSignMiddleware) parseBody(r *http.Request) (body string, err error) {
+	if r.Method == http.MethodGet {
+		return "", nil
+	}
+
+	cnt, _ := ioutil.ReadAll(r.Body)
+	r.Body = ioutil.NopCloser(bytes.NewReader(cnt))
+
+	return string(cnt), nil
+}
+
+func (m *DataSignMiddleware) parseQuery(r *http.Request) (query string, err error) {
+	if vs, err := url.ParseQuery(r.URL.RawQuery); err != nil {
+		return "", err
+	} else {
+		vs.Del("sign")
+		return vs.Encode(), nil
+	}
+}
+
+func (m *DataSignMiddleware) getAppSecret(appName string) (string, error) {
+	if secret, ok := appSecrets[appName]; ok {
+		if secret.Expire.After(time.Now()) == false {
+			return secret.Secret, nil
+		}
+	}
+
+	// 从数据库中读取appSecret
+	if appInfo, err := m.AppInfo.FindOneByAppName(context.Background(), appName); err == nil {
+		appSecretsLock.Lock()
+		defer appSecretsLock.Unlock()
+		appSecrets[appName] = secretExpire{
+			Secret: appInfo.Secret,
+			Status: appInfo.Status,
+			Expire: time.Now().Add(APP_SECRET_CACHE_EXPIRE * time.Second),
+		}
+		if appInfo.Status == 0 {
+			return appInfo.Secret, nil
+		}
+	}
+
+	return "", xerr.NewErrCodeMsg(xerr.REUQEST_PARAM_APP_NAME_ERROR, "该app name错误, 无法进行数据验签")
+}
+
+func (m *DataSignMiddleware) checkTs(ts int64) bool {
+	return time.Now().Unix()-ts <= TIME_OUT
+}

+ 7 - 1
app/cmd/dtgateway/internal/svc/serviceContext.go

@@ -2,18 +2,24 @@ package svc
 
 import (
 	"GtDataStore/app/cmd/dtgateway/internal/config"
+	"GtDataStore/app/cmd/dtgateway/internal/middleware"
 	"GtDataStore/app/cmd/organization/organization"
+	"github.com/zeromicro/go-zero/rest"
 	"github.com/zeromicro/go-zero/zrpc"
 )
 
 type ServiceContext struct {
 	Config          config.Config
 	OrganizationRpc organization.Organization
+	DataSign        rest.Middleware
 }
 
 func NewServiceContext(c config.Config) *ServiceContext {
-	return &ServiceContext{
+	svc := &ServiceContext{
 		Config:          c,
 		OrganizationRpc: organization.NewOrganization(zrpc.MustNewClient(c.OrganizationRpcConf)),
 	}
+	svc.DataSign = middleware.NewDataSignMiddleware(c).Handle
+
+	return svc
 }

+ 19 - 162
app/cmd/dtgateway/internal/types/types.go

@@ -1,127 +1,12 @@
 // Code generated by goctl. DO NOT EDIT.
 package types
 
-type DcWorkingUf struct {
-	Id               int64   `json:"id"`
-	ProjectId        int64   `json:"project_id"`
-	DeviceCode       string  `json:"device_code"`
-	WaterTemperature float64 `json:"water_temperature"` // 水温 摄氏度
-	FeedFlow         float64 `json:"feed_flow"`         // 进水流量
-	ConFlow          float64 `json:"con_flow"`          // 浓水流量
-	ProductFlow      float64 `json:"product_flow"`      // 产水流量
-	FeedPressure     float64 `json:"feed_pressure"`     // 进水压力
-	ConPressure      float64 `json:"con_pressure"`      // 浓水压力
-	ProductPressure  float64 `json:"product_pressure"`  // 产水压力
-	Tmp              float64 `json:"tmp"`               // 跨膜压差
-	Flux             float64 `json:"flux"`              // 膜通量
-	FeedWqTurbidity  float64 `json:"feed_wq_turbidity"` // 进水浊度
-	FeedWqPh         int64   `json:"feed_wq_ph"`        // 进水 PH 值
-	ProductWqPh      int64   `json:"product_wq_ph"`     // 产水 PH 值
-	FeedWqAl         float64 `json:"feed_wq_al"`        // 进水水质:铝
-	ProductWqAl      float64 `json:"product_wq_al"`     // 产水水质:铝
-	FeedWqFe         float64 `json:"feed_wq_fe"`        // 进水水质:铁
-	ProductWqFe      float64 `json:"product_wq_fe"`     // 产水水质:铁
-	FeedWqMn         float64 `json:"feed_wq_mn"`        // 进水水质:锰
-	ProductWqMn      float64 `json:"product_wq_mn"`     // 产水水质:锰
-	FeedWqSio2       float64 `json:"feed_wq_sio2"`      // 进水水质:二氧化硅
-	ProductWqSio2    float64 `json:"product_wq_sio2"`   // 产水水质:二氧化硅
-	FeedWqCod        float64 `json:"feed_wq_cod"`       // 进水水质:COD
-	ProductWqCod     float64 `json:"product_wq_cod"`    // 产水水质:COD
-	FeedWqP          float64 `json:"feed_wq_p"`         // 进水水质:磷
-	ProductWqP       float64 `json:"product_wq_p"`      // 产水水质:磷
-	Step             int64   `json:"step"`              // 设备当前步序值
-	CTime            string  `json:"c_time"`
-}
-
-type DcWorkingRo struct {
-	Id                 int64   `json:"id"`
-	ProjectId          int64   `json:"project_id"`
-	DeviceCode         string  `json:"device_code"`
-	WaterTemperature   float64 `json:"water_temperature"`    // 水温 摄氏度
-	FeedFlow1St        float64 `json:"feed_flow_1st"`        // 一段进水流量
-	ConFlow1St         float64 `json:"con_flow_1st"`         // 一段浓水流量
-	ProductFlow1St     float64 `json:"product_flow_1st"`     // 一段产水流量
-	FeedPressure1St    float64 `json:"feed_pressure_1st"`    // 一段进水压力
-	ConPressure1St     float64 `json:"con_pressure_1st"`     // 一段浓水压力
-	ProductPressure1St float64 `json:"product_pressure_1st"` // 一段产水压力
-	Tmp1St             float64 `json:"tmp_1st"`              // 一段跨膜压差
-	Flux1St            float64 `json:"flux_1st"`             // 一段膜通量
-	Permeability1St    float64 `json:"permeability_1st"`     // 一段渗透率
-	FeedFlow2Nd        float64 `json:"feed_flow_2nd"`        // 二段进水流量
-	ConFlow2Nd         float64 `json:"con_flow_2nd"`         // 二段浓水流量
-	ProductFlow2Nd     float64 `json:"product_flow_2nd"`     // 二段产水流量
-	FeedPressure2Nd    float64 `json:"feed_pressure_2nd"`    // 二段进水压力
-	ConPressure2Nd     float64 `json:"con_pressure_2nd"`     // 二段浓水压力
-	ProductPressure2Nd float64 `json:"product_pressure_2nd"` // 二段产水压力
-	Tmp2Nd             float64 `json:"tmp_2nd"`              // 二段压差
-	Flux2Nd            float64 `json:"flux_2nd"`             // 二段通量
-	Permeability2Nd    float64 `json:"permeability_2nd"`     // 二段渗透率
-	FeedFlow3Th        float64 `json:"feed_flow_3th"`        // 三段进水流量
-	ConFlow3Th         float64 `json:"con_flow_3th"`         // 三段浓水流量
-	ProductFlow3Th     float64 `json:"product_flow_3th"`     // 三段产水流量
-	FeedPressure3Th    float64 `json:"feed_pressure_3th"`    // 三段进水压力
-	ConPressure3Th     float64 `json:"con_pressure_3th"`     // 三段浓水压力
-	ProductPressure3Th float64 `json:"product_pressure_3th"` // 三段产水压力
-	Tmp3Th             float64 `json:"tmp_3th"`              // 三段压差
-	Flux3Th            float64 `json:"flux_3th"`             // 三段通量
-	Permeability3Th    float64 `json:"permeability_3th"`     // 三段渗透率
-	FeedWqTurbidity    float64 `json:"feed_wq_turbidity"`    // 进水浊度
-	FeedWqPh           int64   `json:"feed_wq_ph"`           // 进水 PH 值
-	ProductWqPh        int64   `json:"product_wq_ph"`        // 产水 PH 值
-	FeedWqAl           float64 `json:"feed_wq_al"`           // 进水水质:铝
-	ProductWqAl        float64 `json:"product_wq_al"`        // 产水水质:铝
-	FeedWqFe           float64 `json:"feed_wq_fe"`           // 进水水质:铁
-	ProductWqFe        float64 `json:"product_wq_fe"`        // 产水水质:铁
-	FeedWqMn           float64 `json:"feed_wq_mn"`           // 进水水质:锰
-	ProductWqMn        float64 `json:"product_wq_mn"`        // 产水水质:锰
-	FeedWqSio2         float64 `json:"feed_wq_sio2"`         // 进水水质:二氧化硅
-	ProductWqSio2      float64 `json:"product_wq_sio2"`      // 产水水质:二氧化硅
-	FeedWqCod          float64 `json:"feed_wq_cod"`          // 进水水质:COD
-	ProductWqCod       float64 `json:"product_wq_cod"`       // 产水水质:COD
-	FeedWqP            float64 `json:"feed_wq_p"`            // 进水水质:磷
-	ProductWqP         float64 `json:"product_wq_p"`         // 产水水质:磷
-	Step               int64   `json:"step"`                 // 设备当前步序值
-	CTime              string  `json:"c_time"`
-}
-
-type DcWorkingChest struct {
-	Id                  int64   `json:"id"`
-	ProjectId           int64   `json:"project_id"`
-	DeviceCode          string  `json:"device_code"`
-	Switch              int64   `json:"switch"`                // 药箱液位开关 0: 关 1: 开
-	Level               float64 `json:"level"`                 // 液位高度
-	AgitatorStatus      int64   `json:"agitator_status"`       // 搅拌器运行状态 0: 未运行 1:运行中
-	AgitatorDuration    int64   `json:"agitator_duration"`     // 搅拌器运行时长
-	AgitatorFaultStatus int64   `json:"agitator_fault_status"` // 搅拌器故障状态 0:正常 1:故障
-	CTime               string  `json:"c_time"`
-}
-
-type DcWorkingPump struct {
-	Id           int64   `json:"id"`
-	ProjectId    int64   `json:"project_id"`
-	DeviceCode   string  `json:"device_code"`
-	FeedPressure float64 `json:"feed_pressure"` // 进水压力
-	OutPressure  float64 `json:"out_pressure"`  // 出水压力
-	Duration     int64   `json:"duration"`      // 运行时长 单位 s
-	Current      float64 `json:"current"`       // 运行电流
-	Frequency    float64 `json:"frequency"`     // 运行频率
-	Lift         float64 `json:"lift"`          // 工作扬程
-	Efficiency   float64 `json:"efficiency"`    // 运行效率
-	RunStatus    int64   `json:"run_status"`    // 运行状态 0: 停机 1: 运行正常
-	FaultStatus  int64   `json:"fault_status"`  // 故障状态 0: 正常 1: 故障
-	CTime        string  `json:"c_time"`
-}
-
-type DcWorkingValve struct {
-	Id          int64   `json:"id"`
-	ProjectId   int64   `json:"project_id"`
-	DeviceCode  string  `json:"device_code"`
-	Adjust      int64   `json:"adjust"`       // 是否为调节阀门 0: 否 1: 是
-	Opening     float64 `json:"opening"`      // 当前阀门的开度
-	Closed      int64   `json:"closed"`       // 关到位 全关  0: 否 1: 是
-	Opened      int64   `json:"opened"`       // 开到位 开到 设置的开度 0: 否 1: 是
-	FaultStatus int64   `json:"fault_status"` // 是否故障 0: 否 1: 是
-	CTime       string  `json:"c_time"`
+type CommonParams struct {
+	Ts        int64  `form:"ts"`
+	ProjectId int64  `form:"project_id"`
+	Sign      string `form:"sign"`
+	SignFlag  uint8  `form:"sign_flag,optional"`
+	AppName   string `header:"APP-NAME"`
 }
 
 type CommonResponse struct {
@@ -135,42 +20,19 @@ type DcWorkingReq struct {
 	DeviceCode string `form:"device_code"`
 }
 
-type WorkingUfResp struct {
-	Info *DcWorkingUf `json:"info"`
-}
-
-type WorkingRoResp struct {
-	Info *DcWorkingRo `json:"info"`
-}
-
-type WorkingChestResp struct {
-	Info *DcWorkingChest `json:"info"`
-}
-
-type WorkingValveResp struct {
-	Info *DcWorkingValve `json:"info"`
-}
-
-type WorkingPumpResp struct {
-	Info *DcWorkingPump `json:"info"`
-}
-
 type ItemHistoryData struct {
-	ProjectId int64   `json:"project_id"`
-	ItemName  string  `json:"item_name"`
-	Val       float64 `json:"val"`
-	HTime     string  `json:"h_time"`
+	CommonParams
+	ItemName string  `json:"item_name"`
+	Val      float64 `json:"val"`
+	HTime    string  `json:"h_time"`
 }
 
 type MultiAddItemHistoryDataReq struct {
 	List []*ItemHistoryData `json:"list"`
 }
 
-type MultiAddItemHistoryDataResq struct {
-}
-
 type ItemHistoryDataListReq struct {
-	ProjectId  int64  `form:"project_id"`
+	CommonParams
 	ItemName   string `form:"item_name"`
 	Size       int64  `form:"size"`       //结果间隔
 	Interval   string `form:"interval"`   //时间单位 s,minute,h,day
@@ -180,20 +42,15 @@ type ItemHistoryDataListReq struct {
 }
 
 type ItemHistoryDataByTimeReq struct {
-	ProjectId int64  `form:"project_id"`
-	ItemName  string `form:"item_name"`
-	STime     string `form:"stime"`
-	ETime     string `form:"etime"`
+	CommonParams
+	ItemName string `form:"item_name"`
+	STime    string `form:"stime"`
+	ETime    string `form:"etime"`
 }
 
 type ItemHistoryDataMaxMinByTimeReq struct {
-	ProjectId int64  `form:"project_id"`
-	ItemName  string `form:"item_name"`
-	STime     string `form:"stime"`
-	ETime     string `form:"etime"`
-}
-
-type ItemHistoryDataMaxMinByTimeResq struct {
-	MaxVal float64 `json:"max_val"`
-	MinVal float64 `json:"min_val"`
+	CommonParams
+	ItemName string `form:"item_name"`
+	STime    string `form:"stime"`
+	ETime    string `form:"etime"`
 }

+ 83 - 54
app/model/GtDataStore.sql

@@ -28,6 +28,18 @@ CREATE TABLE `dc_alarm_list` (
                                  KEY `project_id` (`project_id`,`device_code`,`item`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
+-- Create syntax for TABLE 'dc_app_info'
+CREATE TABLE `dc_app_info` (
+                               `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+                               `app_name` varchar(30) NOT NULL DEFAULT '' COMMENT '应用名称',
+                               `project_id` int(11) NOT NULL DEFAULT '0' COMMENT '限定服务的project_id',
+                               `secret` varchar(32) NOT NULL DEFAULT '' COMMENT '数据签名的secret',
+                               `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态 0: 正常 1: 禁用',
+                               `m_time` timestamp NOT NULL COMMENT '更新时间',
+                               PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
+                               UNIQUE KEY `app_name` (`app_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+
 -- Create syntax for TABLE 'dc_clean_bind'
 CREATE TABLE `dc_clean_bind` (
                                  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -68,8 +80,9 @@ CREATE TABLE `dc_device_bind` (
                                   `items` text NOT NULL COMMENT '相关点位集合',
                                   `target_table` varchar(50) NOT NULL DEFAULT '' COMMENT '数据存入目标表名',
                                   PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
-                                  UNIQUE KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='相关点位绑定表';
+                                  KEY `project_id_2` (`project_id`,`device_type`),
+                                  UNIQUE KEY `project_id` (`project_id`,`device_code`,`device_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=60001 COMMENT='相关点位绑定表';
 
 -- Create syntax for TABLE 'dc_device_relation'
 CREATE TABLE `dc_device_relation` (
@@ -95,22 +108,26 @@ CREATE TABLE `dc_event_bind` (
                                  `interval` int(11) NOT NULL DEFAULT '0' COMMENT '检测时间间隔',
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
-                                 UNIQUE KEY `project_id` (`project_id`,`item`,`name`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=60001;
+                                 UNIQUE KEY `project_id` (`project_id`,`item`,`name`),
+                                 KEY `project_id_2` (`project_id`,`rule_flag`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=150001;
 
 -- Create syntax for TABLE 'dc_event_list'
 CREATE TABLE `dc_event_list` (
                                  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
                                  `project_id` int(11) NOT NULL,
                                  `device_code` varchar(50) NOT NULL DEFAULT '',
+                                 `name` varchar(50) NOT NULL DEFAULT '' COMMENT '事件名称',
                                  `item` varchar(50) NOT NULL DEFAULT '',
                                  `val` varchar(20) NOT NULL DEFAULT '' COMMENT '事件发生时,点位的值',
+                                 `old_val` varchar(20) NOT NULL DEFAULT '' COMMENT '事件发生时, 旧的点位值',
+                                 `time` timestamp NOT NULL COMMENT '事件触发时间',
                                  `event_id` int(11) NOT NULL COMMENT '事件 ID dc_event_bind.id',
                                  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '事件标题',
                                  `context` varchar(255) NOT NULL DEFAULT '' COMMENT '事件内容',
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
-                                 KEY `project_id` (`project_id`,`device_code`,`item`)
+                                 KEY `project_id` (`project_id`,`name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
 -- Create syntax for TABLE 'dc_event_rule'
@@ -124,6 +141,22 @@ CREATE TABLE `dc_event_rule` (
                                  UNIQUE KEY `flag` (`flag`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001;
 
+-- Create syntax for TABLE 'dc_item_config'
+CREATE TABLE `dc_item_config` (
+                                  `id` int(10) NOT NULL AUTO_INCREMENT,
+                                  `project_id` int(10) NOT NULL,
+                                  `device_code` varchar(55) NOT NULL COMMENT '位号',
+                                  `item_name` varchar(100) NOT NULL COMMENT '点位名',
+                                  `item_alias` varchar(55) NOT NULL COMMENT '别名',
+                                  `min_val` decimal(10,4) NOT NULL DEFAULT '0' COMMENT '量程最小值',
+                                  `max_val` decimal(10,4) NOT NULL DEFAULT '0' COMMENT '量程最大值',
+                                  `item_precision` tinyint(1) NOT NULL COMMENT '精度',
+                                  `item_unit` varchar(30) NOT NULL COMMENT '单位',
+                                  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
+                                  KEY `idx_project_item` (`project_id`,`item_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=90001 COMMENT='点位量程';
+
 -- Create syntax for TABLE 'dc_item_data'
 CREATE TABLE `dc_item_data` (
                                 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -137,6 +170,30 @@ CREATE TABLE `dc_item_data` (
                                 KEY `tag` (`tag`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=44424777 /*T![ttl] TTL=`htime` + INTERVAL 60 DAY */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
+-- Create syntax for TABLE 'dc_item_history_data_46'
+CREATE TABLE `dc_item_history_data_46` (
+                                           `item_name` varchar(100) NOT NULL DEFAULT '' COMMENT '点位名',
+                                           `val` decimal(12,6) NOT NULL DEFAULT '0' COMMENT '值',
+                                           `h_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集数据时间',
+                                           PRIMARY KEY (`item_name`,`h_time`) /*T![clustered_index] CLUSTERED */
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='单点位秒级历史数据' /*T![ttl] TTL=`h_time` + INTERVAL 12 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+
+-- Create syntax for TABLE 'dc_item_history_data_84'
+CREATE TABLE `dc_item_history_data_84` (
+                                           `item_name` varchar(100) NOT NULL DEFAULT '' COMMENT '点位名',
+                                           `val` decimal(12,6) NOT NULL DEFAULT '0' COMMENT '值',
+                                           `h_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集数据时间',
+                                           PRIMARY KEY (`item_name`,`h_time`) /*T![clustered_index] CLUSTERED */
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='单点位秒级历史数据' /*T![ttl] TTL=`h_time` + INTERVAL 12 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+
+-- Create syntax for TABLE 'dc_item_history_data_92'
+CREATE TABLE `dc_item_history_data_92` (
+                                           `item_name` varchar(100) NOT NULL DEFAULT '' COMMENT '点位名',
+                                           `val` decimal(12,6) NOT NULL DEFAULT '0' COMMENT '值',
+                                           `h_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集数据时间',
+                                           PRIMARY KEY (`item_name`,`h_time`) /*T![clustered_index] CLUSTERED */
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='单点位秒级历史数据' /*T![ttl] TTL=`h_time` + INTERVAL 12 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+
 -- Create syntax for TABLE 'dc_item_map'
 CREATE TABLE `dc_item_map` (
                                `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -149,6 +206,17 @@ CREATE TABLE `dc_item_map` (
                                UNIQUE KEY `project_id` (`project_id`,`source_item`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=60001;
 
+-- Create syntax for TABLE 'dc_project_config'
+CREATE TABLE `dc_project_config` (
+                                     `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+                                     `project_id` int(11) NOT NULL,
+                                     `technologys` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '该项目中要使用的项目 ["A","B"]',
+                                     `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '项目状态  0:禁用 1: 正常',
+                                     `m_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+                                     PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
+                                     UNIQUE KEY `project_id` (`project_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci AUTO_INCREMENT=60001;
+
 -- Create syntax for TABLE 'dc_working_chest'
 CREATE TABLE `dc_working_chest` (
                                     `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -162,7 +230,7 @@ CREATE TABLE `dc_working_chest` (
                                     `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                     PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                     KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='药箱液位' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=42750001 COMMENT='药箱液位' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
 -- Create syntax for TABLE 'dc_working_mf'
 CREATE TABLE `dc_working_mf` (
@@ -194,6 +262,7 @@ CREATE TABLE `dc_working_mf` (
                                  `feed_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:磷',
                                  `product_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '产水水质:磷',
                                  `step` int(11) DEFAULT NULL COMMENT '设备当前步序值',
+                                 `filter_time` decimal(8,2) DEFAULT NULL,
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                  KEY `project_id` (`project_id`,`device_code`)
@@ -248,6 +317,7 @@ CREATE TABLE `dc_working_nf` (
                                  `feed_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:磷',
                                  `product_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '产水水质:磷',
                                  `step` int(11) DEFAULT NULL COMMENT '设备当前步序值',
+                                 `filter_time` decimal(8,2) DEFAULT NULL,
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                  KEY `project_id` (`project_id`,`device_code`)
@@ -270,7 +340,7 @@ CREATE TABLE `dc_working_pump` (
                                    `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                    PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                    KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='水泵' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=79500001 COMMENT='水泵' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
 -- Create syntax for TABLE 'dc_working_ro'
 CREATE TABLE `dc_working_ro` (
@@ -295,7 +365,6 @@ CREATE TABLE `dc_working_ro` (
                                  `product_pressure_2nd` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '二段产水压力',
                                  `tmp_2nd` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '二段压差',
                                  `flux_2nd` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '二段通量',
-                                 `permeability_2nd` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '二段渗透率',
                                  `feed_flow_3th` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '三段进水流量',
                                  `con_flow_3th` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '三段浓水流量',
                                  `product_flow_3th` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '三段产水流量',
@@ -308,6 +377,7 @@ CREATE TABLE `dc_working_ro` (
                                  `feed_wq_turbidity` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水浊度',
                                  `feed_wq_ph` tinyint(4) NOT NULL DEFAULT '0' COMMENT '进水 PH 值',
                                  `product_wq_ph` tinyint(4) NOT NULL DEFAULT '0' COMMENT '产水 PH 值',
+                                 `permeability_2nd` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '二段渗透率',
                                  `feed_wq_al` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:铝',
                                  `product_wq_al` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '产水水质:铝',
                                  `feed_wq_fe` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:铁',
@@ -321,10 +391,11 @@ CREATE TABLE `dc_working_ro` (
                                  `feed_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:磷',
                                  `product_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '产水水质:磷',
                                  `step` int(11) DEFAULT NULL COMMENT '设备当前步序值',
+                                 `filter_time` decimal(8,2) DEFAULT NULL,
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                  KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='反渗透' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=11880001 COMMENT='反渗透' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
 -- Create syntax for TABLE 'dc_working_uf'
 CREATE TABLE `dc_working_uf` (
@@ -356,10 +427,11 @@ CREATE TABLE `dc_working_uf` (
                                  `feed_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '进水水质:磷',
                                  `product_wq_p` decimal(8,4) NOT NULL DEFAULT '0' COMMENT '产水水质:磷',
                                  `step` int(11) DEFAULT NULL COMMENT '设备当前步序值',
+                                 `filter_time` decimal(8,2) DEFAULT NULL,
                                  `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                  KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='超滤' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=11970001 COMMENT='超滤' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
 
 -- Create syntax for TABLE 'dc_working_valve'
 CREATE TABLE `dc_working_valve` (
@@ -374,47 +446,4 @@ CREATE TABLE `dc_working_valve` (
                                     `c_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                     PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
                                     KEY `project_id` (`project_id`,`device_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 COMMENT='阀门' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
-
-CREATE TABLE `dc_project_config` (
-                                     `id` int unsigned NOT NULL AUTO_INCREMENT,
-                                     `project_id` int NOT NULL,
-                                     `technologys` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '该项目中要使用的项目 ["A","B"]',
-                                     `status` tinyint NOT NULL DEFAULT '0' COMMENT '项目状态  0:禁用 1: 正常',
-                                     `m_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-                                     PRIMARY KEY (`id`),
-                                     UNIQUE KEY `project_id` (`project_id`)
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-
-CREATE TABLE `dc_item_history_data_92` (
-        `item_name` varchar(100) NOT NULL DEFAULT '' COMMENT '点位名',
-        `val` decimal(10,4) NOT NULL DEFAULT '0' COMMENT '值',
-        `h_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '采集数据时间',
-        PRIMARY KEY (`item_name`,`h_time`) /*T![clustered_index] CLUSTERED */,
-        KEY `index_project_item` (`item_name`,`c_time`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='锡山单点位秒级历史数据' /*T![ttl] TTL=`h_time` + INTERVAL 12 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;
-
-CREATE TABLE `dc_item_config` (
-      `id` int(10) NOT NULL AUTO_INCREMENT,
-      `project_id` int(10) NOT NULL,
-      `device_code` varchar(55) NOT NULL COMMENT '位号',
-      `item_name` varchar(100) NOT NULL COMMENT '点位名',
-      `item_alias` varchar(55) NOT NULL COMMENT '别名',
-      `min_val` decimal(10,4) NOT NULL DEFAULT '0' COMMENT '量程最小值',
-      `max_val` decimal(10,4) NOT NULL DEFAULT '0' COMMENT '量程最大值',
-      `item_one_value` tinyint(1) NOT NULL DEFAULT '1' COMMENT '约定值1',
-      `item_one_value_color` varchar(50) NOT NULL COMMENT '约定值 1 颜色',
-      `item_zero_value` tinyint(1) NOT NULL COMMENT '约定值 0',
-      `item_zero_value_color` varchar(55) NOT NULL COMMENT '约定值 0 颜色',
-      `is_flicker` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否闪烁 0 不闪烁 1 闪烁',
-      `bit_value` varchar(55) NOT NULL COMMENT '石景山取bit位规则',
-      `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-      PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
-      KEY `idx_project_item` (`project_id`,`item_name`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='点位量程及颜色配置';
-
-
-
-
-
-
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=27630001 COMMENT='阀门' /*T![ttl] TTL=`c_time` + INTERVAL 3 MONTH */ /*T![ttl] TTL_ENABLE='ON' */ /*T![ttl] TTL_JOB_INTERVAL='1h' */;

+ 24 - 0
app/model/dcAppInfoModel.go

@@ -0,0 +1,24 @@
+package model
+
+import "github.com/zeromicro/go-zero/core/stores/sqlx"
+
+var _ DcAppInfoModel = (*customDcAppInfoModel)(nil)
+
+type (
+	// DcAppInfoModel is an interface to be customized, add more methods here,
+	// and implement the added methods in customDcAppInfoModel.
+	DcAppInfoModel interface {
+		dcAppInfoModel
+	}
+
+	customDcAppInfoModel struct {
+		*defaultDcAppInfoModel
+	}
+)
+
+// NewDcAppInfoModel returns a model for the database table.
+func NewDcAppInfoModel(conn sqlx.SqlConn) DcAppInfoModel {
+	return &customDcAppInfoModel{
+		defaultDcAppInfoModel: newDcAppInfoModel(conn),
+	}
+}

+ 111 - 0
app/model/dcAppInfoModel_gen.go

@@ -0,0 +1,111 @@
+// Code generated by goctl. DO NOT EDIT.
+
+package model
+
+import (
+	"context"
+	"database/sql"
+	"fmt"
+	"strings"
+	"time"
+
+	"github.com/zeromicro/go-zero/core/stores/builder"
+	"github.com/zeromicro/go-zero/core/stores/sqlc"
+	"github.com/zeromicro/go-zero/core/stores/sqlx"
+	"github.com/zeromicro/go-zero/core/stringx"
+)
+
+var (
+	dcAppInfoFieldNames          = builder.RawFieldNames(&DcAppInfo{})
+	dcAppInfoRows                = strings.Join(dcAppInfoFieldNames, ",")
+	dcAppInfoRowsExpectAutoSet   = strings.Join(stringx.Remove(dcAppInfoFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
+	dcAppInfoRowsWithPlaceHolder = strings.Join(stringx.Remove(dcAppInfoFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
+)
+
+type (
+	dcAppInfoModel interface {
+		Insert(ctx context.Context, data *DcAppInfo) (sql.Result, error)
+		FindOne(ctx context.Context, id int64) (*DcAppInfo, error)
+		FindOneByAppName(ctx context.Context, appName string) (*DcAppInfo, error)
+		Update(ctx context.Context, data *DcAppInfo) error
+		Delete(ctx context.Context, id int64) error
+	}
+
+	defaultDcAppInfoModel struct {
+		conn  sqlx.SqlConn
+		table string
+	}
+
+	DcAppInfo struct {
+		Id        int64     `db:"id"`
+		AppName   string    `db:"app_name"`   // 应用名称
+		ProjectId int64     `db:"project_id"` // 限定服务的project_id
+		Secret    string    `db:"secret"`     // 数据签名的secret
+		Status    int64     `db:"status"`     // 状态 0: 正常 1: 禁用
+		MTime     time.Time `db:"m_time"`     // 更新时间
+	}
+)
+
+func newDcAppInfoModel(conn sqlx.SqlConn) *defaultDcAppInfoModel {
+	return &defaultDcAppInfoModel{
+		conn:  conn,
+		table: "`dc_app_info`",
+	}
+}
+
+func (m *defaultDcAppInfoModel) withSession(session sqlx.Session) *defaultDcAppInfoModel {
+	return &defaultDcAppInfoModel{
+		conn:  sqlx.NewSqlConnFromSession(session),
+		table: "`dc_app_info`",
+	}
+}
+
+func (m *defaultDcAppInfoModel) Delete(ctx context.Context, id int64) error {
+	query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
+	_, err := m.conn.ExecCtx(ctx, query, id)
+	return err
+}
+
+func (m *defaultDcAppInfoModel) FindOne(ctx context.Context, id int64) (*DcAppInfo, error) {
+	query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", dcAppInfoRows, m.table)
+	var resp DcAppInfo
+	err := m.conn.QueryRowCtx(ctx, &resp, query, id)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}
+
+func (m *defaultDcAppInfoModel) FindOneByAppName(ctx context.Context, appName string) (*DcAppInfo, error) {
+	var resp DcAppInfo
+	query := fmt.Sprintf("select %s from %s where `app_name` = ? limit 1", dcAppInfoRows, m.table)
+	err := m.conn.QueryRowCtx(ctx, &resp, query, appName)
+	switch err {
+	case nil:
+		return &resp, nil
+	case sqlc.ErrNotFound:
+		return nil, ErrNotFound
+	default:
+		return nil, err
+	}
+}
+
+func (m *defaultDcAppInfoModel) Insert(ctx context.Context, data *DcAppInfo) (sql.Result, error) {
+	query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, dcAppInfoRowsExpectAutoSet)
+	ret, err := m.conn.ExecCtx(ctx, query, data.AppName, data.ProjectId, data.Secret, data.Status, data.MTime)
+	return ret, err
+}
+
+func (m *defaultDcAppInfoModel) Update(ctx context.Context, newData *DcAppInfo) error {
+	query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, dcAppInfoRowsWithPlaceHolder)
+	_, err := m.conn.ExecCtx(ctx, query, newData.AppName, newData.ProjectId, newData.Secret, newData.Status, newData.MTime, newData.Id)
+	return err
+}
+
+func (m *defaultDcAppInfoModel) tableName() string {
+	return m.table
+}

+ 112 - 0
common/crypto/aes/aes.go

@@ -0,0 +1,112 @@
+package aes
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+)
+
+const (
+	Zero  string = "Zero"
+	PKCS5 string = "PKCS5"
+	PKCS7 string = "PKCS7"
+)
+
+// plantText: plant text
+// key: size 16,24, 32 match AES-128, AES-192, AES-256
+// padding: one of Zero,PKCS5,PKCS7,default PKCS5
+func CBCEncrypt(plantText, key []byte, padding string) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	switch padding {
+	case Zero:
+		plantText = ZeroPadding(plantText, block.BlockSize())
+	case PKCS7:
+		plantText = PKCS7Padding(plantText, block.BlockSize())
+	default:
+		plantText = PKCS5Padding(plantText, block.BlockSize())
+	}
+
+	blockModel := cipher.NewCBCEncrypter(block, key)
+
+	ciphertext := make([]byte, len(plantText))
+
+	blockModel.CryptBlocks(ciphertext, plantText)
+	return ciphertext, nil
+}
+
+// cipherText: cipher text
+// key: size 16,24, 32 match AES-128, AES-192, AES-256
+// unpadding: one of Zero,PKCS5,PKCS7,default PKCS5
+func CBCDecrypt(ciphertext, key []byte, unpadding string) ([]byte, error) {
+	keyBytes := []byte(key)
+	block, err := aes.NewCipher(keyBytes)
+	if err != nil {
+		return nil, err
+	}
+	blockModel := cipher.NewCBCDecrypter(block, keyBytes)
+	plantText := make([]byte, len(ciphertext))
+	blockModel.CryptBlocks(plantText, ciphertext)
+
+	// fmt.Println(plantText)
+	switch unpadding {
+	case Zero:
+		plantText = ZeroUnPadding(plantText)
+	case PKCS7:
+		plantText = PKCS7UnPadding(plantText)
+	default:
+		plantText = PKCS5UnPadding(plantText)
+	}
+	return plantText, nil
+}
+
+func CBCDecryptNoPadding(ciphertext, key []byte) ([]byte, error) {
+	keyBytes := key
+	block, err := aes.NewCipher(keyBytes)
+	if err != nil {
+		return nil, err
+	}
+	blockModel := cipher.NewCBCDecrypter(block, keyBytes)
+	plantText := make([]byte, len(ciphertext))
+	blockModel.CryptBlocks(plantText, ciphertext)
+	return plantText, nil
+}
+
+func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func PKCS7UnPadding(plantText []byte) []byte {
+	length := len(plantText)
+	unpadding := int(plantText[length-1])
+	return plantText[:(length - unpadding)]
+}
+
+func ZeroPadding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{0}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func ZeroUnPadding(origData []byte) []byte {
+	length := len(origData)
+	unpadding := int(origData[length-1])
+	return origData[:(length - unpadding)]
+}
+
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func PKCS5UnPadding(origData []byte) []byte {
+	length := len(origData)
+	unpadding := int(origData[length-1])
+	return origData[:(length - unpadding)]
+}

+ 23 - 0
common/crypto/aes/aes_test.go

@@ -0,0 +1,23 @@
+package aes
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestAes(t *testing.T) {
+	key := []byte("1111111111111111")
+	var origin string = "this is plant text"
+
+	ciphertext, err := CBCEncrypt([]byte(origin), key, PKCS5)
+	if err != nil {
+		t.Error(err)
+	}
+	fmt.Printf("ciphertext:%s\n", ciphertext)
+
+	planttext, err := CBCDecrypt(ciphertext, key, PKCS5)
+	fmt.Printf("planttext: %s\n", planttext)
+	if string(origin) != string(planttext) {
+		t.FailNow()
+	}
+}

+ 23 - 0
common/crypto/base64/base64.go

@@ -0,0 +1,23 @@
+package base64
+
+import (
+	"encoding/base64"
+)
+
+// Encode Base64编码加密
+func Encode(data []byte) []byte {
+	res := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
+	base64.StdEncoding.Encode(res, data)
+	return res
+}
+
+// Decode Base64编码解密
+func Decode(data []byte) []byte {
+	res := make([]byte, base64.StdEncoding.DecodedLen(len(data)))
+	n, err := base64.StdEncoding.Decode(res, data)
+	if err != nil {
+		//logger.Error(err, string(data))
+		return nil
+	}
+	return res[:n]
+}

+ 104 - 0
common/crypto/des/des.go

@@ -0,0 +1,104 @@
+package des
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/des"
+)
+
+const (
+	Zero  string = "Zero"
+	PKCS5 string = "PKCS5"
+	PKCS7 string = "PKCS7"
+)
+
+/*
+ *plantText: plant text
+  *key: size 8
+   *padding: one of Zero,PKCS5,PKCS7,default PKCS5
+*/
+func CBCEncrypt(plantText, key []byte, padding string) ([]byte, error) {
+	block, err := des.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	switch padding {
+	case Zero:
+		plantText = ZeroPadding(plantText, block.BlockSize())
+	case PKCS7:
+		plantText = PKCS7Padding(plantText, block.BlockSize())
+	default:
+		plantText = PKCS5Padding(plantText, block.BlockSize())
+	}
+
+	blockModel := cipher.NewCBCEncrypter(block, key)
+
+	ciphertext := make([]byte, len(plantText))
+
+	blockModel.CryptBlocks(ciphertext, plantText)
+	return ciphertext, nil
+}
+
+/*
+ *cipherText: cipher text
+  *key: size 8
+   *unpadding: one of Zero,PKCS5,PKCS7,default PKCS5
+*/
+func CBCDecrypt(ciphertext, key []byte, unpadding string) ([]byte, error) {
+	keyBytes := []byte(key)
+	block, err := des.NewCipher(keyBytes)
+	if err != nil {
+		return nil, err
+	}
+	blockModel := cipher.NewCBCDecrypter(block, keyBytes)
+	plantText := make([]byte, len(ciphertext))
+	blockModel.CryptBlocks(plantText, ciphertext)
+
+	switch unpadding {
+	case Zero:
+		plantText = ZeroUnPadding(plantText)
+	case PKCS7:
+		plantText = PKCS7UnPadding(plantText)
+	default:
+		plantText = PKCS5UnPadding(plantText)
+	}
+
+	return plantText, nil
+}
+
+func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func PKCS7UnPadding(plantText []byte) []byte {
+	length := len(plantText)
+	unpadding := int(plantText[length-1])
+	return plantText[:(length - unpadding)]
+}
+
+func ZeroPadding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{0}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func ZeroUnPadding(origData []byte) []byte {
+	length := len(origData)
+	unpadding := int(origData[length-1])
+	return origData[:(length - unpadding)]
+}
+
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func PKCS5UnPadding(origData []byte) []byte {
+	length := len(origData)
+	unpadding := int(origData[length-1])
+	return origData[:(length - unpadding)]
+}

+ 22 - 0
common/crypto/md5/md5.go

@@ -0,0 +1,22 @@
+package md5
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"io/ioutil"
+)
+
+func Md5(input []byte) string {
+	hasher := md5.New()
+	hasher.Write(input)
+
+	return hex.EncodeToString(hasher.Sum(nil))
+}
+
+func Md5File(path string) (string, error) {
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		return "", err
+	}
+	return Md5(data), nil
+}

+ 21 - 0
common/crypto/md5/md5_test.go

@@ -0,0 +1,21 @@
+package md5
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+)
+
+func TestMd5(t *testing.T) {
+	fmt.Println(Md5([]byte("test")))
+}
+
+func TestMd5File(t *testing.T) {
+	x := `{"x":348454,"a":"7asdfuasdf3241234","list":[1,2,3,4,5]}`
+
+	var y map[string]interface{}
+
+	json.Unmarshal([]byte(x), &y)
+
+	t.Log(y)
+}

+ 87 - 0
common/crypto/rsa/rsa.go

@@ -0,0 +1,87 @@
+package rsa
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"errors"
+)
+
+var (
+	ErrPrivateKey = errors.New("private key error")
+	ErrPublicKey  = errors.New("public key error")
+)
+
+func PrivateKey(pri []byte) (*rsa.PrivateKey, error) {
+	block, _ := pem.Decode(pri)
+	if block == nil {
+		return nil, ErrPrivateKey
+	}
+	return x509.ParsePKCS1PrivateKey(block.Bytes)
+}
+
+func PublicKey(pub []byte) (*rsa.PublicKey, error) {
+	block, _ := pem.Decode(pub)
+	if block == nil {
+		return nil, ErrPublicKey
+	}
+	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
+	if err != nil {
+		return nil, err
+	}
+	rsaPub := pubInterface.(*rsa.PublicKey)
+	return rsaPub, nil
+}
+
+func Encrypt(orig, pubKey []byte) ([]byte, error) {
+	pub, err := PublicKey([]byte(pubKey))
+	if err != nil {
+		return nil, err
+	}
+	cipher, err := rsa.EncryptPKCS1v15(rand.Reader, pub, orig)
+	if err != nil {
+		return nil, err
+	}
+
+	return cipher, nil
+}
+
+func Decrypt(cipher, priKey []byte) ([]byte, error) {
+	pri, err := PrivateKey([]byte(priKey))
+	if err != nil {
+		return nil, err
+	}
+	ori, err := rsa.DecryptPKCS1v15(nil, pri, cipher)
+	if err != nil {
+		return nil, err
+	}
+	return ori, nil
+}
+
+func GenerateKey(bits int) (priKey, pubKey []byte, err error) {
+	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
+	if err != nil {
+		return
+	}
+
+	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
+	block := &pem.Block{
+		Type:  "RSA PRIVATE KEY",
+		Bytes: derStream,
+	}
+	priKey = pem.EncodeToMemory(block)
+
+	publicKey := &privateKey.PublicKey
+	derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
+	if err != nil {
+		return
+	}
+
+	block = &pem.Block{
+		Type:  "PUBLIC KEY",
+		Bytes: derPkix,
+	}
+	pubKey = pem.EncodeToMemory(block)
+	return
+}

+ 63 - 0
common/crypto/rsa/rsa_test.go

@@ -0,0 +1,63 @@
+package rsa
+
+import (
+	"testing"
+)
+
+/*const (
+	priKey = `
+-----BEGIN RSA PRIVATE KEY-----
+MFECAQACDQDt0G4B3JeeHjLWvX0CAwEAAQINANmKZncRf2SzCt/qiQIHAP1hu7hC
+NwIHAPBFhAcz6wIHAMKsRD3dIQIGDn4S7aBLAgY5OcfnuCQ=
+-----END RSA PRIVATE KEY-----
+`
+	pubKey = `
+-----BEGIN PUBLIC KEY-----
+MCgwDQYJKoZIhvcNAQEBBQADFwAwFAINAO3QbgHcl54eMta9fQIDAQAB
+-----END PUBLIC KEY-----
+`
+)*/
+
+var priKey string
+var pubKey string
+
+func TestGenerateKey(t *testing.T) {
+	pri, pub, err := GenerateKey(1024)
+	if err != nil {
+		t.Error(err)
+	}
+	priKey = string(pri)
+	pubKey = string(pub)
+}
+
+func TestRSA(t *testing.T) {
+	msg := "1"
+	cipher, err := Encrypt([]byte(msg), []byte(pubKey))
+	if err != nil {
+		t.Error(err)
+		t.FailNow()
+	}
+	ori, err := Decrypt(cipher, []byte(priKey))
+	if err != nil {
+		t.Error(err)
+		t.FailNow()
+	}
+	if string(ori) != msg {
+		t.FailNow()
+	}
+}
+
+func BenchmarkRSA(b *testing.B) {
+	msg := "1"
+	cipher, err := Encrypt([]byte(msg), []byte(pubKey))
+	if err != nil {
+		b.Error(err)
+		b.FailNow()
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := Decrypt(cipher, []byte(priKey)); err != nil {
+			b.Error(err)
+			b.FailNow()
+		}
+	}
+}

+ 22 - 0
common/crypto/sha1/sha1.go

@@ -0,0 +1,22 @@
+package sha1
+
+import (
+	"crypto/sha1"
+	"encoding/hex"
+	"io/ioutil"
+)
+
+func Sha1(input []byte) string {
+	hasher := sha1.New()
+	hasher.Write(input)
+
+	return hex.EncodeToString(hasher.Sum(nil))
+}
+
+func Sha1File(path string) (string, error) {
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		return "", err
+	}
+	return Sha1(data), nil
+}

+ 27 - 0
common/utils/utils.go

@@ -0,0 +1,27 @@
+package utils
+
+import "sort"
+
+// SortMapByKey 对 map[string]interface{} 按照键进行排序
+func SortMapByKey(m map[string]interface{}) map[string]interface{} {
+	// 创建一个 map[string]int,用于记录键的索引
+	indexMap := make(map[string]int)
+	for k := range m {
+		indexMap[k] = len(indexMap)
+	}
+
+	// 对键进行排序
+	keys := make([]string, 0, len(indexMap))
+	for k := range indexMap {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	// 创建排序后的 map[string]interface{}
+	sortedMap := make(map[string]interface{})
+	for _, k := range keys {
+		sortedMap[k] = m[k]
+	}
+
+	return sortedMap
+}

+ 8 - 3
common/xerr/errCode.go

@@ -1,19 +1,24 @@
 package xerr
 
-//成功返回
+// 成功返回
 const OK uint32 = 200
 
 /**(前3位代表业务,后三位代表具体功能)**/
 
-//全局错误码
+// 全局错误码
 const SERVER_COMMON_ERROR uint32 = 100001
 const REUQEST_PARAM_ERROR uint32 = 100002
 const TOKEN_EXPIRE_ERROR uint32 = 100003
 const TOKEN_GENERATE_ERROR uint32 = 100004
 const DB_ERROR uint32 = 100005
 const DB_UPDATE_AFFECTED_ZERO_ERROR uint32 = 100006
+const REUQEST_PARAM_APP_NAME_MISS_ERROR uint32 = 100007 // 请求参数中, 缺少header中的APP_NAME
+const REUQEST_PARAM_SIGN_MISS_ERROR uint32 = 100008     // 请求参数中缺少sign
+const REUQEST_PARAM_DATA_SIGN_ERROR uint32 = 100009     // 请求参数中的sign验证失败
+const REUQEST_PARAM_APP_NAME_ERROR uint32 = 100010      // 请求参数中, APP_NAME不存在或处理不可用的状态
+const REUQEST_PARAM_TS_ERROR uint32 = 100011            // 请求参数中, APP_NAME不存在或处理不可用的状态
 
-//备品备件模块
+// 备品备件模块
 const OUT_AMOUNT_OVER_ON_AMOUNT_ERROR uint32 = 100101
 const CATEGORY_NOT_EXIST_ERROR uint32 = 100102
 const RECORD_NOT_EXIST_ERROR uint32 = 100103