|
@@ -0,0 +1,393 @@
|
|
|
|
+<!-- <!DOCTYPE html>
|
|
|
|
+<html lang="zh-CN">
|
|
|
|
+
|
|
|
|
+<head>
|
|
|
|
+ <meta charset="UTF-8">
|
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
+ <title>登录</title>
|
|
|
|
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
|
|
+ <style>
|
|
|
|
+ * {
|
|
|
|
+ margin: 0;
|
|
|
|
+ padding: 0;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ body {
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ min-height: 100vh;
|
|
|
|
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
|
|
|
|
+ padding: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .container {
|
|
|
|
+ width: 100%;
|
|
|
|
+ max-width: 400px;
|
|
|
|
+ background: rgba(255, 255, 255, 0.9);
|
|
|
|
+ border-radius: 16px;
|
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .header {
|
|
|
|
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
|
|
|
|
+ color: white;
|
|
|
|
+ text-align: center;
|
|
|
|
+ padding: 30px 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .header h1 {
|
|
|
|
+ font-size: 28px;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .header p {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ opacity: 0.9;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .form-container {
|
|
|
|
+ padding: 30px 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .input-group {
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+ position: relative;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .input-group label {
|
|
|
|
+ display: block;
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ color: #333;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .input-group input {
|
|
|
|
+ width: 100%;
|
|
|
|
+ padding: 14px 14px 14px 45px;
|
|
|
|
+ border: 1px solid #ddd;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .input-group input:focus {
|
|
|
|
+ outline: none;
|
|
|
|
+ border-color: #6e8efb;
|
|
|
|
+ box-shadow: 0 0 0 2px rgba(110, 142, 251, 0.2);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .input-group i {
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 15px;
|
|
|
|
+ top: 40px;
|
|
|
|
+ color: #6e8efb;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .remember-forgot {
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .remember-forgot label {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ color: #555;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .remember-forgot input {
|
|
|
|
+ margin-right: 5px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .remember-forgot a {
|
|
|
|
+ color: #6e8efb;
|
|
|
|
+ text-decoration: none;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .remember-forgot a:hover {
|
|
|
|
+ text-decoration: underline;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .btn {
|
|
|
|
+ width: 100%;
|
|
|
|
+ padding: 14px;
|
|
|
|
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
|
|
|
|
+ color: white;
|
|
|
|
+ border: none;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .btn:hover {
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .register-link {
|
|
|
|
+ text-align: center;
|
|
|
|
+ margin-top: 20px;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #555;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .register-link a {
|
|
|
|
+ color: #6e8efb;
|
|
|
|
+ text-decoration: none;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .register-link a:hover {
|
|
|
|
+ text-decoration: underline;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .message {
|
|
|
|
+ padding: 10px;
|
|
|
|
+ margin-top: 15px;
|
|
|
|
+ border-radius: 5px;
|
|
|
|
+ text-align: center;
|
|
|
|
+ display: none;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .error {
|
|
|
|
+ background-color: #ffebee;
|
|
|
|
+ color: #d32f2f;
|
|
|
|
+ border: 1px solid #ffcdd2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .success {
|
|
|
|
+ background-color: #e8f5e9;
|
|
|
|
+ color: #388e3c;
|
|
|
|
+ border: 1px solid #c8e6c9;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @media (max-width: 480px) {
|
|
|
|
+ .container {
|
|
|
|
+ border-radius: 12px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .header {
|
|
|
|
+ padding: 20px 15px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .form-container {
|
|
|
|
+ padding: 20px 15px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ </style>
|
|
|
|
+</head>
|
|
|
|
+
|
|
|
|
+<body>
|
|
|
|
+ <div class="container">
|
|
|
|
+ <div class="header">
|
|
|
|
+ <h1>欢迎回来</h1>
|
|
|
|
+ <p>请输入您的用户名和密码进行登录</p>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="form-container">
|
|
|
|
+ <div class="input-group">
|
|
|
|
+ <label for="username">用户名</label>
|
|
|
|
+ <i class="fas fa-user"></i>
|
|
|
|
+ <input type="text" id="username" placeholder="请输入用户名">
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="input-group">
|
|
|
|
+ <label for="password">密码</label>
|
|
|
|
+ <i class="fas fa-lock"></i>
|
|
|
|
+ <input type="password" id="password" placeholder="请输入密码">
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="remember-forgot">
|
|
|
|
+ <label>
|
|
|
|
+ <input type="checkbox" id="remember">
|
|
|
|
+ 记住我
|
|
|
|
+ </label>
|
|
|
|
+ <a href="#">忘记密码?</a>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <button class="btn" id="loginBtn">登录</button>
|
|
|
|
+
|
|
|
|
+ <div id="message" class="message"></div>
|
|
|
|
+
|
|
|
|
+ <div class="register-link">
|
|
|
|
+ 还没有账号?<a href="#">立即注册</a>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <script>
|
|
|
|
+ document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
+ // Mock用户数据
|
|
|
|
+ const mockUsers = [
|
|
|
|
+ { username: 'admin', password: 'admin123' },
|
|
|
|
+ { username: 'user', password: 'user123' },
|
|
|
|
+ { username: 'test', password: 'test123' },
|
|
|
|
+ { username: 'demo', password: 'demo123' }
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ const loginBtn = document.getElementById('loginBtn');
|
|
|
|
+ const usernameInput = document.getElementById('username');
|
|
|
|
+ const passwordInput = document.getElementById('password');
|
|
|
|
+ const rememberCheckbox = document.getElementById('remember');
|
|
|
|
+ const messageDiv = document.getElementById('message');
|
|
|
|
+
|
|
|
|
+ // 检查是否有保存的用户名
|
|
|
|
+ const savedUsername = localStorage.getItem('rememberedUsername');
|
|
|
|
+ if (savedUsername) {
|
|
|
|
+ usernameInput.value = savedUsername;
|
|
|
|
+ rememberCheckbox.checked = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ loginBtn.addEventListener('click', async function () {
|
|
|
|
+ const username = usernameInput.value.trim();
|
|
|
|
+ const password = passwordInput.value;
|
|
|
|
+
|
|
|
|
+ // 简单的表单验证
|
|
|
|
+ if (!username || !password) {
|
|
|
|
+ showMessage('请输入用户名和密码', 'error');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 验证用户凭据
|
|
|
|
+ const user = mockUsers.find(u => u.username === username && u.password === password);
|
|
|
|
+ let loginObj = {
|
|
|
|
+ username: username,
|
|
|
|
+ password: password
|
|
|
|
+ }
|
|
|
|
+ let res = await fetch("https://dev.fmode.cn/parse/login", {
|
|
|
|
+ "headers": {
|
|
|
|
+ "accept": "*/*",
|
|
|
|
+ "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
|
|
|
+ "content-type": "text/plain;charset=UTF-8",
|
|
|
|
+ "x-parse-application-id": "dev"
|
|
|
|
+ },
|
|
|
|
+ "body": JSON.stringify(loginObj),
|
|
|
|
+ "method": "POST",
|
|
|
|
+ "mode": "cors",
|
|
|
|
+ "credentials": "omit"
|
|
|
|
+ });
|
|
|
|
+ const data = await res.json();
|
|
|
|
+
|
|
|
|
+ console.log(data)
|
|
|
|
+ if (data?.objectId) {
|
|
|
|
+ // 如果勾选了"记住我",保存用户名
|
|
|
|
+ if (rememberCheckbox.checked) {
|
|
|
|
+ localStorage.setItem('rememberedUsername', username);
|
|
|
|
+ } else {
|
|
|
|
+ localStorage.removeItem('rememberedUsername');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ showMessage('登录成功!正在跳转...', 'success');
|
|
|
|
+
|
|
|
|
+ // 模拟登录成功后的跳转
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ alert('登录成功!欢迎 ' + username);
|
|
|
|
+ // 在实际应用中,这里会跳转到首页或其他页面
|
|
|
|
+ // window.location.href = '/home';
|
|
|
|
+ }, 1000);
|
|
|
|
+ } else {
|
|
|
|
+ showMessage('用户名或密码错误', 'error');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ function showMessage(message, type) {
|
|
|
|
+ messageDiv.textContent = message;
|
|
|
|
+ messageDiv.className = 'message ' + type;
|
|
|
|
+ messageDiv.style.display = 'block';
|
|
|
|
+
|
|
|
|
+ // 3秒后隐藏消息
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ messageDiv.style.display = 'none';
|
|
|
|
+ }, 3000);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 按Enter键也可以触发登录
|
|
|
|
+ passwordInput.addEventListener('keypress', function (e) {
|
|
|
|
+ if (e.key === 'Enter') {
|
|
|
|
+ loginBtn.click();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ </script>
|
|
|
|
+</body>
|
|
|
|
+
|
|
|
|
+</html> -->
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+<!DOCTYPE html>
|
|
|
|
+<html lang="en">
|
|
|
|
+<head>
|
|
|
|
+ <meta charset="UTF-8">
|
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
+ <title>Parse.User基本用法示例</title>
|
|
|
|
+ <script src="https://npmcdn.com/parse/dist/parse.min.js"></script>
|
|
|
|
+</head>
|
|
|
|
+<body>
|
|
|
|
+ <script>
|
|
|
|
+ Parse.initialize("dev");
|
|
|
|
+ Parse.serverURL = 'https://dev.fmode.cn/parse'
|
|
|
|
+
|
|
|
|
+ async function register(){
|
|
|
|
+ let username = document.getElementById("username").value
|
|
|
|
+ let password = document.getElementById("password").value
|
|
|
|
+ let user = new Parse.User()
|
|
|
|
+ user.set("username",username)
|
|
|
|
+ user.set("password",password)
|
|
|
|
+ try {
|
|
|
|
+ let result = await user.signUp();
|
|
|
|
+ console.log(result)
|
|
|
|
+ // Hooray! Let them use the app now.
|
|
|
|
+ } catch (error) {
|
|
|
|
+ // Show the error message somewhere and let the user try again.
|
|
|
|
+ alert("Error: " + error.code + " " + error.message);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ async function login(){
|
|
|
|
+ let username = document.getElementById("username").value
|
|
|
|
+ let password = document.getElementById("password").value
|
|
|
|
+ const user = await Parse.User.logIn(username, password);
|
|
|
|
+ }
|
|
|
|
+ async function logout(){
|
|
|
|
+ Parse.User.logOut();
|
|
|
|
+ }
|
|
|
|
+ // 测试ACL读写权限
|
|
|
|
+ async function onCheck() {
|
|
|
|
+ let query = new Parse.Query('Bill')
|
|
|
|
+ let res = await query.get('Zgfr3OXoRm')
|
|
|
|
+ console.log(res);
|
|
|
|
+
|
|
|
|
+ if(res?.id){
|
|
|
|
+ res.set('desc','游戏1')
|
|
|
|
+ await res.save()
|
|
|
|
+ console.log('读写成功');
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ </script>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <div>用户信息<span id="userinfo"></span></div>
|
|
|
|
+ <script>
|
|
|
|
+ document.getElementById("userinfo").innerHTML = Parse.User.current().id + Parse.User.current().get("username")
|
|
|
|
+ </script>
|
|
|
|
+
|
|
|
|
+ <input type="text" id="username">
|
|
|
|
+ <input type="text" id="password">
|
|
|
|
+
|
|
|
|
+ <button onclick="register()">注册</button>
|
|
|
|
+ <button onclick="login()">登录</button>
|
|
|
|
+ <button onclick="logout()">登出</button>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <button onclick="onCheck()">修改数据</button>
|
|
|
|
+
|
|
|
|
+</body>
|
|
|
|
+</html>
|