init
This commit is contained in:
33
uni_modules/nutui-uni/components/sku/index.scss
Normal file
33
uni_modules/nutui-uni/components/sku/index.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
@import '../price/index';
|
||||
@import '../inputnumber/index';
|
||||
@import '../popup/index';
|
||||
|
||||
.nut-theme-dark {
|
||||
.nut-sku {
|
||||
background: $dark-background;
|
||||
}
|
||||
}
|
||||
|
||||
.nut-sku {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
background: $white;
|
||||
|
||||
&-content {
|
||||
flex: 1;
|
||||
margin-top: 24px;
|
||||
overflow: hidden auto;
|
||||
|
||||
&-wrapper {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 0 18px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
uni_modules/nutui-uni/components/sku/index.ts
Normal file
1
uni_modules/nutui-uni/components/sku/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type * from './sku'
|
||||
79
uni_modules/nutui-uni/components/sku/sku.ts
Normal file
79
uni_modules/nutui-uni/components/sku/sku.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { CLOSE_EVENT, UPDATE_VISIBLE_EVENT } from '../_constants'
|
||||
import { commonProps, isBoolean, isNumber, isString, makeArrayProp, makeNumericProp } from '../_utils'
|
||||
|
||||
export const skuProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 是否显示商品规格弹框
|
||||
*/
|
||||
visible: Boolean,
|
||||
/**
|
||||
* @description 商品 sku 数据
|
||||
*/
|
||||
sku: makeArrayProp<any>([]),
|
||||
/**
|
||||
* @description 商品信息
|
||||
*/
|
||||
goods: Object,
|
||||
/**
|
||||
* @description 设置 inputNumber 最大值
|
||||
*/
|
||||
stepperMax: makeNumericProp(99999),
|
||||
/**
|
||||
* @description 设置 inputNumber 最小值
|
||||
*/
|
||||
stepperMin: makeNumericProp(1),
|
||||
/**
|
||||
* 底部按钮设置。[`confirm`, `buy`, `cart`] 分别对应确定、立即购买、加入购物车
|
||||
* @description 底部按钮设置
|
||||
*/
|
||||
btnOptions: makeArrayProp<string>(['confirm']),
|
||||
/**
|
||||
* @description 按钮上部添加文案,默认为空,有值时显示
|
||||
*/
|
||||
btnExtraText: String,
|
||||
/**
|
||||
* @description 数量选择组件左侧文案
|
||||
*/
|
||||
stepperTitle: String,
|
||||
/**
|
||||
* @description InputNumber 与标题之间的文案
|
||||
*/
|
||||
stepperExtraText: {
|
||||
type: [Function, Boolean],
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* @description 立即购买按钮文案
|
||||
*/
|
||||
buyText: String,
|
||||
/**
|
||||
* @description 加入购物车按钮文案
|
||||
*/
|
||||
addCartText: String,
|
||||
/**
|
||||
* @description 确定按钮文案
|
||||
*/
|
||||
confirmText: String,
|
||||
}
|
||||
|
||||
export type SkuProps = ExtractPropTypes<typeof skuProps>
|
||||
|
||||
export const skuEmits = {
|
||||
[UPDATE_VISIBLE_EVENT]: (val: boolean) => isBoolean(val),
|
||||
selectSku: (val: any) => val instanceof Object,
|
||||
changeStepper: (val: number) => isNumber(val),
|
||||
clickBtnOperate: (val: {
|
||||
type: string
|
||||
value: string | number
|
||||
}) => val instanceof Object,
|
||||
clickCloseIcon: () => true,
|
||||
clickOverlay: () => true,
|
||||
[CLOSE_EVENT]: () => true,
|
||||
reduce: (val: number | object) => isNumber(val) || isString(val) || val instanceof Object,
|
||||
add: (val: number | object) => isNumber(val) || isString(val) || val instanceof Object,
|
||||
overLimit: (val: any) => val instanceof Object,
|
||||
}
|
||||
|
||||
export type SkuEmits = typeof skuEmits
|
||||
188
uni_modules/nutui-uni/components/sku/sku.vue
Normal file
188
uni_modules/nutui-uni/components/sku/sku.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, ref, useSlots, watch } from 'vue'
|
||||
import { CLOSE_EVENT, PREFIX, UPDATE_VISIBLE_EVENT } from '../_constants'
|
||||
import { getMainClass } from '../_utils'
|
||||
import { useTranslate } from '../../locale'
|
||||
import NutPopup from '../popup/popup.vue'
|
||||
import SkuHeader from '../skuheader/skuheader.vue'
|
||||
import SkuOperate from '../skuoperate/skuoperate.vue'
|
||||
import SkuSelect from '../skuselect/skuselect.vue'
|
||||
import SkuStepper from '../skustepper/skustepper.vue'
|
||||
import { skuEmits, skuProps } from './sku'
|
||||
|
||||
const props = defineProps(skuProps)
|
||||
|
||||
const emit = defineEmits(skuEmits)
|
||||
|
||||
defineExpose({
|
||||
resetCount,
|
||||
})
|
||||
|
||||
const slots = useSlots()
|
||||
const showPopup = ref(props.visible)
|
||||
const skuStepperRef = ref()
|
||||
const goodsCount = ref(props.stepperMin)
|
||||
const classes = computed(() => {
|
||||
return getMainClass(props, componentName)
|
||||
})
|
||||
watch(
|
||||
() => props.visible,
|
||||
(value) => {
|
||||
showPopup.value = value
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => showPopup.value,
|
||||
(value) => {
|
||||
if (value === false)
|
||||
close()
|
||||
},
|
||||
)
|
||||
|
||||
// 商品规格 sku 选择
|
||||
function selectSku(skus: any) {
|
||||
emit('selectSku', skus)
|
||||
}
|
||||
|
||||
// 数量计步器变化
|
||||
function changeStepper(value: number) {
|
||||
goodsCount.value = value
|
||||
|
||||
emit('changeStepper', value)
|
||||
}
|
||||
|
||||
// 修改购买数量 add 加 reduce 减
|
||||
function add(value: number) {
|
||||
emit('add', value)
|
||||
}
|
||||
|
||||
function reduce(value: number) {
|
||||
emit('reduce', value)
|
||||
}
|
||||
|
||||
// 触发极限值
|
||||
function stepperOverLimit(count: any) {
|
||||
emit('overLimit', count)
|
||||
}
|
||||
|
||||
// 点击 button 操作
|
||||
function clickBtnOperate(btn: string) {
|
||||
emit('clickBtnOperate', {
|
||||
type: btn,
|
||||
value: goodsCount.value,
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
function closePopup(type: string) {
|
||||
if (type === 'icon')
|
||||
emit('clickCloseIcon')
|
||||
|
||||
if (type === 'overlay')
|
||||
emit('clickOverlay')
|
||||
|
||||
if (type === 'close')
|
||||
emit(CLOSE_EVENT)
|
||||
|
||||
showPopup.value = false
|
||||
}
|
||||
|
||||
function close() {
|
||||
emit(UPDATE_VISIBLE_EVENT, false)
|
||||
}
|
||||
|
||||
function resetCount() {
|
||||
skuStepperRef.value.reset()
|
||||
}
|
||||
|
||||
const getSlots = (name: string) => slots[name]
|
||||
|
||||
const hasSkuOperateSlot = getSlots('skuOperate') != null
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-sku`
|
||||
const { translate } = useTranslate(componentName)
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NutPopup
|
||||
v-model:visible="showPopup"
|
||||
safe-area-inset-bottom
|
||||
position="bottom"
|
||||
closeable
|
||||
round
|
||||
custom-style="height: 75%"
|
||||
@click-close-icon="closePopup('icon')"
|
||||
@click-overlay="closePopup('overlay')"
|
||||
@close="closePopup('close')"
|
||||
>
|
||||
<view :class="classes" :style="customStyle">
|
||||
<slot name="skuHeader">
|
||||
<SkuHeader :goods="goods">
|
||||
<template #skuHeaderPrice>
|
||||
<slot name="skuHeaderPrice" />
|
||||
</template>
|
||||
|
||||
<template #skuHeaderExtra>
|
||||
<slot name="skuHeaderExtra" />
|
||||
</template>
|
||||
</SkuHeader>
|
||||
</slot>
|
||||
|
||||
<scroll-view scroll-y class="nut-sku-content">
|
||||
<view class="nut-sku-content-wrapper">
|
||||
<slot name="skuSelectTop" />
|
||||
|
||||
<slot name="skuSelect" />
|
||||
<SkuSelect v-if="!getSlots('sku-select')" :sku="sku" @select-sku="selectSku" />
|
||||
|
||||
<slot name="skuStepper">
|
||||
<SkuStepper
|
||||
ref="skuStepperRef"
|
||||
:goods="goods"
|
||||
:stepper-title="stepperTitle || translate('buyNumber')"
|
||||
:stepper-max="stepperMax"
|
||||
:stepper-min="stepperMin"
|
||||
:stepper-extra-text="stepperExtraText"
|
||||
@add="add"
|
||||
@reduce="reduce"
|
||||
@change-stepper="changeStepper"
|
||||
@over-limit="stepperOverLimit"
|
||||
/>
|
||||
</slot>
|
||||
|
||||
<slot name="skuStepperBottom" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<SkuOperate
|
||||
:btn-extra-text="btnExtraText"
|
||||
:btn-options="btnOptions"
|
||||
:buy-text="buyText || translate('buyNow')"
|
||||
:add-cart-text="addCartText || translate('addToCart')"
|
||||
:confirm-text="confirmText || translate('confirm')"
|
||||
:show-default-operate="!hasSkuOperateSlot"
|
||||
@click-btn-operate="clickBtnOperate"
|
||||
>
|
||||
<template #operateBtn>
|
||||
<slot name="skuOperate" />
|
||||
</template>
|
||||
</SkuOperate>
|
||||
</view>
|
||||
</NutPopup>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
Reference in New Issue
Block a user