Przeglądaj źródła

feat:对接时间轴图片水印

wangsisi 1 dzień temu
rodzic
commit
659fc7daf5

+ 5 - 0
src/api/modules/ali.js

@@ -12,4 +12,9 @@ module.exports = {
         url: config.base_dev_url + "ai/image/recognize",
         type: "post",
     },
+    //getTreeImageList
+    getTreeImageList: {
+        url: config.base_dev_url + "lz_tree_image/treeImageList",
+        type: "post",
+    },
 }

+ 1 - 1
src/components/album_compoents/albumCarouselItem.vue

@@ -92,7 +92,7 @@
             </div>
         </div>
 
-        <popup class="cavans-popup" v-model:show="showPopup">
+        <popup class="cavans-popup" v-model:show="showPopup" teleport="body" z-index="9999">
             <div class="cavans-content">
                 <img class="current-img" :src="previewCanvas" alt="" />
             </div>

+ 188 - 121
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -19,96 +19,116 @@
                     <span class="term-name">{{ t.displayName }}</span>
                     <span class="term-date">{{ formatDate(t.createDate) }}</span>
                 </div>
-                <div v-for="(p, idx) in phenologyList" :key="`phenology-${uniqueTimestamp}-${idx}`" class="phenology-bar">
                 <div
-                    class="phenology-title"
-                    :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
-                    v-if="p.reproductiveList[0]?.phenologyName === getNextPhenologyName(idx, 0)"
+                    v-for="(p, idx) in phenologyList"
+                    :key="`phenology-${uniqueTimestamp}-${idx}`"
+                    class="phenology-bar"
                 >
-                    {{ p.reproductiveList[0]?.phenologyName }}
-                </div>
-                <div
-                    v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
-                    :key="`reproductive-${uniqueTimestamp}-${idx}-${rIdx}`"
-                    class="reproductive-item"
-                >
-                    <div class="arranges">
-                        <div
-                            v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList) ? r.farmWorkArrangeList : []"
-                            :key="`arrange-${uniqueTimestamp}-${idx}-${rIdx}-${aIdx}`"
-                            class="arrange-card"
-                            :class="[
-                                getArrangeStatusClass(fw),
-                                {
-                                    'last-card':
-                                        aIdx === r.farmWorkArrangeList.length - 1 &&
-                                        rIdx !== r.farmWorkArrangeList.length - 1,
-                                },
-                                // 右侧农事卡片跟随物候期颜色:未来节气对应的农事卡片置灰
-                                { 'future-card': !shouldShowBlue(p) },
-                            ]"        
-                            @click="handleRowClick(fw)"
-                        >
-                            <div class="card-content">
-                                <div class="card-left">
-                                    <div class="left-info">
-                                        <div class="left-date">{{ formatDate(fw.createTime) }}</div>
-                                        <div class="text van-ellipsis" v-if="fw?.sourceType === 6">上传者:{{ fw.sourceDataJson.userName }}</div>
-                                        <div class="text green van-ellipsis" v-if="fw?.sourceType === 7">执行者:{{ fw.sourceDataJson.executorName }}</div>
+                    <div
+                        class="phenology-title"
+                        :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
+                        v-if="p.reproductiveList[0]?.phenologyName === getNextPhenologyName(idx, 0)"
+                    >
+                        {{ p.reproductiveList[0]?.phenologyName }}
+                    </div>
+                    <div
+                        v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
+                        :key="`reproductive-${uniqueTimestamp}-${idx}-${rIdx}`"
+                        class="reproductive-item"
+                    >
+                        <div class="arranges">
+                            <div
+                                v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList) ? r.farmWorkArrangeList : []"
+                                :key="`arrange-${uniqueTimestamp}-${idx}-${rIdx}-${aIdx}`"
+                                class="arrange-card"
+                                :class="[
+                                    getArrangeStatusClass(fw),
+                                    {
+                                        'last-card':
+                                            aIdx === r.farmWorkArrangeList.length - 1 &&
+                                            rIdx !== r.farmWorkArrangeList.length - 1,
+                                    },
+                                    // 右侧农事卡片跟随物候期颜色:未来节气对应的农事卡片置灰
+                                    { 'future-card': !shouldShowBlue(p) },
+                                ]"
+                                @click="handleRowClick(fw)"
+                            >
+                                <div class="card-content">
+                                    <div class="card-left">
+                                        <div class="left-info">
+                                            <div class="left-date">{{ formatDate(fw.createTime) }}</div>
+                                            <div class="text van-ellipsis" v-if="fw?.sourceType === 6">
+                                                上传者:{{ fw.sourceDataJson.userName }}
+                                            </div>
+                                            <div class="text green van-ellipsis" v-if="fw?.sourceType === 7">
+                                                执行者:{{ fw.sourceDataJson.executorName }}
+                                            </div>
+                                        </div>
+                                        <div class="title-text van-ellipsis">{{ fw.title }}</div>
+                                    </div>
+                                    <div
+                                        class="card-right"
+                                        v-if="fw.sourceDataJson && fw.sourceDataJson.resFilename"
+                                        @click="handleImageClick(fw)"
+                                    >
+                                        <img :src="base_img_url2 + fw.sourceDataJson?.resFilename?.[0]" alt="" />
+                                        <div class="num" v-if="fw?.sourceDataJson?.imageIds">
+                                            {{ fw?.sourceDataJson?.imageIds.length || 0 }}
+                                        </div>
                                     </div>
