From 2834bf2ec86a51dee810cdb92507ee61f634d8cd Mon Sep 17 00:00:00 2001 From: lupeng_zz <1486083023@qq.com> Date: Sun, 31 May 2026 14:05:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E8=B5=84=E4=BA=A7=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data.go | 12 +- main.go | 807 ++++++++++++++++++++++++++++++++++++++++++++++++-------- req.go | 1 + res.go | 4 + 4 files changed, 716 insertions(+), 108 deletions(-) diff --git a/data.go b/data.go index d11af77..9295fb0 100644 --- a/data.go +++ b/data.go @@ -37,6 +37,8 @@ type devToolata struct { Instrument string `json:"instrument_id"` ProductName string `json:"product_name"` // 产品名称 WellName string `json:"wellname"` // 井名 + PInTime string `json:"person_in_time"` // 入井时间(可能为null) + POutTime string `json:"person_out_time"` // 出井时间(可能为null) InTime string `json:"in_time"` // 入井时间(可能为null) OutTime string `json:"out_time"` // 出井时间(可能为null) Engineer string `json:"engineer"` // 上井工程师(可能为null) @@ -181,15 +183,15 @@ type WellDetailReqData struct { type SeirDetailReqData struct { Opuser string `json:"opuser"` OpuserUuid string `json:"opuser_uuid"` - Series []string `json:"series"` - Instrument []string `json:"instrument"` + Series []string `json:"serial"` + Instrument []string `json:"number"` ProductName []string `json:"productName"` - WellName []string `json:"wellName"` + WellName []string `json:"wellname"` Engineer []string `json:"engineer"` Location []string `json:"location"` ServiceType []string `json:"serviceType"` - StartTime string `json:"startTime"` - EndTime string `json:"endTime"` + StartTime string `json:"in_time_start"` + EndTime string `json:"in_time_end"` Index int `json:"index"` Count int `json:"count"` } diff --git a/main.go b/main.go index 1d08dc2..2b49089 100644 --- a/main.go +++ b/main.go @@ -233,9 +233,9 @@ var ( loc string = "2006-01-02 15:04:05" - // dbPath string = "D:\\deescloud\\deesCloudServer\\ip2region.xdb" - dbPath string = "./ip2region.xdb" - cBuff []byte + dbPath string = "D:\\deescloud\\deesCloudServer\\ip2region.xdb" + // dbPath string = "./ip2region.xdb" + cBuff []byte pageSetting map[string]page_setting_req @@ -355,9 +355,7 @@ func initSqlPool(driverType string) { var err error // sqlConn, err = sql.Open("lodbc", dataSource) // sqlConn, err = sql.Open("odbc", dataSource) - fmt.Println("sssssssssssssssss") sqlConn, err = sql.Open("sqlserver", dataSource) - fmt.Println("aaaaaaaaaaaaaaaaaaaaaaaa") if err = sqlConn.Ping(); err != nil { fmt.Println("sql open:", err.Error()) os.Exit(0) @@ -1557,6 +1555,8 @@ func main() { http.HandleFunc("/deescloud/export_Seir_detail", export_Seir_detail) http.HandleFunc("/deescloud/export_Well_detail", export_Well_detail) http.HandleFunc("/deescloud/getQueryWell", getQueryWell) + http.HandleFunc("/deescloud/export_Seir_detail_en", export_Seir_detail_en) + http.HandleFunc("/deescloud/export_Well_detail_en", export_Well_detail_en) //监听服务 fmt.Println("listen server ...") @@ -3410,7 +3410,7 @@ func get_dev_manage_info(user string, wellname string) (resp []Dev_manage) { m := make(map[string]bool) var data []Dev_manage - sel_sql := fmt.Sprintf(`SELECT [ID],[6803],[6804],[6805],[6806],[6807],COALESCE([6808], '') AS [6808],[6809],[6810],COALESCE([6811], '') AS [6811],COALESCE([6812], '') AS [6812],COALESCE([6813], '') AS [6813],COALESCE([6820], '') AS [6820] FROM [EQUIPMENTASSETS] where [6800]='%s' order by [6802] desc`, wellname) + sel_sql := fmt.Sprintf(`SELECT [ID],[6803],[6804],[6805],[6806],[6807],COALESCE([6808], '') AS [6808],COALESCE([6809], '') as [6810],COALESCE([6810], '') as [6810],COALESCE([6811], '') AS [6811],COALESCE([6812], '') AS [6812],COALESCE([6813], '') AS [6813],COALESCE([6820], '') AS [6820] FROM [EQUIPMENTASSETS] where [6800]='%s' order by [6802] desc`, wellname) rows, err := sqlConn.Query(sel_sql) if err == nil { for rows.Next() { @@ -23262,95 +23262,108 @@ func get_well_history(response http.ResponseWriter, request *http.Request) { var whereSql string var ifWhere bool + // 始终 JOIN well_type_t 表,以便获取每口井的类型信息 + joinSql := ` LEFT JOIN [well_type_t] ON [WellInformation].[WELLNameSource] = [well_type_t].[well_name] ` + if req.Wellname != "" { wellnamesource := "%" + req.Wellname + "%" - whereSql += fmt.Sprintf(` WELLNameSource like '%s'`, wellnamesource) + whereSql += fmt.Sprintf(` WellInformation.WELLNameSource like '%s'`, wellnamesource) ifWhere = true } if req.BeginTime != "" { if ifWhere { - whereSql += fmt.Sprintf(` and CreateTableTime>'%s' `, req.BeginTime) + whereSql += fmt.Sprintf(` and WellInformation.CreateTableTime>'%s' `, req.BeginTime) } else { - whereSql += fmt.Sprintf(` CreateTableTime>'%s' `, req.BeginTime) + whereSql += fmt.Sprintf(` WellInformation.CreateTableTime>'%s' `, req.BeginTime) } ifWhere = true } if req.EndTime != "" { if ifWhere { - whereSql += fmt.Sprintf(` and CreateTableTime<'%s'`, req.EndTime) + whereSql += fmt.Sprintf(` and WellInformation.CreateTableTime<'%s'`, req.EndTime) } else { - whereSql += fmt.Sprintf(` CreateTableTime<'%s'`, req.EndTime) + whereSql += fmt.Sprintf(` WellInformation.CreateTableTime<'%s'`, req.EndTime) } ifWhere = true } if req.Checked { if ifWhere { - whereSql += fmt.Sprintf(` and service_type=1`) + whereSql += fmt.Sprintf(` and WellInformation.service_type=1`) } else { - whereSql += fmt.Sprintf(` service_type=1`) + whereSql += fmt.Sprintf(` WellInformation.service_type=1`) } ifWhere = true } if req.If_warn { if ifWhere { - whereSql += fmt.Sprintf(` and [tool_status_warning]=1`) + whereSql += fmt.Sprintf(` and WellInformation.tool_status_warning=1`) } else { - whereSql += fmt.Sprintf(` [tool_status_warning]=1`) + whereSql += fmt.Sprintf(` WellInformation.tool_status_warning=1`) + } + ifWhere = true + } + + // 类型筛选条件(仅在 req.Type != 0 时添加) + if req.Type != 0 { + typeCondition := fmt.Sprintf(` (well_type_t.well_type & %d) != 0 and well_type_t.if_available != 1`, req.Type) + if ifWhere { + whereSql += fmt.Sprintf(` and %s`, typeCondition) + } else { + whereSql += fmt.Sprintf(` %s`, typeCondition) } ifWhere = true } if spe_name, ok := spe_user[req.OpUser]; ok { if ifWhere { - whereSql += fmt.Sprintf(` and [ClOUDACCOUNT]='%s' `, spe_name) + whereSql += fmt.Sprintf(` and WellInformation.ClOUDACCOUNT='%s' `, spe_name) } else { - whereSql += fmt.Sprintf(` [ClOUDACCOUNT]='%s' `, spe_name) + whereSql += fmt.Sprintf(` WellInformation.ClOUDACCOUNT='%s' `, spe_name) } ifWhere = true } - /*if ifWhere { - whereSql += fmt.Sprintf(` and [es_flag]=1 `) - } else { - whereSql += fmt.Sprintf(` [es_flag]=1 `) - } - ifWhere = true*/ - - // if ifWhere { - // selSql = fmt.Sprintf("select top %d [ID],[WELLNameSource],[stats],[CreateTableTime],COALESCE([Operator],''),[rt_flag],COALESCE([ClOUDACCOUNT],''),[tool_status_warning] from [WellInformation] where [ID] not in (select top %d [ID] from [WellInformation] where %s order by [CreateTableTime],[tool_status_warning] desc) and %s order by [CreateTableTime] DESC,[tool_status_warning] desc", req.Count, (req.Index-1)*req.Count, whereSql, whereSql) - // } else { - // selSql = fmt.Sprintf("select top %d [ID],[WELLNameSource],[stats],[CreateTableTime],COALESCE([Operator],''),[rt_flag],COALESCE([ClOUDACCOUNT],''),[tool_status_warning] from [WellInformation] where [ID] not in (select top %d [ID] from [WellInformation] order by [CreateTableTime],[tool_status_warning] desc) order by [CreateTableTime] DESC,[tool_status_warning] desc", req.Count, (req.Index-1)*req.Count) - // } - + // 构建分页查询 SQL(查询时带上 well_type 字段) if ifWhere { selSql = fmt.Sprintf(` - SELECT [ID],[WELLNameSource],[stats],[CreateTableTime], - COALESCE([Operator],''),[rt_flag], - COALESCE([ClOUDACCOUNT],''),[tool_status_warning] + SELECT WellInformation.[ID], WellInformation.[WELLNameSource], WellInformation.[stats], + WellInformation.[CreateTableTime], + COALESCE(WellInformation.[Operator],''), WellInformation.[rt_flag], + COALESCE(WellInformation.[ClOUDACCOUNT],''), WellInformation.[tool_status_warning], + COALESCE(well_type_t.well_type, 0) as well_type FROM [WellInformation] + %s WHERE %s - ORDER BY [CreateTableTime] DESC, [tool_status_warning] DESC + ORDER BY WellInformation.[CreateTableTime] DESC, WellInformation.[tool_status_warning] DESC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`, - whereSql, (req.Index-1)*req.Count, req.Count) + joinSql, whereSql, (req.Index-1)*req.Count, req.Count) } else { selSql = fmt.Sprintf(` - SELECT [ID],[WELLNameSource],[stats],[CreateTableTime], - COALESCE([Operator],''),[rt_flag], - COALESCE([ClOUDACCOUNT],''),[tool_status_warning] + SELECT WellInformation.[ID], WellInformation.[WELLNameSource], WellInformation.[stats], + WellInformation.[CreateTableTime], + COALESCE(WellInformation.[Operator],''), WellInformation.[rt_flag], + COALESCE(WellInformation.[ClOUDACCOUNT],''), WellInformation.[tool_status_warning], + COALESCE(well_type_t.well_type, 0) as well_type FROM [WellInformation] - ORDER BY [CreateTableTime] DESC, [tool_status_warning] DESC + %s + ORDER BY WellInformation.[CreateTableTime] DESC, WellInformation.[tool_status_warning] DESC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`, - (req.Index-1)*req.Count, req.Count) + joinSql, (req.Index-1)*req.Count, req.Count) } + // 构建计数 SQL if ifWhere { - cntSql = fmt.Sprintf("select count([ID]) from [WellInformation] where %s", whereSql) + cntSql = fmt.Sprintf(` + SELECT COUNT(WellInformation.[ID]) + FROM [WellInformation] + %s + WHERE %s`, joinSql, whereSql) } else { - cntSql = fmt.Sprintf("select count([ID]) from [WellInformation]") + cntSql = fmt.Sprintf(`SELECT COUNT([ID]) FROM [WellInformation]`) } cnt, err := getRecordCount(sqlConn, cntSql) @@ -23358,6 +23371,7 @@ func get_well_history(response http.ResponseWriter, request *http.Request) { logs.Error("getWellEx1 count Query Error", err.Error()) return } + fmt.Println(selSql) row, err := sqlConn.Query(selSql) if err != nil { @@ -23373,8 +23387,10 @@ func get_well_history(response http.ResponseWriter, request *http.Request) { var wellstate int var rt_flag sql.NullInt64 var tsw sql.NullInt64 + var wellType int // 存储类型位掩码 + if err := row.Scan(&id, &d.WellNameSource, &wellstate, &d.Welltime, &d.Welloperator, - &rt_flag, &d.Upload_user, &tsw); err == nil { + &rt_flag, &d.Upload_user, &tsw, &wellType); err == nil { if len(d.Welltime) >= 19 { d.Welltime = d.Welltime[:10] + " " + d.Welltime[11:19] @@ -23398,6 +23414,9 @@ func get_well_history(response http.ResponseWriter, request *http.Request) { d.Tool_state_warning = true } + // 转换类型位掩码为中文字符串 + d.TypeName = convertWellTypeToName(wellType) + resp.Data = append(resp.Data, d) } else { @@ -23415,6 +23434,66 @@ func get_well_history(response http.ResponseWriter, request *http.Request) { logs.Info(fmt.Sprintf("getWellEx1 recv req end, use time: %v ms", (endTime-beginTime)/1e6)) } +// 类型转换函数 +func convertWellTypeToName(wellType int) string { + var t string + + if wellType&(1<<0) != 0 { + t = "测斜" + } + if wellType&(1<<1) != 0 { + if t != "" { + t += "," + "近钻头" + } else { + t = "近钻头" + } + } + if wellType&(1<<2) != 0 { + if t != "" { + t += "," + "电阻率" + } else { + t = "电阻率" + } + } + if wellType&(1<<3) != 0 { + if t != "" { + t += "," + "探管式方位伽马" + } else { + t = "探管式方位伽马" + } + } + if wellType&(1<<4) != 0 { + if t != "" { + t += "," + "钻铤式方位伽马" + } else { + t = "钻铤式方位伽马" + } + } + if wellType&(1<<5) != 0 { + if t != "" { + t += "," + "自然伽马" + } else { + t = "自然伽马" + } + } + if wellType&(1<<6) != 0 { + if t != "" { + t += "," + "工程参数" + } else { + t = "工程参数" + } + } + if wellType&(1<<7) != 0 { + if t != "" { + t += "," + "振动粘滑" + } else { + t = "振动粘滑" + } + } + + return t +} + func getWellEx1_en(response http.ResponseWriter, request *http.Request) { beginTime := time.Now().UnixNano() fmt.Println("getWellEx1_en recv req begin", time.Now().Format("2006-01-02 15:04:05")) @@ -32350,9 +32429,9 @@ func getWellData(ifDesc bool) (data []wellData, err error) { var sqlstr string if ifDesc { - sqlstr = "select [WELLNameSource],[WELLName],[stats],[CreateTableTime],COALESCE([IPADDR],''),COALESCE([Operator],''),COALESCE([ClOUDACCOUNT],''),[service_type] from [WellInformation] order by [CreateTableTime] desc" + sqlstr = "select [WELLNameSource],[WELLName],[stats],[CreateTableTime],COALESCE([IPADDR],''),COALESCE([Operator],''),COALESCE([ClOUDACCOUNT],''),COALESCE([service_type],'') from [WellInformation] order by [CreateTableTime] desc" } else { - sqlstr = "select [WELLNameSource],[WELLName],[stats],[CreateTableTime],COALESCE([IPADDR],''),COALESCE([Operator],''),COALESCE([ClOUDACCOUNT],''),[service_type] from [WellInformation] order by [CreateTableTime] asc" + sqlstr = "select [WELLNameSource],[WELLName],[stats],[CreateTableTime],COALESCE([IPADDR],''),COALESCE([Operator],''),COALESCE([ClOUDACCOUNT],''),COALESCE([service_type],'') from [WellInformation] order by [CreateTableTime] asc" } row, err := sqlConn.Query(sqlstr) @@ -32373,14 +32452,6 @@ func getWellData(ifDesc bool) (data []wellData, err error) { data = append(data, d) - } else { - - if d.WellNameSource == "合H69-3井" { - fmt.Println("d.WellNameSource11111", d.WellNameSource) - } - fmt.Println("d.WellNameSource", d.WellNameSource) - logs.Info("getWellData Query Error", err.Error()) - fmt.Println("getWellData Query Error", err.Error()) } count++ } @@ -34265,8 +34336,13 @@ func get_dev_list(response http.ResponseWriter, request *http.Request) { } // 查询总数 - countSQL := "SELECT COUNT(*) FROM base_worktime_data" + whereSQL - fmt.Println("get_dev_list-sql----", countSQL) + countSQL := `SELECT COUNT(*) FROM ( + SELECT DISTINCT + product_name, series, instrument, well_name, person_in_time, + person_out_time, in_time, out_time, engineer, total_work_time, + current_work_time, service_type, location + FROM base_worktime_data` + whereSQL + ` + ) t` var totalCount int64 err = sqlConn.QueryRow(countSQL).Scan(&totalCount) if err != nil { @@ -34279,11 +34355,13 @@ func get_dev_list(response http.ResponseWriter, request *http.Request) { // 查询数据(分页) offset := (page - 1) * pageSize dataSQL := fmt.Sprintf(` - SELECT + SELECT DISTINCT product_name, series, instrument, well_name, + person_in_time, + person_out_time, in_time, out_time, engineer, @@ -34313,14 +34391,14 @@ func get_dev_list(response http.ResponseWriter, request *http.Request) { for rows.Next() { var d devRespData var ( - productName, serial, number sql.NullString - wellName, inTimeRaw, outTimeRaw sql.NullString - engineer, totalWorkTime, currentWorkTime sql.NullString - serviceType, location sql.NullString + productName, serial, number sql.NullString + wellName, pinTimeRaw, poutTimeRaw, inTimeRaw, outTimeRaw sql.NullString + engineer, totalWorkTime, currentWorkTime sql.NullString + serviceType, location sql.NullString ) err := rows.Scan( &productName, &serial, &number, - &wellName, &inTimeRaw, &outTimeRaw, &engineer, + &wellName, &pinTimeRaw, &poutTimeRaw, &inTimeRaw, &outTimeRaw, &engineer, &totalWorkTime, ¤tWorkTime, &serviceType, &location, ) @@ -34333,6 +34411,8 @@ func get_dev_list(response http.ResponseWriter, request *http.Request) { d.Serial = serial.String d.Number = number.String d.WellName = wellName.String + d.PInTime = formatDateTime(pinTimeRaw.String) + d.POutTime = formatDateTime(poutTimeRaw.String) d.InTime = formatDateTime(inTimeRaw.String) d.OutTime = formatDateTime(outTimeRaw.String) d.Engineer = engineer.String @@ -34391,17 +34471,6 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { return } - // 打印日志验证 - fmt.Println("seriesList--------", reqData.Series) - fmt.Println("instrumentList:", reqData.Instrument) - fmt.Println("productNameList:", reqData.ProductName) - fmt.Println("wellNameList:", reqData.WellName) - fmt.Println("engineerList:", reqData.Engineer) - fmt.Println("locationList:", reqData.Location) - fmt.Println("serviceTypeList:", reqData.ServiceType) - fmt.Println("startTime:", reqData.StartTime) - fmt.Println("endTime:", reqData.EndTime) - // 数组条件 seriesList := reqData.Series instrumentList := reqData.Instrument @@ -34473,7 +34542,7 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { whereParts = append(whereParts, "in_time >= '"+escape(startTime)+"'") } if endTime != "" { - whereParts = append(whereParts, "out_time <= '"+escape(endTime)+"'") + whereParts = append(whereParts, "in_time <= '"+escape(endTime)+"'") } whereClause := "" @@ -34494,12 +34563,12 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { } // 3. 查询数据(带分页) - offset := (page - 1) * pageSize - dataSQL := "SELECT series, instrument, product_name, in_time, out_time, service_type, location, total_work_time, current_work_time, well_name, engineer" + + dataSQL := "SELECT series, instrument, product_name,person_in_time, person_out_time,in_time, out_time, service_type, location, total_work_time, current_work_time, well_name, engineer" + " FROM base_worktime_data" + whereClause + - fmt.Sprintf(" ORDER BY id OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", offset, pageSize) + fmt.Sprintf(" ORDER BY id ") fmt.Println("dataSQL:", dataSQL) + logs.Info("仪器为单位sql:", dataSQL) rows, err := sqlConn.Query(dataSQL) if err != nil { fmt.Println("查询数据失败:", err) @@ -34516,6 +34585,8 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { &tool.Series, &tool.Instrument, &tool.ProductName, + &tool.PInTime, + &tool.POutTime, &tool.InTime, &tool.OutTime, &tool.ServiceType, @@ -34552,8 +34623,8 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { // 表头 headers := []string{ - "序列号", "仪器名称", "编码", "井名称", "仪器入井时间", - "仪器出井时间", "仪器工程师", "本次使用时长", "累计使用时长", "所在地", + "序列号", "仪器名称", "编码", "井名称", "人员上井时间", "人员离井时间", "仪器入井时间", + "仪器出井时间", "仪器工程师", "仪器本次使用时长(h)", "仪器累计使用时长(h)", "所在地", } headerRow := sheet.AddRow() for _, h := range headers { @@ -34569,6 +34640,8 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { tool.ProductName, tool.Instrument, tool.WellName, + formatDateTime(tool.PInTime), + formatDateTime(tool.POutTime), formatDateTime(tool.InTime), formatDateTime(tool.OutTime), tool.Engineer, @@ -34621,16 +34694,277 @@ func export_Seir_detail(response http.ResponseWriter, request *http.Request) { fmt.Println("export_Seir_detail recv req end", time.Now().Format("2006-01-02 15:04:05"), "cost:", (time.Now().UnixNano()-beginTime)/1e6, "ms") } +func export_Seir_detail_en(response http.ResponseWriter, request *http.Request) { + beginTime := time.Now().UnixNano() + + // 1. 解析 JSON Body 参数 + body, err := ioutil.ReadAll(request.Body) + if err != nil { + fmt.Println("读取请求体失败:", err) + response.WriteHeader(http.StatusBadRequest) + response.Write([]byte(`{"code":1,"msg":"Request parameter format error."}`)) + return + } + defer request.Body.Close() + + var reqData SeirDetailReqData + err = json.Unmarshal(body, &reqData) + if err != nil { + fmt.Println("解析JSON失败:", err) + response.WriteHeader(http.StatusBadRequest) + response.Write([]byte(`{"code":1,"msg":"Request parameter format error."}`)) + return + } + + // 数组条件 + seriesList := reqData.Series + instrumentList := reqData.Instrument + productNameList := reqData.ProductName + wellNameList := reqData.WellName + engineerList := reqData.Engineer + locationList := reqData.Location + serviceTypeList := reqData.ServiceType + + // 时间范围 + startTime := reqData.StartTime + endTime := reqData.EndTime + + // 分页 + page := reqData.Index + if page <= 0 { + page = 1 + } + pageSize := reqData.Count + if pageSize <= 0 { + pageSize = 10000 + } + if pageSize > 50000 { + pageSize = 50000 + } + + // 辅助函数:转义单引号(防止SQL注入) + escape := func(s string) string { + return strings.ReplaceAll(s, "'", "''") + } + + // 辅助函数:构建 IN 子句 + buildIn := func(values []string, col string) string { + if len(values) == 0 { + return "" + } + quoted := make([]string, len(values)) + for i, v := range values { + quoted[i] = "'" + escape(v) + "'" + } + return fmt.Sprintf("%s IN (%s)", col, strings.Join(quoted, ",")) + } + + // 动态构建 WHERE 条件 + var whereParts []string + + if parts := buildIn(seriesList, "series"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(instrumentList, "instrument"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(productNameList, "product_name"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(wellNameList, "well_name"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(engineerList, "engineer"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(locationList, "location"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(serviceTypeList, "service_type"); parts != "" { + whereParts = append(whereParts, parts) + } + if startTime != "" { + whereParts = append(whereParts, "in_time >= '"+escape(startTime)+"'") + } + if endTime != "" { + whereParts = append(whereParts, "in_time <= '"+escape(endTime)+"'") + } + + whereClause := "" + if len(whereParts) > 0 { + whereClause = " WHERE " + strings.Join(whereParts, " AND ") + } + + // 2. 查询总记录数 + countSQL := "SELECT COUNT(*) FROM base_worktime_data" + whereClause + fmt.Println("countSQL:", countSQL) + var totalCount int64 + err = sqlConn.QueryRow(countSQL).Scan(&totalCount) + if err != nil { + fmt.Println("查询总数失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to retrieve data from the database."}`)) + return + } + + // 3. 查询数据(带分页) + dataSQL := "SELECT series, instrument, product_name, person_in_time ,person_out_time,in_time, out_time, service_type, location, total_work_time, current_work_time, well_name, engineer" + + " FROM base_worktime_data" + whereClause + + fmt.Sprintf(" ORDER BY id ") + + fmt.Println("dataSQL:", dataSQL) + logs.Info("仪器为单位sql:", dataSQL) + rows, err := sqlConn.Query(dataSQL) + if err != nil { + fmt.Println("查询数据失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to retrieve data from the database."}`)) + return + } + defer rows.Close() + + var allTools []devToolata + for rows.Next() { + var tool devToolata + err := rows.Scan( + &tool.Series, + &tool.Instrument, + &tool.ProductName, + &tool.PInTime, + &tool.POutTime, + &tool.InTime, + &tool.OutTime, + &tool.ServiceType, + &tool.Location, + &tool.TotalWorkTime, + &tool.CurrentWorkTime, + &tool.WellName, + &tool.Engineer, + ) + if err != nil { + fmt.Println("Scan data failed.:", err) + continue + } + allTools = append(allTools, tool) + } + + // 4. 生成 Excel 文件 + file := xlsx.NewFile() + sheet, err := file.AddSheet("Tool Details") + if err != nil { + fmt.Println("创建sheet失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to generate file."}`)) + return + } + + // 样式 + style := xlsx.NewStyle() + font := *xlsx.NewFont(11, "宋体") + style.Font = font + alignment := xlsx.Alignment{Horizontal: "center", Vertical: "center"} + style.Alignment = alignment + style.ApplyAlignment = true + + // 表头 + headers := []string{ + "Serial No.", "instrument name", "Code", "Well Name", "Person On-Site Time", "Person Out-Site Time", "In Hold Time", + "Out Hold Time", "Engineer", "Current Duration (h)", "Total Duration(h)", "Location", + } + headerRow := sheet.AddRow() + for _, h := range headers { + cell := headerRow.AddCell() + cell.SetStyle(style) + cell.Value = h + } + + // 数据行 + for _, tool := range allTools { + values := []string{ + tool.Series, + tool.ProductName, + tool.Instrument, + tool.WellName, + formatDateTime(tool.PInTime), + formatDateTime(tool.POutTime), + formatDateTime(tool.InTime), + formatDateTime(tool.OutTime), + tool.Engineer, + tool.CurrentWorkTime, + tool.TotalWorkTime, + tool.Location, + } + row := sheet.AddRow() + for _, v := range values { + cell := row.AddCell() + cell.SetStyle(style) + cell.Value = v + } + } + + // 5. 保存文件 + err = os.MkdirAll("./authfile", 0755) + if err != nil { + fmt.Println("创建导出目录失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to create directory."}`)) + return + } + + filename := fmt.Sprintf("Well Site Instrument Details List (Instrument)_%s.xlsx", time.Now().Format("20060102150405")) + filePath := fmt.Sprintf("./authfile/%s", filename) + err = file.Save(filePath) + if err != nil { + fmt.Println("保存Excel文件失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to save file."}`)) + return + } + + // 6. 返回响应 + type exportResp struct { + FileId string `json:"fileId"` + TotalCount int64 `json:"totalCount"` + ExportRows int `json:"exportRows"` + } + resp := exportResp{ + FileId: filename, + TotalCount: totalCount, + ExportRows: len(allTools), + } + jresp, _ := json.Marshal(resp) + response.Header().Set("Content-Type", "application/json") + response.Write(jresp) + + fmt.Println("export_Seir_detail recv req end", time.Now().Format("2006-01-02 15:04:05"), "cost:", (time.Now().UnixNano()-beginTime)/1e6, "ms") +} + // 格式化 ISO 8601 时间为 "2006-01-02 15:04:05" func formatDateTime(iso string) string { if iso == "" { return "" } + // 尝试解析 RFC3339 t, err := time.Parse(time.RFC3339, iso) - if err != nil { - return iso // 解析失败返回原值 + if err == nil { + if t.Year() <= 1900 { + return "" + } + return t.Format("2006-01-02 15:04:05") } - return t.Format("2006-01-02 15:04:05") + // 尝试解析 "2006-01-02 15:04:05" 格式 + t, err = time.Parse("2006-01-02 15:04:05", iso) + if err == nil { + if t.Year() <= 1900 { + return "" + } + return t.Format("2006-01-02 15:04:05") + } + // 如果 iso 本身就是 "1900-01-01 00:00:00" 等 + if strings.HasPrefix(iso, "1900-01-01") { + return "" + } + return iso // 其他情况返回原值 } func export_Well_detail(response http.ResponseWriter, request *http.Request) { @@ -34662,6 +34996,11 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { fmt.Println("engineer:", reqData.Engineer) fmt.Println("in_time_start:", reqData.InTimeStart) fmt.Println("in_time_end:", reqData.InTimeEnd) + // if reqData.InTimeStart == "" { + // response.WriteHeader(http.StatusOK) + // response.Write([]byte(`{"code":1,"msg":"请填写入井开始时间"}`)) + // return + // } // 数组条件(从 reqData 中获取) seriesList := reqData.Serial @@ -34726,7 +35065,7 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { whereParts = append(whereParts, "in_time >= '"+escape(startTime)+"'") } if endTime != "" { - whereParts = append(whereParts, "out_time <= '"+escape(endTime)+"'") + whereParts = append(whereParts, "in_time <= '"+escape(endTime)+"'") } whereClause := "" @@ -34747,12 +35086,12 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { } // 3. 查询数据(带分页) - offset := (page - 1) * pageSize // 注意:ORDER BY 必须存在,这里假设表有 id 列,请根据实际调整 - dataSQL := "SELECT series, instrument, product_name, in_time, out_time, service_type, location, total_work_time, current_work_time, well_name, engineer" + + dataSQL := "SELECT well_name, series, instrument, product_name, person_in_time, person_out_time, in_time, out_time, engineer, current_work_time, total_work_time, location" + " FROM base_worktime_data" + whereClause + - fmt.Sprintf(" ORDER BY id OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", offset, pageSize) - + fmt.Sprintf(" ORDER BY id ") + fmt.Println("井为单位sql", dataSQL) + logs.Info("井为单位sql:", dataSQL) rows, err := sqlConn.Query(dataSQL) if err != nil { fmt.Println("查询数据失败:", err) @@ -34766,17 +35105,18 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { for rows.Next() { var tool devToolata err := rows.Scan( - &tool.Series, - &tool.Instrument, - &tool.ProductName, - &tool.InTime, - &tool.OutTime, - &tool.ServiceType, - &tool.Location, - &tool.TotalWorkTime, - &tool.CurrentWorkTime, - &tool.WellName, - &tool.Engineer, + &tool.WellName, // 井名称 + &tool.Series, // 序列号 + &tool.Instrument, // 仪器名称 + &tool.ProductName, // 编码 + &tool.PInTime, // 人员上井时间 + &tool.POutTime, // 人员离井时间 + &tool.InTime, // 仪器入井时间 + &tool.OutTime, // 仪器出井时间 + &tool.Engineer, // 仪器工程师 + &tool.CurrentWorkTime, // 仪器本次使用时长 + &tool.TotalWorkTime, // 仪器累计使用时长(h) + &tool.Location, // 所在地 ) if err != nil { fmt.Println("扫描数据失败:", err) @@ -34805,8 +35145,8 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { // 表头 headers := []string{ - "井名称", "序列号", "仪器名称", "编码", "仪器入井时间", - "仪器出井时间", "仪器工程师", "本次使用时长", "累计使用时长", "所在地", + "井名称", "序列号", "仪器名称", "编码", "人员上井时间", "人员离井时间", "仪器入井时间", + "仪器出井时间", "仪器工程师", "仪器本次使用时长", "仪器累计使用时长(h)", "所在地", } headerRow := sheet.AddRow() for _, h := range headers { @@ -34822,6 +35162,8 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { tool.Series, tool.ProductName, tool.Instrument, + formatDateTime(tool.PInTime), + formatDateTime(tool.POutTime), formatDateTime(tool.InTime), formatDateTime(tool.OutTime), tool.Engineer, @@ -34874,6 +35216,255 @@ func export_Well_detail(response http.ResponseWriter, request *http.Request) { fmt.Println("export_Well_detail recv req end", time.Now().Format("2006-01-02 15:04:05"), "cost:", (time.Now().UnixNano()-beginTime)/1e6, "ms") } +func export_Well_detail_en(response http.ResponseWriter, request *http.Request) { + beginTime := time.Now().UnixNano() + + // 1. 解析 JSON Body 参数 + body, err := ioutil.ReadAll(request.Body) + if err != nil { + fmt.Println("读取请求体失败:", err) + response.WriteHeader(http.StatusBadRequest) + response.Write([]byte(`{"code":1,"msg":"Failed to read request parameters."}`)) + return + } + defer request.Body.Close() + + var reqData WellDetailReqData + err = json.Unmarshal(body, &reqData) + if err != nil { + fmt.Println("解析JSON失败:", err) + response.WriteHeader(http.StatusBadRequest) + response.Write([]byte(`{"code":1,"msg":"Invalid request parameter format."}`)) + return + } + + // 打印日志验证 + fmt.Println("wellNameList--------", reqData.Wellname) + fmt.Println("serial:", reqData.Serial) + fmt.Println("number:", reqData.Number) + fmt.Println("engineer:", reqData.Engineer) + fmt.Println("in_time_start:", reqData.InTimeStart) + fmt.Println("in_time_end:", reqData.InTimeEnd) + // if reqData.InTimeStart == "" { + // response.WriteHeader(http.StatusOK) + // response.Write([]byte(`{"code":1,"msg":"请填写入井开始时间"}`)) + // return + // } + + // 数组条件(从 reqData 中获取) + seriesList := reqData.Serial + instrumentList := reqData.Number + wellNameList := reqData.Wellname + engineerList := reqData.Engineer + serviceType := reqData.ServiceType + + // 时间范围 + startTime := reqData.InTimeStart + endTime := reqData.InTimeEnd + + // 分页(从 reqData 中获取) + page := reqData.Index + if page <= 0 { + page = 1 + } + pageSize := reqData.Count + if pageSize <= 0 { + pageSize = 10000 + } + if pageSize > 50000 { + pageSize = 50000 + } + + // 辅助函数:转义单引号(防止SQL注入) + escape := func(s string) string { + return strings.ReplaceAll(s, "'", "''") + } + + // 辅助函数:构建 IN 子句 + buildIn := func(values []string, col string) string { + if len(values) == 0 { + return "" + } + quoted := make([]string, len(values)) + for i, v := range values { + quoted[i] = "'" + escape(v) + "'" + } + return fmt.Sprintf("%s IN (%s)", col, strings.Join(quoted, ",")) + } + + // 动态构建 WHERE 条件 + var whereParts []string + + if parts := buildIn(seriesList, "series"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(instrumentList, "instrument"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(wellNameList, "well_name"); parts != "" { + whereParts = append(whereParts, parts) + } + if parts := buildIn(engineerList, "engineer"); parts != "" { + whereParts = append(whereParts, parts) + } + if serviceType != "" { + whereParts = append(whereParts, fmt.Sprintf("service_type = '%s'", escape(serviceType))) + } + if startTime != "" { + whereParts = append(whereParts, "in_time >= '"+escape(startTime)+"'") + } + if endTime != "" { + whereParts = append(whereParts, "in_time <= '"+escape(endTime)+"'") + } + + whereClause := "" + if len(whereParts) > 0 { + whereClause = " WHERE " + strings.Join(whereParts, " AND ") + } + + // 2. 查询总记录数 + countSQL := "SELECT COUNT(*) FROM base_worktime_data" + whereClause + fmt.Println("countSQL:", countSQL) + var totalCount int64 + err = sqlConn.QueryRow(countSQL).Scan(&totalCount) + if err != nil { + fmt.Println("查询总数失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to query data."}`)) + return + } + + // 3. 查询数据(带分页) + // 注意:ORDER BY 必须存在,这里假设表有 id 列,请根据实际调整 + dataSQL := "SELECT well_name, series, instrument, product_name, person_in_time, person_out_time, in_time, out_time, engineer, current_work_time, total_work_time, location" + + " FROM base_worktime_data" + whereClause + + fmt.Sprintf(" ORDER BY id ") + fmt.Println("井为单位sql", dataSQL) + logs.Info("井为单位sql:", dataSQL) + rows, err := sqlConn.Query(dataSQL) + if err != nil { + fmt.Println("查询数据失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to query data."}`)) + return + } + defer rows.Close() + + var allTools []devToolata + for rows.Next() { + var tool devToolata + err := rows.Scan( + &tool.WellName, // 井名称 + &tool.Series, // 序列号 + &tool.Instrument, // 仪器名称 + &tool.ProductName, // 编码 + &tool.PInTime, // 人员上井时间 + &tool.POutTime, // 人员离井时间 + &tool.InTime, // 仪器入井时间 + &tool.OutTime, // 仪器出井时间 + &tool.Engineer, // 仪器工程师 + &tool.CurrentWorkTime, // 仪器本次使用时长 + &tool.TotalWorkTime, // 仪器累计使用时长(h) + &tool.Location, // 所在地 + ) + if err != nil { + fmt.Println("扫描数据失败:", err) + continue + } + allTools = append(allTools, tool) + } + + // 4. 生成 Excel 文件 + file := xlsx.NewFile() + sheet, err := file.AddSheet("工具明细") + if err != nil { + fmt.Println("创建sheet失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to generate file."}`)) + return + } + + // 样式 + style := xlsx.NewStyle() + font := *xlsx.NewFont(11, "宋体") + style.Font = font + alignment := xlsx.Alignment{Horizontal: "center", Vertical: "center"} + style.Alignment = alignment + style.ApplyAlignment = true + + // 表头 + headers := []string{ + "Well Name", "Serial No.", "Instrument Name", "Code", "In Time", + "Out Time", "Instrument Engineer", "Current Duration (h)", "Total Duration (h)", "Location", + } + headerRow := sheet.AddRow() + for _, h := range headers { + cell := headerRow.AddCell() + cell.SetStyle(style) + cell.Value = h + } + + // 数据行 + for _, tool := range allTools { + values := []string{ + tool.WellName, + tool.Series, + tool.ProductName, + tool.Instrument, + formatDateTime(tool.PInTime), + formatDateTime(tool.POutTime), + formatDateTime(tool.InTime), + formatDateTime(tool.OutTime), + tool.Engineer, + tool.CurrentWorkTime, + tool.TotalWorkTime, + tool.Location, + } + row := sheet.AddRow() + for _, v := range values { + cell := row.AddCell() + cell.SetStyle(style) + cell.Value = v + } + } + + // 5. 保存文件 + err = os.MkdirAll("./authfile", 0755) + if err != nil { + fmt.Println("创建导出目录失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to create directory."}`)) + return + } + + filename := fmt.Sprintf("井上仪器明细清单(井位)_%s.xlsx", time.Now().Format("20060102150405")) + filePath := fmt.Sprintf("./authfile/%s", filename) + err = file.Save(filePath) + if err != nil { + fmt.Println("保存Excel文件失败:", err) + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte(`{"code":1,"msg":"Failed to save file."}`)) + return + } + + // 6. 返回响应 + type exportResp struct { + FileId string `json:"fileId"` + TotalCount int64 `json:"totalCount"` + ExportRows int `json:"exportRows"` + } + resp := exportResp{ + FileId: filename, + TotalCount: totalCount, + ExportRows: len(allTools), + } + jresp, _ := json.Marshal(resp) + response.Header().Set("Content-Type", "application/json") + response.Write(jresp) + + fmt.Println("export_Well_detail recv req end", time.Now().Format("2006-01-02 15:04:05"), "cost:", (time.Now().UnixNano()-beginTime)/1e6, "ms") +} + func getQueryWell(response http.ResponseWriter, request *http.Request) { beginTime := time.Now().UnixNano() response.Header().Set("Content-Type", "application/json") @@ -34951,9 +35542,9 @@ func getQueryWell(response http.ResponseWriter, request *http.Request) { // 5. 查询工程师 rows, err = sqlConn.Query(` - SELECT DISTINCT engineer FROM base_worktime_data - WHERE engineer IS NOT NULL AND engineer != '' ORDER BY engineer - `) + SELECT DISTINCT engineer FROM base_worktime_data + WHERE engineer IS NOT NULL AND engineer != '' ORDER BY engineer + `) if err != nil { response.WriteHeader(http.StatusInternalServerError) response.Write([]byte(`{"code":1,"msg":"查询工程师失败"}`)) @@ -34962,7 +35553,17 @@ func getQueryWell(response http.ResponseWriter, request *http.Request) { for rows.Next() { var eng string rows.Scan(&eng) - respData.Engineers = append(respData.Engineers, eng) + // 过滤掉纯数字的工程师名 + isPureNum := true + for _, ch := range eng { + if ch < '0' || ch > '9' { + isPureNum = false + break + } + } + if !isPureNum { + respData.Engineers = append(respData.Engineers, eng) + } } rows.Close() diff --git a/req.go b/req.go index c7f7f61..97243cb 100644 --- a/req.go +++ b/req.go @@ -364,6 +364,7 @@ type get_well_ex1_req struct { EndTime string `json:"EndTime"` Checked bool `json:"checked"` If_warn bool `json:"if_warn"` + Type int `json:"type"` // 新增:类型筛选(位掩码) } type GetWellExReq struct { diff --git a/res.go b/res.go index d37e125..2f06ab8 100644 --- a/res.go +++ b/res.go @@ -363,6 +363,8 @@ type wellExData struct { Upload_user string `json:"upload_user"` Tool_state_warning bool `json:"tsw"` + + TypeName string `json:"type_name"` } type SeriesWarning struct { @@ -798,6 +800,8 @@ type devRespData struct { Serial string `json:"serial"` // 系列号 Number string `json:"number"` // 编号 WellName string `json:"wellname"` // 井名 + PInTime string `json:"p_in_time"` // 入井时间(可能为null) + POutTime string `json:"p_out_time"` // 出井时间(可能为null) InTime string `json:"in_time"` // 入井时间(可能为null) OutTime string `json:"out_time"` // 出井时间(可能为null) Engineer string `json:"engineer"` // 上井工程师(可能为null)