验收完成40%
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<!-- 页面编号:F-01;用途:家族动态首页、列表、空态与失败状态。 -->
|
||||
<template>
|
||||
<view class="family-page" :class="{ 'feed-state--list': feedState === 'list', 'feed-state--empty': feedState === 'empty', 'feed-state--error': feedState === 'error' }">
|
||||
<image class="family-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<ModulePageBackground module="family" />
|
||||
<view class="family-page__header"><PageHeader title="家族动态" action="发布" @action="toPublish" /></view>
|
||||
<view class="feed-content">
|
||||
<view class="feed-heading"><text>汤氏家族圈</text><text>家宴、通知与共同记忆</text></view>
|
||||
<scroll-view class="feed-shortcuts" scroll-x :show-scrollbar="false">
|
||||
<view v-for="item in shortcuts" :key="item.key" class="feed-shortcut" @click="openSection(item.key)"><image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" /><text>{{ item.label }}</text></view>
|
||||
<view v-for="item in shortcuts" :key="item.key" class="feed-shortcut" @click="openSection(item.key)"><image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" /><text>{{ item.label }}</text></view>
|
||||
</scroll-view>
|
||||
<template v-if="feedState === 'list'">
|
||||
<view v-for="item in feeds" :key="item.id" class="feed-card" @click="openDetail(item)">
|
||||
@@ -18,17 +18,17 @@
|
||||
<image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill" />
|
||||
<view><text>{{ feedState === 'empty' ? '还没有家族动态' : '家族动态暂不可用' }}</text><text>{{ feedState === 'empty' ? '发布第一条通知、家宴记录或家族故事。' : '请稍后重新进入,已有内容不会受到影响。' }}</text></view>
|
||||
</view>
|
||||
<view class="feed-action" @click="feedState === 'error' ? feedState = 'list' : toPublish()"><image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>{{ feedState === 'error' ? '重新查看' : '发布家族动态' }}</text></view>
|
||||
<view class="feed-action" @click="feedState === 'error' ? feedState = 'list' : toPublish()"><image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>{{ feedState === 'error' ? '重新查看' : '发布家族动态' }}</text></view>
|
||||
</view>
|
||||
<AppTabbar active="family" />
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue';import { onLoad } from '@dcloudio/uni-app';import PageHeader from '@/components/PageHeader.vue';import AppTabbar from '@/components/AppTabbar.vue';import{genealogyContext}from'@/utils/genealogy-context.js'
|
||||
import { ref } from 'vue';import { onLoad } from '@dcloudio/uni-app';import PageHeader from '@/components/PageHeader.vue';import AppTabbar from '@/components/AppTabbar.vue';import ModulePageBackground from '@/components/ModulePageBackground.vue';import{genealogyContext}from'@/utils/genealogy-context.js'
|
||||
const genealogyId=ref('');const feedState=ref('loading');const feeds=[{id:1,tag:'团圆记忆',time:'今天 10:24',title:'端午家宴',content:'今年端午全家相聚,留下了许多温暖照片。',author:'汤正国'},{id:2,tag:'家族通知',time:'昨天 18:02',title:'修谱资料征集',content:'请家人补充老照片中的人物姓名与拍摄时间。',author:'谱主'}];const shortcuts=[{key:'articles',label:'谱文'},{key:'albums',label:'相册'},{key:'rituals',label:'礼仪'},{key:'memos',label:'备忘'}]
|
||||
onLoad(query=>{genealogyId.value=query.genealogyId||genealogyContext.getCurrentGenealogyId()||'';feedState.value=query.state==='empty'?'empty':query.state==='error'?'error':'list'})
|
||||
const toPublish=()=>uni.navigateTo({url:`/pages/family/f02-publish-feed?genealogyId=${genealogyId.value}`});const openDetail=item=>uni.navigateTo({url:`/pages/family/f03-feed-detail?feedId=${item.id}`});const openSection=key=>{const routes={articles:'/pages/family/f04-article-list',albums:'/pages/family/f07-album-list',rituals:'/pages/records/r05-ritual-list',memos:'/pages/records/r10-memo-list'};uni.navigateTo({url:routes[key]})}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.family-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.family-page__paper{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none}.family-page__header,.feed-content{position:relative;z-index:2}.feed-content{padding:24rpx 24rpx 190rpx}.feed-heading text{display:block}.feed-heading text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:31rpx;font-weight:700}.feed-heading text:last-child{margin-top:6rpx;color:$ink-muted;font-size:20rpx}.feed-shortcuts{width:100%;margin-top:15rpx;white-space:nowrap}.feed-shortcut{position:relative;display:inline-block;width:150rpx;height:58rpx;margin-right:10rpx}.feed-shortcut image{position:absolute;inset:0;width:100%;height:100%}.feed-shortcut text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:$ink;font-size:20rpx;font-weight:700}.feed-card,.feed-state-card{position:relative;width:100%;height:calc((100vw - 24px)*.34286);min-height:220rpx;margin-top:17rpx}.feed-card>image,.feed-state-card>image,.feed-action image{position:absolute;inset:0;width:100%;height:100%}.feed-card>view{position:absolute;inset:16% 9%;z-index:1}.feed-card text{display:block}.feed-card text:first-child{color:$brand-red;font-size:18rpx;letter-spacing:2rpx}.feed-card text:nth-child(2){margin-top:5rpx;color:$ink;font-family:STKaiti,KaiTi,serif;font-size:28rpx;font-weight:700}.feed-card text:nth-child(3){margin-top:6rpx;color:$ink-muted;font-size:19rpx}.feed-card text:last-child{margin-top:6rpx;color:#917b62;font-size:17rpx}.feed-state-card{margin-top:70rpx}.feed-state-card>view{position:absolute;inset:25% 12%;z-index:1;text-align:center}.feed-state-card text{display:block}.feed-state-card text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.feed-state-card text:last-child{margin-top:13rpx;color:$ink-muted;font-size:20rpx}.feed-action{position:relative;width:100%;height:76rpx;margin-top:19rpx}.feed-action text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:#fff9ed;font-size:24rpx;font-weight:700}
|
||||
.family-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.family-page__header,.feed-content{position:relative;z-index:2}.feed-content{padding:24rpx 24rpx 190rpx}.feed-heading text{display:block}.feed-heading text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:31rpx;font-weight:700}.feed-heading text:last-child{margin-top:6rpx;color:$ink-muted;font-size:20rpx}.feed-shortcuts{width:100%;margin-top:15rpx;white-space:nowrap}.feed-shortcut{position:relative;display:inline-block;width:150rpx;height:58rpx;margin-right:10rpx}.feed-shortcut image{position:absolute;inset:0;width:100%;height:100%}.feed-shortcut text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:$ink;font-size:20rpx;font-weight:700}.feed-card,.feed-state-card{position:relative;width:100%;height:calc((100vw - 24px)*.34286);min-height:220rpx;margin-top:17rpx}.feed-card>image,.feed-state-card>image,.feed-action image{position:absolute;inset:0;width:100%;height:100%}.feed-card>view{position:absolute;inset:16% 9%;z-index:1}.feed-card text{display:block}.feed-card text:first-child{color:$brand-red;font-size:18rpx;letter-spacing:2rpx}.feed-card text:nth-child(2){margin-top:5rpx;color:$ink;font-family:STKaiti,KaiTi,serif;font-size:28rpx;font-weight:700}.feed-card text:nth-child(3){margin-top:6rpx;color:$ink-muted;font-size:19rpx}.feed-card text:last-child{margin-top:6rpx;color:#917b62;font-size:17rpx}.feed-state-card{margin-top:70rpx}.feed-state-card>view{position:absolute;inset:25% 12%;z-index:1;text-align:center}.feed-state-card text{display:block}.feed-state-card text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.feed-state-card text:last-child{margin-top:13rpx;color:$ink-muted;font-size:20rpx}.feed-action{position:relative;width:100%;height:76rpx;margin-top:19rpx}.feed-action text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:#fff9ed;font-size:24rpx;font-weight:700}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- 页面编号:F-02;用途:发布家族动态与提交结果。 -->
|
||||
<template><view class="publish-page" :class="{'publish-state--form':publishState==='form','publish-state--success':publishState==='success','publish-state--error':publishState==='error'}"><image class="publish-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill"/><view class="publish-page__header"><PageHeader title="发布动态"/></view><view class="publish-panel"><image class="publish-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill"/><view v-if="publishState==='form'" class="publish-form"><text>记录此刻</text><text>分享通知、活动、家族故事或一段共同记忆。</text><view class="publish-field"><image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill"/><textarea v-model="content" maxlength="300" placeholder="写下想对家人说的话" placeholder-class="publish-placeholder"/></view><view class="publish-action" @click="submit"><image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill"/><text>发布动态</text></view></view><view v-else class="publish-result"><text>{{publishState==='success'?'动态已发布':'动态未发布'}}</text><text>{{publishState==='success'?'家人现在可以在家族圈看到这条记录。':'请检查内容后重新发布,当前文字仍保留在页面中。'}}</text><view class="publish-action" @click="publishState='form'"><image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill"/><text>{{publishState==='success'?'继续发布':'重新填写'}}</text></view></view></view></view></template>
|
||||
<script setup>import{ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import PageHeader from'@/components/PageHeader.vue';const content=ref('');const publishState=ref('form');onLoad(query=>{publishState.value=query.state==='success'?'success':query.state==='error'?'error':'form'});const submit=()=>{if(!content.value.trim()){uni.showToast({title:'请先写下动态内容',icon:'none'});return}publishState.value='success'}</script>
|
||||
<style scoped lang="scss">.publish-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.publish-page__paper{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none}.publish-page__header,.publish-panel{position:relative;z-index:2}.publish-panel{width:calc(100% - 32rpx);height:min(640px,calc((100vw - 16px)*1.48));margin:18rpx auto 0}.publish-panel__skin{position:absolute;inset:0;width:100%;height:100%}.publish-form,.publish-result{position:absolute;inset:9% 9%}.publish-form>text,.publish-result>text{display:block}.publish-form>text:first-child,.publish-result>text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:36rpx;font-weight:700}.publish-form>text:nth-child(2),.publish-result>text:nth-child(2){margin-top:12rpx;color:$ink-muted;font-size:21rpx;line-height:1.6}.publish-field{position:relative;height:250rpx;margin-top:24rpx}.publish-field image,.publish-action image{position:absolute;inset:0;width:100%;height:100%}.publish-field textarea{position:absolute;inset:25rpx;z-index:1;width:auto;height:200rpx;color:$ink;font-size:22rpx;line-height:1.7}.publish-placeholder{color:#a79884}.publish-action{position:relative;width:100%;height:78rpx;margin-top:24rpx}.publish-action text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:#fff9ed;font-size:25rpx;font-weight:700}.publish-result{top:30%;text-align:center}.publish-result .publish-action{width:420rpx;max-width:100%;margin:30rpx auto 0}</style>
|
||||
<template><view class="publish-page" :class="{'publish-state--form':publishState==='form','publish-state--success':publishState==='success','publish-state--error':publishState==='error'}"><ModulePageBackground module="family"/><view class="publish-page__header"><PageHeader title="发布动态"/></view><view class="publish-panel"><image class="publish-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill"/><view v-if="publishState==='form'" class="publish-form"><text>记录此刻</text><text>分享通知、活动、家族故事或一段共同记忆。</text><view class="publish-field"><image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill"/><textarea v-model="content" maxlength="300" placeholder="写下想对家人说的话" placeholder-class="publish-placeholder"/></view><AppButton block label="发布动态" @click="submit"/></view><view v-else class="publish-result"><text>{{publishState==='success'?'动态已发布':'动态未发布'}}</text><text>{{publishState==='success'?'家人现在可以在家族圈看到这条记录。':'请检查内容后重新发布,当前文字仍保留在页面中。'}}</text><AppButton block :label="publishState==='success'?'继续发布':'重新填写'" @click="publishState='form'"/></view></view><AppToast :visible="toastVisible" :message="toastMessage"/></view></template>
|
||||
<script setup>import{onUnmounted,ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import AppButton from'@/components/AppButton.vue';import AppToast from'@/components/AppToast.vue';import ModulePageBackground from'@/components/ModulePageBackground.vue';import PageHeader from'@/components/PageHeader.vue';const content=ref('');const publishState=ref('form');const toastVisible=ref(false);const toastMessage=ref('');let toastTimer=null;onLoad(query=>{publishState.value=query.state==='success'?'success':query.state==='error'?'error':'form'});const showToast=message=>{toastMessage.value=message;toastVisible.value=true;if(toastTimer)clearTimeout(toastTimer);toastTimer=setTimeout(()=>{toastVisible.value=false;toastTimer=null},1800)};const submit=()=>{if(!content.value.trim()){showToast('请先写下动态内容');return}publishState.value='success'};onUnmounted(()=>{if(toastTimer)clearTimeout(toastTimer)})</script>
|
||||
<style scoped lang="scss">.publish-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.publish-page__header,.publish-panel{position:relative;z-index:2}.publish-panel{width:calc(100% - 32rpx);height:min(640px,calc((100vw - 16px)*1.48));margin:18rpx auto 0}.publish-panel__skin{position:absolute;inset:0;width:100%;height:100%}.publish-form,.publish-result{position:absolute;inset:9% 9%}.publish-form>text,.publish-result>text{display:block}.publish-form>text:first-child,.publish-result>text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:36rpx;font-weight:700}.publish-form>text:nth-child(2),.publish-result>text:nth-child(2){margin-top:12rpx;color:$ink-muted;font-size:21rpx;line-height:1.6}.publish-field{position:relative;height:250rpx;margin-top:24rpx}.publish-field image{position:absolute;inset:0;width:100%;height:100%}.publish-field textarea{position:absolute;inset:25rpx;z-index:1;width:auto;height:200rpx;color:$ink;font-size:22rpx;line-height:1.7}.publish-placeholder{color:#a79884}.publish-form>.app-button{margin-top:24rpx}.publish-result{top:30%;text-align:center}.publish-result>.app-button{margin:30rpx auto 0}</style>
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
<!-- 页面编号: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"
|
||||
/>
|
||||
<view
|
||||
class="page-shell genealogy-index"
|
||||
:class="{ 'genealogy-index--split': isListLayout }"
|
||||
>
|
||||
<GenealogyPageBackground />
|
||||
<PageHeader
|
||||
root
|
||||
title="我的家谱"
|
||||
@@ -31,14 +25,15 @@
|
||||
<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" />
|
||||
<image class="state-retry__skin" src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text class="state-retry__copy">重新加载</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-else-if="hasGenealogies">
|
||||
<view class="current-slip" @click="openSwitcher">
|
||||
<view class="genealogy-fixed-zone">
|
||||
<view class="current-slip" @click="openSwitcher">
|
||||
<image
|
||||
class="current-frame"
|
||||
src="/static/assets/modules/genealogy/transparent/current-slip-frame.png"
|
||||
@@ -87,90 +82,98 @@
|
||||
<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 class="shortcut-grid">
|
||||
<view
|
||||
v-for="item in applicationRecords"
|
||||
:key="item.id"
|
||||
class="application-record"
|
||||
hover-class="action-hover"
|
||||
@click="openApplication(item)"
|
||||
v-for="item in shortcuts"
|
||||
:key="item.key"
|
||||
class="shortcut-item"
|
||||
@click="openShortcut(item.key)"
|
||||
>
|
||||
<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" />
|
||||
<image class="shortcut-icon" :src="item.icon" mode="aspectFit" />
|
||||
<text class="shortcut-label">{{ item.label }}</text>
|
||||
</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>
|
||||
<image
|
||||
class="section-divider"
|
||||
src="/static/assets/modules/genealogy/transparent/section-divider.png"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
class="genealogy-list-scroll"
|
||||
scroll-y
|
||||
:scroll-top="listScrollCommand"
|
||||
@scroll="handleListScroll"
|
||||
>
|
||||
<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>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<view v-else class="genealogy-empty-state">
|
||||
@@ -203,8 +206,8 @@
|
||||
>
|
||||
<image
|
||||
class="empty-search-action__skin"
|
||||
src="/static/assets/foundation/opaque/a01-primary-button.png"
|
||||
mode="scaleToFill"
|
||||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="empty-search-action__copy empty-search-action__copy--primary">搜索家谱</text>
|
||||
</view>
|
||||
@@ -215,8 +218,8 @@
|
||||
>
|
||||
<image
|
||||
class="empty-invite-action__skin"
|
||||
src="/static/assets/foundation/opaque/a01-secondary-button.png"
|
||||
mode="scaleToFill"
|
||||
src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="empty-invite-action__copy">邀请码加入</text>
|
||||
</view>
|
||||
@@ -231,19 +234,13 @@
|
||||
|
||||
<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" />
|
||||
<image class="add-dialog__skin" src="/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png" mode="aspectFit" />
|
||||
<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>
|
||||
<AppButton block label="搜索家谱" @click="applyToJoin" />
|
||||
<AppButton block type="secondary" label="邀请码加入" @click="joinByInvite" />
|
||||
<AppButton block type="secondary" label="确认没有现有家谱,继续创建" @click="createGenealogy" />
|
||||
<view class="dialog-close" @click="closeAddDialog">取消</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -251,7 +248,7 @@
|
||||
|
||||
<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" />
|
||||
<image class="genealogy-switcher__skin" src="/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png" mode="aspectFit" />
|
||||
<view class="genealogy-switcher__content">
|
||||
<text class="dialog-title">切换当前家谱</text>
|
||||
<view
|
||||
@@ -277,10 +274,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { computed, nextTick, ref } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import AppTabbar from "@/components/AppTabbar.vue";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import GenealogyCard from "@/components/GenealogyCard.vue";
|
||||
import GenealogyPageBackground from "@/components/GenealogyPageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import { genealogies, notifications } from "@/data/mock.js";
|
||||
|
||||
@@ -291,6 +290,8 @@ const forceEmptyState = ref(false);
|
||||
const addDialogVisible = ref(false);
|
||||
const switcherVisible = ref(false);
|
||||
const selectedGenealogyId = ref(genealogies[0]?.id || null);
|
||||
const listScrollCommand = ref(0);
|
||||
const currentListScrollTop = ref(0);
|
||||
|
||||
const readPresentationState = () => {
|
||||
if (typeof location !== "undefined") {
|
||||
@@ -322,6 +323,9 @@ const unreadCount = computed(
|
||||
() => notifications.filter((item) => item.unread).length,
|
||||
);
|
||||
const hasGenealogies = computed(() => !forceEmptyState.value && list.value.length > 0);
|
||||
const isListLayout = computed(
|
||||
() => !isLoading.value && !hasError.value && hasGenealogies.value,
|
||||
);
|
||||
const createdGenealogies = computed(() =>
|
||||
list.value.filter((item, index) => index === 0),
|
||||
);
|
||||
@@ -376,9 +380,19 @@ const openAddDialog = () => { addDialogVisible.value = true; };
|
||||
const closeAddDialog = () => { addDialogVisible.value = false; };
|
||||
const openSwitcher = () => { switcherVisible.value = true; };
|
||||
const closeSwitcher = () => { switcherVisible.value = false; };
|
||||
const selectGenealogy = (genealogy) => {
|
||||
const handleListScroll = (event) => {
|
||||
currentListScrollTop.value = Number(event?.detail?.scrollTop || 0);
|
||||
};
|
||||
const resetListScroll = async () => {
|
||||
listScrollCommand.value = currentListScrollTop.value;
|
||||
await nextTick();
|
||||
listScrollCommand.value = 0;
|
||||
currentListScrollTop.value = 0;
|
||||
};
|
||||
const selectGenealogy = async (genealogy) => {
|
||||
selectedGenealogyId.value = genealogy.id;
|
||||
closeSwitcher();
|
||||
await resetListScroll();
|
||||
};
|
||||
const openApplication = (record) => {
|
||||
const statusQuery = record.id === "pending" ? "pending" : record.id;
|
||||
@@ -408,37 +422,40 @@ const openShortcut = (key) => {
|
||||
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;
|
||||
}
|
||||
|
||||
.genealogy-index--split {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
min-height: 0;
|
||||
flex-direction: column;
|
||||
padding-bottom: calc(112rpx + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.genealogy-index--split .genealogy-content {
|
||||
display: flex;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.genealogy-fixed-zone {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.genealogy-list-scroll {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.current-slip {
|
||||
position: relative;
|
||||
display: block;
|
||||
@@ -531,8 +548,9 @@ const openShortcut = (key) => {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
margin-top: 0;
|
||||
color: $ink-muted;
|
||||
font-size: 25rpx;
|
||||
color: #62584c;
|
||||
font-size: 27rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@@ -635,10 +653,23 @@ const openShortcut = (key) => {
|
||||
.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 {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 16rpx;
|
||||
color: #7f4f16;
|
||||
font-size: 27rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.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__status--muted { color: #62584c; }
|
||||
.application-record__copy {
|
||||
display: block;
|
||||
margin-top: 10rpx;
|
||||
color: #62584c;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.application-record__chevron { position: relative; z-index: 1; width: 32rpx; height: 32rpx; margin-left: 14rpx; }
|
||||
|
||||
.create-action {
|
||||
@@ -862,14 +893,8 @@ const openShortcut = (key) => {
|
||||
.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; }
|
||||
.add-dialog__content > .app-button:first-of-type { margin-top: 34rpx; }
|
||||
.add-dialog__content > .app-button + .app-button { margin-top: 10rpx; }
|
||||
.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; }
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
<!-- 页面编号:G-03;用途:创建家谱与录入首代人物的同路由两步流程。 -->
|
||||
<template>
|
||||
<view class="flow-page">
|
||||
<!-- 纸纹、页头和山水均由完整位图承载,流程内容只叠加文字和控件。 -->
|
||||
<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"
|
||||
/>
|
||||
<GenealogyPageBackground />
|
||||
|
||||
<view class="flow-header">
|
||||
<image
|
||||
@@ -81,8 +71,8 @@
|
||||
<view class="flow-primary-action" hover-class="action-hover" @click="submitCreate">
|
||||
<image
|
||||
class="flow-primary-action__skin"
|
||||
src="/static/assets/foundation/opaque/a01-primary-button.png"
|
||||
mode="scaleToFill"
|
||||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="flow-primary-action__copy">{{ createState === 'submitting' ? '正在创建…' : '创建并录入首代' }}</text>
|
||||
</view>
|
||||
@@ -118,8 +108,8 @@
|
||||
<view class="flow-primary-action" hover-class="action-hover" @click="submitAncestor">
|
||||
<image
|
||||
class="flow-primary-action__skin"
|
||||
src="/static/assets/foundation/opaque/a01-primary-button.png"
|
||||
mode="scaleToFill"
|
||||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="flow-primary-action__copy">{{ ancestorState === 'submitting' ? '正在保存…' : '保存并进入家谱' }}</text>
|
||||
</view>
|
||||
@@ -129,16 +119,16 @@
|
||||
|
||||
<view v-if="duplicateReminderVisible" class="duplicate-reminder-layer" @click="closeDuplicateReminder">
|
||||
<view class="duplicate-reminder" @click.stop>
|
||||
<image class="duplicate-reminder__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill" />
|
||||
<image class="duplicate-reminder__skin" src="/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png" mode="aspectFit" />
|
||||
<view class="duplicate-reminder__content">
|
||||
<text class="duplicate-reminder__title">先确认是否已有家谱</text>
|
||||
<text class="duplicate-reminder__copy">同一家族可能已经建谱。建议先搜索谱名、地区和堂号,避免重复创建。</text>
|
||||
<view class="duplicate-reminder__search" @click="searchExistingGenealogy">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" />
|
||||
<text>先搜索已有家谱</text>
|
||||
</view>
|
||||
<view class="duplicate-reminder__confirm" @click="confirmCreate">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>确认没有,继续创建</text>
|
||||
</view>
|
||||
<view class="duplicate-reminder__cancel" @click="closeDuplicateReminder">返回修改</view>
|
||||
@@ -148,12 +138,12 @@
|
||||
|
||||
<view v-if="ancestorState === 'success'" class="flow-success-layer">
|
||||
<view class="flow-success-dialog">
|
||||
<image class="flow-success-dialog__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill" />
|
||||
<image class="flow-success-dialog__skin" src="/static/assets/modules/auth/transparent/a01-scroll-dialog-v3.png" mode="aspectFit" />
|
||||
<view class="flow-success-dialog__content">
|
||||
<text class="flow-success-dialog__title">家谱创建完成</text>
|
||||
<text class="flow-success-dialog__copy">首代人物已保存,接下来进入家谱总览继续完善资料。</text>
|
||||
<view class="flow-success-dialog__action" @click="enterOverview">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>进入家谱总览</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -165,6 +155,7 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, onUnmounted, reactive, ref } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import GenealogyPageBackground from "@/components/GenealogyPageBackground.vue";
|
||||
|
||||
const currentStep = ref("create");
|
||||
const genealogyId = ref("");
|
||||
@@ -305,31 +296,6 @@ const enterOverview = () => uni.redirectTo({ url: `/pages/genealogy/g05-genealog
|
||||
background: #f9f6ef;
|
||||
}
|
||||
|
||||
.page-paper-texture {
|
||||
position: absolute;
|
||||
top: 112rpx;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.74;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.page-footer-landscape {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 430rpx;
|
||||
opacity: 0.42;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.flow-header {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-05;用途:家谱总览与加载、空数据、失败状态。 -->
|
||||
<template>
|
||||
<view class="overview-page">
|
||||
<image class="overview-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="overview-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="overview-page__header">
|
||||
<PageHeader :title="viewMode === 'public' ? '家谱公开预览' : '家谱总览'" :action="overviewState === 'ready' && viewMode === 'member' && accessRole === 'owner' ? '管理' : ''" @action="toSettings" />
|
||||
</view>
|
||||
@@ -66,7 +65,7 @@
|
||||
<text>{{ genealogy.publicDescription }}</text>
|
||||
</view>
|
||||
<view class="overview-public__action" @click="applyToJoin">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>申请加入这部家谱</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -80,7 +79,7 @@
|
||||
<text class="overview-state-panel__title">{{ stateTitle }}</text>
|
||||
<text class="overview-state-panel__copy">{{ stateCopy }}</text>
|
||||
<view v-if="overviewState !== 'loading'" class="overview-state-panel__action" @click="overviewState === 'error' ? reloadOverview() : toGenealogies()">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ overviewState === 'error' ? '重新查看' : '返回我的家谱' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -91,6 +90,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const genealogy = ref(null)
|
||||
@@ -168,8 +168,6 @@ const applyToJoin = () => uni.navigateTo({ url: `/pages/genealogy/g08-join-appli
|
||||
|
||||
<style scoped lang="scss">
|
||||
.overview-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.overview-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.overview-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.overview-page__header { position: relative; z-index: 3; }
|
||||
.overview-surface { position: relative; z-index: 2; width: 100%; height: min(483px, calc(100vw * 1.3422)); }
|
||||
.overview-surface__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-06;用途:搜索家谱/邀请码加入双模式定位目标家谱。 -->
|
||||
<template>
|
||||
<view class="search-page">
|
||||
<image class="search-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="scaleToFill" />
|
||||
<image class="search-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="search-page__header"><PageHeader title="加入家谱" /></view>
|
||||
|
||||
<view class="search-page__content">
|
||||
@@ -130,6 +129,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad, onUnload, onShow } from '@dcloudio/uni-app'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const mode = ref('search')
|
||||
@@ -220,8 +220,6 @@ const confirmInvite = () => uni.navigateTo({ url: `/pages/genealogy/g08-join-app
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.search-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.search-page__footer { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .15; pointer-events: none; }
|
||||
.search-page__header { position: relative; z-index: 2; }
|
||||
.search-page__content { position: relative; z-index: 3; min-height: calc(100vh - 104rpx); padding: 30rpx 24rpx calc(58rpx + env(safe-area-inset-bottom)); box-sizing: border-box; }
|
||||
.search-title-strip { position: relative; width: 100%; height: 138rpx; }
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-08;用途:申请加入家谱与提交成功/失败状态。 -->
|
||||
<template>
|
||||
<view class="join-page">
|
||||
<image class="join-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="join-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="join-page__header"><PageHeader :title="sourceContract.headerTitle" /></view>
|
||||
|
||||
<view class="join-panel" :class="{
|
||||
@@ -35,7 +34,7 @@
|
||||
|
||||
<text class="join-form__note">{{ sourceContract.note }}</text>
|
||||
<view class="join-action" @click="submitJoin">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ isSubmitting ? sourceContract.submittingLabel : sourceContract.submitLabel }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -45,7 +44,7 @@
|
||||
<text class="join-result__title">{{ joinState === 'success' ? sourceContract.successTitle : sourceContract.errorTitle }}</text>
|
||||
<text class="join-result__copy">{{ resultCopy }}</text>
|
||||
<view class="join-action" @click="joinState === 'success' ? completeFlow() : retryForm()">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ joinState === 'success' ? sourceContract.nextLabel : '重新填写' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -56,6 +55,7 @@
|
||||
<script setup>
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const genealogyId = ref('')
|
||||
@@ -143,8 +143,6 @@ const completeFlow = () => source.value === 'invite' ? toMyGenealogies() : toMyA
|
||||
|
||||
<style scoped lang="scss">
|
||||
.join-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.join-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.join-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.join-page__header { position: relative; z-index: 3; }
|
||||
.join-panel { position: relative; z-index: 2; width: calc(100% - 32rpx); height: min(590px, calc((100vw - 16px) * 1.337)); margin: 22rpx auto 0; }
|
||||
.join-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-09;用途:我的家谱申请列表与空/失败状态。 -->
|
||||
<template>
|
||||
<view class="application-page">
|
||||
<image class="application-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="application-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="application-page__header"><PageHeader title="我的申请" /></view>
|
||||
|
||||
<view class="application-content" :class="{
|
||||
@@ -35,30 +34,30 @@
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="applicationState !== 'list'" class="application-page__action" @click="applicationState === 'error' ? loadApplications({}) : toSearch()">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ applicationState === 'error' ? '重新查看' : '查找公开家谱' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="withdrawTarget" class="withdraw-layer" @click="cancelWithdraw">
|
||||
<view class="withdraw-dialog" @click.stop>
|
||||
<image class="withdraw-dialog__skin" src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill" />
|
||||
<view class="withdraw-dialog__content">
|
||||
<text class="withdraw-dialog__title">撤回加入申请</text>
|
||||
<text class="withdraw-dialog__copy">确认撤回对“{{ withdrawTarget.genealogyName }}”的申请?撤回后如需加入,可重新提交。</text>
|
||||
<view class="withdraw-dialog__actions">
|
||||
<view class="withdraw-action" @click="cancelWithdraw">暂不撤回</view>
|
||||
<view class="withdraw-action withdraw-action--danger" @click="confirmWithdraw">确认撤回</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<AppDialog
|
||||
:visible="!!withdrawTarget"
|
||||
title="撤回加入申请"
|
||||
:message="withdrawTarget ? `确认撤回对“${withdrawTarget.genealogyName}”的申请?撤回后如需加入,可重新提交。` : ''"
|
||||
confirm-text="确认撤回"
|
||||
cancel-text="暂不撤回"
|
||||
show-cancel
|
||||
@confirm="confirmWithdraw"
|
||||
@cancel="cancelWithdraw"
|
||||
@close="cancelWithdraw"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import AppDialog from '@/components/AppDialog.vue'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const applications = ref([])
|
||||
@@ -116,8 +115,6 @@ const toSearch = () => uni.navigateTo({ url: '/pages/genealogy/g06-search-geneal
|
||||
|
||||
<style scoped lang="scss">
|
||||
.application-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.application-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.application-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.application-page__header { position: relative; z-index: 3; }
|
||||
.application-content { position: relative; z-index: 2; padding: 28rpx 24rpx 60rpx; }
|
||||
.application-intro { display: flex; align-items: baseline; justify-content: space-between; margin: 0 8rpx 20rpx; }
|
||||
@@ -142,13 +139,4 @@ const toSearch = () => uni.navigateTo({ url: '/pages/genealogy/g06-search-geneal
|
||||
.application-page__action { position: relative; width: 420rpx; height: 82rpx; margin: 34rpx auto 0; }
|
||||
.application-page__action image { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.application-page__action text { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; height: 100%; color: #fff9ed; font-size: 26rpx; font-weight: 700; }
|
||||
.withdraw-layer { position: fixed; z-index: 30; inset: 0; display: flex; align-items: center; justify-content: center; box-sizing: border-box; padding: 42rpx; background: rgba(34, 20, 12, .58); }
|
||||
.withdraw-dialog { position: relative; width: 100%; max-width: 660rpx; min-height: 390rpx; }
|
||||
.withdraw-dialog__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.withdraw-dialog__content { position: relative; z-index: 1; display: flex; min-height: 390rpx; flex-direction: column; align-items: center; box-sizing: border-box; padding: 74rpx 60rpx 46rpx; text-align: center; }
|
||||
.withdraw-dialog__title { color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 36rpx; font-weight: 700; }
|
||||
.withdraw-dialog__copy { margin-top: 24rpx; color: $ink-muted; font-size: 23rpx; line-height: 38rpx; }
|
||||
.withdraw-dialog__actions { display: flex; width: 100%; margin-top: auto; border-top: 1rpx solid rgba(181, 138, 75, .42); }
|
||||
.withdraw-action { display: flex; flex: 1; min-height: 76rpx; align-items: center; justify-content: center; color: $ink-muted; font-size: 23rpx; }
|
||||
.withdraw-action--danger { border-left: 1rpx solid rgba(181, 138, 75, .42); color: $brand-red; }
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-10;用途:管理员入谱申请审核与空/失败状态。 -->
|
||||
<template>
|
||||
<view class="review-page">
|
||||
<image class="review-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="review-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="review-page__header"><PageHeader title="入谱审核" action="说明" @action="showHelp" /></view>
|
||||
|
||||
<view class="review-content" :class="{
|
||||
@@ -27,10 +26,10 @@
|
||||
<text class="application-card__relation">{{ item.relation }}</text>
|
||||
<view v-if="item.status === 'PENDING'" class="review-actions">
|
||||
<view class="review-action" @click="confirmAudit(item, false)">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" /><text>拒绝</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" /><text>拒绝</text>
|
||||
</view>
|
||||
<view class="review-action" @click="confirmAudit(item, true)">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>通过</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>通过</text>
|
||||
</view>
|
||||
</view>
|
||||
<text v-else class="application-card__status">{{ item.status === 'APPROVED' ? '已通过' : '已拒绝' }}</text>
|
||||
@@ -46,33 +45,23 @@
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="reviewState === 'error'" class="review-page__retry" @click="loadApplications({ genealogyId })">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>重新查看</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>重新查看</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="confirmation || helpVisible" class="review-dialog-layer" @click="closeDialog">
|
||||
<view class="review-dialog" @click.stop>
|
||||
<image class="review-dialog__skin" src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill" />
|
||||
<view class="review-dialog__content">
|
||||
<template v-if="helpVisible">
|
||||
<text class="review-dialog__title">审核说明</text>
|
||||
<text class="review-dialog__copy">请核对申请人的姓名、亲属关系和补充说明,仅确认与本家谱存在真实关系的申请。</text>
|
||||
<view class="review-dialog__single" @click="closeDialog">我知道了</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text class="review-dialog__title">{{ confirmation.approved ? '确认通过申请?' : '确认拒绝申请?' }}</text>
|
||||
<text class="review-dialog__copy">{{ confirmation.approved ? '通过后,申请人将成为本家谱成员。' : '拒绝后,申请人会收到审核结果,并可修改后重新申请。' }}</text>
|
||||
<view class="review-dialog__actions">
|
||||
<view class="review-dialog__action" @click="closeDialog">取消</view>
|
||||
<view class="review-dialog__action review-dialog__action--primary" @click="applyAudit">{{ confirmation.approved ? '确认通过' : '确认拒绝' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<AppDialog
|
||||
:visible="!!confirmation || helpVisible"
|
||||
:title="helpVisible ? '审核说明' : confirmation?.approved ? '确认通过申请?' : '确认拒绝申请?'"
|
||||
:message="helpVisible ? '请核对申请人的姓名、亲属关系和补充说明,仅确认与本家谱存在真实关系的申请。' : confirmation?.approved ? '通过后,申请人将成为本家谱成员。' : '拒绝后,申请人会收到审核结果,并可修改后重新申请。'"
|
||||
:confirm-text="helpVisible ? '我知道了' : confirmation?.approved ? '确认通过' : '确认拒绝'"
|
||||
:show-cancel="!!confirmation"
|
||||
@confirm="helpVisible ? closeDialog() : applyAudit()"
|
||||
@cancel="closeDialog"
|
||||
@close="closeDialog"
|
||||
/>
|
||||
|
||||
<view v-if="feedbackVisible" class="review-feedback">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-toast-v3.png" mode="scaleToFill" />
|
||||
<text>{{ feedbackMessage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -81,6 +70,8 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import AppDialog from '@/components/AppDialog.vue'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
import { genealogyContext } from '@/utils/genealogy-context.js'
|
||||
|
||||
@@ -141,8 +132,6 @@ const showHelp = () => { helpVisible.value = true }
|
||||
|
||||
<style scoped lang="scss">
|
||||
.review-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.review-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.review-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.review-page__header { position: relative; z-index: 3; }
|
||||
.review-content { position: relative; z-index: 2; padding: 24rpx 24rpx 60rpx; }
|
||||
.review-intro { position: relative; margin: 0 8rpx 24rpx; padding-bottom: 22rpx; }
|
||||
@@ -171,16 +160,6 @@ const showHelp = () => { helpVisible.value = true }
|
||||
.review-page__retry { position: relative; width: 420rpx; height: 82rpx; margin: 32rpx auto 0; }
|
||||
.review-page__retry image { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.review-page__retry text { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; height: 100%; color: #fff9ed; font-size: 26rpx; font-weight: 700; }
|
||||
.review-dialog-layer { position: fixed; z-index: 30; inset: 0; display: flex; align-items: center; justify-content: center; box-sizing: border-box; padding: 42rpx; background: rgba(34, 20, 12, .58); }
|
||||
.review-dialog { position: relative; width: 100%; max-width: 660rpx; min-height: 410rpx; }
|
||||
.review-dialog__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.review-dialog__content { position: relative; z-index: 1; display: flex; min-height: 410rpx; flex-direction: column; align-items: center; box-sizing: border-box; padding: 72rpx 60rpx 42rpx; text-align: center; }
|
||||
.review-dialog__title { color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 36rpx; font-weight: 700; }
|
||||
.review-dialog__copy { margin-top: 24rpx; color: $ink-muted; font-size: 23rpx; line-height: 38rpx; }
|
||||
.review-dialog__actions { display: flex; width: 100%; margin-top: auto; border-top: 1rpx solid rgba(181, 138, 75, .42); }
|
||||
.review-dialog__action { display: flex; flex: 1; min-height: 74rpx; align-items: center; justify-content: center; color: $ink-muted; font-size: 23rpx; }
|
||||
.review-dialog__action--primary { border-left: 1rpx solid rgba(181, 138, 75, .42); color: $brand-red; font-weight: 700; }
|
||||
.review-dialog__single { display: flex; min-height: 76rpx; align-items: center; margin-top: auto; color: $brand-red; font-size: 24rpx; font-weight: 700; }
|
||||
.review-feedback { position: fixed; z-index: 40; top: 140rpx; left: 50%; display: flex; min-width: 250rpx; min-height: 76rpx; align-items: center; justify-content: center; padding: 0 36rpx; transform: translateX(-50%); }
|
||||
.review-feedback image { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.review-feedback text { position: relative; z-index: 1; color: $ink; font-size: 23rpx; }
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-11;用途:家谱设置、公开范围与访问说明(页面设计阶段使用本地模拟交互)。 -->
|
||||
<template>
|
||||
<view class="settings-page">
|
||||
<image class="settings-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="settings-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="settings-page__header"><PageHeader title="家谱设置" /></view>
|
||||
|
||||
<view class="settings-panel" :class="{
|
||||
@@ -29,7 +28,7 @@
|
||||
<text class="visibility-block__label">公开范围</text>
|
||||
<view class="visibility-options">
|
||||
<view v-for="option in visibilityOptions" :key="option.value" class="visibility-option" @click="genealogyDraft.visibility = option.value">
|
||||
<image :src="genealogyDraft.visibility === option.value ? '/static/assets/foundation/opaque/a01-primary-button.png' : '/static/assets/foundation/opaque/a01-secondary-button.png'" mode="scaleToFill" />
|
||||
<image :src="genealogyDraft.visibility === option.value ? '/static/assets/foundation/transparent/a01-scroll-primary-v3.png' : '/static/assets/foundation/transparent/a01-scroll-secondary-v3.png'" mode="aspectFit" />
|
||||
<text :class="{ 'visibility-option__text--active': genealogyDraft.visibility === option.value }">{{ option.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -43,7 +42,7 @@
|
||||
</view>
|
||||
|
||||
<view class="settings-action" @click="saveSettings">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>保存设置</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -53,13 +52,13 @@
|
||||
<text class="settings-result__title">{{ settingsState === 'success' ? '新的访问规则已经生效' : settingsState === 'no-permission' ? '当前账号不能修改家谱' : '暂时无法打开家谱设置' }}</text>
|
||||
<text class="settings-result__copy">{{ settingsState === 'success' ? `${genealogyDraft.name} · ${visibilityLabel}` : settingsState === 'no-permission' ? '只有家谱所有者可以修改名称、公开范围和访问说明。' : '请从家谱总览重新进入,当前修改不会被保留。' }}</text>
|
||||
<view class="settings-action" @click="settingsState = 'form'">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ settingsState === 'success' ? '继续调整' : '重新查看' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="feedbackVisible" class="settings-feedback">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" />
|
||||
<text>设置已保存</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -68,6 +67,7 @@
|
||||
<script setup>
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const genealogyId = ref('')
|
||||
@@ -108,8 +108,6 @@ const saveSettings = () => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.settings-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.settings-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.settings-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.settings-page__header { position: relative; z-index: 3; }
|
||||
.settings-panel { position: relative; z-index: 2; width: calc(100% - 32rpx); height: min(620px, calc((100vw - 16px) * 1.43)); margin: 18rpx auto 0; }
|
||||
.settings-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<!-- 页面编号:G-12;用途:字辈诗列表、空状态与批量维护(页面设计阶段使用本地模拟交互)。 -->
|
||||
<template>
|
||||
<view class="poem-page">
|
||||
<image class="poem-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<image class="poem-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
|
||||
<GenealogyPageBackground />
|
||||
<view class="poem-page__header"><PageHeader title="字辈诗" :action="poemState === 'list' ? '维护' : ''" @action="openEditor" /></view>
|
||||
|
||||
<view class="poem-panel" :class="{
|
||||
@@ -27,7 +26,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="poem-action" @click="openEditor">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>维护字辈诗</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>维护字辈诗</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -44,17 +43,17 @@
|
||||
<view class="poem-policy">
|
||||
<text>缺失旧世代时</text>
|
||||
<view class="poem-policy__option" @click="stopMissingOldGeneration = !stopMissingOldGeneration">
|
||||
<image :src="stopMissingOldGeneration ? '/static/assets/foundation/opaque/a01-primary-button.png' : '/static/assets/foundation/opaque/a01-secondary-button.png'" mode="scaleToFill" />
|
||||
<image :src="stopMissingOldGeneration ? '/static/assets/foundation/transparent/a01-scroll-primary-v3.png' : '/static/assets/foundation/transparent/a01-scroll-secondary-v3.png'" mode="aspectFit" />
|
||||
<text :class="{ 'poem-policy__option-text--active': stopMissingOldGeneration }">{{ stopMissingOldGeneration ? '停止并提醒' : '继续补录' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="poem-preview">预览:{{ previewCharacters || '尚未录入字辈' }}</text>
|
||||
<view class="poem-editor__actions">
|
||||
<view class="poem-action" @click="poemState = 'list'">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" /><text class="poem-action__secondary">取消</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" /><text class="poem-action__secondary">取消</text>
|
||||
</view>
|
||||
<view class="poem-action" @click="savePoems">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>保存字辈</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>保存字辈</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -64,12 +63,12 @@
|
||||
<text class="poem-list__title">{{ poemState === 'empty' ? '从第一段传承字序开始' : poemState === 'no-permission' ? '当前账号不能维护字辈' : '暂时无法读取字辈诗' }}</text>
|
||||
<text class="poem-list__copy">{{ poemState === 'empty' ? '管理员可以一次录入连续字辈,系统会按世代拆分展示。' : poemState === 'no-permission' ? '普通成员可以查看字辈,但只有具备管理权限的成员可以维护。' : '请从家谱总览重新进入,或稍后再试。' }}</text>
|
||||
<view class="poem-action" @click="poemState === 'empty' ? openEditor() : poemState = 'list'">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>{{ poemState === 'empty' ? '开始录入' : '重新查看' }}</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>{{ poemState === 'empty' ? '开始录入' : '重新查看' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="feedbackVisible" class="poem-feedback">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" />
|
||||
<text>字辈预览已更新</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -78,6 +77,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const genealogyId = ref('')
|
||||
@@ -121,8 +121,6 @@ const savePoems = () => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.poem-page { position: relative; min-height: 100vh; overflow-x: hidden; background: $paper; }
|
||||
.poem-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
|
||||
.poem-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
|
||||
.poem-page__header { position: relative; z-index: 3; }
|
||||
.poem-panel { position: relative; z-index: 2; width: calc(100% - 32rpx); height: min(650px, calc((100vw - 16px) * 1.5)); margin: 18rpx auto 0; }
|
||||
.poem-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- 页面编号:N-01;用途:消息中心、已读操作、空态与失败状态。 -->
|
||||
<template><view class="notice-page" :class="{'notice-state--list':noticeState==='list','notice-state--empty':noticeState==='empty','notice-state--error':noticeState==='error'}"><image class="notice-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill"/><view class="notice-page__header"><PageHeader title="消息中心" action="全部已读" @action="markAllRead"/></view><view class="notice-content"><template v-if="noticeState==='list'"><view v-for="item in notices" :key="item.id" class="notice-card" @click="readNotice(item)"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>{{item.unread?'未读提醒':'已读'}} · {{item.time}}</text><text>{{item.title}}</text><text>{{item.content}}</text></view></view></template><view v-else class="notice-state-card"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>{{noticeState==='empty'?'暂时没有新消息':'消息中心暂不可用'}}</text><text>{{noticeState==='empty'?'家谱申请、审核结果和家族提醒会留在这里。':'请稍后重新进入,已读状态不会受到影响。'}}</text></view></view><view class="notice-action" @click="noticeState==='error'?noticeState='list':toReview()"><image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill"/><text>{{noticeState==='error'?'重新查看':'前往入谱审核'}}</text></view></view></view></template>
|
||||
<script setup>import{ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import PageHeader from'@/components/PageHeader.vue';import{genealogyContext}from'@/utils/genealogy-context.js';const genealogyId=ref('');const noticeState=ref('loading');const notices=ref([{id:1,title:'申请待审核',content:'汤志成申请加入汤氏家谱,请核实亲属关系。',time:'今天 10:28',unread:true},{id:2,title:'入谱申请已通过',content:'你申请加入汝南汤氏家谱的请求已通过。',time:'昨天 18:10',unread:false}]);onLoad(query=>{genealogyId.value=query.genealogyId||genealogyContext.getCurrentGenealogyId()||'';noticeState.value=query.state==='empty'?'empty':query.state==='error'?'error':'list'});const readNotice=item=>{item.unread=false};const markAllRead=()=>{notices.value.forEach(x=>x.unread=false);uni.showToast({title:'已全部标记为已读',icon:'none'})};const toReview=()=>uni.navigateTo({url:`/pages/genealogy/g10-application-review?genealogyId=${genealogyId.value}`})</script>
|
||||
<style scoped lang="scss">.notice-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.notice-page__paper{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none}.notice-page__header,.notice-content{position:relative;z-index:2}.notice-content{padding:24rpx}.notice-card,.notice-state-card{position:relative;width:100%;height:calc((100vw - 24px)*.34286);min-height:220rpx;margin-bottom:16rpx}.notice-card>image,.notice-state-card>image,.notice-action image{position:absolute;inset:0;width:100%;height:100%}.notice-card>view{position:absolute;inset:17% 9%;z-index:1}.notice-card text{display:block}.notice-card text:first-child{color:$brand-red;font-size:18rpx;letter-spacing:2rpx}.notice-card text:nth-child(2){margin-top:6rpx;color:$ink;font-family:STKaiti,KaiTi,serif;font-size:28rpx;font-weight:700}.notice-card text:last-child{margin-top:7rpx;color:$ink-muted;font-size:19rpx}.notice-state-card{margin-top:70rpx}.notice-state-card>view{position:absolute;inset:25% 12%;z-index:1;text-align:center}.notice-state-card text{display:block}.notice-state-card text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.notice-state-card text:last-child{margin-top:13rpx;color:$ink-muted;font-size:20rpx}.notice-action{position:relative;width:420rpx;height:76rpx;margin:20rpx auto 0}.notice-action text{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;height:100%;color:$ink;font-size:23rpx;font-weight:700}</style>
|
||||
<template><view class="notice-page" :class="{'notice-state--list':noticeState==='list','notice-state--empty':noticeState==='empty','notice-state--error':noticeState==='error'}"><ModulePageBackground module="notification"/><view class="notice-page__header"><PageHeader title="消息中心" action="全部已读" @action="markAllRead"/></view><view class="notice-content"><template v-if="noticeState==='list'"><view v-for="item in notices" :key="item.id" class="notice-card" @click="readNotice(item)"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>{{item.unread?'未读提醒':'已读'}} · {{item.time}}</text><text>{{item.title}}</text><text>{{item.content}}</text></view></view></template><view v-else class="notice-state-card"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>{{noticeState==='empty'?'暂时没有新消息':'消息中心暂不可用'}}</text><text>{{noticeState==='empty'?'家谱申请、审核结果和家族提醒会留在这里。':'请稍后重新进入,已读状态不会受到影响。'}}</text></view></view><AppButton type="secondary" :label="noticeState==='error'?'重新查看':'前往入谱审核'" @click="noticeState==='error'?noticeState='list':toReview()"/></view><AppToast :visible="toastVisible" :message="toastMessage"/></view></template>
|
||||
<script setup>import{onUnmounted,ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import AppButton from'@/components/AppButton.vue';import AppToast from'@/components/AppToast.vue';import ModulePageBackground from'@/components/ModulePageBackground.vue';import PageHeader from'@/components/PageHeader.vue';import{genealogyContext}from'@/utils/genealogy-context.js';const genealogyId=ref('');const noticeState=ref('loading');const toastVisible=ref(false);const toastMessage=ref('');let toastTimer=null;const notices=ref([{id:1,title:'申请待审核',content:'汤志成申请加入汤氏家谱,请核实亲属关系。',time:'今天 10:28',unread:true},{id:2,title:'入谱申请已通过',content:'你申请加入汝南汤氏家谱的请求已通过。',time:'昨天 18:10',unread:false}]);onLoad(query=>{genealogyId.value=query.genealogyId||genealogyContext.getCurrentGenealogyId()||'';noticeState.value=query.state==='empty'?'empty':query.state==='error'?'error':'list'});const readNotice=item=>{item.unread=false};const showToast=message=>{toastMessage.value=message;toastVisible.value=true;if(toastTimer)clearTimeout(toastTimer);toastTimer=setTimeout(()=>{toastVisible.value=false;toastTimer=null},1800)};const markAllRead=()=>{notices.value.forEach(x=>x.unread=false);showToast('已全部标记为已读')};const toReview=()=>uni.navigateTo({url:`/pages/genealogy/g10-application-review?genealogyId=${genealogyId.value}`});onUnmounted(()=>{if(toastTimer)clearTimeout(toastTimer)})</script>
|
||||
<style scoped lang="scss">.notice-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.notice-page__header,.notice-content{position:relative;z-index:2}.notice-content{padding:24rpx}.notice-card,.notice-state-card{position:relative;width:100%;height:calc((100vw - 24px)*.34286);min-height:220rpx;margin-bottom:16rpx}.notice-card>image,.notice-state-card>image{position:absolute;inset:0;width:100%;height:100%}.notice-card>view{position:absolute;inset:17% 9%;z-index:1}.notice-card text{display:block}.notice-card text:first-child{color:$brand-red;font-size:18rpx;letter-spacing:2rpx}.notice-card text:nth-child(2){margin-top:6rpx;color:$ink;font-family:STKaiti,KaiTi,serif;font-size:28rpx;font-weight:700}.notice-card text:last-child{margin-top:7rpx;color:#62584c;font-size:22rpx;font-weight:500}.notice-state-card{margin-top:70rpx}.notice-state-card>view{position:absolute;inset:25% 12%;z-index:1;text-align:center}.notice-state-card text{display:block}.notice-state-card text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.notice-state-card text:last-child{margin-top:13rpx;color:#62584c;font-size:22rpx}.notice-content>.app-button{margin:20rpx auto 0}</style>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- 页面编号:M-01;用途:个人中心首页、提醒与服务导航。 -->
|
||||
<template><view class="profile-page" :class="{'profile-state--ready':profileState==='ready','profile-state--error':profileState==='error'}"><image class="profile-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill"/><view class="profile-page__header"><PageHeader title="我的" action="资料" @action="toProfile"/></view><view class="profile-content"><view v-if="profileState==='ready'" class="profile-panel"><image class="profile-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill"/><view class="profile-panel__body"><view class="profile-heading"><image src="/static/assets/modules/genealogy/transparent/current-seal-frame.png" mode="scaleToFill"/><view><text>汤文清</text><text>139****6421 · 家谱成员</text></view></view><view class="profile-todo" @click="toNotifications"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>待你处理</text><text>2 条家谱提醒与审核通知</text></view></view><view v-for="item in menuItems" :key="item.label" class="profile-menu" @click="openItem(item)"><image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill"/><view><text>{{item.label}}</text><text>{{item.note}}</text></view><text>查看</text></view></view></view><view v-else class="profile-error"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>个人资料暂不可用</text><text>请稍后重新进入,账号和家谱资料不会受到影响。</text></view></view></view><AppTabbar active="profile"/></view></template>
|
||||
<script setup>import{ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import PageHeader from'@/components/PageHeader.vue';import AppTabbar from'@/components/AppTabbar.vue';const profileState=ref('ready');const menuItems=[{label:'账号与安全',note:'密码、手机与设备',url:'/pages/profile/m03-security-settings'},{label:'帮助与反馈',note:'使用说明与问题反馈',url:'/pages/profile/m06-help-center'},{label:'关于家谱',note:'协议、隐私与版本',url:'/pages/profile/m10-about-settings'}];onLoad(query=>{profileState.value=query.state==='error'?'error':'ready'});const toProfile=()=>uni.navigateTo({url:'/pages/profile/m02-edit-profile'});const toNotifications=()=>uni.navigateTo({url:'/pages/notification/n01-message-center'});const openItem=item=>uni.navigateTo({url:item.url})</script>
|
||||
<style scoped lang="scss">.profile-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.profile-page__paper{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none}.profile-page__header,.profile-content{position:relative;z-index:2}.profile-content{padding:18rpx 24rpx 190rpx}.profile-panel{position:relative;width:100%;height:min(650px,calc((100vw - 24px)*1.5))}.profile-panel__skin{position:absolute;inset:0;width:100%;height:100%}.profile-panel__body{position:absolute;inset:7% 8%}.profile-heading{display:flex;align-items:center;gap:18rpx}.profile-heading>image{width:76rpx;height:98rpx}.profile-heading text{display:block}.profile-heading text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:35rpx;font-weight:700}.profile-heading text:last-child{margin-top:7rpx;color:$ink-muted;font-size:19rpx}.profile-todo{position:relative;height:124rpx;margin-top:18rpx}.profile-todo>image,.profile-menu>image,.profile-error>image{position:absolute;inset:0;width:100%;height:100%}.profile-todo>view{position:absolute;inset:22% 9%;z-index:1}.profile-todo text{display:block}.profile-todo text:first-child{color:$brand-red;font-size:22rpx;font-weight:700}.profile-todo text:last-child{margin-top:7rpx;color:$ink-muted;font-size:19rpx}.profile-menu{position:relative;height:76rpx;margin-top:11rpx}.profile-menu>view{position:absolute;top:14rpx;left:22rpx;z-index:1}.profile-menu>view text{display:block}.profile-menu>view text:first-child{color:$ink;font-size:21rpx;font-weight:700}.profile-menu>view text:last-child{margin-top:3rpx;color:$ink-muted;font-size:17rpx}.profile-menu>text{position:absolute;top:29rpx;right:22rpx;z-index:1;color:$brand-red;font-size:18rpx}.profile-error{position:relative;height:230rpx;margin-top:70rpx}.profile-error>view{position:absolute;inset:27% 12%;z-index:1;text-align:center}.profile-error text{display:block}.profile-error text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.profile-error text:last-child{margin-top:13rpx;color:$ink-muted;font-size:20rpx}</style>
|
||||
<template><view class="profile-page" :class="{'profile-state--ready':profileState==='ready','profile-state--error':profileState==='error'}"><ModulePageBackground module="profile"/><view class="profile-page__header"><PageHeader title="我的" action="资料" @action="toProfile"/></view><view class="profile-content"><view v-if="profileState==='ready'" class="profile-panel"><image class="profile-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill"/><view class="profile-panel__body"><view class="profile-heading"><image src="/static/assets/modules/genealogy/transparent/current-seal-frame.png" mode="scaleToFill"/><view><text>汤文清</text><text>139****6421 · 家谱成员</text></view></view><view class="profile-todo" @click="toNotifications"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>待你处理</text><text>2 条家谱提醒与审核通知</text></view></view><view v-for="item in menuItems" :key="item.label" class="profile-menu" @click="openItem(item)"><image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill"/><view><text>{{item.label}}</text><text>{{item.note}}</text></view><text>查看</text></view></view></view><view v-else class="profile-error"><image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill"/><view><text>个人资料暂不可用</text><text>请稍后重新进入,账号和家谱资料不会受到影响。</text></view></view></view><AppTabbar active="profile"/></view></template>
|
||||
<script setup>import{ref}from'vue';import{onLoad}from'@dcloudio/uni-app';import ModulePageBackground from'@/components/ModulePageBackground.vue';import PageHeader from'@/components/PageHeader.vue';import AppTabbar from'@/components/AppTabbar.vue';const profileState=ref('ready');const menuItems=[{label:'账号与安全',note:'密码、手机与设备',url:'/pages/profile/m03-security-settings'},{label:'帮助与反馈',note:'使用说明与问题反馈',url:'/pages/profile/m06-help-center'},{label:'关于家谱',note:'协议、隐私与版本',url:'/pages/profile/m10-about-settings'}];onLoad(query=>{profileState.value=query.state==='error'?'error':'ready'});const toProfile=()=>uni.navigateTo({url:'/pages/profile/m02-edit-profile'});const toNotifications=()=>uni.navigateTo({url:'/pages/notification/n01-message-center'});const openItem=item=>uni.navigateTo({url:item.url})</script>
|
||||
<style scoped lang="scss">.profile-page{position:relative;min-height:100vh;overflow:hidden;background:$paper}.profile-page__header,.profile-content{position:relative;z-index:2}.profile-content{padding:18rpx 24rpx 190rpx}.profile-panel{position:relative;width:100%;height:min(650px,calc((100vw - 24px)*1.5))}.profile-panel__skin{position:absolute;inset:0;width:100%;height:100%}.profile-panel__body{position:absolute;inset:7% 8%}.profile-heading{display:flex;align-items:center;gap:18rpx}.profile-heading>image{width:76rpx;height:98rpx}.profile-heading text{display:block}.profile-heading text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:35rpx;font-weight:700}.profile-heading text:last-child{margin-top:7rpx;color:$ink-muted;font-size:19rpx}.profile-todo{position:relative;height:124rpx;margin-top:18rpx}.profile-todo>image,.profile-menu>image,.profile-error>image{position:absolute;inset:0;width:100%;height:100%}.profile-todo>view{position:absolute;inset:22% 9%;z-index:1}.profile-todo text{display:block}.profile-todo text:first-child{color:$brand-red;font-size:22rpx;font-weight:700}.profile-todo text:last-child{margin-top:7rpx;color:$ink-muted;font-size:19rpx}.profile-menu{position:relative;height:76rpx;margin-top:11rpx}.profile-menu>view{position:absolute;top:14rpx;left:22rpx;z-index:1}.profile-menu>view text{display:block}.profile-menu>view text:first-child{color:$ink;font-size:21rpx;font-weight:700}.profile-menu>view text:last-child{margin-top:3rpx;color:$ink-muted;font-size:17rpx}.profile-menu>text{position:absolute;top:29rpx;right:22rpx;z-index:1;color:$brand-red;font-size:18rpx}.profile-error{position:relative;height:230rpx;margin-top:70rpx}.profile-error>view{position:absolute;inset:27% 12%;z-index:1;text-align:center}.profile-error text{display:block}.profile-error text:first-child{color:$ink;font-family:STKaiti,KaiTi,serif;font-size:30rpx;font-weight:700}.profile-error text:last-child{margin-top:13rpx;color:$ink-muted;font-size:20rpx}</style>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'tree-state--empty': treeState === 'empty',
|
||||
'tree-state--error': treeState === 'error'
|
||||
}">
|
||||
<image class="tree-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<ModulePageBackground module="tree" />
|
||||
<view class="tree-page__header"><PageHeader title="世系树" action="成员目录" @action="toDirectory" /></view>
|
||||
|
||||
<view class="tree-toolbar">
|
||||
@@ -40,7 +40,7 @@
|
||||
<text class="tree-state-card__title">{{ stateCopy.title }}</text>
|
||||
<text class="tree-state-card__copy">{{ stateCopy.copy }}</text>
|
||||
<view class="tree-state-card__action" @click="handleStateAction">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" />
|
||||
<text>{{ stateCopy.action }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -55,10 +55,10 @@
|
||||
</view>
|
||||
<view class="sheet-actions">
|
||||
<view class="sheet-action sheet-member-action" @click="toMember">
|
||||
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" /><text>查看资料</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png" mode="aspectFit" /><text>查看资料</text>
|
||||
</view>
|
||||
<view class="sheet-action" @click="toAddRelative">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>添加亲属</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>添加亲属</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -68,6 +68,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import ModulePageBackground from '@/components/ModulePageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
import { genealogyContext } from '@/utils/genealogy-context.js'
|
||||
|
||||
@@ -122,7 +123,6 @@ const toAddRelative = () => uni.navigateTo({ url: `/pages/tree/t04-add-relative?
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tree-page { position: relative; height: 100vh; overflow: hidden; background: $paper; }
|
||||
.tree-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
|
||||
.tree-page__header, .tree-toolbar, .tree-scroll, .member-sheet { position: relative; z-index: 2; }
|
||||
.tree-toolbar { display: flex; align-items: center; justify-content: space-between; padding: 18rpx 28rpx 14rpx; }
|
||||
.tree-toolbar__title text { display: block; }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- 页面编号:T-03;用途:成员档案详情与失败状态(页面设计阶段使用本地模拟数据)。 -->
|
||||
<template>
|
||||
<view class="member-page" :class="{ 'member-state--detail': memberState === 'detail', 'member-state--error': memberState === 'error' }">
|
||||
<image class="member-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<ModulePageBackground module="tree" />
|
||||
<view class="member-page__header"><PageHeader title="成员档案" :action="memberState === 'detail' ? '编辑' : ''" @action="toEdit" /></view>
|
||||
<view class="member-panel">
|
||||
<image class="member-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill" />
|
||||
@@ -19,12 +19,12 @@
|
||||
<text>长子 · 汤正国</text><text>次子 · 汤正华</text>
|
||||
</view>
|
||||
<view class="member-profile-action" @click="toEdit">
|
||||
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>完善成员档案</text>
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>完善成员档案</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="member-error">
|
||||
<text>成员档案暂不可用</text><text>请从世系树重新选择成员,当前没有可展示的个人资料。</text>
|
||||
<view class="member-profile-action" @click="toTree"><image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>返回世系树</text></view>
|
||||
<view class="member-profile-action" @click="toTree"><image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="aspectFit" /><text>返回世系树</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -32,6 +32,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import ModulePageBackground from '@/components/ModulePageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
import { genealogyContext } from '@/utils/genealogy-context.js'
|
||||
const genealogyId = ref('')
|
||||
@@ -55,7 +56,6 @@ const toTree = () => uni.navigateBack()
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.member-page { position: relative; min-height: 100vh; overflow: hidden; background: $paper; }
|
||||
.member-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
|
||||
.member-page__header { position: relative; z-index: 3; }
|
||||
.member-panel { position: relative; z-index: 2; width: calc(100% - 32rpx); height: min(650px, calc((100vw - 16px) * 1.5)); margin: 18rpx auto 0; }
|
||||
.member-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- 页面编号:T-07;用途:成员目录、搜索、空态与失败状态。 -->
|
||||
<template>
|
||||
<view class="directory-page" :class="{ 'directory-state--list': directoryState === 'list', 'directory-state--empty': directoryState === 'empty', 'directory-state--error': directoryState === 'error' }">
|
||||
<image class="directory-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<ModulePageBackground module="tree" />
|
||||
<view class="directory-page__header"><PageHeader title="成员目录" /></view>
|
||||
<view class="directory-search">
|
||||
<image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill" />
|
||||
@@ -26,6 +26,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import ModulePageBackground from '@/components/ModulePageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
const genealogyId = ref('')
|
||||
const keyword = ref('')
|
||||
@@ -46,7 +47,6 @@ const openMember = (item) => uni.navigateTo({ url: `/pages/tree/t03-member-profi
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.directory-page { position: relative; min-height: 100vh; overflow: hidden; background: $paper; }
|
||||
.directory-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
|
||||
.directory-page__header, .directory-search, .directory-content { position: relative; z-index: 2; }
|
||||
.directory-search { width: calc(100% - 48rpx); height: 84rpx; margin: 20rpx auto 0; }
|
||||
.directory-search image { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
'member-status--deceased': statusState === 'deceased',
|
||||
'member-status--forbidden': statusState === 'forbidden'
|
||||
}">
|
||||
<image class="member-status-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
|
||||
<ModulePageBackground module="tree" />
|
||||
<view class="member-status-page__header"><PageHeader title="成员状态" /></view>
|
||||
<view class="status-tabs">
|
||||
<view v-for="item in tabs" :key="item.value" class="status-tab" @click="statusState = item.value">
|
||||
<image :src="statusState === item.value ? '/static/assets/foundation/opaque/a01-primary-button.png' : '/static/assets/foundation/opaque/a01-secondary-button.png'" mode="scaleToFill" />
|
||||
<image :src="statusState === item.value ? '/static/assets/foundation/transparent/a01-scroll-primary-v3.png' : '/static/assets/foundation/transparent/a01-scroll-secondary-v3.png'" mode="aspectFit" />
|
||||
<text :class="{ 'status-tab__text--active': statusState === item.value }">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -31,6 +31,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import ModulePageBackground from '@/components/ModulePageBackground.vue'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
const statusState = ref('privacy')
|
||||
const tabs = [{ value: 'privacy', label: '隐私' }, { value: 'deceased', label: '纪念' }, { value: 'forbidden', label: '无权限' }]
|
||||
@@ -44,7 +45,6 @@ onLoad((query) => { statusState.value = states[query.state] ? query.state : 'pri
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.member-status-page { position: relative; min-height: 100vh; overflow: hidden; background: $paper; }
|
||||
.member-status-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
|
||||
.member-status-page__header, .status-tabs, .status-card, .status-guidance { position: relative; z-index: 2; }
|
||||
.status-tabs { display: flex; gap: 10rpx; padding: 22rpx 24rpx 0; }
|
||||
.status-tab { position: relative; width: calc(33.333% - 7rpx); height: 62rpx; }
|
||||
|
||||
Reference in New Issue
Block a user