style(home components): clean up scss and use utility classes
- remove unused SCSS style files for Discovery sub-components - replace scoped SCSS styles with inline utility classes across home components - remove redundant style imports and empty style blocks from component files - simplify template conditions and remove unnecessary min-h-0 attributes
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div class="w-full border-box flex flex-col overflow-hidden pl-12 mt-6 mb-6">
|
||||
<span class="font-size-14 color-333">{{ text }}</span>
|
||||
<div class="w-full flex flex-col overflow-hidden pl-[12px] mt-[6px] mb-[6px]">
|
||||
<span class="text-[14px] text-[#333]">{{ text }}</span>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from "vue";
|
||||
|
||||
defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
@@ -14,5 +15,3 @@ defineProps({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div class="empty-container">
|
||||
<div class="flex flex-col items-center justify-center py-[90px]">
|
||||
<!-- 图片变量 -->
|
||||
<img v-if="!hasMessage" :src="imageSrc" class="main-image" />
|
||||
<img v-if="!hasMessage" :src="imageSrc" class="w-[160px] h-[160px] mb-5" />
|
||||
|
||||
<!-- 主标题变量 -->
|
||||
<div v-if="!hasMessage" class="title">{{ mainTitle }}</div>
|
||||
<div v-if="!hasMessage" class="text-[18px] font-bold text-[#2c3e50] mb-1 text-center">{{ mainTitle }}</div>
|
||||
|
||||
<!-- 副标题变量 -->
|
||||
<div v-if="!hasMessage" class="sub-title-wrapper">
|
||||
<span class="dot"></span>
|
||||
<span class="sub-title">{{ subTitle }}</span>
|
||||
<span class="dot"></span>
|
||||
<div v-if="!hasMessage" class="flex items-center">
|
||||
<span class="w-[5px] h-[5px] bg-[#42b983] rounded-full"></span>
|
||||
<span class="text-[12px] text-[#afb9c1] ml-[6px] mr-[6px]">{{ subTitle }}</span>
|
||||
<span class="w-[5px] h-[5px] bg-[#42b983] rounded-full"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -39,45 +39,3 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.empty-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 90px 0;
|
||||
|
||||
.main-image {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
margin-bottom: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sub-title-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.sub-title {
|
||||
font-size: 12px;
|
||||
color: #afb9c1;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: #42b983;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -17,18 +17,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="tabIndex === 0" class="flex-full overflow-hidden min-h-0"
|
||||
@touchstart.capture="handleScrollAreaTouchStart" @touchstart="handleScrollAreaTouchStart"
|
||||
@touchmove="handleScrollAreaTouchMove">
|
||||
<!-- 发现页 -->
|
||||
<div v-show="tabIndex === 0" class="flex-full overflow-hidden" @touchstart.capture="handleScrollAreaTouchStart"
|
||||
@touchstart="handleScrollAreaTouchStart" @touchmove="handleScrollAreaTouchMove">
|
||||
|
||||
<Discovery @scroll-touch-start="handleScrollAreaTouchStart" @scroll-touch="handleScrollAreaTouchMove" />
|
||||
</div>
|
||||
|
||||
<!-- 消息列表(可滚动区域) -->
|
||||
<div v-show="tabIndex === 1" class="flex-full overflow-hidden min-h-0" scroll-y :scroll-top="scrollTop"
|
||||
:scroll-with-animation="true" @scroll="handleScroll" @scrolltolower="handleScrollToLower"
|
||||
@touchstart.capture="handleScrollAreaTouchStart" @touchstart="handleScrollAreaTouchStart"
|
||||
@touchmove="handleScrollAreaTouchMove">
|
||||
<div v-show="tabIndex === 1" class="flex-full overflow-hidden" :scroll-top="scrollTop" @scroll="handleScroll"
|
||||
@scrolltolower="handleScrollToLower" @touchstart.capture="handleScrollAreaTouchStart"
|
||||
@touchstart="handleScrollAreaTouchStart" @touchmove="handleScrollAreaTouchMove">
|
||||
|
||||
<div class="area-msg-list-content" v-for="item in chatMsgList" :key="item.msgId" :id="item.msgId">
|
||||
<template v-if="item.msgType === MessageRole.AI">
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
<template>
|
||||
<div class="card-swiper" :class="{ 'is-single': props.list.length <= 1 }" @touchstart="handleTouchStart"
|
||||
@touchmove.stop.prevent="handleTouchMove" @touchend="handleTouchEnd" @touchcancel="handleTouchCancel">
|
||||
<div class="swiper-stage">
|
||||
<div v-for="slot in renderSlots" :key="slot.key" class="swiper-card"
|
||||
:class="[`is-${slot.role}`, { 'is-current': slot.role === 'current' }]" :style="slot.style"
|
||||
@tap="handleCardTap(slot)">
|
||||
<div class="card-shell">
|
||||
<div class="card-media">
|
||||
<img class="card-image" :src="slot.item.coverImage" mode="aspectFill" />
|
||||
<div class="w-full" @touchstart="handleTouchStart" @touchmove.stop.prevent="handleTouchMove"
|
||||
@touchend="handleTouchEnd" @touchcancel="handleTouchCancel">
|
||||
<div :class="['relative w-full h-[270px] overflow-hidden', list.length <= 1 ? 'overflow-visible' : '']">
|
||||
<div v-for="slot in renderSlots" :key="slot.key"
|
||||
class="absolute left-1/2 top-2 w-[236px] h-[234px] max-w-[calc(100%-56px)] origin-center [will-change:transform,opacity]"
|
||||
:style="slot.style" @tap="handleCardTap(slot)">
|
||||
<div
|
||||
:class="['relative w-full h-full p-2 overflow-hidden rounded-3xl bg-white', slot.role === 'current' ? '[box-shadow:0_12px_20px_rgba(15,23,42,0.18)]' : '[box-shadow:0_12px_20px_rgba(15,23,42,0.14)]']">
|
||||
<div class="w-full h-[142px] m-0 overflow-hidden rounded-[20px]">
|
||||
<img class="block w-full h-full" :src="slot.item.coverImage" />
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div v-if="slot.item.tag" class="card-tag">
|
||||
<div class="px-2">
|
||||
<div v-if="slot.item.tag"
|
||||
class="inline-flex items-center justify-center mt-3 min-w-[50px] max-w-full h-[18px] px-2 rounded bg-[#fff4db] text-[#d78621] text-[9px] font-semibold">
|
||||
{{ slot.item.tag }}
|
||||
</div>
|
||||
<div class="card-title ellipsis-1">
|
||||
<div class="mt-[6px] text-[#172033] text-[16px] leading-[1.2] font-bold truncate">
|
||||
{{ slot.item.title }}
|
||||
</div>
|
||||
<div v-if="slot.item.subTitle" class="card-desc ellipsis-1">
|
||||
<div v-if="slot.item.subTitle" class="mt-[2px] text-[#7f8ea3] text-[12px] leading-[18px] truncate">
|
||||
{{ slot.item.subTitle }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="canSwipe" class="card-mask" :style="getMaskStyle(slot.role)" />
|
||||
<div v-if="canSwipe" class="absolute inset-0 bg-white/42 pointer-events-none"
|
||||
:style="getMaskStyle(slot.role)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,8 +56,7 @@ const SWIPE_THRESHOLD = 60;
|
||||
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
||||
const lerp = (from, to, progress) => from + (to - from) * progress;
|
||||
|
||||
const { windowWidth = 375 } = uni.getWindowInfo();
|
||||
const sideOffset = Math.max(108, Math.min(windowWidth * 0.26, 148));
|
||||
const sideOffset = Math.max(108, Math.min(375 * 0.26, 148));
|
||||
const hiddenOffset = sideOffset + 92;
|
||||
|
||||
const activeCursor = ref(0);
|
||||
@@ -464,8 +466,4 @@ onBeforeUnmount(() => {
|
||||
clearSettleTimer();
|
||||
clearRecycleTimer();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
</script>
|
||||
@@ -1,97 +0,0 @@
|
||||
.card-swiper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.swiper-stage {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 270px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swiper-card {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 8px;
|
||||
width: 236px;
|
||||
height: 234px;
|
||||
max-width: calc(100% - 56px);
|
||||
transform-origin: center center;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
.card-shell {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
border-radius: 24px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 12px 20px rgba(15, 23, 42, 0.14);
|
||||
}
|
||||
|
||||
.card-media {
|
||||
width: 100%;
|
||||
height: 142px;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.card-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.card-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 12px;
|
||||
min-width: 50px;
|
||||
max-width: 100%;
|
||||
height: 18px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #fff4db;
|
||||
color: #d78621;
|
||||
font-size: 9px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
margin-top: 6px;
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
line-height: 1.2;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
margin-top: 2px;
|
||||
color: #7f8ea3;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.card-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, 0.42);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.is-current .card-shell {
|
||||
box-shadow: 0 12px 20px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
|
||||
.is-single .swiper-stage {
|
||||
overflow: visible;
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
<template>
|
||||
<div class="find-tabs-wrapper">
|
||||
<div class="tabs-scroll" scroll-x="true" :scroll-left="scrollLeft" scroll-with-animation="true"
|
||||
@scroll="handleScroll">
|
||||
<div class="tabs-list">
|
||||
<div v-for="(tab, idx) in tabs" :key="idx" :id="getTabId(idx)" class="tab-item"
|
||||
:class="{ active: modelValue === idx }" @tap="handleSwitch(tab, idx)">
|
||||
<div class="tab-content">
|
||||
<div class="tab-label">
|
||||
<span class="tab-text">{{ tab.label }}</span>
|
||||
<div class="w-full bg-transparent">
|
||||
<div class="w-full overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden"
|
||||
:scroll-left="scrollLeft" scroll-with-animation="true" @scroll="handleScroll">
|
||||
<div class="flex items-end h-[50px] gap-4 flex-nowrap px-3">
|
||||
<div v-for="(tab, idx) in tabs" :key="idx" :id="getTabId(idx)"
|
||||
class="relative inline-flex items-center justify-center h-[50px] shrink-0" @tap="handleSwitch(tab, idx)">
|
||||
<div class="relative flex items-center justify-center h-[50px]">
|
||||
<div class="relative inline-flex items-center justify-center">
|
||||
<span
|
||||
:class="['relative text-base font-medium text-[#808c99]/90 z-10 px-1 leading-none', modelValue === idx ? 'text-[#0b0b0b] font-bold' : '']">
|
||||
{{ tab.label }}
|
||||
</span>
|
||||
<img v-if="modelValue === idx && (isZhiNian ? indicatorSrcB : indicatorSrc)"
|
||||
:src="isZhiNian ? indicatorSrcB : indicatorSrc" class="tab-indicator" mode="widthFix" />
|
||||
:src="isZhiNian ? indicatorSrcB : indicatorSrc"
|
||||
class="absolute -bottom-[6px] left-1/2 -translate-x-1/2 w-[56px] h-auto z-[1]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -87,7 +91,3 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
.find-tabs-wrapper {
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tabs-scroll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tabs-list {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
height: 50px;
|
||||
gap: 16px;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 50px;
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.tab-item:last-child {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: rgba(128, 140, 153, 0.9);
|
||||
z-index: 2;
|
||||
padding: 0 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: #0b0b0b;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-indicator {
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 56px;
|
||||
height: auto;
|
||||
z-index: 1;
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<div class="container pl-12">
|
||||
<div class="pl-[12px]">
|
||||
<ModuleTitle :title="themeName" />
|
||||
|
||||
<div class="container-scroll font-size-0 scroll-x whitespace-nowrap">
|
||||
<div
|
||||
class="mt-1 mb-[6px] text-[0] overflow-x-auto whitespace-nowrap [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden">
|
||||
<div class="min-w-[130px] max-w-[150px] bg-white inline-block rounded-[20px] mr-[10px]"
|
||||
v-for="(item, index) in list" :key="index" @click="sendReply(item)">
|
||||
|
||||
<div class="card-item bg-white inline-block rounded-20 mr-10" v-for="(item, index) in list" :key="index"
|
||||
@click="sendReply(item)">
|
||||
<div class="flex flex-row justify-start p-[10px]">
|
||||
<img class="w-[40px] h-[40px] shrink-0 rounded-[14px]" :src="createSvgIndex(index)" />
|
||||
|
||||
<div class="flex flex-row flex-justify-start p-10">
|
||||
<img class="card-img flex-shrink-0 rounded-14" :src="createSvgIndex(index)" />
|
||||
|
||||
<div class="min-width-0 flex flex-col flex-full border-box pl-8 py-4">
|
||||
<div class="w-full font-size-12 font-600 color-171717 ellipsis-1">
|
||||
<div class="min-w-0 flex flex-col flex-full pl-[8px] py-[4px]">
|
||||
<div class="w-full text-[12px] font-semibold text-[#171717] truncate">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<div class="w-full font-size-9 color-94A3B8 ellipsis-1">
|
||||
<div class="w-full text-[9px] text-[#94A3B8] truncate">
|
||||
{{ item.subTitle }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,7 +74,3 @@ const createSvg = (bgColor = '#FFFBEB', iconColor = '#F59E0B', size = 40) => {
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
.container-scroll {
|
||||
margin: 4px 0 6px;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
min-width: 130px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.card-img {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full overflow-hidden min-height-0">
|
||||
<div class="flex-shrink-0">
|
||||
<FindTabs v-if="discoveryTabs.length > 0" v-model="activeIndex" :tabs="discoveryTabs" @change="handleTabChange" />
|
||||
<div class="flex flex-col h-full overflow-hidden">
|
||||
<div class="shrink-0">
|
||||
<FindTabs v-if="discoveryTabs.length" v-model="activeIndex" :tabs="discoveryTabs" @change="handleTabChange" />
|
||||
</div>
|
||||
|
||||
<div class="discovery-scroll flex-full border-box min-height-0" scroll-y show-scrollbar="false"
|
||||
@touchstart="emitScrollTouchStart" @touchmove="emitScrollTouch" @scroll="emitScrollTouch">
|
||||
<CardSwiper v-if="discoveryCards.length > 0" :list="discoveryCards" @didSelectItem="handleCardClick" />
|
||||
<div class="discovery-scroll flex-full" overflow-y @touchstart="emitScrollTouchStart" @touchmove="emitScrollTouch"
|
||||
@scroll="emitScrollTouch">
|
||||
<CardSwiper v-if="discoveryCards.length" :list="discoveryCards" @didSelectItem="handleCardClick" />
|
||||
|
||||
<QuickQuestions v-if="discoveryQuickQuestions.length > 0" :list="discoveryQuickQuestions"
|
||||
<QuickQuestions v-if="discoveryQuickQuestions.length" :list="discoveryQuickQuestions"
|
||||
@didSelectItem="handleQuickQuestionClick" />
|
||||
|
||||
</div>
|
||||
@@ -192,12 +192,3 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.discovery-scroll {
|
||||
flex-basis: 0;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
overscroll-behavior-y: contain;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user