Эх сурвалжийг харах

升级@fs-admin/core
增加百度地图点位选择和轨迹播放

XueNing 5 сар өмнө
parent
commit
5c66b1cbee

+ 4 - 0
index.html

@@ -6,6 +6,10 @@
     <link rel="icon" href="/logo.png" />
     <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
     <title></title>
+
+    <!-- 如需使用百度地图,打开下方注释 -->
+    <!-- <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=应用ak"></script>
+    <script type="text/javascript" src="//bj.bcebos.com/v1/mapopen/github/BMapGLLib/Lushu/src/Lushu.min.js"></script> -->
   </head>
   <body>
     <div id="app"></div>

+ 3 - 2
package.json

@@ -14,8 +14,9 @@
     "micro": "plop micro"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "@element-plus/icons-vue": "^2.3.1",
-    "@fskj-admin/core": "^1.3.1",
+    "@fskj-admin/core": "^1.3.4",
     "@fskj-admin/micro": "^0.1.0",
     "@icon-park/vue-next": "^1.4.2",
     "@sentry/vue": "^8.9.2",
@@ -67,4 +68,4 @@
     "vite-plugin-vue-devtools": "^7.3.1",
     "vue-tsc": "^2.0.21"
   }
-}
+}

+ 13 - 14
pnpm-lock.yaml

@@ -8,12 +8,15 @@ importers:
 
   .:
     dependencies:
+      '@amap/amap-jsapi-loader':
+        specifier: ^1.0.1
+        version: 1.0.1
       '@element-plus/icons-vue':
         specifier: ^2.3.1
         version: 2.3.1(vue@3.4.29(typescript@5.3.3))
       '@fskj-admin/core':
-        specifier: ^1.3.1
-        version: 1.3.1
+        specifier: ^1.3.4
+        version: 1.3.4
       '@fskj-admin/micro':
         specifier: ^0.1.0
         version: 0.1.0
@@ -162,6 +165,9 @@ importers:
 
 packages:
 
+  '@amap/amap-jsapi-loader@1.0.1':
+    resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==}
+
   '@ampproject/remapping@2.3.0':
     resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
     engines: {node: '>=6.0.0'}
@@ -535,8 +541,8 @@ packages:
   '@floating-ui/utils@0.2.2':
     resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==}
 
-  '@fskj-admin/core@1.3.1':
-    resolution: {integrity: sha512-8ZGO75r5rdAttCSCLUAvXm468di9WlV2MQxG3DA4gibZS679T6sRHiDiv+Sk3xRMDJ8hi4Ngi1LQAyxwkS/Egg==}
+  '@fskj-admin/core@1.3.4':
+    resolution: {integrity: sha512-xb1rOIY5n8Qjm/ATvXqmd1LlQN4RxzQoFAv3IW/Y2pJ3xEsSAjOnJkUeYcnw9hC3fNOXMOwaf5kocBp0E1PyNA==}
 
   '@fskj-admin/micro@0.1.0':
     resolution: {integrity: sha512-4Dbg7mubKcDu+jaqll+oY6/7v08h9mh9BTncVkEHd9T4Aqg8ZzcCASaKvrCPhP6/ldgUBrM0MimmzJh0geVXnQ==}
@@ -655,55 +661,46 @@ packages:
     resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
     cpu: [arm]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-arm-musleabihf@4.18.0':
     resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
     cpu: [arm]
     os: [linux]
-    libc: [musl]
 
   '@rollup/rollup-linux-arm64-gnu@4.18.0':
     resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
     cpu: [arm64]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-arm64-musl@4.18.0':
     resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
     cpu: [arm64]
     os: [linux]
-    libc: [musl]
 
   '@rollup/rollup-linux-powerpc64le-gnu@4.18.0':
     resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
     cpu: [ppc64]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-riscv64-gnu@4.18.0':
     resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
     cpu: [riscv64]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-s390x-gnu@4.18.0':
     resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
     cpu: [s390x]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-x64-gnu@4.18.0':
     resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
     cpu: [x64]
     os: [linux]
