Przeglądaj źródła

修改外部链接根据Token获取用户信息来登录

mork 2 tygodni temu
rodzic
commit
e57f07a187

+ 42 - 4
README.md

@@ -1,16 +1,16 @@
 # data_demo
 
-## Project setup
+## 安装依赖
 ```
 npm install
 ```
 
-### Compiles and hot-reloads for development
+### 开发环境
 ```
 npm run serve
 ```
 
-### Compiles and minifies for production
+### 生产环境打包
 ```
 npm run build
 ```
@@ -28,4 +28,42 @@ npm run build
 "scripts": {
     "minify": "terser public/static/plugins/mapDraw.js -o public/static/plugins/mapDraw.min.js -m -c"
 },
-```
+```
+
+## 提交版本记录
+
+- **2026-04-27**
+1、 初始版本,包含基础功能
+2、 登录流程,添加 token 过期检测
+3、 数据上图功能,添加数据上图功能
+4、 首页看板图表,添加项目统计
+5、 Mapbox 地图配置,添加地图配置项
+6、 添加放大、缩小地图功能
+7、 添加地图点击事件
+8、 添加搜索地址功能
+
+- **2026-05-15**
+1、 优化登录流程,添加自动登录功能
+2、 优化地图配置项,添加地图配置项
+4、 Mapbox 地图配置,添加浅色、深色、影像地图配置项
+3、 添加员工数据统计显示
+4、 添加员工数据搜索功能
+5、 Mapbox地图添加绘制配置功能
+6、 添加项目搜索功能
+
+- **2026-05-22**
+1、 优化数据列表子级和员工的信息搜索功能
+2、 优化表格显示效果
+4、 优化Mapbox地图绘制功能
+3、 添加地图中心基线功能
+4、 数据图层添加显隐功能
+5、 列表分区统计显示
+6、 添加项目总数统计
+
+- **2026-06-18**
+1、 增加外部链接自动登陆功能
+2、 优化员工表格分页显示效果
+3、 优化项目信息显示效果
+
+- **2026-09-02**
+1、 优化外部链接自动登陆功能,添加根据token自动登陆验证功能

+ 6 - 0
src/api/common.js

@@ -16,6 +16,11 @@ const updatePassword = (params) => {
   return postform(webConfig.OAUTH_URL + '/user/updatePassword', params);
 }
 
+// 根据token获取用户信息
+const getUserByToken = (params) => {
+  return postform(webConfig.OAUTH_URL + '/api/user/getUserByToken', params);
+}
+
 // 更新内容
 const updateContent = (params) => {
   return postform(webConfig.DMS_URL + '/content/updateContent', params)
@@ -36,4 +41,5 @@ export default {
   updateContent,
   getDmsDataList,
   getModelById,
+  getUserByToken,
 }

+ 2 - 1
src/components/DrawMap.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="tool-bar glass">
+    <div class="tool-bar glass" :style="{ top: loginType == 'AUTO' ? '0px' : '60px' }">
       <button @click="startDraw('point')">🟢 绘点</button>
       <button @click="startDraw('line')">📏 绘线</button>
       <button @click="startDraw('polygon')">🔷 绘面</button>
@@ -24,6 +24,7 @@ export default {
       mapDraw: null,
       isEditDisabled: false,     // 是否禁用编辑功能
       isEditMode: false,        // 编辑模式
+      loginType: sessionStorage.getItem("gisLoginType") || '',
     };
   },
   mounted() {

+ 7 - 6
src/components/LeftMenu.vue

@@ -1,6 +1,6 @@
 <template>
-  <div class="container" ref="myContainer">
-    <div class="left-menu">
+  <div class="container" ref="myContainer" :style="{ marginTop: loginType == 'AUTO' ? '10px' : '70px' }">
+    <div class="left-menu" :style="{ height: loginType == 'AUTO' ? 'calc(100vh - 88px)' : 'calc(100vh - 150px)' }">
         <div class="search-box" v-if="isOpen">
             <el-autocomplete
             v-model="state"
@@ -14,7 +14,7 @@
             <template #append>共{{dataNumber}}条</template>
             </el-autocomplete>
         </div>
-        <div class="menu-content" ref="menuContent">
+        <div class="menu-content" ref="menuContent" :style="{ height: loginType == 'AUTO' ? 'calc(100vh - 170px)' : 'calc(100vh - 240px)' }">
             <!-- // accordion -->
              <!-- <el-collapse expand-icon-position="left" v-model="activeNames" @change="handleChange">
                 <el-collapse-item :title="list+'('+restaurants.filter(item => list.includes(item['市(区)'])).length+')'" :name="i" v-for="(list,i) in CITY_CODE_LIST" :key="list" >
@@ -75,6 +75,7 @@ export default {
         activeChildrenNames: [],
         arrParam: ["补查查询串","补查相似度","补查原因","补查匹配地址","补查点坐标","补查匹配名称","补查buffer_m","补查状态"], //过滤字段
         treeFilter: [],
+        loginType: sessionStorage.getItem("gisLoginType") || '',
     };
   },
   props: {
@@ -244,7 +245,7 @@ export default {
         }else{
             this.isOpen = true;
             this.isOpenText = "<";
-            this.$refs.myContainer.style.width = '400px';
+            this.$refs.myContainer.style.width = '360px';
             this.$refs.menuContent.style.padding = '0 20px';
         }
     }
