index.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. <template>
  2. <div
  3. v-loading="pageLoading"
  4. loading-text="加载中..."
  5. class="page-manage-wrap"
  6. >
  7. <div class="page-manage-menu">
  8. <!-- 搜索部分 -->
  9. <div class="page-manage-menu-search">
  10. <el-input
  11. v-model="searchKey"
  12. placeholder="请输入名称"
  13. @keyup.enter.native="filterClick"
  14. />
  15. <!-- 新增页面按钮 -->
  16. <i
  17. class="page-icon el-icon-plus"
  18. @click="openPageMenuDialog"
  19. />
  20. </div>
  21. <!-- 页面列表 -->
  22. <div class="page-manage-menu-list">
  23. <template v-if="pageDesignListHasLength">
  24. <el-tree
  25. ref="tree"
  26. :key="treeKey"
  27. class="page-list-tree"
  28. node-key="code"
  29. :default-expanded-keys="defaultExpand"
  30. :current-node-key="currentNodeCode"
  31. :data="pageDesignList"
  32. :props="defaultProps"
  33. :filter-node-method="filterNode"
  34. @node-click="nodeClick"
  35. >
  36. <span
  37. slot-scope="{ node, data }"
  38. class="menu-span"
  39. >
  40. <icon-svg :name="pageIconName(data,node)" />
  41. <span
  42. style="padding-left:4px;font-size:14px"
  43. class="tree-node-name"
  44. >{{ data.name }}</span>
  45. <el-dropdown
  46. class="page-list-dropdown"
  47. placement="bottom-start"
  48. node-key="id"
  49. trigger="click"
  50. >
  51. <span class="el-dropdown-link menu-dropdown-link">
  52. <i class="el-icon-more" />
  53. </span>
  54. <el-dropdown-menu slot="dropdown">
  55. <el-dropdown-item @click.native="handleDropdownClick('edit',data,node)">编辑 </el-dropdown-item>
  56. <el-dropdown-item
  57. v-if="data.type!=='catalog'"
  58. @click.native="handleDropdownClick('copy',data,node)"
  59. >复制 </el-dropdown-item>
  60. <el-dropdown-item
  61. class="delete-item"
  62. @click.native="handleDropdownClick('delete',data,node)"
  63. >删除 </el-dropdown-item>
  64. </el-dropdown-menu>
  65. </el-dropdown>
  66. </span>
  67. </el-tree>
  68. </template>
  69. <el-empty
  70. v-else
  71. slot="empty"
  72. />
  73. </div>
  74. </div>
  75. <!-- 预览部分 -->
  76. <div class="page-manage-content">
  77. <div class="page-manage-content-top">
  78. <div class="page-manage-content-top-name">
  79. <icon-svg
  80. v-if="activePage.code"
  81. :name="pageIconImg(activePage)"
  82. class="active-page-icon"
  83. />
  84. {{ activePage.type !== 'catalog'? activePage.name:'' }}
  85. </div>
  86. <div>
  87. <el-button
  88. v-if="pageDesignList.length!==0 && activePage.code"
  89. class="top-button"
  90. icon="el-icon-share"
  91. @click="gopagePreview(activePage)"
  92. >
  93. 新窗口打开
  94. </el-button>
  95. <el-button
  96. v-if="pageDesignList.length!==0 && activePage.code"
  97. class="page-manage-content-top-page"
  98. type="primary"
  99. @click="gopageDesign(activePage)"
  100. >
  101. 设计
  102. </el-button>
  103. </div>
  104. </div>
  105. <div
  106. class="page-manage-content-body-box"
  107. :style="{ padding: activePage.type !== 'dashBoard' ? '16px' : '0' }"
  108. >
  109. <div class="page-manage-content-body">
  110. <el-empty
  111. v-if="!activePage.code"
  112. slot="empty"
  113. description="请在左侧选择页面修改或新增页面"
  114. class="empty-wrap"
  115. />
  116. <div
  117. v-else
  118. :class="{
  119. 'preview-wrap': true,
  120. 'inner-preview-wrap': true,
  121. 'padding': activePage.type === 'form'
  122. }"
  123. >
  124. <BigScreenRun
  125. v-if="activePage.type === 'bigScreen'"
  126. :key="activePage.code"
  127. :code="activePage.code"
  128. />
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. <!-- 新增或编辑弹窗 -->
  134. <AddDialog
  135. ref="AddDialog"
  136. @refreshData="reSearch"
  137. />
  138. <!-- 新增目录弹窗 -->
  139. <el-dialog
  140. :title="catalogData.id ? '编辑目录':'新增目录'"
  141. :visible.sync="catalogVisible"
  142. width="30%"
  143. class="bs-dialog-wrap catalog-dialog bs-el-dialog"
  144. @close="handleClose"
  145. >
  146. <el-form
  147. ref="form"
  148. :model="catalogData"
  149. label-width="80px"
  150. :rules="formRules"
  151. class="bs-el-form"
  152. >
  153. <el-form-item
  154. label="上级目录"
  155. >
  156. <el-select
  157. ref="select"
  158. v-model="catalogData.parentCode"
  159. placeholder="请选择上级目录"
  160. clearable
  161. @change="parentCodeChange"
  162. >
  163. <el-option
  164. key="code"
  165. hidden
  166. :value="catalogData.parentCode"
  167. :label="selectName"
  168. />
  169. <el-tree
  170. :data="catalogList"
  171. :props="defaultProps"
  172. node-key="code"
  173. :check-on-click-node="true"
  174. :expand-on-click-node="false"
  175. @node-click="handleNodeClick"
  176. >
  177. <span
  178. slot-scope="{ data }"
  179. class="menu-span"
  180. >
  181. <span
  182. style="padding-left:4px;font-size:14px"
  183. class="tree-node-name"
  184. >{{ data.name }}</span>
  185. </span>
  186. </el-tree>
  187. </el-select>
  188. </el-form-item>
  189. <el-form-item
  190. label="目录名称"
  191. prop="name"
  192. >
  193. <el-input v-model="catalogData.name" />
  194. </el-form-item>
  195. <el-form-item
  196. label="排序"
  197. >
  198. <el-input-number
  199. v-model="catalogData.orderNum"
  200. :min="0"
  201. :max="30000"
  202. controls-position="right"
  203. />
  204. </el-form-item>
  205. </el-form>
  206. <span
  207. slot="footer"
  208. class="dialog-footer"
  209. >
  210. <el-button
  211. class="bs-el-button-default"
  212. @click="catalogVisible = false"
  213. >取消</el-button>
  214. <el-button
  215. type="primary"
  216. @click="addCatalog"
  217. >确定</el-button>
  218. </span>
  219. </el-dialog>
  220. <ChooseTemplateDialog
  221. ref="ChooseTemplateDialog"
  222. :loading="templateLoading"
  223. :has-create="true"
  224. @addNew="addNew"
  225. @useIt="useIt"
  226. />
  227. <pageMenuDialog
  228. ref="pageMenuDialog"
  229. @addPageDesign="addPageDesign"
  230. />
  231. </div>
  232. </template>
  233. <script>
  234. import AddDialog from './addDialog.vue'
  235. import ChooseTemplateDialog from './ChooseTemplateDialog.vue'
  236. import pageMenuDialog from './pageMenuDialog.vue'
  237. import BigScreenRun from 'data-room-ui/BigScreenRun/index.vue'
  238. import Icon from 'data-room-ui/assets/images/pageIcon/export'
  239. import { getPageType } from './utils'
  240. // import _ from 'lodash'
  241. import cloneDeep from 'lodash/cloneDeep'
  242. import IconSvg from 'data-room-ui/SvgIcon'
  243. let dashBoardPageCode = null
  244. export default {
  245. name: 'PageManage',
  246. components: {
  247. AddDialog,
  248. ChooseTemplateDialog,
  249. pageMenuDialog,
  250. BigScreenRun,
  251. IconSvg
  252. },
  253. // 路由钩子-进入后
  254. beforeRouteEnter (to, from, next) {
  255. next(vm => {
  256. dashBoardPageCode = from.query.code
  257. })
  258. },
  259. props: [],
  260. data () {
  261. return {
  262. isCatalog: false, // 用来判断当前点击的节点是否是目录
  263. parentNode: { code: '' }, // 用来保存当前的父节点
  264. currentTreeNode: {}, // 保存当前点击的节点信息
  265. selectName: '',
  266. catalogList: [],
  267. currentNodeCode: '',
  268. dashBoardConfig: {},
  269. defaultExpand: [], // 默认展开的节点
  270. currentNode: {}, // 默认选中的节点
  271. flag: true,
  272. pageIcon: Icon.getNameList(), // 获取所有的svg
  273. defaultProps: { // el-tree的配置
  274. children: 'children',
  275. label: 'name'
  276. },
  277. showPage: false, // 显示页面
  278. sort: false, // 排序
  279. searchKey: '', // 关键词
  280. parentCode: '', // 当前选中的子节点的父节点的编码
  281. zNodes: [],
  282. ztreeObj: '',
  283. nodeData: {}, // 当前鼠标悬浮时的树节点
  284. activePage: {
  285. code: null,
  286. type: null,
  287. name: null
  288. }, // 当前选中的的树节点
  289. rightClickForm: {
  290. visible: false,
  291. org: {}
  292. },
  293. catalogVisible: false, // 文件夹的弹窗
  294. isAdd: true, // 判断当前目录是新增还是编辑
  295. catalogData: {
  296. id: '',
  297. code: '',
  298. type: 'catalog',
  299. name: '',
  300. parentCode: '',
  301. orderNum: 0
  302. }, // 文件夹数据
  303. // formConf,
  304. formInitInfo: {}, // 初始的数据
  305. pageDesignList: [], // 页面列表
  306. menuList: [{}],
  307. showHover: false,
  308. pageLoading: false,
  309. treeKey: new Date().getTime(),
  310. formRules: {
  311. name: [
  312. { required: true, message: '目录名称不能为空', trigger: 'blur' }
  313. ]
  314. },
  315. catalogDataList: [], // 存储遍历后的所有目录列表
  316. templateLoading: false
  317. }
  318. },
  319. computed: {
  320. pageDesignListHasLength () {
  321. return this.pageDesignList?.length > 0
  322. }
  323. },
  324. watch: {
  325. catalogVisible: {
  326. handler (value) {
  327. if (value) {
  328. this.openCascader(this.currentTreeNode)
  329. }
  330. }
  331. }
  332. },
  333. mounted () {
  334. this.getDataList()
  335. this.chooseCatalog()
  336. },
  337. methods: {
  338. // 关闭新增页面菜单的弹窗
  339. closePageMenuDialog () {
  340. this.$refs.pageMenuDialog.dialogVisible = false
  341. },
  342. // 点击新增打开页面菜单弹窗
  343. openPageMenuDialog () {
  344. this.$refs.pageMenuDialog.dialogVisible = true
  345. },
  346. parentCodeChange (code) {
  347. this.catalogData.parentCode = code
  348. },
  349. // 初始化新增目录时选择上级目录
  350. chooseCatalog () {
  351. this.parentNode = this.activePage?.type === 'catalog' ? this.activePage : { code: '0', name: '根目录' }
  352. this.catalogData.parentCode = this.parentNode.code
  353. this.selectName = this.parentNode.name
  354. },
  355. // 点击下拉选项中的树节点选择上级目录树节点
  356. handleNodeClick (node) {
  357. this.$set(this.catalogData, 'parentCode', node.code)
  358. this.selectName = node.name
  359. this.$refs.select.blur() // 点击后关闭下拉框,因为点击树形控件后select不会自动折叠
  360. },
  361. // 获取所有的目录
  362. openCascader (node) {
  363. const excludeCategory = node.type === 'catalog' && !this.isAdd ? node.code : undefined
  364. this.$dataRoomAxios.post('/bigScreen/category/tree', { searchKey: '', typeList: ['catalog'], excludeCategory, sort: false }).then(data => {
  365. const list = [{ name: '根目录', code: '', children: data }]
  366. this.catalogList = list
  367. }).catch(() => {
  368. })
  369. },
  370. // 默认选择第一项
  371. chooseFirstNode () {
  372. this.defaultExpand = []
  373. // 如果存在activePage则将activePage设置为高亮
  374. if (this.activePage && this.activePage.code) {
  375. this.currentNodeCode = this.activePage.code
  376. this.$nextTick(() => {
  377. if (this.$refs.tree) {
  378. this.$refs.tree.setCurrentKey(this.currentNodeCode)
  379. }
  380. })
  381. this.defaultExpand.push(this.currentNodeCode)
  382. this.currentNode = { ...this.activePage }
  383. } else {
  384. // 如果不存在则默认选择第一项(或者是第一个目录的第一项)
  385. if (this.pageDesignList?.length > 0 && !(this.pageDesignList?.length === 1 && this.pageDesignList[0].type === 'catalog' && (!this.pageDesignList[0].children || this.pageDesignList[0].children?.length === 0))) {
  386. const code = this.getDefaultNode(this.pageDesignList)
  387. if (code) {
  388. this.currentNodeCode = code
  389. this.activePage = { ...this.currentNode }
  390. this.defaultExpand.push(code)
  391. this.$nextTick(() => {
  392. this.$refs.tree.setCurrentKey(code)
  393. })
  394. this.isCatalog = false
  395. }
  396. } else {
  397. this.activePage = { code: '', name: '', type: '' }
  398. }
  399. }
  400. },
  401. // 设置默认节点
  402. getDefaultNode (nodeList) {
  403. for (const node of nodeList) {
  404. if (this.flag) {
  405. if (node.children && node.children.length > 0 && node.type === 'catalog') {
  406. return this.getDefaultNode(node.children)
  407. } else if (!(node.children && node.children?.length > 0) && node?.type === 'catalog') {
  408. continue
  409. } else {
  410. this.flag = false
  411. this.currentNode = node
  412. return node.code
  413. }
  414. } else {
  415. return this.currentNode.code
  416. }
  417. }
  418. },
  419. // 左侧菜单图标
  420. pageIconName (data, node) {
  421. if (data.type === 'bigScreen') {
  422. return this.pageIcon[2]
  423. } else {
  424. return node.expanded ? this.pageIcon[1] : this.pageIcon[0]
  425. }
  426. },
  427. // 顶部图标
  428. pageIconImg () {
  429. return this.pageIcon[2]
  430. },
  431. // 树节点查询
  432. filterClick () {
  433. this.$refs.tree.filter(this.searchKey)
  434. },
  435. filterNode (value, data) {
  436. if (!value) return true
  437. return data.name.indexOf(value) !== -1
  438. },
  439. // 预览
  440. gopagePreview (nodeData) {
  441. if (nodeData.code && nodeData.type === 'bigScreen') {
  442. const { href } = this.$router.resolve({
  443. path: window.BS_CONFIG?.routers?.previewUrl || '/big-screen/preview', // 这里写的是要跳转的路由地址
  444. query: {
  445. code: nodeData.code
  446. }
  447. })
  448. window.open(href, '_blank')
  449. } else if (!nodeData.code) {
  450. this.$message.warning('请先选择表单或页面')
  451. }
  452. },
  453. // 点击节点
  454. nodeClick (treeNode, nodeObj, val) {
  455. this.currentTreeNode = treeNode
  456. // 点击的节点为目录,则当前父节点为目录
  457. if (treeNode.type === 'catalog') {
  458. this.parentNode = cloneDeep(treeNode)
  459. this.isCatalog = true
  460. } else {
  461. this.isCatalog = false
  462. this.activePage = treeNode
  463. // 点击的节点非目录,则为当前节点的父节点
  464. this.parentNode = (!treeNode.parentCode || treeNode.parentCode === '0') ? { code: '0', name: '根目录' } : cloneDeep(nodeObj.parent.data)
  465. }
  466. this.catalogData.parentCode = this.parentNode.code
  467. this.selectName = this.parentNode.name
  468. },
  469. handleClose () {
  470. this.catalogVisible = false
  471. this.$refs.form.clearValidate()
  472. },
  473. // 获取页面的列表(获取,搜索,排序)
  474. getDataList () {
  475. this.pageLoading = true
  476. this.$dataRoomAxios.post('/bigScreen/category/tree', { searchKey: this.searchKey, sort: this.sort }).then(data => {
  477. this.pageDesignList = data
  478. // 如果有addModel这个参数,说明是从页面直接新增过来的,直接进入页面或者表单的填写状态
  479. if (this.$route.query.add) {
  480. this.$refs.AddDialog.init(undefined, this.parentNode, 'form')
  481. }
  482. if (dashBoardPageCode) {
  483. this.$nextTick(() => {
  484. const currentNode = this.findItemBycode(dashBoardPageCode, data)
  485. if (currentNode && currentNode.code) {
  486. this.activePage = currentNode
  487. if (this.$refs.tree) {
  488. this.$refs.tree.setCurrentKey(currentNode)
  489. this.defaultExpand.push(currentNode.code)
  490. }
  491. } else {
  492. this.chooseFirstNode()
  493. }
  494. })
  495. } else {
  496. this.chooseFirstNode()
  497. }
  498. }).catch(() => {
  499. }).finally(() => {
  500. this.pageLoading = false
  501. })
  502. },
  503. // 遍历树节点匹配code
  504. findItemBycode (code, list) {
  505. let node = list.find(item => item.code === code)
  506. if (node) {
  507. return node
  508. } else {
  509. for (let i = 0; i < list?.length; i++) {
  510. if (list[i].children instanceof Array && list[i].children?.length > 0) {
  511. node = this.findItemBycode(code, list[i].children)
  512. if (node) {
  513. return node
  514. }
  515. }
  516. }
  517. return null
  518. }
  519. },
  520. // 对页面进行操作
  521. handleDropdownClick (command, nodeData, node) {
  522. switch (command) {
  523. case 'copy':
  524. this.copyPege(nodeData, node)
  525. break
  526. case 'edit':
  527. this.toEdit(nodeData, node)
  528. break
  529. case 'delete':
  530. this.deletePageDesign(nodeData, node)
  531. break
  532. // case 'code':
  533. // this.code(nodeData, node)
  534. // break
  535. }
  536. },
  537. // code (nodeData, node) {
  538. // axios({
  539. // method: 'get',
  540. // url: `${window.BS_CONFIG.baseUrl}/code/generation/adminPage/${nodeData.code}`,
  541. // headers: {
  542. // },
  543. // // 通过URL传参,后端通过 @RequestParam 注解获取参数
  544. // params: {},
  545. // // 通过body传参,后端通过 @RequestBody 注解获取参数
  546. // data: {},
  547. // withCredentials: false,
  548. // responseType: 'arraybuffer'
  549. // }).then(res => {
  550. // const fileUrl = window.URL.createObjectURL(new Blob([res.data]))
  551. // // 创建超链接
  552. // const fileLink = document.createElement('a')
  553. // fileLink.href = fileUrl
  554. // // 设置下载文件名
  555. // let responseFileName = res.headers.filename
  556. // // 解决中文乱码
  557. // responseFileName = window.decodeURI(responseFileName)
  558. // fileLink.setAttribute('download', responseFileName)
  559. // document.body.appendChild(fileLink)
  560. // // 模拟人工点击下载超链接
  561. // fileLink.click()
  562. // this.submitLoading = false
  563. // // 释放资源
  564. // document.body.removeChild(fileLink)
  565. // window.URL.revokeObjectURL(fileUrl)
  566. // this.step++
  567. // }).catch((error) => {
  568. // this.submitLoading = false
  569. // console.error(error)
  570. // })
  571. // },
  572. // 复制页面
  573. copyPege (nodeData, node) {
  574. this.$dataRoomAxios.post(`/${nodeData.type}/design/copy/${nodeData.code}`).then(() => {
  575. this.getDataList()
  576. })
  577. },
  578. // 新增大屏或新增页面,从空白新建
  579. addNew (parentNode, type) {
  580. this.$refs.AddDialog.init(undefined, this.parentNode, type)
  581. this.flag = true
  582. },
  583. // 大屏 dashboard从模版新建, 使用某个模版新建
  584. useIt (pageTemplateId, parentNode, type) {
  585. this.templateLoading = true
  586. const className = 'com.gccloud.dataroom.core.module.manage.dto.DataRoomPageDTO'
  587. this.$dataRoomAxios.post(`/bigScreen/${type}/design/add/template`, {
  588. pageTemplateId,
  589. parentCode: parentNode.code,
  590. type,
  591. className
  592. }).then((code) => {
  593. const path = window.BS_CONFIG?.routers?.designUrl || '/big-screen/design'
  594. // const { href } = this.$router.resolve({
  595. // path,
  596. // query: {
  597. // code: code
  598. // }
  599. // })
  600. // window.open(href, '_self')
  601. this.$router.push({
  602. path,
  603. query: {
  604. code: code
  605. }
  606. })
  607. }).finally(() => {
  608. this.templateLoading = true
  609. })
  610. },
  611. // 新增页面/表单/目录
  612. addPageDesign (page) {
  613. const type = page.type
  614. const categories = page.categories
  615. if (type !== 'catalog') {
  616. // 如果是大屏,弹出选择模版页面
  617. if (['bigScreen'].includes(type)) {
  618. this.$refs.ChooseTemplateDialog.init(this.parentNode, type)
  619. return
  620. }
  621. this.$refs.AddDialog.init(undefined, this.parentNode, type, categories)
  622. this.flag = true
  623. } else {
  624. // 新增时初始化目录配置
  625. this.catalogData = {
  626. id: '',
  627. code: '',
  628. type: 'catalog',
  629. name: '',
  630. parentCode: this.parentNode.code,
  631. orderNum: 0
  632. }
  633. this.isAdd = true
  634. this.catalogVisible = true
  635. }
  636. },
  637. // 刷新页面
  638. reSearch (treeNode, id) {
  639. this.getDataList()
  640. },
  641. // 编辑
  642. toEdit (nodeData, nodeObj) {
  643. // 编辑目录
  644. if (nodeData.type === 'catalog') {
  645. this.catalogVisible = true
  646. this.catalogData.name = nodeData.name
  647. this.isAdd = false
  648. this.catalogData.id = nodeData.id
  649. this.catalogData.code = nodeData.code
  650. this.catalogData.orderNum = nodeData.orderNum
  651. this.parentNode = (!nodeData.parentCode || nodeData.parentCode === '0') ? { code: '0', name: '根目录' } : cloneDeep(nodeObj.parent.data)
  652. this.catalogData.parentCode = this.parentNode.code
  653. this.selectName = this.parentNode.name
  654. } else {
  655. this.$refs.AddDialog.init(nodeData, this.parentNode)
  656. }
  657. },
  658. // 点击新增/编辑目录
  659. addCatalog () {
  660. this.$refs.form.validate(async (valid) => {
  661. if (!valid) {
  662. return
  663. }
  664. if (this.isAdd) {
  665. this.$dataRoomAxios.post('/bigScreen/category/add',
  666. {
  667. ...this.catalogData,
  668. id: '',
  669. code: ''
  670. }).then(data => {
  671. this.catalogVisible = false
  672. this.getDataList()
  673. this.flag = true
  674. // 关闭页面菜单的弹窗
  675. this.closePageMenuDialog()
  676. }).catch(() => {
  677. })
  678. } else {
  679. this.$dataRoomAxios.post('/bigScreen/category/update', { ...this.catalogData, excludeCategory: this.catalogData.code }).then(data => {
  680. this.catalogVisible = false
  681. this.getDataList()
  682. }).catch(() => {
  683. })
  684. }
  685. })
  686. },
  687. // 删除页面设计
  688. deletePageDesign (nodeData, node) {
  689. const type = getPageType(nodeData.type)// 由于类型与接口不统一需要转化一下
  690. const url = type === 'category' ? `/bigScreen/category/delete/${nodeData.code}` : `/bigScreen/${type}/design/delete/${nodeData.code}`// 接口地址
  691. this.$confirm('确定删除该页面设计?', '提示', {
  692. confirmButtonText: '确定',
  693. cancelButtonText: '取消',
  694. type: 'warning',
  695. customClass: 'bs-el-message-box'
  696. }).then(async () => {
  697. this.$dataRoomAxios.post(url).then(() => {
  698. this.$message({
  699. type: 'success',
  700. message: '删除成功'
  701. })
  702. this.flag = true
  703. this.activePage.code = ''
  704. this.chooseFirstNode()
  705. this.$refs.tree.remove(node)
  706. if (nodeData.type === 'catalog' && this.parentCode === nodeData.code) {
  707. this.parentCode = '0'
  708. }
  709. }).catch(() => {
  710. this.$message({
  711. type: 'error',
  712. message: '删除失败!'
  713. })
  714. })
  715. }).catch()
  716. },
  717. // 点击进入页面设计
  718. gopageDesign (nodeData) {
  719. const path = window.BS_CONFIG?.routers?.designUrl || '/big-screen/design'
  720. const openType = nodeData.type === 'report' ? '_blank' : '_self'
  721. const { href } = this.$router.resolve({
  722. path,
  723. query: {
  724. code: nodeData.code
  725. }
  726. })
  727. window.open(href, openType)
  728. }
  729. }
  730. }
  731. </script>
  732. <style lang="scss" scoped>
  733. .page-type-cover {
  734. position: absolute;
  735. top: 0;
  736. left: 16px;
  737. color: #fff;
  738. background: #00000020;
  739. padding: 4px;
  740. font-size: 12px;
  741. }
  742. .page-manage-wrap{
  743. display: flex;
  744. .page-manage-menu{
  745. width: 260px;
  746. border-right: 2px solid #F5F7FA;
  747. .page-manage-menu-search{
  748. display: flex;
  749. align-items: center;
  750. padding: 10px 15px;
  751. box-sizing: border-box;
  752. justify-content: space-around;
  753. .input-with-select{
  754. margin-bottom: 0px;
  755. }
  756. .page-icon{
  757. font-size: 20px;
  758. margin-left: 10px;
  759. color: var(--bs-el-color-primary);
  760. &:hover{
  761. cursor: pointer;
  762. }
  763. }
  764. }
  765. }
  766. .page-manage-menu-list{
  767. width: 100%;
  768. overflow: auto;
  769. height: calc(100vh - 40px - 50px);
  770. .tree-node-name{
  771. width: 170px;
  772. display: inline-block;
  773. overflow: hidden;
  774. white-space: nowrap;
  775. text-overflow: ellipsis;
  776. }
  777. .el-icon-document{
  778. font-size: 16px;
  779. padding: 5px 5px 0 0;
  780. color: #007afe;
  781. }
  782. .el-icon-notebook-1{
  783. font-size: 16px;
  784. padding: 5px 5px 0 0;
  785. color: #50D4FD;
  786. }
  787. .el-icon-folder{
  788. font-size: 16px;
  789. padding: 5px 5px 0 0;
  790. color: #6477FF;
  791. }
  792. .el-icon-folder-opened{
  793. font-size: 16px;
  794. padding: 5px 5px 0 0;
  795. color: #6477FF;
  796. }
  797. }
  798. .page-manage-content{
  799. width: calc(100vw - 260px);
  800. height: calc(100vh - 40px);
  801. .page-manage-content-top{
  802. height: 50px;
  803. width: 100%;
  804. display: flex;
  805. align-items: center;
  806. justify-content: space-between;
  807. padding: 0 20px;
  808. .page-name-icon{
  809. color: var(--bs-el-color-primary);
  810. padding-right: 10px;
  811. }
  812. }
  813. .page-manage-content-body-box{
  814. width: 100%;
  815. height: calc(100vh - 40px - 50px);
  816. background-color: #F5F7FA;
  817. .page-manage-content-body{
  818. height: 100%;
  819. background-color: #fff;
  820. position: relative;
  821. overflow: auto;
  822. overflow-x: hidden;
  823. ::v-deep .el-input__suffix-inner{
  824. /*pointer-events: none!important;*/
  825. }
  826. .preview-wrap{
  827. /*pointer-events: none;*/
  828. width: 100%;
  829. height: 100%;
  830. position: absolute;
  831. .admin-page-wrap {
  832. height: 100%;
  833. background: #F5F7FA;
  834. }
  835. }
  836. .empty-wrap{
  837. position: absolute;
  838. top:50%;
  839. left:50%;
  840. transform: translate(-50%,-50%);
  841. color: #AAAAAA;
  842. }
  843. }
  844. }
  845. }
  846. }
  847. .el-dropdown{
  848. cursor: pointer;
  849. }
  850. .catalog-dialog{
  851. ::v-deep .el-dialog__body{
  852. min-height: 80px;
  853. }
  854. }
  855. .el-icon-delete{
  856. color: #DF2A2A;
  857. }
  858. .el-dropdown-menu--mini .el-dropdown-menu__item i{
  859. padding-top: 6px;
  860. }
  861. .el-dropdown-menu--mini ::v-deep .el-dropdown-menu__item{
  862. display: flex;
  863. min-width: 100px!important;
  864. line-height: 36px;
  865. margin-bottom: 10px;
  866. .page-opt-list-icon{
  867. font-size: 16px;
  868. padding: 10px 5px 0 0;
  869. color: #007afe;
  870. }
  871. .page-dropdown-right{
  872. .page-name{
  873. font-size: 14px;
  874. }
  875. .page-desc{
  876. color: #878A8B;
  877. font-size: 12px;
  878. line-height: 20px;
  879. }
  880. }
  881. }
  882. .menu-span{
  883. width: 100%;
  884. display: flex;
  885. align-items: center;
  886. .el-dropdown{
  887. position: absolute;
  888. right: 10px;
  889. }
  890. }
  891. .disabled{
  892. pointer-events: auto!important;
  893. cursor: not-allowed!important;
  894. }
  895. .page-list-active{
  896. cursor: pointer;
  897. background-color: #F4F4F4;
  898. }
  899. .el-icon-rank{
  900. cursor: move;
  901. }
  902. .active-page-icon{
  903. margin-right: 5px;
  904. }
  905. .sort-icon {
  906. font-size: 20px;
  907. margin-left: 10px;
  908. color: var(--bs-el-color-primary);
  909. &:hover{
  910. cursor: pointer;
  911. }
  912. }
  913. /* 去除tree前面的小三角形*/
  914. .page-list-tree ::v-deep .el-tree-node__content > .el-tree-node__expand-icon{
  915. width: 20px;
  916. opacity: 0 !important;
  917. }
  918. /*选中树节点后*/
  919. .page-list-tree ::v-deep .ztree li a.curSelectedNode span{
  920. color: var(--bs-el-color-primary)!important;
  921. }
  922. #settingDropdown{
  923. display: inline-block;
  924. float: right;
  925. }
  926. ::v-deep .el-tree-node{
  927. line-height: 40px;
  928. .el-tree-node__content{
  929. line-height: 40px;
  930. height: 100%;
  931. }
  932. }
  933. /*当前tree节点激活样式*/
  934. .page-list-tree ::v-deep .is-current>.el-tree-node__content{
  935. background: #007aff10;
  936. color: var(--bs-el-color-primary);
  937. }
  938. .page-list-tree ::v-deep .is-current>.el-tree-node__content::before{
  939. position: absolute;
  940. left: 0;
  941. border-left: 4px solid var(--bs-el-color-primary);
  942. content: "";
  943. height: 40px;
  944. width: 4px;
  945. }
  946. ::v-deep .el-icon-more{
  947. transform: rotate(90deg);
  948. color: #999999;
  949. font-size: 10px;
  950. }
  951. /*滚动条样式*/
  952. ::v-deep ::-webkit-scrollbar {
  953. width: 6px;
  954. border-radius: 4px;
  955. /*height: 4px;*/
  956. }
  957. ::v-deep ::-webkit-scrollbar-thumb {
  958. background: #dddddd !important;
  959. border-radius: 10px;
  960. }
  961. .padding {
  962. padding: 20px;
  963. background: #fff;
  964. }
  965. .catalog-cascader{
  966. width: 100%!important;
  967. }
  968. .delete-item{
  969. color:#ea0b30!important;
  970. }
  971. </style>