完成全项目响应式审核与换机交接
This commit is contained in:
@@ -20,6 +20,15 @@
|
||||
<text>主支 · 第 12—14 世</text>
|
||||
</view>
|
||||
<view class="tree-toolbar__actions">
|
||||
<text
|
||||
v-if="treeState === 'tree' && treeHasDrifted && selected"
|
||||
class="tree-recenter"
|
||||
role="button"
|
||||
aria-label="回到当前成员"
|
||||
hover-class="tree-action--pressed"
|
||||
@click="recenterSelectedMember"
|
||||
>回到当前</text
|
||||
>
|
||||
<text @click="treeState = 'landscape'">阅读提示</text>
|
||||
<text @click="toRelationship">关系维护</text>
|
||||
</view>
|
||||
@@ -51,18 +60,23 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="treeState === 'tree'" class="lineage-pan-cue">
|
||||
<text>同代分支可左右查看</text>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
class="tree-scroll"
|
||||
:class="{ 'tree-scroll--lineage': treeState === 'tree' }"
|
||||
scroll-x
|
||||
:scroll-left="initialScrollLeft"
|
||||
:scroll-left="treeState === 'tree' ? treeScrollLeft : 0"
|
||||
:show-scrollbar="false"
|
||||
:style="treeScrollStyle"
|
||||
@scroll="handleTreeScroll"
|
||||
>
|
||||
<view
|
||||
class="tree-canvas"
|
||||
:class="{ 'tree-canvas--state': treeState !== 'tree' }"
|
||||
:style="treeMetricsStyle"
|
||||
:style="treeState === 'tree' ? treeMetricsStyle : undefined"
|
||||
>
|
||||
<AppLoading
|
||||
v-if="treeState === 'loading'"
|
||||
@@ -71,10 +85,6 @@
|
||||
/>
|
||||
|
||||
<template v-else-if="treeState === 'tree'">
|
||||
<view class="lineage-pan-cue">
|
||||
<text>同代分支可左右查看</text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-for="connector in lineageConnectors"
|
||||
:key="connector.id"
|
||||
@@ -85,6 +95,7 @@
|
||||
<view
|
||||
v-for="member in layoutMembers"
|
||||
:key="member.id"
|
||||
:id="`tree-member-${member.id}`"
|
||||
class="member-node"
|
||||
:class="{ 'member-node--selected': selected?.id === member.id }"
|
||||
:style="nodeGridStyle(member)"
|
||||
@@ -166,7 +177,7 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||||
@@ -176,7 +187,12 @@ import { genealogyContext } from "@/utils/genealogy-context.js";
|
||||
const genealogyId = ref("");
|
||||
const treeState = ref("loading");
|
||||
const selected = ref(null);
|
||||
const initialScrollLeft = ref(90);
|
||||
const treeScrollLeft = ref(90);
|
||||
const currentTreeScrollLeft = ref(90);
|
||||
const centeredTreeScrollLeft = ref(90);
|
||||
const treeHasDrifted = ref(false);
|
||||
let ignoreTreeScroll = false;
|
||||
let recenterTimer = null;
|
||||
const GRID_UNIT = 5;
|
||||
const NODE_HALF_HEIGHT = 47;
|
||||
const MEMBER_GAP = 250;
|
||||
@@ -409,6 +425,46 @@ onLoad((query) => {
|
||||
treeState.value = "tree";
|
||||
});
|
||||
|
||||
onUnload(() => {
|
||||
if (recenterTimer) clearTimeout(recenterTimer);
|
||||
});
|
||||
|
||||
const handleTreeScroll = (event) => {
|
||||
if (ignoreTreeScroll || treeState.value !== "tree") return;
|
||||
const scrollLeft = Number(event?.detail?.scrollLeft || 0);
|
||||
currentTreeScrollLeft.value = scrollLeft;
|
||||
treeHasDrifted.value = Math.abs(scrollLeft - centeredTreeScrollLeft.value) > 80;
|
||||
};
|
||||
|
||||
const recenterSelectedMember = async () => {
|
||||
if (!selected.value) return;
|
||||
ignoreTreeScroll = true;
|
||||
const [scrollRect, nodeRect] = await new Promise((resolve) => {
|
||||
const query = uni.createSelectorQuery();
|
||||
query.select(".tree-scroll").boundingClientRect();
|
||||
query
|
||||
.select(`#tree-member-${selected.value.id}`)
|
||||
.boundingClientRect();
|
||||
query.exec(resolve);
|
||||
});
|
||||
if (scrollRect && nodeRect) {
|
||||
const centeredScrollLeft = Math.max(
|
||||
0,
|
||||
currentTreeScrollLeft.value +
|
||||
nodeRect.left + nodeRect.width / 2 - (scrollRect.left + scrollRect.width / 2),
|
||||
);
|
||||
treeScrollLeft.value = centeredScrollLeft;
|
||||
currentTreeScrollLeft.value = centeredScrollLeft;
|
||||
centeredTreeScrollLeft.value = centeredScrollLeft;
|
||||
}
|
||||
treeHasDrifted.value = false;
|
||||
if (recenterTimer) clearTimeout(recenterTimer);
|
||||
recenterTimer = setTimeout(() => {
|
||||
ignoreTreeScroll = false;
|
||||
recenterTimer = null;
|
||||
}, 320);
|
||||
};
|
||||
|
||||
const nodeGridStyle = (member) => ({
|
||||
gridColumn: `${member.x / 5 + 1}`,
|
||||
gridRow: `${member.y / 5 + 1}`,
|
||||
@@ -484,6 +540,9 @@ const toAddRelative = () =>
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tree-action--pressed {
|
||||
opacity: 0.72;
|
||||
}
|
||||
.tree-stage--lineage {
|
||||
display: grid;
|
||||
grid-template-columns: 190rpx minmax(0, 1fr);
|
||||
@@ -503,6 +562,7 @@ const toAddRelative = () =>
|
||||
border-right: 1rpx solid rgba(143, 108, 63, 0.2);
|
||||
}
|
||||
.tree-scroll--lineage {
|
||||
grid-area: 1 / 2;
|
||||
min-width: 0;
|
||||
}
|
||||
.tree-canvas {
|
||||
@@ -514,7 +574,7 @@ const toAddRelative = () =>
|
||||
width: calc(100vw - 32rpx);
|
||||
}
|
||||
.lineage-pan-cue {
|
||||
grid-area: 1 / 1 / -1 / -1;
|
||||
grid-area: 1 / 2;
|
||||
align-self: start;
|
||||
justify-self: end;
|
||||
z-index: 3;
|
||||
|
||||
Reference in New Issue
Block a user