|
@@ -1,5 +1,629 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <view class="app_content">
|
|
|
|
|
- <view></view>
|
|
|
|
|
|
|
+ <view class="app-main app-content">
|
|
|
|
|
+
|
|
|
|
|
+ <view class="c_header" :class="myClass">
|
|
|
|
|
+ <view class="header_inside">
|
|
|
|
|
+ <image :src="shopImg"></image>
|
|
|
|
|
+ <view class="shop_info">
|
|
|
|
|
+ <view class="shop_title">{{shopName}}</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 搜索框和花材绿植按钮区域 -->
|
|
|
|
|
+ <view class="search-wrap">
|
|
|
|
|
+ <view class="search-bar">
|
|
|
|
|
+ <app-search-module
|
|
|
|
|
+ v-model="searchText"
|
|
|
|
|
+ placeholder="搜索商品"
|
|
|
|
|
+ @input="searchFn"
|
|
|
|
|
+ :height="66"
|
|
|
|
|
+ :fontSize="28"
|
|
|
|
|
+ />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="buy-material-container">
|
|
|
|
|
+ <button class="buy-material-btn" @click="buyProduct()">
|
|
|
|
|
+ <view class="btn-content">
|
|
|
|
|
+ <text class="btn-text">商城</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <scroll-view scroll-y scroll-with-animation class="tab-view" :scroll-top="scrollTop">
|
|
|
|
|
+ <view v-for="(item,index) in tabbar" :key="index" class="tab-bar-item" :class="[!isSearchMode && currentTab==index ? 'active' : '']" :data-current="index" @tap.stop="swichNav($event ,item)" >
|
|
|
|
|
+ <text>{{item.categoryName}}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view style="height:150upx"></view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 搜索结果展示区域 -->
|
|
|
|
|
+ <scroll-view v-if="isSearchMode" scroll-y class="right-box" @scrolltolower="reachBottom">
|
|
|
|
|
+ <view class="page-view" v-if="!$util.isEmpty(list.data)" >
|
|
|
|
|
+ <view class="goods-list" v-for="(items) in list.data" :key="items.id" @click="toBuy(items)" >
|
|
|
|
|
+ <view class="img-blo">
|
|
|
|
|
+ <image :src="items.smallCover" mode="aspectFill" ></image>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="goods-det">
|
|
|
|
|
+ <view class="goods-det-top">
|
|
|
|
|
+ <view class="goods-name">{{ items.name }}</view>
|
|
|
|
|
+ <view class="goods-sales"></view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="goods-price">¥{{ items.price?parseFloat(items.price):0 }}</view>
|
|
|
|
|
+ <view class="buy-btn">购买</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <block v-else>
|
|
|
|
|
+ <app-wrapper-empty
|
|
|
|
|
+ :title="getEmptyTitle()"
|
|
|
|
|
+ :is-empty="true"
|
|
|
|
|
+ />
|
|
|
|
|
+ </block>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 分类商品展示区域 -->
|
|
|
|
|
+ <block v-for="(item,index) in tabbar" :key="index" >
|
|
|
|
|
+ <scroll-view scroll-y class="right-box" @scrolltolower="reachBottom" v-if="!isSearchMode && currentTab==index" >
|
|
|
|
|
+ <view class="page-view" v-if="!$util.isEmpty(list.data)" >
|
|
|
|
|
+ <view class="goods-list" v-for="(items) in list.data" :key="items.id" @click="toBuy(items)" >
|
|
|
|
|
+ <view class="img-blo">
|
|
|
|
|
+ <image :src="items.smallCover" mode="aspectFill" ></image>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="goods-det">
|
|
|
|
|
+ <view class="goods-det-top">
|
|
|
|
|
+ <view class="goods-name">{{ items.name }}</view>
|
|
|
|
|
+ <view class="goods-sales"></view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="goods-price">¥{{ items.price?parseFloat(items.price):0 }}</view>
|
|
|
|
|
+ <view class="buy-btn">购买</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <block v-else>
|
|
|
|
|
+ <app-wrapper-empty
|
|
|
|
|
+ :title="getEmptyTitle()"
|
|
|
|
|
+ :is-empty="true"
|
|
|
|
|
+ />
|
|
|
|
|
+ </block>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+ </block>
|
|
|
|
|
+
|
|
|
|
|
+ <wangCg :loginStyle.sync="globalLoginStyle" @goToLogin="loginTo()"></wangCg>
|
|
|
</view>
|
|
</view>
|
|
|
-</template>
|
|
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+import { mapGetters } from 'vuex'
|
|
|
|
|
+import AppImg from '@/components/app-img'
|
|
|
|
|
+import wangCg from "@/components/wangCg"
|
|
|
|
|
+import AppWrapperEmpty from '@/components/app-wrapper-empty'
|
|
|
|
|
+import AppSearchModule from '@/components/item/module/app-search'
|
|
|
|
|
+import { getClass, getList } from '@/api/category'
|
|
|
|
|
+import { list,share } from '@/mixins'
|
|
|
|
|
+import { getInfo } from "@/api/shop"
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'mall',
|
|
|
|
|
+ components: {
|
|
|
|
|
+ AppWrapperEmpty,
|
|
|
|
|
+ AppImg,
|
|
|
|
|
+ wangCg,
|
|
|
|
|
+ AppSearchModule
|
|
|
|
|
+ },
|
|
|
|
|
+ mixins: [list, share],
|
|
|
|
|
+ data () {
|
|
|
|
|
+ return {
|
|
|
|
|
+ tabbar: [],
|
|
|
|
|
+ height: 0,
|
|
|
|
|
+ currentTab: 0,
|
|
|
|
|
+ scrollTop: 0,
|
|
|
|
|
+ form: {
|
|
|
|
|
+ categoryId: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ currentTabIndex: 1,
|
|
|
|
|
+ myClass: 'fadeIn',
|
|
|
|
|
+ shopName:'',
|
|
|
|
|
+ shopImg:'',
|
|
|
|
|
+ hdId:0,
|
|
|
|
|
+ searchText: '', // 搜索文本
|
|
|
|
|
+ searchTimer: null, // 搜索防抖定时器
|
|
|
|
|
+ isSearchMode: false, // 是否为搜索模式
|
|
|
|
|
+ lastSearchText: '' // 上次搜索的文本,用于优化
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ ...mapGetters({ loginInfo:"getLoginInfo" })
|
|
|
|
|
+ },
|
|
|
|
|
+ onShareAppMessage(res) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ title: '花束花礼',
|
|
|
|
|
+ desc: "",
|
|
|
|
|
+ path: "pages/home/category?account="+this.option.account,
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ onShow(){
|
|
|
|
|
+ if(!this.$util.isEmpty(this.loginInfo)){
|
|
|
|
|
+ this.globalLoginStyle = 1
|
|
|
|
|
+ }else{
|
|
|
|
|
+ this.globalLoginStyle = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ onUnload() {
|
|
|
|
|
+ // 清理搜索定时器
|
|
|
|
|
+ if (this.searchTimer) {
|
|
|
|
|
+ clearTimeout(this.searchTimer);
|
|
|
|
|
+ this.searchTimer = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ loginInfo: {
|
|
|
|
|
+ deep: true,
|
|
|
|
|
+ handler: function(newVal) {
|
|
|
|
|
+ if(!this.$util.isEmpty(newVal)){
|
|
|
|
|
+ this.globalLoginStyle = 1
|
|
|
|
|
+ }else{
|
|
|
|
|
+ this.globalLoginStyle = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ immediate:true
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ toBuy(item){
|
|
|
|
|
+ let account = this.option.account?this.option.account:0
|
|
|
|
|
+ this.$util.pageTo({url:"/pages/goods/detail?id="+item.id+'&hdId='+this.hdId+'&categoryId='+this.form.categoryId+'&account='+account})
|
|
|
|
|
+ },
|
|
|
|
|
+ buyProduct(){
|
|
|
|
|
+ let account = this.option.account?this.option.account:0
|
|
|
|
|
+ this.$util.pageTo({url:"/pages/home/category?account="+account+'&hdId='+this.hdId+'&id='+this.hdId,type:2})
|
|
|
|
|
+ },
|
|
|
|
|
+ loginTo() {
|
|
|
|
|
+ let account = this.option.account?this.option.account:0
|
|
|
|
|
+ this.$util.pageTo({url:"/pages/login/index?needBack=1&account="+account})
|
|
|
|
|
+ },
|
|
|
|
|
+ init(){
|
|
|
|
|
+ this.hdId = this.option.hdId ? this.option.hdId : 0
|
|
|
|
|
+ this.classInit()
|
|
|
|
|
+ getInfo({hdId:this.hdId}).then(res=>{
|
|
|
|
|
+ if(res.code == 1){
|
|
|
|
|
+ if(res.data.info && res.data.info.merchantName){
|
|
|
|
|
+ let sjName = res.data.info.merchantName
|
|
|
|
|
+ let shopName = res.data.info.shopName ? res.data.info.shopName : '首店'
|
|
|
|
|
+ let name = shopName == '首店' ? sjName : sjName+' '+shopName
|
|
|
|
|
+ this.shopName = name
|
|
|
|
|
+ this.shopImg = res.data.info.avatar
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(res.data.hd && Number(res.data.hd.id) > 0){
|
|
|
|
|
+ if(Number(this.hdId) == 0){
|
|
|
|
|
+ this.hdId = res.data.hd.id
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 搜索输入处理(防抖)
|
|
|
|
|
+ searchFn() {
|
|
|
|
|
+
|
|
|
|
|
+ // 清除之前的定时器
|
|
|
|
|
+ if (this.searchTimer) {
|
|
|
|
|
+ clearTimeout(this.searchTimer)
|
|
|
|
|
+ this.searchTimer = null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果搜索文本为空
|
|
|
|
|
+ if (this.$util.isEmpty(this.searchText)) {
|
|
|
|
|
+ // 如果之前也是空文本(首次点击或焦点清空),跳过搜索
|
|
|
|
|
+ if (this.$util.isEmpty(this.lastSearchText)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果之前有搜索文本,现在清空了,则恢复分类筛选
|
|
|
|
|
+ this.clearSearch()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果搜索文本与上次相同,不重复搜索
|
|
|
|
|
+ if (this.searchText === this.lastSearchText) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 设置防抖定时器,1秒后执行搜索
|
|
|
|
|
+ this.searchTimer = setTimeout(() => {
|
|
|
|
|
+ this.performSearch()
|
|
|
|
|
+ }, 1000)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 执行搜索
|
|
|
|
|
+ performSearch() {
|
|
|
|
|
+ if (this.$util.isEmpty(this.searchText)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.isSearchMode = true
|
|
|
|
|
+ this.lastSearchText = this.searchText
|
|
|
|
|
+ this.resetList()
|
|
|
|
|
+ this.searchGoods()
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 清空搜索,恢复分类筛选
|
|
|
|
|
+ clearSearch() {
|
|
|
|
|
+ this.isSearchMode = false
|
|
|
|
|
+ this.lastSearchText = ''
|
|
|
|
|
+
|
|
|
|
|
+ // 确保搜索框内容被清空
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.searchText = ''
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ this.resetList()
|
|
|
|
|
+ this.getGoodList()
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 搜索商品
|
|
|
|
|
+ searchGoods() {
|
|
|
|
|
+ let hdId = this.option.id?this.option.id:0
|
|
|
|
|
+ return getList({
|
|
|
|
|
+ searchText: this.searchText,
|
|
|
|
|
+ page: this.list.page,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ hdId:hdId
|
|
|
|
|
+ }).then(res => {
|
|
|
|
|
+ this.completes(res)
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ this.$msg('搜索失败')
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ reachBottom () {
|
|
|
|
|
+ console.log('reachBottom----------', this.list.finished)
|
|
|
|
|
+ if (this.list.finished == false) {
|
|
|
|
|
+ // 根据是否为搜索模式决定调用哪个方法
|
|
|
|
|
+ if (this.isSearchMode) {
|
|
|
|
|
+ this.searchGoods().then(res => {
|
|
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.getGoodList().then(res => {
|
|
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async classInit () {
|
|
|
|
|
+ this.getMyClass() .then(res => {
|
|
|
|
|
+ this.getGoodList()
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 分类
|
|
|
|
|
+ getMyClass () {
|
|
|
|
|
+ return getClass().then(res => {
|
|
|
|
|
+ if(res.code && res.code == 1){
|
|
|
|
|
+ this.form.categoryId = res.data[0].id
|
|
|
|
|
+ this.tabbar = res.data
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 列表
|
|
|
|
|
+ getGoodList () {
|
|
|
|
|
+ return getList({ ...this.form, page: this.list.page,pageSize:10 }) .then(res => {
|
|
|
|
|
+ // 处理商品列表数据,completes方法来自list混入
|
|
|
|
|
+ // 该方法会处理分页数据,更新list对象的data、page、finished等属性
|
|
|
|
|
+ // res包含接口返回的商品列表数据,completes方法会将数据添加到this.list.data中
|
|
|
|
|
+ this.completes(res)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 点击标题切换当前页时改变样式
|
|
|
|
|
+ swichNav (e, item) {
|
|
|
|
|
+ let cur = e.currentTarget.dataset.current
|
|
|
|
|
+ if (this.currentTab == cur && !this.isSearchMode) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.currentTab = cur
|
|
|
|
|
+ this.form.categoryId = item.id
|
|
|
|
|
+
|
|
|
|
|
+ // 切换分类时清空搜索状态
|
|
|
|
|
+ this.clearSearchState()
|
|
|
|
|
+ this.resetList()
|
|
|
|
|
+ this.getGoodList()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 判断当前滚动超过一屏时,设置tab标题滚动条。
|
|
|
|
|
+ checkCor () {
|
|
|
|
|
+ let that = this
|
|
|
|
|
+ // 这里计算按照实际情况进行修改,动态数据要进行动态分析
|
|
|
|
|
+ // 思路:窗体高度/单个分类高度 200upx 转px计算 =>得到一屏幕所显示的个数,结合后台传回分类总数进行计算
|
|
|
|
|
+ // 数据很多可以多次if判断然后进行滚动距离计算即可
|
|
|
|
|
+ if (that.currentTab > 7) {
|
|
|
|
|
+ that.scrollTop = 500
|
|
|
|
|
+ } else {
|
|
|
|
|
+ that.scrollTop = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ tabClick (index) {
|
|
|
|
|
+ this.currentTabIndex = index
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 清空搜索状态(不触发数据重新加载)
|
|
|
|
|
+ clearSearchState() {
|
|
|
|
|
+ // 清除定时器
|
|
|
|
|
+ if (this.searchTimer) {
|
|
|
|
|
+ clearTimeout(this.searchTimer)
|
|
|
|
|
+ this.searchTimer = null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 重置搜索相关状态
|
|
|
|
|
+ this.searchText = ''
|
|
|
|
|
+ this.isSearchMode = false
|
|
|
|
|
+ this.lastSearchText = ''
|
|
|
|
|
+
|
|
|
|
|
+ // 确保搜索框内容被清空(强制更新)
|
|
|
|
|
+ // this.$nextTick(() => {
|
|
|
|
|
+ // this.searchText = ''
|
|
|
|
|
+ // })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取空状态提示文字
|
|
|
|
|
+ getEmptyTitle() {
|
|
|
|
|
+ if (this.isSearchMode && this.searchText) {
|
|
|
|
|
+ return `未找到"${this.searchText}"相关商品`
|
|
|
|
|
+ }
|
|
|
|
|
+ return '暂无商品'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 组件销毁时清理定时器
|
|
|
|
|
+ beforeDestroy() {
|
|
|
|
|
+ if (this.searchTimer) {
|
|
|
|
|
+ clearTimeout(this.searchTimer)
|
|
|
|
|
+ this.searchTimer = null
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.app-content {
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+
|
|
|
|
|
+.c_header{
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ padding: 0 15upx;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ background: linear-gradient(to bottom,#3385FF, #fff);
|
|
|
|
|
+ &>.header_inside{
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ height: 124upx;
|
|
|
|
|
+ margin-top: 15upx;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ box-shadow: 0upx 1px 21px 0upx rgba(161, 166, 173, 0.4);
|
|
|
|
|
+ border-radius: 20upx;
|
|
|
|
|
+ padding: 35upx 30upx 30upx 30upx;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ &>image{
|
|
|
|
|
+ height: 60upx;
|
|
|
|
|
+ width: 60upx;
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ border-radius: 10upx;
|
|
|
|
|
+ background-color: #eee;
|
|
|
|
|
+ vertical-align: top;
|
|
|
|
|
+ }
|
|
|
|
|
+ &>.shop_info{
|
|
|
|
|
+ vertical-align: top;
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ margin-left: 20upx;
|
|
|
|
|
+ &>.shop_title{
|
|
|
|
|
+ margin-top:0upx;
|
|
|
|
|
+ font-size:40upx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #060606;
|
|
|
|
|
+ width: 580upx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .fadeIn{
|
|
|
|
|
+ height:160upx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ animation-name: fadeInFrames;
|
|
|
|
|
+ animation-duration:.3s;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+page {
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::-webkit-scrollbar {
|
|
|
|
|
+ width: 0;
|
|
|
|
|
+ height: 0;
|
|
|
|
|
+ color: transparent;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-view {
|
|
|
|
|
+ ::-webkit-scrollbar {
|
|
|
|
|
+ width: 0;
|
|
|
|
|
+ height: 0;
|
|
|
|
|
+ color: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+ width: 200upx;
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ height: calc(100vh - 160upx); /* 调整高度以适应搜索框 */
|
|
|
|
|
+ background-color: #f0f2f6;
|
|
|
|
|
+ .tab-bar-item {
|
|
|
|
|
+ width: 200upx;
|
|
|
|
|
+ height: 110upx;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ font-size: 28upx;
|
|
|
|
|
+ color: #444;
|
|
|
|
|
+ font-weight: 400;
|
|
|
|
|
+ }
|
|
|
|
|
+ .active {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ color: $mainColor;
|
|
|
|
|
+ font-size: 26upx;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .active::before {
|
|
|
|
|
+ content: "";
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ border-left: 8upx solid $mainColor;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+.right-box {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ overflow: auto;
|
|
|
|
|
+ height: calc(100vh - 280upx); /* 调整高度以适应搜索框 */
|
|
|
|
|
+ padding-left: 220upx;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ .page-view {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ margin-bottom:60upx;
|
|
|
|
|
+ .goods-list {
|
|
|
|
|
+ @include disFlex(flex-start, flex-start);
|
|
|
|
|
+ margin: 40upx 0;
|
|
|
|
|
+ .img-blo {
|
|
|
|
|
+ width: 200upx;
|
|
|
|
|
+ height: 200upx;
|
|
|
|
|
+ margin-right: 20upx;
|
|
|
|
|
+ image{
|
|
|
|
|
+ width: 200upx;
|
|
|
|
|
+ height: 200upx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .goods-det {
|
|
|
|
|
+ padding-top: 18upx;
|
|
|
|
|
+ font-size: 28upx;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: calc(100% - 240upx);
|
|
|
|
|
+ .goods-det-top {
|
|
|
|
|
+ .goods-name {
|
|
|
|
|
+ font-size: 32upx;
|
|
|
|
|
+ margin-bottom: 10upx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ display: -webkit-box;
|
|
|
|
|
+ -webkit-line-clamp: 2;
|
|
|
|
|
+ line-clamp: 2;
|
|
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
|
|
+ word-break: break-all;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .goods-price {
|
|
|
|
|
+ font-size: 32upx;
|
|
|
|
|
+ margin-top: 50upx;
|
|
|
|
|
+ color: $mainColor;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 搜索框样式 */
|
|
|
|
|
+.search-wrap {
|
|
|
|
|
+ padding: 15upx 30upx 25upx 30upx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 20upx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ border-radius: 30upx;
|
|
|
|
|
+ padding: 2upx;
|
|
|
|
|
+ box-shadow: 0upx 2px 8px 0upx rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-loading {
|
|
|
|
|
+ padding: 10upx 30upx;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+
|
|
|
|
|
+ .loading-text {
|
|
|
|
|
+ font-size: 24upx;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.buy-material-container {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.buy-material-btn {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ background: linear-gradient(135deg, #4caf50, #66bb6a, #81c784);
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ border-radius: 50upx;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ height: 80upx;
|
|
|
|
|
+ min-width: 160upx;
|
|
|
|
|
+ box-shadow: 0 8upx 20upx rgba(76, 175, 80, 0.3);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ box-shadow: 0 4upx 10upx rgba(76, 175, 80, 0.4);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .btn-content {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .btn-text {
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ font-size: 28upx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ text-shadow: 0 2upx 4upx rgba(0, 0, 0, 0.2);
|
|
|
|
|
+ margin: 0 8upx;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes fadeInFrames {
|
|
|
|
|
+ 0% {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+ height: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ 100% {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ height: 180upx;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.buy-btn {
|
|
|
|
|
+ color: red;
|
|
|
|
|
+ border: 1upx solid red;
|
|
|
|
|
+ border-radius: 10upx;
|
|
|
|
|
+ width: 80upx;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ padding: 5upx 0;
|
|
|
|
|
+ font-size: 25upx;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 30upx;
|
|
|
|
|
+ top: 150upx;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|