Ver código fonte

feat: 需求大厅

lxf 1 semana atrás
pai
commit
b0306905c8

BIN
src/assets/img/home/farm-point.png


+ 13 - 0
src/components/taskItem.vue

@@ -0,0 +1,13 @@
+<template>
+    <div>
+
+    </div>
+</template>
+
+<script setup>
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 282 - 3
src/views/old_mini/farm_manage/components/demandHall.vue

@@ -1,16 +1,295 @@
 <template>
-    <div class="demand-hall">
-        11111
+    <div class="demand-hall" :style="{ height: `calc(100vh - ${tabBarHeight}px - 50px)` }">
+        <!-- 地图 -->
+        <div class="map-container" ref="mapContainer"></div>
+
+        <floating-panel class="floating-panel" v-model:height="height" :anchors="anchors" :content-draggable="false">
+            <div class="hall-content">
+                <div class="select-group">
+                    <el-select class="select-item" v-model="dateValue" placeholder="Select">
+                        <el-option v-for="item in dateOptions" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                    <el-select class="select-item" v-model="areaValue" placeholder="Select">
+                        <el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                    <el-select class="select-item" v-model="areaValue1" placeholder="Select">
+                        <el-option v-for="item in areaOptions1" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                </div>
+                <div class="farm-list">
+                    <div class="farm-item" v-for="item in 3" :key="item">
+                        <div class="item-top">
+                            <div class="top-l">
+                                <div class="item-name">梢期杀虫</div>
+                                <div class="item-time">2025.08.27</div>
+                            </div>
+                            <div class="top-r">查看药物处方</div>
+                        </div>
+                        <div class="item-box">
+                            <div class="title-wrap">
+                                <div class="title-l">
+                                    <div class="item-title">
+                                        未命名农场
+                                    </div>
+                                    <div class="setting-text">设为特别关注</div>
+                                </div>
+                                <div class="title-r">最近服务过</div>
+                            </div>
+                            <div class="item-desc">
+                                <div class="desc-info">
+                                    <div class="desc-info-item">
+                                        <span>农场品种:</span>
+                                        <span class="value">荔枝-桂味</span>
+                                    </div>
+                                    <div class="desc-info-item">
+                                        <span>农场面积:</span>
+                                        <span class="value">500亩</span>
+                                    </div>
+                                </div>
+                                <div class="desc-info copy-info">
+                                    <div class="address van-ellipsis">
+                                        <span>农场位置:</span>
+                                        <span class="value">广东省广州市从化区市从化区从广东省广州市从化区市从化区从</span>
+                                    </div>
+                                    <span class="copy-text">点击复制</span>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </floating-panel>
+        <div class="expand-btn-wrap" v-show="height === defalutHeight">
+            <span>需求</span>
+            <div class="expand-btn" @click="handleExpandBtnClick">
+                <span>展开</span>
+                <el-icon><ArrowUpBold /></el-icon>
+            </div>
+        </div>
     </div>
 </template>
 
 <script setup>
+import { FloatingPanel } from "vant";
+import { computed, nextTick, onMounted, ref } from "vue";
+import { useStore } from "vuex";
+import IndexMap from "../map/index";
+
+const store = useStore();
+const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+
+// const tabBarHeight = ref(localStorage.getItem("tabBarHeight") * 1 || 50);
+
+const defalutHeight = ref(0);
+const anchors = ref([defalutHeight.value, 310 + tabBarHeight.value, Math.round(1 * window.innerHeight) - 40]);
+const height = ref(anchors.value[1]);
+
+const handleExpandBtnClick = () => {
+    height.value = anchors.value[1];
+};
+
+const indexMap = new IndexMap();
+const mapContainer = ref(null);
+
+onMounted(() => {
+    const point = store.state.home.miniUserLocationPoint;
+    nextTick(() => {
+        indexMap.initMap(point, mapContainer.value);
+    });
+});
 
