content.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. <!-- eslint-disable vue/multi-word-component-names -->
  2. <template>
  3. <!-- 主体内容部分 -->
  4. <div class="content">
  5. <!-- 背景 -->
  6. <img v-if="background.show && background.type === 'image'" class="content__background" :src="background.link" />
  7. <video
  8. v-if="background.show && background.type === 'video' && background.isBoard"
  9. class="content__background"
  10. width="100%"
  11. autoplay
  12. loop
  13. muted
  14. disablepictureinpicture
  15. playsinline
  16. >
  17. <source :src="background.link" />
  18. Not Supportted Link Or Browser
  19. </video>
  20. <video
  21. v-if="background.show && background.type === 'video' && !background.isBoard"
  22. class="content__background_1"
  23. width="100%"
  24. autoplay
  25. loop
  26. muted
  27. disablepictureinpicture
  28. playsinline
  29. >
  30. <source :src="background.link" />
  31. Not Supportted Link Or Browser
  32. </video>
  33. <div class="flex w-full h-full" :style="{ flexDirection: layout.direction }">
  34. <div v-for="config in layoutConfig" :key="config.name" :style="{ flexBasis: config.basis, overflow: config.overflow ? 'auto' : 'none' }">
  35. <!-- 告示板部分 -->
  36. <template v-if="config.name === 'board'">
  37. <div
  38. v-if="config.pageType == 'vent_New'"
  39. style="padding-top: 11%"
  40. class="content__module content__module1 flex flex-justify-around flex-items-center flex-wrap"
  41. >
  42. <MiniBoard
  43. v-for="item in config.items"
  44. :key="item.prop"
  45. :label="item.label"
  46. :value="item.value"
  47. :type="config.type"
  48. :layout="config.layout"
  49. />
  50. </div>
  51. <div v-else-if="config.pageType == 'New_fire'" class="content__module flex flex-justify-around flex-items-center flex-wrap">
  52. <MiniBoardNew
  53. v-for="item in config.items"
  54. :key="item.prop"
  55. :label="item.label"
  56. :value="item.value"
  57. :type="config.type"
  58. :layout="config.layout"
  59. />
  60. </div>
  61. <div v-else class="content__module flex flex-justify-around flex-items-center flex-wrap">
  62. <MiniBoard
  63. v-for="item in config.items"
  64. :key="item.prop"
  65. :label="item.label"
  66. :value="item.value"
  67. :type="config.type"
  68. :layout="config.layout"
  69. />
  70. </div>
  71. </template>
  72. <!-- 图表部分,这部分通常需要填充,有告示板、Header等内容需要填充父级 -->
  73. <template v-if="config.name === 'chart'">
  74. <CustomChart v-if="config.pageType == 'New_dust'" class="content__module_dust" :chart-config="config.config" :chart-data="config.data" />
  75. <CustomChart v-else class="content__module" :chart-config="config.config" :chart-data="config.data" />
  76. </template>
  77. <!-- 通常列表部分 -->
  78. <template v-if="config.name === 'list'">
  79. <template v-if="config.type === 'timeline'">
  80. <TimelineList class="content__module" :list-config="config.items" />
  81. </template>
  82. <template v-else-if="config.type === 'timelineNew'">
  83. <TimelineListNew class="content__module" :list-config="config.items" />
  84. </template>
  85. <template v-else>
  86. <CustomList class="content__module" :type="config.type" :list-config="config.items" />
  87. </template>
  88. </template>
  89. <template v-if="config.name === 'fireList'">
  90. <CustomList class="content__module" :type="config.type" :list-config="config.items" />
  91. </template>
  92. <!-- 画廊部分 -->
  93. <template v-if="config.name === 'gallery'">
  94. <CustomGallery class="content__module" :type="config.type" :gallery-config="config.items" />
  95. </template>
  96. <!-- 复杂列表部分 -->
  97. <template v-if="config.name === 'gallery_list'">
  98. <GalleryList class="content__module" :type="config.type" :list-config="config.items" :gallery-config="config.galleryItems" />
  99. </template>
  100. <!-- 复杂列表部分 -->
  101. <template v-if="config.name === 'complex_list'">
  102. <ComplexList class="content__module" :type="config.type" :list-config="config.items" />
  103. </template>
  104. <!-- 表格部分,这部分通常是占一整个模块的 -->
  105. <template v-if="config.name === 'table'">
  106. <CustomTable
  107. class="content__module text-center overflow-auto"
  108. :type="config.type"
  109. :columns="config.columns"
  110. :auto-scroll="config.autoScroll"
  111. :data="config.data"
  112. />
  113. </template>
  114. <template v-if="config.name === 'tabs'">
  115. <CustomTabs class="content__module" :type="config.type" :tab-config="config.items" :overflow="config.overflow" />
  116. </template>
  117. <template v-if="config.name === 'blast_delta'">
  118. <BlastDelta
  119. v-if="config.pageType === 'New_fire'"
  120. class="content__moduleFire"
  121. :pos-monitor="config.data"
  122. :canvasSize="{ width: 250, height: 200 }"
  123. />
  124. <BlastDelta v-else class="content__module" :pos-monitor="config.data" :canvasSize="{ width: 250, height: 200 }" />
  125. </template>
  126. <template v-if="config.name === 'qh_curve'">
  127. <QHCurve class="content__module" :mainfan="config.data" :fan1-prop="config.config.fan1Prop" :fan2-prop="config.config.fan2Prop" />
  128. </template>
  129. <template v-if="config.name === 'ai_chat'">
  130. <AIChat class="content__module" />
  131. </template>
  132. <template v-if="config.name === 'device_alarm'">
  133. <DeviceAlarm class="content__module" :devicedata="config.data" :config="config.config" />
  134. </template>
  135. <!-- lxh -->
  136. <template v-if="config.name === 'select_cs'">
  137. <SelectCs :devicedata="config.data" :config="config.config" />
  138. </template>
  139. <template v-if="config.name === 'measure_detail'">
  140. <MeasureDetail
  141. class="content__module"
  142. :show-title="false"
  143. :composite-data="config.data"
  144. :topconfig="config.config.topconfig"
  145. :btnconfig="config.config.btnconfig"
  146. />
  147. </template>
  148. <template v-if="config.name === 'partition'">
  149. <Partition class="content__module" :type="config.type" :label="config.label" :icon="config.icon" />
  150. </template>
  151. <template v-if="config.name === 'selector_dual_chart'">
  152. <SelectorDualChart :data="config.data" :moduleData="props.moduleData" :config="config" />
  153. </template>
  154. <template v-if="config.name === 'radio_label'">
  155. <RadioLabel class="content__module" :type="config.config.type" :config="config.config" />
  156. </template>
  157. <template v-if="config.name === 'button_list'">
  158. <ButtonList class="content__module" :type="config.config.type" :config="config.config" :buttonList="config.config.buttonList" />
  159. </template>
  160. <template v-if="config.name === 'card_list'">
  161. <cardList class="content__module" :cardData="config.data" />
  162. </template>
  163. <template v-else-if="config.name === 'generalist'">
  164. <generalList class="content__module" :generalData="config.data" />
  165. </template>
  166. <!-- <template v-if="config.key === 'fire_control'">
  167. <FIreControl class="content__module" />
  168. </template>
  169. <template v-if="config.key === 'fire_warn'">
  170. <FIreWarn class="content__module" />
  171. </template> -->
  172. </div>
  173. </div>
  174. </div>
  175. </template>
  176. <script lang="ts" setup>
  177. import { computed } from 'vue';
  178. import {
  179. CommonItem,
  180. Config,
  181. // ModuleDataBoard,
  182. // ModuleDataChart,
  183. // ModuleDataList,
  184. // ModuleDataPreset,
  185. // ModuleDataTable,
  186. } from '../../../deviceManager/configurationTable/types';
  187. import MiniBoard from './detail/MiniBoard.vue';
  188. import TimelineList from './detail/TimelineList.vue';
  189. import TimelineListNew from './detail/TimelineListNew.vue';
  190. import CustomList from './detail/CustomList.vue';
  191. import CustomGallery from './detail/CustomGallery.vue';
  192. import ComplexList from './detail/ComplexList.vue';
  193. import GalleryList from './detail/GalleryList.vue';
  194. import CustomTable from './detail/CustomTable.vue';
  195. import CustomChart from './detail/CustomChart.vue';
  196. import { clone } from 'lodash-es';
  197. import { getData, getFormattedText } from '../hooks/helper';
  198. import BlastDelta from '../../../monitorManager/deviceMonitor/components/device/modal/blastDelta.vue';
  199. import QHCurve from './preset/QHCurve.vue';
  200. import MeasureDetail from './preset/MeasureDetail.vue';
  201. import CustomTabs from './preset/CustomTabs.vue';
  202. import AIChat from '/@/components/AIChat/MiniChat.vue';
  203. import DeviceAlarm from './preset/DeviceAlarm.vue';
  204. import SelectCs from './preset/SelectCs.vue';
  205. import MiniBoardNew from './detail/MiniBoard-New.vue';
  206. import Partition from './preset/partition.vue';
  207. import SelectorDualChart from './preset/selectorDualChart.vue';
  208. import RadioLabel from './preset/radioLabel.vue';
  209. import ButtonList from './preset/buttonList.vue';
  210. import cardList from './preset/cardList.vue';
  211. import generalList from './preset/generalList.vue';
  212. // import FIreWarn from './preset/FIreWarn.vue';
  213. // import FIreControl from './preset/FIreControl.vue';
  214. const props = defineProps<{
  215. data: any;
  216. moduleData: Config['moduleData'];
  217. chartData: any;
  218. }>();
  219. const { background, layout } = props.moduleData;
  220. // 获取当原始配置带 items 项时的最终 items 配置
  221. function getItems(raw, items: CommonItem[]) {
  222. return items.map((i) => {
  223. return {
  224. ...i,
  225. label: getFormattedText(raw, i.label, i.trans),
  226. value: getFormattedText(raw, i.value, i.trans),
  227. };
  228. });
  229. }
  230. // 获取当 List 组件配置带 items 项时的最终 items 配置
  231. function getListItems(raw: any, items: CommonItem[], mapFromData?: boolean) {
  232. if (mapFromData && Array.isArray(raw)) {
  233. return raw.map((data) => {
  234. const item = items[0];
  235. return {
  236. ...item,
  237. label: getFormattedText(data, item.label, item.trans),
  238. value: getFormattedText(data, item.value, item.trans),
  239. };
  240. });
  241. }
  242. return getItems(raw, items);
  243. }
  244. /** 根据配置里的layout将配置格式化为带 key 的具体配置,例如:[{ key: 'list', value: any, ...ModuleDataList }] */
  245. const layoutConfig = computed(() => {
  246. const refData = props.data;
  247. const board = clone(props.moduleData.board) || [];
  248. const list = clone(props.moduleData.list) || [];
  249. const gallery = clone(props.moduleData.gallery) || [];
  250. const complex_list = clone(props.moduleData.complex_list) || [];
  251. const gallery_list = clone(props.moduleData.gallery_list) || [];
  252. const tabs = clone(props.moduleData.tabs) || [];
  253. const chart = clone(props.moduleData.chart) || [];
  254. const table = clone(props.moduleData.table) || [];
  255. const preset = clone(props.moduleData.preset) || [];
  256. const partition = clone(props.moduleData.partition) || [];
  257. const mockData = clone(props.chartData) || [];
  258. return layout.items.reduce((arr: any[], item) => {
  259. switch (item.name) {
  260. case 'board': {
  261. const cfg = board.shift();
  262. if (!cfg) break;
  263. const data = getData(refData, cfg.readFrom, cfg.parser);
  264. arr.push({
  265. overflow: true,
  266. ...item,
  267. ...cfg,
  268. items: getItems(data, cfg.items),
  269. });
  270. break;
  271. }
  272. case 'list': {
  273. const cfg = list.shift();
  274. if (!cfg) break;
  275. const data = getData(refData, cfg.readFrom, cfg.parser);
  276. arr.push({
  277. overflow: true,
  278. ...item,
  279. ...cfg,
  280. items: getListItems(data, cfg.items, cfg.mapFromData),
  281. });
  282. break;
  283. }
  284. case 'gallery': {
  285. const cfg = gallery.shift();
  286. if (!cfg) break;
  287. const data = getData(refData, cfg.readFrom, cfg.parser);
  288. arr.push({
  289. overflow: true,
  290. ...item,
  291. ...cfg,
  292. items: getItems(data, cfg.items),
  293. });
  294. break;
  295. }
  296. case 'complex_list': {
  297. const cfg = complex_list.shift();
  298. if (!cfg) break;
  299. const data = getData(refData, cfg.readFrom, cfg.parser);
  300. if (cfg.mapFromData) {
  301. const firstListItem = cfg.items[0];
  302. arr.push({
  303. overflow: true,
  304. ...item,
  305. ...cfg,
  306. items: (data || []).map((d) => {
  307. return {
  308. title: getFormattedText(d, firstListItem.title, firstListItem.trans),
  309. contents: firstListItem.contents.map((e) => {
  310. return {
  311. ...e,
  312. label: getFormattedText(d, e.label, e.trans),
  313. value: getFormattedText(d, e.value, e.trans),
  314. };
  315. }),
  316. };
  317. }),
  318. });
  319. } else {
  320. arr.push({
  321. overflow: true,
  322. ...item,
  323. ...cfg,
  324. items: cfg.items.map((i) => {
  325. return {
  326. title: getFormattedText(data, i.title, i.trans),
  327. contents: i.contents.map((e) => {
  328. return {
  329. ...e,
  330. label: getFormattedText(data, e.label, e.trans),
  331. value: getFormattedText(data, e.value, e.trans),
  332. };
  333. }),
  334. };
  335. }),
  336. });
  337. }
  338. break;
  339. }
  340. case 'gallery_list': {
  341. const cfg = gallery_list.shift();
  342. if (!cfg) break;
  343. const data = getData(refData, cfg.readFrom, cfg.parser);
  344. arr.push({
  345. overflow: true,
  346. ...item,
  347. ...cfg,
  348. items: getItems(data, cfg.items),
  349. galleryItems: getItems(data, cfg.galleryItems),
  350. });
  351. break;
  352. }
  353. case 'tabs': {
  354. const cfg = tabs.shift();
  355. if (!cfg) break;
  356. const data = getData(refData, cfg.readFrom, cfg.parser);
  357. if (cfg.mapFromData) {
  358. const firstListItem = cfg.items[0];
  359. arr.push({
  360. overflow: true,
  361. ...item,
  362. ...cfg,
  363. items: (data || []).map((d) => {
  364. return {
  365. title: getFormattedText(d, firstListItem.title, firstListItem.trans),
  366. contents: firstListItem.contents.map((e) => {
  367. return {
  368. ...e,
  369. label: getFormattedText(d, e.label, e.trans),
  370. value: getFormattedText(d, e.value, e.trans),
  371. };
  372. }),
  373. };
  374. }),
  375. });
  376. } else {
  377. arr.push({
  378. overflow: true,
  379. ...item,
  380. ...cfg,
  381. items: cfg.items.map((i) => {
  382. return {
  383. title: getFormattedText(data, i.title, i.trans),
  384. contents: i.contents.map((e) => {
  385. return {
  386. ...e,
  387. label: getFormattedText(data, e.label, e.trans),
  388. value: getFormattedText(data, e.value, e.trans),
  389. };
  390. }),
  391. };
  392. }),
  393. });
  394. }
  395. break;
  396. }
  397. case 'chart': {
  398. const cfg = chart.shift();
  399. if (cfg?.type == 'scatter') {
  400. if (!cfg) break;
  401. const data = getData(mockData, cfg.readFrom, cfg.parser);
  402. arr.push({
  403. ...item,
  404. config: cfg,
  405. data,
  406. });
  407. break;
  408. } else {
  409. if (!cfg) break;
  410. const data = getData(refData, cfg.readFrom, cfg.parser);
  411. arr.push({
  412. ...item,
  413. config: cfg,
  414. data,
  415. });
  416. break;
  417. }
  418. }
  419. case 'table': {
  420. const cfg = table.shift();
  421. if (!cfg) break;
  422. const data = getData(refData, cfg.readFrom, cfg.parser);
  423. arr.push({
  424. ...cfg,
  425. ...item,
  426. columns: cfg.columns,
  427. data,
  428. });
  429. break;
  430. }
  431. case 'partition': {
  432. const cfg = partition.shift();
  433. if (!cfg) break;
  434. const data = getData(refData, cfg.readFrom, cfg.parser);
  435. arr.push({
  436. overflow: true,
  437. ...item,
  438. data,
  439. ...cfg,
  440. });
  441. break;
  442. }
  443. default: {
  444. const cfg = preset.shift();
  445. if (!cfg) break;
  446. const data = getData(refData, cfg.readFrom, cfg.parser);
  447. arr.push({
  448. ...item,
  449. data,
  450. config: cfg,
  451. });
  452. break;
  453. }
  454. }
  455. // console.log(arr,'arr---')
  456. return arr;
  457. }, []);
  458. });
  459. </script>
  460. <style lang="less" scoped>
  461. @import '@/design/theme.less';
  462. .content {
  463. height: calc(100% - 30px);
  464. position: relative;
  465. // z-index: -2;
  466. display: flex;
  467. flex-direction: column;
  468. overflow-y: auto; // 这里会导致样式无故添加滚动条
  469. overflow-x: hidden;
  470. }
  471. .content__background {
  472. width: 100%;
  473. // height: 100%;
  474. height: calc(100% - 65px);
  475. position: absolute;
  476. top: 65px;
  477. left: 0;
  478. z-index: 0;
  479. object-fit: fill;
  480. padding: 5px;
  481. box-sizing: border-box;
  482. }
  483. .content__background_1 {
  484. width: 100%;
  485. height: 100%;
  486. position: absolute;
  487. top: 0px;
  488. left: 0;
  489. z-index: 0;
  490. object-fit: fill;
  491. }
  492. .image__background {
  493. width: 35%;
  494. height: 61%;
  495. left: 30%;
  496. }
  497. .content__module {
  498. // margin-top: 5px;
  499. // margin-bottom: 5px;
  500. width: 100%;
  501. height: 100%;
  502. }
  503. .content__module1 {
  504. background: url('@/assets/images/vent/homeNew/databg/4.png');
  505. background-repeat: no-repeat;
  506. background-size: 100% 100%;
  507. height: 129px;
  508. margin-top: 20%;
  509. }
  510. .content__moduleFire {
  511. width: 100%;
  512. height: 100%;
  513. margin-left: -24% !important;
  514. }
  515. .content__module_dust {
  516. background: url('@/assets/images/vent/homeNew/bottomBg.png');
  517. background-repeat: no-repeat;
  518. background-size: 100% 100%;
  519. width: 100%;
  520. height: 100%;
  521. }
  522. // .content__module:first-of-type {
  523. // margin-top: 0;
  524. // }
  525. // .content__module:last-of-type {
  526. // margin-bottom: 0;
  527. // }
  528. ::-webkit-scrollbar {
  529. width: 5px !important;
  530. }
  531. ::-webkit-scrollbar-thumb {
  532. width: 5px !important;
  533. }
  534. :deep(.zxm-select:not(.zxm-select-customize-input) .zxm-select-selector) {
  535. /* background-color: transparent; */
  536. color: #fff;
  537. }
  538. :deep(.zxm-select-arrow) {
  539. color: #fff;
  540. }
  541. :deep(.zxm-select-selection-item) {
  542. color: #fff !important;
  543. }
  544. :deep(.zxm-select-selection-placeholder) {
  545. color: #fff !important;
  546. }
  547. :deep(.dialog-overlay) {
  548. width: 100%;
  549. height: 100%;
  550. position: unset;
  551. box-shadow: unset;
  552. }
  553. ::-webkit-scrollbar {
  554. width: 5px !important;
  555. }
  556. ::-webkit-scrollbar-thumb {
  557. width: 5px !important;
  558. }
  559. </style>