Files
jiapuapp/pages/genealogy/g01-my-genealogies.vue
T
2026-07-16 07:58:53 +08:00

909 lines
27 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.
<!-- 页面编号G-01用途我的家谱列表与首次分流本轮仍待用户重新审核 -->
<template>
<view class="page-shell genealogy-index">
<image
class="page-paper-texture"
src="/static/assets/foundation/opaque/page-paper.jpg"
mode="scaleToFill"
/>
<image
class="page-footer-landscape"
src="/static/assets/foundation/transparent/footer-mountain-bamboo.png"
mode="scaleToFill"
/>
<PageHeader
root
title="我的家谱"
:unread-count="unreadCount"
@notice="toNotifications"
/>
<view class="genealogy-content">
<view v-if="isLoading" class="state-panel state-panel--loading">
<view class="loading-seal"></view>
<text class="state-title">正在整理家谱</text>
<text class="state-copy">请稍候家族记忆正在归卷</text>
</view>
<view v-else-if="hasError" class="state-panel state-panel--error">
<image class="state-panel__skin" src="/static/assets/modules/genealogy/opaque/g01-empty-panel.png" mode="scaleToFill" />
<view class="state-panel__content">
<text class="state-title">暂时无法读取家谱</text>
<text class="state-copy">网络或服务暂不可用请稍后重新查看</text>
<view class="state-retry" hover-class="action-hover" @click="retryLoad">
<image class="state-retry__skin" src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
<text class="state-retry__copy">重新加载</text>
</view>
</view>
</view>
<template v-else-if="hasGenealogies">
<view class="current-slip" @click="openSwitcher">
<image
class="current-frame"
src="/static/assets/modules/genealogy/transparent/current-slip-frame.png"
mode="scaleToFill"
/>
<view class="current-summary">
<view class="current-seal">
<image
class="current-seal-frame"
src="/static/assets/modules/genealogy/transparent/current-seal-frame.png"
mode="scaleToFill"
/>
<text class="current-seal-title">家谱</text>
</view>
<text class="current-name">{{ currentGenealogy.name }}</text>
<text class="current-switch-copy">切换</text>
</view>
<view class="current-info-divider"></view>
<view class="current-meta">
<view class="current-meta-item">
<image
class="current-meta-icon"
src="/static/assets/foundation/transparent/meta-location.png"
mode="aspectFit"
/>
<text class="current-meta-item-text">{{
currentGenealogy.location
}}</text>
</view>
<view class="current-meta-item">
<image
class="current-meta-icon"
src="/static/assets/foundation/transparent/meta-member.png"
mode="aspectFit"
/>
<text class="current-meta-item-text"
>{{ currentGenealogy.memberCount }} 位成员</text
>
</view>
<view class="current-meta-item">
<image
class="current-meta-icon"
src="/static/assets/foundation/transparent/meta-admin.png"
mode="aspectFit"
/>
<text class="current-meta-item-text">管理员</text>
</view>
</view>
</view>
<view class="shortcut-grid">
<view
v-for="item in shortcuts"
:key="item.key"
class="shortcut-item"
@click="openShortcut(item.key)"
>
<image class="shortcut-icon" :src="item.icon" mode="aspectFit" />
<text class="shortcut-label">{{ item.label }}</text>
</view>
</view>
<image
class="section-divider"
src="/static/assets/modules/genealogy/transparent/section-divider.png"
mode="scaleToFill"
/>
<view class="genealogy-lower">
<view v-if="createdGenealogies.length" class="list-section">
<view class="section-heading"><text>我创建的</text></view>
<GenealogyCard
v-for="item in createdGenealogies"
:key="item.id"
:genealogy="item"
role="管理员"
:selected="item.id === currentGenealogy.id"
@select="openGenealogy"
/>
</view>
<view v-if="joinedGenealogies.length" class="list-section">
<view class="section-heading"><text>我加入的</text></view>
<GenealogyCard
v-for="item in joinedGenealogies"
:key="item.id"
:genealogy="item"
role="成员"
@select="openGenealogy"
/>
</view>
<view class="list-section application-section">
<view class="section-heading"><text>加入申请</text></view>
<view
v-for="item in applicationRecords"
:key="item.id"
class="application-record"
hover-class="action-hover"
@click="openApplication(item)"
>
<image class="application-record__skin" src="/static/assets/modules/genealogy/transparent/list-slip-frame.png" mode="scaleToFill" />
<view class="application-record__main">
<view class="application-record__title-row">
<text class="application-record__name">{{ item.name }}</text>
<text class="application-record__status" :class="`application-record__status--${item.tone}`">{{ item.statusLabel }}</text>
</view>
<text class="application-record__copy">{{ item.description }}</text>
</view>
<image class="application-record__chevron" src="/static/assets/foundation/transparent/chevron-right.png" mode="aspectFit" />
</view>
</view>
<view class="create-action" @click="openAddDialog">
<image
class="create-cloud"
src="/static/assets/modules/genealogy/transparent/create-cloud.png"
mode="aspectFit"
/>
<image
class="create-icon"
src="/static/assets/modules/genealogy/transparent/add.png"
mode="aspectFit"
/>
<text>添加家谱</text>
<image
class="create-cloud create-cloud--right"
src="/static/assets/modules/genealogy/transparent/create-cloud.png"
mode="aspectFit"
/>
</view>
</view>
</template>
<view v-else class="genealogy-empty-state">
<view class="empty-panel">
<image
class="empty-panel__skin"
src="/static/assets/modules/genealogy/opaque/g01-empty-panel.png"
mode="scaleToFill"
/>
<view class="empty-panel__content">
<view class="empty-seal">
<image
class="empty-seal__skin"
src="/static/assets/modules/genealogy/transparent/current-seal-frame.png"
mode="scaleToFill"
/>
<text class="empty-seal__text">家谱</text>
</view>
<text class="empty-title">还没有加入任何家谱</text>
<text class="empty-copy">先搜索家族是否已有家谱再选择加入或创建</text>
<image
class="empty-divider"
src="/static/assets/modules/genealogy/transparent/section-divider.png"
mode="scaleToFill"
/>
<view
class="empty-search-action"
hover-class="action-hover"
@click="applyToJoin"
>
<image
class="empty-search-action__skin"
src="/static/assets/foundation/opaque/a01-primary-button.png"
mode="scaleToFill"
/>
<text class="empty-search-action__copy empty-search-action__copy--primary">搜索家谱</text>
</view>
<view
class="empty-invite-action"
hover-class="action-hover"
@click="joinByInvite"
>
<image
class="empty-invite-action__skin"
src="/static/assets/foundation/opaque/a01-secondary-button.png"
mode="scaleToFill"
/>
<text class="empty-invite-action__copy">邀请码加入</text>
</view>
<view class="empty-create-action" hover-class="action-hover" @click="createGenealogy">
<text class="empty-create-action__copy">创建家谱</text>
</view>
<text class="empty-create-note">确认没有现有家谱后再创建避免重复建谱</text>
</view>
</view>
</view>
</view>
<view v-if="addDialogVisible" class="add-dialog-layer" @click="closeAddDialog">
<view class="add-dialog" @click.stop>
<image class="add-dialog__skin" src="/static/assets/modules/genealogy/opaque/g01-empty-panel.png" mode="scaleToFill" />
<view class="add-dialog__content">
<text class="dialog-title">添加家谱</text>
<text class="dialog-copy">建议先搜索已有家谱避免重复创建</text>
<view class="dialog-primary" @click="applyToJoin">
<image class="dialog-action__skin" src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
<text class="dialog-primary__copy">搜索家谱</text>
</view>
<view class="dialog-secondary" @click="joinByInvite">
<image class="dialog-action__skin" src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" />
<text>邀请码加入</text>
</view>
<view class="dialog-create" @click="createGenealogy">确认没有现有家谱继续创建</view>
<view class="dialog-close" @click="closeAddDialog">取消</view>
</view>
</view>
</view>
<view v-if="switcherVisible" class="genealogy-switcher-layer" @click="closeSwitcher">
<view class="genealogy-switcher" @click.stop>
<image class="genealogy-switcher__skin" src="/static/assets/modules/genealogy/opaque/g01-empty-panel.png" mode="scaleToFill" />
<view class="genealogy-switcher__content">
<text class="dialog-title">切换当前家谱</text>
<view
v-for="item in availableGenealogies"
:key="item.id"
class="switcher-item"
:class="{ 'switcher-item--active': item.id === selectedGenealogyId }"
@click="selectGenealogy(item)"
>
<view>
<text class="switcher-item__name">{{ item.name }}</text>
<text class="switcher-item__meta">{{ item.location }} · {{ item.memberCount }} 位成员</text>
</view>
<text class="switcher-item__state">{{ item.id === selectedGenealogyId ? '当前' : '选择' }}</text>
</view>
<view class="dialog-close" @click="closeSwitcher">关闭</view>
</view>
</view>
</view>
<AppTabbar active="genealogy" />
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import AppTabbar from "@/components/AppTabbar.vue";
import GenealogyCard from "@/components/GenealogyCard.vue";
import PageHeader from "@/components/PageHeader.vue";
import { genealogies, notifications } from "@/data/mock.js";
const isLoading = ref(false);
const hasError = ref(false);
const list = ref(genealogies);
const forceEmptyState = ref(false);
const addDialogVisible = ref(false);
const switcherVisible = ref(false);
const selectedGenealogyId = ref(genealogies[0]?.id || null);
const readPresentationState = () => {
if (typeof location !== "undefined") {
const query = new URLSearchParams(location.hash.split("?")[1] || "");
return query.get("state") || "default";
}
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
return currentPage?.options?.state || "default";
};
const syncEmptyStateFromRoute = () => {
const presentationState = readPresentationState();
forceEmptyState.value = presentationState === "empty";
isLoading.value = presentationState === "loading";
hasError.value = presentationState === "error";
};
onLoad(() => {
syncEmptyStateFromRoute();
});
onShow(() => {
syncEmptyStateFromRoute();
});
const unreadCount = computed(
() => notifications.filter((item) => item.unread).length,
);
const hasGenealogies = computed(() => !forceEmptyState.value && list.value.length > 0);
const createdGenealogies = computed(() =>
list.value.filter((item, index) => index === 0),
);
const joinedGenealogies = computed(() =>
list.value.filter((item, index) => index > 0),
);
const availableGenealogies = computed(() => list.value);
const currentGenealogy = computed(() =>
availableGenealogies.value.find((item) => item.id === selectedGenealogyId.value) || availableGenealogies.value[0],
);
// 仅用于页面样式阶段覆盖加入申请的关键状态,不作为接口数据。
const applicationRecords = [
{ id: "pending", name: "汤氏南阳宗谱", statusLabel: "审核中", tone: "pending", description: "申请已提交,等待管理员审核" },
{ id: "rejected", name: "汤氏清河家谱", statusLabel: "被拒绝", tone: "rejected", description: "可修改关系说明后重新申请" },
{ id: "removed", name: "汤氏汝南支谱", statusLabel: "已退出", tone: "muted", description: "如需恢复成员身份,可重新申请加入" },
];
const shortcuts = [
{
key: "tree",
label: "世系图",
icon: "/static/assets/modules/genealogy/transparent/shortcut-tree.png",
},
{
key: "members",
label: "成员",
icon: "/static/assets/modules/genealogy/transparent/shortcut-members.png",
},
{
key: "poem",
label: "字辈诗",
icon: "/static/assets/modules/genealogy/transparent/shortcut-generation-poem.png",
},
{
key: "applications",
label: "申请审核",
icon: "/static/assets/modules/genealogy/transparent/shortcut-application.png",
},
];
const openGenealogy = (genealogy) =>
uni.navigateTo({ url: `/pages/genealogy/g05-genealogy-overview?genealogyId=${genealogy.id}` });
const createGenealogy = () =>
uni.navigateTo({ url: "/pages/genealogy/g03-create-genealogy" });
const applyToJoin = () => uni.navigateTo({ url: "/pages/genealogy/g06-search-genealogies" });
const joinByInvite = () => uni.navigateTo({ url: "/pages/genealogy/g06-search-genealogies?mode=invite" });
const toNotifications = () =>
uni.navigateTo({ url: "/pages/notification/n01-message-center" });
const openAddDialog = () => { addDialogVisible.value = true; };
const closeAddDialog = () => { addDialogVisible.value = false; };
const openSwitcher = () => { switcherVisible.value = true; };
const closeSwitcher = () => { switcherVisible.value = false; };
const selectGenealogy = (genealogy) => {
selectedGenealogyId.value = genealogy.id;
closeSwitcher();
};
const openApplication = (record) => {
const statusQuery = record.id === "pending" ? "pending" : record.id;
uni.navigateTo({ url: `/pages/genealogy/g09-my-applications?status=${statusQuery}` });
};
const retryLoad = () => {
hasError.value = false;
isLoading.value = false;
};
const openShortcut = (key) => {
const paths = {
tree: "/pages/tree/t01-tree-overview",
members: `/pages/genealogy/g05-genealogy-overview?genealogyId=${currentGenealogy.value.id}`,
poem: "/pages/genealogy/g12-generation-poems",
applications: "/pages/genealogy/g10-application-review",
};
uni.navigateTo({ url: paths[key] });
};
</script>
<style scoped lang="scss">
.genealogy-index {
position: relative;
min-height: 100vh;
overflow: hidden;
background: #f9f6ef;
}
.page-paper-texture {
position: absolute;
top: calc(124rpx + var(--status-bar-height, 0px));
right: 0;
bottom: 0;
left: 0;
z-index: 0;
width: 100%;
height: 100%;
opacity: 0.72;
pointer-events: none;
}
.page-footer-landscape {
position: absolute;
right: 0;
bottom: 112rpx;
left: 0;
z-index: 1;
width: 100%;
height: 480rpx;
opacity: 0.5;
pointer-events: none;
}
.genealogy-content {
position: relative;
z-index: 2;
padding: 24rpx 32rpx 176rpx;
}
.current-slip {
position: relative;
display: block;
min-height: 268rpx;
padding: 30rpx 34rpx 28rpx;
box-sizing: border-box;
background: transparent;
}
.current-frame {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.current-seal {
position: relative;
z-index: 1;
display: flex;
width: 80rpx;
height: 128rpx;
flex: 0 0 auto;
align-items: center;
justify-content: center;
margin-right: 24rpx;
color: #fff7e7;
}
.current-seal-frame {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 0;
width: 100%;
height: 100%;
}
.current-seal-title {
position: relative;
z-index: 1;
color: #fff7e7;
font-family: "STKaiti", "KaiTi", serif;
font-size: 32rpx;
font-weight: 700;
letter-spacing: 2rpx;
writing-mode: vertical-rl;
}
.current-summary {
position: relative;
z-index: 1;
display: flex;
min-width: 0;
align-items: center;
}
.current-name {
overflow: hidden;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 50rpx;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.current-switch-copy {
flex: 0 0 auto;
margin-left: auto;
color: $brand-red;
font-size: 23rpx;
}
.current-info-divider {
position: relative;
z-index: 1;
width: 100%;
height: 1rpx;
margin: 14rpx 0 16rpx;
background: rgba(181, 138, 75, 0.48);
}
.current-meta {
position: relative;
z-index: 1;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
margin-top: 0;
color: $ink-muted;
font-size: 25rpx;
line-height: 1.4;
}
.current-meta-item {
display: flex;
align-items: center;
margin: 0;
white-space: nowrap;
.current-meta-item-text{
white-space: nowrap;
}
}
.current-meta-icon {
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.shortcut-grid {
display: flex;
min-height: 194rpx;
align-items: center;
margin-top: 24rpx;
padding: 8rpx 0;
}
.shortcut-item {
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
align-items: center;
}
.shortcut-icon {
width: 82rpx;
height: 82rpx;
}
.shortcut-label {
overflow: hidden;
width: 100%;
margin-top: 12rpx;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 29rpx;
font-weight: 700;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
.section-divider {
display: block;
width: 100%;
height: 30rpx;
margin: 4rpx 0 0;
}
.genealogy-lower {
padding: 12rpx 0 36rpx;
}
.list-section {
margin-top: 16rpx;
}
.section-heading {
display: flex;
min-height: 56rpx;
align-items: center;
margin-bottom: 8rpx;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 34rpx;
font-weight: 700;
}
.section-heading::before {
width: 8rpx;
height: 34rpx;
margin-right: 14rpx;
border-radius: 8rpx;
background: $brand-red;
content: "";
}
.list-section + .list-section {
margin-top: 18rpx;
}
.application-record {
position: relative;
display: flex;
min-height: 138rpx;
align-items: center;
box-sizing: border-box;
padding: 22rpx 26rpx;
}
.application-record__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.application-record__main { position: relative; z-index: 1; min-width: 0; flex: 1; }
.application-record__title-row { display: flex; align-items: center; justify-content: space-between; }
.application-record__name { overflow: hidden; color: $ink; font-family: "STKaiti", "KaiTi", serif; font-size: 32rpx; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.application-record__status { flex: 0 0 auto; margin-left: 16rpx; color: #9a641f; font-size: 23rpx; }
.application-record__status--rejected { color: #a7160c; }
.application-record__status--muted { color: $ink-muted; }
.application-record__copy { display: block; margin-top: 10rpx; color: $ink-muted; font-size: 23rpx; }
.application-record__chevron { position: relative; z-index: 1; width: 32rpx; height: 32rpx; margin-left: 14rpx; }
.create-action {
display: flex;
min-height: 96rpx;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 30rpx;
}
.create-action {
width: 350rpx;
margin: 32rpx auto 0;
border: 2rpx solid $brand-red;
border-radius: 48rpx;
background: rgba(255, 249, 238, 0.66);
color: $brand-red;
font-family: "STKaiti", "KaiTi", serif;
font-size: 32rpx;
font-weight: 700;
letter-spacing: 3rpx;
}
.create-icon {
width: 38rpx;
height: 38rpx;
margin-right: 12rpx;
}
.create-action .create-icon {
width: 40rpx;
height: 40rpx;
margin: 0 8rpx;
}
.create-cloud {
width: 54rpx;
height: 28rpx;
flex: 0 0 auto;
}
.create-action > text {
flex: 0 0 auto;
white-space: nowrap;
}
.create-cloud--right {
transform: scaleX(-1);
}
.state-panel {
position: relative;
display: flex;
min-height: 540rpx;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
padding: 42rpx;
box-sizing: border-box;
text-align: center;
}
.state-title {
margin-top: 24rpx;
color: $ink;
font-family: serif;
font-size: 38rpx;
font-weight: 700;
}
.state-copy {
margin-top: 14rpx;
color: $ink-muted;
font-size: 25rpx;
line-height: 1.7;
}
.loading-seal {
border: 2rpx solid $gold;
}
.loading-seal {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
}
.genealogy-empty-state {
min-height: 856rpx;
}
.empty-panel {
position: relative;
height: 856rpx;
}
.empty-panel__skin {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.empty-panel__content {
position: relative;
z-index: 1;
display: flex;
height: 100%;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 58rpx 60rpx 54rpx;
text-align: center;
}
.empty-seal {
position: relative;
display: flex;
width: 92rpx;
height: 142rpx;
align-items: center;
justify-content: center;
}
.empty-seal__skin {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.empty-seal__text {
position: relative;
z-index: 1;
color: #fff7e7;
font-family: "STKaiti", "KaiTi", serif;
font-size: 32rpx;
font-weight: 700;
letter-spacing: 2rpx;
writing-mode: vertical-rl;
}
.empty-title {
display: block;
margin-top: 24rpx;
color: #392719;
font-family: "STKaiti", "KaiTi", serif;
font-size: 40rpx;
font-weight: 700;
letter-spacing: 2rpx;
}
.empty-copy {
display: block;
min-height: 74rpx;
margin-top: 14rpx;
color: #786654;
font-size: 24rpx;
line-height: 1.75;
}
.empty-divider {
display: block;
width: 100%;
height: 30rpx;
margin-top: 16rpx;
}
.empty-search-action,
.empty-invite-action {
position: relative;
display: flex;
width: 468rpx;
height: 104rpx;
align-items: center;
justify-content: center;
overflow: hidden;
}
.empty-search-action {
margin-top: 20rpx;
}
.empty-invite-action {
margin-top: 14rpx;
}
.empty-search-action__skin,
.empty-invite-action__skin {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.empty-search-action__copy,
.empty-invite-action__copy {
position: relative;
z-index: 1;
color: #7b4e24;
font-family: "STKaiti", "KaiTi", serif;
font-size: 29rpx;
font-weight: 700;
letter-spacing: 3rpx;
}
.empty-search-action__copy--primary { color: #fff9ec; }
.empty-create-action { display: flex; align-items: center; justify-content: center; min-height: 64rpx; margin-top: 8rpx; color: $brand-red; }
.empty-create-action__copy { font-family: "STKaiti", "KaiTi", serif; font-size: 27rpx; text-decoration: underline; text-underline-offset: 8rpx; }
.empty-create-note { display: block; color: $ink-muted; font-size: 20rpx; line-height: 30rpx; }
.state-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.state-panel__content { position: relative; z-index: 1; display: flex; min-height: 540rpx; flex-direction: column; align-items: center; justify-content: center; padding: 42rpx; box-sizing: border-box; }
.state-retry { position: relative; display: flex; width: 360rpx; height: 96rpx; align-items: center; justify-content: center; margin-top: 30rpx; overflow: hidden; }
.state-retry__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.state-retry__copy { position: relative; z-index: 1; color: #fff9ec; font-family: "STKaiti", "KaiTi", serif; font-size: 29rpx; }
.add-dialog-layer,
.genealogy-switcher-layer { position: fixed; z-index: 40; inset: 0; display: flex; align-items: center; justify-content: center; box-sizing: border-box; padding: 40rpx; background: rgba(34, 20, 12, 0.58); }
.add-dialog,
.genealogy-switcher { position: relative; width: 100%; max-width: 670rpx; min-height: 720rpx; }
.add-dialog__skin,
.genealogy-switcher__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.add-dialog__content,
.genealogy-switcher__content { position: relative; z-index: 1; display: flex; min-height: 720rpx; flex-direction: column; align-items: center; box-sizing: border-box; padding: 78rpx 58rpx 50rpx; }
.dialog-title { color: $brand-red; font-family: "STKaiti", "KaiTi", serif; font-size: 42rpx; font-weight: 700; letter-spacing: 4rpx; }
.dialog-copy { margin-top: 18rpx; color: $ink-muted; font-size: 23rpx; }
.dialog-primary,
.dialog-secondary { position: relative; display: flex; width: 100%; height: 98rpx; align-items: center; justify-content: center; overflow: hidden; font-family: "STKaiti", "KaiTi", serif; font-size: 29rpx; }
.dialog-primary { margin-top: 42rpx; color: #fff9ec; }
.dialog-secondary { margin-top: 16rpx; color: #7b4e24; }
.dialog-action__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.dialog-primary__copy,
.dialog-secondary > text { position: relative; z-index: 1; }
.dialog-create { display: flex; min-height: 76rpx; align-items: center; margin-top: 8rpx; color: $brand-red; font-size: 23rpx; }
.dialog-close { display: flex; min-height: 72rpx; align-items: center; justify-content: center; margin-top: auto; color: $ink-muted; font-size: 24rpx; }
.switcher-item { display: flex; width: 100%; min-height: 108rpx; align-items: center; justify-content: space-between; box-sizing: border-box; padding: 18rpx 12rpx; border-bottom: 1rpx solid rgba(181, 138, 75, 0.42); }
.switcher-item:first-of-type { margin-top: 28rpx; }
.switcher-item__name,
.switcher-item__meta { display: block; }
.switcher-item__name { color: $ink; font-family: "STKaiti", "KaiTi", serif; font-size: 31rpx; font-weight: 700; }
.switcher-item__meta { margin-top: 6rpx; color: $ink-muted; font-size: 21rpx; }
.switcher-item__state { color: $brand-red; font-size: 23rpx; }
.switcher-item--active .switcher-item__name { color: $brand-red; }
.action-hover {
opacity: 0.82;
}
@media screen and (max-width: 340px) {
.genealogy-content {
padding-right: 20rpx;
padding-left: 20rpx;
}
.current-name {
font-size: 40rpx;
}
.shortcut-label {
font-size: 23rpx;
}
.current-meta-icon {
width: 28rpx;
height: 28rpx;
}
.create-action {
width: 320rpx;
}
.create-cloud {
width: 46rpx;
}
}
</style>