浏览代码

Merge remote-tracking branch 'refs/remotes/yudao/master'

puhui999 8 月之前
父节点
当前提交
6c0ba7d585

+ 13 - 1
pages/goods/groupon.vue

@@ -199,6 +199,7 @@
 
   /**
    * 去参团
+   *
    * @param record 团长的团购记录
    */
   function onJoinGroupon(record) {
@@ -227,7 +228,6 @@
   }
 
   // 分享信息
-  // TODO @芋艿:分享的接入
   const shareInfo = computed(() => {
     if (isEmpty(state.activity)) return {};
     return sheep.$platform.share.getShareInfo(
@@ -262,9 +262,21 @@
     // 加载商品信息
     const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
     state.goodsId = spu.id;
+    // 默认显示最低价
     activity.products.forEach((product) => {
       spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
     });
+    // 价格、库存使用活动的
+    spu.skus.forEach((sku) => {
+      const product = activity.products.find((product) => product.skuId === sku.id);
+      if (product) {
+        sku.price = product.combinationPrice;
+      } else {
+        // 找不到可能是没配置,则不能发起秒杀
+        sku.stock = 0;
+      }
+    });
+
     // 关闭骨架屏
     state.skeletonLoading = false;
     if (code === 0) {

+ 1 - 1
pages/goods/index.vue

@@ -157,7 +157,7 @@
         items: [{
           skuId: e.id,
           count: e.goods_num,
-		  categoryId: state.goodsInfo.categoryId
+		      categoryId: state.goodsInfo.categoryId
         }]
       }),
     });

+ 3 - 2
pages/goods/seckill.vue

@@ -196,7 +196,7 @@
     });
   }
 
