From 75cdd3cdcec1fc22bddebd6352e5e87e0a8d5d33 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Fri, 18 Apr 2025 10:57:41 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/Home/SearchBox.vue |  442 +++++++++++++++++++++++++++---------------------------
 1 files changed, 223 insertions(+), 219 deletions(-)

diff --git a/src/views/Home/SearchBox.vue b/src/views/Home/SearchBox.vue
index 46d23e7..fb3b28c 100644
--- a/src/views/Home/SearchBox.vue
+++ b/src/views/Home/SearchBox.vue
@@ -1,277 +1,281 @@
 <template>
-  <div class="searchBox" ref="searchBoxRef">
-    <div class="searchInput">
-      <el-select v-model="optionsValue" @change="optionChange" placeholder="请选择查询">
-        <el-option
-          v-for="item in options"
-          :key="item.value"
-          :label="item.label"
-          :value="item.value"
-        />
-      </el-select>
+	<div class="searchBox" ref="searchBoxRef">
+		<div class="searchInput">
+			<el-select v-model="optionsValue" @change="optionChange" placeholder="请选择查询">
+				<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+			</el-select>
 
-      <el-input v-model="searchKey"  @focus="handleFocus" placeholder="请输入搜索关键字"></el-input>
-    </div>
-    <div class="searchBtn" @click="searchClick"></div>
-    <div class="region">
-      <el-tree-select
-        v-model="treeValue"
-        check-strictly
-        lazy
-        :load="load"
-        :props="props"
-        style="width: 240px"
-        @node-click="handleNodeClick"
-      />
-    </div>
-  </div>
-  <div class="select-down-list" ref="selectDownRef" v-show="isSelectDown">
-    <div class="item" v-for="item in downList" @click="selectedValue(item)">{{ item.nickname || item.name }}</div>
-  </div>
+			<el-input
+				v-model="searchKey"
+				@input="handlerInput"
+				@focus="handleFocus"
+				placeholder="请输入搜索关键字"
+			></el-input>
+		</div>
+		<div class="searchBtn" @click="searchClick"></div>
+		<div class="region">
+			<el-tree-select
+				v-model="treeValue"
+				check-strictly
+				lazy
+				:load="load"
+				:props="props"
+				style="width: 240px"
+				@node-click="handleNodeClick"
+			/>
+		</div>
+	</div>
+	<div class="select-down-list" ref="selectDownRef" v-show="isSelectDown">
+		<div class="item" v-for="item in downList" @click="selectedValue(item)">{{ item.nickname || item.name }}</div>
+	</div>
 </template>
 <script setup>
-import { getRegion } from '@/api/home';
-import { searchByKeyword, selectDeviceList } from '@/api/home/common';
-import { useStore } from 'vuex';
+import _ from 'lodash'
+import { getRegion } from '@/api/home'
+import { searchByKeyword, selectDeviceList } from '@/api/home/common'
+import { useStore } from 'vuex'
 import cesiumOperation from '@/utils/cesium-tsa'
 
 const { flyTo } = cesiumOperation()
 
