chore: 首次簽入 Thinkyu ASP.NET 專案

- 加入 Visual Studio / ASP.NET .gitignore
- 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
This commit is contained in:
2026-09-10 09:42:37 +08:00
commit 577060bc78
2496 changed files with 501389 additions and 0 deletions
+256
View File
@@ -0,0 +1,256 @@
// 課程報表 - Vue.js 應用程式
// 檔案位置:Scripts/ClassesReport.js
// ========================================
(() => {
'use strict';
new Vue({
el: '#classesReportApp',
data: {
// API
apiName: 'ClassesService',
// 搜尋條件
search: {
courseCode: '',
courseName: '',
courseDate1: '',
courseDate2: '',
courseLocation: '',
projectID: '',
projectName: '',
closed: '',
timeFormat: 'datetime'
},
// 搜尋結果
classes: [],
loading: false,
// 分頁
currentPage: 1,
pageSize: 20,
totalCount: 0,
// 專案自動完成
projectSuggestions: [],
showProjectSuggestions: false,
projectSearchTimeout: null,
// 匯出
exporting: false,
exportingId: 0
},
computed: {
totalPages() {
return Math.ceil(this.totalCount / this.pageSize);
}
},
mounted() {
console.log('[ClassesReport] Vue app mounted');
// 初始載入資料
this.performSearch();
},
methods: {
/**
* 執行搜尋
*/
async performSearch() {
this.currentPage = 1;
await this.fetchClasses();
},
/**
* 查詢課程列表
*/
async fetchClasses() {
this.loading = true;
try {
const response = await this.$api.call(this.apiName, 'SearchClasses', {
pageIndex: this.currentPage,
pageSize: this.pageSize,
courseCode: this.search.courseCode,
courseName: this.search.courseName,
courseDate1: this.search.courseDate1 || null,
courseDate2: this.search.courseDate2 || null,
courseLocation: this.search.courseLocation,
projectID: this.search.projectID,
closed: this.search.closed === '' ? null : this.search.closed === 'true'
});
if (response.Success) {
this.classes = response.Data || [];
this.totalCount = response.TotalCount || 0;
console.log('[ClassesReport] 載入成功,共 ' + this.totalCount + ' 筆');
} else {
this.$message.error(response.Message || '查詢失敗');
this.classes = [];
this.totalCount = 0;
}
} catch (error) {
console.error('[ClassesReport] 載入錯誤:', error);
this.$message.error('載入資料發生錯誤');
this.classes = [];
this.totalCount = 0;
} finally {
this.loading = false;
}
},
/**
* 清除搜尋條件
*/
clearSearch() {
this.search = {
courseCode: '',
courseName: '',
courseDate1: '',
courseDate2: '',
courseLocation: '',
projectID: '',
projectName: '',
closed: '',
timeFormat: 'datetime'
};
this.performSearch();
},
/**
* 搜尋專案
*/
searchProjects(event) {
const query = this.search.projectName.trim();
if (query.length === 0) {
this.projectSuggestions = [];
return;
}
clearTimeout(this.projectSearchTimeout);
this.projectSearchTimeout = setTimeout(async () => {
try {
const response = await this.$api.call(this.apiName, 'SearchProjects', {
keyword: query
});
if (response.Success) {
this.projectSuggestions = response.Data || [];
} else {
this.projectSuggestions = [];
}
} catch (error) {
console.error('[ClassesReport] 搜尋專案出錯:', error);
this.projectSuggestions = [];
}
}, 300);
},
/**
* 選擇專案
*/
selectProject(project) {
this.search.projectID = project.Value;
this.search.projectName = project.Value + ' ' + project.Name;
this.projectSuggestions = [];
this.showProjectSuggestions = false;
},
/**
* 隱藏專案建議
*/
hideProjectSuggestions() {
setTimeout(() => {
this.showProjectSuggestions = false;
}, 200);
},
/**
* 上一頁
*/
previousPage() {
if (this.currentPage > 1) {
this.currentPage--;
this.fetchClasses();
}
},
/**
* 下一頁
*/
nextPage() {
if (this.currentPage < this.totalPages) {
this.currentPage++;
this.fetchClasses();
}
},
/**
* 匯出報表
*/
async exportReport(courseID) {
if (this.exporting) {
return;
}
this.exporting = true;
this.exportingId = courseID;
try {
const response = await this.$api.call(this.apiName, 'ExportClassesReport', {
classesID: courseID,
timeFormat: this.search.timeFormat
});
if (response.Success) {
// 下載檔案
const fileBase64 = response.Data.FileBase64;
const fileName = response.Data.FileName;
const byteCharacters = atob(fileBase64);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
// 建立下載連結
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('匯出成功');
} else {
this.$message.error('匯出失敗:' + response.Message);
}
} catch (error) {
console.error('[ClassesReport] 匯出報表出錯:', error);
this.$message.error('匯出報表出錯:' + error.message);
} finally {
this.exporting = false;
this.exportingId = 0;
}
},
/**
* 呼叫後端 WebService
*/
async callWebService(methodName, params) {
const url = `${this.apiName}.asmx/${methodName}`;
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
};
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
}
});
})();