使用到的技术: Vue、Element(饿了么)、React jsx



效果:




源码:

-------------------------------------     script    --------------------------------------------

data() {

return {

treeData: [{

id: 1,

label: '一级 1',

isEdit: false,

children: [{

id: 4,

label: '二级 1-1',

isEdit: false,

children: [{id: 9, label: '三级 1-1-1', isEdit: false}, {id: 10, label: '三级 1-1-2', isEdit: false}, {id: 11, label: '三级 1-1-3', isEdit: false}]

},

{

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'}, {id: 6, label: '二级 2-2', isEdit: false}]

},

{

id: 3,

label: '一级 3',

isEdit: false,

children: [{id: 7, label: '二级 3-1', isEdit: false}, {id: 8, label: '二级 3-2', isEdit: false}]

}],

add_question_flag: false,

new_question_name: '',

tree_key: 0,

defaultExpand: []

}

},

methods: {

// 添加新大题

add_new_question() {

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 = ''

},

// 试题名称更新

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) {

return

} else if (parent.level !== 0 && cIndex === 0) { //不同父节点中移动

const parent2 = parent.parent

const children2 = parent2.data.children || parent2.data

const pIndex2 = parseInt(children2.findIndex(p => p.id === parent.data.id), 10) - 1


if (pIndex2 < 0) return

children2[pIndex2].children.push(data)

children.splice(cIndex, 1)

this.defaultExpand[0] = children2[pIndex2].id

} 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) { //父节点不同

const parent2 = parent.parent

const children2 = parent2.data.children || parent2.data

const pIndex2 = parseInt((children2.findIndex(p => p.id === parent.data.id)), 10)


if (pIndex2 === allLevel) return

children2[pIndex2+1].children.push(data)

children.splice(cIndex, 1)

this.defaultExpand[0] = children2[pIndex2+1].id

} 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 type="text" value={data.label} on-blur={ev => this.edit_sure(ev, data)}/>

} else {

return className="node_labe">{data.label}

}

},

// 试卷结构树操作group node,

renderContent(h, {node, data, store}) {

return (

{ this.showOrEdit(data) }

class="tree_node_op">

class="node_edit" on-click={ (ev) => this.nodeEdit(ev, store, data) }>

class="node_delete" on-click={ () => this.nodeDelete(node, data) }>

class="node_up" on-click={ () => this.nodeUp(node, data) }>

class="node_down" on-click={ () => this.nodeDown(store, node, data) }>

)

}

}


---------------------------------------    template    ---------------------------------------------

class="exam_structure">

class="title">试卷结构 class="tip">(可以点击选中对应题目)

type="primary" size="small" class="add_new_question" @click="add_new_question">添加新大题