-    libc: [glibc]
 
   '@rollup/rollup-linux-x64-musl@4.18.0':
     resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
     cpu: [x64]
     os: [linux]
-    libc: [musl]
 
   '@rollup/rollup-win32-arm64-msvc@4.18.0':
     resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
@@ -4223,6 +4220,8 @@ packages:
 
 snapshots:
 
+  '@amap/amap-jsapi-loader@1.0.1': {}
+
   '@ampproject/remapping@2.3.0':
     dependencies:
       '@jridgewell/gen-mapping': 0.3.5
@@ -4620,7 +4619,7 @@ snapshots:
 
   '@floating-ui/utils@0.2.2': {}
 
-  '@fskj-admin/core@1.3.1': {}
+  '@fskj-admin/core@1.3.4': {}
 
   '@fskj-admin/micro@0.1.0': {}
 

+ 275 - 2
src/components/FsMapPicker/components/baidu.vue

@@ -1,13 +1,286 @@
 <script setup lang="ts">
+import { CircleCheck, Location, Plus, Search } from '@element-plus/icons-vue'
+import { ElMessage, type AutocompleteInstance } from 'element-plus'
+
+const ICON_CLASS = 'map-main-marker'
+
+const emits = defineEmits(['done'])
+
+const props = defineProps([
+  'modelValue',
+  'height',
+  'center',
+  'mapKey',
+  'markerSrc',
+  'zoom',
+  'selectedZoom',
+  'mapStyle',
+  'poiType',
+  'poiRadius',
+  'poiKeywords',
+  'okText',
+  'required',
+  'message',
+  'suggestionCity'
+])
+
+let mapIns: any = null
+// 地图容器
+const mapRef = ref<any>()
+const autocompleteRef = ref<AutocompleteInstance>()
+
+// 是否是poi列表点击移动
+const isItemClickMove = ref<boolean>(false)
+// 图标样式
+const centerIconClass = ref<Array<string>>([ICON_CLASS])
+
+// 当前选中
+const current = ref<any>(null)
+
+// 是否加载中
+const loading = ref<boolean>(false)
+
+const poiData = ref<any[]>([])
+
+// 关键字
+const keywords = ref<string>('')
+// 最后一次搜索关键字
+const lastKeywords = ref<any>(null)
+
+// 关键字搜索数据
+const suggestionData = ref<any[]>([])
+
 onMounted(() => {
   initMap()
 })
 /* 初始化地图 */
