| | |
| | | } |
| | | </script> |
| | | |
| | | </style> |
| | | <style lang="scss"> |
| | | /*每个页面公共css */ |
| | | @import '@/uni_modules/uni-scss/index.scss'; |
对比新文件 |
| | |
| | | <template> |
| | | <view class="comment-item"> |
| | | <view class="comment-item-header"> |
| | | <view class="comment-item-header-left"> |
| | | <view class="avatar"> |
| | | <u-avatar :src="avatar" size="50" shape="circle" /> |
| | | </view> |
| | | <view class="comment-content"> |
| | | <view class="author"> |
| | | <text class="nickname">{{ nickname }}</text> |
| | | <view v-if="isAuthor" class="author-flag">作者</view> |
| | | </view> |
| | | <view class="comment-content-text"> |
| | | <text>{{ content }}</text> |
| | | <u-album :urls="images" multipleSize="180" singleSize="500"></u-album> |
| | | <text class="date">{{ date }}</text> |
| | | <text class="address">{{ address }}</text> |
| | | <text class="reply" @click="onReply">回复</text> |
| | | </view> |
| | | </view> |
| | | <view class="comment-opeartor"> |
| | | <u-icon name="heart" size="30" /> |
| | | <view class="comment-opeartor-heart-number">{{ likes }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view style="margin-left: 60rpx; margin-top: 10rrx;"> |
| | | <comment-sub-item avatar="https://img.yzcdn.cn/vant/cat.jpeg" nickname="图墙精选" :isAuthor="true" |
| | | content="如果路线里全是常规景区,没一个特殊的点位,那就是普通团,除非他的住宿安排的很好。。要不然和普通团没任何区别,都是去景区挤,然后上车赶路" :images="urls2" date="2天前" |
| | | address="湖北" :likes="30" @reply="showCommentLayer" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'CommentItem', |
| | | props: { |
| | | avatar: String, |
| | | nickname: String, |
| | | isAuthor: Boolean, |
| | | content: String, |
| | | images: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | date: String, |
| | | address: String, |
| | | likes: Number, |
| | | }, |
| | | data() { |
| | | return { |
| | | urls2: [ |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | ], |
| | | } |
| | | }, |
| | | methods: { |
| | | onReply() { |
| | | this.$emit('reply'); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .comment-item { |
| | | .comment-item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .comment-item-header-left { |
| | | display: flex; |
| | | width: 100%; |
| | | |
| | | .comment-content { |
| | | width: 92%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding-left: 10rpx; |
| | | |
| | | .author { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .nickname { |
| | | font-size: 30rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .author-flag { |
| | | font-size: 20rpx; |
| | | color: #ff4d4f; |
| | | font-weight: bold; |
| | | font-size: 18rpx; |
| | | border-radius: 50rpx; |
| | | padding: 5rpx 10rpx 5rpx 10rpx; |
| | | background-color: rgba(219, 19, 22, 0.219); |
| | | width: 40rpx; |
| | | margin-left: 10rpx; |
| | | height: 25rpx; |
| | | // border: 1px solid #ff4d4f; |
| | | } |
| | | } |
| | | |
| | | .comment-content-text { |
| | | margin-top: 10rpx; |
| | | font-size: 26rpx; |
| | | letter-spacing: 1rpx; |
| | | line-height: 1.5; |
| | | |
| | | .date { |
| | | font-size: 20rpx; |
| | | padding: 10rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .address { |
| | | font-size: 20rpx; |
| | | padding: 10rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .reply { |
| | | font-size: 24rpx; |
| | | padding: 10rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | .comment-opeartor { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | |
| | | // margin-left: 10rpx; |
| | | .comment-opeartor-heart-number { |
| | | width: 100%; |
| | | text-align: center; |
| | | font-size: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <u-popup :show="value" mode="bottom" @open="handleOpen" @close="handleClose" closeOnClickOverlay> |
| | | <view class="comment-popup"> |
| | | <u-textarea v-model="commentContent" placeholder="请输入内容" count :focus="isFocus" :cursor-spacing="150" |
| | | style="background-color: #999999;"></u-textarea> |
| | | |
| | | <view class="comment-btn-view"> |
| | | <view class="comment-btn-icon"> |
| | | <u-icon name="@" size="60" color="#999999"></u-icon> |
| | | <u-icon name="/static/common/smile.png" size="60" color="#999999"></u-icon> |
| | | <u-icon name="photo" size="60" color="#999999" @click="chooseImage"></u-icon> |
| | | <u-icon name="plus-circle" size="60" color="#999999"></u-icon> |
| | | </view> |
| | | <view class="comment-btn"> |
| | | <u-button :disabled="!canSend" type="error" shape="circle" text="发送" size="mini" |
| | | @click="sendComment"></u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 只有在图片选择后才显示上传组件 --> |
| | | <view class="comment-image-upload" v-if="fileList.length > 0"> |
| | | <u-upload :file-list="fileList" name="file" :auto-upload="false" :max-count="9" @afterRead="afterRead" |
| | | @delete="handleDelete" upload-text="上传图片" width="150" height="150" :cursor-spacing="150" |
| | | multiple="true"></u-upload> |
| | | </view> |
| | | |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "CommentPopup", |
| | | props: { |
| | | value: Boolean |
| | | }, |
| | | data() { |
| | | return { |
| | | commentContent: "", |
| | | isFocus: false, |
| | | focusLock: false, |
| | | fileList: [], |
| | | uploadUrl: "https://your-api.com/upload", // 替换为你的上传接口 |
| | | }; |
| | | }, |
| | | watch: { |
| | | value(newVal) { |
| | | if (!newVal) { |
| | | this.isFocus = false; |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | canSend() { |
| | | return this.commentContent.trim() !== '' || this.fileList.length > 0; |
| | | } |
| | | }, |
| | | methods: { |
| | | handleOpen() { |
| | | if (this.focusLock) return; |
| | | this.focusLock = true; |
| | | setTimeout(() => { |
| | | this.isFocus = true; |
| | | this.focusLock = false; |
| | | }, 300); |
| | | }, |
| | | handleClose() { |
| | | this.isFocus = false; |
| | | this.$emit("input", false); |
| | | }, |
| | | |
| | | |
| | | chooseImage() { |
| | | uni.chooseImage({ |
| | | count: 9 - this.fileList.length, |
| | | sizeType: ["original", "compressed"], |
| | | sourceType: ["album", "camera"], |
| | | success: (res) => { |
| | | console.log("选择的图片路径:", res.tempFilePaths); |
| | | res.tempFilePaths.forEach(filePath => { |
| | | const fileItem = { |
| | | url: filePath, |
| | | status: 'ready' |
| | | }; |
| | | this.fileList.push(fileItem); |
| | | this.uploadImage(filePath); // 调用上传 |
| | | }); |
| | | }, |
| | | fail: (err) => { |
| | | console.log("选择失败", err); |
| | | } |
| | | }); |
| | | }, |
| | | uploadImage(filePath) { |
| | | uni.uploadFile({ |
| | | url: this.uploadUrl, |
| | | filePath, |
| | | name: 'file', |
| | | success: (res) => { |
| | | console.log('上传成功', res); |
| | | // 你可以解析返回值,并更新 fileList 中对应的项 |
| | | }, |
| | | fail: (err) => { |
| | | console.error('上传失败', err); |
| | | } |
| | | }); |
| | | }, |
| | | afterRead(file) { |
| | | // 理论上这个不会触发了,因为你已经自己上传了 |
| | | }, |
| | | handleDelete(index, file) { |
| | | this.fileList.splice(index, 1); |
| | | }, |
| | | sendComment() { |
| | | if (!this.canSend) return; |
| | | |
| | | console.log("发送评论:", this.commentContent); |
| | | console.log("附带图片:", this.fileList.map(f => f.url)); |
| | | |
| | | // 这里处理评论内容和图片上传路径的提交逻辑 |
| | | // 例如向后端接口提交 |
| | | |
| | | // 清空状态 |
| | | this.commentContent = ""; |
| | | this.fileList = []; |
| | | this.handleClose(); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .comment-popup { |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .comment-btn-view { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .comment-btn-icon { |
| | | display: flex; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | .comment-btn { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .comment-image-upload { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .horizontal-scroll { |
| | | white-space: nowrap; |
| | | overflow-x: auto; |
| | | padding: 10rpx 0; |
| | | } |
| | | |
| | | .scroll-content { |
| | | display: inline-block; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="comment-item"> |
| | | <view class="comment-item-header"> |
| | | <view class="comment-item-header-left"> |
| | | <view class="avatar"> |
| | | <u-avatar :src="avatar" size="40" shape="circle" /> |
| | | </view> |
| | | <view class="comment-content"> |
| | | <view class="author"> |
| | | <text class="nickname">{{ nickname }}</text> |
| | | <view v-if="isAuthor" class="author-flag">作者</view> |
| | | </view> |
| | | <view class="comment-content-text"> |
| | | <text>{{ content }}</text> |
| | | <u-album :urls="images" multipleSize="180" singleSize="500"></u-album> |
| | | <text class="date">{{ date }}</text> |
| | | <text class="address">{{ address }}</text> |
| | | <text class="reply" @click="onReply">回复</text> |
| | | </view> |
| | | </view> |
| | | <view class="comment-opeartor"> |
| | | <u-icon name="heart" size="30" /> |
| | | <view class="comment-opeartor-heart-number">{{ likes }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'CommentItem', |
| | | props: { |
| | | avatar: String, |
| | | nickname: String, |
| | | isAuthor: Boolean, |
| | | content: String, |
| | | images: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | date: String, |
| | | address: String, |
| | | likes: Number, |
| | | }, |
| | | methods: { |
| | | onReply() { |
| | | this.$emit('reply'); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .comment-item { |
| | | .comment-item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .comment-item-header-left { |
| | | display: flex; |
| | | width: 100%; |
| | | |
| | | .comment-content { |
| | | width: 92%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding-left: 10rpx; |
| | | |
| | | .author { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .nickname { |
| | | font-size: 30rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .author-flag { |
| | | font-size: 20rpx; |
| | | color: #ff4d4f; |
| | | font-weight: bold; |
| | | font-size: 18rpx; |
| | | border-radius: 50rpx; |
| | | padding: 5rpx 10rpx 5rpx 10rpx; |
| | | background-color: rgba(219, 19, 22, 0.219); |
| | | width: 40rpx; |
| | | margin-left: 10rpx; |
| | | height: 25rpx; |
| | | // border: 1px solid #ff4d4f; |
| | | } |
| | | } |
| | | |
| | | .comment-content-text { |
| | | margin-top: 10rpx; |
| | | font-size: 26rpx; |
| | | letter-spacing: 1rpx; |
| | | line-height: 1.5; |
| | | |
| | | .date { |
| | | font-size: 20rpx; |
| | | padding: 10rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .address { |
| | | font-size: 20rpx; |
| | | padding: 10rpx; |
| | | color: #858585; |
| | | } |
| | | |
| | | .reply { |
| | | font-size: 24rpx; |
| | | padding: 10rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | .comment-opeartor { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | |
| | | // margin-left: 10rpx; |
| | | .comment-opeartor-heart-number { |
| | | width: 100%; |
| | | text-align: center; |
| | | font-size: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | </style> |
| | | |
| | |
| | | <template> |
| | | <view class="footer flex customer-footer flex-wrap-normal" style=""> |
| | | <view v-for="(item,index) in tabBar" :key="index" class="footer-item"> |
| | | <view class="item" :class="flg==index?'cur':''" @click="go(index,item)"> |
| | | <view v-for="(item, index) in tabBar" :key="index" class="footer-item"> |
| | | <!-- <view class="item" :class="flg == index ? 'cur' : ''" @click="go(index, item)"> --> |
| | | <view class="item" :class="currentIndex === index ? 'cur' : ''" @click="go(index, item)"> |
| | | |
| | | <!-- <view v-if="index==0"> |
| | | <!-- <view v-if="index==0"> |
| | | <image src="../../static/images/customer/footer/footer-home-1.png" class="footer-icon" |
| | | v-if="flg==0"></image> |
| | | <image src="../../static/images/customer/footer/footer-home-0.png" class="footer-icon" |
| | |
| | | v-if="flg!=3"></image> |
| | | </view> --> |
| | | |
| | | <view> |
| | | {{item.text}} |
| | | </view> |
| | | |
| | | <view> |
| | | {{ item.text }} |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | |
| | | |
| | | </view> |
| | | </template> |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | tabBar: [{ |
| | | export default { |
| | | data() { |
| | | return { |
| | | tabBar: [{ |
| | | |
| | | "text": "首页", |
| | | "pagePath": '/pages/home/home' |
| | | }, |
| | | { |
| | | |
| | | "text": "影视地图", |
| | | "pagePath": '/sub-pages/film-map/index' |
| | | }, |
| | | { |
| | | |
| | | "text": "行程规划", |
| | | "pagePath": '/sub-pages/customer/shopping/shopping' |
| | | }, |
| | | { |
| | | "text": "社区", |
| | | "pagePath": '/pages/user/supplier-user' |
| | | }, |
| | | { |
| | | "text": "我的", |
| | | "pagePath": '/pages/user/supplier-user' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | props: { |
| | | flg: { |
| | | type: String, |
| | | "text": "首页", |
| | | "pagePath": '/pages/home/home' |
| | | }, |
| | | bussincess: { |
| | | type: Boolean, |
| | | default () { |
| | | return false |
| | | } |
| | | } |
| | | }, |
| | | created() {}, |
| | | methods: { |
| | | { |
| | | |
| | | go(index, item) { |
| | | debugger; |
| | | |
| | | uni.navigateTo({ |
| | | url: item.pagePath |
| | | }) |
| | | |
| | | // if (index === 1 || index === 2) { |
| | | // //交易大厅和购物车,这2个可以用跳转方式 |
| | | |
| | | |
| | | // uni.navigateTo({ |
| | | // url: item.pagePath |
| | | // }) |
| | | |
| | | // } else { |
| | | // uni.reLaunch({ |
| | | // url: item.pagePath |
| | | // }); |
| | | // } |
| | | |
| | | "text": "影视地图", |
| | | "pagePath": '/sub-pages/film-map/index' |
| | | }, |
| | | { |
| | | |
| | | "text": "我的种草", |
| | | "pagePath": '/sub-pages/customer/shopping/shopping' |
| | | }, |
| | | { |
| | | "text": "社区", |
| | | "pagePath": '/pages/user/supplier-user' |
| | | }, |
| | | { |
| | | "text": "我的", |
| | | "pagePath": '/sub-pages/mine/index' |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | props: { |
| | | flg: { |
| | | type: String, |
| | | }, |
| | | bussincess: { |
| | | type: Boolean, |
| | | default() { |
| | | return false |
| | | } |
| | | } |
| | | }, |
| | | created() { }, |
| | | computed: { |
| | | currentPath() { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | return '/' + currentPage.route; |
| | | }, |
| | | currentIndex() { |
| | | return this.tabBar.findIndex(item => this.normalizePath(item.pagePath) === this.normalizePath(this.currentPath)); |
| | | } |
| | | }, |
| | | methods: { |
| | | normalizePath(path) { |
| | | return path.replace(/^\/+/, '/'); |
| | | }, |
| | | go(index, item) { |
| | | |
| | | // uni.navigateTo({ |
| | | // url: item.pagePath |
| | | // }) |
| | | uni.reLaunch({ |
| | | url: item.pagePath |
| | | }) |
| | | |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | @import "./main.scss"; |
| | | @import "./main.scss"; |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <u-popup :show="value" mode="left" @open="handleOpen" @close="handleClose" closeOnClickOverlay |
| | | customStyle="background-color: #FAFAFA;"> |
| | | <scroll-view scroll-y class="setting-scroll"> |
| | | <view class="setting-page"> |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="发现好友" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="创作者中心" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="我的草稿" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="我的评论" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="浏览记录" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="订单" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="购物车" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="钱包" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="小程序" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | <u-cell title="社区公约" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="小程序" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | |
| | | </u-cell-group> |
| | | <u-cell-group :border="false" :customStyle="cellGroupStyle"> |
| | | <u-cell title="社区公约" url="/pages/componentsB/tag/tag" :border="false"> |
| | | <u-icon slot="icon" :size="btnSize" name="search"></u-icon> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </view> |
| | | </scroll-view> |
| | | <view class="opeartor-view"> |
| | | <u-grid :border="false" @click="click"> |
| | | <u-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex" |
| | | @click="handleGridClick(baseListItem, baseListIndex)"> |
| | | <u-icon :customStyle="{ paddingTop: 20 + 'rpx' }" :name="baseListItem.name" :size="30"></u-icon> |
| | | <text class="grid-text">{{ baseListItem.title }}</text> |
| | | </u-grid-item> |
| | | </u-grid> |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "SettingPopup", |
| | | props: { |
| | | value: Boolean |
| | | }, |
| | | data() { |
| | | return { |
| | | cellGroupStyle: 'background-color: #ffffff; margin-bottom: 20rpx; border-radius: 16rpx;', |
| | | btnSize: 50, |
| | | baseList: [{ |
| | | name: 'scan', |
| | | title: '扫一扫' |
| | | }, |
| | | { |
| | | name: 'kefu-ermai', |
| | | title: '帮助与客服' |
| | | }, |
| | | { |
| | | name: 'setting', |
| | | title: '设置' |
| | | }, |
| | | ] |
| | | }; |
| | | }, |
| | | watch: { |
| | | value(newVal) { |
| | | if (!newVal) { |
| | | |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | |
| | | }, |
| | | methods: { |
| | | handleGridClick(item, index) { |
| | | console.log('点击了:', item, '索引为:', index); |
| | | |
| | | // 举例:根据 title 跳转 |
| | | if (item.title === '订单') { |
| | | uni.navigateTo({ |
| | | url: '/pages/order/index' |
| | | }); |
| | | } else if (item.title === '购物车') { |
| | | uni.navigateTo({ |
| | | url: '/pages/cart/index' |
| | | }); |
| | | } else { |
| | | // 通用跳转 |
| | | uni.navigateTo({ |
| | | url: item.url || '/pages/default/index' |
| | | }); |
| | | } |
| | | }, |
| | | handleOpen() { }, |
| | | handleClose() { |
| | | this.$emit("input", false); |
| | | }, |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .setting-page { |
| | | width: 400rpx; |
| | | padding: 20rpx; |
| | | box-sizing: border-box; |
| | | overflow-y: auto; |
| | | height: calc(100vh - 200rpx); |
| | | } |
| | | |
| | | .cell-group { |
| | | margin-bottom: 20rpx; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | .opeartor-view { |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | width: 100%; |
| | | padding: 10rpx; |
| | | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | z-index: 10; |
| | | box-sizing: border-box; |
| | | height: 200rpx; |
| | | |
| | | .grid-text { |
| | | font-size: 26rpx; |
| | | color: #909399; |
| | | padding: 10rpx 0 20rpx 0rpx; |
| | | /* #ifndef APP-PLUS */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="section"> |
| | | <u-row> |
| | | <u-col span="6"> |
| | | <view class="row"> |
| | | <u-icon v-if="iconName" :name="iconName" :size="iconSize" :color="iconColor" /> |
| | | <text class="theme-text left-text">{{ title }}</text> |
| | | </view> |
| | | </u-col> |
| | | <u-col span="3"></u-col> |
| | | <u-col span="3"> |
| | | <view class="row-right" @click="go(goUrl)"> |
| | | <text class="theme-text right-text ">{{ optitle }} </text> |
| | | <u-icon name="arrow-rightward" size="25" :color="'var(--icon-color)'" /> |
| | | </view> |
| | | </u-col> |
| | | </u-row> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'SectionTitle', |
| | | props: { |
| | | iconName: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | iconSize: { |
| | | type: [String, Number], |
| | | default: 40 |
| | | }, |
| | | iconColor: { |
| | | type: String, |
| | | default: 'yellow' |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | optitle: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | opIconColor: { |
| | | type: String, |
| | | default: 'white' |
| | | }, |
| | | goUrl: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | |
| | | |
| | | methods: { |
| | | go(url) { |
| | | if (url) { |
| | | uni.navigateTo({ |
| | | url |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | .section{ |
| | | margin-top: 30rpx; |
| | | } |
| | | |
| | | .space-between { |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .row { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | } |
| | | .row-right{ |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | justify-content: end; |
| | | } |
| | | |
| | | .left-text{ |
| | | font-size: 40rpx; |
| | | font-weight: bold; |
| | | color: var(--icon-color); |
| | | letter-spacing: 5rpx; |
| | | } |
| | | |
| | | .right-text{ |
| | | font-size: 25rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .theme-text { |
| | | margin-left: 10rpx; |
| | | } |
| | | </style> |
| | |
| | | import sectionTitle from '@/components/title/section-title' |
| | | Vue.component('section-title', sectionTitle) |
| | | |
| | | import sectionTitleBtn from '@/components/title/section-title-btn' |
| | | Vue.component('section-title-btn', sectionTitleBtn) |
| | | |
| | | // 评论组件 |
| | | import commentTtem from '@/components/comment/comment-item' |
| | | Vue.component('comment-item', commentTtem) |
| | | import commentsubTtem from '@/components/comment/comment-sub-item' |
| | | Vue.component('comment-sub-item', commentsubTtem) |
| | | |
| | | import commentPopup from '@/components/comment/comment-popup' |
| | | Vue.component('comment-popup', commentPopup) |
| | | |
| | | import topTabs from '@/components/top-tabs.vue' |
| | | Vue.component('top-tabs', topTabs) |
| | | |
| | |
| | | "": { |
| | | "dependencies": { |
| | | "moment": "^2.30.1", |
| | | "uview-ui": "^2.0.38" |
| | | "uview-ui": "^2.0.36" |
| | | }, |
| | | "devDependencies": { |
| | | "sass": "^1.77.6", |
| | |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/node": { |
| | | "version": "22.15.17", |
| | | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", |
| | | "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", |
| | | "version": "22.15.18", |
| | | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", |
| | | "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | |
| | | } |
| | | }, |
| | | "node_modules/electron-to-chromium": { |
| | | "version": "1.5.152", |
| | | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz", |
| | | "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==", |
| | | "version": "1.5.155", |
| | | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", |
| | | "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | |
| | | "peer": true |
| | | }, |
| | | "node_modules/sass": { |
| | | "version": "1.88.0", |
| | | "resolved": "https://registry.npmjs.org/sass/-/sass-1.88.0.tgz", |
| | | "integrity": "sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==", |
| | | "version": "1.89.0", |
| | | "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", |
| | | "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "chokidar": "^4.0.0", |
| | |
| | | } |
| | | }, |
| | | "node_modules/terser": { |
| | | "version": "5.39.0", |
| | | "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", |
| | | "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", |
| | | "version": "5.39.2", |
| | | "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.2.tgz", |
| | | "integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "dependencies": { |
| | | "@jridgewell/source-map": "^0.3.3", |
| | | "acorn": "^8.8.2", |
| | | "acorn": "^8.14.0", |
| | | "commander": "^2.20.0", |
| | | "source-map-support": "~0.5.20" |
| | | }, |
| | |
| | | "dev": true |
| | | }, |
| | | "@types/node": { |
| | | "version": "22.15.17", |
| | | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", |
| | | "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", |
| | | "version": "22.15.18", |
| | | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", |
| | | "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "requires": { |
| | |
| | | "optional": true |
| | | }, |
| | | "electron-to-chromium": { |
| | | "version": "1.5.152", |
| | | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz", |
| | | "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==", |
| | | "version": "1.5.155", |
| | | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", |
| | | "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", |
| | | "dev": true, |
| | | "peer": true |
| | | }, |
| | |
| | | "peer": true |
| | | }, |
| | | "sass": { |
| | | "version": "1.88.0", |
| | | "resolved": "https://registry.npmjs.org/sass/-/sass-1.88.0.tgz", |
| | | "integrity": "sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==", |
| | | "version": "1.89.0", |
| | | "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", |
| | | "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", |
| | | "dev": true, |
| | | "requires": { |
| | | "@parcel/watcher": "^2.4.1", |
| | |
| | | "peer": true |
| | | }, |
| | | "terser": { |
| | | "version": "5.39.0", |
| | | "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", |
| | | "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", |
| | | "version": "5.39.2", |
| | | "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.2.tgz", |
| | | "integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==", |
| | | "dev": true, |
| | | "peer": true, |
| | | "requires": { |
| | | "@jridgewell/source-map": "^0.3.3", |
| | | "acorn": "^8.8.2", |
| | | "acorn": "^8.14.0", |
| | | "commander": "^2.20.0", |
| | | "source-map-support": "~0.5.20" |
| | | } |
| | |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "root": "sub-pages/film-list", |
| | | "pages": [ |
| | | { |
| | | "path": "film-list", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true |
| | | } |
| | | } |
| | | |
| | | ,{ |
| | | "path": "film-detail", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true |
| | | // ,"navigationStyle": "custom" |
| | | } |
| | | } |
| | | ,{ |
| | | "path": "film-official-detail", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true |
| | | // ,"navigationStyle": "custom" |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "root": "sub-pages/mine", |
| | | "pages": [ |
| | | { |
| | | "path": "index", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": true |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "globalStyle": { |
| | |
| | | }, |
| | | methods: { |
| | | startExplore() { |
| | | this.showVideo = true; |
| | | // this.showVideo = true; |
| | | // 改成跳转到具体页面 |
| | | uni.navigateTo({ |
| | | url: '/sub-pages/film-list/film-list' |
| | | }); |
| | | }, |
| | | onVideoEnd() { |
| | | // 切换下一个视频 |
| | |
| | | <view class="main-content"> |
| | | <!-- 主要内容展示 --> |
| | | <HomeMain></HomeMain> |
| | | <!-- <view class="row"> |
| | | <u-icon name="star" size="40" color="yellow" /> |
| | | <text class="theme-text">内容精选</text> |
| | | </view> --> |
| | | <section-title title="内容精选" optitle="查看全部" goUrl="/pages/home/home-more" /> |
| | | <trip-card v-for="(item, index) in tripCardList" :key="index" :tag="item.tag" :title="item.title" |
| | | :subtitle="item.subtitle" :score="item.score" :imageUrl="item.imageUrl" :detailUrl="item.detailUrl" /> |
| | | |
| | | <!-- |
| | | <section-title-btn title="内容精选" optitle="查看全部" goUrl="/pages/home/home-more" /> --> |
| | | <view class="section"> |
| | | <u-row> |
| | | <u-col span="6"> |
| | | <view class="row"> |
| | | <!-- <u-icon v-if="iconName" :name="iconName" :size="iconSize" :color="iconColor" /> --> |
| | | <text class="theme-text left-text">内容精选</text> |
| | | </view> |
| | | </u-col> |
| | | <u-col span="3"></u-col> |
| | | <u-col span="3"> |
| | | <view class="row-right"> |
| | | <u-icon name="/static/common/left-arrow-dark.png" size="80" @click="prevPage" /> |
| | | <u-icon name="/static/common/right-arrow-dark.png" size="80" @click="nextPage" /> |
| | | </view> |
| | | </u-col> |
| | | </u-row> |
| | | </view> |
| | | |
| | | <view class="trip-card-swiper"> |
| | | <swiper :current="currentPage" @change="onSwiperChange" circular style="min-height: 1500rpx;"> |
| | | <swiper-item v-for="(group, pageIndex) in pagedTripCards" :key="pageIndex"> |
| | | <trip-card v-for="(item, index) in group" :key="index" :tag="item.tag" :title="item.title" |
| | | :subtitle="item.subtitle" :score="item.score" :imageUrl="item.imageUrl" |
| | | :detailUrl="item.detailUrl" /> |
| | | </swiper-item> |
| | | </swiper> |
| | | </view> |
| | | |
| | | <!-- <trip-card v-for="(item, index) in visibleTripCards" :key="index" :tag="item.tag" :title="item.title" |
| | | :subtitle="item.subtitle" :score="item.score" :imageUrl="item.imageUrl" :detailUrl="item.detailUrl" /> --> |
| | | |
| | | <section-title title="全球影视地标" optitle="查看全部" goUrl="/pages/home/home-more" /> |
| | | <global-geo /> |
| | | |
| | |
| | | return state.currentInfo || {} |
| | | }, |
| | | }), |
| | | visibleTripCards() { |
| | | const start = this.currentPage * this.pageSize; |
| | | const end = start + this.pageSize; |
| | | return this.tripCardList.slice(start, end); |
| | | }, |
| | | totalPages() { |
| | | return Math.ceil(this.tripCardList.length / this.pageSize); |
| | | }, |
| | | pagedTripCards() { |
| | | const pageSize = 3; |
| | | const pages = []; |
| | | for (let i = 0; i < this.tripCardList.length; i += pageSize) { |
| | | pages.push(this.tripCardList.slice(i, i + pageSize)); |
| | | } |
| | | return pages; |
| | | }, |
| | | }, |
| | | components: { |
| | | HomeMain, |
| | |
| | | score: 4.7, |
| | | imageUrl: 'https://ai-public.mastergo.com/ai/img_res/f2262cda01488f5f44f6eabf63e5dc5a.jpg', |
| | | detailUrl: '/pages/detail?id=125' |
| | | }, |
| | | { |
| | | tag: '史诗邮轮2', |
| | | title: '《权力的游戏》君临城朝圣之旅', |
| | | subtitle: '克罗地亚杜布罗夫尼克5日深度游', |
| | | score: 4.9, |
| | | imageUrl: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg', |
| | | detailUrl: '/pages/detail?id=123' |
| | | }, |
| | | { |
| | | tag: '经典路线2', |
| | | title: '冰岛极光探索之旅', |
| | | subtitle: '冬季极地风光6日深度体验', |
| | | score: 4.8, |
| | | imageUrl: 'https://ai-public.mastergo.com/ai/img_res/1a65e5ff6452efb1e6db001fcefd0b42.jpg', |
| | | detailUrl: '/pages/detail?id=124' |
| | | }, |
| | | { |
| | | tag: '文化探秘2', |
| | | title: '日本京都文化巡游', |
| | | subtitle: '探访古都名刹5日行程', |
| | | score: 4.7, |
| | | imageUrl: 'https://ai-public.mastergo.com/ai/img_res/f2262cda01488f5f44f6eabf63e5dc5a.jpg', |
| | | detailUrl: '/pages/detail?id=125' |
| | | } |
| | | ], |
| | | currentPage: 0, |
| | | pageSize: 3, |
| | | cardList: [ |
| | | { |
| | | image: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg', |
| | |
| | | this.theme = theme |
| | | }, |
| | | methods: { |
| | | |
| | | nextPage() { |
| | | if (this.currentPage < this.totalPages - 1) { |
| | | this.currentPage++; |
| | | } |
| | | // else{ |
| | | // this.currentPage = 0; |
| | | // } |
| | | }, |
| | | prevPage() { |
| | | if (this.currentPage > 0) { |
| | | this.currentPage--; |
| | | } |
| | | }, |
| | | onSwiperChange(e) { |
| | | this.currentPage = e.detail.current; |
| | | }, |
| | | |
| | | } |
| | | } |
| | |
| | | |
| | | <style scoped> |
| | | .main-content { |
| | | margin: 40rpx; |
| | | margin: 30rpx; |
| | | } |
| | | |
| | | .row { |
| | |
| | | margin-top: 20rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | </style> |
| | | |
| | | <style scoped lang="scss"> |
| | | .section { |
| | | // margin-top: 30rpx; |
| | | |
| | | .space-between { |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .row { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | } |
| | | |
| | | .row-right { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | // justify-content: end; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .left-text { |
| | | font-size: 40rpx; |
| | | font-weight: bold; |
| | | color: var(--icon-color); |
| | | letter-spacing: 5rpx; |
| | | } |
| | | |
| | | .right-text { |
| | | font-size: 25rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .theme-text { |
| | | margin-left: 10rpx; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | default: "" |
| | | } |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | |
对比新文件 |
| | |
| | | swiper-list 左右滑动切换顶部选项卡 |
| | | https://ext.dcloud.net.cn/plugin?id=2128 |
| | | |
| | | uni-swiper-dot 轮播图指示点 |
| | | https://ext.dcloud.net.cn/plugin?id=284 |
对比新文件 |
| | |
| | | <template> |
| | | <view :class="['app', theme]"> |
| | | |
| | | <!-- <u-swiper :list="list6" height="500" @change="e => currentNum = e.current" :autoplay="false" |
| | | indicatorStyle="right: 20px;top: 20px;" |
| | | > |
| | | <view slot="indicator" class="indicator-num"> |
| | | <text class="indicator-num__text">{{ currentNum + 1 }}/{{ list6.length }}</text> |
| | | </view> |
| | | </u-swiper> --> |
| | | |
| | | <view> |
| | | <u-swiper :list="list6" height="500" @change="e => currentNum = e.current" :autoplay="false"> |
| | | <view slot="indicator" class="indicator"> |
| | | <view class="indicator__dot" v-for="(item, index) in list6" :key="index" |
| | | :class="[index === currentNum && 'indicator__dot--active']"> |
| | | </view> |
| | | </view> |
| | | </u-swiper> |
| | | </view> |
| | | |
| | | |
| | | </view> |
| | | </template> |
| | | <script> |
| | | |
| | | export default { |
| | | components: { |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | current: 0, |
| | | currentNum: 0, |
| | | list6: [ |
| | | "https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg", |
| | | ], |
| | | list7: [ |
| | | "", |
| | | "", |
| | | "", |
| | | ], |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // 尝试读取缓存设置的主题 |
| | | console.log("theme", uni.getStorageSync('theme')) |
| | | const theme = uni.getStorageSync('theme') || 'light' |
| | | this.theme = theme |
| | | |
| | | |
| | | }, |
| | | methods: { |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | .indicator { |
| | | @include flex(row); |
| | | justify-content: center; |
| | | |
| | | &__dot { |
| | | height: 6px; |
| | | width: 6px; |
| | | border-radius: 100px; |
| | | background-color: rgba(255, 255, 255, 0.35); |
| | | margin: 0 5px; |
| | | transition: background-color 0.3s; |
| | | |
| | | &--active { |
| | | background-color: red; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .indicator-num { |
| | | padding: 2px 0; |
| | | background-color: rgba(0, 0, 0, 0.35); |
| | | border-radius: 100px; |
| | | width: 35px; |
| | | @include flex; |
| | | justify-content: center; |
| | | |
| | | &__text { |
| | | color: #ffffff; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- <view :class="['app', theme]"> --> |
| | | <view> |
| | | <view class="page"> |
| | | <u-sticky bgColor="#fff"> |
| | | <view class="card-footer"> |
| | | <view class="user-info"> |
| | | <u-avatar :src="user.avatar" size="60" shape="circle" /> |
| | | <view class="user-text"> |
| | | <text class="nickname">{{ user.username }}</text> |
| | | <!-- <text class="date">{{ item.date }}</text> --> |
| | | </view> |
| | | </view> |
| | | <view class="opera-info"> |
| | | |
| | | <button class="custom-btn">关注</button> |
| | | |
| | | <u-icon name="/static/common/share2.png" size="40" color="#999" /> |
| | | </view> |
| | | </view> |
| | | </u-sticky> |
| | | <scroll-view class="content" scroll-y> |
| | | <view class="swiper-container"> |
| | | <swiper :current="currentNum" @change="onSwiperChange" circular :autoplay="false" |
| | | class="custom-swiper"> |
| | | <swiper-item v-for="(item, index) in list6" :key="index" class="swiper-item"> |
| | | <image :src="item" mode="aspectFill" class="swiper-image" @tap="previewImage(index)" /> |
| | | </swiper-item> |
| | | </swiper> |
| | | |
| | | <!-- 自定义右上角索引 --> |
| | | <view class="indicator-num"> |
| | | <text class="indicator-num__text"> |
| | | {{ currentNum + 1 }}/{{ list6.length }} |
| | | </text> |
| | | |
| | | </view> |
| | | </view> |
| | | |
| | | |
| | | <view class="article-content"> |
| | | <view class="title content-item"> |
| | | <text>我是标题标题我是标题标题我是标题标题我是标题标题</text> |
| | | </view> |
| | | |
| | | <view class="content-item"> |
| | | <rich-text :nodes="desc"></rich-text> |
| | | </view> |
| | | <view class="annotation content-item"> |
| | | <text>4分钟前 美国</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <u-line></u-line> |
| | | |
| | | <view class="comment"> |
| | | |
| | | <view class="writer-view"> |
| | | <u-icon name="chat-fill" size="60" @click="showCommentLayer"></u-icon> |
| | | <view class="comment-operation" @click="showCommentLayer"> |
| | | <u-text size="12px" text="说点什么......" margin="0rpx 0rpx 0rpx 20rpx" |
| | | color="#B9B9B9"></u-text> |
| | | </view> |
| | | </view> |
| | | |
| | | |
| | | <comment-item avatar="https://img.yzcdn.cn/vant/cat.jpeg" nickname="图墙精选" :isAuthor="true" |
| | | content="如果路线里全是常规景区,没一个特殊的点位,那就是普通团,除非他的住宿安排的很好。。要不然和普通团没任何区别,都是去景区挤,然后上车赶路" :images="urls2" |
| | | date="2天前" address="湖北" :likes="30" @reply="showCommentLayer" /> |
| | | |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <!-- 固定底部输入框 --> |
| | | <view class="comment-box"> |
| | | |
| | | <view class="input-row"> |
| | | <view class="comment-input" @click="showCommentLayer"> |
| | | <u-text size="12px" text="说点什么......" margin="0rpx 0rpx 0rpx 20rpx" color="#B9B9B9" |
| | | confirmType="send"></u-text> |
| | | </view> |
| | | <u-icon name="heart" size="60" color="#B9B9B9" label="11"></u-icon> |
| | | <u-icon name="star" size="60" color="#B9B9B9" label="22"></u-icon> |
| | | <u-icon name="chat" size="60" color="#B9B9B9" label="33"></u-icon> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | <!-- <u-popup :show="commentShow" mode="bottom" @close="close" @open="open" closeOnClickOverlay="true"> |
| | | <view class="comment-popup"> |
| | | <u--textarea v-model="commentContent" placeholder="请输入内容" count focus="true"></u--textarea> |
| | | <view class="comment-btn-view"> |
| | | <view class="comment-btn-icon"> |
| | | <u-icon name=" " size="40" color="#999999" label="@" @click="close"></u-icon> |
| | | <u-icon name="/static/common/smile.png" size="40" color="#999999" @click="close"></u-icon> |
| | | <u-icon name="photo" size="40" color="#999999" @click="close"></u-icon> |
| | | <u-icon name="plus-circle" size="40" color="#999999" @click="close"></u-icon> |
| | | </view> |
| | | <view class="comment-btn"> |
| | | <u-button type="error" shape="circle" text="发送" size="mini" disabled></u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-popup> --> |
| | | <comment-popup v-model="commentShow" /> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | |
| | | export default { |
| | | components: { |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | commentShow: false, |
| | | commentContent: '', |
| | | value1: 0, |
| | | current: 0, |
| | | currentNum: 0, |
| | | desc: `😭…… |
| | | 刚从新疆旅游回来,真的踩了好多坑!!打算假期去新疆的姐妹们一定要做好攻略再来!! |
| | | 真的会少踩很多坑!熬夜整理这篇作为普通游客的避坑建议,一定要先看看!! |
| | | . |
| | | ✅【新疆全年玩法】 |
| | | 🚩11-3月:北疆喀纳斯、禾木玩雪;南疆慕士塔格冰川、喀什古城 |
| | | 🚩4-5月:伊犁土尔根杏花沟;南疆帕米尔杏花、大西沟杏花、库里塔格沙漠 |
| | | 🚩6-8月:伊犁那拉提草原、喀拉峻草原、赛里木湖、独库公路、喀纳斯 |
| | | 🚩9-10月:北疆喀纳斯、禾木;南疆胡杨林、罗布人村寨 |
| | | . |
| | | ❇️【自驾or跟团】 |
| | | ✔️新疆每天路程比较远,自驾可能有点累,而且景点比较分散,可以选择报个小团,都是年轻人,玩的也自由。 |
| | | ❌不建议大团喔,人多且很多时间在等人,并且有好看的风景不能随走随停! |
| | | . |
| | | 🚘【路线推荐】 |
| | | ✨D1:乌市—S201沙漠公路—乌伦古湖—五彩滩一布尔津 |
| | | ✨D2:布尔津—禾木桥—禾木村—禾木星空—住禾木 |
| | | ✨D3:禾木一观鱼亭一神仙湾月亮湾卧龙湾一住贾登峪/喀纳斯 |
| | | ✨D4:贾登峪一乌尔禾魔鬼城—乌尔禾 |
| | | ✨D5:乌尔禾一赛里木湖一果子沟大桥—清水河 |
| | | ✨D6:清水河—琼库什台-住特克斯 |
| | | ✨D7:琼库什台—那拉提 |
| | | ✨D8:那拉提—独库公路北段—唐布拉百里画廊—乌鲁木齐<br/> |
| | | . |
| | | #新疆是个好地方 #新疆旅行攻略 #新疆旅游 #不翻车旅行 #新疆小团 #新疆定制游 #旅游不踩坑 #新疆环线`, |
| | | user: { |
| | | id: 3, |
| | | username: '图墙精选', |
| | | avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', |
| | | |
| | | }, |
| | | list6: [ |
| | | "https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg", |
| | | "https://img.yzcdn.cn/vant/cat.jpeg", |
| | | "https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg", |
| | | ], |
| | | inputValue: '', |
| | | urls2: [ |
| | | "https://img.yzcdn.cn/vant/cat.jpeg" |
| | | ], |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // 尝试读取缓存设置的主题 |
| | | console.log("theme", uni.getStorageSync('theme')) |
| | | const theme = uni.getStorageSync('theme') || 'light' |
| | | this.theme = theme |
| | | |
| | | |
| | | }, |
| | | methods: { |
| | | onSwiperChange(e) { |
| | | this.currentNum = e.detail.current; |
| | | }, |
| | | previewImage(index) { |
| | | uni.previewImage({ |
| | | current: this.list6[index], |
| | | urls: this.list6 |
| | | }); |
| | | }, |
| | | click1(e) { console.log('click1', e); }, |
| | | submitComment() { |
| | | if (!this.inputValue) return; |
| | | this.comments.push(this.inputValue); |
| | | this.inputValue = ''; |
| | | }, |
| | | |
| | | showCommentLayer(e) { |
| | | this.commentShow = true |
| | | }, |
| | | open() { |
| | | // console.log('open'); |
| | | }, |
| | | close() { |
| | | this.commentShow = false |
| | | // console.log('close'); |
| | | } |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .page { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100vh; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .swiper-container { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 500rpx; |
| | | } |
| | | |
| | | .custom-swiper { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .swiper-item { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | |
| | | } |
| | | |
| | | .swiper-image { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: cover; |
| | | } |
| | | |
| | | .indicator-num { |
| | | position: absolute; |
| | | top: 20rpx; |
| | | right: 20rpx; |
| | | padding: 4rpx 12rpx; |
| | | background-color: rgba(0, 0, 0, 0.4); |
| | | border-radius: 20rpx; |
| | | } |
| | | |
| | | .indicator-num__text { |
| | | color: #fff; |
| | | font-size: 24rpx; |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss" scoped> |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10rpx; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | .user-info { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .user-text { |
| | | font-size: 30rpx; |
| | | line-height: 30px; |
| | | margin-left: 10rpx; |
| | | |
| | | .nickname { |
| | | font-weight: bold; |
| | | display: block; |
| | | color: #646464; |
| | | letter-spacing: 2rpx; |
| | | } |
| | | |
| | | .date { |
| | | font-size: 12px; |
| | | color: #aaa; |
| | | margin-top: 10rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .opera-info { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | text { |
| | | margin-left: 10rpx; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | .content { |
| | | .annotation { |
| | | margin-top: 10rpx; |
| | | font-size: 20rpx; |
| | | color: #646464; |
| | | } |
| | | } |
| | | |
| | | .comment { |
| | | margin: 10rpx; |
| | | |
| | | // border-top: 1rpx solid #EBEBEB; |
| | | .writer-view { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 30rpx; |
| | | |
| | | .comment-operation { |
| | | font-size: 18rpx; |
| | | background-color: #F4F4F6; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | border-radius: 20px; |
| | | width: 92%; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | .article-content { |
| | | padding: 10rpx; |
| | | font-size: 32rpx; |
| | | letter-spacing: 1rpx; |
| | | |
| | | .title { |
| | | font-size: 36rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .content-item { |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | |
| | | .comment-box { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | padding: 20rpx 20rpx; |
| | | background-color: #fff; |
| | | box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); |
| | | z-index: 999; |
| | | height: 100rpx; |
| | | .input-row { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | height: 80%; |
| | | |
| | | .comment-input { |
| | | width: 300rpx; |
| | | background-color: #F4F4F6; |
| | | border-radius: 50rpx; |
| | | height: 60rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | .flex-input { |
| | | flex: 1; |
| | | margin-right: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .comment-popup { |
| | | margin: 20rpx; |
| | | |
| | | .comment-btn-view { |
| | | margin-top: 20rpx; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | .comment-btn-icon{ |
| | | display: flex; |
| | | } |
| | | .comment-btn{ |
| | | |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | |
| | | <style scoped> |
| | | .custom-btn { |
| | | /* background-color: #ff4d4f; */ |
| | | margin: 0 10rpx; |
| | | /* 自定义背景色 */ |
| | | color: #ff4d4f; |
| | | /* 字体颜色 */ |
| | | font-size: 20rpx; |
| | | /* 字体大小 */ |
| | | border-radius: 50rpx; |
| | | /* 圆角 */ |
| | | padding: 10rpx 20rpx; |
| | | /* 内边距 */ |
| | | border: 1px solid #ff4d4f; |
| | | /* 去除边框 */ |
| | | line-height: 1; |
| | | } |
| | | |
| | | .custom-btn::after { |
| | | border: none; |
| | | /* 去除点击阴影边框 */ |
| | | } |
| | | </style> |
| | | |
| | | <style scoped> |
| | | .page { |
| | | height: 100vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding-bottom: 80rpx; |
| | | /* 留出评论区高度,避免遮挡 */ |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view :class="['app', theme]"> |
| | | <!-- <view class="page"> --> |
| | | <view style="padding-top: 10rpx ;"> |
| | | <u-search height="70" placeholder="搜索" searchIconSize="30" margin="0rpx 30rpx 0rpx 30rpx" v-model="search" |
| | | :show-action="true" @search="onSearch" @custom="onSearch" @clickIcon="onSearch" /> |
| | | </view> |
| | | |
| | | <!-- <u-tabs :list="tabList" @click="click"></u-tabs> --> |
| | | <u-tabs :list="tabList" @click="click"> |
| | | <view slot="right" style="padding-left: 4px;" @tap="$u.toast('插槽被点击')"> |
| | | <u-icon name="list" size="40" bold></u-icon> |
| | | </view> |
| | | </u-tabs> |
| | | |
| | | <view class="list-view"> |
| | | <waterfall ref="helangWaterfall" :col="2"> |
| | | <template v-slot:default="{ list, colWidth }"> |
| | | <waterfall-col v-for="(col, colIndex) in list" :key="colIndex" :colWidth="colWidth"> |
| | | <waterfall-item v-for="(item, itemIndex) in col" :key="item.__waterfall_renderId" :colIndex="colIndex" |
| | | :reportHeightTime="item.__waterfall_reportHeightTime" @height="onRenderHeight"> |
| | | <!-- 自定义内容 --> |
| | | <view class="card" @click="handleDetailClick(item)"> |
| | | <image :src="item.imgurl" mode="widthFix" class="card-image" style="width: 100%;" /> |
| | | <view class="card-title"> |
| | | <u--text :lines="2" size="14px" :text="item.title" :bold="true"></u--text> |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="user-info"> |
| | | <u-avatar :src="item.avatar" size="40" shape="circle" /> |
| | | <view class="user-text"> |
| | | <text class="nickname">{{ item.username }}</text> |
| | | <!-- <text class="date">{{ item.date }}</text> --> |
| | | </view> |
| | | </view> |
| | | <view class="opera-info"> |
| | | <u-icon name="heart" size="30" color="#999" /> |
| | | <text>{{ item.likes }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </waterfall-item> |
| | | </waterfall-col> |
| | | </template> |
| | | </waterfall> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Waterfall from '@/uni_modules/helang-waterfall/components/waterfall/waterfall-list'; |
| | | import WaterfallCol from '@/uni_modules/helang-waterfall/components/waterfall/waterfall-col'; |
| | | import WaterfallItem from '@/uni_modules/helang-waterfall/components/waterfall/waterfall-item'; |
| | | |
| | | |
| | | export default { |
| | | components: { |
| | | Waterfall, |
| | | WaterfallCol, |
| | | WaterfallItem, |
| | | }, |
| | | data() { |
| | | return { |
| | | theme: 'light', // 默认 light,可切换为 dark |
| | | windowHeight: uni.getSystemInfoSync().windowHeight, |
| | | search: '', |
| | | tabList: [{ |
| | | name: '关注', |
| | | }, { |
| | | name: '推荐', |
| | | }, { |
| | | name: '电影' |
| | | }, { |
| | | name: '科技' |
| | | }, { |
| | | name: '音乐' |
| | | }, { |
| | | name: '美食' |
| | | }, { |
| | | name: '文化' |
| | | }, { |
| | | name: '财经' |
| | | }, { |
| | | name: '手工' |
| | | }], |
| | | items: [ |
| | | { |
| | | id: 1, |
| | | title: 'iPhone 高清全屏壁纸,划走就后悔', |
| | | url: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg', |
| | | imgurl: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg', |
| | | username: '草莓喵喵', |
| | | avatar: '/static/avatar1.jpg', |
| | | date: '2024-12-01', |
| | | likes: 1397, |
| | | }, |
| | | { |
| | | id: 2, |
| | | title: '高清 4K 全屏手机壁纸 #高质量壁纸高清 4K 全屏手机壁纸 #高质量壁纸高清 4K 全屏手机壁纸 #高质量壁纸', |
| | | url: 'https://img.yzcdn.cn/vant/cat.jpeg', |
| | | imgurl: 'https://img.yzcdn.cn/vant/cat.jpeg', |
| | | username: '4K wallpaper', |
| | | avatar: '/static/avatar2.jpg', |
| | | date: '02-24', |
| | | likes: 167, |
| | | }, |
| | | { |
| | | id: 3, |
| | | title: 'iPhone 实况动态壁纸 #动态壁纸', |
| | | url: '/static/wallpaper3.jpg', |
| | | imgurl: 'https://img.yzcdn.cn/vant/cat.jpeg', |
| | | username: '图墙精选', |
| | | avatar: '/static/avatar3.jpg', |
| | | date: '03-01', |
| | | likes: 980, |
| | | }, |
| | | { |
| | | id: 4, |
| | | title: '高清小清新壁纸 浪漫的人都有自己的海', |
| | | url: '/static/wallpaper4.jpg', |
| | | imgurl: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg', |
| | | username: 'wallpaper', |
| | | avatar: '/static/avatar4.jpg', |
| | | date: '04-10', |
| | | likes: 456, |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // 尝试读取缓存设置的主题 |
| | | console.log("theme", uni.getStorageSync('theme')) |
| | | const theme = uni.getStorageSync('theme') || 'light' |
| | | this.theme = theme |
| | | |
| | | this.$refs.helangWaterfall.render(this.items, true); |
| | | }, |
| | | methods: { |
| | | onSearch(value) { |
| | | debugger; |
| | | uni.showToast({ |
| | | title: `搜索:${value}`, |
| | | icon: 'none' |
| | | }); |
| | | }, |
| | | |
| | | handleDetailClick(item) { |
| | | if (item.id === 1) { |
| | | uni.navigateTo({ |
| | | url: '/sub-pages/film-list/film-official-detail?id=' + item.id |
| | | }) |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: '/sub-pages/film-list/film-detail?id=' + item.id |
| | | }) |
| | | } |
| | | |
| | | }, |
| | | onRenderHeight({ colIndex, height, reportHeightTimeChange }) { |
| | | this.$refs.helangWaterfall.reportHeight({ |
| | | colIndex, |
| | | height, |
| | | reportHeightTimeChange |
| | | }) |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .page { |
| | | background-color: #F5F5F5; |
| | | } |
| | | |
| | | .list-view { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .filter-bar { |
| | | flex-wrap: wrap; |
| | | } |
| | | </style> |
| | | <style lang="scss"> |
| | | .card { |
| | | border-radius: 10rpx; |
| | | background-color: #FFFFFF; |
| | | font-size: 14px; |
| | | line-height: 20px; |
| | | color: rgb(51, 51, 51); |
| | | // border: 1rpx solid rgb(51, 51, 51); |
| | | |
| | | .card-image { |
| | | border-radius: inherit; |
| | | } |
| | | |
| | | .card-title { |
| | | padding: 10rpx; |
| | | // font-size: 14px; |
| | | font-weight: 500; |
| | | |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 10rpx; |
| | | } |
| | | |
| | | .user-info { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .user-text { |
| | | font-size: 18rpx; |
| | | line-height: 14px; |
| | | margin-left: 10rpx; |
| | | |
| | | .nickname { |
| | | font-weight: bold; |
| | | display: block; |
| | | color: #646464; |
| | | } |
| | | |
| | | .date { |
| | | font-size: 12px; |
| | | color: #aaa; |
| | | margin-top: 10rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .opera-info { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | text { |
| | | margin-left: 10rpx; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="timeline"> |
| | | <view class="timeline-item" v-for="(item, index) in timeList" :key="index"> |
| | | <!-- 左边时间点 --> |
| | | <view class="timeline-left"> |
| | | <view class="dot"></view> |
| | | <!-- 连线,最后一个不显示 --> |
| | | <view class="line" v-if="index !== timeList.length - 1"></view> |
| | | </view> |
| | | |
| | | <!-- 右边内容区域 --> |
| | | <view class="timeline-content"> |
| | | <!-- 你可以在这里自定义内容 --> |
| | | <view class="title"> |
| | | <text>{{ item.title }}</text> |
| | | <text class="time">{{ item.time }}</text> |
| | | </view> |
| | | <view class="desc"> |
| | | {{ item.description }} |
| | | </view> |
| | | <view class="extra" v-if="item.button"> |
| | | <u-button type="primary" size="mini" @click="onAction(item)">处理</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | timeList: [ |
| | | { |
| | | time: '2025-05-01', |
| | | title: '创建订单', |
| | | description: '用户提交订单信息,等待支付。', |
| | | button: true, |
| | | }, |
| | | { |
| | | time: '2025-05-02', |
| | | title: '订单支付', |
| | | description: '订单已支付,准备发货。', |
| | | }, |
| | | { |
| | | time: '2025-05-03', |
| | | title: '发货完成', |
| | | description: '物流:顺丰快递,单号 12345678', |
| | | }, |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | onAction(item) { |
| | | console.log('点击处理', item); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .timeline { |
| | | padding: 30rpx; |
| | | position: relative; |
| | | } |
| | | .timeline-item { |
| | | display: flex; |
| | | position: relative; |
| | | padding-bottom: 40rpx; |
| | | } |
| | | .timeline-left { |
| | | width: 40rpx; |
| | | position: relative; |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | .dot { |
| | | width: 16rpx; |
| | | height: 16rpx; |
| | | background-color: #2979ff; |
| | | border-radius: 50%; |
| | | margin-top: 4rpx; |
| | | } |
| | | .line { |
| | | position: absolute; |
| | | top: 24rpx; |
| | | width: 2rpx; |
| | | height: calc(100% - 24rpx); |
| | | background-color: #dcdfe6; |
| | | } |
| | | .timeline-content { |
| | | flex: 1; |
| | | padding-left: 20rpx; |
| | | } |
| | | .title { |
| | | font-weight: bold; |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | .time { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | .desc { |
| | | margin-top: 10rpx; |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | } |
| | | .extra { |
| | | margin-top: 10rpx; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="container"> |
| | | |
| | | <view class="movie-title"> |
| | | <view><u-text text="破.地狱" size="30"></u-text></view> |
| | | <view><u-text text="The Last Dance" size="20"></u-text></view> |
| | | </view> |
| | | |
| | | <scroll-view scroll-y class="content"> |
| | | <view class="movie-info"> |
| | | |
| | | <image class="movie-poster" src="https://ai-public.mastergo.com/ai/img_res/1ef11f7a594da679d35cddf809a63ec7.jpg" |
| | | mode="aspectFill" /> |
| | | <view class="movie-details"> |
| | | <view class="scene-number"> |
| | | <text>片场</text> |
| | | <text>17</text> |
| | | </view> |
| | | <view class="movie-tags"> |
| | | <text class="tag">剧情/家庭</text> |
| | | <text class="tag">中国香港</text> |
| | | <text class="tag">2024</text> |
| | | </view> |
| | | <u-button text="more" size="normal" icon="play-right-fill" plain type="info"></u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="movie-desc"> |
| | | <text class="desc-text">聚焦香港殡葬文化下的人际关系和生死观念,多数取景地都在殡仪服务扎堆的红磡。</text> |
| | | <text class="desc-text">主要拍摄的殡仪馆外景是万国殡仪馆,不过根据电影官方发布的制作花絮,殡仪馆内景大厅是另外搭建的。</text> |
| | | <text |
| | | class="desc-text">道生接手的"长生店"是位于九龙城福佬村道的百年老字号合昌殡仪,"Hello文"吃宵夜的地方在九龙湾的康乐茶居,火化延姐的地方在葵涌火葬场,甄小姐存户的东华义庄是香港目前唯一仍在运营的义庄。</text> |
| | | </view> |
| | | |
| | | <view class="map-container"> |
| | | <map style="width: 100%; height: 500rpx;" :latitude="latitude" :longitude="longitude" :markers="markers" |
| | | scale="16" show-location></map> |
| | | </view> |
| | | <view> |
| | | <u-tabs v-if="tabList.length" :list="tabList" :current="current" @change="onTabChange" @click="onTabChange" |
| | | lineColor="#2979ff" activeStyle="color: #2979ff"> |
| | | <view slot="left" style="padding-left: 4px;" @tap=""> |
| | | <u-icon name="/static/common/order.png" size="40" bold></u-icon> |
| | | </view> |
| | | <view slot="right" style="padding-left: 4px;" @tap="$u.toast('插槽被点击')"> |
| | | <u-icon name="list" size="40" bold></u-icon> |
| | | </view> |
| | | </u-tabs> |
| | | <swiper class="swiper-box" :current="current" @change="onSwiperChange" duration="300"> |
| | | <swiper-item v-for="(item, index) in tabList" :key="index" class="swiper-item"> |
| | | <film-official-timeline></film-official-timeline> |
| | | </swiper-item> |
| | | </swiper> |
| | | </view> |
| | | |
| | | <view class="comment-section"> |
| | | <u-button class="comment-btn" type="primary" plain>我要发言</u-button> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <view class="back-to-top" @click="scrollToTop"> |
| | | <u-icon name="arrow-up" size="24" color="#666666" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | import FilmOfficialTimeline from './film-official-timeline.vue'; |
| | | export default { |
| | | |
| | | components: { |
| | | FilmOfficialTimeline |
| | | }, |
| | | onLoad(option) { |
| | | // 获取当前位置 |
| | | uni.getLocation({ |
| | | type: 'gcj02', |
| | | success: (res) => { |
| | | this.latitude = res.latitude |
| | | this.longitude = res.longitude |
| | | this.markers = [ |
| | | { |
| | | id: 1, |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | title: "我的位置", |
| | | iconPath: "/static/common/marker.png", // 自定义图标路径 |
| | | width: 30, |
| | | height: 30 |
| | | } |
| | | ] |
| | | } |
| | | }), |
| | | |
| | | uni.getSystemInfo({ |
| | | success: (e) => { |
| | | // #ifdef MP-WEIXIN |
| | | let custom = uni.getMenuButtonBoundingClientRect(); |
| | | this.offsetHeight = custom.bottom + custom.top - e.statusBarHeight + 68; |
| | | // #endif |
| | | console.log('height', this.offsetHeight) |
| | | }, |
| | | }); |
| | | }, |
| | | |
| | | data() { |
| | | return { |
| | | offsetHeight: 0, |
| | | latitude: 0, |
| | | longitude: 0, |
| | | markers: [], |
| | | current: 0, |
| | | tabList: [ |
| | | { name: '剧情' }, |
| | | { name: '距离' }, |
| | | { name: '城市' }, |
| | | ], |
| | | }; |
| | | }, |
| | | methods: { |
| | | goBack() { |
| | | uni.navigateBack(); |
| | | }, |
| | | scrollToTop() { |
| | | uni.pageScrollTo({ |
| | | scrollTop: 0, |
| | | duration: 300 |
| | | }); |
| | | } |
| | | , onTabChange(item) { |
| | | this.current = item.index; // 切换 swiper 面板 |
| | | }, |
| | | onSwiperChange(e) { |
| | | this.current = e.detail.current; // 同步 tabs |
| | | }, |
| | | } |
| | | }; |
| | | </script> |
| | | <style lang="scss"> |
| | | ::v-deep .u-sticky { |
| | | z-index: 999 !important; |
| | | position: sticky; |
| | | left: 0; |
| | | } |
| | | </style> |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | background-color: #ffffff; |
| | | |
| | | .movie-title { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .center-text { |
| | | width: 100%; |
| | | text-align: center; |
| | | display: block; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | .content { |
| | | flex: 1; |
| | | overflow: auto; |
| | | } |
| | | |
| | | .movie-info { |
| | | padding: 32rpx; |
| | | display: flex; |
| | | gap: 32rpx; |
| | | } |
| | | |
| | | .movie-poster { |
| | | width: 400rpx; |
| | | height: 500rpx; |
| | | border-radius: 16rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .movie-details { |
| | | flex: 1; |
| | | } |
| | | |
| | | .scene-number { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | font-size: 32px; |
| | | color: #333333; |
| | | font-weight: bold; |
| | | margin-bottom: 16rpx; |
| | | } |
| | | |
| | | .movie-tags { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16rpx; |
| | | margin-bottom: 32rpx; |
| | | } |
| | | |
| | | .tag { |
| | | font-size: 14px; |
| | | color: #666666; |
| | | } |
| | | |
| | | |
| | | .movie-desc { |
| | | padding: 32rpx; |
| | | border-top: 1px dashed #f5f5f5; |
| | | border-bottom: 1px dashed #f5f5f5; |
| | | } |
| | | |
| | | .desc-text { |
| | | display: block; |
| | | font-size: 14px; |
| | | color: #666666; |
| | | line-height: 1.6; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .map-container { |
| | | padding: 32rpx; |
| | | } |
| | | |
| | | .map-image { |
| | | width: 100%; |
| | | border-radius: 16rpx; |
| | | } |
| | | |
| | | .comment-section { |
| | | padding: 32rpx; |
| | | } |
| | | |
| | | .comment-btn { |
| | | width: 100% !important; |
| | | height: 88rpx; |
| | | line-height: 88rpx; |
| | | background-color: #f5f5f5 !important; |
| | | color: #666666 !important; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .back-to-top { |
| | | position: fixed; |
| | | right: 32rpx; |
| | | bottom: 32rpx; |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 40rpx; |
| | | background-color: #ffffff; |
| | | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .swiper-box { |
| | | min-height: 50vh; |
| | | |
| | | /* 或者你希望的高度 */ |
| | | .swiper-item { |
| | | height: 100%; |
| | | overflow: auto; |
| | | /* 允许滚动内容 */ |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="timeline-container"> |
| | | |
| | | <view v-for="(item, index) in timeline" :key="index" class="timeline-item"> |
| | | <view class="timeline-time">{{ item.time }}</view> |
| | | <view class="timeline-content"> |
| | | <view class="info"> |
| | | <text class="title">{{ item.title }}</text> |
| | | <text class="desc">{{ item.subtitle }}</text> |
| | | <text class="desc">{{ item.location }}</text> |
| | | <text class="desc">{{ item.description }}</text> |
| | | </view> |
| | | <image :src="item.image" class="thumbnail" mode="aspectFill"></image> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "Timeline", |
| | | data() { |
| | | return { |
| | | timeline: [ |
| | | { |
| | | time: "01:21", |
| | | title: "万国殡仪馆", |
| | | subtitle: "International Funeral Parlour", |
| | | location: "中国香港", |
| | | description: "万国殡仪馆", |
| | | image: "https://dummyimage.com/120x70/cccccc/000000&text=Image1" |
| | | }, |
| | | { |
| | | time: "03:11", |
| | | title: "锦记粥粉面饭", |
| | | subtitle: "Kum Kee Restaurant", |
| | | location: "中国香港", |
| | | description: "道生见明叔的地方", |
| | | image: "https://dummyimage.com/120x70/cccccc/000000&text=Image2" |
| | | }, |
| | | { |
| | | time: "08:57", |
| | | title: "康乐茶居", |
| | | subtitle: "Hong Lok Tea House", |
| | | location: "中国香港", |
| | | description: "Hello文道生吃宵夜", |
| | | image: "https://dummyimage.com/120x70/cccccc/000000&text=Image3" |
| | | }, |
| | | { |
| | | time: "10:45", |
| | | title: "阳光洗衣便利店 金巴…", |
| | | subtitle: "Sunshine Laundry (Kimberly St…", |
| | | location: "中国香港", |
| | | description: "洗衣店", |
| | | image: "https://dummyimage.com/120x70/cccccc/000000&text=Image4" |
| | | } |
| | | ] |
| | | }; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .timeline-container { |
| | | padding: 20rpx; |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .timeline-title { |
| | | text-align: center; |
| | | font-size: 36rpx; |
| | | margin-bottom: 30rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .tabs { |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .tab-text { |
| | | font-size: 28rpx; |
| | | margin: 0 20rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .tab-text.active { |
| | | color: #000; |
| | | border-bottom: 4rpx solid #000; |
| | | padding-bottom: 6rpx; |
| | | } |
| | | |
| | | .tab-text.disabled { |
| | | color: #ccc; |
| | | } |
| | | |
| | | .timeline-item { |
| | | display: flex; |
| | | margin-bottom: 40rpx; |
| | | } |
| | | |
| | | .timeline-time { |
| | | color: #C1A14E; |
| | | font-size: 30rpx; |
| | | width: 100rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .timeline-content { |
| | | border-left: 2rpx solid #f0f0f0; |
| | | padding-left: 20rpx; |
| | | flex: 1; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .title { |
| | | font-size: 30rpx; |
| | | font-weight: bold; |
| | | display: block; |
| | | } |
| | | |
| | | .desc { |
| | | font-size: 24rpx; |
| | | color: #666; |
| | | display: block; |
| | | margin-top: 6rpx; |
| | | } |
| | | |
| | | .thumbnail { |
| | | width: 240rpx; |
| | | height: 140rpx; |
| | | margin-left: 20rpx; |
| | | border-radius: 8rpx; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="page"> |
| | | <view class="profile-section" :style="backgroundStyle"> |
| | | |
| | | <view class="top-bar"> |
| | | <u-icon name="list" size="60" color="#D0E1E9" /> |
| | | <view class="top-bar-right"> |
| | | <!-- <u-icon name="edit-pen" size="60" color="#ffffff" class="icon-margin" /> --> |
| | | <u-sticky><u-icon name="share" size="60" color="#D0E1E9" /></u-sticky> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="profile-content"> |
| | | |
| | | <view class="profile-header"> |
| | | <view class="avatar-container"> |
| | | <image class="avatar" |
| | | src="https://ai-public.mastergo.com/ai/img_res/e8ae645c666c247b895b488e60b048f5.jpg" |
| | | mode="aspectFill" /> |
| | | <view class="add-icon"> |
| | | <u-icon name="plus" size="20" color="#333" /> |
| | | </view> |
| | | </view> |
| | | <view class="user-info"> |
| | | <view class="username">小红薯 6786F040</view> |
| | | <view class="user-id">小红书号:95619601810</view> |
| | | <view class="location">IP 属地:江苏</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="edit-profile">点击这里,填写简介</view> |
| | | |
| | | <view class="stats"> |
| | | <view class="stat-row"> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">关注</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">粉丝</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">1</text> |
| | | <text class="label">获赞与收藏</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button text="编辑资料" size="mini" type="info" plain hairline |
| | | :custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }"></u-button> |
| | | <u-icon name="setting" size="40"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <scroll-view class="function-cards" scroll-x="true" show-scrollbar="false"> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">购物车</text> |
| | | <text class="card-subtitle">查看推荐好物</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">创作灵感</text> |
| | | <text class="card-subtitle">学创作找灵感</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | |
| | | <view class="tab-section"> |
| | | <u-sticky> |
| | | <u-tabs :list="tabList" :current="current" @change="onTabChange" lineColor="#2979ff" |
| | | activeStyle="color: #2979ff"></u-tabs> |
| | | </u-sticky> |
| | | <swiper class="swiper-box" :current="current" @change="onSwiperChange" duration="300"> |
| | | <swiper-item v-for="(item, index) in tabList" :key="index"> |
| | | <view class="empty-state"> |
| | | <image class="empty-icon" |
| | | src="https://ai-public.mastergo.com/ai/img_res/fc3cb775274ef0f5e58ac01687a9c121.jpg" |
| | | mode="aspectFit" /> |
| | | <text class="empty-text">快去发布你的笔记吧</text> |
| | | <u-button class="publish-btn" size="mini" type="warning" shape="circle">去发布</u-button> |
| | | </view> |
| | | </swiper-item> |
| | | </swiper> |
| | | </view> |
| | | |
| | | |
| | | <common-footer flg="0"></common-footer> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | backgroundUrl2: 'https://ai-public.mastergo.com/ai/img_res/25f5105167f00aff148acc9bb83aed54.jpg', // 可能是动态获取的图片 URL |
| | | backgroundUrl: '', |
| | | current: 0, |
| | | tabList: [ |
| | | { name: '笔记' }, |
| | | { name: '收藏' }, |
| | | { name: '赞过' }, |
| | | ], |
| | | } |
| | | }, |
| | | |
| | | computed: { |
| | | backgroundStyle() { |
| | | return this.backgroundUrl |
| | | ? `background: url(${this.backgroundUrl}) center center / cover no-repeat;` |
| | | : 'background-color: #1e1e1e;'; |
| | | } |
| | | }, |
| | | methods: { |
| | | getBackgroundStyle() { |
| | | if (this.backgroundUrl) { |
| | | return `background: url(${this.backgroundUrl}) center center / cover no-repeat;`; |
| | | } else { |
| | | return 'background-color: #f5f5f5;'; |
| | | } |
| | | }, |
| | | onTabChange(index) { |
| | | this.current = index; // 切换 swiper 面板 |
| | | }, |
| | | onSwiperChange(e) { |
| | | this.current = e.detail.current; // 同步 tabs |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style> |
| | | .page { |
| | | height: 100vh; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .top-bar { |
| | | position: relative; |
| | | z-index: 3; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 24rpx 32rpx; |
| | | } |
| | | |
| | | .top-bar-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .icon-margin { |
| | | margin-right: 32rpx; |
| | | } |
| | | |
| | | .profile-section { |
| | | position: relative; |
| | | /* height: 680rpx; */ |
| | | } |
| | | |
| | | .bg-image { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .profile-content { |
| | | position: relative; |
| | | z-index: 2; |
| | | padding: 30rpx; |
| | | } |
| | | |
| | | .profile-header { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .avatar-container { |
| | | position: relative; |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .avatar { |
| | | width: 120rpx; |
| | | height: 120rpx; |
| | | border-radius: 60rpx; |
| | | border: 2px solid #ffffff; |
| | | } |
| | | |
| | | .add-icon { |
| | | position: absolute; |
| | | right: -8rpx; |
| | | bottom: -8rpx; |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: #FFE411; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .user-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .username { |
| | | font-size: 30rpx; |
| | | color: #FCFFFE; |
| | | font-weight: bold; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .user-id, |
| | | .location { |
| | | font-size: 26rpx; |
| | | color: #666666; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .edit-profile { |
| | | color: #999999; |
| | | font-size: 26rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .stats { |
| | | display: flex; |
| | | /* margin-bottom: 20rpx; */ |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .stat-row { |
| | | display: flex; |
| | | } |
| | | |
| | | .stat-item { |
| | | margin-right: 48rpx; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .stat-item:last-child { |
| | | margin-right: auto; |
| | | } |
| | | |
| | | .number { |
| | | font-size: 30rpx; |
| | | color: #A19B99; |
| | | font-weight: bold; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .label { |
| | | font-size: 24rpx; |
| | | color: #B1ABA9; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 16rpx; |
| | | } |
| | | |
| | | .edit-btn { |
| | | padding: 0 24rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | } |
| | | |
| | | .settings-btn { |
| | | width: 80rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | padding: 0 !important; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .function-cards { |
| | | /* padding: 32rpx 0; */ |
| | | white-space: nowrap; |
| | | overflow: auto; |
| | | padding-bottom: 20rpx; |
| | | } |
| | | |
| | | .card { |
| | | display: inline-block; |
| | | width: 180rpx; |
| | | height: 80rpx; |
| | | margin-left: 20rpx; |
| | | background-color: rgba(60, 60, 60, 0.4); |
| | | /* 灰色 + 20% 透明度 */ |
| | | border-radius: 16rpx; |
| | | padding: 10rpx; |
| | | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .card:last-child { |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .card-content { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 30rpx; |
| | | color: #E7E1DF; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .card-subtitle { |
| | | font-size: 20rpx; |
| | | color: #BEBBB8; |
| | | } |
| | | |
| | | .tab-section { |
| | | padding: 0 32rpx; |
| | | } |
| | | |
| | | .tab-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 48rpx; |
| | | } |
| | | |
| | | .tab { |
| | | position: relative; |
| | | padding: 16rpx 0; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 48rpx; |
| | | height: 4rpx; |
| | | background-color: #333; |
| | | border-radius: 2rpx; |
| | | } |
| | | |
| | | .tab-text { |
| | | font-size: 16px; |
| | | color: #333; |
| | | margin-right: 8rpx; |
| | | } |
| | | |
| | | .tab-count { |
| | | font-size: 16px; |
| | | color: #999; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | padding: 48rpx 0; |
| | | min-height: 600rpx; |
| | | } |
| | | |
| | | .empty-icon { |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #999; |
| | | /* margin-bottom: 24rpx; */ |
| | | } |
| | | |
| | | .publish-btn { |
| | | background-color: #ffe411 !important; |
| | | color: #333 !important; |
| | | border: none !important; |
| | | border-radius: 32rpx !important; |
| | | padding: 0 48rpx !important; |
| | | } |
| | | </style> |
| | | <style lang="scss" scoped> |
| | | .swiper-box { |
| | | // min-height: 600rpx; |
| | | /* 或 100vh,或具体 px */ |
| | | height: 800px; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="page"> |
| | | <view class="profile-section" :style="backgroundStyle"> |
| | | <view class="top-bar"> |
| | | <u-icon name="list" size="60" color="#D0E1E9" /> |
| | | <view class="top-bar-right"> |
| | | <!-- <u-icon name="edit-pen" size="60" color="#ffffff" class="icon-margin" /> --> |
| | | <u-icon name="share" size="60" color="#D0E1E9" /> |
| | | </view> |
| | | </view> |
| | | <view class="profile-content"> |
| | | |
| | | <view class="profile-header"> |
| | | <view class="avatar-container"> |
| | | <image class="avatar" |
| | | src="https://ai-public.mastergo.com/ai/img_res/e8ae645c666c247b895b488e60b048f5.jpg" |
| | | mode="aspectFill" /> |
| | | <view class="add-icon"> |
| | | <u-icon name="plus" size="20" color="#333" /> |
| | | </view> |
| | | </view> |
| | | <view class="user-info"> |
| | | <view class="username">小红薯 6786F040</view> |
| | | <view class="user-id">小红书号:95619601810</view> |
| | | <view class="location">IP 属地:江苏</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="edit-profile">点击这里,填写简介</view> |
| | | |
| | | <view class="stats"> |
| | | <view class="stat-row"> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">关注</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">粉丝</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">1</text> |
| | | <text class="label">获赞与收藏</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button text="编辑资料" size="mini" type="info" plain hairline |
| | | :custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }"></u-button> |
| | | <u-icon name="setting"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <scroll-view class="function-cards" scroll-x="true" show-scrollbar="false"> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">购物车</text> |
| | | <text class="card-subtitle">查看推荐好物</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">创作灵感</text> |
| | | <text class="card-subtitle">学创作找灵感</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | <view class="tab-section"> |
| | | <view class="tab-header"> |
| | | <view class="tab active"> |
| | | <text class="tab-text">笔记</text> |
| | | <text class="tab-count">0</text> |
| | | </view> |
| | | <view class="tab"> |
| | | <text class="tab-text">收藏</text> |
| | | <text class="tab-count">0</text> |
| | | </view> |
| | | <view class="tab"> |
| | | <text class="tab-text">赞过</text> |
| | | <text class="tab-count">0</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="empty-state"> |
| | | <image class="empty-icon" |
| | | src="https://ai-public.mastergo.com/ai/img_res/fc3cb775274ef0f5e58ac01687a9c121.jpg" |
| | | mode="aspectFit" /> |
| | | <text class="empty-text">快去发布你的笔记吧</text> |
| | | <u-button class="publish-btn" size="mini" type="warning" shape="circle">去发布</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <common-footer flg="0"></common-footer> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | backgroundUrl2: 'https://ai-public.mastergo.com/ai/img_res/25f5105167f00aff148acc9bb83aed54.jpg', // 可能是动态获取的图片 URL |
| | | backgroundUrl: '', |
| | | } |
| | | }, |
| | | |
| | | computed: { |
| | | backgroundStyle() { |
| | | return this.backgroundUrl |
| | | ? `background: url(${this.backgroundUrl}) center center / cover no-repeat;` |
| | | : 'background-color: #1e1e1e;'; |
| | | } |
| | | }, |
| | | methods: { |
| | | getBackgroundStyle() { |
| | | if (this.backgroundUrl) { |
| | | return `background: url(${this.backgroundUrl}) center center / cover no-repeat;`; |
| | | } else { |
| | | return 'background-color: #f5f5f5;'; |
| | | } |
| | | } |
| | | }, |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style> |
| | | .page { |
| | | height: 100%; |
| | | /* background-color: #ffffff; */ |
| | | } |
| | | |
| | | .top-bar { |
| | | position: relative; |
| | | z-index: 3; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 24rpx 32rpx; |
| | | } |
| | | |
| | | .top-bar-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .icon-margin { |
| | | margin-right: 32rpx; |
| | | } |
| | | |
| | | .profile-section { |
| | | position: relative; |
| | | height: 680rpx; |
| | | } |
| | | |
| | | .bg-image { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .profile-content { |
| | | position: relative; |
| | | z-index: 2; |
| | | padding: 30rpx; |
| | | } |
| | | |
| | | .profile-header { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .avatar-container { |
| | | position: relative; |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .avatar { |
| | | width: 120rpx; |
| | | height: 120rpx; |
| | | border-radius: 60rpx; |
| | | border: 2px solid #ffffff; |
| | | } |
| | | |
| | | .add-icon { |
| | | position: absolute; |
| | | right: -8rpx; |
| | | bottom: -8rpx; |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: #FFE411; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .user-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .username { |
| | | font-size: 30rpx; |
| | | color: #FCFFFE; |
| | | font-weight: bold; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .user-id, |
| | | .location { |
| | | font-size: 26rpx; |
| | | color: #666666; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .edit-profile { |
| | | color: #999999; |
| | | font-size: 26rpx; |
| | | margin-bottom: 32rpx; |
| | | } |
| | | |
| | | .stats { |
| | | display: flex; |
| | | margin-bottom: 32rpx; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | .stat-row{ |
| | | display: flex; |
| | | } |
| | | |
| | | .stat-item { |
| | | margin-right: 48rpx; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .stat-item:last-child { |
| | | margin-right: auto; |
| | | } |
| | | |
| | | .number { |
| | | font-size: 30rpx; |
| | | color: #A19B99; |
| | | font-weight: bold; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .label { |
| | | font-size: 24rpx; |
| | | color: #B1ABA9; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 16rpx; |
| | | } |
| | | |
| | | .edit-btn { |
| | | padding: 0 24rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | } |
| | | |
| | | .settings-btn { |
| | | width: 80rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | padding: 0 !important; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .function-cards { |
| | | /* padding: 32rpx 0; */ |
| | | white-space: nowrap; |
| | | overflow: auto; |
| | | } |
| | | |
| | | .card { |
| | | display: inline-block; |
| | | width: 180rpx; |
| | | height: 80rpx; |
| | | margin-left: 20rpx; |
| | | background-color: rgba(60, 60, 60, 0.4); |
| | | /* 灰色 + 20% 透明度 */ |
| | | border-radius: 16rpx; |
| | | padding: 24rpx; |
| | | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .card:last-child { |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .card-content { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 30rpx; |
| | | color: #E7E1DF; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .card-subtitle { |
| | | font-size: 20rpx; |
| | | color: #BEBBB8; |
| | | } |
| | | |
| | | .tab-section { |
| | | padding: 0 32rpx; |
| | | } |
| | | |
| | | .tab-header { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | margin-bottom: 48rpx; |
| | | } |
| | | |
| | | .tab { |
| | | position: relative; |
| | | padding: 16rpx 0; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 48rpx; |
| | | height: 4rpx; |
| | | background-color: #333; |
| | | border-radius: 2rpx; |
| | | } |
| | | |
| | | .tab-text { |
| | | font-size: 16px; |
| | | color: #333; |
| | | margin-right: 8rpx; |
| | | } |
| | | |
| | | .tab-count { |
| | | font-size: 16px; |
| | | color: #999; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | padding: 48rpx 0; |
| | | } |
| | | |
| | | .empty-icon { |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #999; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .publish-btn { |
| | | background-color: #ffe411 !important; |
| | | color: #333 !important; |
| | | border: none !important; |
| | | border-radius: 32rpx !important; |
| | | padding: 0 48rpx !important; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="page"> |
| | | <view class="profile-section" :style="backgroundStyle"> |
| | | |
| | | <view class="top-bar"> |
| | | <u-icon name="list" size="60" color="#D0E1E9" @click="onSettingClick" /> |
| | | <view class="top-bar-right"> |
| | | <!-- <u-icon name="edit-pen" size="60" color="#ffffff" class="icon-margin" /> --> |
| | | <u-icon name="share" size="60" color="#D0E1E9" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="profile-content"> |
| | | |
| | | <view class="profile-header"> |
| | | <view class="avatar-container"> |
| | | <image class="avatar" |
| | | src="https://ai-public.mastergo.com/ai/img_res/e8ae645c666c247b895b488e60b048f5.jpg" |
| | | mode="aspectFill" /> |
| | | <view class="add-icon"> |
| | | <u-icon name="plus" size="20" color="#333" /> |
| | | </view> |
| | | </view> |
| | | <view class="user-info"> |
| | | <view class="username">小红薯 6786F040</view> |
| | | <view class="user-id">小红书号:95619601810</view> |
| | | <view class="location">IP 属地:江苏</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="edit-profile">点击这里,填写简介</view> |
| | | |
| | | <view class="stats"> |
| | | <view class="stat-row"> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">关注</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">0</text> |
| | | <text class="label">粉丝</text> |
| | | </view> |
| | | <view class="stat-item"> |
| | | <text class="number">1</text> |
| | | <text class="label">获赞与收藏</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button text="编辑资料" size="mini" type="info" plain hairline |
| | | :custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }"></u-button> |
| | | <u-icon name="setting" size="40"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <scroll-view class="function-cards" scroll-x="true" show-scrollbar="false"> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">购物车</text> |
| | | <text class="card-subtitle">查看推荐好物</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">创作灵感</text> |
| | | <text class="card-subtitle">学创作找灵感</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | <view class="card"> |
| | | <view class="card-content"> |
| | | <text class="card-title">浏览记录</text> |
| | | <text class="card-subtitle">看过的笔记</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | |
| | | <view class="tab-section"> |
| | | <u-sticky> |
| | | <u-tabs :list="tabList" :current="current" @change="onTabChange" lineColor="#2979ff" |
| | | activeStyle="color: #2979ff"></u-tabs> |
| | | </u-sticky> |
| | | <swiper class="swiper-box" :current="current" @change="onSwiperChange" duration="300"> |
| | | <swiper-item v-for="(item, index) in tabList" :key="index"> |
| | | <view class="empty-state"> |
| | | <image class="empty-icon" |
| | | src="https://ai-public.mastergo.com/ai/img_res/fc3cb775274ef0f5e58ac01687a9c121.jpg" |
| | | mode="aspectFit" /> |
| | | <text class="empty-text">快去发布你的笔记吧</text> |
| | | <u-button class="publish-btn" size="mini" type="warning" shape="circle">去发布</u-button> |
| | | </view> |
| | | </swiper-item> |
| | | </swiper> |
| | | </view> |
| | | |
| | | <common-footer flg="0"></common-footer> |
| | | <setting-popup v-model="settingShow" /> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | import SettingPopup from '@/components/setting/setting-popup.vue' |
| | | export default { |
| | | components: { |
| | | SettingPopup |
| | | }, |
| | | data() { |
| | | return { |
| | | backgroundUrl2: 'https://ai-public.mastergo.com/ai/img_res/25f5105167f00aff148acc9bb83aed54.jpg', // 可能是动态获取的图片 URL |
| | | backgroundUrl: '', |
| | | current: 0, |
| | | tabList: [ |
| | | { name: '笔记' }, |
| | | { name: '收藏' }, |
| | | { name: '赞过' }, |
| | | ], |
| | | settingShow:false, |
| | | } |
| | | }, |
| | | |
| | | computed: { |
| | | backgroundStyle() { |
| | | return this.backgroundUrl |
| | | ? `background: url(${this.backgroundUrl}) center center / cover no-repeat;` |
| | | : 'background-color: #1e1e1e;'; |
| | | } |
| | | }, |
| | | methods: { |
| | | onSettingClick(){ |
| | | this.settingShow = true; |
| | | }, |
| | | getBackgroundStyle() { |
| | | if (this.backgroundUrl) { |
| | | return `background: url(${this.backgroundUrl}) center center / cover no-repeat;`; |
| | | } else { |
| | | return 'background-color: #f5f5f5;'; |
| | | } |
| | | }, |
| | | onTabChange(item) { |
| | | this.current = item.index; // 切换 swiper 面板 |
| | | }, |
| | | onSwiperChange(e) { |
| | | this.current = e.detail.current; // 同步 tabs |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style> |
| | | .page { |
| | | height: 100vh; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .top-bar { |
| | | position: relative; |
| | | z-index: 3; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 24rpx 32rpx; |
| | | } |
| | | |
| | | .top-bar-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .icon-margin { |
| | | margin-right: 32rpx; |
| | | } |
| | | |
| | | .profile-section { |
| | | position: relative; |
| | | /* height: 680rpx; */ |
| | | } |
| | | |
| | | .bg-image { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .profile-content { |
| | | position: relative; |
| | | z-index: 2; |
| | | padding: 30rpx; |
| | | } |
| | | |
| | | .profile-header { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .avatar-container { |
| | | position: relative; |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .avatar { |
| | | width: 120rpx; |
| | | height: 120rpx; |
| | | border-radius: 60rpx; |
| | | border: 2px solid #ffffff; |
| | | } |
| | | |
| | | .add-icon { |
| | | position: absolute; |
| | | right: -8rpx; |
| | | bottom: -8rpx; |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: #FFE411; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .user-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .username { |
| | | font-size: 30rpx; |
| | | color: #FCFFFE; |
| | | font-weight: bold; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .user-id, |
| | | .location { |
| | | font-size: 26rpx; |
| | | color: #666666; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .edit-profile { |
| | | color: #999999; |
| | | font-size: 26rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .stats { |
| | | display: flex; |
| | | /* margin-bottom: 20rpx; */ |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .stat-row { |
| | | display: flex; |
| | | } |
| | | |
| | | .stat-item { |
| | | margin-right: 48rpx; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .stat-item:last-child { |
| | | margin-right: auto; |
| | | } |
| | | |
| | | .number { |
| | | font-size: 30rpx; |
| | | color: #A19B99; |
| | | font-weight: bold; |
| | | margin-bottom: 4rpx; |
| | | } |
| | | |
| | | .label { |
| | | font-size: 24rpx; |
| | | color: #B1ABA9; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 16rpx; |
| | | } |
| | | |
| | | .edit-btn { |
| | | padding: 0 24rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | } |
| | | |
| | | .settings-btn { |
| | | width: 80rpx !important; |
| | | background-color: #f5f5f5 !important; |
| | | color: #333333 !important; |
| | | border: none !important; |
| | | padding: 0 !important; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .function-cards { |
| | | /* padding: 32rpx 0; */ |
| | | white-space: nowrap; |
| | | overflow: auto; |
| | | padding-bottom: 20rpx; |
| | | } |
| | | |
| | | .card { |
| | | display: inline-block; |
| | | width: 180rpx; |
| | | height: 80rpx; |
| | | margin-left: 20rpx; |
| | | background-color: rgba(60, 60, 60, 0.4); |
| | | /* 灰色 + 20% 透明度 */ |
| | | border-radius: 16rpx; |
| | | padding: 10rpx; |
| | | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .card:last-child { |
| | | margin-right: 24rpx; |
| | | } |
| | | |
| | | .card-content { |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 30rpx; |
| | | color: #E7E1DF; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .card-subtitle { |
| | | font-size: 20rpx; |
| | | color: #BEBBB8; |
| | | } |
| | | |
| | | .tab-section { |
| | | padding: 0 32rpx; |
| | | } |
| | | |
| | | .tab-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 48rpx; |
| | | } |
| | | |
| | | .tab { |
| | | position: relative; |
| | | padding: 16rpx 0; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 48rpx; |
| | | height: 4rpx; |
| | | background-color: #333; |
| | | border-radius: 2rpx; |
| | | } |
| | | |
| | | .tab-text { |
| | | font-size: 16px; |
| | | color: #333; |
| | | margin-right: 8rpx; |
| | | } |
| | | |
| | | .tab-count { |
| | | font-size: 16px; |
| | | color: #999; |
| | | } |
| | | |
| | | .empty-state { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | padding: 48rpx 0; |
| | | min-height: 600rpx; |
| | | } |
| | | |
| | | .empty-icon { |
| | | width: 200rpx; |
| | | height: 200rpx; |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .empty-text { |
| | | font-size: 14px; |
| | | color: #999; |
| | | /* margin-bottom: 24rpx; */ |
| | | } |
| | | |
| | | .publish-btn { |
| | | background-color: #ffe411 !important; |
| | | color: #333 !important; |
| | | border: none !important; |
| | | border-radius: 32rpx !important; |
| | | padding: 0 48rpx !important; |
| | | } |
| | | </style> |
| | | <style lang="scss" scoped> |
| | | .swiper-box { |
| | | // min-height: 600rpx; |
| | | /* 或 100vh,或具体 px */ |
| | | min-height: 800px; |
| | | } |
| | | </style> |
| | |
| | | transition: background-color 0.3s; |
| | | |
| | | &.light { |
| | | background-color: #ffffff; |
| | | background-color: #F5F5F5; |
| | | color: #000000; |
| | | --icon-color: #000000; |
| | | --section-title: #000000; |
对比新文件 |
| | |
| | | ## 1.2.4(2024-11-24) |
| | | - [优化] 新增 `udpate` 动态更新数据方法 |
| | | ## 1.2.3(2024-11-02) |
| | | - [修复] 组件重新渲染时未重置待渲染位置的问题 |
| | | - [优化] 图片宽度支持 px 单位 |
| | | ## 1.2.2(2024-10-18) |
| | | - [修复] 解决了因为数据id重复导致的 小程序平台 waterfall-item 组件不会重新渲染的问题 |
| | | ## 1.2.1(2024-10-07) |
| | | 全新升级为组件+插槽的方案实现,极大的简便了组件的使用和内容调整。 |
| | | ## 1.1.6(2022-10-24) |
| | | 修复 初始化渲染变量取值错误问题 |
| | | ## 1.1.5(2022-10-24) |
| | | 初始化渲染增加状态条件判断 |
| | | ## 1.1.4(2022-10-24) |
| | | 修改空数据提示 |
| | | ## 1.1.3(2022-10-24) |
| | | 1、增加内容插槽 |
| | | |
| | | 2、删除状态文本属性 |
| | | |
| | | 3、组件创建时可触发渲染条件 |
| | | ## 1.1.2(2022-09-26) |
| | | 修改了开启布局的判断条件 |
| | | ## 1.1.1(2022-08-28) |
| | | 1、加强组件化封装 |
| | | |
| | | 2、 完善注释和优化使用逻辑 |
| | | ## 1.1.0(2022-08-22) |
| | | 重写渲染列表逻辑 |
| | | ## 1.0.1(2021-06-08) |
| | | 修改插入方向计算方式 |
对比新文件 |
| | |
| | | export const wait = (time = 100)=>{ |
| | | return new Promise((resolve)=>{ |
| | | setTimeout(()=>{ |
| | | resolve(); |
| | | },time); |
| | | }) |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view class="waterfall-col" :style="{width:colWidth}"> |
| | | <slot name="default"></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | |
| | | export default { |
| | | name:"helangWaterfallCol", |
| | | options:{ |
| | | virtualHost: true |
| | | }, |
| | | components: { |
| | | |
| | | }, |
| | | props:{ |
| | | // 栏目宽度 |
| | | colWidth:{ |
| | | type: String, |
| | | default:'' |
| | | }, |
| | | }, |
| | | watch:{ |
| | | |
| | | }, |
| | | computed:{ |
| | | |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | mounted() { |
| | | |
| | | }, |
| | | methods: { |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .waterfall-col{ |
| | | padding:0 10rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view class="waterfall-item"> |
| | | <slot name="default"></slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { wait } from './js/utils.js'; |
| | | export default { |
| | | name:"helangWaterfallItem", |
| | | options:{ |
| | | virtualHost: true |
| | | }, |
| | | props:{ |
| | | colIndex:{ |
| | | type:Number, |
| | | default:0 |
| | | }, |
| | | reportHeightTime:{ |
| | | type:Number | String | undefined | null, |
| | | default:'' |
| | | } |
| | | }, |
| | | watch:{ |
| | | "$props.reportHeightTime"(newValue, oldValue){ |
| | | if(newValue !== oldValue){ |
| | | this.postHeight({ |
| | | reportHeightTimeChange:true |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.postHeight(); |
| | | }, |
| | | methods:{ |
| | | async postHeight(params){ |
| | | const { reportHeightTimeChange = false } = params ?? {}; |
| | | // 添加一个异步的宏任务,部分低性能的移动设备会因为渲染问题导致上报的高度存在错误问题 |
| | | await wait(10); |
| | | // 当前高度 |
| | | const currentHeight = await this.getHeight(); |
| | | // 显示高度 |
| | | const displayHeight = this.displayHeight || 0; |
| | | // 上报高度 |
| | | let height = currentHeight - displayHeight; |
| | | |
| | | // 上报高度为0时,取消上报。防止用户调用 update 函数时错误的reportHeight参数情况 |
| | | if(height === 0){ |
| | | return; |
| | | } |
| | | |
| | | this.$emit("height",{ |
| | | colIndex:this.$props.colIndex, |
| | | height, |
| | | reportHeightTimeChange |
| | | }); |
| | | // 缓存渲染高度 |
| | | this.displayHeight = currentHeight; |
| | | }, |
| | | getHeight(){ |
| | | const query = uni.createSelectorQuery().in(this); |
| | | return new Promise((resolve,reject)=>{ |
| | | query.select('.waterfall-item').boundingClientRect((data) => { |
| | | // 节点高度 |
| | | const height = Math.floor(data.height) || 0; |
| | | resolve(height); |
| | | }).exec(); |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .waterfall-item{ |
| | | & + .waterfall-item{ |
| | | margin-top:20rpx; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <view class="waterfall-box" :class="{'hidden':hideList}"> |
| | | <view class="h-flex-x helang-waterfall-slot"> |
| | | <slot name="default" v-bind:colWidth="colWidth" v-bind:list="renderList"></slot> |
| | | </view> |
| | | </view> |
| | | <slot name="tips"></slot> |
| | | <image |
| | | class="load-image" |
| | | v-for="(item,index) in waitRenderList" |
| | | :key="index" |
| | | v-if="item.__waterfall_imageHeight === undefined" |
| | | :src="item | imageLoadUrl" |
| | | :data-index="index" |
| | | @load="handleImageLoad" |
| | | @error="handleImageLoad" |
| | | ></image> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // 字符串前缀 |
| | | const prefixStr = '__waterfall_'; |
| | | // 图片高度键名 |
| | | const IMAGE_HEIGHT_KEY = `${prefixStr}imageHeight`; |
| | | // 图片缓存键名 |
| | | const IMAGE_CACHE_KEY = `${prefixStr}cacheImageHeight`; |
| | | // 是否渲染 |
| | | const ITEM_SHOW_KEY = `${prefixStr}show`; |
| | | // 渲染ID |
| | | const RENDER_ID = `${prefixStr}renderId`; |
| | | // 上报高度时间 |
| | | const REPORT_TIME = `${prefixStr}reportHeightTime`; |
| | | // 图片链接键名 |
| | | let IMAGE_URL_KEY = ''; |
| | | // 图片PX宽度 |
| | | let IMAGE_PX_WIDTH = 0; |
| | | // 渲染状态 |
| | | const RENDER_STATUS = { |
| | | // 加载中 |
| | | LOADING: 'RENDER_LOADING', |
| | | // 渲染开始 |
| | | START:'RENDER_START', |
| | | // 渲染结束 |
| | | END:'RENDER_END' |
| | | }; |
| | | |
| | | export default { |
| | | name:"helangWaterfallList", |
| | | options:{ |
| | | virtualHost: true |
| | | }, |
| | | components: { |
| | | |
| | | }, |
| | | props:{ |
| | | // 分栏 |
| | | col:{ |
| | | type: Number, |
| | | default:2 |
| | | }, |
| | | // 图片宽度 |
| | | imageWidth:{ |
| | | type: Number | String, |
| | | default:305 |
| | | }, |
| | | // 缓存高度(加速渲染) |
| | | cacheImageHeight:{ |
| | | type: Boolean, |
| | | default:true |
| | | }, |
| | | // 图片链接键名 |
| | | imageKey:{ |
| | | type: String, |
| | | default:'url' |
| | | }, |
| | | // 隐藏列表 |
| | | hideList:{ |
| | | type: Boolean, |
| | | default:false |
| | | }, |
| | | }, |
| | | filters:{ |
| | | imageLoadUrl(data){ |
| | | return data[IMAGE_URL_KEY] ?? ""; |
| | | } |
| | | }, |
| | | watch:{ |
| | | |
| | | }, |
| | | computed:{ |
| | | colWidth(){ |
| | | return `${1 / this.$props.col * 100}%`; |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 待渲染列表 |
| | | waitRenderList:[], |
| | | // 渲染列表 |
| | | renderList:[], |
| | | // 渲染列表高度 |
| | | renderListHeight:[] |
| | | } |
| | | }, |
| | | created() { |
| | | this.initRenderList(); |
| | | // 图片高度缓存 |
| | | if(!uni[IMAGE_CACHE_KEY]){ |
| | | uni[IMAGE_CACHE_KEY] = {}; |
| | | } |
| | | IMAGE_URL_KEY = this.$props.imageKey; |
| | | IMAGE_PX_WIDTH = this.getImagePxWidth(); |
| | | }, |
| | | mounted() { |
| | | |
| | | }, |
| | | methods: { |
| | | // 初始化渲染列表 |
| | | initRenderList(){ |
| | | let list = []; |
| | | let heights = []; |
| | | for(let i = 0; i < this.$props.col; i++){ |
| | | list.push([]); |
| | | heights.push(0); |
| | | } |
| | | this.renderList = list; |
| | | this.renderListHeight = heights; |
| | | this.waitPushIndex = 0; |
| | | }, |
| | | // 获取图片的 px 宽度 |
| | | getImagePxWidth(){ |
| | | const width = this.$props.imageWidth; |
| | | // 是否为px单位 |
| | | if(/^\d+px$/i.test(String(width))){ |
| | | return parseInt(width); |
| | | }else{ |
| | | return uni.upx2px(parseInt(width) || 0) |
| | | } |
| | | |
| | | }, |
| | | // 处理图片加载 |
| | | handleImageLoad(e){ |
| | | const { width = 0, height = 0 } = e.detail; |
| | | const { index } = e.currentTarget.dataset; |
| | | const renderHeight = width === 0 ? 0 : parseInt(IMAGE_PX_WIDTH / width * height); |
| | | |
| | | this.addWaitRenderListImageHeight(index, renderHeight); |
| | | |
| | | if(this.$props.cacheImageHeight){ |
| | | const imageUrl = this.waitRenderList[index][IMAGE_URL_KEY]; |
| | | if(imageUrl.length < 300){ |
| | | uni[IMAGE_CACHE_KEY][imageUrl] = renderHeight; |
| | | } |
| | | } |
| | | |
| | | if(this.checkImageHaveHeight()){ |
| | | this.emitRenderStatusChange(RENDER_STATUS.START); |
| | | this.addRenderData(); |
| | | } |
| | | }, |
| | | // 检查图片是否已全部包含高度 |
| | | checkImageHaveHeight(){ |
| | | const index = this.waitRenderList.findIndex((item)=>{ |
| | | return item[IMAGE_HEIGHT_KEY] === undefined; |
| | | }) |
| | | return index === -1 ? true : false; |
| | | }, |
| | | // 待渲染列表添加图片高度数据 |
| | | addWaitRenderListImageHeight(index,height){ |
| | | this.waitRenderList[index][IMAGE_HEIGHT_KEY] = height; |
| | | }, |
| | | // 查找最小高度的列的索引 |
| | | findSmallColIndex(){ |
| | | let col = 0; |
| | | let size = this.renderListHeight[col]; |
| | | this.renderListHeight.forEach((item,index)=>{ |
| | | if(item < size){ |
| | | col = index; |
| | | size = item; |
| | | } |
| | | }); |
| | | return col; |
| | | }, |
| | | // 追加渲染数据 |
| | | pushRender(data){ |
| | | const index = this.findSmallColIndex(); |
| | | const nowDate = Date.now(); |
| | | this.renderList[index].push({ |
| | | ...data, |
| | | [IMAGE_HEIGHT_KEY]: `${data[IMAGE_HEIGHT_KEY]}px`, |
| | | [RENDER_ID]: `${prefixStr}${nowDate}`, |
| | | [REPORT_TIME]: `${prefixStr}${nowDate}` |
| | | }); |
| | | }, |
| | | // 添加所有渲染数据,方案存在问题暂 |
| | | addAllRenderData(){ |
| | | this.waitPushIndex = 0; |
| | | const add = ()=>{ |
| | | const current = this.waitRenderList[this.waitPushIndex]; |
| | | if(current === undefined){ |
| | | this.waitRenderList = []; |
| | | return; |
| | | } |
| | | this.pushRender(current); |
| | | this.waitPushIndex++; |
| | | |
| | | add(); |
| | | }; |
| | | add(); |
| | | }, |
| | | // 渲染状态变更 |
| | | emitRenderStatusChange(status){ |
| | | this.$emit("statusChange",status); |
| | | }, |
| | | // 提交高度 |
| | | reportHeight(params){ |
| | | const { colIndex, height, reportHeightTimeChange } = params; |
| | | |
| | | this.renderListHeight[colIndex]+=height; |
| | | |
| | | if(reportHeightTimeChange){ |
| | | return; |
| | | } |
| | | |
| | | this.addRenderData(); |
| | | }, |
| | | // 添加一条渲染数据 |
| | | addRenderData(){ |
| | | const index = this.waitPushIndex ?? 0; |
| | | const current = this.waitRenderList[index]; |
| | | if(current === undefined){ |
| | | this.emitRenderStatusChange(RENDER_STATUS.END); |
| | | return; |
| | | } |
| | | this.pushRender(current); |
| | | this.waitPushIndex = index + 1; |
| | | if(this.waitPushIndex >= this.waitRenderList.length){ |
| | | this.waitPushIndex = 0; |
| | | this.waitRenderList = []; |
| | | } |
| | | }, |
| | | // 启动渲染 |
| | | render(list = [],reset = false){ |
| | | if(!list?.length > 0){ |
| | | console.log('河浪瀑布流插件提示:当前数据为空,不会触发列表渲染'); |
| | | return; |
| | | } |
| | | |
| | | if(reset){ |
| | | this.$nextTick(()=>{ |
| | | this.initRenderList(); |
| | | }); |
| | | // this.initRenderList(); |
| | | } |
| | | |
| | | this.waitRenderList = list.map((item)=>{ |
| | | const imageUrl = item[IMAGE_URL_KEY]; |
| | | const imageHeight = uni[IMAGE_CACHE_KEY][imageUrl]; |
| | | const show = this.$props.sameHeight ? true:false; |
| | | |
| | | return { |
| | | ...item, |
| | | [IMAGE_HEIGHT_KEY]: imageHeight, |
| | | // 该属性暂未使用,预留字段 |
| | | [ITEM_SHOW_KEY]: show |
| | | } |
| | | }); |
| | | |
| | | this.emitRenderStatusChange(RENDER_STATUS.LOADING); |
| | | |
| | | if(this.checkImageHaveHeight()){ |
| | | this.emitRenderStatusChange(RENDER_STATUS.START); |
| | | this.addRenderData(); |
| | | } |
| | | }, |
| | | // 更新 |
| | | update(params){ |
| | | const { colIndex, itemIndex, data = {}, reportHeight = false } = params; |
| | | // 当需要重新上报高度时,更新渲染时间 |
| | | if(reportHeight){ |
| | | const nowDate = Date.now(); |
| | | data[REPORT_TIME] = `${prefixStr}${nowDate}`; |
| | | } |
| | | |
| | | this.$set(this.renderList[colIndex], itemIndex, data); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | /* 小程序模式下插槽会增加一个 <scoped-slots-default> DOM节点 */ |
| | | .helang-waterfall-slot > scoped-slots-default{ |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | align-content: flex-start; |
| | | } |
| | | </style> |
| | | <style lang="scss" scoped> |
| | | .waterfall-box { |
| | | padding: 0 10rpx; |
| | | box-sizing: border-box; |
| | | |
| | | &.hidden{ |
| | | display: none; |
| | | } |
| | | |
| | | .list-item{ |
| | | margin-bottom: 0; |
| | | // 设置透明,默认是可视的 |
| | | opacity: 0; |
| | | // 默认超出隐藏,不影响加载中的文字显示效果 |
| | | overflow: hidden; |
| | | height: 0; |
| | | |
| | | &.show{ |
| | | margin-bottom: 20rpx; |
| | | opacity: 1; |
| | | overflow: auto; |
| | | height: auto; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .h-flex-x { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .load-image{ |
| | | display: none !important; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | let list = (page)=>{ |
| | | return new Promise((resolve,reject)=>{ |
| | | setTimeout(() => { |
| | | // 生成随机数方法 |
| | | let random = (min = 0, max) => { |
| | | return Math.floor(Math.random() * max) + min; |
| | | } |
| | | // 待选的图片数据 |
| | | let imgs = []; |
| | | // 待选的标题数据 |
| | | let titles = [ |
| | | '桃花坞里桃花庵,桃花庵里桃花仙;', |
| | | '桃花仙人种桃树,又摘桃花卖酒钱。', |
| | | '酒醒只在花前坐,酒醉还来花下眠;半醒半醉日复日,花落花开年复年。', |
| | | '但愿老死花酒间,不愿鞠躬车马前;', |
| | | '车尘马足富者趣,酒盏花枝贫者缘。若将富贵比贫贱,', |
| | | '一在平地一在天;若将贫贱比车马,他得驱驰我得闲。', |
| | | '别人笑我太疯癫,我笑他人看不穿;不见五陵豪杰墓,无花无酒锄作田。' |
| | | ]; |
| | | |
| | | let res = []; |
| | | let t = `?t=${new Date().getTime()}`; |
| | | for (let i = 0; i < 10; i++) { |
| | | res.push({ |
| | | id:`${Date.now()}_${i+1}`, |
| | | imgUrl:`/uni_modules/helang-waterfall/static/waterfall/${random(0,3)}.jpg`, |
| | | title: titles[random(0, titles.length)], |
| | | money: random(9, 9999), |
| | | label:'官方自营', |
| | | shop:'唐诗三百首旗舰店' |
| | | }) |
| | | } |
| | | resolve(res); |
| | | }, 1000); |
| | | }) |
| | | } |
| | | |
| | | export default { |
| | | getList:list |
| | | } |
对比新文件 |
| | |
| | | { |
| | | "id": "helang-waterfall", |
| | | "displayName": "瀑布流布局-waterfall", |
| | | "version": "1.2.4", |
| | | "description": "一款简单又好用的瀑布流布局组件,全新升级为组件+插槽的方案实现,极大的简便了组件的使用和内容调整。", |
| | | "keywords": [ |
| | | "瀑布流", |
| | | "布局", |
| | | "列表", |
| | | "waterfall" |
| | | ], |
| | | "repository": "https://gitee.com/myDarling/uniapp-extend", |
| | | "engines": { |
| | | "HBuilderX": "^4.0" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "", |
| | | "type": "uniapp-template-page" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y", |
| | | "alipay": "n" |
| | | }, |
| | | "client": { |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "u" |
| | | }, |
| | | "H5-mobile": { |
| | | "Safari": "y", |
| | | "Android Browser": "y", |
| | | "微信浏览器(Android)": "y", |
| | | "QQ浏览器(Android)": "y" |
| | | }, |
| | | "H5-pc": { |
| | | "Chrome": "y", |
| | | "IE": "y", |
| | | "Edge": "y", |
| | | "Firefox": "y", |
| | | "Safari": "y" |
| | | }, |
| | | "小程序": { |
| | | "微信": "y", |
| | | "阿里": "y", |
| | | "百度": "y", |
| | | "字节跳动": "y", |
| | | "QQ": "y" |
| | | }, |
| | | "快应用": { |
| | | "华为": "y", |
| | | "联盟": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <view style="padding: 20rpx 0;"> |
| | | <waterfall |
| | | ref="helangWaterfall" |
| | | :hideList="hideList" |
| | | imageKey="imgUrl" |
| | | @statusChange="handleStatusChange" |
| | | > |
| | | <template v-slot:default="{ list, colWidth }"> |
| | | <waterfall-col |
| | | v-for="(colItem,colIndex) in list" |
| | | :key="colIndex" |
| | | :colWidth="colWidth" |
| | | > |
| | | <template> |
| | | <waterfall-item |
| | | v-for="(item,index) in colItem" |
| | | :key="item.__waterfall_renderId" |
| | | :colIndex="colIndex" |
| | | :reportHeightTime="item.__waterfall_reportHeightTime" |
| | | @height="onRenderHeight" |
| | | > |
| | | <view class="content" @click="handleClick" :data-col_index="colIndex" :data-item_index="index"> |
| | | <image |
| | | class="image" |
| | | mode="aspectFill" |
| | | :src="item.imgUrl" |
| | | :style="{height:item.__waterfall_imageHeight}" |
| | | > |
| | | <!-- 必须给图片的高度设置为 __waterfall_imageHeight 属性的高 --> |
| | | </image> |
| | | <view class="title">{{item.title}}</view> |
| | | <view class="label ellipsis-1">{{item.label}}</view> |
| | | <view class="money ellipsis-1">价格:{{item.money}}元</view> |
| | | <view class="shop ellipsis-1">{{item.shop}}</view> |
| | | <!-- 这个节点真实项目中可删除 --> |
| | | <view |
| | | v-if="(colIndex === 0 && index === 0) || (colIndex === 1 && index === 1)" |
| | | style="margin-top: 8px;border: red solid 1px;padding: 8px;" |
| | | > |
| | | <view style="font-size: 12px;color: red;margin-bottom: 4px;"> |
| | | 次节点为演示 update 函数动态更新数据的能力, |
| | | 真是项目删除即可 |
| | | </view> |
| | | <view> |
| | | <button |
| | | size="mini" |
| | | style="margin-right: 4px;" |
| | | :type="item.star ? 'primary':'warn'" |
| | | @tap.stop="handleStar({ |
| | | colIndex, |
| | | itemIndex:index, |
| | | data:item |
| | | })" |
| | | >{{item.star ? '已':''}}收藏</button> |
| | | </view> |
| | | <view> |
| | | <view |
| | | v-if="item.activeHeight" |
| | | :style="{height:item.activeHeight+'px'}" |
| | | style="background-color: rgba(255, 0, 0, 0.4);font-size: 12px;" |
| | | >当前随机高度:{{ item.activeHeight }}</view> |
| | | <button size="mini" |
| | | @tap.stop="handleActiveHeight({ |
| | | colIndex, |
| | | itemIndex:index, |
| | | data:item |
| | | })" |
| | | >随机高度</button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </waterfall-item> |
| | | </template> |
| | | </waterfall-col> |
| | | </template> |
| | | <template #tips> |
| | | <view class="load-txt"> |
| | | <view v-if="hideList"> |
| | | <template v-if="waterfall.status === 'fail'"> |
| | | <image src="/uni_modules/helang-waterfall/static/waterfall/fail.png" mode="aspectFit"></image> |
| | | <view>数据异常</view> |
| | | </template> |
| | | <template v-else-if="waterfall.status === 'empty'"> |
| | | <image src="/uni_modules/helang-waterfall/static/waterfall/empty.png" mode="aspectFit"></image> |
| | | <view>暂无内容</view> |
| | | </template> |
| | | </view> |
| | | <view v-else style="padding-top: 30rpx;">加载中</view> |
| | | |
| | | </view> |
| | | </template> |
| | | </waterfall> |
| | | <!-- 演示多种效果 --> |
| | | <view class="status-change" @click="onStatusChange">设置</view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // 瀑布流组件 |
| | | import Waterfall from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-list"; |
| | | import WaterfallCol from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-col"; |
| | | import WaterfallItem from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-item"; |
| | | |
| | | // 列表接口模拟数据,真是项目不需要 |
| | | import mockData from '../../mock-data/waterfall-list.js' |
| | | |
| | | export default { |
| | | components: { |
| | | "waterfall": Waterfall, |
| | | "waterfall-col": WaterfallCol, |
| | | "waterfall-item": WaterfallItem |
| | | }, |
| | | computed:{ |
| | | hideList(){ |
| | | return ['fail','empty'].includes(this.waterfall.status); |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 异步请求相关 |
| | | ajax: { |
| | | // 是否可以加载 |
| | | load: true, |
| | | // 每页的请求条件 |
| | | rows:10, |
| | | // 页码 |
| | | page:1, |
| | | // 数据列表 |
| | | dataList:[] |
| | | }, |
| | | // 瀑布流组件相关 |
| | | waterfall:{ |
| | | // 组件状态 |
| | | status:'', |
| | | // 是否渲染完成 |
| | | renderEnd:true |
| | | } |
| | | } |
| | | }, |
| | | onReady() { |
| | | this.getList(); |
| | | }, |
| | | // 触底触发 |
| | | onReachBottom() { |
| | | // 渲染完成,才允许请求下一页 |
| | | if(this.waterfall.renderEnd){ |
| | | this.getList(); |
| | | } |
| | | }, |
| | | // 下拉刷新 |
| | | onPullDownRefresh(){ |
| | | // 正常情况下接口返回应该很会很快。故意延迟调用,让用户有在刷新的体验感 |
| | | setTimeout(()=>{ |
| | | this.ajax.page = 1; |
| | | this.ajax.load = true; |
| | | this.getList(this.ajax.page); |
| | | },800); |
| | | }, |
| | | methods: { |
| | | // 监听渲染高度,此事件为必用 |
| | | onRenderHeight(e){ |
| | | const { colIndex, height, reportHeightTimeChange } = e; |
| | | // 上报当前高度,上报后会自动触发下一项数据的渲染 |
| | | this.$refs.helangWaterfall.reportHeight({ |
| | | colIndex, |
| | | height, |
| | | reportHeightTimeChange |
| | | }); |
| | | }, |
| | | // 获取数据 |
| | | getList() { |
| | | // 请求未完成前禁止发起请求 |
| | | if (!this.ajax.load) { |
| | | return; |
| | | } |
| | | this.ajax.load = false; |
| | | |
| | | // 请求数据, mockData.getList 示例一个 ajax 请求 |
| | | mockData.getList({ |
| | | pageNum:this.ajax.page, |
| | | pageSize:this.ajax.rows |
| | | }).then(res=>{ |
| | | // 获取到的数据,请注意数据结构 |
| | | console.log(res); |
| | | |
| | | // 第一页数据执行以下代码 |
| | | if(this.ajax.page == 1){ |
| | | // 关闭下拉 |
| | | uni.stopPullDownRefresh(); |
| | | } |
| | | |
| | | // 数据无效时处理 |
| | | if(!res || res.length < 1){ |
| | | // 设置提示内容 |
| | | this.waterfall.status = this.ajax.page === 1 ? 'fail' : 'empty'; |
| | | return; |
| | | } |
| | | |
| | | // 当前页面页面为1时,表示列表重绘,场景一般是 刷新/搜索 时 |
| | | const reset = this.ajax.page === 1 ? true : false; |
| | | // 若是重绘列表的话,需要取消 `hideList`属性,隐藏状态下会引发列表尺寸获取错误的问题 |
| | | if(reset){ |
| | | this.waterfall.status = ''; |
| | | } |
| | | // 调用 render 方法,使组件开始进入渲染阶段 |
| | | this.$refs.helangWaterfall.render(res,reset); |
| | | this.ajax.load = true; |
| | | this.ajax.page++; |
| | | }) |
| | | }, |
| | | // 导航状态切换演示监听 |
| | | onStatusChange(){ |
| | | const vlaues = ['','fail','empty']; |
| | | const labels = ['正常展示', '加载异常', '无结果']; |
| | | uni.showActionSheet({ |
| | | itemList: labels, |
| | | success: (res)=> { |
| | | this.waterfall.status = vlaues[res.tapIndex]; |
| | | } |
| | | }); |
| | | }, |
| | | // 瀑布流组件点击事件 |
| | | handleClick(e){ |
| | | const { col_index, item_index } = e?.currentTarget?.dataset; |
| | | uni.showToast({ |
| | | title:`第${col_index+1}栏的${item_index+1}个被点击`, |
| | | icon:'none' |
| | | }); |
| | | }, |
| | | // 处理瀑布流渲染状态 |
| | | handleStatusChange(status){ |
| | | if(status === 'RENDER_END'){ |
| | | this.waterfall.renderEnd = true; |
| | | }else{ |
| | | this.waterfall.renderEnd = false; |
| | | } |
| | | }, |
| | | // 收藏 |
| | | handleStar(params){ |
| | | const { colIndex, itemIndex, data } = params; |
| | | // 切换收藏状态 |
| | | const star = !data?.star; |
| | | this.$refs.helangWaterfall.update({ |
| | | colIndex, |
| | | itemIndex, |
| | | data:{ |
| | | ...data, |
| | | star |
| | | // 此处因为收藏操作不会改变渲染高度,所以不需要传递reportHeight参数 |
| | | } |
| | | }) |
| | | }, |
| | | // 收藏 |
| | | handleActiveHeight(params){ |
| | | const { colIndex, itemIndex, data } = params; |
| | | const activeHeight = Math.floor(Math.random() * 100) + 50; |
| | | this.$refs.helangWaterfall.update({ |
| | | colIndex, |
| | | itemIndex, |
| | | data:{ |
| | | ...data, |
| | | activeHeight |
| | | }, |
| | | // 因为改变高度后会于原来的高度产生差值,需要重新上报高度 |
| | | // update 方法的 reportHeight 参数设置为 true |
| | | reportHeight:true |
| | | }); |
| | | }, |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #f3f3f3; |
| | | } |
| | | |
| | | .content{ |
| | | padding: 20rpx; |
| | | background-color: white; |
| | | border-radius: 4px; |
| | | line-height: 1.3; |
| | | |
| | | .image{ |
| | | display: block; |
| | | width: 100%; |
| | | height: auto; |
| | | } |
| | | |
| | | .ellipsis-1{ |
| | | white-space:nowrap; // 强制一行显示 |
| | | overflow:hidden; // 超出隐藏 |
| | | text-overflow:ellipsis; // 省略号 |
| | | } |
| | | |
| | | .title{ |
| | | font-size: 28rpx; |
| | | color:#666; |
| | | margin: 20rpx 0; |
| | | } |
| | | |
| | | .shop{ |
| | | font-size: 24rpx; |
| | | color:#666; |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .label{ |
| | | padding: 10rpx 20rpx; |
| | | border-radius: 100px; |
| | | background-color: #F00; |
| | | color: white; |
| | | font-size: 24rpx; |
| | | display: inline-block; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .money{ |
| | | font-size: 28rpx; |
| | | color:#F00; |
| | | margin-top: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .load-txt{ |
| | | padding: 0; |
| | | text-align: center; |
| | | color: #999; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | .load-icon{ |
| | | width: 300rpx; |
| | | height: 300rpx; |
| | | margin: 0 auto 20rpx auto; |
| | | display: block; |
| | | } |
| | | |
| | | .status-change{ |
| | | position: fixed; |
| | | left: 10rpx; |
| | | top: 60%; |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | z-index: 100; |
| | | font-size: 24rpx; |
| | | border-radius: 50%; |
| | | background-color: #f00; |
| | | color: #fff; |
| | | line-height: 1; |
| | | opacity: .7; |
| | | box-shadow: 0 0 10px black; |
| | | |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: nowrap; |
| | | justify-content: center; |
| | | align-items: center; |
| | | align-content: center; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | # 瀑布流 helang-waterfall |
| | | |
| | | ## 插件简介 |
| | | |
| | | > 这是一款简单又好用的瀑布流布局组件,从`1.2.1`版本开始全新升级为组件+插槽的方案实现,极大的简便了组件的使用和内容调整。 |
| | | |
| | | #### <font color="red">源码中有详细的注释,请各位开发者按个人需求自行修改。</font> |
| | | |
| | | ### <font color="red">对使用有疑问,可以先导入 [示例项目] 学习 页面与组件的使用流程</font> |
| | | |
| | | ## 组件使用 |
| | | |
| | | ### 示例源码 |
| | | |
| | | > 示例源码较多,请下载示例项目查看 |
| | | |
| | | ### 组件清单 |
| | | ```javascript |
| | | // 引用组件 |
| | | /* 瀑布流组件 */ |
| | | // 容器组件 |
| | | import Waterfall from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-list"; |
| | | // 分栏组件 |
| | | import WaterfallCol from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-col"; |
| | | // 内容组件 |
| | | import WaterfallItem from "@/uni_modules/helang-waterfall/components/waterfall/waterfall-item"; |
| | | |
| | | |
| | | export default { |
| | | // ... |
| | | // 注册组件 |
| | | components: { |
| | | "waterfall": Waterfall, |
| | | "waterfall-col": WaterfallCol, |
| | | "waterfall-item": WaterfallItem |
| | | }, |
| | | // ... |
| | | } |
| | | ``` |
| | | |
| | | ### 容器组件 waterfall-list |
| | | |
| | | #### 插槽 |
| | | 插槽名称 | 透传数据 | 说明 |
| | | --------|------|------ |
| | | default | 详情见default插槽透传数据说明 |瀑布流列表内容,放置 `waterfall-col` 组件 |
| | | tips | - | 瀑布流列表下方提示信息 |
| | | |
| | | #### default插槽透传数据说明 |
| | | |
| | | - 数据结构:`{ list,colWidth }` |
| | | - 字段说明: |
| | | 1. list:渲染的数据列表,数据增加了 `__waterfall_renderId`、`__waterfall_imageHeight` 属性 |
| | | 1. `__waterfall_renderId` 用于<waterfall-item>组件循环渲染的 `key` |
| | | 2. `__waterfall_reportHeightTime` 用于<waterfall-item>组件监听是否需要重新上报高度的时机 |
| | | 3. `__waterfall_imageHeight` 用于<image>标签的 `style高度` |
| | | 2. colWidth:栏目的宽度,用于 <waterfall-col> 组件的`colWidth`属性 |
| | | |
| | | |
| | | #### 属性 |
| | | |
| | | 属性名 | 类型 | 默认值 | 说明 |
| | | --------|------|------|------ |
| | | col | Number | 2 | 列表分栏数量,`不可动态修改` |
| | | imageWidth | Number / String | 305 | 列表中图片渲染的宽度,可支持 px 和 rpx单位的宽度,Number类型为rpx单位,若需要px单位则可写`152px`, `不可动态修改`,305是示例列表的图片渲染宽度 |
| | | imageKey | String | url | 数据中图片的key值,默认为`url` |
| | | hideList | Boolean | false | 是否隐藏列表,可隐藏列表部分来展示更多的提示内容(如:空列表时) |
| | | cacheImageHeight | Boolean | true | 是否缓存图片高度,能减少图片信息的加载过程提高渲染效率。 |
| | | |
| | | #### 方法 |
| | | - 源码演示 |
| | | |
| | | ```javascript |
| | | // 组件绑定 ref |
| | | <waterfall ref="helangWaterfall">...</waterfall> |
| | | |
| | | // 通过 ref 调用组件中的方案 |
| | | // 渲染 |
| | | this.$refs.helangWaterfall.render(数据Array,是否重绘Boolean); |
| | | |
| | | // 上报当前高度 |
| | | this.$refs.helangWaterfall.reportHeight({ |
| | | colIndex: 栏目序号Number, |
| | | height: 高度Number, |
| | | reportHeightTimeChange: 是否需要重新上报高度Boolean |
| | | }); |
| | | |
| | | // 更新数据 |
| | | this.$refs.helangWaterfall.update({ |
| | | colIndex: 栏目序号Number, |
| | | itemIndex: 渲染项序号Number, |
| | | data: 新的数据Object,切记需要保留之前的属性,仅做新属性的覆盖,参考示例项目, |
| | | reportHeight: 是否上报高度Boolean |
| | | }); |
| | | ``` |
| | | - 详细说明 |
| | | |
| | | 方法名称 | 参数 | 说明 |
| | | --------|------|------ |
| | | render | (数据Array,是否重绘Boolean) | 开启瀑布流渲染 |
| | | reportHeight | ({<br /> colIndex: 栏目序号Number,<br /> height: 高度Number,<br /> reportHeightTimeChange: 是否需要重新上报高度Boolean<br />}) | 汇报当前项的渲染高度,数据从`<waterfall-item @height="onRenderHeight">` 获取 |
| | | update | ({<br /> colIndex: 栏目序号Number,<br /> itemIndex: 渲染项序号Number,<br /> data: 新的数据Object,切记需要保留之前的属性,仅做新属性的覆盖,参考示例项目<br /> reportHeight: 是否上报高度Boolean,用于改变数据会导致节点渲染高度发生改变时使用(如有添加、展开、删除节点的操作时)<br />}) | 更新数据,可参考示例项目的收藏和改变高度的功能实现 |
| | | |
| | | #### 事件 |
| | | 事件名称 | 参数 | 说明 |
| | | --------|------|------ |
| | | @statusChange | (渲染状态值String) | 监听瀑布流组件的渲染状态,状态有:`RENDER_LOADING(加载中)`、`RENDER_START(渲染开始)`、`RENDER_END(渲染结束)`,<br />可让业务代码配合拦截部分操作减少渲染过程中的BUG发生 |
| | | |
| | | ### 分栏组件 waterfall-col |
| | | |
| | | #### 属性 |
| | | |
| | | 属性名 | 类型 | 默认值 | 说明 |
| | | --------|------|------|------ |
| | | colWidth | String | '' | 栏目宽度,数据来源于 `waterfall-lsit` 的插槽透传的`colWidth`属性 |
| | | |
| | | ### 内容组件 waterfall-item |
| | | |
| | | #### 属性 |
| | | |
| | | 属性名 | 类型 | 默认值 | 说明 |
| | | --------|------|------|------ |
| | | colIndex | Number | 0 | 栏目索引,用于汇报渲染高度时使用 |
| | | reportHeightTime | Number / String / undefined / null | 0 | 高度上报时间,用于监听是否数据发生更新 |
| | | |
| | | #### 事件 |
| | | |
| | | 方法名 | 回调参数 | 说明 |
| | | --------|------|------ |
| | | @height | ({colIndex, height,reportHeightTimeChange}) | 监听当前内容渲染后的高度,<br />`colIndex`:栏目索引、<br />`height`:渲染的高度值、<br />`reportHeightTimeChange`:是否需要重新上报高度Boolean |
| | | |
| | | ## 常见问题解答 |
| | | |
| | | ### 1. 列表渲染速度太慢,怎么优化? |
| | | |
| | | 瀑布流布局最大的难点是在于图片加载是一个异步的过程,所以本插件也是利用了图片加载这个事件来触发组件初始化完成的。为了更好的加载体验和降低用户的用户的流量消耗,推荐使用`缩略图`来做为列表中的显示(也应当这么做,不只是在瀑布流布局中),这也是做好一个产品最基本的优化要求。 |
| | | |
| | | ## 友情提示: |
| | | 1. 当前项目源码使用了 ES6 和 scss 请添加运行依赖 |
| | | 2. [插件ZIP]只包含模板文件和数据文件,不包含项目运行依赖(如 pages.json) |
| | | 3. [示例项目ZIP]是完整的项目文件,可下载后导入 HBuilderX 中直接运行体验 |
| | | 4. 文件下载在当前页面的上部靠右位置,有 [下载插件ZIP] [下载示例项目ZIP] 按钮,点击即可下载 |