App.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <template>
  2. <!-- <div>地图页面</div> -->
  3. <div class="tabbar">
  4. <div class="nav">
  5. <el-button-group class="ml-4">
  6. <el-button
  7. :type="currentType(0) ? 'primary' : 'default'"
  8. @click="handleSelect(0)"
  9. >地图</el-button
  10. >
  11. <el-button
  12. :type="currentType(1) ? 'primary' : 'default'"
  13. @click="handleSelect(1)"
  14. >卡片</el-button
  15. >
  16. </el-button-group>
  17. </div>
  18. <el-form-item label="所属架构:" class="filter">
  19. <com-company v-model="state.deptId" :id="state.caseId" hideAll />
  20. </el-form-item>
  21. </div>
  22. <div ref="mapEl" class="map-container" v-show="currentType(0)"></div>
  23. <div class="card-container" v-show="currentType(1)">
  24. <div class="card-list">
  25. <template v-for="item of list" v-if="list.length > 0">
  26. <el-card
  27. style="width: 480px"
  28. shadow="hover"
  29. @click="handCardClick(item.caseId)"
  30. >
  31. <img
  32. class="cover"
  33. :src="
  34. item.cover
  35. ? item.cover
  36. : 'https://test-mix3d.4dkankan.com/code/assets/pic.d5781b0c.jpg'
  37. "
  38. style="width: 100%"
  39. />
  40. <div class="card">
  41. <span> 项目: {{ item.projectName }}</span>
  42. <span> 地址: {{ item.projectAddress }}</span>
  43. <span> 类别: {{ item.projectSite }}</span>
  44. </div>
  45. </el-card>
  46. </template>
  47. <template v-else>
  48. <div class="no-data">
  49. <img :src="emptyBG" />
  50. <span>暂无数据</span>
  51. </div>
  52. </template>
  53. </div>
  54. </div>
  55. </template>
  56. <script setup lang="ts">
  57. import { onMounted, ref, computed, onBeforeMount } from "vue";
  58. // import { useRouteQuery } from "@vueuse/router";
  59. import AMapLoader from "@amap/amap-jsapi-loader";
  60. import axios from "axios";
  61. import { getFuseCodeLink } from "../../view/case/help";
  62. import comCompany from "./company-select/index.vue";
  63. import { reactive } from "vue";
  64. import { watch } from "vue";
  65. import { ElLoading } from "element-plus";
  66. import linkIco from "@/assets/image/fire.ico";
  67. import { useUrlSearchParams } from "@vueuse/core";
  68. import emptyBG from "@/assets/image/empty__empty.png";
  69. const params = useUrlSearchParams("history");
  70. console.log("params", params.deptId);
  71. const current = ref(0);
  72. const list = ref<any>([]);
  73. const state = reactive({
  74. deptId: params.deptId || "",
  75. // caseId: params.caseId || "",
  76. });
  77. const link = document.querySelector<HTMLLinkElement>("#app-icon")!;
  78. link.setAttribute("href", linkIco);
  79. document.title = "案件显示";
  80. const currentType = computed(() => (type: number) => current.value === type);
  81. const handleSelect = (type: number) => {
  82. current.value = type;
  83. };
  84. const markers = ref<any>([]);
  85. const getQuery = (
  86. caseId: number,
  87. share: boolean = false,
  88. single: boolean = false
  89. ) =>
  90. `${getFuseCodeLink(caseId, true)}${share ? "&share=1" : ""}${
  91. single ? "&single=1" : ""
  92. }#show/summary`;
  93. const request = axios.create({
  94. baseURL: "",
  95. timeout: 1000,
  96. headers: {
  97. share: 1,
  98. "Content-Type": "application/json",
  99. },
  100. });
  101. const mapEl = ref<HTMLDivElement>();
  102. let AMap, map;
  103. const queryURL = `${import.meta.env.VITE_SEVER_URL}/fusion-xj/web/fireProject/queryProject`
  104. // debugger;
  105. const getDataQuest = () => {
  106. return new Promise(async (reslove, reject) => {
  107. const res = await request.post(
  108. queryURL,
  109. {
  110. pageNum: 1,
  111. pageSize: 10000,
  112. deptId: state.deptId,
  113. }
  114. );
  115. console.log("res.data", res);
  116. if (res.status === 200 && res.data.code === 0) {
  117. reslove(res.data.data.list);
  118. } else {
  119. reslove([]);
  120. }
  121. });
  122. };
  123. const refresh = async () => {
  124. const loading = ElLoading.service({
  125. lock: true,
  126. text: "Loading",
  127. background: "rgba(0, 0, 0, 0.7)",
  128. });
  129. map.remove(markers.value);
  130. markers.value = [];
  131. initMakers();
  132. loading.close();
  133. };
  134. watch(
  135. () => state.deptId,
  136. () => {
  137. refresh();
  138. },
  139. {
  140. immediate: false,
  141. deep: true,
  142. }
  143. );
  144. const initMakers = async () => {
  145. const data = (await getDataQuest()) as any as any[];
  146. console.log("data", data);
  147. const positions: any[] = [];
  148. list.value = data as any[];
  149. Array.from(data).forEach((item: any) => {
  150. // console.log(item)
  151. const latlng = item.latlng;
  152. const coord = latlng.split(",");
  153. console.log("coord", coord, item.caseId);
  154. const url = getQuery(item.caseId, true);
  155. console.log("url", url);
  156. const icon = new AMap.Icon({
  157. image:
  158. "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
  159. size: new AMap.Size(22, 28), //图标所处区域大小
  160. imageSize: new AMap.Size(22, 28), //图标大小
  161. });
  162. const pos = coord.reverse();
  163. positions.push(pos);
  164. const marker = new AMap.Marker({
  165. icon: icon,
  166. position: pos,
  167. title: item.title,
  168. label: item.title,
  169. extData: { url: url, id: item.caseId },
  170. // offset: new AMap.Pixel(-26, -54),
  171. });
  172. markers.value.push(marker);
  173. marker.setMap(map);
  174. marker.on("click", () => {
  175. const data = marker.getExtData();
  176. window.open(data.url);
  177. console.log("click", data);
  178. });
  179. });
  180. var polygon = new AMap.Polygon({
  181. path: positions,
  182. map: map,
  183. strokeOpacity: 0, //透明
  184. fillOpacity: 0, //透明
  185. bubble: true, //事件穿透到地图
  186. });
  187. var overlaysList = map.getAllOverlays("polygon"); //获取多边形图层
  188. map.setFitView(); //自适应显示
  189. };
  190. const loadMap = async () => {
  191. AMap = await AMapLoader.load({
  192. plugins: ["AMap.PlaceSearch"],
  193. key: "e661b00bdf2c44cccf71ef6070ef41b8",
  194. version: "2.0",
  195. });
  196. map = new AMap.Map(mapEl.value, {
  197. WebGLParams: {
  198. preserveDrawingBuffer: true,
  199. },
  200. resizeEnable: true,
  201. });
  202. //添加插件
  203. AMap.plugin(
  204. ["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.MapType"],
  205. function () {
  206. //异步同时加载多个插件
  207. // map.addControl(new AMap.HawkEye()); //显示缩略图
  208. map.addControl(new AMap.Scale()); //显示当前地图中心的比例尺
  209. map.addControl(new AMap.MapType()); //显示当前地图中心的比例尺
  210. }
  211. );
  212. console.log("map", map);
  213. initMakers();
  214. };
  215. onMounted(() => {
  216. // console.log("caseId", caseId);
  217. loadMap();
  218. });
  219. const handCardClick = (id: number) => {
  220. const url = getQuery(id, true);
  221. console.log("url", url);
  222. window.open(url);
  223. };
  224. </script>
  225. <style>
  226. body {
  227. padding: 0;
  228. margin: 0;
  229. }
  230. .map-container {
  231. width: 100%;
  232. height: 100vh;
  233. }
  234. .tabbar {
  235. display: flex;
  236. width: 100%;
  237. position: fixed;
  238. top: 30px;
  239. z-index: 10000;
  240. justify-items: center;
  241. justify-content: center;
  242. }
  243. .tabbar .nav {
  244. display: flex;
  245. /* background: white; */
  246. justify-content: center;
  247. align-items: center;
  248. }
  249. .el-form-item {
  250. margin-bottom: 0px !important;
  251. }
  252. .tabbar .nav .nav_item {
  253. padding: 10px;
  254. cursor: pointer;
  255. }
  256. .card-container {
  257. width: 100%;
  258. padding-top: 100px;
  259. }
  260. .card-list {
  261. margin: 0 auto;
  262. display: flex;
  263. gap: 50px 25px;
  264. width: 90%;
  265. flex-direction: row;
  266. flex-wrap: wrap;
  267. justify-content: center;
  268. }
  269. .cover {
  270. cursor: pointer;
  271. max-height: 220px;
  272. object-fit: cover;
  273. }
  274. .card {
  275. display: flex;
  276. flex-direction: column;
  277. cursor: pointer;
  278. gap: 10px;
  279. }
  280. .filter {
  281. margin: 0;
  282. margin-left: 20px;
  283. }
  284. .amap-ctrl-list-layer {
  285. z-index: 100000;
  286. }
  287. .no-data {
  288. width: 100%;
  289. height: 100%;
  290. /* background: red; */
  291. min-height: 530px;
  292. display: flex;
  293. justify-content: center;
  294. align-items: center;
  295. flex-direction: column;
  296. }
  297. .no-data span {
  298. color: #999;
  299. }
  300. </style>