codernight hace 3 días
padre
commit
65b5e80546
Se han modificado 5 ficheros con 464 adiciones y 44 borrados
  1. 1 1
      public/index.html
  2. 257 0
      src/components/chooseAddress/index.vue
  3. 1 0
      src/config/axios.js
  4. 1 1
      src/config/base.js
  5. 204 42
      src/views/task.vue

+ 1 - 1
public/index.html

@@ -11,7 +11,7 @@
   </title>
   <script>
     window.webConfig = {
-      "webApiBaseUrl": "http://60.247.155.214:8001/zh-admin",
+      "webApiBaseUrl": "https://wrjh5.zzots.cn/zh-admin",
       "webSystemTitle": "正式"
     }
   </script>

+ 257 - 0
src/components/chooseAddress/index.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="location-picker" v-if="visabled">
+    <!-- 地图容器 -->
+    <div id="map-container"></div>
+
+    <div class="confirmLocation">
+      <!-- 搜索框 -->
+      <input
+        v-model="searchText"
+        @change="handleSearch"
+        ref="searchInput"
+        placeholder="搜索地点..."
+      />
+
+      <!-- 搜索结果列表 -->
+      <ul v-if="searchResults.length" class="search-results">
+        <li
+          v-for="(result, index) in searchResults"
+          :key="index"
+          @click="selectSearchResult(result)"
+        >
+          {{ result.name }} - {{ result.address }}
+        </li>
+      </ul>
+
+      <!-- 定位结果展示 -->
+      <div v-if="selectedLocation" class="result">
+        <p>已选择:{{ selectedLocation.address }}</p>
+        <p>经纬度:{{ selectedLocation.lng }}, {{ selectedLocation.lat }}</p>
+      </div>
+
+      <!-- 操作按钮 -->
+      <van-button
+        size="small"
+        @click="confirmLocation"
+        text="确认选择"
+      ></van-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import AMapLoader from "@amap/amap-jsapi-loader";
+
+export default {
+  data() {
+    return {
+      map: null,
+      visabled: false,
+      marker: null,
+      AMapRef: null,
+      searchText: "",
+      selectedLocation: null,
+      searchResults: [], // 搜索结果列表
+    };
+  },
+  methods: {
+    async initMap() {
+      try {
+        this.visabled = true;
+        this.selectedLocation = null;
+        this.searchText = "";
+        // 加载高德地图JS API
+        AMapLoader.load({
+          key: "487c977753dd211e731f1d13d9322f09",
+          version: "2.0",
+          securityJsCode: "2403bc79e3493aa796277092566cda59",
+          plugins: ["AMap.Geocoder", "AMap.PlaceSearch", "AMap.AutoComplete"],
+        }).then((AMap) => {
+          this.AMapRef = AMap;
+          // 初始化地图
+          this.map = new AMap.Map("map-container", {
+            zoom: 15,
+          });
+
+          // 添加点击选点事件
+          this.map.on("click", (e) => {
+            this.updateMarkerPosition(e.lnglat);
+            this.getAddress(e.lnglat.lng, e.lnglat.lat);
+          });
+
+          // 初始化标记点
+          this.marker = new AMap.Marker({
+            position: this.map.getCenter(),
+            map: this.map,
+          });
+        });
+      } catch (error) {
+        console.error("地图初始化失败:", error);
+      }
+    },
+
+    // 更新标记位置
+    updateMarkerPosition(lnglat) {
+      this.marker.setPosition(lnglat);
+      this.map.setCenter(lnglat);
+    },
+
+    getAddress(long, lat) {
+      fetch(
+        `https://restapi.amap.com/v3/geocode/regeo?location=${long},${lat}&key=74d5aa7c4270effe9a18d9cfa6149abf`
+      )
+        .then((res) => res.json())
+        .then((data) => {
+          let address = data.regeocode.addressComponent;
+          this.selectedLocation = {
+            address: data.regeocode.formatted_address,
+            lng: long,
+            lat: lat,
+          };
+        })
+        .catch((error) => {
+          console.log(error);
+        });
+    },
+    // 搜索地点
+    handleSearch() {
+      fetch(
+        `https://restapi.amap.com/v3/place/text?keywords=${this.searchText}&key=74d5aa7c4270effe9a18d9cfa6149abf`
+      )
+        .then((res) => res.json())
+        .then((data) => {
+          this.searchResults = data.pois.map((poi) => ({
+            name: poi.name,
+            address: poi.address,
+            location: poi.location,
+          }));
+          this.$refs.searchInput.blur(); // 收起键盘
+        })
+        .catch((error) => {
+          console.log(error);
+        });
+    },
+
+    // 选择搜索结果
+    selectSearchResult(result) {
+      this.updateMarkerPosition([
+        result.location.split(",")[0],
+        result.location.split(",")[1],
+      ]);
+
+      this.selectedLocation = {
+        lng: result.location.split(",")[0],
+        lat: result.location.split(",")[1],
+        address: result.name + result.address,
+      };
+      this.searchResults = []; // 清空搜索结果
+    },
+
+    // 确认选择
+    confirmLocation() {
+      if (this.selectedLocation) {
+        this.$emit("selected", this.selectedLocation);
+        this.visabled = false;
+      } else {
+        alert("请先在地图上选择位置");
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+#map-container {
+  width: 100%;
+  height: 400px;
+  border: 1px solid #ddd;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+}
+
+.confirmLocation {
+  position: absolute;
+  top: 20px;
+  right: 20px;
+  width: 240px;
+  /* width: calc(100% - 40px); */
+  background: #fff;
+  padding: 15px;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+}
+
+.location-picker {
+  position: fixed;
+  z-index: 999;
+  width: 100%;
+  top: 0;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  background: rgba(255, 255, 255, 0.95);
+  padding: 10px;
+}
+
+input {
+  padding: 10px;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  font-size: 14px;
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.search-results {
+  list-style: none;
+  padding: 0;
+  margin: 10px 0 0;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  max-height: 200px;
+  overflow-y: auto;
+  background: #fff;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.search-results li {
+  padding: 10px;
+  cursor: pointer;
+  border-bottom: 1px solid #eee;
+  font-size: 14px;
+}
+
+.search-results li:last-child {
+  border-bottom: none;
+}
+
+.search-results li:hover {
+  background: #f7f7f7;
+}
+
+.result {
+  font-size: 14px;
+  color: #333;
+  margin-top: 10px;
+}
+
+.result p {
+  margin: 5px 0;
+}
+
+.van-button {
+  width: 100%;
+  background-color: #007bff;
+  color: #fff;
+  border-radius: 4px;
+  font-size: 16px;
+  padding: 10px;
+  text-align: center;
+  cursor: pointer;
+}
+
+.van-button:hover {
+  background-color: #0056b3;
+}
+</style>

+ 1 - 0
src/config/axios.js

@@ -35,6 +35,7 @@ axios.interceptors.request.use(
   function (config) {
     if (config.headers.loading !== false) startLoading()
     config.headers.token = sessionStorage.getItem("token");
+    config.headers['Access-Control-Allow-Origin'] = '*'
     return config;
   },
   function (error) {

+ 1 - 1
src/config/base.js

@@ -7,6 +7,6 @@ const Config = process.env.NODE_ENV == 'development' ? process.env.VUE_APP_SERVE
 console.log(Config);
 // Base route
 export default Config
- // WebSocket
+// WebSocket
 //  export const SocketRootUrl = CONFIG[version].socketUrl;
 

+ 204 - 42
src/views/task.vue

@@ -77,22 +77,30 @@
       <table>
         <thead>
           <tr>
-            <th>管线及单元</th>
-            <th v-if="listTypeName != '默认'">距离</th>
+            <th style="min-width: 150px">管线及单元</th>
+            <th v-if="rectangle && listTypeName != '默认'">距离</th>
             <th>状态</th>
-            <th>时间</th>
-            <th>操作</th>
+            <th>创建人</th>
+            <th>接收人</th>
+            <th style="width: 110px">时间</th>
+            <th style="width: 150px">操作</th>
           </tr>
         </thead>
         <tbody>
           <tr v-for="(row, index) in dataList" :key="index">
             <td>{{ row.lineName }}({{ row.lineUnitName }})</td>
-            <td style="width: 90px" v-if="listTypeName != '默认'">{{ (row.distance/1000).toFixed(2) }}km</td>
+            <td style="width: 90px" v-if="rectangle && listTypeName != '默认'">
+              {{ (row.distance / 1000).toFixed(2) }}km
+            </td>
             <td style="width: 120px">
               <span :style="{ color: isReceivedColor[row.isReceived] }">
                 {{ isReceived[row.isReceived] }}
               </span>
             </td>
+            <td style="width: 90px">{{ row.createName }}</td>
+            <td style="width: 90px">
+              {{ row.receivedUserName ? row.receivedUserName : "暂无" }}
+            </td>
             <td style="width: 90px">{{ row.updateDate.slice(0, -9) }}</td>
             <td>
               <div class="bts" style="width: 170px">
@@ -137,11 +145,16 @@
       </table>
     </div>
     <van-back-top target=".table-container" />
+    <chooseAddress
+      @selected="chooseAddressData"
+      ref="chooseAddressRef"
+    ></chooseAddress>
   </div>
 </template>
 
 <script setup>
 import { useRoute, useRouter } from "vue-router";
+import chooseAddress from "@/components/chooseAddress/index.vue";
 import {
   ref,
   defineProps,
@@ -157,6 +170,7 @@ const route = useRoute();
 const router = useRouter();
 const total = ref(0);
 const scrollContainer = ref();
+const chooseAddressRef = ref();
 const dataList = ref([]);
 import { goBackToApp, saveCode, downFly } from "@/utils/bridge";
 const isLoading = ref(false);
@@ -170,6 +184,7 @@ const listTypeName = computed(() => {
 });
 const rectangle = ref();
 const location = ref();
+const sourceType = ref();
 const itemRef = ref();
 const option1 = [
   { text: "全部", value: "" },
@@ -185,6 +200,7 @@ const option1 = [
 const option2 = ref([
   { text: "默认", value: 0 },
   { text: "离我最近", value: 1 },
+  { text: "选择位置", value: 2 },
 ]);
 
 const isReceivedColor = {
@@ -213,42 +229,153 @@ const dataForm = ref({
   limit: 15,
 });
 
-const getLocation = () => {
-  AMap.plugin("AMap.Geolocation", function () {
-    var geolocation = new AMap.Geolocation({
-      enableHighAccuracy: true, // 开启高精度模式
-      timeout: 1000, // 设置超时时间为 30 秒
-      noIpLocate: 0, // 使用 IP 定位作为备用方案
-      noGeoLocation: 0, // 允许浏览器获取地理位置
-    });
+// 三级定位:GPS → 高德SDK → IP定位
+function getLocationWithFallback() {
+  return new Promise((resolve, reject) => {
+    // 1. 先尝试浏览器高精度定位
+    getBrowserLocation()
+      .then(resolve)
+      .catch(() => {
+        // 2. 失败后降级到高德SDK
+        getAMapLocation()
+          .then(resolve)
+          .catch(() => {
+            // 3. 最终回退到IP定位
+            getIpLocation().then(resolve).catch(reject);
+          });
+      });
+  });
+}
 
-    geolocation.getCurrentPosition(function (status, result) {
-      if (status === "complete") {
-        var lng = result.position.lng;
-        var lat = result.position.lat;
-        console.log(lng, lat);
-      } else {
-        console.error("定位失败", result);
-        fetch(
-          "https://restapi.amap.com/v3/ip?key=74d5aa7c4270effe9a18d9cfa6149abf"
-        )
-          .then((response) => response.json())
-          .then((data) => {
-            console.log("IP 定位:", data);
-            console.log("当前位置:" + data.province + data.city);
-            console.log("经纬度:" + data.rectangle.split(";")[1]);
-            location.value = data.province + data.city;
-            rectangle.value = data.rectangle.split(";")[1];
-            option2.value[1].text = `离我最近(${location.value})`;
-          })
-          .catch((error) => {
-            console.error("IP 定位失败:", error);
-            option2.value[1].text = "定位失败,点击重新定位";
-            showToast("定位失败");
+// 1. 浏览器原生定位
+function getBrowserLocation() {
+  return new Promise((resolve, reject) => {
+    if (!navigator.geolocation) {
+      reject("浏览器不支持定位");
+      return;
+    }
+
+    navigator.geolocation.getCurrentPosition(
+      (position) => {
+        resolve({
+          source: "GPS/WiFi",
+          lng: position.coords.longitude,
+          lat: position.coords.latitude,
+          accuracy: `${position.coords.accuracy}米`,
+        });
+      },
+      (err) => {
+        const errors = {
+          1: "PERMISSION_DENIED (用户拒绝/无权限)",
+          2: "POSITION_UNAVAILABLE (无法获取信号)",
+          3: "TIMEOUT (超时)",
+        };
+        console.error(`定位失败: ${errors[err.code] || err.message}`);
+
+        // 额外诊断信息
+        navigator.permissions
+          .query({ name: "geolocation" })
+          .then((permission) => {
+            console.log("权限状态:", permission.state);
           });
+        if (navigator.connection) {
+          console.log("网络类型:", navigator.connection.effectiveType);
+        }
+        reject(`浏览器定位失败: ${err.message}`);
+      },
+      {
+        enableHighAccuracy: true,
+        timeout: 8000,
+        maximumAge: 0,
       }
+    );
+  });
+}
+
+// 2. 高德SDK混合定位
+function getAMapLocation() {
+  return new Promise((resolve, reject) => {
+    if (!window.AMap) {
+      reject("高德SDK未加载");
+      return;
+    }
+
+    AMap.plugin("AMap.Geolocation", () => {
+      const geo = new AMap.Geolocation({
+        enableHighAccuracy: true,
+        timeout: 10000,
+      });
+
+      geo.getCurrentPosition(
+        (status, result) => {
+          if (status === "complete") {
+            resolve({
+              source: "高德混合定位",
+              lng: result.position.lng,
+              lat: result.position.lat,
+              address: result.formattedAddress,
+            });
+          } else {
+            reject(`高德定位失败: ${result.message}`);
+          }
+        },
+        (error) => {
+          reject(`高德定位异常: ${error}`);
+        }
+      );
     });
   });
+}
+
+// 3. IP定位兜底
+function getIpLocation() {
+  return fetch(
+    "https://restapi.amap.com/v3/ip?key=74d5aa7c4270effe9a18d9cfa6149abf"
+  )
+    .then((response) => response.json())
+    .then((data) => {
+      if (data.status === "1") {
+        // 从rectangle中提取中心点经纬度(示例:"116.1,39.1;116.2,39.2")
+        const [lng, lat] = data.rectangle
+          .split(";")[0]
+          .split(",")
+          .map(parseFloat);
+        return {
+          source: "IP定位",
+          lng: lng,
+          lat: lat,
+          province: data.province,
+          city: data.city,
+          accuracy: "城市级",
+        };
+      } else {
+        throw new Error(data.info || "IP定位失败");
+      }
+    });
+}
+
+const getAddress = (long, lat, source) => {
+  fetch(
+    `https://restapi.amap.com/v3/geocode/regeo?location=${long},${lat}&key=74d5aa7c4270effe9a18d9cfa6149abf`
+  )
+    .then((res) => res.json())
+    .then((data) => {
+      let address = data.regeocode.addressComponent;
+      // alert(address.province + address.city + address.district);
+      if (sourceType.value == "自定义") {
+        return;
+      }
+      option2.value[1].text =
+        address.province + address.city + address.district + "(" + source + ")";
+      sourceType.value = source;
+    })
+    .catch((error) => {
+      console.log(error);
+
+      option2.value[1].text = "定位失败,点击重新定位";
+      sourceType.value = null;
+      showToast("定位失败");
+    });
 };
 
 //获取数据
@@ -288,6 +415,17 @@ const getList = (e) => {
     });
 };
 
+const chooseAddressData = (x) => {
+  option2.value[1].text = x.address + "(自定义)";
+  sourceType.value = "自定义";
+  rectangle.value = x.lng + "," + x.lat;
+  dataForm.value.lietType = 1;
+  dataList.value = [];
+  dataForm.value.page = 1;
+  more.value = false;
+  getList();
+};
+
 // 详情
 const todetails = (e) => {
   let ruters = {
@@ -319,11 +457,26 @@ const changeisReceived = (event) => {
   }
   getList();
 };
-const changelietType = () => {
+const changelietType = (x) => {
+  if (x == 2) {
+    chooseAddressRef.value.initMap();
+    return;
+  }
   if (!rectangle.value) {
-    getLocation();
+    getLocationWithFallback()
+      .then((data) => {
+        console.log("定位成功:", data);
+        rectangle.value = data.lng + "," + data.lat;
+        getAddress(data.lng, data.lat);
+      })
+      .catch((err) => {
+        console.error("所有定位方式均失败:", err);
+        option2.value[1].text = "定位失败,点击重新定位";
+        showToast("定位失败");
+      });
     return;
   }
+
   dataList.value = [];
   dataForm.value.page = 1;
   more.value = false;
@@ -503,12 +656,21 @@ onMounted(() => {
 
   // 获取滚动容器元素
   const scrollContainer = document.getElementById("scroll-container");
-
+  rectangle.value = "";
   // 监听滚动事件
   scrollContainer.addEventListener("scroll", handleScroll);
-
   getList(1);
-  getLocation();
+  getLocationWithFallback()
+    .then((data) => {
+      console.log("定位成功:", data);
+      rectangle.value = data.lng + "," + data.lat;
+      getAddress(data.lng, data.lat, data.source);
+    })
+    .catch((err) => {
+      console.error("所有定位方式均失败:", err);
+      option2.value[1].text = "定位失败,点击重新定位";
+      showToast("定位失败");
+    });
 });
 </script>
 
@@ -524,6 +686,7 @@ onMounted(() => {
 table {
   width: 100%;
   border-collapse: collapse;
+  font-size: 0.8rem;
 }
 
 thead {
@@ -537,7 +700,6 @@ td {
   padding: 8px;
   border: 1px solid #ddd;
 }
-
 .bts {
   display: flex;
   justify-content: space-around;