IndexView.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <div class="home">
  3. <Header v-if="loginType != 'AUTO'"></Header>
  4. <Map ref="childRef"/>
  5. <DrawMap></DrawMap>
  6. <div :class="loginType == 'AUTO' ? 'search-box-auto': 'search-box'">
  7. <div class="search-input">
  8. <el-autocomplete
  9. v-model="searchText"
  10. popper-class="home-custom-dropdown"
  11. :popper-append-to-body="false"
  12. :fetch-suggestions="querySearchAsync"
  13. :placeholder="selectType == '0' ? '请输入地址' : '请输入员工'"
  14. clearable :clear-icon="CloseBold"
  15. @select="handleSelect"
  16. :fit-input-width="false"
  17. show-overflow-tooltip
  18. >
  19. <template #append>
  20. <el-select v-model="selectType" placeholder="请选择搜索类型" style="width: 80px">
  21. <el-option label="地址" value="0" />
  22. <el-option label="员工" value="1" />
  23. </el-select>
  24. </template>
  25. <!-- 自定义下拉选项插槽 #default -->
  26. <template #default="{ item }">
  27. <el-tooltip
  28. :content="item.value"
  29. placement="right"
  30. effect="dark"
  31. :disabled="!isOverflow"
  32. >
  33. <div class="text-ellipsis" @mouseenter="handleMouseEnter($event)">
  34. {{ item.value }}
  35. </div>
  36. </el-tooltip>
  37. </template>
  38. </el-autocomplete>
  39. </div>
  40. </div>
  41. <div class="map-box">
  42. <div class="map-group">
  43. <div :class="{'map-item':true,'active':baseMap=='zwb'}" @click="selectMap('zwb')">
  44. <div style="height: 52px;"><img src="../../public/static/image/zwb.png" class="map-img" mode="scaleToFill" /></div>
  45. <div class="map-img-name">浅色地图</div>
  46. </div>
  47. <div :class="{'map-item':true,'active':baseMap=='asb'}" @click="selectMap('asb')">
  48. <div style="height: 52px;"><img src="../../public/static/image/asb.png" class="map-img" mode="scaleToFill" /></div>
  49. <div class="map-img-name">深色地图</div>
  50. </div>
  51. <div :class="{'map-item':true,'active':baseMap=='yxt'}" @click="selectMap('yxt')">
  52. <div style="height: 52px;"><img src="../../public/static/image/yxt.png" class="map-img" mode="scaleToFill" /></div>
  53. <div class="map-img-name">影像地图</div>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </template>
  59. <script>
  60. import mapCommonApi from "@/api/mapCommon";
  61. import commonAPI from "@/api/common";
  62. import Map from "@/components/Map.vue";
  63. import Header from "@/components/Header.vue";
  64. import DrawMap from "@/components/DrawMap.vue";
  65. export default {
  66. name: "IndexView",
  67. components: {
  68. Map,
  69. Header,
  70. DrawMap
  71. },
  72. data() {
  73. return {
  74. baseMap:'zwb',
  75. searchText: '',
  76. timeout: null,
  77. selectType:'0',
  78. ygDataList:[],
  79. loginType: sessionStorage.getItem("gisLoginType") || '',
  80. isOverflow: false,
  81. };
  82. },
  83. mounted() {
  84. this.initData();
  85. },
  86. beforeDestroy() {
  87. // 在组件销毁前移除事件监听器
  88. },
  89. methods: {
  90. initData(){
  91. this.getDmsDataList();
  92. },
  93. handleMouseEnter(e) {
  94. const dom = e.target
  95. // 判断内容是否溢出:scrollWidth > clientWidth
  96. this.isOverflow = dom.scrollWidth > dom.clientWidth
  97. },
  98. getDmsDataList(){
  99. const that = this;
  100. let requestParams = {
  101. columnId: webConfig.columnArr[0].id,
  102. states: "0,1,2,3",
  103. orderBy: JSON.stringify([{ field: "c_xm", orderByType: 2 }]),
  104. pageSize: 99999,
  105. page: 0,
  106. };
  107. commonAPI.getDmsDataList(requestParams).then((res) => {
  108. if (res.code == 200){
  109. let data = res.content.data;
  110. data = data.map(item => {
  111. // 给每个属性名称添加 c_ 前缀
  112. const newItem = {};
  113. for (const key in item) {
  114. // 如果已经有c_
  115. if (key.includes("c_")) {
  116. let itemkey = key.replace(/c_/g, "");
  117. newItem['c_' + itemkey] = item[key];
  118. }else{
  119. newItem[key] = item[key];
  120. }
  121. }
  122. return newItem;
  123. })
  124. that.ygDataList = data;
  125. }else{
  126. // that.$message({ message: '无员工数据', type: 'info' })
  127. }
  128. });
  129. },
  130. selectMap(map){
  131. this.baseMap = map;
  132. if(map == 'zwb'){
  133. //切换底图后重新绑定
  134. window.mapboxMap.on('style.load', this.$refs.childRef.initBaseMap("zwb"));
  135. }else if(map == 'asb'){
  136. //切换底图后重新绑定
  137. window.mapboxMap.on('style.load', this.$refs.childRef.initBaseMap("asb"));
  138. }else if(map == 'yxt'){
  139. //切换底图后重新绑定
  140. window.mapboxMap.on('style.load', this.$refs.childRef.initBaseMap("yxt"));
  141. }
  142. },
  143. querySearchAsync(queryString, cb) {
  144. let that = this;
  145. if(queryString == ''){
  146. if(window.mapboxMap.getSource('point-source')){
  147. let jsondata = {type: "FeatureCollection",features: []};
  148. window.mapboxMap.getSource('point-source').setData(jsondata);
  149. }
  150. clearTimeout(that.timeout);
  151. that.timeout = setTimeout(() => {
  152. cb([]);
  153. }, 0);
  154. }else{
  155. if(that.selectType == "0"){
  156. that.querySearchAddr(queryString,cb);
  157. }else{
  158. that.queryTableData(queryString,cb);
  159. }
  160. }
  161. },
  162. queryTableData(text,cb){
  163. const that = this;
  164. let results = [];
  165. that.ygDataList.filter(item => {
  166. if(item.c_xm.includes(text)){
  167. item.value = item.c_xm;
  168. results.push(item);
  169. }
  170. })
  171. cb(results);
  172. },
  173. querySearchAddr(text,cb){
  174. let that = this;
  175. mapCommonApi.getSerachAddress3({
  176. "address": text
  177. }).then((res) => {
  178. let results = res.content.data;
  179. results.forEach(item => {
  180. item.value = item.address;
  181. })
  182. clearTimeout(that.timeout);
  183. that.timeout = setTimeout(() => {
  184. cb(results);
  185. }, 1000 * Math.random());
  186. }).catch((err) => {
  187. clearTimeout(that.timeout);
  188. that.timeout = setTimeout(() => {
  189. cb([]);
  190. }, 0);
  191. });
  192. },
  193. handleSelect(item) {
  194. let that = this;
  195. if(that.selectType == "0"){
  196. if(item){
  197. let Lon = item.location.split(',')[0]
  198. let Lat = item.location.split(',')[1]
  199. let center = [parseFloat(Lon), parseFloat(Lat)]
  200. window.mapboxMap.flyTo({
  201. center: center,
  202. zoom: 18,
  203. pitch: 0,
  204. });
  205. let jsondata = {
  206. type: 'FeatureCollection',
  207. features: [
  208. {
  209. type: 'Feature',
  210. properties: {
  211. title: item.address,
  212. icon: 'location-icon'
  213. },
  214. geometry: {
  215. type: 'Point',
  216. coordinates: center
  217. }
  218. }
  219. ]
  220. };
  221. if(window.mapboxMap.getSource('point-source')){
  222. window.mapboxMap.getSource('point-source').setData(jsondata);
  223. }else{
  224. window.mapboxMap.addSource('point-source', {
  225. type: 'geojson',
  226. data: jsondata
  227. });
  228. window.mapboxMap.addLayer({
  229. id: 'location-layer',
  230. type: 'symbol', // symbol = 图标/文字图层
  231. source: 'point-source',
  232. layout: {
  233. 'icon-image': 'location-icon', // 使用自定义图标
  234. 'icon-size': 1.5, // 图标大小
  235. 'icon-allow-overlap': true, // 允许图标重叠
  236. 'icon-rotate': 0, // 旋转角度
  237. 'icon-offset': [0, -20] // 图标偏移(上下左右)
  238. },
  239. paint: {
  240. 'icon-opacity': 1 // 透明度
  241. }
  242. });
  243. }
  244. }
  245. }else{
  246. sessionStorage.setItem('guid', "");
  247. that.$refs.childRef.setTableShow(that.searchText)
  248. }
  249. },
  250. }
  251. };
  252. </script>
  253. <style>
  254. .el-select__wrapper{
  255. min-height: 40px !important;
  256. background: transparent !important;
  257. /* box-shadow: 0 0 0 1px #01346fe0 inset; */
  258. }
  259. .el-select__placeholder{
  260. color: #fff !important;
  261. }
  262. .el-tag.el-tag--info{
  263. --el-tag-text-color: #ffffff !important;
  264. }
  265. .el-tag.el-tag--info {
  266. --el-tag-bg-color: #f3f3f700;
  267. }
  268. .el-popper.is-light{
  269. background: #01346fe0 !important;
  270. border: 1px solid #01346fe0 !important;
  271. max-width: none !important;
  272. }
  273. .el-select-dropdown__item{
  274. color: #fff !important;
  275. }
  276. .el-select-dropdown__item.is-hovering{
  277. background: linear-gradient(to right, #01346fe0, #02a7bd, #01346fe0) !important;
  278. color: #fff !important;
  279. }
  280. .home-custom-dropdown {
  281. width: 400px !important;
  282. max-width: 400px;
  283. overflow: auto;
  284. }
  285. /* 单行溢出,显示省略号 */
  286. .text-ellipsis {
  287. white-space: nowrap;
  288. overflow: hidden;
  289. text-overflow: ellipsis;
  290. width: 100%;
  291. }
  292. </style>
  293. <style lang="less" scoped>
  294. .home {
  295. width: 100%;
  296. height: 100%;
  297. // position: relative;
  298. // user-select: none;
  299. /* Chrome, Opera, Safari */
  300. // -moz-user-select: none;
  301. /* Firefox */
  302. // -ms-user-select: none;
  303. /* Internet Explorer/Edge */
  304. // -khtml-user-select: none;
  305. /* Konqueror/Safari */
  306. // -webkit-user-select: none;
  307. /* Webkit */
  308. // user-select: none;
  309. /* 标准语法 */
  310. }
  311. .search-box {
  312. position: absolute;
  313. top: 60px;
  314. left: 42%;
  315. z-index: 999;
  316. padding: 12px 20px;
  317. width: 400px;
  318. .search-input{
  319. -webkit-backdrop-filter: blur(5px);
  320. backdrop-filter: blur(5px);
  321. background: #01346f99;
  322. border-radius: 4px;
  323. }
  324. }
  325. .search-box-auto {
  326. position: absolute;
  327. top: 0px;
  328. left: 42%;
  329. z-index: 999;
  330. padding: 12px 20px;
  331. width: 400px;
  332. .search-input{
  333. -webkit-backdrop-filter: blur(5px);
  334. backdrop-filter: blur(5px);
  335. background: #01346f99;
  336. border-radius: 4px;
  337. }
  338. }
  339. .map-box{
  340. position: fixed;
  341. right: 50px;
  342. bottom: 50px;
  343. display: flex;
  344. align-items: center;
  345. z-index: 10;
  346. .map-group{
  347. display: flex;
  348. gap: 5px;
  349. align-items: center;
  350. background-color: #01346f3d;
  351. border: 1px solid #01346f3d;
  352. padding: 5px;
  353. border-radius: 5px;
  354. .map-item{
  355. display: grid;
  356. // gap: 0px 10px;
  357. // align-items: center;
  358. text-align: center;
  359. border-radius: 5px;
  360. // background: white;
  361. cursor: pointer;
  362. border: 2px solid #2881f600;
  363. }
  364. .map-item:hover{
  365. color: #2880f6;
  366. border: 2px solid #2880f6;
  367. }
  368. .active{
  369. color: #2880f6;
  370. border: 2px solid #2880f6;
  371. }
  372. .map-img{
  373. width: 80px;
  374. height: 100%;
  375. border-radius: 3px 3px 0px 0px;
  376. }
  377. .map-img-name{
  378. padding-bottom: 5px;
  379. background: #fff;
  380. border-radius: 0px 0px 3px 3px;
  381. }
  382. }
  383. }
  384. </style>