diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/authfile/1752200922199960200.pdf b/authfile/1752200922199960200.pdf deleted file mode 100644 index 285837f..0000000 Binary files a/authfile/1752200922199960200.pdf and /dev/null differ diff --git a/deescloud.exe b/deescloud.exe index 1ad4d2d..8a1f0f5 100644 Binary files a/deescloud.exe and b/deescloud.exe differ diff --git a/main.go b/main.go index f891d33..c748fd4 100644 --- a/main.go +++ b/main.go @@ -1533,6 +1533,7 @@ func main() { http.HandleFunc("/deescloud/get_b_life", get_battery_life) http.HandleFunc("/deescloud/get_tool_WarningCsv", get_tool_WarningCsv) + http.HandleFunc("/deescloud/getInstrumentMess", getInstrumentMess) //监听服务 fmt.Println("listen server ...") @@ -3329,7 +3330,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],[6808],[6809],[6810],[6811],[6812],[6813],[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],[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) rows, err := sqlConn.Query(sel_sql) if err == nil { for rows.Next() { @@ -3337,6 +3338,7 @@ func get_dev_manage_info(user string, wellname string) (resp []Dev_manage) { var s string if err = rows.Scan(&v.ID, &v.Sid, &v.Iid, &v.Ver, &v.P_date, &v.Cal_date, &v.Total_wt, &v.Cur_wt, &v.Repair_cnt, &v.Region, &v.Location, &v.Responsible, &s); err != nil { logs.Error(fmt.Sprintf(`get_dev_manage_info scan upload err:%s`, err.Error())) + fmt.Println(fmt.Sprintf(`get_dev_manage_info scan upload err:%s`, err.Error())) } else { if s == "1" { v.Flag = true @@ -3447,8 +3449,9 @@ func get_tool_warning_pdf(response http.ResponseWriter, request *http.Request) { } -func leftOneData(wellName string) []VibrationStatData { +func leftOneData(wellName string, IsMemory *bool) []VibrationStatData { var db string + var cmdSql string var sql string var results []VibrationStatData rwLocker.RLock() @@ -3457,6 +3460,10 @@ func leftOneData(wellName string) []VibrationStatData { count105 := 0 count106 := 0 fmt.Println("wellName---------", wellName) + memory := false // 默认值 + if IsMemory != nil { + memory = *IsMemory // 使用传入值 + } if v, ok := wellNamemap[wellName]; ok { rwLocker.RUnlock() db = v @@ -3464,29 +3471,49 @@ func leftOneData(wellName string) []VibrationStatData { rwLocker.RUnlock() return results // return empty slice if well not found } + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { fmt.Println("振动粘滑数据未找到") return results // return empty slice if connection fails } - - sql = fmt.Sprintf("SELECT DISTINCT [4303] AS DEEP, [4304] AS TIME, [4305] AS CODE, [4306] AS VALUE, CASE WHEN [4305] in(104,105) THEN CASE WHEN [4306] < 0.5 THEN 0 WHEN [4306] >= 0.5 AND [4306] < 1 THEN 1 WHEN [4306] >= 1 AND [4306] < 2 THEN 2 WHEN [4306] >= 2 AND [4306] < 3 THEN 3 WHEN [4306] >= 3 AND [4306] < 5 THEN 4 WHEN [4306] >= 5 AND [4306] < 8 THEN 5 WHEN [4306] >= 8 AND [4306] < 15 THEN 6 WHEN [4306] >= 15 THEN 7 ELSE NULL END WHEN [4305] = 106 THEN CASE WHEN [4306] < 40 THEN 0 WHEN [4306] >= 40 AND [4306] < 60 THEN 1 WHEN [4306] >= 60 AND [4306] < 80 THEN 2 WHEN [4306] >= 80 AND [4306] < 100 THEN 3 WHEN [4306] >= 100 AND [4306] < 120 THEN 4 WHEN [4306] >= 120 AND [4306] < 150 THEN 5 WHEN [4306] >= 150 THEN 6 ELSE NULL END ELSE NULL END AS LEVEL FROM DECODETABLE WHERE [4305] IN (104, 105, 106) ORDER BY [4303] DESC;") + if memory { + sql = fmt.Sprintf("SELECT COALESCE([6875], 0) AS DEEP, CONVERT(varchar(19), CONVERT(datetime, [6874]), 120) AS TIME, CODE, CASE CODE WHEN 104 THEN [6878] WHEN 105 THEN [6881] WHEN 106 THEN [6885] END AS VALUE, CASE CODE WHEN 104 THEN [6887] WHEN 105 THEN [6888] WHEN 106 THEN [6889] END AS LEVEL FROM STICKMEMORY CROSS APPLY (VALUES (104), (105), (106)) AS Codes(CODE) ORDER BY CONVERT(datetime, [6874]) ASC") + } else { + sql = fmt.Sprintf("SELECT DISTINCT [4303] AS DEEP, [4304] AS TIME, [4305] AS CODE, [4306] AS VALUE, CASE WHEN [4305] in(104,105) THEN CASE WHEN [4306] < 0.5 THEN 0 WHEN [4306] >= 0.5 AND [4306] < 1 THEN 1 WHEN [4306] >= 1 AND [4306] < 2 THEN 2 WHEN [4306] >= 2 AND [4306] < 3 THEN 3 WHEN [4306] >= 3 AND [4306] < 5 THEN 4 WHEN [4306] >= 5 AND [4306] < 8 THEN 5 WHEN [4306] >= 8 AND [4306] < 15 THEN 6 WHEN [4306] >= 15 THEN 7 ELSE NULL END WHEN [4305] = 106 THEN CASE WHEN [4306] < 40 THEN 0 WHEN [4306] >= 40 AND [4306] < 60 THEN 1 WHEN [4306] >= 60 AND [4306] < 80 THEN 2 WHEN [4306] >= 80 AND [4306] < 100 THEN 3 WHEN [4306] >= 100 AND [4306] < 120 THEN 4 WHEN [4306] >= 120 AND [4306] < 150 THEN 5 WHEN [4306] >= 150 THEN 6 ELSE NULL END ELSE NULL END AS LEVEL FROM DECODETABLE WHERE [4305] IN (104, 105, 106) ORDER BY [4304] ASC;") + } + fmt.Println("执行的查询sql-----------------------------------", sql) fmt.Sprintf("执行SQL查询: %s", sql) rows, err := conn.Query(sql) if err != nil { logs.Info("Query Error", err.Error()) + fmt.Println("Query Error", err.Error()) return results // return empty slice if query fails } defer rows.Close() - + fmt.Println("数据获取成功") for rows.Next() { var data VibrationStatData - + fmt.Println("数据获取成功111111111111") err := rows.Scan(&data.Deep, &data.Time, &data.Code, &data.Value, &data.Level) if err != nil { - logs.Info("Scan Error", err.Error()) + fmt.Println("Scan Error", err.Error()) continue } + fmt.Println("Code: %d, Value: %f, Level: %d", data.Code, data.Value, data.Level) // 统计各类CODE的数量 switch data.Code { case 104: @@ -3496,8 +3523,17 @@ func leftOneData(wellName string) []VibrationStatData { case 106: count106++ } + results = append(results, data) } + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } return results // return the populated results } @@ -3540,6 +3576,8 @@ func convertToStatsData(vibrationData []VibrationStatData, code int) [][]string } } + fmt.Println("total---", total) + // 计算百分比 percentage := "0.00%" if total > 0 { @@ -3553,14 +3591,20 @@ func convertToStatsData(vibrationData []VibrationStatData, code int) [][]string percentage, }) } - + if total > 0 { + statsData = append(statsData, []string{ + "Total", + strconv.Itoa(total), + "100.00%", // 保持百分比格式一致 + }) + return statsData + } // 添加总计行 statsData = append(statsData, []string{ - " ", + "Total", strconv.Itoa(total), - "100.00%", // 保持百分比格式一致 + "0.00%", // 保持百分比格式一致 }) - fmt.Println("statsData,-------------------", statsData) return statsData } @@ -3615,12 +3659,20 @@ func convertStickSlipData(vibrationData []VibrationStatData) [][]string { percentage, }) } + if total > 0 { + result = append(result, []string{ + "Total", + strconv.Itoa(total), // 这里使用动态计算的total + "100%", + }) + return result + } // 添加总计行(使用动态计算的总数) result = append(result, []string{ - " ", + "Total", strconv.Itoa(total), // 这里使用动态计算的total - "100%", + "0.00%", }) return result @@ -3646,6 +3698,24 @@ func determineStickSlipLevel(value float64) int { } } +func parseTime(timeStr string) (time.Time, error) { + //2025/1/21 12:48 + // 先尝试 RFC3339 格式 (带T的格式) + t, err := time.Parse(time.RFC3339, timeStr) + if err == nil { + return t, nil + } + + // 再尝试普通格式 (空格分隔) + t, err = time.Parse("2006-01-02 15:04:05", timeStr) + if err == nil { + return t, nil + } + + // 如果两种格式都失败,返回错误 + return time.Time{}, fmt.Errorf("无法解析时间字符串: %s", timeStr) +} + func generateVibrationTable(vibrationData []VibrationStatData, code int) [][]string { // 1. 根据code过滤数据 filteredData := make([]VibrationStatData, 0) @@ -3684,8 +3754,10 @@ func generateVibrationTable(vibrationData []VibrationStatData, code int) [][]str // 计算当前点到下一个点的时间段(最后一个点不计算) if i < len(filteredData)-1 { - currentTime, err1 := time.Parse(time.RFC3339, current.Time) - nextTime, err2 := time.Parse(time.RFC3339, filteredData[i+1].Time) + // currentTime, err1 := time.Parse(time.RFC3339, current.Time) + // nextTime, err2 := time.Parse(time.RFC3339, filteredData[i+1].Time) + currentTime, err1 := parseTime(current.Time) + nextTime, err2 := parseTime(filteredData[i+1].Time) if err1 == nil && err2 == nil { duration := nextTime.Sub(currentTime).Minutes() @@ -3707,8 +3779,16 @@ func generateVibrationTable(vibrationData []VibrationStatData, code int) [][]str } // 4. 构建结果表格 table := make([][]string, 8) + for level := 0; level < 8; level++ { - col1 := fmt.Sprintf("Level%d %d", level, counts[level]) + // 直接在 "Level" 后面添加两个空格 + levelStr := fmt.Sprintf(" Level %d", level) // 注意这里有两个空格 + + // 使用固定宽度格式化 Level 和计数 + col1 := fmt.Sprintf("%-8s %-6s", + levelStr, + fmt.Sprintf(" %d", counts[level])) + col2 := formatDuration(durations[level]) col3 := "No Limit" if level >= 4 { @@ -3722,25 +3802,37 @@ func generateVibrationTable(vibrationData []VibrationStatData, code int) [][]str func makeEmptyTable() [][]string { table := make([][]string, 8) + levelCounts := make([]int, 8) for level := 0; level < 8; level++ { - col1 := fmt.Sprintf("Level%d 0", level) - col2 := "0min 0h" + count := 0 + if level <= 6 { + count = levelCounts[level] + } + + levelStr := fmt.Sprintf(" Level %d", level) + col1 := fmt.Sprintf("%-8s %-6s", + levelStr, + fmt.Sprintf(" %d", count)) + fmt.Println("col1--", col1) + col2 := fmt.Sprintf("%4dmin %3dh", 0, 0) col3 := "No Limit" if level >= 4 { - col3 = "0%" + col3 = calculateThreshold(level, 0) } table[level] = []string{col1, col2, col3} } return table } -// 格式化持续时间(分钟 -> "Xmin Yh"格式) func formatDuration(totalMinutes float64) string { - // 四舍五入到整数分钟 - totalRounded := math.Round(totalMinutes) - hours := int(totalRounded) / 60 - minutes := int(totalRounded) % 60 - return fmt.Sprintf("%dmin %dh", minutes, hours) + rawMinutes := int(math.Round(totalMinutes)) + rawHours := rawMinutes / 60 + + // 使用固定宽度格式化分钟和小时 + minStr := fmt.Sprintf("%4dmin", rawMinutes) // 固定4位宽度(9999min) + hourStr := fmt.Sprintf("%2dh", rawHours) // 固定2位宽度(99h) + + return minStr + " " + hourStr // 中间两个空格 } // 计算阈值百分比 @@ -3768,21 +3860,27 @@ func calculateThreshold(level int, totalMinutes float64) string { } func generateVibrationTableData(vibrationData []VibrationStatData) [][]string { - // 初始化全零统计数组 (Level0-7) levelCounts := make([]int, 8) // 出现次数 levelDurations := make([]int, 8) // 持续时间(秒) - // 正确的时间解析函数 (RFC3339格式) parseTime := func(t string) time.Time { + // 1. 先尝试 RFC3339 格式 (带T的格式) parsed, err := time.Parse(time.RFC3339, t) - if err != nil { - fmt.Printf("!!! 时间解析失败: %s\n", t) - return time.Time{} // 返回零值 + if err == nil { + return parsed } - return parsed - } + // 2. 如果失败,尝试你指定的格式 "2006-01-02 15:04:05" + parsed, err = time.Parse("2006-01-02 15:04:05", t) + if err == nil { + return parsed + } + + // 3. 如果两种格式都失败,记录错误 + fmt.Printf("!!! 时间解析失败: %s (错误: %v)\n", t, err) + return time.Time{} // 返回零值 + } // 筛选Code=106的数据 var filteredData []VibrationStatData for _, data := range vibrationData { @@ -3845,43 +3943,42 @@ func generateVibrationTableData(vibrationData []VibrationStatData) [][]string { for level := 0; level < 8; level++ { // 第一列:Level和出现次数 count := 0 - if level <= 6 { // 确保level7的计数为0 + if level <= 6 { count = levelCounts[level] } - col1 := fmt.Sprintf("Level%d %d", level, count) + + levelStr := fmt.Sprintf(" Level %d", level) + col1 := fmt.Sprintf("%-8s %-6s", + levelStr, + fmt.Sprintf(" %d", count)) // 第二列:持续时间转换 totalSeconds := 0 - if level <= 6 { // 确保level7的持续时间为0 + if level <= 6 { totalSeconds = levelDurations[level] } - minutes := totalSeconds / 60 - hours := minutes / 60 - remainingMinutes := minutes % 60 - col2 := fmt.Sprintf("%dmin %dh", remainingMinutes, hours) + + totalMinutes := totalSeconds / 60 + totalHours := totalMinutes / 60 + + // 固定宽度格式化:分钟(4位) + "min" + 小时(4位) + "h" + col2 := fmt.Sprintf("%4dmin %3dh", totalMinutes, totalHours) // 第三列:特殊级别处理 col3 := "No Limit" + //特殊处理占位符,要不然打印的pdf格式就乱掉了。 switch level { case 6: percentage := float64(totalSeconds) / (300 * 60) * 100 - col3 = fmt.Sprintf("%.0f%%", percentage) + if percentage >= 100 { + col3 = fmt.Sprintf("%3.0f%%", percentage) // 100% -> "100%" + } else if percentage >= 10 { + col3 = fmt.Sprintf(" %2.0f%%", percentage) // 10-99% -> " 50%" + } else { + col3 = fmt.Sprintf(" %1.0f%%", percentage) // 0-9% -> " 0%" + } case 7: - col3 = "0%" // 强制level7显示0% - } - - // Level1的详细计算过程 - if level == 1 { - fmt.Printf("\n>>> LEVEL1 最终计算详情:\n") - fmt.Printf(" 总秒数: %d秒 (来自levelDurations[1])\n", levelDurations[1]) - fmt.Printf(" 总分钟: %d分钟 (%d秒 / 60)\n", minutes, levelDurations[1]) - fmt.Printf(" 小时: %d小时 (%d分钟 / 60)\n", hours, minutes) - fmt.Printf(" 剩余分钟: %d分钟 (%d分钟 %% 60)\n", remainingMinutes, minutes) - fmt.Printf(" => 格式化字符串: \"%dmin %dh\"\n", remainingMinutes, hours) - fmt.Printf(" 出现次数: %d次 (来自levelCounts[1])\n", levelCounts[1]) - fmt.Printf(" => 第一列: \"Level%d %d\"\n", level, count) - fmt.Printf(" 第三列: Level1使用默认值 \"%s\"\n", col3) - fmt.Printf(" => 最终行内容: [%s, %s, %s]\n", col1, col2, col3) + col3 = " 0%" // 3位宽度保持对齐 } table[level] = []string{col1, col2, col3} @@ -3892,15 +3989,6 @@ func generateVibrationTableData(vibrationData []VibrationStatData) [][]string { return table } -// 辅助函数:将秒数组转换为分钟数组 -func convertSecondsToMinutes(seconds []int) []float64 { - minutes := make([]float64, len(seconds)) - for i, sec := range seconds { - minutes[i] = float64(sec) / 60.0 - } - return minutes -} - // func generateVibrationTableData(vibrationData []VibrationStatData) [][]string { // // 初始化全零统计数组 (Level0-7) // levelCounts := make([]int, 8) // 出现次数 @@ -4019,22 +4107,25 @@ func calculateLevel(value float64) int { func ExtractTimeDepthRange(vibrationData []VibrationStatData) TimeDepthRange { if len(vibrationData) == 0 { return TimeDepthRange{ - FromTime: "N/A", - ToTime: "N/A", + FromTime: " ", + ToTime: " ", MinDepth: 0, MaxDepth: 0, } } // 初始化第一个数据点 - firstTime, _ := time.Parse(time.RFC3339, vibrationData[0].Time) + // firstTime, _ := time.Parse(time.RFC3339, vibrationData[0].Time) + firstTime, _ := parseTime(vibrationData[0].Time) minTime, maxTime := firstTime, firstTime minDepth, maxDepth := vibrationData[0].Deep, vibrationData[0].Deep // 遍历所有数据点 for _, data := range vibrationData { // 解析时间 - t, err := time.Parse(time.RFC3339, data.Time) + // t, err := time.Parse(time.RFC3339, data.Time) + fmt.Println("data.Time", data.Time) + t, err := parseTime(data.Time) if err != nil { continue // 跳过格式错误的数据 } @@ -4074,10 +4165,11 @@ func get_vibration_report_pdf(response http.ResponseWriter, request *http.Reques var baseinfo get_vibration_resp var filename string - - vibrationData := leftOneData(req.Wellname) + fmt.Println("IsMemory------------------", req.IsMemory) + vibrationData := leftOneData(req.Wellname, &req.IsMemory) fmt.Println("vibrationData------------", vibrationData) timeDepth := ExtractTimeDepthRange(vibrationData) + fmt.Println("timeDepth------------", timeDepth) statsData104 := convertToStatsData(vibrationData, 104) //左侧第一个表格数据 statsData105 := convertToStatsData(vibrationData, 105) //左侧第二个表格数据 statsData106 := convertStickSlipData(vibrationData) //左侧第三个表格数据 @@ -4564,263 +4656,263 @@ func export_tool_warning_pdf(opuser string, baseinfo get_srr_base_resp, data []T return } -func get_tool_warning_info(user string, wellname string) (resp []Tool_warning) { - - ps_info := get_ps_info(user) - - var data []Tool_warning - sel_sql := fmt.Sprintf(`select [time],[err_level],[context] FROM [analysis_tool_warning] where [wellname]='%s' order by [time] desc`, wellname) - rows, err := sqlConn.Query(sel_sql) - if err == nil { - for rows.Next() { - var v Tool_warning - if err = rows.Scan(&v.Time, &v.Err_level, &v.Context); err != nil { - logs.Error(fmt.Sprintf(`get_tool_warning_info scan upload err:%s`, err.Error())) - } else { - if len(v.Time) >= 19 { - v.Time = v.Time[:10] + " " + v.Time[11:19] - v.Time = do_time_by_ps(v.Time, ps_info) - } - - if ps_info.R1 == "2" { - if strings.Contains(v.Context, "MPa") { - bid := strings.Index(v.Context, "=") - eid := strings.Index(v.Context, "(") - - f, _ := strconv.ParseFloat(v.Context[bid+1:eid], 64) - f, _ = decimal.NewFromFloat(float64(145.038 * f)).Round(2).Float64() - - v.Context = v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] - - v.Context = strings.ReplaceAll(v.Context, "MPa", "psi") - } - } - - if ps_info.R2 == "2" { - if strings.Contains(v.Context, "℃") { - - bid := strings.Index(v.Context, "=") - eid := strings.Index(v.Context, "(") - - f, _ := strconv.ParseFloat(v.Context[bid+1:eid], 64) - f, _ = decimal.NewFromFloat(float64(1.8*f + 32)).Round(2).Float64() - - v.Context = v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] - - v.Context = strings.ReplaceAll(v.Context, "℃", "℉") - } - } - - data = append(data, v) - } - } - rows.Close() - } - - if len(data) > 0 { - resp = data - } else { - resp = []Tool_warning{} - } - - return -} - // func get_tool_warning_info(user string, wellname string) (resp []Tool_warning) { + // ps_info := get_ps_info(user) -// // 第一个查询:获取仪器组合 -// sel_sql := `SELECT [2327], [2328] FROM REPAIRANDMENT -// WHERE [2321] = @wellname AND [2327] IS NOT NULL -// GROUP BY [2327], [2328]` -// rows, err := sqlConn.Query(sel_sql, sql.Named("wellname", wellname)) -// if err != nil { -// fmt.Println("仪器组合查询错误:", err.Error()) -// return -// } -// defer rows.Close() - -// // 获取仪器组合列表 -// type ToolPair struct { -// Series string -// Instrument string -// } -// var toolPairs []ToolPair - -// for rows.Next() { -// var ( -// seriesPtr sql.NullString -// instrumentPtr sql.NullString -// ) - -// err = rows.Scan(&seriesPtr, &instrumentPtr) -// if err != nil { -// fmt.Println("仪器组合行扫描错误:", err.Error()) -// continue -// } - -// toolPairs = append(toolPairs, ToolPair{ -// Series: seriesPtr.String, -// Instrument: instrumentPtr.String, -// }) -// } - -// if err = rows.Err(); err != nil { -// fmt.Println("仪器组合遍历错误:", err.Error()) -// } - -// // 第二个查询:获取警告信息 -// warningSql := `SELECT [time], [err_level], [context] -// FROM [analysis_tool_warning] -// WHERE [wellname] = @wellname -// ORDER BY [time] DESC` -// warningRows, err := sqlConn.Query(warningSql, sql.Named("wellname", wellname)) -// if err != nil { -// fmt.Println("警告信息查询错误:", err.Error()) -// return -// } -// defer warningRows.Close() - -// // 存储所有警告记录 -// var warnings []Tool_warning -// for warningRows.Next() { -// var w Tool_warning -// var ( -// timePtr sql.NullString -// errLevelPtr sql.NullString -// contextPtr sql.NullString -// ) - -// err = warningRows.Scan(&timePtr, &errLevelPtr, &contextPtr) -// if err != nil { -// fmt.Println("警告信息行扫描错误:", err.Error()) -// continue -// } - -// w.Time = timePtr.String -// w.Err_level = errLevelPtr.String -// w.Context = contextPtr.String -// warnings = append(warnings, w) -// } - -// if err = warningRows.Err(); err != nil { -// fmt.Println("警告信息遍历错误:", err.Error()) -// } - -// // 处理结果:检查每个仪器组合是否出现在警告记录中 // var data []Tool_warning -// for _, pair := range toolPairs { -// v := Tool_warning{ -// Series: pair.Series, -// Instrument: pair.Instrument, -// Flag: 0, // 默认flag=0 -// } - -// // 构建要查找的字符串格式:系列号 + 空格 + 仪器号 -// searchStr := pair.Series + " " + pair.Instrument - -// // 在警告记录中查找匹配的context -// for _, warn := range warnings { -// if strings.Contains(warn.Context, searchStr) { -// // 找到匹配项,使用警告记录的信息 -// v.Time = warn.Time -// v.Err_level = warn.Err_level -// v.Context = warn.Context -// v.Flag = 1 // 设置flag=1 - -// // 处理时间格式 +// sel_sql := fmt.Sprintf(`select [time],[err_level],[context] FROM [analysis_tool_warning] where [wellname]='%s' order by [time] desc`, wellname) +// rows, err := sqlConn.Query(sel_sql) +// fmt.Println("sel_sql-----------", sel_sql) +// if err == nil { +// for rows.Next() { +// var v Tool_warning +// if err = rows.Scan(&v.Time, &v.Err_level, &v.Context); err != nil { +// logs.Error(fmt.Sprintf(`get_tool_warning_info scan upload err:%s`, err.Error())) +// } else { // if len(v.Time) >= 19 { -// originalTime := v.Time // v.Time = v.Time[:10] + " " + v.Time[11:19] -// fmt.Printf("格式化时间: %s -> %s\n", originalTime, v.Time) - -// convertedTime := do_time_by_ps(v.Time, ps_info) -// fmt.Printf("转换时间: %s -> %s\n", v.Time, convertedTime) -// v.Time = convertedTime -// } else { -// fmt.Printf("时间格式异常,长度不足19: %s\n", v.Time) +// v.Time = do_time_by_ps(v.Time, ps_info) // } - -// // 压力单位转换 // if ps_info.R1 == "2" { // if strings.Contains(v.Context, "MPa") { -// fmt.Printf("压力单位转换(MPa->psi): %s\n", v.Context) - // bid := strings.Index(v.Context, "=") // eid := strings.Index(v.Context, "(") -// if bid != -1 && eid != -1 && bid < eid { -// valueStr := v.Context[bid+1 : eid] -// f, err := strconv.ParseFloat(valueStr, 64) -// if err == nil { -// originalValue := f -// f = 145.038 * f -// f, _ = decimal.NewFromFloat(f).Round(2).Float64() +// f, _ := strconv.ParseFloat(v.Context[bid+1:eid], 64) +// f, _ = decimal.NewFromFloat(float64(145.038 * f)).Round(2).Float64() -// newContext := v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] -// fmt.Printf("压力值转换: %.2f MPa -> %.2f psi\n", originalValue, f) +// v.Context = v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] -// v.Context = strings.ReplaceAll(newContext, "MPa", "psi") -// } else { -// fmt.Printf("解析压力值失败: %s\n", valueStr) -// } -// } else { -// fmt.Println("在内容中未找到有效的压力值位置") -// } +// v.Context = strings.ReplaceAll(v.Context, "MPa", "psi") // } // } -// // 温度单位转换 // if ps_info.R2 == "2" { // if strings.Contains(v.Context, "℃") { -// logs.Info(fmt.Sprintf("温度单位转换(℃->℉): %s", v.Context)) // bid := strings.Index(v.Context, "=") // eid := strings.Index(v.Context, "(") -// if bid != -1 && eid != -1 && bid < eid { -// valueStr := v.Context[bid+1 : eid] -// f, err := strconv.ParseFloat(valueStr, 64) -// if err == nil { -// originalValue := f -// f = 1.8*f + 32 -// f, _ = decimal.NewFromFloat(f).Round(2).Float64() +// f, _ := strconv.ParseFloat(v.Context[bid+1:eid], 64) +// f, _ = decimal.NewFromFloat(float64(1.8*f + 32)).Round(2).Float64() -// newContext := v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] -// fmt.Printf("温度值转换: %.2f ℃ -> %.2f ℉\n", originalValue, f) +// v.Context = v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] -// v.Context = strings.ReplaceAll(newContext, "℃", "℉") -// } else { -// fmt.Printf("解析温度值失败: %s\n", valueStr) -// } -// } else { -// fmt.Println("在内容中未找到有效的温度值位置") -// } +// v.Context = strings.ReplaceAll(v.Context, "℃", "℉") // } // } -// // 找到匹配后跳出循环 -// break +// data = append(data, v) // } // } - -// data = append(data, v) -// fmt.Printf("处理后的数据: %+v\n", v) +// rows.Close() // } -// fmt.Printf("总共处理 %d 条仪器组合\n", len(data)) - // if len(data) > 0 { // resp = data -// fmt.Printf("成功返回 %d 条警告信息\n", len(data)) // } else { -// logs.Info("未查询到任何仪器组合") // resp = []Tool_warning{} // } // return // } +func get_tool_warning_info(user string, wellname string) (resp []Tool_warning) { + ps_info := get_ps_info(user) + + // 第一个查询:获取仪器组合 + sel_sql := `select DISTINCT [2327], [2328] from REPAIRANDMENT where [2321] = @wellname AND [2327] IS NOT NULL` + rows, err := sqlConn.Query(sel_sql, sql.Named("wellname", wellname)) + if err != nil { + fmt.Println("仪器组合查询错误:", err.Error()) + return + } + defer rows.Close() + + // 获取仪器组合列表 + type ToolPair struct { + Series string + Instrument string + } + var toolPairs []ToolPair + + for rows.Next() { + var ( + seriesPtr sql.NullString + instrumentPtr sql.NullString + ) + + err = rows.Scan(&seriesPtr, &instrumentPtr) + if err != nil { + fmt.Println("仪器组合行扫描错误:", err.Error()) + continue + } + + toolPairs = append(toolPairs, ToolPair{ + Series: seriesPtr.String, + Instrument: instrumentPtr.String, + }) + } + + if err = rows.Err(); err != nil { + fmt.Println("仪器组合遍历错误:", err.Error()) + } + + // 第二个查询:获取警告信息 + warningSql := `SELECT [time], [err_level], [context] + FROM [analysis_tool_warning] + WHERE [wellname] = @wellname + ORDER BY [time] DESC` + warningRows, err := sqlConn.Query(warningSql, sql.Named("wellname", wellname)) + if err != nil { + fmt.Println("警告信息查询错误:", err.Error()) + return + } + defer warningRows.Close() + + fmt.Println("警告信息:-----------------", warningRows) + + // 存储所有警告记录 + var warnings []Tool_warning + for warningRows.Next() { + var w Tool_warning + var ( + timePtr sql.NullString + errLevelPtr sql.NullString + contextPtr sql.NullString + ) + + err = warningRows.Scan(&timePtr, &errLevelPtr, &contextPtr) + if err != nil { + fmt.Println("警告信息行扫描错误:", err.Error()) + continue + } + + w.Time = timePtr.String + w.Err_level = errLevelPtr.String + w.Context = contextPtr.String + warnings = append(warnings, w) + } + + if err = warningRows.Err(); err != nil { + fmt.Println("警告信息遍历错误:", err.Error()) + } + + // 处理结果:检查每个仪器组合是否出现在警告记录中 + var data []Tool_warning + for _, pair := range toolPairs { + v := Tool_warning{ + Series: pair.Series, + Instrument: pair.Instrument, + Flag: 0, // 默认flag=0 + } + + // 构建要查找的字符串格式:系列号 + 空格 + 仪器号 + searchStr := pair.Series + " " + pair.Instrument + + // 在警告记录中查找匹配的context + for _, warn := range warnings { + if strings.Contains(warn.Context, searchStr) { + // 找到匹配项,使用警告记录的信息 + v.Time = warn.Time + v.Err_level = warn.Err_level + v.Context = warn.Context + v.Flag = 1 // 设置flag=1 + + // 处理时间格式 + if len(v.Time) >= 19 { + originalTime := v.Time + v.Time = v.Time[:10] + " " + v.Time[11:19] + fmt.Printf("格式化时间: %s -> %s\n", originalTime, v.Time) + + convertedTime := do_time_by_ps(v.Time, ps_info) + fmt.Printf("转换时间: %s -> %s\n", v.Time, convertedTime) + v.Time = convertedTime + } else { + fmt.Printf("时间格式异常,长度不足19: %s\n", v.Time) + } + + // 压力单位转换 + if ps_info.R1 == "2" { + if strings.Contains(v.Context, "MPa") { + fmt.Printf("压力单位转换(MPa->psi): %s\n", v.Context) + + bid := strings.Index(v.Context, "=") + eid := strings.Index(v.Context, "(") + + if bid != -1 && eid != -1 && bid < eid { + valueStr := v.Context[bid+1 : eid] + f, err := strconv.ParseFloat(valueStr, 64) + if err == nil { + originalValue := f + f = 145.038 * f + f, _ = decimal.NewFromFloat(f).Round(2).Float64() + + newContext := v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] + fmt.Printf("压力值转换: %.2f MPa -> %.2f psi\n", originalValue, f) + + v.Context = strings.ReplaceAll(newContext, "MPa", "psi") + } else { + fmt.Printf("解析压力值失败: %s\n", valueStr) + } + } else { + fmt.Println("在内容中未找到有效的压力值位置") + } + } + } + + // 温度单位转换 + if ps_info.R2 == "2" { + if strings.Contains(v.Context, "℃") { + logs.Info(fmt.Sprintf("温度单位转换(℃->℉): %s", v.Context)) + + bid := strings.Index(v.Context, "=") + eid := strings.Index(v.Context, "(") + + if bid != -1 && eid != -1 && bid < eid { + valueStr := v.Context[bid+1 : eid] + f, err := strconv.ParseFloat(valueStr, 64) + if err == nil { + originalValue := f + f = 1.8*f + 32 + f, _ = decimal.NewFromFloat(f).Round(2).Float64() + + newContext := v.Context[:bid+1] + fmt.Sprintf("%.02f", f) + v.Context[eid:] + fmt.Printf("温度值转换: %.2f ℃ -> %.2f ℉\n", originalValue, f) + + v.Context = strings.ReplaceAll(newContext, "℃", "℉") + } else { + fmt.Printf("解析温度值失败: %s\n", valueStr) + } + } else { + fmt.Println("在内容中未找到有效的温度值位置") + } + } + } + + // 找到匹配后跳出循环 + break + } + } + + data = append(data, v) + fmt.Printf("处理后的数据: %+v\n", v) + } + + fmt.Printf("总共处理 %d 条仪器组合\n", len(data)) + + if len(data) > 0 { + resp = data + fmt.Printf("成功返回 %d 条警告信息\n", len(data)) + } else { + logs.Info("未查询到任何仪器组合") + resp = []Tool_warning{} + } + + return +} + func get_tool_warning_info_en(user string, wellname string) (resp []Tool_warning) { ps_info := get_ps_info(user) @@ -4972,7 +5064,7 @@ func get_srr_pdf_en(response http.ResponseWriter, request *http.Request) { state = get_srr_state_info(req.OpUser, req.Wellname) events = get_srr_event_info_en(req.OpUser, req.Wellname) - filename = export_srr_pdf_en(req.OpUser, baseinfo, state, events) + filename = export_srr_pdf_en(req.OpUser, req.Flag, baseinfo, state, events) resp.FileId = fmt.Sprintf(`%v.pdf`, filename) jdata, _ := json.Marshal(resp) @@ -5725,7 +5817,7 @@ func get_srr_pdf_page_cnt(opuser string, baseinfo get_srr_base_resp, state []Srr return } -func export_srr_pdf_en(opuser string, baseinfo get_srr_base_resp, state []Srr_state, event []Srr_event) (filename string) { +func export_srr_pdf_en(opuser string, flag bool, baseinfo get_srr_base_resp, state []Srr_state, event []Srr_event) (filename string) { ps_info := get_ps_info(opuser) @@ -5955,68 +6047,22 @@ func export_srr_pdf_en(opuser string, baseinfo get_srr_base_resp, state []Srr_st pdf.Text(fmt.Sprintf(`IP+Port:%s`, baseinfo.Ip)) pdf.SetXY(margin_left+(1.5*h_span), base) pdf.Text(fmt.Sprintf(`area:%s`, baseinfo.Location)) + if flag { + if len(event) > 0 { - if len(event) > 0 { + if base+span+span > page_H { + pdf.SetXY(page_F_x, page_F_y) + pdf.Text(fmt.Sprintf(`%v/%v`, cur_page, total_page)) + cur_page++ - if base+span+span > page_H { - pdf.SetXY(page_F_x, page_F_y) - pdf.Text(fmt.Sprintf(`%v/%v`, cur_page, total_page)) - cur_page++ - - pdf.AddPage() - base = margin_top - pdf.SetXY(margin_left*1, base) - } else { - pdf.SetXY(margin_left*1, base) - } - - base += span - pdf.SetLineWidth(0.1) - pdf.Line(margin_left, base, margin_left+360, base) - - pdf.Line(margin_left, base, margin_left, base+span) - pdf.Line(margin_left+120, base, margin_left+120, base+span) - pdf.Line(margin_left+240, base, margin_left+240, base+span) - pdf.Line(margin_left+360, base, margin_left+360, base+span) - - var option gopdf.CellOption - option.Align = gopdf.Middle | gopdf.Center - pdf.SetXY(margin_left, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "Start Time", option) - pdf.SetXY(margin_left+120, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "End Time", option) - pdf.SetXY(margin_left+240, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "Event", option) - - base += span - pdf.Line(margin_left, base, margin_left+360, base) - } - - pdf.SetFont("simfang", "", 12) - for i := 0; i < len(event); i++ { - ev := event[i] - - /* - if len(ev.Bt) >= 19 { - ev.Bt = ev.Bt[:16] + pdf.AddPage() + base = margin_top + pdf.SetXY(margin_left*1, base) + } else { + pdf.SetXY(margin_left*1, base) } - if len(ev.Et) >= 19 { - ev.Et = ev.Et[:16] - } - */ - - if base+span > page_H { - pdf.SetXY(page_F_x, page_F_y) - pdf.Text(fmt.Sprintf(`%v/%v`, cur_page, total_page)) - cur_page++ - - pdf.AddPage() - base = margin_top - pdf.SetXY(margin_left*1, base) - - //表头 - pdf.SetFont("simfang", "", 14) + base += span pdf.SetLineWidth(0.1) pdf.Line(margin_left, base, margin_left+360, base) @@ -6036,32 +6082,78 @@ func export_srr_pdf_en(opuser string, baseinfo get_srr_base_resp, state []Srr_st base += span pdf.Line(margin_left, base, margin_left+360, base) - } else { - pdf.SetXY(margin_left*1, base) } pdf.SetFont("simfang", "", 12) - pdf.SetLineWidth(0.1) - pdf.Line(margin_left, base, margin_left+360, base) + for i := 0; i < len(event); i++ { + ev := event[i] - pdf.Line(margin_left, base, margin_left, base+span) - pdf.Line(margin_left+120, base, margin_left+120, base+span) - pdf.Line(margin_left+240, base, margin_left+240, base+span) - pdf.Line(margin_left+360, base, margin_left+360, base+span) + /* + if len(ev.Bt) >= 19 { + ev.Bt = ev.Bt[:16] + } - var option gopdf.CellOption - option.Align = gopdf.Middle | gopdf.Center - pdf.SetXY(margin_left, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Bt, option) - pdf.SetXY(margin_left+120, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Et, option) - pdf.SetXY(margin_left+240, base) - pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Event_name, option) + if len(ev.Et) >= 19 { + ev.Et = ev.Et[:16] + } + */ - base += span - pdf.Line(margin_left, base, margin_left+360, base) + if base+span > page_H { + pdf.SetXY(page_F_x, page_F_y) + pdf.Text(fmt.Sprintf(`%v/%v`, cur_page, total_page)) + cur_page++ + + pdf.AddPage() + base = margin_top + pdf.SetXY(margin_left*1, base) + + //表头 + pdf.SetFont("simfang", "", 14) + pdf.SetLineWidth(0.1) + pdf.Line(margin_left, base, margin_left+360, base) + + pdf.Line(margin_left, base, margin_left, base+span) + pdf.Line(margin_left+120, base, margin_left+120, base+span) + pdf.Line(margin_left+240, base, margin_left+240, base+span) + pdf.Line(margin_left+360, base, margin_left+360, base+span) + + var option gopdf.CellOption + option.Align = gopdf.Middle | gopdf.Center + pdf.SetXY(margin_left, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "Start Time", option) + pdf.SetXY(margin_left+120, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "End Time", option) + pdf.SetXY(margin_left+240, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, "Event", option) + + base += span + pdf.Line(margin_left, base, margin_left+360, base) + } else { + pdf.SetXY(margin_left*1, base) + } + + pdf.SetFont("simfang", "", 12) + pdf.SetLineWidth(0.1) + pdf.Line(margin_left, base, margin_left+360, base) + + pdf.Line(margin_left, base, margin_left, base+span) + pdf.Line(margin_left+120, base, margin_left+120, base+span) + pdf.Line(margin_left+240, base, margin_left+240, base+span) + pdf.Line(margin_left+360, base, margin_left+360, base+span) + + var option gopdf.CellOption + option.Align = gopdf.Middle | gopdf.Center + pdf.SetXY(margin_left, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Bt, option) + pdf.SetXY(margin_left+120, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Et, option) + pdf.SetXY(margin_left+240, base) + pdf.CellWithOption(&gopdf.Rect{H: span, W: 120}, ev.Event_name, option) + + base += span + pdf.Line(margin_left, base, margin_left+360, base) + } } - pdf.SetFont("simfang", "", 14) base += (span / 2) if base > page_H { @@ -6471,10 +6563,11 @@ func export_srr_pdf(opuser string, flag bool, baseinfo get_srr_base_resp, state return } +// 右侧三个的最后一行 func calculateTotalRow(tableData [][]string) []string { totalCount := 0 totalMinutes := 0 - + totalHours := 0 for _, row := range tableData { // 解析第一列:计数 levelParts := strings.Fields(row[0]) @@ -6488,32 +6581,60 @@ func calculateTotalRow(tableData [][]string) []string { // 解析第二列:时长 durationParts := strings.Fields(row[1]) if len(durationParts) >= 2 { - // 分钟部分 + // 分钟部分 - 直接累计 minStr := strings.TrimSuffix(durationParts[0], "min") minutes, err := strconv.Atoi(minStr) if err == nil { totalMinutes += minutes } - // 小时部分 + // 小时部分 - 直接累计(不再转换为分钟) hourStr := strings.TrimSuffix(durationParts[1], "h") hours, err := strconv.Atoi(hourStr) if err == nil { - totalMinutes += hours * 60 + totalHours += hours // 新增一个totalHours变量来累计小时 } } } - // 格式化总时长 - hours := totalMinutes / 60 - minutes := totalMinutes % 60 - durationStr := fmt.Sprintf("%dmin %dh", minutes, hours) + formattedLevel := fmt.Sprintf("%-9s", " Total") // 固定占9字符宽度 + formattedCount := fmt.Sprintf(" %-5d", totalCount) // 空格+数字,占6字符宽度 + col1 := formattedLevel + " " + formattedCount // 中间加2个空格 - return []string{ - fmt.Sprintf("Total %d", totalCount), - durationStr, - "", + // 分钟部分固定7字符宽度(最大99999min) + minPart := fmt.Sprintf("%7s", fmt.Sprintf("%dmin", totalMinutes)) + + // 从分钟计算小时(向下取整) + totalHours2 := totalMinutes / 60 + + // 小时部分处理:当小时数为一位数时左对齐 + hourPart := fmt.Sprintf("%dh", totalHours2) + if totalHours2 < 10 { + hourPart = fmt.Sprintf("%-3s", " "+hourPart) // 一位数时左对齐 + } else { + hourPart = fmt.Sprintf("%3s", hourPart) // 多位数时右对齐 } + + col2 := minPart + " " + hourPart // 中间加2个空格 + return []string{col1, col2, ""} + // formattedLevel := fmt.Sprintf("%-9s", " Total") // 固定占9字符宽度 + // formattedCount := fmt.Sprintf(" %-5d", totalCount) // 空格+数字,占6字符宽度 + // col1 := formattedLevel + " " + formattedCount // 中间加2个空格 + + // // 分钟部分固定7字符宽度(最大99999min) + // minPart := fmt.Sprintf("%7s", fmt.Sprintf("%dmin", totalMinutes)) + + // // 小时部分处理:当小时数为一位数时左对齐 + // hourPart := fmt.Sprintf("%dh", totalHours) + // if totalHours < 10 { + // hourPart = fmt.Sprintf("%-3s", " "+hourPart) // 一位数时左对齐 + // } else { + // hourPart = fmt.Sprintf("%3s", hourPart) // 多位数时右对齐 + // } + + // col2 := minPart + " " + hourPart // 中间加2个空格 + // return []string{col1, col2, ""} + } func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRange, statsData [][]string, axialData [][]string, stickSlipData [][]string, tableDataOne [][]string, tableDataTwo [][]string, tableDataThree [][]string) (filename string) { @@ -6562,7 +6683,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa colWidth := totalWidth / 4 // Well Num: 1 pdf.SetXY(margin_left, fieldY) // 井名 - pdf.CellWithOption(&gopdf.Rect{H: 20, W: colWidth}, "Well Num: "+baseinfo.Wellname, option) + pdf.CellWithOption(&gopdf.Rect{H: 20, W: colWidth}, "Well Name: "+baseinfo.Wellname, option) // Well Team: 2 pdf.SetXY(margin_left+colWidth, fieldY) // 井队 @@ -6841,7 +6962,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa pdf.CellWithOption(&gopdf.Rect{H: titleHeightT, W: tableTotalWidth}, "Vibration Limits", cellOpt) // 绘制标题边框 - pdf.SetLineWidth(0.5) + pdf.SetLineWidth(1) pdf.RectFromUpperLeft(tableLeftStartX, titleYT, tableTotalWidth, titleHeightT) // 绘制表头 - 增大表头字体 @@ -6872,7 +6993,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa } // 绘制表头边框 - pdf.SetLineWidth(0.5) + pdf.SetLineWidth(1) pdf.SetStrokeColor(0, 0, 0) pdf.RectFromUpperLeft(tableLeftStartX, headerYT, tableTotalWidth, headerHeightT) @@ -6932,7 +7053,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa pdf.CellWithOption(&gopdf.Rect{H: titleHeight, W: totalTableWidth}, "Lateral Vibration", option) // 绘制标题边框 - pdf.SetLineWidth(0.5) + pdf.SetLineWidth(1) //边框线宽度 pdf.Line(tableStartX, titleY, tableStartX+totalTableWidth, titleY) // 顶部边框 pdf.Line(tableStartX, titleY+titleHeight, tableStartX+totalTableWidth, titleY+titleHeight) // 底部边框 pdf.Line(tableStartX, titleY, tableStartX, titleY+titleHeight) // 左边框 @@ -6952,22 +7073,11 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa pdf.CellWithOption(&gopdf.Rect{H: headerHeight, W: colWidths[i]}, Yheaders[i], tableOption) currentX += colWidths[i] } + // 3. 计算表格主体高度 rowHeight := 12.0 tableBodyHeight := float64(len(tableDataOne)) * rowHeight - // 4. 绘制外边框(从表头开始) - pdf.Line(tableStartX, headerY, tableStartX, headerY+headerHeight+tableBodyHeight) // 左边框 - pdf.Line(tableStartX+totalTableWidth, headerY, tableStartX+totalTableWidth, headerY+headerHeight+tableBodyHeight) // 右边框 - pdf.Line(tableStartX, headerY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, headerY+headerHeight+tableBodyHeight) // 底部边框 - - // 5. 绘制垂直分隔线(从表头开始) - currentX = tableStartX - for i := 0; i < len(colWidths)-1; i++ { - currentX += colWidths[i] - pdf.Line(currentX, headerY, currentX, headerY+headerHeight+tableBodyHeight) // 垂直分隔线 - } - // 6. 绘制数据行 pdf.SetFont("simfang", "", 9) for rowIdx, row := range tableDataOne { @@ -6975,18 +7085,17 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa // 根据等级设置背景色 switch rowIdx { - case 0, 1, 2: // Level0, Level1, Level2 - 绿色背景 + case 0, 1, 2, 3: // Level0, Level1, Level2 - 绿色背景 pdf.SetFillColor(144, 238, 144) // 浅绿色 - case 3, 4: // Level3, Level4 - 黄色背景 + case 4, 5: // Level3, Level4 - 黄色背景 pdf.SetFillColor(255, 255, 0) // 浅黄色 - case 5, 6, 7: // Level5, Level6 - 红色背景 + case 6, 7: // Level5, Level6 - 红色背景 pdf.SetFillColor(255, 99, 71) // 浅红色 default: // Level7和其他 - 默认白色 pdf.SetFillColor(148, 0, 211) //紫色 } - // 绘制行背景(矩形填充) - pdf.Rectangle(tableStartX, rowY, tableStartX+totalTableWidth, rowY+rowHeight, "F", 0, 0) + pdf.Rectangle(tableStartX+0.8, rowY, tableStartX+totalTableWidth-0.7, rowY+rowHeight, "F", 0, 0) // 重置文本颜色(确保文本可读) pdf.SetTextColor(0, 0, 0) // 黑色文本 @@ -6999,7 +7108,19 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa currentX += colWidths[colIdx] } } + // 4. 绘制外边框(从表头开始) + pdf.Line(tableStartX, headerY, tableStartX, headerY+headerHeight+tableBodyHeight) // 左边框 + pdf.Line(tableStartX+totalTableWidth, headerY, tableStartX+totalTableWidth, headerY+headerHeight+tableBodyHeight) // 右边框 + pdf.Line(tableStartX, headerY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, headerY+headerHeight+tableBodyHeight) // 底部边框 + // 5. 绘制垂直分隔线(从表头开始) + currentX = tableStartX + for i := 0; i < len(colWidths)-1; i++ { + currentX += colWidths[i] + // pdf.Line(currentX, headerY, currentX, headerY+headerHeight+tableBodyHeight) // 垂直分隔线 + pdf.Line(currentX, headerY, currentX, headerY+headerHeight) + } + pdf.Line(tableStartX, headerY+headerHeight-0.8, tableStartX+totalTableWidth, headerY+headerHeight) // 7. 添加汇总行(Total行) totalRowY := headerY + headerHeight + float64(len(tableDataOne))*rowHeight // 计算Total行Y坐标 // 设置文字居中 @@ -7028,7 +7149,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa pdf.CellWithOption(&gopdf.Rect{H: titleHeight, W: totalTableWidth}, "AXial Vibration", option) // 绘制标题边框 - pdf.SetLineWidth(0.5) + pdf.SetLineWidth(1) pdf.Line(tableStartX, secondTitleY, tableStartX+totalTableWidth, secondTitleY) pdf.Line(tableStartX, secondTitleY+titleHeight, tableStartX+totalTableWidth, secondTitleY+titleHeight) pdf.Line(tableStartX, secondTitleY, tableStartX, secondTitleY+titleHeight) @@ -7046,18 +7167,6 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa currentX += colWidths[i] } - //绘制外边框 - pdf.Line(tableStartX, secondHeaderY, tableStartX, secondHeaderY+headerHeight+tableBodyHeight) - pdf.Line(tableStartX+totalTableWidth, secondHeaderY, tableStartX+totalTableWidth, secondHeaderY+headerHeight+tableBodyHeight) - pdf.Line(tableStartX, secondHeaderY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, secondHeaderY+headerHeight+tableBodyHeight) - - //绘制垂直分隔线 - currentX = tableStartX - for i := 0; i < len(colWidths)-1; i++ { - currentX += colWidths[i] - pdf.Line(currentX, secondHeaderY, currentX, secondHeaderY+headerHeight+tableBodyHeight) - } - pdf.SetFont("simfang", "", 9) for rowIdx, row := range tableDataTwo { rowY := secondHeaderY + headerHeight + float64(rowIdx)*rowHeight @@ -7075,7 +7184,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa } // 绘制行背景(先填充矩形) - pdf.Rectangle(tableStartX, rowY, tableStartX+totalTableWidth, rowY+rowHeight, "F", 0, 0) + pdf.Rectangle(tableStartX+0.8, rowY, tableStartX+totalTableWidth-0.7, rowY+rowHeight, "F", 0, 0) // 重置文本颜色为黑色确保可读性 pdf.SetTextColor(0, 0, 0) @@ -7088,7 +7197,18 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa currentX += colWidths[colIdx] } } + //绘制外边框 + pdf.Line(tableStartX, secondHeaderY, tableStartX, secondHeaderY+headerHeight+tableBodyHeight) + pdf.Line(tableStartX+totalTableWidth, secondHeaderY, tableStartX+totalTableWidth, secondHeaderY+headerHeight+tableBodyHeight) + pdf.Line(tableStartX, secondHeaderY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, secondHeaderY+headerHeight+tableBodyHeight) + //绘制垂直分隔线 + currentX = tableStartX + for i := 0; i < len(colWidths)-1; i++ { + currentX += colWidths[i] + pdf.Line(currentX, secondHeaderY, currentX, secondHeaderY+headerHeight) + } + pdf.Line(tableStartX, secondHeaderY+headerHeight-0.8, tableStartX+totalTableWidth, secondHeaderY+headerHeight) // 2.6 添加汇总行(Total行) secondTotalRowY := secondHeaderY + headerHeight + float64(len(tableDataTwo))*rowHeight @@ -7110,6 +7230,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa // 计算第三个表格的起始Y坐标(第二个表格底部+20像素间距) thirdTableStartY := secondTotalRowY + rowHeight + 20 + //====================================新增右侧表格Stick Slip=========================================== // 3. 绘制第三个表格(Stick Slip) // 3.1 绘制标题区域 pdf.SetFont("simfang", "", 14) @@ -7120,7 +7241,7 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa pdf.CellWithOption(&gopdf.Rect{H: titleHeight, W: totalTableWidth}, "Stick Slip", option) // 绘制标题边框 - pdf.SetLineWidth(0.5) + pdf.SetLineWidth(1) pdf.Line(tableStartX, thirdTitleY, tableStartX+totalTableWidth, thirdTitleY) pdf.Line(tableStartX, thirdTitleY+titleHeight, tableStartX+totalTableWidth, thirdTitleY+titleHeight) pdf.Line(tableStartX, thirdTitleY, tableStartX, thirdTitleY+titleHeight) @@ -7138,18 +7259,6 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa currentX += colWidths[i] } - // 3.3 绘制外边框 - pdf.Line(tableStartX, thirdHeaderY, tableStartX, thirdHeaderY+headerHeight+tableBodyHeight) - pdf.Line(tableStartX+totalTableWidth, thirdHeaderY, tableStartX+totalTableWidth, thirdHeaderY+headerHeight+tableBodyHeight) - pdf.Line(tableStartX, thirdHeaderY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, thirdHeaderY+headerHeight+tableBodyHeight) - - // 3.4 绘制垂直分隔线 - currentX = tableStartX - for i := 0; i < len(colWidths)-1; i++ { - currentX += colWidths[i] - pdf.Line(currentX, thirdHeaderY, currentX, thirdHeaderY+headerHeight+tableBodyHeight) - } - // 3.5 绘制数据行(与前两个表格数据相同) pdf.SetFont("simfang", "", 9) for rowIdx, row := range tableDataThree { @@ -7166,7 +7275,8 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa default: // Level7和其他 - 默认紫色 pdf.SetFillColor(148, 0, 211) //紫色 } - pdf.Rectangle(tableStartX, rowY, tableStartX+totalTableWidth, rowY+rowHeight, "F", 0, 0) + pdf.Line(tableStartX, thirdHeaderY+headerHeight-0.8, tableStartX+totalTableWidth, thirdHeaderY+headerHeight) + pdf.Rectangle(tableStartX+0.8, rowY, tableStartX+totalTableWidth-0.7, rowY+rowHeight, "F", 0, 0) // 确保文本为黑色 pdf.SetTextColor(0, 0, 0) @@ -7178,10 +7288,20 @@ func export_vibration_pdf(baseinfo get_vibration_resp, vibrationData TimeDepthRa currentX += colWidths[colIdx] } } + // 3.3 绘制外边框 + pdf.Line(tableStartX, thirdHeaderY, tableStartX, thirdHeaderY+headerHeight+tableBodyHeight) + pdf.Line(tableStartX+totalTableWidth, thirdHeaderY, tableStartX+totalTableWidth, thirdHeaderY+headerHeight+tableBodyHeight) + pdf.Line(tableStartX, thirdHeaderY+headerHeight+tableBodyHeight, tableStartX+totalTableWidth, thirdHeaderY+headerHeight+tableBodyHeight) + // 3.4 绘制垂直分隔线 + currentX = tableStartX + for i := 0; i < len(colWidths)-1; i++ { + currentX += colWidths[i] + pdf.Line(currentX, thirdHeaderY, currentX, thirdHeaderY+headerHeight) + } // 3.6 添加汇总行(Total行) thirdTotalRowY := thirdHeaderY + headerHeight + float64(len(tableDataThree))*rowHeight - + fmt.Println("tableDataThree:", tableDataThree) // 绘制Total行文字内容(与前两个表格相同) currentX = tableStartX for colIdx, cell := range calculateTotalRow(tableDataThree) { @@ -24481,7 +24601,7 @@ func getMhSCsv_en(response http.ResponseWriter, request *http.Request) { var resp MhExportResp var db string - + var cmdSql string var conn *sql.DB var err error @@ -24506,7 +24626,20 @@ func getMhSCsv_en(response http.ResponseWriter, request *http.Request) { goto write_csv } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err = getOdbcConn(db) if err != nil { logs.Info("Connecting Error", err.Error()) @@ -24562,7 +24695,14 @@ write_csv: w.Flush() resp.FileId = fmt.Sprintf(`%v.csv`, beginTime) - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } exit: jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) @@ -24585,7 +24725,7 @@ func getMhSCsv(response http.ResponseWriter, request *http.Request) { var resp MhExportResp var db string - + var cmdSql string var conn *sql.DB var err error @@ -24610,7 +24750,20 @@ func getMhSCsv(response http.ResponseWriter, request *http.Request) { goto write_csv } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err = getOdbcConn(db) if err != nil { logs.Info("Connecting Error", err.Error()) @@ -24666,7 +24819,14 @@ write_csv: w.Flush() resp.FileId = fmt.Sprintf(`%v.csv`, beginTime) - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } exit: jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) @@ -24697,7 +24857,7 @@ func getMhS(response http.ResponseWriter, request *http.Request) { ps_info.R2 = "1" ps_info.R3 = "1" } - + var cmdSql string var db string var sqlstr string @@ -24713,7 +24873,20 @@ func getMhS(response http.ResponseWriter, request *http.Request) { rwLocker.RUnlock() goto exit } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err = getOdbcConn(db) if err != nil { logs.Info("Connecting Error", err.Error()) @@ -24766,7 +24939,14 @@ exit: if err != nil { logs.Error("getMhS:", err.Error()) } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } endTime := time.Now().UnixNano() fmt.Println(fmt.Sprintf("getMhS recv req end, use time: %v ms", (endTime-beginTime)/1e6)) } @@ -27182,7 +27362,7 @@ func wsGetWellRealTimeData(lang string, id string, user string, ioCh chan []GetH } else { updateWellNameLocker.RUnlock() } - + var cmdSql string var db string rwLocker.RLock() if v, ok := wellNamemap[id]; ok { @@ -27193,7 +27373,20 @@ func wsGetWellRealTimeData(lang string, id string, user string, ioCh chan []GetH rwLocker.RUnlock() return } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { fmt.Println("wsGetWellRealTimeData sql open db err:", err.Error()) @@ -27322,6 +27515,14 @@ func wsGetWellRealTimeData(lang string, id string, user string, ioCh chan []GetH goto exit } } + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } exit: } @@ -27336,7 +27537,7 @@ func getWellRealTimeData_en(response http.ResponseWriter, request *http.Request) var cnt int var resp getWellRealTimeDataResp - + var cmdSql string var db string rwLocker.RLock() @@ -27356,7 +27557,20 @@ func getWellRealTimeData_en(response http.ResponseWriter, request *http.Request) fmt.Fprintf(response, string(jdata)) return } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { logs.Info("Connecting Error", err.Error()) @@ -27492,7 +27706,14 @@ func getWellRealTimeData_en(response http.ResponseWriter, request *http.Request) jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } endTime := time.Now().UnixNano() fmt.Println(fmt.Sprintf("getWellRealTimeData_en recv req end, use time: %v ms", (endTime-beginTime)/1e6)) @@ -27669,7 +27890,7 @@ func getWellRealTimeData(response http.ResponseWriter, request *http.Request) { var resp getWellRealTimeDataResp var db string - + var cmdSql string rwLocker.RLock() if v, ok := wellNamemap[req.Id]; ok { rwLocker.RUnlock() @@ -27688,6 +27909,20 @@ func getWellRealTimeData(response http.ResponseWriter, request *http.Request) { return } + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { logs.Info("Connecting Error", err.Error()) @@ -27824,6 +28059,15 @@ func getWellRealTimeData(response http.ResponseWriter, request *http.Request) { jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } + endTime := time.Now().UnixNano() fmt.Println(fmt.Sprintf("getWellRealTimeData recv req end, use time: %v ms", (endTime-beginTime)/1e6)) @@ -27962,6 +28206,7 @@ func exportWellHistory_en(response http.ResponseWriter, request *http.Request) { var conn *sql.DB var err error + var cmdSql string var db string var row *sql.Rows @@ -27980,7 +28225,20 @@ func exportWellHistory_en(response http.ResponseWriter, request *http.Request) { goto write_csv } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err = getOdbcConn(db) if err != nil { logs.Info("exportWellHistory_en Connecting Error", err.Error()) @@ -28064,7 +28322,14 @@ func exportWellHistory_en(response http.ResponseWriter, request *http.Request) { logs.Info("Query Error", err.Error()) } } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } write_csv: var data [][]string var w *csv.Writer @@ -28116,6 +28381,7 @@ func exportWellHistory(response http.ResponseWriter, request *http.Request) { var conn *sql.DB var err error var db string + var cmdSql string var row *sql.Rows var selSql string @@ -28133,7 +28399,20 @@ func exportWellHistory(response http.ResponseWriter, request *http.Request) { goto write_csv } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err = getOdbcConn(db) if err != nil { logs.Info("exportWellHistory Connecting Error", err.Error()) @@ -28217,7 +28496,14 @@ func exportWellHistory(response http.ResponseWriter, request *http.Request) { logs.Info("Query Error", err.Error()) } } - + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } write_csv: var data [][]string var w *csv.Writer @@ -28271,6 +28557,7 @@ func getWellHistory_en(response http.ResponseWriter, request *http.Request) { var resp GetHisWellResp var db string + var cmdSql string rwLocker.RLock() if v, ok := wellNamemap[req.Id]; ok { @@ -28284,7 +28571,21 @@ func getWellHistory_en(response http.ResponseWriter, request *http.Request) { fmt.Fprintf(response, string(jdata)) return } - + // 这些库被设置为了离线状态,需要先设置为启用状态 + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { logs.Info("getWellHistory_en Connecting Error", err.Error()) @@ -28425,6 +28726,15 @@ func getWellHistory_en(response http.ResponseWriter, request *http.Request) { jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } + endTime := time.Now().UnixNano() fmt.Println(fmt.Sprintf("getWellHistory_en recv req end, use time: %v ms", (endTime-beginTime)/1e6)) @@ -28443,7 +28753,7 @@ func getWellHistory(response http.ResponseWriter, request *http.Request) { var resp GetHisWellResp var db string - + var cmdSql string rwLocker.RLock() if v, ok := wellNamemap[req.Id]; ok { rwLocker.RUnlock() @@ -28456,7 +28766,21 @@ func getWellHistory(response http.ResponseWriter, request *http.Request) { fmt.Fprintf(response, string(jdata)) return } - + // 这些库被设置为了离线状态,需要先设置为启用状态 + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + logs.Info("链接master库失败", err.Error()) + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } conn, err := getOdbcConn(db) if err != nil { logs.Info("getWellHistory Connecting Error", err.Error()) @@ -28604,112 +28928,20 @@ func getWellHistory(response http.ResponseWriter, request *http.Request) { jdata, _ := json.Marshal(resp) fmt.Fprintf(response, string(jdata)) + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + cmdSql = fmt.Sprintf("ALTER DATABASE [%s] SET OFFLINE", db) + _, err = conn.Exec(cmdSql) + } + endTime := time.Now().UnixNano() fmt.Println(fmt.Sprintf("getWellHistory recv req end, use time: %v ms", (endTime-beginTime)/1e6)) } -// func getWellHistory(response http.ResponseWriter, request *http.Request) { -// fmt.Println("getWellHistory---------------------开始") -// fmt.Println("getWellHistory recv req begin", time.Now().Format("2006-01-02 15:04:05")) - -// reqdata, _ := ioutil.ReadAll(request.Body) -// var req GetHisWellReq -// json.Unmarshal(reqdata, &req) - -// var resp GetHisWellResp -// var db string - -// rwLocker.RLock() -// if v, ok := wellNamemap[req.Id]; ok { -// rwLocker.RUnlock() -// db = v -// } else { -// logs.Info(fmt.Sprintf("wellsourcename: %s not exist!", req.Id)) -// rwLocker.RUnlock() - -// jdata, _ := json.Marshal(resp) -// fmt.Fprintf(response, string(jdata)) -// return -// } - -// conn, err := getOdbcConn(db) -// if err != nil { -// logs.Info("getWellHistory Connecting Error", err.Error()) - -// jdata, _ := json.Marshal(resp) -// fmt.Fprintf(response, string(jdata)) -// return -// } -// defer conn.Close() - -// } - -// 设置数据库在线 -func setDatabaseOnline(dbName string) error { - // 1. 连接到master数据库 - masterConn, err := sql.Open("odbc", "DSN=master_db;") // 替换为您的master数据库DSN - if err != nil { - return fmt.Errorf("连接master数据库失败: %w", err) - } - defer masterConn.Close() - - // 2. 执行在线命令 - _, err = masterConn.Exec(fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", dbName)) - if err != nil { - return fmt.Errorf("执行在线命令失败: %w", err) - } - - // 3. 验证状态 - var status string - err = masterConn.QueryRow(fmt.Sprintf( - "SELECT state_desc FROM sys.databases WHERE name = '%s'", dbName)).Scan(&status) - - if err != nil { - return fmt.Errorf("状态验证失败: %w", err) - } - - if status != "ONLINE" { - return fmt.Errorf("数据库状态异常: %s", status) - } - - logs.Info(fmt.Sprintf("数据库 %s 已成功设置为在线状态", dbName)) - return nil -} - -// 设置数据库离线 -func setDatabaseOffline(dbName string) error { - // 1. 连接到master数据库 - masterConn, err := sql.Open("odbc", "DSN=master_db;") // 替换为您的master数据库DSN - if err != nil { - return fmt.Errorf("连接master数据库失败: %w", err) - } - defer masterConn.Close() - - // 2. 执行离线命令 - _, err = masterConn.Exec(fmt.Sprintf( - "ALTER DATABASE [%s] SET OFFLINE WITH ROLLBACK IMMEDIATE", dbName)) - if err != nil { - return fmt.Errorf("执行离线命令失败: %w", err) - } - - // 3. 验证状态 - var status string - err = masterConn.QueryRow(fmt.Sprintf( - "SELECT state_desc FROM sys.databases WHERE name = '%s'", dbName)).Scan(&status) - - if err != nil { - return fmt.Errorf("状态验证失败: %w", err) - } - - if status != "OFFLINE" { - return fmt.Errorf("数据库状态异常: %s", status) - } - - logs.Info(fmt.Sprintf("数据库 %s 已成功设置为离线状态", dbName)) - return nil -} - // 获取在线井 func getWell_en(response http.ResponseWriter, request *http.Request) { beginTime := time.Now().UnixNano() @@ -28909,6 +29141,252 @@ func getWell(response http.ResponseWriter, request *http.Request) { logs.Info(fmt.Sprintf("getWell recv req end, use time: %v ms", (endTime-beginTime)/1e6)) } +func getInstrumentMess(response http.ResponseWriter, request *http.Request) { + //解析请求数据 + reqdata, err := ioutil.ReadAll(request.Body) + if err != nil { + http.Error(response, "读取请求体失败", http.StatusBadRequest) + return + } + + var req InstrumentMess + if err := json.Unmarshal(reqdata, &req); err != nil { + http.Error(response, "无效的 JSON 格式", http.StatusBadRequest) + return + } + + //查询仪器所在的所有井 + sqlWellData := fmt.Sprintf(`SELECT DISTINCT wi.WELLNameSource , wi.WELLName FROM WellInformation wi JOIN REPAIRANDMENT r ON wi.WELLNameSource = r.[2321] WHERE r.[2327] = '%s' AND r.[2328] = '%s'`, req.Series, req.Instrument) + wellRow, err := sqlConn.Query(sqlWellData) + if err != nil { + fmt.Println("查询错误:", err) + return + } + defer wellRow.Close() + var wellInfos []get_vibration_resp + for wellRow.Next() { + var wellInfo get_vibration_resp + if err := wellRow.Scan(&wellInfo.WellNameSource, &wellInfo.Wellname); err == nil { + wellInfos = append(wellInfos, wellInfo) + } + } + + //查询维保表的工作时长、版本号、系列号、仪器号、出厂日期 + sqlQuery := fmt.Sprintf(` + SELECT DISTINCT TOP 1 + ID, [2321], [2327], [2328], [2339], FORMAT([2329], 'yyyy-MM-ddTHH:mm:ssZ') AS Time, + COALESCE([2340], '') AS [2340], + CASE + WHEN COALESCE([2326], 0) < COALESCE([2340], 0) THEN COALESCE([2340], '') + ELSE COALESCE([2326], '') + END AS [2326] + FROM REPAIRANDMENT + WHERE [2321] = '%s' AND [2327] = '%s' AND [2328] = '%s' ORDER BY ID DESC + `, req.WellName, req.Series, req.Instrument) + + // 执行查询 + row, err := sqlConn.Query(sqlQuery) + if err != nil { + fmt.Println("查询错误:", err) + http.Error(response, "数据库查询失败", http.StatusInternalServerError) + return + } + defer row.Close() + + // 处理查询结果(仅取第一条记录) + var resp InstrumentMessRespdata + if row.Next() { + if err := row.Scan( + &resp.ID, + &resp.WellName, + &resp.Series, + &resp.Instrument, + &resp.Version, + &resp.Time, + &resp.WorkTimes, + &resp.WorkTime, + ); err != nil { + fmt.Println("解析错误:", err) + http.Error(response, "解析数据库结果失败", http.StatusInternalServerError) + return + } + } else { + // 如果没有数据,返回空结构体(或自定义错误) + fmt.Println("未找到数据") + } + //获取工作信息 + resp.WorkMessList = workMess(wellInfos, req.Flag, req.Content) + //获取维修信息 + resp.GetLcmRespData = getMaintenanceMess(req.Series, req.Instrument, req.Opuser) + + //返回 JSON 响应 + response.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(response).Encode(resp); err != nil { + fmt.Println("JSON 编码错误:", err) + http.Error(response, "返回结果编码失败", http.StatusInternalServerError) + } +} + +func workMess(wellInfos []get_vibration_resp, flag string, content string) []WellMessRespdata { + + var results []WellMessRespdata + if len(wellInfos) == 0 { + fmt.Println("wellInfos 是空的,没有数据可打印") + return results + } + + var db string + + // 循环打印每个 WellNameSource + fmt.Println("开始打印 WellNameSource 列表:") + workMessSql := `SELECT + [5200] AS WellName, + (SELECT TOP 1 [5203] + FROM [dbo].[EQUIPMENTRECORDS] t2 + WHERE t2.[5200] = t1.[5200] + ORDER BY t2.ID DESC) AS SampleField, + CONVERT(VARCHAR(50), MIN([5217])) + '-' + CONVERT(VARCHAR(50), MAX([5217])) AS ValueInterval, + MAX([5220]) AS GlobalMax1, + MAX([5221]) AS GlobalMax2, + CONVERT(VARCHAR(1000), ( + SELECT DISTINCT ',' + [5202] + FROM [dbo].[EQUIPMENTRECORDS] t2 + WHERE t2.[5200] = t1.[5200] + FOR XML PATH('') + )) AS PersonnelList + FROM [dbo].[EQUIPMENTRECORDS] t1` + for _, well := range wellInfos { + qsql := workMessSql + fmt.Sprintf(` WHERE [5200] = '%s' GROUP BY [5200]`, well.WellNameSource) + + db = well.Wellname + // 这些库被设置为了离线状态,需要先设置为启用状态 + if strings.HasPrefix(db, "LH2020-") || + strings.HasPrefix(db, "LH2021-") || + strings.HasPrefix(db, "LH2022-") || + strings.HasPrefix(db, "LH2023-") || + strings.HasPrefix(db, "LH2024-") { + conn, err := getOdbcConn("master") + if err != nil { + fmt.Println("链接master库失败", err.Error()) + } + defer conn.Close() + cmdSql := fmt.Sprintf("ALTER DATABASE [%s] SET ONLINE", db) + _, err = conn.Exec(cmdSql) + } + + conn, err := getOdbcConn(db) + if err != nil { + fmt.Println("查询失败", err.Error()) + continue + } + defer conn.Close() + rows, err := conn.Query(qsql) + if err != nil { + fmt.Println("查询工作状态出错", err.Error()) + continue + } + + defer rows.Close() + + for rows.Next() { + var item WellMessRespdata + var wellName, sampleField, valueInterval, personnelList, globalMax1, globalMax2 string + err := rows.Scan(&wellName, &sampleField, &valueInterval, &globalMax1, &globalMax2, &personnelList) + if err != nil { + fmt.Println("扫描数据失败", db, err.Error()) + continue + } + // 映射到结构体 + item.WellName = wellName + item.SampleField = sampleField + item.ValueInterval = valueInterval + item.GlobalMax1 = globalMax1 + item.GlobalMax2 = globalMax2 + item.PersonnelList = personnelList + if flag == "0" { + item.Content = "良好" + } else { + item.Content = content + } + + results = append(results, item) + } + } + return results +} + +func getMaintenanceMess(series string, instrument string, opuser string) []GetLcmRespData { + + var result []GetLcmRespData + ps_info := get_ps_info(opuser) + + var whereSql string + var ifWhere bool + + if series != "" { + likeid := "%" + series + "%" + if ifWhere { + whereSql += fmt.Sprintf(` and [sid] like '%s'`, likeid) + } else { + whereSql = fmt.Sprintf(` [sid] like '%s'`, likeid) + } + ifWhere = true + } + + if instrument != "" { + likeid := "%" + instrument + "%" + if ifWhere { + whereSql += fmt.Sprintf(` and [iid] like '%s'`, likeid) + } else { + whereSql = fmt.Sprintf(` [iid] like '%s'`, likeid) + } + ifWhere = true + } + + // 默认查询所有记录,可以根据需要添加分页逻辑 + selSql := "select [ID],[sid],[iid],[repair_cnt],[repair_level],[repair_context],[time],[user] from [life_cycle_manager]" + if ifWhere { + selSql += " where" + whereSql + } + selSql += " order by time desc" + + conn, err := getOdbcConn("WellNameInformation") + rows, err := conn.Query(selSql) + if err != nil { + logs.Error("getLcm Query Error", err.Error()) + return result + } + defer rows.Close() + + for rows.Next() { + var d GetLcmRespData + if err = rows.Scan(&d.ID, &d.Series, &d.InstrumentID, &d.Repair_cnt, &d.Repair_level, &d.Note, &d.Time, &d.Applicanter); err != nil { + logs.Error("getLcm scan Error", err.Error()) + continue + } + + // 处理时间格式 + if len(d.Time) >= 19 { + d.Time = d.Time[:10] + " " + d.Time[11:19] + d.Time = do_time_by_ps(d.Time, ps_info) + } + + // 判断是否显示操作按钮(12小时内) + timeLayout := "2006-01-02 15:04:05" + loc, _ := time.LoadLocation("Local") + opTime, err := time.ParseInLocation(timeLayout, d.Time, loc) + if err == nil { + d.IfShowOp = time.Since(opTime).Hours() < 12 + } else { + d.IfShowOp = false + } + + result = append(result, d) + } + + return result +} + // 跨域测试 func test(response http.ResponseWriter, request *http.Request) { fmt.Println("recv test req") diff --git a/req.go b/req.go index a84c854..5cde06f 100644 --- a/req.go +++ b/req.go @@ -155,6 +155,7 @@ type get_vibration_req struct { Wellname string `json:"wellname"` //井名 WellNameSource string `json:"wellNameSource"` //井名对应库 Uploadname string `json:"upload_name"` + IsMemory bool `json:"is_memory"` //是否勾选存储数据 } type get_nb_csv_req struct { @@ -654,3 +655,14 @@ type GetWellData struct { Index int `json:"index"` Count int `json:"count"` } + +// 仪器汇总页面的参数体 +type InstrumentMess struct { + Instrument string `json:"instrument"` + Opuser string `json:"opuser"` + Opuser_uuid string `json:"opuser_uuid"` + Series string `json:"series"` + WellName string `json:"wellName"` + Flag string `json:"flag"` + Content string `json:"content"` +} diff --git a/res.go b/res.go index 08778b6..65a4570 100644 --- a/res.go +++ b/res.go @@ -739,3 +739,26 @@ type GetUsersRespdata struct { Cnt int `json:"cnt"` LoginTime string `json:"loginTime"` } + +type InstrumentMessRespdata struct { + ID string `json:"id"` + WellName string `json:"wellName"` + Time string `json:"time"` + Series string `json:"series"` + Instrument string `json:"instrument"` + Version string `json:"version"` + WorkTime string `json:"workTime"` //累计工作时间 + WorkTimes string `json:"workTimes"` //本次工作时间 + WorkMessList []WellMessRespdata `json:"data"` + GetLcmRespData []GetLcmRespData `json:"data1"` +} + +type WellMessRespdata struct { + WellName string `json:"wellName"` //井名称 + SampleField string `json:"sampleField"` //入井状态 + ValueInterval string `json:"valueInterval"` //入井井深 + GlobalMax1 string `json:"globalMax1"` //最高工作温度 + GlobalMax2 string `json:"globalMax2"` //最高承压 + PersonnelList string `json:"personnelList"` //累计工作时间 + Content string `json:"content"` //仪器工作情况 +}