Bladeren bron

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

刘秀芳 1 dag geleden
bovenliggende
commit
30ddce1273

+ 7 - 7
src/components/chatWindow.vue

@@ -548,13 +548,13 @@ const functionButtons = ref([
             router.push(`/farm_card?farmId=${farmVal.value}`);
         }
     },
-    {
-        text: '农场相册',
-        handler: () => {
-            // 跳转到农场相册页面
-            router.push(`/farm_photo`);
-        }
-    }
+    // {
+    //     text: '农场相册',
+    //     handler: () => {
+    //         // 跳转到农场相册页面
+    //         router.push(`/farm_photo`);
+    //     }
+    // }
 ]);
 
 // 辅助函数

+ 64 - 0
src/components/pageComponents/CommonBox.vue

@@ -0,0 +1,64 @@
+<template>
+    <div class="common-box">
+        <div class="common-title">
+            <div class="common-title-left">
+                <img src="@/assets/img/home/label-icon.png" alt="" />
+                <span>{{ title }}</span>
+            </div>
+            <div class="common-title-right">
+                <slot name="right"></slot>
+            </div>
+        </div>
+        <div class="common-content">
+            <slot></slot>
+        </div>
+    </div>
+</template>
+
+<script setup>
+defineProps({
+    title: {
+        type: String,
+        default: "",
+    },
+});
+</script>
+
+<style scoped lang="scss">
+.common-box {
+    padding: 16px 12px;
+    background: #fff;
+    border-radius: 8px;
+
+    .common-title {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        font-size: 16px;
+        color: #000;
+        padding-bottom: 12px;
+        border-bottom: 1px solid #f5f5f5;
+        .common-title-left {
+            display: flex;
+            align-items: center;
+            gap: 6px;
+            font-weight: 500;
+            img {
+                width: 14px;
+                height: 8px;
+            }
+        }
+        .common-title-right {
+            font-size: 13px;
+            color: rgba(0, 0, 0, 0.6);
+        }
+    }
+
+    .common-content {
+        margin-top: 12px;
+    }
+}
+.common-box + .common-box {
+    margin-top: 12px;
+}
+</style>

+ 206 - 0
src/components/pageComponents/FarmInfoCard.vue

@@ -0,0 +1,206 @@
+<template>
+    <div class="farm-info-card" :class="{ 'has-footer': showFooter }" @click="handleClick">
+        <div class="item-content">
+            <div class="item-left">
+                <img class="map-img" :src="data.mapImage || '/map.png'" alt="地图" />
+                <div class="item-info">
+                    <div class="item-header">
+                        <div class="farm-name">{{ data.farmName }}</div>
+                        <div class="tags">
+                            <span class="tag tag-area">{{ data.area }}</span>
+                            <span class="tag tag-variety">{{ data.variety }}</span>
+                        </div>
+                    </div>
+                    <div class="farm-address">{{ data.address }}</div>
+                </div>
+            </div>
+            <!-- 右侧按钮插槽 -->
+            <div v-if="hasRightSlot" class="item-right-btn" @click.stop>
+                <slot name="right"></slot>
+            </div>
+        </div>
+        <!-- 底部内容:服务次数或自定义内容 -->
+        <div v-if="showFooter" class="item-footer">
+            <slot name="footer">
+                <template v-if="data.serviceCount !== undefined">
+                    农事服务过<span class="service-count">{{ data.serviceCount }}</span
+                    >次
+                    <span class="view-detail">查看详情</span>
+                </template>
+            </slot>
+        </div>
+        <!-- 底部提示框:需求信息和预计收益 -->
+        <template v-if="showBottomTip">
+            <slot name="bottomTip">
+                <div class="item-footer" v-if="data.day">
+                    距离农事执行已
+                    <span class="service-count">{{ data.day }}</span>
+                    天,提醒用户拍照,增加信誉度!
+                </div>
+                <div class="item-footer item-bottom-tip" v-if="data.estimatedIncome">
+                    <div>当前农场有 <span>{{ data.farmInfo }}</span> 的农情需求</div>
+                    <div class="income-text">预计收益 <span>{{ data.estimatedIncome }}元</span></div>
+                </div>
+            </slot>
+        </template>
+    </div>
+</template>
+
+<script setup>
+import { computed, useSlots } from "vue";
+
+const props = defineProps({
+    data: {
+        type: Object,
+        required: true,
+        validator: (value) => {
+            return (
+                value.farmName !== undefined &&
+                value.area !== undefined &&
+                value.variety !== undefined &&
+                value.address !== undefined
+            );
+        },
+    },
+});
+
+const emit = defineEmits(["click"]);
+const slots = useSlots();
+
+const showFooter = computed(() => {
+    return props.data.serviceCount !== undefined || !!slots.footer;
+});
+
+const hasRightSlot = computed(() => {
+    return !!slots.right;
+});
+
+const showBottomTip = computed(() => {
+    return props.data.day !== undefined || props.data.estimatedIncome !== undefined || !!slots.bottomTip;
+});
+
+const handleClick = () => {
+    emit("click", props.data);
+};
+</script>
+
+<style lang="scss" scoped>
+.farm-info-card {
+    background: #fff;
+    border-radius: 8px;
+    position: relative;
+
+    &.has-footer {
+        padding: 12px 10px;
+        border-radius: 5px;
+    }
+
+    &:not(.has-footer) {
+        padding: 16px 12px;
+        display: flex;
+        flex-direction: column;
+        align-items: stretch;
+    }
+
+    .item-content {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
+        .map-img {
+            width: 40px;
+            height: 40px;
+            border-radius: 6px;
+            object-fit: cover;
+        }
+        .item-left {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+        }
+        .item-info {
+            .item-header {
+                display: flex;
+                gap: 10px;
+                font-size: 14px;
+                margin-bottom: 4px;
+                .farm-name {
+                    font-weight: 600;
+                    color: #000;
+                }
+                .tags {
+                    display: flex;
+                    gap: 6px;
+                    .tag {
+                        padding: 1px 8px;
+                        border-radius: 2px;
+                        font-size: 12px;
+                        &.tag-area {
+                            background: #f4f4f4;
+                            color: #1d2129;
+                        }
+
+                        &.tag-variety {
+                            background: rgba(232, 243, 255, 1);
+                            color: #2199f8;
+                        }
+                    }
+                }
+            }
+            .farm-address {
+                font-size: 12px;
+                color: #86909c;
+            }
+        }
+    }
+
+    .item-footer {
+        background: linear-gradient(90deg, rgba(33, 153, 248, 0.2) 0%, transparent 100%);
+        padding: 6px 8px;
+        display: flex;
+        align-items: center;
+        border-radius: 4px;
+        margin-top: 10px;
+        color: #2e2e2e;
+        font-size: 12px;
+        span {
+            color: #2199f8;
+            font-weight: 500;
+        }
+        .service-count {
+            margin: 0 2px;
+        }
+        .view-detail {
+            margin-left: 10px;
+        }
+    }
+
+    .item-right-btn {
+        text-align: center;
+        color: #888b8d;
+        font-size: 12px;
+        padding: 5px 12px;
+        border-radius: 20px;
+        border: 1px solid #888b8d;
+    }
+
+    .item-bottom-tip {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        background: linear-gradient(90deg, rgba(254, 164, 94, 0.2) 0%, transparent 100%);
+        span{
+            color: #EB7B20;
+            font-weight: 500;
+        }
+        .income-text{
+            color: #EFB789;
+        }
+    }
+}
+
+.farm-info-card + .farm-info-card {
+    margin-top: 12px;
+}
+</style>

+ 220 - 0
src/components/pageComponents/PlanList.vue

@@ -0,0 +1,220 @@
+<template>
+    <div class="expert-prescription">
+        <div class="plan-menu">
+            <el-anchor :container="containerRef" direction="vertical" type="default" @click="handleClick">
+                <el-menu :default-active="defaultActive" class="el-menu-vertical-demo">
+                    <el-sub-menu v-for="(menu, index) in menuData" :key="index" :index="String(menu.id)">
+                        <template #title>
+                            <img class="menu-icon" :src="require(`@/assets/img/gallery/icon-${index}.png`)" />
+                            <span class="menu-text">{{ menu.name }}</span>
+                        </template>
+                        <el-menu-item
+                            v-for="item in menu.farmWorkArrangeList"
+                            :key="item.id"
+                            :index="`${menu.id}-${item.id}`"
+                        >
+                            <el-anchor-link
+                                :href="'#' + menu.name + item.farmWorkDetail?.name"
+                                :title="item.farmWorkDetail?.name || '摇花落花'"
+                            />
+                        </el-menu-item>
+                    </el-sub-menu>
+                </el-menu>
+            </el-anchor>
+        </div>
+        <div class="expert-content" ref="containerRef">
+            <slot :menuData="menuData">
+                <div v-for="(section, index) in menuData" :key="index" class="content-section">
+                    <div
+                        class="section-item"
+                        v-for="(sub, subI) in section.farmWorkArrangeList"
+                        :key="index + '-' + subI"
+                    >
+                        <div class="section-id" :id="section.name + sub.farmWorkDetail?.name"></div>
+                        <record-item :record-item-data="sub">
+                            <template #title>
+                                <div class="box-title">
+                                    <div class="title-l">
+                                        {{ sub.farmWorkDetail?.name }}
+                                        <span class="parent-text">{{ section.name }}</span>
+                                    </div>
+                                </div>
+                            </template>
+                        </record-item>
+                    </div>
+                </div>
+            </slot>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from "vue";
+import recordItem from "@/components/recordItem.vue";
+
+const props = defineProps({
+    farmId: {
+        type: [Number, String],
+        required: true,
+    },
+    containerId: {
+        type: [Number, String],
+        default: 2,
+    },
+    defaultActive: {
+        type: String,
+        default: "1-1",
+    },
+});
+
+const menuData = ref([]);
+const containerRef = ref(null);
+
+function getPlanWorkList() {
+    VE_API.home
+        .getPhenologyFarmWorkList({ farmId: props.farmId, containerId: props.containerId })
+        .then(({ data }) => {
+            menuData.value = data;
+        });
+}
+
+onMounted(() => {
+    getPlanWorkList();
+});
+
+const handleClick = (e) => {
+    e.preventDefault();
+};
+</script>
+
+<style scoped lang="scss">
+.expert-prescription {
+    display: flex;
+    width: 100%;
+    height: 100%;
+    .plan-menu {
+        width: 100px;
+        height: 100%;
+        overflow: auto;
+        box-sizing: border-box;
+        background: #fff;
+        .menu-icon {
+            width: 13px;
+        }
+        .menu-text {
+            padding: 0 4px;
+        }
+        ::v-deep {
+            .el-anchor {
+                height: 100%;
+                background: none;
+            }
+            .el-anchor__marker {
+                display: none;
+            }
+            .el-menu {
+                background: none;
+                border: none;
+                .el-sub-menu__title {
+                    background: none;
+                    padding: 0 2px;
+                    justify-content: center;
+                }
+                .el-sub-menu__title {
+                    height: 32px;
+                }
+                .el-sub-menu .el-sub-menu__icon-arrow {
+                    position: static;
+                    padding-top: 6px;
+                }
+                .el-sub-menu {
+                    margin-bottom: 16px;
+                    &.is-opened {
+                        .el-sub-menu__icon-arrow {
+                            padding-bottom: 6px;
+                            padding-top: 0;
+                        }
+                    }
+                    .el-menu-item {
+                        height: 32px;
+                        line-height: 32px;
+                        margin: 4px 8px;
+                        padding: 0 2px;
+                        justify-content: center;
+                        background: none;
+                    }
+                    .el-menu-item.is-active {
+                        background: none;
+                        color: #fff;
+                    }
+                    .el-anchor__item {
+                        width: 100%;
+                        text-align: center;
+                    }
+                    .el-anchor__link {
+                        color: #666666;
+                    }
+                    .el-anchor__link.is-active {
+                        background: rgba(33, 153, 248, 0.1);
+                        border-radius: 20px;
+                        color: #2199f8;
+                        border: 1px solid #2199f8;
+                    }
+                }
+            }
+            .el-anchor__list {
+                padding-left: 0;
+            }
+        }
+    }
+    .expert-content {
+        width: calc(100% - 100px);
+        height: 100%;
+        overflow: auto;
+        box-sizing: border-box;
+        .content-section {
+            position: relative;
+            .section-item {
+                position: relative;
+                border-radius: 14px;
+                border: 1px solid rgba(228, 228, 228, 0.5);
+                .record-item{
+                    padding: 12px 0;
+                }
+            }
+            .section-item + .section-item{
+                margin-top: 10px;
+            }
+            .section-id {
+                position: absolute;
+                top: 0;
+                width: 100%;
+                height: 1px;
+            }
+        }
+        .content-section + .content-section{
+            margin-top: 10px;
+        }
+        .box-title {
+            display: flex;
+            align-items: center;
+            padding-bottom: 8px;
+            border-bottom: 1px solid #f5f5f5;
+            margin-bottom: 8px;
+            .title-l {
+                font-size: 16px;
+                font-weight: 600;
+                color: #000;
+                .parent-text {
+                    margin-left: 5px;
+                    font-size: 12px;
+                    font-weight: normal;
+                    padding: 4px 6px;
+                    border-radius: 14px;
+                    background: rgba(119, 119, 119, 0.1);
+                }
+            }
+        }
+    }
+}
+</style>

