Tree.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <template>
  2. <div class="tree-main">
  3. <Tree :data="treeData" :render="renderContent" ref="tree"></Tree>
  4. <Modal v-model="modalFlag" title="添加新节点" ok-text="确认" cancel-text="取消" @on-ok="handleAddNode">
  5. <Row class="modelRow">
  6. <span>
  7. 当前章节:
  8. <span style="margin-left:10px;">{{currentNode.title}}</span>
  9. </span>
  10. </Row>
  11. <Row class="modelRow">
  12. <span>章节类型:</span>
  13. <RadioGroup v-model="nodeType" type="button">
  14. <Radio label="章节"></Radio>
  15. <Radio label="课件"></Radio>
  16. </RadioGroup>
  17. </Row>
  18. <Row class="modelRow">
  19. <span>章节名称:</span>
  20. <Input v-model="inputValue" placeholder="输入新节点名称" style="width: 100%" />
  21. </Row>
  22. </Modal>
  23. <Modal v-model="editFlag" title="修改节点" ok-text="确认" cancel-text="取消" @on-ok="handleUpdateNode">
  24. <Row class="modelRow">
  25. <span>
  26. 当前名称:
  27. <span style="margin-left:10px;">{{currentNode.title}}</span>
  28. </span>
  29. </Row>
  30. <Row class="modelRow">
  31. <span>章节类型:</span>
  32. <RadioGroup v-model="nodeType" type="button">
  33. <Radio label="章节"></Radio>
  34. <Radio label="课件"></Radio>
  35. </RadioGroup>
  36. </Row>
  37. <Row class="modelRow">
  38. <span>章节名称:</span>
  39. <Input v-model="editValue" placeholder="输入节点新名称" style="width: 100%" />
  40. </Row>
  41. </Modal>
  42. </div>
  43. </template>
  44. <script>
  45. export default {
  46. props:["treeDatas","volumeCode"],
  47. data() {
  48. return {
  49. bookSelect: "语文人教课标版四年级上册",
  50. periodList: [],
  51. subjectList: [],
  52. versionList: [],
  53. gradeList: [],
  54. slideGradeList: [],
  55. treeData: [],
  56. inputValue: "",
  57. editValue: "",
  58. modalFlag: false,
  59. editFlag: false,
  60. addBookFlag: false,
  61. nodeType: "章节",
  62. currentNode: "",
  63. currentLiNode: "",
  64. buttonProps: {
  65. type: "default",
  66. size: "small"
  67. },
  68. periodSelect: "",
  69. subjectSelect: "",
  70. versionSelect: "",
  71. gradeSelect: "",
  72. periodName: "",
  73. subjectName: "",
  74. versionName: "",
  75. gradeName: "",
  76. };
  77. },
  78. created() {
  79. this.treeData = this.treeDatas;
  80. },
  81. methods: {
  82. renderContent(h, { root, node, data }) {
  83. let that = this;
  84. return h(
  85. "span",
  86. {
  87. style: {
  88. display: "inline-block",
  89. width: "95%",
  90. textAlign: "left",
  91. paddingLeft: "2%",
  92. cursor: "pointer",
  93. position: "relative",
  94. boxSizing: "border-box"
  95. },
  96. domProps: {
  97. className: "singleClass"
  98. },
  99. on: {
  100. click: () => {
  101. this.titleClick(root, node, data, event);
  102. },
  103. mouseover: e => {
  104. e.stopPropagation();
  105. this.handleLiOver(event);
  106. },
  107. mouseleave: e => {
  108. e.stopPropagation();
  109. this.handleLiLeave(node, event);
  110. }
  111. }
  112. },
  113. [
  114. h("span", [
  115. h("Icon", {
  116. props: {
  117. type:
  118. data.children && data.children.length > 0
  119. ? "md-albums"
  120. : "ios-paper-outline"
  121. },
  122. style: {
  123. marginRight: "5px",
  124. display: "none"
  125. }
  126. }),
  127. h("span", data.title)
  128. ]),
  129. h(
  130. "span",
  131. {
  132. style: {
  133. float: "right",
  134. top: "6px",
  135. display: "none"
  136. },
  137. on: {
  138. mouseleave: e => {
  139. e.stopPropagation();
  140. //this.hideTools(event);
  141. },
  142. },
  143. domProps: {
  144. className: "tools"
  145. }
  146. },
  147. [
  148. h(
  149. "Icon",
  150. {
  151. props: {
  152. type: "md-add",
  153. title: "添加"
  154. },
  155. on: {
  156. click: e => {
  157. e.stopPropagation();
  158. this.appendClick(data);
  159. }
  160. }
  161. },
  162. ),
  163. h(
  164. "Icon",
  165. {
  166. props: {
  167. type: "md-remove"
  168. },
  169. on: {
  170. click: e => {
  171. e.stopPropagation();
  172. this.remove(root, node, data);
  173. }
  174. }
  175. },
  176. ),
  177. h(
  178. "Icon",
  179. {
  180. props: {
  181. type: "md-arrow-round-up"
  182. },
  183. on: {
  184. click: e => {
  185. e.stopPropagation();
  186. this.moveUp(root, node, data);
  187. }
  188. }
  189. },
  190. ),
  191. h(
  192. "Icon",
  193. {
  194. props: {
  195. type: "md-arrow-round-down"
  196. },
  197. on: {
  198. click: e => {
  199. e.stopPropagation();
  200. this.moveDown(root, node, data);
  201. }
  202. }
  203. },
  204. ),
  205. h(
  206. "Icon",
  207. {
  208. props: {
  209. type: "md-create"
  210. },
  211. on: {
  212. click: e => {
  213. e.stopPropagation();
  214. this.editClick(node, data);
  215. }
  216. }
  217. },
  218. )
  219. ]
  220. )
  221. ]
  222. );
  223. },
  224. // 添加节点
  225. append(data, value) {
  226. const children = data.children || [];
  227. let newChild = {
  228. title: value,
  229. order: children.length,
  230. pid: data.rowKey,
  231. children: [],
  232. expand: true,
  233. type: data.type,
  234. volumeCode: this.volumeCode,
  235. remark: "备注",
  236. }
  237. children.push(newChild);
  238. this.$set(data, "children", children);
  239. this.$api.SaveOrUpdateSingleNode(newChild).then(res => {
  240. this.$Message.success("添加成功");
  241. this.$api.FindSyllabusByVolumeCode({ VolumeCode: this.volumeCode, Status: 1 }).then(res => {
  242. this.treeData = res.result.data;
  243. })
  244. })
  245. },
  246. // 删除节点
  247. remove(root, node, data) {
  248. const parentKey = root.find(el => el === node).parent;
  249. const parent = root.find(el => el.nodeKey === parentKey).node;
  250. const index = parent.children.indexOf(data);
  251. parent.children.splice(index, 1);
  252. data.status = 0;
  253. this.$api.SaveOrUpdateSingleNode(data).then(res => {
  254. this.$Message.success("删除成功");
  255. })
  256. },
  257. // 点击编辑
  258. editClick(node, data) {
  259. this.currentNode = data;
  260. this.editFlag = true;
  261. this.editValue = "";
  262. },
  263. //添加节点 弹出输入框
  264. appendClick(data) {
  265. this.currentNode = data;
  266. this.modalFlag = true;
  267. this.inputValue = "";
  268. },
  269. // 确认添加节点
  270. handleAddNode() {
  271. if (this.inputValue != "") {
  272. this.append(this.currentNode, this.inputValue);
  273. } else {
  274. this.modalFlag = false;
  275. }
  276. },
  277. // 修改节点
  278. handleUpdateNode() {
  279. if (this.editValue != "") {
  280. this.$api.SaveOrUpdateSingleNode(this.currentNode).then(res => {
  281. this.$Message.success("修改成功");
  282. this.currentNode.title = this.editValue;
  283. })
  284. } else {
  285. this.editFlag = false;
  286. }
  287. },
  288. // 标题点击收缩展开
  289. titleClick(root, node, data, event) {
  290. data.expand = !data.expand;
  291. },
  292. // 根目录点击事件
  293. rootClick(data) {
  294. data.expand = !data.expand;
  295. },
  296. // 上移章节操作
  297. moveUp(root, node, data) {
  298. const parentKey = root.find(el => el === node).parent;
  299. const parent = root.find(el => el.nodeKey === parentKey).node;
  300. const index = parent.children.indexOf(data);
  301. const nodeIndex = root.indexOf(node);
  302. let currentTitle = data.title;
  303. let currentExpand = data.expand;
  304. let currentChildren = data.children || [];
  305. let preChildren = (parent.children[index - 1]) ? (parent.children[index - 1]).children : [];
  306. if (index != 0) {
  307. data.title = parent.children[index - 1].title;
  308. parent.children[index - 1].title = currentTitle;
  309. parent.children[index - 1].expand = currentExpand;
  310. data.children = preChildren;
  311. data.expand = parent.children[index - 1].expand;
  312. parent.children[index - 1].children = currentChildren;
  313. }
  314. },
  315. // 下移章节操作
  316. moveDown(root, node, data) {
  317. const parentKey = root.find(el => el === node).parent;
  318. const parent = root.find(el => el.nodeKey === parentKey).node;
  319. const index = parent.children.indexOf(data);
  320. let currentTitle = data.title;
  321. let currentChildren = data.children || [];
  322. let nextChildren = (parent.children[index + 1]) ? (parent.children[index + 1]).children : [];
  323. if (index != parent.children.length - 1) {
  324. data.title = parent.children[index + 1].title;
  325. data.children = nextChildren;
  326. parent.children[index + 1].title = currentTitle;
  327. parent.children[index + 1].children = currentChildren;
  328. }
  329. },
  330. // 更多操作
  331. handleTools(root, node, data, event) {
  332. let toolsDom = event.currentTarget.nextElementSibling;
  333. const parentKey = root.find(el => el === node).parent;
  334. const parent = root.find(el => el.nodeKey === parentKey).node;
  335. const index = parent.children.indexOf(data);
  336. let list = document.getElementsByClassName("tools");
  337. let cFlag = toolsDom.style.display;
  338. for (let i = 0; i < list.length; i++) {
  339. list[i].style.display = "none";
  340. }
  341. // 判断TOOL显示与隐藏
  342. if (cFlag == "none") {
  343. toolsDom.style.display = "inline-flex";
  344. toolsDom.classList.add("animated");
  345. toolsDom.classList.add("slideInDown");
  346. } else {
  347. toolsDom.style.display = "none";
  348. }
  349. },
  350. // 鼠标从工具条移开的时候隐藏
  351. hideTools(event) {
  352. event.currentTarget.style.display = "none";
  353. },
  354. handleLiOver(event) {
  355. event.currentTarget.lastElementChild.style.display = "block";
  356. event.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.68)";
  357. event.currentTarget.style.border = "1px solid #000";
  358. },
  359. handleLiLeave(node, event) {
  360. event.currentTarget.lastElementChild.style.display = "none";
  361. if (this.currentLiNode.nodeKey != node.nodeKey) {
  362. event.currentTarget.style.backgroundColor = "transparent";
  363. event.currentTarget.style.border = "0";
  364. }
  365. },
  366. // 添加教材
  367. handleAddBook() {
  368. this.$api.FindPeriods({}).then(res => {
  369. this.periodList = res.result.data;
  370. this.periodSelect = this.periodList[0].rowKey;
  371. this.periodName = this.periodList[0].name;
  372. let Pcode = {
  373. value: this.periodList[0].rowKey,
  374. label: this.periodList[0].name
  375. }
  376. this.periodChange(Pcode);
  377. })
  378. this.addBookFlag = true;
  379. },
  380. // 学段选择变化
  381. periodChange(val) {
  382. this.$api.FindSubjects({ Pcode: val.value }).then(res => {
  383. if (res.result.data.length > 0) {
  384. this.subjectList = res.result.data;
  385. this.subjectSelect = this.subjectList[0].rowKey;
  386. this.periodName = val.label;
  387. let Pcode = {
  388. value: this.subjectList[0].rowKey,
  389. label: this.subjectList[0].name
  390. }
  391. this.subjectChange(Pcode);
  392. }
  393. })
  394. },
  395. // 学科选择变化
  396. subjectChange(val) {
  397. this.$api.FindEditions({ Pscode: val.value }).then(res => {
  398. if (res.result.data.length > 0) {
  399. this.versionList = res.result.data;
  400. this.versionSelect = this.versionList[0].rowKey;
  401. this.subjectName = val.label;
  402. let Pcode = {
  403. value: this.versionList[0].rowKey,
  404. label: this.versionList[0].name
  405. }
  406. this.versionChange(Pcode);
  407. }
  408. })
  409. },
  410. // 版本选择变化
  411. versionChange(val) {
  412. this.$api.FindTerms({ Psecode: val.value }).then(res => {
  413. this.gradeList = res.result.data;
  414. this.gradeSelect = this.gradeList.length > 0 ? this.gradeList[0].rowKey : "无";
  415. this.versionName = val.label;
  416. let Pcode = {
  417. value: this.gradeList.length > 0 ? this.gradeList[0].rowKey : "",
  418. label: this.gradeList.length > 0 ? this.gradeList[0].name : ""
  419. }
  420. if (this.gradeList.length > 0) {
  421. this.gradeChange(Pcode);
  422. }
  423. })
  424. },
  425. //册别选择变化
  426. gradeChange(val) {
  427. this.gradeName = val.label ? val.label : "";
  428. },
  429. // 确认添加教材返回教材名称
  430. handleAddConfirm() {
  431. let periodRowKeys = [];
  432. let perioArr = this.periodList;
  433. for (let item of perioArr) {
  434. periodRowKeys.push(item.rowKey);
  435. }
  436. let bookName = this.periodName + this.subjectName + this.versionName + this.gradeName;
  437. this.treeData[0].title = bookName;
  438. }
  439. },
  440. };
  441. </script>
  442. <style scoped>
  443. .tree-main {
  444. margin-left: 5%;
  445. width: 90%;
  446. }
  447. .tree-main /deep/ .ivu-icon-ios-paper-outline {
  448. font-size: 16px;
  449. }
  450. .tree-main /deep/ .ivu-select {
  451. width: 80% !important;
  452. }
  453. .slideSelect .ivu-select-selection {
  454. height: 40px;
  455. background: #d8d8d870;
  456. border: 1px solid #808080;
  457. }
  458. .slideSelect, .slideSelect .ivu-icon {
  459. color: rgba(255,255,255,.8);
  460. }
  461. .tree-main /deep/ .ivu-select-single .ivu-select-selection .ivu-select-selected-value {
  462. height: 40px;
  463. line-height: 40px;
  464. font-size: 14px;
  465. }
  466. /* .ivu-tree ul li {
  467. margin: 18px 0;
  468. } */
  469. .tree-main /deep/ .ivu-tree ul {
  470. font-size: 14px;
  471. }
  472. .tree-main /deep/ .ivu-tree ul li {
  473. margin:8px 0;
  474. }
  475. .ivu-tree .ivu-tree-arrow {
  476. width: 2%;
  477. }
  478. .ivu-input-wrapper {
  479. width: 80% !important;
  480. }
  481. .modelRow {
  482. margin: 20px;
  483. font-size: 14px;
  484. }
  485. .tree-main /deep/ .tools {
  486. position: absolute;
  487. right: 60px;
  488. bottom:5px;
  489. display: inline-flex;
  490. z-index: 999;
  491. }
  492. .tree-main /deep/ .tools .ivu-icon {
  493. margin-right: 15px;
  494. font-size: 16px;
  495. font-weight: 200;
  496. color: #808080;
  497. }
  498. .btn_more {
  499. background: #fff;
  500. border: 1px solid rgb(248,248,248);
  501. }
  502. .animated {
  503. animation-duration: 0.5s;
  504. }
  505. @-webkit-keyframes slideInDown {
  506. from {
  507. -webkit-transform: translate3d(0,-10%, 0);
  508. transform: translate3d(0, -10%, 0) !important;
  509. visibility: visible;
  510. }
  511. to {
  512. -webkit-transform: translate3d(0, 0%, 0);
  513. transform: translate3d(0, 0%, 0);
  514. }
  515. }
  516. @keyframes slideInDown {
  517. from {
  518. -webkit-transform: translate3d(0, -10%, 0);
  519. transform: translate3d(0, -10%, 0) !important;
  520. visibility: visible;
  521. }
  522. to {
  523. -webkit-transform: translate3d(0, 0%, 0);
  524. transform: translate3d(0, 0%, 0);
  525. }
  526. }
  527. .slideInDown {
  528. -webkit-animation-name: slideInDown;
  529. animation-name: slideInDown;
  530. }
  531. .tree-main /deep/ .singleClass {
  532. display: inline-flex !important;
  533. flex-direction: row;
  534. align-items: center;
  535. height: 40px;
  536. }
  537. .btn-addClass {
  538. width: 16%;
  539. padding: 10px 6px !important;
  540. }
  541. .ivu-tabs-nav-scroll {
  542. display: flex;
  543. justify-content: center;
  544. }
  545. .addBookArea .ivu-select {
  546. width: 80% !important;
  547. margin-left: 30px;
  548. }
  549. .addBookArea .ivu-select-single .ivu-select-selection {
  550. height: 32px;
  551. }
  552. .addBookArea .ivu-row {
  553. margin: 30px 20px;
  554. }
  555. .addBookArea .ivu-select-selected-value {
  556. height: 32px !important;
  557. line-height: 32px !important;
  558. font-size: 12px !important;
  559. }
  560. .ivu-tabs {
  561. overflow: unset;
  562. }
  563. </style>