-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
109 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,105 +7,123 @@ | |
<title>salvo</title> | ||
</head> | ||
<body id="body"> | ||
<div | ||
class="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8" | ||
> | ||
<div class="w-full max-w-md space-y-8"> | ||
<div> | ||
<h2 | ||
class="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900" | ||
> | ||
{{login}} | ||
</h2> | ||
</div> | ||
<form class="mt-8 space-y-6" action="#" method="POST"> | ||
<input type="hidden" name="remember" value="true" /> | ||
<div class="-space-y-px rounded-md shadow-sm"> | ||
<div> | ||
<label for="username" class="sr-only">{{username}}</label> | ||
<input | ||
id="username" | ||
name="username" | ||
type="text" | ||
autocomplete="username" | ||
required | ||
class="relative block w-full appearance-none rounded-none rounded-t-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-sky-500 focus:outline-none focus:ring-sky-500 sm:text-sm" | ||
placeholder="username" | ||
/> | ||
</div> | ||
<div x-data="loginForm()"> | ||
<template x-if="!isLoggedIn"> | ||
<div | ||
class="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8" | ||
> | ||
<div class="w-full max-w-md space-y-8"> | ||
<div> | ||
<label for="password" class="sr-only">{{password}}</label> | ||
<input | ||
id="password" | ||
name="password" | ||
type="password" | ||
autocomplete="current-password" | ||
required | ||
class="relative block w-full appearance-none rounded-none rounded-b-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-sky-500 focus:outline-none focus:ring-sky-500 sm:text-sm" | ||
placeholder="Password" | ||
/> | ||
<h2 | ||
class="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900" | ||
> | ||
login | ||
</h2> | ||
</div> | ||
</div> | ||
<div> | ||
<button | ||
hx-post="/login" | ||
hx-target-error="error" | ||
hx-target="#body" | ||
hx-swap="outerHTML" | ||
type="submit" | ||
class="group relative flex w-full justify-center rounded-md border border-transparent bg-sky-600 py-2 px-4 text-sm font-medium text-white hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2" | ||
> | ||
<span class="absolute inset-y-0 left-0 flex items-center pl-3"> | ||
<svg | ||
class="h-5 w-5 text-sky-500 group-hover:text-sky-400" | ||
xmlns="http://www.w3.org/2000/svg" | ||
viewBox="0 0 20 20" | ||
fill="currentColor" | ||
aria-hidden="true" | ||
> | ||
<path | ||
fill-rule="evenodd" | ||
d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z" | ||
clip-rule="evenodd" | ||
<form class="mt-8 space-y-6" @submit.prevent="submit"> | ||
<input type="hidden" name="remember" value="true" /> | ||
<div class="-space-y-px rounded-md shadow-sm"> | ||
<div> | ||
<label for="username" class="sr-only">账号</label> | ||
<input | ||
x-model="username" | ||
type="text" | ||
autocomplete="username" | ||
required | ||
class="relative block w-full appearance-none rounded-none rounded-t-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-sky-500 focus:outline-none focus:ring-sky-500 sm:text-sm" | ||
placeholder="username" | ||
/> | ||
</div> | ||
<div> | ||
<label for="password" class="sr-only">密码</label> | ||
<input | ||
x-model="password" | ||
type="password" | ||
autocomplete="current-password" | ||
required | ||
class="relative block w-full appearance-none rounded-none rounded-b-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-sky-500 focus:outline-none focus:ring-sky-500 sm:text-sm" | ||
placeholder="Password" | ||
/> | ||
</svg> | ||
</span> | ||
Sign in | ||
</button> | ||
</div> | ||
</div> | ||
<div> | ||
<button | ||
type="submit" | ||
class="group relative flex w-full justify-center rounded-md border border-transparent bg-sky-600 py-2 px-4 text-sm font-medium text-white hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2" | ||
> | ||
<span | ||
class="absolute inset-y-0 left-0 flex items-center pl-3" | ||
> | ||
<svg | ||
class="h-5 w-5 text-sky-500 group-hover:text-sky-400" | ||
xmlns="http://www.w3.org/2000/svg" | ||
viewBox="0 0 20 20" | ||
fill="currentColor" | ||
aria-hidden="true" | ||
> | ||
<path | ||
fill-rule="evenodd" | ||
d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z" | ||
clip-rule="evenodd" | ||
/> | ||
</svg> | ||
</span> | ||
Sign in | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
</template> | ||
<template x-if="isLoggedIn"> | ||
<div x-html="userList"></div> | ||
</template> | ||
</div> | ||
</body> | ||
<script src="https://cdn.tailwindcss.com"></script> | ||
<script src="https://unpkg.com/[email protected]"></script> | ||
<script src="https://unpkg.com/[email protected]"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> | ||
<script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | ||
<script src="//unpkg.com/alpinejs" defer></script> | ||
<script> | ||
htmx.onLoad(function (target) { | ||
document.body.addEventListener("htmx:afterRequest", function (evt) { | ||
const targetError = | ||
evt.target.attributes.getNamedItem("hx-target-error"); | ||
if (evt.detail.failed && targetError) { | ||
let data = JSON.parse(evt.detail.xhr.response); | ||
console.log(data); | ||
Swal.fire({ | ||
title: "Error!", | ||
text: data.msg, | ||
icon: "error", | ||
confirmButtonText: "close", | ||
}); | ||
} | ||
}); | ||
document.body.addEventListener("htmx:beforeRequest", function (evt) { | ||
const targetError = | ||
evt.target.attributes.getNamedItem("hx-target-error"); | ||
if (targetError) { | ||
//document.getElementById(targetError.value).style.display = "none"; | ||
} | ||
}); | ||
}); | ||
function loginForm() { | ||
return { | ||
username: "", | ||
password: "", | ||
isLoggedIn: false, | ||
userList: "", | ||
async submit() { | ||
try { | ||
const response = await fetch("/login", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
username: this.username, | ||
password: this.password, | ||
}), | ||
}); | ||
if (!response.ok) { | ||
const data = await response.json(); | ||
throw new Error(`${data.msg}`); | ||
} | ||
this.isLoggedIn = true; | ||
const userListResponse = await fetch("/user", { | ||
headers: { | ||
"X-Fragment-Header": "true", | ||
}, | ||
}); | ||
this.userList = await userListResponse.text(); | ||
history.pushState(null, '', '/user'); | ||
} catch (error) { | ||
Swal.fire({ | ||
title: "Error!", | ||
text: error.message, | ||
icon: "error", | ||
confirmButtonText: "OK", | ||
}); | ||
} | ||
}, | ||
}; | ||
} | ||
</script> | ||
</html> |