Преглед изворни кода

feat:添加农场相册功能和对接农事方案接口

wangsisi пре 1 недеља
родитељ
комит
69e356a97a

+ 1 - 0
src/api/config.js

@@ -18,6 +18,7 @@ module.exports = {
     base_img_url4: "https://xyz2.sysuimars.cn/",
     base_video_url : "https://minio.sysuimars.com/sysuimars/",
     resize: "?x-oss-process=image/resize,w_1000",
+    resize_300: "?x-oss-process=image/resize,w_300,p_30/format,webp/quality,q_20",
     //获取请求头中的参数体
     getOptBody : (opt)=>{
         return JSON.parse(opt.body);

+ 38 - 35
src/components/chatWindow.vue

@@ -320,6 +320,7 @@ const handleImgUrl = (url) => {
         return base_img_url2 + url + resize;
     }
 }
+
 watch(
     () => props.userId,
     async (newValue) => {
@@ -394,27 +395,19 @@ watch(
                         query: newQuery
                     });
                 }
-                if (props.text) {
-                    sendMsg("text", props.text);
-                    messages.value.push({
-                        sender: "sent",
-                        senderIcon: senderIcon.value,
-                        messageType: "text",
-                        content: props.text,
-                    });
-                    if (props.img) {
-                        const imgArr = JSON.parse(props.img);
-                        if (imgArr.length) {
-                            imgArr.forEach((item) => {
-                                sendMsg("image", "", { url: item, thumbnailUrl: item + resize });
-                                messages.value.push({
-                                    sender: "sent",
-                                    senderIcon: senderIcon.value,
-                                    messageType: "image",
-                                    content: item,
-                                });
-                            });
-                        }
+                if (route.query.selectedImgs) {
+                    const imgArr = JSON.parse(route.query.selectedImgs);
+                    if (imgArr && imgArr.length) {
+                        imgArr.forEach((item) => {
+                            sendImageMessage(item);
+                        });
+                        // 图片发送完成后,清除路由中的 selectedImgs 参数
+                        const newQuery = { ...route.query };
+                        delete newQuery.selectedImgs;
+                        router.replace({
+                            path: route.path,
+                            query: newQuery
+                        });
                     }
                 }
             });
@@ -516,6 +509,11 @@ const sendMessage = (message) => {
                 reportType: message.reportType,
             });
         }else{
+            sendMsg('report','',{
+                title: message.title,
+                reportId: message.reportId,
+                reportType: message.reportType,
+            });
             console.log('其他文件1');
         }
     }else{
@@ -546,12 +544,12 @@ const sendTextMessage = () => {
 };
 
 // 发送图片消息
-const sendImageMessage = (imageUrl) => {
+const sendImageMessage = (thumbnailUrl) => {
     const message = {
         sender: "sent",
         messageType: "image",
         senderIcon: senderIcon.value,
-        content: imageUrl,
+        content: thumbnailUrl,
         time: getCurrentTime(),
     };
     sendMessage(message);
@@ -589,7 +587,6 @@ const handleImageUpload = (event) => {
             imageUrl = base_img_url2 + resFilename;
             sendImageMessage(imageUrl);
         });
-        // const imageUrl = URL.createObjectURL(file);
     }
 };
 
@@ -677,17 +674,19 @@ const functionButtons = ref([
     // {
     //     text: "农事卡片",
     //     handler: () => {
+    //         clearSession.value = false
     //         // 跳转到农事卡片页面
     //         router.push(`/farm_card?farmId=${farmVal.value}`);
     //     },
     // },
-    // {
-    //     text: '农场相册',
-    //     handler: () => {
-    //         // 跳转到农场相册页面
-    //         router.push(`/farm_photo?farmId=${farmVal.value}&isCheck=true`);
-    //     }
-    // }
+    {
+        text: '农场相册',
+        handler: () => {
+            clearSession.value = false
+            // 跳转到农场相册页面
+            router.push(`/farm_photo?farmId=${farmVal.value}&isCheck=true&userId=${props.userId}`);
+        }
+    }
 ]);
 
 // 辅助函数
