diff --git a/src/db.rs b/src/db.rs index a2c84c9..275144a 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,10 +1,105 @@ -use sqlx::postgres::PgPool; // 修改导入路径 +use sqlx::PgPool; use std::env; +// 从 models 模块引入 WeatherData 结构体 +use crate::models::WeatherData; + +// 这个函数封装了所有与数据库交互的逻辑 +pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData) -> Result { + // 1. 根据 openid 查询 user_id + let user_id = match sqlx::query_as::<_, (i32,)>("SELECT id FROM users WHERE openid = $1") + .bind(&weather_data.openid) + .fetch_optional(pool) + .await + { + Ok(Some((id,))) => id, + Ok(None) => { + return Err(format!("未找到openid为 {} 的用户", weather_data.openid)); + } + Err(e) => { + return Err(format!("查询用户失败: {}", e)); + } + }; + + // 2. 准备插入数据的 SQL 语句 + let insert_query = r#" + INSERT INTO weather_data ( + user_id, title, date, hour, min, longitude, latitude, daysincejanfirst, + theta, solardeclination, sunaltitude, overallcloudiness, lowcloudiness, + cloudindex, solarradiationlevel, hasmeasuredwindspeed, measuredwindspeed, + convertedwindspeed, measurementheight, areatype, pointwindspeed, + atmosphericstability, suitabilitydegree, winddirection, averagewinddirection, + winddirectionstandarddeviation, windspeed, averagewindspeed, windspeedsuitability, + winddirectionsuitability, overallsuitability, inspectiontype, assignmentnumber, + calculatedwindspeed + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, + $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34 + ) RETURNING id + "#; + + // 转换经纬度为字符串 + let longitude_str = weather_data.longitude.to_string(); + let latitude_str = weather_data.latitude.to_string(); + + // 3. 执行插入操作 + let inserted_id = match sqlx::query_as::<_, (i32,)>(insert_query) + .bind(user_id) + .bind(&weather_data.title) + .bind(weather_data.date) // NaiveDate 类型,sqlx 会自动处理 + .bind(weather_data.hours) + .bind(weather_data.min) + .bind(&longitude_str) + .bind(&latitude_str) + .bind(weather_data.day_since_jan_first) + .bind(weather_data.theta) + .bind(weather_data.solar_declination) + .bind(weather_data.sun_altitude) + .bind(&weather_data.overall_cloudiness) + .bind(&weather_data.low_cloudiness) + .bind(&weather_data.cloud_index) + .bind(weather_data.solar_radiation_level as i32) + .bind(weather_data.has_measured_wind_speed) + .bind(weather_data.measured_wind_speed) + .bind(weather_data.converted_wind_speed as i32) + .bind(weather_data.measurement_height) + .bind(&weather_data.area_type) + .bind(weather_data.point_wind_speed) + .bind(&weather_data.atmospheric_stability) + .bind(&weather_data.suitability_degree) + .bind( + serde_json::to_value(&weather_data.wind_direction) + .map_err(|e| format!("JSON 序列化失败: {}", e))?, + ) + .bind(weather_data.average_wind_direction) + .bind(weather_data.wind_direction_standard_deviation) + .bind( + serde_json::to_value(&weather_data.wind_speed) + .map_err(|e| format!("JSON 序列化失败: {}", e))?, + ) + .bind(weather_data.average_wind_speed) + .bind(&weather_data.wind_speed_suitability) + .bind(&weather_data.wind_direction_suitability) + .bind(&weather_data.overall_suitability) + .bind(&weather_data.inspection_type) + .bind(&weather_data.assignment_number) + .bind(weather_data.calculated_wind_speed) + .fetch_one(pool) + .await + { + Ok((id,)) => id, + Err(e) => { + return Err(format!("插入数据失败: {}", e)); + } + }; + + // 4. 成功,返回插入的 ID + Ok(inserted_id) +} + pub async fn create_pool() -> Result { dotenvy::dotenv().ok(); - let database_url = env::var("DATABASE_URL") - .expect("DATABASE_URL must be set in .env file"); - + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set in .env file"); + PgPool::connect(&database_url).await -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 47254d0..775c656 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use sqlx::postgres::PgPool; mod db; mod models; +use db::insert_weather_data; use models::WeatherData; // 定义请求体结构 @@ -203,123 +204,32 @@ async fn post_weather_data( data: web::Json, pool: web::Data, ) -> impl Responder { - // 打印接收的数据 - println!("Received weather data: {:#?}", data); + println!("Received weather data, preparing to insert into DB..."); - // 1. 根据openid查询user_id - let openid = &data.openid; - let query_user = r#" - SELECT id FROM users WHERE openid = $1 - "#; - - let user_id_result: Result, sqlx::Error> = - sqlx::query_as::<_, (i32,)>(query_user) - .bind(openid) - .fetch_optional(pool.get_ref()) - .await; - - let user_id = match user_id_result { - Ok(Some((id,))) => id, - Ok(None) => { - let error_msg = format!("未找到openid为 {} 的用户", openid); - eprintln!("{}", error_msg); - // 返回200状态码,但success为false - return HttpResponse::Ok().json(serde_json::json!({ - "success": false, - "errcode": 404, - "errmsg": error_msg - })); - } - Err(e) => { - let error_msg = format!("查询用户失败: {}", e); - eprintln!("{}", error_msg); - return HttpResponse::Ok().json(serde_json::json!({ - "success": false, - "errcode": 500, - "errmsg": error_msg - })); - } - }; - - // 2. 将天气数据插入数据库 - let insert_query = r#" - INSERT INTO weather_data ( - user_id, title, date, hour, min, longitude, latitude, daysincejanfirst, - theta, solardeclination, sunaltitude, overallcloudiness, lowcloudiness, - cloudindex, solarradiationlevel, hasmeasuredwindspeed, measuredwindspeed, - convertedwindspeed, measurementheight, areatype, pointwindspeed, - atmosphericstability, suitabilitydegree, winddirection, averagewinddirection, - winddirectionstandarddeviation, windspeed, averagewindspeed, windspeedsuitability, - winddirectionsuitability, overallsuitability, inspectiontype, assignmentnumber, - calculatedwindspeed - ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, - $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34 - ) RETURNING id - "#; - - // 转换经纬度为字符串 - let longitude_str = data.longitude.to_string(); - let latitude_str = data.latitude.to_string(); - - // 执行插入操作 - let result = sqlx::query_as::<_, (i32,)>(insert_query) - .bind(user_id) - .bind(&data.title) - .bind(&data.date) - .bind(data.hours) - .bind(data.min) - .bind(&longitude_str) - .bind(&latitude_str) - .bind(data.day_since_jan_first) - .bind(data.theta) - .bind(data.solar_declination) - .bind(data.sun_altitude) - .bind(&data.overall_cloudiness) - .bind(&data.low_cloudiness) - .bind(&data.cloud_index) - .bind(data.solar_radiation_level as i32) - .bind(data.has_measured_wind_speed) - .bind(data.measured_wind_speed) - .bind(data.converted_wind_speed as i32) - .bind(data.measurement_height) - .bind(&data.area_type) - .bind(data.point_wind_speed) - .bind(&data.atmospheric_stability) - .bind(&data.suitability_degree) - .bind(serde_json::to_value(&data.wind_direction).unwrap()) - .bind(data.average_wind_direction) - .bind(data.wind_direction_standard_deviation) - .bind(serde_json::to_value(&data.wind_speed).unwrap()) - .bind(data.average_wind_speed) - .bind(&data.wind_speed_suitability) - .bind(&data.wind_direction_suitability) - .bind(&data.overall_suitability) - .bind(&data.inspection_type) - .bind(&data.assignment_number) - .bind(data.calculated_wind_speed) - .fetch_one(pool.get_ref()) - .await; - - match result { - Ok((inserted_id,)) => { + // 调用 db.rs 中的函数来处理数据库逻辑 + match insert_weather_data(pool.get_ref(), &data).await { + Ok(inserted_id) => { println!( "Successfully inserted weather data with id: {}", inserted_id ); HttpResponse::Ok().json(serde_json::json!({ - "success": true, // 前端期望的成功标识 + "success": true, "message": "Weather data inserted successfully", "inserted_id": inserted_id, "received_assignment": data.assignment_number })) } - Err(e) => { - let error_msg = format!("插入数据失败: {}", e); - eprintln!("{}", error_msg); + Err(error_msg) => { + eprintln!("Database operation failed: {}", error_msg); + // 根据错误信息返回统一格式的错误响应 + let mut errcode = 500; + if error_msg.starts_with("未找到openid") { + errcode = 404; + } HttpResponse::Ok().json(serde_json::json!({ - "success": false, // 前端期望的失败标识 - "errcode": 500, + "success": false, + "errcode": errcode, "errmsg": error_msg })) }