-  // 分享信息 TODO 芋艿:待接入
+  // 分享信息
   const shareInfo = computed(() => {
     if (isEmpty(unref(activity))) return {};
     return sheep.$platform.share.getShareInfo(
@@ -220,6 +220,7 @@
 
   const activity = ref();
   const timeStatusEnum = ref('');
+
   // 查询活动
   const getActivity = async (id) => {
     const { data } = await SeckillApi.getSeckillActivity(id);
@@ -230,9 +231,9 @@
     await getSpu(data.spuId);
   };
 
+  // 查询商品
   const getSpu = async (id) => {
     const { data } = await SpuApi.getSpuDetail(id);
-    // 模拟
     data.activity_type = 'seckill';
     state.goodsInfo = data;
     // 处理轮播图

+ 6 - 5
pages/index/category.vue

@@ -131,12 +131,13 @@
     getGoodsList();
   }
 
-  onLoad(async () => {
+  onLoad(async (params) => {
     await getList();
-    // 如果是 first 风格,需要加载商品分页
-    if (state.style === 'first_one' || state.style === 'first_two') {
-      onMenu(0);
-    }
+
+    // 首页点击分类的处理:查找满足条件的分类
+    const foundCategory = state.categoryList.find(category => category.id === params.id);
+    // 如果找到则调用 onMenu 自动勾选相应分类,否则调用 onMenu(0) 勾选第一个分类
+    onMenu(foundCategory ? state.categoryList.indexOf(foundCategory) : 0);
   });
 
   onReachBottom(() => {

+ 5 - 5
sheep/components/s-block-item/s-block-item.vue

@@ -9,7 +9,7 @@
     <!-- 基础组件:列表导航 -->
     <s-menu-list v-if="type === 'MenuList'" :data="data" />
     <!-- 基础组件:宫格导航 -->
-    <s-menu-grid v-if="type === 'MenuGrid'" :data="data" />
+    <s-menu-grid v-if="type === 'MenuGrid'" :data="data" :styles="styles" />
     <!-- 基础组件:弹窗广告 -->
     <s-popup-image v-if="type === 'Popover'" :data="data" />
     <!-- 基础组件:悬浮按钮 -->
@@ -47,13 +47,13 @@
     <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" />
 
     <!-- 用户组件:用户卡片 -->
-    <s-user-card v-if="type === 'UserCard'" />
+    <s-user-card v-if="type === 'UserCard'" :data="data" :styles="styles" />
     <!-- 用户组件:用户订单 -->
-    <s-order-card v-if="type === 'UserOrder'" :data="data" />
+    <s-order-card v-if="type === 'UserOrder'" :data="data" :styles="styles" />
     <!-- 用户组件:用户资产 -->
-    <s-wallet-card v-if="type === 'UserWallet'" />
+    <s-wallet-card v-if="type === 'UserWallet'" :data="data" :styles="styles" />
     <!-- 用户组件:用户卡券 -->
-    <s-coupon-card v-if="type === 'UserCoupon'" />
+    <s-coupon-card v-if="type === 'UserCoupon'" :data="data" :styles="styles" />
   </view>
 </template>
 

+ 24 - 1
sheep/components/s-coupon-card/s-coupon-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户卡券 -->
 <template>
-	<view class="ss-coupon-menu-wrap ss-flex ss-col-center">
+	<view class="ss-coupon-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
 		<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title"
 			@tap="sheep.$router.go(item.path, { type: item.type })"
 			:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
@@ -15,6 +15,7 @@
 	 * 装修组件 - 优惠券菜单
 	 */
 	import sheep from '@/sheep';
+	import { computed } from 'vue';
 
 	// 接收参数
 	const props = defineProps({
@@ -52,6 +53,28 @@
 				];
 			},
 		},
+		// 装修数据
+		data: {
+		  type: Object,
+		  default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+		  type: Object,
+		  default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+	  // 直接从 props.styles 解构
+	  const { bgType, bgImg, bgColor } = props.styles; 
+	
+	  // 根据 bgType 返回相应的样式
+	  return {
+		background: bgType === 'img'
+			? `url(${bgImg}) no-repeat top center / 100% 100%`
+			: bgColor
+		};
 	});
 </script>
 

+ 307 - 326
sheep/components/s-menu-button/s-menu-button.vue

@@ -1,363 +1,344 @@
 <!-- 装修基础组件:菜单导航(金刚区) -->
 <template>
-  <!-- 包裹层 -->
-  <view
-    class="ui-swiper"
-    :class="[props.mode, props.bg, props.ui]"
-    :style="[{ height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]"
-  >
-    <!-- 轮播 -->
-    <swiper
-      :circular="props.circular"
-      :current="state.cur"
-      :autoplay="props.autoplay"
-      :interval="props.interval"
-      :duration="props.duration"
-      :style="[{ height: swiperHeight + 'rpx' }]"
-      @change="swiperChange"
-    >
-      <swiper-item
-        v-for="(arr, index) in menuList"
-        :key="index"
-        :class="{ cur: state.cur == index }"
-      >
-        <!-- 宫格 -->
-        <view class="grid-wrap">
-          <view
-            v-for="(item, index) in arr"
-            :key="index"
-            class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
-            :style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]"
-            hover-class="ss-hover-btn"
-            @tap="sheep.$router.go(item.url)"
-          >
-            <view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
-              <view
-                v-if="item.badge.show"
-                class="tag-box"
-                :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
-              >
-                {{ item.badge.text }}
-              </view>
-              <image
-                v-if="item.iconUrl"
-                class="menu-icon"
-                :style="[
+	<!-- 包裹层 -->
+	<view class="ui-swiper" :class="[props.mode, props.ui]"
+		:style="[bgStyle, { height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]">
+		<!-- 轮播 -->
+		<swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay" :interval="props.interval"
+			:duration="props.duration" :style="[{ height: swiperHeight + 'rpx' }]" @change="swiperChange">
+			<swiper-item v-for="(arr, index) in menuList" :key="index" :class="{ cur: state.cur == index }">
+				<!-- 宫格 -->
+				<view class="grid-wrap">
+					<view v-for="(item, index) in arr" :key="index"
+						class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
+						:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" hover-class="ss-hover-btn"
+						@tap="sheep.$router.go(item.url)">
+						<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
+							<view v-if="item.badge.show" class="tag-box"
+								:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
+								{{ item.badge.text }}
+							</view>
+							<image v-if="item.iconUrl" class="menu-icon" :style="[
                   {
                     width: props.iconSize + 'rpx',
                     height: props.iconSize + 'rpx',
                   },
-                ]"
-                :src="sheep.$url.cdn(item.iconUrl)"
-                mode="aspectFill"
-              ></image>
-              <view
-                v-if="data.layout === 'iconText'"
-                class="menu-title"
-                :style="[{ color: item.titleColor }]"
-              >
-                {{ item.title }}
-              </view>
-            </view>
-          </view>
-        </view>
-      </swiper-item>
-    </swiper>
-    <!-- 指示点 -->
-    <template v-if="menuList.length > 1">
-      <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
-        <view
-          class="line-box"
-          v-for="(item, index) in menuList.length"
-          :key="index"
-          :class="[state.cur == index ? 'cur' : '', props.dotCur]"
-        ></view>
-      </view>
-      <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
-        <view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
-          <view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
-        </view>
-      </view>
-    </template>
-  </view>
+                ]" :src="sheep.$url.cdn(item.iconUrl)" mode="aspectFill"></image>
+							<view v-if="data.layout === 'iconText'" class="menu-title"
+								:style="[{ color: item.titleColor }]">
+								{{ item.title }}
+							</view>
+						</view>
+					</view>
+				</view>
+			</swiper-item>
+		</swiper>
+		<!-- 指示点 -->
+		<template v-if="menuList.length > 1">
+			<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
+				<view class="line-box" v-for="(item, index) in menuList.length" :key="index"
+					:class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
+			</view>
+			<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
+				<view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
+					<view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
+				</view>
+			</view>
+		</template>
+	</view>
 </template>
 
 <script setup>
-  /**
-   * 轮播menu
-   *
-   * @property {Boolean} circular = false  		- 是否采用衔接滑动,即播放到末尾后重新回到开头
-   * @property {Boolean} autoplay = true  		- 是否自动切换
-   * @property {Number} interval = 5000  			- 自动切换时间间隔
-   * @property {Number} duration = 500  			- 滑动动画时长,app-nvue不支持
-   * @property {Array} list = [] 					- 轮播数据
-   * @property {String} ui = ''  					- 样式class
-   * @property {String} mode  					- 模式
-   * @property {String} dotStyle  				- 指示点样式
-   * @property {String} dotCur= 'ui-BG-Main' 		- 当前指示点样式,默认主题色
-   * @property {String} bg  						- 背景
-   *
-   * @property {String|Number} col = 4  			- 一行数量
-   *  @property {String|Number} row = 1 			- 几行
-   * @property {String} hasBorder 				- 是否有边框
-   * @property {String} borderColor 				- 边框颜色
-   * @property {String} background		  		- 背景
-   * @property {String} hoverClass 				- 按压样式类
-   * @property {String} hoverStayTime 		  	- 动画时间
-   *
-   * @property {Array} list 		  				- 导航列表
-   * @property {Number} iconSize 		  			- 图标大小
-   * @property {String} color 		  			- 标题颜色
-   *
-   */
+	/**
+	 * 轮播menu
+	 *
+	 * @property {Boolean} circular = false  		- 是否采用衔接滑动,即播放到末尾后重新回到开头
+	 * @property {Boolean} autoplay = true  		- 是否自动切换
+	 * @property {Number} interval = 5000  			- 自动切换时间间隔
+	 * @property {Number} duration = 500  			- 滑动动画时长,app-nvue不支持
+	 * @property {Array} list = [] 					- 轮播数据
+	 * @property {String} ui = ''  					- 样式class
+	 * @property {String} mode  					- 模式
+	 * @property {String} dotStyle  				- 指示点样式
+	 * @property {String} dotCur= 'ui-BG-Main' 		- 当前指示点样式,默认主题色
+	 * @property {String} bg  						- 背景
+	 *
+	 * @property {String|Number} col = 4  			- 一行数量
+	 * @property {String|Number} row = 1 			- 几行
+	 * @property {String} hasBorder 				- 是否有边框
+	 * @property {String} borderColor 				- 边框颜色
+	 * @property {String} background		  		- 背景
+	 * @property {String} hoverClass 				- 按压样式类
+	 * @property {String} hoverStayTime 		  	- 动画时间
+	 *
+	 * @property {Array} list 		  				- 导航列表
+	 * @property {Number} iconSize 		  			- 图标大小
+	 * @property {String} color 		  			- 标题颜色
+	 *
+	 */
 
-  import { reactive, computed } from 'vue';
-  import sheep from '@/sheep';
+	import {
+		reactive,
+		computed
+	} from 'vue';
+	import sheep from '@/sheep';
 
-  // 数据
-  const state = reactive({
-    cur: 0,
-  });
+	// 数据
+	const state = reactive({
+		cur: 0,
+	});
 
-  // 接收参数
+	// 接收参数
 
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-    styles: {
-      type: Object,
-      default() {},
-    },
-    circular: {
-      type: Boolean,
-      default: true,
-    },
-    autoplay: {
-      type: Boolean,
-      default: false,
-    },
-    interval: {
-      type: Number,
-      default: 5000,
-    },
-    duration: {
-      type: Number,
-      default: 500,
-    },
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+		circular: {
+			type: Boolean,
+			default: true,
+		},
+		autoplay: {
+			type: Boolean,
+			default: false,
+		},
+		interval: {
+			type: Number,
+			default: 5000,
+		},
+		duration: {
+			type: Number,
+			default: 500,
+		},
+		ui: {
+			type: String,
+			default: '',
+		},
+		mode: {
+			//default
+			type: String,
+			default: 'default',
+		},
+		dotStyle: {
+			type: String,
+			default: 'long', //default long tag
+		},
+		dotCur: {
+			type: String,
+			default: 'ui-BG-Main',
+		},
+		height: {
+			type: Number,
+			default: 300,
+		},
+		// 是否有边框
+		hasBorder: {
+			type: Boolean,
+			default: true,
+		},
+		// 边框颜色
+		borderColor: {
+			type: String,
+			default: 'red',
+		},
+		background: {
+			type: String,
+			default: 'blue',
+		},
+		hoverClass: {
+			type: String,
+			default: 'ss-hover-class', //'none'为没有hover效果
+		},
+		// 一排宫格数
+		col: {
+			type: [Number, String],
+			default: 3,
+		},
+		iconSize: {
+			type: Number,
+			default: 80,
+		},
+		color: {
+			type: String,
+			default: '#000',
+		},
+	});
 
