search.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <template>
  2. <view :class="['search-content']">
  3. <view class="search-box">
  4. <view class="search-input-box">
  5. <svg
  6. t="1733904658291"
  7. class="search-icon"
  8. viewBox="0 0 1024 1024"
  9. version="1.1"
  10. xmlns="http://www.w3.org/2000/svg"
  11. p-id="5981"
  12. xmlns:xlink="http://www.w3.org/1999/xlink"
  13. >
  14. <path
  15. d="M174.545 465.455c0-18.619 16.291-34.91 34.91-34.91s34.909 16.291 34.909 34.91c0 121.018 100.072 221.09 221.09 221.09 18.619 0 34.91 16.291 34.91 34.91s-16.291 34.909-34.91 34.909c-160.581 0-290.909-130.328-290.909-290.91z m290.91 360.727c200.145 0 360.727-160.582 360.727-360.727S665.6 104.727 465.455 104.727 104.727 265.31 104.727 465.455 265.31 826.182 465.455 826.182z m323.49-76.8L961.164 921.6c13.963 13.964 13.963 34.91 0 48.873-13.964 13.963-34.91 13.963-48.873 0L737.745 795.927c-74.472 60.51-169.89 97.746-272.29 97.746C228.073 896 34.909 702.836 34.909 465.455S228.073 34.909 465.455 34.909 896 228.073 896 465.455c0 109.381-39.564 209.454-107.055 283.927z"
  16. p-id="5982"
  17. ></path>
  18. </svg>
  19. <input
  20. confirm-type="search"
  21. ref="searchInputRef"
  22. class="search-input"
  23. :auto-blur="true"
  24. type="text"
  25. placeholder="请输入关键字"
  26. v-model="locationName"
  27. @blur="onSearchFocus(true)"
  28. placeholder-class="placeholder"
  29. />
  30. </view>
  31. <view class="search-select">
  32. <view class="select-item" @click.stop="$refs.cityRef.open()">
  33. <text class="item-text one-row">{{
  34. params.codeLabel || "办理区域"
  35. }}</text>
  36. <u-icon
  37. name="arrow-down-fill"
  38. :color="downFillColor"
  39. size="14"
  40. ></u-icon>
  41. </view>
  42. <view class="select-item" @click.stop="$refs.mapTypeRef.open()">
  43. <text class="item-text one-row">{{
  44. params.typeName || "位置类型"
  45. }}</text>
  46. <u-icon
  47. name="arrow-down-fill"
  48. :color="downFillColor"
  49. size="14"
  50. ></u-icon>
  51. </view>
  52. <view v-if="mapConfig.navigationName" class="select-item" @click.stop="$refs.mapAdRef.open()">
  53. <text class="item-text one-row">{{mapConfig.navigationName}}</text>
  54. <u-icon
  55. name="arrow-down-fill"
  56. :color="downFillColor"
  57. size="14"
  58. ></u-icon>
  59. </view>
  60. </view>
  61. </view>
  62. <!-- 选择地址 -->
  63. <city
  64. ref="cityRef"
  65. :code.sync="params.code"
  66. @cityName="(e) => (params.codeLabel = e)"
  67. />
  68. <!-- 选择位置类型 -->
  69. <mapType
  70. ref="mapTypeRef"
  71. :mapTypeId.sync="params.mapTypeId"
  72. @typeName="(e) => (params.typeName = e)"
  73. />
  74. <!-- 选择高频事项指引 -->
  75. <mapAd
  76. ref="mapAdRef"
  77. :mapAdId.sync="params.mapAdId"
  78. @mapAdSelect="mapAdSelect"
  79. />
  80. </view>
  81. </template>
  82. <script>
  83. import { EventBus } from "@/utils/vueBus.js";
  84. import { getLocation } from "@/utils/tool.js";
  85. import $confog from "@/config/index.js";
  86. import { getMapMatterDetail_Api } from "@/api/map.js";
  87. export default {
  88. props: {
  89. mapConfig: {
  90. type: Object,
  91. default: () => {},
  92. },
  93. },
  94. data() {
  95. return {
  96. locationPower: false,
  97. locationName: undefined,
  98. selfLatitude: undefined,
  99. selfLongitude: undefined,
  100. // selfLatitude: 30.482926,
  101. // selfLongitude: 114.414431,
  102. params: {
  103. code: undefined,
  104. codeLabel: undefined,
  105. mapTypeId: undefined,
  106. typeName: undefined,
  107. },
  108. LocationTimeout: null,
  109. SearchTimeout: null,
  110. type: $confog.type,
  111. downFillColor: "#808080",
  112. getLocationNum: 1,
  113. };
  114. },
  115. created() {
  116. this.type = $confog.type;
  117. this.downFillColor = $confog.type === "H6" ? "#808080" : "#101010";
  118. this.init();
  119. },
  120. mounted() {
  121. EventBus.$on("TianDiTuSearch", (callBack) => {
  122. this.handleSearch(callBack);
  123. }); // 确保在组件销毁前移除事件监听
  124. },
  125. beforeDestroy() {
  126. EventBus.$off("TianDiTuSearch");
  127. },
  128. methods: {
  129. init() {
  130. clearTimeout(this.LocationTimeout);
  131. this.LocationTimeout = null;
  132. this.LocationTimeout = setTimeout(() => {
  133. getLocation()
  134. .then((res) => {
  135. const { longitude, latitude } = res || {};
  136. if (longitude && latitude) {
  137. this.selfLatitude = latitude;
  138. this.selfLongitude = longitude;
  139. clearTimeout(this.LocationTimeout);
  140. this.LocationTimeout = null;
  141. this.onSearchFocus();
  142. this.$store.dispatch("updateUseLocation", {
  143. longitude,
  144. latitude,
  145. });
  146. } else {
  147. this.getLocationNum++;
  148. if (this.getLocationNum <= 5) {
  149. this.init();
  150. }
  151. }
  152. })
  153. .catch((err) => {
  154. this.getLocationNum++;
  155. if (this.getLocationNum <= 5) {
  156. this.init();
  157. }
  158. });
  159. }, 1000);
  160. },
  161. /**
  162. * 获取定位
  163. * 有callBack,着是手动定位,地图会平移调用搜索,所以无需再次搜索
  164. * 没有callBack,则需要手动收索
  165. *
  166. */
  167. handleSearch(callBack) {
  168. try {
  169. uni.showLoading({
  170. mask: true,
  171. });
  172. getLocation()
  173. .then((res) => {
  174. const { longitude, latitude } = res || {};
  175. if (longitude && latitude) {
  176. this.selfLatitude = latitude;
  177. this.selfLongitude = longitude;
  178. }
  179. callBack &&
  180. callBack({ longitude: res.longitude, latitude: res.latitude });
  181. })
  182. .catch((err) => {
  183. if (this.selfLatitude && this.selfLongitude) {
  184. callBack &&
  185. callBack({
  186. longitude: this.selfLatitude,
  187. latitude: this.selfLongitude,
  188. });
  189. } else {
  190. uni.showToast({
  191. title: "获取定位失败",
  192. icon: "none",
  193. });
  194. }
  195. })
  196. .finally(() => {
  197. uni.hideLoading();
  198. });
  199. } catch (error) {
  200. console.log(999977999, error);
  201. //TODO handle the exception
  202. }
  203. },
  204. onSearchFocus(search = false) {
  205. try {
  206. clearTimeout(this.SearchTimeout);
  207. this.SearchTimeout = null;
  208. this.SearchTimeout = setTimeout(() => {
  209. let pms = {};
  210. try {
  211. if (this.params.code) {
  212. pms.areaCode = this.params.code || undefined;
  213. }
  214. pms.mapTypeId = this.params.mapTypeId;
  215. pms.selfLatitude = this.selfLatitude;
  216. pms.selfLongitude = this.selfLongitude;
  217. pms.locationName = this.locationName;
  218. pms.search = search;
  219. } catch (error) {
  220. console.log("定位收索11 error", error);
  221. //TODO handle the exception
  222. }
  223. this.$emit("handleSearch", pms);
  224. }, 150);
  225. } catch (error) {
  226. console.log(999977999, error);
  227. //TODO handle the exception
  228. }
  229. },
  230. getVal() {
  231. return {};
  232. },
  233. mapAdSelect(val) {
  234. const { adId, jumpType, outsideAddress, resourceModelId } = val;
  235. switch (jumpType) {
  236. case 0: //图文
  237. case 1: //图文&视频
  238. uni.navigateTo({
  239. url: "/pages/map/model/adDetail?mapAdId=" + adId,
  240. });
  241. break;
  242. case 2: //内部资源
  243. getMapMatterDetail_Api({ id: resourceModelId }).then((result) => {
  244. uni.navigateTo({
  245. url: "/pages/map/matterDetails",
  246. success: function (res) {
  247. // 通过eventChannel向被打开页面传送数据
  248. res.eventChannel.emit("acceptDataFromOpenerPage", result);
  249. },
  250. });
  251. });
  252. return;
  253. uni.navigateTo({
  254. url: "/pages/pages/map/adDetail?mapAdId=" + adId,
  255. });
  256. break;
  257. case 3: //外部链接
  258. window.open(outsideAddress, "_blank");
  259. break;
  260. }
  261. },
  262. getMapList() {},
  263. },
  264. watch: {
  265. params: {
  266. handler(newV, oldV) {
  267. this.onSearchFocus(true);
  268. },
  269. deep: true,
  270. },
  271. },
  272. };
  273. </script>
  274. <style lang="scss" scoped>
  275. $radius_: 20rpx;
  276. $heig_: 80rpx;
  277. .search-box {
  278. // padding: 20rpx 20rpx 0;
  279. position: fixed;
  280. left: 20rpx;
  281. top: 20rpx;
  282. right: 20rpx;
  283. z-index: 999;
  284. background-color: #fff;
  285. border-radius: $radius_;
  286. overflow: hidden;
  287. .search-input-box {
  288. width: 100%;
  289. height: $heig_;
  290. border-radius: $radius_;
  291. box-shadow: 0rpx -10rpx 30rpx #ccc;
  292. display: flex;
  293. align-items: center;
  294. padding: 0 10px;
  295. color: #020202;
  296. font-size: 28rpx;
  297. .search-icon {
  298. width: 45rpx;
  299. height: 45rpx;
  300. path {
  301. fill: #666666;
  302. }
  303. }
  304. .search-input {
  305. padding-left: 10px;
  306. }
  307. .placeholder {
  308. color: #b3b3b3;
  309. }
  310. }
  311. .search-select {
  312. // border-top: 1rpx solid #E8E8E8;
  313. width: 100%;
  314. height: $heig_;
  315. display: flex;
  316. // justify-content: space-between;
  317. align-items: center;
  318. padding: 0 28rpx;
  319. .select-item {
  320. // width: 50%;
  321. display: flex;
  322. justify-content: center;
  323. align-items: center;
  324. font-size: 28rpx;
  325. padding: 0 10rpx;
  326. color: #1a1a1a;
  327. min-width: 28rpx;
  328. margin-right: 65rpx;
  329. .item-text {
  330. display: inline-block;
  331. padding-right: 14rpx;
  332. overflow: hidden;
  333. }
  334. &:last-child {
  335. margin: 0;
  336. }
  337. }
  338. }
  339. }
  340. .h6-search-content {
  341. .search-select {
  342. .item-text {
  343. color: #929292;
  344. }
  345. }
  346. }
  347. </style>