SpatialAnalysis.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <template>
  2. <div class="menu-content">
  3. <div class="gradient-text common-dialog-title2">空间分析</div>
  4. <div class="analyze-data-container">
  5. <div class="item" @click="handleShowDetail">
  6. <div class="item-label">行政镇(个)</div>
  7. <div class="item-value">{{ validateNum(analysisData.townCount) }}</div>
  8. </div>
  9. <div class="item" @click="handleShowDetail">
  10. <div class="item-label">行政村(个)</div>
  11. <div class="item-value">{{ validateNum(analysisData.villageCount) }}</div>
  12. </div>
  13. <div class="item" @click="handleShowDetail">
  14. <div class="item-label">面积(km²)</div>
  15. <div class="item-value">{{ validateNum(analysisData.areaSize) }}</div>
  16. </div>
  17. <div class="item" @click="handleShowDetail">
  18. <div class="item-label">常住人口(万)</div>
  19. <div class="item-value">{{ validateNum(analysisData.populationSize) }}</div>
  20. </div>
  21. <div class="item" @click="handleShowDetail">
  22. <div class="item-label">GDP(万元)</div>
  23. <div class="item-value">{{ validateNum(analysisData.GDP) }}</div>
  24. </div>
  25. <div class="flex" style="margin: 15px 0 10px; width: 100%">
  26. <el-input v-model="keyword" class="custom-input2" placeholder="请输入" size="large" style="flex: 1" />
  27. </div>
  28. <div class="flex" style="flex-wrap: wrap">
  29. <div v-for="(item, index) in filteredList" :key="index" class="item2">{{ item.name + '(' + item.list.length + ')' }}</div>
  30. </div>
  31. </div>
  32. <Dialog v-model="showDetail" title="空间分析" height="760px" hide-footer>
  33. <div class="common-table">
  34. <div class="table-header">
  35. <div class="td">序号</div>
  36. <div class="td">行政镇</div>
  37. <div class="td">行政村</div>
  38. <div class="td">常住人口(万)</div>
  39. <div class="td">面积(km2)</div>
  40. <div class="td">GDP(亿元)</div>
  41. </div>
  42. <div v-for="(item, index) in analysisData.townData" :key="index" class="tr">
  43. <div class="td">{{ index + 1 }}</div>
  44. <div class="td">{{ item.townName }}</div>
  45. <div class="td">{{ item.villageName ? item.villageName : '-' }}</div>
  46. <div class="td">{{ item.populationSize }}</div>
  47. <div class="td">{{ item.areaSize }}</div>
  48. <div class="td">{{ item.GDP }}</div>
  49. </div>
  50. </div>
  51. </Dialog>
  52. </div>
  53. </template>
  54. <script lang="ts" setup name="AnalyzeDataDialog">
  55. import { validateNum } from '@/utils/ruoyi';
  56. import { getSpatialAnalysis } from '@/api/globalMap';
  57. import { deepClone } from '@/utils';
  58. const props = defineProps({
  59. updateLocation: []
  60. });
  61. const emits = defineEmits(['handleMenu']);
  62. const keyword = ref('');
  63. let analysisData = ref({
  64. townCount: '',
  65. villageCount: '',
  66. areaSize: '',
  67. populationSize: '',
  68. GDP: '',
  69. list: []
  70. });
  71. const filteredList = computed(() => {
  72. const data = deepClone(analysisData.value.list);
  73. return data.filter((item) => {
  74. if (!!keyword.value) {
  75. // 模糊搜索逻辑,这里简单使用 includes 进行包含关系判断
  76. let flag = item.name.toLowerCase().includes(keyword.value.toLowerCase());
  77. if (flag) {
  78. return true;
  79. } else {
  80. let res = filteredSubItems(item);
  81. if (res && res.length > 0) {
  82. item.list = res;
  83. return true;
  84. } else {
  85. return false;
  86. }
  87. }
  88. } else {
  89. return true;
  90. }
  91. });
  92. });
  93. const filteredSubItems = (parentItem) => {
  94. return parentItem.list.filter((subItem) => {
  95. return subItem.name.toLowerCase().includes(keyword.value.toLowerCase());
  96. });
  97. };
  98. const location = ref([]);
  99. watch(
  100. () => props.updateLocation,
  101. () => {
  102. location.value = props.updateLocation;
  103. },
  104. {
  105. immediate: true,
  106. deep: true
  107. }
  108. );
  109. watch(
  110. () => location,
  111. () => {
  112. getSpatialAnalysis(location.value).then((res) => {
  113. if (res.data && res.data.list) {
  114. const list = [];
  115. res.data.list.forEach((item) => {
  116. if (item.num > 0) {
  117. list.push(item);
  118. }
  119. });
  120. res.data.list = list;
  121. }
  122. if (res.data && res.data.townData) {
  123. const data = [];
  124. res.data.townData.forEach((item) => {
  125. data.push(item);
  126. item.children.forEach((item2) => {
  127. const obj = deepClone(item2);
  128. obj.townName = item.townName;
  129. data.push(obj);
  130. });
  131. delete item.children;
  132. });
  133. res.data.townData = data;
  134. }
  135. analysisData.value = res.data;
  136. });
  137. },
  138. {
  139. immediate: true,
  140. deep: true
  141. }
  142. );
  143. let showDetail = ref(false);
  144. const handleShowDetail = () => {
  145. showDetail.value = true;
  146. };
  147. </script>
  148. <style lang="scss" scoped>
  149. .menu-content {
  150. width: 574px;
  151. height: 581px;
  152. background: url('@/assets/images/map/rightMenu/content.png') no-repeat;
  153. background-size: 100% 100%;
  154. padding: 60px 10px 10px 15px;
  155. font-size: 14px;
  156. position: relative;
  157. color: #ffffff;
  158. }
  159. .analyze-data-container {
  160. width: 100%;
  161. font-size: 16px;
  162. padding: 10px 0;
  163. display: flex;
  164. flex-wrap: wrap;
  165. .item {
  166. width: 130px;
  167. height: 60px;
  168. background: url('@/assets/images/map/rightMenu/ironTower/boxBg.png') no-repeat;
  169. background-size: 100% 100%;
  170. color: #fff;
  171. display: flex;
  172. flex-direction: column;
  173. justify-content: center;
  174. align-items: center;
  175. font-size: 14px;
  176. margin-right: 9px;
  177. cursor: pointer;
  178. &:nth-child(4) {
  179. margin-right: 0;
  180. }
  181. &:nth-child(5) {
  182. margin-top: 10px;
  183. }
  184. .item-label {
  185. margin-bottom: 5px;
  186. }
  187. }
  188. }
  189. .item2 {
  190. background-color: #0b184b;
  191. font-size: 14px;
  192. padding: 5px 10px;
  193. margin-right: 10px;
  194. color: #ffffff;
  195. border: 2px solid #247dff;
  196. border-radius: 4px;
  197. margin-top: 5px;
  198. }
  199. </style>