-    ui: {
-      type: String,
-      default: '',
-    },
-    mode: {
-      //default
-      type: String,
-      default: 'default',
-    },
-    dotStyle: {
-      type: String,
-      default: 'long', //default long tag
-    },
-    dotCur: {
-      type: String,
-      default: 'ui-BG-Main',
-    },
-    bg: {
-      type: String,
-      default: 'bg-none',
-    },
-    height: {
-      type: Number,
-      default: 300,
-    },
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		console.log(props.styles)
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
-    // 是否有边框
-    hasBorder: {
-      type: Boolean,
-      default: true,
-    },
-    // 边框颜色
-    borderColor: {
-      type: String,
-      default: 'red',
-    },
-    background: {
-      type: String,
-      default: 'blue',
-    },
-    hoverClass: {
-      type: String,
-      default: 'ss-hover-class', //'none'为没有hover效果
-    },
-    // 一排宫格数
-    col: {
-      type: [Number, String],
-      default: 3,
-    },
-    iconSize: {
-      type: Number,
-      default: 80,
-    },
-    color: {
-      type: String,
-      default: '#000',
-    },
-  });
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 
-  // 生成数据
-  const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
-  const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
-  const windowWidth = sheep.$platform.device.windowWidth;
+	// 生成数据
+	const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
+	const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
+	const windowWidth = sheep.$platform.device.windowWidth;
 
