333
This commit is contained in:
parent
8aaf0396f1
commit
e443805972
|
|
@ -80,12 +80,8 @@ namespace WorkCameraExport.Forms
|
|||
_apiService.SetBaseUrl(_settings.ServerUrl);
|
||||
_apiService.SetToken(_settings.SavedToken);
|
||||
|
||||
// 验证 Token 是否有效(通过调用一个简单的 API)
|
||||
var (success, _, _) = await _apiService.GetExportCountAsync(new WorkRecordExportQuery
|
||||
{
|
||||
PageNum = 1,
|
||||
PageSize = 1
|
||||
});
|
||||
// 验证 Token 是否有效(通过获取当前用户信息)
|
||||
var (success, _, _) = await _apiService.GetCurrentUserAsync();
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace WorkCameraExport.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
txtExportPath.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
txtExportPath.Text = PathService.ExportDirectory;
|
||||
}
|
||||
|
||||
UpdateExportButtonState();
|
||||
|
|
|
|||
|
|
@ -194,10 +194,11 @@ namespace WorkCameraExport.Forms
|
|||
return;
|
||||
}
|
||||
|
||||
var outputPath = GetExcelExportPath();
|
||||
if (string.IsNullOrEmpty(outputPath)) return;
|
||||
// 直接生成导出路径,不使用文件对话框
|
||||
var fileName = $"月报表_{dtpMonth.Value:yyyyMM}_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
|
||||
var outputPath = Path.Combine(PathService.ExportDirectory, fileName);
|
||||
|
||||
_logService?.Info($"开始导出月报表 Excel,共 {_currentData.Count} 条记录");
|
||||
_logService?.Info($"开始导出月报表 Excel,共 {_currentData.Count} 条记录,路径: {outputPath}");
|
||||
|
||||
SetLoadingState(true);
|
||||
lblStatusBar.Text = "正在导出 Excel...";
|
||||
|
|
@ -221,7 +222,7 @@ namespace WorkCameraExport.Forms
|
|||
_logService?.Info($"导出完成: {outputPath}");
|
||||
|
||||
var result = MessageBox.Show(
|
||||
"导出完成!是否打开文件所在目录?",
|
||||
$"导出完成!\n文件已保存到:{outputPath}\n\n是否打开文件所在目录?",
|
||||
"提示",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
|
@ -242,27 +243,6 @@ namespace WorkCameraExport.Forms
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Excel 导出路径
|
||||
/// </summary>
|
||||
private string? GetExcelExportPath()
|
||||
{
|
||||
using var dialog = new SaveFileDialog
|
||||
{
|
||||
Title = "选择导出位置",
|
||||
Filter = "Excel 文件 (*.xlsx)|*.xlsx",
|
||||
FileName = $"月报表_{dtpMonth.Value:yyyyMM}_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
return dialog.FileName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 下载照片 ZIP 功能
|
||||
|
|
@ -281,8 +261,10 @@ namespace WorkCameraExport.Forms
|
|||
public async Task DownloadPhotosZipAsync()
|
||||
{
|
||||
var yearMonth = dtpMonth.Value.ToString("yyyy-MM");
|
||||
var outputPath = GetZipExportPath(yearMonth);
|
||||
if (string.IsNullOrEmpty(outputPath)) return;
|
||||
|
||||
// 直接生成导出路径,不使用文件对话框
|
||||
var fileName = $"工作照片_{yearMonth.Replace("-", "")}_{DateTime.Now:yyyyMMdd_HHmmss}.zip";
|
||||
var outputPath = Path.Combine(PathService.ExportDirectory, fileName);
|
||||
|
||||
if (_isExporting)
|
||||
{
|
||||
|
|
@ -290,7 +272,7 @@ namespace WorkCameraExport.Forms
|
|||
return;
|
||||
}
|
||||
|
||||
_logService?.Info($"开始下载照片 ZIP,月份: {yearMonth}");
|
||||
_logService?.Info($"开始下载照片 ZIP,月份: {yearMonth},路径: {outputPath}");
|
||||
|
||||
_isExporting = true;
|
||||
_exportCts = new CancellationTokenSource();
|
||||
|
|
@ -318,7 +300,7 @@ namespace WorkCameraExport.Forms
|
|||
_logService?.Info($"下载完成: {outputPath}");
|
||||
|
||||
var result = MessageBox.Show(
|
||||
"下载完成!是否打开文件所在目录?",
|
||||
$"下载完成!\n文件已保存到:{outputPath}\n\n是否打开文件所在目录?",
|
||||
"提示",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
|
@ -349,27 +331,6 @@ namespace WorkCameraExport.Forms
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 ZIP 导出路径
|
||||
/// </summary>
|
||||
private string? GetZipExportPath(string yearMonth)
|
||||
{
|
||||
using var dialog = new SaveFileDialog
|
||||
{
|
||||
Title = "选择保存位置",
|
||||
Filter = "ZIP 文件 (*.zip)|*.zip",
|
||||
FileName = $"工作照片_{yearMonth.Replace("-", "")}_{DateTime.Now:yyyyMMdd_HHmmss}.zip",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
return dialog.FileName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新下载进度
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -687,10 +687,11 @@ namespace WorkCameraExport.Forms
|
|||
return;
|
||||
}
|
||||
|
||||
var outputPath = GetExportPath();
|
||||
if (string.IsNullOrEmpty(outputPath)) return;
|
||||
// 直接生成导出路径,不使用文件对话框
|
||||
var fileName = $"工作记录导出_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
|
||||
var outputPath = Path.Combine(PathService.ExportDirectory, fileName);
|
||||
|
||||
_logService?.Info($"开始导出全部数据,共 {_totalRecords} 条记录");
|
||||
_logService?.Info($"开始导出全部数据,共 {_totalRecords} 条记录,路径: {outputPath}");
|
||||
await DoExportAsync(outputPath, null);
|
||||
}
|
||||
|
||||
|
|
@ -701,34 +702,14 @@ namespace WorkCameraExport.Forms
|
|||
{
|
||||
if (ids.Count == 0) return;
|
||||
|
||||
var outputPath = GetExportPath();
|
||||
if (string.IsNullOrEmpty(outputPath)) return;
|
||||
// 直接生成导出路径,不使用文件对话框
|
||||
var fileName = $"工作记录导出_选中{ids.Count}条_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
|
||||
var outputPath = Path.Combine(PathService.ExportDirectory, fileName);
|
||||
|
||||
_logService?.Info($"开始导出选中数据,共 {ids.Count} 条记录");
|
||||
_logService?.Info($"开始导出选中数据,共 {ids.Count} 条记录,路径: {outputPath}");
|
||||
await DoExportAsync(outputPath, ids);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取导出路径
|
||||
/// </summary>
|
||||
private string? GetExportPath()
|
||||
{
|
||||
using var dialog = new SaveFileDialog
|
||||
{
|
||||
Title = "选择导出位置",
|
||||
Filter = "Excel 文件 (*.xlsx)|*.xlsx",
|
||||
FileName = $"工作记录导出_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
return dialog.FileName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行导出
|
||||
/// </summary>
|
||||
|
|
@ -775,7 +756,7 @@ namespace WorkCameraExport.Forms
|
|||
_logService?.Info($"导出完成: {outputPath}");
|
||||
|
||||
var result = MessageBox.Show(
|
||||
"导出完成!是否打开文件所在目录?",
|
||||
$"导出完成!\n文件已保存到:{outputPath}\n\n是否打开文件所在目录?",
|
||||
"提示",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
|
|
|||
|
|
@ -89,6 +89,30 @@ namespace WorkCameraExport.Models
|
|||
public string NickName { get; set; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户信息响应(/system/user/profile 接口)
|
||||
/// </summary>
|
||||
public class UserProfileResponse
|
||||
{
|
||||
public UserProfileDto? User { get; set; }
|
||||
public List<string>? Roles { get; set; }
|
||||
public string? PostGroup { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户详细信息
|
||||
/// </summary>
|
||||
public class UserProfileDto
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public string? UserName { get; set; }
|
||||
public string? NickName { get; set; }
|
||||
public string? DeptName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Phonenumber { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 工作记录导出查询请求
|
||||
/// </summary>
|
||||
|
|
@ -116,14 +140,17 @@ namespace WorkCameraExport.Models
|
|||
public string Address { get; set; } = "";
|
||||
public string Content { get; set; } = "";
|
||||
public string StatusName { get; set; } = "";
|
||||
public List<WorkerDto> Workers { get; set; } = new();
|
||||
/// <summary>
|
||||
/// 施工人员名称列表(与服务端保持一致,为字符串列表)
|
||||
/// </summary>
|
||||
public List<string> Workers { get; set; } = new();
|
||||
public List<string> Images { get; set; } = new();
|
||||
public DateTime? CreateTime { get; set; }
|
||||
public DateTime? UpdateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取工作人员名称列表(便捷属性)
|
||||
/// 获取工作人员名称列表(便捷属性,保持向后兼容)
|
||||
/// </summary>
|
||||
public List<string> WorkerNames => Workers?.Select(w => w.WorkerName).ToList() ?? new List<string>();
|
||||
public List<string> WorkerNames => Workers ?? new List<string>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using WorkCameraExport.Services;
|
||||
|
||||
namespace WorkCameraExport.Models
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -30,18 +32,15 @@ namespace WorkCameraExport.Models
|
|||
/// </summary>
|
||||
public void Validate()
|
||||
{
|
||||
// 并发数限制在 1-10
|
||||
if (ImageDownloadConcurrency < 1) ImageDownloadConcurrency = 1;
|
||||
if (ImageDownloadConcurrency > 10) ImageDownloadConcurrency = 10;
|
||||
|
||||
// 压缩质量限制在 30-100
|
||||
if (ImageCompressQuality < 30) ImageCompressQuality = 30;
|
||||
if (ImageCompressQuality > 100) ImageCompressQuality = 100;
|
||||
|
||||
// 默认保存路径为空时使用桌面
|
||||
if (string.IsNullOrWhiteSpace(DefaultSavePath))
|
||||
{
|
||||
DefaultSavePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
DefaultSavePath = PathService.ExportDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +51,7 @@ namespace WorkCameraExport.Models
|
|||
{
|
||||
return new AppConfig
|
||||
{
|
||||
DefaultSavePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
|
||||
DefaultSavePath = PathService.ExportDirectory,
|
||||
ImageDownloadConcurrency = 5,
|
||||
ImageCompressQuality = 50,
|
||||
AutoCleanTempFiles = true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Text.Json;
|
||||
using WorkCameraExport.Services;
|
||||
|
||||
namespace WorkCameraExport.Models
|
||||
{
|
||||
|
|
@ -7,11 +8,6 @@ namespace WorkCameraExport.Models
|
|||
/// </summary>
|
||||
public class AppSettings
|
||||
{
|
||||
private static readonly string SettingsPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"WorkCameraExport",
|
||||
"settings.json");
|
||||
|
||||
/// <summary>
|
||||
/// 服务器地址
|
||||
/// </summary>
|
||||
|
|
@ -49,9 +45,10 @@ namespace WorkCameraExport.Models
|
|||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(SettingsPath))
|
||||
var path = PathService.SettingsFile;
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var json = File.ReadAllText(SettingsPath);
|
||||
var json = File.ReadAllText(path);
|
||||
return JsonSerializer.Deserialize<AppSettings>(json) ?? new AppSettings();
|
||||
}
|
||||
}
|
||||
|
|
@ -69,17 +66,11 @@ namespace WorkCameraExport.Models
|
|||
{
|
||||
try
|
||||
{
|
||||
var directory = Path.GetDirectoryName(SettingsPath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var json = JsonSerializer.Serialize(this, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
File.WriteAllText(SettingsPath, json);
|
||||
File.WriteAllText(PathService.SettingsFile, json);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ static class Program
|
|||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
static async Task Main()
|
||||
{
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
|
|
@ -37,26 +37,23 @@ static class Program
|
|||
// 主循环:处理登录失效后重新登录
|
||||
while (true)
|
||||
{
|
||||
// 显示登录窗体
|
||||
using var loginForm = new LoginForm(apiService, configService);
|
||||
if (loginForm.ShowDialog() != DialogResult.OK)
|
||||
// 先尝试自动登录
|
||||
var autoLoginSuccess = await loginStateManager.TryAutoLoginAsync();
|
||||
|
||||
if (!autoLoginSuccess)
|
||||
{
|
||||
// 用户取消登录,退出应用
|
||||
return;
|
||||
}
|
||||
|
||||
// 登录成功,保存登录状态(无论是自动登录还是手动登录)
|
||||
if (loginForm.Token != null)
|
||||
{
|
||||
var settings = Models.AppSettings.Load();
|
||||
if (loginForm.IsAutoLogin)
|
||||
// 自动登录失败,显示登录窗体
|
||||
using var loginForm = new LoginForm(apiService, configService);
|
||||
if (loginForm.ShowDialog() != DialogResult.OK)
|
||||
{
|
||||
// 自动登录成功,启动 Token 检查定时器(不重新保存凭证)
|
||||
loginStateManager.OnAutoLoginSuccess(settings.Username);
|
||||
// 用户取消登录,退出应用
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// 手动登录成功,保存登录状态
|
||||
if (loginForm.Token != null)
|
||||
{
|
||||
// 手动登录成功,保存凭证并启动定时器
|
||||
var settings = Models.AppSettings.Load();
|
||||
loginStateManager.OnLoginSuccess(
|
||||
settings.ServerUrl,
|
||||
settings.Username,
|
||||
|
|
|
|||
|
|
@ -248,6 +248,34 @@ namespace WorkCameraExport.Services
|
|||
_refreshToken = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户信息(用于验证 Token 有效性)
|
||||
/// </summary>
|
||||
public async Task<(bool Success, string Message, UserInfo? Data)> GetCurrentUserAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await GetAsync<UserProfileResponse>("/system/user/profile");
|
||||
|
||||
if (response.IsSuccess && response.Data?.User != null)
|
||||
{
|
||||
return (true, "获取成功", new UserInfo
|
||||
{
|
||||
UserId = response.Data.User.UserId,
|
||||
UserName = response.Data.User.UserName ?? "",
|
||||
NickName = response.Data.User.NickName ?? ""
|
||||
});
|
||||
}
|
||||
|
||||
return (false, response.Msg ?? "获取用户信息失败", null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logService?.Error($"获取用户信息异常: {ex.Message}", ex);
|
||||
return (false, $"获取用户信息异常: {ex.Message}", null);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 统计接口
|
||||
|
|
@ -425,7 +453,7 @@ namespace WorkCameraExport.Services
|
|||
await EnsureTokenValidAsync();
|
||||
var queryParams = BuildQueryString(query);
|
||||
var response = await ExecuteWithRetryAsync(() =>
|
||||
GetAsync<List<MonthlyReportDto>>($"/api/workrecord/monthlyReport?{queryParams}"));
|
||||
GetAsync<List<MonthlyReportDto>>($"/business/CamWorkers/list?{queryParams}"));
|
||||
|
||||
if (response.IsSuccess && response.Data != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@ namespace WorkCameraExport.Services
|
|||
/// </summary>
|
||||
public class ConfigService : IConfigService
|
||||
{
|
||||
private readonly string _appDataPath;
|
||||
private readonly string _configFilePath;
|
||||
private readonly string _credentialsFilePath;
|
||||
private readonly string _tempPath;
|
||||
private readonly string _logPath;
|
||||
|
||||
// 用于加密凭证的密钥(AES-256 需要 32 字节密钥,16 字节 IV)
|
||||
private static readonly byte[] EncryptionKey = Encoding.UTF8.GetBytes("WorkCameraExport2025SecretKey!!!"); // 32 bytes
|
||||
private static readonly byte[] EncryptionIV = Encoding.UTF8.GetBytes("WCE2025InitVect!"); // 16 bytes
|
||||
|
|
@ -29,46 +23,31 @@ namespace WorkCameraExport.Services
|
|||
|
||||
public ConfigService()
|
||||
{
|
||||
_appDataPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"WorkCameraExport");
|
||||
_configFilePath = Path.Combine(_appDataPath, "config.json");
|
||||
_credentialsFilePath = Path.Combine(_appDataPath, "credentials.dat");
|
||||
_tempPath = Path.Combine(_appDataPath, "temp");
|
||||
_logPath = Path.Combine(_appDataPath, "logs");
|
||||
|
||||
EnsureDirectoriesExist();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试的构造函数,允许指定自定义路径
|
||||
/// 用于测试的构造函数
|
||||
/// </summary>
|
||||
public ConfigService(string appDataPath)
|
||||
public ConfigService(string _)
|
||||
{
|
||||
_appDataPath = appDataPath;
|
||||
_configFilePath = Path.Combine(_appDataPath, "config.json");
|
||||
_credentialsFilePath = Path.Combine(_appDataPath, "credentials.dat");
|
||||
_tempPath = Path.Combine(_appDataPath, "temp");
|
||||
_logPath = Path.Combine(_appDataPath, "logs");
|
||||
|
||||
EnsureDirectoriesExist();
|
||||
}
|
||||
|
||||
#region IConfigService 实现
|
||||
|
||||
public string AppDataPath => _appDataPath;
|
||||
public string TempPath => _tempPath;
|
||||
public string LogPath => _logPath;
|
||||
public string AppDataPath => PathService.BaseDirectory;
|
||||
public string TempPath => PathService.TempDirectory;
|
||||
public string LogPath => PathService.LogDirectory;
|
||||
|
||||
public bool HasSavedCredentials => File.Exists(_credentialsFilePath);
|
||||
public bool HasSavedCredentials => File.Exists(PathService.CredentialsFile);
|
||||
|
||||
public AppConfig LoadConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_configFilePath))
|
||||
var path = PathService.ConfigFile;
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var json = File.ReadAllText(_configFilePath);
|
||||
var json = File.ReadAllText(path);
|
||||
var config = JsonSerializer.Deserialize<AppConfig>(json, JsonOptions);
|
||||
if (config != null)
|
||||
{
|
||||
|
|
@ -89,7 +68,7 @@ namespace WorkCameraExport.Services
|
|||
{
|
||||
config.Validate();
|
||||
var json = JsonSerializer.Serialize(config, JsonOptions);
|
||||
File.WriteAllText(_configFilePath, json);
|
||||
File.WriteAllText(PathService.ConfigFile, json);
|
||||
}
|
||||
|
||||
public void SaveCredentials(string serverUrl, string token, string username)
|
||||
|
|
@ -104,17 +83,18 @@ namespace WorkCameraExport.Services
|
|||
|
||||
var json = JsonSerializer.Serialize(credentials, JsonOptions);
|
||||
var encrypted = Encrypt(json);
|
||||
File.WriteAllBytes(_credentialsFilePath, encrypted);
|
||||
File.WriteAllBytes(PathService.CredentialsFile, encrypted);
|
||||
}
|
||||
|
||||
public (string ServerUrl, string Token, string Username)? LoadCredentials()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(_credentialsFilePath))
|
||||
var path = PathService.CredentialsFile;
|
||||
if (!File.Exists(path))
|
||||
return null;
|
||||
|
||||
var encrypted = File.ReadAllBytes(_credentialsFilePath);
|
||||
var encrypted = File.ReadAllBytes(path);
|
||||
var json = Decrypt(encrypted);
|
||||
var credentials = JsonSerializer.Deserialize<CredentialsData>(json, JsonOptions);
|
||||
|
||||
|
|
@ -138,9 +118,10 @@ namespace WorkCameraExport.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_credentialsFilePath))
|
||||
var path = PathService.CredentialsFile;
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(_credentialsFilePath);
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
|
@ -153,9 +134,10 @@ namespace WorkCameraExport.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(_tempPath))
|
||||
var tempPath = PathService.TempDirectory;
|
||||
if (Directory.Exists(tempPath))
|
||||
{
|
||||
var directory = new DirectoryInfo(_tempPath);
|
||||
var directory = new DirectoryInfo(tempPath);
|
||||
foreach (var file in directory.GetFiles())
|
||||
{
|
||||
try { file.Delete(); } catch { }
|
||||
|
|
@ -176,16 +158,6 @@ namespace WorkCameraExport.Services
|
|||
|
||||
#region 私有方法
|
||||
|
||||
private void EnsureDirectoriesExist()
|
||||
{
|
||||
if (!Directory.Exists(_appDataPath))
|
||||
Directory.CreateDirectory(_appDataPath);
|
||||
if (!Directory.Exists(_tempPath))
|
||||
Directory.CreateDirectory(_tempPath);
|
||||
if (!Directory.Exists(_logPath))
|
||||
Directory.CreateDirectory(_logPath);
|
||||
}
|
||||
|
||||
private static byte[] Encrypt(string plainText)
|
||||
{
|
||||
using var aes = Aes.Create();
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ namespace WorkCameraExport.Services
|
|||
Address = dto.Address,
|
||||
Content = dto.Content,
|
||||
StatusName = dto.StatusName,
|
||||
Workers = dto.Workers, // 保持 List<WorkerDto> 类型
|
||||
Workers = dto.Workers?.Select(w => w.WorkerName).ToList() ?? new List<string>(),
|
||||
Images = dto.Images.Select(i => i.Url).ToList(),
|
||||
CreateTime = dto.CreateTime,
|
||||
UpdateTime = dto.UpdateTime
|
||||
|
|
|
|||
|
|
@ -57,18 +57,23 @@ namespace WorkCameraExport.Services
|
|||
/// <returns>是否自动登录成功</returns>
|
||||
public async Task<bool> TryAutoLoginAsync()
|
||||
{
|
||||
// 每次尝试自动登录时重新加载设置,确保获取最新的保存信息
|
||||
var settings = AppSettings.Load();
|
||||
|
||||
_logService?.Info($"[自动登录] 检查设置: RememberMe={settings.RememberMe}, ServerUrl={settings.ServerUrl}, SavedToken长度={settings.SavedToken?.Length ?? 0}");
|
||||
|
||||
// 首先检查 AppSettings 中的保存信息
|
||||
if (!_settings.RememberMe ||
|
||||
string.IsNullOrEmpty(_settings.ServerUrl) ||
|
||||
string.IsNullOrEmpty(_settings.SavedToken))
|
||||
if (!settings.RememberMe ||
|
||||
string.IsNullOrEmpty(settings.ServerUrl) ||
|
||||
string.IsNullOrEmpty(settings.SavedToken))
|
||||
{
|
||||
_logService?.Info("未找到保存的登录信息,跳过自动登录");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查 Token 是否已过期
|
||||
if (_settings.TokenExpireTime.HasValue &&
|
||||
_settings.TokenExpireTime.Value <= DateTime.Now)
|
||||
if (settings.TokenExpireTime.HasValue &&
|
||||
settings.TokenExpireTime.Value <= DateTime.Now)
|
||||
{
|
||||
_logService?.Info("保存的 Token 已过期,清除登录信息");
|
||||
ClearLoginState();
|
||||
|
|
@ -79,25 +84,21 @@ namespace WorkCameraExport.Services
|
|||
|
||||
try
|
||||
{
|
||||
_apiService.SetBaseUrl(_settings.ServerUrl);
|
||||
_apiService.SetToken(_settings.SavedToken);
|
||||
_apiService.SetBaseUrl(settings.ServerUrl);
|
||||
_apiService.SetToken(settings.SavedToken);
|
||||
|
||||
// 验证 Token 是否有效
|
||||
var (success, _, _) = await _apiService.GetExportCountAsync(new WorkRecordExportQuery
|
||||
{
|
||||
PageNum = 1,
|
||||
PageSize = 1
|
||||
});
|
||||
// 验证 Token 是否有效(通过获取当前用户信息)
|
||||
var (success, message, userInfo) = await _apiService.GetCurrentUserAsync();
|
||||
|
||||
if (success)
|
||||
if (success && userInfo != null)
|
||||
{
|
||||
CurrentUsername = _settings.Username;
|
||||
CurrentUsername = userInfo.UserName ?? settings.Username;
|
||||
StartTokenCheckTimer();
|
||||
_logService?.Info($"自动登录成功,用户: {CurrentUsername}");
|
||||
return true;
|
||||
}
|
||||
|
||||
_logService?.Warn("Token 验证失败,清除登录信息");
|
||||
_logService?.Warn($"Token 验证失败: {message},清除登录信息");
|
||||
ClearLoginState();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -181,11 +182,8 @@ namespace WorkCameraExport.Services
|
|||
|
||||
try
|
||||
{
|
||||
var (success, _, _) = await _apiService.GetExportCountAsync(new WorkRecordExportQuery
|
||||
{
|
||||
PageNum = 1,
|
||||
PageSize = 1
|
||||
});
|
||||
// 通过获取当前用户信息验证 Token 有效性
|
||||
var (success, _, _) = await _apiService.GetCurrentUserAsync();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
|
|
|||
86
client/WorkCameraExport/Services/PathService.cs
Normal file
86
client/WorkCameraExport/Services/PathService.cs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
namespace WorkCameraExport.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 路径服务 - 统一管理所有文件路径,全部基于 exe 所在目录
|
||||
/// </summary>
|
||||
public static class PathService
|
||||
{
|
||||
private static readonly string _baseDir;
|
||||
|
||||
static PathService()
|
||||
{
|
||||
// 使用 AppContext.BaseDirectory,兼容单文件发布
|
||||
_baseDir = AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取基础目录(exe 所在目录)
|
||||
/// </summary>
|
||||
public static string BaseDirectory => _baseDir;
|
||||
|
||||
/// <summary>
|
||||
/// 获取设置文件路径
|
||||
/// </summary>
|
||||
public static string SettingsFile => Path.Combine(_baseDir, "settings.json");
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置文件路径
|
||||
/// </summary>
|
||||
public static string ConfigFile => Path.Combine(_baseDir, "config.json");
|
||||
|
||||
/// <summary>
|
||||
/// 获取凭证文件路径
|
||||
/// </summary>
|
||||
public static string CredentialsFile => Path.Combine(_baseDir, "credentials.dat");
|
||||
|
||||
/// <summary>
|
||||
/// 获取日志目录
|
||||
/// </summary>
|
||||
public static string LogDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
var dir = Path.Combine(_baseDir, "logs");
|
||||
EnsureDirectoryExists(dir);
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取临时文件目录
|
||||
/// </summary>
|
||||
public static string TempDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
var dir = Path.Combine(_baseDir, "temp");
|
||||
EnsureDirectoryExists(dir);
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取导出目录
|
||||
/// </summary>
|
||||
public static string ExportDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
var dir = Path.Combine(_baseDir, "Export");
|
||||
EnsureDirectoryExists(dir);
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保目录存在
|
||||
/// </summary>
|
||||
private static void EnsureDirectoryExists(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user