+ 65 - 0
src/components/pageComponents/StatsBox.vue

@@ -0,0 +1,65 @@
+<template>
+    <div class="stats">
+        <div v-for="(item, index) in statsData" :key="index" class="col">
+            <div class="num">
+                {{ item.value }}
+                <span class="unit"> {{ item.unit }}</span>
+            </div>
+            <div class="desc">{{ item.desc }}</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+defineProps({
+    statsData: {
+        type: Array,
+        required: true,
+        default: () => [],
+    },
+});
+</script>
+
+<style scoped lang="scss">
+.stats {
+    display: flex;
+    align-items: stretch;
+    justify-content: space-between;
+    background: rgba(33, 153, 248, 0.1);
+    border: 1px solid rgba(33, 153, 248, 0.2);
+    border-radius: 10px;
+    padding: 10px 8px;
+    font-size: 14px;
+    margin-top: 12px;
+
+    .col {
+        flex: 1;
+        text-align: center;
+
+        .num {
+            color: #2199f8;
+            font-weight: 600;
+            font-size: 16px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+
+            .unit {
+                margin-left: 4px;
+                font-size: 13px;
+                font-weight: 400;
+                color: rgba(0, 0, 0, 0.5);
+            }
+        }
+
+        .desc {
+            color: #000;
+            margin-top: 4px;
+        }
+    }
+
+    .col + .col {
+        border-left: 1px solid rgba(33, 153, 248, 0.4);
+    }
+}
+</style>

+ 93 - 0
src/components/pageComponents/TabList.vue

@@ -0,0 +1,93 @@
+<template>
+    <div class="tabs-container" :class="[`tabs-type-${type}`, { 'tabs-small': tabs.length <= 2 }]">
+        <div 
+            v-for="(tab, index) in tabs" 
+            :key="index"
+            class="tab-item"
+            :class="{ active: modelValue === index }"
+            @click="handleTabClick(index)"
+        >
+            {{ tab }}
+        </div>
+    </div>
+</template>
+
+<script setup>
+const props = defineProps({
+    tabs: {
+        type: Array,
+        required: true,
+        default: () => []
+    },
+    modelValue: {
+        type: Number,
+        default: 0
+    },
+    type: {
+        type: String,
+        default: 'default', // 'default' | 'light'
+        validator: (value) => ['default', 'light'].includes(value)
+    }
+});
+
+const emit = defineEmits(['update:modelValue', 'change']);
+
+const handleTabClick = (index) => {
+    emit('update:modelValue', index);
+    emit('change', index, props.tabs[index]);
+};
+</script>
+
+<style scoped lang="scss">
+.tabs-container {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    
+    .tab-item {
+        flex: 1;
+        padding: 6px 0;
+        border-radius: 20px;
+        text-align: center;
+        cursor: pointer;
+        transition: all 0.3s ease;
+    }
+    
+    // 标签数量 <= 2 时的样式
+    &.tabs-small {
+        gap: 8px;
+        
+        .tab-item {
+            flex: none;
+            padding: 5px 12px;
+        }
+    }
+    
+    // 默认样式
+    &.tabs-type-default {
+        .tab-item {
+            background: #F7F8FA;
+            color: #8B8B8B;
+            
+            &.active {
+                background: #2199F8;
+                color: #ffffff;
+            }
+        }
+    }
+    
+    // 浅色样式(激活:浅蓝色背景+深蓝色文字,未激活:浅灰色背景+中灰色文字)
+    &.tabs-type-light {
+        .tab-item {
+            background: #F7F8FA;
+            color: #8B8B8B;
+            
+            &.active {
+                background: rgba(33, 153, 248, 0.1);
+                color: #2199F8;
+            }
+        }
+    }
+}
+</style>
+

+ 185 - 2
src/components/recordItem.vue

@@ -1,9 +1,52 @@
 <template>
     <div class="record-item">
         <div class="record-title">
-            <slot name="title"></slot>
+            <!-- 内置标题模板 -->
+            <div v-if="titleMode === 'default'" class="box-title">
+                <div class="title-l">
+                    {{ recordItemData.title || recordItemData.farmWorkDetail?.name || '' }}
+                    <span v-if="getParentTitle()" class="parent-text">
+                        {{ getParentTitle() }}
+                    </span>
+                </div>
+                <!-- 按钮样式 -->
+                <div v-if="titleRightText && titleRightType !== 'dot'" class="title-r title-r-button">{{ titleRightText }}</div>
+                <!-- 点样式 -->
+                <div v-if="titleRightDotText && titleRightType === 'dot'" class="title-r title-r-dot">
+                    <span class="r-dot"></span>
+                    {{ titleRightDotText }}
+                </div>
+            </div>
+            <!-- 自定义标题插槽 -->
+            <slot v-else name="title"></slot>
         </div>
-        <slot name="content" v-if="showContent"></slot>
+        <!-- 服务详情模式的内容 -->
+        <div v-if="contentMode === 'serviceDetail'" class="record-content service-detail-content">
+            <div class="content-info">
+                <div class="info-line">
+                    药物处方:<span class="info-val">{{ getPrescriptionInfo(recordItemData) }}</span>
+                </div>
+                <div class="review-title info-line">
+                    复核成效
+                    <div class="info-val">
+                        {{ recordItemData.reCheckText || '通过精准农业技术的应用,作物产量实现了两位数的增长,病虫害的发生率大幅下降,土壤肥力的提升' }}
+                    </div>
+                </div>
+                <div class="review-image" v-if="recordItemData.beforeImage || recordItemData.afterImage">
+                    <div class="image-wrapper" v-if="recordItemData.beforeImage">
+                        <span class="image-label">农事前</span>
+                        <img :src="recordItemData.beforeImage" alt="" />
+                    </div>
+                    <div class="image-wrapper" v-if="recordItemData.afterImage">
+                        <span class="image-label">农事后</span>
+                        <img :src="recordItemData.afterImage" alt="" />
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!-- 自定义内容插槽 -->
+        <slot name="content" v-else-if="showContent"></slot>
+        <!-- 默认内容 -->
         <div class="record-content" v-else>
             <div class="info-item">
                 推荐时间:
@@ -97,7 +140,49 @@ const props = defineProps({
         type: Boolean,
         default: false,
     },
+    contentMode: {
+        type: String,
+        default: '',
+        validator: (value) => ['', 'serviceDetail'].includes(value),
+    },
+    titleMode: {
+        type: String,
+        default: '',
+        validator: (value) => ['', 'default'].includes(value),
+    },
+    titleRightText: {
+        type: String,
+        default: '',
+    },
+    titleRightType: {
+        type: String,
+        default: 'button',
+        validator: (value) => ['button', 'dot'].includes(value),
+    },
+    titleRightDotText: {
+        type: String,
+        default: '',
+    },
 });
+
+const getPrescriptionInfo = (section) => {
+    // 从section的prescriptionList中获取药物信息
+    if (section.prescriptionList && section.prescriptionList.length > 0) {
+        const firstPrescription = section.prescriptionList[0];
+        if (firstPrescription.pesticideFertilizerList && firstPrescription.pesticideFertilizerList.length > 0) {
+            const firstDrug = firstPrescription.pesticideFertilizerList[0];
+            const ratio = firstDrug.ratio || firstDrug.defaultRatio || 1000;
+            return `${ratio}倍${firstDrug.brand}${firstDrug.pesticideFertilizerName}`;
+        }
+    }
+    return "1000倍国光乙烯利"; // 默认值
+};
+
+const getParentTitle = () => {
+    return props.recordItemData?.parentTitle || 
+           props.recordItemData?.farmWorkDetail?.parentTitle || 
+           '';
+};
 </script>
 
 <style lang="scss" scoped>
@@ -109,6 +194,57 @@ const props = defineProps({
     .record-title {
         font-size: 16px;
         color: #333333;
+        .box-title {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding-bottom: 8px;
+            .title-l {
+                font-size: 16px;
+                font-weight: 600;
+                color: #000;
+                display: flex;
+                align-items: center;
+                .parent-text {
+                    margin-left: 5px;
+                    font-size: 12px;
+                    font-weight: normal;
+                    padding: 4px 6px;
+                    border-radius: 14px;
+                    background: rgba(119, 119, 119, 0.1);
+                }
+            }
+            .title-btn {
+                width: 24px;
+                height: 24px;
+                border-radius: 50%;
+                background: #2199f8;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+            }
+            .title-r {
+                font-size: 12px;
+                &.title-r-button {
+                    padding: 5px 10px;
+                    border-radius: 20px;
+                    border: 1px solid #ff953d;
+                    color: #ff953d;
+                }
+                &.title-r-dot {
+                    display: flex;
+                    align-items: center;
+                    color: #393939;
+                    .r-dot {
+                        width: 6px;
+                        height: 6px;
+                        border-radius: 50%;
+                        background: #393939;
+                        margin-right: 5px;
+                    }
+                }
+            }
+        }
     }
     .record-content {
         font-size: 12px;
@@ -175,5 +311,52 @@ const props = defineProps({
             }
         }
     }
+    // 服务详情模式样式
+    .service-detail-content {
+        .content-info {
+            padding-top: 8px;
+            .info-line {
+                font-size: 12px;
+                color: #bbbbbb;
+                margin-bottom: 8px;
+                line-height: 1.4;
+                .info-val {
+                    color: #666666;
+                }
+            }
+            .review-title {
+                .info-val {
+                    margin-top: 5px;
+                }
+            }
+            .review-image {
+                display: flex;
+                align-items: center;
+                gap: 8px;
+                .image-wrapper {
+                    position: relative;
+                    flex: 1;
+                    img {
+                        width: 100%;
+                        height: 105px;
+                        object-fit: cover;
+                        border-radius: 8px;
+                    }
+                    .image-label {
+                        position: absolute;
+                        top: 4px;
+                        left: 4px;
+                        padding: 4px 10px;
+                        background: rgba(54, 52, 52, 0.6);
+                        color: #fff;
+                        font-size: 12px;
+                        border-radius: 8px 0 8px 0;
+                        z-index: 1;
+                        backdrop-filter: blur(4px);
+                    }
+                }
+            }
+        }
+    }
 }
 </style>

+ 12 - 0
src/router/globalRoutes.js

@@ -302,4 +302,16 @@ export default [
         name: "ServiceDetail",
         component: () => import("@/views/old_mini/mine/pages/serviceDetail.vue"),
     },
+    // 农场详情
+    {
+        path: "/farm_details",
+        name: "FarmDetails",
+        component: () => import("@/views/old_mini/user/farmDetails.vue"),
+    },
+    // 编辑农事方案
+    {
+        path: "/edit_plan",
+        name: "EditPlan",
+        component: () => import("@/views/old_mini/plan/editPlan.vue"),
+    },
 ];

+ 91 - 57
src/styles/common.scss

@@ -15,19 +15,21 @@ body {
     width: 100%;
     height: 100%;
     line-height: 24px;
-    font: 14px Helvetica Neue,Helvetica,Tahoma,Arial,sans-serif;
+    font: 14px Helvetica Neue, Helvetica, Tahoma, Arial, sans-serif;
     overflow: hidden;
     margin: 0;
     padding: 0;
     border: 0;
 }
-#app {
-    // background: #000;
-}
 img {
     vertical-align: middle;
 }
-h1, h2, h3, h4, h5, h6 {
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
     font-weight: 400;
 }
 