-  // current 改变时会触发 change 事件
-  const swiperChange = (e) => {
-    state.cur = e.detail.current;
-  };
+	// current 改变时会触发 change 事件
+	const swiperChange = (e) => {
+		state.cur = e.detail.current;
+	};
 
-  // 重组数据
-  const splitData = (oArr = [], length = 1) => {
-    let arr = [];
-    let minArr = [];
-    oArr.forEach((c) => {
-      if (minArr.length === length) {
-        minArr = [];
-      }
-      if (minArr.length === 0) {
-        arr.push(minArr);
-      }
-      minArr.push(c);
-    });
+	// 重组数据
+	const splitData = (oArr = [], length = 1) => {
+		let arr = [];
+		let minArr = [];
+		oArr.forEach((c) => {
+			if (minArr.length === length) {
+				minArr = [];
+			}
+			if (minArr.length === 0) {
+				arr.push(minArr);
+			}
+			minArr.push(c);
+		});
 
-    return arr;
-  };
+		return arr;
+	};
 </script>
 
 <style lang="scss" scoped>
-  .grid-wrap {
-    width: 100%;
-    display: flex;
-    position: relative;
-    box-sizing: border-box;
-    overflow: hidden;
-    flex-wrap: wrap;
-    align-items: center;
-  }
-  .menu-box {
-    position: relative;
-    z-index: 1;
-    transform: translate(0, 0);
+	.grid-wrap {
+		width: 100%;
+		display: flex;
+		position: relative;
+		box-sizing: border-box;
+		overflow: hidden;
+		flex-wrap: wrap;
+		align-items: center;
+	}
 
-    .tag-box {
-      position: absolute;
-      z-index: 2;
-      top: 0;
-      right: -6rpx;
-      font-size: 2em;
-      line-height: 1;
-      padding: 0.4em 0.6em 0.3em;
-      transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
-      transform-origin: 100% 0;
-      border-radius: 200rpx;
-      white-space: nowrap;
-    }
+	.menu-box {
+		position: relative;
+		z-index: 1;
+		transform: translate(0, 0);
 
-    .menu-icon {
-      transform: translate(0, 0);
-      width: 80rpx;
-      height: 80rpx;
-      padding-bottom: 10rpx;
-    }
+		.tag-box {
+			position: absolute;
+			z-index: 2;
+			top: 0;
+			right: -6rpx;
+			font-size: 2em;
+			line-height: 1;
+			padding: 0.4em 0.6em 0.3em;
+			transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
+			transform-origin: 100% 0;
+			border-radius: 200rpx;
+			white-space: nowrap;
+		}
 
-    .menu-title {
-      font-size: 24rpx;
-      color: #333;
-    }
-  }
+		.menu-icon {
+			transform: translate(0, 0);
+			width: 80rpx;
+			height: 80rpx;
+			padding-bottom: 10rpx;
+		}
 
-  ::v-deep(.ui-swiper) {
-    position: relative;
-    z-index: 1;
+		.menu-title {
+			font-size: 24rpx;
+			color: #333;
+		}
+	}
 
-    .ui-swiper-dot {
-      position: absolute;
-      width: 100%;
-      bottom: 20rpx;
-      height: 30rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      z-index: 2;
+	::v-deep(.ui-swiper) {
+		position: relative;
+		z-index: 1;
 
-      &.default .line-box {
-        display: inline-flex;
-        border-radius: 50rpx;
-        width: 6px;
-        height: 6px;
-        border: 2px solid transparent;
-        margin: 0 10rpx;
-        opacity: 0.3;
-        position: relative;
-        justify-content: center;
-        align-items: center;
+		.ui-swiper-dot {
+			position: absolute;
+			width: 100%;
+			bottom: 20rpx;
+			height: 30rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			z-index: 2;
 
-        &.cur {
-          width: 8px;
-          height: 8px;
-          opacity: 1;
-          border: 0px solid transparent;
-        }
+			&.default .line-box {
+				display: inline-flex;
+				border-radius: 50rpx;
+				width: 6px;
+				height: 6px;
+				border: 2px solid transparent;
+				margin: 0 10rpx;
+				opacity: 0.3;
+				position: relative;
+				justify-content: center;
+				align-items: center;
 
-        &.cur::after {
-          content: '';
-          border-radius: 50rpx;
-          width: 4px;
-          height: 4px;
-          background-color: #fff;
-        }
-      }
+				&.cur {
+					width: 8px;
+					height: 8px;
+					opacity: 1;
+					border: 0px solid transparent;
+				}
 
-      &.long .line-box {
-        display: inline-block;
-        border-radius: 100rpx;
-        width: 6px;
-        height: 6px;
-        margin: 0 10rpx;
-        opacity: 0.3;
-        position: relative;
+				&.cur::after {
+					content: '';
+					border-radius: 50rpx;
+					width: 4px;
+					height: 4px;
+					background-color: #fff;
+				}
+			}
 
-        &.cur {
-          width: 24rpx;
-          opacity: 1;
-        }
+			&.long .line-box {
+				display: inline-block;
+				border-radius: 100rpx;
+				width: 6px;
+				height: 6px;
+				margin: 0 10rpx;
+				opacity: 0.3;
+				position: relative;
 
-        &.cur::after {
-        }
-      }
+				&.cur {
+					width: 24rpx;
+					opacity: 1;
+				}
 
-      &.line {
-        bottom: 20rpx;
+				&.cur::after {}
+			}
 
-        .line-box {
-          display: inline-block;
-          width: 30px;
-          height: 3px;
-          opacity: 0.3;
-          position: relative;
+			&.line {
+				bottom: 20rpx;
 
-          &.cur {
-            opacity: 1;
-          }
-        }
-      }
+				.line-box {
+					display: inline-block;
+					width: 30px;
+					height: 3px;
+					opacity: 0.3;
+					position: relative;
 
-      &.tag {
-        justify-content: flex-end;
-        position: absolute;
-        bottom: 20rpx;
-        right: 20rpx;
-      }
-    }
-  }
-</style>
+					&.cur {
+						opacity: 1;
+					}
+				}
+			}
+
+			&.tag {
+				justify-content: flex-end;
+				position: absolute;
+				bottom: 20rpx;
+				right: 20rpx;
+			}
+		}
+	}
+</style>

