- 效果图 WFSuUMAIp6.gif
-
实现方式,利用卡迪尔坐标来匹配(所有可选项商品类别的坐标, 和商品类别可选条件坐标数组进行对比, 利用集合来获取可选商品类别)
*上代码
<template>
<view style="padding-left: 40upx; padding-top: 50upx;">
<view v-for="(spec, index) in phones.specList" class="row" :key="spec.title" v-if="showPage">
<view style="font-size: 28upx; color: #333333;">{{spec.title}}</view>
<view v-for="(item, i) in spec.list" :key="item.title" @click="itemClick(item, index)">
<view :class="getItem(item)">{{item.title}}</view>
</view>
</view>
<view v-if="sellCount != 0">{{'剩余: ' + sellCount + '\n选择商品条目id: ' + sellId}}</view>
</view>
</template>
<script>
export default {
data() {
return {
phones: {
specList: [{
title: "颜色",
list: ["红色", "紫色"]
},
{
title: "套餐",
list: ["套餐一", "套餐二"]
},
{
title: "内存",
list: ["64G", "128G", "256G"]
},
{
title: "网络",
list: ["联通", "移动", "电信"]
},
],
specCombinationList: [{
id: "1",
specs: ["紫色", "套餐一", "64G", "电信"],
count: 20
},
{
id: "2",
specs: ["紫色", "套餐一", "128G", "电信"],
count: 18
},
{
id: "3",
specs: ["紫色", "套餐二", "128G", "联通"],
count: 15
},
{
id: "4",
specs: ["红色", "套餐二", "256G", "移动"],
count: 10
}
],
},
marryConditions: [], //匹配条件数组 specCombinationList里面的条件
marryItems: {}, //匹配项 所有顶点集合
set: null, //可选顶点集合
alreadys: null, //放 已经选中了的顶点集合
showPage: false,
sellCount: 0,
sellId: '',
}
},
watch: {
},
created() {
this.initData()
this.showPage = true
},
methods: {
//转换数据 设置坐标
initData() {
this.set = new Set()
this.alreadys = new Set()
this.phones.specList.forEach((spec, index) => {
spec.list.forEach((t, i) => {
var tmp = {
title: '',
point: {
x: 0,
y: index
}
}
tmp.point.x = i
tmp.title = t
spec.list[i] = tmp
this.marryItems[t] = tmp.point
})
})
/*
0 1 2
0 紫 红
1 一 二
2 64 128 256
(紫,二,256 [0, 1, 2])
( 二 point(1, 1) 用y = 1 取数组找下标1的值 = 1 存在
一 point(0, 1) y = 1 下标1 = 1 不存在
红 point(1, 0) y = 0 下标0 = 0 不存在
紫 point(0, 0) y = 0 下标0 = 0 存在
128 point(1, 2) y = 2 下标2 = 2 不存在
)
*/
//取x, 用y取匹配( 取y用x好像无法匹配 )
this.phones.specCombinationList.forEach((spec, index) => {
var arr = []
spec.specs.forEach(e => {
if (this.marryItems.hasOwnProperty(e)) {
arr.push(this.marryItems[e].x)
}
})
this.marryConditions.push(arr)
})
},
itemClick(item, index) {
// 选中的顶点不在可选顶点中,不可选
if (!this.set._empty()) {
if (!this.set.has(item.title)) {
console.log('不可选')
return
}
}
//判断是否有相同类目的顶点
let sameTop = this.hasSameTop(item)
if(sameTop){
//有相同类目的顶点
this.deleteSameTop(item)
}else{
// 没有相同类目的顶点直接加入集合
this.alreadys.add(item)
}
this.alreadys._log()
this.set.clear()
//迭代所有的条件, 同时满足alreadys里面的顶点的交集
var tmpSet = new Set()
this.marryConditions.forEach((arr, index) => {
var b = true
this.alreadys.forEach(already => {
if (arr[already.point.y] != already.point.x) {
b = false
}
})
if (b) {
let tmpSet = new Set(this.phones.specCombinationList[index].specs)
this.set = new Set([...this.set, ...tmpSet])
tmpSet = new Set([...this.set, ...tmpSet])
}
})
//判断如果只有一个类目的顶点, 要把该类目的所有顶点都加到集合中
if (this.alreadys._length() == 1) {
let tmpItem = this.alreadys._findIndex(0)
this.phones.specList[tmpItem.point.y].list.forEach(e=>{
this.set.add(e.title)
})
}
//是否选择完成
if (this.alreadys._length() == this.phones.specList.length) {
//选择完成, 获取剩余数量显示出来
this.calculateSellCount()
} else {
this.sellCount = 0
}
},
//是否有相同的顶点
hasSameTop(item){
var flag = false
this.alreadys.forEach(e=>{
if(e.point.y == item.point.y){
flag = true
}
})
return flag
},
deleteSameTop(item){
//如果有相同类目的顶点
if(this.alreadys.has(item)){
//选择的同一个顶点
this.alreadys.delete(item)
}else{
//选择同一个类目不同的顶点, 先清空集合内同一个类目的顶点, 在加入选中的顶点
this.alreadys.forEach(e=>{
if(e.point.y == item.point.y){
this.alreadys.delete(e)
}
})
this.alreadys.add(item)
}
},
calculateSellCount() {
this.marryConditions.forEach((arr, index) => {
var b = true
this.alreadys.forEach(already => {
if (arr[already.point.y] != already.point.x) {
b = false
}
})
if (b) {
this.sellCount = this.phones.specCombinationList[index].count
this.sellId = this.phones.specCombinationList[index].id
}
})
},
alreadysTitle() {
var set = new Set()
this.alreadys.forEach(e => {
set.add(e.title)
})
return set
},
getItem(item) {
// this.set._log()
// this.alreadysTitle()._log()
let title = item.title
var c;
if (this.alreadysTitle().has(title)) {
c = 'item_select'
} else {
if (this.set._empty()) {
c = 'item'
} else if (this.set.has(title)) {
c = 'item'
} else {
c = 'item_disable'
}
}
// console.log(c)
return c
}
},
}
</script>
<style scoped>
.row {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 30upx;
}
.item {
height: 30upx;
padding: 20upx;
border-style: solid;
border-width: 1upx;
border-color: #EEEEEE;
color: #333333;
font-size: 28upx;
text-align: center;
margin-left: 40upx;
}
.item_select {
height: 30upx;
padding: 20upx;
border-style: solid;
border-width: 1upx;
border-color: red;
color: red;
font-size: 28upx;
text-align: center;
margin-left: 40upx;
}
.item_disable {
height: 30upx;
padding: 20upx;
border-style: solid;
border-width: 1upx;
border-color: #999999;
color: #999999;
font-size: 28upx;
text-align: center;
margin-left: 40upx;
}
</style>
- proprety
Set.prototype._log = function (){
var str = ''
this.forEach(e=>{
str += (JSON.stringify(e) + '\n')
})
console.log(str)
}
Set.prototype._empty = function (){
var count = 0
this.forEach(e=>{
count++
})
return count == 0
}
Set.prototype._length = function (){
var count = 0
this.forEach(e=>{
count++
})
return count
}
Set.prototype._findIndex = function (index){
var arr = Array.from(this)
var obj
arr.forEach((e, i)=>{
if(i == index){
obj = e
}
})
return obj
}
网友评论