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,221 @@
<%@ Page Title="簡訊帳號管理" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="MessageAccountManage.aspx.cs" Inherits="報到系統.Forms.MessageAccountManage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<link href="<%= ResolveUrlWithSysVer("~/Content/MessageAccountManage.css") %>" rel="stylesheet" type="text/css" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div id="messageAccountManageApp" class="page-container">
<div class="page-header">
<h1 class="page-title">簡訊帳號管理</h1>
<p class="page-description">管理計畫的簡訊發送帳號密碼</p>
</div>
<!-- 目前預設平台區塊(含 inline 切換) -->
<div style="margin-bottom:12px; border:1px solid #c8d8f8; border-radius:4px; background:#f0f4ff; overflow:hidden;">
<div style="padding:10px 16px; display:flex; align-items:center; gap:16px;">
<span>目前預設平台:<strong>{{ currentPlatform ? currentPlatform.PlatformName + '' + currentPlatform.PlatformCode + '' : '載入中...' }}</strong></span>
<button type="button" class="btn btn-secondary btn-sm" @click="showSwitchPanel = !showSwitchPanel">
{{ showSwitchPanel ? '收合' : '切換平台' }}
</button>
</div>
<div v-if="showSwitchPanel" style="padding:10px 16px 14px; border-top:1px solid #c8d8f8; background:#fff; display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
<label style="margin:0;">切換為:</label>
<select v-model="switchPlatformCode" class="form-control" style="width:220px;">
<option v-for="p in platforms" :key="p.PlatformCode" :value="p.PlatformCode">{{ p.PlatformName }}{{ p.PlatformCode }}</option>
</select>
<button type="button" class="btn btn-primary btn-sm" @click="setCurrentPlatform">確認切換</button>
<button type="button" class="btn btn-secondary btn-sm" @click="showSwitchPanel = false">取消</button>
</div>
</div>
<!-- 平台設定區塊 -->
<div class="search-panel" style="margin-bottom:12px;">
<div style="display:flex; align-items:center; cursor:pointer; user-select:none;" @click="showPlatformSettings = !showPlatformSettings">
<strong>平台帳號設定</strong>
<span style="margin-left:8px;">{{ showPlatformSettings ? '▲' : '▼' }}</span>
</div>
<div v-if="showPlatformSettings" style="margin-top:12px;">
<div v-for="p in platforms" :key="p.PlatformCode" style="display:flex; align-items:center; gap:12px; margin-bottom:10px; flex-wrap:wrap;">
<span style="min-width:80px; font-weight:bold;">{{ p.PlatformName }}</span>
<input type="text" v-model="p.Account" class="form-control" style="width:200px;" placeholder="主帳號">
<input :type="p.showPwd ? 'text' : 'password'" v-model="p.Password" class="form-control" style="width:200px;" placeholder="主密碼">
<button type="button" class="btn-template" @click="p.showPwd = !p.showPwd">{{ p.showPwd ? '隱藏' : '顯示' }}</button>
<button type="button" class="btn btn-primary btn-sm" @click="savePlatformSetting(p)">儲存</button>
</div>
</div>
</div>
<!-- 搜尋面板 -->
<div class="search-panel">
<div class="search-row">
<div class="search-field-inline autocomplete-field w-6">
<label class="search-label-inline">計畫</label>
<div class="autocomplete-container" style="flex: 1;">
<input
type="text"
v-model="search.projectName"
@input="searchProjects"
@focus="showProjectSuggestions = true"
@blur="hideProjectSuggestions"
class="search-input autocomplete-input"
placeholder="請輸入計畫編號或名稱">
<div class="autocomplete-dropdown" v-if="showProjectSuggestions && projectSuggestions.length > 0">
<div
v-for="suggestion in projectSuggestions"
:key="suggestion.Value"
class="autocomplete-item"
@click="selectProject(suggestion)">
<span class="autocomplete-value">{{ suggestion.Value }}</span>
<span class="autocomplete-name">{{ suggestion.Name }}</span>
</div>
</div>
</div>
</div>
<div class="search-field-inline w-4">
<label class="search-label-inline">平台</label>
<select v-model="search.platformCode" class="search-input">
<option value="">全部</option>
<option v-for="p in platforms" :key="p.PlatformCode" :value="p.PlatformCode">{{ p.PlatformName }}{{ p.PlatformCode }}</option>
</select>
</div>
</div>
<div class="search-actions">
<button type="button" class="btn btn-secondary" @click="clearSearch">清除</button>
<button type="button" class="btn btn-primary" @click="performSearch">搜尋</button>
<button type="button" class="btn btn-success" style="margin-left: 10px;" @click="openAddModal">新增帳號</button>
</div>
</div>
<!-- 列表區域 -->
<div class="result-panel">
<table class="result-table">
<thead>
<tr>
<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>
</tr>
</thead>
<tbody>
<tr v-if="loading">
<td colspan="6" class="empty-message">載入中...</td>
</tr>
<tr v-else-if="accountList.length === 0">
<td colspan="6" class="empty-message">查無資料</td>
</tr>
<tr v-else v-for="item in accountList" :key="item.ID">
<td class="text-center">{{ item.ProjectID }}</td>
<td>{{ item.ProjectName || '' }}</td>
<td class="text-center">{{ getPlatformName(item.PlatformCode) }}</td>
<td class="password-cell">
<span v-if="!item.showPassword" class="password-mask">●●●●●●●●</span>
<span v-else class="password-text">{{ item.MMSAccount }}</span>
</td>
<td class="password-cell">
<span v-if="!item.showPassword" class="password-mask">●●●●●●●●</span>
<span v-else class="password-text">{{ item.MMSPassword }}</span>
<button type="button" class="btn-icon" @click.prevent="togglePasswordDisplay(item)">
{{ item.showPassword ? '隱藏' : '顯示' }}
</button>
</td>
<td class="text-center">
<button type="button" class="btn btn-primary btn-sm" @click="openEditModal(item)">編輯</button>
<button type="button" class="btn btn-danger btn-sm" @click="deleteAccount(item)">刪除</button>
</td>
</tr>
</tbody>
</table>
<!-- 分頁 -->
<div class="pagination" v-if="totalCount > 0">
<button type="button" class="btn btn-secondary btn-sm" :disabled="currentPage === 1" @click="previousPage">上一頁</button>
<span class="pagination-info">第 {{ currentPage }} / {{ totalPages }} 頁,共 {{ totalCount }} 筆</span>
<button type="button" class="btn btn-secondary btn-sm" :disabled="currentPage === totalPages" @click="nextPage">下一頁</button>
</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-group-inline autocomplete-field">
<label class="form-label-inline required">計畫代號</label>
<div class="autocomplete-container" style="flex: 1;">
<input
type="text"
v-model="editItem.projectName"
@input="searchEditProjectSuggestions"
@focus="showEditProjectSuggestions = true"
@blur="hideEditProjectSuggestions"
class="form-control autocomplete-input"
:disabled="!isNewMode"
placeholder="請輸入計畫編號或名稱">
<div class="autocomplete-dropdown" v-if="showEditProjectSuggestions && editProjectSuggestions.length > 0">
<div
v-for="suggestion in editProjectSuggestions"
:key="suggestion.Value"
class="autocomplete-item"
@click="selectEditProject(suggestion)">
<span class="autocomplete-value">{{ suggestion.Value }}</span>
<span class="autocomplete-name">{{ suggestion.Name }}</span>
</div>
</div>
</div>
</div>
<div class="error-message" v-if="validationErrors.ProjectID">{{ validationErrors.ProjectID }}</div>
<!-- 使用平台 -->
<div class="form-group-inline">
<label class="form-label-inline">使用平台</label>
<select v-model="editItem.PlatformCode" class="form-control">
<option v-for="p in platforms" :key="p.PlatformCode" :value="p.PlatformCode">{{ p.PlatformName }}{{ p.PlatformCode }}</option>
</select>
</div>
<!-- 簡訊帳號 -->
<div class="form-group-inline">
<label class="form-label-inline required">簡訊帳號</label>
<input type="text"
v-model="editItem.MMSAccount"
class="form-control"
placeholder="請輸入簡訊帳號"
maxlength="50">
<div class="error-message" v-if="validationErrors.MMSAccount">{{ validationErrors.MMSAccount }}</div>
</div>
<!-- 簡訊密碼 -->
<div class="form-group-inline">
<label class="form-label-inline required">簡訊密碼</label>
<input :type="showPassword ? 'text' : 'password'"
v-model="editItem.MMSPassword"
class="form-control"
placeholder="請輸入簡訊密碼"
maxlength="50">
<button type="button" class="btn-template" @click.prevent="toggleEditPasswordDisplay">
{{ showPassword ? '隱藏' : '顯示' }}
</button>
<div class="error-message" v-if="validationErrors.MMSPassword">{{ validationErrors.MMSPassword }}</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" @click="closeModal">取消</button>
<button type="button" class="btn btn-primary" @click="saveAccount">存檔</button>
</div>
</div>
</div>
</div>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="script" runat="server">
<script src="<%= ResolveUrlWithSysVer("~/Scripts/MessageAccountManage.js") %>"></script>
</asp:Content>