lifanagju_citu 5 ماه پیش
والد
کامیت
986fd8e55e

+ 1 - 0
components.d.ts

@@ -58,6 +58,7 @@ declare module 'vue' {
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     SimilarPositions: typeof import('./src/components/Position/similarPositions.vue')['default']
+    SuNumberBox: typeof import('./src/components/FormUI/su-number-box/su-number-box.vue')['default']
     SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
     TextArea: typeof import('./src/components/FormUI/textArea/index.vue')['default']
     TextInput: typeof import('./src/components/FormUI/TextInput/index.vue')['default']

+ 248 - 0
src/components/FormUI/su-number-box/su-number-box.vue

@@ -0,0 +1,248 @@
+<template>
+  <view class="uni-numbox">
+    <!-- <view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{ background }"> -->
+    <!-- <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }"
+				:style="{ color }">
+				-
+			</text> -->
+    <!-- <text
+      class="cicon-move-round"
+      :class="{
+        'uni-numbox--disabled': inputValue <= min || disabled,
+        'groupon-btn': activity === 'groupon',
+        'seckill-btn': activity === 'seckill',
+      }"
+      @click="_calcValue('minus')"
+    ></text> -->
+    <v-btn
+      icon="mdi-minus" 
+      size="x-small" 
+      :disabled="inputValue <= min || disabled" 
+      @click="_calcValue('minus')"
+    ></v-btn>
+    <!-- </view> -->
+    <input
+      :disabled="disabled"
+      @focus="_onFocus"
+      @blur="_onBlur"
+      class="uni-numbox__value inputItem mx-2"
+      type="number"
+      v-model="inputValue"
+      :style="{ color }"
+    />
+    <!-- <view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns">
+			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }">+</text>
+		</view> -->
+    <v-btn
+      icon="mdi-plus" 
+      size="x-small" 
+      :disabled="inputValue >= max || disabled" 
+      @click="_calcValue('plus')"
+    ></v-btn>
+    <!-- <text
+      class="cicon-add-round"
+      :class="{
+        'uni-numbox--disabled': inputValue >= max || disabled,
+        'groupon-btn': activity === 'groupon',
+        'seckill-btn': activity === 'seckill',
+      }"
+      @click="_calcValue('plus')"
+    ></text> -->
+  </view>
+</template>
+<script>
+  /**
+   * NumberBox 数字输入框
+   * @description 带加减按钮的数字输入框
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=31
+   * @property {Number} value 输入框当前值
+   * @property {Number} min 最小值
+   * @property {Number} max 最大值
+   * @property {Number} step 每次点击改变的间隔大小
+   * @property {String} background 背景色
+   * @property {String} color 字体颜色(前景色)
+   * @property {Boolean} disabled = [true|false] 是否为禁用状态
+   * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
+   * @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
+   * @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
+   */
+
+  export default {
+    name: 'UniNumberBox',
+    emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
+    props: {
+      value: {
+        type: [Number, String],
+        default: 1,
+      },
+      modelValue: {
+        type: [Number, String],
+        default: 1,
+      },
+      min: {
+        type: Number,
+        default: 0,
+      },
+      max: {
+        type: Number,
+        default: 100,
+      },
+      step: {
+        type: Number,
+        default: 1,
+      },
+      background: {
+        type: String,
+        default: '#f5f5f5',
+      },
+      color: {
+        type: String,
+        default: '#333',
+      },
+      disabled: {
+        type: Boolean,
+        default: false,
+      },
+      activity: {
+        type: String,
+        default: 'none',
+      },
+    },
+    data() {
+      return {
+        inputValue: 0,
+      };
+    },
+    watch: {
+      value(val) {
+        this.inputValue = +val;
+      },
+      modelValue(val) {
+        this.inputValue = +val;
+      },
+    },
+    created() {
+      if (this.value === 1) {
+        this.inputValue = +this.modelValue;
+      }
+      if (this.modelValue === 1) {
+        this.inputValue = +this.value;
+      }
+    },
+    methods: {
+      _calcValue(type) {
+        if (this.disabled) {
+          return;
+        }
+        const scale = this._getDecimalScale();
+        let value = this.inputValue * scale;
+        let step = this.step * scale;
+        if (type === 'minus') {
+          value -= step;
+          if (value < this.min * scale) {
+            return;
+          }
+          if (value > this.max * scale) {
+            value = this.max * scale;
+          }
+        }
+
+        if (type === 'plus') {
+          value += step;
+          if (value > this.max * scale) {
+            return;
+          }
+          if (value < this.min * scale) {
+            value = this.min * scale;
+          }
+        }
+
+        this.inputValue = (value / scale).toFixed(String(scale).length - 1);
+        this.$emit('change', +this.inputValue);
+        // TODO vue2 兼容
+        this.$emit('input', +this.inputValue);
+        // TODO vue3 兼容
+        this.$emit('update:modelValue', +this.inputValue);
+      },
+      _getDecimalScale() {
+        let scale = 1;
+        // 浮点型
+        if (~~this.step !== this.step) {
+          scale = Math.pow(10, String(this.step).split('.')[1].length);
+        }
+        return scale;
+      },
+      _onBlur(event) {
+        this.$emit('blur', event);
+        let value = event.detail.value;
+        if (!value) {
+          // this.inputValue = 0;
+          return;
+        }
+        value = +value;
+        if (value > this.max) {
+          value = this.max;
+        } else if (value < this.min) {
+          value = this.min;
+        }
+        const scale = this._getDecimalScale();
+        this.inputValue = value.toFixed(String(scale).length - 1);
+        this.$emit('change', +this.inputValue);
+        this.$emit('input', +this.inputValue);
+      },
+      _onFocus(event) {
+        this.$emit('focus', event);
+      },
+    },
+  };
+</script>
+<style lang="scss" scoped>
+  .uni-numbox .uni-numbox--disabled {
+    color: #c0c0c0 !important;
+    /* #ifdef H5 */
+    cursor: not-allowed;
+    /* #endif */
+  }
+
+  .uni-numbox {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    align-items: center;
+  }
+
+  .uni-numbox__value {
+    width: 70px;
+    text-align: center;
+    // font-size: 30rpx;
+  }
+
+  .cicon-move-round {
+    font-size: 44rpx;
+    color: var(--ui-BG-Main);
+  }
+
+  .cicon-add-round {
+    font-size: 44rpx;
+    color: var(--ui-BG-Main);
+  }
+
+  .groupon-btn {
+    color: #ff6000;
+  }
+
+  .seckill-btn {
+    color: #ff5854;
+  }
+
+  input::-webkit-outer-spin-button, input::-webkit-inner-spin-button{
+    -webkit-appearance: none !important;
+    margin: 0; 
+  }
+  .inputItem {
+    width: 70px; 
+    border: 1px solid #eee; 
+    padding: 2px 5px; 
+    text-align: center;
+  }
+</style>

