333
This commit is contained in:
parent
0708675fb5
commit
08aaf97f3d
|
|
@ -311,7 +311,7 @@ namespace WorkCameraExport.Tests
|
||||||
Address = $"地址{i}",
|
Address = $"地址{i}",
|
||||||
Content = $"工作内容{i}",
|
Content = $"工作内容{i}",
|
||||||
StatusName = "正常",
|
StatusName = "正常",
|
||||||
Workers = new List<WorkerDto> { new WorkerDto { Id = i, WorkerName = $"工人{i}" } },
|
Workers = new List<string> { $"工人{i}" },
|
||||||
Images = new List<string>(),
|
Images = new List<string>(),
|
||||||
CreateTime = DateTime.Now.AddDays(-i),
|
CreateTime = DateTime.Now.AddDays(-i),
|
||||||
UpdateTime = DateTime.Now
|
UpdateTime = DateTime.Now
|
||||||
|
|
@ -331,7 +331,7 @@ namespace WorkCameraExport.Tests
|
||||||
Address = "测试地址",
|
Address = "测试地址",
|
||||||
Content = "测试内容",
|
Content = "测试内容",
|
||||||
StatusName = "正常",
|
StatusName = "正常",
|
||||||
Workers = new List<WorkerDto> { new WorkerDto { Id = 1, WorkerName = "测试工人" } },
|
Workers = new List<string> { "测试工人" },
|
||||||
Images = Enumerable.Range(1, imageCount)
|
Images = Enumerable.Range(1, imageCount)
|
||||||
.Select(i => $"http://test.local/image{i}.jpg")
|
.Select(i => $"http://test.local/image{i}.jpg")
|
||||||
.ToList(),
|
.ToList(),
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ namespace WorkCameraExport.Forms
|
||||||
public void NavigateToMigration()
|
public void NavigateToMigration()
|
||||||
{
|
{
|
||||||
_logService?.Info("导航到数据迁移界面");
|
_logService?.Info("导航到数据迁移界面");
|
||||||
using var form = new MigrationForm(_apiService);
|
using var form = new MigrationForm(_apiService, _logService);
|
||||||
form.ShowDialog(this);
|
form.ShowDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@ namespace WorkCameraExport.Forms
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var migrationForm = new MigrationForm(_apiService);
|
using var migrationForm = new MigrationForm(_apiService, null);
|
||||||
migrationForm.ShowDialog(this);
|
migrationForm.ShowDialog(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,8 @@ namespace WorkCameraExport.Forms
|
||||||
dgvRecords.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
dgvRecords.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
dgvRecords.Size = new Size(910, 315);
|
dgvRecords.Size = new Size(910, 315);
|
||||||
dgvRecords.TabIndex = 0;
|
dgvRecords.TabIndex = 0;
|
||||||
dgvRecords.CellContentClick += dgvRecords_CellContentClick;
|
dgvRecords.CellValueChanged += dgvRecords_CellValueChanged;
|
||||||
|
dgvRecords.CurrentCellDirtyStateChanged += dgvRecords_CurrentCellDirtyStateChanged;
|
||||||
|
|
||||||
//
|
//
|
||||||
// colSelect
|
// colSelect
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using WorkCameraExport.Models;
|
using WorkCameraExport.Models;
|
||||||
using WorkCameraExport.Services;
|
using WorkCameraExport.Services;
|
||||||
|
using WorkCameraExport.Services.Interfaces;
|
||||||
|
|
||||||
namespace WorkCameraExport.Forms
|
namespace WorkCameraExport.Forms
|
||||||
{
|
{
|
||||||
|
|
@ -10,6 +11,7 @@ namespace WorkCameraExport.Forms
|
||||||
{
|
{
|
||||||
private readonly ApiService _apiService;
|
private readonly ApiService _apiService;
|
||||||
private readonly CosService _cosService;
|
private readonly CosService _cosService;
|
||||||
|
private readonly ILogService? _logService;
|
||||||
private CancellationTokenSource? _migrationCts;
|
private CancellationTokenSource? _migrationCts;
|
||||||
private bool _isMigrating;
|
private bool _isMigrating;
|
||||||
|
|
||||||
|
|
@ -17,11 +19,12 @@ namespace WorkCameraExport.Forms
|
||||||
private List<MigrationRecordDto> _records = new();
|
private List<MigrationRecordDto> _records = new();
|
||||||
private int _totalRecords;
|
private int _totalRecords;
|
||||||
|
|
||||||
public MigrationForm(ApiService apiService)
|
public MigrationForm(ApiService apiService, ILogService? logService = null)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_apiService = apiService;
|
_apiService = apiService;
|
||||||
_cosService = new CosService();
|
_logService = logService;
|
||||||
|
_cosService = new CosService(logService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -69,12 +72,16 @@ namespace WorkCameraExport.Forms
|
||||||
_records.Clear();
|
_records.Clear();
|
||||||
_totalRecords = 0;
|
_totalRecords = 0;
|
||||||
|
|
||||||
|
_logService?.Info("[迁移界面] 开始查询迁移记录");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var query = BuildQuery();
|
var query = BuildQuery();
|
||||||
query.PageNum = 1;
|
query.PageNum = 1;
|
||||||
query.PageSize = 50;
|
query.PageSize = 50;
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移界面] 查询条件: 开始={query.StartDate}, 结束={query.EndDate}, 状态={query.Status}");
|
||||||
|
|
||||||
// 获取所有记录(分页获取)
|
// 获取所有记录(分页获取)
|
||||||
var allRecords = new List<MigrationRecordDto>();
|
var allRecords = new List<MigrationRecordDto>();
|
||||||
int pageNum = 1;
|
int pageNum = 1;
|
||||||
|
|
@ -86,6 +93,7 @@ namespace WorkCameraExport.Forms
|
||||||
|
|
||||||
if (!success || data == null)
|
if (!success || data == null)
|
||||||
{
|
{
|
||||||
|
_logService?.Error($"[迁移界面] 查询失败: {message}");
|
||||||
ShowError(message);
|
ShowError(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -93,6 +101,8 @@ namespace WorkCameraExport.Forms
|
||||||
allRecords.AddRange(data.Result);
|
allRecords.AddRange(data.Result);
|
||||||
_totalRecords = data.TotalNum;
|
_totalRecords = data.TotalNum;
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移界面] 第{pageNum}页获取 {data.Result.Count} 条, 累计 {allRecords.Count}/{_totalRecords}");
|
||||||
|
|
||||||
if (data.Result.Count < 50 || pageNum >= data.TotalPage)
|
if (data.Result.Count < 50 || pageNum >= data.TotalPage)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -123,6 +133,7 @@ namespace WorkCameraExport.Forms
|
||||||
UpdateSelectedCount();
|
UpdateSelectedCount();
|
||||||
lblStatusBar.Text = $"查询完成,共 {_totalRecords} 条记录";
|
lblStatusBar.Text = $"查询完成,共 {_totalRecords} 条记录";
|
||||||
lblStatusBar.ForeColor = Color.Green;
|
lblStatusBar.ForeColor = Color.Green;
|
||||||
|
_logService?.Info($"[迁移界面] 查询完成, 共 {_totalRecords} 条记录");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -188,18 +199,25 @@ namespace WorkCameraExport.Forms
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据网格单元格点击事件
|
/// 数据网格单元格值变更事件(用于复选框)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void dgvRecords_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
private void dgvRecords_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
|
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
|
||||||
{
|
{
|
||||||
// 延迟更新,等待复选框状态变更
|
UpdateSelectedCount();
|
||||||
BeginInvoke(new Action(() =>
|
UpdateMigrateButtonState();
|
||||||
{
|
}
|
||||||
UpdateSelectedCount();
|
}
|
||||||
UpdateMigrateButtonState();
|
|
||||||
}));
|
/// <summary>
|
||||||
|
/// 数据网格当前单元格脏状态变更事件(立即提交复选框编辑)
|
||||||
|
/// </summary>
|
||||||
|
private void dgvRecords_CurrentCellDirtyStateChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (dgvRecords.IsCurrentCellDirty && dgvRecords.CurrentCell is DataGridViewCheckBoxCell)
|
||||||
|
{
|
||||||
|
dgvRecords.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,18 +307,24 @@ namespace WorkCameraExport.Forms
|
||||||
int totalRecords = records.Count;
|
int totalRecords = records.Count;
|
||||||
int processedRecords = 0;
|
int processedRecords = 0;
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移界面] 开始迁移, 共 {totalRecords} 条记录");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取 COS 临时密钥
|
// 获取 COS 临时密钥
|
||||||
lblCurrentRecord.Text = "正在获取 COS 临时密钥...";
|
lblCurrentRecord.Text = "正在获取 COS 临时密钥...";
|
||||||
|
_logService?.Info("[迁移界面] 正在获取 COS 临时密钥...");
|
||||||
var (credSuccess, credMessage, credentials) = await _apiService.GetTempCredentialsAsync();
|
var (credSuccess, credMessage, credentials) = await _apiService.GetTempCredentialsAsync();
|
||||||
|
|
||||||
if (!credSuccess || credentials == null)
|
if (!credSuccess || credentials == null)
|
||||||
{
|
{
|
||||||
|
_logService?.Error($"[迁移界面] 获取 COS 临时密钥失败: {credMessage}");
|
||||||
ShowError($"获取 COS 临时密钥失败: {credMessage}");
|
ShowError($"获取 COS 临时密钥失败: {credMessage}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移界面] COS 临时密钥获取成功, Bucket={credentials.Bucket}, Region={credentials.Region}");
|
||||||
|
|
||||||
// 初始化 COS 服务
|
// 初始化 COS 服务
|
||||||
_cosService.Initialize(credentials);
|
_cosService.Initialize(credentials);
|
||||||
|
|
||||||
|
|
@ -309,6 +333,7 @@ namespace WorkCameraExport.Forms
|
||||||
{
|
{
|
||||||
if (_migrationCts.Token.IsCancellationRequested)
|
if (_migrationCts.Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
_logService?.Info("[迁移界面] 迁移已取消");
|
||||||
lblStatusBar.Text = "迁移已取消";
|
lblStatusBar.Text = "迁移已取消";
|
||||||
lblStatusBar.ForeColor = Color.Orange;
|
lblStatusBar.ForeColor = Color.Orange;
|
||||||
break;
|
break;
|
||||||
|
|
@ -316,6 +341,7 @@ namespace WorkCameraExport.Forms
|
||||||
|
|
||||||
processedRecords++;
|
processedRecords++;
|
||||||
lblCurrentRecord.Text = $"正在迁移记录 {record.Id} ({processedRecords}/{totalRecords})...";
|
lblCurrentRecord.Text = $"正在迁移记录 {record.Id} ({processedRecords}/{totalRecords})...";
|
||||||
|
_logService?.Info($"[迁移界面] 开始迁移记录 {record.Id}, 图片数={record.Images?.Count ?? 0}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -324,23 +350,26 @@ namespace WorkCameraExport.Forms
|
||||||
if (migrationResult)
|
if (migrationResult)
|
||||||
{
|
{
|
||||||
successCount++;
|
successCount++;
|
||||||
|
_logService?.Info($"[迁移界面] 记录 {record.Id} 迁移成功");
|
||||||
UpdateRowStatus(record.Id, "已迁移", Color.Green);
|
UpdateRowStatus(record.Id, "已迁移", Color.Green);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
failCount++;
|
failCount++;
|
||||||
|
_logService?.Warn($"[迁移界面] 记录 {record.Id} 迁移失败");
|
||||||
UpdateRowStatus(record.Id, "迁移失败", Color.Red);
|
UpdateRowStatus(record.Id, "迁移失败", Color.Red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
_logService?.Info("[迁移界面] 迁移操作被取消");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
failCount++;
|
failCount++;
|
||||||
|
_logService?.Error($"[迁移界面] 记录 {record.Id} 迁移异常: {ex.Message}", ex);
|
||||||
UpdateRowStatus(record.Id, "迁移失败", Color.Red);
|
UpdateRowStatus(record.Id, "迁移失败", Color.Red);
|
||||||
System.Diagnostics.Debug.WriteLine($"迁移记录 {record.Id} 失败: {ex.Message}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新进度
|
// 更新进度
|
||||||
|
|
@ -357,6 +386,7 @@ namespace WorkCameraExport.Forms
|
||||||
lblCurrentRecord.Text = $"迁移完成!成功: {successCount}, 失败: {failCount}";
|
lblCurrentRecord.Text = $"迁移完成!成功: {successCount}, 失败: {failCount}";
|
||||||
lblStatusBar.Text = $"迁移完成,成功 {successCount} 条,失败 {failCount} 条";
|
lblStatusBar.Text = $"迁移完成,成功 {successCount} 条,失败 {failCount} 条";
|
||||||
lblStatusBar.ForeColor = failCount > 0 ? Color.Orange : Color.Green;
|
lblStatusBar.ForeColor = failCount > 0 ? Color.Orange : Color.Green;
|
||||||
|
_logService?.Info($"[迁移界面] 迁移完成, 成功={successCount}, 失败={failCount}");
|
||||||
|
|
||||||
MessageBox.Show(
|
MessageBox.Show(
|
||||||
$"迁移完成!\n\n成功: {successCount} 条\n失败: {failCount} 条",
|
$"迁移完成!\n\n成功: {successCount} 条\n失败: {failCount} 条",
|
||||||
|
|
@ -388,9 +418,12 @@ namespace WorkCameraExport.Forms
|
||||||
// 获取需要迁移的图片(未迁移的)
|
// 获取需要迁移的图片(未迁移的)
|
||||||
var imagesToMigrate = record.Images.Where(img => !img.IsMigrated).ToList();
|
var imagesToMigrate = record.Images.Where(img => !img.IsMigrated).ToList();
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id}: 总图片={record.Images?.Count ?? 0}, 待迁移={imagesToMigrate.Count}");
|
||||||
|
|
||||||
if (imagesToMigrate.Count == 0)
|
if (imagesToMigrate.Count == 0)
|
||||||
{
|
{
|
||||||
// 没有需要迁移的图片,直接返回成功
|
// 没有需要迁移的图片,直接返回成功
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id}: 无需迁移的图片, 跳过");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,31 +440,39 @@ namespace WorkCameraExport.Forms
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id} 图片 {imageIndex}/{totalImages}: 开始下载 {image.Url}");
|
||||||
|
|
||||||
// 1. 下载原图片
|
// 1. 下载原图片
|
||||||
var (downloadSuccess, imageData, downloadMessage) =
|
var (downloadSuccess, imageData, downloadMessage) =
|
||||||
await _apiService.DownloadImageAsync(image.Url, cancellationToken);
|
await _apiService.DownloadImageAsync(image.Url, cancellationToken);
|
||||||
|
|
||||||
if (!downloadSuccess || imageData == null)
|
if (!downloadSuccess || imageData == null)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"下载图片失败: {image.Url} - {downloadMessage}");
|
_logService?.Warn($"[迁移] 记录 {record.Id} 图片下载失败: {downloadMessage}, URL={image.Url}");
|
||||||
continue; // 跳过失败的图片,继续处理其他图片
|
continue; // 跳过失败的图片,继续处理其他图片
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id} 图片下载成功, 大小={imageData.Length} bytes");
|
||||||
|
|
||||||
// 2. 生成 COS 路径
|
// 2. 生成 COS 路径
|
||||||
var recordTime = record.RecordTime ?? DateTime.Now;
|
var recordTime = record.RecordTime ?? DateTime.Now;
|
||||||
var fileName = CosService.GenerateFileName(".jpg");
|
var fileName = CosService.GenerateFileName(".jpg");
|
||||||
var cosKey = CosService.GenerateCosKey(recordTime, "当日照片", "", fileName);
|
var cosKey = CosService.GenerateCosKey(recordTime, "当日照片", "", fileName);
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id} 准备上传到 COS, Key={cosKey}");
|
||||||
|
|
||||||
// 3. 上传到 COS
|
// 3. 上传到 COS
|
||||||
var (uploadSuccess, uploadMessage, cosUrl) =
|
var (uploadSuccess, uploadMessage, cosUrl) =
|
||||||
await _cosService.UploadBytesAsync(imageData, cosKey, cancellationToken: cancellationToken);
|
await _cosService.UploadBytesAsync(imageData, cosKey, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
if (!uploadSuccess || string.IsNullOrEmpty(cosUrl))
|
if (!uploadSuccess || string.IsNullOrEmpty(cosUrl))
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"上传图片失败: {uploadMessage}");
|
_logService?.Warn($"[迁移] 记录 {record.Id} 上传COS失败: {uploadMessage}");
|
||||||
continue; // 跳过失败的图片,继续处理其他图片
|
continue; // 跳过失败的图片,继续处理其他图片
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id} 上传COS成功, NewUrl={cosUrl}");
|
||||||
|
|
||||||
// 4. 记录 URL 映射
|
// 4. 记录 URL 映射
|
||||||
urlPairs.Add(new MigrationUrlPair
|
urlPairs.Add(new MigrationUrlPair
|
||||||
{
|
{
|
||||||
|
|
@ -445,11 +486,13 @@ namespace WorkCameraExport.Forms
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"处理图片异常: {image.Url} - {ex.Message}");
|
_logService?.Error($"[迁移] 记录 {record.Id} 处理图片异常: {ex.Message}, URL={image.Url}", ex);
|
||||||
continue; // 跳过失败的图片,继续处理其他图片
|
continue; // 跳过失败的图片,继续处理其他图片
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id}: 成功处理 {urlPairs.Count}/{totalImages} 张图片");
|
||||||
|
|
||||||
// 5. 调用 API 更新 URL
|
// 5. 调用 API 更新 URL
|
||||||
if (urlPairs.Count > 0)
|
if (urlPairs.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -459,16 +502,21 @@ namespace WorkCameraExport.Forms
|
||||||
ImageUrls = urlPairs
|
ImageUrls = urlPairs
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id}: 调用API更新URL, 数量={urlPairs.Count}");
|
||||||
var (updateSuccess, updateMessage) = await _apiService.UpdateMigrationUrlsAsync(updateRequest);
|
var (updateSuccess, updateMessage) = await _apiService.UpdateMigrationUrlsAsync(updateRequest);
|
||||||
|
|
||||||
if (!updateSuccess)
|
if (!updateSuccess)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"更新 URL 失败: {updateMessage}");
|
_logService?.Error($"[迁移] 记录 {record.Id} 更新URL失败: {updateMessage}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[迁移] 记录 {record.Id}: API更新URL成功");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// 如果所有图片都成功迁移,返回成功
|
{
|
||||||
|
_logService?.Warn($"[迁移] 记录 {record.Id}: 没有成功迁移的图片, 不调用更新API");
|
||||||
|
} // 如果所有图片都成功迁移,返回成功
|
||||||
return urlPairs.Count == imagesToMigrate.Count;
|
return urlPairs.Count == imagesToMigrate.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,15 @@ namespace WorkCameraExport.Services
|
||||||
|
|
||||||
if (response.IsSuccess && response.Data != null)
|
if (response.IsSuccess && response.Data != null)
|
||||||
{
|
{
|
||||||
|
// 调试日志:记录反序列化后的 Workers 数据
|
||||||
|
foreach (var record in response.Data.Result.Take(3)) // 只记录前3条
|
||||||
|
{
|
||||||
|
var workersInfo = record.Workers != null
|
||||||
|
? $"Workers数量={record.Workers.Count}, 名称=[{string.Join(", ", record.Workers.Select(w => w.WorkerName ?? "null"))}]"
|
||||||
|
: "Workers=null";
|
||||||
|
_logService?.Info($"[反序列化] 记录ID={record.Id}, {workersInfo}");
|
||||||
|
}
|
||||||
|
|
||||||
return (true, "查询成功", response.Data);
|
return (true, "查询成功", response.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,6 +572,7 @@ namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logService?.Info($"[迁移] 开始查询迁移列表, 页码={query.PageNum}, 状态={query.Status}");
|
||||||
await EnsureTokenValidAsync();
|
await EnsureTokenValidAsync();
|
||||||
var queryParams = BuildQueryString(query);
|
var queryParams = BuildQueryString(query);
|
||||||
var response = await ExecuteWithRetryAsync(() =>
|
var response = await ExecuteWithRetryAsync(() =>
|
||||||
|
|
@ -570,14 +580,16 @@ namespace WorkCameraExport.Services
|
||||||
|
|
||||||
if (response.IsSuccess && response.Data != null)
|
if (response.IsSuccess && response.Data != null)
|
||||||
{
|
{
|
||||||
|
_logService?.Info($"[迁移] 查询成功, 共 {response.Data.TotalNum} 条记录");
|
||||||
return (true, "查询成功", response.Data);
|
return (true, "查询成功", response.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Warn($"[迁移] 查询失败: {response.Msg}, Code={response.Code}");
|
||||||
return (false, response.Msg ?? "查询失败", null);
|
return (false, response.Msg ?? "查询失败", null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logService?.Error($"查询迁移列表异常: {ex.Message}", ex);
|
_logService?.Error($"[迁移] 查询迁移列表异常: {ex.Message}", ex);
|
||||||
return (false, $"查询异常: {ex.Message}", null);
|
return (false, $"查询异常: {ex.Message}", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -590,20 +602,23 @@ namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logService?.Info($"[迁移] 开始更新URL, 记录ID={request.RecordId}, 图片数={request.ImageUrls?.Count ?? 0}");
|
||||||
await EnsureTokenValidAsync();
|
await EnsureTokenValidAsync();
|
||||||
var response = await ExecuteWithRetryAsync(() =>
|
var response = await ExecuteWithRetryAsync(() =>
|
||||||
PostAsync<object>("/api/workrecord/migration/update", request));
|
PostAsync<object>("/api/workrecord/migration/update", request));
|
||||||
|
|
||||||
if (response.IsSuccess)
|
if (response.IsSuccess)
|
||||||
{
|
{
|
||||||
|
_logService?.Info($"[迁移] 更新URL成功, 记录ID={request.RecordId}");
|
||||||
return (true, "更新成功");
|
return (true, "更新成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Warn($"[迁移] 更新URL失败: {response.Msg}, Code={response.Code}");
|
||||||
return (false, response.Msg ?? "更新失败");
|
return (false, response.Msg ?? "更新失败");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logService?.Error($"更新迁移URL异常: {ex.Message}", ex);
|
_logService?.Error($"[迁移] 更新迁移URL异常: {ex.Message}", ex);
|
||||||
return (false, $"更新异常: {ex.Message}");
|
return (false, $"更新异常: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -769,6 +784,9 @@ namespace WorkCameraExport.Services
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// 调试日志:记录原始 JSON 响应(完整内容)
|
||||||
|
_logService?.Info($"[API响应] {endpoint} 原始JSON: {content}");
|
||||||
|
|
||||||
return JsonSerializer.Deserialize<PagedResult<T>>(content, JsonOptions)
|
return JsonSerializer.Deserialize<PagedResult<T>>(content, JsonOptions)
|
||||||
?? new PagedResult<T> { Code = 500, Msg = "解析响应失败" };
|
?? new PagedResult<T> { Code = 500, Msg = "解析响应失败" };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using COSXML.Auth;
|
||||||
using COSXML.Model.Object;
|
using COSXML.Model.Object;
|
||||||
using COSXML.Transfer;
|
using COSXML.Transfer;
|
||||||
using WorkCameraExport.Models;
|
using WorkCameraExport.Models;
|
||||||
|
using WorkCameraExport.Services.Interfaces;
|
||||||
|
|
||||||
namespace WorkCameraExport.Services
|
namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
|
|
@ -13,14 +14,21 @@ namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
private CosXml? _cosXml;
|
private CosXml? _cosXml;
|
||||||
private CosTempCredentials? _credentials;
|
private CosTempCredentials? _credentials;
|
||||||
|
private readonly ILogService? _logService;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
|
public CosService(ILogService? logService = null)
|
||||||
|
{
|
||||||
|
_logService = logService;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化 COS 客户端
|
/// 初始化 COS 客户端
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Initialize(CosTempCredentials credentials)
|
public void Initialize(CosTempCredentials credentials)
|
||||||
{
|
{
|
||||||
_credentials = credentials;
|
_credentials = credentials;
|
||||||
|
_logService?.Info($"[COS] 初始化, Region={credentials.Region}, Bucket={credentials.Bucket}");
|
||||||
|
|
||||||
var config = new CosXmlConfig.Builder()
|
var config = new CosXmlConfig.Builder()
|
||||||
.IsHttps(true)
|
.IsHttps(true)
|
||||||
|
|
@ -35,6 +43,7 @@ namespace WorkCameraExport.Services
|
||||||
credentials.SessionToken);
|
credentials.SessionToken);
|
||||||
|
|
||||||
_cosXml = new CosXmlServer(config, credentialProvider);
|
_cosXml = new CosXmlServer(config, credentialProvider);
|
||||||
|
_logService?.Info("[COS] 初始化完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -58,9 +67,12 @@ namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
if (!IsInitialized || _cosXml == null || _credentials == null)
|
if (!IsInitialized || _cosXml == null || _credentials == null)
|
||||||
{
|
{
|
||||||
|
_logService?.Error("[COS] 上传失败: 服务未初始化");
|
||||||
return (false, "COS 服务未初始化", null);
|
return (false, "COS 服务未初始化", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logService?.Info($"[COS] 开始上传文件: {localFilePath} -> {cosKey}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var transferConfig = new TransferConfig();
|
var transferConfig = new TransferConfig();
|
||||||
|
|
@ -83,27 +95,33 @@ namespace WorkCameraExport.Services
|
||||||
if (result.IsSuccessful())
|
if (result.IsSuccessful())
|
||||||
{
|
{
|
||||||
var cosUrl = $"https://{_credentials.Bucket}.cos.{_credentials.Region}.myqcloud.com/{cosKey}";
|
var cosUrl = $"https://{_credentials.Bucket}.cos.{_credentials.Region}.myqcloud.com/{cosKey}";
|
||||||
|
_logService?.Info($"[COS] 上传成功: {cosUrl}");
|
||||||
return (true, "上传成功", cosUrl);
|
return (true, "上传成功", cosUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_logService?.Warn($"[COS] 上传失败: result.IsSuccessful()=false");
|
||||||
return (false, "上传失败", null);
|
return (false, "上传失败", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
_logService?.Info("[COS] 上传已取消");
|
||||||
return (false, "上传已取消", null);
|
return (false, "上传已取消", null);
|
||||||
}
|
}
|
||||||
catch (COSXML.CosException.CosClientException clientEx)
|
catch (COSXML.CosException.CosClientException clientEx)
|
||||||
{
|
{
|
||||||
|
_logService?.Error($"[COS] 客户端异常: {clientEx.Message}", clientEx);
|
||||||
return (false, $"客户端异常: {clientEx.Message}", null);
|
return (false, $"客户端异常: {clientEx.Message}", null);
|
||||||
}
|
}
|
||||||
catch (COSXML.CosException.CosServerException serverEx)
|
catch (COSXML.CosException.CosServerException serverEx)
|
||||||
{
|
{
|
||||||
|
_logService?.Error($"[COS] 服务端异常: {serverEx.GetInfo()}");
|
||||||
return (false, $"服务端异常: {serverEx.GetInfo()}", null);
|
return (false, $"服务端异常: {serverEx.GetInfo()}", null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
_logService?.Error($"[COS] 上传异常: {ex.Message}", ex);
|
||||||
return (false, $"上传异常: {ex.Message}", null);
|
return (false, $"上传异常: {ex.Message}", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,12 @@ namespace WorkCameraExport.Services
|
||||||
WorkRecordExportItem record,
|
WorkRecordExportItem record,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// 调试日志:记录写入 Excel 时的 Workers 数据
|
||||||
|
var workersValue = record.Workers != null
|
||||||
|
? $"Workers数量={record.Workers.Count}, 值=[{string.Join(", ", record.Workers)}]"
|
||||||
|
: "Workers=null";
|
||||||
|
_logService?.Info($"[Excel写入] 行{row}, 记录ID={record.Id}, {workersValue}");
|
||||||
|
|
||||||
worksheet.Cells[row, 1].Value = row - 1; // 序号
|
worksheet.Cells[row, 1].Value = row - 1; // 序号
|
||||||
worksheet.Cells[row, 2].Value = record.DeptName;
|
worksheet.Cells[row, 2].Value = record.DeptName;
|
||||||
// 第3列是图片,稍后处理
|
// 第3列是图片,稍后处理
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,20 @@ namespace WorkCameraExport.Services
|
||||||
{
|
{
|
||||||
return records.Select(r =>
|
return records.Select(r =>
|
||||||
{
|
{
|
||||||
|
// 调试日志:记录 FromDto 前的 Workers 数据
|
||||||
|
var workersInfo = r.Workers != null
|
||||||
|
? $"Workers数量={r.Workers.Count}, 值=[{string.Join(", ", r.Workers)}]"
|
||||||
|
: "Workers=null";
|
||||||
|
_logService?.Info($"[BuildExportItems] 记录ID={r.Id}, {workersInfo}");
|
||||||
|
|
||||||
var item = WorkRecordExportItem.FromDto(r);
|
var item = WorkRecordExportItem.FromDto(r);
|
||||||
|
|
||||||
|
// 调试日志:记录 FromDto 后的 Workers 数据
|
||||||
|
var itemWorkersInfo = item.Workers != null
|
||||||
|
? $"Workers数量={item.Workers.Count}, 值=[{string.Join(", ", item.Workers)}]"
|
||||||
|
: "Workers=null";
|
||||||
|
_logService?.Info($"[BuildExportItems->FromDto后] 记录ID={item.Id}, {itemWorkersInfo}");
|
||||||
|
|
||||||
item.ImagePaths = r.Images
|
item.ImagePaths = r.Images
|
||||||
.Where(url => !string.IsNullOrEmpty(url) && imagePathMap.ContainsKey(url))
|
.Where(url => !string.IsNullOrEmpty(url) && imagePathMap.ContainsKey(url))
|
||||||
.Select(url => imagePathMap[url])
|
.Select(url => imagePathMap[url])
|
||||||
|
|
@ -334,6 +347,17 @@ namespace WorkCameraExport.Services
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkRecordExportDto ConvertToExportDto(WorkRecordDto dto)
|
private WorkRecordExportDto ConvertToExportDto(WorkRecordDto dto)
|
||||||
{
|
{
|
||||||
|
// 调试日志:记录转换前的 Workers 数据
|
||||||
|
var workersBeforeConvert = dto.Workers != null
|
||||||
|
? $"Workers数量={dto.Workers.Count}, 名称=[{string.Join(", ", dto.Workers.Select(w => w.WorkerName ?? "null"))}]"
|
||||||
|
: "Workers=null";
|
||||||
|
_logService?.Info($"[转换前] 记录ID={dto.Id}, {workersBeforeConvert}");
|
||||||
|
|
||||||
|
var workerNames = dto.Workers?.Select(w => w.WorkerName).ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
// 调试日志:记录转换后的 Workers 数据
|
||||||
|
_logService?.Info($"[转换后] 记录ID={dto.Id}, WorkerNames=[{string.Join(", ", workerNames)}]");
|
||||||
|
|
||||||
return new WorkRecordExportDto
|
return new WorkRecordExportDto
|
||||||
{
|
{
|
||||||
Id = dto.Id,
|
Id = dto.Id,
|
||||||
|
|
@ -344,7 +368,7 @@ namespace WorkCameraExport.Services
|
||||||
Address = dto.Address,
|
Address = dto.Address,
|
||||||
Content = dto.Content,
|
Content = dto.Content,
|
||||||
StatusName = dto.StatusName,
|
StatusName = dto.StatusName,
|
||||||
Workers = dto.Workers?.Select(w => w.WorkerName).ToList() ?? new List<string>(),
|
Workers = workerNames,
|
||||||
Images = dto.Images.Select(i => i.Url).ToList(),
|
Images = dto.Images.Select(i => i.Url).ToList(),
|
||||||
CreateTime = dto.CreateTime,
|
CreateTime = dto.CreateTime,
|
||||||
UpdateTime = dto.UpdateTime
|
UpdateTime = dto.UpdateTime
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,10 @@ namespace ZR.Admin.WebApi.Controllers.Business
|
||||||
var info = response.Adapt<CamWorkrecordDto>();
|
var info = response.Adapt<CamWorkrecordDto>();
|
||||||
if (info != null)
|
if (info != null)
|
||||||
{
|
{
|
||||||
var names = _CamWorkerService.AsQueryable().Where(it => it.WorkrecordId == info.Id).Select(it => it.WorkerName).ToList();
|
// 获取工作人员列表
|
||||||
info.Worker = names != null && names.Count > 0 ? string.Join(",", names) : "";
|
var workers = _CamWorkerService.AsQueryable().Where(it => it.WorkrecordId == info.Id).ToList();
|
||||||
|
info.Workers = workers.Select(w => new CamWorkersDto { Id = w.Id, WorkerName = w.WorkerName }).ToList();
|
||||||
|
info.Worker = workers.Count > 0 ? string.Join(",", workers.Select(w => w.WorkerName)) : "";
|
||||||
|
|
||||||
// 获取图片列表
|
// 获取图片列表
|
||||||
var imageRecords = _CamWorkrecordImageService.GetListByWorkrecordId(info.Id);
|
var imageRecords = _CamWorkrecordImageService.GetListByWorkrecordId(info.Id);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
"name" : "随工水印相机",
|
"name" : "随工水印相机",
|
||||||
"appid" : "__UNI__37E1E71",
|
"appid" : "__UNI__37E1E71",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "1.0.5",
|
"versionName" : "1.0.5.03",
|
||||||
"versionCode" : 105,
|
"versionCode" : 106,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
|
|
|
||||||
|
|
@ -776,10 +776,17 @@ const handleSaveImage = async () => {
|
||||||
await addWatermarkToImage();
|
await addWatermarkToImage();
|
||||||
|
|
||||||
// 保存水印图片到相册
|
// 保存水印图片到相册
|
||||||
if (imageSrc.value) {
|
// if (imageSrc.value) {
|
||||||
await saveImageToPhotosAlbum(imageSrc.value);
|
// await saveImageToPhotosAlbum(imageSrc.value);
|
||||||
|
// }
|
||||||
|
try {
|
||||||
|
if (imageList.value.length > 0) {
|
||||||
|
const watermarkPaths = imageList.value.map(img => img.watermark);
|
||||||
|
await saveImagesToPhotosAlbum(watermarkPaths);
|
||||||
|
}
|
||||||
|
} catch (saveError) {
|
||||||
|
console.error("保存图片到相册失败:", saveError);
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "图片保存成功",
|
title: "图片保存成功",
|
||||||
|
|
@ -914,8 +921,8 @@ const fallbackToV2Upload = async (_remarks, validWorkers) => {
|
||||||
// 保存所有水印图片到相册
|
// 保存所有水印图片到相册
|
||||||
try {
|
try {
|
||||||
if (imageList.value.length > 0) {
|
if (imageList.value.length > 0) {
|
||||||
const watermarkPaths = imageList.value.map(img => img.watermark);
|
//const watermarkPaths = imageList.value.map(img => img.watermark);
|
||||||
await saveImagesToPhotosAlbum(watermarkPaths);
|
//await saveImagesToPhotosAlbum(watermarkPaths);
|
||||||
}
|
}
|
||||||
} catch (saveError) {
|
} catch (saveError) {
|
||||||
console.error("保存图片到相册失败:", saveError);
|
console.error("保存图片到相册失败:", saveError);
|
||||||
|
|
@ -1083,8 +1090,8 @@ const handleSaveAndSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
// 保存所有水印图片到相册
|
// 保存所有水印图片到相册
|
||||||
if (imageList.value.length > 0) {
|
if (imageList.value.length > 0) {
|
||||||
const watermarkPaths = imageList.value.map(img => img.watermark);
|
// const watermarkPaths = imageList.value.map(img => img.watermark);
|
||||||
const saveResult = await saveImagesToPhotosAlbum(watermarkPaths);
|
// const saveResult = await saveImagesToPhotosAlbum(watermarkPaths);
|
||||||
console.log(`保存到相册完成: 成功${saveResult.success}张, 失败${saveResult.failed}张`);
|
console.log(`保存到相册完成: 成功${saveResult.success}张, 失败${saveResult.failed}张`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user