@@ -77,7 +79,7 @@ h1, h2, h3, h4, h5, h6 {
     height: calc(100vh - #{$nav-height} - 80px);
 }
 
-.no-events{
+.no-events {
     -webkit-pointer-events: none;
     -moz-pointer-events: none;
     -ms-pointer-events: none;
@@ -85,7 +87,7 @@ h1, h2, h3, h4, h5, h6 {
     pointer-events: none;
 }
 
-.yse-events{
+.yse-events {
     -webkit-pointer-events: auto;
     -moz-pointer-events: auto;
     -ms-pointer-events: auto;
@@ -93,7 +95,7 @@ h1, h2, h3, h4, h5, h6 {
     pointer-events: auto;
     text-decoration: none;
 }
-.yse-events input{
+.yse-events input {
     -webkit-pointer-events: auto;
     -moz-pointer-events: auto;
     -ms-pointer-events: auto;
@@ -102,7 +104,7 @@ h1, h2, h3, h4, h5, h6 {
     text-decoration: none;
 }
 
-.pure-events{
+.pure-events {
     -webkit-pointer-events: auto;
     -moz-pointer-events: auto;
     -ms-pointer-events: auto;
@@ -110,37 +112,37 @@ h1, h2, h3, h4, h5, h6 {
     pointer-events: auto;
 }
 
-.inline{
+.inline {
     display: inline;
 }
 
-.general-font1{
-    font-family:"microsoft yahei",Georgia,Serif;
+.general-font1 {
+    font-family: "microsoft yahei", Georgia, Serif;
     color: whitesmoke;
 }
 
-.general-font2{
-    font-family:"KaiTi",Georgia,Serif;
+.general-font2 {
+    font-family: "KaiTi", Georgia, Serif;
     color: whitesmoke;
 }
 
-.label-bg{
+.label-bg {
     background-color: #ffffff50;
     border-radius: 5px;
 }
 
-.cursor-default{
-    cursor:default;
+.cursor-default {
+    cursor: default;
 }
-.cursor-pointer{
-    cursor:pointer;
+.cursor-pointer {
+    cursor: pointer;
 }
-div{
+div {
     // font-family: PingFangSC-Medium, PingFang SC;
-    font-family: Helvetica Neue,Helvetica,Tahoma,Arial,sans-serif;
+    font-family: Helvetica Neue, Helvetica, Tahoma, Arial, sans-serif;
 }
 
-.ol-zoom{
+.ol-zoom {
     /*隐藏地图左上角的+-号*/
     display: none;
 }
@@ -148,13 +150,13 @@ div{
 // 图片预览去除下载和翻转
 .PhotoSlider__BannerWrap {
     .PhotoSlider__BannerRight {
-      svg {
-        &:nth-child(1),
-        &:nth-child(4),
-        &:nth-child(5) {
-          display: none;
+        svg {
+            &:nth-child(1),
+            &:nth-child(4),
+            &:nth-child(5) {
+                display: none;
+            }
         }
-      }
     }
 }
 
@@ -162,40 +164,44 @@ div{
     display: flex;
     align-items: center;
     justify-content: space-between;
-    .v-select{
-        .el-select__wrapper{
+    .v-select {
+        .el-select__wrapper {
             box-shadow: none;
-            background: #C8F1F7;
-            border: 1px solid #00D5F6;
+            background: #c8f1f7;
+            border: 1px solid #00d5f6;
             border-radius: 20px;
-            color: #00BEDB;
+            color: #00bedb;
         }
-        .el-select__placeholder,.el-select__caret,.el-select__placeholder.is-transparent{
-            color: #00BEDB;
+        .el-select__placeholder,
+        .el-select__caret,
+        .el-select__placeholder.is-transparent {
+            color: #00bedb;
             text-align: center;
         }
     }
-    .v-select + .v-select{
+    .v-select + .v-select {
         margin-left: 16px;
     }
 }
 
-.v-select-defalut-group{
+.v-select-defalut-group {
     display: flex;
     align-items: center;
     justify-content: space-between;
-    .v-select{
-        .el-select__wrapper{
+    .v-select {
+        .el-select__wrapper {
             box-shadow: none;
-            border: 1px solid #DDDDDD;
+            border: 1px solid #dddddd;
             border-radius: 20px;
         }
-        .el-select__placeholder,.el-select__caret,.el-select__placeholder.is-transparent{
+        .el-select__placeholder,
+        .el-select__caret,
+        .el-select__placeholder.is-transparent {
             color: #000;
             text-align: center;
         }
     }
-    .v-select + .v-select{
+    .v-select + .v-select {
         margin-left: 8px;
     }
 }
@@ -206,7 +212,7 @@ div{
 }
 
 .SOURCEHANSANSCN_0 {
-    font-family: 'SOURCEHANSANSCN_0', sans-serif; /* 使用自定义字体 */  
+    font-family: "SOURCEHANSANSCN_0", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -215,7 +221,7 @@ div{
 }
 
 .SIMKAI {
-    font-family: 'SIMKAI', sans-serif; /* 使用自定义字体 */  
+    font-family: "SIMKAI", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -224,7 +230,7 @@ div{
 }
 
 .PangMenZhengDao-FONT {
-    font-family: 'PangMenZhengDao', sans-serif; /* 使用自定义字体 */  
+    font-family: "PangMenZhengDao", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -233,7 +239,7 @@ div{
 }
 
 .YOUSHE-FONT {
-    font-family: 'YOUSHE', sans-serif; /* 使用自定义字体 */  
+    font-family: "YOUSHE", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -242,7 +248,7 @@ div{
 }
 
 .SOURCEHANSANSCN-FONT {
-    font-family: 'SOURCEHANSANSCN', sans-serif; /* 使用自定义字体 */  
+    font-family: "SOURCEHANSANSCN", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -251,7 +257,7 @@ div{
 }
 
 .SIMLI-FONT {
-    font-family: 'SIMLI', sans-serif; /* 使用自定义字体 */  
+    font-family: "SIMLI", sans-serif; /* 使用自定义字体 */
 }
 
 @font-face {
@@ -260,24 +266,52 @@ div{
 }
 
 .SMILEYSANS-FONT {
-    font-family: 'SmileySans', sans-serif; /* 使用自定义字体 */  
+    font-family: "SmileySans", sans-serif; /* 使用自定义字体 */
 }
 
 .ellipsis-l2 {
-	white-space: pre-line;
-	overflow: hidden;
-	text-overflow: ellipsis;
+    white-space: pre-line;
+    overflow: hidden;
+    text-overflow: ellipsis;
     word-break: break-all;
-	display: -webkit-box !important;
+    display: -webkit-box !important;
     -webkit-line-clamp: 2;
     -webkit-box-orient: vertical !important;
 }
 .ellipsis-l1 {
-	white-space: pre-line;
-	overflow: hidden;
-	text-overflow: ellipsis;
+    white-space: pre-line;
+    overflow: hidden;
+    text-overflow: ellipsis;
     word-break: break-all;
-	display: -webkit-box !important;
+    display: -webkit-box !important;
     -webkit-line-clamp: 1;
     -webkit-box-orient: vertical !important;
 }
+
+.custom-bottom-fixed-btns {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 12px;
+    background: #ffffff;
+    box-shadow: 2px 2px 4.5px rgba(0, 0, 0, 0.4);
+    z-index: 100;
+    .bottom-btn {
+        padding: 10px 20px;
+        border-radius: 25px;
+        text-align: center;
+        &.secondary-btn {
+            color: #666666;
+            border: 1px solid rgba(153, 153, 153, 0.5);
+        }
+        &.primary-btn {
+            background: linear-gradient(140deg, #9FD5FF, #2199F8);
+            color: #ffffff;
+            border: none;
+        }
+    }
+}

+ 25 - 8
src/views/old_mini/mine/index.vue

@@ -14,10 +14,15 @@
                     </div>
                     <div class="user-day">这是您使用飞鸟有味的第15天</div>
                 </div>
+                
             </div>
             <div class="code-icon" v-if="curRole === 1">
                 <img src="@/assets/img/mine/code-icon.png" alt="" />
             </div>
+            <div class="switch-role-btn" v-if="curRole === 2">
+                <span>切换身份</span>
+                <el-icon><Switch /></el-icon>
+            </div>
         </div>
         <div class="mine-content">
             <div class="garden-info" v-if="curRole !== 0">
@@ -51,7 +56,7 @@ import { useRouter } from "vue-router";
 const router = useRouter();
 
 // 0: 农户, 1: 专家, 2:农资农服
-const curRole = ref(2)
+const curRole = ref(2);
 
 // 网格项数据
 const gridItems = ref([]);
@@ -133,9 +138,13 @@ const cellItems = computed(() => {
         ];
     } else {
         return [
-        {
+            {
+                title: "我的消息",
+                path: "/message_list",
+            },
+            {
                 title: "农事方案",
-                path: "/service_records",
+                path: "/agricultural_plan",
             },
             {
                 title: "服务记录",
@@ -149,10 +158,6 @@ const cellItems = computed(() => {
                 title: "服务维护",
                 path: "/service_manage?identity=NZ&role=2",
             },
-            {
-                title: "退出登录",
-                path: "/logout",
-            },
         ];
     }
 });
@@ -198,7 +203,7 @@ const handleCellClick = (item) => {
         justify-content: space-between;
         .user-info-box {
             display: flex;
-            align-items: center;
+            align-items: center;     
             .avatar {
                 border: 1px solid #fff;
                 margin-right: 12px;
@@ -230,6 +235,18 @@ const handleCellClick = (item) => {
                 height: 100%;
             }
         }
+        .switch-role-btn{
+            margin-right: -16px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding: 5px 10px 6px 12px;
+            color: #fff;
+            background: #2199F8;
+            border-radius: 25px 0 0 25px;
+            gap: 5px;
+            font-size: 13px;
+        }
     }
     .mine-content {
         margin-top: 20px;

+ 31 - 267
src/views/old_mini/mine/pages/serviceDetail.vue

@@ -2,87 +2,35 @@
     <div class="service-detail-page">
         <custom-header name="服务详情"></custom-header>
         <div class="service-detail-content">
-            <div class="record-box">
-                <div class="item-left">
-                    <img class="map-img" src="/map.png" alt="地图" />
-                    <div class="item-cont">
-                        <div class="item-header">
-                            <div class="farm-name">从化荔博园</div>
-                            <div class="tags">
-                                <span class="tag tag-area">200亩</span>
-                                <span class="tag tag-variety">桂味</span>
-                            </div>
-                        </div>
-                        <div class="farm-address">广东省广州市从化区从化区</div>
-                    </div>
-                </div>
-                <div class="item-right">在线沟通</div>
-            </div>
+            <farm-info-card
+                class="record-box"
+                :data="{
+                    farmName: '从化荔博园',
+                    area: '200亩',
+                    variety: '桂味',
+                    address: '广东省广州市从化区从化区',
+                    mapImage: '/map.png',
+                }"
+            >
+                <template #right>
+                    <div>在线沟通</div>
+                </template>
+            </farm-info-card>
             <div class="farm-service-box">
                 <div class="service-title">
                     <img src="@/assets/img/home/label-icon.png" alt="" />
                     <span>农事服务</span>
                 </div>
-                <div class="stats">
-                    <div class="col">
-                        <div class="num">1258<span class="unit"> 元</span></div>
-                        <div class="desc">总收益</div>
-                    </div>
-                    <div class="col">
-                        <div class="num">1258<span class="unit"> 元</span></div>
-                        <div class="desc">投入成本</div>
-                    </div>
-                    <div class="col">
-                        <div class="num">118<span class="unit"> 次</span></div>
-                        <div class="desc">服务次数</div>
-                    </div>
-                </div>
+                <stats-box :stats-data="statsData" />
                 <div v-for="(section, index) in contentData" :key="index" class="content-section">
                     <record-item
                         :record-item-data="section"
                         :onlyRecipeName="true"
-                        :showContent="true"
+                        content-mode="serviceDetail"
+                        title-mode="default"
+                        title-right-text="分享成果"
                         class="recipe-item"
-                    >
-                        <template #title>
-                            <div class="box-title">
-                                <div class="title-l">
-                                    {{ section.title }}
-                                    <span class="parent-text">{{ section.parentTitle || "秋梢期" }}</span>
-                                </div>
-                                <div class="title-r">分享成果</div>
-                            </div>
-                        </template>
-                        <template #content>
-                            <div class="content-info">
-                                <div class="info-line">
-                                    药物处方:<span class="info-val">{{ getPrescriptionInfo(section) }}</span>
-                                </div>
-                                <div class="review-title info-line">
-                                    复核成效
-                                    <div class="info-val">
-                                        通过精准农业技术的应用,作物产量实现了两位数的增长,病虫害的发生率大幅下降,土壤肥力的提升
-                                    </div>
-                                </div>
-                                <div class="review-image">
-                                    <div class="image-wrapper">
-                                        <span class="image-label">农事前</span>
-                                        <img
-                                            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
-                                            alt=""
-                                        />
-                                    </div>
-                                    <div class="image-wrapper">
-                                        <span class="image-label">农事后</span>
-                                        <img
-                                            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
-                                            alt=""
-                                        />
-                                    </div>
-                                </div>
-                            </div>
-                        </template>
-                    </record-item>
+                    />
                 </div>
             </div>
         </div>
@@ -91,21 +39,16 @@
 
 <script setup>
 import customHeader from "@/components/customHeader.vue";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
+import StatsBox from "@/components/pageComponents/StatsBox.vue";
 import { ref } from "vue";
 import recordItem from "@/components/recordItem.vue";
 
-const getPrescriptionInfo = (section) => {
-    // 从section的prescriptionList中获取药物信息
-    if (section.prescriptionList && section.prescriptionList.length > 0) {
-        const firstPrescription = section.prescriptionList[0];
-        if (firstPrescription.pesticideFertilizerList && firstPrescription.pesticideFertilizerList.length > 0) {
-            const firstDrug = firstPrescription.pesticideFertilizerList[0];
-            const ratio = firstDrug.ratio || firstDrug.defaultRatio || 1000;
-            return `${ratio}倍${firstDrug.brand}${firstDrug.pesticideFertilizerName}`;
-        }
-    }
-    return "1000倍国光乙烯利"; // 默认值
-};
+const statsData = ref([
+    { value: "1258", unit: "元", desc: "总收益" },
+    { value: "1258", unit: "元", desc: "投入成本" },
+    { value: "118", unit: "次", desc: "服务次数" },
+]);
 
 const contentData = ref([
     {
@@ -114,7 +57,9 @@ const contentData = ref([
         parentTitle: "秋梢期",
         isExpanded: false, // 添加展开状态
         hasApplied: false, // 是否已发起需求
-        reCheckText: "本次农事复核成效优异,作物产量潜力实现大幅增长,虫害风险控制优异,未发现虫害风险",
+        reCheckText: "通过精准农业技术的应用,作物产量实现了两位数的增长,病虫害的发生率大幅下降,土壤肥力的提升",
+        beforeImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
+        afterImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
         expert: 91356,
         orderStatus: 3,
         activeStatus: 0,
@@ -199,6 +144,7 @@ const contentData = ref([
         ],
     },
 ]);
+
 </script>
 
 <style lang="scss" scoped>
@@ -209,65 +155,7 @@ const contentData = ref([
     .service-detail-content {
         padding: 10px 12px;
         .record-box {
-            background: #fff;
-            padding: 16px 12px;
-            border-radius: 8px;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            .item-left {
-                display: flex;
-                gap: 8px;
-                .map-img {
-                    width: 40px;
-                    height: 40px;
-                    border-radius: 6px;
-                    object-fit: cover;
-                }
-                .item-cont {
-                    .item-header {
-                        display: flex;
-                        justify-content: space-between;
-                        gap: 10px;
-                        font-size: 14px;
-                        margin-bottom: 4px;
-                        .farm-name {
-                            font-weight: 600;
-                            color: #000;
-                        }
-                        .tags {
-                            display: flex;
-                            gap: 6px;
-                            .tag {
-                                padding: 1px 8px;
-                                border-radius: 2px;
-                                font-size: 12px;
-                                &.tag-area {
-                                    background: #f4f4f4;
-                                    color: #1d2129;
-                                }
-
-                                &.tag-variety {
-                                    background: rgba(232, 243, 255, 1);
-                                    color: #2199f8;
-                                }
-                            }
-                        }
-                    }
-                    .farm-address {
-                        font-size: 12px;
-                        color: #86909c;
-                    }
-                }
-            }
-            .item-right {
-                text-align: center;
-                color: #888b8d;
-                font-size: 12px;
-                padding: 5px 12px;
-                border-radius: 20px;
-                border: 1px solid #888b8d;
-            }
+            margin-bottom: 0;
         }
         .farm-service-box {
             padding: 16px 12px;
@@ -288,134 +176,10 @@ const contentData = ref([
                     height: 8px;
                 }
             }
-            .stats {
-                display: flex;
-                align-items: stretch;
-                justify-content: space-between;
-                background: rgba(33, 153, 248, 0.1);
-                border: 1px solid rgba(33, 153, 248, 0.2);
-                border-radius: 10px;
-                padding: 10px 8px;
-                font-size: 14px;
-                margin-top: 12px;
-                .col {
-                    flex: 1;
-                    text-align: center;
-                    .num {
-                        color: #2199f8;
-                        font-weight: 600;
-                        font-size: 16px;
-                        .unit {
-                            font-size: 14px;
-                            font-weight: 400;
-                            color: #000;
-                        }
-                    }
-                    .desc {
-                        color: #000;
-                        margin-top: 4px;
-                    }
-                }
-                .col + .col {
-                    border-left: 1px solid rgba(33, 153, 248, 0.4);
-                }
-            }
             .content-section {
                 .recipe-item {
                     border: 1px solid rgba(0, 0, 0, 0.1);
                     margin: 12px 0 0 0;
-                    .box-title {
-                        display: flex;
-                        align-items: center;
-                        justify-content: space-between;
-                        padding-bottom: 8px;
-                        .title-l {
-                            font-size: 16px;
-                            font-weight: 600;
-                            color: #000;
-                            .parent-text {
-                                margin-left: 5px;
-                                font-size: 12px;
-                                font-weight: normal;
-                                padding: 4px 6px;
-                                border-radius: 14px;
-                                background: rgba(119, 119, 119, 0.1);
-                            }
-                        }
-                        .title-btn {
-                            width: 24px;
-                            height: 24px;
-                            border-radius: 50%;
-                            background: #2199f8;
-                            display: flex;
-                            align-items: center;
-                            justify-content: center;
-                        }
-                        .title-r {
-                            padding: 5px 10px;
-                            border-radius: 20px;
-                            border: 1px solid #FF953D;
-                            color: #FF953D;
-                            font-size: 12px;
-                        }
-                    }
-                    .content-info {
-                        padding-top: 8px;
-                        .info-line {
-                            font-size: 12px;
-                            color: #bbbbbb;
-                            margin-bottom: 8px;
-                            line-height: 1.4;
-                            .info-val {
-                                color: #666666;
-                            }
-                        }
-                        .review-title {
-                            .info-val {
-                                margin-top: 5px;
-                            }
-                        }
-                        .review-image {
-                            display: flex;
-                            align-items: center;
-                            gap: 8px;
-                            .image-wrapper {
-                                position: relative;
-                                flex: 1;
-                                img {
-                                    width: 100%;
-                                    height: 105px;
-                                    object-fit: cover;
-                                    border-radius: 8px;
-                                }
-                                .image-label {
-                                    position: absolute;
-                                    top: 4px;
-                                    left: 4px;
-                                    padding: 4px 10px;
-                                    background: rgba(54, 52, 52, 0.6);
-                                    color: #fff;
-                                    font-size: 12px;
-                                    border-radius: 8px 0 8px 0;
-                                    z-index: 1;
-                                    backdrop-filter: blur(4px);
-                                }
-                            }
-                        }
-                        .reminder-box {
-                            background: linear-gradient(90deg, #d9ebfc, transparent);
-                            border-radius: 4px;
-                            padding: 6px 8px;
-                            font-size: 12px;
-                            color: #2e2e2e;
-                            line-height: 1.4;
-                            margin-top: 8px;
-                            .highlight-number {
-                                color: #2199f8;
-                                font-weight: 500;
-                            }
-                        }
-                    }
                 }
             }
         }

+ 10 - 95
src/views/old_mini/mine/pages/serviceRecords.vue

@@ -10,32 +10,20 @@
             </el-select>
         </div>
         <div class="record-list">
-            <div class="record-item" v-for="(item, index) in recordList" :key="index" @click="handleItemClick(item)">
-                <div class="item-content">
-                    <img class="map-img" src="/map.png" alt="地图" />
-                    <div class="item-right">
-                        <div class="item-header">
-                            <div class="farm-name">{{ item.farmName }}</div>
-                            <div class="tags">
-                                <span class="tag tag-area">{{ item.area }}</span>
-                                <span class="tag tag-variety">{{ item.variety }}</span>
-                            </div>
-                        </div>
-                        <div class="farm-address">{{ item.address }}</div>
-                    </div>
-                </div>
-                <div class="item-footer">
-                    农事服务过<span class="service-count">{{ item.serviceCount }}</span
-                    >次
-                    <span class="view-detail">查看详情</span>
-                </div>
-            </div>
+            <farm-info-card
+                v-for="(item, index) in recordList"
+                :key="index"
+                :data="item"
+                @click="handleItemClick"
+                class="record-item"
+            />
         </div>
     </div>
 </template>
 <script setup>
 import { ref } from "vue";
 import customHeader from "@/components/customHeader.vue";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
 import { useRouter } from "vue-router";
 const router = useRouter();
 // 服务记录列表数据
@@ -75,8 +63,8 @@ const recordList = ref([
 ]);
 
 // 处理列表项点击
-const handleItemClick = (item) => {
-    console.log("点击了服务记录项:", item);
+const handleItemClick = (data) => {
+    console.log("点击了服务记录项:", data);
     // TODO: 跳转到详情页
     router.push("/service_detail");
 };
@@ -129,79 +117,6 @@ const areaOptions = [
     }
     .record-list {
         padding: 6px 12px;
-        .record-item {
-            background: #fff;
-            padding: 12px 10px;
-            border-radius: 5px;
-            .item-content {
-                display: flex;
-                gap: 8px;
-                .map-img {
-                    width: 40px;
-                    height: 40px;
-                    border-radius: 6px;
-                    object-fit: cover;
-                }
-                .item-right {
-                    .item-header {
-                        display: flex;
-                        justify-content: space-between;
-                        gap: 10px;
-                        font-size: 14px;
-                        margin-bottom: 4px;
-                        .farm-name {
-                            font-weight: 600;
-                            color: #000;
-                        }
-                        .tags {
-                            display: flex;
-                            gap: 6px;
-                            .tag {
-                                padding: 1px 8px;
-                                border-radius: 2px;
-                                font-size: 12px;
-                                &.tag-area {
-                                    background: #f4f4f4;
-                                    color: #1d2129;
-                                }
-
-                                &.tag-variety {
-                                    background: rgba(232, 243, 255, 1);
-                                    color: #2199f8;
-                                }
-                            }
-                        }
-                    }
-                    .farm-address {
-                        font-size: 12px;
-                        color: #86909c;
-                    }
-                }
-            }
-            .item-footer {
-                background: linear-gradient(90deg, rgba(33, 153, 248, 0.2) 0%, transparent 100%);
-                padding: 6px 8px;
-                display: flex;
-                align-items: center;
-                border-radius: 4px;
-                margin-top: 10px;
-                color: #2e2e2e;
-                font-size: 12px;
-                span {
-                    color: #2199f8;
-                    font-weight: 500;
-                }
-                .service-count {
-                    margin: 0 2px;
-                }
-                .view-detail {
-                    margin-left: 10px;
-                }
-            }
-        }
-        .record-item + .record-item {
-            margin-top: 12px;
-        }
     }
 }
 </style>

+ 25 - 4
src/views/old_mini/modify_work/index.vue

@@ -1,8 +1,8 @@
 <template>
     <div class="new-farming-page">
-        <custom-header :name="isAdd ? '新增农事' : '农事详情'"></custom-header>
+        <custom-header :name="isAdd ? '新增农事' : isEdit ? '编辑报价' : '农事详情'"></custom-header>
         <div class="new-farming-content">
-            <div v-if="!isAdd">
+            <div v-if="!isAdd && !isEdit">
                 <div class="step-wrap">
                     <farm-steps :currentStep="0" />
                 </div>
@@ -362,7 +362,12 @@
                         </div>
                     </div>
                 </div>
-                <div class="submit-btn" v-if="!isAdd">
+
+                <div class="submit-btn" v-if="isEdit">
+                    <div class="btn second" @click.prevent="cancelEdit">取消编辑</div>
+                    <div class="btn" @click.prevent="submitForm(formRef)">保存报价</div>
+                </div>
+                <div class="submit-btn" v-if="!isAdd && !isEdit">
                     <div class="btn second" @click="handleIgnore">忽略</div>
                     <div class="btn" @click.prevent="submitForm(formRef)">下发农事</div>
                 </div>
@@ -395,7 +400,7 @@
 <script setup>
 import { onActivated, ref, reactive, onDeactivated, computed, onMounted } from "vue";
 import { useRouter, useRoute } from "vue-router";
-import { ElMessage } from "element-plus";
+import { ElMessage ,ElMessageBox} from "element-plus";
 import customHeader from "@/components/customHeader.vue";
 import NewFarmMap from "./newFarmMap";
 import { useStore } from "vuex";
@@ -417,7 +422,9 @@ const isAdd = ref(false)
 const showTaskPopup = ref(false);
 const taskPopupType = ref('warning');
 
+const isEdit = ref(false)
 isAdd.value = route.query.isAdd ? true : false
+isEdit.value = route.query.isEdit ? true : false
 onMounted(() => {
     const id = route.query.id;
     if (id) {
@@ -500,6 +507,20 @@ const resetForm = (formEl) => {
     regionId.value = null;
 };
 
+const cancelEdit = () => {
+    ElMessageBox.confirm("确认要取消编辑吗?", "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
+    })
+        .then(() => {
+            router.back();
+        })
+        .catch(() => {
+            console.log("取消编辑");
+        });
+};
+
 // 表单
 const formRef = ref();
 const dynamicValidateForm = reactive({

+ 147 - 0
src/views/old_mini/plan/editPlan.vue

@@ -0,0 +1,147 @@
+<template>
+    <div class="edit-plan">
+        <custom-header name="查看详情"></custom-header>
+        <div class="edit-plan-content">
+            <record-item :record-item-data="contentData" title-mode="default" class="recipe-item" />
+            <prescription-table> </prescription-table>
+        </div>
+        <div class="custom-bottom-fixed-btns">
+            <div class="bottom-btn secondary-btn" @click="deletePrescription">删除处方</div>
+            <div class="bottom-btn primary-btn" @click="editPrice">编辑报价</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import customHeader from "@/components/customHeader.vue";
+import recordItem from "@/components/recordItem.vue";
+import prescriptionTable from "@/views/old_mini/agri_work/components/prescriptionTable.vue";
+import { ref } from "vue";
+import { ElMessageBox } from "element-plus";
+import { useRouter } from "vue-router";
+
+const router = useRouter();
+const deletePrescription = () => {
+    ElMessageBox.confirm("确认要删除该处方吗?", "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
+    })
+        .then(() => {
+            console.log("删除成功");
+        })
+        .catch(() => {
+            console.log("取消删除");
+        });
+};
+const editPrice = () => {
+    router.push({
+        path: "/modify_work",
+        query: { data: JSON.stringify(["生长异常"]), gardenId: 766, isEdit: true },
+    });
+};
+
+const contentData = ref({
+    title: "巡园农事",
+    parentTitle: "秋梢期",
+    reCheckText: "通过精准农业技术的应用,作物产量实现了两位数的增长,病虫害的发生率大幅下降,土壤肥力的提升",
+    beforeImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
+    afterImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
+    expert: 91356,
+    orderStatus: 3,
+    activeStatus: 0,
+    regionId: 2,
+    speciesId: "1",
+    speciesName: "荔枝",
+    farmWorkId: "699343457474318336",
+    farmWorkLibId: "699343457474318336",
+    farmWorkLibName: "梢期防虫",
+    farmWorkName: "梢期防虫",
+    expertIcon:
+        "https://birdseye-img.sysuimars.com/birdseye-look-vue/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250411150343.png",
+    expertName: "韦帮稳",
+    attention: "daskdjakjd",
+    beforeExecuteDate: "2025-08-01",
+    executeDate: "2025-08-15",
+    code: "BZ-BC-04-SQFC-20",
+    expertPrescription: "",
+    condition: "单树嫩叶率大于20.0%",
+    defaultFarmWork: 0,
+    farmWorkType: 3,
+    farmWorkTypeName: "病虫",
+    usageMode: "叶面施",
+    serviceMain: "广州泽秾丰农资有限公司",
+    updateDate6: null,
+    confirmPicture: [],
+    executeMain: "广州泽秾丰农资有限公司",
+    storeShortName: "泽秾丰",
+    serviceRegion: "广州市从化区荔枝博览园",
+    prescriptionList: [
+        {
+            name: "营养",
+            pesticideFertilizerList: [
+                {
+                    defaultDroneRatio: null,
+                    defaultName: "尿素",
+                    defaultRatio: 0,
+                    id: null,
+                    muPrice: null,
+                    muUsage: 15000.0,
+                    muUsage2: 15000.0,
+                    ratio: 0,
+                    ratio2: 0,
+                    remark: "",
+                    usageMode: "",
+                    usageModeList: ["叶面施、根部施"],
+                    orderId: null,
+                    pesticideFertilizerCode: "1001",
+                    pesticideFertilizerId: "1",
+                    pesticideFertilizerName: "尿素",
+                    brand: "山东联盟",
+                    typeName: "营养",
+                    price: 132,
+                    unit: "g",
+                    executeStyle: null,
+                },
+                {
+                    defaultDroneRatio: null,
+                    defaultName: "15-15-15复合肥",
+                    defaultRatio: 0,
+                    id: null,
+                    muPrice: null,
+                    muUsage: 45000.0,
+                    muUsage2: 45000.0,
+                    ratio: 0,
+                    ratio2: 0,
+                    remark: "",
+                    usageMode: "",
+                    usageModeList: ["根部施"],
+                    orderId: null,
+                    pesticideFertilizerCode: "1002",
+                    pesticideFertilizerId: "2",
+                    pesticideFertilizerName: "15-15-15复合肥",
+                    brand: "金正大",
+                    typeName: "营养",
+                    price: 220,
+                    unit: "g",
+                    executeStyle: null,
+                },
+            ],
+        },
+    ],
+});
+</script>
+
+<style scoped lang="scss">
+.edit-plan {
+    width: 100%;
+    height: 100vh;
+    background: #f2f3f5;
+    .edit-plan-content {
+        padding: 12px;
+        .record-item {
+            margin: 0;
+        }
+    }
+}
+</style>

+ 581 - 0
src/views/old_mini/plan/index copy.vue

@@ -0,0 +1,581 @@
+<template>
+    <div class="plan-page">
+        <custom-header name="农事方案"></custom-header>
+        <div class="plan-title">
+            <div class="tabs">
+                <div class="tab" :class="{ active: activeTab === 'left' }" @click="setActiveTab('left')">专家方案</div>
+                <div class="tab" :class="{ active: activeTab === 'right' }" @click="setActiveTab('right')">
+                    我的方案
+                    <span class="badge-dot">2</span>
+                </div>
+                <div class="slider" :style="sliderStyle"></div>
+            </div>
+        </div>
+        <div class="plan-content" v-if="activeTab === 'left'">
+            <div class="filter-wrap">
+                <div class="filter-l">指导专家:韦帮稳</div>
+                <div class="filter-r" @click="toPage">更多专家<el-icon><ArrowRightBold /></el-icon></div>
+            </div>
+            <div class="expert-prescription">
+                <div class="plan-menu">
+                    <el-anchor :container="containerRef" direction="vertical" type="default" @click="handleClick">
+                        <el-menu :default-active="defaultActive" class="el-menu-vertical-demo">
+                            <el-sub-menu v-for="(menu, index) in menuData" :key="index" :index="String(menu.id)">
+                                <template #title>
+                                    <img class="menu-icon" :src="require(`@/assets/img/gallery/icon-${index}.png`)" />
+                                    <span class="menu-text">{{ menu.name }}</span>
+                                </template>
+                                <el-menu-item v-for="item in menu.farmWorkArrangeList" :key="item.id" :index="`${menu.id}-${item.id}`">
+                                    <el-anchor-link :href="'#'+menu.name+item.farmWorkDetail?.name" :title="item.farmWorkDetail?.name || '摇花落花'" />
+                                </el-menu-item>
+                            </el-sub-menu>
+                        </el-menu>
+                    </el-anchor>
+                </div>
+                <div class="expert-content" ref="containerRef">
+                    <div v-for="(section, index) in menuData" :key="index" class="content-section">
+                        <div class="section-item" v-for="(sub, subI) in section.farmWorkArrangeList" :key="index+'-'+subI">
+                            <div class="section-id" :id="section.name+sub.farmWorkDetail?.name"></div>
+                            <record-item :record-item-data="sub">
+                                <template #title>
+                                    <div class="box-title">
+                                        <div class="title-l">
+                                            {{ sub.farmWorkDetail?.name }}
+                                            <span class="parent-text">{{ section.name }}</span>
+                                        </div>
+                                        <!-- <div class="title-btn" v-if="sub.selected == 0" @click="addToMyPlan">
+                                            <el-icon color="#fff" size="14"><Plus /></el-icon>
+                                        </div> -->
+                                    </div>
+                                </template>
+                            </record-item>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- 底部 -->
+            <div class="fixed-bottom">
+                <div class="bottom-l">
+                    <div class="l-btn">
+                        <el-icon color="#666666" class="btn-icon" size="16"><Download /></el-icon>
+                        下载处方
+                    </div>
+                    <div class="l-btn">
+                        <el-icon color="#666666" class="btn-icon" size="16"><ChatDotRound /></el-icon>
+                        咨询专家
+                    </div>
+                </div>
+                <div class="bottom-r">全部添加</div>
+            </div>
+        </div>
+        <div class="plan-content my-recipe" v-if="activeTab === 'right'">
+            <my-prescription :isSubPage="true"></my-prescription>
+            <!-- <div class="fixed-bottom">
+                <div class="bottom-l">
+                    <div class="l-btn">
+                        <img class="btn-icon calculator-icon" src="@/assets/img/home/calculator.png" alt="" />
+                        投入产出计算器
+                    </div>
+                </div>
+                <div class="bottom-r">新增农事</div>
+            </div> -->
+        </div>
+    </div>
+    <add-group ref="addGroupRef" />
+</template>
+
+<script setup>
+import { computed, onMounted, ref } from "vue";
+import recordItem from "@/components/recordItem.vue";
+import addGroup from "./components/addGroup.vue";
+import myPrescription from "./components/myPrescription.vue";
+import customHeader from "@/components/customHeader.vue";
+import { useStore } from "vuex";
+import { useRouter, useRoute } from "vue-router";
+const store = useStore();
+const router = useRouter()
+const route = useRoute()
+
+const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+
+const containerRef = ref(null);
+const handleClick = (e) => {
+    e.preventDefault();
+};
+const activeTab = ref("left");
+// const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+const sliderStyle = computed(() => {
+    // 根据当前激活的选项卡计算滑动条位置
+    const position = activeTab.value === "left" ? "25%" : "75%";
+    return {
+        left: `calc(${position} - 12px)`, // 减去滑动条宽度的一半以实现居中
+    };
+});
+function setActiveTab(tab) {
+    activeTab.value = tab;
+}
+const typeVal = ref([1, 3]);
+
+const typeOptions = ref([
+    {
+        value: 1,
+        label: "荔枝",
+        children: [
+            {
+                value: 2,
+                label: "井岗红糯",
+            },
+            {
+                value: 3,
+                label: "桂味",
+            },
+            {
+                value: 4,
+                label: "妃子笑",
+            },
+            {
+                value: 5,
+                label: "黑叶",
+            },
+        ],
+    },
+    {
+        value: 6,
+        label: "龙眼",
+        children: [
+            {
+                value: 7,
+                label: "龙眼1",
+            },
+            {
+                value: 8,
+                label: "龙眼2",
+            },
+            {
+                value: 9,
+                label: "龙眼3",
+            },
+            {
+                value: 10,
+                label: "龙眼4",
+            },
+        ],
+    },
+    {
+        value: 11,
+        label: "枇杷",
+        children: [
+            {
+                value: 12,
+                label: "枇杷1",
+            },
+            {
+                value: 13,
+                label: "枇杷2",
+            },
+            {
+                value: 14,
+                label: "枇杷3",
+            },
+            {
+                value: 15,
+                label: "枇杷4",
+            },
+        ],
+    },
+]);
+
+const proviceVal = ref("广东");
+const proviceOptions = ref([
+    {
+        value: "广东",
+        label: "广东省",
+    },
+    {
+        value: "广西",
+        label: "广西省",
+    },
+    {
+        value: "福建",
+        label: "福建省",
+    },
+    {
+        value: "海南",
+        label: "海南省",
+    },
+]);
+
+// 菜单
+const defaultActive = ref("1-1");
+
+const menuData = ref([])
+
+const activePlanIndex = ref(0);
+const handlePlanClick = (index) => {
+    activePlanIndex.value = index;
+};
+
+const addGroupRef = ref(null);
+// 新增方案
+function newPlan() {
+    addGroupRef.value.openClientPopup();
+}
+
+// 将专家处方添加到我的处方
+function addToMyPlan() {
+    addGroupRef.value.openClientPopup({type: "edit"});
+}
+
+function toPage() {
+    router.push("/expert_list?isToSelect=true")
+}
+
+function getWorkList() {
+    VE_API.home.getPhenologyFarmWorkList({farmId: 93301, containerId: route.query.containerId || 2}).then(({data}) => {
+        menuData.value = data
+    })
+}
+
+onMounted(() => {
+    getWorkList()
+})
+</script>
+
+<style lang="scss" scoped>
+.plan-page {
+    position: relative;
+    height: 100vh;
+    .plan-title {
+        width: 158px;
+        margin: 0 auto;
+        padding: 6px 0;
+        .tabs {
+            display: flex;
+            position: relative;
+            height: 36px;
+            line-height: 36px;
+            .tab {
+                flex: 1;
+                text-align: center;
+                cursor: pointer;
+                color: rgba(0, 0, 0, 0.5);
+                z-index: 2;
+                transition: color 0.3s ease;
+                position: relative;
+                &.active {
+                    color: #000000;
+                    font-weight: bold;
+                }
+                .badge-dot {
+                    position: absolute;
+                    top: 0;
+                    right: -6px;
+                    width: 16px;
+                    height: 16px;
+                    background-color: #ff0000;
+                    border-radius: 50%;
+                    font-size: 12px;
+                    line-height: 16px;
+                    color: #fff;
+                }
+            }
+            .slider {
+                position: absolute;
+                height: 4px;
+                width: 24px;
+                background: #2199f8;
+                border-radius: 16px;
+                bottom: 0;
+                left: calc(25% - 12px); /* 初始位置在第一个选项卡中间 */
+                transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+            }
+        }
+
+        .content {
+            padding: 20px;
+            background: #f8f9fa;
+            border-radius: 8px;
+            min-height: 200px;
+        }
+
+        .content-section {
+            display: none;
+            animation: fadeIn 0.5s ease;
+            
+            .section-item {
+                position: relative;
+            }
+        }
+
+        .content-section.active {
+            display: block;
+        }
+
+        @keyframes fadeIn {
+            from {
+                opacity: 0;
+                transform: translateY(10px);
+            }
+            to {
+                opacity: 1;
+                transform: translateY(0);
+            }
+        }
+    }
+    .plan-content {
+        background: #f5f7fb;
+        .filter-wrap {
+            padding: 10px 12px;
+            width: 100%;
+            box-sizing: border-box;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .filter-r {
+                height: 32px;
+                display: flex;
+                align-items: center;
+                padding: 0 18px;
+                background: rgba(33, 153, 248, 0.1);
+                border-radius: 20px;
+                color: #2199F8;
+                font-size: 14px;
+            }
+        }
+    }
+    .fixed-bottom {
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 14px 12px;
+        background: #fff;
+        box-sizing: border-box;
+        border-top: 1px solid rgba(153, 153, 153, 0.2);
+        .bottom-l {
+            display: flex;
+            align-items: center;
+            .l-btn {
+                border: 1px solid rgba(153, 153, 153, 0.5);
+                border-radius: 30px;
+                padding: 0 8px 0 12px;
+                height: 32px;
+                line-height: 32px;
+                box-sizing: border-box;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                color: #666666;
+                .btn-icon {
+                    padding-right: 3px;
+                }
+                .calculator-icon {
+                    width: 12px;
+                }
+            }
+            .l-btn + .l-btn {
+                margin-left: 10px;
+            }
+        }
+        .bottom-r {
+            height: 32px;
+            line-height: 32px;
+            background: #2199f8;
+            border-radius: 20px;
+            color: #fff;
+            padding: 0 12px;
+        }
+    }
+    .expert-prescription {
+        display: flex;
+        width: 100%;
+        height: calc(100vh - 52px - 48px - 50px);
+        .plan-menu {
+            width: 100px;
+            height: 100%;
+            overflow: auto;
+            padding: 10px 0;
+            box-sizing: border-box;
+            background: #fff;
+            border-radius: 0 10px 10px 0;
+            .menu-icon {
+                width: 13px;
+            }
+            .menu-text {
+                padding: 0 4px;
+            }
+            ::v-deep {
+                .el-anchor {
+                    height: 100%;
+                    background: none;
+                }
+                .el-anchor__marker {
+                    display: none;
+                }
+                .el-menu {
+                    background: none;
+                    border: none;
+                    .el-sub-menu__title {
+                        background: none;
+                        padding: 0 2px;
+                        justify-content: center;
+                    }
+                    .el-sub-menu__title {
+                        height: 32px;
+                    }
+                    .el-sub-menu .el-sub-menu__icon-arrow {
+                        position: static;
+                        padding-top: 6px;
+                    }
+                    .el-sub-menu {
+                        margin-bottom: 16px;
+                        &.is-opened {
+                            .el-sub-menu__icon-arrow {
+                                padding-bottom: 6px;
+                                padding-top: 0;
+                            }
+                        }
+                        .el-menu-item {
+                            height: 32px;
+                            line-height: 32px;
+                            margin: 4px 8px;
+                            padding: 0 2px;
+                            justify-content: center;
+                            background: none;
+                        }
+                        .el-menu-item.is-active {
+                            background: none;
+                            color: #fff;
+                        }
+                        .el-anchor__item {
+                            width: 100%;
+                            text-align: center;
+                        }
+                        .el-anchor__link {
+                            color: #666666;
+                        }
+                        .el-anchor__link.is-active {
+                            background: rgba(33, 153, 248, 0.1);
+                            border-radius: 20px;
+                            color: #2199F8;
+                            border: 1px solid #2199F8;
+                        }
+                    }
+                }
+                .el-anchor__list {
+                    padding-left: 0;
+                }
+            }
+        }
+        .expert-content {
+            width: calc(100% - 100px);
+            height: 100%;
+            overflow: auto;
+            padding-bottom: 80px;
+            box-sizing: border-box;
+            .content-section {
+                position: relative;
+                .section-item {
+                    position: relative;
+                }
+                .section-id {
+                    position: absolute;
+                    // top: -6px;
+                    top: 0;
+                    width: 100%;
+                    height: 1px;
+                }
+            }
+            .box-title {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+                padding-bottom: 8px;
+                border-bottom: 1px solid #f5f5f5;
+                margin-bottom: 8px;
+                .title-l {
+                    font-size: 16px;
+                    font-weight: 600;
+                    color: #000;
+                    .parent-text {
+                        margin-left: 5px;
+                        font-size: 12px;
+                        font-weight: normal;
+                        padding: 4px 6px;
+                        border-radius: 14px;
+                        background: rgba(119, 119, 119, 0.1);
+                    }
+                }
+                .title-btn {
+                    width: 24px;
+                    height: 24px;
+                    border-radius: 50%;
+                    background: #2199f8;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                }
+            }
+        }
+    }
+
+    .my-recipe {
+        .filter-wrap {
+            .plan-box {
+                display: flex;
+                overflow: auto;
+                white-space: nowrap;
+                align-items: center;
+                padding-left: 12px;
+                .plan-item {
+                    color: #000000;
+                    background: #f1f1f1;
+                    padding: 0 12px;
+                    height: 32px;
+                    line-height: 32px;
+                    border-radius: 20px;
+                    &.active {
+                        background: rgba(33, 153, 248, 0.2);
+                        color: #2199f8;
+                    }
+                }
+                .plan-item + .plan-item {
+                    margin-left: 10px;
+                }
+            }
+            .plan-add {
+                width: 80px;
+                height: 30px;
+                border: 1px solid #2199f8;
+                border-radius: 20px;
+                flex: none;
+                line-height: 32px;
+                text-align: center;
+                margin: 0 12px;
+                color: #2199f8;
+                font-size: 14px;
+            }
+        }
+        .title-r {
+            display: flex;
+            align-items: center;
+            .btn-item {
+                width: 24px;
+                height: 24px;
+                border-radius: 50%;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                background: #2199f8;
+                &.del-btn {
+                    margin-right: 5px;
+                    background: #ff953d;
+                }
+            }
+        }
+    }
+}
+</style>

+ 38 - 525
src/views/old_mini/plan/index.vue

@@ -1,493 +1,71 @@
 <template>
-    <div class="plan-page">
+    <div class="farm-card-page">
         <custom-header name="农事方案"></custom-header>
-        <div class="plan-title">
-            <div class="tabs">
-                <div class="tab" :class="{ active: activeTab === 'left' }" @click="setActiveTab('left')">专家方案</div>
-                <div class="tab" :class="{ active: activeTab === 'right' }" @click="setActiveTab('right')">
-                    我的方案
-                    <span class="badge-dot">2</span>
-                </div>
-                <div class="slider" :style="sliderStyle"></div>
-            </div>
-        </div>
-        <div class="plan-content" v-if="activeTab === 'left'">
-            <div class="filter-wrap">
-                <div class="filter-l">指导专家:韦帮稳</div>
-                <div class="filter-r" @click="toPage">更多专家<el-icon><ArrowRightBold /></el-icon></div>
-            </div>
-            <div class="expert-prescription">
-                <div class="plan-menu">
-                    <el-anchor :container="containerRef" direction="vertical" type="default" @click="handleClick">
-                        <el-menu :default-active="defaultActive" class="el-menu-vertical-demo">
-                            <el-sub-menu v-for="(menu, index) in menuData" :key="index" :index="String(menu.id)">
-                                <template #title>
-                                    <img class="menu-icon" :src="require(`@/assets/img/gallery/icon-${index}.png`)" />
-                                    <span class="menu-text">{{ menu.name }}</span>
-                                </template>
-                                <el-menu-item v-for="item in menu.farmWorkArrangeList" :key="item.id" :index="`${menu.id}-${item.id}`">
-                                    <el-anchor-link :href="'#'+menu.name+item.farmWorkDetail?.name" :title="item.farmWorkDetail?.name || '摇花落花'" />
-                                </el-menu-item>
-                            </el-sub-menu>
-                        </el-menu>
-                    </el-anchor>
-                </div>
-                <div class="expert-content" ref="containerRef">
+        <div class="farm-card-content">
+            <PlanList :farm-id="93301" :container-id="route.query.containerId || 2" :default-active="defaultActive">
+                <template #default="{ menuData }">
                     <div v-for="(section, index) in menuData" :key="index" class="content-section">
-                        <div class="section-item" v-for="(sub, subI) in section.farmWorkArrangeList" :key="index+'-'+subI">
-                            <div class="section-id" :id="section.name+sub.farmWorkDetail?.name"></div>
-                            <record-item :record-item-data="sub">
+                        <div
+                            class="section-item"
+                            v-for="(sub, subI) in section.farmWorkArrangeList"
+                            :key="index + '-' + subI"
+                        >
+                            <div class="section-id" :id="section.name + sub.farmWorkDetail?.name"></div>
+                            <record-item :record-item-data="sub" @click="handleClick(sub)">
                                 <template #title>
                                     <div class="box-title">
                                         <div class="title-l">
                                             {{ sub.farmWorkDetail?.name }}
                                             <span class="parent-text">{{ section.name }}</span>
                                         </div>
-                                        <!-- <div class="title-btn" v-if="sub.selected == 0" @click="addToMyPlan">
-                                            <el-icon color="#fff" size="14"><Plus /></el-icon>
-                                        </div> -->
+                                        <div class="title-r" v-if="curRole === 2">
+                                            <el-icon color="#2199F8" size="16"><Edit /></el-icon>
+                                        </div>
                                     </div>
                                 </template>
                             </record-item>
                         </div>
                     </div>
-                </div>
-            </div>
-            <!-- 底部 -->
-            <div class="fixed-bottom">
-                <div class="bottom-l">
-                    <div class="l-btn">
-                        <el-icon color="#666666" class="btn-icon" size="16"><Download /></el-icon>
-                        下载处方
-                    </div>
-                    <div class="l-btn">
-                        <el-icon color="#666666" class="btn-icon" size="16"><ChatDotRound /></el-icon>
-                        咨询专家
-                    </div>
-                </div>
-                <div class="bottom-r">全部添加</div>
-            </div>
-        </div>
-        <div class="plan-content my-recipe" v-if="activeTab === 'right'">
-            <my-prescription :isSubPage="true"></my-prescription>
-            <!-- <div class="fixed-bottom">
-                <div class="bottom-l">
-                    <div class="l-btn">
-                        <img class="btn-icon calculator-icon" src="@/assets/img/home/calculator.png" alt="" />
-                        投入产出计算器
-                    </div>
-                </div>
-                <div class="bottom-r">新增农事</div>
-            </div> -->
+                </template>
+            </PlanList>
         </div>
     </div>
-    <add-group ref="addGroupRef" />
 </template>
 
 <script setup>
-import { computed, onMounted, ref } from "vue";
-import recordItem from "@/components/recordItem.vue";
-import addGroup from "./components/addGroup.vue";
-import myPrescription from "./components/myPrescription.vue";
 import customHeader from "@/components/customHeader.vue";
-import { useStore } from "vuex";
-import { useRouter, useRoute } from "vue-router";
-const store = useStore();
-const router = useRouter()
-const route = useRoute()
-
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-
-const containerRef = ref(null);
-const handleClick = (e) => {
-    e.preventDefault();
-};
-const activeTab = ref("left");
-// const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-const sliderStyle = computed(() => {
-    // 根据当前激活的选项卡计算滑动条位置
-    const position = activeTab.value === "left" ? "25%" : "75%";
-    return {
-        left: `calc(${position} - 12px)`, // 减去滑动条宽度的一半以实现居中
-    };
-});
-function setActiveTab(tab) {
-    activeTab.value = tab;
-}
-const typeVal = ref([1, 3]);
-
-const typeOptions = ref([
-    {
-        value: 1,
-        label: "荔枝",
-        children: [
-            {
-                value: 2,
-                label: "井岗红糯",
-            },
-            {
-                value: 3,
-                label: "桂味",
-            },
-            {
-                value: 4,
-                label: "妃子笑",
-            },
-            {
-                value: 5,
-                label: "黑叶",
-            },
-        ],
-    },
-    {
-        value: 6,
-        label: "龙眼",
-        children: [
-            {
-                value: 7,
-                label: "龙眼1",
-            },
-            {
-                value: 8,
-                label: "龙眼2",
-            },
-            {
-                value: 9,
-                label: "龙眼3",
-            },
-            {
-                value: 10,
-                label: "龙眼4",
-            },
-        ],
-    },
-    {
-        value: 11,
-        label: "枇杷",
-        children: [
-            {
-                value: 12,
-                label: "枇杷1",
-            },
-            {
-                value: 13,
-                label: "枇杷2",
-            },
-            {
-                value: 14,
-                label: "枇杷3",
-            },
-            {
-                value: 15,
-                label: "枇杷4",
-            },
-        ],
-    },
-]);
-
-const proviceVal = ref("广东");
-const proviceOptions = ref([
-    {
-        value: "广东",
-        label: "广东省",
-    },
-    {
-        value: "广西",
-        label: "广西省",
-    },
-    {
-        value: "福建",
-        label: "福建省",
-    },
-    {
-        value: "海南",
-        label: "海南省",
-    },
-]);
+import { ref } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import recordItem from "@/components/recordItem.vue";
+import PlanList from "@/components/pageComponents/PlanList.vue";
 
+const curRole = ref(localStorage.getItem("curRole") || 0);
+const route = useRoute();
+const router = useRouter();
 // 菜单
 const defaultActive = ref("1-1");
 
-const menuData = ref([])
-
-const activePlanIndex = ref(0);
-const handlePlanClick = (index) => {
-    activePlanIndex.value = index;
+const handleClick = (sub) => {
+    if (curRole.value === 2) {
+        router.push(`/edit_plan?id=${sub.id}`);
+    }
 };
-
-const addGroupRef = ref(null);
-// 新增方案
-function newPlan() {
-    addGroupRef.value.openClientPopup();
-}
-
-// 将专家处方添加到我的处方
-function addToMyPlan() {
-    addGroupRef.value.openClientPopup({type: "edit"});
-}
-
-function toPage() {
-    router.push("/expert_list?isToSelect=true")
-}
-
-function getWorkList() {
-    VE_API.home.getPhenologyFarmWorkList({farmId: 93301, containerId: route.query.containerId || 2}).then(({data}) => {
-        menuData.value = data
-    })
-}
-
-onMounted(() => {
-    getWorkList()
-})
 </script>
 
-<style lang="scss" scoped>
-.plan-page {
-    position: relative;
+<style scoped lang="scss">
+.farm-card-page {
+    width: 100%;
     height: 100vh;
-    .plan-title {
-        width: 158px;
-        margin: 0 auto;
-        padding: 6px 0;
-        .tabs {
-            display: flex;
-            position: relative;
-            height: 36px;
-            line-height: 36px;
-            .tab {
-                flex: 1;
-                text-align: center;
-                cursor: pointer;
-                color: rgba(0, 0, 0, 0.5);
-                z-index: 2;
-                transition: color 0.3s ease;
-                position: relative;
-                &.active {
-                    color: #000000;
-                    font-weight: bold;
-                }
-                .badge-dot {
-                    position: absolute;
-                    top: 0;
-                    right: -6px;
-                    width: 16px;
-                    height: 16px;
-                    background-color: #ff0000;
-                    border-radius: 50%;
-                    font-size: 12px;
-                    line-height: 16px;
-                    color: #fff;
-                }
-            }
-            .slider {
-                position: absolute;
-                height: 4px;
-                width: 24px;
-                background: #2199f8;
-                border-radius: 16px;
-                bottom: 0;
-                left: calc(25% - 12px); /* 初始位置在第一个选项卡中间 */
-                transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
-            }
-        }
-
-        .content {
-            padding: 20px;
-            background: #f8f9fa;
-            border-radius: 8px;
-            min-height: 200px;
-        }
-
-        .content-section {
-            display: none;
-            animation: fadeIn 0.5s ease;
-            
-            .section-item {
-                position: relative;
-            }
-        }
-
-        .content-section.active {
-            display: block;
-        }
-
-        @keyframes fadeIn {
-            from {
-                opacity: 0;
-                transform: translateY(10px);
-            }
-            to {
-                opacity: 1;
-                transform: translateY(0);
-            }
-        }
-    }
-    .plan-content {
-        background: #f5f7fb;
-        .filter-wrap {
-            padding: 10px 12px;
-            width: 100%;
-            box-sizing: border-box;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            .filter-r {
-                height: 32px;
-                display: flex;
-                align-items: center;
-                padding: 0 18px;
-                background: rgba(33, 153, 248, 0.1);
-                border-radius: 20px;
-                color: #2199F8;
-                font-size: 14px;
-            }
-        }
-    }
-    .fixed-bottom {
-        position: absolute;
-        bottom: 0;
-        left: 0;
+    background: #f5f7fb;
+    .farm-card-content {
         width: 100%;
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        padding: 14px 12px;
-        background: #fff;
-        box-sizing: border-box;
-        border-top: 1px solid rgba(153, 153, 153, 0.2);
-        .bottom-l {
-            display: flex;
-            align-items: center;
-            .l-btn {
-                border: 1px solid rgba(153, 153, 153, 0.5);
-                border-radius: 30px;
-                padding: 0 8px 0 12px;
-                height: 32px;
-                line-height: 32px;
-                box-sizing: border-box;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                color: #666666;
-                .btn-icon {
-                    padding-right: 3px;
-                }
-                .calculator-icon {
-                    width: 12px;
-                }
-            }
-            .l-btn + .l-btn {
-                margin-left: 10px;
-            }
-        }
-        .bottom-r {
-            height: 32px;
-            line-height: 32px;
-            background: #2199f8;
-            border-radius: 20px;
-            color: #fff;
-            padding: 0 12px;
-        }
-    }
-    .expert-prescription {
-        display: flex;
-        width: 100%;
-        height: calc(100vh - 52px - 48px - 50px);
-        .plan-menu {
-            width: 100px;
+        height: calc(100vh - 40px);
+        padding-top: 10px;
+        ::v-deep .expert-prescription {
             height: 100%;
-            overflow: auto;
-            padding: 10px 0;
-            box-sizing: border-box;
-            background: #fff;
-            border-radius: 0 10px 10px 0;
-            .menu-icon {
-                width: 13px;
-            }
-            .menu-text {
-                padding: 0 4px;
-            }
-            ::v-deep {
-                .el-anchor {
-                    height: 100%;
-                    background: none;
-                }
-                .el-anchor__marker {
-                    display: none;
-                }
-                .el-menu {
-                    background: none;
-                    border: none;
-                    .el-sub-menu__title {
-                        background: none;
-                        padding: 0 2px;
-                        justify-content: center;
-                    }
-                    .el-sub-menu__title {
-                        height: 32px;
-                    }
-                    .el-sub-menu .el-sub-menu__icon-arrow {
-                        position: static;
-                        padding-top: 6px;
-                    }
-                    .el-sub-menu {
-                        margin-bottom: 16px;
-                        &.is-opened {
-                            .el-sub-menu__icon-arrow {
-                                padding-bottom: 6px;
-                                padding-top: 0;
-                            }
-                        }
-                        .el-menu-item {
-                            height: 32px;
-                            line-height: 32px;
-                            margin: 4px 8px;
-                            padding: 0 2px;
-                            justify-content: center;
-                            background: none;
-                        }
-                        .el-menu-item.is-active {
-                            background: none;
-                            color: #fff;
-                        }
-                        .el-anchor__item {
-                            width: 100%;
-                            text-align: center;
-                        }
-                        .el-anchor__link {
-                            color: #666666;
-                        }
-                        .el-anchor__link.is-active {
-                            background: rgba(33, 153, 248, 0.1);
-                            border-radius: 20px;
-                            color: #2199F8;
-                            border: 1px solid #2199F8;
-                        }
-                    }
-                }
-                .el-anchor__list {
-                    padding-left: 0;
-                }
-            }
-        }
-        .expert-content {
-            width: calc(100% - 100px);
-            height: 100%;
-            overflow: auto;
-            padding-bottom: 80px;
-            box-sizing: border-box;
-            .content-section {
-                position: relative;
-                .section-item {
-                    position: relative;
-                }
-                .section-id {
-                    position: absolute;
-                    // top: -6px;
-                    top: 0;
-                    width: 100%;
-                    height: 1px;
-                }
+            .plan-menu {
+                padding: 10px 0;
+                border-radius: 0 10px 10px 0;
             }
             .box-title {
                 display: flex;
@@ -509,71 +87,6 @@ onMounted(() => {
                         background: rgba(119, 119, 119, 0.1);
                     }
                 }
-                .title-btn {
-                    width: 24px;
-                    height: 24px;
-                    border-radius: 50%;
-                    background: #2199f8;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                }
-            }
-        }
-    }
-
-    .my-recipe {
-        .filter-wrap {
-            .plan-box {
-                display: flex;
-                overflow: auto;
-                white-space: nowrap;
-                align-items: center;
-                padding-left: 12px;
-                .plan-item {
-                    color: #000000;
-                    background: #f1f1f1;
-                    padding: 0 12px;
-                    height: 32px;
-                    line-height: 32px;
-                    border-radius: 20px;
-                    &.active {
-                        background: rgba(33, 153, 248, 0.2);
-                        color: #2199f8;
-                    }
-                }
-                .plan-item + .plan-item {
-                    margin-left: 10px;
-                }
-            }
-            .plan-add {
-                width: 80px;
-                height: 30px;
-                border: 1px solid #2199f8;
-                border-radius: 20px;
-                flex: none;
-                line-height: 32px;
-                text-align: center;
-                margin: 0 12px;
-                color: #2199f8;
-                font-size: 14px;
-            }
-        }
-        .title-r {
-            display: flex;
-            align-items: center;
-            .btn-item {
-                width: 24px;
-                height: 24px;
-                border-radius: 50%;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                background: #2199f8;
-                &.del-btn {
-                    margin-right: 5px;
-                    background: #ff953d;
-                }
             }
         }
     }

+ 340 - 0
src/views/old_mini/user/farmDetails.vue

@@ -0,0 +1,340 @@
+<template>
+    <div class="farm-details-page">
+        <custom-header name="农场详情"></custom-header>
+        <div class="farm-details-content">
+            <farm-info-card
+                :data="{
+                    farmName: '从化荔博园',
+                    area: '200亩',
+                    variety: '桂味',
+                    address: '广东省广州市从化区从化区',
+                    mapImage: '/map.png',
+                }"
+            >
+                <template #right>
+                    <div>基本信息</div>
+                </template>
+            </farm-info-card>
+            <tabs v-model:active="activeTab" class="custom-tabs" scrollspy sticky offset-top="40" background="#f5f7fb">
+                <tab title="农情互动" class="tab-item">
+                    <common-box title="农情互动">
+                        <template #right>
+                            <span>查看详情</span>
+                        </template>
+                        <div class="question-header">
+                            <img class="question-icon" src="@/assets/img/home/ask-icon.png" alt="" />
+                            <div class="question-title">在白点期,您当前农场是否出现白点?</div>
+                        </div>
+                        <template v-if="isImg">
+                            <div class="answer-content">答:2025.05.18 已经出现白点</div>
+                            <div class="answer-img">
+                                <img src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" alt="" />
+                                <img src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" alt="" />
+                                <img src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" alt="" />
+                            </div>
+                        </template>
+                        <div v-else class="answer-btn">
+                            <div class="answer-btn-item">转发给客户</div>
+                            <div class="answer-btn-item-group">
+                                <div class="answer-btn-item">否</div>
+                                <div class="answer-btn-item primary">是</div>
+                            </div>
+                        </div>
+                    </common-box>
+                </tab>
+                <tab title="农事服务" class="tab-item">
+                    <common-box title="农事服务">
+                        <template #right>
+                            <span>查看详情</span>
+                        </template>
+                        <tab-list
+                            type="light"
+                            v-model="farmServiceActiveTab"
+                            :tabs="farmServiceTabs"
+                            @change="handleFarmServiceTabChange"
+                        />
+                        <stats-box :stats-data="serviceStatsData" />
+                        <div v-for="(section, index) in contentData" :key="index" class="content-section">
+                            <record-item
+                                :record-item-data="section"
+                                onlyRecipeName
+                                :content-mode="farmServiceActiveTab === 0 ? 'serviceDetail' : ''"
+                                title-mode="default"
+                                title-right-type="dot"
+                                title-right-dot-text="2区"
+                                class="recipe-item"
+                            />
+                        </div>
+                    </common-box>
+                </tab>
+                <tab title="农场报告" class="tab-item">
+                    <common-box title="农场报告">
+                        <template #right>
+                            <span>查看详情</span>
+                        </template>
+                        <span class="report-content"
+                            >果园面积共XX亩,共有XX棵生产树。果园面积共XX亩,共有XX棵生产树。果园面积共XX亩,共有XX棵生产树。果园面积共XX亩,共有XX棵生产树。果园面积共XX亩,共有XX棵生产树。果园面积共XX亩,共有XX棵生产树。</span
+                        >
+                    </common-box>
+                </tab>
+                <tab title="农事方案" class="tab-item">
+                    <common-box title="农事方案">
+                        <template #right>
+                            <span>查看更多</span>
+                        </template>
+                        <plan-list :farm-id="93301" :container-id="route.query.containerId || 2" class="plan-list-wrapper" />
+                    </common-box>
+                </tab>
+            </tabs>
+        </div>
+        <div class="custom-bottom-fixed-btns">
+            <div class="bottom-btn secondary-btn">转发给客户</div>
+            <div class="bottom-btn primary-btn">在线沟通</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { useRoute } from "vue-router";
+import { Tab, Tabs } from "vant";
+import customHeader from "@/components/customHeader.vue";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
+import tabList from "@/components/pageComponents/TabList.vue";
+import commonBox from "@/components/pageComponents/CommonBox.vue";
+import StatsBox from "@/components/pageComponents/StatsBox.vue";
+import recordItem from "@/components/recordItem.vue";
+import PlanList from "@/components/pageComponents/PlanList.vue";
+
+const route = useRoute();
+const activeTab = ref(0);
+
+const farmServiceTabs = ["过往服务", "未来服务"];
+const farmServiceActiveTab = ref(0);
+
+const handleFarmServiceTabChange = (index) => {
+    console.log("切换到标签页:", index, farmServiceTabs[index]);
+    if(index === 0){
+        serviceStatsData.value = [
+            { value: "1258", unit: "元", desc: "总收益" },
+            { value: "1258", unit: "元", desc: "投入成本" },
+            { value: "118", unit: "次", desc: "服务次数" },
+        ];
+    }else{
+        serviceStatsData.value = [
+            { value: "1258", unit: "元", desc: "预计收益" },
+            { value: "1258", unit: "元", desc: "预计成本" },
+        ];
+    }
+};
+
+const serviceStatsData = ref([
+    { value: "1258", unit: "元", desc: "总收益" },
+    { value: "1258", unit: "元", desc: "投入成本" },
+    { value: "118", unit: "次", desc: "服务次数" },
+]);
+
+const contentData = ref([
+    {
+        targetId: "part1",
+        title: "巡园农事",
+        parentTitle: "秋梢期",
+        isExpanded: false, // 添加展开状态
+        hasApplied: false, // 是否已发起需求
+        reCheckText: "通过精准农业技术的应用,作物产量实现了两位数的增长,病虫害的发生率大幅下降,土壤肥力的提升",
+        beforeImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
+        afterImage: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
+        expert: 91356,
+        orderStatus: 3,
+        activeStatus: 0,
+        regionId: 2,
+        speciesId: "1",
+        speciesName: "荔枝",
+        farmWorkId: "699343457474318336",
+        farmWorkLibId: "699343457474318336",
+        farmWorkLibName: "梢期防虫",
+        farmWorkName: "梢期防虫",
+        expertIcon:
+            "https://birdseye-img.sysuimars.com/birdseye-look-vue/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20250411150343.png",
+        expertName: "韦帮稳",
+        icon: 4,
+        beforeExecuteDate: "2025-08-01",
+        executeDate: "2025-08-15",
+        code: "BZ-BC-04-SQFC-20",
+        expertPrescription: "",
+        condition: "单树嫩叶率大于20.0%",
+        defaultFarmWork: 0,
+        farmWorkType: 3,
+        farmWorkTypeName: "病虫",
+        usageMode: "叶面施",
+        serviceMain: "广州泽秾丰农资有限公司",
+        updateDate6: null,
+        confirmPicture: [],
+        executeMain: "广州泽秾丰农资有限公司",
+        storeShortName: "泽秾丰",
+        serviceRegion: "广州市从化区荔枝博览园",
+        prescriptionList: [
+            {
+                name: "营养",
+                pesticideFertilizerList: [
+                    {
+                        defaultDroneRatio: null,
+                        defaultName: "尿素",
+                        defaultRatio: 0,
+                        id: null,
+                        muPrice: null,
+                        muUsage: 15000.0,
+                        muUsage2: 15000.0,
+                        ratio: 0,
+                        ratio2: 0,
+                        remark: "",
+                        usageMode: "",
+                        usageModeList: ["叶面施、根部施"],
+                        orderId: null,
+                        pesticideFertilizerCode: "1001",
+                        pesticideFertilizerId: "1",
+                        pesticideFertilizerName: "尿素",
+                        brand: "山东联盟",
+                        typeName: "营养",
+                        price: 132,
+                        unit: "g",
+                        executeStyle: null,
+                    },
+                    {
+                        defaultDroneRatio: null,
+                        defaultName: "15-15-15复合肥",
+                        defaultRatio: 0,
+                        id: null,
+                        muPrice: null,
+                        muUsage: 45000.0,
+                        muUsage2: 45000.0,
+                        ratio: 0,
+                        ratio2: 0,
+                        remark: "",
+                        usageMode: "",
+                        usageModeList: ["根部施"],
+                        orderId: null,
+                        pesticideFertilizerCode: "1002",
+                        pesticideFertilizerId: "2",
+                        pesticideFertilizerName: "15-15-15复合肥",
+                        brand: "金正大",
+                        typeName: "营养",
+                        price: 220,
+                        unit: "g",
+                        executeStyle: null,
+                    },
+                ],
+            },
+        ],
+    },
+]);
+
+const isImg = ref(false);
+</script>
+
+<style scoped lang="scss">
+.farm-details-page {
+    width: 100%;
+    height: 100vh;
+    background: #f2f3f5;
+    .farm-details-content {
+        box-sizing: border-box;
+        padding: 10px 12px 70px 12px;
+        overflow: auto;
+        height: calc(100% - 40px);
+        box-sizing: border-box;
+        .custom-tabs {
+            ::v-deep {
+                .van-tabs__wrap {
+                    height: auto;
+                }
+                .van-tabs__nav {
+                    .van-tab {
+                        color: #8b8b8b;
+                        background: #f7f8fa;
+                        height: 34px;
+                        font-weight: 400;
+                        border-radius: 25px;
+                    }
+                    .van-tab--active {
+                        color: #fff;
+                        background: #2199f8;
+                        font-weight: 400;
+                    }
+                }
+
+                .van-tabs__line {
+                    display: none;
+                }
+                .van-tabs__nav--line {
+                    padding: 12px 0;
+                }
+            }
+            .tab-item + .tab-item {
+                margin-top: 12px;
+            }
+        }
+        .question-header {
+            display: flex;
+            align-items: center;
+            margin-bottom: 6px;
+            gap: 8px;
+            font-weight: 500;
+            .question-icon {
+                width: 22px;
+                height: 20px;
+            }
+        }
+        .answer-content {
+            color: #333333;
+            margin: 6px 0 10px 0;
+        }
+        .answer-img {
+            display: flex;
+            gap: 5px;
+            img {
+                flex: 1;
+                height: 105px;
+                border-radius: 5px;
+            }
+        }
+        .content-section {
+            .recipe-item {
+                border: 1px solid rgba(0, 0, 0, 0.1);
+                margin: 12px 0 0 0;
+            }
+        }
+        .plan-list-wrapper {
+            height: 500px;
+            margin-top: 12px;
+        }
+        .report-content {
+            font-size: 13px;
+        }
+        .answer-btn {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            margin-top: 10px;
+            > div {
+                display: flex;
+                gap: 10px;
+            }
+        }
+        .answer-btn-item {
+            padding: 7px 12px;
+            border-radius: 25px;
+            font-size: 12px;
+            text-align: center;
+            background: rgba(33, 153, 248, 0.1);
+            color: #2199f8;
+            min-width: 52px;
+            box-sizing: border-box;
+            &.primary {
+                background: #2199f8;
+                color: #ffffff;
+            }
+        }
+    }
+}
+</style>

+ 32 - 49
src/views/old_mini/user/index.vue

@@ -22,20 +22,26 @@
                     <template #value>
                         <div @click.stop="hadnleManage(item)" class="text">管理</div>
                     </template>
-                    <div class="list-item" v-for="(ele, idx) in item.children" :key="idx + ele.id">
-                        <div class="item-flex">
-                            <img class="photo" src="" alt="" />
-                            <div class="item-text">
-                                <div class="name">
-                                    <span>农场111</span>
-                                    <el-icon color="#2199F8" size="16"><Edit /></el-icon>
-                                </div>
-                                <div>农场品种:荔枝-桂味</div>
-                                <div>农场面积:190亩</div>
-                                <div>农场位置:湖北省武汉市富里唱鑫园5023</div>
-                            </div>
-                        </div>
-                    </div>
+                    <farm-info-card
+                        v-for="(ele, idx) in item.children"
+                        :key="idx + ele.id"
+                        class="list-item"
+                        :data="{
+                            farmName: ele.farmName || '农场111',
+                            area: ele.area || '190亩',
+                            variety: ele.variety || `荔枝-${ele.name}`,
+                            address: ele.address || '湖北省武汉市富里唱鑫园5023',
+                            mapImage: ele.mapImage || '/map.png',
+                            // day: 15,
+                            farmInfo: '梢期杀虫',
+                            estimatedIncome: ele.estimatedIncome || 2585
+                        }"
+                        @click="handleItemClick"
+                    >
+                        <template #right>
+                            <div>在线沟通</div>
+                        </template>
+                    </farm-info-card>
                 </collapse-item>
             </collapse>
         </div>
@@ -52,6 +58,7 @@ import { Collapse, CollapseItem } from "vant";
 import { ref } from "vue";
 import { useRouter } from "vue-router";
 import addPopup from "./components/addPopup.vue";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
 const router = useRouter();
 
 const input = ref("");
@@ -71,6 +78,11 @@ const hadnleManage = (value) => {
     router.push(`/user_manage?name=${value.name}&total=${value.children.length}&isGroup=${value.isGroup}`);
 };
 
+// 处理列表项点击
+const handleItemClick = (data) => {
+    router.push(`/farm_details?farmId=${data.farmId}`);
+};
+
 const list = ref([
     {
         name: "常用列表",
@@ -159,9 +171,12 @@ const activeNames = ref([0]);
         width: 100%;
         margin-top: 12px;
         .text {
-            color: #2199F8;
+            color: #7c7c7c;
         }
         ::v-deep {
+            .van-collapse-item__content{
+                padding: 0;
+            }
             .van-cell {
                 border-radius: 5px 5px 0 0;
                 justify-content: space-between;
@@ -194,41 +209,9 @@ const activeNames = ref([0]);
             }
         }
         .list-item {
-            border-radius: 12px;
-            background: #fff;
-            position: relative;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            .item-flex {
-                display: flex;
-                align-items: center;
-            }
-            .photo {
-                width: 68px;
-                height: 68px;
-                border-radius: 8px;
-                margin-right: 12px;
-                background: red;
+            & + .list-item {
+                margin: 0;
             }
-            .item-text {
-                color: #999999;
-                font-size: 12px;
-                line-height: 1.6;
-                .name {
-                    display: flex;
-                    align-items: center;
-                    span {
-                        font-size: 15px;
-                        color: #000;
-                        font-weight: 500;
-                        margin-right: 5px;
-                    }
-                }
-            }
-        }
-        .list-item + .list-item {
-            margin-top: 12px;
         }
     }
     .footer {