chore: 将用户登录退出等操作抽离为公共 JS 脚本

This commit is contained in:
Frankie Huang 2025-05-05 16:23:45 +08:00
parent 2266162984
commit 991ca62c68
2 changed files with 210 additions and 143 deletions

View File

@ -8,7 +8,7 @@
<Checkbox v-model="autoLogin" size="large">记住登录状态</Checkbox> <Checkbox v-model="autoLogin" size="large">记住登录状态</Checkbox>
<!-- <a>忘记密码</a> --> <!-- <a>忘记密码</a> -->
</div> </div>
<Submit /> <Submit :loading="submitLoading" />
<Space split>还未拥有账号<Button type="text" @click="signInOrSignUp = false">前往注册</Button></Space> <Space split>还未拥有账号<Button type="text" @click="signInOrSignUp = false">前往注册</Button></Space>
</Login> </Login>
<Login v-else @on-submit="handleSignUp"> <Login v-else @on-submit="handleSignUp">
@ -16,16 +16,16 @@
<Email name="mail" /> <Email name="mail" />
<Password name="password" /> <Password name="password" />
<Password name="passwordConfirm" placeholder="确认密码" /> <Password name="passwordConfirm" placeholder="确认密码" />
<Submit>注册</Submit> <Submit :loading="submitLoading">注册</Submit>
<Space split>已经拥有账号<Button type="text" @click="signInOrSignUp = true">前往登录</Button></Space> <Space split>已经拥有账号<Button type="text" @click="signInOrSignUp = true">前往登录</Button></Space>
</Login> </Login>
</Modal> </Modal>
</template> </template>
<script setup> <script setup>
import md5 from 'js-md5'; import { SignIn, SignUp, SendSignUpEmail, CheckLoginStatus, Logout } from '/src/utils/userHandler';
import { ref, watch, onMounted } from "vue"; import { ref, watch, onMounted } from "vue";
import { Message } from 'view-ui-plus' import { Message } from 'view-ui-plus';
const props = defineProps({ const props = defineProps({
visible: { visible: {
@ -56,57 +56,26 @@ watch(showFormModal, (visible) => {
const signInOrSignUp = ref(true); const signInOrSignUp = ref(true);
const autoLogin = ref(false); const autoLogin = ref(false);
const submitLoading = ref(false);
// Cookie
const setPHPSessionToCookie = (sessionID) => {
if (sessionID) {
document.cookie = `PHPSESSID=${sessionID}; max-age=604800; SameSite=None; secure; path=/`;
}
}
const getPHPSessionFromCookie = () => {
let PHPSESSID = '';
const cookies = document.cookie.split('; ');
cookies.forEach(cookie => {
const [key, value] = cookie.split('=');
if (key === 'PHPSESSID') {
PHPSESSID = decodeURIComponent(value); // %20
}
});
return PHPSESSID;
}
const delPHPSessionFromCookie = () => {
document.cookie = `PHPSESSID=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
}
const handleSignIn = (valid, { username, password }) => { const handleSignIn = (valid, { username, password }) => {
if (valid) { if (!valid) {
fetch('https://myafei.cn/php/ajax.php', { return;
method: 'POST', }
body: JSON.stringify({ submitLoading.value = true;
'func': 'login', SignIn(username, password, autoLogin.value)
'username': username, .then((data) => {
'is_email': /^[0-9a-zA-Z_-]{1,100}$/.test(username) ? false : true, Message.success('登录成功');
'password': md5(password), //
'isRemember': autoLogin.value, emit('update:loginStatus', true);
}), // loading
}).then(response => { submitLoading.value = false;
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`); showFormModal.value = false;
return response.json(); })
}).then(data => { .catch((error) => {
if (data.status == 0) { submitLoading.value = false;
Message.success('登录成功');
setPHPSessionToCookie(data.PHPSESSID);
//
emit('update:loginStatus', true);
//
showFormModal.value = false;
} else {
Message.error(data.error);
}
}).catch(error => {
Message.error(`登录发生异常: ${error}`); Message.error(`登录发生异常: ${error}`);
}); });
}
}; };
const handleSignUp = (valid, { username, mail, password, passwordConfirm }) => { const handleSignUp = (valid, { username, mail, password, passwordConfirm }) => {
@ -118,107 +87,47 @@ const handleSignUp = (valid, { username, mail, password, passwordConfirm }) => {
return; return;
} }
fetch('https://myafei.cn/php/ajax.php', { submitLoading.value = true;
method: 'POST', SignUp(username, mail, password)
body: JSON.stringify({ .then((data) => {
'func': 'register', // userID
'username': username, SendSignUpEmail(data.id)
'email': mail, .then((data) => {
'password': md5(password), Message.success('请前往邮箱激活账号(没收到的话检查垃圾箱),激活后再回来登录账号');
}), //
}).then(response => { submitLoading.value = false;
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`); signInOrSignUp.value = true;
return response.json(); })
}).then(data => { .catch((error) => {
if (data.status == 0) { submitLoading.value = false;
// Message.error(`发送激活邮件发生异常: ${error}`);
sendSignUpEmail(data.id); });
} else { })
Message.error(data.error); .catch((error) => {
} submitLoading.value = false;
}).catch(error => { Message.error(`注册发生异常: ${error}`);
Message.error(`注册发生异常: ${error}`); });
});
}; };
const sendSignUpEmail = (userID) => {
fetch('https://myafei.cn/php/ajax.php', {
method: 'POST',
body: JSON.stringify({
'func': 'resend_email',
'id': userID,
'path': '/',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
Message.success('请前往邮箱激活账号(没收到的话检查垃圾箱),激活后再回来登录账号');
//
signInOrSignUp.value = true;
} else if (data.status == -100) {
Message.warning('邮箱已被激活');
} else {
Message.error('激活邮件发送失败:' + data.error);
}
}).catch(error => {
Message.error(`邮件发送异常: ${error}`);
});
}
const checkLoginStatus = async () => { const checkLoginStatus = async () => {
// cookie PHPSESSID CheckLoginStatus()
const PHPSESSID = getPHPSessionFromCookie(); .then((data) => {
let loginStatus = false;
await fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
method: 'POST',
body: JSON.stringify({
'func': 'is_login',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
emit('update:loginStatus', true); emit('update:loginStatus', true);
loginStatus = true; })
} else { .catch((error) => {
loginStatus = false; Message.error(`检查登录状态发生异常: ${error}`);
} });
}).catch(error => {
Message.error(`检查登录状态时发生异常: ${error}`);
loginStatus = false;
});
return loginStatus;
} }
const logout = async () => { const logout = async () => {
const PHPSESSID = getPHPSessionFromCookie(); Logout()
let logoutStatus = false; .then((data) => {
await fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
method: 'POST',
body: JSON.stringify({
'func': 'logout',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
Message.info('登出成功'); Message.info('登出成功');
delPHPSessionFromCookie();
emit('update:loginStatus', false); emit('update:loginStatus', false);
logoutStatus = true; })
} else { .catch((error) => {
Message.error(data.error); Message.error(`登出发生异常: ${error}`);
logoutStatus = false; });
}
}).catch(error => {
Message.error(`登出发生异常: ${error}`);
logoutStatus = false;
});
return logoutStatus;
} }
defineExpose({ defineExpose({

158
src/utils/userHandler.js Normal file
View File

@ -0,0 +1,158 @@
import md5 from 'js-md5';
// 由于是跨域登录,需要手动设置并携带 Cookie
const setPHPSessionToCookie = (sessionID) => {
if (sessionID) {
document.cookie = `PHPSESSID=${sessionID}; max-age=604800; SameSite=None; secure; path=/`;
}
}
const getPHPSessionFromCookie = () => {
let PHPSESSID = '';
const cookies = document.cookie.split('; ');
cookies.forEach(cookie => {
const [key, value] = cookie.split('=');
if (key === 'PHPSESSID') {
PHPSESSID = decodeURIComponent(value); // 解码特殊字符(如空格、%20
}
});
return PHPSESSID;
}
const delPHPSessionFromCookie = () => {
document.cookie = `PHPSESSID=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
}
const SignIn = (username, password, autoLogin) => {
return new Promise((resolve, reject) => {
fetch('https://myafei.cn/php/ajax.php', {
method: 'POST',
body: JSON.stringify({
'func': 'login',
'username': username,
'is_email': /^[0-9a-zA-Z_-]{1,100}$/.test(username) ? false : true,
'password': md5(password),
'isRemember': autoLogin,
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
setPHPSessionToCookie(data.PHPSESSID);
resolve(data);
} else {
reject(new Error(data.error));
}
}).catch(error => {
reject(error);
});
})
}
const SignUp = (username, mail, password) => {
return new Promise((resolve, reject) => {
fetch('https://myafei.cn/php/ajax.php', {
method: 'POST',
body: JSON.stringify({
'func': 'register',
'username': username,
'email': mail,
'password': md5(password),
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
resolve(data);
} else {
reject(new Error(data.error));
}
}).catch(error => {
reject(error);
});
});
}
const SendSignUpEmail = (userID) => {
return new Promise((resolve, reject) => {
fetch('https://myafei.cn/php/ajax.php', {
method: 'POST',
body: JSON.stringify({
'func': 'resend_email',
'id': userID,
'path': '/',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
resolve(data);
} else if (data.status == -100) {
reject(new Error('邮箱已被激活'));
} else {
reject(new Error(data.error));
}
}).catch(error => {
reject(error);
});
});
}
const CheckLoginStatus = () => {
return new Promise((resolve, reject) => {
// 先从 cookie 中拿到 PHPSESSID
const PHPSESSID = getPHPSessionFromCookie();
fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
method: 'POST',
body: JSON.stringify({
'func': 'is_login',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
resolve(data);
} else {
// 未登录不抛出异常
}
}).catch(error => {
reject(error);
});
});
}
const Logout = () => {
return new Promise((resolve, reject) => {
const PHPSESSID = getPHPSessionFromCookie();
fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
method: 'POST',
body: JSON.stringify({
'func': 'logout',
}),
}).then(response => {
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
return response.json();
}).then(data => {
if (data.status == 0) {
delPHPSessionFromCookie();
resolve();
} else {
reject(new Error(data.error));
}
}).catch(error => {
reject(error);
});
});
}
export {
SignIn,
SignUp,
SendSignUpEmail,
CheckLoginStatus,
Logout,
};