lxf 5 часов назад
Родитель
Сommit
584db064ce
1 измененных файлов с 136 добавлено и 4 удалено
  1. 136 4
      src/views/old_mini/agri_file/components/fileFloat.vue

+ 136 - 4
src/views/old_mini/agri_file/components/fileFloat.vue

@@ -1,11 +1,26 @@
 <template>
+
+<div class="add-btn">点击新建管理分区</div>
+
     <floating-panel class="file-float-panel" :class="{'custom-panel': height === anchors[0]}" v-model:height="height" :anchors="anchors">
         <div class="file-float-content">
             <div class="float-tabs">
+                <div class="tab-active-bg" :style="activeBgStyle"></div>
                 <div class="tab-item" @click="changeTab(0)" :class="{ 'tab-item-active': activeTab === 0 }">物候记录</div>
                 <div class="tab-item" @click="changeTab(1)" :class="{ 'tab-item-active': activeTab === 1 }">异常记录</div>
                 <div class="tab-item" @click="changeTab(2)" :class="{ 'tab-item-active': activeTab === 2 }">农事记录</div>
             </div>
+
+            <div class="tab-content-group" v-show="height !== anchors[0]">
+                <div class="tab-loading" v-if="isCurrentTabLoading">加载中...</div>
+                <div class="tab-empty" v-else-if="currentList.length === 0">暂无记录</div>
+                <div class="tab-content-item" v-for="item in currentList" :key="item.id">
+                    <div class="time-tag">{{ item.date }}</div>
+                    <div class="item-info">
+                        {{ item.textPrefix }} <span class="blue-text">{{ item.highlight }}</span>
+                    </div>
+                </div>
+            </div>
         </div>
     </floating-panel>
 </template>
@@ -13,7 +28,7 @@
 <script setup>
 
 import { FloatingPanel } from 'vant';
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
 const anchors = [
     130,
     Math.round(0.4 * window.innerHeight),
@@ -22,13 +37,74 @@ const anchors = [
 const height = ref(anchors[0]);
 
 const activeTab = ref(0);
+const dataMap = ref({ 0: [], 1: [], 2: [] });
+const loadingMap = ref({ 0: false, 1: false, 2: false });
+const loadedMap = ref({ 0: false, 1: false, 2: false });
+
 const changeTab = (index) => {
     activeTab.value = index;
+    ensureTabData(index);
 };
 
+const activeBgStyle = computed(() => ({
+    transform: `translateX(${activeTab.value * 100}%)`,
+}));
+
+const currentList = computed(() => dataMap.value[activeTab.value] || []);
+const isCurrentTabLoading = computed(() => !!loadingMap.value[activeTab.value]);
+
+function getMockDataByTab(tab) {
+    if (tab === 0) {
+        return [
+            { id: "p1", date: "04/18", textPrefix: "管理分区一出现 新梢占比为", highlight: "15 %" },
+            { id: "p2", date: "04/19", textPrefix: "管理分区二进入 花穗萌动", highlight: "60 %" },
+        ];
+    }
+    if (tab === 1) {
+        return [
+            { id: "a1", date: "04/18", textPrefix: "管理分区三发现 异常叶片占比", highlight: "8 %" },
+        ];
+    }
+    return [
+        { id: "w1", date: "04/17", textPrefix: "管理分区一完成 修枝作业进度", highlight: "100 %" },
+        { id: "w2", date: "04/18", textPrefix: "管理分区二完成 灌溉作业进度", highlight: "100 %" },
+    ];
+}
+
+async function ensureTabData(tab) {
+    if (loadedMap.value[tab] || loadingMap.value[tab]) return;
+    loadingMap.value[tab] = true;
+    try {
+        // TODO: 替换为真实接口请求,按 tab 类型获取不同记录
+        const list = await new Promise((resolve) => {
+            setTimeout(() => resolve(getMockDataByTab(tab)), 250);
+        });
+        dataMap.value[tab] = list || [];
+        loadedMap.value[tab] = true;
+    } finally {
+        loadingMap.value[tab] = false;
+    }
+}
+
+ensureTabData(0);
+
 </script>
 
 <style lang="scss" scoped>
+
+.add-btn {
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    color: #fff;
+    border-radius: 20px;
+    padding: 0 20px;
+    background: #2199f8;
+    height: 40px;
+    line-height: 40px;
+    cursor: pointer;
+}
 .file-float-panel {
     left: 12px;
     width: calc(100% - 24px);
@@ -51,24 +127,80 @@ const changeTab = (index) => {
     background: #fff;
     border-radius: 0 0 10px 10px;
     .float-tabs {
+        position: relative;
         border-radius: 4px;
         padding: 3px;
         background: #E9E9E9;
-        display: flex;
+        display: grid;
+        grid-template-columns: repeat(3, minmax(0, 1fr));
         align-items: center;
-        justify-content: space-between;
+        overflow: hidden;
+
+        .tab-active-bg {
+            position: absolute;
+            top: 3px;
+            left: 3px;
+            width: calc((100% - 6px) / 3);
+            height: 26px;
+            border-radius: 4px;
+            background: #fff;
+            transition: transform 0.25s ease;
+        }
+
         .tab-item {
+            position: relative;
+            z-index: 1;
             flex: 1;
             height: 26px;
             line-height: 26px;
             text-align: center;
             color: #767676;
             border-radius: 4px;
+            transition: color 0.2s ease;
             &.tab-item-active {
-                background: #fff;
                 color: #0D0D0D;
             }
         }
     }
+
+    .tab-content-group {
+        padding-top: 12px;
+
+        .tab-loading,
+        .tab-empty {
+            text-align: center;
+            color: #9a9a9a;
+            font-size: 13px;
+            padding: 14px 0;
+        }
+
+        .tab-content-item + .tab-content-item {
+            margin-top: 10px;
+        }
+
+        .tab-content-item {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .time-tag {
+                color: #2199F8;
+                background: rgba(33, 153, 248, 0.1);
+                font-size: 12px;
+                height: 21px;
+                line-height: 21px;
+                padding: 0 6px;
+            }
+
+            .item-info {
+                color: rgba(60, 60, 60, 0.5);
+                line-height: 21px;
+            }
+
+            .blue-text {
+                color: #2199f8;
+            }
+        }
+    }
 }
 </style>