diff --git a/src/change.pug b/src/change.pug new file mode 100644 index 0000000..89fc7b6 --- /dev/null +++ b/src/change.pug @@ -0,0 +1,53 @@ +html(lang="zh-Hant") + head + title ExpTech | 更改密碼 + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1") + meta(name="description", content="更改 ExpTech 帳號密碼") + + //- Facebook Meta Tags + meta(property="og:site_name", content="探索科技 | ExpTech Studio") + meta(property="og:url", content="https://exptech.com.tw/api/v1/file/exptech/register.html") + meta(property="og:type", content="website") + meta(property="og:title", content="更改密碼") + meta(property="og:description", content="更改 ExpTech 帳號密碼") + meta(property="og:image", content="https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/image/Icon/ExpTech.png") + + //- Twitter Meta Tags + meta(name="twitter:card", content="summary") + meta(property="twitter:domain", content="exptech.com.tw") + meta(property="twitter:url", content="https://exptech.com.tw/api/v1/file/exptech/register.html") + meta(name="twitter:title", content="更改密碼") + meta(name="twitter:description", content="更改 ExpTech 帳號密碼") + meta(name="twitter:image", content="https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/image/Icon/ExpTech.png") + + link(rel="stylesheet", href="./stylesheets/change.scss") + link(rel="preconnect", href="https://fonts.googleapis.com") + link(rel="preconnect", href="https://fonts.gstatic.com", crossorigin) + link(href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500&display=swap", rel="stylesheet") + + body + main + #container + .title 更改密碼 + .description 更改 ExpTech 密碼 + #form-view.view + form#change.change-form + .form-item-container + .form-item + label.required(for="new-password") 密碼 + input#new-password(type="password", name="password", placeholder="密碼", autocomplete="new-password", required) + #password-strength + .form-item + label.required(for="repeat-password") 確認密碼 + input#repeat-password(type="password", name="password", placeholder="確認密碼", autocomplete="new-password", required) + button#login(type="button") 登入帳號 + button#submit(type="submit") 更改密碼 + #success-view.view + svg.check-mark(xmlns="http://www.w3.org/2000/svg", height="128", width="128", viewBox="0 96 960 960"): path(d="M421 744.537 690.537 475l-34.845-34.23L421 675.847 302.539 557.385l-33.846 34.23L421 744.537Zm59.067 211.462q-78.221 0-147.397-29.92-69.176-29.92-120.989-81.71-51.814-51.791-81.747-120.936-29.933-69.146-29.933-147.366 0-78.836 29.92-148.204 29.92-69.369 81.71-120.682 51.791-51.314 120.936-81.247 69.146-29.933 147.366-29.933 78.836 0 148.204 29.92 69.369 29.92 120.682 81.21 51.314 51.291 81.247 120.629 29.933 69.337 29.933 148.173 0 78.221-29.92 147.397-29.92 69.176-81.21 120.989-51.291 51.814-120.629 81.747-69.337 29.933-148.173 29.933ZM480 910.615q139.692 0 237.154-97.769Q814.615 715.077 814.615 576q0-139.692-97.461-237.154Q619.692 241.385 480 241.385q-139.077 0-236.846 97.461Q145.385 436.308 145.385 576q0 139.077 97.769 236.846T480 910.615ZM480 576Z") + .success-title title 更改密碼成功 + .success-description 將在五秒後跳轉回登入畫面 + a.info(href="https://exptech.com.tw/f?v=discord") Discord 伺服器 + + script(src="./scripts/change.js") + \ No newline at end of file diff --git a/src/forget.pug b/src/forget.pug new file mode 100644 index 0000000..41dad37 --- /dev/null +++ b/src/forget.pug @@ -0,0 +1,51 @@ +html(lang="zh-Hant") + head + title ExpTech | 忘記密碼 + meta(charset="utf-8") + meta(name="viewport", content="width=device-width, initial-scale=1") + meta(name="description", content="ExpTech 帳號忘記密碼") + + //- Facebook Meta Tags + meta(property="og:site_name", content="探索科技 | ExpTech Studio") + meta(property="og:url", content="https://exptech.com.tw/api/v1/file/exptech/register.html") + meta(property="og:type", content="website") + meta(property="og:title", content="忘記密碼") + meta(property="og:description", content="ExpTech 帳號忘記密碼") + meta(property="og:image", content="https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/image/Icon/ExpTech.png") + + //- Twitter Meta Tags + meta(name="twitter:card", content="summary") + meta(property="twitter:domain", content="exptech.com.tw") + meta(property="twitter:url", content="https://exptech.com.tw/api/v1/file/exptech/register.html") + meta(name="twitter:title", content="忘記密碼") + meta(name="twitter:description", content="ExpTech 帳號忘記密碼") + meta(name="twitter:image", content="https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/image/Icon/ExpTech.png") + + link(rel="stylesheet", href="./stylesheets/forget.scss") + link(rel="preconnect", href="https://fonts.googleapis.com") + link(rel="preconnect", href="https://fonts.gstatic.com", crossorigin) + link(href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500&display=swap", rel="stylesheet") + + + body + main + #container + .title 忘記密碼 + .description 重設您的 ExpTech 密碼 + #form-view.view + form#forget.forget-form + .form-item-container + .form-item + label.required(for="email") 電子郵件地址 + input#email(type="email", name="email", placeholder="電子郵件地址", autocomplete="email", required) + button#login(type="button") 登入帳號 + button#submit(type="submit") 送出 + #success-view.view + svg.check-mark(xmlns="http://www.w3.org/2000/svg", height="128", width="128", viewBox="0 96 960 960"): path(d="M421 744.537 690.537 475l-34.845-34.23L421 675.847 302.539 557.385l-33.846 34.23L421 744.537Zm59.067 211.462q-78.221 0-147.397-29.92-69.176-29.92-120.989-81.71-51.814-51.791-81.747-120.936-29.933-69.146-29.933-147.366 0-78.836 29.92-148.204 29.92-69.369 81.71-120.682 51.791-51.314 120.936-81.247 69.146-29.933 147.366-29.933 78.836 0 148.204 29.92 69.369 29.92 120.682 81.21 51.314 51.291 81.247 120.629 29.933 69.337 29.933 148.173 0 78.221-29.92 147.397-29.92 69.176-81.21 120.989-51.291 51.814-120.629 81.747-69.337 29.933-148.173 29.933ZM480 910.615q139.692 0 237.154-97.769Q814.615 715.077 814.615 576q0-139.692-97.461-237.154Q619.692 241.385 480 241.385q-139.077 0-236.846 97.461Q145.385 436.308 145.385 576q0 139.077 97.769 236.846T480 910.615ZM480 576Z") + .success-title.title 發送成功 + .success-description 已寄驗證信到你電子郵件地址請查收 + .success-description 將在五秒後跳轉回登入畫面 + a.info(href="https://exptech.com.tw/f?v=discord") Discord 伺服器 + + script(src="./scripts/forget.js") + \ No newline at end of file diff --git a/src/login.pug b/src/login.pug index 7266b48..820e77e 100644 --- a/src/login.pug +++ b/src/login.pug @@ -39,10 +39,8 @@ html(lang="zh-Hant") .form-item label.required(for="password") 用戶密碼 input#password(type="password", name="password", placeholder="用戶密碼", autocomplete="current-password", required) - a.forget-password(href="./forget.html") 忘記密碼? - a.forget-password(href="./change.html") 更改密碼? - div - | 如果這不是你的電腦,請使用私密瀏覽視窗登入。 + a.forget-password(href="./forget.pug") 忘記密碼? + div 如果這不是你的電腦,請使用私密瀏覽視窗登入。 button#register(type="button") 註冊帳號 button#submit(type="submit") 登入 a.info(href="https://exptech.com.tw/discord") Discord 伺服器 diff --git a/src/scripts/change.js b/src/scripts/change.js new file mode 100644 index 0000000..38560c6 --- /dev/null +++ b/src/scripts/change.js @@ -0,0 +1,172 @@ +const password_strength = document.getElementById("password-strength"); +const new_password = document.getElementById("new-password"); +const email = document.getElementById("email"); +const password = document.getElementById("password"); +const success_view = document.getElementById("success-view"); +const form_view = document.getElementById("form-view"); +const container = document.getElementById("container"); +const submit = document.getElementById("submit"); +const changeForm = document.getElementById("change"); + +document.getElementById("login").onclick = (e) => { + window.location.href = "./login.html"; +}; + +new_password.oninput = (e) => { + this.value = new_password.value; + password_strength.style.display = "block"; + + if (this.value.match(/(?=.*[^A-Za-z0-9@_\.-])/)) + return (password_strength.className = "error invalid"); + + if ( + this.value.match( + /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.{10,})/, + ) + ) + password_strength.className = "very-strong"; + else if (this.value.match(/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/)) + password_strength.className = "strong"; + else if (this.value.match(/((?=.*[a-zA-Z0-9])(?=.{6,}))/)) + password_strength.className = "medium"; + else if (this.value.length > 0) password_strength.className = "weak"; + else password_strength.className = "error empty"; +}; + +const urlSearchParams = new URLSearchParams(window.location.search); +const params = Object.fromEntries(urlSearchParams.entries()); + +if (!params.token) + document.location.replace("./login.html"); + +changeForm.addEventListener("submit", (e) => { + + container.style.height = form_view.offsetHeight + 76; + form_view.style.position = "absolute"; + success_view.style.position = "absolute"; + success_view.style.display = "block"; + form_view.style.opacity = 0; + container.style.height = success_view.offsetHeight + 76; + setTimeout(() => { + success_view.style.position = ""; + success_view.style.opacity = 1; + form_view.style.display = "none"; + form_view.style.position = ""; + }, 100); + + setTimeout(() => (window.location.href = "./login.html"), 5_000); + + e.preventDefault(); + + email.setCustomValidity(""); + password.setCustomValidity(""); + new_password.setCustomValidity(""); + + let values = { + email : email.value, + pass : password.value, + new_pass : new_password.value, + }; + + if (params.token) + values = { + token : params.token, + new_pass : new_password.value, + }; + + + submit.disabled = true; + + fetch("https://exptech.com.tw/api/v1/et/change", { + method : "POST", + headers : { "Content-Type": "application/json" }, + body : JSON.stringify({ + token : values.token, + email : values.email, + pass : values.pass, + new_pass : values.new_pass, + }), + }) + .then(async (res) => { + if (res.ok) { + container.style.height = form_view.offsetHeight + 76; + form_view.style.position = "absolute"; + success_view.style.position = "absolute"; + success_view.style.display = "block"; + form_view.style.opacity = 0; + container.style.height = success_view.offsetHeight + 76; + setTimeout(() => { + success_view.style.position = ""; + success_view.style.opacity = 1; + form_view.style.display = "none"; + form_view.style.position = ""; + }, 100); + + setTimeout(() => (window.location.href = "./login.html"), 5_000); + } else { + switch (await res.text()) { + case "Invaild email!": { + email.setCustomValidity("電子郵件地址無效。"); + email.reportValidity(); + break; + } + + case "Invaild pass!": { + password.setCustomValidity("舊密碼無效。"); + password.reportValidity(); + break; + } + + case "Invaild new pass!": { + new_password.setCustomValidity("新密碼無效。"); + new_password.reportValidity(); + break; + } + + case "Pass format error!": { + password.setCustomValidity("舊密碼格式錯誤。"); + password.reportValidity(); + break; + } + + case "New pass format error!": { + new_password.setCustomValidity("新密碼格式錯誤。"); + new_password.reportValidity(); + break; + } + + case "No changes found!": { + new_password.setCustomValidity("沒有發現任何變化。"); + new_password.reportValidity(); + break; + } + + case "Pass error!": { + password.setCustomValidity("舊密碼錯誤。"); + password.reportValidity(); + break; + } + + case "This account was not found!": { + new_password.setCustomValidity( + "找不到此帳戶,可能尚未註冊。", + ); + new_password.reportValidity(); + break; + } + + default: { + console.error(res); + break; + } + } + submit.disabled = false; + } + }) + .catch((err) => { + console.error(err); + submit.disabled = false; + const res = err.request.response; + alert(res); + }); +}); \ No newline at end of file diff --git a/src/scripts/forget.js b/src/scripts/forget.js new file mode 100644 index 0000000..4e8b1b6 --- /dev/null +++ b/src/scripts/forget.js @@ -0,0 +1,70 @@ +const submit = document.getElementById("submit"); +const email = document.getElementById("email"); +const container = document.getElementById("container"); +const success_view = document.getElementById("success-view"); +const form_view = document.getElementById("form-view"); +const forgetForm = document.getElementById("forget"); + +document.getElementById("login").onclick = (e) => { + window.location.href = "./login.html"; +}; + +forgetForm.addEventListener("submit", (e) => { + e.preventDefault(); + email.setCustomValidity(""); + email.reportValidity(); + + const values = { email: email.value }; + + submit.disabled = true; + + fetch("https://exptech.com.tw/api/v1/et/forget", { + method : "POST", + headers : { "Content-Type": "application/json" }, + body : JSON.stringify({ email: values.email }), + }) + .then(async (res) => { + if (res.ok) { + container.style.height = form_view.offsetHeight + 76; + form_view.style.position = "absolute"; + success_view.style.position = "absolute"; + success_view.style.display = "block"; + form_view.style.opacity = 0; + container.style.height = success_view.offsetHeight + 76; + setTimeout(() => { + success_view.style.position = ""; + success_view.style.opacity = 1; + form_view.style.display = "none"; + form_view.style.position = ""; + }, 100); + + setTimeout(() => (window.location.href = "./login.html"), 5_000); + } else { + switch (await res.text()) { + case "Invaild email!": { + email.setCustomValidity("電子郵件地址無效。"); + email.reportValidity(); + break; + } + + case "This account was not found!": { + email.setCustomValidity("找不到此帳戶,可能尚未註冊。"); + email.reportValidity(); + break; + } + + default: { + console.error(res); + break; + } + } + submit.disabled = false; + } + }) + .catch((err) => { + console.error(err); + submit.disabled = false; + const res = err.request.response; + alert(res); + }); +}); \ No newline at end of file diff --git a/src/stylesheets/change.scss b/src/stylesheets/change.scss new file mode 100644 index 0000000..aae782c --- /dev/null +++ b/src/stylesheets/change.scss @@ -0,0 +1,291 @@ +@use "./components/input.scss"; + +:root { + --background: 300deg 100% 99%; + --on-background: 336deg 9% 11%; + --primary: 327deg 42, 42%; + --on-primary: 0 0% 100%; + --primary-container: 335deg 100% 92%; + --on-primary-container: 322deg 100% 12%; + --outline: 336deg 6% 48%; + --surface-variant: 341deg 40% 91%; + --on-surface-variant: 337deg 9% 29%; + --error: 0deg 75% 42%; + --medium: 47deg 100% 23%; + --strong: 72deg 100% 20%; + --very-strong: 300deg 76% 37%; +} + +body { + display: grid; + align-items: center; + justify-content: center; + margin: 0; + padding: 0; + height: 100svh; + color: hsl(var(--on-background)); + background-color: hsl(var(--background)); + font-family: Lato, "Noto Sans TC", sans-serif; + line-height: 18px; + overflow-x: hidden; + user-select: none; +} + +.view { + width: 400px; + transition: opacity 100ms ease-in-out; +} + +#form-view { + opacity: 1; +} + +#success-view { + display: none; + opacity: 0; +} + +.check-mark { + display: block; + margin: 32px auto; + fill: hsl(var(--primary)); +} + +.success-title { + color: hsl(var(--on-surface-variant)); +} + +.success-description { + margin: 8px; + color: hsl(var(--outline)); + text-align: center; + font-size: 16px; + line-height: 18px; +} + +#container { + width: 400px; + padding: 48px 36px; + padding-left: 28px; + background-color: hsla(var(--primary), 0.04); + outline: 1px solid hsl(var(--surface-variant)); + box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1); + border-radius: 8px; +} + +.title { + font-size: 24px; + line-height: 26px; + font-weight: bold; + text-align: center; + margin-bottom: 8px; +} + +.description { + text-align: center; + margin: 16px; +} + +.change-form { + display: table; + margin: 0; + width: 100%; +} + +.form-item-container { + margin-left: 8px; + margin-bottom: 48px; +} + +.form-item { + display: flex; + flex-direction: column; + margin-bottom: 12px; +} + +.form-item { + margin-bottom: 12px; +} + +#password-strength { + display: none; + position: relative; + height: 4px; + margin-top: 12px; + margin-bottom: 32px; + border-radius: 4px; + background-color: hsl(var(--surface-variant)); +} + +#password-strength::before { + content: ""; + position: absolute; + height: 100%; + width: 100%; + border-radius: 4px; + background-color: transparent; + transition: width .1s ease-in-out, + background-color .1s ease-in-out; +} + +#password-strength::after { + content: ""; + position: absolute; + top: 100%; + margin: 8px 0; + font-weight: bold; + font-size: 14px; + line-height: 16px; + transition: color .1s ease-in-out; +} + +#password-strength.error::before { + color: hsl(var(--error)); + background-color: hsl(var(--error)); +} + +#password-strength.weak::before { + width: 25%; + color: hsl(var(--outline)); + background-color: hsl(var(--outline)); +} + +#password-strength.medium::before { + width: 50%; + color: hsl(var(--medium)); + background-color: hsl(var(--medium)); +} + +#password-strength.strong::before { + width: 75%; + color: hsl(var(--strong)); + background-color: hsl(var(--strong)); +} + +#password-strength.very-strong::before { + width: 100%; + color: hsl(var(--very-strong)); + background-color: hsl(var(--very-strong)); +} + +#password-strength.error::after { + color: hsl(var(--error)); +} + +#password-strength.empty::after { + content: "密碼不得為空"; +} + +#password-strength.invalid::after { + content: "密碼只能包含大小寫半形英數、 _ 、 . 、- 和 @"; +} + +#password-strength.weak::after { + content: "密碼強度:弱"; + width: 25%; + color: hsl(var(--outline)); +} + +#password-strength.medium::after { + content: "密碼強度:中等"; + width: 50%; + color: hsl(var(--medium)); +} + +#password-strength.strong::after { + content: "密碼強度:強"; + width: 75%; + color: hsl(var(--strong)); +} + +#password-strength.very-strong::after { + content: "密碼強度:非常強"; + width: 100%; + color: hsl(var(--very-strong)); +} + +#login { + all: unset; + padding: 10px 8px; + background-color: transparent; + color: hsl(var(--primary)); + border-radius: 4px; + font-size: 16px; + line-height: 18px; + font-weight: bold; + transition: background-color .1s ease-in-out, + opacity .1s ease-in-out; +} + +.hidden{ + display: none; +} + +#login:hover { + background-color: hsla(var(--primary), 0.12); +} + +#submit { + all: unset; + padding: 10px 24px; + background-color: hsl(var(--primary)); + color: hsl(var(--on-primary)); + border-radius: 4px; + font-size: 16px; + line-height: 18px; + font-weight: bold; + float: right; + transition: opacity .1s ease-in-out; +} + +#login:active, +#submit:active, +a:active { + opacity: 0.8; +} + +.change-password { + align-self: start; + font-size: 14px; + font-weight: bold; + margin: 12px 0; + color: hsl(var(--primary)); + text-decoration: none; +} + +.info { + display: inline-block; + margin: 16px; + font-size: 14px; + line-height: 16px; + color: hsla(var(--on-surface-variant), .6); + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: 336deg 9% 11%; + --on-background: 349deg 22% 90%; + --primary: 332 100% 84%; + --on-primary: 323deg 77 21%; + --primary-container: 325deg 53% 31%; + --on-primary-container: 335deg 100% 92%; + --outline: 341deg 8% 58%; + --surface-variant: 337deg 9% 29%; + --on-surface-variant: 340deg 17% 80%; + --error: 6deg 100% 84%; + --medium: 47deg 88% 51%; + --strong: 71deg 100% 42%; + --very-strong: 308deg 100% 83%; + } + + ::-ms-reveal { + filter: invert(100%); + } +} + +@media screen and (max-width: 768px) { + #container { + width: auto; + } +} \ No newline at end of file diff --git a/src/stylesheets/forget.scss b/src/stylesheets/forget.scss new file mode 100644 index 0000000..f831031 --- /dev/null +++ b/src/stylesheets/forget.scss @@ -0,0 +1,182 @@ +@use "./components/input.scss"; + +:root { + --background: 300deg 100% 99%; + --on-background: 336deg 9% 11%; + --primary: 327deg 42, 42%; + --on-primary: 0 0% 100%; + --primary-container: 335deg 100% 92%; + --on-primary-container: 322deg 100% 12%; + --outline: 336deg 6% 48%; + --surface-variant: 341deg 40% 91%; + --on-surface-variant: 337deg 9% 29%; +} + +body { + display: grid; + align-items: center; + justify-content: center; + margin: 0; + padding: 0; + height: 100svh; + color: hsl(var(--on-background)); + background-color: hsl(var(--background)); + font-family: Lato, "Noto Sans TC", sans-serif; + line-height: 18px; + overflow-x: hidden; + user-select: none; +} + +.view { + width: 400px; + transition: opacity 100ms ease-in-out; +} + +#form-view { + opacity: 1; +} + +#success-view { + display: none; + opacity: 0; +} + +.check-mark { + display: block; + margin: 32px auto; + fill: hsl(var(--primary)); +} + +.success-title { + color: hsl(var(--on-surface-variant)); +} + +.success-description { + margin: 8px; + color: hsl(var(--outline)); + text-align: center; + font-size: 16px; + line-height: 18px; +} + +#container { + width: 400px; + padding: 48px 36px; + padding-left: 28px; + background-color: hsla(var(--primary), 0.04); + outline: 1px solid hsl(var(--surface-variant)); + box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1); + border-radius: 8px; +} + +.title { + font-size: 24px; + line-height: 26px; + font-weight: bold; + text-align: center; + margin-bottom: 8px; +} + +.description { + text-align: center; + margin: 16px; +} + +.forget-form { + display: table; + margin: 0; + width: 100%; +} + +.form-item-container { + margin-left: 8px; + margin-bottom: 48px; +} + +.form-item { + display: flex; + flex-direction: column; + margin-bottom: 12px; +} + +.form-item { + margin-bottom: 12px; +} + +#login { + all: unset; + padding: 10px 8px; + background-color: transparent; + color: hsl(var(--primary)); + border-radius: 4px; + font-size: 16px; + line-height: 18px; + font-weight: bold; + transition: background-color .1s ease-in-out, + opacity .1s ease-in-out; +} + +#login:hover { + background-color: hsla(var(--primary), 0.12); +} + +#submit { + all: unset; + padding: 10px 24px; + background-color: hsl(var(--primary)); + color: hsl(var(--on-primary)); + border-radius: 4px; + font-size: 16px; + line-height: 18px; + font-weight: bold; + float: right; + transition: opacity .1s ease-in-out; +} + +#login:active, +#submit:active, +a:active { + opacity: 0.8; +} + +.forget-password { + align-self: start; + font-size: 14px; + font-weight: bold; + margin: 12px 0; + color: hsl(var(--primary)); + text-decoration: none; +} + +.info { + display: inline-block; + margin: 16px; + font-size: 14px; + line-height: 16px; + color: hsla(var(--on-surface-variant), .6); + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: 336deg 9% 11%; + --on-background: 349deg 22% 90%; + --primary: 332 100% 84%; + --on-primary: 323deg 77 21%; + --primary-container: 325deg 53% 31%; + --on-primary-container: 335deg 100% 92%; + --outline: 341deg 8% 58%; + --surface-variant: 337deg 9% 29%; + --on-surface-variant: 340deg 17% 80%; + } + + ::-ms-reveal { + filter: invert(100%); + } +} + +@media screen and (max-width: 768px) { + #container { + width: auto; + } +} \ No newline at end of file diff --git a/src/user.pug b/src/user.pug index 89b82a6..aa5cd1c 100644 --- a/src/user.pug +++ b/src/user.pug @@ -305,11 +305,11 @@ html(lang="zh-Hant") .application .application-name-container .application-name rts-map - .application-version v0.0.17 + .application-version v0.1.0-alpha.3 .application-maintainer Maintained by Kamiya .application-description rts-map 即時觀測地圖。 .link-container - a.link(href="http://cdn.discordapp.com/attachments/1067331542294216724/1150721152793190481/rts-map_0.0.17.exe", rel="noopener noreferrer", download) + a.link(href="https://cdn.discordapp.com/attachments/1067331542294216724/1201518464121196574/rts-map_0.1.0-alpha.3.exe", rel="noopener noreferrer", download) +icon("download") .link-text 下載 (Discord CDN)