diff --git a/docs/demos/views/sku.vue b/docs/demos/views/sku.vue index 97bc35520..6a956a76c 100644 --- a/docs/demos/views/sku.vue +++ b/docs/demos/views/sku.vue @@ -20,6 +20,24 @@ + +
+ + {{ $t('title2') }} +
+
+
import data from '../mock/sku'; +import { LIMIT_TYPE } from '../../../packages/sku/constants'; export default { i18n: { 'zh-CN': { sku: data['zh-CN'], + title2: '自定义步进器相关配置', stepperTitle: '我要买', button1: '积分兑换', button2: '买买买' }, 'en-US': { sku: data['en-US'], + title2: 'Custom Stepper Related Config', stepperTitle: 'Stepper title', button1: 'Button', button2: 'Button' @@ -76,6 +97,22 @@ export default { initialSku: { s1: '30349', s2: '1193' + }, + customStepperConfig: { + quotaText: '单次限购100件', + handleOverLimit: (data) => { + const { action, limitType, quota } = data; + + if (action === 'minus') { + Toast('至少选择一件商品'); + } else if (action === 'plus') { + if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { + Toast(`限购${quota}件`); + } else { + Toast('库存不够了~~'); + } + } + } } }; }, diff --git a/docs/markdown/en-US/sku.md b/docs/markdown/en-US/sku.md index bef63dc4d..3c35d5bf3 100644 --- a/docs/markdown/en-US/sku.md +++ b/docs/markdown/en-US/sku.md @@ -27,6 +27,23 @@ Vue.use(Sku); /> ``` +#### Custom Stepper Config + +```html + +``` + #### Advanced Usage ```html @@ -72,6 +89,7 @@ Vue.use(Sku); | reset-selected-sku-on-hide | Whether to reset selected sku when hide | `Boolean` | `false` | - | | disable-stepper-input | Whether to disable stepper input | `Boolean` | `false` | - | | stepper-title | Quantity title | `String` | `Quantity` | - | +| custom-stepper-config | Custom stepper related config | `Object` | `{}` | - | ### Event @@ -156,6 +174,32 @@ goods: { } ``` + +#### customStepperConfig Data Structure +```javascript +customStepperConfig: { + // custom quota text + quotaText: 'only 5 can buy', + // custom callback when over limit + handleOverLimit: (data) => { + const { action, limitType, quota, quotaUsed } = data; + + if (action === 'minus') { + Toast('at least select one'); + } else if (action === 'plus') { + // const { LIMIT_TYPE } = Sku.skuConstants; + if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { + let msg = `Buy up to ${quota}`; + if (quotaUsed > 0) msg += `,you already buy ${quotaUsed}`; + Toast(msg); + } else { + Toast('not enough stock'); + } + } + } +} +``` + #### Event Params Data Structure ```javascript diff --git a/docs/markdown/zh-CN/sku.md b/docs/markdown/zh-CN/sku.md index d8e555ec4..21b4f3a19 100644 --- a/docs/markdown/zh-CN/sku.md +++ b/docs/markdown/zh-CN/sku.md @@ -27,6 +27,23 @@ Vue.use(Sku); /> ``` +#### 自定义步进器相关配置 + +```html + +``` + #### 高级用法 ```html @@ -73,6 +90,7 @@ Vue.use(Sku); | reset-selected-sku-on-hide | 窗口隐藏时重置已选择的sku | `Boolean` | `false` | - | | disable-stepper-input | 是否禁用sku中stepper的input框 | `Boolean` | `false` | - | | stepper-title | 数量选择组件左侧文案 | `String` | `购买数量` | - | +| custom-stepper-config | 步进器相关自定义配置 | `Object` | `{}` | - | ### Event @@ -163,6 +181,31 @@ goods: { } ``` +#### customStepperConfig 对象结构 +```javascript +customStepperConfig: { + // 自定义限购文案 + quotaText: '每次限购xxx件', + // 自定义步进器超过限制时的回调 + handleOverLimit: (data) => { + const { action, limitType, quota, quotaUsed } = data; + + if (action === 'minus') { + Toast('至少选择一件商品'); + } else if (action === 'plus') { + // const { LIMIT_TYPE } = Sku.skuConstants; + if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { + let msg = `单次限购${quota}件`; + if (quotaUsed > 0) msg += `,您已购买${quotaUsed}`; + Toast(msg); + } else { + Toast('库存不够了~~'); + } + } + } +} +``` + #### 添加购物车和点击购买回调函数接收的 skuData 对象结构 ```javascript skuData: { diff --git a/packages/sku/Sku.vue b/packages/sku/Sku.vue index 475c86de3..7d503a2ab 100644 --- a/packages/sku/Sku.vue +++ b/packages/sku/Sku.vue @@ -66,6 +66,7 @@ :quota-used="quotaUsed" :disable-stepper-input="disableStepperInput" :hide-stock="hideStock" + :custom-stepper-config="customStepperConfig" /> @@ -159,6 +160,10 @@ export default create({ messagePlaceholderMap: { type: Object, default: () => ({}) + }, + customStepperConfig: { + type: Object, + default: () => ({}) } }, @@ -328,7 +333,15 @@ export default create({ this.selectedNum = num; }, - onOverLimit({ action, limitType, quota, quotaUsed }) { + onOverLimit(data) { + const { action, limitType, quota, quotaUsed } = data; + const { handleOverLimit } = this.customStepperConfig; + + if (handleOverLimit) { + handleOverLimit(data); + return; + } + if (action === 'minus') { Toast(this.$t('least')); } else if (action === 'plus') { diff --git a/packages/sku/components/SkuStepper.vue b/packages/sku/components/SkuStepper.vue index 08f8f197b..4c705a41d 100644 --- a/packages/sku/components/SkuStepper.vue +++ b/packages/sku/components/SkuStepper.vue @@ -12,7 +12,7 @@ />
{{ $t('remain', stock) }}
-
{{ $t('quota', quota) }}
+
{{ quotaText }}
@@ -40,7 +40,8 @@ export default create({ quota: Number, quotaUsed: Number, hideStock: Boolean, - disableStepperInput: Boolean + disableStepperInput: Boolean, + customStepperConfig: Object }, data() { @@ -69,6 +70,18 @@ export default create({ } return this.skuStockNum; }, + quotaText() { + const { quotaText } = this.customStepperConfig; + let text = ''; + + if (quotaText) { + text = quotaText; + } else if (this.quota > 0) { + text = this.$t('quota', this.quota); + } + + return text; + }, stepperLimit() { const quotaLimit = this.quota - this.quotaUsed; let limit; diff --git a/packages/sku/constants.js b/packages/sku/constants.js index 80b443ee6..0d83bd7ce 100644 --- a/packages/sku/constants.js +++ b/packages/sku/constants.js @@ -2,3 +2,7 @@ export const LIMIT_TYPE = { QUOTA_LIMIT: 0, STOCK_LIMIT: 1 }; + +export default { + LIMIT_TYPE +}; diff --git a/packages/sku/index.js b/packages/sku/index.js index 4c21c126c..76ad3e005 100644 --- a/packages/sku/index.js +++ b/packages/sku/index.js @@ -6,6 +6,7 @@ import SkuStepper from './components/SkuStepper'; import SkuRow from './components/SkuRow'; import SkuRowItem from './components/SkuRowItem'; import skuHelper from './utils/skuHelper'; +import constants from './constants'; Sku.SkuActions = SkuActions; Sku.SkuHeader = SkuHeader; @@ -14,5 +15,6 @@ Sku.SkuStepper = SkuStepper; Sku.SkuRow = SkuRow; Sku.SkuRowItem = SkuRowItem; Sku.skuHelper = skuHelper; +Sku.skuConstants = constants; export default Sku; diff --git a/test/unit/specs/sku.spec.js b/test/unit/specs/sku.spec.js index f78f6944f..499939444 100644 --- a/test/unit/specs/sku.spec.js +++ b/test/unit/specs/sku.spec.js @@ -1,4 +1,5 @@ import Sku from 'packages/sku'; +import Toast from 'packages/toast'; import { mount } from 'avoriaz'; import { DOMChecker } from '../utils'; import data from '../mock/sku'; @@ -155,6 +156,60 @@ describe('Sku', (done) => { }); }); + it('should toast custom error when change step value', (done) => { + wrapper = mount(Sku, { + attachToDocument: true, + propsData: { + value: true, + sku: data.sku, + goodsId: data.goods_id, + goods: goods, + quota: data.quota, + quotaUsed: data.quota_used, + customStepperConfig: { + quotaText: '单次限购100件', + handleOverLimit: (data) => { + const { action, limitType, quota } = data; + + if (action === 'minus') { + Toast('至少选择一件商品'); + } else if (action === 'plus') { + if (limitType === 0) { + Toast(`限购${quota}件`); + } else { + Toast('库存不够了~~'); + } + } + } + } + } + }); + + // 点击减号 + const minusBtn = wrapper.find('.van-stepper__minus')[0]; + minusBtn.trigger('click'); + wrapper.vm.$nextTick(() => { + const toastText = document.querySelector('.van-toast div'); + expect(toastText.textContent).to.equal('至少选择一件商品'); + + // 手动修改购买数量 + const stepperInput = wrapper.find('.van-stepper__input')[0]; + stepperInput.element.value = 20; + stepperInput.trigger('input'); + wrapper.vm.$nextTick(() => { + expect(+stepperInput.element.value).to.equal(data.quota - data.quota_used); + + // 达到购买上限时,点击加号 + const plusBtn = wrapper.find('.van-stepper__plus')[0]; + plusBtn.trigger('click'); + wrapper.vm.$nextTick(() => { + expect(toastText.textContent).to.equal(`限购${data.quota}件`); + done(); + }); + }); + }); + }); + it('should not render sku group when none_sku is true', (done) => { const newData = Object.assign({}, data); newData.sku.none_sku = true; // eslint-disable-line