Commit ee729155 authored by Jason's avatar Jason

Token vault selectitem list

parent 2598a65b
......@@ -397,3 +397,4 @@ msbuild.wrn
.vs/
*/bin/
GemmiUgc/wwwroot/user_upload/
doc
\ No newline at end of file
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
#township.txt
township.txt
# 忽略開啟sqlite產生的附加檔
*.db-shm
*.db-wal
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
Temple.db
Temple1.db
*.swp
*.*~
project.lock.json
.DS_Store
*.pyc
nupkg/
# Visual Studio Code
.vscode
# Rider
.idea
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
msbuild.log
msbuild.err
msbuild.wrn
# Visual Studio 2015
.vs/
*/bin/
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.32106.194
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TokenVault management", "backstage\TokenVault management.csproj", "{41BECD6A-15B3-45DA-841A-E3C22B5A3884}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{41BECD6A-15B3-45DA-841A-E3C22B5A3884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{41BECD6A-15B3-45DA-841A-E3C22B5A3884}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41BECD6A-15B3-45DA-841A-E3C22B5A3884}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41BECD6A-15B3-45DA-841A-E3C22B5A3884}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C9B79A1E-E10C-4FE1-BACA-8958408F78ED}
EndGlobalSection
EndGlobal
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.0",
"commands": [
"dotnet-ef"
]
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using backstage.Helpers;
using backstage.Models;
using System.Net.Http;
namespace backstage.Controllers
{
#region ToBeExpiredViewBag Class
public class ToBeExpiredViewBag
{
public string CustomerName { get; set; }
public string ItemName { get; set; }
public string CustomerPhone { get; set; }
public string Name { get; set; }
public string DueDate { get; set; }
}
#endregion
[Authorize]
public class HomeController : Controller
{
private readonly IConfiguration _config;
private readonly ICallApi _callApi;
/// <summary>
/// 讀取組態用
/// </summary>
public HomeController(IConfiguration config, ICallApi callApi)
{
_config = config;
_callApi = callApi;
}
public async Task<IActionResult> Index()
{
ResultModel result = new ResultModel();
return View();
}
public IActionResult Error()
{
return View();
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using backstage.Helpers;
using backstage.Models;
using backstage.Models.Users;
using Newtonsoft.Json.Linq;
using System.Linq;
using backstage.Models.TokenVault;
namespace backstage.Controllers
{
public class TokenVaultController : Controller
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IConfiguration _config;
private readonly ICallApi _callApi;
private static Logger logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// 讀取組態用
/// </summary>
public TokenVaultController(IConfiguration config, ICallApi callApi, IHttpContextAccessor httpContextAccessor)
{
_config = config;
_callApi = callApi;
_httpContextAccessor = httpContextAccessor;
}
[HttpGet]
public async Task<IActionResult> ListTokenVault()
{
var TokenVaultResponse = new TokenVaultResponse();
// 確認使用者是否已經登入
if (!User.Identity.IsAuthenticated)
{
return RedirectToAction("Login");
}
#region 取得部門列表
var DepartmentsResponse = new DepartmentsResponse();
var url = _config["IP"] + "/merchant/list";
var httpMethod = HttpMethod.Post;
// 取得使用者的 "token" Claim 值
string token = User.FindFirstValue("token");
var parameters = new Dictionary<string, string>
{
{ "token", token }
};
var apiResult = await _callApi.CallAPI(url, parameters, httpMethod);
if (apiResult.IsSuccess)
{
DepartmentsResponse = JsonConvert.DeserializeObject<DepartmentsResponse>(apiResult.Data.ToString());
if (DepartmentsResponse.r == 0)
{
ViewBag.DepartmentsList = (from o in DepartmentsResponse.merchants
select new SelectListItem
{
Value = o.merchant_id.ToString(),
Text = o.name
}).ToList();
}
}
#endregion
return View();
}
[HttpPost]
public async Task<IActionResult> ListTokenVaultAjax(int merchantId)
{
// 確認使用者是否已經登入
if (!User.Identity.IsAuthenticated)
{
return RedirectToAction("Login");
}
// 取得使用者的 "token" Claim 值
string token = User.FindFirstValue("token");
var url = _config["IP"] + "/v2/vault";
var httpMethod = HttpMethod.Get;
var parameters = new Dictionary<string, string>
{
{ "Merchant_id", merchantId.ToString()}
};
var apiResult = await _callApi.CallAPI(url, parameters, httpMethod);
if (apiResult.IsSuccess)
{
var TokenVaultResponse = JsonConvert.DeserializeObject<TokenVaultResponse>(apiResult.Data.ToString());
if (TokenVaultResponse.r == 0)
{
if (TokenVaultResponse.info.Count > 0)
{
// 轉出html
string outputHtml = "";
foreach (var vault in TokenVaultResponse.info)
{
string htmlCode = @$"<tr id=""{vault.vault_id}"" class=""expense-color"">
<td><a asp-action=""Detail"" asp-route-Id=""{vault.vault_id}""> {vault.vault_id}</a></td>
<td>{vault.name}</td>
<td>{vault.desc}</td>
<td>{vault.type}</td>
<td>{vault.created}</td>
<td>{vault.tokenCount}</td>
<td>{vault.userCount}</td>
</tr>";
outputHtml += htmlCode;
}
return Content(outputHtml);
}
else
{
return Ok();
}
}
else
{
return Ok();
}
}
else
{
return Ok();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using backstage.Helpers;
using backstage.Models;
using backstage.Models.Users;
using Newtonsoft.Json.Linq;
namespace backstage.Controllers
{
public class UserController : Controller
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IConfiguration _config;
private readonly ICallApi _callApi;
private static Logger logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// 讀取組態用
/// </summary>
public UserController(IConfiguration config, ICallApi callApi, IHttpContextAccessor httpContextAccessor)
{
_config = config;
_callApi = callApi;
_httpContextAccessor = httpContextAccessor;
}
[Authorize]
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpGet]
public async Task<IActionResult> Login()
{
if (HttpContext.User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Home");
}
return View();
}
[HttpGet]
public async Task<IActionResult> ListUsers()
{
var UserResponse = new UserResponse();
var url = _config["IP"]+ "/admin/list";
// 確認使用者是否已經登入
if (!User.Identity.IsAuthenticated)
{
return RedirectToAction("Login");
}
var httpMethod = HttpMethod.Post;
// 取得使用者的 "token" Claim 值
string token = User.FindFirstValue("token");
var types = new[] { "all" };
var data = new { inc = types };
var parameters = new Dictionary<string, string>
{
{ "token", token },
{ "types", JsonConvert.SerializeObject(data)}
//{ "types", "{\"inc\":[\"all\"]}"}
};
var apiResult = await _callApi.CallAPI(url, parameters, httpMethod);
if (apiResult.IsSuccess)
{
UserResponse = JsonConvert.DeserializeObject<UserResponse>(apiResult.Data.ToString());
if (UserResponse.r == 0)
{
return View(UserResponse);
}
}
return Ok(apiResult.Data.ToString());
}
[HttpGet]
public async Task<IActionResult> ListDepartments()
{
var DepartmentsResponse = new DepartmentsResponse();
var url = _config["IP"] + "/merchant/list";
// 確認使用者是否已經登入
if (!User.Identity.IsAuthenticated)
{
return RedirectToAction("Login");
}
var httpMethod = HttpMethod.Post;
// 取得使用者的 "token" Claim 值
string token = User.FindFirstValue("token");
var parameters = new Dictionary<string, string>
{
{ "token", token }
};
var apiResult = await _callApi.CallAPI(url, parameters, httpMethod);
if (apiResult.IsSuccess)
{
DepartmentsResponse = JsonConvert.DeserializeObject<DepartmentsResponse>(apiResult.Data.ToString());
if (DepartmentsResponse.r == 0)
{
return View(DepartmentsResponse);
}
}
return Ok(apiResult.Data.ToString());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(User user, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(user);
}
//var u = await _UserRepository.Login(user);
var u = new UserLogin();
var url = _config["IP"];
var parameters = new Dictionary<string, string>
{
{ "username", user.username },
{ "pwd", user.pwd },
{ "reqPermFlag[0]","admin-login"}
};
var httpMethod = HttpMethod.Post;
try
{
var apiResult = await _callApi.CallAPI(url, parameters, httpMethod);
if (apiResult.IsSuccess)
{
// API 呼叫成功,進行相應的處理
u = JsonConvert.DeserializeObject<UserLogin>(apiResult.Data.ToString());
if (u.r == 0 && !string.IsNullOrEmpty(u.token))
{
#region 寫入TOKEN
int LoginExpireMinute = Convert.ToInt32(_config["LoginExpireMinute"]);
string key = _config["TokenKey"];
var Cookieoptions = new CookieOptions();
////時間一到就會把Token從Cookie洗掉,如果Expires沒比API的Expires長,則每次Token過期都須重新登入
Cookieoptions.Expires = DateTime.Now.AddMinutes(LoginExpireMinute);
//Cookieoptions.SameSite = SameSiteMode.Strict;
Cookieoptions.HttpOnly = true;
var userClaims = new ClaimsIdentity(new[]
{
new Claim("username", user.username),
new Claim("token", u.token),
}, CookieAuthenticationDefaults.AuthenticationScheme);
//將 ClaimsIdentity 設定給 ClaimsPrincipal (持有者)
ClaimsPrincipal principal = new ClaimsPrincipal(userClaims);
//登入動作
try
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties()
{
//是否可以被刷新
AllowRefresh = true,
// 設置了一個 1 天 有效期的持久化 cookie
IsPersistent = true, //IsPersistent = false,瀏覽器關閉即刻登出
//用戶頁面停留太久,逾期時間,在此設定的話會覆蓋Startup.cs裡的逾期設定
ExpiresUtc = DateTime.Now.AddMinutes(LoginExpireMinute),
});
}
catch (Exception ex)
{
logger.Trace(ex.Message + ex.InnerException?.Message);
}
#endregion
return RedirectToAction("Index", "Home");
}
else
{
// API 呼叫失敗,進行相應的錯誤處理
return BadRequest(apiResult.Message);
}
}
else
{
// API 呼叫失敗,進行相應的錯誤處理
return BadRequest(apiResult.Message);
}
}
catch (Exception ex)
{
// 處理 API 呼叫發生的例外狀況
return StatusCode(500, $"API 呼叫發生錯誤:{ex.Message}");
}
}
[HttpGet]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync();
foreach (var cookieKey in Request.Cookies.Keys)
HttpContext.Response.Cookies.Delete(cookieKey);
return RedirectToAction(nameof(Login));
}
public async Task<IActionResult> List()
{
//TempData["IsSuccess"] = result.IsSuccess;
//TempData["msg"] = result.Message;
//return View(viewModel);
throw new NotImplementedException();
}
public async Task<ResultModel> Delete(int id)
{
throw new NotImplementedException();
}
}
}
\ No newline at end of file

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using backstage.Models;
using NLog;
using System.Net.Http;
using System.Net.Http.Headers;
using backstage.Helpers;
namespace backstage.Helpers
{
public interface ICallApi
{
Task<ResultModel> CallAPI(string url, Dictionary<string, string> parameters, HttpMethod httpMethod);
}
public class CallApi : ICallApi
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IConfiguration _config;
private static Logger logger = LogManager.GetCurrentClassLogger();
public CallApi(IHttpContextAccessor httpContextAccessor, IConfiguration config)
{
_config = config;
_httpContextAccessor = httpContextAccessor;
}
public async Task<ResultModel> CallAPI(string url, Dictionary<string, string> parameters, HttpMethod httpMethod)
{
var result = new ResultModel();
using (var handler = new HttpClientHandler())
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, certChain, policyErrors) => true;
using (var client = new HttpClient(handler))
{
try
{
// 將參數轉換為 x-www-form-urlencoded 格式
var content = new FormUrlEncodedContent(parameters);
// 建立 HttpRequestMessage 物件,設定 URL 和 HTTP 方法
var request = new HttpRequestMessage(httpMethod, url)
{
Content = content
};
// 計算 Content-Length
var contentLength = await content.ReadAsStringAsync();
// 取得主機名稱
var host = new Uri(url).Host;
// 設定 Content-Type 標頭
string token = _httpContextAccessor.HttpContext.User.FindFirstValue("token");
if (!string.IsNullOrEmpty(token))
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
request.Content.Headers.ContentLength = contentLength.Length;
request.Headers.Host = host;
// 執行 API 呼叫
var response = await client.SendAsync(request);
// 檢查回應狀態碼
if (response.IsSuccessStatusCode)
{
// 讀取回應內容
result.Data = await response.Content.ReadAsStringAsync();
result.IsSuccess = true;
return result;
}
else
{
// 處理 API 呼叫失敗的情況
Console.WriteLine($"API 呼叫失敗:{response.StatusCode}");
result.Message = $"API 呼叫失敗:{response.StatusCode}";
return result;
}
}
catch (Exception ex)
{
// 處理例外情況
Console.WriteLine($"API 呼叫發生錯誤:{ex.Message}");
result.Message = $"API 呼叫失敗:{ex.Message}";
return result;
}
}
}
}
}
}
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace backstage.Models
{
public static class Enums
{
/// <summary>
/// 帳號類型
/// </summary>
public enum Role
{
超級管理員 = 0,
一般管理員 =1
}
}
}
using System;
namespace backstage.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
using backstage.Models;
namespace ExtensionMethods
{
public static class QueryStringExtension
{
public static string GenerateQueryString<T>(this T t) {
var result = new ResultModel();
var queryString = from p in t.GetType().GetProperties()
where p.GetValue(t, null) != null
select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(t, null).ToString());
return ("?"+String.Join("&",queryString.ToArray()));
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace backstage.Models
{
public class ResultModel
{
public bool IsSuccess { get; set; } = false;
public string Message { get; set; }
public object Data { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace backstage.Models.TokenVault
{
public class TokenVault
{
public int vault_id { get; set; }
public string name { get; set; }
public string desc { get; set; }
public int type { get; set; }
public int enabled { get; set; }
public DateTime created { get; set; }
public int tokenCount { get; set; }
public int userCount { get; set; }
}
public class TokenVaultResponse
{
public int r { get; set; }
public string m { get; set; }
public string flags { get; set; }
//public int count { get; set; }
public List<TokenVault> info { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace backstage.Models.Users
{
public class Department
{
//public int Id { get; set; }
public int merchant_id { get; set; }
public string address { get; set; }
public string country_id { get; set; }
public string postcode { get; set; }
public string phone { get; set; }
public string fax { get; set; }
public string vatid { get; set; }
public string name { get; set; }
public string name_en { get; set; }
public int enabled { get; set; }
public DateTime creation_date { get; set; }
public DateTime vatid_verify { get; set; }
public DateTime deposit_book_verify { get; set; }
public DateTime vatdeposit_book_verify { get; set; }
public DateTime user_natid_verify { get; set; }
public DateTime enabled_transaction { get; set; }
public string merchant_type { get; set; }
public string merchant_level{ get; set; }
public int tts { get; set; }
}
public class DepartmentsResponse
{
public int r { get; set; }
public string m { get; set; }
public string flags { get; set; }
public int count { get; set; }
public List<Department> merchants { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace backstage.Models.Users
{
public class User
{
public int uid { get; set; }
public string name { get; set; }
public string name_en { get; set; }
public string username { get; set; }
public string pwd { get; set; }
public int locked { get; set; }
public DateTime creation_date { get; set; }
public int enabled { get; set; }
public DateTime birthdate { get; set; }
public string marital_status { get; set; }
public string gender { get; set; }
public string education { get; set; }
public string natid { get; set; }
public string lang { get; set; }
//[NotMapped]
//public string newPassword { get; set; }
//[NotMapped]
//public string ConfirmNewPassword { get; set; }
//public byte[] PasswordHash { get; set; }
//public byte[] PasswordSalt { get; set; }
//public int role { get; set; }
}
public class UserLogin
{
//public int Id { get; set; }
public int r { get; set; }
public string token { get; set; }
public string m { get; set; }
public string flags { get; set; }
}
public class UserResponse
{
public int r { get; set; }
public string m { get; set; }
public int userCount { get; set; }
public List<User> Users{ get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace backstage.Models.Users
{
public class UserForChangePassword:IValidatableObject
{
public string Username { get; set; }
[Required]
public string pwd { get; set; }
[Required]
public string NewPassword { get; set; }
[Required]
public string ConfirmNewPassword { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (NewPassword != ConfirmNewPassword)
{
yield return new ValidationResult("兩次密碼輸入不相符", new string[] { "ConfirmNewPassword" });
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace backstage.Models.Users
{
public class UserForRegister : IValidatableObject
{
[Required]
[EmailAddress]
public string Username { get; set; }
[Required]
[StringLength(50, MinimumLength = 6, ErrorMessage = "請輸入6~50位字元當作密碼")]
public string pwd { get; set; }
[Required]
public string ConfirmPassword { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (pwd != ConfirmPassword)
{
yield return new ValidationResult("兩次密碼輸入不相符", new string[] { "ConfirmPassword" });
}
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
namespace backstage
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, config) =>
{
var env = hostContext.HostingEnvironment;
config.AddJsonFile(path: "appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(path: $"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
webBuilder.UseIISIntegration();
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5425",
"sslPort": 44399
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"backstage": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000"
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Helpers;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using backstage.Helpers;
using backstage.Models;
namespace backstage
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
double LoginExpireMinute = Convert.ToDouble(Configuration["LoginExpireMinute"]);
services.AddControllersWithViews();
services.AddAuthorization();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie("Cookies", option =>
{
option.Cookie.HttpOnly = true;
option.LoginPath = new PathString("/User/Login");
option.LogoutPath = new PathString("/User/Logout");
option.Cookie.Name = "backstage";
option.Cookie.SameSite = SameSiteMode.Strict;
////�n�J���Įɶ�
});
// �N Session �s�b ASP.NET Core �O���餤
services.AddDistributedMemoryCache();
services.AddHttpContextAccessor();
services.AddSession(options =>
{
options.Cookie.Name = "TokenVault";
options.IdleTimeout = TimeSpan.FromMinutes(LoginExpireMinute);
options.Cookie.HttpOnly = true;
});
services.AddAntiforgery(
opts =>
{
opts.Cookie.Name = "anticsrf";
opts.FormFieldName = "anticsrf";
});
services.AddScoped<ICallApi, CallApi>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseStatusCodePagesWithRedirects("/Home/Error"); //������http�}�Y������URL
}
//�Ϥ��]CSP���Y�L�k���J �ݳB�z
//app.Use(async (context, next) =>
//{
// context.Response.Headers.Add(
// "Content-Security-Policy",
// //"style-src 'self' 'sha256-aqNNdDLnnrDOnTNdkJpYlAxKVJtLt9CtFLklmInuUAE=';" +
// "img-src 'self';" +
// "frame-src https://calendar.google.com/;"+
// "script-src 'self' 'nonce-KUY8VewuvyUYVEIvEFue4vwyiuf';" +
// "frame-ancestors 'none';"
// );
// context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
// context.Response.Headers.Add("X-Frame-Options", "DENY");
// context.Response.Headers.Add("X-Xss-Protection", "1");
// await next();
//});
// SessionMiddleware �[�J Pipeline
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
//app.UseSession();
//�ҥ� cookie ��h�\��
app.UseCookiePolicy();
//�ҥΨ����ѧO
app.UseAuthentication();
//�ҥα��v�\��
app.UseAuthorization();
// �o�T�ӫe�ᦸ�Ǥ����ճ�
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>28d28566-ab78-4937-80f5-db81b331c511</UserSecretsId>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Models\FinancialItem\**" />
<Compile Remove="Models\FinancialRecord\**" />
<Compile Remove="Models\Payment\**" />
<Content Remove="Models\FinancialItem\**" />
<Content Remove="Models\FinancialRecord\**" />
<Content Remove="Models\Payment\**" />
<EmbeddedResource Remove="Models\FinancialItem\**" />
<EmbeddedResource Remove="Models\FinancialRecord\**" />
<EmbeddedResource Remove="Models\Payment\**" />
<None Remove="Models\FinancialItem\**" />
<None Remove="Models\FinancialRecord\**" />
<None Remove="Models\Payment\**" />
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\css\style.css.map" />
<None Include="wwwroot\favicon.ico" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Bold.eot" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Bold.ttf" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Bold.woff" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Bold.woff2" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Light.eot" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Light.ttf" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Light.woff" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Light.woff2" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Medium.eot" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Medium.ttf" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Medium.woff" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Medium.woff2" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Regular.eot" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Regular.ttf" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Regular.woff" />
<None Include="wwwroot\fonts\Ubuntu\Ubuntu-Regular.woff2" />
<None Include="wwwroot\images\dashboard\circle.png" />
<None Include="wwwroot\images\dashboard\circle.svg" />
<None Include="wwwroot\images\dashboard\img_1.jpg" />
<None Include="wwwroot\images\dashboard\img_2.jpg" />
<None Include="wwwroot\images\dashboard\img_3.jpg" />
<None Include="wwwroot\images\dashboard\img_4.jpg" />
<None Include="wwwroot\images\faces-clipart\pic-1.png" />
<None Include="wwwroot\images\faces-clipart\pic-2.png" />
<None Include="wwwroot\images\faces-clipart\pic-3.png" />
<None Include="wwwroot\images\faces-clipart\pic-4.png" />
<None Include="wwwroot\images\favicon.png" />
<None Include="wwwroot\images\sprites\blue.png" />
<None Include="wwwroot\images\sprites\dark.png" />
<None Include="wwwroot\images\sprites\flag.png" />
<None Include="wwwroot\images\sprites\green.png" />
<None Include="wwwroot\images\sprites\jsgrid-icons.png" />
<None Include="wwwroot\images\sprites\red.png" />
<None Include="wwwroot\images\sprites\yellow.png" />
<None Include="wwwroot\js\chart.js" />
<None Include="wwwroot\js\dashboard.js" />
<None Include="wwwroot\js\file-upload.js" />
<None Include="wwwroot\js\hoverable-collapse.js" />
<None Include="wwwroot\js\misc.js" />
<None Include="wwwroot\js\off-canvas.js" />
<None Include="wwwroot\js\site.js" />
<None Include="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js" />
<None Include="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js" />
<None Include="wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt" />
<None Include="wwwroot\lib\jquery-validation\dist\additional-methods.js" />
<None Include="wwwroot\lib\jquery-validation\dist\additional-methods.min.js" />
<None Include="wwwroot\lib\jquery-validation\dist\jquery.validate.js" />
<None Include="wwwroot\lib\jquery-validation\dist\jquery.validate.min.js" />
<None Include="wwwroot\lib\jquery-validation\LICENSE.md" />
<None Include="wwwroot\lib\jquery\dist\jquery.js" />
<None Include="wwwroot\lib\jquery\dist\jquery.min.js" />
<None Include="wwwroot\lib\jquery\dist\jquery.min.map" />
<None Include="wwwroot\lib\jquery\LICENSE.txt" />
<None Include="wwwroot\scss\components\_badges.scss" />
<None Include="wwwroot\scss\components\_bootstrap-progress.scss" />
<None Include="wwwroot\scss\components\_breadcrumbs.scss" />
<None Include="wwwroot\scss\components\_buttons.scss" />
<None Include="wwwroot\scss\components\_cards.scss" />
<None Include="wwwroot\scss\components\_checkbox-radio.scss" />
<None Include="wwwroot\scss\components\_dropdown.scss" />
<None Include="wwwroot\scss\components\_forms.scss" />
<None Include="wwwroot\scss\components\_icons.scss" />
<None Include="wwwroot\scss\components\_lists.scss" />
<None Include="wwwroot\scss\components\_preview.scss" />
<None Include="wwwroot\scss\components\_tables.scss" />
<None Include="wwwroot\scss\components\_todo-list.scss" />
<None Include="wwwroot\scss\landing-screens\_auth.scss" />
<None Include="wwwroot\scss\mixins\_animation.scss" />
<None Include="wwwroot\scss\mixins\_background.scss" />
<None Include="wwwroot\scss\mixins\_badges.scss" />
<None Include="wwwroot\scss\mixins\_blockqoute.scss" />
<None Include="wwwroot\scss\mixins\_breadcrumbs.scss" />
<None Include="wwwroot\scss\mixins\_buttons.scss" />
<None Include="wwwroot\scss\mixins\_cards.scss" />
<None Include="wwwroot\scss\mixins\_misc.scss" />
<None Include="wwwroot\scss\mixins\_pagination.scss" />
<None Include="wwwroot\scss\mixins\_popovers.scss" />
<None Include="wwwroot\scss\mixins\_text.scss" />
<None Include="wwwroot\scss\mixins\_tooltips.scss" />
<None Include="wwwroot\scss\style.scss" />
<None Include="wwwroot\scss\_dashboard.scss" />
<None Include="wwwroot\scss\_demo.scss" />
<None Include="wwwroot\scss\_fonts.scss" />
<None Include="wwwroot\scss\_footer.scss" />
<None Include="wwwroot\scss\_functions.scss" />
<None Include="wwwroot\scss\_layouts.scss" />
<None Include="wwwroot\scss\_misc.scss" />
<None Include="wwwroot\scss\_navbar.scss" />
<None Include="wwwroot\scss\_reset.scss" />
<None Include="wwwroot\scss\_sidebar.scss" />
<None Include="wwwroot\scss\_typography.scss" />
<None Include="wwwroot\scss\_utilities.scss" />
<None Include="wwwroot\scss\_variables.scss" />
<None Include="wwwroot\scss\_vertical-wrapper.scss" />
<None Include="wwwroot\scss\_widget-grid.scss" />
<None Include="wwwroot\vendors\chart.js\Chart.min.js" />
<None Include="wwwroot\vendors\css\vendor.bundle.base.css" />
<None Include="wwwroot\vendors\js\bootstrap.min.js.map" />
<None Include="wwwroot\vendors\js\vendor.bundle.base.js" />
<None Include="wwwroot\vendors\mdi\css\materialdesignicons.min.css" />
<None Include="wwwroot\vendors\mdi\css\materialdesignicons.min.css.map" />
<None Include="wwwroot\vendors\mdi\fonts\materialdesignicons-webfont.eot" />
<None Include="wwwroot\vendors\mdi\fonts\materialdesignicons-webfont.ttf" />
<None Include="wwwroot\vendors\mdi\fonts\materialdesignicons-webfont.woff" />
<None Include="wwwroot\vendors\mdi\fonts\materialdesignicons-webfont.woff2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="DocumentFormat.OpenXml" Version="2.10.0-beta0002" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNet.WebPages" Version="3.2.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SQLite" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
<PackageReference Include="Nancy" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="PuppeteerSharp" Version="7.1.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.30.0" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="appsettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\fonts\bootstrap\" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" appsettings_1production_1json__JsonSchema="" properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
</Project>
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>新宅 濟福寺景德祠-後台</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- End Required meta tags -->
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
@*<link rel="stylesheet" href="~/css/site.css" />*@
<!-- Layout styles -->
<link rel="stylesheet" href="~/css/style.css">
<!-- End layout styles -->
<link rel="shortcut icon" href="~/images/favicon.png" />
</head>
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center text-center error-page bg-primary">
<div class="row flex-grow">
<div class="col-lg-7 mx-auto text-white">
<div class="row align-items-center d-flex flex-row">
<div class="col-lg-6 text-lg-right pr-lg-4">
<h1 class="display-1 mb-0">404</h1>
</div>
<div class="col-lg-6 error-page-divider text-lg-left pl-lg-4">
<h2>拍謝!</h2>
<h3 class="font-weight-light">這個頁面不見了噢</h3>
</div>
</div>
<div class="row mt-5">
<div class="col-12 text-center mt-xl-2">
<a class="text-white font-weight-medium" asp-action="Index">回到首頁</a>
</div>
</div>
</div>
</div>
</div>
<!-- content-wrapper ends -->
</div>
<!-- page-body-wrapper ends -->
</div>
<!-- container-scroller -->
<!-- plugins:js -->
<script src="./assets/vendors/js/vendor.bundle.base.js"></script>
<!-- endinject -->
</body>
</html>
\ No newline at end of file

@{
ViewData["Title"] = "Index";
}
<div class="page-header">
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div id="msgDiv"></div>
</div>
@*<div class="row">
<div class="col-lg-6 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">代辦事項</h4>
<div class="add-items d-flex">
<input id="new_task" type="text" class="form-control todo-list-input" placeholder="要做什麼呢?">
<button class="add btn btn-primary font-weight-bold todo-list-add-btn white-nowrap" id="add-task">新增</button>
</div>
<div class="list-wrapper scrollbar">
<ul class="d-flex flex-column-reverse todo-list todo-list-custom">
</ul>
</div>
</div>
</div>
</div>
<div class="col-lg-6 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<h4 class="card-title">購買項目到期提醒(前後一個月)</h4>
<div class="table-scroll scrollbar">
<table class="table table-hover">
<thead>
<tr>
<th>到期日</th>
<th>項目</th>
<th>聯絡人</th>
<th>聯絡手機</th>
<th>登記姓名</th>
</tr>
</thead>
<tbody>
@if (ViewBag.ToBeExpired != null)
{
@foreach (var i in ViewBag.ToBeExpired)
{
<tr>
<td><label class="text-danger">@i.DueDate</label></td>
<td>@i.ItemName</td>
<td>@i.CustomerName</td>
<td>@i.CustomerPhone</td>
<td>@i.Name</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>*@
</div>
@section Scripts{
<script src="~/js/Home.js"></script>
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
@*$(function () {
let eventsArr = [];
let eventsTable = document.getElementById("eventsTable");
let trElems = eventsTable.getElementsByTagName("tr")
for (let tr of trElems) {
let tdElems = tr.getElementsByTagName("td");
let eventObj = {
id: tdElems[0].innerText,
title: tdElems[1].innerText,
start: tdElems[2].innerText,
};
eventsArr.push(eventObj);
}
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'zh-cn',
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prevYear prev,next nextYear today',
center: 'title',
right: 'dayGridMonth timeGridWeek timeGridDay'
},
buttonText: {
today: '今天',
month: '月',
week: '周',
day: '日',
},
events: eventsArr
});
calendar.render();
})*@
</script>
}
\ No newline at end of file

@*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>@ViewData["Title"]</title>
<!-- End Required meta tags -->
<!-- plugins:css -->
<link rel="stylesheet" href="~/vendors/mdi/css/materialdesignicons.min.css">
<link rel="stylesheet" href="~/vendors/css/vendor.bundle.base.css">
<!-- endinject -->
<link href="~/lib/bootstrap-4.5.0-dist/css/bootstrap.css" rel="stylesheet" />
@*<link rel="stylesheet" href="~/css/site.css" />*@
<!-- Layout styles -->
<link rel="stylesheet" href="~/css/style.css">
<!-- End layout styles -->
<link rel="shortcut icon" href="~/images/favicon.png" />
<!--jquery ui datepicker-->
<link href="~/lib/jquery-ui/jquery-ui.min.css" rel="stylesheet" />
<!--END jquery ui datepicker-->
<!--fullcalendar@3.10.5-->
<link href='~/lib/fullcalendar@3.10.5/fullcalendar.min.css' rel='stylesheet' />
<link href='~/lib/fullcalendar@3.10.5/fullcalendar.print.css' rel='stylesheet' media='print' />
<!--END fullcalendar@3.10.5-->
<link href="~/lib/datetimepicker/css/bootstrap-datetimepicker.css" rel="stylesheet" />
<link href="~/css/myStylecss.css" rel="stylesheet" />
@RenderSection("header", required: false)
</head>
<body>
<nav class="navbar default-layout-navbar col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
<div class="text-center navbar-brand-wrapper d-flex align-items-center justify-content-center">
<a class="navbar-brand brand-logo" asp-controller="Home" asp-action="Index"><img src="~/images/logo.png" alt="logo" /></a>
@*<a class="navbar-brand brand-logo-mini" asp-controller="Home" asp-action="Index"><img src="~/images/logo-mini.svg" alt="logo" /></a>*@
</div>
<div class="navbar-menu-wrapper d-flex align-items-stretch">
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="mdi mdi-menu"></span>
</button>
<ul class="navbar-nav navbar-nav-right">
<li class="nav-item nav-profile dropdown">
@if (User.Identity.IsAuthenticated)
{
<a class="nav-link dropdown-toggle" id="profileDropdown" href="#" data-toggle="dropdown" aria-expanded="false">
<div class="nav-profile-img">
<img src="~/images/faces/man.svg" alt="image">
<span class="availability-status online"></span>
</div>
<div class="nav-profile-text">
<p class="mb-1 text-black">@Context.User.Claims.FirstOrDefault(m => m.Type == "username").Value</p>
</div>
</a>
<div class="dropdown-menu navbar-dropdown" aria-labelledby="profileDropdown">
<a class="dropdown-item" asp-controller="User" asp-action="ChangePassword">
<i class="mdi mdi-lock-open mr-2"></i>更改密碼
</a>
<a class="dropdown-item" asp-controller="User" asp-action="Register">
<i class="mdi mdi-account-plus mr-2"></i>註冊管理員
</a>
<a class="dropdown-item" asp-controller="UserManage" asp-action="GetUserManage">
<i class="mdi mdi-account-details mr-2"></i>帳號管理
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" asp-controller="User" asp-action="Logout">
<i class="mdi mdi-logout mr-2 text-danger"></i>登出
</a>
</div>
}
else
{
<a class="nav-link " asp-controller="User" asp-action="Login"> Login </a>
}
</li>
<li class="nav-item d-none d-lg-block full-screen-link">
<a class="nav-link">
<i class="mdi mdi-fullscreen" id="fullscreen-button"></i>
</a>
</li>
</ul>
<button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button" data-toggle="offcanvas">
<span class="mdi mdi-menu"></span>
</button>
</div>
</nav>
<!-- partial -->
<div class="container-fluid page-body-wrapper">
<!-- partial:./partials/_sidebar.html -->
<nav class="sidebar sidebar-offcanvas" id="sidebar">
<ul class="nav ">
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#Member" aria-expanded="false" aria-controls="Member">
<span class="menu-title">帳號管理</span>
<i class="menu-arrow"></i>
<i class="mdi mdi-account-multiple menu-icon"></i>
</a>
<div class="collapse" id="Member">
<ul class="nav flex-column sub-menu">
<li class="nav-item"> <a class="nav-link" asp-controller="User" asp-action="ListUsers">使用者列表</a></li>
<li class="nav-item"> <a class="nav-link" asp-controller="User" asp-action="ListDepartments">部門列表</a></li>
<li class="nav-item"> <a class="nav-link" asp-controller="User" asp-action="CreateUser">新增使用者</a></li>
@*<li class="nav-item"> <a class="nav-link" asp-controller="Member" asp-action="GetMember">信徒資料</a></li>*@
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#Income" aria-expanded="false">
<span class="menu-title">Token Vault管理</span>
<i class="menu-arrow"></i>
<i class="mdi mdi-database menu-icon"></i>
</a>
<div class="collapse" id="Income">
<ul class="nav flex-column sub-menu">
<li class="nav-item"> <a class="nav-link" asp-controller="TokenVault" asp-action="ListTokenVault">Token Vault列表</a></li>
<li class="nav-item"> <a class="nav-link" asp-controller="" asp-action="">新增Token Vault</a></li>
<li class="nav-item"> <a class="nav-link" asp-controller="" asp-action="">Token Entry</a></li>
@*<li class="nav-item"> <a class="nav-link" asp-controller="FinancialRecordIncome" asp-action="GetIncome">收入紀錄管理</a></li>*@
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#FinancialRecordExpenses" aria-expanded="false" aria-controls="FinancialRecordExpenses">
<span class="menu-title">Key Management</span>
<i class="menu-arrow"></i>
<i class="mdi mdi-bank menu-icon"></i>
</a>
<div class="collapse" id="FinancialRecordExpenses">
<ul class="nav flex-column sub-menu">
<li class="nav-item"> <a class="nav-link" asp-controller="" asp-action="">Key列表</a></li>
@*<li class="nav-item"> <a class="nav-link" asp-controller="FinancialRecordExpenses" asp-action="List">支出紀錄管理</a></li>*@
</ul>
</div>
</li>
</ul>
</nav><!-- partial -->
<div class="main-panel">
<div class="content-wrapper">
@RenderBody()
</div>
<footer class="footer">
<div class="d-sm-flex justify-content-center">
<span class="text-center d-sm-inline-block">Copyright © 2023 @*<a href="https://www.bootstrapdash.com/" target="_blank">*@Taipay@*</a>*@ . All rights reserved.</span>
</div>
</footer>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/misc.js"></script>
@*<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>*@
<script src="~/lib/bootstrap-4.5.0-dist/js/bootstrap.js"></script>
<script src="~/js/functions.js"></script>
<!-- plugins:js -->
@*<script src="~/vendors/js/vendor.bundle.base.js"></script>*@
<!-- endinject -->
<!-- Plugin js for this page -->
<!-- End plugin js for this page -->
<!-- inject:js -->
<script src="~/js/off-canvas.js"></script>
<script src="~/js/hoverable-collapse.js"></script>
<!-- endinject -->
<!-- Custom js for this page -->
<script src="~/js/file-upload.js"></script>
<!-- End custom js for this page -->
<!--fullcalendar@3.10.5 locale-all.js和datepicker-zh-TW.js衝到,順序不能對調-->
<!--<script src='~/lib/fullcalendar@3.10.5/moment.min.js'></script>
<script src='~/lib/fullcalendar@3.10.5/fullcalendar.min.js'></script>
<script src='~/lib/fullcalendar@3.10.5/locale-all.js'></script>-->
<!--END fullcalendar@3.10.5-->
<!--jquery ui datepicker-->
<script src="~/lib/jquery-ui/jquery-ui.min.js"></script>
<script src="~/lib/jquery.ba-dotimeout.js"></script>
<script src="~/js/datepicker-zh-TW.js"></script>
<!--END jquery ui datepicker-->
@*<!--不用Request就可以驗證輸入資料-->
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>*@
<script src="~/lib/datetimepicker/js/bootstrap-datetimepicker.js"></script>
<script src="~/lib/datetimepicker/js/locales/bootstrap-datetimepicker.zh-TW.js"></script>
<script src="~/js/site.js"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@model backstage.Models.TokenVault.TokenVaultResponse
@{
ViewData["Title"] = "TokenVault列表管理";
}
<div class="page-header">
<h3 class="page-title">TokenVault列表管理</h3>
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div id="msgDiv"></div>
</div>
<div class="row">
<div class="col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<form method="get" asp-action="List">
<h4 class="card-title">TokenVault列表管理</h4>
<div class="row justify-content-center">
<div class="col-12 col-md-10 no-padding rank-space">
<div class="row justify-content-center">
<select id="selectDepartmentList"class="form-control col-10 col-md form-control margin-right margin-top" asp-items="ViewBag.DepartmentsList">
<option value="">選擇部門</option>
</select>
</div>
<div class="row">
<div id="errorMsg" asp-validation-summary="All" class="text-danger"></div>
</div>
</div>
</div>
<div>
<div class="rank-table">
<div class="table-responsive">
<table class="table table-striped expense-color">
<thead>
<tr class="expense-color">
<th>vault_id</th>
<th>name</th>
<th>desc</th>
<th>type</th>
<th>created</th>
<th>tokenCount</th>
<th>userCount</th>
@*<th class="tblColEllipsis">備註</th>*@
<th></th>
</tr>
</thead>
<tbody id="tbody">
@*@if (Model.info.Count>0)
{
@foreach (var i in Model.info)
{
<tr id="@i.vault_id" class="expense-color">
<td><a asp-action="Detail" asp-route-Id="@i.vault_id"> @i.vault_id</a></td>
<td>@i.name</td>
<td>@i.desc</td>
<td>@i.type</td>
<td>@i.created</td>
<td>@i.tokenCount</td>
<td>@i.userCount</td>
</tr>
}
}*@
</tbody>
</table>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@section Scripts{
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf">
$('document').ready(function () {
var msg = '@TempData["msg"]';
var IsSuccess = '@TempData["IsSuccess"]';
console.log(IsSuccess + msg);
if (msg != '') {
showAlert(IsSuccess, msg);
}
// 當選擇下拉選單時觸發事件
$('#selectDepartmentList').change(function () {
var selectedValue = $(this).val(); // 獲取選擇的值
// 使用 AJAX 傳遞選擇的值
$.ajax({
url: '/TokenVault/ListTokenVaultAjax', // 替換為適當的控制器方法路徑
type: 'POST', // 或 'GET',根據實際需求
data: { merchantId: selectedValue },
success: function (response) {
$('#tbody').empty();
$('#tbody').append(response);
// 在成功取得回應後的處理邏輯
console.log(response);
},
error: function (xhr, status, error) {
// 在發生錯誤時的處理邏輯
console.error(error);
}
});
});
})
</script>
}
\ No newline at end of file
@model backstage.Models.Users.DepartmentsResponse
<div class="page-header">
<h3 class="page-title">部門列表管理</h3>
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div id="msgDiv"></div>
</div>
<div class="row">
<div class="col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
@*列表*@
<div class="">
<table class="table table-striped">
<thead>
<tr>
<th>merchant_id</th>
<th>address</th>
<th>country_id</th>
<th>postcode</th>
<th>phone</th>
@*<th>fax</th>*@
<th>vatid</th>
<th>name</th>
<th>enabled</th>
<th>creation_date</th>
@*<th>vatid_verify</th>
<th>deposit_book_verify</th>
<th>user_natid_verify</th>
<th>enabled_transaction</th>*@
<th>merchant_type</th>
<th>merchant_level</th>
<th>tts</th>
</tr>
</thead>
<tbody>
@{
if (Model.count > 0)
{
@foreach (var i in Model.merchants)
{
<tr id="@i.merchant_id">
<td>@i.merchant_id</td>
<td>@i.address</td>
<td>@i.country_id</td>
<td>@i.postcode</td>
<td>@i.phone</td>
@*<td>@i.fax</td>*@
<td>@i.vatid</td>
<td>@i.name</td>
<td>@i.enabled</td>
<td>@i.creation_date</td>
@*<td>@i.vatid_verify</td>
<td>@i.deposit_book_verify</td>
<td>@i.user_natid_verify</td>
<td>@i.enabled_transaction</td>*@
<td>@i.merchant_type</td>
<td>@i.merchant_level</td>
<td>@i.tts</td>
@*<td class="text-right">
<a class="btn btn-primary" asp-action="EditEventItem" asp-route-id="@i.Id"><i class="mdi mdi-grease-pencil"></i>編輯</a>
<button class="btn btn-inverse-danger" id="eventItem-delete-btn" data-id="@i.Id" data-name="@i.Title"><i class="mdi mdi-delete-forever"></i>刪除</button>
</td>*@
</tr>
}
}
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
@model backstage.Models.Users.UserResponse
<div class="page-header">
<h3 class="page-title">使用者列表管理</h3>
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div id="msgDiv"></div>
</div>
<div class="row">
<div class="col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
@*列表*@
<div class="">
<table class="table table-striped">
<thead>
<tr>
<th>uid</th>
<th>name</th>
<th>name_en</th>
<th>username</th>
<th>locked</th>
<th>creation_date</th>
<th>enabled</th>
<th>birthdate</th>
<th>marital_status</th>
<th>gender</th>
<th>education</th>
<th>natid</th>
<th>lang</th>
</tr>
</thead>
<tbody>
@{
if (Model.userCount > 0)
{
@foreach (var i in Model.Users)
{
<tr id="@i.uid">
<td>@i.uid</td>
<td>@i.name</td>
<td>@i.name_en</td>
<td>@i.username</td>
<td>@i.locked</td>
<td>@i.creation_date</td>
<td>@i.enabled</td>
<td>@i.birthdate</td>
<td>@i.marital_status</td>
<td>@i.gender</td>
<td>@i.education</td>
<td>@i.natid</td>
<td>@i.lang</td>
@*<td class="text-right">
<a class="btn btn-primary" asp-action="EditEventItem" asp-route-id="@i.Id"><i class="mdi mdi-grease-pencil"></i>編輯</a>
<button class="btn btn-inverse-danger" id="eventItem-delete-btn" data-id="@i.Id" data-name="@i.Title"><i class="mdi mdi-delete-forever"></i>刪除</button>
</td>*@
</tr>
}
}
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
@model backstage.Models.Users.User
@{
ViewData["Title"] = "Login";
}
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>@ViewData["Title"]</title>
<!-- End Required meta tags -->
<!-- plugins:css -->
<link rel="stylesheet" href="~/vendors/mdi/css/materialdesignicons.min.css">
<link rel="stylesheet" href="~/vendors/css/vendor.bundle.base.css">
<!-- endinject -->
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
@*<link rel="stylesheet" href="~/css/site.css" />*@
<!-- Layout styles -->
<link rel="stylesheet" href="~/css/style.css">
<!-- End layout styles -->
<link rel="shortcut icon" href="~/images/favicon.png" />
<!--jquery ui datepicker-->
<link href="~/lib/jquery-ui/jquery-ui.min.css" rel="stylesheet" />
<!--END jquery ui datepicker-->
</head>
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth">
<div class="row flex-grow">
<div class="col-lg-4 mx-auto">
<div class="auth-form-light text-left p-5">
<div class="brand-logo">
@*<img src="~/images/logo.svg">*@
</div>
<h4 class="text-center">TokenVault管理後台</h4>
<input id="msg" hidden value="@TempData["msg"]" />
@if (TempData["isSuccess"] != null)
{
<input id="isSuccess" hidden value="@TempData["isSuccess"].ToString()" />
}
<div id="msgDiv"></div>
<!-- <h6 class="font-weight-light">基本資料</h6> -->
<form class="pt-3" method="post" asp-action="login" asp-route-ReturnUrl=@Context.Request.Query["ReturnUrl"]>
<div id="errorMsg" asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<input class="form-control form-control-lg" asp-for="username" placeholder="帳號" />
<span asp-validation-for="username" class="text-danger"></span>
</div>
<div class="form-group">
<input class="form-control form-control-lg" type="password" asp-for="pwd" placeholder="密碼" />
<span asp-validation-for="pwd" class="text-danger"></span>
</div>
<div class="mt-3">
<button type="submit" class="btn btn-block btn-gradient-primary btn-lg font-weight-medium">登入</button>
</div>
@*<div class="my-2 d-flex justify-content-between align-items-center">
<div class="form-check">
<label class="form-check-label text-muted">
<input type="checkbox" asp-for="keepLogin" class="form-check-input">保持登入
</label>
</div>
<a asp-action="RecoverPassword" class="auth-link text-black">忘記密碼</a>
</div>*@
@*<div class="mb-2">
<button type="button" class="btn btn-block btn-facebook">
<i class="mdi mdi-facebook mr-2"></i>使用facebook登入</button>
</div>*@
<div class="text-center mt-4 font-weight-light">沒有帳號?<a asp-action="Register" class="text-primary">建立</a></div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- content-wrapper ends -->
@*<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>*@
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<!-- plugins:js -->
<script src="~/vendors/js/vendor.bundle.base.js"></script>
<!-- endinject -->
<!-- Plugin js for this page -->
<!-- End plugin js for this page -->
<!-- inject:js -->
<script src="~/js/off-canvas.js"></script>
<script src="~/js/hoverable-collapse.js"></script>
<script src="~/js/misc.js"></script>
<!-- endinject -->
<!-- Custom js for this page -->
<script src="~/js/file-upload.js"></script>
<!-- End custom js for this page -->
<!--jquery ui datepicker-->
<script src="~/lib/jquery-ui/jquery-ui.min.js"></script>
<!--END jquery ui datepicker-->
<script src="~/js/jquery.ba-dotimeout.js"></script>
</body>
</html>
@model backstage.Models.Users.UserForRegister
@{
ViewData["Title"] = "Register";
}
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>@ViewData["Title"]</title>
<!-- End Required meta tags -->
<!-- plugins:css -->
<link rel="stylesheet" href="~/vendors/mdi/css/materialdesignicons.min.css">
<link rel="stylesheet" href="~/vendors/css/vendor.bundle.base.css">
<!-- endinject -->
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
@*<link rel="stylesheet" href="~/css/site.css" />*@
<!-- Layout styles -->
<link rel="stylesheet" href="~/css/style.css">
<!-- End layout styles -->
<link rel="shortcut icon" href="~/images/favicon.png" />
</head>
<body>
<input id="msg" hidden value="@TempData["msg"]" />
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth">
<div class="row flex-grow">
<div class="col-lg-4 mx-auto">
<div class="auth-form-light text-left p-5">
<div class="brand-logo">
<img src="~/images/logo.svg">
</div>
<h4 class="text-center">濟福寺景德祠</h4>
<!-- <h6 class="font-weight-light">基本資料</h6> -->
<form class="pt-3" method="post" asp-action="register" asp-route-ReturnUrl="/User/Login">
<div id="errorMsg" asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<input class="form-control form-control-lg" asp-for="Username" placeholder="e-mail" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<input class="form-control form-control-lg" type="password" asp-for="pwd" placeholder="密碼" />
<span asp-validation-for="pwd" class="text-danger"></span>
</div>
<div class="form-group">
<input class="form-control form-control-lg" type="password" asp-for="ConfirmPassword" placeholder="確認密碼" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="mt-3">
<button type="submit" class="btn btn-block btn-gradient-primary btn-lg font-weight-medium">註冊</button>
</div>
@*<a asp-action="Login" class="text-center mt-4 font-weight-light">返回登入</a>*@
<div class="text-center mt-4 font-weight-light"><a asp-action="Login" class="text-primary">返回登入</a></div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- content-wrapper ends -->
@*<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>*@
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<!-- plugins:js -->
<script src="~/vendors/js/vendor.bundle.base.js"></script>
<!-- endinject -->
<!-- Plugin js for this page -->
<!-- End plugin js for this page -->
<!-- inject:js -->
<script src="~/js/off-canvas.js"></script>
<script src="~/js/hoverable-collapse.js"></script>
<script src="~/js/misc.js"></script>
<!-- endinject -->
<!-- Custom js for this page -->
<script src="~/js/file-upload.js"></script>
<!-- End custom js for this page -->
<script src="~/js/jquery.ba-dotimeout.js"></script>
<script src="~/js/User.js"></script>
</body>
</html>
@using backstage
@using backstage.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
{
"LoginExpireMinute": 180,
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"IP": "http://118.163.142.162:8082",
"key": "backstage2019-0149849165168"
}
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
]
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info"
internalLogFile="c:\temp\internal-nlog.txt">
<!-- 啟用 ASP.NET Core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- log 儲存目標 -->
<targets>
<!-- 儲存目標類型為 "檔案" -->
<target xsi:type="File" name="User_Log" fileName=".\logs\User_Log\nlog-User_Log-${shortdate}.log"
layout="${longdate}${newline}${uppercase:${level}}|${logger}${newline}${message} ${exception:format=tostring}${newline}" />
<target xsi:type="File" name="CallApi_Log" fileName=".\logs\CallApi_Log\nlog-CallApi_Log-${shortdate}.log"
layout="${longdate}${newline}${uppercase:${level}}|${logger}${newline}${message} ${exception:format=tostring}${newline}" />
</targets>
<!-- 設定 logger 名稱與 log 儲存目標的對應 -->
<rules>
<logger name="backstage.Controllers.UserController" minlevel="Trace" writeTo="User_Log" />
<logger name="backstage.Helpers.CallApi" minlevel="Trace" writeTo="CallApi_Log" />
</rules>
</nlog>
\ No newline at end of file
.dottedTable {
border-style: dotted;
width: 600px;
height: 100px;
border: 1px dashed #0000ff
}
.dotted {
border-style: dotted;
width:100px;
height: 100px;
border: 1px dashed #0000ff
}
.showLine {
float: left;
height: 10px;
width: 100%;
border: 0;
background: url(/images/xian.png) center bottom no-repeat;
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 153 187" style="enable-background:new 0 0 153 187;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.2;fill:#FFFFFF;}
</style>
<g>
<title>3</title>
<desc>Created with Sketch.</desc>
<g id="Mask-_x2B_-Mask-Mask" transform="translate(14.000000, 0.000000)">
<g id="Mask">
</g>
<g id="Mask_1_">
<path class="st0" d="M138,141.2c-3.6,0.5-7.3,0.8-11,0.8c-29.6,0-55.4-16.5-68.6-40.9c-6-11-9.4-23.7-9.4-37.1
c0-26.5,13.2-49.9,33.4-64H138v129.5"/>
</g>
<g id="Mask_2_">
<path class="st0" d="M138,141.2V187H-15c0.2-43.3,31.9-79.1,73.4-85.9c4.6-0.8,9.3-1.1,14.1-1.1c26.1,0,49.5,11.4,65.5,29.5"/>
</g>
</g>
</g>
</svg>

$(function () {
let href = this.location.pathname;
console.log('href=' + href)
$('#clearBtn').click(function () {
$('input').val("");
});
/*let pay_type = $(".pay-type-create option:selected").text();
if (pay_type == "支票") {
$('.check-create-hide').show();
}
else {
$('.check-create-hide').hide();
}*/
//for home/index todolist
//============首頁todo list功能================
if (href === "/") {
//編輯
$('.todo-list').on('change', 'input[type="checkbox"]', function () {
let checkbox = $(this);
$(this).parents('li').toggleClass('completed');
$(this).attr('disabled', true);
let checked = $(this).prop('checked');
let thisId = $(this).data('id');
$.post('/home/ChangeToDoListItem', { id: thisId, IsDone: checked }).done(function (data) {
console.log($(this))
checkbox.attr('disabled', false);
showAlert(data.isSuccess, data.message);
});
});
//新增
$('#add-task').click(function () {
var post_data = { Subject: $('#new_task').val() };
$.post('/home/CreateItem', post_data).done(function (data) {
showAlert(data.isSuccess, data.message);
if (data.isSuccess) {
$('#new_task').val('');
var item = JSON.parse(data.data);
console.log(item)
$('.todo-list-custom').append("<li><div class='form-check'><label class='form-check-label'><input class='checkbox' type='checkbox' data-id='" + item.id + "'/>" + item.subject + "<i class='input-helper'></i></label></div><i class='remove mdi mdi-close-circle-outline' data-id='" + item.id + "'></i></li>");
}
});
});
//=============刪除todolist=============
$('.todo-list').on('click', '.remove', function () {
let item = $(this).parent('li');
//console.log($(this).siblings('.form-check').find('.checkbox').prop('disabled'));
let checkbox = $(this).siblings('.form-check').find('.checkbox');
let checkboxStatus = checkbox.prop('disabled');
let checked = checkbox.prop('checked');
console.log('checked=' + checked)
if (!checkboxStatus) {
if (checked == true) {
console.log($(this).data("id"));
var post_data = { id: $(this).data("id") };
$.post('/home/DeleteToDoListItem', post_data).done(function (data) {
showAlert(data.isSuccess, data.message);
if (data.isSuccess)
item.remove();
});
}
}
});
}
//============END首頁todo list功能================
$('#openUploadModal').click(function () {
$('#fileList').html("");
})
//uploadModal
$('#inputGroupFile01').on('change', function () {
var files = $('input[name="files"]').prop('files');//获取到文件列表
var names = [];
for (var i = 0; i != files.length; i++) {
console.log(files[i].name)
names.push(files[i].name);
}
if (files.length > 1) {
$('#fileList').html(names.join("</br>"));
$(this).next('label').html("multiple files");
}
else {
$('#fileList').html("");
$(this).next('label').html(names[0]);
}
})
$('#uploadBtn').click(function () {
var files = $('input[name="files"]').prop('files');//获取到文件列表
if (files.length == 0) {
alert('請選擇圖片');
return;
} else {
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("files", files[i]);
}
formData.append('Route', "Home");
$.ajax({
url: "/Upload/UploadImage",
data: formData,
processData: false,
contentType: false,
type: HttpMethod.Post,
success: function (data) {
$('input[name="files"]').val('');
console.log("test");
console.log(data);
alert(data.message);
if (data.isSuccess) {
let inputFile = $('#inputGroupFile01')
const input = document.querySelector('#inputGroupFile01')
input.value = '';
$('#uploadModal').modal('hide');
}
},
error: function (data) {
console.log(data);
}
});
}
});
//============首頁通知功能================
function GetNotifyForAjax() {
$.post('/home/GetNotifyCountForAjax').done(function (data) {
//console.log(data.data)
$('.count-symbol').prop('hidden', false);
if (data.data != 0) { $('.count-symbol').show() }
else {
$('.count-symbol').hide();
$('#notifyData>a:not(:nth-last-child(1))').remove();
$('#setReadBtn').addClass('disabled')
}
});
}
if (!href.includes("Login") && !href.includes("login")) {
//notify navbar
//setInterval(function () { GetNotifyForAjax() }, 3000);
}
$('#notificationDropdown').click(function () {
$.post('/home/GetNotifyDataForAjax').done(function (data) {
var mydata = JSON.parse(data.data);
//console.log(mydata)
if (mydata != null) {
$('#setReadBtn').removeClass('disabled')
$('#notifyList>a:not(:nth-last-child(1))').remove();
for (var item in mydata) {
var obj = mydata[item];
//console.log(obj)
/*let icon_tea = '<div class="preview-thumbnail"><div class="preview-icon bg-success"><i class="mdi mdi-leaf"></i></div></div>';
let icon_fortuneLight = '<div class="preview-thumbnail"><div class="preview-icon bg-warning"><i class="mdi mdi-coin"></i></div></div>';
let icon_brightLight = '<div class="preview-thumbnail"><div class="preview-icon bg-info"><i class="mdi mdi-white-balance-incandescent"></i></div></div>';
let icon_donate = '<div class="preview-thumbnail"><div class="preview-icon bg-danger"><i class="mdi mdi-cash-usd"></i></div></div>';
let icon_default = '<div class="preview-thumbnail"><div class="preview-icon"></div></div>'
var icon;
switch (obj.itemName) {
case '青草茶': icon = icon_tea;
break;
case '文昌': icon = icon_brightLight;
break;
case '財利燈': icon = icon_fortuneLight;
break;
case '捐贈': icon = icon_donate;
break;
default: icon = icon_default;
break;
}*/
if (obj.itemName == null || obj.itemName == "")
obj.itemName = "Null";
let icon = "";
let fontColor = "";
//回傳字串象徵的顏色
let colorHex = TextColor(obj.itemName);
//判斷背景顏色深淺來決定字的顏色
let ContrastYIQ = getContrastYIQ(colorHex);
if (ContrastYIQ == "light")
fontColor = "#000000";
else
fontColor = "#ffffff";
icon = "<input type='button' value='" + obj.itemName.split("")[0] + "' style='width: 50px; height: 50px; border-radius: 50%; font-size: 15pt; background-color: " + colorHex + "; border: none; color: " + fontColor + "'>"
let row = "<a href='/FinancialRecordIncome/GetIncome?Type=收入' class='dropdown-item preview-item'>" + icon + "<div class='preview-item-content d-flex align-items-start flex-column justify-content-center'>"
+ "<h6 class='preview-subject font-weight-normal mb-1'>" + obj.memberName + "</h6><p class='text-gray ellipsis mb-0'>" + obj.itemName + "</p></div></a >"
$('#notifyList').append(row);
}
}
});
});
//設為已讀
$('#setReadBtn').click(function () {
$.post('/home/ReadNotifyDataForAjax').done(function (data) {
if (data.isSuccess) {
showAlert(data.isSuccess, data.message);
}
});
});
//============END首頁通知功能================
})
\ No newline at end of file
This diff is collapsed.
/* Chinese initialisation for the jQuery UI date picker plugin. */
/* Written by Ressol (ressol@gmail.com). */
(function (factory) {
"use strict";
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["../widgets/datepicker"], factory);
} else {
// Browser globals
factory(jQuery.datepicker);
}
})(function (datepicker) {
"use strict";
datepicker.regional["zh-TW"] = {
closeText: "關閉",
prevText: "&#x3C;上個月",
nextText: "下個月&#x3E;",
currentText: "今天",
monthNames: ["一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"],
monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"],
dayNames: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
dayNamesShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
dayNamesMin: ["日", "一", "二", "三", "四", "五", "六"],
weekHeader: "週",
dateFormat: "yy/mm/dd",
firstDay: 1,
isRTL: false,
showMonthAfterYear: true,
yearSuffix: "年"
};
datepicker.setDefaults(datepicker.regional["zh-TW"]);
return datepicker.regional["zh-TW"];
});
\ No newline at end of file
(function($) {
'use strict';
$(function() {
$('.file-upload-browse').on('click', function() {
var file = $(this).parent().parent().parent().find('.file-upload-default');
file.trigger('click');
});
$('.file-upload-default').on('change', function() {
$(this).parent().find('.form-control').val($(this).val().replace(/C:\\fakepath\\/i, ''));
});
});
})(jQuery);
\ No newline at end of file

//----------cookie get set delete----------Start
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) {
let result = parts.pop().split(';').shift();
console.log(result);
return result;
}
}
function setCookie(name, value, minute) {
var expires = "";
if (minute) {
var date = new Date();
date.setTime(date.getTime() + (minute * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
var cookie = name + "=" + (value || "") + expires + "; path=/";
document.cookie = cookie;
}
function deleteCookie(name) {
document.cookie = name + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}
//----------cookie get set delete----------END
//----------formatDate----------Start
function formatDate(date) {
var dateString = new Date(date.getTime() - (date.getTimezoneOffset() * 60000))
.toISOString()
.split("T")[0];
return dateString;
}
Date.prototype.setFormat = function (format) {
let year = this.getFullYear();
let month = this.getMonth() + 1;
let day = this.getDate();
if (format == "yyyy-MM-dd")
return year + '-' + (month < 10 ? '0' : '') + month + '-' + (day < 10 ? '0' : '') + day;
if (format == "yyyy/MM/dd")
return year + '/' + (month < 10 ? '0' : '') + month + '/' + (day < 10 ? '0' : '') + day;
}
Date.prototype.addMonth = function (num) {
let year = this.getFullYear();
let month = this.getMonth() + num;
let day = this.getDate();
return new Date(year, month, day);
}
//----------formatDate----------END
//----------通知 字首icon function----------Start
function TextColor(text) {
let charArray = text.split("");
let total = 0;
for (let i in charArray) {
total += charArray[i].codePointAt(0)
}
let f = parseFloat("0." + total);
return "#" + ((1 << 24) * f | 0).toString(16);
}
//16進制顏色轉化為RGB顏色
function colorRgb(str) {
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
var sColor = str.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
var sColorNew = "#";
for (var i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
//處理六位的顏色值
var sColorChange = [];
for (var i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
return "rgb(" + sColorChange.join(",") + ")";
} else {
return sColor;
}
}
//判斷是否為亮色
function getContrastYIQ(hexcolor) {
var colorrgb = colorRgb(hexcolor);
var colors = colorrgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
var red = colors[1];
var green = colors[2];
var blue = colors[3];
var brightness;
brightness = (red * 299) + (green * 587) + (blue * 114);
brightness = brightness / 255000;
if (brightness >= 0.5) {
return "light";
} else {
return "dark";
}
}
//----------通知 字首icon function----------END
(function($) {
'use strict';
//Open submenu on hover in compact sidebar mode and horizontal menu mode
$(document).on('mouseenter mouseleave', '.sidebar .nav-item', function(ev) {
var body = $('body');
var sidebarIconOnly = body.hasClass("sidebar-icon-only");
var sidebarFixed = body.hasClass("sidebar-fixed");
if (!('ontouchstart' in document.documentElement)) {
if (sidebarIconOnly) {
if (sidebarFixed) {
if (ev.type === 'mouseenter') {
body.removeClass('sidebar-icon-only');
}
} else {
var $menuItem = $(this);
if (ev.type === 'mouseenter') {
$menuItem.addClass('hover-open')
} else {
$menuItem.removeClass('hover-open')
}
}
}
}
});
$('.aside-toggler').click(function(){
$('.chat-list-wrapper').toggleClass('slide')
});
})(jQuery);
\ No newline at end of file
var ChartColor = ["#5D62B4", "#54C3BE", "#EF726F", "#F9C446", "rgb(93.0, 98.0, 180.0)", "#21B7EC", "#04BCCC"];
var primaryColor = getComputedStyle(document.body).getPropertyValue('--primary');
var secondaryColor = getComputedStyle(document.body).getPropertyValue('--secondary');
var successColor = getComputedStyle(document.body).getPropertyValue('--success');
var warningColor = getComputedStyle(document.body).getPropertyValue('--warning');
var dangerColor = getComputedStyle(document.body).getPropertyValue('--danger');
var infoColor = getComputedStyle(document.body).getPropertyValue('--info');
var darkColor = getComputedStyle(document.body).getPropertyValue('--dark');
var lightColor = getComputedStyle(document.body).getPropertyValue('--light');
(function ($) {
'use strict';
$(function () {
var body = $('body');
var contentWrapper = $('.content-wrapper');
var scroller = $('.container-scroller');
var footer = $('.footer');
var sidebar = $('.sidebar');
//Add active class to nav-link based on url dynamically
//Active class can be hard coded directly in html file also as required
function addActiveClass(element) {
if (current === "") {
//for root url
//console.log(element.attr('href'));
if (element.attr('href').indexOf("index") !== -1) {
element.parents('.nav-item').last().addClass('active');
if (element.parents('.sub-menu').length) {
element.closest('.collapse').addClass('show');
element.addClass('active');
}
}
} else {
//for other url
//console.log(element.attr('href'));
if (element.attr('href').indexOf(current) !== -1 && element.attr('href').indexOf(current2) !== -1) {
if (type !== '') {
if (element.attr('href').indexOf(type) === -1)
return;
}
element.parents('.nav-item').last().addClass('active');
if (element.parents('.sub-menu').length) {
element.closest('.collapse').addClass('show');
element.addClass('active');
}
if (element.parents('.submenu-item').length) {
element.addClass('active');
}
}
}
}
//console.log("location.pathname=" + location.pathname);
var current = location.pathname.split("/").slice(2)[0];
var root = location.pathname.split("/")[1];
var urlParams = new URLSearchParams(window.location.search);
//console.log('1type=' + urlParams.get('Type'));
var type = '';
if (urlParams.get('Type') !== null)
type = encodeURIComponent( urlParams.get('Type'));
//console.log('2type=' + type);
if (current !== undefined) {
//console.log('current=' + current);
current = current.replace(/^\/|\/$/g, '');
}
let current2 = "";
if (current === "GetReport") {
let githubURL = new URL(location.href);
let params = githubURL.searchParams;
var type = params.get('Type');
current2 = encodeURIComponent(type);
} else
current2 = root;
$('.nav li a', sidebar).each(function () {
var $this = $(this);
addActiveClass($this);
});
//$('.horizontal-menu .nav li a').each(function () {
// var $this = $(this);
// addActiveClass($this);
//});
//Close other submenu in sidebar on opening any
sidebar.on('show.bs.collapse', '.collapse', function () {
sidebar.find('.collapse.show').collapse('hide');
});
//Change sidebar and content-wrapper height
applyStyles();
function applyStyles() {
//Applying perfect scrollbar
if (!body.hasClass("rtl")) {
if (body.hasClass("sidebar-fixed")) {
var fixedSidebarScroll = new PerfectScrollbar('#sidebar .nav');
}
}
}
$('[data-toggle="minimize"]').on("click", function () {
if ((body.hasClass('sidebar-toggle-display')) || (body.hasClass('sidebar-absolute'))) {
body.toggleClass('sidebar-hidden');
} else {
body.toggleClass('sidebar-icon-only');
}
});
//checkbox and radios
$(".form-check label,.form-radio label").append('<i class="input-helper"></i>');
//fullscreen
$("#fullscreen-button").on("click", function toggleFullScreen() {
if ((document.fullScreenElement !== undefined && document.fullScreenElement === null) || (document.msFullscreenElement !== undefined && document.msFullscreenElement === null) || (document.mozFullScreen !== undefined && !document.mozFullScreen) || (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen)) {
if (document.documentElement.requestFullScreen) {
document.documentElement.requestFullScreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullScreen) {
document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (document.documentElement.msRequestFullscreen) {
document.documentElement.msRequestFullscreen();
}
} else {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
})
});
})(jQuery);
\ No newline at end of file
(function($) {
'use strict';
$(function() {
$('[data-toggle="offcanvas"]').on("click", function() {
$('.sidebar-offcanvas').toggleClass('active')
});
});
})(jQuery);
\ No newline at end of file

//========show alert通知訊息============
function showAlert(status, msg) {
console.log('showAlert=' + status)
color = 'alert-success';
if (status !== 'True' && status !== true) {
color = 'alert-danger';
status = 'Error!';
}
else {
status = 'Success!';
}
$.doTimeout('alert');
$('#msgDiv').html('<div class="alert ' + color + ' alert-dismissible">' +
'<button type="button" class="close" data-dismiss="alert">&times;</button>' +
' <strong>' + status + '</strong> ' + msg + '</div>');
$("#msgDiv").show();
$.doTimeout('alert', 4000, function () {
$("#msgDiv").slideUp(200, function () {
$(this).alert('close');
});
})
}
//========END show alert通知訊息============
//$('#FinancialItemId').change(function () {
//alert($(this).children('option:selected').data('has-believer'));
//});
//分頁使用
//停用submit先將form表單補上page後 在重新submit
$('#selectPage button').click(function (e) {
e.preventDefault();
//console.log('id=' + $(this).data('page'))
var input_Page = $("<input>").attr("type", "hidden").attr("name", "page").val($(this).data('page'));
$('form').append(input_Page);
//console.log('form=' + $('form').serialize());
$('form').submit();
})
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*!
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus:not(:focus-visible) {
outline: 0 !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]) {
color: inherit;
text-decoration: none;
}
a:not([href]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
-ms-overflow-style: scrollbar;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg {
overflow: hidden;
vertical-align: middle;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #6c757d;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
[role="button"] {
cursor: pointer;
}
select {
word-wrap: normal;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button:not(:disabled),
[type="button"]:not(:disabled),
[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
cursor: pointer;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */
\ No newline at end of file
/*!
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment