<template>
<div>
<el-form :inline="true">
<el-row>
<el-col>
<el-form-item>
<el-input placeholder="输入关键字进行过滤" v-model="filterText">
</el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="small"
class="add_new_question"
@click="add_new_question"
><i></i>新增父节点</el-button
>
<el-button type="primary" size="mini" @click="handleSave"
>保存</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="question_info_lists">
<el-tree
ref="tree"
:key="tree_key"
:data="treeData"
node-key="id"
:render-content="renderContent"
:expand-on-click-node="false"
:default-expanded-keys="defaultExpand"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
:filter-node-method="filterNode"
></el-tree>
<!-- 添加父节点 -->
<el-dialog
title="新增节点"
:visible.sync="add_question_flag"
width="400px"
append-to-body
>
<el-form label-width="100px">
<el-row>
<el-col>
<el-form-item label="父节点">
<el-input
v-model="new_question_name"
placeholder="请输入大题名称"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="add_question_sure">确 定</el-button>
<el-button @click="add_question_cancel">取 消</el-button>
</div>
</el-dialog>
<el-dialog
title="策划项"
:visible.sync="openPlanning"
width="900px"
append-to-body
>
<inDustry :haveSingle="haveSingle" @selectRow="selectRow"></inDustry>
<!-- -->
</el-dialog>
</div>
</div>
</template>
<script>
import inDustry from "./industry";
export default {
components: { inDustry },
name: "treeList",
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
},
methods: {
// 比如点击操作的时候要保持展开状态 this.defaultExpand = this.recordExpand;
nodeExpand(row) {
if(!this.recordExpand.includes(row.id)){
this.recordExpand.push(row.id);
}
},
nodeCollapse(row) {
this.recordExpand = this.recordExpand.filter((item) => {
return item !== row.id;
});
},
renderContent(h, { node, data, store }) {
const labelWidth = 300; // 设置节点内容的定宽
return (
<div class="box">
<el-tooltip effect="dark" content={data.label}>
<div style={{ width: `${labelWidth}px`, flex:1, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }} className="node_labe">{data.label}</div>
</el-tooltip>
{/* <span>{this.showOrEdit(data)}</span> */}
<div class="tree_node_op" style="float: right, flex:1">
<i
class="el-icon-edit"
on-click={(ev) => this.nodeEdit(ev, store, data)}
></i>
<i
class="el-icon-delete"
on-click={() => this.nodeDelete(node, data)}
></i>
<i
class="el-icon-upload2"
on-click={() => this.nodeUp(node, data)}
></i>
<i
class="el-icon-download"
on-click={() => this.nodeDown(store, node, data)}
></i>
<i
class="el-icon-plus"
on-click={() => this.append(store, node, data)}
></i>
<el-dropdown
class="my-dropdown"
on-command={() => this.handleDropdownCommand(store, node, data)}
>
<span class="el-dropdown-link">
下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>选项一</el-dropdown-item>
<el-dropdown-item>选项二</el-dropdown-item>
<el-dropdown-item>选项三</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
);
},
// 保存
handleSave() {
console.log(this.treeData, "数据");
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
// 添加新大题
add_new_question() {
this.filterText = "";
this.add_question_flag = true;
},
add_question_sure() {
//确定
const nodeObj = {
id: "",
label: this.new_question_name,
isEdit: false,
children: [],
};
this.treeData.push(nodeObj);
this.add_question_flag = false;
},
add_question_cancel() {
//取消
this.add_question_flag = false;
this.new_question_name = "";
},
selectRow(row) {
this.openPlanning = false;
var maxid = "20";
//新增数据
const nodeapp = {
id: ++maxid,
label: row.nickname,
isEdit: false,
children: [],
};
this.newData.children.push(nodeapp);
if (!this.nodeList.expanded) {
this.nodeList.expanded = true;
}
const parent = node.parent;
const children = parent.data;
const cIndex = children.findIndex((d) => d.id === this.newData.id);
const tempChildrenNodex2 = children[cIndex]; //拿到被添加的上一级
console.log(tempChildrenNodex2.children[cIndex - 1], "添加父级");
},
handleDropdownCommand(store, node, data) {
console.log(store, node, "执行命令");
},
// 增加
append(store, node, data) {
console.log(store, node, "cunxia");
this.newData = data;
this.nodeList = node;
this.$nextTick(() => {
this.haveSingle = true;
});
this.openPlanning = true;
},
handleOptionClick(data, option, dropdownId) {
console.log(`点击了 ${option}`);
console.log("当前节点数据:", data);
this.$refs[dropdownId].hide(); // 点击后隐藏下拉菜单
},
// 修改
nodeEdit(ev, store, data) {
data.isEdit = true;
this.$nextTick(() => {
const $input =
ev.target.parentNode.parentNode.querySelector("input") ||
ev.target.parentElement.parentElement.querySelector("input");
!$input ? "" : $input.focus();
});
},
edit_sure(ev, data) {
const $input =
ev.target.parentNode.parentNode.querySelector("input") ||
ev.target.parentElement.parentElement.querySelector("input");
if (!$input) {
return false;
} else {
data.label = $input.value;
data.isEdit = false;
}
},
// 节点删除
nodeDelete(node, data) {
const parent = node.parent;
const children = parent.data.children || parent.data;
const index = children.findIndex((d) => d.id === data.id);
children.splice(index, 1);
},
// 节点上移
nodeUp(node, data) {
const parent = node.parent;
const children = parent.data.children || parent.data;
const cIndex = children.findIndex((d) => d.id === data.id);
if (parent.level === 0 && cIndex === 0) {
this.$message.error("一级节点不能移动");
return;
} else if (parent.level !== 0 && cIndex === 0) {
//不同父节点中移动
this.$message.error("不同父节点中移动");
} else if (
(parent.level === 0 && cIndex !== 0) ||
(parent.level !== 0 && cIndex !== 0)
) {
const tempChildrenNodex1 = children[cIndex - 1];
const tempChildrenNodex2 = children[cIndex];
this.$set(children, cIndex - 1, tempChildrenNodex2);
this.$set(children, cIndex, tempChildrenNodex1);
this.defaultExpand[0] = data.id;
}
this.tree_key++;
},
// 节点下移
nodeDown(store, node, data) {
const parent = node.parent;
const children = parent.data.children || parent.data;
const cIndex = children.findIndex((d) => d.id === data.id);
const cLength = children.length - 1; // 最边上的节点
const allLevel = store.data.length - 1; // 树的深度
if (parent.level === allLevel && cIndex === cLength) {
// 最最末的节点
return;
} else if (parent.level !== allLevel && cIndex === cLength) {
//父节点不同
this.$message.error("末级节点不能移动");
} else if (
(parent.level === allLevel && cIndex !== cLength) ||
(parent.level !== allLevel && cIndex !== cLength)
) {
// 父节点相同
const tempChildrenNodex1 = children[cIndex + 1];
const tempChildrenNodex2 = children[cIndex];
this.$set(children, cIndex + 1, tempChildrenNodex2);
this.$set(children, cIndex, tempChildrenNodex1);
this.defaultExpand[0] = data.id;
}
this.tree_key++;
},
showOrEdit(data) {
if (data.isEdit) {
return (
<input
type="text"
value={data.label}
on-blur={(ev) => this.edit_sure(ev, data)}
/>
);
} else {
return <span className="node_labe">{data.label}</span>;
}
},
// 结构树操作group node,
},
data() {
return {
newData: {},
nodeList: {},
openPlanning: false,
templateSelection: "",
haveSingle: false,
filterText: "",
treeData: [
{
id: 1,
label: "一级 1",
isEdit: false,
children: [
{
id: 4,
label: "二级 1-1",
isEdit: false,
children: [
{ id: 9, label: "三级 1-1-1", isEdit: false, children: [] },
{
id: 10,
label: "三级 1-1-2",
isEdit: false,
children: [],
},
{
id: 11,
label: "三级 1-1-3",
isEdit: false,
children: [],
},
],
},
{
id: 12,
label: "二级 1-2",
isEdit: false,
children: [],
},
{
id: 13,
label: "二级 1-3",
isEdit: false,
children: [],
},
],
},
{
id: 2,
label: "一级 2",
isEdit: false,
children: [
{ id: 5, label: "二级 2-1", isEdit: false, children: [] },
{
id: 6,
label: "二级 2-2",
isEdit: false,
children: [],
},
],
},
{
id: 3,
label: "一级 3",
isEdit: false,
children: [
{ id: 7, label: "二级 3-1", isEdit: false, children: [] },
{
id: 8,
label: "二级 3-2",
isEdit: false,
children: [],
},
],
},
],
add_question_flag: false,
new_question_name: "",
tree_key: 0,
defaultExpand: [],
recordExpand:[],
};
},
};
</script>
<style>
.box {
display: flex;
width: 300px;
}
i {
margin: 0 5px;
}
.el-tree-node__content > .el-tree-node__expand-icon {
padding: 6px;
margin-top: -3px;
}
</style>
把renderContent 方法里面的el-dropdown-item按照循环的方式去写 修改如下
renderContent(h, { node, data, store }) {
const labelWidth = 300; // 设置节点内容的定宽
// 生成下拉菜单选项数组
const dropdownOptions = [
{ id: 1, label: "选项一" },
{ id: 2, label: "选项二" },
{ id: 3, label: "选项三" },
];
const dropdownItems = dropdownOptions.map((option) =>
h(
"el-dropdown-item",
{
key: option.id,
props: {
command: option.id,
},
},
option.label
)
);
return (
<div class="box">
<el-tooltip effect="dark" content={data.label}>
<div
style={{
width: `${labelWidth}px`,
flex: 1,
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
}}
className="node_labe"
>
{data.label}
</div>
</el-tooltip>
{/* <span>{this.showOrEdit(data)}</span> */}
<div class="tree_node_op" style="float: right, flex:1">
{/* <i
class="el-icon-edit"
on-click={(ev) => this.nodeEdit(ev, store, data)}
></i> */}
<i
class="el-icon-delete"
on-click={() => this.nodeDelete(node, data)}
></i>
<i
class="el-icon-upload2"
on-click={() => this.nodeUp(node, data)}
></i>
<i
class="el-icon-download"
on-click={() => this.nodeDown(store, node, data)}
></i>
<i
class="el-icon-plus"
on-click={() => this.append(store, node, data)}
></i>
<el-dropdown
class="my-dropdown"
on-command={() => this.handleDropdownCommand(store, node, data)}
>
<span class="el-dropdown-link">
流程菜单<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
{dropdownItems}
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
);
},