+ 93 - 71
sheep/components/s-menu-grid/s-menu-grid.vue

@@ -1,82 +1,104 @@
 <!-- 装修基础组件:宫格导航 -->
 <template>
-  <uni-grid :showBorder="Boolean(data.border)" :column="data.column">
-    <uni-grid-item
-      v-for="(item, index) in data.list"
-      :key="index"
-      @tap="sheep.$router.go(item.url)"
-    >
-      <view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
-        <view class="img-box">
-          <view
-            class="tag-box"
-            v-if="item.badge.show"
-            :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
-          >
-            {{ item.badge.text }}
-          </view>
-          <image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
-        </view>
+	<view :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+		<uni-grid :showBorder="Boolean(data.border)" :column="data.column">
+			<uni-grid-item v-for="(item, index) in data.list" :key="index" @tap="sheep.$router.go(item.url)">
+				<view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
+					<view class="img-box">
+						<view class="tag-box" v-if="item.badge.show"
+							:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
+							{{ item.badge.text }}
+						</view>
+						<image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
+					</view>
+
+					<view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
+						<view class="grid-text" :style="[{ color: item.titleColor }]">
+							{{ item.title }}
+						</view>
+						<view class="grid-tip" :style="[{ color: item.subtitleColor }]">
+							{{ item.subtitle }}
+						</view>
+					</view>
+				</view>
+			</uni-grid-item>
+		</uni-grid>
+	</view>
 