-                                    <div class="title-text van-ellipsis">{{ fw.title }}</div>
-                                </div>
-                                <div class="card-right" v-if="fw.sourceDataJson" @click="handleImageClick(fw)">
-                                    <img src="@/assets/img/home/farm.png" alt="" />
-                                    <div class="num" v-if="fw?.sourceDataJson?.imageIds">{{ fw?.sourceDataJson?.imageIds.length || 0 }}</div>
-                                    <!-- <div class="num" v-if="fw?.sourceDataJson?.imageIds">{{ fw?.sourceDataJson?.imageIds.length || 0 }}</div> -->
                                 </div>
                             </div>
                         </div>
-                    </div>
-                    <template v-if="r.name === r.phenologyName">
-                        <div
-                            class="phenology-name single"
-                            :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
-                            :style="r.phenologyName === getNextPhenologyName(idx, rIdx) ? 'padding: 6px 0;' : ''"
-                        >
-                            {{ r.name }}
-                        </div>
-                    </template>
-                    <template v-else>
-                        <template v-if="r.phenologyName === getNextPhenologyName(idx, rIdx)">
+                        <template v-if="r.name === r.phenologyName">
                             <div
-                                class="phenology-name"
-                                :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
+                                class="phenology-name single"
+                                :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
+                                :style="r.phenologyName === getNextPhenologyName(idx, rIdx) ? 'padding: 6px 0;' : ''"
                             >
                                 {{ r.name }}
                             </div>
                         </template>
                         <template v-else>
-                            <div
-                                class="phenology-name"
-                                :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
-                            >
-                                {{ r.name }}
-                            </div>
-                            <div
-                                class="phenology-name mr"
-                                :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
-                            >
-                                {{ r.phenologyName }}
-                            </div>
+                            <template v-if="r.phenologyName === getNextPhenologyName(idx, rIdx)">
+                                <div
+                                    class="phenology-name"
+                                    :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
+                                >
+                                    {{ r.name }}
+                                </div>
+                            </template>
+                            <template v-else>
+                                <div
+                                    class="phenology-name"
+                                    :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
+                                >
+                                    {{ r.name }}
+                                </div>
+                                <div
+                                    class="phenology-name mr"
+                                    :class="{
+                                        'phenology-red': !shouldShowBlue(p),
+                                        'phenology-blue': shouldShowBlue(p),
+                                    }"
+                                >
+                                    {{ r.phenologyName }}
+                                </div>
+                            </template>
                         </template>
-                    </template>
+                    </div>
                 </div>
-            </div>
             </template>
         </div>
     </div>
     <!-- 图片弹窗 -->