+ 1 - 7
src/views/mall/components/details.vue

@@ -44,7 +44,7 @@ const getData = async () => {
   obj.sliderPicUrls = obj.sliderPicUrls || []
   skus.value = obj.skus || []
   goodsInfo.value = obj
-  console.log('getProductDetail:', goodsInfo.value)
+  // console.log('getProductDetail:', goodsInfo.value)
 }
 getData()
 
@@ -89,10 +89,4 @@ const calcPrice = (price) => { return price && (price-0) ? (price-0)/100 : '' }
   line-height: 34px;
   text-decoration: line-through;
 }
-.buyCount {
-  display: flex;
-  align-items: center;
-}
-.salesCount {
-}
 </style>

+ 394 - 203
src/views/mall/components/detailsComponents/s-select-sku.vue

@@ -1,6 +1,43 @@
 <template>
-  <div class="ss-modal-box bg-white ss-flex-col">
-    <!-- SKU 信息 -->
+  <!-- SKU 信息 -->
+  <div>
+    <!-- <div>
+      <div class="header-left ss-m-r-30">
+        <image
+          class="sku-image"
+          :src="state.selectedSku.picUrl || goodsInfo.picUrl"
+          mode="aspectFill"
+        />
+      </div>
+      <div class="header-right ss-flex-col ss-row-between ss-flex-1">
+        <div class="goods-title ss-line-2">{{ goodsInfo.name }}</div>
+        <div class="header-right-bottom ss-flex ss-col-center ss-row-between">
+          <div class="ss-flex">
+            <div class="price-text">
+              {{
+                fen2yuan(
+                  state.selectedSku.promotionPrice || state.selectedSku.price || goodsInfo.price,
+                )
+              }}
+              <text v-if="state.selectedSku.promotionType > 0">
+                <text class="iconBox" v-if="state.selectedSku.promotionType === 4">
+                  限时优惠
+                </text>
+                <text class="iconBox" v-else-if="state.selectedSku.promotionType === 6">
+                  会员价
+                </text>
+                <text class="origin-price-text">
+                  {{ fen2yuan(state.selectedSku.price) }}
+                </text>
+              </text>
+            </div>
+          </div>
+          <div class="stock-text ss-m-l-20">
+            {{ formatStock('exact', state.selectedSku.stock || goodsInfo.stock) }}
+          </div>
+        </div>
+      </div>
+    </div> -->
     <!-- 属性选择 -->
     <div class="d-flex mb-5" v-for="property in propertyList" :key="property.id">
       <span class="l-s-10 parameterColor mb-1">{{ property.name }}</span>:
