修改完成待测试
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
class="page-shell genealogy-index"
|
||||
:class="{ 'genealogy-index--split': isListLayout }"
|
||||
>
|
||||
<GenealogyPageBackground />
|
||||
<GenealogyPageBackground tone="light" />
|
||||
<PageHeader
|
||||
root
|
||||
notice
|
||||
@@ -56,69 +56,6 @@
|
||||
</view>
|
||||
|
||||
<template v-else-if="hasGenealogies">
|
||||
<view class="genealogy-fixed-zone">
|
||||
<view class="current-slip" @click="openSwitcher">
|
||||
<view class="current-summary">
|
||||
<view class="current-seal">
|
||||
<text class="current-seal-title">家谱</text>
|
||||
</view>
|
||||
<text class="current-name">{{ currentGenealogy.name }}</text>
|
||||
<text class="current-switch-copy">切换</text>
|
||||
</view>
|
||||
<view class="current-info-divider"></view>
|
||||
<view class="current-meta">
|
||||
<view class="current-meta-item current-meta-item--location">
|
||||
<image
|
||||
class="current-meta-icon"
|
||||
src="/static/assets/foundation/transparent/meta-location.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="current-meta-item-text">{{
|
||||
currentGenealogy.location
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="current-meta-item current-meta-item--members">
|
||||
<image
|
||||
class="current-meta-icon"
|
||||
src="/static/assets/foundation/transparent/meta-member.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="current-meta-item-text"
|
||||
>{{ currentGenealogy.memberCount }} 位成员</text
|
||||
>
|
||||
</view>
|
||||
<view class="current-meta-item current-meta-item--role">
|
||||
<image
|
||||
class="current-meta-icon"
|
||||
src="/static/assets/foundation/transparent/meta-admin.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<text class="current-meta-item-text">{{
|
||||
currentRoleLabel
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="shortcut-grid">
|
||||
<view
|
||||
v-for="shortcut in visibleShortcuts"
|
||||
:key="shortcut.key"
|
||||
class="shortcut-item"
|
||||
@click="openShortcut(shortcut.key)"
|
||||
>
|
||||
<image class="shortcut-icon" :src="shortcut.icon" mode="aspectFit" />
|
||||
<text class="shortcut-label">{{ shortcut.label }}</text>
|
||||
</view>
|
||||
</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
|
||||
@@ -126,8 +63,13 @@
|
||||
@scroll="handleListScroll"
|
||||
>
|
||||
<view class="genealogy-lower">
|
||||
<view class="genealogy-list-toolbar">
|
||||
<view class="section-heading genealogy-list-heading">
|
||||
<text>{{ managedGenealogies.length ? "我管理的" : "我加入的" }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="managedGenealogies.length" class="list-section">
|
||||
<view class="section-heading"><text>我管理的</text></view>
|
||||
<GenealogyCard
|
||||
v-for="genealogy in managedGenealogies"
|
||||
:key="genealogy.id"
|
||||
@@ -139,7 +81,7 @@
|
||||
</view>
|
||||
|
||||
<view v-if="memberGenealogies.length" class="list-section">
|
||||
<view class="section-heading"><text>我加入的</text></view>
|
||||
<view v-if="managedGenealogies.length" class="section-heading"><text>我加入的</text></view>
|
||||
<GenealogyCard
|
||||
v-for="genealogy in memberGenealogies"
|
||||
:key="genealogy.id"
|
||||
@@ -171,85 +113,33 @@
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="featured-media-section">
|
||||
<view class="featured-media-heading">
|
||||
<view>
|
||||
<text class="featured-media-heading__title">宣传视频</text>
|
||||
<text class="featured-media-heading__copy">家谱文化与使用介绍</text>
|
||||
</view>
|
||||
<button class="featured-media-more" @click="openPlatformVideos">
|
||||
查看更多
|
||||
</button>
|
||||
</view>
|
||||
<view v-if="featuredVideoState === 'loading'" class="featured-media-state">
|
||||
<AppLoading text="正在读取宣传视频" />
|
||||
</view>
|
||||
<view v-else-if="featuredVideoState === 'error'" class="featured-media-state">
|
||||
<text>宣传视频暂时无法显示</text>
|
||||
<button class="featured-media-retry" @click="loadFeaturedVideos">重新加载</button>
|
||||
</view>
|
||||
<view v-else-if="featuredVideos.length" class="featured-media-grid">
|
||||
<view
|
||||
v-for="video in featuredVideos"
|
||||
:key="video.id"
|
||||
class="featured-media-card"
|
||||
>
|
||||
<view
|
||||
v-if="video.coverFile?.accessUrl"
|
||||
class="featured-media-cover-button"
|
||||
role="button"
|
||||
:aria-label="`播放${video.title}`"
|
||||
hover-class="action-hover"
|
||||
@click="openFeaturedVideo(video)"
|
||||
>
|
||||
<image
|
||||
class="featured-media-cover"
|
||||
:src="video.coverFile.accessUrl"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="featured-media-play" aria-hidden="true"></view>
|
||||
</view>
|
||||
<video
|
||||
v-else
|
||||
class="featured-media-video"
|
||||
:src="video.videoFile.accessUrl"
|
||||
controls
|
||||
object-fit="cover"
|
||||
/>
|
||||
<button class="featured-media-title" @click="openFeaturedVideo(video)">
|
||||
{{ video.title }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="featured-media-state featured-media-state--empty">
|
||||
<text>暂时没有推荐视频</text>
|
||||
<button class="featured-media-more featured-media-more--empty" @click="openPlatformVideos">
|
||||
查看全部视频
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="create-action" @click="openAddDialog">
|
||||
<view class="create-action" hover-class="action-hover" @click="openAddDialog">
|
||||
<image
|
||||
class="create-cloud"
|
||||
src="/static/assets/modules/genealogy/transparent/create-cloud.png"
|
||||
mode="aspectFit"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<image
|
||||
class="create-icon"
|
||||
src="/static/assets/modules/genealogy/transparent/add.png"
|
||||
mode="aspectFit"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<text>添加家谱</text>
|
||||
<image
|
||||
class="create-cloud create-cloud--right"
|
||||
src="/static/assets/modules/genealogy/transparent/create-cloud.png"
|
||||
mode="aspectFit"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</view>
|
||||
<AppPromotionStrip placement="home_bottom" title="家谱服务推荐" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
<HomeAdvertisementPanel
|
||||
class="home-content-fixed"
|
||||
@open="openContentHome"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<view v-else class="genealogy-empty-state">
|
||||
@@ -284,12 +174,6 @@
|
||||
>
|
||||
<text class="empty-create-action__copy">创建家谱</text>
|
||||
</view>
|
||||
<AppButton
|
||||
block
|
||||
type="secondary"
|
||||
label="观看宣传视频"
|
||||
@click="openPlatformVideos"
|
||||
/>
|
||||
<text class="empty-create-note"
|
||||
>确认没有现有家谱后再创建,避免重复建谱</text
|
||||
>
|
||||
@@ -322,7 +206,7 @@
|
||||
@saved="applySavedGenealogyOrder"
|
||||
/>
|
||||
|
||||
<AppTabbar active="genealogy" />
|
||||
<AppTabbar active="genealogy" tone="light" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -332,9 +216,9 @@ import { onBackPress, onLoad, onShow, onUnload } from "@dcloudio/uni-app";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import AppTabbar from "@/components/AppTabbar.vue";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppPromotionStrip from "@/components/AppPromotionStrip.vue";
|
||||
import GenealogyAddDialog from "@/components/genealogy/AddDialog.vue";
|
||||
import GenealogyCard from "@/components/genealogy/Card.vue";
|
||||
import HomeAdvertisementPanel from "@/components/genealogy/HomeAdvertisementPanel.vue";
|
||||
import GenealogyOrderDialog from "@/components/genealogy/OrderDialog.vue";
|
||||
import GenealogyPageBackground from "@/components/genealogy/PageBackground.vue";
|
||||
import GenealogySwitcherDialog from "@/components/genealogy/SwitcherDialog.vue";
|
||||
@@ -345,12 +229,11 @@ import {
|
||||
} from "@/services/api/request-controller.js";
|
||||
import { getRequestErrorMessage } from "@/services/api/request-error-message.js";
|
||||
import { genealogyApi } from "@/services/api/genealogy-service.js";
|
||||
import { PLATFORM_VIDEO_PLACEMENT } from "@/services/api/family-media-contract.js";
|
||||
import { genealogyCapabilityApi } from "@/services/api/genealogy-capability-service.js";
|
||||
import { notificationApi } from "@/services/api/notification-service.js";
|
||||
import { genealogyContext } from "@/utils/genealogy/context.js";
|
||||
import {
|
||||
consumeNavigationResult,
|
||||
goRoot,
|
||||
handleBackPress,
|
||||
openPage,
|
||||
runBackGuard,
|
||||
@@ -372,18 +255,14 @@ const listScrollCommand = ref(0);
|
||||
const currentListScrollTop = ref(0);
|
||||
const unreadCount = ref(0);
|
||||
const creationQuota = ref(null);
|
||||
const featuredVideos = ref([]);
|
||||
const featuredVideoState = ref("loading");
|
||||
const genealogyListRequestController = createRequestController();
|
||||
const unreadRequestController = createRequestController();
|
||||
const quotaRequestController = createRequestController();
|
||||
const featuredVideoRequestController = createRequestController();
|
||||
// uni-app 的 abort 与成功回调可能在同一事件循环竞争。控制器负责取消任务,
|
||||
// generation 再阻止已经迟到的旧响应覆盖新页面状态,两层保护不能互相替代。
|
||||
let genealogyLoadGeneration = 0;
|
||||
let unreadLoadGeneration = 0;
|
||||
let quotaLoadGeneration = 0;
|
||||
let featuredVideoLoadGeneration = 0;
|
||||
let pageActive = true;
|
||||
let skipNextShowRefresh = true;
|
||||
|
||||
@@ -485,37 +364,11 @@ const loadQuota = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadFeaturedVideos = async () => {
|
||||
const generation = ++featuredVideoLoadGeneration;
|
||||
featuredVideoRequestController.abort();
|
||||
featuredVideoState.value = "loading";
|
||||
try {
|
||||
const rows = await genealogyCapabilityApi.getPlatformVideos(
|
||||
PLATFORM_VIDEO_PLACEMENT.HOME_FEATURED,
|
||||
{ requestController: featuredVideoRequestController },
|
||||
);
|
||||
if (!pageActive || generation !== featuredVideoLoadGeneration) return;
|
||||
featuredVideos.value = rows.slice(0, 2);
|
||||
featuredVideoState.value = "ready";
|
||||
} catch (error) {
|
||||
if (
|
||||
!pageActive ||
|
||||
generation !== featuredVideoLoadGeneration ||
|
||||
isRequestCancelled(error)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
featuredVideos.value = [];
|
||||
featuredVideoState.value = "error";
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((query) => {
|
||||
requestedGenealogyId.value = String(query?.genealogyId || "");
|
||||
loadGenealogies();
|
||||
loadUnreadCount();
|
||||
loadQuota();
|
||||
loadFeaturedVideos();
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
@@ -527,7 +380,6 @@ onShow(() => {
|
||||
) {
|
||||
requestedGenealogyId.value = navigationResult.entityId;
|
||||
loadGenealogies();
|
||||
loadFeaturedVideos();
|
||||
return;
|
||||
}
|
||||
if (skipNextShowRefresh) {
|
||||
@@ -537,7 +389,6 @@ onShow(() => {
|
||||
loadGenealogies();
|
||||
loadUnreadCount();
|
||||
loadQuota();
|
||||
loadFeaturedVideos();
|
||||
});
|
||||
|
||||
onUnload(() => {
|
||||
@@ -545,11 +396,9 @@ onUnload(() => {
|
||||
genealogyLoadGeneration += 1;
|
||||
unreadLoadGeneration += 1;
|
||||
quotaLoadGeneration += 1;
|
||||
featuredVideoLoadGeneration += 1;
|
||||
genealogyListRequestController.abort();
|
||||
unreadRequestController.abort();
|
||||
quotaRequestController.abort();
|
||||
featuredVideoRequestController.abort();
|
||||
});
|
||||
|
||||
const hasGenealogies = computed(() => genealogies.value.length > 0);
|
||||
@@ -572,40 +421,6 @@ const currentGenealogy = computed(
|
||||
(genealogy) => genealogy.id === selectedGenealogyId.value,
|
||||
) || null,
|
||||
);
|
||||
const canManageCurrentGenealogy = computed(
|
||||
() => currentGenealogy.value?.canManage === true,
|
||||
);
|
||||
const currentRoleLabel = computed(() =>
|
||||
canManageCurrentGenealogy.value ? "管理员" : "成员",
|
||||
);
|
||||
|
||||
const shortcuts = [
|
||||
{
|
||||
key: "tree",
|
||||
label: "世系图",
|
||||
icon: "/static/assets/modules/genealogy/transparent/shortcut-tree.png",
|
||||
},
|
||||
{
|
||||
key: "members",
|
||||
label: "成员",
|
||||
icon: "/static/assets/modules/genealogy/transparent/shortcut-members.png",
|
||||
},
|
||||
{
|
||||
key: "poem",
|
||||
label: "字辈诗",
|
||||
icon: "/static/assets/modules/genealogy/transparent/shortcut-generation-poem.png",
|
||||
},
|
||||
{
|
||||
key: "applications",
|
||||
label: "申请审核",
|
||||
icon: "/static/assets/modules/genealogy/transparent/shortcut-application.png",
|
||||
},
|
||||
];
|
||||
const visibleShortcuts = computed(() =>
|
||||
canManageCurrentGenealogy.value
|
||||
? shortcuts
|
||||
: shortcuts.filter((shortcut) => shortcut.key !== "applications"),
|
||||
);
|
||||
|
||||
const openGenealogy = (genealogy) =>
|
||||
openPage("G05", { genealogyId: String(genealogy.id) }, "G01").then(
|
||||
@@ -644,21 +459,7 @@ const openSwitcher = () => {
|
||||
const closeSwitcher = () => {
|
||||
switcherVisible.value = false;
|
||||
};
|
||||
const openPlatformVideos = () =>
|
||||
openPage(
|
||||
"F11",
|
||||
{ placement: PLATFORM_VIDEO_PLACEMENT.VIDEO_CENTER },
|
||||
"G01",
|
||||
);
|
||||
const openFeaturedVideo = (video) =>
|
||||
openPage(
|
||||
"F11",
|
||||
{
|
||||
placement: PLATFORM_VIDEO_PLACEMENT.HOME_FEATURED,
|
||||
videoId: String(video.id),
|
||||
},
|
||||
"G01",
|
||||
);
|
||||
const openContentHome = () => goRoot("F01");
|
||||
const openOrderDialog = () => {
|
||||
if (genealogies.value.length < 2) return;
|
||||
orderDialogVisible.value = true;
|
||||
@@ -714,17 +515,6 @@ const retryGenealogyLoad = () => {
|
||||
loadGenealogies();
|
||||
};
|
||||
|
||||
const openShortcut = (shortcutKey) => {
|
||||
if (!currentGenealogy.value) return;
|
||||
const genealogyId = String(currentGenealogy.value.id);
|
||||
const actions = {
|
||||
tree: () => openPage("T01", { genealogyId }, "G01"),
|
||||
members: () => openPage("G13", { genealogyId }, "G01"),
|
||||
poem: () => openPage("G12", { genealogyId }, "G01"),
|
||||
applications: () => openPage("G10", { genealogyId }, "G01"),
|
||||
};
|
||||
return actions[shortcutKey]?.();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -735,12 +525,12 @@ const openShortcut = (shortcutKey) => {
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: #f9f6ef;
|
||||
background: #faf8f3;
|
||||
}
|
||||
|
||||
.genealogy-content {
|
||||
z-index: 1;
|
||||
padding: 24rpx 32rpx calc(176rpx + env(safe-area-inset-bottom));
|
||||
padding: 0 32rpx calc(176rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.genealogy-index--split {
|
||||
@@ -760,10 +550,6 @@ const openShortcut = (shortcutKey) => {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.genealogy-fixed-zone {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.genealogy-list-scroll {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
@@ -771,151 +557,25 @@ const openShortcut = (shortcutKey) => {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.current-slip {
|
||||
@include adaptive-genealogy-current-slip;
|
||||
display: block;
|
||||
min-height: 300rpx;
|
||||
padding: 30rpx 34rpx 28rpx;
|
||||
.genealogy-list-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 70rpx;
|
||||
padding: 0 4rpx 2rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.current-seal {
|
||||
display: flex;
|
||||
width: 80rpx;
|
||||
height: 128rpx;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 24rpx;
|
||||
background: url("/static/assets/modules/genealogy/transparent/current-seal-frame.png")
|
||||
center / contain no-repeat;
|
||||
color: #fff7e7;
|
||||
}
|
||||
.current-seal-title {
|
||||
color: #fff7e7;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(17px, 32rpx, 22px);
|
||||
font-weight: 700;
|
||||
letter-spacing: 2rpx;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.current-summary {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
}
|
||||
.current-name {
|
||||
min-width: 0;
|
||||
.genealogy-list-heading {
|
||||
flex: 1;
|
||||
color: $ink;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(18px, 34rpx, 24px);
|
||||
font-weight: 700;
|
||||
line-height: 1.25;
|
||||
overflow: hidden;
|
||||
overflow-wrap: anywhere;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
.current-switch-copy {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 16rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border: 1rpx solid rgba(159, 23, 15, 0.34);
|
||||
border-radius: 999rpx;
|
||||
color: $brand-red;
|
||||
font-size: clamp(15px, 25rpx, 18px);
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.current-info-divider {
|
||||
width: 100%;
|
||||
height: 1rpx;
|
||||
margin: 18rpx 0 16rpx;
|
||||
background: rgba(181, 138, 75, 0.48);
|
||||
}
|
||||
|
||||
.current-meta {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
column-gap: 28rpx;
|
||||
row-gap: 10rpx;
|
||||
margin-top: 0;
|
||||
color: #62584c;
|
||||
font-size: clamp(15px, 25rpx, 18px);
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.current-meta-item {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
|
||||
.current-meta-item-text {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
.current-meta-item--location {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.current-meta-item--role {
|
||||
justify-self: end;
|
||||
}
|
||||
.current-meta-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
flex: 0 0 auto;
|
||||
margin-right: 8rpx;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.shortcut-grid {
|
||||
display: flex;
|
||||
min-height: 168rpx;
|
||||
align-items: center;
|
||||
margin-top: 18rpx;
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
|
||||
.shortcut-item {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.shortcut-icon {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
.shortcut-label {
|
||||
width: 100%;
|
||||
margin-top: 10rpx;
|
||||
color: $ink;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(16px, 27rpx, 19px);
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.section-divider {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 30rpx;
|
||||
margin: 4rpx 0 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.genealogy-lower {
|
||||
padding: 12rpx 0 36rpx;
|
||||
padding: 0 0 24rpx;
|
||||
}
|
||||
|
||||
.list-section {
|
||||
margin-top: 16rpx;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
@@ -951,7 +611,7 @@ const openShortcut = (shortcutKey) => {
|
||||
padding: 24rpx 28rpx;
|
||||
border: 1rpx solid rgba(149, 103, 49, 0.24);
|
||||
border-radius: 14rpx;
|
||||
background: rgba(255, 250, 240, 0.72);
|
||||
background: rgba(255, 253, 249, 0.84);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -978,164 +638,17 @@ const openShortcut = (shortcutKey) => {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.featured-media-section {
|
||||
margin: 0 0 24rpx;
|
||||
padding: 26rpx 24rpx;
|
||||
border: 1rpx solid rgba(149, 103, 49, 0.24);
|
||||
border-radius: 14rpx;
|
||||
background: rgba(255, 250, 240, 0.72);
|
||||
}
|
||||
|
||||
.featured-media-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.featured-media-heading__title,
|
||||
.featured-media-heading__copy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.featured-media-heading__title {
|
||||
color: #5c4330;
|
||||
font-size: clamp(16px, 28rpx, 20px);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.featured-media-heading__copy {
|
||||
margin-top: 8rpx;
|
||||
color: #8a7564;
|
||||
font-size: clamp(14px, 23rpx, 17px);
|
||||
}
|
||||
|
||||
.featured-media-more,
|
||||
.featured-media-retry,
|
||||
.featured-media-title {
|
||||
min-height: var(--app-touch-min);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.featured-media-more::after,
|
||||
.featured-media-retry::after,
|
||||
.featured-media-title::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.featured-media-more,
|
||||
.featured-media-retry {
|
||||
flex: 0 0 auto;
|
||||
color: $brand-red;
|
||||
font-size: clamp(13px, 22rpx, 16px);
|
||||
}
|
||||
|
||||
.featured-media-state {
|
||||
display: flex;
|
||||
min-height: 176rpx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
color: $ink-muted;
|
||||
font-size: clamp(14px, 23rpx, 17px);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.featured-media-state--empty {
|
||||
min-height: 138rpx;
|
||||
}
|
||||
|
||||
.featured-media-more--empty {
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.featured-media-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16rpx;
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
|
||||
.featured-media-card {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.featured-media-cover-button,
|
||||
.featured-media-video {
|
||||
width: 100%;
|
||||
height: 176rpx;
|
||||
border-radius: 10rpx;
|
||||
background: #1f1b17;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.featured-media-cover-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.featured-media-cover {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.featured-media-play {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
background: rgba(45, 29, 19, 0.62);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.featured-media-play::after {
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 5rpx;
|
||||
border-top: 10rpx solid transparent;
|
||||
border-bottom: 10rpx solid transparent;
|
||||
border-left: 16rpx solid #fff;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.featured-media-title {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-top: 8rpx;
|
||||
color: $ink;
|
||||
font-size: clamp(14px, 24rpx, 17px);
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.create-action {
|
||||
display: flex;
|
||||
width: 350rpx;
|
||||
min-height: 96rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
font-size: clamp(17px, 30rpx, 22px);
|
||||
}
|
||||
|
||||
.create-action {
|
||||
width: 350rpx;
|
||||
margin: 32rpx auto 0;
|
||||
margin: 8rpx auto 24rpx;
|
||||
border: 2rpx solid $brand-red;
|
||||
border-radius: 48rpx;
|
||||
background: rgba(255, 249, 238, 0.66);
|
||||
background: rgba(255, 253, 249, 0.8);
|
||||
box-sizing: border-box;
|
||||
color: $brand-red;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(17px, 32rpx, 22px);
|
||||
@@ -1144,28 +657,31 @@ const openShortcut = (shortcutKey) => {
|
||||
}
|
||||
|
||||
.create-icon {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
.create-action .create-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
|
||||
.create-cloud {
|
||||
width: 54rpx;
|
||||
height: 28rpx;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.create-action > text {
|
||||
flex: 0 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.create-cloud--right {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.home-content-fixed {
|
||||
flex: 0 0 auto;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.state-panel {
|
||||
display: flex;
|
||||
min-height: 540rpx;
|
||||
@@ -1382,16 +898,6 @@ const openShortcut = (shortcutKey) => {
|
||||
padding-right: 20rpx;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
.current-name {
|
||||
font-size: clamp(20px, 40rpx, 26px);
|
||||
}
|
||||
.shortcut-label {
|
||||
font-size: clamp(14px, 23rpx, 17px);
|
||||
}
|
||||
.current-meta-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
.create-action {
|
||||
width: 320rpx;
|
||||
}
|
||||
|
||||
+118
-23
@@ -198,15 +198,26 @@
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="overview-family" @click="toFamily">
|
||||
<view>
|
||||
<text>家族近况</text>
|
||||
<text>进入家族圈查看动态</text>
|
||||
<view class="overview-family-content">
|
||||
<view class="overview-family-content__heading">
|
||||
<text>家族内容</text>
|
||||
<text>按用途进入动态、影像与家族事务</text>
|
||||
</view>
|
||||
<view
|
||||
v-for="group in familyContentGroups"
|
||||
:key="group.key"
|
||||
class="overview-family-group"
|
||||
>
|
||||
<text class="overview-family-group__title">{{ group.title }}</text>
|
||||
<view class="overview-family-grid">
|
||||
<button
|
||||
v-for="item in group.items"
|
||||
:key="item.key"
|
||||
class="overview-family-link"
|
||||
@click="openFamilySection(item.key)"
|
||||
>{{ item.label }}</button>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
src="/static/assets/foundation/transparent/chevron-right.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</view>
|
||||
<view class="overview-note">
|
||||
<text class="overview-note__title">成员资料按家谱访问规则保护</text>
|
||||
@@ -280,7 +291,6 @@ import { getRequestErrorMessage } from "@/services/api/request-error-message.js"
|
||||
import { getGenealogyAccessPresetLabel } from "@/utils/genealogy/access-policy.js";
|
||||
import {
|
||||
goBack,
|
||||
goRoot,
|
||||
handleBackPress,
|
||||
openPage,
|
||||
returnTo,
|
||||
@@ -378,7 +388,53 @@ onUnload(() => {
|
||||
const reloadOverview = () => loadGenealogy({ genealogyId: genealogyId.value });
|
||||
const toGenealogies = () => returnTo("G01", {});
|
||||
const toTree = () => openPage("T01", { genealogyId: genealogyId.value }, "G05");
|
||||
const toFamily = () => goRoot("F01", { genealogyId: genealogyId.value });
|
||||
const familyContentGroups = [
|
||||
{
|
||||
key: "memories",
|
||||
title: "家族记录",
|
||||
items: [
|
||||
{ key: "feed", label: "家族动态" },
|
||||
{ key: "articles", label: "谱文" },
|
||||
{ key: "albums", label: "相册" },
|
||||
{ key: "videos", label: "家族视频" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "affairs",
|
||||
title: "家族事务",
|
||||
items: [
|
||||
{ key: "rituals", label: "礼仪" },
|
||||
{ key: "memos", label: "备忘" },
|
||||
{ key: "benefactors", label: "家族恩人" },
|
||||
{ key: "people", label: "人物录" },
|
||||
{ key: "gifts", label: "贺礼簿" },
|
||||
{ key: "merits", label: "功德录" },
|
||||
],
|
||||
},
|
||||
];
|
||||
const openFamilySection = (key) => {
|
||||
if (!genealogyId.value) return;
|
||||
if (key === "feed") return openPage("F12", { genealogyId: genealogyId.value }, "G05");
|
||||
const routes = {
|
||||
articles: "F04",
|
||||
albums: "F07",
|
||||
rituals: "R05",
|
||||
memos: "R10",
|
||||
benefactors: "R10",
|
||||
people: "R01",
|
||||
gifts: "R03",
|
||||
merits: "R11",
|
||||
videos: "F10",
|
||||
};
|
||||
return openPage(
|
||||
routes[key],
|
||||
{
|
||||
genealogyId: genealogyId.value,
|
||||
...(key === "benefactors" ? { memoType: "benefactor" } : {}),
|
||||
},
|
||||
"G05",
|
||||
);
|
||||
};
|
||||
const toApplications = () =>
|
||||
openPage("G10", { genealogyId: genealogyId.value }, "G05");
|
||||
const toSettings = () =>
|
||||
@@ -573,8 +629,7 @@ onBackPress((event) => handleBackPress(event, requestBack));
|
||||
.overview-summary text {
|
||||
display: block;
|
||||
}
|
||||
.overview-action__chevron,
|
||||
.overview-family image {
|
||||
.overview-action__chevron {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
opacity: 0.68;
|
||||
@@ -593,27 +648,67 @@ onBackPress((event) => handleBackPress(event, requestBack));
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 0;
|
||||
}
|
||||
.overview-family {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 26rpx;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
.overview-family-content {
|
||||
margin: 14rpx 42rpx 0;
|
||||
padding: 20rpx 0;
|
||||
padding: 24rpx 0 0;
|
||||
border-top: 1rpx solid rgba(152, 119, 72, 0.28);
|
||||
}
|
||||
|
||||
.overview-family-content__heading text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.overview-family-content__heading text:first-child {
|
||||
color: $ink;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(18px, 31rpx, 22px);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.overview-family-content__heading text:last-child {
|
||||
margin-top: 5rpx;
|
||||
color: $ink-muted;
|
||||
font-size: clamp(13px, 20rpx, 16px);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.overview-family text {
|
||||
display: block;
|
||||
|
||||
.overview-family-group {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
.overview-family text:first-child {
|
||||
margin-bottom: 3rpx;
|
||||
|
||||
.overview-family-group__title {
|
||||
display: block;
|
||||
color: #7f4f16;
|
||||
font-size: clamp(14px, 22rpx, 17px);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.overview-family-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 12rpx;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.overview-family-link {
|
||||
display: flex;
|
||||
min-height: 76rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 8rpx 10rpx;
|
||||
border: 1rpx solid rgba(181, 137, 63, 0.34);
|
||||
border-radius: 8rpx;
|
||||
background: rgba(247, 237, 218, 0.76);
|
||||
color: $ink;
|
||||
font-family: "STKaiti", "KaiTi", serif;
|
||||
font-size: clamp(16px, 27rpx, 20px);
|
||||
font-size: clamp(14px, 22rpx, 17px);
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.overview-family-link::after {
|
||||
border: 0;
|
||||
}
|
||||
.overview-note {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user