84 lines
5.1 KiB
Vue
84 lines
5.1 KiB
Vue
<template>
|
||
<view class="page-shell detail-page">
|
||
<PageHeader title="家谱总览" action="管理" @action="showSoon" />
|
||
<view v-if="genealogy" class="genealogy-hero">
|
||
<text class="hero-kicker">{{ genealogy.hall || '堂号待补' }} · {{ genealogy.location || '所在地待补' }}</text>
|
||
<text class="hero-title">{{ genealogy.name }}</text>
|
||
<text class="hero-motto">{{ genealogy.motto || '敦亲睦族,敬祖传家。' }}</text>
|
||
<view class="hero-stats"><text>共 {{ genealogy.memberCount || 0 }} 人</text><text>已激活 {{ genealogy.activeCount || 0 }} 人</text><text>{{ genealogy.visibility || '仅成员可见' }}</text></view>
|
||
</view>
|
||
<view v-else class="state-copy">{{ loadError || '正在载入家谱…' }}</view>
|
||
|
||
<template v-if="genealogy">
|
||
<view class="core-actions paper-card">
|
||
<view class="section-title">家谱核心</view>
|
||
<view class="action-grid">
|
||
<view class="action-cell primary-cell" @click="toTree"><text>世系树</text><text>查看家脉关系</text></view>
|
||
<view class="action-cell" @click="toFirstPerson"><text>录入族人</text><text>从首代开始完善</text></view>
|
||
<view class="action-cell" @click="showSoon"><text>字辈谱</text><text>传承行辈次序</text></view>
|
||
<view class="action-cell" @click="toApplications"><text>入谱审核</text><text>处理加入申请</text></view>
|
||
</view>
|
||
</view>
|
||
<view class="family-summary"><text class="section-title">家族近况</text><view class="summary-row" @click="toFamily"><text>进入家族圈查看动态</text><text>查看</text></view></view>
|
||
<view class="invite-block"><text class="invite-title">邀亲人,共建家谱</text><text class="invite-copy">族人申请加入后,由创建者审核确认。</text><button class="primary-button" @click="showSoon">邀请亲人</button></view>
|
||
</template>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import PageHeader from '@/components/PageHeader.vue'
|
||
import { appApi } from '@/utils/api.js'
|
||
import { genealogyContext } from '@/utils/genealogy-context.js'
|
||
|
||
const genealogy = ref(null)
|
||
const genealogyId = ref('')
|
||
const loadError = ref('')
|
||
|
||
const loadGenealogy = async (id) => {
|
||
genealogyId.value = id || genealogyContext.getCurrentGenealogyId()
|
||
if (!genealogyId.value) {
|
||
loadError.value = '未找到当前家谱,请从“我的家谱”重新进入。'
|
||
return
|
||
}
|
||
genealogyContext.setCurrentGenealogyId(genealogyId.value)
|
||
try {
|
||
genealogy.value = await appApi.getOverview(genealogyId.value)
|
||
if (!genealogy.value) loadError.value = '家谱不存在或无权访问。'
|
||
} catch (error) {
|
||
loadError.value = error.message || '家谱加载失败。'
|
||
}
|
||
}
|
||
|
||
onLoad((query) => loadGenealogy(query.id))
|
||
const toTree = () => uni.navigateTo({ url: `/pages/tree/index?genealogyId=${genealogyId.value}` })
|
||
const toFirstPerson = () => uni.navigateTo({ url: `/pages/lineage/first-person?genealogyId=${genealogyId.value}` })
|
||
const toFamily = () => uni.reLaunch({ url: '/pages/family/index' })
|
||
const toApplications = () => uni.navigateTo({ url: `/pages/genealogy/applications?genealogyId=${genealogyId.value}` })
|
||
const showSoon = () => uni.showToast({ title: '该模块将在后续阶段接入', icon: 'none' })
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.detail-page { padding-bottom: 48rpx; }
|
||
.genealogy-hero { padding: 48rpx 34rpx 38rpx; background: $navy; color: #fff8ec; }
|
||
.hero-kicker { display: block; color: #e6c57f; font-size: 22rpx; letter-spacing: 4rpx; }
|
||
.hero-title { display: block; margin-top: 20rpx; font-family: serif; font-size: 52rpx; font-weight: 700; letter-spacing: 4rpx; }
|
||
.hero-motto { display: block; margin-top: 16rpx; color: #eadcbf; font-size: 25rpx; }
|
||
.hero-stats { display: flex; flex-wrap: wrap; gap: 12rpx 20rpx; margin-top: 28rpx; color: #dac797; font-size: 22rpx; }
|
||
.state-copy { padding: 80rpx 40rpx; color: $ink-muted; font-size: 27rpx; text-align: center; }
|
||
.core-actions { margin: -18rpx 28rpx 0; padding: 30rpx; }
|
||
.action-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16rpx; margin-top: 26rpx; }
|
||
.action-cell { min-height: 122rpx; padding: 20rpx; box-sizing: border-box; border: 1rpx solid #e7d9be; background: #fbf5e9; }
|
||
.action-cell text { display: block; color: $ink; font-size: 28rpx; font-weight: 700; }
|
||
.action-cell text + text { margin-top: 10rpx; color: $ink-muted; font-size: 21rpx; font-weight: 400; }
|
||
.primary-cell { border-color: $brand-red; background: #f8ede3; }
|
||
.primary-cell text:first-child { color: $brand-red; }
|
||
.family-summary { margin: 38rpx 28rpx 0; }
|
||
.summary-row { display: flex; justify-content: space-between; margin-top: 14rpx; padding: 24rpx 6rpx; border-bottom: 1rpx solid #dfd1b6; color: $ink-muted; font-size: 25rpx; }
|
||
.summary-row text:last-child { color: $brand-red; }
|
||
.invite-block { margin: 42rpx 28rpx 0; padding: 32rpx; border: 1rpx solid $gold; background: #efe0c0; }
|
||
.invite-title { display: block; color: $brand-red; font-family: serif; font-size: 37rpx; font-weight: 700; }
|
||
.invite-copy { display: block; margin: 14rpx 0 24rpx; color: $ink-muted; font-size: 23rpx; }
|
||
</style>
|