-const initMap = () => {}
+const initMap = () => {
+  mapIns = new BMapGL.Map(mapRef.value) // 创建Map实例
+  mapIns.centerAndZoom(new BMapGL.Point(props.center[0], props.center[1]), props.zoom) // 初始化地图,设置中心点坐标和地图级别
+  mapIns.enableScrollWheelZoom(true) //开启鼠标滚轮缩放
+  if (props.mapStyle) {
+    mapIns.setMapStyleV2({ styleId: props.mapStyle })
+  }
+
+  mapIns.on('moveend', () => {
+    if (isItemClickMove.value) {
+      isItemClickMove.value = false
+      return
+    }
+    bounceIcon()
+    const { lng, lat } = mapIns.getCenter()
+    searchPOI(lng, lat)
+  })
+
+  // 第一次加载
+  searchPOI(props.center[0], props.center[1])
+}
+
+/* poi 搜索 */
+const searchPOI = (lng: number, lat: number) => {
+  loading.value = true
+  current.value = null
+  searchNearBy(lng, lat)
+    .then(res => {
+      loading.value = false
+      poiData.value = res
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+
+/* 设置地图中心点 */
+const setMapCenter = (lng: number, lat: number, zoom: number) => {
+  if (lng && lat) {
+    if (zoom == null) {
+      mapIns.setCenter([lng, lat])
+    } else {
+      mapIns.flyTo(new BMapGL.Point(lng, lat), zoom)
+    }
+  }
+}
+
+/* poi 点击 */
+const handleItemClick = (item: any) => {
+  const { lng, lat } = item
+  setMapCenter(lng, lat, props.selectedZoom)
+  isItemClickMove.value = true
+  current.value = item
+}
+
+/* 让地图图标跳动 */
+const bounceIcon = () => {
+  nextTick(() => {
+    centerIconClass.value = [ICON_CLASS]
+    setTimeout(() => {
+      centerIconClass.value = [ICON_CLASS, 'map-main-marker-bounce']
+    }, 0)
+  })
+}
+
+/* 确认选择 */
+const handleConfirm = () => {
+  // 是否强制选择
+  if (props.required && !current.value) {
+    ElMessage.error(props.message)
+    return
+  }
+  // 如果右侧不选择,则返回当前中心点
+  const { lng, lat } = mapIns.getCenter()
+  emits('done', current.value || { lng, lat })
+}
+
+/* 关键字搜索 */
+const handleSelect = (keyword: string, callback?: any) => {
+  if (!keyword || lastKeywords.value === keyword) {
+    callback && callback(suggestionData.value)
+    return
+  }
+  lastKeywords.value = keyword
+  searchKeywords(keyword)
+    .then(result => {
+      suggestionData.value = result
+      callback && callback(suggestionData.value)
+    })
+    .catch((e: Error) => {
+      console.error(e)
+      callback && callback(suggestionData.value)
+    })
+}
+
+/* 关键字搜索选中 */
+const handleSelectSelect = (item: any) => {
+  autocompleteRef.value && autocompleteRef.value.blur()
+  const { lng, lat } = item
+  setMapCenter(lng, lat, props.selectedZoom)
+  bounceIcon()
+}
+
+/* 检索附近兴趣点 */
+const searchNearBy = (lng: number, lat: number): Promise<any[]> => {
+  return new Promise((resolve, reject) => {
+    jsonp(
+      `https://api.map.baidu.com/place/v2/search?query=${props.poiKeywords}&location=${lat},${lng}&radius=${props.poiRadius}&page_size=20&output=json&ak=${props.mapKey}`,
+      (result: any) => {
+        if (result.status === 0) {
+          resolve(result.results.map((d: any) => formatPoi(d)))
+        } else {
+          reject(new Error(result.message))
+          return
+        }
+      }
+    )
+  })
+}
+
+// 关键字检索
+const searchKeywords = (keyword: string): Promise<any[]> => {
+  return new Promise((resolve, reject) => {
+    jsonp(
+      `https://api.map.baidu.com/place/v2/suggestion?query=${keyword}&region=${props.suggestionCity}&city_limit=true&output=json&ak=${props.mapKey}`,
+      (res: any) => {
+        if (res.status === 0) {
+          const tips = (res.result as any[]).filter(d => !!d.location)
+          resolve(tips.map(d => formatPoi(d)))
+        } else {
+          reject(new Error(res.message))
+        }
+      }
+    )
+  })
+}
+
+const jsonp = (url: string, callback: Function) => {
+  // 创建一个随机的回调函数名,避免命名冲突
+  const callbackFuncName = 'jsonp_callback_' + Math.round(100000 * Math.random())
+  // 将回调函数名添加到 URL 的查询参数中
+  url += (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callbackFuncName
+  // 创建一个全局的回调函数
+  ;(window as any)[callbackFuncName] = function (data: any) {
+    // 回调函数执行后,删除全局函数并释放资源
+    delete (window as any)[callbackFuncName]
+    document.body.removeChild(script)
+
+    // 调用传入的回调函数处理数据
+    callback(data)
+  }
+  // 创建一个 script 标签
+  const script = document.createElement('script')
+  script.src = url
+
+  // 将 script 标签插入到页面中,发起 JSONP 请求
+  document.body.appendChild(script)
+}
+
+/* 格式化返回的点位 */
+const formatPoi = (item: any) => {
+  return {
+    ...item,
+    lng: item.location.lng,
+    lat: item.location.lat
+  }
+}
+
+onBeforeUnmount(() => {
+  /* 销毁地图 */
+  mapIns && mapIns.destroy()
+  mapIns = null
+  current.value = null
+  loading.value = false
+  poiData.value = []
+})
 </script>
 
 <template>
-  <div></div>
+  <div class="map-container">
+    <div class="map-main">
+      <div ref="mapRef" :style="{ height }"></div>
+      <el-icon class="map-icon-plus" color="var(--el-color-primary)">
+        <Plus />
+      </el-icon>
+      <img :src="markerSrc" :class="centerIconClass" />
+      <el-autocomplete
+        v-model="keywords"
+        valueKey="name"
+        :clearable="true"
+        :fetch-suggestions="handleSelect"
+        placeholder="请输入关键字进行搜索"
+        @select="handleSelectSelect"
+        class="map-keywrod-input"
+        ref="autocompleteRef"
+      >
+        <template #prefix>
+          <el-icon class="el-input__icon">
+            <Search />
+          </el-icon>
+        </template>
+      </el-autocomplete>
+    </div>
+    <div class="map-poi-side">
+      <div class="map-poi-list" v-loading="loading">
+        <div class="map-poi-item" v-for="item in poiData" :key="item.id" @click="handleItemClick(item)">
+          <div class="map-poi-icon">
+            <el-icon size="18">
+              <Location />
+            </el-icon>
+          </div>
+          <div class="map-poi-desc">
+            <div class="map-poi-title">{{ item.name }}</div>
+            <div class="map-poi-address">{{ item.address }}</div>
+          </div>
+          <div class="map-poi-icon map-poi-icon-checked">
+            <el-icon size="18" color="var(--el-color-primary)" v-if="current === item">
+              <CircleCheck />
+            </el-icon>
+          </div>
+        </div>
+      </div>
+      <div class="map-poi-button">
+        <el-button type="primary" @click="handleConfirm" style="width: 100%">{{ okText }}</el-button>
+      </div>
+    </div>
+  </div>
 </template>
 
 <style scoped lang="scss"></style>

+ 3 - 2
src/components/FsMapPicker/index.vue

@@ -19,7 +19,8 @@ const props = withDefaults(defineProps<MapPickerProps>(), {
   zoom: 11,
   selectedZoom: 17,
   message: '请选择位置',
-  okText: '确定'
+  okText: '确定',
+  poiKeywords: ''
 })
 
 /* 处理选择完成事件 */
@@ -45,7 +46,7 @@ const updateModalValue = (modelValue: boolean) => {
       <!-- 高德地图 -->
       <Amap v-if="type === 'amap'" v-bind="props" :style="{ height }" @done="handleDone" />
       <!-- 百度地图 -->
-      <BaiDu v-else />
+      <BaiDu v-else v-bind="props" :style="{ height }" @done="handleDone" />
     </template>
   </el-dialog>
 </template>

+ 2 - 2
src/components/FsPrinter/index.vue

@@ -94,7 +94,7 @@ defineExpose({
           </td>
         </tr>
       </tbody>
-      <tfoot v-if="$slots.footer">
+      <!-- <tfoot v-if="$slots.footer">
         <tr>
           <td>
             <div class="custom-printer-footer" :style="footerStyle">
@@ -102,7 +102,7 @@ defineExpose({
             </div>
           </td>
         </tr>
-      </tfoot>
+      </tfoot> -->
     </table>
   </Teleport>
 </template>

+ 2 - 0
src/global.d.ts

@@ -0,0 +1,2 @@
+declare var BMapGL: any
+declare var BMapGLLib: any

+ 0 - 3
src/views/extension/imageUpload/index.vue

@@ -58,9 +58,6 @@ const submit = () => {
         <el-radio label="否" :value="false"> </el-radio>
       </el-radio-group>
     </div>
-    <div>
-      {{ images }}
-    </div>
   </el-card>
   <el-card header="支持多选" shadow="never" class="mt-3">
     <el-image-upload v-model="images2" multiple :limit="5" :uploadFunction="uploadFunction" @remove="onRemove" />

+ 1 - 1
src/views/extension/map/amap.vue

@@ -24,7 +24,7 @@ const mapPickerDone = (data: any) => {
       <p>详细信息:{{ mapData.address }}</p>
     </div>
     <el-button type="primary" @click="openPicker">打开地图选择</el-button>
-    <FsMapPicker v-model="showPicker" map-key="80b0e2d75dc7bb2534e9d6e8ed79ab9e" @done="mapPickerDone" />
+    <FsMapPicker v-model="showPicker" map-key="" @done="mapPickerDone" />
   </div>
 </template>
 

+ 1 - 1
src/views/extension/map/amapTrack.vue

@@ -36,7 +36,7 @@ const lineData = [
 /* 渲染轨迹回放地图 */
 const renderTrackMap = () => {
   AMapLoader.load({
-    key: '80b0e2d75dc7bb2534e9d6e8ed79ab9e',
+    key: '',
     version: '2.0',
     plugins: ['AMap.MoveAnimation', 'AMap.Marker', 'AMap.Polyline']
   })

+ 42 - 0
src/views/extension/map/baidu.vue

@@ -0,0 +1,42 @@
+<script setup lang="ts">
+// 是否显示地图位置选择
+const showMapPicker = ref<boolean>(false)
+
+const mapData = ref({
+  lat: '',
+  lng: '',
+  name: '',
+  address: ''
+})
+
+/* 打开位置选择 */
+const openPicker = () => {
+  showMapPicker.value = true
+}
+
+/* 地图选择完毕 */
+const mapPickerDone = (data: any) => {
+  mapData.value = data
+}
+</script>
+
+<template>
+  <div>
+    <div>
+      <p>经度:{{ mapData.lng }}</p>
+      <p>纬度:{{ mapData.lat }}</p>
+      <p>地址:{{ mapData.name }}</p>
+      <p>详细信息:{{ mapData.address }}</p>
+    </div>
+    <el-button type="primary" @click="openPicker">打开地图选择</el-button>
+    <fs-map-picker
+      v-model="showMapPicker"
+      type="baidu"
+      poiKeywords="美食$银行$酒店$公园$学校$超市$医院"
+      map-key=""
+      @done="mapPickerDone"
+    ></fs-map-picker>
+  </div>
+</template>
+
+<style scoped lang="scss"></style>

+ 107 - 0
src/views/extension/map/baiduTrack.vue

@@ -0,0 +1,107 @@
+<script lang="ts" setup>
+/* 地图容器 */
+const trackMapRef = ref<HTMLElement | null>(null)
+
+/* 小车轨迹地图的实例 */
+let mapInsTrack: any
+
+let lushu: any
+
+/* 轨迹路线 */
+const lineData = [
+  [112.55863627550298, 37.86535449354035],
+  [112.56712335932487, 37.86535449354035],
+  [112.5799752291123, 37.866315720275935],
+  [112.58821982482502, 37.866507964105715],
+  [112.59234212268136, 37.866315720275935],
+  [112.59258461079057, 37.85997139015577],
+  [112.59282709889975, 37.85381878648066],
+  [112.59258461079057, 37.84901170452819],
+  [112.59258461079057, 37.83881964551115],
+  [112.59306958700896, 37.83478088959811],
+  [112.59403953944575, 37.83151125720199],
+  [112.59015972969863, 37.82227856519498],
+  [112.57294307394565, 37.82381742809322],
+  [112.5688207760893, 37.82362507200052],
+  [112.55839378739381, 37.82381742809322],
+  [112.54820928680755, 37.82343271540223],
+  [112.54263206029601, 37.82381742809322]
+]
+
+/* 渲染轨迹回放地图 */
+const renderTrackMap = () => {
+  mapInsTrack = new BMapGL.Map(trackMapRef.value) // 创建Map实例
+  mapInsTrack.centerAndZoom(new BMapGL.Point(112.55863627550298, 37.86535449354035), 12) // 初始化地图,设置中心点坐标和地图级别
+  mapInsTrack.enableScrollWheelZoom(true) //开启鼠标滚轮缩放
+
+  createLine()
+  // 创建路书
+  createLuShu()
+}
+
+/* 绘制线路 */
+const createLine = () => {
+  const polyline = new BMapGL.Polyline(
+    lineData.map((item: any) => new BMapGL.Point(item[0], item[1])),
+    {
+      strokeColor: '#ff0000',
+      strokeWeight: 4,
+      strokeOpacity: 1
+    }
+  )
+  mapInsTrack.addOverlay(polyline)
+}
+
+/* 创建路书 */
+const createLuShu = () => {
+  // 存在清除
+  if (lushu) {
+    lushu.stop()
+    lushu = null
+  }
+  // 删除选择之前的坐标
+  lushu = new BMapGLLib.LuShu(
+    mapInsTrack,
+    lineData.map((item: any) => new BMapGL.Point(item[0], item[1])),
+    {
+      autoView: true, // 是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
+      icon: new BMapGL.Icon(
+        'https://bj.bcebos.com/v1/mapopen/github/BMapGLLib/Lushu/examples/images/car.png',
+        new BMapGL.Size(42, 52),
+        { anchor: new BMapGL.Size(10, 10) }
+      ),
+      speed: 1000, // 速度
+      enableRotation: true // 是否设置marker随着道路的走向进行旋转
+    }
+  )
+}
+
+const startTrackAnim = () => {
+  lushu && lushu.start()
+}
+
+const pauseTrackAnim = () => {
+  lushu && lushu.pause()
+}
+
+/* 渲染地图 */
+onMounted(() => {
+  renderTrackMap()
+})
+
+/* 销毁地图 */
+onBeforeUnmount(() => {
+  if (mapInsTrack) {
+    mapInsTrack.destroy()
+    mapInsTrack = null
+  }
+})
+</script>
+
+<template>
+  <div ref="trackMapRef" style="height: 360px; max-width: 800px; margin-bottom: 16px"></div>
+  <div>
+    <el-button type="primary" @click="startTrackAnim"> 开始移动 </el-button>
+    <el-button type="primary" @click="pauseTrackAnim"> 暂停移动 </el-button>
+  </div>
+</template>

+ 7 - 106
src/views/extension/map/index.vue

@@ -1,108 +1,8 @@
 <script setup lang="ts">
 import Amap from './amap.vue'
 import AmapTrack from './amapTrack.vue'
-let bmap: any = null
-let lushu: any = null
-
-const data = [
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.483671256780845,
-    lon: 112.35835768559537
-  },
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.48392562378963,
-    lon: 112.35380873633531
-  },
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.484445885520906,
-    lon: 112.34942980034347
-  },
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.484613829160985,
-    lon: 112.34826673209832
-  },
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.48548191169621,
-    lon: 112.34776796383788
-  },
-  {
-    licensePlate: '',
-    speed: 47,
-    sendData: 1718434061000,
-    lat: 36.48727931765302,
-    lon: 112.34804304633398
-  }
-]
-
-const points: any = []
-
-onMounted(() => {
-  initMap()
-})
-
-const initMap = () => {
-  const center = new (window as any).BMap.Point(112.35835768559537, 36.483671256780845)
-  bmap = new (window as any).BMap.Map('map') // 创建Map实例
-  bmap.centerAndZoom(center, 14) // 初始化地图,设置中心点坐标和地图级别
-  bmap.enableScrollWheelZoom(true) // 开启鼠标滚轮缩放
-
-  // 初始化数据
-  for (let i = 0; i < data.length; i++) {
-    points.push(new (window as any).BMap.Point(data[i].lon, data[i].lat))
-  }
-
-  createTrack()
-}
-
-/* 开始动画 */
-const start = () => {
-  if (lushu) {
-    lushu.start()
-    lushu.showInfoWindow()
-  }
-}
-
-/* 暂停动画 */
-const pause = () => {
-  if (lushu) {
-    lushu.pause()
-  }
-}
-
-/* 创建轨迹动画 */
-const createTrack = () => {
-  // 实例化一个驾车导航用来生成路线
-  bmap.addOverlay(new (window as any).BMap.Polyline(points, { strokeColor: 'red' }))
-  bmap.setViewport(points)
-
-  lushu = new (window as any).BMapLib.LuShu(bmap, points, {
-    defaultContent: '默认内容',
-    autoView: true, //是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
-    icon: new (window as any).BMap.Icon('/car.png', new (window as any).BMap.Size(52, 26), {
-      anchor: new (window as any).BMap.Size(27, 13)
-    }),
-    speed: 500,
-    enableRotation: true //是否设置marker随着道路的走向进行旋转
-  })
-  console.log(lushu)
-  // const start = new (window as any).BMap.Point(points[0].lng, points[0].lat)
-  // const end = new (window as any).BMap.Point(points[points.length - 1].lng, points[points.length - 1].lat)
-}
+import Baidu from './baidu.vue'
+import BaiduTrack from './baiduTrack.vue'
 </script>
 
 <template>
@@ -112,10 +12,11 @@ const createTrack = () => {
   <el-card header="高德地图轨迹回放" shadow="never" class="mt-3">
     <AmapTrack />
   </el-card>
-  <el-card header="轨迹回放" shadow="never" class="mt-3">
-    <el-button type="primary" @click="start">开始动画</el-button>
-    <el-button type="primary" @click="pause">暂停动画</el-button>
-    <div id="map" class="w-full h-300px mt-3"></div>
+  <el-card header="百度地图" shadow="never" class="mt-3">
+    <Baidu />
+  </el-card>
+  <el-card header="百度地图轨迹回放" shadow="never" class="mt-3">
+    <BaiduTrack />
   </el-card>
 </template>
 

+ 0 - 1
src/views/extension/printer/index.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 import type { PrintDirection, PrintOrientation, PrintTarget } from '@/components/FsPrinter/types'
 import { ElLoading } from 'element-plus'
-import FsPrinter from '@/components/FsPrinter/index.vue'
 import PrintContract from './printContract.vue'
 import { printPdf } from '@/components/FsPrinter/util'
 

+ 27 - 27
src/views/extension/printer/printContract.vue

@@ -1,3 +1,29 @@
+<script lang="ts" setup>
+import { ref } from 'vue'
+import type { PrintTarget } from '@/components/FsPrinter/types'
+
+defineProps<{
+  /** 合同数据 */
+  data?: any
+  /** 始终显示 */
+  isStatic: boolean
+  /** 打印位置 */
+  target: PrintTarget
+}>()
+
+/** 打印组件 */
+const printerRef = ref()
+
+/** 打印 */
+const print = () => {
+  if (printerRef.value) {
+    printerRef.value?.print()
+  }
+}
+
+defineExpose({ print })
+</script>
+
 <!-- 房屋租赁合同 -->
 <template>
   <fs-printer
@@ -18,7 +44,7 @@
         <img src="/logo.png" style="height: 15px; width: 15px; vertical-align: -2px" />
         <span> 方是公寓房屋租赁合同</span>
       </div>
-      <div style="color: #888">电话:0.51-8888888</div>
+      <div style="color: #888">电话:0351-8888888</div>
     </template>
     <div v-if="!!data" style="page-break-after: always">
       <div style="font-size: 35px; text-align: center">房屋租赁合同</div>
@@ -102,32 +128,6 @@
   </fs-printer>
 </template>
 
-<script lang="ts" setup>
-import { ref } from 'vue'
-import type { PrintTarget } from '@/components/FsPrinter/types'
-
-defineProps<{
-  /** 合同数据 */
-  data?: any
-  /** 始终显示 */
-  isStatic: boolean
-  /** 打印位置 */
-  target: PrintTarget
-}>()
-
-/** 打印组件 */
-const printerRef = ref()
-
-/** 打印 */
-const print = () => {
-  if (printerRef.value) {
-    printerRef.value?.print()
-  }
-}
-
-defineExpose({ print })
-</script>
-
 <style lang="scss" scoped>
 .demo-input {
   height: 24px;