index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <template>
  2. <div class="home-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
  3. <!-- <div class="banner-wrap" @click="handleBannerClick">
  4. <img class="banner-img" :src="bannerObj?.media?.[0]" alt="" />
  5. <div class="banner-title">
  6. <span class="van-multi-ellipsis--l2">{{ bannerObj?.title }}</span>
  7. </div>
  8. </div> -->
  9. <!-- 天气遮罩 -->
  10. <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
  11. <!-- 天气 -->
  12. <weather-info ref="weatherInfoRef" class="weather-info" @weatherExpanded="weatherExpanded" :isGarden="false"
  13. @changeGarden="changeGarden"></weather-info>
  14. <div class="expert-home">
  15. <div class="expert-banner" @click="handleExpertBannerClick">
  16. <img class="expert-banner-img" src="@/assets/img/home/banner.png" alt="">
  17. <div class="expert-desc">
  18. <img class="expert-desc-icon" src="@/assets/img/home/expert-text.png" alt="">
  19. <div class="desc-text"><span class="dotted"></span>您有一条长势报告,请查看</div>
  20. </div>
  21. </div>
  22. </div>
  23. <knowledge-card />
  24. <!-- <template v-if="userType == 2">
  25. </template> -->
  26. <!-- <template v-else>
  27. <AgriculturalDynamics />
  28. </template> -->
  29. </div>
  30. <tip-popup v-model:show="showTipPopup" type="warning" text="请设置" highlightText="种植方案" buttonText="去设置"
  31. @confirm="handleBtn" :closeOnClickOverlay="false" :zIndex="9999" />
  32. <!-- 农事执行弹窗 -->
  33. <agri-execute-popup v-model:show="showAgriExecutePopup" :popupData="agriExecuteData" @later="handleAgriLater"
  34. @executed="handleAgriExecuted" />
  35. <!-- 提醒时间选择弹窗 -->
  36. <reminder-time-popup v-model:show="showReminderTimePopup" @confirm="handleReminderTimeConfirm" />
  37. <!-- 执行轨迹弹窗 -->
  38. <execute-trace-popup v-model:show="showExecuteTracePopup" @later="handleTraceLater" @confirm="handleTraceConfirm" />
  39. </template>
  40. <script setup>
  41. import { ref, computed, onActivated, onMounted } from "vue";
  42. import { useStore } from "vuex";
  43. import weatherInfo from "@/components/weatherInfo.vue";
  44. import AgriculturalDynamics from "./components/AgriculturalDynamics.vue";
  45. import { useRouter, useRoute } from "vue-router";
  46. import wx from "weixin-js-sdk";
  47. import tipPopup from "@/components/popup/tipPopup.vue";
  48. import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
  49. import reminderTimePopup from "@/components/popup/reminderTimePopup.vue";
  50. import executeTracePopup from "@/components/popup/executeTracePopup.vue";
  51. import knowledgeCard from "./components/knowledgeCard.vue";
  52. const store = useStore();
  53. const tabBarHeight = computed(() => store.state.home.tabBarHeight);
  54. const router = useRouter();
  55. const route = useRoute();
  56. const showTipPopup = ref(false);
  57. const handleBtn = () => {
  58. router.push("/plan?pageType=plant&headerTitle=请设置您的种植方案");
  59. };
  60. // 农事执行弹窗相关
  61. const showAgriExecutePopup = ref(false); // 农事执行弹窗
  62. const agriExecuteData = ref({
  63. expertName: "韦帮稳",
  64. title: "梢期杀虫 农事执行",
  65. abnormalText: "由于***异常的出现,由于***异常的出现,由于***异常的出现,由于***异常的出现,",
  66. imageUrl: "",
  67. laterBtn: true,
  68. });
  69. // 农事执行弹窗相关方法
  70. const handleAgriLater = () => {
  71. console.log("稍后执行");
  72. // 可以在这里添加稍后执行的逻辑
  73. // 关闭当前弹窗
  74. showAgriExecutePopup.value = false;
  75. // 显示提醒时间选择弹窗
  76. showReminderTimePopup.value = true;
  77. };
  78. const handleAgriExecuted = () => {
  79. console.log("我已执行111",agriExecuteData.value);
  80. if(agriExecuteData.value.executedButtonText === '查看任务'){
  81. router.push("/interaction_list?expertMiniUserId=81881");
  82. }else{
  83. // 显示执行轨迹弹窗
  84. showExecuteTracePopup.value = true;
  85. }
  86. // 关闭当前弹窗
  87. showAgriExecutePopup.value = false;
  88. };
  89. // 提醒时间选择弹窗相关
  90. const showReminderTimePopup = ref(false);
  91. // 确认提醒时间
  92. const handleReminderTimeConfirm = (time) => {
  93. console.log("选择的提醒时间:", time);
  94. // 可以在这里添加提交提醒时间的逻辑
  95. };
  96. // 执行轨迹弹窗相关
  97. const showExecuteTracePopup = ref(false);
  98. // 稍后上传
  99. const handleTraceLater = () => {
  100. console.log("稍后上传");
  101. // 可以在这里添加稍后上传的逻辑
  102. };
  103. // 确认上传
  104. const handleTraceConfirm = () => {
  105. console.log("确认上传");
  106. // 可以在这里添加确认上传的逻辑
  107. };
  108. //判断是否存在可用方案
  109. async function checkExistsEnabledScheme() {
  110. const { data } = await VE_API.home.existsEnabledScheme({ containerId: null });
  111. if (!data && localStorage.getItem("SET_USER_CUR_ROLE") == 2) {
  112. showTipPopup.value = true;
  113. }
  114. }
  115. const gardenId = ref(null);
  116. const changeGarden = ({ id }) => {
  117. gardenId.value = id;
  118. getExpertByFarmId();
  119. };
  120. const expertInfo = ref({});
  121. const getExpertByFarmId = () => {
  122. VE_API.home.getExpertByFarmId({ farmId: gardenId.value }).then(({ data }) => {
  123. expertInfo.value = data || {};
  124. sessionStorage.setItem("expertId", data.appUserId);
  125. });
  126. };
  127. // 监测卡片数据
  128. const monitorCards = ref({
  129. left: {
  130. title: "农情采集",
  131. content: "精准监测 科学决策",
  132. route: "/pest",
  133. },
  134. right: [
  135. {
  136. title: "病虫识别",
  137. content: "智能识别 快速诊断",
  138. route: "/pest",
  139. },
  140. // {
  141. // title: "新增客户",
  142. // content: "农情先知 高效管理",
  143. // route: "/create_farm?type=client&isReload=true&from=home",
  144. // },
  145. ],
  146. });
  147. // 卡片点击事件
  148. const handleCardClick = (card) => {
  149. const dropdownGardenItem = ref({
  150. organId: 766,
  151. periodId: 1,
  152. name: "荔博园",
  153. });
  154. if (card.title === "农情采集") {
  155. dropdownGardenItem.value.page = "create_farm";
  156. wx.miniProgram.navigateTo({
  157. url: `/pages/subPages/new_recognize/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
  158. });
  159. } else if (card.title === "病虫识别") {
  160. dropdownGardenItem.value.page = "album_recognize";
  161. wx.miniProgram.navigateTo({
  162. url: `/pages/subPages/new_recognize/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
  163. });
  164. } else {
  165. router.push(card.route);
  166. }
  167. };
  168. onActivated(() => {
  169. getManagerList();
  170. if (userType.value != 2) {
  171. checkExistsEnabledScheme()
  172. }
  173. getBannerList();
  174. // 检测是否从创建农场页面成功返回
  175. if (route.query.showSuccess === "true") {
  176. // 清除URL参数,避免刷新页面时再次显示弹窗
  177. router.replace({
  178. path: "/home",
  179. query: { reload: route.query.reload },
  180. });
  181. }
  182. checkHasUnrepliedTriggeredInteraction();
  183. });
  184. const userType = ref(localStorage.getItem("USER_TYPE"));
  185. onMounted(() => {
  186. if (userType.value != 2) {
  187. monitorCards.value.right.push({
  188. title: "新增客户",
  189. content: "农情先知 高效管理",
  190. route: "/create_farm?type=client&isReload=true&from=home",
  191. });
  192. }
  193. });
  194. const checkHasUnrepliedTriggeredInteraction = async () => {
  195. const { data } = await VE_API.home.hasUnrepliedTriggeredInteraction({ farmId: localStorage.getItem("selectedFarmId") });
  196. if (data && data.interactionTypeName?.length) {
  197. agriExecuteData.value = {
  198. expertName: data.expertName || "韦帮稳",
  199. title: data.interactionTypeName,
  200. abnormalText: data.reason,
  201. exampleImg: JSON.parse(data.exampleImagesJson)[0],
  202. executedButtonText: '查看任务',
  203. };
  204. showAgriExecutePopup.value = true;
  205. }
  206. };
  207. // 查询当前农资店的成员列表(只保留有"任务接单"权限的成员)
  208. const getManagerList = async () => {
  209. const { data } = await VE_API.mine.listManagerList({ onlyExecutor: true });
  210. if (data && data.length > 0) {
  211. // 过滤 permissionList 中包含"任务接单"的成员,并过滤掉超管(role为1)
  212. const executorList = data.filter((item) => item.role !== 1);
  213. sessionStorage.setItem("executorList", JSON.stringify(executorList));
  214. }
  215. };
  216. const bannerObj = ref({});
  217. const getBannerList = () => {
  218. const params = {
  219. page: 1,
  220. limit: 1,
  221. topicId: 5,
  222. };
  223. VE_API.home.warningPageList(params).then(({ data }) => {
  224. bannerObj.value = data[0] || {};
  225. });
  226. };
  227. const isExpanded = ref(false);
  228. const weatherInfoRef = ref(null);
  229. const weatherExpanded = (isExpandedValue) => {
  230. isExpanded.value = isExpandedValue;
  231. };
  232. // 点击遮罩时收起天气
  233. const handleMaskClick = () => {
  234. if (weatherInfoRef.value && weatherInfoRef.value.toggleExpand) {
  235. weatherInfoRef.value.toggleExpand();
  236. }
  237. };
  238. const handleExpertBannerClick = () => {
  239. router.push("/consult?userId=81881");
  240. };
  241. const handleBannerClick = () => {
  242. router.push(`/warning_detail?id=${bannerObj.value.id}`);
  243. };
  244. </script>
  245. <style scoped lang="scss">
  246. .home-index {
  247. width: 100%;
  248. height: 100vh;
  249. overflow: auto;
  250. position: relative;
  251. // background: linear-gradient(180deg, #f4f9fd 0%, #f9f9f9 100%);
  252. background: linear-gradient(180deg, #F9F9F9 0%, #F0F8FF 31.47%, #F9F9F9 46.81%, #F9F9F9 100%);
  253. .banner-wrap {
  254. width: 100%;
  255. height: 200px;
  256. position: relative;
  257. z-index: 1;
  258. .banner-img {
  259. width: 100%;
  260. height: 100%;
  261. object-fit: cover;
  262. }
  263. .banner-title {
  264. position: absolute;
  265. bottom: 0;
  266. left: 0;
  267. width: 100%;
  268. padding: 10px 12px 34px 12px;
  269. box-sizing: border-box;
  270. background: linear-gradient(180deg,
  271. rgba(102, 102, 102, 0) -64.3%,
  272. rgba(0, 0, 0, 0.0074) -1.43%,
  273. rgba(0, 0, 0, 0.684747) 39.67%,
  274. rgba(0, 0, 0, 0.74) 40.09%,
  275. rgba(0, 0, 0, 0.74) 83.2%);
  276. color: #fff;
  277. font-weight: bold;
  278. backdrop-filter: blur(2px);
  279. }
  280. }
  281. .weather-mask {
  282. position: fixed;
  283. top: 0;
  284. left: 0;
  285. width: 100%;
  286. height: 100%;
  287. background-color: rgba(0, 0, 0, 0.52);
  288. z-index: 2;
  289. }
  290. .weather-info {
  291. width: calc(100% - 20px);
  292. position: absolute;
  293. // top: calc(200px - 28px);
  294. top: 8px;
  295. left: 10px;
  296. z-index: 3;
  297. }
  298. .expert-home {
  299. padding: 90px 10px 10px 10px;
  300. .expert-banner {
  301. position: relative;
  302. .expert-banner-img {
  303. width: 100%;
  304. }
  305. .expert-desc {
  306. position: absolute;
  307. bottom: 0;
  308. left: 0;
  309. width: 100%;
  310. border-radius: 0 0 8px 8px;
  311. padding: 6px 8px;
  312. box-sizing: border-box;
  313. background: rgba(0, 0, 0, 0.5);
  314. color: #fff;
  315. backdrop-filter: blur(4px);
  316. display: flex;
  317. align-items: center;
  318. justify-content: space-between;
  319. .expert-desc-icon {
  320. width: 91px;
  321. }
  322. .desc-text {
  323. font-family: "PangMenZhengDao";
  324. font-size: 14px;
  325. color: #fff;
  326. display: flex;
  327. align-items: center;
  328. justify-content: center;
  329. gap: 6px;
  330. .dotted {
  331. width: 5px;
  332. height: 5px;
  333. background: #fff;
  334. border-radius: 50%;
  335. }
  336. }
  337. }
  338. }
  339. }
  340. }
  341. </style>