@@ -26,255 +63,409 @@
       </span>
     </div>
     <!-- 购买数量 -->
-    <div class="buyCount mb-10">
+    <!-- <div class="buyCount mb-10">
       <span class="parameterColor"><span class="l-s-10">数量</span>:</span>
       <div class="d-flex">
-        <v-btn icon="mdi-minus" size="x-small" :disabled="number<=1" @click="number > 1 ? number-- : 0"></v-btn>
+        <v-btn icon="mdi-minus" size="x-small" :disabled="number<=1" @click="handleReduce"></v-btn>
         <input
-          v-model="state.selectedSku.goods_num"
+          v-model="number"
           class="inputItem mx-2"
           type="number"
           :disabled="!goodsInfo.stock"
           @change="onNumberChange"
         >
-        <v-btn icon="mdi-plus" size="x-small" :disabled="goodsInfo.stock ? number >= (state.selectedSku.stock) : true" @click="number ? number++ : 0"></v-btn>
+        <v-btn icon="mdi-plus" size="x-small" :disabled="number >= (state.selectedSku.stock)" @click="handleIncrease"></v-btn>
+      </div>
+      <div class="ml-3" style="color: #b7b7b7; font-size: 14px;">库存:{{ state.selectedSku.stock || props.goodsInfo.stock }}</div>
+    </div> -->
+    <div class="modal-content ss-flex-1">
+      <div>
+        <div class="buyCount mb-10">
+          <span class="parameterColor"><span class="l-s-10">数量</span>:</span>
+          <su-number-box
+            :min="1"
+            :max="state.selectedSku.stock"
+            :step="1"
+            v-model="state.selectedSku.goods_num"
+            @change="onNumberChange($event)"
+          />
+        </div>
       </div>
-      <!-- 库存 -->
-      <div class="ml-3" style="color: #b7b7b7; font-size: 14px;">{{ formatStock('exact', state.selectedSku.stock || goodsInfo.stock) }}</div>
-      <!-- <div class="ml-3" style="color: #b7b7b7; font-size: 14px;">库存:{{ goodsInfo.stock || 0 }}</div> -->
     </div>
+    <!-- 操作区 onAddCart onBuy -->
     <div>
-      <v-btn class="buttons" color="primary" @click="null">立即购买</v-btn>
+      <v-btn class="buttons" color="primary" @click="onBuy">立即购买</v-btn>
     </div>
   </div>
 </template>
 
 <script setup>
 defineOptions({name: 'wares-s-select-sku'})
-import { computed, reactive, watch, ref } from 'vue'
+import Snackbar from '@/plugins/snackbar'
+import suNumberBox from '@/components/FormUI/su-number-box/su-number-box.vue'
+import { computed, reactive, watch } from 'vue'
 import { convertProductPropertyList } from '@/views/mall/utils'
