feat: 龙里小程序第一次上传
This commit is contained in:
commit
f23d598328
59 files changed
+11482
No files matched your search
@@ -0,0 +1,96 @@
|
||||
<script setup>
|
||||
/**
|
||||
* 首页板块卡(图片 + 顶部锚定文字 + 圆形箭头)
|
||||
* variant: tall(左一通高) | short(右二上下)
|
||||
* 结构与文案位置随 variant 变化,用 computed 输出「互斥」的类串,
|
||||
* 避免同一属性被两个类同时声明而依赖 CSS 顺序。
|
||||
*
|
||||
* ⚠️ 尺寸传递(踩过的坑):小程序里自定义组件是「宿主节点 → 根节点」两层,
|
||||
* 父级写在 <SectionTile class="…"> 上的尺寸类**只落在宿主节点上**,根节点拿不到。
|
||||
* 而本组件内部全是绝对定位,根节点高度一旦是 auto 就塌成 0 → 整块不可见。
|
||||
* → 因此**高度由组件自持**(sizeCls,按 variant 给),不依赖父级;
|
||||
* **宽度**仍由父级在宿主节点上分配(flex-[1.06] / flex-1)。
|
||||
*/
|
||||
import { computed } from "vue";
|
||||
import { goCatalog } from "@/utils/nav";
|
||||
|
||||
const props = defineProps({
|
||||
section: { type: Object, required: true },
|
||||
variant: { type: String, default: "short" },
|
||||
});
|
||||
|
||||
const isTall = computed(() => props.variant === "tall");
|
||||
|
||||
/**
|
||||
* ⚠️ 卡片高度**由组件自持**,不吃父级传来的尺寸。
|
||||
* 原因:小程序自定义组件是「宿主节点 → 内部根节点」两层,父级写在
|
||||
* `<SectionTile class="h-[226px]">` 上的类只落在**宿主节点**,内部根节点拿不到;
|
||||
* 而本组件内部全是绝对定位,根节点高度一旦是 auto 就塌成 0 → 整块不可见。
|
||||
* 若改成内部用 h-full(百分比),又要求宿主恰好有确定高度,链路太脆;
|
||||
* 高度本来就是 variant 的固有属性,直接写在这里最稳(宿主会被内容撑开)。
|
||||
*/
|
||||
const sizeCls = computed(() => (isTall.value ? "h-[226px]" : "h-[108px]"));
|
||||
|
||||
const shadowText = "[text-shadow:0_1px_3px_rgba(0,0,0,0.55),0_2px_14px_rgba(0,0,0,0.5)]";
|
||||
|
||||
/** 文字块定位:通高卡稍微下移,半高卡收紧 */
|
||||
const titleBoxCls = computed(() =>
|
||||
isTall.value ? "absolute left-[15px] right-[13px] top-[15px] z-[2]" : "absolute left-[13px] right-[12px] top-3 z-[2]"
|
||||
);
|
||||
|
||||
const titleCls = computed(() =>
|
||||
isTall.value
|
||||
? `block text-white text-[20px] font-bold tracking-[0.2px] leading-[1.2] ${shadowText}`
|
||||
: `block text-white text-[15px] font-bold tracking-[0.4px] leading-[1.2] ${shadowText}`
|
||||
);
|
||||
|
||||
const subCls = computed(() =>
|
||||
isTall.value
|
||||
? `block text-[rgba(255,255,255,0.94)] text-hint leading-[1.5] mt-[6px] line-clamp-3 ${shadowText}`
|
||||
: `block text-[rgba(255,255,255,0.94)] text-[9.5px] leading-[1.45] mt-1 line-clamp-2 ${shadowText}`
|
||||
);
|
||||
|
||||
const arrowCls = computed(() =>
|
||||
isTall.value
|
||||
? "right-[14px] bottom-[14px] w-11 h-11 border-[rgba(255,255,255,0.6)]"
|
||||
: "right-3 bottom-3 w-8 h-8 border-[rgba(255,255,255,0.46)]"
|
||||
);
|
||||
|
||||
const onTap = () => goCatalog(props.section.key);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view
|
||||
class="relative rounded-tile overflow-hidden shadow-tile"
|
||||
:class="sizeCls"
|
||||
hover-class="opacity-95"
|
||||
@click="onTap"
|
||||
>
|
||||
<image class="absolute inset-0 w-full h-full" :src="section.coverImage" mode="aspectFill" />
|
||||
|
||||
<!-- 遮罩:文字锚顶部 → 顶部最重 -->
|
||||
<view class="absolute inset-0" :class="isTall ? 'scrim-tile-tall' : 'scrim-tile'" />
|
||||
|
||||
<!-- 内描边 -->
|
||||
<view class="pointer-events-none absolute inset-0 rounded-tile border-[0.5px] border-[rgba(255,255,255,0.24)]" />
|
||||
|
||||
<view :class="titleBoxCls">
|
||||
<text :class="titleCls">{{ section.title }}</text>
|
||||
<text :class="subCls">{{ section.subtitle }}</text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="absolute rounded-full flex items-center justify-center z-[2] bg-[rgba(255,255,255,0.2)] border-[0.5px] shadow-[0_6px_16px_rgba(0,0,0,0.22)]"
|
||||
:class="arrowCls"
|
||||
>
|
||||
<AppIcon name="arrow" tone="white" :size="isTall ? 22 : 17" />
|
||||
</view>
|
||||
|
||||
<!-- 通高卡右下角放轮播指示点 -->
|
||||
<view v-if="isTall" class="absolute left-[15px] bottom-[23px] flex gap-[5px] z-[2]">
|
||||
<view class="w-[14px] h-[5px] rounded-full bg-white" />
|
||||
<view class="w-[5px] h-[5px] rounded-full bg-[rgba(255,255,255,0.45)]" />
|
||||
<view class="w-[5px] h-[5px] rounded-full bg-[rgba(255,255,255,0.45)]" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
Reference in new issue
Block a user