|
@@ -0,0 +1,522 @@
|
|
|
+<template>
|
|
|
+ <div class="tree-main">
|
|
|
+
|
|
|
+ <Tree :data="treeData" :render="renderContent" ref="tree"></Tree>
|
|
|
+ <Modal v-model="modalFlag" title="添加新节点" ok-text="确认" cancel-text="取消" @on-ok="handleAddNode">
|
|
|
+ <Row class="modelRow">
|
|
|
+ <span>
|
|
|
+ 当前章节:
|
|
|
+ <span style="margin-left:10px;">{{currentNode.title}}</span>
|
|
|
+ </span>
|
|
|
+ </Row>
|
|
|
+ <Row class="modelRow">
|
|
|
+ <span>节点名称:</span>
|
|
|
+ <Input v-model="inputValue" placeholder="输入新节点名称" style="width: 100%" />
|
|
|
+ </Row>
|
|
|
+ </Modal>
|
|
|
+ <Modal v-model="editFlag" title="修改节点" ok-text="确认" cancel-text="取消" @on-ok="handleUpdateNode">
|
|
|
+ <Row class="modelRow">
|
|
|
+ <span>
|
|
|
+ 当前名称:
|
|
|
+ <span style="margin-left:10px;">{{currentNode.title}}</span>
|
|
|
+ </span>
|
|
|
+ </Row>
|
|
|
+ <Row class="modelRow">
|
|
|
+ <span>修改名称:</span>
|
|
|
+ <Input v-model="editValue" placeholder="输入节点新名称" style="width: 100%" />
|
|
|
+ </Row>
|
|
|
+ </Modal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ props: ["treeDatas", "volumeCode"],
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ treeData: [],
|
|
|
+ inputValue: "",
|
|
|
+ editValue: "",
|
|
|
+ modalFlag: false,
|
|
|
+ editFlag: false,
|
|
|
+ addBookFlag: false,
|
|
|
+ nodeType: "章节",
|
|
|
+ currentNode: "",
|
|
|
+ currentLiNode: "",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.treeData = this.treeDatas;
|
|
|
+ },
|
|
|
+ watch:{
|
|
|
+ treeDatas: {
|
|
|
+ handler(newValue, oldValue) {
|
|
|
+ this.treeData = newValue;
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ renderContent(h, { root, node, data }) {
|
|
|
+ let that = this;
|
|
|
+ return h(
|
|
|
+ "span",
|
|
|
+ {
|
|
|
+ domProps: {
|
|
|
+ className: "singleClass"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: () => {
|
|
|
+ this.titleClick(data);
|
|
|
+ },
|
|
|
+ mouseover: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.handleLiOver(event);
|
|
|
+ },
|
|
|
+ mouseleave: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.handleLiLeave(node, event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [
|
|
|
+ h("span", [
|
|
|
+ h("Icon", {
|
|
|
+ props: {
|
|
|
+ type:
|
|
|
+ data.children && data.children.length > 0
|
|
|
+ ? "md-albums"
|
|
|
+ : "ios-paper-outline"
|
|
|
+ },
|
|
|
+ style: {
|
|
|
+ marginRight: "5px",
|
|
|
+ display: "none",
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ h("span", data.title)
|
|
|
+ ]),
|
|
|
+ h(
|
|
|
+ "span",
|
|
|
+ {
|
|
|
+ style: {
|
|
|
+ float: "right",
|
|
|
+ top: "14px",
|
|
|
+ display: "none"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ mouseleave: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ //this.hideTools(event);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ domProps: {
|
|
|
+ className: "tools"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [
|
|
|
+ h(
|
|
|
+ "Icon",
|
|
|
+ {
|
|
|
+ props: {
|
|
|
+ type: "md-add",
|
|
|
+ title: "添加"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.appendClick(data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ h(
|
|
|
+ "Icon",
|
|
|
+ {
|
|
|
+ props: {
|
|
|
+ type: "md-remove"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.remove(root, node, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ h(
|
|
|
+ "Icon",
|
|
|
+ {
|
|
|
+ props: {
|
|
|
+ type: "md-arrow-round-up"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.moveUp(root, node, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ h(
|
|
|
+ "Icon",
|
|
|
+ {
|
|
|
+ props: {
|
|
|
+ type: "md-arrow-round-down"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.moveDown(root, node, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ h(
|
|
|
+ "Icon",
|
|
|
+ {
|
|
|
+ props: {
|
|
|
+ type: "md-create"
|
|
|
+ },
|
|
|
+ on: {
|
|
|
+ click: e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ this.editClick(node, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ )
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ ]
|
|
|
+ );
|
|
|
+ },
|
|
|
+ // 添加节点
|
|
|
+ append(data, value) {
|
|
|
+ const children = data.children || [];
|
|
|
+ let newChild = {
|
|
|
+ title: value,
|
|
|
+ order: children.length,
|
|
|
+ pid: data.rowKey,
|
|
|
+ children: [],
|
|
|
+ expand: true,
|
|
|
+ type: data.type,
|
|
|
+ volumeCode: this.volumeCode,
|
|
|
+ remark: "备注",
|
|
|
+ }
|
|
|
+ children.push(newChild);
|
|
|
+ this.$set(data, "children", children);
|
|
|
+ this.$api.SaveOrUpdateSingleNode(newChild).then(res => {
|
|
|
+ this.$Message.success("添加成功");
|
|
|
+ this.$api.FindSyllabusByVolumeCode({ VolumeCode: this.volumeCode, Status: 1 }).then(res => {
|
|
|
+ this.treeData = res.result.data;
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 删除节点
|
|
|
+ remove(root, node, data) {
|
|
|
+ data.status = 0;
|
|
|
+ this.$api.SaveOrUpdateSingleNode(data).then(res => {
|
|
|
+ this.$Message.success("删除成功");
|
|
|
+ this.$api.FindSyllabusByVolumeCode({ VolumeCode: this.volumeCode, Status: 1 }).then(res => {
|
|
|
+ this.treeData = res.result.data;
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 点击编辑
|
|
|
+ editClick(node, data) {
|
|
|
+ this.currentNode = data;
|
|
|
+ this.editFlag = true;
|
|
|
+ this.editValue = "";
|
|
|
+ },
|
|
|
+ //添加节点 弹出输入框
|
|
|
+ appendClick(data) {
|
|
|
+ this.currentNode = data;
|
|
|
+ this.modalFlag = true;
|
|
|
+ this.inputValue = "";
|
|
|
+ },
|
|
|
+ // 确认添加节点
|
|
|
+ handleAddNode() {
|
|
|
+ if (this.inputValue != "") {
|
|
|
+ this.append(this.currentNode, this.inputValue);
|
|
|
+ } else {
|
|
|
+ this.modalFlag = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 修改节点
|
|
|
+ handleUpdateNode() {
|
|
|
+ if (this.editValue != "") {
|
|
|
+ this.$api.SaveOrUpdateSingleNode(this.currentNode).then(res => {
|
|
|
+ this.$Message.success("修改成功");
|
|
|
+ this.currentNode.title = this.editValue;
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.editFlag = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 标题点击收缩展开
|
|
|
+ titleClick(data) {
|
|
|
+ data.expand = !data.expand;
|
|
|
+ },
|
|
|
+ // 根目录点击事件
|
|
|
+ rootClick(data) {
|
|
|
+ data.expand = !data.expand;
|
|
|
+ },
|
|
|
+ // 上移章节操作
|
|
|
+ moveUp(root, node, data) {
|
|
|
+ let that = this;
|
|
|
+ let list = [];
|
|
|
+ const parentKey = root.find(el => el === node).parent;
|
|
|
+
|
|
|
+ //判断是否存在父级
|
|
|
+ if (parentKey == null || parentKey == undefined) {
|
|
|
+ list = that.treeData;
|
|
|
+ } else {
|
|
|
+ list = root.find(el => el.nodeKey === parentKey).node.children;
|
|
|
+ }
|
|
|
+ const index = list.indexOf(data);
|
|
|
+ let currentOrder = data.order;
|
|
|
+
|
|
|
+ //第一个元素无法上移
|
|
|
+ if (index != 0) {
|
|
|
+ let preData = list[index - 1];
|
|
|
+ if (data.order == preData.order) {
|
|
|
+ data.order = data.order - 1;
|
|
|
+ } else {
|
|
|
+ data.order = preData.order;
|
|
|
+ preData.order = currentOrder;
|
|
|
+ }
|
|
|
+ //更新两条数据
|
|
|
+ that.$api.SaveOrUpdateSingleNode(data);
|
|
|
+ that.$api.SaveOrUpdateSingleNode(preData);
|
|
|
+
|
|
|
+ //移动后刷新数据
|
|
|
+ setTimeout(function () {
|
|
|
+ that.$api.FindSyllabusByVolumeCode({ VolumeCode: that.volumeCode, Status: 1 }).then(res => {
|
|
|
+ that.treeData = res.result.data;
|
|
|
+ })
|
|
|
+ }, 500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 下移章节操作
|
|
|
+ moveDown(root, node, data) {
|
|
|
+ let that = this;
|
|
|
+ let list = [];
|
|
|
+ const parentKey = root.find(el => el === node).parent;
|
|
|
+
|
|
|
+ //判断是否存在父级
|
|
|
+ if (parentKey == null || parentKey == undefined) {
|
|
|
+ list = that.treeData;
|
|
|
+ } else {
|
|
|
+ list = root.find(el => el.nodeKey === parentKey).node.children;
|
|
|
+ }
|
|
|
+ const index = list.indexOf(data);
|
|
|
+ let currentOrder = data.order;
|
|
|
+ //最后一个元素无法下移
|
|
|
+ if (index != (list.length - 1)) {
|
|
|
+ let nextData = list[index + 1];
|
|
|
+ if (data.order == nextData.order) {
|
|
|
+ data.order = data.order + 1;
|
|
|
+ } else {
|
|
|
+ data.order = nextData.order;
|
|
|
+ nextData.order = currentOrder;
|
|
|
+ }
|
|
|
+ //更新两条数据
|
|
|
+ that.$api.SaveOrUpdateSingleNode(data);
|
|
|
+ that.$api.SaveOrUpdateSingleNode(nextData);
|
|
|
+
|
|
|
+ //移动后刷新数据
|
|
|
+ setTimeout(function () {
|
|
|
+ that.$api.FindSyllabusByVolumeCode({ VolumeCode: that.volumeCode, Status: 1 }).then(res => {
|
|
|
+ that.treeData = res.result.data;
|
|
|
+ })
|
|
|
+ }, 500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 更多操作
|
|
|
+ handleTools(root, node, data, event) {
|
|
|
+ let toolsDom = event.currentTarget.nextElementSibling;
|
|
|
+ const parentKey = root.find(el => el === node).parent;
|
|
|
+ const parent = root.find(el => el.nodeKey === parentKey).node;
|
|
|
+ const index = parent.children.indexOf(data);
|
|
|
+ let list = document.getElementsByClassName("tools");
|
|
|
+ let cFlag = toolsDom.style.display;
|
|
|
+ for (let i = 0; i < list.length; i++) {
|
|
|
+ list[i].style.display = "none";
|
|
|
+ }
|
|
|
+ // 判断TOOL显示与隐藏
|
|
|
+ if (cFlag == "none") {
|
|
|
+ toolsDom.style.display = "inline-flex";
|
|
|
+ toolsDom.classList.add("animated");
|
|
|
+ toolsDom.classList.add("slideInDown");
|
|
|
+ } else {
|
|
|
+ toolsDom.style.display = "none";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 鼠标从工具条移开的时候隐藏
|
|
|
+ hideTools(event) {
|
|
|
+ event.currentTarget.style.display = "none";
|
|
|
+ },
|
|
|
+ handleLiOver(event) {
|
|
|
+ event.currentTarget.lastElementChild.style.display = "block";
|
|
|
+ event.currentTarget.style.backgroundColor = "rgba(55, 55, 55, 0.68)";
|
|
|
+ event.currentTarget.style.border = "1px solid #000";
|
|
|
+ },
|
|
|
+ handleLiLeave(node, event) {
|
|
|
+ event.currentTarget.lastElementChild.style.display = "none";
|
|
|
+ if (this.currentLiNode.nodeKey != node.nodeKey) {
|
|
|
+ event.currentTarget.style.backgroundColor = "transparent";
|
|
|
+ event.currentTarget.style.border = "0";
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ },
|
|
|
+ };
|
|
|
+</script>
|
|
|
+<style scoped>
|
|
|
+ .tree-main {
|
|
|
+ margin-left: 5%;
|
|
|
+ width: 90%;
|
|
|
+ user-select:none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .ivu-icon-ios-paper-outline {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .ivu-select {
|
|
|
+ width: 80% !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .slideSelect .ivu-select-selection {
|
|
|
+ height: 40px;
|
|
|
+ background: #d8d8d870;
|
|
|
+ border: 1px solid #808080;
|
|
|
+ }
|
|
|
+
|
|
|
+ .slideSelect, .slideSelect .ivu-icon {
|
|
|
+ color: rgba(255,255,255,.8);
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .ivu-select-single .ivu-select-selection .ivu-select-selected-value {
|
|
|
+ height: 40px;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ /* .ivu-tree ul li {
|
|
|
+ margin: 18px 0;
|
|
|
+ } */
|
|
|
+ .tree-main /deep/ .ivu-tree ul {
|
|
|
+ font-size: 14px;
|
|
|
+ position:relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*.tree-main /deep/ .ivu-tree ul::after {
|
|
|
+ content: " ";
|
|
|
+ position: absolute;
|
|
|
+ width: 0;
|
|
|
+ height: 100%;
|
|
|
+ border-left: 1px dashed #fff;
|
|
|
+ left: 5px;
|
|
|
+ top: -11px;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ .tree-main /deep/ .ivu-tree ul li {
|
|
|
+ margin: 8px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ivu-tree .ivu-tree-arrow {
|
|
|
+ width: 2%;
|
|
|
+ }
|
|
|
+ .ivu-tree /deep/ .ivu-tree-arrow i{
|
|
|
+ color:#fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ivu-input-wrapper {
|
|
|
+ width: 80% !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .modelRow {
|
|
|
+ margin: 20px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .tools {
|
|
|
+ position: absolute;
|
|
|
+ right: 60px;
|
|
|
+ bottom: 5px;
|
|
|
+ display: inline-flex;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .tools .ivu-icon {
|
|
|
+ margin-right: 15px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 200;
|
|
|
+ color: rgba(255,255,255,.8);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn_more {
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid rgb(248,248,248);
|
|
|
+ }
|
|
|
+
|
|
|
+ .animated {
|
|
|
+ animation-duration: 0.5s;
|
|
|
+ }
|
|
|
+
|
|
|
+ @-webkit-keyframes slideInDown {
|
|
|
+ from {
|
|
|
+ -webkit-transform: translate3d(0,-10%, 0);
|
|
|
+ transform: translate3d(0, -10%, 0) !important;
|
|
|
+ visibility: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ to {
|
|
|
+ -webkit-transform: translate3d(0, 0%, 0);
|
|
|
+ transform: translate3d(0, 0%, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes slideInDown {
|
|
|
+ from {
|
|
|
+ -webkit-transform: translate3d(0, -10%, 0);
|
|
|
+ transform: translate3d(0, -10%, 0) !important;
|
|
|
+ visibility: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ to {
|
|
|
+ -webkit-transform: translate3d(0, 0%, 0);
|
|
|
+ transform: translate3d(0, 0%, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .slideInDown {
|
|
|
+ -webkit-animation-name: slideInDown;
|
|
|
+ animation-name: slideInDown;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tree-main /deep/ .singleClass {
|
|
|
+ display: inline-flex !important;
|
|
|
+ position:relative;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ width:100%;
|
|
|
+ font-size:14px;
|
|
|
+ height: 50px;
|
|
|
+ padding-left:10px;
|
|
|
+ color:#fff;
|
|
|
+ user-select:none;
|
|
|
+ cursor:pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*.tree-main /deep/ .singleClass:before {
|
|
|
+ content: " ";
|
|
|
+ position: absolute;
|
|
|
+ width: 100px;
|
|
|
+ height: 0;
|
|
|
+ left: 5px;
|
|
|
+ top: 20px;
|
|
|
+ border-top: 1px dashed #fff;
|
|
|
+ }*/
|
|
|
+
|
|
|
+
|
|
|
+</style>
|