調整 video 開啓先比對
新增 env 多個遠端路徑 新増 env 能比對檔案路徑 20250704
This commit is contained in:
parent
d041ff1f80
commit
8f456c347d
80
DataCheck.cs
Normal file
80
DataCheck.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace DataCheck
|
||||
{
|
||||
public class DataChecker
|
||||
{
|
||||
public DataChecker()
|
||||
{
|
||||
// 加入你要同步的資料夾
|
||||
SyncFolder(Utils.Env.GetPath("video", ""), @"D:\video", "video", new[] { ".mpg" });
|
||||
|
||||
}
|
||||
|
||||
private void SyncFolder(string serverPath, string localPath, string label, string[] extensions)
|
||||
{
|
||||
|
||||
if (!Directory.Exists(localPath))
|
||||
{
|
||||
Directory.CreateDirectory(localPath);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(serverPath))
|
||||
{
|
||||
Console.WriteLine($"找不到伺服器資料夾:{serverPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var serverFiles = Directory.GetFiles(serverPath)
|
||||
.Where(f => extensions.Contains(Path.GetExtension(f), StringComparer.OrdinalIgnoreCase))
|
||||
.Select(f => new FileInfo(f))
|
||||
.ToDictionary(f => f.Name, f => f);
|
||||
|
||||
var localFiles = Directory.GetFiles(localPath)
|
||||
.Where(f => extensions.Contains(Path.GetExtension(f), StringComparer.OrdinalIgnoreCase))
|
||||
.Select(f => new FileInfo(f))
|
||||
.ToDictionary(f => f.Name, f => f);
|
||||
|
||||
// 1. 複製或更新檔案
|
||||
foreach (var serverFile in serverFiles)
|
||||
{
|
||||
bool needsCopy = !localFiles.ContainsKey(serverFile.Key) ||
|
||||
serverFile.Value.LastWriteTime > localFiles[serverFile.Key].LastWriteTime;
|
||||
|
||||
if (needsCopy)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dest = Path.Combine(localPath, serverFile.Key);
|
||||
File.Copy(serverFile.Value.FullName, dest, true);
|
||||
Console.WriteLine($"更新{label}: {serverFile.Key}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"複製{label}失敗 {serverFile.Key}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 刪除多餘的本地檔案
|
||||
foreach (var localFile in localFiles)
|
||||
{
|
||||
if (!serverFiles.ContainsKey(localFile.Key))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(localFile.Value.FullName);
|
||||
Console.WriteLine($"刪除多餘{label}: {localFile.Key}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"刪除{label}失敗 {localFile.Key}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
105
Env.cs
105
Env.cs
@ -6,56 +6,87 @@ namespace Utils
|
||||
{
|
||||
public static class Env
|
||||
{
|
||||
public static readonly string KtvPath = @"\\pc101\KTVData";
|
||||
private static readonly Dictionary<string, string> _values;
|
||||
private static string KtvPath = "";
|
||||
private static readonly List<string> KtvPaths = new()
|
||||
{
|
||||
@"\\sshost\KTVSuperstar",
|
||||
@"\\pc101\KTVSuperstar"
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> _values = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
static Env()
|
||||
{
|
||||
var path = Path.Combine(KtvPath, "config.ini");
|
||||
_values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (!File.Exists(path))
|
||||
foreach (var path in KtvPaths)
|
||||
{
|
||||
Console.WriteLine($"❌ 找不到環境檔案:{path}");
|
||||
return;
|
||||
var configPath = Path.Combine(path, "config.ini");
|
||||
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
KtvPath = path;
|
||||
Console.WriteLine("✅ 找到設定檔:" + configPath);
|
||||
|
||||
foreach (var line in File.ReadAllLines(configPath))
|
||||
{
|
||||
var trimmed = line.Trim();
|
||||
if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith("#")) continue;
|
||||
|
||||
var index = trimmed.IndexOf('=');
|
||||
if (index < 0) continue;
|
||||
|
||||
var key = trimmed[..index].Trim();
|
||||
var value = trimmed[(index + 1)..].Trim();
|
||||
|
||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
||||
value = value[1..^1];
|
||||
|
||||
_values[key] = value;
|
||||
}
|
||||
|
||||
return; // 找到一份 config 就跳出
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var line in File.ReadAllLines(path))
|
||||
Console.WriteLine("❌ 所有指定目錄都找不到 config.ini");
|
||||
}
|
||||
|
||||
public static string Get(string key, string fallback = "") =>
|
||||
_values.TryGetValue(key, out var value) ? value : fallback;
|
||||
|
||||
public static bool GetBool(string key, bool fallback = false) =>
|
||||
_values.TryGetValue(key, out var value) && bool.TryParse(value, out var result)
|
||||
? result : fallback;
|
||||
|
||||
public static int GetInt(string key, int fallback = 0) =>
|
||||
_values.TryGetValue(key, out var value) && int.TryParse(value, out var result)
|
||||
? result : fallback;
|
||||
|
||||
public static string GetPath(string key, string fallback = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(KtvPath))
|
||||
{
|
||||
var trimmed = line.Trim();
|
||||
if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith("#")) continue;
|
||||
Console.WriteLine("⚠️ KtvPath 尚未設定,將使用 fallback。");
|
||||
return fallback;
|
||||
}
|
||||
|
||||
var index = trimmed.IndexOf('=');
|
||||
if (index < 0) continue;
|
||||
var path = Path.Combine(KtvPath, key);
|
||||
|
||||
var key = trimmed[..index].Trim();
|
||||
var value = trimmed[(index + 1)..].Trim();
|
||||
|
||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
||||
value = value[1..^1]; // 去除引號
|
||||
|
||||
_values[key] = value;
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"⚠️ 找不到目錄:{path},使用 fallback:{fallback}");
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Get(string key, string fallback = "")
|
||||
public static string GetDBConnection()
|
||||
{
|
||||
return _values.TryGetValue(key, out var value) ? value : fallback;
|
||||
return $"Server={Get("DBServer", "localhost")};Port={Get("DBPort", "3306")};Database={Get("Database", "test")};User={Get("DBUser", "root")};Password={Get("DBPassword", "")};";
|
||||
}
|
||||
|
||||
public static bool GetBool(string key, bool fallback = false)
|
||||
{
|
||||
return _values.TryGetValue(key, out var value) && bool.TryParse(value, out var result)
|
||||
? result
|
||||
: fallback;
|
||||
}
|
||||
|
||||
public static int GetInt(string key, int fallback = 0)
|
||||
{
|
||||
return _values.TryGetValue(key, out var value) && int.TryParse(value, out var result)
|
||||
? result
|
||||
: fallback;
|
||||
}
|
||||
|
||||
// 可加上 GetFloat、GetDouble、GetTimeSpan ... 視需要
|
||||
// 如需支援更多型別可自行擴充:GetFloat, GetDouble, GetDateTime 等
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,9 @@ namespace DualScreenDemo
|
||||
private List<Image> LoadImagesFromFolder(string folderName)
|
||||
{
|
||||
List<Image> images = new();
|
||||
string folderPath = Path.Combine(Utils.Env.KtvPath, folderName);
|
||||
string folderPath = Utils.Env.GetPath(folderName, "");
|
||||
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Console.WriteLine($" 找不到遠端資料夾:{folderPath}");
|
||||
return images;
|
||||
}
|
||||
if (folderPath.Equals("")) return images;
|
||||
|
||||
string[] imageFiles = Directory.GetFiles(folderPath, "*.jpg");
|
||||
|
||||
|
@ -9,7 +9,7 @@ namespace DualScreenDemo{
|
||||
|
||||
private static string GetConnectionString()
|
||||
{
|
||||
return $"Server={Utils.Env.Get("DBServer", "localhost")};Port={Utils.Env.Get("DBPort", "3306")};Database={Utils.Env.Get("Database", "test")};User={Utils.Env.Get("DBUser", "root")};Password={Utils.Env.Get("DBPassword", "")};";
|
||||
return Utils.Env.GetDBConnection();
|
||||
}
|
||||
|
||||
public bool isLoggedIn = false;
|
||||
|
@ -1549,92 +1549,7 @@ namespace DualScreenDemo
|
||||
publicSongList = new List<SongData>();
|
||||
playedSongsHistory = new List<SongData>();
|
||||
playStates = new List<PlayState>();
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 檢查是否能連接到 SVR01
|
||||
string serverVideoPath = Path.Combine(Utils.Env.KtvPath, "video");
|
||||
|
||||
string localVideoPath = @"D:\video";
|
||||
|
||||
if (!Directory.Exists(serverVideoPath))
|
||||
{
|
||||
Console.WriteLine("未連接到 SVR,使用本地影片");
|
||||
LoadLocalVideoFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 確認本地文件夾是否存在(不存在則創立)
|
||||
if (!Directory.Exists(localVideoPath))
|
||||
{
|
||||
Directory.CreateDirectory(localVideoPath);
|
||||
}
|
||||
|
||||
// 獲取服務器和本地的所有文件
|
||||
var serverFiles = Directory.GetFiles(serverVideoPath, "*.mpg")
|
||||
.Select(f => new FileInfo(f))
|
||||
.ToDictionary(f => f.Name, f => f);
|
||||
|
||||
var localFiles = Directory.GetFiles(localVideoPath, "*.mpg")
|
||||
.Select(f => new FileInfo(f))
|
||||
.ToDictionary(f => f.Name, f => f);
|
||||
|
||||
// 3-1. 檢查並更新文件
|
||||
foreach (var serverFile in serverFiles)
|
||||
{
|
||||
bool needsCopy = false;
|
||||
string localFilePath = Path.Combine(localVideoPath, serverFile.Key);
|
||||
|
||||
if (!localFiles.ContainsKey(serverFile.Key))
|
||||
{
|
||||
needsCopy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var localFile = localFiles[serverFile.Key];
|
||||
if (serverFile.Value.LastWriteTime > localFile.LastWriteTime)
|
||||
{
|
||||
needsCopy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsCopy)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Copy(serverFile.Value.FullName, localFilePath, true);
|
||||
Console.WriteLine($"更新影片: {serverFile.Key}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"複製影片失敗 {serverFile.Key}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3-2. 清除本地有但伺服器已經沒有的檔案
|
||||
foreach (var localFile in localFiles)
|
||||
{
|
||||
if (!serverFiles.ContainsKey(localFile.Key))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(localFile.Value.FullName);
|
||||
Console.WriteLine($"刪除本地多餘影片: {localFile.Key}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"刪除影片失敗 {localFile.Key}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 4. 載入更新後的本地文件
|
||||
LoadLocalVideoFiles();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"更新影片失敗:{ex.Message}");
|
||||
LoadLocalVideoFiles(); // 出錯時使用本地文件
|
||||
}
|
||||
LoadLocalVideoFiles();
|
||||
}
|
||||
|
||||
// 將原本的本地文件載入邏輯抽取為單獨的方法
|
||||
@ -1642,74 +1557,33 @@ namespace DualScreenDemo
|
||||
{
|
||||
try
|
||||
{
|
||||
string videoDirectory = @"D:\video\";
|
||||
string[] videoFiles = Directory.GetFiles(videoDirectory, "*.mpg");
|
||||
string[] videoFiles = Directory.GetFiles(@"D:\video\", "*.mpg");
|
||||
string pattern = @"^(?<songNumber>\d+)-.*?-(?<songName>[^-]+)-";
|
||||
|
||||
foreach (var songPath in videoFiles)
|
||||
{
|
||||
string fileName = Path.GetFileNameWithoutExtension(songPath);
|
||||
Match match = Regex.Match(fileName, pattern);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
string songNumber = match.Groups["songNumber"].Value;
|
||||
string songName = match.Groups["songName"].Value;
|
||||
|
||||
SongData song = new SongData(
|
||||
songNumber, // songNumber
|
||||
//"", // songNumberB
|
||||
songName, // song
|
||||
//0, // songLength
|
||||
"", // artistA
|
||||
"", // artistB
|
||||
"", // filename
|
||||
//"", // category
|
||||
//DateTime.Now, // dateAdded
|
||||
songPath, // songFilePathHost1
|
||||
"", // songFilePathHost2
|
||||
"", // songFilePathHost3
|
||||
"", // songFilePathHost4
|
||||
"", // songFilePathHost5
|
||||
//"", // songFilePathHost6
|
||||
//"", // songFilePathHost7
|
||||
//"", // songFilePathHost8
|
||||
//"", // songFilePathHost9
|
||||
//"", // songFilePathHost10
|
||||
//"", // humanVoice
|
||||
//"", // songType
|
||||
1 // priority
|
||||
);
|
||||
publicSongList.Add(song);
|
||||
}
|
||||
else
|
||||
{
|
||||
SongData song = new SongData(
|
||||
"", // songNumber
|
||||
//"", // songNumberB
|
||||
"", // song
|
||||
//0, // songLength
|
||||
"", // artistA
|
||||
"", // artistB
|
||||
"", // filename
|
||||
//"", // category
|
||||
//DateTime.Now, // dateAdded
|
||||
songPath, // songFilePathHost1
|
||||
"", // songFilePathHost2
|
||||
"", // songFilePathHost3
|
||||
"", // songFilePathHost4
|
||||
"", // songFilePathHost5
|
||||
//"", // songFilePathHost6
|
||||
//"", // songFilePathHost7
|
||||
//"", // songFilePathHost8
|
||||
//"", // songFilePathHost9
|
||||
//"", // songFilePathHost10
|
||||
//"", // humanVoice
|
||||
//"", // songType
|
||||
1 // priority
|
||||
);
|
||||
publicSongList.Add(song);
|
||||
string songNumber = "";
|
||||
string songName = "";
|
||||
if (match.Success){
|
||||
songNumber = match.Groups["songNumber"].Value;
|
||||
songName = match.Groups["songName"].Value;
|
||||
}
|
||||
SongData song = new SongData(
|
||||
songNumber, // songNumber
|
||||
songName, // song
|
||||
"", // artistA
|
||||
"", // artistB
|
||||
"", // filename
|
||||
songPath, // songFilePathHost1
|
||||
"", // songFilePathHost2
|
||||
"", // songFilePathHost3
|
||||
"", // songFilePathHost4
|
||||
"", // songFilePathHost5
|
||||
1 // priority
|
||||
);
|
||||
publicSongList.Add(song);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -36,6 +36,7 @@ namespace DualScreenDemo
|
||||
|
||||
//Console.WriteLine("正在與中控取得聯繫...");
|
||||
var sender = new heartbeatSender();
|
||||
var cherker =new DataCheck.DataChecker();
|
||||
|
||||
try
|
||||
{
|
||||
@ -80,7 +81,7 @@ namespace DualScreenDemo
|
||||
|
||||
// 在完整初始化後檢查狀態
|
||||
InitializeSecondaryScreen();
|
||||
|
||||
|
||||
WatchDog _watchDog = new WatchDog(
|
||||
() => VideoPlayerForm.Instance.GetCurrentVideoStatus(),
|
||||
() => primaryForm.IsAppResponsive()
|
||||
@ -91,7 +92,7 @@ namespace DualScreenDemo
|
||||
{
|
||||
_watchDog.Stop();
|
||||
};
|
||||
|
||||
|
||||
|
||||
primaryForm.Show();
|
||||
Application.Run(primaryForm);
|
||||
|
Loading…
x
Reference in New Issue
Block a user