优化个人中心与界面交互
This commit is contained in:
@@ -204,6 +204,25 @@
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
|
||||
<el-dialog
|
||||
v-model="profileDialogVisible"
|
||||
class="profile-settings-dialog"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:before-close="beforeProfileDialogClose"
|
||||
width="980px"
|
||||
align-center
|
||||
destroy-on-close
|
||||
@closed="profileDialogDirty = false"
|
||||
>
|
||||
<ProfileSettings
|
||||
@close-request="requestProfileDialogClose"
|
||||
@dirty-change="profileDialogDirty = $event"
|
||||
@saved="profileDialogVisible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -221,6 +240,7 @@ import {
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { getProjectRoutePermission, hasProjectPermission, projectRouteLandingPaths } from "../utils/projectRoutePermissions";
|
||||
import { forceLogout, LOGOUT_REASON_MANUAL } from "../session/sessionManager";
|
||||
import ProfileSettings from "../views/ProfileSettings.vue";
|
||||
|
||||
const auth = useAuthStore();
|
||||
const study = useStudyStore();
|
||||
@@ -235,6 +255,8 @@ const canAccessProjectPath = (path: string) =>
|
||||
const canAccessAnyProjectPath = (paths: string[]) => paths.some((path) => canAccessProjectPath(path));
|
||||
const hasAnyProjectModuleAccess = computed(() => canAccessAnyProjectPath(projectRouteLandingPaths));
|
||||
const loggingOut = ref(false);
|
||||
const profileDialogVisible = ref(false);
|
||||
const profileDialogDirty = ref(false);
|
||||
|
||||
/* 动态设置 body 上的侧边栏宽度 CSS 变量,用于全局弹窗定位偏移 */
|
||||
const hasSidebar = computed(() => isAdmin.value || !!study.currentStudy);
|
||||
@@ -480,7 +502,33 @@ const onCommand = (cmd: string) => {
|
||||
if (cmd === "logout") {
|
||||
onLogout();
|
||||
} else if (cmd === "profile") {
|
||||
router.push("/profile");
|
||||
profileDialogVisible.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const confirmDiscardProfileChanges = async () => {
|
||||
if (!profileDialogDirty.value) return true;
|
||||
const confirmed = await ElMessageBox.confirm(
|
||||
"当前修改尚未保存,关闭后将丢失这些改动。",
|
||||
"确认关闭个人中心",
|
||||
{
|
||||
type: "warning",
|
||||
confirmButtonText: "关闭",
|
||||
cancelButtonText: "继续编辑",
|
||||
}
|
||||
).catch(() => false);
|
||||
return Boolean(confirmed);
|
||||
};
|
||||
|
||||
const requestProfileDialogClose = async () => {
|
||||
if (await confirmDiscardProfileChanges()) {
|
||||
profileDialogVisible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const beforeProfileDialogClose = async (done: () => void) => {
|
||||
if (await confirmDiscardProfileChanges()) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -931,4 +979,18 @@ const onCommand = (cmd: string) => {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:global(.profile-settings-dialog) {
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 24px 70px rgba(15, 23, 42, 0.26);
|
||||
}
|
||||
|
||||
:global(.profile-settings-dialog .el-dialog__header) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global(.profile-settings-dialog .el-dialog__body) {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -52,4 +52,19 @@ describe("Layout breadcrumbs", () => {
|
||||
expect(source).toContain("forceLogout(LOGOUT_REASON_MANUAL)");
|
||||
expect(source).toContain('loggingOut ? "正在退出..." : TEXT.menu.logout');
|
||||
});
|
||||
|
||||
it("opens profile settings as a desktop-style dialog instead of navigating away", () => {
|
||||
const source = readLayout();
|
||||
|
||||
expect(source).toContain('v-model="profileDialogVisible"');
|
||||
expect(source).toContain('class="profile-settings-dialog"');
|
||||
expect(source).toContain(':close-on-click-modal="false"');
|
||||
expect(source).toContain(':close-on-press-escape="false"');
|
||||
expect(source).toContain('@close-request="requestProfileDialogClose"');
|
||||
expect(source).toContain('@dirty-change="profileDialogDirty = $event"');
|
||||
expect(source).toContain('@saved="profileDialogVisible = false"');
|
||||
expect(source).toContain("profileDialogVisible.value = true");
|
||||
expect(source).toContain("confirmDiscardProfileChanges");
|
||||
expect(source).not.toContain('router.push("/profile")');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user