reviewWork.vue 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. <template>
  2. <div class="work-wrap">
  3. <custom-header name="农事详情" :isClose="paramsPage.goBack ? false : true"></custom-header>
  4. <div
  5. class="work-content recheck-title"
  6. :class="{ 'no-bottom': curRole == '0' && (!workItem.reviewImage || !workItem.reviewImage.length) }"
  7. v-loading="loading"
  8. >
  9. <div class="tabs-content-item">
  10. <div class="common-card-title">
  11. <img class="icon" src="@/assets/img/home/label-icon.png" alt="" />
  12. <span>农事信息</span>
  13. </div>
  14. <div class="info-box">
  15. <div class="info-l">
  16. <img class="farm-img" src="@/assets/img/home/farm.png" alt="" />
  17. </div>
  18. <div class="info-r">
  19. <div class="farm-name">{{ workItem.farmName }}</div>
  20. <div class="info-item">
  21. <div class="info-name">农事名称:</div>
  22. <div class="info-value">{{ workItem.farmWorkName }} ({{ workItem.executeDate }})</div>
  23. </div>
  24. <div class="info-item">
  25. <div class="info-name">农事目的:</div>
  26. <div class="info-value">{{ workItem.purpose || "--" }}</div>
  27. </div>
  28. <div class="info-item">
  29. <div class="info-name">肥药处方:</div>
  30. <div class="info-value">
  31. <div class="rescription" v-if="workItem?.prescriptionList">
  32. <span
  33. v-for="(fertilizer, fertilizerI) in workItem.prescriptionList"
  34. :key="fertilizerI"
  35. >
  36. <span
  37. v-for="(pest, pestI) in fertilizer.pesticideFertilizerList"
  38. :key="'sub' + pestI"
  39. >
  40. {{ pest.defaultName || pest.pesticideFertilizerName }}
  41. <span
  42. v-if="
  43. pestI !== fertilizer.pesticideFertilizerList.length - 1 ||
  44. fertilizerI !== workItem.prescriptionList.length - 1
  45. "
  46. >
  47. +
  48. </span>
  49. </span>
  50. </span>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. <div class="info-box subject-content">
  57. <div class="subject-box">
  58. <div class="subject-item cost-l">
  59. <img class="subject-img" src="@/assets/img/home/nz.png" alt="" />
  60. <div class="subject-tag">
  61. {{ workItem.serviceMain }}
  62. <el-icon class="right-icon" size="10"><ArrowRight /></el-icon>
  63. </div>
  64. </div>
  65. <div class="subject-item">
  66. <img class="subject-img" :src="workItem.expertIcon" alt="" />
  67. <div class="subject-tag">
  68. {{ workItem.expertName }}
  69. <el-icon class="right-icon" size="10"><ArrowRight /></el-icon>
  70. </div>
  71. </div>
  72. </div>
  73. </div>
  74. </div>
  75. <div class="tabs-content-item">
  76. <div class="common-card-title">
  77. <img class="icon" src="@/assets/img/home/label-icon.png" alt="" />
  78. <span>复核成效</span>
  79. </div>
  80. <div class="info-box bottom-box">
  81. <div class="recheck-box">
  82. <div class="recheck-ablum">
  83. <!-- <div class="img-list over-img-box">
  84. <album-carousel :key="1" labelText="农事前" :images="triggerImg"></album-carousel>
  85. </div> -->
  86. <div class="img-list over-img-box">
  87. <album-carousel
  88. class="execute-img"
  89. :key="1"
  90. labelText="执行照片"
  91. :imgData="workItem"
  92. :images="workItem.executeEvidence"
  93. ></album-carousel>
  94. </div>
  95. <div
  96. class="img-list over-img-box"
  97. v-if="workItem.reviewImage && workItem.reviewImage.length"
  98. >
  99. <album-carousel
  100. :key="2"
  101. labelText="复核照片"
  102. :isAchievementImgs="true"
  103. :imgData="workItem"
  104. :images="workItem.reviewImage"
  105. ></album-carousel>
  106. </div>
  107. <!-- <div class="img-list over-img-box" v-if="combinedReviewImages.length">
  108. <album-carousel :key="3" :isAchievementImgs="true" :images="combinedReviewImages"></album-carousel>
  109. </div> -->
  110. <div class="img-list" v-if="!workItem.reviewImage || !workItem.reviewImage.length">
  111. <div
  112. class="recheck-text-wrap active"
  113. :class="{
  114. 'center-wrap': !imageArr.length,
  115. }"
  116. >
  117. <div class="date" v-show="workItem.reviewDate">{{ workItem.reviewDate }}</div>
  118. <upload
  119. exampleImg
  120. @handleUpload="handleUpload"
  121. class="upload-wrap"
  122. :style="{
  123. height:
  124. imageArr.length && !diffInDays(workItem.reviewDate) > 0
  125. ? 'auto'
  126. : '254px',
  127. }"
  128. >
  129. <template
  130. v-if="
  131. diffInDays(workItem.reviewDate) == 0 ||
  132. diffInDays(workItem.reviewDate) == null
  133. "
  134. >
  135. <img
  136. class="img-icon"
  137. :src="require(`@/assets/img/gallery/img-icon-act.png`)"
  138. alt=""
  139. />
  140. <div class="recheck-text">点击上传照片</div>
  141. </template>
  142. <!-- <template v-else>
  143. <img class="img-icon" src="@/assets/img/gallery/img-icon.png" alt="" />
  144. <div class="recheck-text">等待复核</div>
  145. <div class="recheck-desc" v-show="diffInDays(workItem.reviewDate) >= 0">
  146. (剩余{{ diffInDays(workItem.reviewDate) }}天)
  147. </div>
  148. </template> -->
  149. </upload>
  150. <div
  151. class="submit"
  152. v-show="imageArr.length && !diffInDays(workItem.reviewDate) > 0"
  153. @click="handleSubmit('reviewImage2')"
  154. >
  155. 确认上传
  156. </div>
  157. </div>
  158. </div>
  159. <!-- <div class="img-list" v-else>
  160. <div
  161. class="recheck-text-wrap no-events"
  162. :class="{
  163. active: !diffInDays(workItem.reviewDate) > 0 && curRole === '0',
  164. 'yse-events': curRole === '0' && !diffInDays(workItem.reviewDate) > 0,
  165. 'center-wrap': !imageArr2.length,
  166. }"
  167. >
  168. <div class="date" v-show="workItem.reviewDate">{{ workItem.reviewDate }}</div>
  169. <upload
  170. exampleImg
  171. @handleUpload="handleUpload2"
  172. class="upload-wrap"
  173. :style="{
  174. height:
  175. imageArr2.length && !diffInDays(workItem.reviewDate) > 0
  176. ? 'auto'
  177. : '254px',
  178. }"
  179. >
  180. <template
  181. v-if="
  182. diffInDays(workItem.reviewDate) == 0 ||
  183. diffInDays(workItem.reviewDate) == null
  184. "
  185. >
  186. <img
  187. class="img-icon"
  188. :src="
  189. require(`@/assets/img/gallery/img-icon${
  190. curRole === '0' ? '-act' : ''
  191. }.png`)
  192. "
  193. alt=""
  194. />
  195. <div class="recheck-text">
  196. {{ curRole === "2" ? "等待农户上传" : "点击上传照片" }}
  197. </div>
  198. <div
  199. class="recheck-desc"
  200. v-show="curRole === '2' && diffInDays(workItem.reviewDate) != 0"
  201. >
  202. </div>
  203. </template>
  204. <template v-else>
  205. <img class="img-icon" src="@/assets/img/gallery/img-icon.png" alt="" />
  206. <div class="recheck-text">等待复核</div>
  207. <div class="recheck-desc" v-show="diffInDays(workItem.reviewDate) >= 0">
  208. (剩余{{ diffInDays(workItem.reviewDate) }}天)
  209. </div>
  210. </template>
  211. </upload>
  212. <div
  213. class="submit"
  214. v-show="imageArr2.length && !diffInDays(workItem.reviewDate) > 0"
  215. @click="handleSubmit('reviewImage2')"
  216. >
  217. 确认上传
  218. </div>
  219. </div>
  220. </div> -->
  221. </div>
  222. </div>
  223. </div>
  224. </div>
  225. <!-- 按钮 -->
  226. <div class="up-btn-group" v-show="isPlan">
  227. <template v-if="curRole === '2'">
  228. <div
  229. class="up-btn"
  230. :class="{ btn: workItem.executeEvidence && workItem.executeEvidence.length }"
  231. v-show="workItem.reviewImage && !workItem.reviewImage.length"
  232. >
  233. 提醒农户拍照
  234. </div>
  235. </template>
  236. <template v-else>
  237. <div
  238. class="up-btn btn"
  239. @click="handleContact"
  240. v-show="workItem.reviewImage && workItem.reviewImage.length && !imageArr.length"
  241. >
  242. 联系专家
  243. </div>
  244. </template>
  245. </div>
  246. <div class="fixed-btn-wrap" :class="{ center: !paramsPage.isBtn }">
  247. <div class="fixed-btn more" @click="handleMore" v-if="paramsPage.isBtn">查看更多农事</div>
  248. <div class="fixed-btn excute" @click="generateReport">生成成果报告</div>
  249. </div>
  250. <div
  251. class="fixed-btn-wrap center"
  252. v-if="curRole == '0' && workItem.reviewImage && workItem.reviewImage.length"
  253. >
  254. <div class="fixed-btn excute" @click="handleShare">转发</div>
  255. </div>
  256. <!-- 组合照片(用于生成合成图片) -->
  257. <div class="review-hide-box">
  258. <div class="review-image" ref="reviewComboRef">
  259. <div class="review-mask">
  260. <div class="review-text">复核成效</div>
  261. <div class="review-content">
  262. {{ workItem?.reCheckText }}
  263. </div>
  264. </div>
  265. <div class="vs-wrap" v-if="workItem?.reviewImage && workItem?.reviewImage?.length">
  266. <img src="@/assets/img/home/vs.png" alt="" />
  267. </div>
  268. <div class="review-image-item" v-if="triggerImg?.length">
  269. <div class="review-image-item-title">复核照片</div>
  270. <!-- <img
  271. class="review-image-item-img left-img"
  272. :src="base_img_url2 + triggerImg[triggerImg.length - 1].cloudFilename"
  273. alt=""
  274. /> -->
  275. <img
  276. class="review-image-item-img left-img"
  277. :src="leftCoverImg"
  278. style="
  279. width: 100%;
  280. height: 255px;
  281. display: block;
  282. image-rendering: auto;
  283. "
  284. />
  285. </div>
  286. <div class="review-image-item" v-if="workItem?.reviewImage?.length">
  287. <!-- <img
  288. class="review-image-item-img right-img"
  289. :src="base_img_url2 + workItem.reviewImage[workItem.reviewImage.length - 1]"
  290. alt=""
  291. /> -->
  292. <img
  293. class="review-image-item-img right-img"
  294. :src="rightCoverImg"
  295. style="
  296. width: 100%;
  297. height: 255px;
  298. display: block;
  299. image-rendering: auto;
  300. "
  301. />
  302. </div>
  303. </div>
  304. </div>
  305. </div>
  306. <!-- 上传图片弹窗 -->
  307. <upload-popup :executionData="workItem"></upload-popup>
  308. <!-- 分享农事成效弹窗 -->
  309. <review-popup ref="reviewPopupRef" />
  310. <!-- 上传农事成效弹窗 -->
  311. <upload-execute ref="uploadExecuteRef" :onlyShare="true" />
  312. </div>
  313. </template>
  314. <script setup>
  315. import { Tab, Tabs } from "vant";
  316. import customHeader from "@/components/customHeader.vue";
  317. import { onMounted, ref, onDeactivated, onActivated, onUnmounted, nextTick, watch } from "vue";
  318. import { useRoute, useRouter } from "vue-router";
  319. import upload from "@/components/upload";
  320. import AlbumCarousel from "@/components/album_compoents/albumCarousel";
  321. import { ElMessage } from "element-plus";
  322. import uploadPopup from "@/components/popup/uploadPopup.vue";
  323. import { base_img_url2 } from "@/api/config";
  324. import reviewPopup from "@/views/old_mini/task_condition/components/reviewPopup.vue";
  325. import uploadExecute from "@/views/old_mini/task_condition/components/uploadExecute.vue";
  326. import html2canvas from "html2canvas";
  327. const route = useRoute();
  328. const router = useRouter();
  329. const uploadExecuteRef = ref(null);
  330. const workItem = ref({});
  331. const curRole = ref("");
  332. // 农事规划页面-显示上传农事凭证按钮
  333. const isPlan = ref(false);
  334. const loading = ref(false);
  335. const reviewComboRef = ref(null);
  336. const combinedReviewImages = ref([]);
  337. const diffInDays = (date, type = "minus") => {
  338. const targetDate = new Date(date);
  339. const currentDate = new Date(); // 获取当前系统时间
  340. let diffInMs;
  341. if (type === "minus") {
  342. diffInMs = targetDate - currentDate;
  343. } else {
  344. diffInMs = currentDate - targetDate;
  345. }
  346. const day = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
  347. return day + 1 >= 0 ? day + 1 : null;
  348. };
  349. const paramsPage = ref({});
  350. onActivated(() => {
  351. window.scrollTo(0, 0);
  352. curRole.value = localStorage.getItem("SET_USER_CUR_ROLE");
  353. paramsPage.value = route.query.miniJson ? JSON.parse(route.query.miniJson) : {};
  354. getDetail();
  355. getTriggerImg(paramsPage.value.id);
  356. });
  357. const getDetail = () => {
  358. if (!paramsPage.value.id) return;
  359. loading.value = true;
  360. VE_API.z_farm_work_record
  361. .getDetail({ id: paramsPage.value.id })
  362. .then(({ data }) => {
  363. workItem.value = data[0];
  364. })
  365. .finally(() => {
  366. loading.value = false;
  367. });
  368. };
  369. const triggerImg = ref([]);
  370. const getTriggerImg = (farmWorkRecordId) => {
  371. VE_API.z_farm_work_record.getTriggerImg({ farmWorkRecordId }).then(({ data }) => {
  372. triggerImg.value = data || [];
  373. });
  374. };
  375. // 生成组合照片,传给相册组件
  376. const generateCombinedReviewImage = async () => {
  377. try {
  378. await prepareCoverImages()
  379. await nextTick()
  380. const canvas = await html2canvas(reviewComboRef.value, {
  381. backgroundColor: null,
  382. useCORS: true,
  383. allowTaint: true,
  384. scale: window.devicePixelRatio || 2,
  385. })
  386. combinedReviewImages.value = [canvas.toDataURL('image/png')]
  387. } catch (e) {
  388. console.error('生成组合照片失败', e)
  389. }
  390. }
  391. const prepareCoverImages = async () => {
  392. await nextTick()
  393. const itemEl =
  394. reviewComboRef.value.querySelector('.review-image-item')
  395. const cssWidth = itemEl.offsetWidth
  396. const cssHeight = 255
  397. if (triggerImg.value?.length) {
  398. leftCoverImg.value = await coverImageToBase64HD(
  399. base_img_url2 + triggerImg.value.at(-1).cloudFilename,
  400. cssWidth,
  401. cssHeight
  402. )
  403. }
  404. if (workItem.value?.reviewImage?.length) {
  405. rightCoverImg.value = await coverImageToBase64HD(
  406. base_img_url2 + workItem.value.reviewImage.at(-1),
  407. cssWidth,
  408. cssHeight
  409. )
  410. }
  411. }
  412. const leftCoverImg = ref('')
  413. const rightCoverImg = ref('')
  414. function coverImageToBase64HD(imgUrl, cssWidth, cssHeight) {
  415. return new Promise((resolve, reject) => {
  416. const dpr = window.devicePixelRatio || 2
  417. const img = new Image()
  418. img.crossOrigin = 'anonymous'
  419. img.src = imgUrl
  420. img.onload = () => {
  421. // ⚠️ 用“物理像素”创建 canvas
  422. const canvas = document.createElement('canvas')
  423. canvas.width = cssWidth * dpr
  424. canvas.height = cssHeight * dpr
  425. const ctx = canvas.getContext('2d')
  426. ctx.scale(dpr, dpr)
  427. const imgRatio = img.width / img.height
  428. const targetRatio = cssWidth / cssHeight
  429. let sx = 0, sy = 0, sw = img.width, sh = img.height
  430. if (imgRatio > targetRatio) {
  431. sw = img.height * targetRatio
  432. sx = (img.width - sw) / 2
  433. } else {
  434. sh = img.width / targetRatio
  435. sy = (img.height - sh) / 2
  436. }
  437. ctx.drawImage(
  438. img,
  439. sx, sy, sw, sh,
  440. 0, 0, cssWidth, cssHeight
  441. )
  442. resolve(canvas.toDataURL('image/png'))
  443. }
  444. img.onerror = reject
  445. })
  446. }
  447. watch(
  448. () => [triggerImg.value, workItem.value.reviewImage],
  449. ([preImgs, reviewImgs]) => {
  450. if (preImgs && preImgs.length && reviewImgs && reviewImgs.length) {
  451. generateCombinedReviewImage();
  452. }
  453. },
  454. { deep: true }
  455. );
  456. //确认上传
  457. const handleSubmit = () => {
  458. const params = {
  459. executeEvidence: imageArr.value,
  460. recordId: workItem.value.id,
  461. };
  462. VE_API.monitor.addReviewImg(params).then(({ code }) => {
  463. if (code === 0) {
  464. getDetail();
  465. ElMessage.success("您已上传成功");
  466. imageArr.value = [];
  467. }
  468. });
  469. };
  470. const reviewPopupRef = ref(null);
  471. const handleShare = () => {
  472. const preImg = triggerImg.value.length
  473. ? base_img_url2 + triggerImg.value[triggerImg.value.length - 1].cloudFilename
  474. : "";
  475. const resImg = workItem.value?.reviewImage?.length
  476. ? base_img_url2 + workItem.value.reviewImage[workItem.value.reviewImage.length - 1]
  477. : "";
  478. reviewPopupRef.value.handleShowPopup(workItem.value.id, preImg, resImg);
  479. };
  480. const generateReport = () => {
  481. router.push({
  482. path: "/achievement_report",
  483. query: { miniJson: JSON.stringify({ id: workItem.value.id }) },
  484. });
  485. };
  486. const handleRemindUser = () => {
  487. uploadExecuteRef.value.showPopup({ ...workItem.value, type: "remindUser" });
  488. };
  489. const handleMore = () => {
  490. router.push(`/service_detail?farmId=${workItem.value.farmId}`);
  491. };
  492. // 清理数据的函数
  493. const clearData = () => {
  494. workItem.value = {};
  495. triggerImg.value = [];
  496. imageArr.value = [];
  497. paramsPage.value = {};
  498. isPlan.value = false;
  499. curRole.value = "";
  500. loading.value = false;
  501. };
  502. onDeactivated(() => {
  503. clearData();
  504. });
  505. onUnmounted(() => {
  506. clearData();
  507. });
  508. // //联系专家
  509. // const handleContact = () => {
  510. // router.push(`/dialogue?userId=${workItem.value.expert}&name=${workItem.value.expertUserName}`);
  511. // };
  512. const imageArr = ref([]);
  513. const handleUpload = ({ imgArr }) => {
  514. imageArr.value = imgArr;
  515. };
  516. </script>
  517. <style lang="scss" scoped>
  518. .work-wrap {
  519. .center-wrap {
  520. ::v-deep {
  521. .van-uploader__wrapper {
  522. justify-content: center;
  523. }
  524. }
  525. }
  526. .work-content {
  527. padding-top: 1px;
  528. background: #f5f5f5;
  529. padding-bottom: 12px;
  530. font-size: 14px;
  531. height: calc(100vh - 40px);
  532. box-sizing: border-box;
  533. overflow: auto;
  534. &.recheck-title {
  535. padding-bottom: 86px;
  536. .common-card-title {
  537. font-size: 16px;
  538. display: flex;
  539. align-items: center;
  540. border-bottom: 1px solid #f5f5f5;
  541. padding-bottom: 10px;
  542. .icon {
  543. width: 14px;
  544. height: 8px;
  545. padding-right: 6px;
  546. }
  547. }
  548. &.no-bottom {
  549. padding-bottom: 26px;
  550. }
  551. }
  552. .up-btn-group {
  553. position: fixed;
  554. bottom: 80px;
  555. left: 12px;
  556. display: flex;
  557. justify-content: center;
  558. width: calc(100% - 24px);
  559. .up-btn {
  560. background: linear-gradient(45deg, #9fd5ff, #2199f8);
  561. flex: 1;
  562. height: 40px;
  563. border: 2px solid rgba(255, 255, 255, 0.66);
  564. color: #fff;
  565. font-size: 14px;
  566. border-radius: 40px;
  567. line-height: 38px;
  568. text-align: center;
  569. box-sizing: border-box;
  570. }
  571. .orange {
  572. margin-left: 12px;
  573. background: linear-gradient(45deg, #ffd887, #ed9e1e);
  574. }
  575. .btn {
  576. width: 200px;
  577. flex: none;
  578. }
  579. }
  580. .fixed-btn-wrap {
  581. position: fixed;
  582. z-index: 10;
  583. bottom: 0;
  584. left: 0;
  585. width: 100%;
  586. padding: 10px 12px 25px;
  587. box-sizing: border-box;
  588. display: flex;
  589. align-items: center;
  590. justify-content: space-between;
  591. background: #fff;
  592. box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
  593. &.center {
  594. justify-content: center;
  595. }
  596. .fixed-btn {
  597. width: 120px;
  598. text-align: center;
  599. height: 40px;
  600. line-height: 40px;
  601. background: linear-gradient(180deg, #70bffe, #2199f8);
  602. border-radius: 25px;
  603. color: #fff;
  604. font-size: 14px;
  605. box-sizing: border-box;
  606. &.expert {
  607. width: 180px;
  608. }
  609. &.orange {
  610. color: #ff953d;
  611. border: 1px solid #ff953d;
  612. background: #fff;
  613. }
  614. &.excute {
  615. background: linear-gradient(180deg, #ffd887, #ed9e1e);
  616. }
  617. &.more {
  618. background: #ffffff;
  619. border: 1px solid rgba(153, 153, 153, 0.5);
  620. color: #666666;
  621. }
  622. &.second {
  623. background: #ffffff;
  624. border: 1px solid #2199f8;
  625. color: #2199f8;
  626. }
  627. }
  628. }
  629. .tabs-content-item {
  630. padding: 12px 12px 16px 12px;
  631. margin: 0 12px;
  632. border-radius: 8px;
  633. background: #fff;
  634. margin-top: 12px;
  635. position: relative;
  636. .execute-img {
  637. margin-top: 12px;
  638. }
  639. .card-title {
  640. display: flex;
  641. justify-content: space-between;
  642. align-items: center;
  643. padding-bottom: 10px;
  644. .card-title-l {
  645. display: flex;
  646. align-items: center;
  647. font-size: 16px;
  648. .icon {
  649. width: 14px;
  650. height: 8px;
  651. padding-right: 6px;
  652. }
  653. }
  654. .card-title-r {
  655. font-size: 14px;
  656. color: #2199f8;
  657. }
  658. }
  659. .info-box {
  660. // padding-top: 12px;
  661. display: flex;
  662. align-items: center;
  663. &.subject-content {
  664. border: none;
  665. }
  666. &.cost-wrap {
  667. padding-top: 8px;
  668. }
  669. &.bottom-box {
  670. flex-direction: column;
  671. }
  672. .info-l {
  673. .farm-img {
  674. width: 78px;
  675. width: 78px;
  676. border-radius: 8px;
  677. object-fit: scale-down;
  678. }
  679. }
  680. .info-r {
  681. padding-left: 12px;
  682. }
  683. .farm-name {
  684. font-weight: bold;
  685. font-size: 14px;
  686. color: #000;
  687. padding-bottom: 4px;
  688. }
  689. .info-item {
  690. display: flex;
  691. font-size: 12px;
  692. .info-name {
  693. color: #bbbbbb;
  694. flex: none;
  695. }
  696. .info-value {
  697. color: #666666;
  698. }
  699. }
  700. .info-item + .info-item {
  701. margin-top: 4px;
  702. }
  703. }
  704. .subject-box {
  705. width: 100%;
  706. display: flex;
  707. align-items: center;
  708. justify-content: space-around;
  709. background: #fafafa;
  710. .subject-item {
  711. border-radius: 8px;
  712. padding: 4px 4px;
  713. display: flex;
  714. flex-direction: column;
  715. align-items: center;
  716. justify-content: center;
  717. width: 33%;
  718. .subject-img {
  719. width: 30px;
  720. height: 30px;
  721. object-fit: cover;
  722. border-radius: 50%;
  723. padding-bottom: 4px;
  724. }
  725. .subject-tag {
  726. font-size: 12px;
  727. padding: 2px 3px 3px 8px;
  728. background: #e0efff;
  729. color: #2199f8;
  730. border-radius: 4px;
  731. &.cost-text {
  732. margin-left: 8px;
  733. font-size: 16px;
  734. color: #2199f8;
  735. padding: 1px 8px;
  736. }
  737. }
  738. }
  739. .subject-item + .subject-item {
  740. margin-left: 6px;
  741. }
  742. .cost-l {
  743. position: relative;
  744. &::after {
  745. content: "";
  746. position: absolute;
  747. right: 0;
  748. top: 16px;
  749. height: calc(100% - 32px);
  750. width: 1px;
  751. background: rgba(0, 0, 0, 0.05);
  752. }
  753. }
  754. }
  755. .cost-box {
  756. border-radius: 5px;
  757. background: none;
  758. .cost-item {
  759. display: flex;
  760. align-items: center;
  761. flex-direction: row;
  762. }
  763. .subject-item {
  764. background: none;
  765. width: 50%;
  766. }
  767. .cost-l {
  768. position: relative;
  769. &::after {
  770. content: "";
  771. position: absolute;
  772. right: 0;
  773. top: 0;
  774. height: 100%;
  775. width: 1px;
  776. background: rgba(0, 0, 0, 0.05);
  777. }
  778. }
  779. .cost-text {
  780. font-size: 16px;
  781. color: #2199f8;
  782. padding-bottom: 5px;
  783. }
  784. }
  785. .recheck-box,
  786. .recheck-ablum {
  787. width: 100%;
  788. }
  789. .evaluate {
  790. background: #fff;
  791. border-radius: 5px;
  792. padding: 4px 8px 10px 8px;
  793. margin-right: 8px;
  794. .evaluate-title {
  795. font-size: 16px;
  796. font-weight: 500;
  797. display: flex;
  798. align-items: center;
  799. justify-content: space-between;
  800. margin-bottom: 8px;
  801. .more {
  802. font-size: 14px;
  803. color: #999999;
  804. font-weight: 400;
  805. display: flex;
  806. align-items: center;
  807. }
  808. }
  809. .rate {
  810. display: flex;
  811. justify-content: space-between;
  812. ::v-deep {
  813. .el-rate {
  814. --el-rate-icon-margin: 0;
  815. }
  816. .el-rate--small .el-rate__icon {
  817. font-size: 12px;
  818. }
  819. }
  820. .rate-item {
  821. display: flex;
  822. align-items: center;
  823. border-radius: 4px;
  824. padding: 4px 0px;
  825. font-size: 11px;
  826. .name {
  827. margin-right: 2px;
  828. color: #666666;
  829. position: relative;
  830. top: 2px;
  831. }
  832. .num {
  833. color: #f3c11d;
  834. margin-left: 2px;
  835. }
  836. }
  837. .line {
  838. width: 1px;
  839. height: 12px;
  840. background: #cdd7e1;
  841. position: relative;
  842. top: 13px;
  843. margin: 0 3px;
  844. }
  845. }
  846. .comment {
  847. .user-info {
  848. display: flex;
  849. align-items: center;
  850. margin-bottom: 2px;
  851. .user-name {
  852. font-weight: 500;
  853. margin-left: 8px;
  854. span {
  855. font-weight: 400;
  856. font-size: 12px;
  857. color: #999999;
  858. }
  859. }
  860. }
  861. }
  862. }
  863. .img-list + .img-list,
  864. .upload-wrap {
  865. margin-top: 12px;
  866. }
  867. // .over-img-box {
  868. // ::v-deep {
  869. // img {
  870. // border-radius: 8px;
  871. // }
  872. // }
  873. // }
  874. .img-list {
  875. width: 100%;
  876. }
  877. .upload-wrap {
  878. display: flex;
  879. flex-direction: column;
  880. justify-content: center;
  881. height: 254px;
  882. width: 100%;
  883. padding: 25px 0 12px 10px;
  884. box-sizing: border-box;
  885. }
  886. .recheck-text-wrap {
  887. width: 100%;
  888. border-radius: 8px;
  889. background: #f2f3f5;
  890. color: #666666;
  891. font-size: 14px;
  892. position: relative;
  893. &.active {
  894. background: rgba(33, 153, 248, 0.1);
  895. border: 1px solid #2199f8;
  896. color: #2199f8;
  897. .date {
  898. background: linear-gradient(170deg, #9fd5ff, #2199f8);
  899. }
  900. .recheck-desc {
  901. color: #2199f8;
  902. }
  903. }
  904. .submit {
  905. background: #2199f8;
  906. border-radius: 4px;
  907. padding: 8px;
  908. font-size: 16px;
  909. color: #fff;
  910. margin: 0 10px 16px;
  911. text-align: center;
  912. }
  913. .date {
  914. position: absolute;
  915. top: 0;
  916. left: 0;
  917. background: #bebebe;
  918. border-radius: 8px 0 8px 0;
  919. color: #fff;
  920. font-size: 12px;
  921. padding: 3px 6px;
  922. font-family: "PangMenZhengDao";
  923. }
  924. .recheck-text {
  925. padding: 8px 0 2px 0;
  926. }
  927. .recheck-desc {
  928. font-size: 12px;
  929. color: #999999;
  930. }
  931. .img-icon {
  932. width: 40px;
  933. height: 40px;
  934. }
  935. }
  936. .sub-title {
  937. display: flex;
  938. align-items: center;
  939. justify-content: center;
  940. .sub-line {
  941. width: 12px;
  942. height: 2px;
  943. border-radius: 1px;
  944. background: #d9d9d9;
  945. }
  946. .sub-name {
  947. padding: 0 5px;
  948. font-size: 14px;
  949. color: #666666;
  950. }
  951. }
  952. }
  953. }
  954. .review-hide-box {
  955. position: absolute;
  956. left: 0;
  957. width: 100%;
  958. height: 100%;
  959. z-index: -1;
  960. bottom: 0;
  961. }
  962. .review-image {
  963. position: relative;
  964. display: flex;
  965. align-items: center;
  966. justify-content: center;
  967. gap: 8px;
  968. margin: 12px;
  969. background: #fff;
  970. border-radius: 8px;
  971. .review-mask {
  972. z-index: 1;
  973. pointer-events: none;
  974. position: absolute;
  975. left: 0;
  976. top: 0;
  977. width: 100%;
  978. height: 100%;
  979. border-radius: 8px;
  980. background: linear-gradient(
  981. 360deg,
  982. rgba(0, 0, 0, 0.78) 0%,
  983. rgba(0, 0, 0, 0.437208) 19.87%,
  984. rgba(0, 0, 0, 0) 33.99%
  985. );
  986. display: flex;
  987. flex-direction: column;
  988. align-items: baseline;
  989. justify-content: end;
  990. padding: 12px;
  991. box-sizing: border-box;
  992. color: #fff;
  993. .review-text {
  994. font-family: "PangMenZhengDao";
  995. font-size: 16px;
  996. margin-bottom: 1px;
  997. }
  998. .review-content {
  999. font-size: 10px;
  1000. line-height: 15px;
  1001. }
  1002. }
  1003. .vs-wrap {
  1004. position: absolute;
  1005. left: 50%;
  1006. top: 50%;
  1007. transform: translate(-50%, -50%);
  1008. width: 40px;
  1009. height: 40px;
  1010. z-index: 10;
  1011. img {
  1012. width: 100%;
  1013. height: 100%;
  1014. object-fit: cover;
  1015. }
  1016. }
  1017. .review-image-item {
  1018. position: relative;
  1019. flex: 1;
  1020. .review-image-item-title {
  1021. position: absolute;
  1022. top: 0;
  1023. left: 0;
  1024. background: rgba(54, 52, 52, 0.6);
  1025. padding: 4px 10px;
  1026. border-radius: 8px 0 8px 0;
  1027. backdrop-filter: 4px;
  1028. font-size: 12px;
  1029. color: #fff;
  1030. }
  1031. // .review-image-item-img {
  1032. // width: 100%;
  1033. // height: 250px;
  1034. // object-fit: cover;
  1035. // }
  1036. .review-image-item-img {
  1037. width: 100%;
  1038. height: 100%;
  1039. object-fit: cover;
  1040. object-position: center;
  1041. }
  1042. .left-img {
  1043. border-radius: 8px 0 0 8px;
  1044. }
  1045. .right-img {
  1046. border-radius: 0 8px 8px 0;
  1047. }
  1048. }
  1049. }
  1050. }
  1051. </style>