albumCarouselItem.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. <template>
  2. <div class="carousel-container">
  3. <!-- 图片列表 -->
  4. <div class="carousel-wrapper" :style="carouselStyle">
  5. <!-- <photo-provider v-if="images" :photo-closable="true" @visibleChange="handleVisibleChange">
  6. <template v-for="(photo, index) in images"
  7. :key="photo.id">
  8. <album-draw-box :isShowNum="0" :farmId="766" :photo="photo" :current="currentIndex" :index="index" :length="images.length"
  9. ></album-draw-box>
  10. </template>
  11. </photo-provider> -->
  12. <div class="carousel-img" v-for="(photo, index) in images" :key="index">
  13. <div class="label-text" v-if="labelText">{{ labelText }}</div>
  14. <img class="img-dom" :index="index" @click="clickPhoto(photo)" :src="getPhotoSrc(photo)" alt="" />
  15. <div class="carousel-img-mask app-mask" v-if="!isAchievementImgs && imgType === 'app'">
  16. <div class="mask-content app-mask-content">
  17. <div class="app-mask-top">
  18. <div class="app-mask-top-left">
  19. <div class="app-year">{{ formatYear(imgData?.createTime || imgData?.updateTime) }}</div>
  20. <div class="app-date-wrapper">
  21. <div class="app-date-line"></div>
  22. <div class="app-date">
  23. {{ formatMonthDay(imgData?.createTime || imgData?.updateTime) }}
  24. </div>
  25. </div>
  26. </div>
  27. <div>
  28. <!-- <div class="app-mask-top-right">
  29. <div class="app-phenology">当前处于 {{ imgData?.phenologyName }}</div>
  30. <div class="app-uploader">上传人:{{ imgData?.sourceDataJson?.userName }}</div>
  31. </div> -->
  32. <!-- 底部中间/右侧:天气信息和位置 -->
  33. <div class="app-mask-bottom">
  34. <div class="app-weather-info">
  35. <div class="app-weather-item">
  36. <img class="app-weather-icon" src="@/assets/watermark/temp.png" alt="" />
  37. <span
  38. >{{ imgData?.sourceDataJson?.suitability?.tempMin }}-{{
  39. imgData?.sourceDataJson?.suitability?.tempMax
  40. }}℃ {{ imgData?.sourceDataJson?.suitability?.tempSuitability }}</span
  41. >
  42. </div>
  43. <div class="app-weather-item">
  44. <img class="app-weather-icon" src="@/assets/watermark/shidu.png" alt="" />
  45. <span>{{ imgData?.sourceDataJson?.suitability?.humiditySuitability }}</span>
  46. </div>
  47. <div class="app-weather-item">
  48. <img class="app-weather-icon" src="@/assets/watermark/fushe.png" alt="" />
  49. <span>{{ imgData?.sourceDataJson?.suitability?.vindexSuitability }}</span>
  50. </div>
  51. <!-- <span class="app-weather-separator" v-if="imgData?.sourceDataJson?.address">-</span>
  52. <span class="app-location">
  53. {{ imgData?.sourceDataJson?.address }}
  54. </span> -->
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. <div class="carousel-img-mask app-mask" v-else-if="!isAchievementImgs && imgType === 'dji'">
  62. <div class="mask-content app-mask-content">
  63. <div class="dji-mask-top">
  64. <span>{{ imgData?.sourceDataJson?.resFilename?.[index]?.treeCode }}</span>
  65. <span>蓬径:{{ imgData?.sourceDataJson?.resFilename?.[index]?.pengjing }}m</span>
  66. <span>高度:{{ imgData?.sourceDataJson?.resFilename?.[index]?.height.toFixed(1) }}m</span>
  67. <span>{{ imgData?.sourceDataJson?.resFilename?.[index]?.highYield === 1 ? '高产树' : '低产树' }}</span>
  68. <span>{{ imgData?.sourceDataJson?.resFilename?.[index]?.pingzhong }}</span>
  69. </div>
  70. <div class="app-mask-bottom">
  71. <div class="app-weather-info">
  72. <div class="app-weather-item">
  73. <img class="app-weather-icon" src="@/assets/watermark/temp.png" alt="" />
  74. <span
  75. >{{ imgData?.sourceDataJson?.suitability?.tempMin }}-{{
  76. imgData?.sourceDataJson?.suitability?.tempMax
  77. }}℃ {{ imgData?.sourceDataJson?.suitability?.tempSuitability }}</span
  78. >
  79. </div>
  80. <div class="app-weather-item">
  81. <img class="app-weather-icon" src="@/assets/watermark/shidu.png" alt="" />
  82. <span>{{ imgData?.sourceDataJson?.suitability?.humiditySuitability }}</span>
  83. </div>
  84. <div class="app-weather-item">
  85. <img class="app-weather-icon" src="@/assets/watermark/fushe.png" alt="" />
  86. <span>{{ imgData?.sourceDataJson?.suitability?.vindexSuitability }}</span>
  87. </div>
  88. </div>
  89. </div>
  90. <div class="garden-info">
  91. <span class="drone-date">{{ imgData?.droneDate }}</span>
  92. <span class="code van-ellipsis">{{ imgData?.sourceDataJson?.resFilename?.[index]?.longCode }}</span>
  93. </div>
  94. <div class="base-map-wrapper" v-if="imgData?.sourceDataJson?.resFilename?.[index]?.baseMap">
  95. <img
  96. class="base-map-img"
  97. :src="imgData?.sourceDataJson?.resFilename?.[index]?.baseMap"
  98. alt=""
  99. />
  100. </div>
  101. </div>
  102. </div>
  103. <template v-else>
  104. <div class="carousel-img-mask" v-if="!isAchievementImgs">
  105. <div class="mask-content">
  106. <div class="mask-line line-top">
  107. <span class="date-text">{{ imgData?.executeDate }}</span>
  108. <span class="line-separator">|</span>
  109. <span class="executor-text">执行人:{{ imgData?.executeName }}</span>
  110. </div>
  111. <div class="mask-line line-middle">
  112. <span class="work-name">{{ imgData?.farmWorkName }}</span>
  113. <span class="line-separator">|</span>
  114. <span class="location-text">
  115. <img src="@/assets/watermark/address.png" alt="location" class="location-icon" />
  116. {{ imgData?.farmName }}
  117. </span>
  118. </div>
  119. <div class="mask-line line-bottom">
  120. <span class="prescription-text">药物处方:{{ prescriptionText }}</span>
  121. </div>
  122. </div>
  123. </div>
  124. <div class="carousel-img-mask" v-if="isAchievementImgs && imgData?.reCheckText">
  125. <div class="mask-content">
  126. <div class="review-effect-text">{{ $t('复核成效') }}</div>
  127. <div class="review-effect-content">
  128. <span class="review-effect-content-text">{{ imgData?.reCheckText }}</span>
  129. </div>
  130. </div>
  131. </div>
  132. </template>
  133. </div>
  134. </div>
  135. <!-- 左右箭头 -->
  136. <div @click.stop="prev" v-if="currentIndex !== 0" class="arrow left-arrow">
  137. <el-icon color="#F0D09C"><ArrowLeftBold /></el-icon>
  138. </div>
  139. <div @click.stop="next" v-if="images && currentIndex !== images.length - 1" class="arrow right-arrow">
  140. <el-icon color="#F0D09C"><ArrowRightBold /></el-icon>
  141. </div>
  142. <div class="curren-img" v-if="currentPhoto">
  143. <div ref="currentImgRef" class="carousel-img" :class="{ noFit: isAchievementImgs }">
  144. <img class="img-dom" :src="currentPhoto" alt="" />
  145. <img src="@/assets/img/home/qrcode.png" alt="" class="code-icon" />
  146. <div class="carousel-img-mask" v-if="!isAchievementImgs">
  147. <div class="mask-content">
  148. <div class="mask-line line-top">
  149. <span class="date-text">{{ imgData?.executeDate }}</span>
  150. <span class="line-separator">|</span>
  151. <span class="executor-text">执行人:{{ imgData?.executeName }}</span>
  152. </div>
  153. <div class="mask-line line-middle">
  154. <span class="work-name">{{ imgData?.farmWorkName }}</span>
  155. <span class="line-separator">|</span>
  156. <span class="location-text">
  157. <img src="@/assets/watermark/address.png" alt="location" class="location-icon" />
  158. {{ imgData?.farmName }}
  159. </span>
  160. </div>
  161. <div class="mask-line line-bottom">
  162. <span class="prescription-text">药物处方:{{ prescriptionText }}</span>
  163. </div>
  164. </div>
  165. </div>
  166. <div class="carousel-img-mask" v-if="isAchievementImgs && imgData?.reCheckText">
  167. <div class="mask-content">
  168. <div class="review-effect-text">{{ $t('复核成效') }}</div>
  169. <div class="review-effect-content">
  170. <span class="review-effect-content-text">{{ imgData?.reCheckText }}</span>
  171. </div>
  172. </div>
  173. </div>
  174. </div>
  175. </div>
  176. <popup class="cavans-popup" v-model:show="showPopup" teleport="body" z-index="9999">
  177. <div class="cavans-content">
  178. <img class="current-img" :src="previewCanvas" alt="" />
  179. </div>
  180. <!-- 底部操作按钮 -->
  181. <div class="bottom-actions" @click.stop="showPopup = false">
  182. <div class="action-buttons">
  183. <div class="action-btn text-btn">{{ $t('&lt;&lt;长按图片保存或转发&gt;&gt;') }}</div>
  184. <!-- <div class="action-btn green-btn" @click.stop="handleWechat">
  185. <div class="icon-circle">
  186. <img src="@/assets/img/home/wechat.png" alt="" />
  187. </div>
  188. <span class="btn-label">{{ $t('微信') }}</span>
  189. </div>
  190. <div class="action-btn orange-btn" @click.stop="handleSaveImage">
  191. <div class="icon-circle">
  192. <el-icon :size="24"><Download /></el-icon>
  193. </div>
  194. <span class="btn-label">{{ $t('保存图片') }}</span>
  195. </div> -->
  196. </div>
  197. <div class="cancel-btn" @click="handleCancel">{{ $t('取消') }}</div>
  198. </div>
  199. </popup>
  200. </div>
  201. </template>
  202. <script setup>
  203. import { Popup } from "vant";
  204. import { toRefs, ref, computed, onMounted, onUnmounted, nextTick, watch } from "vue";
  205. import AlbumDrawBox from "./albumDrawBox.vue";
  206. import html2canvas from "html2canvas";
  207. import { base_img_url2 } from "@/api/config";
  208. import "./cacheImg.js";
  209. const props = defineProps({
  210. images: {
  211. type: Array,
  212. required: true,
  213. },
  214. labelText: {
  215. type: String,
  216. default: "",
  217. },
  218. isAchievementImgs: {
  219. type: Boolean,
  220. default: false,
  221. },
  222. imgData: {
  223. type: Object,
  224. default: () => {},
  225. },
  226. imgType: {
  227. type: String,
  228. default: "",
  229. },
  230. disableClick: {
  231. type: Boolean,
  232. default: false,
  233. },
  234. });
  235. const { images, labelText, isAchievementImgs, imgType, disableClick } = toRefs(props);
  236. let timer = null;
  237. const currentIndex = ref(0);
  238. onMounted(() => {
  239. updateImagePosition();
  240. clearAndRestartTimer();
  241. prescriptionText.value = buildPrescriptionText(props.imgData.prescriptionList);
  242. });
  243. onUnmounted(() => {
  244. clearInterval(timer);
  245. });
  246. watch(
  247. () => props.imgData,
  248. (newVal) => {
  249. if (newVal && newVal.prescriptionList) {
  250. prescriptionText.value = buildPrescriptionText(newVal.prescriptionList);
  251. }
  252. }
  253. );
  254. const prescriptionText = ref("");
  255. function buildPrescriptionText(list) {
  256. if (!list || !Array.isArray(list) || list.length === 0) {
  257. return "无处方";
  258. }
  259. try {
  260. // 兼容原有格式:嵌套结构 [{ pesticideFertilizerList: [...] }]
  261. if (list[0]?.pesticideFertilizerList) {
  262. const result = list
  263. .map((group) =>
  264. (group.pesticideFertilizerList || [])
  265. .map((p) => p.defaultName || p.pesticideFertilizerName || "")
  266. .filter(Boolean)
  267. .join("+")
  268. )
  269. .filter(Boolean)
  270. .join("+");
  271. return result || "无处方";
  272. }
  273. // 兼容新格式:直接是字符串数组 ["药物1", "药物2"]
  274. if (typeof list[0] === "string") {
  275. return list.filter(Boolean).join("+") || "无处方";
  276. }
  277. // 兼容新格式:对象数组 [{ defaultName: "xxx" }, { defaultName: "yyy" }]
  278. if (list[0]?.defaultName || list[0]?.pesticideFertilizerName) {
  279. return list
  280. .map((p) => p.defaultName || p.pesticideFertilizerName || "")
  281. .filter(Boolean)
  282. .join("+") || "无处方";
  283. }
  284. return "无处方";
  285. } catch {
  286. return "无处方";
  287. }
  288. }
  289. const updateImagePosition = () => {
  290. carouselStyle.value.transform = `translateX(-${currentIndex.value * 100}%)`;
  291. };
  292. const clickPhotoShow = () => {
  293. if (timer) {
  294. clearInterval(timer);
  295. }
  296. };
  297. // 图片显隐切换回调
  298. const handleVisibleChange = ({ visible }) => {
  299. if (visible.value) {
  300. if (timer) {
  301. clearInterval(timer);
  302. }
  303. } else {
  304. clearAndRestartTimer();
  305. }
  306. };
  307. // 计算轮播图样式
  308. const carouselStyle = computed(() => {
  309. return {
  310. transform: `translateX(-${currentIndex.value * 100}%)`,
  311. };
  312. });
  313. // 下一张图片
  314. const next = () => {
  315. // 图片总数
  316. const totalImages = images.value.length;
  317. currentIndex.value = (currentIndex.value + 1) % totalImages;
  318. updateImagePosition();
  319. clearAndRestartTimer();
  320. };
  321. // 上一张图片
  322. const prev = () => {
  323. // 图片总数
  324. const totalImages = images.value.length;
  325. currentIndex.value = (currentIndex.value - 1 + totalImages) % totalImages;
  326. updateImagePosition();
  327. clearAndRestartTimer();
  328. };
  329. const clearAndRestartTimer = () => {
  330. if (timer) {
  331. clearInterval(timer);
  332. }
  333. // timer = setInterval(next, 5000);
  334. };
  335. const showPopup = ref(false);
  336. const currentPhoto = ref(null);
  337. const previewCanvas = ref(null);
  338. const currentImgRef = ref(null);
  339. const clickPhoto = (photo) => {
  340. if (disableClick.value) {
  341. return;
  342. }
  343. currentPhoto.value = getPhotoSrc(photo);
  344. nextTick(async () => {
  345. const canvas = await html2canvas(currentImgRef.value, {
  346. backgroundColor: "#ffffff00",
  347. scrollY: -window.scrollY, // 处理滚动条位置
  348. allowTaint: true, // 允许跨域图片
  349. useCORS: true, // 使用CORS
  350. scale: 2, // 提高分辨率(2倍)
  351. height: currentImgRef.value.scrollHeight, // 设置完整高度
  352. width: currentImgRef.value.scrollWidth, // 设置完整宽度
  353. logging: true, // 开启日志(调试用)
  354. });
  355. // 转换为图片并下载
  356. const image = canvas.toDataURL("image/png");
  357. setTimeout(() => {
  358. previewCanvas.value = image;
  359. showPopup.value = true;
  360. }, 100);
  361. });
  362. };
  363. const handleSaveImage = () => {
  364. downloadImage(previewCanvas.value, "执行照片");
  365. };
  366. function downloadImage(dataUrl, filename) {
  367. const link = document.createElement("a");
  368. link.href = dataUrl;
  369. link.download = filename;
  370. document.body.appendChild(link);
  371. link.click();
  372. document.body.removeChild(link);
  373. }
  374. const getPhotoSrc = (photo) => {
  375. // if (isAchievementImgs.value) {
  376. // return photo;
  377. // }
  378. return base_img_url2 + (photo.cloudFilename ? photo.cloudFilename : photo);
  379. };
  380. // 格式化年份
  381. const formatYear = (dateStr) => {
  382. if (!dateStr) return "";
  383. const date = new Date(dateStr);
  384. if (Number.isNaN(date.getTime())) return "";
  385. return date.getFullYear().toString();
  386. };
  387. // 格式化月/日
  388. const formatMonthDay = (dateStr) => {
  389. if (!dateStr) return "";
  390. const date = new Date(dateStr);
  391. if (Number.isNaN(date.getTime())) return "";
  392. const m = date.getMonth() + 1;
  393. const d = date.getDate();
  394. return `${m}/${d}`;
  395. };
  396. </script>
  397. <style lang="scss" scoped>
  398. @import "src/styles/index";
  399. .carousel-container {
  400. position: relative;
  401. width: 100%;
  402. overflow: hidden;
  403. margin: 0 auto;
  404. .curren-img {
  405. position: fixed;
  406. bottom: 0;
  407. left: 0;
  408. right: 0;
  409. width: 80%;
  410. height: 100%;
  411. margin: 0 auto;
  412. z-index: -1;
  413. pointer-events: none;
  414. .carousel-img {
  415. width: 100%;
  416. position: relative;
  417. overflow: hidden;
  418. }
  419. .img-dom {
  420. width: 100%;
  421. height: 100%;
  422. object-fit: cover;
  423. border-radius: 8px;
  424. }
  425. }
  426. .carousel-wrapper {
  427. display: flex;
  428. transition: transform 0.5s ease;
  429. width: 100%;
  430. .carousel-img {
  431. width: calc(100vw - 48px);
  432. min-width: calc(100vw - 48px);
  433. // min-width: 312px;
  434. // height: 255px;
  435. max-height: 90vh;
  436. object-fit: cover;
  437. position: relative;
  438. overflow: hidden;
  439. &.noFit {
  440. height: auto;
  441. object-fit: contain;
  442. }
  443. .img-dom {
  444. width: 100%;
  445. height: 100%;
  446. object-fit: cover;
  447. border-radius: 8px;
  448. }
  449. &.noFit {
  450. .img-dom {
  451. height: auto;
  452. object-fit: contain;
  453. }
  454. }
  455. }
  456. }
  457. .code-icon {
  458. position: absolute;
  459. right: 12px;
  460. top: 12px;
  461. width: 40px;
  462. }
  463. .carousel-img-mask {
  464. position: absolute;
  465. bottom: -2px;
  466. left: -2px;
  467. width: calc(100% + 2px);
  468. height: 80%;
  469. background: linear-gradient(360deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.4) 25%, rgba(0, 0, 0, 0) 40%);
  470. z-index: 1;
  471. pointer-events: none;
  472. display: flex;
  473. align-items: flex-end;
  474. padding: 8px 12px;
  475. box-sizing: border-box;
  476. border-radius: 8px 8px 12px 12px;
  477. &.app-mask {
  478. padding: 0;
  479. height: 100%;
  480. }
  481. .mask-content {
  482. width: 100%;
  483. color: #ffffff;
  484. font-size: 10px;
  485. line-height: 15px;
  486. &.app-mask-content {
  487. padding: 10px 8px;
  488. font-size: 12px;
  489. background: rgba(0, 0, 0, 0.2);
  490. backdrop-filter: blur(4px);
  491. .dji-mask-top {
  492. background: rgba(0, 0, 0, 0.4);
  493. backdrop-filter: blur(4px);
  494. border-radius: 5px 0 5px 0;
  495. padding: 6px 11px;
  496. position: absolute;
  497. top: -203px;
  498. left: 0;
  499. display: flex;
  500. gap: 9px;
  501. font-size: 10px;
  502. }
  503. .garden-info {
  504. display: flex;
  505. align-items: center;
  506. margin-top: 4px;
  507. width: calc(100% - 125px);
  508. .code {
  509. font-size: 10px;
  510. opacity: 0.5;
  511. margin-left: 5px;
  512. width: 100%;
  513. display: inline-block;
  514. }
  515. }
  516. .base-map-wrapper {
  517. position: absolute;
  518. bottom: 4px;
  519. right: 0;
  520. width: 125px;
  521. height: 94px;
  522. z-index: 1;
  523. .base-map-img {
  524. width: 100%;
  525. height: 100%;
  526. border-radius: 4px;
  527. border: 1px solid #ffffff;
  528. object-fit: cover;
  529. box-sizing: border-box;
  530. }
  531. }
  532. .app-mask-top {
  533. display: flex;
  534. align-items: center;
  535. gap: 12px;
  536. .app-mask-top-left {
  537. display: flex;
  538. flex-direction: column;
  539. align-items: flex-start;
  540. .app-year {
  541. font-size: 12px;
  542. color: #ffffff;
  543. margin-bottom: 4px;
  544. }
  545. .app-date-wrapper {
  546. position: relative;
  547. .app-date-line {
  548. position: absolute;
  549. top: -2px;
  550. left: 0;
  551. right: 0;
  552. height: 1px;
  553. background: #ffffff;
  554. }
  555. .app-date {
  556. font-size: 12px;
  557. color: #ffffff;
  558. position: relative;
  559. }
  560. }
  561. }
  562. .app-mask-top-right {
  563. display: flex;
  564. align-items: center;
  565. gap: 12px;
  566. .app-phenology {
  567. color: #f0d09c;
  568. font-weight: 500;
  569. }
  570. .app-uploader {
  571. font-size: 10px;
  572. color: #ffffff;
  573. opacity: 0.5;
  574. }
  575. }
  576. }
  577. .app-mask-bottom {
  578. display: flex;
  579. align-items: center;
  580. .app-weather-info {
  581. display: flex;
  582. align-items: center;
  583. flex-wrap: wrap;
  584. gap: 5px;
  585. .app-weather-item {
  586. color: #ffffff;
  587. display: flex;
  588. align-items: center;
  589. gap: 2px;
  590. .app-weather-icon {
  591. width: 15px;
  592. height: 15px;
  593. }
  594. }
  595. .app-weather-separator {
  596. font-size: 10px;
  597. color: #ffffff;
  598. margin: 0 4px;
  599. }
  600. .app-location {
  601. font-size: 10px;
  602. color: #ffffff;
  603. opacity: 0.5;
  604. }
  605. }
  606. }
  607. }
  608. }
  609. .review-effect-text {
  610. font-family: "PangMenZhengDao";
  611. font-size: 16px;
  612. margin-bottom: 4px;
  613. }
  614. .review-effect-content {
  615. font-size: 10px;
  616. line-height: 15px;
  617. }
  618. .mask-line {
  619. display: flex;
  620. align-items: center;
  621. flex-wrap: wrap;
  622. }
  623. .prescription-text {
  624. display: flex;
  625. .prescription-text-label {
  626. flex: none;
  627. }
  628. }
  629. .line-middle {
  630. margin-top: 4px;
  631. .work-name {
  632. font-family: "PangMenZhengDao", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial,
  633. sans-serif;
  634. font-size: 17px;
  635. }
  636. }
  637. .line-bottom {
  638. margin-top: 4px;
  639. }
  640. .date-text {
  641. font-family: "PangMenZhengDao";
  642. font-size: 12px;
  643. }
  644. .date-text,
  645. .executor-text,
  646. .location-text {
  647. white-space: nowrap;
  648. }
  649. .location-icon {
  650. width: 9px;
  651. height: 10px;
  652. margin-right: 2px;
  653. }
  654. .line-separator {
  655. margin: 0 6px;
  656. }
  657. }
  658. .label-text {
  659. position: absolute;
  660. top: 0;
  661. left: 0;
  662. padding: 4px 10px;
  663. background: rgba(54, 52, 52, 0.8);
  664. color: #fff;
  665. font-size: 12px;
  666. border-radius: 8px 0 8px 0;
  667. z-index: 1;
  668. }
  669. .blur-bg {
  670. position: absolute;
  671. top: 0;
  672. width: 100%;
  673. height: 100%;
  674. backdrop-filter: blur(1.4px);
  675. .blur-content {
  676. border-radius: 8px;
  677. background: rgba(0, 0, 0, 0.5);
  678. width: 100%;
  679. height: 100%;
  680. display: flex;
  681. flex-direction: column;
  682. align-items: center;
  683. justify-content: center;
  684. font-size: 12px;
  685. color: #fff;
  686. .blur-img {
  687. img {
  688. width: 54px;
  689. position: relative;
  690. left: 4px;
  691. top: 4px;
  692. }
  693. }
  694. .blur-text {
  695. padding: 8px 0;
  696. text-align: center;
  697. line-height: 1.5;
  698. }
  699. .blur-btn {
  700. padding: 0 40px;
  701. box-shadow: 0 -2px 2px #86c9ff;
  702. height: 28px;
  703. line-height: 28px;
  704. border-radius: 50px;
  705. background: rgba(33, 153, 248, 0.7);
  706. // background: linear-gradient(#86C9FF, rgba(255, 255, 255, 0));
  707. }
  708. }
  709. }
  710. .arrow {
  711. position: absolute;
  712. top: 50%;
  713. transform: translateY(-50%);
  714. background: rgba(0, 0, 0, 0.5);
  715. width: rpx(72);
  716. height: rpx(72);
  717. border-radius: 50%;
  718. display: inline-flex;
  719. align-items: center;
  720. justify-content: center;
  721. cursor: pointer;
  722. pointer-events: all;
  723. }
  724. .left-arrow {
  725. left: rpx(32);
  726. }
  727. .right-arrow {
  728. right: rpx(32);
  729. }
  730. }
  731. .cavans-popup {
  732. width: 100%;
  733. max-width: 100%;
  734. max-height: 90vh;
  735. background: none;
  736. border-radius: 12px;
  737. overflow: auto;
  738. display: flex;
  739. flex-direction: column;
  740. backdrop-filter: 4px;
  741. .cavans-content {
  742. text-align: center;
  743. padding: 16px;
  744. .current-img {
  745. width: 100%;
  746. }
  747. }
  748. // 底部操作按钮
  749. .bottom-actions {
  750. flex-shrink: 0;
  751. .action-buttons {
  752. padding: 16px;
  753. display: flex;
  754. justify-content: space-around;
  755. .action-btn {
  756. display: flex;
  757. flex-direction: column;
  758. align-items: center;
  759. cursor: pointer;
  760. &.text-btn {
  761. font-size: 12px;
  762. color: rgba(255, 255, 255, 0.7);
  763. }
  764. .icon-circle {
  765. width: 48px;
  766. height: 48px;
  767. border-radius: 50%;
  768. display: flex;
  769. align-items: center;
  770. justify-content: center;
  771. color: #fff;
  772. margin-bottom: 4px;
  773. .el-icon {
  774. color: #fff;
  775. }
  776. img {
  777. width: 50px;
  778. }
  779. }
  780. &.blue-btn .icon-circle {
  781. background: #2199f8;
  782. }
  783. &.green-btn .icon-circle {
  784. background: #07c160;
  785. }
  786. &.orange-btn .icon-circle {
  787. background: #ff790b;
  788. }
  789. .btn-label {
  790. font-size: 12px;
  791. color: #fff;
  792. }
  793. }
  794. }
  795. .cancel-btn {
  796. text-align: center;
  797. font-size: 18px;
  798. color: #fff;
  799. cursor: pointer;
  800. }
  801. }
  802. }
  803. </style>