@@ -303,7 +304,7 @@ export default {
 
 
 .container {
-    width: 400px;
+    width: 360px;
     // height: 100vh;
     position: fixed;
     top: 0px;
@@ -355,7 +356,7 @@ export default {
     position: absolute;
     top: 46.5%;
     z-index: 999;
-    left: 400px;
+    left: 360px;
     height: 50px;
     background: #01346f99;
     line-height: 50px;

+ 1 - 1
src/components/Map.vue

@@ -153,7 +153,7 @@ export default {
         columnId: 1719,
         modelId: 1753,
       };
-      // console.log(params);
+      console.log(params);
       commonAPI.updateContent(params).then(res => {
         if(res.code == 200){
           ElMessage.success("保存成功");

+ 89 - 0
src/utils/util.js

@@ -77,9 +77,98 @@ function geojsonToWkt(geojson) {
 
   throw new Error('不支持的几何类型: ' + geom.type);
 }
+/**
+ * WKT 转 GeoJSON Geometry,和 geojsonToWkt 成对使用
+ * @param {string} wktStr WKT字符串
+ * @returns {GeoJSON.Geometry} 几何对象
+ */
+function wktToGeoJson(wktStr) {
+  const s = wktStr.trim();
+
+  // 匹配类型,提取括号内内容
+  const pointReg = /^POINT\s*\(\s*([\d\.\-]+)\s+([\d\.\-]+)\s*\)$/i;
+  const lineReg = /^LINESTRING\s*\(\s*(.+?)\s*\)$/i;
+  const polygonReg = /^POLYGON\s*\(\s*(.+?)\s*\)$/i;
+  const multiPointReg = /^MULTIPOINT\s*\(\s*(.+?)\s*\)$/i;
+  const multiLineReg = /^MULTILINESTRING\s*\(\s*(.+?)\s*\)$/i;
+  const multiPolygonReg = /^MULTIPOLYGON\s*\(\s*(.+?)\s*\)$/i;
+  const geoCollReg = /^GEOMETRYCOLLECTION\s*\(\s*(.+?)\s*\)$/i;
+
+  // 辅助:把 "x y,x y" => [[x1,y1],[x2,y2]]
+  function parseCoordList(str) {
+    return str.split(',').map(p => {
+      const [x, y] = p.trim().split(/\s+/).map(Number);
+      return [x, y];
+    });
+  }
+
+  // 辅助:解析环集合 " (x y,...),(x y,...) "
+  function parseRingList(str) {
+    return str.match(/\(([^)]+)\)/g).map(ringStr => {
+      const inner = ringStr.replace(/[()]/g, '').trim();
+      return parseCoordList(inner);
+    });
+  }
+
+  // Point
+  let m = s.match(pointReg);
+  if (m) {
+    const [, x, y] = m;
+    return { type: 'Point', coordinates: [Number(x), Number(y)] };
+  }
+
+  // LineString
+  m = s.match(lineReg);
+  if (m) {
+    return { type: 'LineString', coordinates: parseCoordList(m[1]) };
+  }
+
+  // Polygon
+  m = s.match(polygonReg);
+  if (m) {
+    return { type: 'Polygon', coordinates: parseRingList(m[1]) };
+  }
+
+  // MultiPoint
+  m = s.match(multiPointReg);
+  if (m) {
+    return { type: 'MultiPoint', coordinates: parseCoordList(m[1]) };
+  }
+
+  // MultiLineString
+  m = s.match(multiLineReg);
+  if (m) {
+    const lines = parseRingList(m[1]);
+    return { type: 'MultiLineString', coordinates: lines };
+  }
+
+  // MultiPolygon
+  m = s.match(multiPolygonReg);
+  if (m) {
+    const polyStrs = m[1].match(/\(\([^)]+\)\)/g);
+    const polygons = polyStrs.map(pStr => {
+      const inner = pStr.replace(/^\(|\)$/g, '');
+      return parseRingList(inner);
+    });
+    return { type: 'MultiPolygon', coordinates: polygons };
+  }
+
+  // GeometryCollection
+  m = s.match(geoCollReg);
+  if (m) {
+    // 简单分割,只处理简单WKT,不处理嵌套括号复杂场景
+    const geoParts = m[1].split(/(?<=\))\s*,\s*(?=[A-Z])/i);
+    const geometries = geoParts.map(part => wktToGeoJson(part.trim()));
+    return { type: 'GeometryCollection', geometries };
+  }
+
+  throw new Error(`不支持的WKT类型:${s}`);
+}
+
 
 export default {
   terminalType,
   isChinese,
   geojsonToWkt,
+  wktToGeoJson,
 }

+ 57 - 25
src/views/AutoLogin.vue

@@ -7,6 +7,7 @@
 <script>
 import encrypt‌ from "@/utils/encrypt‌"; // 加密登录
 import { ElMessage, ElLoading } from "element-plus";
+import commonAPI from '@/api/common'
 
 export default {
   name: "AutoLogin",
@@ -26,48 +27,81 @@ export default {
     let that = this;
     // 监听父页面发来的消息
     window.addEventListener('message', async (e) => {
+      // console.log("校验发送来源:", e.origin);
       // 校验发送来源,防止恶意页面跨域发送消息
-      console.log("校验发送来源:", e.origin);
-      if (e.origin !== 'http://localhost:5173' && e.origin !== 'http://121.43.55.7:2124') return
+      if(!e.origin.includes("localhost") && !e.origin.includes("121.43.55.7")) {
+        ElMessage({
+          message: "加载失败",
+          type: "error",
+          duration: 1500
+        });
+      }else{
+        // that.showLoading();
         const data = e.data
         if (data.type === 'AUTO_LOGIN') {
-          const { username, password } = data
-          that.ruleForm.username = username;
-          that.ruleForm.password = password;
+          // const { username, password } = data
+          // that.ruleForm.username = username;
+          // that.ruleForm.password = password;
           // 执行登录
-          that.onAutoSubmit();
+          // that.onAutoSubmit();
+          const { token } = data
+          localStorage.setItem("token", token);
+          that.getUserByToken(token);
         }
-      })
+      }
+      
+    })
   },
   methods: {
     showLoading(){
         this.loginLoad = ElLoading.service({
           lock: true,
-          text: 'Loading',
-          background: 'rgba(0, 0, 0, 0.7)',
+          text: '加载地图中...',
+          background: '#1a2a3a',
         })
     },
+
+    getUserByToken(param){
+      // console.log(param,"getUserByToken");
+      let that = this;
+      sessionStorage.setItem("gisLoginType", "AUTO");//自动登录类型
+      // that.loginLoad.close();
+      that.$store.state.login = true;
+      that.$router.push("/index");
+      let params = {
+        serviceId: "0",
+        strUrl: "/api/user/getUserByToken",
+        token: param
+      }
+      commonAPI.getUserByToken(params).then((res) => {
+        //  console.log(res,"==================");
+        that.$store.state.user = res.content;
+        // that.$router.push("/index");
+      }).catch((err) => {
+        that.$store.state.user = null;
+        that.$router.push("/login");
+      });
+    },
     onAutoSubmit() {
       let that = this;
-      console.log("进来了");
-      this.showLoading();
       encrypt‌(that.ruleForm).then((res) => {
-            this.loginLoad.close();
+            that.loginLoad.close();
             that.$store.state.login = true;
             that.$store.state.user = res.content;
             that.$router.push("/index");
-            ElMessage({
-              message: "加载成功",
-              type: "success",
-              duration: 1500
-            });
+            // ElMessage({
+            //   message: "加载成功",
+            //   type: "success",
+            //   duration: 1500
+            // });
+            sessionStorage.setItem("gisLoginType", "AUTO");
         }).catch((err) => {
-          this.loginLoad.close();
-          ElMessage({
-              message: err,
-              type: "error",
-              duration: 1500
-          });
+          that.loginLoad.close();
+          // ElMessage({
+          //     message: err,
+          //     type: "error",
+          //     duration: 1500
+          // });
       });
     }
   }
@@ -78,8 +112,6 @@ export default {
 .main {
   height: 100%;
   width: 100%;
-  position: absolute;
-  background-color: #fffbf0;
 }
 
 </style>

+ 18 - 3
src/views/IndexView.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="home">
-    <Header></Header>
+    <Header v-if="loginType != 'AUTO'"></Header>
     <Map ref="childRef"/>
     <DrawMap></DrawMap>
 
-    <div class="search-box">
+    <div :class="loginType == 'AUTO' ? 'search-box-auto': 'search-box'">
       <div class="search-input">
         <el-autocomplete
         v-model="searchText"
@@ -66,7 +66,8 @@ export default {
       searchText: '',
       timeout:  null,
       selectType:'0',
-      ygDataList:[]
+      ygDataList:[],
+      loginType: sessionStorage.getItem("gisLoginType") || '',
     };
   },
   mounted() {
@@ -304,6 +305,20 @@ export default {
     border-radius: 4px;
   }
 }
+.search-box-auto {
+  position: absolute;
+  top: 0px;
+  left: 42%;
+  z-index: 999;
+  padding: 12px 20px;
+  width: 400px;
+  .search-input{
+    -webkit-backdrop-filter: blur(5px);
+    backdrop-filter: blur(5px);
+    background: #01346f99;
+    border-radius: 4px;
+  }
+}
 .map-box{
     position: fixed;
     right: 50px;

+ 2 - 0
src/views/Login.vue

@@ -84,6 +84,7 @@ export default {
           that.loginLoad = true;
           encrypt‌(that.ruleForm).then((res) => {
               // console.log(res);
+                sessionStorage.setItem("gisLoginType", "MANUAL");
                 that.loginLoad = false;
                 that.$store.state.login = true;
                 that.$store.state.user = res.content;
@@ -93,6 +94,7 @@ export default {
                   type: "success",
                   duration: 1500
                 });
+                
             }).catch((err) => {
               that.loginLoad = false;
               ElMessage({