+
+const searchValue = ref("");
+const search = () => {
+    console.log(searchValue.value);
+};
+const dateValue = ref("1");
+const dateOptions = [
+    { value: "1", label: "农事类型" },
+    { value: "2", label: "2" },
+    { value: "3", label: "3" },
+];
+const areaValue = ref("1");
+const areaOptions = [
+    { value: "1", label: "距离" },
+    { value: "2", label: "2" },
+    { value: "3", label: "3" },
+];
+const areaValue1 = ref("1");
+const areaOptions1 = [
+    { value: "1", label: "区域筛选" },
+    { value: "2", label: "2" },
+    { value: "3", label: "3" },
+];
 </script>
 
 <style lang="scss" scoped>
 .demand-hall {
     width: 100%;
     height: 100%;
+    position: relative;
+    overflow: hidden;
+    .map-container {
+        width: 100%;
+        height: 100%;
+    }
+
+    .expand-btn-wrap {
+        position: absolute;
+        bottom: 12px;
+        left: 12px;
+        width: calc(100% - 24px);
+        background-image: linear-gradient(180deg, #d7eafc 0%, #ffffff 100%);
+        border-radius: 14px;
+        padding: 15px 12px;
+        box-sizing: border-box;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-weight: 500;
+        font-size: 15px;
+        .expand-btn {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 4px;
+            font-size: 13px;
+            color: #2199f8;
+        }
+    }
+
+    .hall-content {
+        .farm-list {
+            border-top: 1px solid rgba(0, 0, 0, 0.1);
+            padding: 8px 12px 12px 12px;
+        }
+        .farm-item {
+            background: #CFE9FF;
+            border-radius: 14px;
+            .item-top {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+                padding: 10px 12px;
+                color: #2199F8;
+                font-size: 14px;
+                .top-l {
+                    display: flex;
+                    align-items: center;
+                    font-size: 16px;
+                    color: #000000;
+                }
+                .item-name {
+                    margin-right: 5px;
+                    color: #FFFFFF;
+                    padding: 0 10px;
+                    height: 29px;
+                    border-radius: 4px;
+                    line-height: 29px;
+                    background: linear-gradient(180deg, #7BC5FF, #2199F8);
+                }
+            }
+            .item-box {
+                background: #fff;
+                border-radius: 10px 10px 14px 14px;
+                padding: 10px 12px;
+            }
+            .title-wrap {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+                .title-l {
+                    display: flex;
+                    align-items: center;
+                    .setting-text {
+                        padding-left: 11px;
+                        font-size: 12px;
+                        color: #2199F8;
+                    }
+                }
+                .title-r {
+                    color: rgba(255, 131, 29, 0.36);
+                    font-size: 12px;
+                }
+            }
+            .item-title {
+                font-size: 16px;
+                font-weight: 500;
+                margin: 2px 0 5px 0;
+            }
+            .item-desc {
+                font-size: 13px;
+                color: #bbbbbb;
+                line-height: 18px;
+                .desc-info {
+                    display: flex;
+                    .desc-info-item {
+                        flex: 1;
+                        .value {
+                            color: #666666;
+                        }
+                    }
+                }
+                .copy-info {
+                    margin-top: 4px;
+                    .address {
+                        max-width: 80%;
+                        .value {
+                            color: #666666;
+                        }
+                    }
+                    .copy-text {
+                        margin-left: 8px;
+                        color: #2199f8;
+                    }
+                }
+            }
+        }
+        .farm-item + .farm-item {
+            margin-top: 10px;
+        }
+
+        
+    .select-group {
+        display: flex;
+        padding: 0 12px;
+        .select-item {
+            width: 100%;
+            ::v-deep {
+                .el-select__wrapper {
+                    text-align: center;
+                    gap: 2px;
+                    box-shadow: none;
+                    justify-content: center;
+                    background: none;
+                }
+                .el-select__selection {
+                    flex: none;
+                    width: fit-content;
+                }
+                .el-select__placeholder {
+                    position: static;
+                    transform: none;
+                    width: fit-content;
+                    color: rgba(0, 0, 0, 0.2);
+                }
+                .el-select__caret {
+                    color: rgba(0, 0, 0, 0.2);
+                }
+            }
+        }
+    }
+    }
+}
+
+.floating-panel {
+    width: 100%;
+    background: #ffffff;
+    ::v-deep {
+        .van-floating-panel__content {
+            background: transparent;
+            overflow: hidden;
+        }
+    }
 }
-</style>
+</style>

+ 42 - 0
src/views/old_mini/farm_manage/map/index.js

@@ -0,0 +1,42 @@
+import * as KMap from "@/utils/ol-map/KMap";
+import * as util from "@/common/ol_common.js";
+import config from "@/api/config.js";
+import { Point } from 'ol/geom';
+import Feature from "ol/Feature";
+import Style from "ol/style/Style";
+import Icon from "ol/style/Icon";
+/**
+ * @description 地图层对象
+ */
+class IndexMap {
+  constructor() {
+    let that = this;
+    let vectorStyle = new KMap.VectorStyle();
+    this.vectorStyle = vectorStyle;
+    // 位置图标
+    this.clickPointLayer = new KMap.VectorLayer("clickPointLayer", 9999, {
+      style: (f) => {
+        return new Style({
+          image: new Icon({
+            src: require("@/assets/img/home/farm-point.png"),
+            scale: 0.5,
+            anchor: [0.5, 1],
+          }),
+        });
+      },
+    });
+  }
+
+  initMap(location, target) {
+    let level = 16;
+    let coordinate = util.wktCastGeom(location).getFirstCoordinate();
+    this.kmap = new KMap.Map(target, level, coordinate[0], coordinate[1], null, 8, 22, "vec" );
+    let xyz2 = config.base_img_url3 + "map/lby/{z}/{x}/{y}.png";
+    this.kmap.addXYZLayer(xyz2, { minZoom: 8, maxZoom: 22 }, 2);
+    this.kmap.addLayer(this.clickPointLayer.layer);
+    let point = new Feature(new Point(coordinate))
+    this.clickPointLayer.addFeature(point)
+  }
+}
+
+export default IndexMap;

+ 3 - 10
src/views/old_mini/home/components/homeFloatingPanel.vue

@@ -143,19 +143,12 @@ import { useStore } from "vuex";
 import { computed, ref } from "vue";
 import RecordTask from "./recordTask.vue";
 
-const props = defineProps({
-    isExpert: {
-        type: Boolean,
-        default: false,
-    },
-});
-
 const store = useStore();
 // const tabBarHeight = computed(() => store.state.home.tabBarHeight);
 const tabBarHeight = ref(localStorage.getItem("tabBarHeight") * 1 || 50);
 
 const defalutHeight = ref(0);
-const anchors = ref([defalutHeight.value, 310 + tabBarHeight.value, Math.round(1 * window.innerHeight) - (props.isExpert ? 40 : 0)]);
+const anchors = ref([defalutHeight.value, 310 + tabBarHeight.value, Math.round(1 * window.innerHeight)]);
 const height = ref(anchors.value[1]);
 
 const containerRef = ref(null);
@@ -163,7 +156,7 @@ const handleClick = (e) => {
     e.preventDefault();
 };
 
-const activeTab = ref(0);
+const activeTab = ref(1);
 const tabs = ref(["农事任务", "农场档案"]);
 
 const handleTabClick = (index) => {
@@ -207,7 +200,7 @@ const handleHeightChange = ({ height }) => {
         cardContentHeight.value = 180;
         cardContentRef.value.scrollTo({ top: 0, behavior: "smooth" });
     } else if (height === anchors.value[2]) {
-        cardContentHeight.value = Math.round(1 * window.innerHeight) - (tabBarHeight.value - (props.isExpert ? 40 : 0)) - 180;
+        cardContentHeight.value = Math.round(1 * window.innerHeight) - (tabBarHeight.value - 40) - 180;
     }
     emit("heightChange", height);
 };