Просмотр исходного кода

使用 gemini 优化 MapIndex.vue 和 AMap.vue 页面的 UI

reghao 1 день назад
Родитель
Сommit
ba79bf4718
3 измененных файлов с 324 добавлено и 109 удалено
  1. 2 0
      src/router/index.js
  2. 157 32
      src/views/map/AMap.vue
  3. 165 77
      src/views/map/MapIndex.vue

+ 2 - 0
src/router/index.js

@@ -4,6 +4,7 @@ import Vue from 'vue'
 import DiskRouter from './disk'
 import UserRouter from './user'
 import BlogRouter from './blog'
+import MapRouter from './map'
 import BackgroundDevopsRouter from './background_devops'
 import BackgroundAccountRouter from './background_account'
 import BackgroundMyRouter from './background_my'
@@ -45,6 +46,7 @@ export const constantRoutes = [
   DiskRouter,
   UserRouter,
   BlogRouter,
+  MapRouter,
   {
     path: '/',
     name: 'Vod',

+ 157 - 32
src/views/map/AMap.vue

@@ -1,38 +1,75 @@
 <template>
-  <el-container>
-    <el-header height="60">
-      <span style="float: left; padding: 5px; color: red">点击地图上任意点触发操作</span>
-      <el-button style="float: right; padding: 5px" type="text" @click="clearCircle">清除圆形</el-button>
-      <el-button style="float: right; padding: 5px" type="text" @click="onPathNavigator">路径巡航</el-button>
-      <el-button style="float: right; padding: 5px" type="text" @click="addPath">{{ addPathText }}</el-button>
+  <el-container class="map-sub-container">
+    <el-header height="50px" class="operation-header">
+      <div class="left-tip">
+        <i class="el-icon-info" />
+        <span>点击地图触发操作</span>
+      </div>
+      <div class="right-actions">
+        <el-button
+          :type="enableAddPath ? 'success' : 'primary'"
+          size="small"
+          icon="el-icon-plus"
+          @click="addPath"
+        >
+          {{ addPathText }}
+        </el-button>
+        <el-button type="info" size="small" icon="el-icon-guide" @click="onPathNavigator">
+          路径巡航
+        </el-button>
+        <el-button type="danger" size="small" plain icon="el-icon-delete" @click="clearCircle">
+          清除圆形
+        </el-button>
+      </div>
     </el-header>
-    <el-main>
-      <div id="container" class="text item amap-wrapper" />
+
+    <el-main class="map-main-wrapper">
+      <div id="container" class="amap-instance" />
     </el-main>
 
-    <el-dialog :visible.sync="showPositionDialog" width="30%" center>
-      <el-card class="box-card" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-        <div slot="header" class="clearfix">
-          <span>操作</span>
-          <el-button style="float: right; padding: 5px" type="text" @click="onSavePosition">保存坐标</el-button>
-          <el-button v-if="!showInput" style="float: right; padding: 5px" type="text" @click="onDrawCircle">绘制圆形</el-button>
-          <el-button style="float: right; padding: 5px" type="text" @click="onSaveMyPosition">保存为我的位置</el-button>
+    <el-dialog
+      :visible.sync="showPositionDialog"
+      width="400px"
+      custom-class="custom-map-dialog"
+      center
+      append-to-body
+    >
+      <div slot="title" class="dialog-title">
+        <i class="el-icon-location-information"></i>
+        <span>位置详情与操作</span>
+      </div>
+
+      <div class="dialog-body">
+        <div class="coord-display">
+          <div class="label">选定坐标:</div>
+          <div class="value" v-if="positionForm.lng !== null && positionForm.lat !== null">
+            {{ positionForm.lng.toFixed(6) }}, {{ positionForm.lat.toFixed(6) }}
+          </div>
+          <div class="value" v-else>-- , --</div>
+        </div>
+
+        <el-divider></el-divider>
+
+        <div v-if="showInput" class="radius-setter">
+          <p class="input-tip">设置绘制半径 (米)</p>
+          <div class="input-row">
+            <el-input-number
+              v-model="radius"
+              :min="10"
+              :max="10000"
+              controls-position="right"
+              style="width: 100%"
+            />
+            <el-button type="primary" @click="handleNumChange" style="margin-top: 15px; width: 100%">确定半径并绘制</el-button>
+          </div>
         </div>
-        <div class="text item">
-          <el-row>
-            <span style="color: #0a84ff">
-              选中的坐标: <span style="color: red">({{ positionForm.lng }}, {{ positionForm.lat }})</span>
-            </span>
-          </el-row>
-          <el-row>
-            <span v-if="showInput">
-              选择半径(单位米):
-              <el-input-number v-model="radius" :min="0" :max="10000" style="margin-left: 5px" />
-              <el-button style="float: right; padding: 5px" type="text" @click="handleNumChange">确定半径</el-button>
-            </span>
-          </el-row>
+
+        <div v-else class="action-grid">
+          <el-button icon="el-icon-document-add" @click="onSavePosition">保存坐标</el-button>
+          <el-button icon="el-icon-magic-stick" type="success" @click="onDrawCircle">绘制圆形</el-button>
+          <el-button icon="el-icon-star-off" type="warning" @click="onSaveMyPosition">设为我的位置</el-button>
         </div>
-      </el-card>
+      </div>
     </el-dialog>
   </el-container>
 </template>
@@ -332,9 +369,97 @@ export default {
 }
 </script>
 
-<style>
-.amap-wrapper {
+<style scoped lang="scss">
+.map-sub-container {
+  height: 100%;
+  background-color: #fff;
+  border-radius: 8px;
+  overflow: hidden;
+  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
+}
+
+.operation-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background-color: #fcfcfc;
+  border-bottom: 1px solid #ebeef5;
+  padding: 0 15px !important;
+
+  .left-tip {
+    color: #f56c6c;
+    font-size: 13px;
+    display: flex;
+    align-items: center;
+    i { margin-right: 5px; }
+  }
+
+  .right-actions {
+    display: flex;
+    gap: 10px;
+  }
+}
+
+.map-main-wrapper {
+  padding: 0 !important;
+  position: relative;
+}
+
+.amap-instance {
   width: 100%;
-  height: 600px;
+  height: calc(100vh - 180px); // 动态计算高度,适配父级 MapIndex
+}
+
+/* 对话框美化 */
+::v-deep .custom-map-dialog {
+  border-radius: 12px;
+  .el-dialog__header {
+    padding: 20px;
+    border-bottom: 1px solid #f2f6fc;
+  }
+  .el-dialog__body {
+    padding: 10px 25px 30px;
+  }
+}
+
+.dialog-title {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.coord-display {
+  background: #f0f7ff;
+  padding: 15px;
+  border-radius: 8px;
+  text-align: center;
+  .label { font-size: 12px; color: #79bbff; margin-bottom: 5px; }
+  .value { font-family: 'Courier New', Courier, monospace; font-weight: bold; color: #409EFF; font-size: 16px; }
+}
+
+.action-grid {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  .el-button {
+    margin-left: 0 !important;
+    justify-content: flex-start;
+  }
+}
+
+.radius-setter {
+  .input-tip { font-size: 13px; color: #909399; margin-bottom: 10px; }
+}
+
+/* 按钮悬浮动画 */
+.el-button {
+  transition: all 0.2s ease;
+  &:hover {
+    transform: translateY(-1px);
+    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+  }
 }
 </style>

+ 165 - 77
src/views/map/MapIndex.vue

@@ -1,72 +1,60 @@
 <template>
-  <el-container style="border: 1px solid #eee">
-    <el-header style="text-align: right; font-size: 12px">
-      <el-col :md="2">
-        <ul class="el-menu--horizontal el-menu">
-          <li class="el-menu-item">
-            <a href="/map" style="text-decoration-line: none">
-              <img src="@/assets/img/logo.png" class="el-avatar--circle el-avatar--medium" alt="img">
-              map
-            </a>
-          </li>
-        </ul>
-      </el-col>
-      <el-col :md="20">
-        <el-menu
-          :default-active="this.$route.path"
-          router
-          mode="horizontal"
-        >
-          <el-menu-item index="/map/photo">
-            <i class="el-icon-map-location" />
-            <span slot="title">照片地图</span>
-          </el-menu-item>
-          <el-menu-item index="/map/chart">
-            <i class="el-icon-map-location" />
-            <span slot="title">数据地图</span>
-          </el-menu-item>
-          <el-menu-item index="/map/ol">
-            <i class="el-icon-map-location" />
-            <span slot="title">OL地图</span>
-          </el-menu-item>
-        </el-menu>
-      </el-col>
-      <el-col :md="2">
-        <ul class="el-menu--horizontal el-menu">
-          <li class="el-menu-item">
-            <el-dropdown v-if="user">
-              <img
-                :src="user.avatarUrl"
-                class="el-avatar--circle el-avatar--medium"
-                style="margin-right: 10px; margin-top: 15px"
-                alt=""
-              >
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item
-                  icon="el-icon-s-platform"
-                  class="size"
-                  @click.native="goToHome"
-                >主站</el-dropdown-item>
-                <el-dropdown-item
-                  icon="el-icon-error"
-                  class="size"
-                  @click.native="goToLogout"
-                >退出</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-            <span
-              v-else
-              style="color: #007bff"
-            >登入</span>
-          </li>
-        </ul>
-      </el-col>
+  <el-container class="map-layout-container">
+    <el-header class="map-header" height="64px">
+      <div class="header-content">
+        <div class="logo-area">
+          <router-link to="/map" class="logo-link">
+            <img src="@/assets/img/logo.png" alt="logo" class="logo-img">
+            <span class="logo-text">地图</span>
+          </router-link>
+        </div>
+
+        <div class="menu-area">
+          <el-menu
+            :default-active="$route.path"
+            router
+            mode="horizontal"
+            class="custom-map-menu"
+          >
+            <el-menu-item index="/map/photo">
+              <i class="el-icon-picture-outline" />
+              <span>照片地图</span>
+            </el-menu-item>
+            <el-menu-item index="/map/chart">
+              <i class="el-icon-data-analysis" />
+              <span>数据地图</span>
+            </el-menu-item>
+            <el-menu-item index="/map/ol">
+              <i class="el-icon-map-location" />
+              <span>OL地图</span>
+            </el-menu-item>
+          </el-menu>
+        </div>
+
+        <div class="user-area">
+          <el-dropdown v-if="user" trigger="hover">
+            <div class="avatar-wrapper">
+              <img :src="user.avatarUrl" class="user-avatar" alt="avatar">
+              <i class="el-icon-caret-bottom" />
+            </div>
+            <el-dropdown-menu slot="dropdown" class="user-dropdown">
+              <el-dropdown-item icon="el-icon-s-platform" @click.native="goToHome">主站首页</el-dropdown-item>
+              <el-dropdown-item icon="el-icon-switch-button" divided @click.native="goToLogout">退出登录</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+
+          <el-button v-else type="primary" size="small" round @click="$router.push('/login')">
+            登 录
+          </el-button>
+        </div>
+      </div>
     </el-header>
-    <el-container>
-      <el-main>
-        <router-view />
-      </el-main>
-    </el-container>
+
+    <el-main class="map-main">
+      <transition name="fade-transform" mode="out-in">
+        <router-view :key="$route.fullPath" />
+      </transition>
+    </el-main>
   </el-container>
 </template>
 
@@ -82,20 +70,120 @@ export default {
       user: null
     }
   },
-  watch: {
-    // 地址栏 url 发生变化时重新加载本页面
-    $route() {
-      this.$router.go()
-    }
-  },
+  // 删除了 $route 的 watch,避免死循环刷新
   created() {
-    const userInfo = getAuthedUser()
-    if (userInfo !== null) {
-      this.user = userInfo
+    this.initUser()
+  },
+  methods: {
+    initUser() {
+      const userInfo = getAuthedUser()
+      if (userInfo) {
+        this.user = userInfo
+      }
     }
   }
 }
 </script>
 
-<style>
+<style lang="scss" scoped>
+.map-layout-container {
+  min-height: 100vh;
+  background-color: #f5f7fa;
+}
+
+.map-header {
+  background: #ffffff;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+  position: sticky;
+  top: 0;
+  z-index: 1000;
+  padding: 0 40px;
+}
+
+.header-content {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 100%;
+}
+
+/* Logo 样式 */
+.logo-area {
+  .logo-link {
+    display: flex;
+    align-items: center;
+    text-decoration: none;
+    transition: transform 0.3s;
+    &:hover { transform: scale(1.02); }
+  }
+  .logo-img {
+    width: 32px;
+    height: 32px;
+    border-radius: 50%;
+    margin-right: 10px;
+  }
+  .logo-text {
+    font-size: 18px;
+    font-weight: bold;
+    color: #303133;
+    letter-spacing: 1px;
+  }
+}
+
+/* 菜单样式重置 */
+.menu-area {
+  flex: 1;
+  margin: 0 40px;
+  .custom-map-menu.el-menu--horizontal {
+    border-bottom: none;
+    display: flex;
+    justify-content: center;
+
+    .el-menu-item {
+      height: 64px;
+      line-height: 64px;
+      font-size: 15px;
+      &:hover { background-color: transparent !important; color: #409EFF !important; }
+      &.is-active { border-bottom-width: 3px; font-weight: bold; }
+    }
+  }
+}
+
+/* 用户区域 */
+.user-area {
+  .avatar-wrapper {
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    .user-avatar {
+      width: 36px;
+      height: 36px;
+      border-radius: 50%;
+      border: 2px solid #ebeef5;
+      transition: border-color 0.3s;
+      &:hover { border-color: #409EFF; }
+    }
+    i { margin-left: 5px; color: #909399; }
+  }
+}
+
+.map-main {
+  padding: 20px;
+  /* 确保地图容器高度能撑满 */
+  height: calc(100vh - 64px);
+  overflow-y: auto;
+}
+
+/* 简单过渡动画 */
+.fade-transform-enter-active, .fade-transform-leave-active {
+  transition: all .3s;
+}
+.fade-transform-enter {
+  opacity: 0;
+  transform: translateX(-10px);
+}
+.fade-transform-leave-to {
+  opacity: 0;
+  transform: translateX(10px);
+}
 </style>