Explorar o código

Merge branch 'master' of http://www.sysuimars.cn:3000/feiniao/feiniao-farm-h5

lxf hai 1 semana
pai
achega
fd62995e89

+ 6 - 0
src/router/globalRoutes.js

@@ -360,4 +360,10 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/home/subPages/prescriptionPage.vue"),
     },
+    // 提醒客户
+    {
+        path: "/remind_customer",
+        name: "RemindCustomer",
+        component: () => import("@/views/old_mini/task_condition/components/remindCustomer.vue"),
+    },
 ];

+ 85 - 9
src/views/old_mini/home/subPages/warningDetail.vue

@@ -1,13 +1,15 @@
 <template>
     <div class="warning-detail">
         <custom-header name="查看详情"></custom-header>
-        <div class="article-content">
+        <div class="article-content" :class="{ 'is-link': isLink }">
             <div class="article-header">
                 <div class="title">{{ warningDetail.title }}</div>
                 <div class="author-info">
                     <el-avatar :size="16" :src="warningDetail.icon" />
                     <span class="author-name">{{ warningDetail.name }}</span>
-                    <span class="qa-date">{{ warningDetail?.createTime && warningDetail?.createTime?.slice(0, 10) }}</span>
+                    <span class="qa-date">{{
+                        warningDetail?.createTime && warningDetail?.createTime?.slice(0, 10)
+                    }}</span>
                 </div>
             </div>
 
@@ -18,24 +20,48 @@
             <div class="article-text">
                 <span v-html="warningDetail.content"></span>
             </div>
+
+            <div class="article-footer">
+                <div class="footer-top">
+                    <img class="icon" src="@/assets/img/home/ask-icon.png" alt="" />
+                    <div class="title">在白点期,您当前农场是否出现白点?</div>
+                </div>
+                <div class="footer-bottom" :style="{ justifyContent: !isLink ? 'center' : 'flex-end' }">
+                    <div class="edit-btn" v-if="!isLink">编辑问题</div>
+                    <template v-else>
+                        <div class="edit-btn">否,未出现</div>
+                        <div class="edit-btn primary-btn">是,已出现</div>
+                    </template>
+                </div>
+            </div>
+
+            <div class="custom-bottom-fixed-btns" v-if="!isLink">
+                <div class="bottom-btn primary-btn" @click="handleForward">转发</div>
+            </div>
         </div>
     </div>
 </template>
 
 <script setup>
 import customHeader from "@/components/customHeader.vue";
-import { ref,onActivated } from "vue";
+import { ref, onActivated } from "vue";
 import { useRoute } from "vue-router";
 
 const route = useRoute();
 
+const isLink = ref(false);
+
 const warningDetail = ref({});
 const showImage = ref(false);
 onActivated(() => {
-    showImage.value = route.query.showImage === 'true' ? true : false;
+    showImage.value = route.query.showImage === "true" ? true : false;
     getWarningDetail();
 });
 
