index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. <template>
  2. <el-dialog
  3. title="组件库"
  4. :visible.sync="dialogVisible"
  5. width="80%"
  6. :modal="true"
  7. :modal-append-to-body="false"
  8. :appen-to-body="true"
  9. class="bs-dialog-wrap bs-el-dialog"
  10. @closed="close"
  11. >
  12. <div class="content">
  13. <el-tabs v-model="activeName">
  14. <el-tab-pane
  15. label="自定义组件"
  16. name="combination"
  17. >
  18. <div class="big-screen-list-wrap">
  19. <div class="top-search-wrap">
  20. <el-input
  21. v-model="searchKey"
  22. class="bs-el-input"
  23. placeholder="请输入组件名称"
  24. prefix-icon="el-icon-search"
  25. clearable
  26. @clear="reSearch"
  27. @keyup.enter.native="reSearch"
  28. />
  29. <el-select
  30. v-model="code"
  31. class="bs-el-select"
  32. popper-class="bs-el-select"
  33. placeholder="请选择分组"
  34. clearable
  35. @change="reSearch"
  36. >
  37. <el-option
  38. v-for="item in options"
  39. :key="item.code"
  40. :label="item.name"
  41. :value="item.code"
  42. />
  43. </el-select>
  44. <el-button
  45. size="small"
  46. style="margin-right: 20px"
  47. type="primary"
  48. @click="reSearch"
  49. >
  50. 搜索
  51. </el-button>
  52. </div>
  53. <div
  54. v-if="list.length !== 0"
  55. v-loading="loading"
  56. class="list-wrap bs-scrollbar"
  57. element-loading-text="加载中"
  58. :style="{
  59. display: gridComputed ? 'grid' : 'flex',
  60. justifyContent: gridComputed ? 'space-around' : 'flex-start'
  61. }"
  62. >
  63. <!-- <div v-if="list.length !== 0"> -->
  64. <div
  65. v-for="screen in list"
  66. :key="screen.id"
  67. class="big-screen-card-wrap"
  68. :style="{
  69. width: gridComputed ? 'auto' : '290px'
  70. }"
  71. @click="chooseComponent(screen)"
  72. >
  73. <div
  74. :class="focus.id == screen.id ? 'focus' : ''"
  75. class="big-screen-card-inner"
  76. >
  77. <div class="big-screen-card-img">
  78. <el-image
  79. :src="screen.coverPicture"
  80. fit="contain"
  81. style="width: 100%; height: 100%"
  82. >
  83. <div
  84. slot="placeholder"
  85. class="image-slot"
  86. >
  87. 加载中···
  88. </div>
  89. <div slot="error" class="image-slot" style="font-size: 20px">
  90. <div class="error-img-text"> {{ screen.name }}</div>
  91. </div>
  92. </el-image>
  93. </div>
  94. <div class="big-screen-bottom">
  95. <div
  96. class="left-bigscreen-title"
  97. :title="screen.name"
  98. >
  99. {{ screen.name }}
  100. </div>
  101. </div>
  102. </div>
  103. </div>
  104. </div>
  105. <div
  106. v-else
  107. class="empty"
  108. >
  109. 暂无数据
  110. </div>
  111. <div class="footer-pagination-wrap">
  112. <div class="bs-pagination">
  113. <el-pagination
  114. class="bs-el-pagination"
  115. popper-class="bs-el-pagination"
  116. background
  117. layout="total, prev, pager, next, sizes"
  118. :page-size="size"
  119. prev-text="上一页"
  120. next-text="下一页"
  121. :total="totalCount"
  122. :page-sizes="[10, 20, 50, 100]"
  123. :current-page="current"
  124. @current-change="currentChangeHandle"
  125. @size-change="sizeChangeHandle"
  126. />
  127. </div>
  128. </div>
  129. </div>
  130. </el-tab-pane>
  131. <el-tab-pane
  132. label="业务组件"
  133. name="bizComponent"
  134. >
  135. <div class="big-screen-list-wrap">
  136. <div class="top-search-wrap">
  137. <el-input
  138. v-model="name"
  139. class="bs-el-input"
  140. placeholder="请输入组件名称"
  141. prefix-icon="el-icon-search"
  142. clearable
  143. @clear="reSearch"
  144. @keyup.enter.native="reSearch"
  145. />
  146. <el-select
  147. v-model="code"
  148. class="bs-el-select"
  149. popper-class="bs-el-select"
  150. placeholder="请选择分组"
  151. clearable
  152. @change="reSearch"
  153. >
  154. <el-option
  155. v-for="item in options"
  156. :key="item.code"
  157. :label="item.name"
  158. :value="item.code"
  159. />
  160. </el-select>
  161. <el-button
  162. size="small"
  163. style="margin-right: 20px"
  164. type="primary"
  165. @click="reSearch"
  166. >
  167. 搜索
  168. </el-button>
  169. </div>
  170. <div
  171. v-if="bizComponentList.length !== 0"
  172. v-loading="loading"
  173. class="list-wrap bs-scrollbar"
  174. element-loading-text="加载中"
  175. :style="{
  176. display: bizFridComputed ? 'grid' : 'flex',
  177. justifyContent: bizFridComputed ? 'space-around' : 'flex-start'
  178. }"
  179. >
  180. <!-- <div v-if="list.length !== 0"> -->
  181. <div
  182. v-for="screen in bizComponentList"
  183. :key="screen.id"
  184. class="big-screen-card-wrap"
  185. :style="{
  186. width: bizFridComputed ? 'auto' : '290px'
  187. }"
  188. @click="chooseComponent(screen)"
  189. >
  190. <div
  191. :class="focus.id == screen.id ? 'focus' : ''"
  192. class="big-screen-card-inner"
  193. >
  194. <div class="big-screen-card-img">
  195. <el-image
  196. :src="screen.coverPicture"
  197. fit="contain"
  198. style="width: 100%; height: 100%"
  199. >
  200. <div
  201. slot="placeholder"
  202. class="image-slot"
  203. >
  204. 加载中···
  205. </div>
  206. <div slot="error" class="image-slot" style="font-size: 20px">
  207. <div class="error-img-text"> {{ screen.name }}</div>
  208. </div>
  209. </el-image>
  210. </div>
  211. <div class="big-screen-bottom">
  212. <div
  213. class="left-bigscreen-title"
  214. :title="screen.name"
  215. >
  216. {{ screen.name }}
  217. </div>
  218. </div>
  219. </div>
  220. </div>
  221. </div>
  222. <div
  223. v-else
  224. class="empty"
  225. >
  226. 暂无数据
  227. </div>
  228. <div class="footer-pagination-wrap">
  229. <div class="bs-pagination">
  230. <el-pagination
  231. class="bs-el-pagination"
  232. popper-class="bs-el-pagination"
  233. background
  234. layout="total, prev, pager, next, sizes"
  235. :page-size="size"
  236. prev-text="上一页"
  237. next-text="下一页"
  238. :total="totalCount"
  239. :page-sizes="[10, 20, 50, 100]"
  240. :current-page="current"
  241. @current-change="currentChangeHandle"
  242. @size-change="sizeChangeHandle"
  243. />
  244. </div>
  245. </div>
  246. </div>
  247. </el-tab-pane>
  248. <el-tab-pane
  249. label="系统组件"
  250. name="remote"
  251. >
  252. <div class="big-screen-list-wrap">
  253. <div
  254. v-if="remoteComponentlist.length !== 0"
  255. v-loading="loading"
  256. class="list-wrap bs-scrollbar"
  257. element-loading-text="加载中"
  258. :style="{
  259. display: remoteComponentsGridComputed ? 'grid' : 'flex',
  260. justifyContent: remoteComponentsGridComputed ? 'space-around' : 'flex-start'
  261. }"
  262. >
  263. <div
  264. v-for="component in remoteComponentlist"
  265. :key="component.title"
  266. class="big-screen-card-wrap"
  267. :style="{
  268. width: remoteComponentsGridComputed ? 'auto' : '290px'
  269. }"
  270. @click="chooseComponent(component)"
  271. >
  272. <div
  273. :class="component.title == focus.title ? 'focus' : ''"
  274. class="big-screen-card-inner"
  275. >
  276. <div class="big-screen-card-img">
  277. <el-image
  278. :src="component.img"
  279. fit="contain"
  280. style="width: 100%; height: 100%"
  281. >
  282. <div
  283. slot="placeholder"
  284. class="image-slot"
  285. >
  286. 加载中···
  287. </div>
  288. </el-image>
  289. </div>
  290. <div class="big-screen-bottom">
  291. <div
  292. class="left-bigscreen-title"
  293. :title="component.title"
  294. >
  295. {{ component.title }}
  296. </div>
  297. </div>
  298. </div>
  299. </div>
  300. </div>
  301. <div
  302. v-else
  303. class="empty"
  304. >
  305. 暂无数据
  306. </div>
  307. </div>
  308. </el-tab-pane>
  309. </el-tabs>
  310. </div>
  311. <div
  312. slot="footer"
  313. class="dialog-footer"
  314. >
  315. <el-button
  316. class="bs-el-button-default"
  317. @click="dialogVisible = false"
  318. >
  319. 取消
  320. </el-button>
  321. <el-button
  322. type="primary"
  323. @click="confirm"
  324. >
  325. 确定
  326. </el-button>
  327. </div>
  328. </el-dialog>
  329. </template>
  330. <script>
  331. import { get } from 'packages/js/utils/http'
  332. import { pageMixins } from 'packages/js/mixins/page'
  333. import _ from 'lodash'
  334. import innerRemoteComponents, { getRemoteComponents, getRemoteComponentConfig } from 'packages/RemoteComponents/remoteComponentsList'
  335. import { getBizComponentPage } from 'packages/js/api/bigScreenApi'
  336. export default {
  337. name: 'ComponentDialog',
  338. mixins: [pageMixins],
  339. props: {},
  340. data () {
  341. return {
  342. dialogVisible: false,
  343. loading: false,
  344. options: [], // 分组列表
  345. code: '',
  346. focus: -1,
  347. list: [],
  348. searchKey: '',
  349. name: '', // 业务组件搜索关键字
  350. activeName: 'combination',
  351. remoteComponentlist: [],
  352. // 业务组件列表
  353. bizComponentList: []
  354. }
  355. },
  356. computed: {
  357. gridComputed () {
  358. return this.list.length > 3
  359. },
  360. remoteComponentsGridComputed () {
  361. return this.remoteComponentlist.length > 3
  362. },
  363. bizFridComputed () {
  364. return this.bizComponentList.length > 3
  365. }
  366. },
  367. watch: {
  368. activeName () {
  369. this.getCatalogList()
  370. }
  371. },
  372. mounted () {
  373. this.remoteComponentlist = [...innerRemoteComponents, ...getRemoteComponents()]
  374. },
  375. methods: {
  376. chooseComponent (component) {
  377. this.focus = _.cloneDeep(component)
  378. },
  379. close () {},
  380. init () {
  381. this.dialogVisible = true
  382. this.current = 1
  383. this.searchKey = ''
  384. this.code = ''
  385. this.focus = -1
  386. this.getDataList()
  387. this.getCatalogList()
  388. },
  389. // 点击确定
  390. confirm () {
  391. this.dialogVisible = false
  392. if (this.activeName === 'combination') {
  393. if (Object.keys(this.focus).length) {
  394. this.$emit('setComponent', this.focus)
  395. }
  396. } else if (['remote'].includes(this.activeName)) {
  397. if (_.isEmpty(this.focus)) {
  398. return
  399. }
  400. this.$emit('setRemoteComponent', this.focus)
  401. } if (['bizComponent'].includes(this.activeName)) {
  402. let config = {}
  403. if (_.isEmpty(this.focus)) {
  404. return
  405. }
  406. config.code = this.focus.code
  407. config.name = this.focus.name
  408. config = getRemoteComponentConfig(this.focus.code, this.focus.name)
  409. this.$emit('setRemoteComponent', config)
  410. }
  411. },
  412. getDataList () {
  413. this.loading = true
  414. get('/bigScreen/design/page', {
  415. parentCode: this.code || null,
  416. current: this.current,
  417. size: this.size,
  418. searchKey: this.searchKey,
  419. type: 'component'
  420. })
  421. .then((data) => {
  422. this.list = data.list
  423. this.totalCount = data.totalCount
  424. })
  425. .finally(() => {
  426. this.loading = false
  427. })
  428. getBizComponentPage({
  429. parentCode: this.code || null,
  430. current: this.current,
  431. size: this.size,
  432. searchKey: this.searchKey,
  433. name: this.name
  434. }).then((data) => {
  435. this.bizComponentList = data.list
  436. this.totalCount = data.totalCount
  437. this.loading = false
  438. })
  439. },
  440. // 获取目录的列表
  441. getCatalogList () {
  442. const url = this.activeName === 'combination' ? '/bigScreen/type/list/componentCatalog' : '/bigScreen/type/list/bizComponentCatalog'
  443. get(url)
  444. .then((data) => {
  445. this.options = data
  446. })
  447. .catch(() => {})
  448. }
  449. }
  450. }
  451. </script>
  452. <style lang="scss" scoped>
  453. @import '~packages/assets/style/bsTheme.scss';
  454. .big-screen-list-wrap {
  455. position: relative;
  456. height: 100%;
  457. padding: 16px;
  458. color: #9ea9b2;
  459. background-color: var(--bs-background-1) !important;
  460. .top-search-wrap {
  461. display: flex;
  462. align-items: center;
  463. justify-content: flex-end;
  464. margin-bottom: 12px;
  465. .el-input {
  466. width: 200px;
  467. margin-right: 20px;
  468. /deep/.el-input__inner {
  469. background-color: #232832 !important;
  470. }
  471. }
  472. .el-select {
  473. margin-right: 20px;
  474. /deep/.el-input__inner {
  475. background-color: #232832 !important;
  476. }
  477. }
  478. }
  479. .list-wrap {
  480. /* display: grid; */
  481. overflow: auto;
  482. // 间隙自适应
  483. justify-content: space-around;
  484. // max-height: calc(100vh - 270px);
  485. display: grid;
  486. grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  487. grid-gap: 15px;
  488. /deep/ .el-loading-mask {
  489. display: flex;
  490. align-items: center;
  491. justify-content: center;
  492. height: calc(100vh - 260px) !important;
  493. z-index: 999;
  494. top: 50px;
  495. }
  496. .big-screen-card-wrap {
  497. position: relative;
  498. height: 230px;
  499. cursor: pointer;
  500. &:hover {
  501. .screen-card__hover {
  502. height: 180px;
  503. }
  504. }
  505. .screen-card__hover {
  506. position: absolute;
  507. z-index: 999;
  508. top: 0;
  509. right: 0;
  510. left: 0;
  511. display: flex;
  512. overflow: hidden;
  513. align-items: center;
  514. justify-content: center;
  515. height: 0;
  516. transition: height 0.4s;
  517. background: #00000099;
  518. }
  519. .focus {
  520. color: var(--bs-el-text) !important;
  521. border: 1px solid var(--bs-el-color-primary) !important;
  522. }
  523. .big-screen-card-inner {
  524. overflow: hidden;
  525. width: 100%;
  526. height: 100%;
  527. cursor: pointer;
  528. background-color: var(--bs-background-2);
  529. box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
  530. color: var(--bs-el-title);
  531. border: 1px solid var(--bs-background-2);
  532. &:hover {
  533. color: var(--bs-el-text);
  534. border: 1px solid var(--bs-el-color-primary);
  535. }
  536. .add-big-screen-card-text {
  537. font-size: 24px;
  538. }
  539. .big-screen-card-img {
  540. width: 100%;
  541. height: 180px;
  542. img {
  543. width: 100%;
  544. height: 100%;
  545. object-fit: cover;
  546. }
  547. /deep/.image-slot {
  548. height: 100%;
  549. background-color: var(--bs-background-2);
  550. display: flex;
  551. align-items: center;
  552. justify-content: center;
  553. }
  554. /deep/.el-image__error {
  555. background-color: #1d1d1d;
  556. }
  557. }
  558. .big-screen-bottom {
  559. display: flex;
  560. align-items: center;
  561. flex-direction: row;
  562. justify-content: space-between;
  563. box-sizing: border-box;
  564. width: 100%;
  565. /*height: 26px;*/
  566. padding: 0 10px;
  567. height: calc(100% - 180px);
  568. color: var(--bs-el-title);
  569. background-color: var(--bs-background-2);
  570. .left-bigscreen-title {
  571. font-size: 14px;
  572. overflow: hidden;
  573. width: 120px;
  574. white-space: nowrap;
  575. text-overflow: ellipsis;
  576. }
  577. .right-bigscreen-time-title {
  578. font-size: 14px;
  579. overflow: hidden;
  580. width: 140px;
  581. white-space: nowrap;
  582. text-overflow: ellipsis;
  583. }
  584. }
  585. .big-screen-card-text {
  586. font-size: 14px;
  587. padding: 10px;
  588. text-align: center;
  589. color: #333;
  590. }
  591. }
  592. .big-screen-card-inner-add {
  593. display: flex;
  594. align-items: center;
  595. justify-content: center;
  596. }
  597. }
  598. }
  599. .el-loading-parent--relative {
  600. position: unset !important;
  601. }
  602. .footer-pagination-wrap {
  603. display: flex;
  604. align-items: center;
  605. justify-content: flex-end;
  606. width: 100%;
  607. margin-top: 20px;
  608. padding: 0 20px;
  609. }
  610. }
  611. .bs-pagination {
  612. ::v-deep .el-input__inner {
  613. width: 110px !important;
  614. border: none;
  615. background: var(--bs-el-background-1);
  616. }
  617. }
  618. .empty {
  619. width: 100%;
  620. height: 70%;
  621. min-height: 300px;
  622. display: flex;
  623. justify-content: center;
  624. align-items: center;
  625. }
  626. /deep/ .el-tabs__item {
  627. color: var(--bs-el-text);
  628. }
  629. .error-img-text{
  630. overflow:hidden;
  631. padding:0 10px;
  632. white-space: nowrap;
  633. text-overflow: ellipsis;
  634. -o-text-overflow:ellipsis;
  635. }
  636. </style>