PublicSongChecker 完成

還原 點歌流
20250704
This commit is contained in:
jasonchenwork 2025-07-04 18:19:41 +08:00
parent 8f456c347d
commit c1437a02d9
13 changed files with 135 additions and 375 deletions

View File

@ -7,8 +7,6 @@ namespace DBObj
public string ArtistA { get; set; }
public string ArtistB { get; set; }
public string FileName { get; set; }
public string SongFilePathHost1 { get; set; }
public string SongFilePathHost2 { get; set; }
public string ArtistASimplified { get; set; }
public string ArtistBSimplified { get; set; }
public string SongSimplified { get; set; }
@ -42,19 +40,24 @@ namespace DBObj
}
*/
public SongData(string songNumber, string song, string artistA, string artistB, string filename, string songFilePathHost1, string songFilePathHost2, string artistASimplified, string artistBSimplified, string songSimplified, int humanVoice)
public SongData(string songNumber, string song, string filename, int humanVoice)
{
SongNumber = songNumber;
Song = song;
FileName = filename;
HumanVoice = humanVoice;
}
public SongData(string songNumber, string song, string artistA, string artistB, string filename, string artistASimplified, string artistBSimplified, string songSimplified, int humanVoice)
{
SongNumber = songNumber;
Song = song;
ArtistA = artistA;
ArtistB = artistB;
FileName = filename;
SongFilePathHost1 = songFilePathHost1;
SongFilePathHost2 = songFilePathHost2;
FileName = filename;
ArtistASimplified = artistASimplified;
ArtistBSimplified = artistBSimplified;
SongSimplified = songSimplified;
HumanVoice = humanVoice;
HumanVoice = humanVoice;
}
public override string ToString()

View File

@ -1,80 +0,0 @@
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}");
}
}
}
}
}
}

View File

@ -786,8 +786,7 @@ namespace DualScreenDemo
{
song.Song,
song.ArtistA,
song.SongFilePathHost1,
song.SongFilePathHost2,
song.FileName,
PlayState = playState.HasValue ? (playState.Value == PlayState.Playing ? "播放中" : "播放完畢") : null // 如果状态为 null不返回状态信息
};
}
@ -1118,21 +1117,11 @@ namespace DualScreenDemo
song.Song,
song.ArtistA,
song.SongNumber,
//song.Category,
//song.PhoneticNotation,
//song.PinyinNotation,
//song.ArtistAPhonetic,
//song.ArtistBPhonetic,
song.ArtistASimplified,
song.ArtistBSimplified,
song.SongSimplified,
//song.SongGenre,
//song.ArtistAPinyin,
//song.ArtistBPinyin,
song.HumanVoice,
//song.AddedTime,
song.SongFilePathHost1,
song.SongFilePathHost2 // 例如语言类别等信息
song.FileName
})
.ToList(),
status = "success",

View File

