index.vue 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. <template>
  2. <div class="achievement-report-page" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
  3. <!-- 天气遮罩 -->
  4. <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
  5. <!-- 组件:天气 -->
  6. <weather-info ref="weatherInfoRef" from="growth_report" class="weather-info" @weatherExpanded="weatherExpanded"
  7. @changeGarden="changeGarden" :isGarden="true"></weather-info>
  8. <div class="report-content-wrap" v-if="hasReport" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.1)">
  9. <swipe ref="swipeRef" class="my-swipe" :loop="false" indicator-color="white" @change="handleSwipeChange">
  10. <swipe-item v-for="(item, index) in regionsData" :key="index">
  11. <div class="report-content has-report" :style="{ minHeight: `calc(100vh - ${tabBarHeight}px)` }">
  12. <!-- <img src="@/assets/img/home/qrcode.png" alt="" class="code-icon" /> -->
  13. <img class="header-img" src="@/assets/img/home/report.png" alt="" />
  14. <div class="report-header">
  15. <!-- <img class="header-book" src="@/assets/img/home/book.png" alt="" /> -->
  16. <div class="time-tag">{{ workItems?.[0]?.reportDate }}</div>
  17. <div class="report-title">{{regionsData[currentIndex]?.regionName}}长势报告</div>
  18. <div class="report-info">
  19. <div class="info-item">
  20. <img class="info-icon" src="@/assets/img/home/farm.png" alt="" />
  21. <span class="info-text">{{ currentFarmName }}</span>
  22. </div>
  23. </div>
  24. <!-- 左滑查看更多 -->
  25. <div class="swipe-more-tag" v-show="currentIndex < regionsData.length - 1">
  26. 左滑查看更多分区
  27. </div>
  28. </div>
  29. <div class="report-box">
  30. <div class="box-title warning">今日巡园重点</div>
  31. <div class="box-text w-100">
  32. <div class="row">
  33. <div
  34. v-for="(card, cardI) in todayPatrolFocus"
  35. :key="cardI"
  36. class="status-card"
  37. :class="'today-'+card.color"
  38. @click="handleTodayPatrolFocusClick(card)"
  39. >
  40. <!-- <badge class="status-badge" dot
  41. :offset="[80, -10]">
  42. </badge> -->
  43. <div class="status-title">
  44. {{ card.title }}
  45. </div>
  46. <div class="status-sub">
  47. {{ card.description }}
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. <div class="report-box">
  54. <div class="box-title warning">待执行农事</div>
  55. <div class="box-text w-100">
  56. <div class="row">
  57. <div
  58. v-for="(card, cardI) in pendingFarmWork"
  59. :key="cardI"
  60. class="status-card pending-card"
  61. :style="{ background: card.purposeColor, color: card.purposeColor === '#FFFFFF' ? '#000' : '#fff' }"
  62. :class="card.type"
  63. @click="handlePendingFarmWorkClick(card)"
  64. >
  65. <!-- <badge class="status-badge" dot
  66. :offset="[80, -10]">
  67. </badge> -->
  68. <div v-if="card.executionLimitDays || card.executionLimitDays === 0" class="tag-name" :style="{ borderColor: card.purposeColor, color: card.purposeColor }">限时 {{ card.executionLimitDays }} 天</div>
  69. <div class="status-title">
  70. {{ card.name }}
  71. </div>
  72. <div class="status-sub pending-sub" :style="{ color: card.purposeColor === '#FFFFFF' ? '#000' : '#fff' }">
  73. {{ card.purposeName }}
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. <div class="report-box" v-for="(work, workI) in workItems" :key="workI">
  80. <div class="box-title">{{ work?.title }}</div>
  81. <div class="box-text">
  82. <div class="box-bg" v-show="work?.backgroundDesc">
  83. <span class="box-subtitle">背景描述:</span>
  84. <div class="pre-text">{{ work?.backgroundDesc }}</div>
  85. </div>
  86. <div class="box-advice" v-show="work?.suggestion">
  87. <span class="box-subtitle">对策建议:</span>
  88. <div class="pre-text">{{ work?.suggestion }}</div>
  89. </div>
  90. <div class="box-sum pre-text" v-show="work?.summary">{{ work?.summary }}</div>
  91. </div>
  92. </div>
  93. <!-- <div class="report-box">
  94. <div class="box-text next-info">
  95. <div class="box-bg">
  96. <span class="box-subtitle">下一次农情互动预告:</span>
  97. <div v-html="workItem?.nextInteractionPreview"></div>
  98. </div>
  99. </div>
  100. </div> -->
  101. </div>
  102. </swipe-item>
  103. </swipe>
  104. </div>
  105. <div v-else class="fake-report-wrap report-content-wrap">
  106. <div class="report-content">
  107. <img class="header-img" src="@/assets/img/home/report.png" alt="" />
  108. <div class="report-header">
  109. <!-- <img class="header-book" src="@/assets/img/home/book.png" alt="" /> -->
  110. <div class="time-tag">{{ new Date().toISOString().split('T')[0] }}</div>
  111. <div class="report-title" @click="handleAddFarm">作物长势报告</div>
  112. <div class="report-info pb-4">
  113. <div class="info-item">
  114. <img class="info-icon" src="@/assets/img/home/farm.png" alt="" />
  115. <span class="info-text">示范农场</span>
  116. </div>
  117. </div>
  118. </div>
  119. <div class="fake-img">
  120. <img src="@/assets/img/home/fake.png" alt="" class="fake-img-item" />
  121. </div>
  122. <div class="lock-img">
  123. <img @click="handleLockClick" src="@/assets/img/home/lock-blue.png" alt="" class="has-click lock-img-item" />
  124. <div class="lock-text">
  125. 专属数字农场,种好卖好
  126. <div>点击解锁一键溯源增产</div>
  127. </div>
  128. <div @click="handleLockClick" class="lock-btn has-click">点击解锁</div>
  129. </div>
  130. <div class="lock-bg"></div>
  131. </div>
  132. </div>
  133. <!-- 首次进入页面的左滑查看提示遮罩 -->
  134. <div class="swipe-guide-mask" v-if="showSwipeGuide" @click="closeSwipeGuide">
  135. <div class="swipe-guide-content">
  136. <img class="swipe-guide-icon" src="@/assets/img/home/point.png" alt="swipe" />
  137. <div class="swipe-guide-text">左滑查看其它分区报告</div>
  138. </div>
  139. </div>
  140. <tip-popup v-model:show="showBindSuccess" type="success" text="您的农场已绑定成功" hideBtn />
  141. <start-interact-popup ref="startInteractPopupRef" />
  142. <agri-execute-popup ref="agriExecutePopupRef" />
  143. </div>
  144. </template>
  145. <script setup>
  146. import wx from "weixin-js-sdk";
  147. import weatherInfo from "@/components/weatherInfo.vue";
  148. import { ref, onActivated, onDeactivated, onUnmounted, computed, nextTick } from "vue";
  149. import { useRoute, useRouter } from "vue-router";
  150. import { useStore } from "vuex";
  151. import { Swipe, SwipeItem, Badge } from 'vant';
  152. import tipPopup from "@/components/popup/tipPopup.vue";
  153. import startInteractPopup from "@/components/popup/startInteractPopup.vue";
  154. import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
  155. const store = useStore();
  156. const tabBarHeight = computed(() => store.state.home.tabBarHeight);
  157. const route = useRoute();
  158. const router = useRouter();
  159. const loading = ref(false);
  160. const hasReport = ref(false);
  161. const workItems = ref([]);
  162. const swipeRef = ref(null);
  163. const paramsPage = ref({});
  164. const showBindSuccess = ref(false);
  165. const startInteractPopupRef = ref(null);
  166. const agriExecutePopupRef = ref(null);
  167. // 天气组件相关
  168. const isExpanded = ref(false);
  169. const weatherInfoRef = ref(null);
  170. // 首次进入页面的左滑提示遮罩
  171. const showSwipeGuide = ref(false);
  172. const weatherExpanded = (isExpandedValue) => {
  173. isExpanded.value = isExpandedValue;
  174. };
  175. // 点击遮罩时收起天气
  176. const handleMaskClick = () => {
  177. if (weatherInfoRef.value && weatherInfoRef.value.toggleExpand) {
  178. weatherInfoRef.value.toggleExpand();
  179. }
  180. };
  181. const currentFarmName = ref('');
  182. // 切换农场时,更新报告数据
  183. const changeGarden = async ({ id, name }) => {
  184. if (!id) return;
  185. currentFarmName.value = name;
  186. swipeRef.value && swipeRef.value.swipeTo(0, {immediate:true});
  187. currentIndex.value = 0;
  188. paramsPage.value = {
  189. ...(paramsPage.value || {}),
  190. subjectId: id,
  191. };
  192. // 初始化品种/大物候期转换
  193. startInteractPopupRef.value.getPhenologyInitOrConfirmStatus();
  194. await getRegions();
  195. };
  196. onActivated(() => {
  197. window.scrollTo(0, 0);
  198. // 如果路由中带有 miniJson,并且其中有 showBind,则展示绑定成功弹窗
  199. const { miniJson } = route.query || {};
  200. if (miniJson) {
  201. try {
  202. const parsed = typeof miniJson === "string" ? JSON.parse(miniJson) : miniJson;
  203. if (parsed && parsed.showBind) {
  204. showBindSuccess.value = true;
  205. // 处理完后清空路由中的 miniJson 参数,避免重复弹出
  206. const newQuery = { ...(route.query || {}) };
  207. delete newQuery.miniJson;
  208. router.replace({ path: route.path, query: newQuery });
  209. }
  210. } catch (e) {
  211. // miniJson 解析失败时忽略,不影响正常流程
  212. }
  213. }
  214. // getResultReport();
  215. });
  216. // 关闭左滑提示遮罩
  217. const closeSwipeGuide = () => {
  218. showSwipeGuide.value = false;
  219. };
  220. const userInfo = localStorage.getItem("localUserInfo");
  221. const userInfoObj = userInfo ? JSON.parse(userInfo) : {};
  222. const handleLockClick = () => {
  223. if (currentFarmName.value) {
  224. router.push("/interaction?subjectId=" + localStorage.getItem("selectedFarmId"));
  225. return;
  226. }
  227. if (userInfoObj?.tel) {
  228. router.push(`/create_farm?from=growth_report&isReload=true`);
  229. return;
  230. }
  231. wx.miniProgram.navigateTo({
  232. url: '/pages/subPages/phone_auth/index',
  233. });
  234. }
  235. const handleAddFarm = () => {
  236. router.push(`/create_farm?from=growth_report&isReload=true`);
  237. }
  238. const todayPatrolFocus = ref([]);
  239. const pendingFarmWork = ref([]);
  240. const handlePendingFarmWorkClick = (card) => {
  241. router.push({
  242. path: "/work_detail",
  243. query: {
  244. miniJson: JSON.stringify({
  245. paramsPage: JSON.stringify({
  246. farmId: paramsPage.value.farmId,
  247. farmWorkLibId: card?.farmWorkLibId,
  248. recordId: card?.recordId,
  249. typeId: regionsData.value[currentIndex.value].typeId
  250. }),
  251. }),
  252. },
  253. });
  254. }
  255. // 点击今日巡园重点
  256. const handleTodayPatrolFocusClick = (card) => {
  257. if (!card.interactionTypeId) return;
  258. router.push(`/interaction_list?farmId=${paramsPage.value.farmId}&regionId=${paramsPage.value.regionId}&interactionTypeId=${card.interactionTypeId}`);
  259. }
  260. const getTodayPatrolFocus = () => {
  261. VE_API.report.todayPatrolFocus({ farmId: paramsPage.value.farmId, regionId:paramsPage.value.regionId }).then(({ data }) => {
  262. todayPatrolFocus.value = data || [];
  263. });
  264. }
  265. const getPendingFarmWork = () => {
  266. VE_API.report.pendingFarmWork({ farmId: paramsPage.value.farmId, regionId: paramsPage.value.regionId }).then(({ data }) => {
  267. pendingFarmWork.value = data || [];
  268. });
  269. }
  270. const currentIndex = ref(0);
  271. const handleSwipeChange = (index) => {
  272. currentIndex.value = index;
  273. if (paramsPage.value.regionId !== regionsData.value[index].regionId) {
  274. paramsPage.value = {
  275. ...(paramsPage.value || {}),
  276. farmId: regionsData.value[index].farmId,
  277. regionId: regionsData.value[index].regionId,
  278. };
  279. getTodayPatrolFocus();
  280. getPendingFarmWork();
  281. getDetail();
  282. }
  283. }
  284. const getDetail = () => {
  285. if (!paramsPage.value.farmId) return;
  286. loading.value = true;
  287. VE_API.report
  288. .reproductiveReport({ farmId: paramsPage.value.farmId, regionId: paramsPage.value.regionId })
  289. .then(({ data }) => {
  290. workItems.value = data || [];
  291. })
  292. .finally(() => {
  293. loading.value = false;
  294. });
  295. };
  296. const regionsData = ref([]);
  297. const getRegions = async () => {
  298. VE_API.monitor.listRegionsBySubjectId({
  299. subjectId: paramsPage.value.subjectId,
  300. }).then(({ data }) => {
  301. regionsData.value = data || [];
  302. if(regionsData.value.length > 0) {
  303. const guideKey = "GROWTH_REPORT_SWIPE_GUIDE_SHOWN";
  304. if (!localStorage.getItem(guideKey) && regionsData.value.length > 1) {
  305. showSwipeGuide.value = true;
  306. localStorage.setItem(guideKey, "1");
  307. }
  308. hasReport.value = true;
  309. // 如果不是点击农情报告已生成弹窗过来的,则显示农情互动弹窗
  310. if(!route.query.hideInteraction) {
  311. agriExecutePopupRef.value.showPopup(regionsData.value[currentIndex.value].farmId);
  312. }
  313. paramsPage.value = {
  314. ...(paramsPage.value || {}),
  315. farmId: regionsData.value[currentIndex.value].farmId,
  316. regionId: regionsData.value[currentIndex.value].regionId,
  317. };
  318. getTodayPatrolFocus();
  319. getPendingFarmWork();
  320. getDetail();
  321. // 如果是新增品种后跳转过来的,等待 Swipe 实例挂载后再定位
  322. if (route.query.addVarietyCount) {
  323. const targetIndex = Number(route.query.addVarietyCount);
  324. if (!Number.isNaN(targetIndex) && targetIndex >= 0) {
  325. const safeIndex = Math.min(targetIndex, regionsData.value.length - 1);
  326. const reverseIndex = Math.min(
  327. regionsData.value.length - 1,
  328. Math.max(0, regionsData.value.length - safeIndex)
  329. );
  330. nextTick(() => {
  331. swipeRef.value?.swipeTo?.(reverseIndex, { immediate: true });
  332. });
  333. }
  334. }
  335. } else {
  336. hasReport.value = false;
  337. }
  338. });
  339. }
  340. // 清理数据的函数
  341. const clearData = () => {
  342. workItems.value = [];
  343. paramsPage.value = {};
  344. loading.value = false;
  345. };
  346. onDeactivated(() => {
  347. clearData();
  348. });
  349. onUnmounted(() => {
  350. clearData();
  351. });
  352. </script>
  353. <style lang="scss" scoped>
  354. .achievement-report-page {
  355. width: 100%;
  356. height: 100vh;
  357. background: linear-gradient(195.35deg, #d4e4ff 16.34%, rgba(93, 189, 255, 0) 50.3%),
  358. linear-gradient(156.64deg, rgba(255, 255, 255, 0.16) 27.7%, rgba(255, 255, 255, 0) 72.82%);
  359. .weather-mask {
  360. position: fixed;
  361. top: 0;
  362. left: 0;
  363. width: 100%;
  364. height: 100%;
  365. background-color: rgba(0, 0, 0, 0.52);
  366. z-index: 11;
  367. }
  368. .weather-info {
  369. width: calc(100% - 20px);
  370. position: absolute;
  371. z-index: 12;
  372. left: 10px;
  373. top: 12px;
  374. }
  375. .fake-report-wrap {
  376. width: 100%;
  377. .no-report-img {
  378. width: 100%;
  379. }
  380. .fake-img {
  381. position: relative;
  382. .fake-img-item {
  383. width: 100%;
  384. }
  385. }
  386. }
  387. .report-content-wrap {
  388. height: 100%;
  389. // padding-bottom: 60px;
  390. overflow: auto;
  391. box-sizing: border-box;
  392. position: relative;
  393. .bottom-btn {
  394. z-index: 2;
  395. position: fixed;
  396. bottom: 0;
  397. left: 0;
  398. width: 100%;
  399. background: #fff;
  400. height: 60px;
  401. display: flex;
  402. align-items: center;
  403. justify-content: space-between;
  404. padding: 0 12px;
  405. box-sizing: border-box;
  406. box-shadow: 2px 2px 4.5px 0px rgba(0, 0, 0, 0.4);
  407. .btn-item {
  408. height: 40px;
  409. line-height: 40px;
  410. padding: 0 24px;
  411. border-radius: 20px;
  412. font-size: 14px;
  413. &.second {
  414. color: #666666;
  415. border: 1px solid rgba(153, 153, 153, 0.5);
  416. }
  417. &.primay {
  418. padding: 0 34px;
  419. background: linear-gradient(180deg, #76c3ff, #2199f8);
  420. color: #fff;
  421. }
  422. }
  423. }
  424. }
  425. // 首次进入页面左滑提示遮罩
  426. .swipe-guide-mask {
  427. position: fixed;
  428. left: 0;
  429. top: 0;
  430. width: 100%;
  431. height: 100%;
  432. background: rgba(0, 0, 0, 0.6);
  433. z-index: 99999;
  434. display: flex;
  435. align-items: center;
  436. justify-content: center;
  437. .swipe-guide-content {
  438. display: flex;
  439. flex-direction: column;
  440. align-items: center;
  441. justify-content: center;
  442. color: #ffffff;
  443. text-align: center;
  444. }
  445. .swipe-guide-icon {
  446. width: 71px;
  447. height: 79px;
  448. object-fit: contain;
  449. margin-bottom: 23px;
  450. }
  451. .swipe-guide-text {
  452. font-size: 20px;
  453. }
  454. }
  455. .code-icon {
  456. position: absolute;
  457. right: 10px;
  458. top: 12px;
  459. width: 48px;
  460. }
  461. .report-content {
  462. // background: url("@/assets/img/home/report_bg.png") no-repeat center center;
  463. // background: linear-gradient(0deg, #9BCCFF, #9BCCFF),
  464. // linear-gradient(160deg, rgba(255, 255, 255, 0.16) 30%, rgba(255, 255, 255, 0) 72%);
  465. background: #abd4ff;
  466. background-size: 100% auto;
  467. background-position: top center;
  468. padding: 0 16px 26px 16px;
  469. box-sizing: border-box;
  470. position: relative;
  471. &.has-report {
  472. min-height: 100%;
  473. background: linear-gradient(0deg, #9BCCFF, #9BCCFF),
  474. linear-gradient(156.64deg, rgba(255, 255, 255, 0.16) 27.7%, rgba(255, 255, 255, 0) 72.82%);
  475. }
  476. .lock-bg {
  477. position: absolute;
  478. top: 230px;
  479. left: 0;
  480. width: 100%;
  481. height: calc(100% - 230px);
  482. background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.38) 50%, rgba(255, 255, 255, 0) 100%),
  483. linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
  484. }
  485. .lock-img {
  486. pointer-events: none;
  487. position: fixed;
  488. z-index: 10;
  489. top: 50%;
  490. left: 50%;
  491. transform: translate(-50%, -20%);
  492. width: 100%;
  493. display: flex;
  494. align-items: center;
  495. justify-content: center;
  496. flex-direction: column;
  497. gap: 16px;
  498. .lock-img-item {
  499. width: 57px;
  500. }
  501. .has-click {
  502. pointer-events: auto;
  503. }
  504. .lock-text {
  505. font-size: 14px;
  506. color: #000;
  507. padding: 5px 64px;
  508. line-height: 21px;
  509. background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 50%, rgba(255, 255, 255, 0) 100%);
  510. }
  511. .lock-btn {
  512. width: 140px;
  513. height: 40px;
  514. line-height: 40px;
  515. text-align: center;
  516. background: linear-gradient(180deg, #76C3FF 0%, #2199F8 100%);
  517. border-radius: 25px;
  518. color: #fff;
  519. font-size: 16px;
  520. }
  521. }
  522. .header-img {
  523. position: absolute;
  524. top: 0;
  525. left: 0;
  526. width: 100%;
  527. }
  528. .report-header {
  529. position: relative;
  530. padding-top: 112px;
  531. .header-book {
  532. position: absolute;
  533. right: 0;
  534. bottom: -6px;
  535. height: 88px;
  536. z-index: 10;
  537. }
  538. .time-tag {
  539. background: #2199F8;
  540. border-radius: 5px 0 5px 0;
  541. height: 23px;
  542. line-height: 23px;
  543. font-size: 13px;
  544. font-weight: 500;
  545. color: #fff;
  546. padding: 0 9px;
  547. width: fit-content;
  548. margin-bottom: 2px;
  549. }
  550. .report-title {
  551. font-family: "PangMenZhengDao";
  552. font-size: 34px;
  553. line-height: 38px;
  554. color: #000000;
  555. }
  556. .report-info {
  557. padding: 12px 0 28px 0;
  558. &.pb-4 {
  559. padding-bottom: 4px;
  560. }
  561. .info-item {
  562. width: fit-content;
  563. display: flex;
  564. height: 33px;
  565. align-items: center;
  566. padding: 0 18px 0 6px;
  567. background: linear-gradient(90deg, rgba(255, 255, 255, 0.58) 0%, rgba(255, 255, 255, 0.0696) 100%);
  568. border-radius: 20px;
  569. border: 0.5px solid rgba(33, 153, 248, 0.35);
  570. gap: 6px;
  571. .info-icon {
  572. width: 26px;
  573. height: 26px;
  574. object-fit: cover;
  575. border-radius: 50%;
  576. }
  577. .info-text {
  578. font-size: 14px;
  579. color: #000;
  580. }
  581. }
  582. .info-item+.info-item {
  583. margin-top: 5px;
  584. }
  585. }
  586. // 左滑查看更多标签
  587. .swipe-more-tag {
  588. position: absolute;
  589. bottom: 10px;
  590. right: -16px;
  591. box-sizing: border-box;
  592. width: 36px;
  593. height: 134px;
  594. padding: 0px 10px 2px 0;
  595. background: rgba(0, 0, 0, 0.7);
  596. border-radius: 10px 0 0 10px;
  597. letter-spacing: 2px;
  598. color: #ffffff;
  599. font-size: 12px;
  600. text-align: center;
  601. line-height: 20px;
  602. writing-mode: vertical-rl;
  603. text-orientation: mixed;
  604. }
  605. }
  606. .report-box {
  607. display: flex;
  608. align-items: center;
  609. padding: 8px;
  610. background: linear-gradient(0deg, #ffffff 86.32%, #2199f8 136.87%);
  611. border: 1px solid #ffffff;
  612. border-radius: 8px;
  613. gap: 5px;
  614. position: relative;
  615. .report-box-item {
  616. flex: 1;
  617. background: rgba(33, 153, 248, 0.1);
  618. border-radius: 8px;
  619. min-height: 62px;
  620. box-sizing: border-box;
  621. padding: 2px 4px;
  622. display: flex;
  623. flex-direction: column;
  624. justify-content: center;
  625. .item-content {
  626. color: #2199f8;
  627. font-size: 14px;
  628. text-align: center;
  629. }
  630. .item-title {
  631. color: #000000;
  632. font-size: 10px;
  633. text-align: center;
  634. padding-top: 5px;
  635. }
  636. }
  637. .box-title {
  638. position: absolute;
  639. top: -8px;
  640. left: -1px;
  641. height: 32px;
  642. line-height: 26px;
  643. font-family: "PangMenZhengDao";
  644. font-size: 14px;
  645. padding: 0 10px;
  646. color: #ffffff;
  647. background: url("@/assets/img/home/title-bg.png") no-repeat center center / 100% 100%;
  648. &.warning {
  649. background: url("@/assets/img/home/title-bg-warning.png") no-repeat center center / 100% 100%;
  650. }
  651. }
  652. .w-100 {
  653. width: 100%;
  654. }
  655. .box-text {
  656. padding: 22px 0 8px 0;
  657. font-weight: 350;
  658. line-height: 21px;
  659. .pre-text {
  660. white-space: pre-line;
  661. word-break: break-word;
  662. }
  663. .box-subtitle {
  664. color: #000;
  665. }
  666. .box-bg {
  667. font-weight: 400;
  668. color: rgba(0, 0, 0, 0.5);
  669. }
  670. .box-advice {
  671. color: rgba(0, 0, 0, 0.5);
  672. padding-top: 10px;
  673. }
  674. .box-sum {
  675. margin-top: 10px;
  676. background: rgba(33, 153, 248, 0.1);
  677. border-radius: 5px;
  678. padding: 10px;
  679. line-height: 20px;
  680. color: #2199F8;
  681. }
  682. &.next-info {
  683. padding: 8px 0 8px 0;
  684. }
  685. }
  686. .row {
  687. display: grid;
  688. grid-template-columns: repeat(3, 1fr);
  689. gap: 6px;
  690. .status-card {
  691. border-radius: 2px;
  692. padding: 7px 0;
  693. background: #ffffff;
  694. border: 0.5px solid #e5e6eb;
  695. color: #000;
  696. display: flex;
  697. flex-direction: column;
  698. align-items: center;
  699. justify-content: center;
  700. &.today-red {
  701. background: #FF6A6A;
  702. color: #fff;
  703. .status-sub {
  704. color: #fff;
  705. }
  706. }
  707. &.pending-card {
  708. color: #fff;
  709. position: relative;
  710. padding: 9px 0 7px 0;
  711. .tag-name {
  712. position: absolute;
  713. top: -8px;
  714. right: 0;
  715. background: #fff;
  716. color: #FF6A6A;
  717. font-size: 10px;
  718. height: 17px;
  719. line-height: 17px;
  720. padding: 0 3px;
  721. border-radius: 2px;
  722. box-sizing: border-box;
  723. border: 0.5px solid #FF6A6A;
  724. }
  725. }
  726. .status-badge {
  727. // position: absolute;
  728. // top: 0;
  729. // right: 0;
  730. }
  731. .status-title {
  732. font-size: 16px;
  733. line-height: 24px;
  734. }
  735. .status-sub {
  736. font-size: 10px;
  737. color: rgba(32, 32, 32, 0.4);
  738. line-height: 15px;
  739. &.pending-sub {
  740. color: #fff;
  741. line-height: 13px;
  742. }
  743. }
  744. &.risk-strong {
  745. background: #FF6A6A;
  746. border-color: #FF6A6A;
  747. .status-title,
  748. .status-sub {
  749. color: #ffffff;
  750. }
  751. }
  752. &.danger {
  753. background: #FFE9E9;
  754. border-color: #ff8e8e;
  755. .status-sub {
  756. color: #FF6A6A;
  757. }
  758. }
  759. }
  760. }
  761. }
  762. .report-box+.report-box {
  763. margin-top: 20px;
  764. }
  765. .report-excute {
  766. position: relative;
  767. margin-top: 12px;
  768. .tag-label {
  769. position: absolute;
  770. top: 0;
  771. left: 0;
  772. padding: 4px 10px;
  773. background: rgba(54, 52, 52, 0.8);
  774. color: #fff;
  775. font-size: 12px;
  776. border-radius: 8px 0 8px 0;
  777. z-index: 1;
  778. }
  779. ::v-deep {
  780. .carousel-container .carousel-wrapper .carousel-img {
  781. min-width: calc(100vw - 32px);
  782. width: calc(100vw - 32px);
  783. }
  784. }
  785. }
  786. }
  787. .download-btn {
  788. position: fixed;
  789. bottom: 20px;
  790. left: 50%;
  791. // background: #fff;
  792. // box-shadow: 2px 2px 4.5px 0px #00000066;
  793. // width: 100%;
  794. transform: translateX(-50%);
  795. }
  796. .review-hide-box {
  797. position: absolute;
  798. left: 0;
  799. width: 100%;
  800. height: 100%;
  801. z-index: -1;
  802. bottom: 0;
  803. }
  804. .review-image {
  805. position: relative;
  806. display: flex;
  807. align-items: center;
  808. justify-content: center;
  809. gap: 8px;
  810. margin: 12px;
  811. background: #fff;
  812. border-radius: 8px;
  813. .review-mask {
  814. z-index: 1;
  815. pointer-events: none;
  816. position: absolute;
  817. left: 0;
  818. top: 0;
  819. width: 100%;
  820. height: 100%;
  821. border-radius: 8px;
  822. background: linear-gradient(360deg,
  823. rgba(0, 0, 0, 0.78) 0%,
  824. rgba(0, 0, 0, 0.437208) 19.87%,
  825. rgba(0, 0, 0, 0) 33.99%);
  826. display: flex;
  827. flex-direction: column;
  828. align-items: baseline;
  829. justify-content: end;
  830. padding: 12px;
  831. box-sizing: border-box;
  832. color: #fff;
  833. .review-text {
  834. font-family: "PangMenZhengDao";
  835. font-size: 16px;
  836. margin-bottom: 1px;
  837. }
  838. .review-content {
  839. font-size: 10px;
  840. line-height: 15px;
  841. }
  842. }
  843. .vs-wrap {
  844. position: absolute;
  845. left: 50%;
  846. top: 50%;
  847. transform: translate(-50%, -50%);
  848. width: 40px;
  849. height: 40px;
  850. z-index: 10;
  851. img {
  852. width: 100%;
  853. height: 100%;
  854. object-fit: cover;
  855. }
  856. }
  857. .review-image-item {
  858. position: relative;
  859. flex: 1;
  860. .review-image-item-title {
  861. position: absolute;
  862. top: 0;
  863. left: 0;
  864. background: rgba(54, 52, 52, 0.6);
  865. padding: 4px 10px;
  866. border-radius: 8px 0 8px 0;
  867. backdrop-filter: 4px;
  868. font-size: 12px;
  869. color: #fff;
  870. }
  871. // .review-image-item-img {
  872. // width: 100%;
  873. // height: 250px;
  874. // object-fit: cover;
  875. // }
  876. .review-image-item-img {
  877. width: 100%;
  878. height: 100%;
  879. object-fit: cover;
  880. object-position: center;
  881. }
  882. .left-img {
  883. border-radius: 8px 0 0 8px;
  884. }
  885. .right-img {
  886. border-radius: 0 8px 8px 0;
  887. }
  888. }
  889. }
  890. }
  891. .cavans-popup {
  892. width: 100%;
  893. max-width: 100%;
  894. max-height: 92vh;
  895. background: none;
  896. border-radius: 12px;
  897. overflow: auto;
  898. display: flex;
  899. flex-direction: column;
  900. backdrop-filter: 4px;
  901. .cavans-content {
  902. text-align: center;
  903. padding: 0 12px;
  904. height: fit-content;
  905. overflow: auto;
  906. .current-img {
  907. width: 100%;
  908. }
  909. }
  910. // 底部操作按钮
  911. .bottom-actions {
  912. flex-shrink: 0;
  913. .action-buttons {
  914. padding: 12px 0 4px 0;
  915. display: flex;
  916. justify-content: space-around;
  917. .action-btn {
  918. display: flex;
  919. flex-direction: column;
  920. align-items: center;
  921. cursor: pointer;
  922. &.text-btn {
  923. font-size: 12px;
  924. color: rgba(255, 255, 255, 0.7);
  925. }
  926. .icon-circle {
  927. width: 48px;
  928. height: 48px;
  929. border-radius: 50%;
  930. display: flex;
  931. align-items: center;
  932. justify-content: center;
  933. color: #fff;
  934. margin-bottom: 4px;
  935. .el-icon {
  936. color: #fff;
  937. }
  938. img {
  939. width: 50px;
  940. }
  941. }
  942. &.blue-btn .icon-circle {
  943. background: #2199f8;
  944. }
  945. &.green-btn .icon-circle {
  946. background: #07c160;
  947. }
  948. &.orange-btn .icon-circle {
  949. background: #ff790b;
  950. }
  951. .btn-label {
  952. font-size: 12px;
  953. color: #fff;
  954. }
  955. }
  956. }
  957. .cancel-btn {
  958. text-align: center;
  959. font-size: 18px;
  960. color: #fff;
  961. cursor: pointer;
  962. }
  963. }
  964. }
  965. </style>