-const store = useStore();
-const searchKey = ref('');
-const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode);
-const selectedAreaCode = computed(() => store.state.user.selectedAreaCode);
-const areaValue = ref('江西省');
-const treeValue = ref(userAreaCode.value);
-let first = true;
-const searchBoxRef = ref(null);
-const selectDownRef = ref(null);
+const store = useStore()
+const searchKey = ref('')
+const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode)
+const selectedAreaCode = computed(() => store.state.user.selectedAreaCode)
+const areaValue = ref('江西省')
+const treeValue = ref(userAreaCode.value)
+let first = true
+const searchBoxRef = ref(null)
+const selectDownRef = ref(null)
 
 function handleNodeClick(data) {
-  areaValue.value = data.name;
-  store.commit('setSelectedAreaCode', data.code);
+	areaValue.value = data.name
+	store.commit('setSelectedAreaCode', data.code)
 }
 
 const props = {
-  label: 'name',
-  value: 'code',
-  children: 'children',
-};
+	label: 'name',
+	value: 'code',
+	children: 'children',
+}
 const load = async (node, resolve) => {
-  if (first) {
-    first = false;
-    const res = await getRegion(userAreaCode.value);
-    const { provinceCode, provinceName } = res?.data?.data?.[0] || {};
-    resolve([{ code: provinceCode, name: provinceName }]);
-    return;
-  }
-  const code = node?.data?.code || userAreaCode.value;
-  if ((node?.data?.regionLevel || 0) > 2) return resolve([]);
-  getRegion(code).then(res => {
-    resolve(res?.data?.data || []);
-  });
-};
+	if (first) {
+		first = false
+		const res = await getRegion(userAreaCode.value)
+		const { provinceCode, provinceName } = res?.data?.data?.[0] || {}
+		resolve([{ code: provinceCode, name: provinceName }])
+		return
+	}
+	const code = node?.data?.code || userAreaCode.value
+	if ((node?.data?.regionLevel || 0) > 2) return resolve([])
+	getRegion(code).then(res => {
+		resolve(res?.data?.data || [])
+	})
+}
 
-const optionsValue = ref('1');
+const optionsValue = ref('1')
 const options = [
-  {
-    value: '1',
-    label: '机巢',
-  },
-  {
-    value: '2',
-    label: '地址',
-  },
-];
+	{
+		value: '1',
+		label: '机巢',
+	},
+	{
+		value: '2',
+		label: '地址',
+	},
+]
 
-const isSelectDown = ref(false);
-// 下拉数据列表
-const machineNestList = ref([]);
+const isSelectDown = ref(false)
+
 // 地址搜索结果
-const downList = ref([]);
-const position = ref({});
+const downList = ref([])
+const position = ref({})
 
 // 获取机巢搜索结果
 const getDeviceList = async () => {
-  const res = await selectDeviceList({nickname: searchKey.value});
-  if (res.data.code !== 0) return;
-  machineNestList.value = res?.data?.data || [];
-  downList.value = res?.data?.data || [];
-};
+	const res = await selectDeviceList({ nickname: searchKey.value })
+	if (res.data.code !== 0) return
+	downList.value = res?.data?.data || []
+}
 // 获取地址搜索结果
 const getAddressList = async () => {
-  const res = await searchByKeyword(encodeURIComponent(`${areaValue.value}+${searchKey.value}`));
-  if (res.data.code !== 0) return;
-  downList.value = res?.data?.data.tips || [];
-  if (downList.value.length > 0) {
-    isSelectDown.value = true;
-  }
-};
+	const res = await searchByKeyword(encodeURIComponent(`${areaValue.value}+${searchKey.value}`))
+	if (res.data.code !== 0) return
+	downList.value = res?.data?.data.tips || []
+	if (downList.value.length > 0) {
+		isSelectDown.value = true
+	}
+}
 // 搜索结果
 const searchClick = () => {
 	const longitude = Number(position.value.longitude)
 	const latitude = Number(position.value.latitude)
 	flyTo({ longitude, latitude }, 1, 1000)
-};
+}
 
 // 地址和机巢的切换
 const optionChange = () => {
-  searchKey.value = '';
-  downList.value = [];
-};
+	searchKey.value = ''
+	downList.value = []
+
+	inputSelect()
+}
+
+// input对应下拉数据初始化
+const inputSelect = () => {
+	if (optionsValue.value === '2') {
+		getAddressList()
+	} else {
+		getDeviceList()
+	}
+}
+
+inputSelect()
+
+// 输入框input事件
+const handlerInput = _.debounce(inputSelect, 1000)
+
 // 输入框获取焦点
 const handleFocus = () => {
-  if (optionsValue.value === '1') {
-    isSelectDown.value = true;
-    downList.value = machineNestList.value;
-  }
-};
+	isSelectDown.value = true
+}
 // 机巢下拉获取值
 const selectedValue = item => {
-  searchKey.value = item.nickname || item.name;
-  if (optionsValue.value === '1') {
-    position.value = item;
-  } else {
-    position.value = { longitude: item.location.split(',')[0], latitude: item.location.split(',')[1] };
-  }
-  
-  isSelectDown.value = false;
-};
+	searchKey.value = item.nickname || item.name
+	if (optionsValue.value === '1') {
+		position.value = item
+	} else {
+		position.value = { longitude: item.location.split(',')[0], latitude: item.location.split(',')[1] }
+	}
 