-        <view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
-          <view class="grid-text" :style="[{ color: item.titleColor }]">
-            {{ item.title }}
-          </view>
-          <view class="grid-tip" :style="[{ color: item.subtitleColor }]">
-            {{ item.subtitle }}
-          </view>
-        </view>
-      </view>
-    </uni-grid-item>
-  </uni-grid>
 </template>
 
 <script setup>
-  import sheep from '@/sheep';
+	import sheep from '@/sheep';
+	import {
+		computed
+	} from 'vue';
+
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-  });
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 </script>
 
 <style lang="scss" scoped>
-  .menu-image {
-    width: 24px;
-    height: 24px;
-  }
-  .grid-item-box {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    height: 100%;
-    .img-box {
-      position: relative;
-      .tag-box {
-        position: absolute;
-        z-index: 2;
-        top: 0;
-        right: 0;
-        font-size: 2em;
-        line-height: 1;
-        padding: 0.4em 0.6em 0.3em;
-        transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
-        transform-origin: 100% 0;
-        border-radius: 200rpx;
-        white-space: nowrap;
-      }
-    }
+	.menu-image {
+		width: 24px;
+		height: 24px;
+	}
+
+	.grid-item-box {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		height: 100%;
+
+		.img-box {
+			position: relative;
+
+			.tag-box {
+				position: absolute;
+				z-index: 2;
+				top: 0;
+				right: 0;
+				font-size: 2em;
+				line-height: 1;
+				padding: 0.4em 0.6em 0.3em;
+				transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
+				transform-origin: 100% 0;
+				border-radius: 200rpx;
+				white-space: nowrap;
+			}
+		}
 
-    .title-box {
-      .grid-tip {
-        font-size: 24rpx;
-        white-space: nowrap;
-        text-align: center;
-      }
-    }
-  }
-</style>
+		.title-box {
+			.grid-tip {
+				font-size: 24rpx;
+				white-space: nowrap;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 26 - 2
sheep/components/s-order-card/s-order-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户订单 -->
 <template>
-  <view class="ss-order-menu-wrap ss-flex ss-col-center">
+  <view class="ss-order-menu-wrap ss-flex ss-col-center" :style="[style, { marginLeft: `${data.space}px` }]">
     <view
       class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
       v-for="item in orderMap"
@@ -67,8 +67,32 @@
       path: '/pages/order/list',
     },
   ];
-
+  // 接收参数
+  const props = defineProps({
+  	// 装修数据
+  	data: {
+  	  type: Object,
+  	  default: () => ({}),
+  	},
+  	// 装修样式
+  	styles: {
+  	  type: Object,
+  	  default: () => ({}),
+  	},
+  });
+  // 设置角标
   const numData = computed(() => sheep.$store('user').numData);
+  // 设置背景样式
+  const style = computed(() => {
+    // 直接从 props.styles 解构
+    const { bgType, bgImg, bgColor } = props.styles; 
+    // 根据 bgType 返回相应的样式
+    return {
+  		background: bgType === 'img'
+  			? `url(${bgImg}) no-repeat top center / 100% 100%`
+  			: bgColor
+  	};
+  });
 </script>
 
 <style lang="scss" scoped>

+ 93 - 84
sheep/components/s-title-block/s-title-block.vue

@@ -1,100 +1,109 @@
 <!-- 装修商品组件:标题栏 -->
 <template>
-  <view
-    class="ss-title-wrap ss-flex ss-col-center"
-    :class="[state.typeMap[data.textAlign]]"
-    :style="[elStyles]"
-  >
-    <view class="title-content">
-      <!-- 主标题 -->
-      <view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
-      <!-- 副标题 -->
-      <view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
-    </view>
-    <!-- 查看更多 -->
-    <view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
-          :style="{color: data.descriptionColor}">
-      <view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
-      <text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
-    </view>
-  </view>
+	<view class="ss-title-wrap ss-flex ss-col-center" :class="[state.typeMap[data.textAlign]]" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+		<view class="title-content">
+			<!-- 主标题 -->
+			<view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
+			<!-- 副标题 -->
+			<view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
+		</view>
+		<!-- 查看更多 -->
+		<view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
+			:style="{color: data.descriptionColor}">
+			<view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
+			<text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
+		</view>
+	</view>
 </template>
 
 <script setup>
-  /**
-   * 标题栏
-   */
-  import { reactive } from 'vue';
-  import sheep from '@/sheep';
+	/**
+	 * 标题栏
+	 */
+	import {
+		reactive,
+		computed
+	} from 'vue';
+	import sheep from '@/sheep';
 
-  // 数据
-  const state = reactive({
-    typeMap: {
-      left: 'ss-row-left',
-      center: 'ss-row-center',
-    },
-  });
+	// 数据
+	const state = reactive({
+		typeMap: {
+			left: 'ss-row-left',
+			center: 'ss-row-center',
+		},
+	});
 
-  // 接收参数
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-    styles: {
-      type: Object,
-      default() {},
-    },
-  });
+	// 接收参数
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		console.log(props.data)
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
-  // 组件样式
-  const elStyles = {
-    background: `url(${sheep.$url.cdn(props.data.bgImgUrl)}) no-repeat top center / 100% auto`,
-    fontSize: `${props.data.titleSize}px`,
-    fontWeight: `${props.data.titleWeight}px`,
-  };
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 
-  // 标题样式
-  const titleStyles = {
-    color: props.data.titleColor,
-    fontSize: `${props.data.titleSize}px`,
-    textAlign: props.data.textAlign
-  };
+	// 标题样式
+	const titleStyles = {
+		color: props.data.titleColor,
+		fontSize: `${props.data.titleSize}px`,
+		textAlign: props.data.textAlign
+	};
 