+const handleForward = () => {
+    console.log("转发");
+};
+
 const getWarningDetail = () => {
     const params = {
         id: route.query.id,
@@ -54,9 +80,11 @@ const getWarningDetail = () => {
     .article-content {
         padding: 8px 16px;
         overflow-y: auto;
-        height: calc(100% - 40px);
+        height: calc(100% - 40px - 60px);
         box-sizing: border-box;
-
+        &.is-link {
+            height: calc(100% - 40px);
+        }
         .article-header {
             .title {
                 font-size: 18px;
@@ -72,7 +100,8 @@ const getWarningDetail = () => {
                 padding-bottom: 12px;
                 border-bottom: 1px solid #f5f5f5;
 
-                .author-name,.qa-date {
+                .author-name,
+                .qa-date {
                     font-size: 14px;
                     color: #666;
                     font-weight: normal;
@@ -91,8 +120,8 @@ const getWarningDetail = () => {
                 object-fit: cover;
             }
         }
-        .article-text{
-            ::v-deep{
+        .article-text {
+            ::v-deep {
                 img {
                     width: 100%;
                     height: 175px;
@@ -101,6 +130,53 @@ const getWarningDetail = () => {
                 }
             }
         }
+
+        .article-footer {
+            margin-top: 12px;
+            border-radius: 8px;
+            border: 1px solid #2199f8;
+            padding: 10px;
+            .footer-top {
+                display: flex;
+                align-items: center;
+                gap: 8px;
+
+                .icon {
+                    width: 20px;
+                    height: 20px;
+                }
+
+                .title {
+                    font-size: 16px;
+                    font-weight: 600;
+                }
+            }
+
+            .footer-bottom {
+                display: flex;
+                justify-content: flex-end;
+                gap: 10px;
+                margin-top: 10px;
+                .edit-btn {
+                    padding: 7px 20px;
+                    background: rgba(33, 153, 248, 0.1);
+                    color: #2199f8;
+                    border-radius: 25px;
+                    font-size: 12px;
+                    text-align: center;
+                    &.primary-btn{
+                        background: #2199f8;
+                        color: #fff;
+                    }
+                }
+            }
+        }
+    }
+    .custom-bottom-fixed-btns {
+        justify-content: center;
+        .primary-btn {
+            padding: 10px 34px;
+        }
     }
 }
 </style>

+ 3 - 3
src/views/old_mini/mine/index.vue

@@ -206,12 +206,12 @@ const cellItems = computed(() => {
     } else {
         return [
             {
-                title: "我的消息",
+                title: "系统提醒",
                 path: "/message",
             },
             {
-                title: "农事方案",
-                path: "/agricultural_plan",
+                title: "种植方案",
+                path: "/plan?farmId=101532&pageType=plant",
             },
             {
                 title: "服务记录",

+ 80 - 15
src/views/old_mini/monitor/subPages/plan.vue

@@ -1,8 +1,14 @@
 <template>
     <div class="plan-page">
-        <custom-header name="农事规划"></custom-header>
+        <custom-header :name="pageType === 'plant' ? '种植方案' : '农事规划'"></custom-header>
         <div class="plan-content">
-            <div class="timeline-container" ref="timelineContainerRef">
+            <div class="plan-content-header" v-if="pageType === 'plant'">
+                <el-select class="select-item" v-model="value" placeholder="选择品类">
+                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+                <tab-list type="light" v-model="active" :tabs="tabs" @change="handleTabChange" />
+            </div>
+            <div class="timeline-container" ref="timelineContainerRef" :class="{ 'timeline-container-plant': pageType === 'plant' }">
                 <div class="timeline-list" :style="getListStyle">
                     <div class="timeline-middle-line"></div>
                     <!-- 物候期覆盖条(progress 为起点,progress2 为终点,单位 %) -->
@@ -88,12 +94,17 @@
     <!-- 新增:激活上传弹窗 -->
     <active-upload-popup ref="activeUploadPopupRef" @handleUploadSuccess="getFarmWorkPlan"></active-upload-popup>
     <!-- 互动设置弹窗 -->
-    <interact-popup ref="interactPopupRef" @handleSaveSuccess="getFarmWorkPlan" @handleDeleteInteract="handleDeleteInteract"></interact-popup>
+    <interact-popup
+        ref="interactPopupRef"
+        @handleSaveSuccess="getFarmWorkPlan"
+        @handleDeleteInteract="handleDeleteInteract"
+    ></interact-popup>
 </template>
 
 <script setup>
 import { ref, onMounted, computed, nextTick } from "vue";
 import customHeader from "@/components/customHeader.vue";
+import tabList from "@/components/pageComponents/TabList.vue";
 import { useRouter, useRoute } from "vue-router";
 import detailDialog from "@/components/detailDialog.vue";
 import eventBus from "@/api/eventBus";
@@ -120,7 +131,41 @@ const getCurrentSeason = () => {
     }
 };
 
+const active = ref(1);
+const tabs = ref([
+    {
+        id: 1,
+        name: "标准化方案",
+    },
+    {
+        id: 2,
+        name: "全托管方案",
+    },
+    {
+        id: 3,
+        name: "半托管方案",
+    },
+]);
+const handleTabChange = (id, item) => {
+    active.value = id;
+    console.log(id, item);
+};
+
+const value = ref("1");
+const options = ref([
+    {
+        value: "1",
+        label: "荔枝",
+    },
+    {
+        value: "2",
+        label: "全托管方案",
+    },
+]);
+
+const pageType = ref("");
 onMounted(() => {
+    pageType.value = route.query.pageType || "";
     getFarmWorkPlan();
 });
 
@@ -214,9 +259,9 @@ const handleEdit = (item) => {
     if (interactPopupRef.value) {
         interactPopupRef.value.showPopup({
             arrangeIdVal: item.id,
-            interactTitleVal: item.farmWorkName || '梢期杀虫', // 使用农事名称作为标题
-            interactTimeVal: item.interactTime || '', // 如果有已保存的互动时间
-            forceTriggerTimeVal: item.forceTriggerTime || '', // 如果有已保存的强制触发时间
+            interactTitleVal: item.farmWorkName || "梢期杀虫", // 使用农事名称作为标题
+            interactTimeVal: item.interactTime || "", // 如果有已保存的互动时间
+            forceTriggerTimeVal: item.forceTriggerTime || "", // 如果有已保存的强制触发时间
             interactQuestionVal: item.interactQuestion, // 如果有已保存的互动问题
         });
     }
@@ -264,7 +309,7 @@ const getListStyle = computed(() => {
     const minP = minProgress.value;
     const maxP = maxProgress.value;
     const range = Math.max(1, maxP - minP); // 避免除0
-    const total = (solarTerms.value?.length || 0) * 250;
+    const total = (solarTerms.value?.length || 0) * 450;
     const minH = total; // 无上下留白
     return { minHeight: `${minH}px` };
 });
@@ -274,7 +319,7 @@ const getTermStyle = (t) => {
     const minP = minProgress.value;
     const maxP = maxProgress.value;
     const range = Math.max(1, maxP - minP); // 避免除0
-    const total = (solarTerms.value?.length || 0) * 250;
+    const total = (solarTerms.value?.length || 0) * 450;
     // 将progress映射到0开始的位置,最小progress对应top: 0
     const normalizedP = range > 0 ? ((p - minP) / range) * 100 : 0;
     const top = (normalizedP / 100) * total;
@@ -305,7 +350,7 @@ const handleSeasonClick = (seasonValue) => {
     const minP = minProgress.value;
     const maxP = maxProgress.value;
     const range = Math.max(1, maxP - minP);
-    const total = (solarTerms.value?.length || 0) * 250;
+    const total = (solarTerms.value?.length || 0) * 450;
     const normalizedP = range > 0 ? ((p - minP) / range) * 100 : 0;
     const targetTop = (normalizedP / 100) * total; // 内容内的像素位置
     const wrap = timelineContainerRef.value;
@@ -327,7 +372,7 @@ const getPhenologyBarStyle = (item) => {
     const minP = minProgress.value;
     const maxP = maxProgress.value;
     const range = Math.max(1, maxP - minP);
-    const total = (solarTerms.value?.length || 0) * 250; // 有效绘制区高度(px)
+    const total = (solarTerms.value?.length || 0) * 450; // 有效绘制区高度(px)
     // 将progress映射到0开始的位置
     const normalizedStart = range > 0 ? ((start - minP) / range) * 100 : 0;
     const normalizedEnd = range > 0 ? ((end - minP) / range) * 100 : 0;
@@ -393,7 +438,7 @@ const getPhenologyBarHeight = (item) => {
     const minP = minProgress.value;
     const maxP = maxProgress.value;
     const range = Math.max(1, maxP - minP);
-    const total = (solarTerms.value?.length || 0) * 250;
+    const total = (solarTerms.value?.length || 0) * 450;
     // 将progress映射到0开始的位置
     const normalizedStart = range > 0 ? ((start - minP) / range) * 100 : 0;
     const normalizedEnd = range > 0 ? ((end - minP) / range) * 100 : 0;
@@ -409,22 +454,42 @@ const getReproductiveItemHeight = (phenologyItem) => {
     // 如果列表为空,返回 barHeight;否则等分
     return listLength > 0 ? barHeight / listLength : barHeight;
 };
-
 </script>
 
 <style scoped lang="scss">
 .plan-page {
     width: 100%;
     height: 100vh;
-    background: #fff;
+    background: #f5f7fb;
     .plan-content {
         padding: 12px 0;
+        .plan-content-header {
+            display: flex;
+            align-items: center;
+            gap: 12px;
+            margin-bottom: 10px;
+            margin-left: 12px;
+            .select-item{
+                width: 82px;
+                ::v-deep {
+                    .el-select__wrapper {
+                        box-shadow: none;
+                        border-radius: 25px;
+                        border: 0.5px solid rgba(153, 153, 153, 0.5);
+                    }
+                }
+            }
+        }
+        
         .timeline-container {
             height: calc(100vh - 40px - 73px);
             overflow: auto;
             position: relative;
             box-sizing: border-box;
             padding: 0 12px;
+            &.timeline-container-plant{
+                height: calc(100vh - 40px - 73px - 38px);
+            }
             .timeline-list {
                 position: relative;
             }
@@ -588,7 +653,7 @@ const getReproductiveItemHeight = (phenologyItem) => {
                     width: 100%;
                     height: 46px;
                     line-height: 30px;
-                    background: #fff;
+                    background: #f5f7fb;
                     font-size: 13px;
                     word-break: break-all;
                     writing-mode: vertical-rl;
@@ -603,7 +668,7 @@ const getReproductiveItemHeight = (phenologyItem) => {
     .custom-bottom-fixed-btns {
         justify-content: center;
         .primary-btn {
-            padding: 10px 34px;
+            padding: 10px 50px;
         }
     }
 }

+ 1 - 1
src/views/old_mini/plan/index.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="farm-card-page">
-        <custom-header name="农事方案"></custom-header>
+        <custom-header name="种植方案"></custom-header>
         <!-- <Tabs v-model:active="activeTab" class="tabs-wrap" v-if="!route.query.containerId">
             <Tab title="专家方案">
                 <expert-list :isShowHeader="true"></expert-list>

+ 8 - 1
src/views/old_mini/task_condition/components/interact.vue

@@ -58,7 +58,7 @@
                                 <div class="farm-addr">{{ item?.address }}</div>
                             </div>
                         </div>
-                        <div class="right-wrap">提醒客户</div>
+                        <div class="right-wrap" @click="handleRemindCustomer(item)">提醒客户</div>
                     </div>
                     <div class="item-bottom">
                         <div class="bottom-tag">
@@ -544,6 +544,13 @@ function handleSelectCurrentPhenology(item) {
         phenologyListVal: phenologyList.value,
     });
 }
+
+function handleRemindCustomer(item) {
+    router.push({
+        path: "/remind_customer",
+        query: { id: item.id },
+    });
+}
 </script>
 
 <style lang="scss" scoped>

+ 131 - 0
src/views/old_mini/task_condition/components/remindCustomer.vue

@@ -0,0 +1,131 @@
+<template>
+    <div class="service-records-page">
+        <custom-header name="提醒客户"></custom-header>
+        <div class="record-list">
+            <div v-for="(item, index) in renderList" :key="index" class="record-card">
+                <img class="thumb" :src="item.thumb" alt="农场缩略图" @error="handleImgError" />
+                <div class="card-body" @click="handleItemClick(item.raw)">
+                    <div class="card-body-left">
+                        <div class="title van-multi-ellipsis--l2">{{ item.title }}</div>
+                        <div class="date">{{ item.date }}</div>
+                    </div>
+                    <div class="forward-btn" @click.stop="handleForward(item.raw)">转发</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script setup>
+import { ref, onMounted, computed } from "vue";
+import customHeader from "@/components/customHeader.vue";
+import { useRouter } from "vue-router";
+import defaultThumb from "@/assets/img/home/farm.png";
+const router = useRouter();
+
+// 服务记录列表数据
+const recordList = ref([]);
+
+onMounted(() => {
+    getUserList();
+});
+
+const getUserList = async () => {
+    const { data } = await VE_API.user.userList();
+    if (data.length) {
+        recordList.value = data.filter((item) => item.serviceCount != 0);
+    }
+};
+const formatDate = (dateStr) => {
+    if (!dateStr) return "--";
+    const date = new Date(dateStr);
+    if (Number.isNaN(date.getTime())) return dateStr;
+    const y = date.getFullYear();
+    const m = `${date.getMonth() + 1}`.padStart(2, "0");
+    const d = `${date.getDate()}`.padStart(2, "0");
+    return `${y}-${m}-${d}`;
+};
+const renderList = [
+    {
+        title: "湛江出现了高温灼烧气象预警,请注意某某防范!",
+        date: "2025-11-12",
+        thumb: defaultThumb,
+    },
+    {
+        title: "农情互动提醒:",
+        date: "2025-11-12",
+        thumb: defaultThumb,
+    },
+    {
+        title: "农事执行提醒",
+        date: "2025-11-12",
+        thumb: defaultThumb,
+    },
+];
+// 处理列表项点击
+const handleItemClick = (data) => {
+    router.push(`/warning_detail?id=782295538706944000&showImage=true`);
+};
+// 处理转发按钮点击
+const handleForward = (data) => {
+    // TODO: 实现转发功能
+    console.log("转发", data);
+};
+const handleImgError = (e) => {
+    e.target.src = defaultThumb;
+};
+</script>
+<style lang="scss" scoped>
+.service-records-page {
+    width: 100%;
+    min-height: 100vh;
+    background: #f5f5f5;
+    .record-list {
+        padding: 10px 12px;
+        display: flex;
+        flex-direction: column;
+        gap: 10px;
+    }
+    .record-card {
+        display: flex;
+        gap: 12px;
+        padding: 12px 10px;
+        background: #ffffff;
+        border-radius: 12px;
+        align-items: center;
+        height: 98px;
+        box-sizing: border-box;
+        .thumb {
+            width: 80px;
+            height: 74px;
+            border-radius: 8px;
+            object-fit: cover;
+        }
+        .card-body {
+            width: calc(100% - 80px - 12px);
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .card-body-left{
+                width: calc(100% - 62px - 12px);
+                height: 95%;
+                display: flex;
+                flex-direction: column;
+                justify-content: space-between;
+                .date {
+                    font-size: 13px;
+                    color: #86909C;
+                    margin-top: 4px;
+                }
+            }
+        }
+        .forward-btn {
+            padding: 6px 19px;
+            background: rgba(33, 153, 248, 0.1);
+            color: #2199F8;
+            border-radius: 25px;
+            font-size: 12px;
+        }
+    }
+}
+</style>

+ 1 - 1
src/views/old_mini/user/farmDetails.vue

@@ -27,7 +27,7 @@
                                 <div class="farm-info-footer-item-value">1450<span class="unit">元</span></div>
                             </div>
                         </div>
-                        <div class="footer-action" @click="handleDetail('plan?farmId=101532&miniJson={\'farmId\':101532}')">农事规划</div>
+                        <div class="footer-action" @click="handleDetail('plan')">农事规划</div>
                     </div>
                 </template>
             </farm-info-card>