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
+305
View File
@@ -0,0 +1,305 @@
<%@ Page Title="課程參加人員" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="SignUpList.aspx.cs" Inherits="報到系統.Forms.SignUpList" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<link href="<%= ResolveUrlWithSysVer("~/Content/SignUpList.css") %>" rel="stylesheet" type="text/css" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div id="signUpApp" class="page-container">
<div class="page-header">
<h1 class="page-title">課程參加人員</h1>
</div>
<!-- 課程選擇面板 -->
<div class="search-panel">
<div class="search-row">
<div class="search-field-inline w-6">
<label class="search-label-inline">選擇課程</label>
<div class="search-input-group">
<select v-model="selectedCourseID" class="search-input" @change="onCourseSelected">
<option value="">-- 請選擇課程 --</option>
<option v-for="course in courses" :key="course.ID" :value="course.ID">
{{ course.CourseName }} ({{ $format.date(course.CourseDate) }})
</option>
</select>
<label class="search-checkbox-label">
<input type="checkbox" v-model="includeClosed"> 包含已結案
</label>
</div>
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">序號</label>
<input type="number" v-model.number="search.seqNo" class="search-input" placeholder="請輸入序號" @keyup.enter="performSearch">
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">姓名搜尋</label>
<input type="text" v-model="search.name" class="search-input" placeholder="請輸入姓名" @keyup.enter="performSearch">
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">手機搜尋</label>
<input type="text" v-model="search.mobile" class="search-input" placeholder="請輸入手機號" @keyup.enter="performSearch">
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">身分別</label>
<select v-model="search.idType" class="search-input">
<option value="">-- 全部 --</option>
<option value="___EMPTY___">-- 未輸入 --</option>
<option value="失業給付">失業給付</option>
<option value="一般民眾">一般民眾</option>
<option value="青年尋職">青年尋職</option>
</select>
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">身分證字號</label>
<div class="search-input-group">
<input type="text" v-model="search.idNumber" class="search-input" placeholder="請輸入身分證字號" @keyup.enter="performSearch">
<label class="search-checkbox-label">
<input type="checkbox" v-model="search.idNumberEmpty"> 未輸入
</label>
</div>
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">餐點</label>
<select v-model="search.mealType" class="search-input">
<option value="">-- 全部 --</option>
<option value="___EMPTY___">-- 未輸入 --</option>
<option value="素食">素食</option>
<option value="非素食">非素食</option>
<option value="不用餐">不用餐</option>
</select>
</div>
<div class="search-field-inline w-3">
<label class="search-label-inline">電子郵件</label>
<div class="search-input-group">
<input type="text" v-model="search.email" class="search-input" placeholder="請輸入電子郵件" @keyup.enter="performSearch">
<label class="search-checkbox-label">
<input type="checkbox" v-model="search.emailEmpty"> 未輸入
</label>
</div>
</div>
</div>
<div class="search-actions">
<button class="btn btn-secondary" @click="clearSearch">清除</button>
<button class="btn btn-primary" @click="performSearch">搜尋</button>
</div>
</div>
<!-- 搜尋結果 -->
<div class="result-panel" v-if="selectedCourseID">
<div class="result-header">
<span class="result-title">參加人員清單</span>
<div class="header-actions">
<!-- 批發簡訊功能區 -->
<div class="sms-send-compact">
<span class="sms-selected-count">發送簡訊已選 {{ selectedIds.length }} 人</span>
<button class="btn btn-secondary btn-sm" @click="clearSmsSelection"
:disabled="selectedIds.length === 0">清除已選</button>
<button class="btn btn-primary btn-sm" @click="sendSmsBatch"
:disabled="selectedIds.length === 0 || sendingSmsBatch">
{{ sendingSmsBatch ? '發送中...' : '發送簡訊' }}
</button>
<button class="btn btn-secondary btn-sm" @click="checkBalance">查詢餘額</button>
</div>
</div>
</div>
<table class="result-table">
<thead>
<tr>
<th class="text-center" style="width: 50px;">
<input type="checkbox" v-model="selectAllCurrentPage" @change="toggleSelectAll" :indeterminate="hasIndeterminate">
</th>
<th class="text-center" style="width: 50px;">序號</th>
<th class="text-center">姓名</th>
<th class="text-center">性別</th>
<th class="text-center">手機號</th>
<th class="text-center">身分別</th>
<th class="text-center">身分證字號</th>
<th class="text-center">餐點</th>
<th class="text-center">電子郵件</th>
<th class="text-center">失業給付認定次數</th>
<th class="text-center">報名方式</th>
<th class="text-center">簡訊發送</th>
<th class="text-center">簽到時間</th>
<th class="text-center">簽退時間</th>
<th class="text-center">操作
<button class="btn btn-success btn-sm" style="margin-left: 10px;" @click="openAddModal">新增</button>
</th>
</tr>
</thead>
<tbody>
<tr v-if="loading">
<td colspan="15" class="empty-message">載入中...</td>
</tr>
<tr v-else-if="signups.length === 0">
<td colspan="15" class="empty-message">查無資料</td>
</tr>
<tr v-else v-for="item in signups" :key="item.ID">
<td class="text-center">
<input type="checkbox" :value="item.ID" v-model="selectedIds" @change="updateSelectAllState">
</td>
<td class="text-center">{{ item.SeqNo }}</td>
<td>{{ item.Name }}</td>
<td class="text-center">{{ item.Gender || '未設定' }}</td>
<td class="text-center">{{ item.Mobile }}</td>
<td class="text-center">{{ item.IDType || '未設定' }}</td>
<td class="text-center">{{ item.IDNumber || '未填' }}</td>
<td class="text-center">{{ item.MealType || '未設定' }}</td>
<td class="text-center">{{ item.Email || '未填' }}</td>
<td class="text-center">{{ item.LossJobTimes !== null && item.LossJobTimes !== undefined ? item.LossJobTimes : '未填' }}</td>
<td class="text-center">{{ item.SignUpType || '未設定' }}</td>
<td class="text-center">{{ item.MessageSending }}</td>
<td class="text-center">{{ $format.dateTime(item.CheckInTime) }}</td>
<td class="text-center">{{ $format.dateTime(item.CheckOutTime) }}</td>
<td class="text-center">
<button class="btn btn-primary btn-sm" @click="openEditModal(item)">更正</button>
<button class="btn btn-danger btn-sm" @click="deleteSignUp(item)">刪除</button>
</td>
</tr>
</tbody>
</table>
<!-- 分頁 -->
<div class="pagination" v-if="totalCount > 0">
<div class="pagination-control">
<button class="btn btn-secondary btn-sm" :disabled="currentPage === 1" @click="goToFirstPage">第一頁</button>
<button class="btn btn-secondary btn-sm" :disabled="currentPage === 1" @click="goToPage(currentPage - 1)">上一頁</button>
<span class="pagination-label">第</span>
<select v-model.number="currentPage" class="pagination-select" @change="loadSignUps">
<option v-for="page in totalPages" :key="page" :value="page">{{ page }}</option>
</select>
<span class="pagination-label">頁</span>
<button class="btn btn-secondary btn-sm" :disabled="currentPage === totalPages" @click="goToPage(currentPage + 1)">下一頁</button>
<button class="btn btn-secondary btn-sm" :disabled="currentPage === totalPages" @click="goToLastPage">最後頁</button>
<span class="pagination-label">|</span>
<span class="pagination-label">每頁</span>
<select v-model.number="pageSize" class="pagination-select" @change="onPageSizeChanged">
<option :value="10">10</option>
<option :value="20">20</option>
<option :value="50">50</option>
<option :value="100">100</option>
</select>
<span class="pagination-label">筆,共</span>
<span class="pagination-count">{{ totalCount }}</span>
<span class="pagination-label">筆</span>
</div>
</div>
</div>
<div class="result-panel" v-else>
<div class="empty-message" style="padding: 40px;">請先選擇要查詢的課程</div>
</div>
<!-- 新增/更正彈窗 -->
<div class="modal" :class="{ show: showModal }">
<div class="modal-dialog">
<div class="modal-header">
<h3 class="modal-title">{{ isNewMode ? '新增參加人員' : '更正參加人員' }}</h3>
</div>
<div class="modal-body">
<!-- 第一行:姓名、手機號 -->
<div class="form-row">
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline required">姓名</label>
<input type="text" v-model="editItem.Name" class="form-control" maxlength="100" placeholder="請輸入姓名">
</div>
<div class="error-message" v-if="validationErrors.Name">{{ validationErrors.Name }}</div>
</div>
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline required">手機號</label>
<input type="text" v-model="editItem.Mobile" class="form-control" maxlength="20" placeholder="請輸入手機號">
</div>
<div class="error-message" v-if="validationErrors.Mobile">{{ validationErrors.Mobile }}</div>
</div>
</div>
<!-- 第二行:身分別、身分證字號 -->
<div class="form-row">
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">身分別</label>
<select v-model="editItem.IDType" class="form-control">
<option value="">-- 請選擇 --</option>
<option value="失業給付">失業給付</option>
<option value="一般民眾">一般民眾</option>
<option value="青年尋職">青年尋職</option>
</select>
</div>
</div>
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">身分證字號</label>
<input type="text" v-model="editItem.IDNumber" class="form-control" maxlength="20" placeholder="請輸入身分證字號">
</div>
<div class="error-message" v-if="validationErrors.IDNumber">{{ validationErrors.IDNumber }}</div>
</div>
</div>
<!-- 第三行:餐點、報名方式 -->
<div class="form-row">
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">餐點</label>
<select v-model="editItem.MealType" class="form-control">
<option value="">-- 請選擇 --</option>
<option value="素食">素食</option>
<option value="非素食">非素食</option>
<option value="不用餐">不用餐</option>
</select>
</div>
</div>
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">報名方式</label>
<select v-model="editItem.SignUpType" class="form-control">
<option value="">-- 請選擇 --</option>
<option value="預約">預約</option>
<option value="現場">現場</option>
</select>
</div>
</div>
</div>
<!-- 第四行:電子郵件 -->
<div class="form-row">
<div class="form-col-100">
<div class="form-group-inline">
<label class="form-label-inline">電子郵件</label>
<input type="text" v-model="editItem.Email" class="form-control" maxlength="100" placeholder="請輸入電子郵件">
</div>
<div class="error-message" v-if="validationErrors.Email">{{ validationErrors.Email }}</div>
</div>
</div>
<!-- 第五行:性別、失業給付認定次數 -->
<div class="form-row">
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">性別</label>
<select v-model="editItem.Gender" class="form-control">
<option value="">-- 請選擇 --</option>
<option value="男">男</option>
<option value="女">女</option>
<option value="其他">其他</option>
</select>
</div>
</div>
<div class="form-col-50">
<div class="form-group-inline">
<label class="form-label-inline">失業給付認定次數</label>
<input type="number" v-model.number="editItem.LossJobTimes" class="form-control" min="0" placeholder="請輸入次數">
</div>
<div class="error-message" v-if="validationErrors.LossJobTimes">{{ validationErrors.LossJobTimes }}</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" @click="closeModal">取消</button>
<button class="btn btn-primary" @click="saveSignUp">存檔</button>
</div>
</div>
</div>
</div>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="script" runat="server">
<script src="<%= ResolveUrlWithSysVer("~/Scripts/SignUpList.js") %>"></script>
</asp:Content>