新增:伙伴云API对接 控制器

This commit is contained in:
2025-12-15 08:51:00 +08:00
parent 4230fa4d27
commit b3520ee98e
8 changed files with 1610 additions and 123 deletions

View File

@@ -0,0 +1,660 @@
using Common;
using LinqToDB.Common;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.SS.Formula.Functions;
using RestSharp;
using System.Collections;
using static NPOI.HSSF.UserModel.HeaderFooter;
using MySql.Data.MySqlClient;
using System.Data;
using BLW_Log.Models;
namespace BLW_Log.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class HuobanController : ControllerBase
{
private readonly string baseUrl = "https://api.huoban.com/";
private readonly string API_Key = "FIQBLpReK6nAJ0CzYOxmNgKtEpa0cApctanSZyGW";
private readonly List<string> TblSPHeader = ["审批状态", "报备编号", "项目名称", "客房数量", "所属客户", "负责人", "流程结束时间"];
/// <summary>
/// 创建返回结果的辅助方法
/// </summary>
/// <param name="isSuccess">是否成功</param>
/// <param name="message">返回消息</param>
/// <param name="statusCode">状态码</param>
/// <param name="data">返回数据</param>
/// <returns>ReturnInfo对象</returns>
private ReturnInfo CreateResult(bool isSuccess, string message, int statusCode, object? data = null)
{
return new ReturnInfo
{
isok = isSuccess,
message = message,
status = statusCode,
response = data
};
}
/// <summary>
/// 获取工作区ID内部方法
/// </summary>
/// <returns>工作区ID</returns>
private string GetHuobanSpaceList()
{
try
{
// 创建 REST 客户端
var options = new RestClientOptions(baseUrl);
var client = new RestClient(options);
// 创建请求
var request = new RestRequest("openapi/v1/space/list", Method.Get);
// 添加授权头
request.AddHeader("Open-Authorization", $"Bearer {API_Key}");
// 执行请求
var response = client.Execute(request);
string space_id = "";
if (response.IsSuccessful)
{
// 解析响应内容
var responseData = JsonConvert.DeserializeObject<dynamic>(response.Content);
foreach (var item in responseData.data.spaces)
{
if (item.name == "宝来威智能(广东)有限公司")
{
space_id = item.space_id;
break;
}
}
}
return space_id;
}
catch (Exception ex)
{
return "";
}
}
/// <summary>
/// 获取"项目报备"表格ID
/// </summary>
/// <param name="space_id">工作区ID</param>
/// <returns>表格ID</returns>
private string GetProjectReportTableId(string space_id)
{
try
{
// 创建 REST 客户端
var options = new RestClientOptions(baseUrl);
var client = new RestClient(options);
// 创建请求
var request = new RestRequest("openapi/v1/table/list", Method.Post);
// 添加授权头
request.AddHeader("Open-Authorization", $"Bearer {API_Key}");
request.AddHeader("Content-Type", "application/json");
// 添加请求体
var requestBody = new { space_id };
request.AddJsonBody(requestBody);
// 执行请求
var response = client.Execute(request);
if (response.IsSuccessful)
{
// 解析响应内容
var responseData = JsonConvert.DeserializeObject<dynamic>(response.Content);
string table_id = "";
foreach (var item in responseData.data.tables)
{
if (item.name == "项目报备")
{
table_id = item.table_id;
break;
}
}
return table_id;
}
else
{
return "";
}
}
catch (Exception ex)
{
return "";
}
}
/// <summary>
/// 获取"项目报备"表格表头
/// </summary>
/// <param name="space_id">工作区ID</param>
/// <returns>表格ID</returns>
private Dictionary<string, string> GetProjectReportTableHeader(string table_id)
{
try
{
// 创建 REST 客户端
var options = new RestClientOptions(baseUrl);
var client = new RestClient(options);
// 创建请求
var request = new RestRequest($"openapi/v1/table/{table_id}", Method.Post);
// 添加授权头
request.AddHeader("Open-Authorization", $"Bearer {API_Key}");
request.AddHeader("Content-Type", "application/json");
// 执行请求
var response = client.Execute(request);
if (response.IsSuccessful)
{
Dictionary<string, string> tabelHeader = [];
// 解析响应内容
var responseData = JsonConvert.DeserializeObject<TblRoot>(response.Content);
var dic = responseData.data.table.fields;
foreach (dynamic item in dic)
{
if (TblSPHeader.Contains(Convert.ToString(item.name)))
{
tabelHeader.Add(item.field_id.ToString(), item.name.ToString());
}
}
return tabelHeader;
}
else
{
return [];
}
}
catch (Exception ex)
{
return [];
}
}
/// <summary>
/// 查询"项目报备"数据列表
/// </summary>
/// <param name="table_id">表格ID</param>
/// <returns>数据列表</returns>
private dynamic QueryProjectReportData(string table_id, Dictionary<string, string> TblHeader, int limit = 5, int offset = 0)
{
try
{
// 创建 REST 客户端
var options = new RestClientOptions(baseUrl);
var client = new RestClient(options);
// 创建请求
var request = new RestRequest("openapi/v1/item/list", Method.Post);
// 添加授权头
request.AddHeader("Open-Authorization", $"Bearer {API_Key}");
request.AddHeader("Content-Type", "application/json");
// 构建请求体
var requestBody = new
{
table_id,
filter = new
{
and = new ArrayList
{
new
{
field = "2200000565424395",
query = new
{
eq = new List<string> { "2" }
}
}
}
},
order = new
{
field_id = "2200000565427086",
type = "desc"
},
limit = limit,
offset = offset,
with_field_config = 0
};
request.AddJsonBody(requestBody);
// 执行请求
var response = client.Execute(request);
if (response.IsSuccessful)
{
// 解析响应内容
TblListRoot resp = JsonConvert.DeserializeObject<TblListRoot>(response.Content);
TblListData responseData = resp.data;
var rs = new
{
total = responseData.total,
filtered = responseData.filtered,
hasMore = responseData.has_more,
fields = GetItemsListDic(TblHeader, responseData.items)
};
return rs;
}
else
{
return null;
}
}
catch (Exception ex)
{
return ex.Message;
}
}
/// <summary>
/// 获取元素列表
/// </summary>
private List<TblProject> GetItemsListDic(Dictionary<string, string> TblHeader, List<TblListItem> itemList)
{
List<TblProject> res = [];
try
{
foreach (var item in itemList)
{
TblProject pro = new();
var fls = item.fields;
bool isPass = true;
foreach (var flsitem in fls)
{
if (!TblHeader.ContainsKey(flsitem.Key))
{
continue;
}
if (TblHeader[flsitem.Key].Equals("审批状态"))
{
try
{
var t = Convert.ToString(fls[flsitem.Key][0].name);
if (t != "已通过")
{
isPass = false;
}
}
catch
{
isPass = false;
}
}
if (TblHeader[flsitem.Key].Equals("报备编号"))
{
pro.guid = Convert.ToString(fls[flsitem.Key]);
pro.report_id = Convert.ToString(fls[flsitem.Key]);
}
if (TblHeader[flsitem.Key].Equals("项目名称"))
{
pro.hotel_name = Convert.ToString(fls[flsitem.Key]);
}
if (TblHeader[flsitem.Key].Equals("客房数量"))
{
pro.remarks += "_" + Convert.ToString(fls[flsitem.Key]) + "间客房";
}
if (TblHeader[flsitem.Key].Equals("负责人"))
{
pro.creator = Convert.ToString(fls[flsitem.Key][0].name);
}
if (TblHeader[flsitem.Key].Equals("所属客户"))
{
try
{
pro.remarks += "_" + Convert.ToString(fls[flsitem.Key][0].title);
}
catch { }
}
if (TblHeader[flsitem.Key].Equals("流程结束时间"))
{
try
{
pro.created_at = Convert.ToDateTime(fls[flsitem.Key]);
}
catch { }
}
}
if (isPass && !string.IsNullOrEmpty(pro.hotel_name))
{
pro.remarks = pro.remarks.StartsWith('_') ? pro.remarks[1..] : pro.remarks;
res.Add(pro);
}
}
}
catch (Exception ex)
{
// 异常处理
Console.WriteLine(ex.StackTrace + ex.Message);
}
return res;
}
/// <summary>
/// 获取"项目报备"表中所有数据
/// </summary>
/// <returns>所有数据列表</returns>
[HttpPost]
public ReturnInfo GetAllProjectReportData()
{
try
{
// 1. 获取工作区ID
string space_id = GetHuobanSpaceList();
// 参数验证检查工作区ID是否为空
if (string.IsNullOrEmpty(space_id))
{
return CreateResult(false, "获取工作区ID失败", 400, null);
}
// 2. 获取"项目报备"表格ID
string table_id = GetProjectReportTableId(space_id);
// 参数验证检查表格ID是否为空
if (string.IsNullOrEmpty(table_id))
{
return CreateResult(false, "获取表格ID失败", 400, null);
}
// 3. 获取"项目报备"表格ID
var tableHeader = GetProjectReportTableHeader(table_id);
// 参数验证:检查表格表头是否为空
if (tableHeader.Count <= 0)
{
return CreateResult(false, "获取表格表头失败", 400, null);
}
int limit = 20;
int offset = 0;
bool stopFetching = false;
int totalAdded = 0;
List<TblProject> allItems = new List<TblProject>();
while (!stopFetching)
{
// 4. 查询"项目报备"数据列表
dynamic data = QueryProjectReportData(table_id, tableHeader, limit, offset);
// 结果验证:检查数据是否获取成功
if (data == null)
{
return CreateResult(false, "获取数据失败", 500, null);
}
List<TblProject> items = data.fields;
if (items == null || items.Count == 0) break;
foreach (var item in items)
{
if (CheckProjectExists(item.report_id))
{
stopFetching = true;
break;
}
// Insert
WebProjectAdd(item);
totalAdded++;
//allItems.Add(item);
}
if (stopFetching) break;
if ((bool)data.hasMore == false) break;
offset += limit;
}
// 4. 返回成功结果
return CreateResult(true, $"同步完成,新增 {totalAdded} 条记录", 200/*, allItems*/);
}
catch (Exception ex)
{
// 异常处理:返回包含异常信息的错误结果
return CreateResult(false, $"发生异常: {ex.Message}", 500, ex.ToString());
}
}
#region
/// <summary>
/// 检查项目是否存在
/// </summary>
private bool CheckProjectExists(string report_id)
{
string sql = "SELECT count(1) as count FROM `cdr_library`.`tbl_web_project` WHERE report_id = @report_id AND is_valid = 1";
var parameters = new[] { new MySqlParameter("@report_id", report_id) };
var res = ExecuteQuery(sql, parameters);
if (res.isok && res.response != null)
{
try
{
var json = JArray.Parse(res.response.ToString());
if (json.Count > 0 && json[0]["count"] != null)
{
return Convert.ToInt32(json[0]["count"]) > 0;
}
}
catch { }
}
return false;
}
/// <summary>
/// 添加项目到数据库
/// </summary>
private ReturnInfo WebProjectAdd(TblProject project)
{
string sql = @"
INSERT INTO `cdr_library`.`tbl_web_project`
(report_id, hotel_name, room_type_count, room_data_json, remarks, creator, created_at, is_valid, guid)
VALUES (@report_id, @hotel_name, @room_type_count, @room_data_json, @remarks, @creator, @created_at, 1, @guid)";
var parameters = new[]
{
new MySqlParameter("@report_id", project.report_id ?? (object)DBNull.Value),
new MySqlParameter("@hotel_name", project.hotel_name ?? (object)DBNull.Value),
new MySqlParameter("@room_type_count", project.room_type_count),
new MySqlParameter("@room_data_json", project.room_data_json ?? (object)DBNull.Value),
new MySqlParameter("@remarks", project.remarks ?? (object)DBNull.Value),
new MySqlParameter("@creator", project.creator ?? (object)DBNull.Value),
new MySqlParameter("@created_at", project.created_at),
new MySqlParameter("@guid", project.guid ?? Guid.NewGuid().ToString("N"))
};
return ExecuteNonQueryWithGuid(sql, parameters);
}
/// <summary>
/// 通用查询执行方法(参数化版本)
/// </summary>
private ReturnInfo ExecuteQuery(string sql, MySqlParameter[] parameters = null)
{
try
{
using var conn = new MySqlConnection(ReadConfig.Instance.MySQLConnectionString);
conn.Open();
using var cmd = new MySqlCommand(sql, conn);
if (parameters != null)
{
cmd.Parameters.AddRange(parameters);
}
using var adapter = new MySqlDataAdapter(cmd);
var ds = new DataSet();
adapter.Fill(ds);
if (ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
{
return new ReturnInfo
{
isok = true,
message = "查询成功,但未返回数据",
status = 200,
response = null
};
}
return new ReturnInfo
{
isok = true,
message = "查询成功",
status = 200,
response = Newtonsoft.Json.JsonConvert.SerializeObject(ds.Tables[0])
};
}
catch (Exception ex)
{
return new ReturnInfo
{
isok = false,
message = ex.Message,
status = 500,
response = null
};
}
}
/// <summary>
/// 通用增删改执行方法参数化版本返回GUID
/// </summary>
private ReturnInfo ExecuteNonQueryWithGuid(string sql, MySqlParameter[] parameters, string guid = null)
{
try
{
using var conn = new MySqlConnection(ReadConfig.Instance.MySQLConnectionString);
conn.Open();
using var cmd = new MySqlCommand(sql, conn);
if (parameters != null)
{
cmd.Parameters.AddRange(parameters);
}
int affectedRows = cmd.ExecuteNonQuery();
if (affectedRows > 0)
{
return new ReturnInfo
{
isok = true,
message = "操作成功",
status = 200,
response = guid ?? GetGuidFromParameters(parameters) ?? "操作完成"
};
}
return new ReturnInfo
{
isok = false,
message = "操作未影响任何数据",
status = 400,
response = null
};
}
catch (Exception ex)
{
return new ReturnInfo
{
isok = false,
message = ex.Message,
status = 500,
response = null
};
}
}
/// <summary>
/// 从参数中提取GUID值
/// </summary>
private string GetGuidFromParameters(MySqlParameter[] parameters)
{
if (parameters == null) return null;
var guidParam = parameters.FirstOrDefault(p => p.ParameterName == "@guid");
return guidParam?.Value?.ToString();
}
#endregion
}
public class TblRoot
{
public int code { get; set; }
public string message { get; set; }
public TblData data { get; set; }
}
public class TblData
{
public TblHeader table { get; set; }
}
public class TblHeader
{
public string table_id { get; set; }
public string name { get; set; }
public string alias { get; set; }
public string space_id { get; set; }
public string created_on { get; set; }
public List<dynamic> fields { get; set; }
}
public class TblListRoot
{
public int code { get; set; }
public string message { get; set; }
public TblListData data { get; set; }
public object meta { get; set; }
}
public class TblListData
{
public int total { get; set; }
public int filtered { get; set; }
public bool has_more { get; set; }
public List<TblListItem> items { get; set; }
}
public class TblListItem
{
public string item_id { get; set; }
public string title { get; set; }
public Dictionary<string, dynamic> fields { get; set; }
public object created_by { get; set; }
public string created_on { get; set; }
public object updated_by { get; set; }
public string updated_on { get; set; }
}
public class TblProject
{
public string report_id { get; set; }
public string hotel_name { get; set; }
public int room_type_count { get; set; }
public string room_data_json { get; set; }
public string? remarks { get; set; }
public string creator { get; set; }
public DateTime created_at { get; set; }
public bool is_valid { get; set; }
public string? guid { get; set; }
public TblProject()
{
this.is_valid = true;
this.room_type_count = 1;
this.room_data_json = "[]";
}
}
}

