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
@@ -0,0 +1,229 @@
# SignUpImport - 新增「重複檢查」功能
## 功能概述
匯入參加人員時,若「姓名+手機號」的組合在同一活動中已經存在,則自動跳過該記錄,避免重複匯入。
## 實現細節
### 1. 後端修改 (SignUpService.asmx.cs)
#### ConfirmImport 方法增強
```csharp
public BaseResponse ConfirmImport(int courseID, List<SignUpItem> items)
{
// 1. 查詢現有參加人員(同一活動)
SignUpList existingSignups = dac.Select(
noInputReturnAll: true,
CourseID: courseID,
...
);
// 2. 建立重複檢查集合
HashSet<string> existingCombinations = new HashSet<string>();
foreach (var signup in existingSignups)
{
string key = CreateCompositeKey(signup.Name, signup.Mobile);
existingCombinations.Add(key);
}
// 3. 逐筆檢查並匯入
foreach (var item in items)
{
string compositeKey = CreateCompositeKey(item.Name, item.Mobile);
if (existingCombinations.Contains(compositeKey))
{
// 跳過重複記錄
skippedCount++;
skippedRecords.Add($"{item.Name} ({item.Mobile})");
continue;
}
// 插入新記錄
dac.InsertOne(item);
existingCombinations.Add(compositeKey); // 加入集合,避免批次內重複
}
}
```
#### 複合鍵生成
```csharp
private string CreateCompositeKey(string name, string mobile)
{
return (name ?? "").Trim() + "|" + (mobile ?? "").Trim();
}
```
### 2. 前端修改 (SignUpImport.aspx)
#### 匯入結果顯示
```html
<!-- 顯示成功、跳過、失敗的統計 -->
<span>成功:{{ importResult.details.SuccessCount }} 筆</span>
<span v-if="importResult.details.SkippedCount > 0">跳過:{{ importResult.details.SkippedCount }} 筆</span>
<span v-if="importResult.details.ErrorCount > 0">失敗:{{ importResult.details.ErrorCount }} 筆</span>
<!-- 跳過記錄詳情 -->
<div class="skipped-records" v-if="importResult.details.SkippedRecords && importResult.details.SkippedRecords.length > 0">
<div class="skipped-title">❌ 跳過的重複記錄:</div>
<div class="skipped-list">
<div class="skipped-item" v-for="record in importResult.details.SkippedRecords.slice(0, 10)">
{{ record }}
</div>
<div v-if="importResult.details.SkippedRecords.length > 10">
... 還有 {{ importResult.details.SkippedRecords.length - 10 }} 筆
</div>
</div>
</div>
```
### 3. 樣式增強 (SignUpImport.css)
#### 跳過記錄樣式
```css
.skipped-records {
margin-top: var(--spacing-md);
padding-top: var(--spacing-md);
border-top: 1px solid #ddd;
}
.skipped-title {
color: #f57c00;
font-weight: 600;
margin-bottom: 8px;
font-size: 14px;
}
.skipped-item {
color: #f57c00;
font-size: 13px;
margin-bottom: 4px;
padding-left: 20px;
position: relative;
}
.skipped-item::before {
content: '⊘ ';
position: absolute;
left: 0;
}
```
## 工作流程
```
上傳 Excel 檔案
後端驗證(FileUploadHandler.ashx
├─ 檢查欄位格式
├─ 驗證必填欄位
└─ 返回預覽 (✓/✗ 狀態)
前端顯示預覽(可編輯)
├─ 顯示有效列(✓)
├─ 顯示錯誤列(✗)和錯誤訊息
└─ 統計有效筆數
使用者確認匯入
後端執行匯入(ConfirmImport
├─ 查詢現有參加人員 (同一活動)
├─ 建立重複檢查集合 (Name|Mobile)
├─ 逐筆檢查:
│ ├─ 若重複 → 跳過並記錄
│ └─ 若不重複 → 插入並加入集合
└─ 返回結果統計
前端顯示結果
├─ 成功:X 筆
├─ 跳過:Y 筆(列出跳過的記錄)
└─ 失敗:Z 筆(列出失敗原因)
```
## 回傳資料結構
### ConfirmImport Response
```javascript
{
Success: true,
Message: "成功匯入 10 筆資料,跳過 3 筆重複資料,失敗 0 筆",
Data: {
SuccessCount: 10, // 成功新增筆數
SkippedCount: 3, // 跳過(重複)筆數
ErrorCount: 0, // 失敗筆數
Errors: [], // 失敗詳情
SkippedRecords: [ // 跳過記錄詳情
"王小明 (0912345678)",
"李美麗 (0923456789)",
"張大衛 (0934567890)"
]
}
}
```
## 重複檢查邏輯
### 檢查範圍
- **範圍**:同一活動內
- **檢查欄位**:姓名 (Name) + 手機號 (Mobile)
- **大小寫敏感**:否(轉換為小寫比較)
- **空白敏感**:否(.Trim() 處理)
### 複合鍵格式
```
key = "王小明|0912345678"
```
### 重複判定規則
```
if (Name.Trim() == "王小明" AND Mobile.Trim() == "0912345678")
{
// 認為重複,跳過
}
```
## 使用者體驗
### 成功案例
```
成功匯入 20 筆資料,跳過 5 筆重複資料
跳過的重複記錄:
⊘ 王小明 (0912345678)
⊘ 李美麗 (0923456789)
⊘ 張大衛 (0934567890)
... 還有 2 筆
```
### 視覺反饋
- **成功** → 綠色背景 (✓)
- **跳過** → 橙色文字 (⊘)
- **失敗** → 紅色文字 (✗)
## 相關檔案修改
| 檔案 | 修改內容 |
|-----|--------|
| `Services/SignUpService.asmx.cs` | ConfirmImport 方法新增重複檢查邏輯 + CreateCompositeKey 方法 |
| `Forms/SignUpImport.aspx` | 匯入結果顯示新增跳過統計和跳過記錄列表 |
| `Content/SignUpImport.css` | 新增 .skipped-records 和相關樣式 |
| `Scripts/SignUpImport.js` | 無修改(後端自動處理)|
## 性能考量
### 算法複雜度
- **時間複雜度**:O(n) 其中 n = 現有記錄數 + 匯入記錄數
- **空間複雜度**O(n) 用於 HashSet
### 優化點
1. 使用 `HashSet<T>` 而非 ListO(1) 查詢而非 O(n)
2. 同時檢查「現有記錄」和「同批次內記錄」,避免同批次重複
## 測試清單
- [ ] 匯入無重複資料 → 全部成功
- [ ] 匯入有部分重複資料 → 成功 + 跳過
- [ ] 匯入全部重複資料 → 全部跳過
- [ ] 同批次內有重複 → 跳過後續重複
- [ ] 驗證錯誤 + 重複混合 → 正確統計每種情況
- [ ] 驗證跳過記錄列表正確顯示
- [ ] 驗證成功/跳過/失敗的計數準確