transform:translate (-50%,-50%) 造成的文字模糊和解决方案

本文介绍了一种使用Flex布局而非Transform来确保文本在Div中既水平又垂直居中的方法,以此避免字体边缘模糊的问题。

首先先上图,图片为工作项目图片,为了避嫌,打了个码。

如图所示,为了让文字在一个div中水平垂直都居中显示,用absolute定位和transform将文字放在了一个div的中间位置,

此时字号并不小,但字体边缘模糊。




这是因为transform时div的宽度或者高度并不是偶数,移动50%之后,像素点并不是整数,出了小数,和显示像素没有对上。

解决方案是使用flex完成垂直居中,设置排列方向为column,并设置justify-content: center,最后用text-align: center完成水平居中。方能保证文字显示清晰。

<style> /* 使用唯一前缀避免样式冲突 */ .fp-carousel-module { position: relative; width: 100%; max-width: 80%; height: 500px; overflow: hidden; margin: 20px auto; perspective: 1200px; box-sizing: border-box; border-radius: 8px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .fp-carousel-module .fp-carousel-container { position: relative; width: 100%; height: 100%; isolation: isolate; /* 创建新的层叠上下文 */ } .fp-carousel-module .fp-carousel-item { position: absolute; top: 50%; left: 50%; width: 60%; height: 80%; transform: translate(-50%, -50%); border-radius: 12px; box-shadow: 0 15px 35px rgba(0,0,0,0.25); transition: transform 0.7s cubic-bezier(0.25, 0.1, 0.25, 1), filter 0.7s ease, opacity 0.7s ease; z-index: 1; overflow: hidden; background: #fff; will-change: transform; cursor: pointer; } .fp-carousel-module .fp-carousel-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; } .fp-carousel-module .fp-description { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0,0,0,0.8)); color: white; padding: 20px 15px 15px; transform: translateY(100%); transition: transform 0.5s ease-out; text-align: center; font-size: 16px; font-weight: 500; pointer-events: none; } /* 当前激活项样式 */ .fp-carousel-module .fp-carousel-item.fp-active { transform: translate(-50%, -50%) scale(1.15); z-index: 100; box-shadow: 0 25px 50px rgba(0,0,0,0.3); cursor: default; } .fp-carousel-module .fp-carousel-item.fp-active .fp-description { transform: translateY(0); } /* 堆叠项样式 */ .fp-carousel-module .fp-carousel-item.fp-prev { transform: translate(calc(-150% - 30px), -50%) scale(0.85); z-index: 20; opacity: 0.85; filter: blur(1px); } .fp-carousel-module .fp-carousel-item.fp-next { transform: translate(calc(50% + 30px), -50%) scale(0.85); z-index: 20; opacity: 0.85; filter: blur(1px); } .fp-carousel-module .fp-carousel-item.fp-prev-far { transform: translate(calc(-250% - 60px), -50%) scale(0.7); z-index: 15; opacity: 0.7; filter: blur(2px); } .fp-carousel-module .fp-carousel-item.fp-next-far { transform: translate(calc(150% + 60px), -50%) scale(0.7); z-index: 15; opacity: 0.7; filter: blur(2px); } .fp-carousel-module .fp-carousel-item.fp-hidden { opacity: 0; z-index: 0; transform: translate(calc(-50% + 300px), -50%) scale(0.5); } /* 悬停效果 */ .fp-carousel-module .fp-carousel-item.fp-prev::after, .fp-carousel-module .fp-carousel-item.fp-next::after, .fp-carousel-module .fp-carousel-item.fp-prev-far::after, .fp-carousel-module .fp-carousel-item.fp-next-far::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.1); transition: background 0.3s ease; } .fp-carousel-module .fp-carousel-item.fp-prev:hover::after, .fp-carousel-module .fp-carousel-item.fp-next:hover::after, .fp-carousel-module .fp-carousel-item.fp-prev-far:hover::after, .fp-carousel-module .fp-carousel-item.fp-next-far:hover::after { background: rgba(255,255,255,0.3); } /* 导航按钮 */ .fp-carousel-module .fp-nav-btn { position: absolute; top: 0; height: 100%; width: 15%; z-index: 200; display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0.5; transition: opacity 0.3s ease; } .fp-carousel-module .fp-nav-btn::before { content: ''; position: absolute; top: 0; bottom: 0; width: 100%; z-index: -1; } .fp-carousel-module .fp-nav-btn:hover { opacity: 1; } .fp-carousel-module .fp-nav-btn.fp-prev-btn { left: 0; } .fp-carousel-module .fp-nav-btn.fp-prev-btn::before { background: linear-gradient(90deg, rgba(0,0,0,0.4), transparent); } .fp-carousel-module .fp-nav-btn.fp-prev-btn .fp-arrow { transform: rotate(180deg); margin-left: -20px; } .fp-carousel-module .fp-nav-btn.fp-next-btn { right: 0; } .fp-carousel-module .fp-nav-btn.fp-next-btn::before { background: linear-gradient(270deg, rgba(0,0,0,0.4), transparent); } .fp-carousel-module .fp-arrow { display: block; width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,0.8); display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; color: #333; box-shadow: 0 2px 10px rgba(0,0,0,0.2); pointer-events: auto; transition: transform 0.2s ease, background 0.2s ease; } .fp-carousel-module .fp-arrow:hover { background: rgba(255,255,255,1); transform: scale(1.1); } /* 响应式设计 */ @media (max-width: 768px) { .fp-carousel-module { height: 400px; } .fp-carousel-module .fp-carousel-item { width: 70%; height: 85%; } .fp-carousel-module .fp-nav-btn { width: 20%; } } @media (max-width: 480px) { .fp-carousel-module { height: 300px; } .fp-carousel-module .fp-carousel-item { width: 85%; height: 90%; } .fp-carousel-module .fp-description { font-size: 14px; padding: 15px 10px 10px; } } </style> <div class="fp-carousel-module"> <div class="fp-carousel-container"> <div class="fp-carousel-item fp-active" data-index="0"> <img src="https://picsum.photos/id/1015/1000/750" alt="Mountain View"> <div class="fp-description">Majestic mountain range at sunrise</div> </div> <div class="fp-carousel-item fp-next" data-index="1"> <img src="https://picsum.photos/id/1035/1000/750" alt="Ocean Waves"> <div class="fp-description">Turquoise ocean waves crashing on rocks</div> </div> <div class="fp-carousel-item fp-next-far" data-index="2"> <img src="https://picsum.photos/id/1040/1000/750" alt="Forest Path"> <div class="fp-description">Mystical forest path covered in moss</div> </div> <div class="fp-carousel-item fp-prev" data-index="3"> <img src="https://picsum.photos/id/1031/1000/750" alt="Desert Dunes"> <div class="fp-description">Golden desert dunes at sunset</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="4"> <img src="https://picsum.photos/id/1018/1000/750" alt="City Skyline"> <div class="fp-description">Urban city skyline at twilight</div> </div> <div class="fp-nav-btn fp-prev-btn"> <div class="fp-arrow">❮</div> </div> <div class="fp-nav-btn fp-next-btn"> <div class="fp-arrow">❯</div> </div> </div> </div> <script> (function() { // 封装整个轮播逻辑避免全局污染 const initCarousel = function(module) { const container = module.querySelector('.fp-carousel-container'); const items = Array.from(module.querySelectorAll('.fp-carousel-item')); const prevBtn = module.querySelector('.fp-prev-btn'); const nextBtn = module.querySelector('.fp-next-btn'); let currentIndex = 0; // 初始化位置 updatePositions(); // 事件绑定函数 const bindEvents = function() { // 图片点击事件 items.forEach(item => { item.addEventListener('click', function(e) { e.stopPropagation(); if (this.classList.contains('fp-next') || this.classList.contains('fp-next-far')) { navigate(1); } else if (this.classList.contains('fp-prev') || this.classList.contains('fp-prev-far')) { navigate(-1); } }); }); // 容器区域点击 container.addEventListener('click', function(e) { const rect = container.getBoundingClientRect(); const clickX = e.clientX - rect.left; if (clickX > rect.width * 3/4) { navigate(1); } else if (clickX < rect.width * 1/4) { navigate(-1); } }); // 导航按钮 prevBtn.addEventListener('click', function(e) { e.stopPropagation(); navigate(-1); }); nextBtn.addEventListener('click', function(e) { e.stopPropagation(); navigate(1); }); // 键盘导航 - 仅在当前轮播激活时响应 document.addEventListener('keydown', function(e) { // 检查事件是否发生在当前轮播模块内 if (document.activeElement.closest('.fp-carousel-module') !== module) return; if (e.key === 'ArrowLeft') { navigate(-1); } else if (e.key === 'ArrowRight') { navigate(1); } }); // 响应式调整 window.addEventListener('resize', function() { updatePositions(); }); }; // 导航函数 function navigate(direction) { currentIndex = (currentIndex + direction + items.length) % items.length; updatePositions(); } // 更新位置 function updatePositions() { items.forEach((item, index) => { item.classList.remove('fp-active', 'fp-prev', 'fp-next', 'fp-prev-far', 'fp-next-far', 'fp-hidden'); const position = (index - currentIndex + items.length) % items.length; if (position === 0) { item.classList.add('fp-active'); } else if (position === 1) { item.classList.add('fp-next'); } else if (position === 2) { item.classList.add('fp-next-far'); } else if (position === items.length - 1) { item.classList.add('fp-prev'); } else if (position === items.length - 2) { item.classList.add('fp-prev-far'); } else { item.classList.add('fp-hidden'); } }); } // 初始化事件绑定 bindEvents(); }; // 初始化页面上的所有轮播模块 document.querySelectorAll('.fp-carousel-module').forEach(initCarousel); })(); </script> 这段代码表现出的容器右边上下两个圆角出现闪烁问题怎么修改?左边的箭头方向错了
06-15
<!-- 我希望这里做一个展开 收缩 -->帮我做一个 展开收缩 展示量行文字就行 <template> <view class="wrap"> <fu-loading v-if="isShowLoading"></fu-loading> <block v-else> <view v-for="item in lists"> <view class="fu-goods-line pr" @tap.stop="handleJumpDiy" style="width:calc(100% - 20px)" data-type="navigateTo" :data-url="`/pages/mine/newsDetail/newsDetail?id=${item.id}`"> <image v-if="item.is_top == 1" src="https://apps.xiaodan01.com/xcx/home/top_ico.png" mode="widthFix" class="zd"></image> <view class="tn-flex tn-flex-direction-column tn-margin-top-sm tn-margin-bottom" style="width:100%"> <view class="blogger__item"> <view class="blogger__author tn-flex tn-flex-row-between tn-flex-col-center"> <view class="justify__author__info"> <view class="tn-flex tn-flex-row-center"> <view style="display: flex; flex-wrap: nowrap;"> <view class=""> <image :src="item.head_img" style="width:48px;height:48px;border-radius: 24px;"></image> </view> <view class="tn-padding-right tn-text-ellipsis" style="width: 250px;margin-left: 10px;"> <view style="display: flex;align-items: center;"> <view class="tn-padding-right tn-padding-left-sm tn-text-bold tn-text-ellipsis" style="margin-left:3px" :style="item.is_pingtai == 1 ? 'color:#f37b1d' : ''">{{ item.user_nickname }}</view> <image v-if="item.is_pingtai == 1" style="width:31rpx;" src="https://apps.xiaodan01.com/xcx/images/rz.png" mode="widthFix"></image> <image v-if="item.is_pingtai == 0 && item.user_level_img != ''" style="width:31rpx;" :src="item.user_level_img" mode="widthFix"></image> </view> <view style="color:#999;">{{ item.create_time }}</view> </view> </view> </view> </view> </view> <view class="flex blogger__desc tn-margin-top-sm tn-margin-bottom-sm tn-text-justify tn-flex-col-center tn-flex-row-left"> <view class="blogger__desc__label tn-float-left tn-margin-right tn-bg-gray--light tn-round tn-text-sm tn-text-bold"> <text class="blogger__desc__label--prefix" style="color: #1172f4;">#</text> <text class="tn-text-df" style="color: #1172f4;">{{ item.name }}</text> </view> <text class="blogger__desc__content tn-flex-1 tn-text-justify tn-text-df">{{ item.title }}</text> </view> <!-- 我希望这里做一个展开 收缩 --> <view class="flex blogger__desc tn-margin-top-sm tn-margin-bottom-sm tn-text-justify tn-flex-col-center tn-flex-row-left"> <text class="blogger__desc__content tn-flex-1 tn-text-justify tn-text-df">{{ item.body_txt }}</text> </view> <block v-if="item.images"> <view class="tn-padding-top-xs" style="padding-top: 5px; display: flex; width: 100%; justify-content: space-between; flex-wrap: wrap; position: relative;"> <!-- 遍历图片列表 --> <block v-if="item.images"> <view class="tn-padding-top-xs" style="padding-top: 5px; display: flex; width: 100%; flex-wrap: wrap; position: relative;" :style="item.images.length == 2 ? '' : 'justify-content: space-between'"> <block v-for="(image_item, image_index) in item.images" :key="image_index" @tap.stop="multiImagePreview(image_item, item.images)"> <view v-if="image_index < 6" style="position: relative" :class="item.images.length === 4 ? 'fourGridStyle' : (item.images.length === 5 ? (image_index < 3 ? 'fiveGridStyleA' : 'fiveGridStyleB') : 'defaultStyle')" :style="item.images.length == 2 ? 'margin-right:5px' : ''"> <image class="blogger__main-image" :src="image_item" mode="aspectFill" :class="(image_index === 5 && item.images.length > 6) ? 'imageBaseStyle blurStyle ' : 'imageBaseStyle'"></image> <!-- +号显示保持原样 --> <view v-if="image_index === 5 && item.images.length > 6" class="" style="position: absolute; right:0;top:0px; width: 100%; height: 100%; background: rgb(0 0 0 / 53%); border-radius: 8px; text-align: center;line-height: 120px;font-size: 25px;color:#fff;"> +{{item.images.length - 5}} </view> </view> </block> </view> </block> </view> </block> <view class="text-999" style="font-size: 24rpx;" v-if="item.show_price != ''"> 交易价格: <text class="fyjg"> {{item.show_price}}元 </text> </view> <view style="display: flex; justify-content: space-between; align-items: center; color: #999;font-size: 20rpx;"> <view class="justify-content-item tn-color-gray tn-text-center"> <view class=""> <text class="blogger__count-icon tn-icon-message"></text> <text class="tn-padding-right">{{ item.comment_num }}评论</text> <text class="blogger__count-icon tn-icon-like"></text> <text class="">{{ item.user_like_num }}点赞</text> </view> </view> <view class="justify-content-item tn-flex tn-flex-col-center"> <image :src="STATIC_URL+'delxx.png?v=1'" mode="widthFix" class="dele" v-if="item.is_me == 1" @tap.stop="delFabu(item.id)"></image> <text class="tn-color-gray" v-if="item.click_count > 0">{{item.click_count}}人浏览</text> </view> </view> </view> </view> </view> </view> </block> <view class="" style="height: 50px;"></view> <uni-load-more v-if="lists.length > 1" :status='status'></uni-load-more> <fu-empty-ui emptyImage="nodata" v-if="lists.length == 0 && !isShowLoading" pagingListNoListDataText=""></fu-empty-ui> <uTabbar v-model="current" :list="list" :mid-button="true" :hide-tab-bar="true" :mid-button-size="110" :height="110" :icon-size="48" active-color="#3370EB" inactiveColor="#333333" @change="changeTab"></uTabbar> </view> </template> <script> import uTabbar from '@/components/u-tabbar/u-tabbar.vue'; import { tabbarList } from '@/common/utils/tabbar.js'; // 导入函数 export default { components:{ uTabbar }, props: { num: { type: Number, default: 10 }, is_collect: { type: Number, default: 0 }, isHome: { type: Number, default: 0 }, titleNone: { type: String, default: '最新发布' }, cid: { type: Number / String, default: 0 }, my_user_id: { type: Number / String, default: 0 }, cityName: { type: String, default: '' }, districtName: { type: String, default: '' }, showTitle: { type: Boolean, default: true }, model: { type: String, default: 'inline' }, keywords: { type: String, default: '' }, showInline: { type: Boolean, default: false } }, data() { return { list: tabbarList(), current: 0, content: [{ userAvatar: '', userName: '', date: '', label: [''], desc: '', content: '', mainImage: [], collectionCount: 431, commentCount: 26, likeCount: 84 }], navList: [{ id: 0, text: '最新', num: 0, }, ], // 切换列表 type: 0, lists: [], status: 'more', page: 1, size: 10, isInit: false, isShowLoading: false, }; }, methods: { changeTab(type){ console.log(type,'type’'); if(type == 0){ this.refresh() //加载首页 }else if(type == 1){ //发布 this.goUrl() }else if(type == 2){ //个人中心 } }, goUrl(){ if(!global.token){ this.toLoginDiy() return false } // 因为只能获取到一级名称 所以还是 跳转过去吧 console.log(this.thisCid) if(this.thisCid == 5){ console.log('招聘求职 外侧没意义'); }else{ //其他论坛内容 uni.navigateTo({ url:'/pages/mine/publish/publish'+'?is_bianmin=0&id='+this.thisCid+'&title='+this.name }) } }, delFabu(_id) { let that = this this.$util.showModal({ title: '确认删除?', content: '删除后不可恢复', success: res => { if (res.confirm) { that.$api.post(global.apiUrls.delFabu, { id: _id }).then(res => { that.$message.info(res.data.msg) if (res.data.code == 1) { setTimeout(function() { that.refresh() //重新加载 }, 800); }else{ } }); } } }); }, // 改造为返回样式对象 getImageStyle(index, images) { const totalImages = images.length; let width = "32%"; if (totalImages === 4) { width = "49%"; } else if (totalImages === 5) { width = index < 3 ? "32%" : "49%"; } // 返回对象格式(关键修改) return { width: width, height: '210rpx', 'margin-bottom': '5px', 'border-radius': '8px', position: 'relative' }; }, // 模糊样式改造 getImageBlurStyle(index, images) { // 返回对象格式 return index === 5 && images.length > 6 ? { filter: 'blur(2px)', width: '100%', height: '100%', 'border-radius': '8px' } : { width: '100%', height: '100%', 'border-radius': '8px' }; }, tabClick(e) { if (this.flag) { return false } let index = e.index; this.type = this.navList[index].id; this.refresh() }, loadData() { console.log('加载'); if (this.status != 'more') return; this.status = "loading"; if (this.page == 1) { this.isShowLoading = true; } var data = { is_luntan: 1, type: 2, //列表 city_name: this.cityName, district_name: this.districtName, page: this.page, category_id: this.cid, my_user_id:this.my_user_id, list_rows: this.size, keyword: this.keywords, is_home: this.isHome, is_collect:this.is_collect } console.log(data, '首页论坛data'); if (global.token && global.userInfo) { data.user_id = global.userInfo.id } console.log("首页论坛请求接口参数-", data) var that = this this.$api.post(global.apiUrls.homeList, data).then(res => { // console.log('首页论坛请求接口result',res); this.isShowLoading = false; if (res.statusCode == 200 && res.data.code == 1) { res = res.data; console.log("论坛列表", res); var totalSize = res.data.total; var curPageData = res.data.data; if (this.page == 1) this.lists = []; this.lists = this.lists.concat(curPageData); if (this.lists.length < totalSize) { this.status = "more"; this.page++; } else { this.status = "noMore"; } }else{ this.$message.info(res.data.msg) } this.isInit = true; uni.stopPullDownRefresh(); }) .catch((err) => { this.isShowLoading = false; console.log("ERROR", err); uni.stopPullDownRefresh(); }); }, refresh() { this.page = 1; this.status = 'more'; this.lists = []; this.loadData(); } }, } </script> <style lang="scss" scoped> .dele{ width: 30rpx; margin-right: 4px; } .fyjg{ color:$moneyJin } // 3图模式 .defaultStyle{ width: 32%; height: 210rpx; margin-bottom: 5px } // 4图模式 .fourGridStyle{ width: 49%; height: 210rpx;margin-bottom: 5px } // 5图模式(前3后2) .fiveGridStyleA{ width: 32%; height: 210rpx } .fiveGridStyleB{ width: 49%; height: 210rpx; margin-top: 5px; } // 图片基础样式 .imageBaseStyle{ width: 100%; height: 100%; border-radius: 8px } .blurStyle{ filter: blur(2px); width: 100%; height: 100% } .wrap { width: 100%; .title { height: 100rpx; line-height: 100rpx; image { width: 48rpx; height: 32rpx; margin: 0 24rpx; } } .content { padding: 0 20rpx; } } .nav-bar-wrap { position: fixed; top: 0; left: 0; right: 0; } .sort-wrap { position: fixed; left: 0; right: 0; } .height-100 { height: 100rpx; } .block-180 { width: 180rpx; min-width: 180rpx; height: 180rpx; min-height: 180rpx; position: relative; image { width: 100%; height: 100%; border-radius: 8rpx; } .null { position: absolute; top: 0; right: 0; bottom: 0; left: 0; border-radius: 8rpx; background-color: rgba(0, 0, 0, 0.45); color: #ffffff; font-size: 36rpx; text-align: center; line-height: 180rpx; } } .list-item+.list-item { border-top: 1rpx solid #eeeeee; } .overlay-animate { position: fixed; } .float-action { width: 72rpx; height: 72rpx; border-radius: 50%; // background-color: rgba(165, 165, 165, .85); position: fixed; right: 20rpx; bottom: 280rpx; z-index: 996; border: 1rpx solid #cccccc; .cuIcon-cart { color: #cccccc; } } .animate { position: fixed; border-radius: 50%; z-index: 995; transform-origin: 50% 50%; transition: transform linear 0.5s, left linear 0.5s, top cubic-bezier(0.3, -0.2, 1, 0) 0.5s !important; image { width: 100rpx; height: 100rpx; border-radius: 50%; } } // 商品卡片line .fu-goods-line { /* min-height: 570rpx; */ // padding: 24rpx 0; border-radius: 16rpx; background-color: #ffffff; // margin-top: 20rpx; display: flex; // border-bottom: 1rpx solid #EEEEEE; margin-bottom: 24rpx; width: calc(100% - 20px); margin: 10px; .block-246 { // padding: 24rpx 24rpx 0; .img { width: 140rpx; height: 140rpx; border-radius: 6rpx; background-color: #eeeeee; } } .content { flex: 1; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between; } } // 商品卡片block .fu-goods-block { overflow: hidden; margin-bottom: 20rpx; padding: 0 10rpx; .wrap-box { background-color: #ffffff; border-radius: 16rpx; .square-wrap { width: 100%; height: 0; padding-bottom: 100%; box-sizing: border-box; position: relative; .square-box { position: absolute; left: 0; top: 0; right: 0; bottom: 0; border-radius: 16rpx 16rpx 0 0; image { width: 100%; height: 100%; border-radius: 24rpx 24rpx 0 0; } } } .image { width: 100%; border-radius: 24rpx 24rpx 0 0; } } .content { padding: 20rpx; } } .item-activity-label { padding: 2rpx 5rpx; /* margin: 5rpx; */ font-size: 24rpx; border-radius: 6rpx; border: 1px solid; margin: 0rpx 1px 0px; display: inline-block; transform: scale(0.8); } .search-form { margin-left: 12rpx; } .item-goods-label { padding: 4rpx 10rpx; margin-right: 10rpx; height: 32rpx; background: rgba(255, 239, 239, 1); border-radius: 4px; color: #ff6464; font-size: 24rpx; text-align: center; width: 84rpx; } .item-activity-label { padding: 0 8rpx; height: 32rpx; line-height: 30rpx; border: 1px solid #FA2033; opacity: 1; border-radius: 4rpx; font-size: 20rpx; font-family: PingFang SC; font-weight: 400; color: #FA2033; margin-right: 16rpx; &:nth-of-type(1) { border: 1px solid #0A7CE6; color: #0A7CE6; } } .padding-lr-24 { padding: 0 24rpx; } .padding-lr-4 { padding: 0 4rpx; } .sales-number { margin-top: 16rpx; } .through-price { margin-left: 16rpx; color: #BFBFBF; } ::v-deep .solid-bottom::after { border-bottom: 0; } .pr { position: relative; } .zd { position: absolute; z-index: 1; width: 30px; top: 0; left: 0 } .car { width: 104rpx; height: 104rpx; position: fixed; right: 28rpx; bottom: 300rpx; background: url(https://apps.xiaodan01.com/xcx/car-s.png); background-size: 100% 100%; } // new .template-circle { max-height: 100vh; } .tn-tabbar-height { min-height: 120rpx; height: calc(140rpx + env(safe-area-inset-bottom) / 2); } /* 自定义导航栏内容 start */ .custom-nav { height: 100%; &__back { margin: auto 5rpx; font-size: 40rpx; margin-right: 10rpx; margin-left: 30rpx; flex-basis: 5%; } &__search { flex-basis: 60%; width: 100%; height: 100%; &__box { width: 100%; height: 70%; padding: 10rpx 0; margin: 0 30rpx; border-radius: 60rpx 60rpx 0 60rpx; font-size: 24rpx; } &__icon { padding-right: 10rpx; margin-left: 20rpx; font-size: 30rpx; } &__text { color: #AAAAAA; } } } .logo-image { width: 60rpx; height: 60rpx; position: relative; margin-top: -15rpx; } .logo-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 50%; } /* 自定义导航栏内容 end */ /* 博主头像 start*/ .image-circle { // padding: 95rpx; width: 190rpx; height: 190rpx; font-size: 40rpx; font-weight: 300; position: relative; } .image-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 10rpx; } /* 文章内容 start*/ .blogger { &__item { padding: 30rpx; } &__author { &__btn { margin-right: -12rpx; opacity: 0.5; } } &__desc { line-height: 55rpx; &__label { padding: 0 20rpx; margin: 0rpx 18rpx 0 0; &--prefix { color: #00FFC8; padding-right: 10rpx; } } &__content {} } &__content { margin-top: 18rpx; padding-right: 18rpx; &__data { line-height: 46rpx; text-align: justify; overflow: hidden; transition: all 0.25s ease-in-out; } &__status { margin-top: 10rpx; font-size: 26rpx; color: #82B2FF; } } &__main-image { border-radius: 16rpx; &--1 { max-width: 80%; max-height: 300rpx; } &--2 { max-width: 260rpx; max-height: 260rpx; } &--3 { height: 212rpx; width: 100%; } } &__count-icon { font-size: 40rpx; padding-right: 5rpx; } &__ad { width: 100%; height: 500rpx; transform: translate3d(0px, 0px, 0px) !important; ::v-deep .uni-swiper-slide-frame { transform: translate3d(0px, 0px, 0px) !important; } .uni-swiper-slide-frame { transform: translate3d(0px, 0px, 0px) !important; } &__item { position: absolute; width: 100%; height: 100%; transform-origin: left center; transform: translate3d(100%, 0px, 0px) scale(1) !important; transition: transform 0.25s ease-in-out; z-index: 1; &--0 { transform: translate3d(0%, 0px, 0px) scale(1) !important; z-index: 4; } &--1 { transform: translate3d(13%, 0px, 0px) scale(0.9) !important; z-index: 3; } &--2 { transform: translate3d(26%, 0px, 0px) scale(0.8) !important; z-index: 2; } } &__content { border-radius: 40rpx; width: 640rpx; height: 500rpx; overflow: hidden; } &__image { width: 100%; height: 100%; } } } /* 文章内容 end*/ /* 间隔线 start*/ .tn-strip-bottom { width: 100%; border-bottom: 20rpx solid rgba(241, 241, 241, 0.8); } /* 间隔线 end*/ /* 广告内容 start */ .ad-image { width: 80rpx; height: 80rpx; position: relative; } .ad-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 20%; } /* 自定义导航栏内容 end */ /* 全屏轮播 start*/ .card-swiper { height: 100vh !important; } .card-swiper swiper-item { width: 750rpx !important; left: 0rpx; box-sizing: border-box; overflow: initial; } .card-swiper swiper-item .swiper-item { width: 100%; display: block; height: 100vh; border-radius: 0rpx; transform: scale(1); transition: all 0.2s ease-in 0s; overflow: hidden; } .card-swiper swiper-item.cur .swiper-item { transform: none; transition: all 0.2s ease-in 0s; } .card-swiper swiper-item .swiper-item-png { margin-top: -50vh; width: 100%; display: block; border-radius: 0rpx; transform: translate(1040rpx, 20rpx) scale(0.5, 0.5); transition: all 0.6s ease 0s; // overflow: hidden; } .card-swiper swiper-item.cur .swiper-item-png { margin-top: -100vh; width: 900rpx; transform: translate(-80rpx, 0rpx) scale(1, 1); transition: all 0.6s ease 0s; } .image-banner { display: flex; align-items: center; justify-content: center; } .image-banner image { width: 100%; } /* 轮播指示点 start*/ .indication { z-index: 9999; width: 100%; height: 36rpx; position: fixed; // display:flex; display: block; flex-direction: row; align-items: center; justify-content: center; } .spot { background-color: #000; opacity: 0.3; width: 10rpx; height: 10rpx; border-radius: 20rpx; margin: 20rpx 0 !important; left: 95vw; top: -60vh; position: relative; } .spot.active { opacity: 0.6; height: 30rpx; background-color: #000; } /* 资讯主图 start*/ .image-article { border-radius: 8rpx; border: 1rpx solid #F8F7F8; width: 200rpx; height: 200rpx; position: relative; } .image-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 10rpx; } .article-shadow { border-radius: 15rpx; box-shadow: 0rpx 0rpx 50rpx 0rpx rgba(0, 0, 0, 0.07); } /* 文字截取*/ .clamp-text-1 { -webkit-line-clamp: 1; display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; overflow: hidden; } .clamp-text-2 { -webkit-line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; overflow: hidden; } /* 标签内容 start*/ .tn-tag-content { &__item { display: inline-block; line-height: 35rpx; padding: 5rpx 25rpx; &--prefix { padding-right: 10rpx; } } } /* 图标容器9 start */ .icon9 { &__item { width: 30%; background-color: #FFFFFF; border-radius: 10rpx; padding: 30rpx; margin: 20rpx 10rpx; transform: scale(1); transition: transform 0.3s linear; transform-origin: center center; &--icon { width: 110rpx; height: 110rpx; font-size: 65rpx; border-radius: 50%; margin: 20rpx 40rpx; position: relative; z-index: 1; &::after { content: " "; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; bottom: 0; border-radius: inherit; opacity: 1; transform: scale(1, 1); background-size: 100% 100%; background-image: url(https://resource.tuniaokj.com/images/cool_bg_image/icon_bg5.png); } } } } /* 悬浮 */ .tnxuanfu { animation: suspension 3s ease-in-out infinite; } @keyframes suspension { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-0.8rem); } } /* 悬浮按钮 */ .button-shop { width: 90rpx; height: 90rpx; display: flex; flex-direction: row; position: fixed; /* bottom:200rpx; right: 20rpx; */ left: 5rpx; top: 5rpx; z-index: 1001; border-radius: 100px; opacity: 0.9; } /* 按钮 */ .edit { bottom: 300rpx; right: 75rpx; position: fixed; z-index: 9999; } .pa, .pa0 { position: absolute } .pa0 { left: 0; top: 0 } .bg0 { width: 100rpx; height: 100rpx; top: 50%; left: 50%; transform: translate(-50%, -50%); } .bg1 { width: 100%; height: 100%; } .hx-box { top: 50%; left: 50%; width: 100rpx; height: 100rpx; transform-style: preserve-3d; transform: translate(-50%, -50%) rotateY(75deg) rotateZ(10deg); } .hx-box .pr { width: 100rpx; height: 100rpx; transform-style: preserve-3d; animation: hxz 20s linear infinite; } @keyframes hxz { 0% { transform: rotateX(0deg); } 100% { transform: rotateX(-360deg); } } .hx-box .pr .pa0 { width: 100rpx; height: 100rpx; /* border: 4px solid #5ec0ff; */ border-radius: 1000px; } .hx-box .pr .pa0 .span { display: block; width: 100%; height: 100%; background: url(https://resource.tuniaokj.com/images/cool_bg_image/arc4.png) no-repeat center center; background-size: 100% 100%; animation: hx 4s linear infinite; } @keyframes hx { to { transform: rotate(360deg); } } .hx-k1 { transform: rotateX(-60deg) rotateZ(-60deg) } .hx-k2 { transform: rotateX(-30deg) rotateZ(-30deg) } .hx-k3 { transform: rotateX(0deg) rotateZ(0deg) } .hx-k4 { transform: rotateX(30deg) rotateZ(30deg) } .hx-k5 { transform: rotateX(60deg) rotateZ(60deg) } .hx-k6 { transform: rotateX(90deg) rotateZ(90deg) } </style>
11-08
现在这样 但是有的文章超出两行 没有展示展开收缩的文字按钮 这是代码:<template> <view class="wrap"> <fu-loading v-if="isShowLoading"></fu-loading> <block v-else> <view v-for="item in lists"> <view class="fu-goods-line pr" @tap.stop="handleJumpDiy" style="width:calc(100% - 20px)" data-type="navigateTo" :data-url="`/pages/mine/newsDetail/newsDetail?id=${item.id}`"> <image v-if="item.is_top == 1" src="https://apps.xiaodan01.com/xcx/home/top_ico.png" mode="widthFix" class="zd"></image> <view class="tn-flex tn-flex-direction-column tn-margin-top-sm tn-margin-bottom" style="width:100%"> <view class="blogger__item"> <view class="blogger__author tn-flex tn-flex-row-between tn-flex-col-center"> <view class="justify__author__info"> <view class="tn-flex tn-flex-row-center"> <view style="display: flex; flex-wrap: nowrap;"> <view class=""> <image :src="item.head_img" style="width:48px;height:48px;border-radius: 24px;"></image> </view> <view class="tn-padding-right tn-text-ellipsis" style="width: 250px;margin-left: 10px;"> <view style="display: flex;align-items: center;"> <view class="tn-padding-right tn-padding-left-sm tn-text-bold tn-text-ellipsis" style="margin-left:3px" :style="item.is_pingtai == 1 ? 'color:#f37b1d' : ''">{{ item.user_nickname }}</view> <image v-if="item.is_pingtai == 1" style="width:31rpx;" src="https://apps.xiaodan01.com/xcx/images/rz.png" mode="widthFix"></image> <image v-if="item.is_pingtai == 0 && item.user_level_img != ''" style="width:31rpx;" :src="item.user_level_img" mode="widthFix"></image> </view> <view style="color:#999;">{{ item.create_time }}</view> </view> </view> </view> </view> </view> <view class="flex blogger__desc tn-margin-top-sm tn-margin-bottom-sm tn-text-justify tn-flex-col-center tn-flex-row-left"> <view class="blogger__desc__label tn-float-left tn-margin-right tn-bg-gray--light tn-round tn-text-sm tn-text-bold"> <text class="blogger__desc__label--prefix" style="color: #1172f4;">#</text> <text class="tn-text-df" style="color: #1172f4;">{{ item.name }}</text> </view> <text class="blogger__desc__content tn-flex-1 tn-text-justify tn-text-df">{{ item.title }}</text> </view> <!-- 添加展开/收起按钮 --> <!-- 展开收缩区域:文本 + 右侧按钮 --> <view v-if="item.body_txt" class="expand-container" @tap.stop="toggleExpand(item)" > <!-- 文本部分(限制两行) --> <text class="blogger__desc__content tn-flex-1 tn-text-justify tn-text-df clamp-2" :class="[item.isExpanded ? 'expanded' : '']" >{{ item.body_txt }}</text> <!-- 按钮图标部分(靠右) --> <view class="toggle-button" v-if="item.body_txt.length > 100" > <text class="toggle-text">{{ item.isExpanded ? '收起' : '展开' }}</text> <u-icon :name="item.isExpanded ? 'arrow-up' : 'arrow-down'" size="24" color="#999" ></u-icon> </view> </view> <block v-if="item.images"> <view class="tn-padding-top-xs" style="padding-top: 5px; display: flex; width: 100%; justify-content: space-between; flex-wrap: wrap; position: relative;"> <!-- 遍历图片列表 --> <block v-if="item.images"> <view class="tn-padding-top-xs" style="padding-top: 5px; display: flex; width: 100%; flex-wrap: wrap; position: relative;" :style="item.images.length == 2 ? '' : 'justify-content: space-between'"> <block v-for="(image_item, image_index) in item.images" :key="image_index" @tap.stop="multiImagePreview(image_item, item.images)"> <view v-if="image_index < 6" style="position: relative" :class="item.images.length === 4 ? 'fourGridStyle' : (item.images.length === 5 ? (image_index < 3 ? 'fiveGridStyleA' : 'fiveGridStyleB') : 'defaultStyle')" :style="item.images.length == 2 ? 'margin-right:5px' : ''"> <image class="blogger__main-image" :src="image_item" mode="aspectFill" :class="(image_index === 5 && item.images.length > 6) ? 'imageBaseStyle blurStyle ' : 'imageBaseStyle'"></image> <!-- +号显示保持原样 --> <view v-if="image_index === 5 && item.images.length > 6" class="" style="position: absolute; right:0;top:0px; width: 100%; height: 100%; background: rgb(0 0 0 / 53%); border-radius: 8px; text-align: center;line-height: 120px;font-size: 25px;color:#fff;"> +{{item.images.length - 5}} </view> </view> </block> </view> </block> </view> </block> <view class="text-999" style="font-size: 24rpx;" v-if="item.show_price != ''"> 交易价格: <text class="fyjg"> {{item.show_price}}元 </text> </view> <view style="display: flex; justify-content: space-between; align-items: center; color: #999;font-size: 20rpx;"> <view class="justify-content-item tn-color-gray tn-text-center"> <view class=""> <text class="blogger__count-icon tn-icon-message"></text> <text class="tn-padding-right">{{ item.comment_num }}评论</text> <text class="blogger__count-icon tn-icon-like"></text> <text class="">{{ item.user_like_num }}点赞</text> </view> </view> <view class="justify-content-item tn-flex tn-flex-col-center"> <image :src="STATIC_URL+'delxx.png?v=1'" mode="widthFix" class="dele" v-if="item.is_me == 1" @tap.stop="delFabu(item.id)"></image> <text class="tn-color-gray" v-if="item.click_count > 0">{{item.click_count}}人浏览</text> </view> </view> </view> </view> </view> </view> </block> <view class="" style="height: 50px;"></view> <uni-load-more v-if="lists.length > 1" :status='status'></uni-load-more> <fu-empty-ui emptyImage="nodata" v-if="lists.length == 0 && !isShowLoading" pagingListNoListDataText=""></fu-empty-ui> <uTabbar v-model="current" :list="list" :mid-button="true" :hide-tab-bar="true" :mid-button-size="110" :height="110" :icon-size="48" active-color="#3370EB" inactiveColor="#333333" @change="changeTab"></uTabbar> </view> </template> <script> import uTabbar from '@/components/u-tabbar/u-tabbar.vue'; import { tabbarList } from '@/common/utils/tabbar.js'; // 导入函数 export default { components:{ uTabbar }, props: { num: { type: Number, default: 10 }, is_collect: { type: Number, default: 0 }, isHome: { type: Number, default: 0 }, titleNone: { type: String, default: '最新发布' }, cid: { type: Number / String, default: 0 }, my_user_id: { type: Number / String, default: 0 }, cityName: { type: String, default: '' }, districtName: { type: String, default: '' }, showTitle: { type: Boolean, default: true }, model: { type: String, default: 'inline' }, keywords: { type: String, default: '' }, showInline: { type: Boolean, default: false } }, data() { return { list: tabbarList(), current: 0, content: [{ userAvatar: '', userName: '', date: '', label: [''], desc: '', content: '', mainImage: [], collectionCount: 431, commentCount: 26, likeCount: 84 }], navList: [{ id: 0, text: '最新', num: 0, }, ], // 切换列表 type: 0, lists: [], status: 'more', page: 1, size: 10, isInit: false, isShowLoading: false, }; }, methods: { changeTab(type){ console.log(type,'type’'); if(type == 0){ this.refresh() //加载首页 }else if(type == 1){ //发布 this.goUrl() }else if(type == 2){ //个人中心 } }, goUrl(){ if(!global.token){ this.toLoginDiy() return false } // 因为只能获取到一级名称 所以还是 跳转过去吧 console.log(this.thisCid) if(this.thisCid == 5){ console.log('招聘求职 外侧没意义'); }else{ //其他论坛内容 uni.navigateTo({ url:'/pages/mine/publish/publish'+'?is_bianmin=0&id='+this.thisCid+'&title='+this.name }) } }, delFabu(_id) { let that = this this.$util.showModal({ title: '确认删除?', content: '删除后不可恢复', success: res => { if (res.confirm) { that.$api.post(global.apiUrls.delFabu, { id: _id }).then(res => { that.$message.info(res.data.msg) if (res.data.code == 1) { setTimeout(function() { that.refresh() //重新加载 }, 800); }else{ } }); } } }); }, // 改造为返回样式对象 getImageStyle(index, images) { const totalImages = images.length; let width = "32%"; if (totalImages === 4) { width = "49%"; } else if (totalImages === 5) { width = index < 3 ? "32%" : "49%"; } // 返回对象格式(关键修改) return { width: width, height: '210rpx', 'margin-bottom': '5px', 'border-radius': '8px', position: 'relative' }; }, // 模糊样式改造 getImageBlurStyle(index, images) { // 返回对象格式 return index === 5 && images.length > 6 ? { filter: 'blur(2px)', width: '100%', height: '100%', 'border-radius': '8px' } : { width: '100%', height: '100%', 'border-radius': '8px' }; }, tabClick(e) { if (this.flag) { return false } let index = e.index; this.type = this.navList[index].id; this.refresh() }, toggleExpand(item) { this.$set(item, 'isExpanded', !item.isExpanded); // 确保响应式更新 }, loadData() { console.log('加载'); if (this.status != 'more') return; this.status = "loading"; if (this.page == 1) { this.isShowLoading = true; } var data = { is_luntan: 1, type: 2, //列表 city_name: this.cityName, district_name: this.districtName, page: this.page, category_id: this.cid, my_user_id:this.my_user_id, list_rows: this.size, keyword: this.keywords, is_home: this.isHome, is_collect:this.is_collect } console.log(data, '首页论坛data'); if (global.token && global.userInfo) { data.user_id = global.userInfo.id } console.log("首页论坛请求接口参数-", data) var that = this this.$api.post(global.apiUrls.homeList, data).then(res => { // console.log('首页论坛请求接口result',res); this.isShowLoading = false; if (res.statusCode == 200 && res.data.code == 1) { res = res.data; console.log("论坛列表", res); var totalSize = res.data.total; var curPageData = res.data.data; if (this.page == 1) this.lists = []; // this.lists = this.lists.concat(curPageData); this.lists = this.lists.concat(curPageData.map(item => { return { ...item, isExpanded: false // 默认不展开 }; })); if (this.lists.length < totalSize) { this.status = "more"; this.page++; } else { this.status = "noMore"; } }else{ this.$message.info(res.data.msg) } this.isInit = true; uni.stopPullDownRefresh(); }) .catch((err) => { this.isShowLoading = false; console.log("ERROR", err); uni.stopPullDownRefresh(); }); }, refresh() { this.page = 1; this.status = 'more'; this.lists = []; this.loadData(); } }, } </script> <style lang="scss" scoped> .dele{ width: 30rpx; margin-right: 4px; } .fyjg{ color:$moneyJin } // 3图模式 .defaultStyle{ width: 32%; height: 210rpx; margin-bottom: 5px } // 4图模式 .fourGridStyle{ width: 49%; height: 210rpx;margin-bottom: 5px } // 5图模式(前3后2) .fiveGridStyleA{ width: 32%; height: 210rpx } .fiveGridStyleB{ width: 49%; height: 210rpx; margin-top: 5px; } // 图片基础样式 .imageBaseStyle{ width: 100%; height: 100%; border-radius: 8px } .blurStyle{ filter: blur(2px); width: 100%; height: 100% } .wrap { width: 100%; .title { height: 100rpx; line-height: 100rpx; image { width: 48rpx; height: 32rpx; margin: 0 24rpx; } } .content { padding: 0 20rpx; } } .nav-bar-wrap { position: fixed; top: 0; left: 0; right: 0; } .sort-wrap { position: fixed; left: 0; right: 0; } .height-100 { height: 100rpx; } .block-180 { width: 180rpx; min-width: 180rpx; height: 180rpx; min-height: 180rpx; position: relative; image { width: 100%; height: 100%; border-radius: 8rpx; } .null { position: absolute; top: 0; right: 0; bottom: 0; left: 0; border-radius: 8rpx; background-color: rgba(0, 0, 0, 0.45); color: #ffffff; font-size: 36rpx; text-align: center; line-height: 180rpx; } } .list-item+.list-item { border-top: 1rpx solid #eeeeee; } .overlay-animate { position: fixed; } .float-action { width: 72rpx; height: 72rpx; border-radius: 50%; // background-color: rgba(165, 165, 165, .85); position: fixed; right: 20rpx; bottom: 280rpx; z-index: 996; border: 1rpx solid #cccccc; .cuIcon-cart { color: #cccccc; } } .animate { position: fixed; border-radius: 50%; z-index: 995; transform-origin: 50% 50%; transition: transform linear 0.5s, left linear 0.5s, top cubic-bezier(0.3, -0.2, 1, 0) 0.5s !important; image { width: 100rpx; height: 100rpx; border-radius: 50%; } } // 商品卡片line .fu-goods-line { /* min-height: 570rpx; */ // padding: 24rpx 0; border-radius: 16rpx; background-color: #ffffff; // margin-top: 20rpx; display: flex; // border-bottom: 1rpx solid #EEEEEE; margin-bottom: 24rpx; width: calc(100% - 20px); margin: 10px; .block-246 { // padding: 24rpx 24rpx 0; .img { width: 140rpx; height: 140rpx; border-radius: 6rpx; background-color: #eeeeee; } } .content { flex: 1; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between; } } // 商品卡片block .fu-goods-block { overflow: hidden; margin-bottom: 20rpx; padding: 0 10rpx; .wrap-box { background-color: #ffffff; border-radius: 16rpx; .square-wrap { width: 100%; height: 0; padding-bottom: 100%; box-sizing: border-box; position: relative; .square-box { position: absolute; left: 0; top: 0; right: 0; bottom: 0; border-radius: 16rpx 16rpx 0 0; image { width: 100%; height: 100%; border-radius: 24rpx 24rpx 0 0; } } } .image { width: 100%; border-radius: 24rpx 24rpx 0 0; } } .content { padding: 20rpx; } } .item-activity-label { padding: 2rpx 5rpx; /* margin: 5rpx; */ font-size: 24rpx; border-radius: 6rpx; border: 1px solid; margin: 0rpx 1px 0px; display: inline-block; transform: scale(0.8); } .search-form { margin-left: 12rpx; } .item-goods-label { padding: 4rpx 10rpx; margin-right: 10rpx; height: 32rpx; background: rgba(255, 239, 239, 1); border-radius: 4px; color: #ff6464; font-size: 24rpx; text-align: center; width: 84rpx; } .item-activity-label { padding: 0 8rpx; height: 32rpx; line-height: 30rpx; border: 1px solid #FA2033; opacity: 1; border-radius: 4rpx; font-size: 20rpx; font-family: PingFang SC; font-weight: 400; color: #FA2033; margin-right: 16rpx; &:nth-of-type(1) { border: 1px solid #0A7CE6; color: #0A7CE6; } } .padding-lr-24 { padding: 0 24rpx; } .padding-lr-4 { padding: 0 4rpx; } .sales-number { margin-top: 16rpx; } .through-price { margin-left: 16rpx; color: #BFBFBF; } ::v-deep .solid-bottom::after { border-bottom: 0; } .pr { position: relative; } .zd { position: absolute; z-index: 1; width: 30px; top: 0; left: 0 } .car { width: 104rpx; height: 104rpx; position: fixed; right: 28rpx; bottom: 300rpx; background: url(https://apps.xiaodan01.com/xcx/car-s.png); background-size: 100% 100%; } // new .template-circle { max-height: 100vh; } .tn-tabbar-height { min-height: 120rpx; height: calc(140rpx + env(safe-area-inset-bottom) / 2); } /* 自定义导航栏内容 start */ .custom-nav { height: 100%; &__back { margin: auto 5rpx; font-size: 40rpx; margin-right: 10rpx; margin-left: 30rpx; flex-basis: 5%; } &__search { flex-basis: 60%; width: 100%; height: 100%; &__box { width: 100%; height: 70%; padding: 10rpx 0; margin: 0 30rpx; border-radius: 60rpx 60rpx 0 60rpx; font-size: 24rpx; } &__icon { padding-right: 10rpx; margin-left: 20rpx; font-size: 30rpx; } &__text { color: #AAAAAA; } } } .logo-image { width: 60rpx; height: 60rpx; position: relative; margin-top: -15rpx; } .logo-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 50%; } /* 自定义导航栏内容 end */ /* 博主头像 start*/ .image-circle { // padding: 95rpx; width: 190rpx; height: 190rpx; font-size: 40rpx; font-weight: 300; position: relative; } .image-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 10rpx; } /* 文章内容 start*/ .blogger { &__item { padding: 30rpx; } &__author { &__btn { margin-right: -12rpx; opacity: 0.5; } } &__desc { line-height: 55rpx; &__label { padding: 0 20rpx; margin: 0rpx 18rpx 0 0; &--prefix { color: #00FFC8; padding-right: 10rpx; } } &__content {} } &__content { margin-top: 18rpx; padding-right: 18rpx; &__data { line-height: 46rpx; text-align: justify; overflow: hidden; transition: all 0.25s ease-in-out; } &__status { margin-top: 10rpx; font-size: 26rpx; color: #82B2FF; } } &__main-image { border-radius: 16rpx; &--1 { max-width: 80%; max-height: 300rpx; } &--2 { max-width: 260rpx; max-height: 260rpx; } &--3 { height: 212rpx; width: 100%; } } &__count-icon { font-size: 40rpx; padding-right: 5rpx; } &__ad { width: 100%; height: 500rpx; transform: translate3d(0px, 0px, 0px) !important; ::v-deep .uni-swiper-slide-frame { transform: translate3d(0px, 0px, 0px) !important; } .uni-swiper-slide-frame { transform: translate3d(0px, 0px, 0px) !important; } &__item { position: absolute; width: 100%; height: 100%; transform-origin: left center; transform: translate3d(100%, 0px, 0px) scale(1) !important; transition: transform 0.25s ease-in-out; z-index: 1; &--0 { transform: translate3d(0%, 0px, 0px) scale(1) !important; z-index: 4; } &--1 { transform: translate3d(13%, 0px, 0px) scale(0.9) !important; z-index: 3; } &--2 { transform: translate3d(26%, 0px, 0px) scale(0.8) !important; z-index: 2; } } &__content { border-radius: 40rpx; width: 640rpx; height: 500rpx; overflow: hidden; } &__image { width: 100%; height: 100%; } } } /* 文章内容 end*/ /* 间隔线 start*/ .tn-strip-bottom { width: 100%; border-bottom: 20rpx solid rgba(241, 241, 241, 0.8); } /* 间隔线 end*/ /* 广告内容 start */ .ad-image { width: 80rpx; height: 80rpx; position: relative; } .ad-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 20%; } /* 自定义导航栏内容 end */ /* 全屏轮播 start*/ .card-swiper { height: 100vh !important; } .card-swiper swiper-item { width: 750rpx !important; left: 0rpx; box-sizing: border-box; overflow: initial; } .card-swiper swiper-item .swiper-item { width: 100%; display: block; height: 100vh; border-radius: 0rpx; transform: scale(1); transition: all 0.2s ease-in 0s; overflow: hidden; } .card-swiper swiper-item.cur .swiper-item { transform: none; transition: all 0.2s ease-in 0s; } .card-swiper swiper-item .swiper-item-png { margin-top: -50vh; width: 100%; display: block; border-radius: 0rpx; transform: translate(1040rpx, 20rpx) scale(0.5, 0.5); transition: all 0.6s ease 0s; // overflow: hidden; } .card-swiper swiper-item.cur .swiper-item-png { margin-top: -100vh; width: 900rpx; transform: translate(-80rpx, 0rpx) scale(1, 1); transition: all 0.6s ease 0s; } .image-banner { display: flex; align-items: center; justify-content: center; } .image-banner image { width: 100%; } /* 轮播指示点 start*/ .indication { z-index: 9999; width: 100%; height: 36rpx; position: fixed; // display:flex; display: block; flex-direction: row; align-items: center; justify-content: center; } .spot { background-color: #000; opacity: 0.3; width: 10rpx; height: 10rpx; border-radius: 20rpx; margin: 20rpx 0 !important; left: 95vw; top: -60vh; position: relative; } .spot.active { opacity: 0.6; height: 30rpx; background-color: #000; } /* 资讯主图 start*/ .image-article { border-radius: 8rpx; border: 1rpx solid #F8F7F8; width: 200rpx; height: 200rpx; position: relative; } .image-pic { background-size: cover; background-repeat: no-repeat; // background-attachment:fixed; background-position: top; border-radius: 10rpx; } .article-shadow { border-radius: 15rpx; box-shadow: 0rpx 0rpx 50rpx 0rpx rgba(0, 0, 0, 0.07); } /* 文字截取*/ .clamp-text-1 { -webkit-line-clamp: 1; display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; overflow: hidden; } .clamp-text-2 { -webkit-line-clamp: 2; display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; overflow: hidden; } /* 标签内容 start*/ .tn-tag-content { &__item { display: inline-block; line-height: 35rpx; padding: 5rpx 25rpx; &--prefix { padding-right: 10rpx; } } } /* 图标容器9 start */ .icon9 { &__item { width: 30%; background-color: #FFFFFF; border-radius: 10rpx; padding: 30rpx; margin: 20rpx 10rpx; transform: scale(1); transition: transform 0.3s linear; transform-origin: center center; &--icon { width: 110rpx; height: 110rpx; font-size: 65rpx; border-radius: 50%; margin: 20rpx 40rpx; position: relative; z-index: 1; &::after { content: " "; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; bottom: 0; border-radius: inherit; opacity: 1; transform: scale(1, 1); background-size: 100% 100%; background-image: url(https://resource.tuniaokj.com/images/cool_bg_image/icon_bg5.png); } } } } /* 悬浮 */ .tnxuanfu { animation: suspension 3s ease-in-out infinite; } @keyframes suspension { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-0.8rem); } } /* 悬浮按钮 */ .button-shop { width: 90rpx; height: 90rpx; display: flex; flex-direction: row; position: fixed; /* bottom:200rpx; right: 20rpx; */ left: 5rpx; top: 5rpx; z-index: 1001; border-radius: 100px; opacity: 0.9; } /* 按钮 */ .edit { bottom: 300rpx; right: 75rpx; position: fixed; z-index: 9999; } .pa, .pa0 { position: absolute } /* 展开容器:左右布局 */ .expand-container { display: flex; align-items: flex-start; /* 垂直顶部对齐 */ justify-content: space-between; width: 100%; padding: 0 30rpx; /* 与内容对齐 */ color: #666; font-size: 28rpx; line-height: 1.5; } /* 文本部分 */ .blogger__desc__content { flex: 1; margin-right: 10rpx; word-break: break-word; } /* 限制为2行 */ .clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* 展开后不限制行数 */ .expanded { -webkit-line-clamp: unset !important; overflow: visible; display: block; } /* 右侧按钮区域 */ .toggle-button { display: flex; align-items: center; white-space: nowrap; /* 防止文字换行 */ color: #999; font-size: 26rpx; } </style>
最新发布
11-08
<template> <!-- 蒙层(全屏层级,仅覆盖非操作区) --> <view v-if="visible" class="zy-check-bottom-mask-layer" @click="handleMaskClick"> <view :class="{ 'zy-check-bottom-mask-false': !mask, 'zy-check-bottom-mask': mask }" :style="{ height: '100%' }" /> </view> <!-- 弹窗(独立层级,浮在蒙层之上) --> <view v-if="visible" class="zy-check-bottom-popup-wrapper"> <view class="zy-check-bottom-popup"> <!-- 可选项滚动区域 --> <scroll-view class="zy-check-bottom-options" :class="{ 'zy-check-bottom-options-scrollable': options.length > maxVisibleItems }" scroll-y :style="{ '--max-visible-height': maxVisibleHeight }" > <view v-for="(item, index) in options" :key="getValue(item)" class="zy-check-bottom-option-item" :class="{ 'zy-check-bottom-option-selected': isSelected(item) }" @click="toggleOption(item)" > <text class="zy-check-bottom-option-text" :class="{ 'zy-check-bottom-option-text-selected': isSelected(item) }" > {{ getLabel(item) }} </text> <uni-icons v-if="isSelected(item)" class="zy-check-bottom-checkmark" type="checkmarkempty" color="#0f56d5" /> </view> </scroll-view> <!-- 分割线 --> <view class="zy-check-bottom-divider" /> <!-- 取消按钮 --> <view class="zy-check-bottom-cancel" @click="handleCancel"> <text class="zy-check-bottom-cancel-text">取消</text> </view> </view> </view> </template> <script> export default { name: 'ZyCheckBottom', props: { modelValue: { type: Boolean, default: false }, options: { type: Array, required: true }, labelKey: { type: String, default: 'label' }, valueKey: { type: String, default: 'value' }, maxSelected: { type: Number, default: Infinity }, defaultSelected: { type: Array, default: () => [] }, mask: { type: Boolean, default: true }, maxVisibleItems: { type: Number, default: 3 } }, emits: ['update:modelValue', 'change', 'confirm'], data() { return { selectedValues: [...this.defaultSelected] } }, computed: { visible() { return this.modelValue }, maxVisibleHeight() { return `${this.maxVisibleItems * 57}px` } }, mounted() {}, methods: { getLabel(item) { return item[this.labelKey] }, getValue(item) { return item[this.valueKey] }, isSelected(item) { return this.selectedValues.includes(this.getValue(item)) }, toggleOption(item) { const value = this.getValue(item) const index = this.selectedValues.indexOf(value) if (index > -1) { this.selectedValues.splice(index, 1) this.$emit('change', { item, selected: false }) } else { if (this.selectedValues.length >= this.maxSelected) { uni.showToast({ title: `最多选中 ${this.maxSelected} 项`, icon: 'none', duration: 1500 }) return } this.selectedValues.push(value) this.$emit('change', { item, selected: true }) } }, handleCancel() { this.selectedValues = [...this.defaultSelected] // 恢复默认 this.close(true) }, handleMaskClick() { this.close(false) // 点击蒙层视为非取消关闭 }, close(fromCancel) { this.$emit('update:modelValue', false) this.$emit('confirm', { selected: this.selectedValues.map(val => this.options.find(opt => this.getValue(opt) === val)).filter(Boolean), fromCancel }) } } } </script> <style lang="scss"> /* 蒙层外层:覆盖全屏,但只显示上半部分 */ .zy-check-bottom-mask-layer { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 998; /* 蒙层层级 */ pointer-events: auto; } .zy-check-bottom-mask { width: 100%; background-color: #000000; opacity: 0.5; } .zy-check-bottom-mask-false { opacity: 0; width: 100%; } /* 弹窗外层:固定在底部,浮在蒙层之上 */ .zy-check-bottom-popup-wrapper { position: fixed; bottom: 0; left: 0; width: 100%; z-index: 999; /* 高于蒙层 */ background-color: #fff; /* 确保不侵入底部安全区 */ padding-bottom: env(safe-area-inset-bottom); /* ✅ 关键:顶部圆角 */ border-radius: 8px 8px 0 0; /* ✅ 确保子元素不溢出圆角边界 */ overflow: hidden; } /* 弹窗整体布局改为 flex 列布局 */ .zy-check-bottom-popup { background-color: #ffffff; width: 100%; box-sizing: border-box; display: flex; flex-direction: column; min-height: 57px; /* 防止空内容塌陷 */ } /* 滚动区域:允许纵向滚动,限制最大高度 */ .zy-check-bottom-options { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; max-height: var(--max-visible-height); /* 使用 CSS 变量 */ } .zy-check-bottom-options-scrollable { overflow-y: auto; } /* 单个选项保持居中等样式不变 */ .zy-check-bottom-option-item { position: relative; height: 57px; display: flex; align-items: center; justify-content: center; /* 主轴居中:X 轴居中 */ padding: 0 60rpx; box-sizing: border-box; } .zy-check-bottom-option-item::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; /* 先设成 1px */ background-color: #eeeeee; transform: scaleY(0.5); /* 缩小一半 → 视觉上就是 0.5px */ transform-origin: bottom; pointer-events: none; } .zy-check-bottom-option-item:last-child::after { display: none; } /* 文本:完全居中,不受对号影响 */ .zy-check-bottom-option-text { font-size: $uni-font-size-18; color: $uni-text-color; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: calc(100% - 100rpx); /* 防止太长碰到右边 */ text-align: center; z-index: 1; /* 确保在上层 */ } /* 选中状态文字颜色 */ .zy-check-bottom-option-selected .zy-check-bottom-option-text { color: $uni-primary; } .zy-check-bottom-option-text-selected { transform: translate(8px, 0px); } /* ✅ 对号:绝对定位,脱离文档流 */ .zy-check-bottom-checkmark { transform: translate(22px, 0px); color: $uni-primary; font-weight: bold; font-size: $uni-font-size-18; width: auto; height: auto; z-index: 2; /* 确保显示在上面 */ } /* 分割线:固定在取消按钮上方 */ .zy-check-bottom-divider { height: 8px; background-color: $uni-bg-color; /* 不再随内容滚动 */ } /* 取消按钮 */ .zy-check-bottom-cancel { height: 57px; display: flex; align-items: center; justify-content: center; } .zy-check-bottom-cancel-text { font-size: $uni-font-size-18; color: $uni-text-color; text-align: center; font-weight: 400; } </style>
09-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值