|
@@ -77,22 +77,30 @@
|
|
<table>
|
|
<table>
|
|
<thead>
|
|
<thead>
|
|
<tr>
|
|
<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>接收人</th>
|
|
|
|
+ <th style="width: 110px">时间</th>
|
|
|
|
+ <th style="width: 150px">操作</th>
|
|
</tr>
|
|
</tr>
|
|
</thead>
|
|
</thead>
|
|
<tbody>
|
|
<tbody>
|
|
<tr v-for="(row, index) in dataList" :key="index">
|
|
<tr v-for="(row, index) in dataList" :key="index">
|
|
<td>{{ row.lineName }}({{ row.lineUnitName }})</td>
|
|
<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">
|
|
<td style="width: 120px">
|
|
<span :style="{ color: isReceivedColor[row.isReceived] }">
|
|
<span :style="{ color: isReceivedColor[row.isReceived] }">
|
|
{{ isReceived[row.isReceived] }}
|
|
{{ isReceived[row.isReceived] }}
|
|
</span>
|
|
</span>
|
|
</td>
|
|
</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 style="width: 90px">{{ row.updateDate.slice(0, -9) }}</td>
|
|
<td>
|
|
<td>
|
|
<div class="bts" style="width: 170px">
|
|
<div class="bts" style="width: 170px">
|
|
@@ -137,11 +145,16 @@
|
|
</table>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<van-back-top target=".table-container" />
|
|
<van-back-top target=".table-container" />
|
|
|
|
+ <chooseAddress
|
|
|
|
+ @selected="chooseAddressData"
|
|
|
|
+ ref="chooseAddressRef"
|
|
|
|
+ ></chooseAddress>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
import { useRoute, useRouter } from "vue-router";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
+import chooseAddress from "@/components/chooseAddress/index.vue";
|
|
import {
|
|
import {
|
|
ref,
|
|
ref,
|
|
defineProps,
|
|
defineProps,
|
|
@@ -157,6 +170,7 @@ const route = useRoute();
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
const total = ref(0);
|
|
const total = ref(0);
|
|
const scrollContainer = ref();
|
|
const scrollContainer = ref();
|
|
|
|
+const chooseAddressRef = ref();
|
|
const dataList = ref([]);
|
|
const dataList = ref([]);
|
|
import { goBackToApp, saveCode, downFly } from "@/utils/bridge";
|
|
import { goBackToApp, saveCode, downFly } from "@/utils/bridge";
|
|
const isLoading = ref(false);
|
|
const isLoading = ref(false);
|
|
@@ -170,6 +184,7 @@ const listTypeName = computed(() => {
|
|
});
|
|
});
|
|
const rectangle = ref();
|
|
const rectangle = ref();
|
|
const location = ref();
|
|
const location = ref();
|
|
|
|
+const sourceType = ref();
|
|
const itemRef = ref();
|
|
const itemRef = ref();
|
|
const option1 = [
|
|
const option1 = [
|
|
{ text: "全部", value: "" },
|
|
{ text: "全部", value: "" },
|
|
@@ -185,6 +200,7 @@ const option1 = [
|
|
const option2 = ref([
|
|
const option2 = ref([
|
|
{ text: "默认", value: 0 },
|
|
{ text: "默认", value: 0 },
|
|
{ text: "离我最近", value: 1 },
|
|
{ text: "离我最近", value: 1 },
|
|
|
|
+ { text: "选择位置", value: 2 },
|
|
]);
|
|
]);
|
|
|
|
|
|
const isReceivedColor = {
|
|
const isReceivedColor = {
|
|
@@ -213,42 +229,153 @@ const dataForm = ref({
|
|
limit: 15,
|
|
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) => {
|
|
const todetails = (e) => {
|
|
let ruters = {
|
|
let ruters = {
|
|
@@ -319,11 +457,26 @@ const changeisReceived = (event) => {
|
|
}
|
|
}
|
|
getList();
|
|
getList();
|
|
};
|
|
};
|
|
-const changelietType = () => {
|
|
|
|
|
|
+const changelietType = (x) => {
|
|
|
|
+ if (x == 2) {
|
|
|
|
+ chooseAddressRef.value.initMap();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
if (!rectangle.value) {
|
|
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;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
dataList.value = [];
|
|
dataList.value = [];
|
|
dataForm.value.page = 1;
|
|
dataForm.value.page = 1;
|
|
more.value = false;
|
|
more.value = false;
|
|
@@ -503,12 +656,21 @@ onMounted(() => {
|
|
|
|
|
|
// 获取滚动容器元素
|
|
// 获取滚动容器元素
|
|
const scrollContainer = document.getElementById("scroll-container");
|
|
const scrollContainer = document.getElementById("scroll-container");
|
|
-
|
|
|
|
|
|
+ rectangle.value = "";
|
|
// 监听滚动事件
|
|
// 监听滚动事件
|
|
scrollContainer.addEventListener("scroll", handleScroll);
|
|
scrollContainer.addEventListener("scroll", handleScroll);
|
|
-
|
|
|
|
getList(1);
|
|
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>
|
|
</script>
|
|
|
|
|
|
@@ -524,6 +686,7 @@ onMounted(() => {
|
|
table {
|
|
table {
|
|
width: 100%;
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
border-collapse: collapse;
|
|
|
|
+ font-size: 0.8rem;
|
|
}
|
|
}
|
|
|
|
|
|
thead {
|
|
thead {
|
|
@@ -537,7 +700,6 @@ td {
|
|
padding: 8px;
|
|
padding: 8px;
|
|
border: 1px solid #ddd;
|
|
border: 1px solid #ddd;
|
|
}
|
|
}
|
|
-
|
|
|
|
.bts {
|
|
.bts {
|
|
display: flex;
|
|
display: flex;
|
|
justify-content: space-around;
|
|
justify-content: space-around;
|