index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <template>
  2. <div class="biz-display-container">
  3. <div v-if="headerShow" class="biz-display-header">
  4. <slot name="header">
  5. {{ title }}
  6. </slot>
  7. </div>
  8. <div class="biz-display-body" :style="{ height: bodyHeight }">
  9. <template v-if="displayType === 'chart'">
  10. <gw-chart :option="data"></gw-chart>
  11. </template>
  12. <template v-if="displayType === 'list'">
  13. <el-table :data="data" height="100%" stripe
  14. @row-click="handleRowClick">
  15. <el-table-column v-for="column in columns" :key="column.key" :label="column.value"
  16. :prop="column.key">
  17. <template #default="scope">
  18. {{ getValueByKey(scope.row, column.key) }}
  19. </template>
  20. </el-table-column>
  21. </el-table>
  22. </template>
  23. <template v-if="displayType === 'table'">
  24. <gw-table-two :columnNumber="columnNumber" :data="data"></gw-table-two>
  25. </template>
  26. <template v-if="displayType === 'text'">
  27. <span v-html="data"></span>
  28. </template>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup>
  33. import GwChart from "@/components/chart/GwEchart.vue";
  34. import {getChartOption, getFormListData, getTableData, getText} from '@/utils/biz'
  35. import GwTableTwo from "./GwTableTwo.vue";
  36. import bus from '@/utils/bus'
  37. import {filterData} from "@/utils/data.js";
  38. import {isDate, isNumber} from "@/utils/validate.js";
  39. import {parseTime} from "@/utils/ruoyi.js";
  40. defineExpose({
  41. loadData
  42. })
  43. const slots = useSlots();
  44. const props = defineProps({
  45. config: {
  46. type: Object,
  47. },
  48. showTitle: {
  49. type: Boolean,
  50. default: true
  51. },
  52. });
  53. const headerShow = computed(() => (!!title.value || slots.header) && props.showTitle)
  54. const bodyHeight = computed(() => {
  55. if (headerShow.value) {
  56. return 'calc(100% - 1rem - 20px)'
  57. } else {
  58. return '100%'
  59. }
  60. })
  61. const data = ref(null)
  62. const title = ref(null)
  63. const displayType = ref(null)
  64. const columnNumber = ref(1)
  65. const columns = ref([])
  66. const clickConfig = ref(null)
  67. function loadData(config) {
  68. if (!config) {
  69. return
  70. }
  71. config.value = config
  72. displayType.value = config.type
  73. title.value = config.name
  74. // 解析点击配置
  75. const renderingOptions = JSON.parse(config.renderingOptions || '{}')
  76. clickConfig.value = renderingOptions.clickAction || {type: 'none'}
  77. switch (config.type) {
  78. case 'chart':
  79. nextTick(() => {
  80. getChartOption(config).then(r => data.value = r);
  81. })
  82. return;
  83. case 'list':
  84. columns.value = renderingOptions.columns
  85. debugger
  86. return getTableData(config).then(r => data.value = r);
  87. case 'table':
  88. columnNumber.value = renderingOptions.columnNumber
  89. return getFormListData(config).then(r => data.value = r);
  90. case 'text':
  91. return getText(config).then(r => data.value = r);
  92. }
  93. }
  94. // 处理行点击事件
  95. function handleRowClick(row, column, event) {
  96. if (!clickConfig.value || clickConfig.value.type === 'none') {
  97. return
  98. }
  99. if (clickConfig.value.type === 'map') {
  100. const latitude = row[clickConfig.value.latitudeField]
  101. const longitude = row[clickConfig.value.longitudeField]
  102. if (latitude && longitude) {
  103. // 跳转到地图页面,传递经纬度参数
  104. bus.emit('show-map-position', {latitude, longitude, highlight: true})
  105. }
  106. }
  107. }
  108. function getValueByKey(obj, key) {
  109. let value = filterData(obj, key);
  110. if (isNumber(value)) {
  111. value = value.toFixed(2)
  112. } else if (isDate(value)) {
  113. value = parseTime(new Date(value), '{m}-{d} {h}')
  114. }
  115. return value
  116. }
  117. watch(() => props.config, (config) => {
  118. if (config) {
  119. loadData(config)
  120. }
  121. }, {immediate: true})
  122. </script>
  123. <style lang="scss" scoped>
  124. .biz-display-container {
  125. width: 100%;
  126. height: 100%;
  127. .biz-display-header {
  128. display: flex;
  129. justify-content: center;
  130. align-items: center;
  131. font-size: 1rem;
  132. text-align: center;
  133. padding: 10px 0;
  134. }
  135. .biz-display-body {
  136. height: calc(100% - 1rem - 20px);
  137. }
  138. }
  139. </style>