Files
Wx_WxCheck_Prod/WxCheckMvc/Controllers/CheckController.cs

961 lines
46 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Hosting;
using System.IO;
namespace WxCheckMvc.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class CheckController : ControllerBase
{
private readonly MySqlConnection _connection;
private readonly HttpClient _httpClient;
private readonly IConfiguration _configuration;
private readonly IWebHostEnvironment _environment;
public CheckController(MySqlConnection connection, IHttpClientFactory httpClientFactory, IConfiguration configuration, IWebHostEnvironment environment)
{
_connection = connection;
_httpClient = httpClientFactory.CreateClient();
_configuration = configuration;
_environment = environment;
}
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file, [FromForm] string rootPathType, [FromForm] string userKey)
{
try
{
if (file == null || file.Length == 0)
{
return BadRequest(new { success = false, message = "请选择文件" });
}
// 1. 确定保存路径
// 默认使用 Avatar如果传入了 rootPathType 则使用传入值
string folderName = "Avatar";
if (!string.IsNullOrWhiteSpace(rootPathType))
{
// 安全检查:只允许字母、数字、下划线,防止路径遍历
if (rootPathType.Any(c => !char.IsLetterOrDigit(c) && c != '_'))
{
return BadRequest(new { success = false, message = "rootPathType 包含非法字符,只允许字母、数字和下划线" });
}
folderName = rootPathType;
}
string webRootPath = _environment.WebRootPath;
string uploadDir = Path.Combine(webRootPath, folderName);
// 如果文件夹不存在,则创建
if (!Directory.Exists(uploadDir))
{
Directory.CreateDirectory(uploadDir);
}
// 2. 生成唯一文件名并保存
string fileExtension = Path.GetExtension(file.FileName);
string newFileName = Guid.NewGuid().ToString("N") + fileExtension;
string filePath = Path.Combine(uploadDir, newFileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
// 构建返回URL
string relativePath = $"/{folderName}/{newFileName}";
string fullUrl = $"{Request.Scheme}://{Request.Host}{relativePath}";
// 3. 如果提供了 UserKey更新数据库中的 AvatarUrl
if (!string.IsNullOrWhiteSpace(userKey))
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
string updateSql = "UPDATE xcx_users SET AvatarUrl = @AvatarUrl, UpdateTime = NOW() WHERE UserKey = @UserKey";
using (MySqlCommand cmd = new(updateSql, _connection))
{
cmd.Parameters.AddWithValue("@AvatarUrl", fullUrl);
cmd.Parameters.AddWithValue("@UserKey", userKey);
await cmd.ExecuteNonQueryAsync();
}
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
return Ok(new { success = true, message = "上传成功", url = fullUrl, path = relativePath });
}
catch (Exception ex)
{
// 确保连接关闭
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
return StatusCode(500, new { success = false, message = "上传失败", error = ex.Message });
}
}
// 将经纬度转换为地址信息
public async Task<string> ConvertCoordinatesToAddress(string longitude,string latitude)
{
try
{
// 使用高德地图API进行逆地理编码
string apiKey = _configuration["AmapApi:ApiKey"] ?? "4d5cb7818664ada68ae5f68783b8bd4c";
string url = $"https://restapi.amap.com/v3/geocode/regeo?output=json&location={longitude},{latitude}&key={apiKey}&radius=1000&extensions=all";
var response = await _httpClient.GetStringAsync(url);
var jsonDoc = JsonDocument.Parse(response);
var root = jsonDoc.RootElement;
if (root.GetProperty("status").GetString() == "1" && root.TryGetProperty("regeocode", out var regeocodeElement) && regeocodeElement.ValueKind != JsonValueKind.Null)
{
if (regeocodeElement.TryGetProperty("formatted_address", out var formatted_address))
{
return formatted_address.ToString();
}
if (regeocodeElement.TryGetProperty("addressComponent", out var addressComponent))
{
string province = addressComponent.TryGetProperty("province", out var provinceElement) && provinceElement.ValueKind == JsonValueKind.String ? provinceElement.GetString() : "";
string city = addressComponent.TryGetProperty("city", out var cityElement) && cityElement.ValueKind == JsonValueKind.String ? cityElement.GetString() : "";
string district = addressComponent.TryGetProperty("district", out var districtElement) && districtElement.ValueKind == JsonValueKind.String ? districtElement.GetString() : "";
string township = addressComponent.TryGetProperty("township", out var townshipElement) && townshipElement.ValueKind == JsonValueKind.String ? townshipElement.GetString() : "";
// 获取街道和门牌号信息
string street = "";
string streetNumber = "";
double distance = 0;
// 方法1从addressComponent获取街道信息
if (addressComponent.TryGetProperty("streetNumber", out var streetNumberElement) && streetNumberElement.ValueKind == JsonValueKind.Object)
{
street = streetNumberElement.TryGetProperty("street", out var streetElement) && streetElement.ValueKind == JsonValueKind.String ? streetElement.GetString() : "";
streetNumber = streetNumberElement.TryGetProperty("number", out var numberElement) && numberElement.ValueKind == JsonValueKind.String ? numberElement.GetString() : "";
// 获取距离信息
if (streetNumberElement.TryGetProperty("distance", out var distanceElement) && distanceElement.ValueKind == JsonValueKind.String)
{
double.TryParse(distanceElement.GetString(), out distance);
}
}
// 方法2如果方法1没有获取到街道信息尝试从aoi信息中获取
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("aois", out var aoisElement) && aoisElement.ValueKind == JsonValueKind.Array)
{
var aoisArray = aoisElement.EnumerateArray();
foreach (var aoi in aoisArray)
{
if (aoi.TryGetProperty("name", out var aoiNameElement) && aoiNameElement.ValueKind == JsonValueKind.String)
{
street = aoiNameElement.GetString();
break; // 取第一个AOI作为街道信息
}
}
}
// 方法3如果前两种方法都没有获取到街道信息尝试从pois信息中获取
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("pois", out var poisElement) && poisElement.ValueKind == JsonValueKind.Array)
{
var poisArray = poisElement.EnumerateArray();
foreach (var poi in poisArray)
{
if (poi.TryGetProperty("name", out var poiNameElement) && poiNameElement.ValueKind == JsonValueKind.String)
{
street = poiNameElement.GetString();
break; // 取第一个POI作为街道信息
}
}
}
// 方法4如果以上方法都没有获取到街道信息尝试从formatted_address中解析
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("formatted_address", out var formattedAddressElement) && formattedAddressElement.ValueKind == JsonValueKind.String)
{
string formattedAddress = formattedAddressElement.GetString();
// 尝试从格式化地址中提取街道信息
// 格式化地址通常格式为:省 市 区 街道 具体地址
// 使用字符串数组作为分隔符
string[] separators = { " ", "省", "市", "区", "县", "镇", "街道", "路", "巷", "号" };
var addressParts = formattedAddress.Split(separators, StringSplitOptions.RemoveEmptyEntries);
// 查找可能包含街道信息的部分
for (int i = 0; i < addressParts.Length; i++)
{
var part = addressParts[i];
// 如果部分包含"路"、"街"、"巷"等关键词,可能是街道信息
if (part.Contains('路') || part.Contains('街') || part.Contains('巷') || part.Contains('道'))
{
street = part;
// 如果下一个部分存在且不是区县名称,可能是门牌号
if (i + 1 < addressParts.Length &&
!addressParts[i + 1].Contains('区') &&
!addressParts[i + 1].Contains('县'))
{
streetNumber = addressParts[i + 1];
}
break;
}
}
}
// 方法5如果仍然没有获取到街道信息尝试从nearestRoad信息中获取
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("streetNumber", out var nearestStreetElement) &&
nearestStreetElement.ValueKind == JsonValueKind.Object)
{
if (nearestStreetElement.TryGetProperty("street", out var nearestStreetNameElement) && nearestStreetNameElement.ValueKind == JsonValueKind.String)
{
street = nearestStreetNameElement.GetString();
}
}
// 构建详细地址字符串
string address = "";
if (!string.IsNullOrEmpty(province))
{
address += province;
}
if (!string.IsNullOrEmpty(city) && city != province)
{
address += " " + city;
}
if (!string.IsNullOrEmpty(district))
{
address += " " + district;
}
if (!string.IsNullOrEmpty(township))
{
address += " " + township;
}
if (!string.IsNullOrEmpty(street))
{
address += " " + street;
}
if (!string.IsNullOrEmpty(streetNumber))
{
address += " " + streetNumber;
}
// 如果有距离信息,添加到地址后面
if (distance > 0)
{
address += $" {distance:F1}米";
}
if (string.IsNullOrEmpty(address))
{
return "未获取到位置信息(高德返回值为空) " + latitude + "," + longitude;
}
return address.Trim();
}
}
return latitude + "," + longitude; ; // 如果API调用失败返回原始值
}
catch (Exception)
{
return latitude + "," + longitude; ; // 如果发生异常,返回原始值
}
}
[HttpPost]
public async Task<IActionResult> CheckAddress([FromBody] CheckAddressRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
// 从数据库查询经纬度信息
string latitude = "";
string longitude = "";
using (MySqlCommand cmd = new("SELECT Latitude, Longitude FROM xcx_conversation WHERE Guid = @Guid AND IsDeleted = 0", _connection))
{
cmd.Parameters.AddWithValue("@Guid", request.Guid);
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
latitude = reader.IsDBNull(0) ? "" : reader.GetString(0);
longitude = reader.IsDBNull(1) ? "" : reader.GetString(1);
}
else
{
return NotFound(new { success = false, message = "记录不存在或已被删除" });
}
}
}
// 转换经纬度为地址
var address = await ConvertCoordinatesToAddress(longitude, latitude);
// 更新数据库中的UserLocation字段
using (MySqlCommand cmd = new("UPDATE xcx_conversation SET UserLocation = @UserLocation WHERE Guid = @Guid AND IsDeleted = 0", _connection))
{
cmd.Parameters.AddWithValue("@Guid", request.Guid);
cmd.Parameters.AddWithValue("@UserLocation", address);
int rowsAffected = await cmd.ExecuteNonQueryAsync();
if (rowsAffected == 0)
{
return NotFound(new { success = false, message = "记录不存在或已被删除" });
}
}
return Ok(new { success = true, message = "地址更新成功", address });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "更新失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 添加会话记录
[HttpPost]
public async Task<IActionResult> AddConversation([FromBody] ConversationRequest request)
{
DateTime nowtime = DateTime.Now;
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
// 解析经纬度并转换为地址
string address = "";
string latitude = "";
string longitude = "";
// 否则尝试从UserLocation字段解析
if (!string.IsNullOrEmpty(request.UserLocation))
{
string[] parts = request.UserLocation.Split(',');
if (parts.Length == 2)
{
if (double.TryParse(parts[0], out double lat) && double.TryParse(parts[1], out double lng))
{
longitude = lng.ToString();
latitude = lat.ToString();
address = "";// await ConvertCoordinatesToAddress(latitude, longitude);
}
}
}
// 生成GUID
string conversationGuid = string.IsNullOrEmpty(request.Guid) ? Guid.NewGuid().ToString("N") : request.Guid;
long conversationId = 0;
using (MySqlCommand cmd = new("INSERT INTO xcx_conversation (UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, Guid, SpeakingTime) VALUES (@UserKey, @ConversationContent, @SendMethod, @UserLocation, @Latitude, @Longitude, @RecordTime, @RecordTimeUTCStamp, @IsDeleted, @CreateTime, @MessageType, @Guid, @SpeakingTime); SELECT LAST_INSERT_ID();", _connection))
{
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
cmd.Parameters.AddWithValue("@ConversationContent", request.ConversationContent);
cmd.Parameters.AddWithValue("@SendMethod", request.SendMethod);
cmd.Parameters.AddWithValue("@UserLocation", address);
cmd.Parameters.AddWithValue("@Latitude", latitude);
cmd.Parameters.AddWithValue("@Longitude", longitude);
cmd.Parameters.AddWithValue("@RecordTime", nowtime);
cmd.Parameters.AddWithValue("@CreateTime", nowtime);
cmd.Parameters.AddWithValue("@RecordTimeUTCStamp", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
cmd.Parameters.AddWithValue("@IsDeleted", 0);
cmd.Parameters.AddWithValue("@Guid", conversationGuid);
cmd.Parameters.AddWithValue("@SpeakingTime", request.SpeakingTime);
object result = await cmd.ExecuteScalarAsync();
conversationId = Convert.ToInt64(result);
}
// 查询刚插入的记录,并左连接用户表
if (conversationId > 0)
{
string query = @"SELECT convs.Id, convs.Guid, convs.UserKey, convs.ConversationContent, convs.SendMethod,
convs.UserLocation, convs.Latitude, convs.Longitude, convs.RecordTime,
convs.RecordTimeUTCStamp, convs.IsDeleted, convs.CreateTime, convs.MessageType, convs.SpeakingTime,
users.UserName, users.WeChatName, users.PhoneNumber, users.AvatarUrl
FROM xcx_conversation AS convs
LEFT JOIN xcx_users AS users ON convs.UserKey = users.UserKey
WHERE convs.Guid = @Guid";
using (MySqlCommand cmd = new(query, _connection))
{
cmd.Parameters.AddWithValue("@Guid", conversationGuid);
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
// 构建要发送到Redis的数据
var messageData = new Dictionary<string, string>
{
["Id"] = reader.GetInt64(0).ToString(),
["Guid"] = reader.IsDBNull(1) ? "" : reader.GetString(1),
["UserKey"] = reader.GetString(2),
["ConversationContent"] = reader.GetString(3),
["SendMethod"] = reader.GetString(4),
["UserLocation"] = reader.IsDBNull(5) ? "" : reader.GetString(5),
["Latitude"] = reader.IsDBNull(6) ? "" : reader.GetString(6),
["Longitude"] = reader.IsDBNull(7) ? "" : reader.GetString(7),
["RecordTime"] = reader.GetDateTime(8).ToString("yyyy-MM-dd HH:mm:ss"),
["RecordTimeUTCStamp"] = reader.GetInt64(9).ToString(),
["IsDeleted"] = reader.GetBoolean(10).ToString(),
["CreateTime"] = reader.GetDateTime(11).ToString("yyyy-MM-dd HH:mm:ss"),
["MessageType"] = reader.GetInt32(12).ToString(),
["SpeakingTime"] = reader.IsDBNull(13) ? "" : reader.GetInt32(13).ToString(),
["UserName"] = reader.IsDBNull(14) ? "" : reader.GetString(14),
["WeChatName"] = reader.IsDBNull(15) ? "" : reader.GetString(15),
["PhoneNumber"] = reader.IsDBNull(16) ? "" : reader.GetString(16),
["AvatarUrl"] = reader.IsDBNull(17) ? "" : reader.GetString(17)
};
// 发送到Redis Stream
try
{
// 确保Stream和Group存在
CSRedisCacheHelper.XGroupCreate("xcx_msg", "xcx_group", "0");
// 将Dictionary转换为params (string, string)[]格式
var fieldValues = messageData.SelectMany(kvp => new (string, string)[] { (kvp.Key, kvp.Value) }).ToArray();
// 添加消息到Stream
string messageId = CSRedisCacheHelper.XAdd("xcx_msg", fieldValues);
// 记录日志(可选)
System.Diagnostics.Debug.WriteLine($"消息已发送到Redis Stream: {messageId}");
}
catch (Exception ex)
{
// 记录错误但不影响主流程
System.Diagnostics.Debug.WriteLine($"发送到Redis Stream失败: {ex.Message}");
}
}
}
}
}
return Ok(new { success = true, message = "收到!", conversationGuid, receivedTime = nowtime.ToString("yyyy-MM-dd HH:mm:ss") });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "发送失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 根据UserKey查询会话记录
[HttpPost]
public async Task<IActionResult> GetConversations([FromBody] UserKeyRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
List<ConversationResponse> conversations = [];
// 构建查询SQL根据MessageType参数决定是否添加过滤条件
string query = "SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime FROM xcx_conversation WHERE UserKey = @UserKey AND IsDeleted = 0";
if (request.MessageType == 1)
{
query += " AND MessageType = @MessageType";
}
query += " ORDER BY RecordTimeUTCStamp DESC";
using (MySqlCommand cmd = new(query, _connection))
{
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
conversations.Add(new ConversationResponse
{
Id = reader.GetInt64(0),
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
UserKey = reader.GetString(2),
ConversationContent = reader.GetString(3),
SendMethod = reader.GetString(4),
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
RecordTime = reader.GetDateTime(8),
RecordTimeUTCStamp = reader.GetInt64(9),
IsDeleted = reader.GetBoolean(10),
CreateTime = reader.GetDateTime(11),
MessageType = reader.GetInt32(12),
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
});
}
}
}
return Ok(new { success = true, data = conversations.OrderBy(z => z.RecordTimeUTCStamp) });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 更新会话记录
[HttpPost]
public async Task<IActionResult> UpdateConversation([FromBody] UpdateConversationRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
DateTime nowtime = DateTime.Now;
using (MySqlCommand cmd = new("UPDATE xcx_conversation SET ConversationContent = @ConversationContent, SendMethod = @SendMethod, UserLocation = @UserLocation, MessageType = @MessageType, RecordTime = @RecordTime WHERE Guid = @Guid AND UserKey = @UserKey", _connection))
{
cmd.Parameters.AddWithValue("@Guid", request.Guid);
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
cmd.Parameters.AddWithValue("@ConversationContent", request.ConversationContent);
cmd.Parameters.AddWithValue("@SendMethod", request.SendMethod);
cmd.Parameters.AddWithValue("@UserLocation", "");//request.UserLocation ?? "");
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
cmd.Parameters.AddWithValue("@RecordTime", nowtime);
int rowsAffected = await cmd.ExecuteNonQueryAsync();
if (rowsAffected == 0)
{
return NotFound(new { success = false, message = "记录不存在或无权限修改" });
}
}
return Ok(new { success = true, message = "更新成功" , receivedTime = nowtime.ToString("yyyy-MM-dd HH:mm:ss") });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "更新失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 软删除会话记录
[HttpPost]
public async Task<IActionResult> DeleteConversation([FromBody] DeleteConversationRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
using (MySqlCommand cmd = new("UPDATE xcx_conversation SET IsDeleted = 1 WHERE Guid = @Guid AND UserKey = @UserKey AND IsDeleted = 0", _connection))
{
cmd.Parameters.AddWithValue("@Guid", request.Guid);
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
int rowsAffected = await cmd.ExecuteNonQueryAsync();
if (rowsAffected == 0)
{
return NotFound(new { success = false, message = "记录不存在或已被删除" });
}
}
return Ok(new { success = true, message = "删除成功" });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "删除失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 根据GUID查询会话记录不考虑IsDeleted状态
[HttpPost]
public async Task<IActionResult> GetConversationByGuid([FromBody] GetConversationByGuidRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
// 查询记录不考虑IsDeleted状态
string query = @"SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation,
Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime
FROM xcx_conversation
WHERE Guid = @Guid";
using (MySqlCommand cmd = new(query, _connection))
{
cmd.Parameters.AddWithValue("@Guid", request.Guid);
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
var conversation = new ConversationResponse
{
Id = reader.GetInt64(0),
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
UserKey = reader.GetString(2),
ConversationContent = reader.GetString(3),
SendMethod = reader.GetString(4),
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
RecordTime = reader.GetDateTime(8),
RecordTimeUTCStamp = reader.GetInt64(9),
IsDeleted = reader.GetBoolean(10),
CreateTime = reader.GetDateTime(11),
MessageType = reader.GetInt32(12),
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
};
return Ok(new { success = true, message = "查询成功", data = conversation });
}
else
{
return NotFound(new { success = false, message = "未找到该记录" });
}
}
}
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 分页查询会话记录
[HttpPost]
public async Task<IActionResult> GetConversationsByPage([FromBody] PaginationRequest request)
{
try
{
if (_connection.State != ConnectionState.Open)
{
await _connection.OpenAsync();
}
// 验证并设置默认值
if (request.Page < 1) request.Page = 1;
if (request.PageSize < 1 || request.PageSize > 100) request.PageSize = 10;
int offset = (request.Page - 1) * request.PageSize;
List<ConversationResponse> conversations = [];
// 构建分页查询SQL根据MessageType参数决定是否添加过滤条件
string query = @"SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime
FROM xcx_conversation
WHERE UserKey = @UserKey AND IsDeleted = 0";
if (request.MessageType == 1)
{
query += " AND MessageType = @MessageType";
}
query += " ORDER BY RecordTimeUTCStamp DESC LIMIT @Offset, @Limit";
using (MySqlCommand cmd = new(query, _connection))
{
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
if (request.MessageType == 1)
{
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
}
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@Limit", request.PageSize);
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
conversations.Add(new ConversationResponse
{
Id = reader.GetInt64(0),
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
UserKey = reader.GetString(2),
ConversationContent = reader.GetString(3),
SendMethod = reader.GetString(4),
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
RecordTime = reader.GetDateTime(8),
RecordTimeUTCStamp = reader.GetInt64(9),
IsDeleted = reader.GetBoolean(10),
CreateTime = reader.GetDateTime(11),
MessageType = reader.GetInt32(12),
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
});
}
}
}
// 查询总数根据MessageType参数决定是否添加过滤条件
int totalCount = 0;
string countQuery = "SELECT COUNT(*) FROM xcx_conversation WHERE UserKey = @UserKey AND IsDeleted = 0";
if (request.MessageType == 1)
{
countQuery += " AND MessageType = @MessageType";
}
using (MySqlCommand countCmd = new(countQuery, _connection))
{
countCmd.Parameters.AddWithValue("@UserKey", request.UserKey);
if (request.MessageType == 1)
{
countCmd.Parameters.AddWithValue("@MessageType", request.MessageType);
}
totalCount = Convert.ToInt32(await countCmd.ExecuteScalarAsync());
}
int totalPages = (int)Math.Ceiling((double)totalCount / request.PageSize);
return Ok(new {
success = true,
data = new {
conversations = conversations.OrderBy(z => z.RecordTimeUTCStamp),
totalCount = totalCount,
page = request.Page,
pageSize = request.PageSize,
totalPages = totalPages
}
});
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
}
finally
{
if (_connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
}
}
}
// 从Redis Stream读取消息
[HttpPost]
public async Task<IActionResult> ReadMessageFromRedis([FromBody] RedisMessageRequest request)
{
try
{
// 确保Stream和Group存在
CSRedisCacheHelper.XGroupCreate("xcx_msg", "xcx_group", "0");
// 从Redis Stream读取消息
string groupName = request.GroupName ?? "xcx_group";
string consumerName = request.ConsumerName ?? "consumer_" + DateTime.Now.Ticks;
string messages = CSRedisCacheHelper.XReadGroup("xcx_msg", groupName, consumerName, request.Count ?? 1);
if (string.IsNullOrEmpty(messages))
{
return Ok(new { success = true, message = "没有新消息", data = new List<string>() });
}
// 解析消息
var messageList = new List<object>();
try
{
var messageEntries = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(messages);
if (messageEntries != null)
{
foreach (var entry in messageEntries)
{
if (entry.TryGetValue("Id", out var id) &&
entry.TryGetValue("Values", out var values))
{
var messageData = new Dictionary<string, string>();
// 如果Values是JsonElement需要进一步解析
if (values is JsonElement valuesElement && valuesElement.ValueKind == JsonValueKind.Object)
{
foreach (var property in valuesElement.EnumerateObject())
{
messageData[property.Name] = property.Value.GetString() ?? "";
}
}
else if (values is Dictionary<string, string> valuesDict)
{
messageData = valuesDict;
}
messageData["MessageId"] = id.ToString();
messageList.Add(messageData);
}
}
}
}
catch (Exception parseEx)
{
// 如果解析失败,尝试直接返回原始消息
System.Diagnostics.Debug.WriteLine($"解析消息失败: {parseEx.Message}");
messageList.Add(new { RawMessage = messages });
}
return Ok(new { success = true, message = "成功读取消息", data = messageList });
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "读取消息失败", error = ex.Message });
}
}
}
// 请求和响应模型
public class ConversationRequest
{
public string UserKey { get; set; }
public string ConversationContent { get; set; }
public string SendMethod { get; set; }
public string UserLocation { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public int MessageType { get; set; } = 1; // 1:公有2:私有
public string? Guid { get; set; } // 会话唯一标识
public int? SpeakingTime { get; set; } // 对话时长
}
public class UserKeyRequest
{
public string UserKey { get; set; }
public int MessageType { get; set; } = 0; // 0:不判断消息类型1:公有2:私有
}
public class PaginationRequest
{
public string UserKey { get; set; }
public int Page { get; set; } = 1; // 默认第一页
public int PageSize { get; set; } = 10; // 默认每页10条
public int MessageType { get; set; } = 0; // 0:不判断消息类型1:公有2:私有
}
public class UpdateConversationRequest
{
public long? Id { get; set; }
public string Guid { get; set; } // 会话唯一标识
public string UserKey { get; set; }
public string ConversationContent { get; set; }
public string SendMethod { get; set; }
public string UserLocation { get; set; }
public int MessageType { get; set; } = 0;
public int? SpeakingTime { get; set; }
}
public class DeleteConversationRequest
{
public long? Id { get; set; }
public string Guid { get; set; } // 会话唯一标识
public string UserKey { get; set; }
}
public class CheckAddressRequest
{
public long? Id { get; set; }
public string Guid { get; set; } // 会话唯一标识
}
public class GetConversationByGuidRequest
{
public long? Id { get; set; }
public string Guid { get; set; } // 会话唯一标识
}
public class ConversationResponse
{
public long Id { get; set; }
public string Guid { get; set; } // 会话唯一标识
public string UserKey { get; set; }
public string ConversationContent { get; set; }
public string SendMethod { get; set; }
public string UserLocation { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public DateTime RecordTime { get; set; }
public long RecordTimeUTCStamp { get; set; }
public bool IsDeleted { get; set; }
public DateTime CreateTime { get; set; }
public int MessageType { get; set; } // 1:公有消息2:私有消息
public int? SpeakingTime { get; set; }
}
public class RedisMessageRequest
{
public string GroupName { get; set; } = "xcx_group";
public string ConsumerName { get; set; }
public int? Count { get; set; } = 1;
}
}