-// 监听搜索关键字变化
-watch(searchKey, async (newVal) => {
-  if (optionsValue.value === '2') {
-    await getAddressList();
-  } else {
-    await getDeviceList();
-  }
-}, { immediate: false });
+	isSelectDown.value = false
+}
 
 onMounted(() => {
-  document.addEventListener('click', handleClickOutside);
-});
+	document.addEventListener('click', handleClickOutside)
+})
 
 onUnmounted(() => {
-  document.removeEventListener('click', handleClickOutside);
-});
+	document.removeEventListener('click', handleClickOutside)
+})
 
-const handleClickOutside = (event) => {
-  if (!searchBoxRef.value?.contains(event.target) && !selectDownRef.value?.contains(event.target)) {
-    isSelectDown.value = false;
-  }
-};
+const handleClickOutside = event => {
+	if (!searchBoxRef.value?.contains(event.target) && !selectDownRef.value?.contains(event.target)) {
+		isSelectDown.value = false
+	}
+}
 </script>
 <style scoped lang="scss">
 .select-down-list {
-  position: absolute;
-  top: 188px;
-  left: 44%;
-  transform: translateX(-40%);
-  width: 220px;
-  height: 256px;
-  overflow-y: auto;
-  background: linear-gradient( 180deg, #0D3556 0%, #012350 100%);
-  border-radius: 0px 0px 8px 8px;
-  border: 1px solid;
-  border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
-  opacity: 0.8;
-  &::-webkit-scrollbar {
-    width: 0;
-    display: none;
-  }
-  -ms-overflow-style: none;  /* IE and Edge */
-  scrollbar-width: none;  /* Firefox */
-  .item {
-    color: #FFFFFF;
-    height: 32px;
-    line-height: 32px;
-    text-align: center;
-    cursor: pointer;
-    &:hover {
-      background: linear-gradient( 90deg, rgba(0,122,255,0) 0%, rgba(0,98,204,0.6) 50%, rgba(0,73,153,0) 100%);
-      border: 1px solid;
-      border-image: linear-gradient(90deg, rgba(0, 199, 190, 0), rgba(48, 176, 199, 1), rgba(0, 199, 190, 0)) 1 1;
-    }
-  }
+	position: absolute;
+	top: 188px;
+	left: 44%;
+	transform: translateX(-40%);
+	width: 220px;
+	height: 256px;
+	overflow-y: auto;
+	background: linear-gradient(180deg, #0d3556 0%, #012350 100%);
+	border-radius: 0px 0px 8px 8px;
+	border: 1px solid;
+	border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
+	opacity: 0.8;
+	&::-webkit-scrollbar {
+		width: 0;
+		display: none;
+	}
+	-ms-overflow-style: none; /* IE and Edge */
+	scrollbar-width: none; /* Firefox */
+	.item {
+		color: #ffffff;
+		height: 32px;
+		line-height: 32px;
+		text-align: center;
+		cursor: pointer;
+		&:hover {
+			background: linear-gradient(90deg, rgba(0, 122, 255, 0) 0%, rgba(0, 98, 204, 0.6) 50%, rgba(0, 73, 153, 0) 100%);
+			border: 1px solid;
+			border-image: linear-gradient(90deg, rgba(0, 199, 190, 0), rgba(48, 176, 199, 1), rgba(0, 199, 190, 0)) 1 1;
+		}
+	}
 }
 .searchBox {
-  width: 420px;
-  height: 43px;
-  position: absolute;
-  top: 145px;
-  left: 50%;
-  transform: translateX(-50%);
-  display: flex;
+	width: 420px;
+	height: 43px;
+	position: absolute;
+	top: 145px;
+	left: 50%;
+	transform: translateX(-50%);
+	display: flex;
 
-  .el-select {
-    width: 130px;
-    height: 100%;
+	.el-select {
+		width: 130px;
+		height: 100%;
 
-    :deep() {
-      .el-select__wrapper {
-        background: transparent;
-        border: none;
-        box-shadow: none;
-        height: 100%;
-        padding-left: 20px;
-      }
+		:deep() {
+			.el-select__wrapper {
+				background: transparent;
+				border: none;
+				box-shadow: none;
+				height: 100%;
+				padding-left: 20px;
+			}
 
-      .el-select__selected-item {
-        font-family: Source Han Sans CN, Source Han Sans CN, serif;
-        font-weight: 400;
-        font-size: 14px;
-        color: #ffffff;
-        line-height: 18px;
-      }
-    }
-  }
+			.el-select__selected-item {
+				font-family: Source Han Sans CN, Source Han Sans CN, serif;
+				font-weight: 400;
+				font-size: 14px;
+				color: #ffffff;
+				line-height: 18px;
+			}
+		}
+	}
 
-  .searchInput {
-    width: 243px;
-    height: 100%;
-    background: url('@/assets/images/home/searchBox/searchBg1.png') no-repeat center / 100% 100%;
-    display: flex;
+	.searchInput {
+		width: 243px;
+		height: 100%;
+		background: url('@/assets/images/home/searchBox/searchBg1.png') no-repeat center / 100% 100%;
+		display: flex;
 
-    .el-input {
-      height: 100%;
+		.el-input {
+			height: 100%;
 
-      :deep() {
-        .el-input__wrapper {
-          background: transparent;
-          border: none;
-          box-shadow: none;
-          height: 100%;
-        }
+			:deep() {
+				.el-input__wrapper {
+					background: transparent;
+					border: none;
+					box-shadow: none;
+					height: 100%;
+				}
 
-        .el-input__inner {
-          font-family: Source Han Sans CN, Source Han Sans CN, serif;
-          font-weight: 400;
-          font-size: 14px;
-          color: #ffffff;
-          line-height: 18px;
-        }
-      }
-    }
-  }
+				.el-input__inner {
+					font-family: Source Han Sans CN, Source Han Sans CN, serif;
+					font-weight: 400;
+					font-size: 14px;
+					color: #ffffff;
+					line-height: 18px;
+				}
+			}
+		}
+	}
 
-  .searchBtn {
-    width: 67px;
-    height: 100%;
-    background: url('@/assets/images/home/searchBox/searchBg2.png') no-repeat center / 100% 100%;
-    cursor: pointer;
-  }
+	.searchBtn {
+		width: 67px;
+		height: 100%;
+		background: url('@/assets/images/home/searchBox/searchBg2.png') no-repeat center / 100% 100%;
+		cursor: pointer;
+	}
 
-  .region {
-    width: 0;
-    flex-grow: 1;
-    background: url('@/assets/images/home/searchBox/searchBg3.png') no-repeat center / 100% 100%;
+	.region {
+		width: 0;
+		flex-grow: 1;
+		background: url('@/assets/images/home/searchBox/searchBg3.png') no-repeat center / 100% 100%;
 
-    :deep() {
-      .el-select__wrapper {
-        width: 100px;
-        padding-left: 20px;
-      }
-    }
-  }
+		:deep() {
+			.el-select__wrapper {
+				width: 100px;
+				padding-left: 20px;
+			}
+		}
+	}
 }
 </style>

--
Gitblit v1.9.3