Cascader 级联选择器
2022年9月29日大约 4 分钟
Cascader 级联选择器
默认值设置
function cascader(o, options) {
let toString = Object.prototype.toString,
// k = Object.keys(o),
k = o,
len = options.length,
res = [];
let current, v, child, num;
for (let i = 0; i < len;) {
current = options[i++];
v = current.c_id;
child = current.children;
num = k.indexOf(v);
if (num > -1) {
res.push(k.splice(num, 1));
if (k.length === 0) {
break;
}
}
if (toString.call(child) === "[object Array]" && child.length > 0) {
var xx = cartwheel([v], child, k);
if (xx && xx.length) {
res.push(...xx)
}
}
}
return res;
}
function cartwheel(row, c, k, arr) {
if (!arr) {
arr = []
}
let toString = Object.prototype.toString
let len = c.length;
let current, v, child, num;
for (let i = 0; i < len;) {
current = c[i++];
v = current.c_id;
child = current.children;
num = k.indexOf(v);
if (num > -1) {
arr.push([...row, ...k.splice(num, 1)]);
if (k.length === 0) {
return;
}
}
if (toString.call(child) === "[object Array]" && child.length > 0) {
cartwheel([...row, v], child, k, arr);
}
}
return arr;
}
let options = [{ "c_id": "192", "p_id": "0", "c_name": "休闲食品", "children": [{ "c_id": "1581", "p_id": "192", "c_name": "鸭界头牌" }, { "c_id": "1377", "p_id": "192", "c_name": "周黑鸭" }, { "c_id": "1109", "p_id": "192", "c_name": "绝味" }, { "c_id": "829", "p_id": "192", "c_name": "良品铺子" }, { "c_id": "1221", "p_id": "192", "c_name": "百草味" }] }, { "c_id": "838", "p_id": "0", "c_name": "火锅产品", "children": [{ "c_id": "839", "p_id": "838", "c_name": "火锅酱料" }, { "c_id": "943", "p_id": "838", "c_name": "火锅 锅 & 煤气罐" }, { "c_id": "993", "p_id": "838", "c_name": "火锅牛羊肉" }, { "c_id": "1075", "p_id": "838", "c_name": "自燃方便火锅" }, { "c_id": "1293", "p_id": "838", "c_name": "主食" }] }]
let o = ['192', '1221', '1293', '839', '1581','1075']
let res = cascader(o, options);
console.log(res);
// [ [ '192' ], [ '192', '1581' ], [ '192', '1221' ] ]
表格合并
<el-table
:data="taskdata"
:span-method="arraySpanMethod"
border
align="center"
style="width: 100%"
>
<el-table-column
align="center"
v-for="item,i in thead"
:fixed="i == 0"
:key="i"
:prop="item.val+''"
:label="item.name+''"
:width="i == 0 ? 80 : 50"
>
</el-table-column>
</el-table>
export default {
components: {},
data() {
return {
rowData: [],
columnData: [],
pos: 0,
top_title:[
{
"name": "人员",
"val": "nickname"
},
{
"name": 1,
"val": 1
},
.
.
.
{
"name": 30,
"val": 30
}
]
};
},
props: {},
created() {
let data = [{
"1": "后端接口",
"2": "后端接口",
...
"30": "",
"main_title": "xxx",
"nickname": "xxx",
"same_data": [1,2,3,4,5,6] //相同的项集合
}]
this.getSpanData(data)
},
mounted() {},
computed: {},
methods: {
// 计算需要合并的单元格
getSpanData(data) {
// 存放计算好的合并单元格的规则
this.rowData = [];
for (var i = 0, len = data.length; i < len; i++) {
//l行处理
if (i === 0) {
this.rowData.push(1);
this.pos = 0;
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].nickname === data[i - 1].nickname) {
this.rowData[this.pos] += 1;
this.rowData.push(0);
} else {
this.rowData.push(1);
this.pos = i;
}
}
//列处理
this.columnData[i] = data[i].same_data;
}
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
let _row = null;
let _col = null;
//合并行
if (columnIndex === 0) {
_row = this.rowData[rowIndex];
_col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
//合并列
if (
this.columnData[rowIndex] &&
this.columnData[rowIndex][0] == columnIndex
) {
return [1, this.columnData[rowIndex].length];
}
},
},
};
SKU