-const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
-const props = defineProps({
-  goodsInfo: {
-    type: Object,
-    default() {},
+
+  const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
+  const props = defineProps({
+    goodsInfo: {
+      type: Object,
+      default() {},
+    },
+  });
+
+  const state = reactive({
+    selectedSku: {}, // 选中的 SKU
+    currentPropertyArray: [], // 当前选中的属性,实际是个 Map。key 是 property 编号,value 是 value 编号
+  });
+
+  const propertyList = convertProductPropertyList(props.goodsInfo.skus);
+  // SKU 列表
+  const skuList = computed(() => {
+    let skuPrices = props.goodsInfo.skus;
+    for (let price of skuPrices) {
+      price.value_id_array = price.properties.map((item) => item.valueId);
+    }
+    return skuPrices;
+  });
+
+  watch(
+    () => state.selectedSku,
+    (newVal) => {
+      emits('change', newVal);
+    },
+    {
+      immediate: true, // 立即执行
+      deep: true, // 深度监听
+    },
+  );
+
+  // 输入框改变数量
+  function onNumberChange(e) {
+    if (e === 0) return;
+    if (state.selectedSku.goods_num === e) return;
+    state.selectedSku.goods_num = e;
   }
-});
-
-const state = reactive({
-  selectedSku: {}, // 选中的 SKU
-  currentPropertyArray: [], // 当前选中的属性,实际是个 Map。key 是 property 编号,value 是 value 编号
-});
-
-const onNumberChange = () => {
-  if (number.value === 0) return
-  if (state.selectedSku.goods_num === number.value) return
-  state.selectedSku.goods_num = number.value
-  // if ( number.value < 0) return number.value = goodsInfo.value.stock ? 1 : 0
-  // if ( number.value > goodsInfo.value.stock) number.value = goodsInfo.value.stock
-  // number.value = parseInt( number.value)
-}
-
-// SKU 列表
-const skuList = computed(() => {
-  let skuPrices =  props.goodsInfo.skus?.length ? props.goodsInfo.skus : []
-  for (let price of skuPrices) {
-    price.value_id_array = price.properties.map((item) => item.valueId);
+
+  // 加入购物车
+  // function onAddCart() {
+  //   if (state.selectedSku.id <= 0) {
+  //     Snackbar.warning('请选择商品规格')
+  //     return;
+  //   }
+  //   if (state.selectedSku.stock <= 0) {
+  //     Snackbar.warning('库存不足')
+  //     return;
+  //   }
+
+  //   emits('addCart', state.selectedSku);
+  // }
+
+  // 立即购买
+  function onBuy() {
+    if (state.selectedSku.id <= 0) {
+      Snackbar.warning('请选择商品规格')
+      return;
+    }
+    if (state.selectedSku.stock <= 0) {
+      Snackbar.warning('库存不足')
+      return;
+    }
+    emits('buy', state.selectedSku);
   }
-  return skuPrices;
-});
-
-const number = ref(0)
-const stockShow = ref(0)
-const propertyList = ref([])
-watch(
-  () => props.goodsInfo,
-  (newVal) => {
-    if (newVal && Object.keys(newVal)) {
-      stockShow.value = newVal.goodsInfo.stock-0
-      number.value = stock.value ? 1 : 0
-      if (newVal.skus && newVal.skus.length) {
-        propertyList.value = newVal.goodsInfo.skus?.length ? convertProductPropertyList(newVal.goodsInfo.skus) : []
-        // console.log('propertyList:', propertyList.value)
+
+  // 改变禁用状态:计算每个 property 属性值的按钮,是否禁用
+  function changeDisabled(isChecked = false, propertyId = 0, valueId = 0) {
+    let newSkus = []; // 所有可以选择的 sku 数组
+    if (isChecked) {
+      // 情况一:选中 property
+      // 获得当前点击选中 property 的、所有可用 SKU
+      for (let price of skuList.value) {
+        if (price.stock <= 0) {
+          continue;
+        }
+        if (price.value_id_array.indexOf(valueId) >= 0) {
+          newSkus.push(price);
+        }
       }
+    } else {
+      // 情况二:取消选中 property
+      // 当前所选 property 下,所有可以选择的 SKU
+      newSkus = getCanUseSkuList();
+    }
+
+    // 所有存在并且有库存未选择的 SKU 的 value 属性值 id
+    let noChooseValueIds = [];
+    for (let price of newSkus) {
+      noChooseValueIds = noChooseValueIds.concat(price.value_id_array);
     }
-  },
-  {
-    immediate: true, // 立即执行
-    // deep: true, // 深度监听
-  },
-);
-
-watch(
-  () => state.selectedSku,
-  (newVal) => {
-    emits('change', newVal);
-  },
-  {
-    immediate: true, // 立即执行
-    deep: true, // 深度监听
-  },
-);
-
-
-// 改变禁用状态:计算每个 property 属性值的按钮,是否禁用
-function changeDisabled(isChecked = false, propertyId = 0, valueId = 0) {
-  let newSkus = []; // 所有可以选择的 sku 数组
-  if (isChecked) {
-    // 情况一:选中 property
-    // 获得当前点击选中 property 的、所有可用 SKU
-    for (let price of skuList.value) {
-      if (price.stock <= 0) {
+    noChooseValueIds = Array.from(new Set(noChooseValueIds)); // 去重
+
+    if (isChecked) {
+      // 去除当前选中的 value 属性值 id
+      let index = noChooseValueIds.indexOf(valueId);
+      noChooseValueIds.splice(index, 1);
+    } else {
+      // 循环去除当前已选择的 value 属性值 id
+      state.currentPropertyArray.forEach((currentPropertyId) => {
+        if (currentPropertyId.toString() !== '') {
+          return;
+        }
+        // currentPropertyId 为空是反选 填充的
+        let index = noChooseValueIds.indexOf(currentPropertyId);
+        if (index >= 0) {
+          // currentPropertyId 存在于 noChooseValueIds
+          noChooseValueIds.splice(index, 1);
+        }
+      });
+    }
+
+    // 当前已选择的 property 数组
+    let choosePropertyIds = [];
+    if (!isChecked) {
+      // 当前已选择的 property
+      state.currentPropertyArray.forEach((currentPropertyId, currentValueId) => {
+        if (currentPropertyId !== '') {
+          // currentPropertyId 为空是反选 填充的
+          choosePropertyIds.push(currentValueId);
+        }
+      });
+    } else {
+      // 当前点击选择的 property
+      choosePropertyIds = [propertyId];
+    }
+
+    for (let propertyIndex in propertyList) {
+      // 当前点击的 property、或者取消选择时候,已选中的 property 不进行处理
+      if (choosePropertyIds.indexOf(propertyList[propertyIndex]['id']) >= 0) {
         continue;
       }
-      if (price.value_id_array.indexOf(valueId) >= 0) {
-        newSkus.push(price);
+      // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
+      for (let valueIndex in propertyList[propertyIndex]['values']) {
+        propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
+          noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
       }
     }
-  } else {
-    // 情况二:取消选中 property
-    // 当前所选 property 下,所有可以选择的 SKU
-    newSkus = getCanUseSkuList();
   }
 
-  // 所有存在并且有库存未选择的 SKU 的 value 属性值 id
-  let noChooseValueIds = [];
-  for (let price of newSkus) {
-    noChooseValueIds = noChooseValueIds.concat(price.value_id_array);
-  }
-  noChooseValueIds = Array.from(new Set(noChooseValueIds)); // 去重
-
-  if (isChecked) {
-    // 去除当前选中的 value 属性值 id
-    let index = noChooseValueIds.indexOf(valueId);
-    noChooseValueIds.splice(index, 1);
-  } else {
-    // 循环去除当前已选择的 value 属性值 id
-    state.currentPropertyArray.forEach((currentPropertyId) => {
-      if (currentPropertyId.toString() !== '') {
-        return;
+  // 当前所选属性下,获取所有有库存的 SKU 们
+  function getCanUseSkuList() {
+    let newSkus = [];
+    for (let sku of skuList.value) {
+      if (sku.stock <= 0) {
+        continue;
       }
-      // currentPropertyId 为空是反选 填充的
-      let index = noChooseValueIds.indexOf(currentPropertyId);
-      if (index >= 0) {
-        // currentPropertyId 存在于 noChooseValueIds
-        noChooseValueIds.splice(index, 1);
+      let isOk = true;
+      state.currentPropertyArray.forEach((propertyId) => {
+        // propertyId 不为空,并且,这个 条 sku 没有被选中,则排除
+        if (propertyId.toString() !== '' && sku.value_id_array.indexOf(propertyId) < 0) {
+          isOk = false;
+        }
+      });
+      if (isOk) {
+        newSkus.push(sku);
       }
-    });
+    }
+    return newSkus;
   }
 
-  // 当前已选择的 property 数组
-  let choosePropertyIds = [];
-  if (!isChecked) {
-    // 当前已选择的 property
-    state.currentPropertyArray.forEach((currentPropertyId, currentValueId) => {
+  // 选择规格
+  function onSelectSku(propertyId, valueId) {
+    // 清空已选择
+    let isChecked = true; // 选中 or 取消选中
+    if (
+      state.currentPropertyArray[propertyId] !== undefined &&
+      state.currentPropertyArray[propertyId] === valueId
+    ) {
+      // 点击已被选中的,删除并填充 ''
+      isChecked = false;
+      state.currentPropertyArray.splice(propertyId, 1, '');
+    } else {
+      // 选中
+      state.currentPropertyArray[propertyId] = valueId;
+    }
+
+    // 选中的 property 大类
+    let choosePropertyId = [];
+    state.currentPropertyArray.forEach((currentPropertyId) => {
       if (currentPropertyId !== '') {
         // currentPropertyId 为空是反选 填充的
-        choosePropertyIds.push(currentValueId);
+        choosePropertyId.push(currentPropertyId);
       }
     });
-  } else {
-    // 当前点击选择的 property
-    choosePropertyIds = [propertyId];
-  }
 
-  for (let propertyIndex in propertyList.value) {
-    // 当前点击的 property、或者取消选择时候,已选中的 property 不进行处理
-    if (choosePropertyIds.indexOf(propertyList.value[propertyIndex]['id']) >= 0) {
-      continue;
-    }
-    // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
-    for (let valueIndex in propertyList.value[propertyIndex]['values']) {
-      propertyList.value[propertyIndex]['values'][valueIndex]['disabled'] =
-        noChooseValueIds.indexOf(propertyList.value[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
+    // 当前所选 property 下,所有可以选择的 SKU 们
+    let newSkuList = getCanUseSkuList();
+
+    // 判断所有 property 大类是否选择完成
+    if (choosePropertyId.length === propertyList.length && newSkuList.length) {
+      newSkuList[0].goods_num = state.selectedSku.goods_num || 1;
+      state.selectedSku = newSkuList[0];
+    } else {
+      state.selectedSku = {};
     }
+
+    // 改变 property 禁用状态
+    changeDisabled(isChecked, propertyId, valueId);
   }
-}
-
-// 当前所选属性下,获取所有有库存的 SKU 们
-function getCanUseSkuList() {
-  let newSkus = [];
-  for (let sku of skuList.value) {
-    if (sku.stock <= 0) {
-      continue;
+
+  changeDisabled(false);
+  // TODO 芋艿:待讨论的优化点:1)单规格,要不要默认选中;2)默认要不要选中第一个规格
+</script>
+
+<style lang="scss" scoped>
+  // 主题色渐变,横向
+  .ui-BG-Main-Gradient {
+    // background: linear-gradient(90deg, #ff3000, #ff300099);
+    background: var(--v-primary-base);
+    color: #fff !important;
+  }
+  .disabled-btn {
+    color: #c6c6c6;
+    background: #f8f8f8;
+  }
+  .parameterColor {
+    color: #7a7a7a;
+  }
+  input::-webkit-outer-spin-button, input::-webkit-inner-spin-button{
+    -webkit-appearance: none !important;
+    margin: 0; 
+  }
+  .inputItem {
+    width: 70px; border: 1px solid #eee; padding: 0 5px; text-align: center;
+  }
+  .buyCount {
+    display: flex;
+    align-items: center;
+  }
+  // 购买
+  .buy-box {
+    padding: 10rpx 0;
+
+    .add-btn {
+      width: 356rpx;
+      height: 80rpx;
+      border-radius: 40rpx 0 0 40rpx;
+      background-color: var(--ui-BG-Main-light);
+      color: var(--ui-BG-Main);
     }
-    let isOk = true;
-    state.currentPropertyArray.forEach((propertyId) => {
-      // propertyId 不为空,并且,这个 条 sku 没有被选中,则排除
-      if (propertyId.toString() !== '' && sku.value_id_array.indexOf(propertyId) < 0) {
-        isOk = false;
-      }
-    });
-    if (isOk) {
-      newSkus.push(sku);
+
+    .buy-btn {
+      width: 356rpx;
+      height: 80rpx;
+      border-radius: 0 40rpx 40rpx 0;
+      background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+      color: #fff;
+    }
+
+    .score-btn {
+      width: 100%;
+      margin: 0 20rpx;
+      height: 80rpx;
+      border-radius: 40rpx;
+      background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+      color: #fff;
     }
-  }
-  return newSkus;
-}
-
-// 选择规格
-function onSelectSku(propertyId, valueId) {
-  // 清空已选择
-  let isChecked = true; // 选中 or 取消选中
-  if (
-    state.currentPropertyArray[propertyId] !== undefined &&
-    state.currentPropertyArray[propertyId] === valueId
-  ) {
-    // 点击已被选中的,删除并填充 ''
-    isChecked = false;
-    state.currentPropertyArray.splice(propertyId, 1, '');
-  } else {
-    // 选中
-    state.currentPropertyArray[propertyId] = valueId;
   }
 
-  // 选中的 property 大类
-  let choosePropertyId = [];
-  state.currentPropertyArray.forEach((currentPropertyId) => {
-    if (currentPropertyId !== '') {
-      // currentPropertyId 为空是反选 填充的
-      choosePropertyId.push(currentPropertyId);
+  .ss-modal-box {
+    border-radius: 30rpx 30rpx 0 0;
+    max-height: 1000rpx;
+
+    .modal-header {
+      position: relative;
+      padding: 80rpx 20rpx 40rpx;
+
+      .sku-image {
+        width: 160rpx;
+        height: 160rpx;
+        border-radius: 10rpx;
+      }
+
+      .header-right {
+        height: 160rpx;
+      }
+
+      .close-icon {
+        position: absolute;
+        top: 10rpx;
+        right: 20rpx;
+        font-size: 46rpx;
+        opacity: 0.2;
+      }
+
+      .goods-title {
+        font-size: 28rpx;
+        font-weight: 500;
+        line-height: 42rpx;
+      }
+
+      .score-img {
+        width: 36rpx;
+        height: 36rpx;
+        margin: 0 4rpx;
+      }
+      .stock-text {
+        font-size: 26rpx;
+        color: #999999;
+      }
     }
-  });
 
-  // 当前所选 property 下,所有可以选择的 SKU 们
-  let newSkuList = getCanUseSkuList();
+    .modal-content {
+      padding: 0 20rpx;
+
+      .modal-content-scroll {
+        max-height: 600rpx;
+
+        .label-text {
+          font-size: 26rpx;
+          font-weight: 500;
+        }
 
-  // 判断所有 property 大类是否选择完成
-  if (choosePropertyId.length === propertyList.value.length && newSkuList.length) {
-    newSkuList[0].goods_num = state.selectedSku.goods_num || 1;
-    state.selectedSku = newSkuList[0];
-  } else {
-    state.selectedSku = {};
+        .buy-num-box {
+          height: 100rpx;
+        }
+
+        .spec-btn {
+          height: 60rpx;
+          min-width: 100rpx;
+          padding: 0 30rpx;
+          background: #f4f4f4;
+          border-radius: 30rpx;
+          color: #434343;
+          font-size: 26rpx;
+          margin-right: 10rpx;
+          margin-bottom: 10rpx;
+        }
+
+        .disabled-btn {
+          // font-weight: 400;
+          color: #c6c6c6;
+          background: #f8f8f8;
+        }
+      }
+    }
   }
 
-  // 改变 property 禁用状态
-  changeDisabled(isChecked, propertyId, valueId);
-}
+  .iconBox {
+    width: fit-content;
+    height: fit-content;
+    padding: 2rpx 10rpx;
+    background-color: rgb(255, 242, 241);
+    color: #ff2621;
+    font-size: 24rpx;
+    margin-left: 5rpx;
+  }
 
-changeDisabled(false);
-// TODO 芋艿:待讨论的优化点:1)单规格,要不要默认选中;2)默认要不要选中第一个规格
-</script>
+  .origin-price-text {
+    font-size: 26rpx;
+    font-weight: 400;
+    text-decoration: line-through;
+    color: gray;
+    font-family: OPPOSANS;
 
-<style lang="scss" scoped>
-// 主题色渐变,横向
-.ui-BG-Main-Gradient {
-  // background: linear-gradient(90deg, #ff3000, #ff300099);
-  background: var(--v-primary-base);
-  color: #fff !important;
-}
-.disabled-btn {
-  color: #c6c6c6;
-  background: #f8f8f8;
-}
-.parameterColor {
-  color: #7a7a7a;
-}
-input::-webkit-outer-spin-button, input::-webkit-inner-spin-button{
-  -webkit-appearance: none !important;
-  margin: 0; 
-}
-.inputItem {
-  width: 70px; border: 1px solid #eee; padding: 0 5px; text-align: center;
-}
+    &::before {
+      content: '¥';
+    }
+  }
 </style>