201 lines
5.6 KiB
Vue
201 lines
5.6 KiB
Vue
<template>
|
|
<div class="user-profile">
|
|
<el-row :gutter="20">
|
|
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
|
<ProfileCard
|
|
:user-info="userInfo"
|
|
@change-avatar="handleAvatarChange"
|
|
/>
|
|
|
|
<QuickActions @logout="handleLogout" />
|
|
</el-col>
|
|
|
|
<el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
|
|
<DetailCard
|
|
:user-info="userInfo"
|
|
:format-date="formatDate"
|
|
:get-sex-text="getSexText"
|
|
@edit="handleEditProfile"
|
|
/>
|
|
|
|
<SecurityCard
|
|
:user-info="userInfo"
|
|
@change-password="handleChangePassword"
|
|
@bind-phone="bindPhoneDialogVisible = true"
|
|
@bind-email="bindEmailDialogVisible = true"
|
|
/>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<EditProfileDialog
|
|
v-model="editDialogVisible"
|
|
:user-info="userInfo"
|
|
:user-id="authStore.user?.id"
|
|
@saved="fetchUserInfo"
|
|
/>
|
|
|
|
<ChangePasswordDialog
|
|
v-model="passwordDialogVisible"
|
|
:user-id="authStore.user?.id"
|
|
/>
|
|
|
|
<BindPhoneDialog
|
|
v-model="bindPhoneDialogVisible"
|
|
:user-info="userInfo"
|
|
:user-id="authStore.user?.id"
|
|
@saved="fetchUserInfo"
|
|
/>
|
|
|
|
<BindEmailDialog
|
|
v-model="bindEmailDialogVisible"
|
|
:user-info="userInfo"
|
|
:user-id="authStore.user?.id"
|
|
@saved="fetchUserInfo"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from "vue";
|
|
import { useRouter } from "vue-router";
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
import { getUserInfo } from "@/api/user";
|
|
import { useAuthStore } from "@/stores/auth";
|
|
import ProfileCard from "./components/ProfileCard.vue";
|
|
import QuickActions from "./components/QuickActions.vue";
|
|
import DetailCard from "./components/DetailCard.vue";
|
|
import SecurityCard from "./components/SecurityCard.vue";
|
|
import EditProfileDialog from "./components/EditProfileDialog.vue";
|
|
import ChangePasswordDialog from "./components/ChangePasswordDialog.vue";
|
|
import BindPhoneDialog from "./components/BindPhoneDialog.vue";
|
|
import BindEmailDialog from "./components/BindEmailDialog.vue";
|
|
|
|
const router = useRouter();
|
|
const authStore = useAuthStore();
|
|
|
|
const userInfo = ref(null);
|
|
const editDialogVisible = ref(false);
|
|
const passwordDialogVisible = ref(false);
|
|
const bindPhoneDialogVisible = ref(false);
|
|
const bindEmailDialogVisible = ref(false);
|
|
|
|
const formatDate = (date) => {
|
|
if (!date) return "-";
|
|
const d = new Date(date);
|
|
const year = d.getFullYear();
|
|
const month = String(d.getMonth() + 1).padStart(2, "0");
|
|
const day = String(d.getDate()).padStart(2, "0");
|
|
const hours = String(d.getHours()).padStart(2, "0");
|
|
const minutes = String(d.getMinutes()).padStart(2, "0");
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
|
};
|
|
|
|
const getSexText = (sex) => {
|
|
const map = {
|
|
0: "保密",
|
|
1: "男",
|
|
2: "女"
|
|
};
|
|
return map[sex] || "-";
|
|
};
|
|
|
|
const fetchUserInfo = async () => {
|
|
try {
|
|
const userId = authStore.user?.id;
|
|
if (!userId) {
|
|
ElMessage.error("用户ID不存在");
|
|
return;
|
|
}
|
|
const res = await getUserInfo(userId);
|
|
if (res.code === 200) {
|
|
userInfo.value = res.data;
|
|
}
|
|
} catch (error) {
|
|
console.error("获取用户信息失败", error);
|
|
ElMessage.error("获取用户信息失败");
|
|
}
|
|
};
|
|
|
|
const handleEditProfile = () => {
|
|
editDialogVisible.value = true;
|
|
};
|
|
|
|
const handleChangePassword = () => {
|
|
passwordDialogVisible.value = true;
|
|
};
|
|
|
|
const handleAvatarChange = () => {
|
|
ElMessage.info("头像上传功能开发中");
|
|
};
|
|
|
|
const handleLogout = () => {
|
|
ElMessageBox.confirm("确定要退出登录吗?", "提示", {
|
|
confirmButtonText: "确定",
|
|
cancelButtonText: "取消",
|
|
type: "warning"
|
|
}).then(async () => {
|
|
try {
|
|
await authStore.logout(authStore.user?.id);
|
|
} catch (error) {
|
|
console.error("退出登录接口调用失败:", error);
|
|
}
|
|
|
|
// 清除所有本地存储
|
|
localStorage.removeItem("active_tab");
|
|
localStorage.removeItem("1123567809876");
|
|
localStorage.removeItem("tabs_list");
|
|
localStorage.removeItem("token");
|
|
localStorage.removeItem("user");
|
|
localStorage.removeItem("tenant");
|
|
|
|
sessionStorage.removeItem("active_tab");
|
|
sessionStorage.removeItem("456");
|
|
sessionStorage.removeItem("tabs_list");
|
|
sessionStorage.removeItem("token");
|
|
sessionStorage.removeItem("user");
|
|
sessionStorage.removeItem("tenant");
|
|
|
|
// 清除所有 cookies,包括跨域和不同路径的 cookie
|
|
const clearCookie = (name) => {
|
|
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=`;
|
|
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${location.hostname}`;
|
|
if (location.hostname !== "localhost") {
|
|
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${location.hostname}`;
|
|
}
|
|
};
|
|
|
|
// 清除所有已知 cookie
|
|
clearCookie("PHPSESSID");
|
|
clearCookie("token");
|
|
clearCookie("user");
|
|
clearCookie("tenant");
|
|
|
|
// 同时清除所有现有的 cookie
|
|
const cookies = document.cookie.split(";");
|
|
for (let i = 0; i < cookies.length; i++) {
|
|
const cookie = cookies[i].trim();
|
|
const eqPos = cookie.indexOf("=");
|
|
const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
|
|
if (name) {
|
|
clearCookie(name);
|
|
}
|
|
}
|
|
|
|
authStore.clearToken();
|
|
router.push("/login");
|
|
ElMessage.success("已退出登录");
|
|
}).catch(() => {});
|
|
};
|
|
|
|
onMounted(() => {
|
|
fetchUserInfo();
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.user-profile {
|
|
padding: 0;
|
|
}
|
|
</style>
|