Procházet zdrojové kódy

Merge branch 'feature_20250423-首页AI图标拖拽' into release

zhujindu před 7 měsíci
rodič
revize
8af83f3e30
4 změnil soubory, kde provedl 121 přidání a 35 odebrání
  1. 62 0
      src/directive/dialog/drag.js
  2. 11 0
      src/directive/index.js
  3. 3 0
      src/main.js
  4. 45 35
      src/views/home/index.vue

+ 62 - 0
src/directive/dialog/drag.js

@@ -0,0 +1,62 @@
+/**
+ * v-dialogDrag 弹窗拖拽
+ * Copyright (c) 2019 ruoyi
+ */
+
+// 当前设备
+const isDevice = localStorage.getItem('isDevice');
+
+export default {
+  bind(el, binding, vnode, oldVnode) {
+    const value = binding.value;
+    if (value == false) return;
+    if (isDevice == 'PC') return;
+    let initialTouchX = 0;
+    let initialTouchY = 0;
+    let initialLeft = 0;
+    let initialTop = 0;
+
+    el.addEventListener(
+      'touchstart',
+      (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        e.currentTarget.style.touchAction = 'none';
+        const touch = e.touches[0];
+        initialTouchX = touch.clientX;
+        initialTouchY = touch.clientY;
+        initialLeft = e.currentTarget.offsetLeft;
+        initialTop = e.currentTarget.offsetTop;
+      },
+      false
+    );
+    el.addEventListener(
+      'touchmove',
+      function (e) {
+        e.preventDefault();
+        e.stopPropagation();
+        const clientX = e.targetTouches[0].clientX;
+        const clientY = e.targetTouches[0].clientY;
+        // 限制拖拽范围
+        const clientWidth = document.documentElement.clientWidth;
+        const clientHeight = document.documentElement.clientHeight;
+
+        // 计算边界限制
+        const maxLeft = clientWidth - this.offsetWidth;
+        const maxTop = clientHeight - this.offsetHeight;
+        // 计算基于初始位置的移动量并应用边界限制
+        const deltaX = clientX - initialTouchX;
+        const deltaY = clientY - initialTouchY;
+        const left = initialLeft + deltaX;
+        const top = initialTop + deltaY;
+
+        // 添加边界限制
+        this.style.left = `${Math.max(0, Math.min(left, maxLeft))}px`;
+        this.style.top = `${Math.max(0, Math.min(top, maxTop))}px`;
+        localStorage.setItem(this.className, JSON.stringify([this.style.left, this.style.top]));
+      },
+      false
+    );
+    el.addEventListener('touchend', function (e) {}, false);
+  },
+};

+ 11 - 0
src/directive/index.js

@@ -0,0 +1,11 @@
+import dialogDrag from './dialog/drag';
+
+const install = function (Vue) {
+  Vue.directive('dialogDrag', dialogDrag);
+};
+
+if (window.Vue) {
+  Vue.use(install); // eslint-disable-line
+}
+
+export default install;

+ 3 - 0
src/main.js

@@ -37,6 +37,7 @@ import ElProgress from 'element-ui/lib/progress';
 import 'element-ui/lib/theme-chalk/progress.css';
 import ElDialog from 'element-ui/lib/dialog';
 import 'element-ui/lib/theme-chalk/dialog.css';
+import directive from './directive'; // directive
 // import wx from 'weixin-js-sdk';
 // jenkins 测试打包前先合并
 
@@ -76,6 +77,8 @@ if (isProd) {
   Vue.use(vConsole);
 }
 
+Vue.use(directive);
+
 new Vue({
   router,
   store,

+ 45 - 35
src/views/home/index.vue

@@ -26,15 +26,17 @@
         <bottomBtn :tabVal="tabVal" ref="bottomBtn"></bottomBtn>
       </div>
     </div>
-    <div class="AIIcon" @click="deepseek">
-      <van-icon class="img" :name="require('@/assets/ai.png')" size="40" />
+    <div class="floatingIcon" :style="setSIcontyle" v-dialogDrag>
+      <div class="AIIcon" @click="deepseek">
+        <van-icon class="img" :name="require('@/assets/ai.png')" size="40" />
+      </div>
+      <a
+        class="feedback"
+        href="https://qiweitest.nipponpaint.com.cn/weixin/ecoRules/redirect/1064/0"
+        target="_blank"
+        ><img src="./../../assets/feedback.png"
+      /></a>
     </div>
-    <a
-      class="feedback"
-      href="https://qiweitest.nipponpaint.com.cn/weixin/ecoRules/redirect/1064/0"
-      target="_blank"
-      ><img src="./../../assets/feedback.png"
-    /></a>
     <tab-bar></tab-bar>
   </div>
 </template>
@@ -60,6 +62,10 @@ export default {
       hintTabPageIndex: 0,
       isGZorJZ: null,
       isLoading: false,
+      setSIcontyle: {
+        bottom: '85px',
+        right: '14px',
+      },
     };
   },
   watch: {
@@ -86,6 +92,13 @@ export default {
   },
   created() {
     this.getDict();
+    let floatingIconStyle = JSON.parse(localStorage.getItem('floatingIcon'));
+    if (floatingIconStyle && floatingIconStyle.length) {
+      this.setSIcontyle = {
+        left: floatingIconStyle[0],
+        top: floatingIconStyle[1],
+      };
+    }
   },
   mounted() {},
   methods: {
@@ -192,6 +205,7 @@ export default {
 </style>
 <style lang="scss">
 .homePage {
+  position: relative;
   display: flex;
   flex-direction: column;
   .myTab {
@@ -225,34 +239,30 @@ export default {
   .bottomBtn {
     margin-bottom: 55px;
   }
-  .AIIcon {
-    position: fixed;
-    /* color: #666; */
-    display: inline-block;
-    /* box-shadow: 0px 2px 7px -5px #000; */
-    /* border-radius: 100px; */
-    /* overflow: hidden; */
-    right: 14px;
-    cursor: pointer;
-    bottom: 140px;
-    /* background-color: white; */
-  }
-  .AIIcon .img {
-    border-radius: 100px;
-    float: left;
-  }
-  .AIIcon .img .van-icon__image {
-    border-radius: 100px;
-  }
-  .feedback {
-    position: fixed;
-    bottom: 85px;
-    right: 14px;
+  .floatingIcon {
+    position: absolute;
     width: 40px;
-    z-index: 9999;
-  }
-  .feedback img {
-    width: 100%;
+    z-index: 99999;
+    height: min-content;
+    .AIIcon {
+      width: 100%;
+      display: inline-block;
+      cursor: pointer;
+    }
+    .AIIcon .img {
+      border-radius: 100px;
+      float: left;
+    }
+    .AIIcon .img .van-icon__image {
+      border-radius: 100px;
+    }
+    .feedback {
+      display: inline-block;
+      width: 100%;
+    }
+    .feedback img {
+      width: 100%;
+    }
   }
 }
 </style>