@ -1004,7 +1004,7 @@ private static void SongDisplayTimer_Elapsed(object sender, EventArgs e)
if (songIndex >= 0 && songIndex < totalSongs)
{
selectedSong = LanguageSongList[songIndex];
Console.WriteLine("Adding song to playlist: " + LanguageSongList[songIndex].Song + " " + selectedSong.SongFilePathHost1);
Console.WriteLine("Adding song to playlist: " + LanguageSongList[songIndex].Song + " " + selectedSong.FileName);
// DisplayActionWithSong(currentPage, songIndex, "點播");
@ -1036,7 +1036,7 @@ private static void SongDisplayTimer_Elapsed(object sender, EventArgs e)
if (songIndex < totalSongs)
{
selectedSong = LanguageSongList[songIndex];
Console.WriteLine("Adding song to playlist: " + LanguageSongList[songIndex].Song + " " + selectedSong.SongFilePathHost1 );
Console.WriteLine("Adding song to playlist: " + LanguageSongList[songIndex].Song + " " + selectedSong.FileName );
// DisplayActionWithSong(currentPage, songIndex, "插播");
@ -1120,7 +1120,7 @@ private static void SongDisplayTimer_Elapsed(object sender, EventArgs e)
if (songIndex < totalSongs)
{
selectedSong = LanguageSongList[songIndex];
Console.WriteLine("Adding song to playlist C: " + LanguageSongList[songIndex].Song + " " + selectedSong.SongFilePathHost1);
Console.WriteLine("Adding song to playlist C: " + LanguageSongList[songIndex].Song + " " + selectedSong.FileName);
DisplaySongsWithArrows(currentPage, songIndex);
@ -1531,40 +1531,12 @@ private void DisplayArtists(List<Artist> artists, int page)//歌星點進去後
{
try
{
var filePath1 = songData.SongFilePathHost1;
var filePath2 = songData.SongFilePathHost2;
//var filePath1 = songData.SongFilePathHost1;
//var filePath2 = songData.SongFilePathHost2;
// 之後還要設計成本地的資料夾位置
var filename = songData.FileName;
bool checkpath = false;
string pathToPlay = "";
if (File.Exists(filename))
string pathToPlay = songData.FileName;
if (File.Exists(pathToPlay))
{
pathToPlay = filename;
checkpath = true;
PrimaryForm.WriteLog(String.Format("{0} Using local file: {1}", songData.Song,filename));
}
else if (File.Exists(filePath1))
{
pathToPlay = filePath1;
checkpath = true;
PrimaryForm.WriteLog(String.Format("{0} Using Host1 file: {1}", songData.Song, filePath1));
}
else if (File.Exists(filePath2))
{
pathToPlay = filePath2;
checkpath = true;
PrimaryForm.WriteLog(String.Format("{0} Using Host2 file: {1}", songData.Song, filePath2));
}
else
{
PrimaryForm.WriteLog(String.Format("File not found on hosts: {0}, {1} and {2}", filename, filePath1, filePath2));
}
if (checkpath)
{
//做判定 決定pathToPlay值
//pathToPlay = File.Exists(filePath1) ? filePath1 : filePath2;
bool wasEmpty = PrimaryForm.userRequestedSongs.Count == 0;
PrimaryForm.userRequestedSongs.Add(songData);
@ -1599,19 +1571,13 @@ private void DisplayArtists(List<Artist> artists, int page)//歌星點進去後
try
{
// 從 songData 中取得兩個可能的檔案路徑主機1與主機2
var filePath1 = songData.SongFilePathHost1;
var filePath2 = songData.SongFilePathHost2;
var pathToPlay = songData.FileName;
// 檢查兩個主機上的檔案是否皆不存在
if (!File.Exists(filePath1) && !File.Exists(filePath2))
{
// 若兩個都找不到,寫入 Log 並不加入歌單
PrimaryForm.WriteLog(String.Format("File not found on both hosts: {0} and {1}", filePath1, filePath2));
}
else
if (File.Exists(pathToPlay))
{
// 若其中一個存在,就用第一個存在的那個檔案
var pathToPlay = File.Exists(filePath1) ? filePath1 : filePath2;
Console.WriteLine("path to play" + pathToPlay);
// 檢查目前使用者歌單是否為空

View File

@ -37,23 +37,16 @@ namespace DualScreenDemo{
{
while (reader.Read())
{
string songNumber = reader["song_id"].ToString();
string song = reader["song_name"].ToString();
string artistA = reader["artistA"].ToString();
string artistB = reader["artistB"].ToString();
string fileName = reader["song_filename"].ToString();
string songFilePathHost1 = Path.Combine(@"\\SVR01\e\", fileName);
string songFilePathHost2 = Path.Combine(@"\\SVR02\e\", fileName);
string artistASimplified = reader["artistA_simplified"].ToString();
string artistBSimplified = reader["artistB_simplified"].ToString();
string songSimplified = reader["song_simplified"].ToString();
int humanVoice = Convert.ToInt32(reader["vocal"]);
searchResults.Add(new SongData(
songNumber, song, artistA, artistB,fileName,
songFilePathHost1, songFilePathHost2,
artistASimplified, artistBSimplified,
songSimplified, humanVoice
reader["song_id"].ToString(),
reader["song_name"].ToString(),
reader["artistA"].ToString(),
reader["artistB"].ToString(),
reader["song_filename"].ToString(),
reader["artistA_simplified"].ToString(),
reader["artistB_simplified"].ToString(),
reader["song_simplified"].ToString(),
Convert.ToInt32(reader["vocal"])
));
}
}

View File

@ -120,7 +120,6 @@ namespace DualScreenDemo
public VideoPlayerForm videoPlayerForm;
public List<SongData> currentSongList;
public List<Artist> currentArtistList;
public List<SongData> publicSongList;
public static List<SongData> userRequestedSongs;
public static List<SongData> playedSongsHistory;
public static List<PlayState> playStates;
@ -1546,50 +1545,9 @@ namespace DualScreenDemo
private void LoadSongData()
{
userRequestedSongs = new List<SongData>();
publicSongList = new List<SongData>();
playedSongsHistory = new List<SongData>();
playStates = new List<PlayState>();
LoadLocalVideoFiles();
}
// 將原本的本地文件載入邏輯抽取為單獨的方法
private void LoadLocalVideoFiles()
{
try
{
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);
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)
{
MessageBox.Show($"Failed to read video files: {ex.Message}");
}
}
private Bitmap ResizeImage(Image image, int width, int height)

View File

@ -13,6 +13,7 @@ namespace DualScreenDemo
internal static SerialPortManager serialPortManager;
private static PrimaryForm primaryForm; // 儲存實例的參考
public static string RoomState = Utils.Env.Get("RoomStates", "CLOSE");
public static DataCheck.PublicSongChecker cherker;
[STAThread]
static void Main()
@ -36,7 +37,7 @@ namespace DualScreenDemo
//Console.WriteLine("正在與中控取得聯繫...");
var sender = new heartbeatSender();
var cherker =new DataCheck.DataChecker();
cherker =new DataCheck.PublicSongChecker();
try
{
@ -64,8 +65,8 @@ namespace DualScreenDemo
}
// 啟動服務器
var TCP = new TCPServer();
Task.Run(() => HttpServerManager.StartServer());
Task.Run(() => TCPServerManager.StartServer());
// 註冊事件
Application.ApplicationExit += (sender, e) => SerialPortManager.CloseSerialPortSafely();
@ -82,18 +83,6 @@ namespace DualScreenDemo
// 在完整初始化後檢查狀態
InitializeSecondaryScreen();
WatchDog _watchDog = new WatchDog(
() => VideoPlayerForm.Instance.GetCurrentVideoStatus(),
() => primaryForm.IsAppResponsive()
);
_watchDog.Start();
Console.WriteLine("啟動WatchDog進行監聽");
AppDomain.CurrentDomain.ProcessExit += (s, e) =>
{
_watchDog.Stop();
};
primaryForm.Show();
Application.Run(primaryForm);
@ -161,7 +150,7 @@ namespace DualScreenDemo
primaryForm.videoPlayerForm.Show();
// 初始化公共播放列表
primaryForm.videoPlayerForm.InitializePublicPlaylist(primaryForm.publicSongList);
primaryForm.videoPlayerForm.InitializePublicPlaylist(cherker.GetSongs());
}
}
}
@ -185,7 +174,7 @@ namespace DualScreenDemo
{
primaryForm.videoPlayerForm = new VideoPlayerForm();
// primaryForm.primaryMediaPlayerForm = new PrimaryMediaPlayerForm(primaryForm, primaryForm.secondaryMediaPlayerForm);
primaryForm.videoPlayerForm.InitializePublicPlaylist(primaryForm.publicSongList);
primaryForm.videoPlayerForm.InitializePublicPlaylist(cherker.GetSongs());
primaryForm.videoPlayerForm.Show();
}
}

84
PublicSongChecker.cs Normal file
View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
using DBObj;
namespace DataCheck
{
public class PublicSongChecker
{
private List<SongData> publicSongList = new();
public PublicSongChecker()
{
string serverPath = Utils.Env.GetPath("video", "");
string localPath = @"D:\video";
// 加入你要同步的資料夾
SyncFolder(serverPath, localPath, "video", new[] { ".mpg" });
}
public List<SongData> GetSongs()
{
return publicSongList;
}
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) {
string dest = Path.Combine(localPath, serverFile.Key);
bool needsCopy = !localFiles.ContainsKey(serverFile.Key) ||
serverFile.Value.LastWriteTime > localFiles[serverFile.Key].LastWriteTime;
if (needsCopy) {
try {
File.Copy(serverFile.Value.FullName, dest, true);
Console.WriteLine($"✅ 更新 {label}: {serverFile.Key}");
} catch (Exception ex) {
Console.WriteLine($"❌ 複製 {label} 失敗 {serverFile.Key}: {ex.Message}");
continue; // 如果複製失敗就不加入 SongData
}
}
string fileName = Path.GetFileNameWithoutExtension(serverFile.Key);
Match match = Regex.Match(fileName, @"^(?<songNumber>\d+)-.*?-(?<songName>[^-]+)-");
if (match.Success) {
publicSongList.Add(new SongData(
match.Groups["songNumber"].Value, // songNumber
match.Groups["songName"].Value, // song
Path.Combine(localPath, serverFile.Key), // songFilePathHost1
1 // priority
));
}
}
// 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}");
}
}
}
}
}
}

View File

@ -14,12 +14,14 @@ namespace DualScreenDemo
private const int Port = 1000;
private readonly string hostNameSuffix;
//private bool isProcessingCommand = false;
public TCPServer()
{
listener = new TcpListener(IPAddress.Any, Port);
hostNameSuffix = GetHostNameSuffix();
_ = Task.Run(() => Start());
}
private bool IsFormReady(Form form)
@ -136,11 +138,7 @@ namespace DualScreenDemo
string closePath = @"D:\video\CLOSE.MPG";
if (File.Exists(closePath))
{
SongData closeSong = new SongData(
"0", "結束播放", "", "", "",
closePath, "", "", "", "",
1
);
SongData closeSong = new SongData("0", "結束播放",closePath, 1);
VideoPlayerForm.publicPlaylist = new List<SongData>();
VideoPlayerForm.playingSongList = new List<SongData>();
PrimaryForm.playedSongsHistory = new List<SongData>();

View File

@ -1,11 +0,0 @@
namespace DualScreenDemo
{
public static class TCPServerManager
{
public static void StartServer()
{
TCPServer server = new TCPServer();
server.Start();
}
}
}

View File

@ -612,8 +612,7 @@ namespace DualScreenDemo
if (File.Exists(welcomePath))
{
publicPlaylist.Add(new SongData(
"0", "歡迎光臨", "", "", "", welcomePath,
"", "", "", "", 1
"0", "歡迎光臨", welcomePath, 1
));
}
@ -624,8 +623,7 @@ namespace DualScreenDemo
if (File.Exists(bgmPath))
{
publicPlaylist.Add(new SongData(
i.ToString(), $"背景音樂{i:D2}",
"", "", "", bgmPath, "", "", "", "", 1
i.ToString(), $"背景音樂{i:D2}", bgmPath, 1
));
}
}
@ -638,11 +636,7 @@ namespace DualScreenDemo
foreach (var songPath in videoFiles)
{
string fileName = Path.GetFileNameWithoutExtension(songPath);
publicPlaylist.Add(new SongData(
"0", fileName, "", "", "",
songPath, "", "", "", "",
1
));
publicPlaylist.Add(new SongData("0", fileName,songPath,1));
}
}
@ -769,7 +763,7 @@ namespace DualScreenDemo
var songToPlay = currentPlaylist[currentSongIndex];
// pathToPlay 需要調整
var pathToPlay = File.Exists(songToPlay.SongFilePathHost1) ? songToPlay.SongFilePathHost1 : songToPlay.SongFilePathHost2;
var pathToPlay = songToPlay.FileName;
// 若兩個 host 上都找不到檔案就直接結束
if (!File.Exists(pathToPlay))
@ -966,9 +960,7 @@ namespace DualScreenDemo
string welcomePath = @"D:\video\welcome.mpg";
if (File.Exists(welcomePath))
{
publicPlaylist.Add(new SongData(
"0", "歡迎光臨", "", "", "", welcomePath, "", "", "", "", 1
));
publicPlaylist.Add(new SongData("0", "歡迎光臨", welcomePath, 1));
}
// 添加 BGM 序列
@ -977,10 +969,7 @@ namespace DualScreenDemo
string bgmPath = $@"D:\video\BGM{i:D2}.mpg";
if (File.Exists(bgmPath))
{
publicPlaylist.Add(new SongData(
i.ToString(), $"背景音樂{i:D2}", "", "", "", bgmPath,
"", "", "", "", 1
));
publicPlaylist.Add(new SongData(i.ToString(), $"背景音樂{i:D2}", bgmPath, 1));
}
}
@ -1000,7 +989,7 @@ namespace DualScreenDemo
List<SongData> currentPlaylist = isUserPlaylistPlaying ? playingSongList : publicPlaylist;
if (!currentPlaylist.Any()) return;
var songToPlay = currentPlaylist[currentSongIndex];
var pathToPlay = File.Exists(songToPlay.SongFilePathHost1) ? songToPlay.SongFilePathHost1 : songToPlay.SongFilePathHost2;
var pathToPlay = songToPlay.FileName;
if (!File.Exists(pathToPlay))
{
MessageBox.Show("File does not exist on both hosts.");
@ -1570,9 +1559,7 @@ namespace DualScreenDemo
if (audioTrack1 == -1)
{
audioTrack1 = i;
}
else if (audioTrack2 == -1)
{
} else if (audioTrack2 == -1) {
audioTrack2 = i;
}
@ -1663,19 +1650,8 @@ namespace DualScreenDemo
public void AddSongToPlaylist(SongData songData)
{
try
{
var filePath1 = songData.SongFilePathHost1;
var filePath2 = songData.SongFilePathHost2;
if (!File.Exists(filePath1) && !File.Exists(filePath2))
{
PrimaryForm.WriteLog(String.Format("File not found on both hosts: {0} and {1}", filePath1, filePath2));
return;
}
try{
bool wasEmpty = PrimaryForm.userRequestedSongs.Count == 0;
// 查找所有相同歌曲的索引
var sameNameIndices = new List<int>();
for (int i = 0; i < PrimaryForm.playedSongsHistory.Count; i++)
@ -1745,19 +1721,8 @@ namespace DualScreenDemo
public void InsertSongToPlaylist(SongData songData)
{
try
{
var filePath1 = songData.SongFilePathHost1;
var filePath2 = songData.SongFilePathHost2;
if (!File.Exists(filePath1) && !File.Exists(filePath2))
{
PrimaryForm.WriteLog(String.Format("File not found on both hosts: {0} and {1}", filePath1, filePath2));
return;
}
try{
bool wasEmpty = PrimaryForm.userRequestedSongs.Count == 0;
// 查找所有相同歌曲的索引
var sameNameIndices = new List<int>();
for (int i = 0; i < PrimaryForm.playedSongsHistory.Count; i++)

View File

@ -1,84 +0,0 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using DualScreenDemo.Shared;
public class WatchDog
{
private Func<VideoStatus> getVideoStatus;
private Func<bool> isApplicationResponsive;
private Thread watchdogThread;
private bool running = false;
private double lastPosition = -1;
private int freezeCounter = 0;
public WatchDog(Func<VideoStatus> getVideoPositionFunc, Func<bool> isAppResponsiveFunc)
{
getVideoStatus = getVideoPositionFunc;
isApplicationResponsive = isAppResponsiveFunc;
}
public void Start()
{
running = true;
watchdogThread = new Thread(Run);
watchdogThread.IsBackground = true;
watchdogThread.Start();
}
public void Stop()
{
running = false;
watchdogThread?.Join();
}
private void Run()
{
while (running)
{
var status = getVideoStatus(); // 改用 getVideoStatus 取得完整狀態
bool responsive = isApplicationResponsive();
if (!status.IsGraphOk)
{
Log($"影片圖表異常: {status.LastError}");
}
else if(status.PlayState != "Paused")
{
double currentPosition = status.PositionSeconds;
if (Math.Abs(currentPosition - lastPosition) < 0.001)
{
freezeCounter++;
if (freezeCounter >= 3)
{
Log($"影片疑似卡死3次位置沒變位置={currentPosition:F2}秒,播放狀態={status.PlayState}");
freezeCounter = 0; // 記得 reset
}
}
else
{
freezeCounter = 0;
}
lastPosition = currentPosition;
}
if (!responsive)
{
Log("UI 疑似卡死Invoke 失敗)");
}
Thread.Sleep(5000);
}
}
private void Log(string message)
{
string logFilePath = Path.Combine("txt", "watchdog_log.txt");
File.AppendAllText(logFilePath, $"{DateTime.Now}: {message}{Environment.NewLine}");
}
}

View File

@ -71,11 +71,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<!-- 複製資料夾 foods -->
<Content Include="foods\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<!-- 複製資料夾 db -->
<Content Include="db\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -90,11 +85,6 @@
<Content Include="themes\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<!-- 複製資料夾 news -->
<Content Include="news\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<!-- 複製資料夾 sounds -->
<Content Include="sounds\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>