Files
jiapuapp/pages/profile/m10-about-settings.vue
T

235 lines
6.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 页面编号M-10用途协议隐私版本与退出登录 -->
<template>
<view
class="about-page"
:class="{ 'about-state--logging-out': logoutSubmitting }"
>
<ModulePageBackground module="profile" />
<view class="page-layer"
><PageHeader title="关于家谱" custom-back @back="requestBack"
/></view>
<view class="page-content page-layer">
<view class="brand-card"
><image
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
/><text>家谱</text><text>传承每一段值得珍藏的家族记忆</text
><text>版本 {{ appVersion }}</text></view
>
<view class="settings-list">
<view
v-for="item in agreementItems"
:key="item.key"
class="settings-row"
role="button"
:aria-label="item.label"
@click="openAgreement(item)"
><view
><text>{{ item.label }}</text
><text>{{ item.note }}</text></view
><image
src="/static/assets/foundation/transparent/chevron-right.png"
mode="aspectFit"
/></view>
</view>
<AppButton
block
type="secondary"
label="退出登录"
@click="logoutVisible = true"
/>
</view>
<AppDialog
:visible="agreementVisible"
:close-on-mask="false"
eyebrow="协议与说明"
:title="activeAgreement.label"
:message="activeAgreement.copy"
confirm-text="关闭"
@confirm="agreementVisible = false"
@close="agreementVisible = false"
/>
<AppDialog
:visible="logoutVisible"
eyebrow="账号操作"
title="确认退出登录?"
message="退出后需要重新验证账号;本机保存的密码不会被保留。"
:confirm-text="logoutSubmitting ? '正在退出' : '确认退出'"
cancel-text="取消"
show-cancel
:close-on-mask="false"
@confirm="confirmLogout"
@cancel="logoutVisible = false"
@close="logoutVisible = false"
/>
</view>
</template>
<script setup>
import { reactive, ref } from "vue";
import { onBackPress, onUnload } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import AppDialog from "@/components/AppDialog.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import manifest from "@/manifest.json";
import { appApi, createRequestController } from "@/utils/api.js";
import { goRoot, handleBackPress, runBackGuard } from "@/utils/navigation.js";
import { session } from "@/utils/session.js";
const appVersion = manifest.versionName;
const agreementItems = [
{
key: "terms",
label: "用户协议",
note: "了解账号与服务使用规则",
copy: "用户协议正文将在正式协议服务接入后展示。当前页面不代表最终法律文本。",
},
{
key: "privacy",
label: "隐私政策",
note: "了解个人资料如何使用与保护",
copy: "隐私政策正文将在正式协议服务接入后展示。敏感资料默认按权限与脱敏规则展示。",
},
{
key: "version",
label: "版本说明",
note: `当前版本 ${appVersion}`,
copy: `当前安装版本为 ${appVersion}。基础版本采用浅色国风主题。`,
},
];
const activeAgreement = reactive({ label: "", copy: "" });
const agreementVisible = ref(false);
const logoutVisible = ref(false);
const logoutSubmitting = ref(false);
const logoutRequestController = createRequestController();
const openAgreement = (item) => {
activeAgreement.label = item.label;
activeAgreement.copy = item.copy;
agreementVisible.value = true;
};
const confirmLogout = async () => {
if (logoutSubmitting.value) return false;
logoutSubmitting.value = true;
try {
await appApi.logout({ requestController: logoutRequestController });
} catch {
// 退出请求的结果未知时仍必须撤销本机会话,不能保留旧授权或自动重试。
} finally {
session.clear();
logoutVisible.value = false;
logoutSubmitting.value = false;
}
return goRoot("A01");
};
const closeActiveDialog = () => {
if (logoutVisible.value) logoutVisible.value = false;
else agreementVisible.value = false;
};
const requestBack = () =>
runBackGuard({
transientOpen: agreementVisible.value || logoutVisible.value,
"close-transient": closeActiveDialog,
});
onBackPress((event) => handleBackPress(event, requestBack));
onUnload(() => logoutRequestController.abort());
</script>
<style scoped lang="scss">
@import "../../styles/adaptive-frame-profiles.scss";
.about-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.page-layer {
z-index: 1;
}
.page-content {
flex: 1;
padding: 28rpx 30rpx 72rpx;
}
.brand-card {
@include adaptive-profile-summary;
display: flex;
min-height: 300rpx;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 36rpx 44rpx;
text-align: center;
}
.brand-card image {
width: 92rpx;
height: 106rpx;
}
.brand-card text {
display: block;
}
.brand-card text:nth-child(2) {
margin-top: 6rpx;
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(20px, 40rpx, 26px);
font-weight: 700;
letter-spacing: 4rpx;
}
.brand-card text:nth-child(3) {
margin-top: 8rpx;
color: $ink-muted;
font-size: clamp(14px, 22rpx, 17px);
line-height: 1.5;
}
.brand-card text:last-child {
margin-top: 10rpx;
color: $ink-muted;
font-size: clamp(13px, 20rpx, 16px);
}
.settings-list {
display: flex;
flex-direction: column;
gap: 12rpx;
margin-top: 22rpx;
}
.settings-row {
@include adaptive-profile-field;
display: grid;
grid-template-columns: minmax(0, 1fr) 32rpx;
min-height: 104rpx;
align-items: center;
gap: 18rpx;
padding: 18rpx 30rpx;
}
.settings-row view {
min-width: 0;
}
.settings-row text {
display: block;
overflow-wrap: anywhere;
}
.settings-row text:first-child {
color: $ink;
font-size: clamp(15px, 24rpx, 18px);
font-weight: 700;
}
.settings-row text:last-child {
margin-top: 6rpx;
color: $ink-muted;
font-size: clamp(13px, 20rpx, 16px);
}
.settings-row image {
width: 30rpx;
height: 30rpx;
}
.page-content > .app-button {
margin-top: 28rpx;
}
@media (max-width: 340px) {
.page-content {
padding-right: 22rpx;
padding-left: 22rpx;
}
}
</style>