index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <template>
  2. <div class="gis-layout">
  3. <EasyMapComponent
  4. class="map"
  5. @easyMapLoad="mapLoad"
  6. />
  7. <div class="gis-menu">
  8. <img class="gis-menu-bottom" src="@/assets/images/gis-layout/gis-layout-menu_bottom.png" alt=""/>
  9. <template v-for="item in menuCpt">
  10. <div class="gis-menu-item __hover" :class="{active: $route.name === item.name, max: String(item.meta.title).length >5}" @click="$router.push({name: item.name})">
  11. {{item.meta.title}}
  12. </div>
  13. </template>
  14. </div>
  15. <div class="gis-tools">
  16. <div class="gt-search __box-shadow">
  17. <el-autocomplete
  18. ref="ref_search"
  19. v-model="searchInput"
  20. :fetch-suggestions="searchHandleMapSearch"
  21. :popper-append-to-body="false"
  22. clearable
  23. :debounce="800"
  24. placeholder="请输入关键字进行搜索"
  25. @select="searchToMapLocation"
  26. >
  27. <template #default="{ item }">
  28. <div class="search-item __hover">
  29. <img :src="item.icon"/>
  30. <div class="name">{{item.name}}</div>
  31. </div>
  32. </template>
  33. </el-autocomplete>
  34. <div class="search-icon __hover" @click="ref_search.focus()">
  35. <SvgIcon name="search" color="#ffffff"/>
  36. </div>
  37. </div>
  38. <div class="gt-tools __box-shadow">
  39. <template v-for="(item, index) in ToolsMapper">
  40. <div class="tools-line" v-if="index > 0"/>
  41. <div class="tools-item __hover" :class="{active: toolsType === item.value}" @click="toolsHandleClick(item)">
  42. {{item.label}}
  43. </div>
  44. </template>
  45. </div>
  46. <div class="gt-tools-component" v-if="toolsType && toolsType !== 'clear'">
  47. <Component :is="toolsCom" :map="map" :mapFunc="mapFunc"/>
  48. </div>
  49. </div>
  50. <div class="gis-content">
  51. <RouterViewCom/>
  52. </div>
  53. </div>
  54. </template>
  55. <script lang="ts">
  56. import {
  57. defineComponent,
  58. computed,
  59. onMounted,
  60. ref,
  61. reactive,
  62. watch,
  63. getCurrentInstance,
  64. ComponentInternalInstance,
  65. toRefs,
  66. nextTick
  67. } from 'vue'
  68. import {useStore} from 'vuex'
  69. import {useRouter, useRoute} from 'vue-router'
  70. import {ElMessage, ElMessageBox} from "element-plus";
  71. import RouterViewCom from '@/layout/router-view.vue'
  72. import ElementCom from './tools/element.vue'
  73. import SelectCom from './tools/select.vue'
  74. import AnalysisCom from './tools/analysis.vue'
  75. import ToolCom from './tools/tool.vue'
  76. import PositionCom from './tools/position.vue'
  77. import BaseCom from './tools/base.vue'
  78. import ExampleCom from './tools/example.vue'
  79. export default defineComponent({
  80. name: '',
  81. components: {
  82. RouterViewCom,
  83. ElementCom,
  84. SelectCom,
  85. AnalysisCom,
  86. ToolCom,
  87. PositionCom,
  88. BaseCom,
  89. ExampleCom,
  90. },
  91. props: {},
  92. setup(props, {emit}) {
  93. const store = useStore();
  94. const router = useRouter();
  95. const route = useRoute();
  96. const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
  97. const state = reactive({
  98. map: <any>null,
  99. mapFunc: <any>null,
  100. searchInput: '',
  101. toolsType: '',
  102. toolsCom: null,
  103. toolsParams: {
  104. }
  105. })
  106. const ToolsMapper = [
  107. {label: '图层', value: 'element', com: ElementCom},
  108. {label: '框选', value: 'select', com: SelectCom},
  109. {label: '周边分析', value: 'analysis', com: AnalysisCom},
  110. {label: '清空图层', value: 'clear', com: undefined},
  111. {label: '工具', value: 'tool', com: ToolCom},
  112. {label: '定位', value: 'position', com: PositionCom},
  113. {label: '底图', value: 'base', com: BaseCom},
  114. {label: '图例', value: 'example', com: ExampleCom},
  115. ]
  116. const ref_search = ref()
  117. const mapLoad = (map, func) => {
  118. state.map = map
  119. state.mapFunc = func
  120. }
  121. const menuCpt = computed(() => {
  122. return router.options.routes.filter(v => v.name === store.state.gis.menuRootName)[0].children
  123. })
  124. const searchHandleMapSearch = (queryString: string, cb: (arg: any) => void) => {
  125. if (queryString.trim()) {
  126. const arr = [
  127. {name: 123},
  128. {name: 123},
  129. {name: 123},
  130. {name: 123},
  131. {name: 123},
  132. {name: 123},
  133. ]
  134. // if (state.showBayonet) {
  135. // state.searchAllList.bayonet.forEach(v => {
  136. // if (v.name?.includes(queryString)) {
  137. // arr.push(v)
  138. // }
  139. // })
  140. // }
  141. // if (state.showVideo) {
  142. // state.searchAllList.video.forEach(v => {
  143. // if (v.name?.includes(queryString)) {
  144. // arr.push(v)
  145. // }
  146. // })
  147. // }
  148. // if (state.showElement) {
  149. // state.searchAllList.element.forEach(v => {
  150. // if (v.name?.includes(queryString)) {
  151. // arr.push(v)
  152. // }
  153. // })
  154. // }
  155. cb(arr)
  156. } else {
  157. cb([])
  158. }
  159. }
  160. const searchToMapLocation = (val) => {
  161. state.searchInput = val.name
  162. // if (val.source === 'element') {
  163. // state.elementFilter.forEach(l => {
  164. // l.list.forEach(v => {
  165. // if (v.value === val.elementType) {
  166. // v.active = true
  167. // }
  168. // })
  169. // })
  170. // }
  171. // positionSwitchGeom(val.geomType, val.coordinates, true, val.source)
  172. }
  173. const toolsHandleClick = (item) => {
  174. if (item.value === 'clear') {
  175. } else {
  176. state.toolsCom = item.com
  177. state.toolsType = (state.toolsType === item.value ? '' : item.value)
  178. }
  179. }
  180. onMounted(() => {
  181. })
  182. return {
  183. ...toRefs(state),
  184. mapLoad,
  185. ToolsMapper,
  186. ref_search,
  187. menuCpt,
  188. searchHandleMapSearch,
  189. searchToMapLocation,
  190. toolsHandleClick,
  191. }
  192. },
  193. })
  194. </script>
  195. <style scoped lang="scss">
  196. .gis-layout {
  197. width: 100%;
  198. height: 100vh;
  199. position: absolute;
  200. top: 0;
  201. left: 0;
  202. z-index: 2;
  203. display: flex;
  204. align-items: center;
  205. justify-content: center;
  206. .map {
  207. z-index: 1;
  208. }
  209. .gis-menu {
  210. $diff: 14px;
  211. $menuBottom: 16px;
  212. position: absolute;
  213. z-index: 2;
  214. bottom: $menuBottom;
  215. display: flex;
  216. justify-content: center;
  217. align-items: center;
  218. &:before, &:after {
  219. content: '';
  220. background-image: url("@/assets/images/gis-layout/gis-layout-menu_side.png");
  221. width: 246px;
  222. height: 39px;
  223. position: absolute;
  224. bottom: -$menuBottom;
  225. }
  226. &:before {
  227. left: calc((#{$diff} + 246px) * -1);
  228. }
  229. &:after {
  230. right: calc((#{$diff} + 246px) * -1);
  231. transform: rotateY(180deg);
  232. }
  233. .gis-menu-bottom {
  234. position: absolute;
  235. height: 9px;
  236. width: calc(100% + 10px + #{$diff} * 2);
  237. bottom: -$menuBottom;
  238. }
  239. .gis-menu-item {
  240. width: 95px;
  241. height: 36px;
  242. background-image: url("@/assets/images/gis-layout/gis-layout-menu_item-min.png");
  243. background-size: 100% 100%;
  244. background-repeat: no-repeat;
  245. display: flex;
  246. align-items: center;
  247. justify-content: center;
  248. font-size: 18px;
  249. font-family: YouSheBiaoTiHei;
  250. font-weight: 400;
  251. color: #60AEFF;
  252. &:not(&:last-child) {
  253. margin-right: 4px;
  254. }
  255. &.active {
  256. color: #FFFFFF;
  257. background-image: url("@/assets/images/gis-layout/gis-layout-menu_item-min_active.png");
  258. }
  259. &.max {
  260. width: 125px;
  261. background-image: url("@/assets/images/gis-layout/gis-layout-menu_item-max.png");
  262. &.active {
  263. background-image: url("@/assets/images/gis-layout/gis-layout-menu_item-max_active.png");
  264. }
  265. }
  266. }
  267. }
  268. .gis-tools {
  269. position: absolute;
  270. z-index: 3;
  271. top: 10px;
  272. right: 10px;
  273. width: 404px;
  274. >div {
  275. box-sizing: border-box;
  276. }
  277. .gt-search {
  278. height: 38px;
  279. width: 100%;
  280. display: flex;
  281. align-items: center;
  282. .search-icon {
  283. width: 54px;
  284. height: 100%;
  285. background-color: #3e8ef7;
  286. display: flex;
  287. align-items: center;
  288. justify-content: center;
  289. }
  290. :deep(.el-autocomplete) {
  291. flex: 1;
  292. height: 100%;
  293. .el-input {
  294. width: 100%;
  295. height: 100%;
  296. .el-input__wrapper {
  297. border-radius: 0;
  298. }
  299. }
  300. }
  301. :deep(.el-autocomplete__popper) {
  302. opacity: 0.9;
  303. background-image: linear-gradient(45deg,transparent 10px,#101D69 10px), linear-gradient(-135deg,transparent 10px,#101D69 10px);
  304. border: none;
  305. .el-popper__arrow::before {
  306. background: #101D69;
  307. border-color: #101D69;
  308. }
  309. .el-autocomplete-suggestion {
  310. .el-scrollbar {
  311. .el-autocomplete-suggestion__wrap {
  312. .el-scrollbar__view {
  313. >li {
  314. &:hover {
  315. background-color: rgba(59,84,172,0.5);
  316. }
  317. .search-item {
  318. display: flex;
  319. align-items: center;
  320. justify-content: flex-start;
  321. >img {
  322. margin-right: 6px;
  323. width: 16px;
  324. height: 16px;
  325. }
  326. .name {
  327. color: #ffffff;
  328. }
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. }
  336. }
  337. .gt-tools {
  338. width: 100%;
  339. height: 38px;
  340. margin-top: 2px;
  341. background-color: #FFFFFF;
  342. border: 1px solid #C7CFDE;
  343. display: flex;
  344. align-items: center;
  345. justify-content: space-around;
  346. padding: 0 8px;
  347. .tools-item {
  348. font-size: 14px;
  349. font-family: Microsoft YaHei;
  350. font-weight: 400;
  351. color: #AEAEAE;
  352. &.active {
  353. color: #1174DB;
  354. font-weight: bold;
  355. }
  356. }
  357. .tools-line {
  358. width: 1px;
  359. height: 16px;
  360. background: linear-gradient(0deg, rgba(174,174,174,0) 0%, rgba(213,213,213,0.99) 50%, rgba(174,174,174,0) 100%);
  361. }
  362. }
  363. .gt-tools-component {
  364. width: 100%;
  365. margin-top: 2px;
  366. }
  367. }
  368. .gis-content {
  369. position: absolute;
  370. z-index: 4;
  371. top: 0;
  372. left: 0;
  373. }
  374. }
  375. </style>