@@ -758,13 +757,17 @@ onActivated(() => {
 
 // 检查选中的农事工作数据
 const checkSelectedFarmWork = () => {
-    const selectedFarmWork = localStorage.getItem("selectedFarmWork");
+    const selectedFarmWork = sessionStorage.getItem("selectedFarmWork");
     if (selectedFarmWork) {
         const data = JSON.parse(selectedFarmWork);
+        const message = {
+            ...data,
+            coverUrl:''
+        };
         // 发送对话样式的消息
-        sendDialogMessage(data.dialogMessage);
+        sendMessage(data);
         // 清除localStorage中的数据
-        localStorage.removeItem("selectedFarmWork");
+        sessionStorage.removeItem("selectedFarmWork");
     }
 };
 
@@ -772,7 +775,7 @@ const checkSelectedFarmWork = () => {
 const sendDialogMessage = (dialogData) => {
     const message = {
         sender: "sent",
-        messageType: "dialog",
+        messageType: "report",
         senderIcon: senderIcon.value,
         content: dialogData,
         time: getCurrentTime(),

+ 20 - 1
src/components/pageComponents/PlanList.vue

@@ -41,6 +41,12 @@
                                     <div class="title-r" v-if="curRole == 2 && isEdit">
                                         <el-icon color="#2199F8" size="16"><Edit /></el-icon>
                                     </div>
+                                    <div class="title-r" v-if="isCheck">
+                                        <radio
+                                                :name="`${section.id}-${sub.id}`"
+                                                v-model="selectedItem"
+                                            />
+                                    </div>
                                 </div>
                             </template>
                         </record-item>
@@ -55,6 +61,7 @@
 import { ref, onMounted, watch } from "vue";
 import recordItem from "@/components/recordItem.vue";
 import { useRouter } from "vue-router";
+import { Radio } from "vant";
 
 const router = useRouter();
 
@@ -79,8 +86,17 @@ const props = defineProps({
         type: [Number, String],
         default: null,
     },
+    isCheck: {
+        type: Boolean,
+        default: false,
+    },
 });
 
+const emit = defineEmits(["selectionChange"]);
+
+// 选中状态
+const selectedItem = ref("");
+
 const curRole = localStorage.getItem("SET_USER_CUR_ROLE")
 const menuData = ref([]);
 const containerRef = ref(null);
@@ -116,13 +132,16 @@ const getFarmTypeText = (type) => {
 };
 
 const handleEdit = (sub) => {
-    console.log('sub', sub);
     if(curRole == 2 && props.isEdit){
         router.push({
             path: "/edit_plan",
             query: { arrangeId: sub.arrangeId }
         });
     }
+    if(props.isCheck){
+        selectedItem.value = `${sub.phenologyId}-${sub.id}`;
+        emit("selectionChange", sub);
+    }
 };
 
 watch(() => (props.schemeId || props.containerId), (newVal) => {

+ 5 - 6
src/views/old_mini/home/patrolPhoto.vue

@@ -81,9 +81,10 @@ import { ref, onMounted, nextTick, watch } from "vue";
 import { useRouter, useRoute } from "vue-router";
 import { List } from "vant";
 import { ElMessage } from "element-plus";
-import { base_img_url2 } from "@/api/config";
+import { base_img_url2,resize_300 } from "@/api/config";
 import customHeader from "@/components/customHeader.vue";
 
+
 const router = useRouter();
 const route = useRoute();
 const tabActive = ref(0);
@@ -237,7 +238,7 @@ const loadNextDateImages = () => {
                 const photoArr = data.images.map((item) => ({
                     ...item,
                     uid: buildImageUid(item),
-                    path: base_img_url2 + (item.resFilename || item.filename) + "?x-oss-process=image/resize,w_300",
+                    path: base_img_url2 + (item.resFilename || item.filename) + resize_300,
                 }));
 
                 // 将当前日期的图片数据添加到列表中
@@ -313,13 +314,11 @@ const handleSend = () => {
     photoListByDate.value.forEach((dateItem) => {
         dateItem.images.forEach((image) => {
             if (isImageSelected(image.uid)) {
-                // 返回 filename 或 resFilename
-                selectedFilenames.push(image.resFilename || image.filename);
+                selectedFilenames.push(base_img_url2 + image.filename);
             }
         });
     });
-    console.log("选中的图片filename:", selectedFilenames);
-    return selectedFilenames;
+    router.push(`/chat_frame?userId=${route.query.userId}&farmId=${farmId.value}&formPage=monitor&selectedImgs=${JSON.stringify(selectedFilenames)}`);
 };
 </script>
 

+ 38 - 278
src/views/old_mini/plan/farmCard.vue

@@ -1,59 +1,8 @@
 <template>
     <div class="farm-card-page">
-        <custom-header name="农卡片"></custom-header>
+        <custom-header name="农卡片"></custom-header>
         <div class="farm-card-content">
-            <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-r">
-                                            <radio
-                                                :name="`${section.id}-${sub.id}`"
-                                                v-model="selectedItem"
-                                                @change="handleSelectionChange"
-                                            />
-                                        </div>
-                                    </div>
-                                </template>
-                            </record-item>
-                        </div>
-                    </div>
-                </div>
-            </div>
+            <plan-list class="plan-list" :farmId="route.query.farmId" isCheck @selectionChange="handleSelectionChange"></plan-list>
         </div>
     </div>
     <div class="selection-info" v-if="selectedItem">
@@ -63,112 +12,56 @@
 
 <script setup>
 import customHeader from "@/components/customHeader.vue";
-import { ref, onMounted } from "vue";
+import { ref } from "vue";
 import { useRoute, useRouter } from "vue-router";
-import recordItem from "@/components/recordItem.vue";
-import { Radio } from "vant";
+import PlanList from "@/components/pageComponents/PlanList.vue";
+import { ElMessage } from "element-plus";
 
 const route = useRoute();
 const router = useRouter();
-const containerRef = ref(null);
-const handleClick = (e) => {
-    e.preventDefault();
-};
-// 菜单
-const defaultActive = ref("1-1");
 
-const menuData = ref([]);
 // 选中状态
-const selectedItem = ref("");
-
-function getWorkList() {
-    VE_API.home
-        .getPhenologyFarmWorkList({ farmId: 93301, containerId: route.query.containerId || 2 })
-        .then(({ data }) => {
-            menuData.value = data;
-        });
-}
+const selectedItem = ref({});
 
-// 处理选择变化
-const handleSelectionChange = (value) => {
-    selectedItem.value = value;
-    console.log("选中项:", value);
-};
+// 本地用户头像
+const localUserInfoIcon = (() => {
+    try {
+        const info = JSON.parse(localStorage.getItem("localUserInfo") || "{}");
+        return info?.icon || "";
+    } catch (e) {
+        return "";
+    }
+})();
 
 // 发送功能
 const handleSend = () => {
-    if (!selectedItem.value) {
-        console.log("请先选择一项");
+    if (!selectedItem.value.id) {
+        ElMessage.warning("请先选择一项");
         return;
     }
     
-    // 找到选中的项目数据
-    let selectedData = null;
-    for (const section of menuData.value) {
-        for (const sub of section.farmWorkArrangeList) {
-            if (`${section.id}-${sub.id}` === selectedItem.value) {
-                selectedData = {
-                    sectionName: section.name,
-                    workName: sub.farmWorkDetail?.name,
-                    executeDate: sub.farmWorkDetail?.executeDate,
-                    condition: sub.farmWorkDetail?.condition,
-                    code: sub.farmWorkDetail?.code,
-                    attention: sub.attention
-                };
-                break;
-            }
-        }
-        if (selectedData) break;
+    // 创建对话样式的消息
+    const dialogMessage = {
+        sender: "sent",
+        messageType: "report",
+        senderIcon: localUserInfoIcon,
+        title: `分享了一个${selectedItem.value.name}的农事`,
+        reportId:selectedItem.value.id,
+        reportType:'farm_card',
     }
     
-    if (selectedData) {
-        // 创建对话样式的消息
-        const dialogMessage = createDialogMessage(selectedData);
-        
-        // 返回到上一页并传递数据
-        router.back();
-        
-        // 可以通过事件总线或其他方式传递数据到聊天窗口
-        // 这里使用localStorage临时存储,实际项目中可以使用事件总线
-        localStorage.setItem('selectedFarmWork', JSON.stringify({
-            data: selectedData,
-            dialogMessage: dialogMessage
-        }));
-    }
+    // 返回到上一页并传递数据
+    router.back();
+    
+    // 可以通过事件总线或其他方式传递数据到聊天窗口
+    // 这里使用localStorage临时存储,实际项目中可以使用事件总线
+    sessionStorage.setItem('selectedFarmWork', JSON.stringify(dialogMessage));
 };
 
-// 创建对话样式的消息
-const createDialogMessage = (selectedData) => {
-    return {
-        type: 'farm_work_selection',
-        title: '农事复核情况',
-        content: `这是${selectedData.sectionName}${selectedData.workName}的农事复核情况,请查看~`,
-        beforeAfter: {
-            before: {
-                title: '农事前',
-                description: '农事执行前的状态',
-                image: 'https://birdseye-img.sysuimars.com/before-image.jpg' // 实际项目中应该是真实的图片URL
-            },
-            after: {
-                title: '农事后', 
-                description: '农事执行后的状态',
-                image: 'https://birdseye-img.sysuimars.com/after-image.jpg' // 实际项目中应该是真实的图片URL
-            }
-        },
-        workDetails: {
-            name: selectedData.workName,
-            section: selectedData.sectionName,
-            executeDate: selectedData.executeDate,
-            condition: selectedData.condition,
-            code: selectedData.code,
-            attention: selectedData.attention
-        }
-    };
+// 处理选择变化
+const handleSelectionChange = (value) => {
+    selectedItem.value = value;
 };
-
-onMounted(() => {
-    getWorkList();
-});
 </script>
 
 <style scoped lang="scss">
@@ -178,143 +71,10 @@ onMounted(() => {
     background: #f5f7fb;
     .farm-card-content {
         width: 100%;
-        height: 100%;
-        .expert-prescription {
-            display: flex;
-            width: 100%;
-            height: calc(100vh - 40px);
-            padding-top: 10px;
-            .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-r {
-                        display: flex;
-                        align-items: center;
-                    }
-                    .title-btn {
-                        width: 24px;
-                        height: 24px;
-                        border-radius: 50%;
-                        background: #2199f8;
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                    }
-                }
-            }
+        height: calc(100% - 35px);
+        .plan-list {
+            height: 100%;
+            margin-top: 10px;
         }
     }
 }