-    <popup v-model:show="showImagePopup" closeable round class="image-popup" z-index="9999" teleport="body">
-        <div class="popup-content">
-            <p>图片详情</p>
-        </div>
+    <popup v-model:show="showImagePopup" round class="image-popup" z-index="9999" teleport="body">
+        <album-carousel
+            class="popup-content"
+            :key="currentImageData?.sourceDataJson?.resFilename?.length"
+            labelText=""
+            :imgData="currentImageData"
+            :images="currentImageData?.sourceDataJson?.resFilename || []"
+        ></album-carousel>
     </popup>
 </template>
 
@@ -116,6 +136,8 @@
 import { ref, nextTick, watch, onMounted, onUnmounted } from "vue";
 import { ElMessage } from "element-plus";
 import { Empty, Popup } from "vant";
+import { base_img_url2 } from "@/api/config";
+import AlbumCarousel from "@/components/album_compoents/albumCarousel";
 
 const props = defineProps({
     // 农场 ID,用于请求农事规划数据
@@ -238,11 +260,39 @@ const batchValidatePesticideFertilizerQuotes = (ids, items) => {
         .catch(() => {});
 };
 
+// 获取图片 URL 列表
+const fetchImageUrls = async (params) => {
+    try {
+        const res = await VE_API.ali.getTreeImageList(params);
+        if (res.code === 0 && Array.isArray(res.data)) {
+            // 将 resFilename 加上 base_img_url2 前缀后返回
+            return res.data.map((item) => {
+                if (item.filename) {
+                    return item.filename;
+                }
+                return null;
+            });
+        }
+        return [];
+    } catch (error) {
+        console.error("获取图片列表失败:", error);
+        return [];
+    }
+};
+
 // 点击图片
+const currentImageData = ref({});
 const handleImageClick = (fw) => {
-    console.log(fw,'fw');
+    console.log(fw, "fw");
+    currentImageData.value = {
+        ...fw,
+        executeName: fw.sourceDataJson.userName,
+        executeDate: formatDate(fw.updateTime),
+        farmName: fw.sourceDataJson.farmName,
+        farmWorkLibName: fw.sourceDataJson.farmWorkLibName,
+    };
     showImagePopup.value = true;
-}
+};
 
 // 获取下一个reproductive-item的phenologyName
 const getNextPhenologyName = (currentPhenologyIdx, currentReproductiveIdx) => {
@@ -448,7 +498,7 @@ const getFarmWorkPlan = () => {
 
     VE_API.monitor
         .getArchivesList({ farmId: props.farmId })
-        .then(({ data, code }) => {
+        .then(async ({ data, code }) => {
             if (code === 0) {
                 const list = Array.isArray(data?.solarTermsList) ? data.solarTermsList : [];
                 const filtered = list
@@ -465,35 +515,62 @@ const getFarmWorkPlan = () => {
                     }));
                 solarTerms.value = filtered;
                 // 物候期数据
-                phenologyList.value = Array.isArray(data?.phenologyList)
-                    ? data.phenologyList.map((it) => {
-                          const reproductiveList = Array.isArray(it.reproductiveList)
-                              ? it.reproductiveList.map((r) => {
-                                    const farmWorkArrangeList = Array.isArray(r.broadcastList)
-                                        ? r.broadcastList.map((fw) => ({
-                                              ...fw,
-                                              sourceDataJson: fw.sourceData && JSON.parse(fw.sourceData),
-                                              containerSpaceTimeId: it.containerSpaceTimeId,
-                                          }))
-                                        : [];
-                                    return {
-                                        ...r,
-                                        farmWorkArrangeList,
-                                    };
-                                })
-                              : [];
-                          return {
-                              id: it.id ?? it.phenologyId ?? it.name ?? `${it.progress}-${it.progress2}`,
-                              progress: Number(it.progress) || 0, // 起点 %
-                              progress2: Number(it.progress2) || 0, // 终点 %
-                              startDate: it.startDate,
-                              startTimeMs: safeParseDate(
-                                  it.startDate || it.beginDate || it.startTime || it.start || it.start_at
-                              ),
-                              reproductiveList,
-                          };
-                      })
+                const processedPhenologyList = Array.isArray(data?.phenologyList)
+                    ? await Promise.all(
+                          data.phenologyList.map(async (it) => {
+                              const reproductiveList = Array.isArray(it.reproductiveList)
+                                  ? await Promise.all(
+                                        it.reproductiveList.map(async (r) => {
+                                            const farmWorkArrangeList = Array.isArray(r.broadcastList)
+                                                ? await Promise.all(
+                                                      r.broadcastList.map(async (fw) => {
+                                                          let sourceDataJson =
+                                                              fw.sourceData && JSON.parse(fw.sourceData);
+                                                          // 如果有 imageIds,获取图片 URL
+                                                          if (
+                                                              sourceDataJson &&
+                                                              sourceDataJson.imageIds &&
+                                                              Array.isArray(sourceDataJson.imageIds) &&
+                                                              sourceDataJson.imageIds.length > 0
+                                                          ) {
+                                                              const resFilenameList = await fetchImageUrls({
+                                                                  imageIds: sourceDataJson.imageIds,
+                                                                  page: 1,
+                                                                  limit: 100,
+                                                              });
+                                                              // 将获取到的 resFilename(已加上 base_img_url2 前缀)添加到 sourceDataJson
+                                                              console.log(resFilenameList, "resFilenameList");
+                                                              sourceDataJson.resFilename = resFilenameList;
+                                                          }
+                                                          return {
+                                                              ...fw,
+                                                              sourceDataJson,
+                                                              containerSpaceTimeId: it.containerSpaceTimeId,
+                                                          };
+                                                      })
+                                                  )
+                                                : [];
+                                            return {
+                                                ...r,
+                                                farmWorkArrangeList,
+                                            };
+                                        })
+                                    )
+                                  : [];
+                              return {
+                                  id: it.id ?? it.phenologyId ?? it.name ?? `${it.progress}-${it.progress2}`,
+                                  progress: Number(it.progress) || 0, // 起点 %
+                                  progress2: Number(it.progress2) || 0, // 终点 %
+                                  startDate: it.startDate,
+                                  startTimeMs: safeParseDate(
+                                      it.startDate || it.beginDate || it.startTime || it.start || it.start_at
+                                  ),
+                                  reproductiveList,
+                              };
+                          })
+                      )
                     : [];
+                phenologyList.value = processedPhenologyList;
                 // 使用多次 nextTick 和 requestAnimationFrame 确保DOM完全渲染
                 nextTick(() => {
                     requestAnimationFrame(() => {
@@ -576,7 +653,7 @@ const getFarmWorkPlan = () => {
                 if (farmWorkIds.length > 0) {
                     batchValidatePesticideFertilizerQuotes(farmWorkIds, farmWorks);
                 }
-                
+
                 // 判断是否为空数据:没有节气或没有物候期数据
                 if (solarTerms.value.length === 0 && phenologyList.value.length === 0) {
                     isEmpty.value = true;
@@ -608,22 +685,14 @@ const updateFarmWorkPlan = () => {
 };
 
 watch(
-    () => props.farmId || props.containerId,
+    () => props.farmId,
     (val) => {
         if (val) {
             isInitialLoad.value = true;
             updateFarmWorkPlan();
         }
     },
-    { immediate: true }
-);
-watch(
-    () => props.schemeId,
-    (val) => {
-        // if (val) {
-        updateFarmWorkPlan();
-        // }
-    }
+    // { immediate: true }
 );
 
 // 格式化日期为 MM-DD 格式
@@ -910,7 +979,7 @@ watch(
                                 display: flex;
                                 align-items: center;
                                 gap: 5px;
-                                .left-date { 
+                                .left-date {
                                     color: #fff;
                                     background: #2199f8;
                                     padding: 1px 5px;
@@ -940,6 +1009,8 @@ watch(
                             img {
                                 width: 45px;
                                 height: 45px;
+                                border-radius: 4px;
+                                object-fit: cover;
                             }
                             .num {
                                 position: absolute;
@@ -1076,13 +1147,9 @@ watch(
 
 <style lang="scss" scoped>
 .image-popup {
-    width: 100%;
+    width: 327px;
     .popup-content {
-        p {
-            margin: 0;
-            font-size: 16px;
-            color: #333;
-        }
+        width: 100%;
     }
 }
 </style>