-  // 副标题
-  const descStyles = {
-    color: props.data.descriptionColor,
-    textAlign: props.data.textAlign,
-    fontSize: `${props.data.descriptionSize}px`,
-    fontWeight: `${props.data.descriptionWeight}px`,
-  };
+	// 副标题
+	const descStyles = {
+		color: props.data.descriptionColor,
+		textAlign: props.data.textAlign,
+		fontSize: `${props.data.descriptionSize}px`,
+		fontWeight: `${props.data.descriptionWeight}px`,
+	};
 </script>
 
 <style lang="scss" scoped>
-  .ss-title-wrap {
-    height: 80rpx;
-    position: relative;
+	.ss-title-wrap {
+		height: 80rpx;
+		position: relative;
 
-    .title-content {
-      .title-text {
-        font-size: 30rpx;
-        color: #333;
-      }
+		.title-content {
+			.title-text {
+				font-size: 30rpx;
+				color: #333;
+			}
 
-      .sub-title-text {
-        font-size: 22rpx;
-        color: #999;
-      }
-    }
+			.sub-title-text {
+				font-size: 22rpx;
+				color: #999;
+			}
+		}
 
-    .more-box {
-      white-space: nowrap;
-      font-size: 22rpx;
-      color: #999;
-      position: absolute;
-      top: 50%;
-      transform: translateY(-50%);
-      right: 20rpx;
-    }
-  }
-</style>
+		.more-box {
+			white-space: nowrap;
+			font-size: 22rpx;
+			color: #999;
+			position: absolute;
+			top: 50%;
+			transform: translateY(-50%);
+			right: 20rpx;
+		}
+	}
+</style>