<Add-Specs ref="add_specs" @success="handleSpecsSuccess" ></Add-Specs>
<script>
export default {
methods: {
handleAddSpecs() {
this.$refs.add_specs.open();
},
handleSpecsSuccess(new_specs = []) {
var oldObj = {};
this.form.specs_price.map(function (v) {
oldObj[v.s_name] = v;
});
if (!this.form.specs_price.length) {
new_specs.map((v) => {
this.form.specs_price.push({
s_name: v,
s_name_en: v,
specs_img: "",
status: 1,
});
});
} else if (this.form.specs_price.length == 1) {
if (this.form.specs_price[0].s_name == "") {
let data = [];
new_specs.map((v) => {
data.push({
s_name: v,
s_name_en: v,
specs_img: "",
status: 1,
});
});
this.form.specs_price = data;
} else {
new_specs.map((v) => {
if (!oldObj[v]) {
this.form.specs_price.push({
s_name: v,
s_name_en: v,
specs_img: "",
status: 1,
});
}
});
}
} else {
new_specs.map((v) => {
if (!oldObj[v]) {
this.form.specs_price.push({
s_name: v,
s_name_en: v,
specs_img: "",
status: 1,
});
}
});
}
}
}
}
</script>
<template>
<!-- 批量添加规格 -->
<el-dialog
title="批量添加规格"
:modal-append-to-body="false"
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="showbox"
width="900px"
>
<div
v-for="(item, index) in attrs"
:key="index"
class="flex flex-column m-b-20"
>
<div class="m-b-5"><span class="m-r-5">{{item.value}}</span>
<i
class="el-icon-delete"
@click="handleRemoveRole(index)"
></i>
</div>
<div class="flex flex-row-wrap">
<el-tag
type="dot"
closable
color="primary"
v-for="(j, indexn) in item.list"
:key="indexn"
:name="j"
class="m-r-10"
@close="handleRemove2(item.list,indexn)"
>{{j}}</el-tag>
<el-input
size="small"
style="width:200px"
placeholder="请输入属性名称"
v-model="item.list.attrsVal"
>
<el-button
slot="append"
@click="createAttr(item.list.attrsVal,index)"
>添加</el-button>
</el-input>
</div>
</div>
<div v-if="!showadd">
<el-button
size="small"
type="success"
@click="addSpecs"
>添加新规格</el-button>
<el-button
size="small"
type="primary"
v-if="createBnt"
@click="createData"
>立即生成</el-button>
</div>
<div v-if="showadd">
<avue-form
v-model="specsForm"
:option="specsOption"
@submit="specsSubmit"
>
<template
slot-scope="scope"
slot="menuForm"
>
<el-button @click="showadd = false">取消</el-button>
</template>
</avue-form>
</div>
</el-dialog>
</template>
<script>
export default {
name: "AddSpecs",
components: {},
data() {
return {
skuArray: [],
skuList: [],
showadd: false,
showbox: false,
attrs: [],
createBnt: false,
specsForm: {},
specsOption: {
menuSpan: 8,
emptyBtn: false,
column: [
{
label: "规格",
prop: "name",
placeholder: "规格名称",
tip: "例如:颜色",
span: 8,
rules: [
{
required: true,
message: "请输入规格",
trigger: "blur",
},
],
},
{
label: "规格值",
prop: "value",
placeholder: "规格值",
tip: "例如:红色,绿色,蓝色",
span: 8,
rules: [
{
required: true,
message: "请输入规格值",
trigger: "blur",
},
],
},
],
},
};
},
props: {},
created() {},
mounted() {},
computed: {},
methods: {
open() {
this.showbox = true;
},
addSpecs() {
this.showadd = true;
},
specsSubmit(form, done) {
let data = {
value: form.name,
list: [form.value],
};
this.attrs.push(data);
var hash = {};
this.attrs = this.attrs.reduce(function (item, next) {
hash[next.value]
? ""
: (hash[next.value] = true && item.push(next));
return item;
}, []);
this.showadd = false;
this.createBnt = true;
this.clearAttr();
done();
},
clearAttr() {
this.specsForm.name = "";
this.specsForm.value = "";
},
// 删除规格
handleRemoveRole(index) {
this.attrs.splice(index, 1);
},
// 删除属性
handleRemove2(item, index) {
if (item.length == 1) {
this.$message.error("至少保留一个属性");
} else {
item.splice(index, 1);
}
},
// 添加属性
createAttr(num, idx) {
if (num) {
this.attrs[idx].list.push(num);
var hash = {};
this.attrs[idx].list = this.attrs[idx].list.reduce(function (
item,
next
) {
/* eslint-disable */
hash[next] ? "" : (hash[next] = true && item.push(next));
return item;
},
[]);
} else {
return;
}
},
createData() {
// 先清空数据,保证连续点击按钮,数据不会重复
this.skuArray = [];
this.skuList = [];
// 将选中的规格组合成一个大数组 [[1, 2], [a, b]...]
this.attrs.forEach((element) => {
element.list.length > 0 ? this.skuArray.push(element.list) : "";
});
this.getSkuData([], 0, this.skuArray);
let new_specs = [];
this.skuList.map((v) => {
new_specs.push(v.join("-"));
});
this.$emit("success", new_specs);
this.showbox = false;
this.showadd = false;
},
// 递归获取每条SKU数据
getSkuData(skuArr = [], i, list) {
for (let j = 0; j < list[i].length; j++) {
if (i < list.length - 1) {
skuArr[i] = list[i][j];
this.getSkuData(skuArr, i + 1, list); // 递归循环
} else {
this.skuList.push([...skuArr, list[i][j]]); // 扩展运算符,连接两个数组
}
}
},
},
};
</script>