View File

@@ -1,10 +1,18 @@
using BLW_Log.Models;
using Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Asn1.Ocsp;
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace BLW_Log.Controllers
{
@@ -13,10 +21,14 @@ namespace BLW_Log.Controllers
public class PanelSelectionController : ControllerBase
{
public readonly IMemoryCache _memoryCache;
public PanelSelectionController(IMemoryCache memoryCache)
private readonly IWebHostEnvironment _webHostEnvironment;
public PanelSelectionController(IMemoryCache memoryCache, IWebHostEnvironment webHostEnvironment)
{
this._memoryCache = memoryCache;
this._webHostEnvironment = webHostEnvironment;
}
#region
/// <summary>
/// 查看预览图
@@ -26,8 +38,24 @@ namespace BLW_Log.Controllers
{
try
{
const string noticeId = "CellCorelDRAW";
CSRedisCacheHelper.Publish(noticeId, Newtonsoft.Json.JsonConvert.SerializeObject(request));
// 记录日志
LogOperation(request.User, "SendToCDR", request.ProjectName, request.PictureNum, request);
bool success = PublishToRedis(new RedisInfo
{
Type = "CellCorelDRAW",
ObjToRedis = new CellCorelDRAW() { MsgType = 1, MsgNode = request }
});
if (!success)
{
return new ReturnInfo
{
isok = false,
message = "发送到Redis失败",
status = 500,
response = null
};
}
DateTime startTime = DateTime.Now;
Dictionary<string, string> pcn = new()
@@ -57,6 +85,7 @@ namespace BLW_Log.Controllers
}
}
#endregion
#region
@@ -100,7 +129,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery("SELECT * FROM `cdr_library`.`tbl_cdr_file`");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -119,7 +148,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery("SELECT * FROM `cdr_library`.`tbl_cdr_file` WHERE PreviewPath IS NULL");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
@@ -140,7 +169,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($@"SELECT DISTINCT f.* FROM `cdr_library`.`tbl_cdr_file` f INNER JOIN `cdr_library`.`tbl_iconlibrary` i ON f.ID = i.FID WHERE i.IconType = 1 AND f.PreviewPath IS NULL");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
@@ -162,7 +191,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_model` WHERE FID = {Info.FID}");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -188,7 +217,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_pattern` WHERE FID = {Info.FID}");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -215,7 +244,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_trench` WHERE MID = {Info.MID}");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -236,7 +265,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_location` WHERE PID = {Info.PID}");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -257,7 +286,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_iconlibrary` WHERE IconType = 1");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -277,7 +306,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_iconlibrary` WHERE IconType = 2");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -297,7 +326,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_iconlibrary` WHERE IconType = 3");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -317,7 +346,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_iconlibrary` WHERE IconType = 4");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -337,7 +366,7 @@ namespace BLW_Log.Controllers
else
{
var rs = ExecuteQuery($"SELECT * FROM `cdr_library`.`tbl_font`");
_memoryCache.Set(key, rs, TimeSpan.FromHours(1));
_memoryCache.Set(key, rs, TimeSpan.FromMinutes(2));
return rs;
}
}
@@ -354,9 +383,9 @@ namespace BLW_Log.Controllers
{
string sql = @"
INSERT INTO `cdr_library`.`tbl_web_log`
(username, action_time, action_type, hotel_name, target_type, method, target_id, user_ip, user_location, user_agent, is_valid, guid)
VALUES (@username, @action_time, @action_type, @hotel_name, @target_type, @method, @target_id, @user_ip, @user_location, @user_agent, 1, @guid)";
(username, action_time, action_type, hotel_name, target_type, method, target_id, user_ip, user_location, user_agent, is_valid, operation)
VALUES (@username, @action_time, @action_type, @hotel_name, @target_type, @method, @target_id, @user_ip, @user_location, @user_agent, 1, @operation)";
var parameters = new[]
{
new MySqlParameter("@username", log.username ?? (object)DBNull.Value),
@@ -369,7 +398,7 @@ namespace BLW_Log.Controllers
new MySqlParameter("@user_ip", log.user_ip ?? (object)DBNull.Value),
new MySqlParameter("@user_location", log.user_location ?? (object)DBNull.Value),
new MySqlParameter("@user_agent", log.user_agent ?? (object)DBNull.Value),
new MySqlParameter("@guid", Guid.NewGuid().ToString("N"))
new MySqlParameter("@operation", log.operation ?? (object)DBNull.Value)
};
return ExecuteNonQueryWithGuid(sql, parameters);
@@ -382,8 +411,8 @@ namespace BLW_Log.Controllers
UPDATE `cdr_library`.`tbl_web_log` SET
username=@username, action_time=@action_time, action_type=@action_type,
hotel_name=@hotel_name, target_type=@target_type, method=@method,
target_id=@target_id, user_ip=@user_ip, user_location=@user_location, user_agent=@user_agent
WHERE guid=@guid";
target_id=@target_id, user_ip=@user_ip, user_location=@user_location, user_agent=@user_agent, operation=@operation
WHERE id=@id";
var parameters = new[]
{
@@ -397,22 +426,24 @@ namespace BLW_Log.Controllers
new MySqlParameter("@user_ip", log.user_ip ?? (object)DBNull.Value),
new MySqlParameter("@user_location", log.user_location ?? (object)DBNull.Value),
new MySqlParameter("@user_agent", log.user_agent ?? (object)DBNull.Value),
new MySqlParameter("@guid", log.guid ?? (object)DBNull.Value)
new MySqlParameter("@operation", log.operation ?? (object)DBNull.Value)
};
return ExecuteNonQueryWithGuid(sql, parameters, log.guid);
return ExecuteNonQueryWithGuid(sql, parameters, log.id.ToString());
}
[HttpPost]
public ReturnInfo WebLogDelete([FromBody] string guid)
public ReturnInfo WebLogDelete([FromBody] string id)
{
string sql = "UPDATE `cdr_library`.`tbl_web_log` SET is_valid=0 WHERE guid=@guid";
var parameter = new MySqlParameter("@guid", guid ?? (object)DBNull.Value);
return ExecuteNonQueryWithGuid(sql, new[] { parameter }, guid);
// tbl_web_log identifies rows by `id` (bigint), not `guid`.
if (!long.TryParse(id, out long idVal))
{
return new ReturnInfo { isok = false, message = "Invalid id parameter", status = 400, response = null };
}
string sql = "UPDATE `cdr_library`.`tbl_web_log` SET is_valid=0 WHERE id=@id";
var parameter = new MySqlParameter("@id", idVal);
return ExecuteNonQueryWithGuid(sql, new[] { parameter }, id);
}
#endregion
#region tbl_web_panel_list
[HttpPost]
public ReturnInfo WebPanelListQuery() => ExecuteQuery("SELECT * FROM `cdr_library`.`tbl_web_panel_list` WHERE is_valid = 1");
@@ -422,10 +453,10 @@ namespace BLW_Log.Controllers
string sql = @"
INSERT INTO `cdr_library`.`tbl_web_panel_list`
(panel_list_name, gang_series, model_type, gang_material_id, panel_count,
panel_info_json, logo_json, cdr_filename, thumbnail_large,
carving_quantity, position, carving_filename, design_status, panel_info_json, logo_json, cdr_filename, thumbnail_large,
thumbnail_small, erp_part_number, remarks, created_at, is_valid, guid)
VALUES (@panel_list_name, @gang_series, @model_type, @gang_material_id, @panel_count,
@panel_info_json, @logo_json, @cdr_filename, @thumbnail_large,
@carving_quantity, @position, @carving_filename, @design_status, @panel_info_json, @logo_json, @cdr_filename, @thumbnail_large,
@thumbnail_small, @erp_part_number, @remarks, @created_at, 1, @guid)";
var parameters = new[]
@@ -435,6 +466,10 @@ namespace BLW_Log.Controllers
new MySqlParameter("@model_type", panel.model_type ?? (object)DBNull.Value),
new MySqlParameter("@gang_material_id", panel.gang_material_id ?? (object)DBNull.Value),
new MySqlParameter("@panel_count", panel.panel_count ?? (object)DBNull.Value),
new MySqlParameter("@carving_quantity", panel.carving_quantity ?? (object)DBNull.Value),
new MySqlParameter("@position", panel.position ?? (object)DBNull.Value),
new MySqlParameter("@carving_filename", panel.carving_filename ?? (object)DBNull.Value),
new MySqlParameter("@design_status", panel.design_status ?? (object)DBNull.Value),
new MySqlParameter("@panel_info_json", panel.panel_info_json ?? (object)DBNull.Value),
new MySqlParameter("@logo_json", panel.logo_json ?? (object)DBNull.Value),
new MySqlParameter("@cdr_filename", panel.cdr_filename ?? (object)DBNull.Value),
@@ -456,11 +491,11 @@ namespace BLW_Log.Controllers
UPDATE `cdr_library`.`tbl_web_panel_list` SET
panel_list_name=@panel_list_name, gang_series=@gang_series,
model_type=@model_type, gang_material_id=@gang_material_id,
panel_count=@panel_count, panel_info_json=@panel_info_json,
logo_json=@logo_json, cdr_filename=@cdr_filename,
panel_count=@panel_count, carving_quantity=@carving_quantity, position=@position,
carving_filename=@carving_filename, design_status=@design_status, panel_info_json=@panel_info_json, logo_json=@logo_json, cdr_filename=@cdr_filename,
thumbnail_large=@thumbnail_large, thumbnail_small=@thumbnail_small,
erp_part_number=@erp_part_number, remarks=@remarks
WHERE guid=@guid";
WHERE guid=@guid;";
var parameters = new[]
{
@@ -469,6 +504,10 @@ namespace BLW_Log.Controllers
new MySqlParameter("@model_type", panel.model_type ?? (object)DBNull.Value),
new MySqlParameter("@gang_material_id", panel.gang_material_id ?? (object)DBNull.Value),
new MySqlParameter("@panel_count", panel.panel_count ?? (object)DBNull.Value),
new MySqlParameter("@carving_quantity", panel.carving_quantity ?? (object)DBNull.Value),
new MySqlParameter("@position", panel.position ?? (object)DBNull.Value),
new MySqlParameter("@carving_filename", panel.carving_filename ?? (object)DBNull.Value),
new MySqlParameter("@design_status", panel.design_status ?? (object)DBNull.Value),
new MySqlParameter("@panel_info_json", panel.panel_info_json ?? (object)DBNull.Value),
new MySqlParameter("@logo_json", panel.logo_json ?? (object)DBNull.Value),
new MySqlParameter("@cdr_filename", panel.cdr_filename ?? (object)DBNull.Value),
@@ -545,7 +584,7 @@ namespace BLW_Log.Controllers
}
[HttpPost]
public ReturnInfo WebPanelUnitUpdate([FromBody] TblWebPanelUnit unit)
public async Task<ReturnInfo> WebPanelUnitUpdate([FromBody] TblWebPanelUnit unit)
{
string sql = @"
UPDATE `cdr_library`.`tbl_web_panel_unit` SET
@@ -609,7 +648,7 @@ namespace BLW_Log.Controllers
{
new MySqlParameter("@guid_pattern", $"%{unit.guid}%")
};
SetProjectUpdateCdr(new QueryInfo { GUID = unit.project_guid });
ExecuteNonQueryWithGuid(updateSql, updateParameters);
}
}
@@ -780,8 +819,8 @@ namespace BLW_Log.Controllers
{
string sql = @"
INSERT INTO `cdr_library`.`tbl_web_project`
(report_id, hotel_name, room_type_count, room_data_json, remarks, creator, created_at, is_valid, guid)
VALUES (@report_id, @hotel_name, @room_type_count, @room_data_json, @remarks, @creator, @created_at, 1, @guid)";
(report_id, hotel_name, room_type_count, room_data_json, remarks, creator, created_at, is_valid, guid, edit_status, cdr_filename)
VALUES (@report_id, @hotel_name, @room_type_count, @room_data_json, @remarks, @creator, @created_at, 1, @guid, @edit_status, @cdr_filename)";
var parameters = new[]
{
@@ -792,19 +831,41 @@ namespace BLW_Log.Controllers
new MySqlParameter("@remarks", project.remarks ?? (object)DBNull.Value),
new MySqlParameter("@creator", project.creator),
new MySqlParameter("@created_at", project.created_at),
new MySqlParameter("@guid", Guid.NewGuid().ToString("N"))
new MySqlParameter("@guid", Guid.NewGuid().ToString("N")),
new MySqlParameter("@edit_status", project.edit_status ?? (object)DBNull.Value),
new MySqlParameter("@cdr_filename", project.cdr_filename ?? (object)DBNull.Value)
};
return ExecuteNonQueryWithGuid(sql, parameters);
}
/// <summary>
/// 清空项目的编辑状态和cdr文件名
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public ReturnInfo SetProjectUpdateCdr([FromBody] QueryInfo info)
{
string sql = @"
UPDATE `cdr_library`.`tbl_web_project` SET
edit_status='', cdr_filename=''
WHERE guid=@guid";
var parameters = new[]
{
new MySqlParameter("@guid", info.GUID ?? (object)DBNull.Value)
};
return ExecuteNonQueryWithGuid(sql, parameters, info.GUID);
}
[HttpPost]
public ReturnInfo WebProjectUpdate([FromBody] TblWebProject project)
{
string sql = @"
UPDATE `cdr_library`.`tbl_web_project` SET
report_id=@report_id, hotel_name=@hotel_name, room_type_count=@room_type_count,
room_data_json=@room_data_json, remarks=@remarks, creator=@creator
room_data_json=@room_data_json, remarks=@remarks, creator=@creator,
edit_status=@edit_status, cdr_filename=@cdr_filename
WHERE guid=@guid";
var parameters = new[]
@@ -815,6 +876,8 @@ namespace BLW_Log.Controllers
new MySqlParameter("@room_data_json", project.room_data_json),
new MySqlParameter("@remarks", project.remarks ?? (object)DBNull.Value),
new MySqlParameter("@creator", project.creator),
new MySqlParameter("@edit_status", project.edit_status ?? (object)DBNull.Value),
new MySqlParameter("@cdr_filename", project.cdr_filename ?? (object)DBNull.Value),
new MySqlParameter("@guid", project.guid ?? (object)DBNull.Value)
};
@@ -828,6 +891,264 @@ namespace BLW_Log.Controllers
var parameter = new MySqlParameter("@guid", guid ?? (object)DBNull.Value);
return ExecuteNonQueryWithGuid(sql, new[] { parameter }, guid);
}
[HttpPost]
public ReturnInfo GetWebProject([FromBody] QueryInfo info)
{
string sql = "SELECT * FROM `cdr_library`.`tbl_web_project` WHERE guid=@Guid;";
var parameter = new MySqlParameter("@guid", info.GUID ?? (object)DBNull.Value);
return ExecuteQuery(sql, new[] { parameter });
}
/// <summary>
/// 发送CDR文件的路径表单到Redis生成队列
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public ReturnInfo GetAllProjectCDR([FromBody] QueryInfo info)
{
string sql = @"SELECT DISTINCT p.hotel_name, rt.room_name, pnl.model_type, pnl.gang_series,
pnl.panel_list_name,pnl.cdr_filename,pnl.position,pnl.carving_quantity,pnl.thumbnail_large,pnl.carving_filename
FROM `cdr_library`.`tbl_web_project` p
JOIN `cdr_library`.`tbl_web_room_type` rt ON p.room_data_json LIKE CONCAT('%', rt.guid, '%')
JOIN `cdr_library`.`tbl_web_panel_list` pnl ON rt.panel_group_count LIKE CONCAT('%', pnl.guid, '%')
WHERE p.guid=@guid ORDER BY rt.room_name;";
var parameter = new MySqlParameter("@guid", info.GUID ?? (object)DBNull.Value);
// 将当前项目状态置为生成中,避免重复触发或并发问题
string updateSql = "UPDATE `cdr_library`.`tbl_web_project` SET edit_status='生成中' WHERE guid=@guid";
ExecuteNonQueryWithGuid(updateSql, new[] { parameter }, info.GUID);
var eq = ExecuteQuery(sql, new[] { parameter });
// 获取tbl_web_project的整行数据
string projectSql = "SELECT * FROM `cdr_library`.`tbl_web_project` WHERE guid = @guid";
var projectQueryResult = ExecuteQuery(projectSql, new[] { parameter });
string hotel_name = JsonConvert.DeserializeObject<DataTable>(projectQueryResult.response.ToString()).Rows[0]["hotel_name"].ToString();
// 解析两个查询结果如果有为JToken以便合并发送到Redis
JToken? panelsToken = null;
JToken? projectToken = null;
try
{
if (eq != null && eq.response != null) panelsToken = JToken.Parse(eq.response!.ToString());
}
catch { panelsToken = null; }
try
{
if (projectQueryResult != null && projectQueryResult.response != null) projectToken = JToken.Parse(projectQueryResult.response!.ToString());
}
catch { projectToken = null; }
string picNum = Guid.NewGuid().ToString("N");
var combinedPayload = new
{
project = projectToken,
panels = panelsToken,
picNum
};
bool success = PublishToRedis(new RedisInfo
{
Type = "CellCorelDRAW",
ObjToRedis = new CellCorelDRAW() { MsgType = 2, MsgNode = combinedPayload }
});
Dictionary<string, string> pcn = new()
{
{ picNum, info.GUID ?? string.Empty }
};
CSRedisCacheHelper.LPush("PicNumList", pcn);
LogOperation(info.UserName, "GetAllProjectCDR", hotel_name, info.GUID, info);
return new() { isok = success, message = success ? "已提交到生成队列" : "提交到生成队列失败", status = success ? 200 : 500, response = null };
}
/// <summary>
/// 获取下载CDR文件的路径表单
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public ReturnInfo GetWebProjectCDR([FromBody] QueryInfo info)
{
string sql = @"SELECT DISTINCT p.hotel_name, rt.room_name, pnl.model_type, pnl.gang_series,
pnl.panel_list_name,pnl.cdr_filename,pnl.position,pnl.carving_quantity,pnl.thumbnail_large,pnl.carving_filename
FROM `cdr_library`.`tbl_web_project` p
JOIN `cdr_library`.`tbl_web_room_type` rt ON p.room_data_json LIKE CONCAT('%', rt.guid, '%')
JOIN `cdr_library`.`tbl_web_panel_list` pnl ON rt.panel_group_count LIKE CONCAT('%', pnl.guid, '%')
WHERE p.guid=@guid;";
var parameter = new MySqlParameter("@guid", info.GUID ?? (object)DBNull.Value);
return ExecuteQuery(sql, new[] { parameter });
}
/// <summary>
/// 下载文件
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> DownloadProjectCDR([FromBody] QueryInfo info)
{
try
{
string hotel_name = "";
string sql = @"SELECT DISTINCT p.hotel_name, rt.room_name, pnl.model_type, pnl.gang_series,
pnl.panel_list_name,pnl.cdr_filename,pnl.position,pnl.carving_quantity,pnl.thumbnail_large,pnl.carving_filename
FROM `cdr_library`.`tbl_web_project` p
JOIN `cdr_library`.`tbl_web_room_type` rt ON p.room_data_json LIKE CONCAT('%', rt.guid, '%')
JOIN `cdr_library`.`tbl_web_panel_list` pnl ON rt.panel_group_count LIKE CONCAT('%', pnl.guid, '%')
WHERE p.guid=@guid;";
var parameter = new MySqlParameter("@guid", info.GUID ?? (object)DBNull.Value);
var queryResult = ExecuteQuery(sql, new[] { parameter });
if (!queryResult.isok || queryResult.response == null)
{
return NotFound("未找到相关数据");
}
var dt = JsonConvert.DeserializeObject<DataTable>(queryResult.response.ToString());
if (dt == null || dt.Rows.Count == 0)
{
return NotFound("未找到相关数据");
}
// 先获取项目级的cdr文件路径确认存在否则直接返回错误
var projectResult = GetWebProject(info);
if (!projectResult.isok || projectResult.response == null)
{
return NotFound("未找到项目数据");
}
var projectDt = JsonConvert.DeserializeObject<DataTable>(projectResult.response.ToString());
if (projectDt == null || projectDt.Rows.Count == 0)
{
return NotFound("未找到项目数据");
}
string projectCdr = projectDt.Rows[0]["cdr_filename"]?.ToString()?.Trim() ?? string.Empty;
if (string.IsNullOrWhiteSpace(projectCdr))
{
return BadRequest("总路径不存在");
}
// 校验每条记录的必要文件是否已生成thumbnail_large, carving_filename, cdr_filename
foreach (DataRow row in dt.Rows)
{
string thumbnail = row["thumbnail_large"]?.ToString()?.Trim() ?? string.Empty;
string carving = row["carving_filename"]?.ToString()?.Trim() ?? string.Empty;
string cdr = row["cdr_filename"]?.ToString()?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(thumbnail) || string.IsNullOrEmpty(carving) || string.IsNullOrEmpty(cdr))
{
// 如果任一文件为空,则直接返回错误提示
return BadRequest("有图片尚未生成");
}
}
var memoryStream = new MemoryStream();
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var dateStr = DateTime.Now.ToString("yyyyMMdd");
var usedNames = new HashSet<string>();
foreach (DataRow row in dt.Rows)
{
hotel_name = row["hotel_name"]?.ToString() ?? "";
string carving_quantity = row["carving_quantity"]?.ToString() ?? "0";
string room_name = row["room_name"]?.ToString() ?? "";
string panel_list_name = row["panel_list_name"]?.ToString() ?? "";
string gang_series = row["gang_series"]?.ToString() ?? "";
string model_type = row["model_type"]?.ToString() ?? "";
string formatted_model_type = FormatNameFront12(model_type);
string baseFileName = $"数量{carving_quantity}_{hotel_name}_{room_name}_{panel_list_name}_{gang_series}_{formatted_model_type}_{dateStr}";
// CDR
string cdrPath = "\\PanelSelectionPic\\" + row["cdr_filename"]?.ToString();
if (!string.IsNullOrWhiteSpace(cdrPath))
{
AddFileToZip(archive, _webHostEnvironment.WebRootPath, cdrPath, $"CDR/{baseFileName}.cdr", usedNames);
}
// PNG
string pngPath = "\\PanelSelectionPic\\" + row["thumbnail_large"]?.ToString();
if (!string.IsNullOrWhiteSpace(pngPath))
{
AddFileToZip(archive, _webHostEnvironment.WebRootPath, pngPath, $"雕刻/{baseFileName}.png", usedNames);
}
// PLT
string pltPath = "\\PanelSelectionPic\\" + row["carving_filename"]?.ToString();
if (!string.IsNullOrWhiteSpace(pltPath))
{
AddFileToZip(archive, _webHostEnvironment.WebRootPath, pltPath, $"雕刻/{baseFileName}.plt", usedNames);
}
}
// 添加整体项目的 CDR 文件到 CDR/ 目录下
if (!string.IsNullOrWhiteSpace(projectCdr))
{
AddFileToZip(archive, _webHostEnvironment.WebRootPath, "\\PanelSelectionPic\\" + projectCdr, $"CDR/{hotel_name}_总预览图.cdr", usedNames);
}
}
// 记录日志
LogOperation(info.UserName, "DownloadProjectCDR", hotel_name, info.GUID, info);
memoryStream.Position = 0;
return File(memoryStream, "application/zip", $"{hotel_name}_{DateTime.Now:yyyyMMddHHmmss}.zip");
}
catch (Exception ex)
{
return StatusCode(500, $"打包下载失败: {ex.Message}");
}
}
private string FormatNameFront12(string model_type)
{
if (string.IsNullOrEmpty(model_type)) return "";
var parts = model_type.Split('_');
if (parts.Length <= 3) return "";
return string.Join("_", parts.Skip(1).Take(parts.Length - 3));
}
private void AddFileToZip(ZipArchive archive, string webRootPath, string filePath, string entryPath, HashSet<string> usedNames)
{
try
{
// Handle duplicates
string finalEntryPath = entryPath;
int counter = 1;
while (usedNames.Contains(finalEntryPath))
{
string ext = Path.GetExtension(entryPath);
string nameWithoutExt = Path.GetFileNameWithoutExtension(entryPath);
string dir = Path.GetDirectoryName(entryPath)?.Replace("\\", "/") ?? "";
if (!string.IsNullOrEmpty(dir)) dir += "/";
finalEntryPath = $"{dir}{nameWithoutExt}_{counter}{ext}";
counter++;
}
usedNames.Add(finalEntryPath);
// Resolve physical path
if (filePath.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
if (Uri.TryCreate(filePath, UriKind.Absolute, out Uri uri))
{
filePath = uri.LocalPath;
}
}
filePath = filePath.TrimStart('/', '\\');
string physicalPath = Path.Combine(webRootPath, filePath);
if (System.IO.File.Exists(physicalPath))
{
archive.CreateEntryFromFile(physicalPath, finalEntryPath);
}
}
catch
{
// Ignore errors for individual files
}
}
#endregion
#region tbl_web_room_type
@@ -895,7 +1216,7 @@ namespace BLW_Log.Controllers
{
var generatingItems = new
{
PanelLists = ExecuteQuery("SELECT guid, thumbnail_large FROM `cdr_library`.`tbl_web_panel_list` WHERE thumbnail_small = '生成中' AND is_valid = 1"),
PanelLists = ExecuteQuery("SELECT guid, thumbnail_large FROM `cdr_library`.`tbl_web_panel_list` WHERE design_status = '生成中' AND is_valid = 1"),
PanelUnits = ExecuteQuery("SELECT guid, thumbnail_large FROM `cdr_library`.`tbl_web_panel_unit` WHERE design_status = '生成中' AND is_valid = 1")
};
@@ -920,7 +1241,59 @@ namespace BLW_Log.Controllers
}
#endregion
#region
#region
/// <summary>
/// 记录操作日志
/// </summary>
private void LogOperation(string username, string actionType, string hotelName, string targetId, object operationData)
{
try
{
string userIp = HttpContext.Connection.RemoteIpAddress?.ToString();
string userAgent = Request.Headers["User-Agent"].ToString();
// Ensure required fields are not null to satisfy DB constraints
var safeUsername = string.IsNullOrEmpty(username) ? (User?.Identity?.Name ?? "system") : username;
var log = new TblWebLog
{
username = safeUsername,
action_type = actionType,
hotel_name = hotelName,
target_id = targetId,
operation = JsonConvert.SerializeObject(operationData),
user_ip = userIp,
user_agent = userAgent,
user_location = "", // 默认空字符串
method = actionType, // 使用actionType作为method
target_type = "Project" // 默认为Project可根据需要调整
};
WebLogAdd(log);
}
catch (Exception ex)
{
// 记录日志失败不应影响主流程,仅打印错误
Console.WriteLine($"记录日志失败: {ex.Message}");
}
}
/// <summary>
/// Publish到Redis
/// </summary>
public bool PublishToRedis(RedisInfo request)
{
try
{
CSRedisCacheHelper.Publish(request.Type, Newtonsoft.Json.JsonConvert.SerializeObject(request.ObjToRedis));
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 通用查询执行方法(参数化版本)
/// </summary>
@@ -1061,6 +1434,7 @@ namespace BLW_Log.Controllers
public int? PID { get; set; }
public int? MID { get; set; }
public string? GUID { get; set; }
public string? UserName { get; set; }
}
public class TblWebLog
{
@@ -1071,12 +1445,12 @@ namespace BLW_Log.Controllers
public string? hotel_name { get; set; }
public string? target_type { get; set; }
public string? method { get; set; }
public long? target_id { get; set; }
public string? target_id { get; set; }
public string? user_ip { get; set; }
public string? user_location { get; set; }
public string? user_agent { get; set; }
public bool? is_valid { get; set; }
public string? guid { get; set; }
public string? operation { get; set; }
public TblWebLog()
{
this.action_time = DateTime.Now;
@@ -1091,6 +1465,10 @@ namespace BLW_Log.Controllers
public string? gang_series { get; set; }
public string? model_type { get; set; }
public int? panel_count { get; set; } // 新增字段
public int? carving_quantity { get; set; } // 新增字段:雕刻数量
public string? position { get; set; } // 新增字段:位置
public string? carving_filename { get; set; } // 新增字段:雕刻图
public string? design_status { get; set; } // 新增字段:设计状态
public long? gang_material_id { get; set; }
public string? panel_info_json { get; set; }
public string? logo_json { get; set; }
@@ -1159,6 +1537,8 @@ namespace BLW_Log.Controllers
public DateTime created_at { get; set; }
public bool is_valid { get; set; }
public string? guid { get; set; }
public string? edit_status { get; set; }
public string? cdr_filename { get; set; }
public TblWebProject()
{
this.created_at = DateTime.Now;
@@ -1209,5 +1589,4 @@ public class CopyPanelUnitRequest
/// </summary>
public string NewProjectGuid { get; set; }
}
#endregion