// 处理场景 规格选择
//当用户选择第一项的时候 其他几行是否有可以选中的 要进行标识
//当前行是否可以选中的也要标识
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<div v-for="(item, i) in attrBasics" :key="i" class="g-g-list">
<span class="g-l-t ">{{ item.attrName }}:</span>
<div class="span">
<span v-for="(child, j) in item.children" v-show="child.status == 2" :key="j"
class="c-btn" :class="
child.isCheck == 1 ? 'active'
:child.isCheck == 2 ? 'is-check':''" @click.stop="guiGChange(child, i, j)">{{ child.valueName }}</span>
</div>
</div>
</div>
<style>
.g-g-list {
font-size: 14px;
color: #871811;
}
.g-l-t {
margin-right: 8px;
}
.span {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.c-btn {
width: 64px;
height: 25px;
line-height: 23px;
border: 1px solid #CCCCCC;
margin: 0 8px 0 0;
font-size: 12px;
border-radius: 8px;
text-align: center;
cursor: pointer;
}
.c-btn.active {
border: none;
background: linear-gradient(360deg, #FFA750 0%, #FF7700 100%);
color: #fff;
}
/* 不能选中 */
.c-btn.is-check {
color: #fff;
background-color: #000;
}
</style>
<script>
const { createApp } = Vue
createApp({
data() {
return {
goodsAttrs: [], // 展示的规格选择
goodsAttrsCurIndex: [], // 选择判断
arrSkuId: [], // skuid
attrBasics: [] // 展示的规格选择
}
},
mounted() {
const attrBasics = [
{
attrId: 3,
attrName: "味道",
status: 2, // 2表示在售 在售的才显示
valueId: 731,
valueName: "蓝莓味"
},
{
attrId: 3,
attrName: "味道",
status: 2,
valueId: 732,
valueName: "芒果味"
},
{
attrId: 3,
attrName: "味道",
status: 2,
valueId: 734,
valueName: "西柚味"
},
{
attrId: 3,
attrName: "味道",
status: 2,
valueId: 735,
valueName: "辣味"
},
{
attrId: 4504,
attrName: "口感",
status: 2,
valueId: 4573,
valueName: "甜"
},
{
attrId: 4504,
attrName: "口感",
status: 2,
valueId: 4574,
valueName: "咸"
},
{
attrId: 4506,
attrName: "糕点口味",
status: 2,
valueId: 4575,
valueName: "奶油味"
},
{
attrId: 4506,
attrName: "糕点口味",
status: 2,
valueId: 4576,
valueName: "奶味"
},
{
attrId: 4506,
attrName: "糕点口味",
status: 2,
valueId: 4577,
valueName: "辣味"
},
]
// 所有规格数据
const goodsAttrs = [
{
attrId: 3,
attrName: "味道",
isSelectSort: false,
skuCode: "SK0000658003",
status: 2,
valueId: 734,
valueName: "西柚味",
},
{
attrId: 3,
attrName: "味道",
isSelectSort: false,
skuCode: "SK0000658002",
status: 2,
valueId: 732,
valueName: "芒果味",
},
{
attrId: 3,
attrName: "味道",
isSelectSort: false,
skuCode: "SK0000658001",
status: 2,
valueId: 731,
valueName: "蓝莓味"
},
{
attrId: 3,
attrName: "味道",
isSelectSort: false,
skuCode: "SK0000658005",
status: 2,
valueId: 735,
valueName: "辣味"
},
{
attrId: 4504,
attrName: "口感",
isSelectSort: false,
skuCode: "SK0000658003",
status: 2,
valueId: 4573,
valueName: "甜",
},
{
attrId: 4504,
attrName: "口感",
isSelectSort: false,
skuCode: "SK0000658002",
status: 2,
valueId: 4573,
valueName: "甜"
},
{
attrId: 4504,
attrName: "口感",
isSelectSort: false,
skuCode: "SK0000658001",
status: 2,
valueId: 4573,
valueName: "甜"
},
{
attrId: 4504,
attrName: "口感",
isSelectSort: false,
skuCode: "SK0000658004",
status: 2,
valueId: 4574,
valueName: "咸"
},
{
attrId: 4506,
attrName: "糕点口味",
isSelectSort: false,
skuCode: "SK0000658003",
status: 2,
valueId: 4575,
valueName: "奶油味"
},
{
attrId: 4506,
attrName: "糕点口味",
isSelectSort: false,
skuCode: "SK0000658002",
status: 2,
valueId: 4575,
valueName: "奶油味"
},
{
attrId: 4506,
attrName: "糕点口味",
isSelectSort: false,
skuCode: "SK0000658001",
status: 2,
valueId: 4575,
valueName: "奶油味"
},
{
attrId: 4506,
attrName: "糕点口味",
isSelectSort: false,
skuCode: "SK0000658004",
status: 2,
valueId: 4576,
valueName: "奶味"
},
{
attrId: 4506,
attrName: "糕点口味",
isSelectSort: false,
skuCode: "SK0000658005",
status: 2,
valueId: 4577,
valueName: "辣味"
},
]
this.goodsAttrs = goodsAttrs
const attr = goodsAttrs
const attr2 = attrBasics || []
let arrtNameArr = []
attr2.forEach(e => {
e.skuCodeArr = []
e.children = []
arrtNameArr.push({
attrName: e.attrName
})
})
arrtNameArr = this.noReaptObj(arrtNameArr, 'attrName')
// 添加每一行选中的状态 和 数据
arrtNameArr.forEach(e => {
this.goodsAttrsCurIndex.push({
index: -1,
valueId: -1,
skuId: []
})
})
// 保存所有skuId
const arrSkuId = []
for (let i = 0; i < attr.length; i++) {
const e = attr[i]
arrSkuId.push({
valueId: e.valueId,
skuCode: e.skuCode
})
// 添加所有相同属性的 skuID
for (let j = 0; j < attr2.length; j++) {
const e2 = attr2[j]
if (e.attrName === e2.attrName) {
e2.children.push({
valueId: e.valueId,
status: e.status,
isCheck: 0, // 0 标识默认可以点击 1标识选中 2标识不能选中
valueName: e.valueName
})
}
// 去重所有相同的 属性名
e2.children = this.noReaptObj(e2.children, 'valueName')
}
}
const r = this.noReaptObj(attr2, 'attrName')
// 确定默认选中的状态
r.forEach((e, i) => {
if (e.children.length === 1) {
this.goodsAttrsCurIndex[i].index = 0
this.goodsAttrsCurIndex[i].valueId = e.valueId
}
})
// 确定默认选中的skuid
for (let i = 0; i < this.goodsAttrsCurIndex.length; i++) {
const e = this.goodsAttrsCurIndex[i]
for (let j = 0; j < arrSkuId.length; j++) {
const e2 = arrSkuId[j]
if (e.valueId === e2.valueId) {
e.skuId.push(e2.skuCode)
}
}
}
this.attrBasics = r
this.arrSkuId = arrSkuId
// console.log(r)
// console.log(arrSkuId)
// console.log(this.goodsAttrsCurIndex)
// 默认数据处理 只有一个的情况下 是否选中
for (let i = 0; i < this.goodsAttrsCurIndex.length; i++) {
const e = this.goodsAttrsCurIndex[i]
if (e.index === -1) continue
for (let j = 0; j < r[i].children.length; j++) {
const e2 = r[i].children[j]
this.guiGChange(e2, i, j)
}
}
},
methods: {
noReaptObj(arr, key) {
const newArr = []
const obj = {}
for (var i = 0; i < arr.length; i++) {
if (!obj[arr[i][key]]) {
newArr.push(arr[i])
obj[arr[i][key]] = true
}
}
return newArr
},
guiGChange(child, attrI, childJ) {
if (child.isCheck === 1 && this.attrBasics[attrI].children.length === 1) return
child.isCheck = child.isCheck === 0 ? 1 : 0
const valueId = child.isCheck === 0 ? '' : child.valueId
this.goodsAttrsCurIndex[attrI].skuId.length = 0
if (valueId) {
// 给每一个选中的状态添加 数据
this.goodsAttrs.forEach(e => {
if (e.valueId === valueId) {
this.goodsAttrsCurIndex[attrI].index = childJ
this.goodsAttrsCurIndex[attrI].valueId = valueId
this.goodsAttrsCurIndex[attrI].skuId.push(e.skuCode)
}
})
} else {
this.goodsAttrsCurIndex[attrI].index = -1
this.goodsAttrsCurIndex[attrI].valueId = -1
}
// console.log(this.goodsAttrsCurIndex)
/**
* 判断选中当前的某一个行的规格的时候,剩下的规格按钮是否能被选中
* 选中的按钮不一定是按顺序选择的可能是 从下往上
*/
// 循环当前选中的数据
for (let i = 0; i < this.goodsAttrsCurIndex.length; i++) {
const e = this.goodsAttrsCurIndex[i]
// 存剩余的行数 选中的skuId交集
let arr = []
// 除开当前行数 剩下行数的skuId交集
for (let j = 0; j < this.goodsAttrsCurIndex.length; j++) {
const e2 = this.goodsAttrsCurIndex[j]
if (i === j) continue
if (!arr.length) {
// 拿到当前的skuId
e2.skuId.forEach(e => {
arr.push(e)
})
// arr.concat(e2.skuId)
// console.log(arr)
} else {
// 选中两种规格的时候 取出交集用于第三个规格的判断
// console.log(e2.skuId)
if (e2.skuId.length) {
// 取出剩余交集 跟 剩余行比较
arr = arr.filter((v) => {
return e2.skuId.indexOf(v) > -1
})
}
}
}
// 循环展示数据 当前行数 未选中的按钮 是否可以点击的处理
for (let x = 0; x < this.attrBasics.length; x++) {
const xG = this.attrBasics[x]
// 当前i行的判断
if (i === x) {
// 循环当前i行的所有skuid
for (let y = 0; y < xG.children.length; y++) {
const yG = xG.children[y]
let arrId = []
// 当前选中的不算
if (y === e.index) continue
// 当前i行 下 未选中按钮 所包含的某一个的skuId
// 进行判断是否可以选中
for (let z = 0; z < this.arrSkuId.length; z++) {
const zG = this.arrSkuId[z]
if (yG.valueId === zG.valueId) {
arrId.push(zG.skuCode)
}
}
// console.log(arrId);
// console.log(arr);
// 当前按钮 行的交集
if (!arr.length) {
// 同行可以选中的
yG['isCheck'] = 0 // 是否可选
}else if (arr.length === 1) {
// 其他行的skuid交集只有一个的时候 当前行skuid包含就选中
arrId = arrId.filter((v) => {
return arr.indexOf(v) > -1
})
yG['isCheck'] = arrId.length ? 1 : 2 // 是否可选
this.goodsAttrsCurIndex[i].index = arrId.length ? y : -1
this.goodsAttrsCurIndex[i].valueId = arrId.length ? yG.valueId : -1
} else {
// 剩余行数的交集 进行交集的判断
arrId = arrId.filter((v) => {
return arr.indexOf(v) > -1
})
// console.log(arrId);
yG['isCheck'] = arrId.length ? 0 : 2 // 是否可选
}
}
}
}
}
}
},
}).mount('#app')
</script>
</body>
</html>