+ 24 - 5
sheep/components/s-user-card/s-user-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户卡片 -->
 <template>
-	<view class="ss-user-info-wrap ss-p-t-50">
+	<view class="ss-user-info-wrap ss-p-t-50" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
 		<view class="ss-flex ss-col-center ss-row-between ss-m-b-20">
 			<view class="left-box ss-flex ss-col-center ss-m-l-36">
 				<view class="avatar-box ss-m-r-24">
@@ -70,9 +70,15 @@
 	const isLogin = computed(() => sheep.$store('user').isLogin);
 	// 接收参数
 	const props = defineProps({
-		background: {
-			type: String,
-			default: '',
+		// 装修数据
+		data: {
+		  type: Object,
+		  default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+		  type: Object,
+		  default: () => ({}),
 		},
 		// 头像
 		avatar: {
@@ -96,7 +102,20 @@
 			default: '1',
 		},
 	});
-
+	
+	// 设置背景样式
+	const bgStyle = computed(() => {
+	  // 直接从 props.styles 解构
+	  const { bgType, bgImg, bgColor } = props.styles; 
+	
+	  // 根据 bgType 返回相应的样式
+	  return {
+		background: bgType === 'img'
+			? `url(${bgImg}) no-repeat top center / 100% 100%`
+			: bgColor
+		};
+	});
+	// 绑定手机号
 	function onBind() {
 		showAuthModal('changeMobile');
 	}

+ 28 - 2
sheep/components/s-wallet-card/s-wallet-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户资产 -->
 <template>
-	<view class="ss-wallet-menu-wrap ss-flex ss-col-center">
+	<view class="ss-wallet-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
 		<view class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
 			@tap="sheep.$router.go('/pages/user/wallet/money')">
 			<view class="value-box ss-flex ss-col-bottom">
@@ -42,8 +42,34 @@
 	 */
 	import { computed } from 'vue';
 	import sheep from '@/sheep';
-  import { fen2yuan } from '../../hooks/useGoods';
+	import { fen2yuan } from '../../hooks/useGoods';
 
+	// 接收参数
+	const props = defineProps({
+		// 装修数据
+		data: {
+		  type: Object,
+		  default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+		  type: Object,
+		  default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+	  // 直接从 props.styles 解构
+	  const { bgType, bgImg, bgColor } = props.styles; 
+	
+	  // 根据 bgType 返回相应的样式
+	  return {
+		background: bgType === 'img'
+			? `url(${bgImg}) no-repeat top center / 100% 100%`
+			: bgColor
+		};
+	});
+	
 	const userWallet = computed(() => sheep.$store('user').userWallet);
 	const userInfo = computed(() => sheep.$store('user').userInfo);
 	const numData = computed(() => sheep.$store('user').numData);