agriculturalDetail.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <template>
  2. <div class="agricultural-detail">
  3. <custom-header name="农事详情"></custom-header>
  4. <div class="detail-content">
  5. <div class="card-wrap" v-if="route.query.title !== '气象风险'">
  6. <div class="card-box photo-card">
  7. <div class="card-title">
  8. <span>农情照片</span>
  9. <span class="date">{{ imgInfo.samplingTime }}</span>
  10. </div>
  11. <div class="ratio-tip" :class="archiveColorObj[route.query.title]">
  12. <div class="title">{{ route.query.title }}</div>
  13. <span class="content van-ellipsis">{{ route.query.content }}</span>
  14. </div>
  15. <!-- <div class="location-tip">
  16. 由于系统审核,某些照片拍摄位置与农场相差超 3 公里,请在农场现场使用水印相机重新拍摄上传,谢谢配合
  17. </div> -->
  18. <div class="photo-grid">
  19. <div v-for="(photo, index) in imgInfo.imageList" :key="photo.id" class="photo-item"
  20. @click="handlePhotoClick(index)">
  21. <img :src="photo.url" alt="农情照片" />
  22. </div>
  23. </div>
  24. </div>
  25. <div class="card-box region-card">
  26. <div class="card-title">区域勾选</div>
  27. <div class="map-container" ref="mapContainer"></div>
  28. </div>
  29. </div>
  30. <div class="card-wrap" v-else>
  31. <div class="card-box risk-card">
  32. <div class="card-title">
  33. <span>农情详情</span>
  34. <span class="date">2025.05.06</span>
  35. </div>
  36. <img class="risk-image" src="" alt="">
  37. <div class="risk-content">
  38. <p class="risk-highlight">
  39. <span class="risk-title">高湿风险:</span>
  40. <span class="risk-text">预计未来7天平均相对湿度≥85%,伴随间歇性小雨或雾天。</span>
  41. </p>
  42. <p>潜在危害:田间湿度过高极易诱发霜疫霉病、炭疽病等真菌病害,病菌侵染幼果后导致腐烂、脱落。影响幼果正常发育和果皮着色,可能造成裂果、烂果。</p>
  43. <p>高湿环境利于蒂蛀虫等害虫繁殖,成虫活动增加,增加后期虫果率。</p>
  44. <div class="warning-tip">预警等级:黄色预警(中等风险),建议在未来48小时内启动预防措施。</div>
  45. </div>
  46. </div>
  47. </div>
  48. </div>
  49. </div>
  50. </template>
  51. <script setup>
  52. import { useRoute } from "vue-router";
  53. import { ref, onActivated, computed } from "vue";
  54. import customHeader from "@/components/customHeader.vue";
  55. import { showImagePreview } from 'vant';
  56. import IndexMap from "@/views/old_mini/common_map/index.js";
  57. const route = useRoute();
  58. const mapContainer = ref(null);
  59. const indexMap = new IndexMap();
  60. const previewImages = computed(() => {
  61. const list = imgInfo.value?.imageList || [];
  62. return list.map((item) => item?.url).filter(Boolean);
  63. });
  64. const archiveColorObj = {
  65. '管理信息': "green",
  66. '异常发现': "red",
  67. '气象风险': "orange",
  68. // '气象风险': "yellow",
  69. };
  70. const handlePhotoClick = (index) => {
  71. const images = previewImages.value;
  72. const safeIndex = Math.min(Math.max(Number(index) || 0, 0), Math.max(images.length - 1, 0));
  73. showImagePreview({
  74. images,
  75. startPosition: safeIndex,
  76. closeable: true,
  77. showIndex: true,
  78. });
  79. };
  80. onActivated(() => {
  81. // getFarmImagePage();
  82. if(route.query.title !== '气象风险') {
  83. indexMap.initMap('POINT(113.6142086995688 23.585836479509055)', mapContainer.value);
  84. }
  85. });
  86. const imgInfo = ref({});
  87. const getFarmImagePage = () => {
  88. VE_API.monitor.getFarmImagePage({
  89. id: route.query.id
  90. }).then((res) => {
  91. if (res.code === 0) {
  92. imgInfo.value = res.data;
  93. }
  94. });
  95. };
  96. </script>
  97. <style lang="scss" scoped>
  98. .agricultural-detail {
  99. min-height: 100vh;
  100. width: 100%;
  101. background: #f2f3f5;
  102. .detail-content {
  103. padding: 12px;
  104. padding-bottom: 24px;
  105. box-sizing: border-box;
  106. .card-wrap {
  107. .card-box {
  108. background: #fff;
  109. border-radius: 8px;
  110. padding: 12px 16px;
  111. box-sizing: border-box;
  112. .card-title {
  113. font-size: 16px;
  114. display: flex;
  115. align-items: center;
  116. justify-content: space-between;
  117. margin-bottom: 12px;
  118. .date {
  119. font-size: 12px;
  120. color: rgba(0, 0, 0, 0.2);
  121. }
  122. }
  123. }
  124. .sampling-card {
  125. .sampling-title {
  126. font-size: 16px;
  127. font-weight: 500;
  128. color: #333;
  129. margin-bottom: 6px;
  130. }
  131. .sampling-desc {
  132. font-size: 14px;
  133. color: rgba(0, 0, 0, 0.5);
  134. }
  135. }
  136. .photo-card {
  137. .ratio-tip {
  138. font-size: 14px;
  139. padding: 5px 8px;
  140. background: rgba(33, 153, 248, 0.08);
  141. border-radius: 5px;
  142. display: flex;
  143. align-items: center;
  144. .title {
  145. font-size: 12px;
  146. color: #fff;
  147. margin-right: 12px;
  148. background: #2199f8;
  149. padding: 2px 6px;
  150. border-radius: 2px;
  151. }
  152. .content {
  153. max-width: 210px;
  154. }
  155. &.green {
  156. background: rgba(71, 184, 129, 0.1);
  157. .title {
  158. background: #47B881;
  159. }
  160. }
  161. &.red {
  162. background: rgba(255, 78, 78, 0.1);
  163. .title {
  164. background: #FF4E4E;
  165. }
  166. }
  167. &.orange {
  168. background: rgba(255, 148, 61, 0.1);
  169. .title {
  170. background: #FF943D;
  171. }
  172. }
  173. }
  174. .location-tip {
  175. margin-top: 12px;
  176. padding: 5px 10px;
  177. border: 1px solid #FF953D;
  178. border-radius: 5px;
  179. color: #FA7406;
  180. }
  181. .photo-grid {
  182. margin-top: 12px;
  183. display: grid;
  184. grid-template-columns: repeat(4, 1fr);
  185. grid-gap: 6px;
  186. .photo-item {
  187. position: relative;
  188. width: 100%;
  189. padding-bottom: 100%;
  190. border-radius: 8px;
  191. overflow: hidden;
  192. background: #e5f5e5;
  193. img {
  194. position: absolute;
  195. inset: 0;
  196. width: 100%;
  197. height: 100%;
  198. object-fit: cover;
  199. display: block;
  200. }
  201. }
  202. }
  203. }
  204. .risk-card {
  205. .risk-image {
  206. width: 100%;
  207. height: 170px;
  208. border-radius: 5px;
  209. margin-bottom: 12px;
  210. background: #ff8a3d;
  211. }
  212. .risk-content {
  213. line-height: 22px;
  214. border-radius: 5px;
  215. padding: 5px 8px;
  216. background: rgba(190, 190, 190, 0.11);
  217. p {
  218. margin: 0 0 12px;
  219. }
  220. .risk-highlight {
  221. .risk-title {
  222. font-weight: 500;
  223. color: #FFAA14;
  224. }
  225. }
  226. }
  227. .warning-tip {
  228. border-radius: 5px;
  229. background: rgba(255, 177, 41, 0.1);
  230. color: #FFAA14;
  231. font-size: 14px;
  232. line-height: 22px;
  233. font-weight: 500;
  234. padding: 5px 8px;
  235. }
  236. }
  237. .region-card {
  238. margin-top: 10px;
  239. .map-container {
  240. width: 100%;
  241. height: 170px;
  242. clip-path: inset(0px round 5px);
  243. }
  244. }
  245. }
  246. }
  247. }
  248. .image-popup {
  249. width: 327px;
  250. border-radius: 8px;
  251. .popup-content {
  252. width: 100%;
  253. }
  254. }
  255. </style>