123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- <template>
- <scroll-view class="mini-spec" scroll-y="true" show-scrollbar="false">
- <view class="spec-item" v-for="(item,i) in demoData" :key="i">
- <view class="spec-title">{{ item }}</view>
- <!--多个选项-->
- <view class="spec-list">
- <view class="spec-value" v-for="(sku,index) in showSpec[item]" :key="index" @tap="chooseSpec(item, sku)"
- :class="[{active:selectedArr[item] === sku}]">
- <!-- wx:class="{{ { theme_main_bk:selectedArr[item] === sku , no:filters.noActive(notSelectable,sku)} }}" -->
- {{ sku }}
- </view>
- </view>
- </view>
- </scroll-view>
- </template>
- <script lang='ts'>
- import {
- Component,
- Prop,
- Watch,
- Emit,
- Vue
- } from 'vue-property-decorator';
- @Component({})
- export default class MiniSpec extends Vue {
- proContent: any = null;
- showSpec: any = {}; // 用于展示的规格选项
- reSku: Array < any >= []; // 重组后的sku-->[{path: "三人份-BT辣-羊肉-炒",sku: "000UNLI4"}]
- selectedArr: Array < any >= []; // 所有选中的规格与key的组合
- notSelectable: Array < any >= [];
- allPath: any = {};
- keys: string = ""; // 所有可选属性行
- selectedCache: Array < any >= []; // 已选中的缓存
- spliter: string = "-"; // 分隔符
- curtSelect: string = ""; // 当前选中的规格
- @Prop({
- default: {}
- }) specData: any;
- @Prop({
- default: false
- }) sellOut!: boolean;
- get demoData() {
- return Object.keys(this.showSpec) || [];
- }
- @Watch('specData', {
- deep: true,
- immediate: true,
- })
- specDataChange(val: any) {
- this.proContent = val;
- this.proContent.skuList.length && this.initData();
- }
- initData() {
- // 售罄不执行
- if (this.sellOut) {
- return;
- }
- //proContent未准备好 不执行
- if (!this.proContent) return;
- // 单规格未设置'默认'规格时,不执行
- if (!this.proContent.skuList[0].attrs) return;
- // 暂时不过滤库存为0 的商品
- // this.filterNullSku();
- // 过滤 keys 可选的规格名称 ['款式','口味']
- this.keys = this.filterKeys(this.proContent);
- // console.log('this.keys------>', this.keys);
- // 展示给用户的规格选项
- this.showSpec = this.getshowSpec(this.proContent.skuList);
- // console.log("this.showSpec------>", this.showSpec);
- // this.reSku ==》[{path:'大-不辣',sku:111},{path:'大-辣',sku:111}]
- this.reSku = this.combineAttr(this.proContent.skuList);
- // console.log('this.reSku------>', this.reSku)
- this.buildResult(this.reSku);
- // 只有一个sku时默认选中所有选项
- const oneSku = this.proContent.skuList.length === 1;
- // 开局选中
- let skuItem = this.proContent.skuList;
- console.log('选中的规格', this.selectedArr)
- for (let k in this.selectedArr) {
- skuItem[0].attrs.map((sku: any) => {
- if (sku.keyName == k) {
- this.selectedArr[k] = sku.value;
- }
- });
- }
- this.updateStatus(this.getSelectedItem());
- this.getChoose()
- }
- filterKeys(proContent: any): any {
- // let keys =[]
- // proContent.skuList.map((item,index)=>{
- // item.attrs.map(res=> keys.push(res.keyName))
- // })
- // keys = [...new Set(keys)]
- // return keys
- // console.log("proContent", proContent);
- let keys: Array < any >= [];
- (proContent.skuList[0] as any).attrs.map((res: any) => keys.push(res.keyName));
- keys = [...new Set(keys)];
- return keys;
- }
- // 属性点击事件
- chooseSpec(skey: any, sval: any) {
- // skey->选中的规格key,sval->选中的规格值
- // this.curtSelect = sval;
- // console.log(!this.notSelectable.includes(sval))
- if (!this.notSelectable.includes(sval)) {
- if (this.selectedArr[skey] === sval) {
- // this.selectedArr[skey] = "";
- this.$set(this.selectedArr, skey, '')
- } else {
- // this.selectedArr[skey] = sval;
- this.$set(this.selectedArr, skey, sval)
- }
- this.updateStatus(this.getSelectedItem());
- // this.$emit('getChoose', this.selectedArr);
- this.getChoose()
- }
- }
- // // 将sku stock为0的sku过滤掉 一个sku的不过滤了
- // filterNullSku() {
- // if (this.proContent && this.proContent.skuList.length > 1) {
- // let sku = {};
- // sku = this.proContent.skuList.filter((item) => item.stock > 0);
- // this.proContent.skuList = sku;
- // }
- // }
- // 将商品数据中的 sku 用 key 过滤出所有可选的商品规格
- getshowSpec(skuList: any) {
- let keys = this.keys;
- let jsons: any = {};
- let select: any = {};
- for (let key_val of keys) {
- jsons[key_val] = [];
- select[key_val] = "";
- for (let j = 0; j < skuList.length; j++) {
- for (let i = 0; i < keys.length; i++) {
- if (
- skuList[j].attrs[i].keyName &&
- skuList[j].attrs[i].keyName === key_val
- ) {
- jsons[key_val].push(skuList[j].attrs[i].value);
- }
- }
- }
- }
- for (let i in jsons) {
- jsons[i] = [...new Set(jsons[i])];
- }
- this.selectedArr = select; // 后面储存已选属性要用到 {颜色:'',尺寸: ''...}
- // console.log('this.selectedArr------>', this.selectedArr);
- return jsons;
- }
- // 计算组合数据
- combineAttr(skuList: any) {
- let allKeys: Array < any >= [];
- skuList.map((res: any) => {
- let values: Array < any > = [];
- res.attrs.forEach((key: any) => {
- values.push(key.value);
- });
- allKeys.push({
- path: values.join(this.spliter),
- kid: res.kid,
- });
- });
- return allKeys;
- }
- /**
- * 生成所有子集是否可选、库存状态 map
- * items =》 [{path:'大-不辣',sku:111},{path:'大-辣',sku:111}]
- * allKeys =>["大-辣", "大-不辣", "中-不辣", "中-辣", "小-辣", "小-不辣"]
- * return =>{ 不辣:{skus:[123,12323]}}
- */
- buildResult(items: any) {
- this.allPath = {};
- let allKeys = items.map((res: any) => res.path);
- for (let i = 0; i < allKeys.length; i++) {
- let sku: string = items[i].kid;
- let values: Array < any > = allKeys[i].split(this.spliter);
- let allSets = this.powerset(values);
- // 每个组合的子集
- // 清空allpath,zcj
- // this.allPath = {};
- for (let j = 0; j < allSets.length; j++) {
- let set = allSets[j];
- let key = set.join(this.spliter);
- if (this.allPath[key]) {
- this.allPath[key].skus.push(sku);
- } else {
- this.allPath[key] = {
- skus: [sku],
- };
- }
- }
- }
- // console.log('this.allPath------>', this.allPath);
- }
- powerset(arr: any) {
- let ps: any = [
- []
- ];
- for (let i = 0; i < arr.length; i++) {
- for (let j = 0, len = ps.length; j < len; j++) {
- ps.push(ps[j].concat(arr[i]));
- }
- }
- return ps;
- }
- // 过滤分隔符
- trimSpliter(str: any) {
- // ⊙abc⊙ => abc
- // ⊙a⊙⊙b⊙c⊙ => a⊙b⊙c
- let reLeft = new RegExp("^" + this.spliter + "+", "g");
- let reRight = new RegExp(this.spliter + "+$", "g");
- let reSpliter = new RegExp(this.spliter + "+", "g");
- return str
- .replace(reLeft, "")
- .replace(reRight, "")
- .replace(reSpliter, this.spliter);
- }
- // 获取当前选中的属性 =>['大','不辣']
- getSelectedItem() {
- let result: any = [];
- result = Object.values(this.selectedArr);
- return result;
- }
- // 更新所有属性状态
- updateStatus(selected: any) {
- this.notSelectable = [];
- for (let i = 0, len = this.keys.length; i < len; i++) {
- let key: any = this.keys[i];
- let data: any = this.showSpec[key];
- // console.log('data',data);
- let copy: any = selected.slice();
- // console.log('copy',copy);
- for (let j = 0; j < data.length; j++) {
- let item: any = data[j];
- if (selected[i] === item) continue;
- copy[i] = item;
- let curr = this.trimSpliter(copy.join(this.spliter));
- if (!this.allPath[curr]) {
- this.notSelectable.push(item);
- // console.log("this.notSelectable------>", this.notSelectable);
- }
- }
- }
- if (!this.getSelectedItem().includes("")) {
- let choSku: any = this.getSelectedItem().join(this.spliter);
- // console.log(choSku);
- // console.log("findSku1", this.allPath[choSku]);
- this.findSku(this.allPath[choSku].skus[0])
- }
- }
- // emit===================================
- @Emit('getChoose')
- getChoose() {
- return this.selectedArr
- }
- @Emit('findSku')
- findSku(value: any) {
- return value
- }
- }
- </script>
- <style lang='scss' scoped>
- .mini-spec {
- max-height: vw(200);
- overflow-y: scroll;
- @include hide-scrollbar() .spec-item {
- @include word-vw(14, $gray3);
- .spec-title {
- @include word-vw(16, $gray3);
- line-height: vw(40);
- }
- .spec-list {
- display: flex;
- flex-wrap: wrap;
- margin-top: vw(6);
- .spec-value {
- min-width: vw(100);
- max-width: vw(345);
- @include ellipsis();
- height: vw(32);
- line-height: vw(32);
- padding: 0 vw(10);
- box-sizing: border-box;
- text-align: center;
- @include word-vw(14, $gray3);
- background: #fff;
- border-radius: vw(8);
- margin-right: vw(18);
- margin-bottom: vw(16);
- &.active {
- /* background: #fff; */
- color: #E33C64;
- /* background-color: $bk-color; */
- /* border: vw(1) solid $main-color; */
- }
- &.no {
- color: $gray9;
- background: #EFEFEF;
- }
- }
- .spec-value:last-child {
- margin-right: 0;
- }
- }
- }
- }
- </style>
|