Files
jiapuapp/pages/tree/t06-edit-relationship.vue
T
2026-07-24 07:56:33 +08:00

127 lines
6.1 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.
<!-- 页面编号T-06用途展示指定成员的同辈排行调整入口 -->
<template>
<view
class="rank-page"
:class="{
'rank-state--loading': rankState === 'loading',
'rank-state--form': rankState === 'form',
'rank-state--unavailable': rankState === 'unavailable',
'rank-state--error': rankState === 'error',
}"
>
<ModulePageBackground module="tree" />
<view class="rank-page__header"><PageHeader title="调整排行" custom-back @back="goBack" /></view>
<view class="rank-panel">
<AppLoading v-if="rankState === 'loading'" text="正在读取成员资料" description="请稍候,正在确认待调整人物。" />
<view v-else-if="rankState === 'form' && member" class="rank-form">
<text class="form-eyebrow">同辈排行</text>
<text class="form-title">调整{{ member.name }}的排行</text>
<text class="form-copy">排行调整必须由服务端以同辈原子操作完成避免逐人保存造成部分成功</text>
<view class="member-context">
<text>当前成员</text><text> {{ member.generation }} · {{ member.branch }}</text>
</view>
<view class="rank-notice">
<text>当前服务状态</text>
<text>尚未提供带版本冲突处理和完整结果的同辈原子重排合同</text>
</view>
<view class="form-action" @click="showRankUnavailable">
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="scaleToFill" />
<text>查看服务状态</text>
</view>
</view>
<view v-else class="rank-result">
<text class="form-eyebrow">{{ rankState === "unavailable" ? "服务暂未开放" : "成员入口无效" }}</text>
<text class="form-title">{{ rankState === "unavailable" ? "暂不能提交排行调整" : "暂时无法读取成员资料" }}</text>
<text class="form-copy">{{ rankState === "unavailable" ? "当前人物更新接口只有单人物 sortOrder 候选,不能保证同辈排行原子一致。本页不会逐人写入,也不会显示本地预览成功。" : errorMessage }}</text>
<view class="form-action" @click="rankState === 'unavailable' ? (rankState = 'form') : goBack()">
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="scaleToFill" />
<text>{{ rankState === "unavailable" ? "返回查看" : "返回世系树" }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
import AppLoading from "@/components/AppLoading.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { appApi, createRequestController, isRequestCancelled } from "@/utils/api.js";
import { goBack, handleBackPress } from "@/utils/navigation.js";
const rankState = ref("loading");
const genealogyId = ref("");
const personId = ref("");
const member = ref(null);
const errorMessage = ref("");
const rankRequestController = createRequestController();
let loadSequence = 0;
const loadMember = async () => {
const activeLoad = ++loadSequence;
rankState.value = "loading";
try {
const result = await appApi.getPerson(genealogyId.value, personId.value, {
requestController: rankRequestController,
});
if (activeLoad !== loadSequence) return;
member.value = result;
errorMessage.value = "";
rankState.value = "form";
} catch (error) {
if (activeLoad !== loadSequence || isRequestCancelled(error)) return;
member.value = null;
errorMessage.value = error?.message || "当前成员资料暂不可用,请返回世系树后重试。";
rankState.value = "error";
}
};
const showRankUnavailable = () => {
rankState.value = "unavailable";
};
onLoad((query) => {
genealogyId.value = String(query.genealogyId || "");
personId.value = String(query.personId || "");
if (!genealogyId.value || !personId.value || query.mode !== "rank") {
rankState.value = "error";
errorMessage.value = "当前排行入口无效,请从人物操作面板重新进入。";
return;
}
void loadMember();
});
onUnload(() => {
loadSequence += 1;
rankRequestController.abort();
});
onBackPress((event) => handleBackPress(event, goBack));
</script>
<style scoped lang="scss">
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
.rank-page { display: flex; min-height: 100vh; flex-direction: column; background: $paper; }
.rank-page__header { z-index: 3; }
.rank-panel { @include adaptive.adaptive-tree-panel; z-index: 2; width: calc(100% - 32rpx); margin: 18rpx auto 28rpx; padding: 7.5% 8%; }
.form-eyebrow { display: block; color: $brand-red; font-size: 22rpx; letter-spacing: 3rpx; }
.form-title { display: block; margin-top: 10rpx; color: $ink; font-family: "STKaiti", "KaiTi", serif; font-size: 34rpx; font-weight: 700; line-height: 1.35; }
.form-copy { display: block; margin-top: 10rpx; color: $ink-muted; font-size: 24rpx; line-height: 1.5; }
.member-context, .rank-notice { @include adaptive.adaptive-tree-field; display: grid; grid-template-columns: auto minmax(0, 1fr); min-height: 78rpx; align-items: center; gap: 20rpx; margin-top: 16rpx; padding: 12rpx 22rpx; }
.member-context text:first-child, .rank-notice text:first-child { color: $ink; font-size: 24rpx; font-weight: 700; }
.member-context text:last-child, .rank-notice text:last-child { min-width: 0; color: $ink-muted; font-size: 23rpx; line-height: 1.45; text-align: right; }
.form-action { display: grid; width: 100%; min-height: 76rpx; margin-top: 22rpx; }
.form-action image, .form-action text { grid-area: 1 / 1; width: 100%; height: 100%; }
.form-action text { z-index: 1; display: flex; align-items: center; justify-content: center; color: #fff9ed; font-size: 24rpx; font-weight: 700; }
.rank-result { margin-top: 30%; text-align: center; }
.rank-result .form-eyebrow, .rank-result .form-copy { text-align: center; }
.rank-result .form-action { width: 420rpx; max-width: 100%; margin-right: auto; margin-left: auto; }
@media (min-width: 400px) { .rank-panel { width: calc(100% - 48rpx); } }
</style>