Files
jiapuapp/pages/genealogy/index.vue
T

574 lines
13 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.
<template>
<view class="page-shell genealogy-index">
<image
class="page-paper-texture"
src="/static/assets/backgrounds/paper-rice-texture-v2.jpg"
mode="scaleToFill"
/>
<image
class="page-footer-landscape"
src="/static/assets/backgrounds/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>
<template v-else-if="hasGenealogies">
<view class="current-slip" @click="openGenealogy(currentGenealogy)">
<image
class="current-frame"
src="/static/assets/backgrounds/genealogy-current-slip-frame.png"
mode="scaleToFill"
/>
<view class="current-seal">
<image
class="current-seal-frame"
src="/static/assets/icons/genealogy/seal-current-frame-v1.png"
mode="scaleToFill"
/>
<text class="current-seal-title">家谱</text>
</view>
<view class="current-copy">
<text class="current-name">{{ currentGenealogy.name }}</text>
<view class="current-info-divider"></view>
<view class="current-meta">
<view class="current-meta-item">
<image
class="current-meta-icon"
src="/static/assets/icons/common/location-v1.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/icons/common/member-meta-v1.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/icons/common/admin-v1.png"
mode="aspectFit"
/>
<text class="current-meta-item-text">管理员</text>
</view>
</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/backgrounds/genealogy-section-divider-v2.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="create-action" @click="createGenealogy">
<image
class="create-cloud"
src="/static/assets/icons/action/create-cloud-v1.png"
mode="aspectFit"
/>
<image
class="create-icon"
src="/static/assets/icons/action/add-v2.png"
mode="aspectFit"
/>
<text>新建家谱</text>
<image
class="create-cloud create-cloud--right"
src="/static/assets/icons/action/create-cloud-v1.png"
mode="aspectFit"
/>
</view>
</view>
</template>
<view v-else class="state-panel state-panel--empty">
<view class="empty-scroll"><text>待立家谱</text></view>
<text class="state-title">从第一位家人开始</text>
<text class="state-copy">为家族留下可传承的名字故事与记忆</text>
<view class="empty-primary" @click="createGenealogy">
<image
class="create-icon"
src="/static/assets/icons/action/add-v2.png"
mode="aspectFit"
/>
<text>新建家谱</text>
</view>
<view class="empty-secondary" @click="applyToJoin"
><text>搜索并申请加入</text></view
>
</view>
</view>
<AppTabbar active="genealogy" />
</view>
</template>
<script setup>
import { computed, ref } from "vue";
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 list = ref(genealogies);
const unreadCount = computed(
() => notifications.filter((item) => item.unread).length,
);
const hasGenealogies = computed(() => 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 currentGenealogy = computed(() => list.value[0]);
const shortcuts = [
{
key: "tree",
label: "世系图",
icon: "/static/assets/icons/genealogy/tree-v2.png",
},
{
key: "members",
label: "成员",
icon: "/static/assets/icons/genealogy/members-v2.png",
},
{
key: "poem",
label: "字辈诗",
icon: "/static/assets/icons/genealogy/generation-poem-v2.png",
},
{
key: "applications",
label: "申请审核",
icon: "/static/assets/icons/genealogy/application-v2.png",
},
];
const openGenealogy = (genealogy) =>
uni.navigateTo({ url: `/pages/genealogy/detail?id=${genealogy.id}` });
const createGenealogy = () =>
uni.navigateTo({ url: "/pages/genealogy/create" });
const applyToJoin = () => uni.navigateTo({ url: "/pages/genealogy/search" });
const toNotifications = () =>
uni.navigateTo({ url: "/pages/notification/index" });
const openShortcut = (key) => {
const paths = {
tree: "/pages/tree/index",
members: `/pages/genealogy/detail?id=${currentGenealogy.value.id}`,
poem: "/pages/content/list?type=poem",
applications: "/pages/genealogy/applications",
};
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: 184rpx;
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: 128rpx;
left: 0;
z-index: 1;
width: 100%;
height: 360rpx;
opacity: 0.48;
pointer-events: none;
}
.genealogy-content {
position: relative;
z-index: 2;
padding: 28rpx 48rpx 194rpx;
}
.current-slip {
position: relative;
display: flex;
min-height: 272rpx;
align-items: center;
padding: 34rpx 30rpx;
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: 136rpx;
flex: 0 0 auto;
align-items: center;
justify-content: center;
margin-right: 26rpx;
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-copy {
position: relative;
z-index: 1;
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
}
.current-name {
overflow: hidden;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 50rpx;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.current-info-divider {
width: 100%;
height: 1rpx;
margin: 20rpx 0 18rpx;
background: rgba(181, 138, 75, 0.48);
}
.current-meta {
display: flex;
flex-wrap: nowrap;
margin-top: 0;
color: $ink-muted;
font-size: 25rpx;
line-height: 1.4;
}
.current-meta-item {
display: flex;
align-items: center;
margin: 0 22rpx 8rpx 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: 208rpx;
align-items: center;
margin-top: 36rpx;
padding: 14rpx 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: 10rpx 0 2rpx;
}
.genealogy-lower {
padding: 18rpx 0 44rpx;
}
.list-section {
margin-top: 22rpx;
}
.section-heading {
display: flex;
min-height: 64rpx;
align-items: center;
margin-bottom: 12rpx;
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: 26rpx;
}
.create-action,
.empty-primary,
.empty-secondary {
display: flex;
min-height: 96rpx;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 30rpx;
}
.create-action {
width: 420rpx;
margin: 42rpx 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-weight: 700;
letter-spacing: 3rpx;
}
.empty-primary {
width: 360rpx;
margin: 32rpx auto 0;
border: 2rpx solid $brand-red;
border-radius: 48rpx;
background: rgba(255, 249, 238, 0.94);
color: $brand-red;
font-family: serif;
font-weight: 700;
letter-spacing: 3rpx;
}
.create-icon {
width: 38rpx;
height: 38rpx;
margin-right: 12rpx;
}
.create-action .create-icon {
width: 44rpx;
height: 44rpx;
margin: 0 12rpx;
}
.create-cloud {
width: 64rpx;
height: 32rpx;
}
.create-cloud--right {
transform: scaleX(-1);
}
.state-panel {
display: flex;
min-height: 540rpx;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 42rpx;
box-sizing: border-box;
border: 2rpx solid $gold-soft;
border-radius: 18rpx;
background: rgba(255, 249, 238, 0.76);
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,
.empty-scroll {
border: 2rpx solid $gold;
}
.loading-seal {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
}
.empty-scroll {
display: flex;
width: 154rpx;
height: 196rpx;
align-items: center;
justify-content: center;
color: $gold;
font-family: serif;
font-size: 33rpx;
writing-mode: vertical-rl;
}
.empty-secondary {
margin-top: 16rpx;
color: $ink-muted;
font-size: 27rpx;
}
@media screen and (max-width: 340px) {
.genealogy-content {
padding-right: 24rpx;
padding-left: 24rpx;
}
.current-name {
font-size: 40rpx;
}
.shortcut-label {
font-size: 23rpx;
}
.current-meta-item {
margin-right: 12rpx;
}
.current-meta-icon {
width: 28rpx;
height: 28rpx;
}
.create-action {
width: 360rpx;
}
.create-cloud {
width: 48rpx;
}
}
</style>