Detail.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. <script setup>
  2. import apiReport from '@/api/modules/report'
  3. import { useRoute } from 'vue-router'
  4. import { Message, Toast } from 'tdesign-mobile-vue';
  5. import apiUser from '@/api/modules/user'
  6. import { useThrottleFn } from '@vueuse/core'
  7. const route = useRoute()
  8. // 获取用户信息
  9. let userInfo = null
  10. async function getUserInfo() {
  11. const res = await apiUser.userInfo()
  12. if (res.Ret === 200 && res.ErrCode === 0) {
  13. userInfo = res.data
  14. }
  15. }
  16. getUserInfo()
  17. const defaultImg = new URL(`@/assets/imgs/default-author.png`, import.meta.url).href
  18. const reportId = route.query.reportid
  19. const reportInfo = ref(null)
  20. const reportContent = ref('')
  21. const isFollowed = ref(false)
  22. const authorInfoList=ref([])
  23. const isLogin=ref(true)
  24. const productId = route.query.productId
  25. const isSubscribe=ref(true)
  26. const isFree=ref(true)
  27. const priceNum=ref('')
  28. const visible = ref(false);
  29. const subscribeStatus = ref('')//expired --过期 unSubscribe--未订阅 subscribed--订阅中
  30. const riskLevelStatus=ref('')//expired过期的 unTest未测评 unMatch风险等级不匹配
  31. const headImgStyle = ref([])
  32. const endImgStyle = ref([])
  33. const layoutBaseInfo = ref({
  34. '研报标题': '',
  35. '研报作者': '',
  36. '创建时间': ''
  37. })
  38. // 报告内容分页
  39. const pageSize = 20
  40. let page = 0
  41. let endPageNum = 0
  42. let contentTotals = []
  43. const renderContentList = ref([])
  44. function splitReportContent(data) {
  45. const arr = data.split('</p>');
  46. contentTotals = arr.map(_ => _ + '</p>')
  47. renderContentList.value = contentTotals.slice(0, pageSize)
  48. endPageNum = parseInt(contentTotals.length / pageSize) + 1;
  49. }
  50. function handleLoadContent() {
  51. renderContentList.value = renderContentList.value.concat(contentTotals.slice(page * pageSize, (page + 1) * pageSize))
  52. }
  53. async function getReportInfo() {
  54. //获取研报详情
  55. if (!reportId || !productId) return
  56. const res = await apiReport.getReportDetail({
  57. reportId: reportId,
  58. productId: productId
  59. })
  60. if (res.Ret === 200 && res.ErrCode === 0) {
  61. const { detail, authorInfo, price } = res.data
  62. authorInfoList.value=authorInfo
  63. reportInfo.value = detail
  64. isLogin.value=res.data.login
  65. riskLevelStatus.value=res.data.riskLevelStatus
  66. headImgStyle.value = reportInfo.value.headResource.style ? JSON.parse(reportInfo.value.headResource.style) : []
  67. endImgStyle.value = reportInfo.value.endResource.style ? JSON.parse(reportInfo.value.endResource.style) : []
  68. layoutBaseInfo.value['研报标题'] = reportInfo.value.title
  69. layoutBaseInfo.value['研报作者'] = reportInfo.value.author
  70. layoutBaseInfo.value['创建时间'] = reportInfo.value.publishTime
  71. isSubscribe.value=res.data.isSubscribe
  72. isFree.value=res.data.isFree
  73. priceNum.value=price
  74. subscribeStatus.value=res.data.subscribeStatus
  75. getAuthorFollowState()
  76. nextTick(() => {
  77. handlePreviewImgs()
  78. })
  79. // 设置分享文案
  80. wx.miniProgram.postMessage({
  81. data: {
  82. title: reportInfo.value.title
  83. }
  84. });
  85. reportContent.value = reportInfo.value.content
  86. splitReportContent(reportContent.value)
  87. }
  88. }
  89. getReportInfo()
  90. function getAuthorFollowState() {
  91. apiUser.getFollowState({
  92. names: reportInfo.value.author
  93. }).then(res => {
  94. if (res.Ret === 200 && res.ErrCode === 0) {
  95. isFollowed.value = res.data.followStatus === 'following'
  96. }
  97. })
  98. }
  99. function changeFollowState() {
  100. if (authorInfoList.value.length > 1) {
  101. visible.value = true
  102. } else {
  103. apiUser.followAuthor({
  104. analystNames: reportInfo.value.author,
  105. followType: isFollowed.value ? 'unfollowed' : 'following',
  106. mobile: userInfo?.mobile || ''
  107. }).then(res => {
  108. if (res.Ret === 200 && res.ErrCode === 0) {
  109. isFollowed.value = !isFollowed.value
  110. Toast({
  111. theme: 'success',
  112. direction: 'row',
  113. message: isFollowed.value ? '关注成功' : '取消关注成功',
  114. })
  115. }
  116. })
  117. }
  118. }
  119. function onClose() {
  120. visible.value = false
  121. }
  122. // 关注列表
  123. function changeFollowStateList(item) {
  124. console.log(item);
  125. apiUser.followAuthor({
  126. analystNames: item.name,
  127. followType: item.following === 'unfollowed' ? 'following' : 'unfollowed',
  128. mobile: userInfo?.mobile || ''
  129. }).then(res => {
  130. if (res.Ret === 200 && res.ErrCode === 0) {
  131. item.following = item.following === 'unfollowed' ? 'following' : 'unfollowed'
  132. getAuthorFollowState()
  133. Toast({
  134. theme: 'success',
  135. direction: 'row',
  136. message: item.following === 'unfollowed' ? '取消关注成功' : '关注成功',
  137. })
  138. }
  139. })
  140. }
  141. // 显示免责声明
  142. const isShowMZSM = ref(false)
  143. // 显示返回顶部
  144. const showToTop = ref(false)
  145. const handlePageScroll = useThrottleFn(() => {
  146. const top = document.documentElement.scrollTop || document.body.scrollTop
  147. if (top > window.outerHeight) {
  148. showToTop.value = true
  149. } else {
  150. showToTop.value = false
  151. }
  152. if (page >= endPageNum) return
  153. const clientHeight = document.documentElement.clientHeight || document.body.clientHeight; // 可视高度
  154. const scrollHeight = document.body.scrollHeight; // 总高度
  155. const bufferHeight = 400;
  156. if ((scrollHeight - top - clientHeight) < bufferHeight + 100) {
  157. console.log('触底')
  158. page++
  159. handleLoadContent();
  160. }
  161. }, 300)
  162. function handleBackTop() {
  163. document.body.scrollTop = document.documentElement.scrollTop = 0
  164. }
  165. // 点击报告内容中的图片
  166. function handlePreviewImgs() {
  167. document.getElementById('rich-content').addEventListener('click', function (event) {
  168. let imgArray = [];
  169. let curImageSrc = event.target.src;
  170. let oParent = event.target.parentNode;
  171. if (curImageSrc && !oParent.hasAttribute('href')) {
  172. let imgs = document.querySelectorAll('.rich-content img');
  173. for (let i = 0; i < imgs.length; i++) {
  174. let itemSrc = imgs[i].src;
  175. imgArray.push(itemSrc);
  176. }
  177. wx.previewImage({ current: curImageSrc, urls: imgArray });
  178. }
  179. });
  180. }
  181. onMounted(() => {
  182. window.addEventListener('scroll', handlePageScroll)
  183. })
  184. onUnmounted(() => {
  185. window.removeEventListener('scroll', handlePageScroll)
  186. })
  187. function handleGoLogin() {
  188. const redirectUrl = encodeURIComponent(`/pages-report/reportDetail/index?id=${route.query.reportid}`)
  189. wx.miniProgram.reLaunch({
  190. url: `/pages/login/index?redirectUrl=${redirectUrl}`
  191. })
  192. }
  193. //跳转风险测评
  194. function handleGoTestRisk(){
  195. wx.miniProgram.reLaunch({
  196. url: `/pages/user/riskLevelPage`
  197. })
  198. }
  199. //跳转购买
  200. function goPrimary(){
  201. wx.miniProgram.reLaunch({
  202. url: `/pages-order/payPage/index?id=${productId}`
  203. })
  204. }
  205. // 跳转研究员详情页
  206. function goDetails(item){
  207. wx.miniProgram.reLaunch({
  208. url:'/pages-user/authordetail/index?id='+item.id
  209. })
  210. }
  211. </script>
  212. <template>
  213. <div :class="!isLogin||['expired','unTest','unMatch'].includes(riskLevelStatus) || (!isSubscribe && !isFree)? 'no-auth-box report-detail-page' : 'report-detail-page'" v-if="reportInfo">
  214. <!-- 智能研报有版头版尾 -->
  215. <div class="html-head-img-box" v-if="reportInfo.headResource.imgUrl">
  216. <img
  217. :src="reportInfo.headResource.imgUrl"
  218. alt=""
  219. style="display: block; width: 100%"
  220. />
  221. <div
  222. class="head-layout-item"
  223. v-for="item in headImgStyle"
  224. :key="item.value"
  225. :style="{
  226. fontFamily: item.family,
  227. fontSize: item.size,
  228. fontWeight: item.weight,
  229. textAlign: item.align,
  230. color: item.color,
  231. width: item.width,
  232. height: item.height,
  233. left: item.left,
  234. top: item.top,
  235. }"
  236. >
  237. {{ layoutBaseInfo[item.value] }}
  238. </div>
  239. </div>
  240. <div
  241. class="time-box"
  242. style="text-align: right"
  243. v-if="reportInfo.headResource.imgUrl"
  244. >
  245. <span>如有内容疑问 请查看 &nbsp;</span>
  246. <span class="btn" @click="isShowMZSM = true">免责声明</span>
  247. </div>
  248. <template
  249. v-if="!reportInfo.headResource.imgUrl && !reportInfo.endResource.imgUrl"
  250. >
  251. <div class="title-box">{{ reportInfo.title }}</div>
  252. <div class="author-box">
  253. <div class="img-box">
  254. <img
  255. :src="authorInfoList?.[0].headImgUrl|| defaultImg"
  256. />
  257. </div>
  258. <div class="author-info">
  259. <span class="name">
  260. <template v-for="(item, index) in authorInfoList" :key="index">
  261. {{ item.name }} {{ index === authorInfoList.length - 1 ? "" : "、" }}
  262. </template>
  263. </span>
  264. <span class="time">{{ reportInfo.publishTime }}&nbsp;{{reportInfo.riskLevel}}</span>
  265. </div>
  266. <div
  267. @click="changeFollowState"
  268. :class="['opt-btn', isFollowed ? 'followed' : '']"
  269. v-if="isLogin"
  270. >
  271. {{ isFollowed ? "取消关注" : "关注" }}
  272. </div>
  273. </div>
  274. <div class="time-box">
  275. <span class="btn" @click="isShowMZSM = true">免责声明</span>
  276. </div>
  277. </template>
  278. <div class="des-box" v-if="reportInfo.abstract">
  279. <svg-icon name="icon01"></svg-icon>
  280. <div>{{ reportInfo.abstract }}</div>
  281. </div>
  282. <div
  283. id="rich-content"
  284. class="report-content-box rich-content"
  285. v-html="reportContent"
  286. v-if="false"
  287. />
  288. <template v-else>
  289. <div
  290. id="rich-content"
  291. class="report-content-box rich-content"
  292. v-if="!reportInfo.hasChapter"
  293. >
  294. <div v-for="item in renderContentList" :key="item" v-html="item"></div>
  295. </div>
  296. <!-- 章节报告 -->
  297. <div
  298. id="rich-content"
  299. class="report-content-box rich-content"
  300. v-if="reportInfo.hasChapter"
  301. >
  302. <div
  303. class="chapter-item-wrap"
  304. v-for="(chapter, index) in reportInfo.chapters"
  305. :key="index"
  306. >
  307. <div class="chapter-title">
  308. <h3 class="chapter-title-text">{{ chapter.title }}</h3>
  309. </div>
  310. <div v-html="chapter.content"></div>
  311. </div>
  312. </div>
  313. </template>
  314. <!-- 拼接版尾 -->
  315. <div class="html-end-img-box" v-if="reportInfo.endResource.imgUrl">
  316. <img
  317. :src="reportInfo.endResource.imgUrl"
  318. alt=""
  319. style="display: block; width: 100%"
  320. />
  321. <div
  322. class="head-layout-item"
  323. v-for="item in endImgStyle"
  324. :key="item.value"
  325. :style="{
  326. fontFamily: item.family,
  327. fontSize: item.size * 2 + 'px',
  328. fontWeight: item.weight,
  329. textAlign: item.align,
  330. color: item.color,
  331. width: item.width,
  332. height: item.height,
  333. left: item.left,
  334. top: item.top,
  335. }"
  336. >
  337. {{ layoutBaseInfo[item.value] }}
  338. </div>
  339. </div>
  340. <!-- 右侧悬浮操作栏 -->
  341. <div class="right-fix-box">
  342. <!-- 返回顶部 -->
  343. <div class="item back-top-img">
  344. <svg-icon
  345. name="backtop"
  346. v-show="showToTop"
  347. @click="handleBackTop"
  348. class="back-top-img"
  349. />
  350. </div>
  351. </div>
  352. </div>
  353. <!-- 无权限\未登录 -->
  354. <div class="no-auth-wrap" v-if="!isLogin||['expired','unTest','unMatch'].includes(riskLevelStatus)">
  355. <div class="opcity-box"></div>
  356. <div class="content-box">
  357. <img class="icon" src="@/assets/imgs/lock-img.png" alt="" />
  358. <template v-if="!isLogin">
  359. <div class="text">您尚未登录,请登录后查看</div>
  360. <t-button
  361. theme="primary"
  362. block
  363. style="width: 300px; margin: 30px auto"
  364. @click="handleGoLogin"
  365. >去登陆</t-button
  366. >
  367. </template>
  368. <template v-else>
  369. <div class="text" v-if="riskLevelStatus==='expired'">您的风险测评已过期,请完成风险测评</div>
  370. <div class="text" v-if="riskLevelStatus==='unTest'">您尚未进行风险测评,请完成风险测评</div>
  371. <div class="text" v-if="riskLevelStatus==='unMatch'">您的风险等级无法查看此内容<br>请查看其他内容</div>
  372. <t-button
  373. theme="primary"
  374. block
  375. style="width: 300px; margin: 30px auto"
  376. v-if="['expired','unTest'].includes(riskLevelStatus)"
  377. @click="handleGoTestRisk"
  378. >风险测评</t-button
  379. >
  380. </template>
  381. </div>
  382. </div>
  383. <div class="no-auth-wrap" v-else-if="!isSubscribe && !isFree">
  384. <div class="opcity-box"></div>
  385. <div class="content-box subscribe-box">
  386. <div class="icon-box">
  387. <img class="icon subscribe" src="@/assets/imgs/lock.png" alt="" />
  388. <div class="text" v-if="subscribeStatus==='expired'">您的权限已过期<br>若需继续查看可点击【立即订阅】</div>
  389. <div class="text" v-if="subscribeStatus==='unSubscribe'">您暂无阅读权限<br>若感兴趣请点击【立即订阅】</div>
  390. </div>
  391. <div class="pay-btn">
  392. <div class="pay-btn-confirm">
  393. <div class="pay-btn-money">
  394. <span>合计</span>
  395. <span class="pay">¥{{ priceNum }}</span>
  396. </div>
  397. <t-button
  398. class="btn"
  399. theme="primary"
  400. shape="round"
  401. block
  402. @click="goPrimary"
  403. >立即订阅</t-button>
  404. </div>
  405. </div>
  406. </div>
  407. </div>
  408. <!-- 免责声明 -->
  409. <disclaimers-wrap v-model:show="isShowMZSM" />
  410. <!-- 关注弹窗 -->
  411. <t-popup v-model="visible" placement="center" style="width: 350px">
  412. <t-icon class="close-btn" name="close-circle" size="32" color="#fff" @click="onClose" />
  413. <div class="author-popup">
  414. <div class="title">作者详情</div>
  415. <div class="authorList-box" v-for="(item, index) in authorInfoList" :key="index">
  416. <div class="img-list-box" @click="goDetails(item)">
  417. <img
  418. :src="authorInfoList?.[0].headImgUrl|| defaultImg"
  419. />
  420. </div>
  421. <div class="name-list-box" @click="goDetails(item)">
  422. {{ item.name }}
  423. </div>
  424. <div
  425. @click="changeFollowStateList(item)"
  426. :class="['opt-btn', item.following === 'following' ? 'following' : '']"
  427. v-if="isLogin"
  428. >
  429. {{ item.following === 'following' ? "取消关注" : "关注" }}
  430. </div>
  431. </div>
  432. </div>
  433. </t-popup>
  434. </template>
  435. <style lang="scss" scoped>
  436. .report-detail-page {
  437. background-color: #fff;
  438. padding: var(--page-padding);
  439. .title-box {
  440. font-size: 36px;
  441. line-height: 44px;
  442. margin-bottom: 20px;
  443. }
  444. .author-box {
  445. display: flex;
  446. align-items: center;
  447. .img-box {
  448. width: 78px;
  449. height: 78px;
  450. border-radius: 50%;
  451. overflow: hidden;
  452. img {
  453. width: 100%;
  454. height: 100%;
  455. }
  456. }
  457. .author-info {
  458. margin-left: 30px;
  459. flex: 1;
  460. .name {
  461. /* display: block; */
  462. display: -webkit-box;
  463. overflow: hidden;
  464. text-overflow: ellipsis;
  465. -webkit-line-clamp: 2;
  466. line-break: anywhere;
  467. -webkit-box-orient: vertical;
  468. }
  469. .time {
  470. display: block;
  471. margin-top: 10px;
  472. font-size: var(--font-size-small);
  473. color: var(--text-color-grey);
  474. }
  475. }
  476. .opt-btn {
  477. margin-left: auto;
  478. align-self: flex-start;
  479. min-width: 140px;
  480. height: 40px;
  481. padding: 5px 10px;
  482. border-radius: 8px;
  483. background-color: var(--primary-color);
  484. color: var(--text-color-inverse);
  485. text-align: center;
  486. &.followed {
  487. background-color: var(--bg-disabled-color);
  488. color: var(--text-color-grey);
  489. }
  490. }
  491. }
  492. .time-box {
  493. font-size: var(--font-size-small);
  494. text-align: right;
  495. .btn {
  496. color: var(--primary-color);
  497. position: relative;
  498. top: -34px;
  499. }
  500. }
  501. .des-box {
  502. background-color: #f8f8f8;
  503. padding: 20px;
  504. margin: 20px 0;
  505. display: flex;
  506. gap: 0 10px;
  507. color: var(--text-color-sub);
  508. font-size: var(--font-size-small);
  509. line-height: 36px;
  510. }
  511. .report-content-box {
  512. margin-top: 20px;
  513. line-height: 1.8;
  514. font-size: 36px;
  515. :deep(img) {
  516. width: 100% !important;
  517. }
  518. :deep(span) {
  519. font-size: 36px !important;
  520. line-height: 1.8 !important;
  521. background-color: rgba(255, 255, 255, 0) !important;
  522. }
  523. :deep(p) {
  524. font-size: 36px !important;
  525. line-height: 1.8 !important;
  526. background-color: rgba(255, 255, 255, 0) !important;
  527. }
  528. :deep(ul) {
  529. font-size: 36px !important;
  530. line-height: 1.8 !important;
  531. background-color: rgba(255, 255, 255, 0) !important;
  532. }
  533. :deep(ol) {
  534. font-size: 36px !important;
  535. line-height: 1.8 !important;
  536. background-color: rgba(255, 255, 255, 0) !important;
  537. }
  538. :deep(iframe) {
  539. width: 100% !important;
  540. }
  541. :deep(li) {
  542. font-size: 36px !important;
  543. line-height: 1.8 !important;
  544. background-color: rgba(255, 255, 255, 0) !important;
  545. list-style: inherit !important;
  546. list-style-position: inside !important;
  547. }
  548. :deep(span.fr-emoticon) {
  549. width: 36px !important;
  550. height: 36px !important;
  551. background-repeat: no-repeat !important;
  552. background-size: cover !important;
  553. display: inline-block !important;
  554. vertical-align: middle !important;
  555. }
  556. .chapter-item-wrap {
  557. padding: 20px 0;
  558. .chapter-title {
  559. display: flex;
  560. align-items: center;
  561. font-size: 30px;
  562. .type {
  563. height: fit-content;
  564. display: inline-block;
  565. color: #fff;
  566. padding: 10px 20px;
  567. background-color: #e6a23c;
  568. border-radius: 8px;
  569. margin-right: 20px;
  570. }
  571. .chapter-title-text {
  572. font-size: 30px;
  573. }
  574. }
  575. }
  576. }
  577. .right-fix-box {
  578. position: fixed;
  579. z-index: 99;
  580. right: 34px;
  581. bottom: 130px;
  582. //加上这个保证back-top-img不会重复渲染
  583. transform: translateZ(0); //不知道什么原理
  584. .item {
  585. margin-top: 10px;
  586. }
  587. .back-top-img {
  588. width: 100px;
  589. height: 100px;
  590. display: block;
  591. }
  592. }
  593. .html-head-img-box,
  594. .html-end-img-box {
  595. margin-bottom: 10px;
  596. position: relative;
  597. overflow: hidden;
  598. .head-layout-item {
  599. position: absolute;
  600. overflow: hidden;
  601. box-sizing: border-box;
  602. }
  603. }
  604. }
  605. .no-auth-box {
  606. height: 100vh;
  607. overflow: hidden;
  608. }
  609. .no-auth-wrap {
  610. position: fixed;
  611. left: 0;
  612. right: 0;
  613. bottom: 0;
  614. z-index: 99;
  615. .opcity-box {
  616. height: 129px;
  617. background: linear-gradient(
  618. 360deg,
  619. #ffffff 0%,
  620. rgba(255, 255, 255, 0) 100%
  621. );
  622. }
  623. .content-box {
  624. background-color: #fff;
  625. padding-bottom: 240px;
  626. text-align: center;
  627. color: var(--primary-color);
  628. }
  629. .subscribe-box {
  630. padding-bottom: 0;
  631. }
  632. .icon {
  633. display: block;
  634. margin: 0 auto;
  635. width: 100%;
  636. }
  637. .subscribe {
  638. width: 200px;
  639. height: 200px;
  640. margin-bottom: 30px;
  641. }
  642. .icon-box {
  643. margin-bottom: 120px;
  644. }
  645. .pay-btn {
  646. width: 100%;
  647. margin: 0 auto;
  648. background-color: #fff;
  649. border-radius: 16px;
  650. padding: 40px;
  651. display: flex;
  652. justify-content: flex-end;
  653. align-items: center;
  654. border-top: #C0C0C0 1px solid;
  655. // position: absolute;
  656. // bottom: 0;
  657. .pay-btn-cancel {
  658. color: #0078E8;
  659. font-size: 28px;
  660. }
  661. .pay-btn-confirm{
  662. width: 100%;
  663. display: flex;
  664. justify-content: flex-end;
  665. align-items: center;
  666. .pay-btn-money {
  667. display: flex;
  668. justify-content: space-between;
  669. align-items: center;
  670. font-size: 32px;
  671. text-align: right;
  672. color: #999999;
  673. margin-right: 20px;
  674. .pay{
  675. font-size: 36px;
  676. color: #e54d42;
  677. margin-left: 10px;
  678. }
  679. }
  680. .btn {
  681. width: 40%;
  682. }
  683. }
  684. }
  685. }
  686. .close-btn {
  687. position: absolute;
  688. left: 100%;
  689. margin-left: -16px;
  690. top: calc(-1 * (24px + 32px));
  691. }
  692. .title {
  693. padding: 30rpx;
  694. font-size: 32px;
  695. color: #323233;
  696. text-align: center;
  697. }
  698. .author-popup {
  699. padding: 30px;
  700. .authorList-box {
  701. margin: 20px 0;
  702. display: flex;
  703. justify-content: space-between;
  704. align-items: center;
  705. .img-list-box {
  706. width: 78px;
  707. height: 78px;
  708. border-radius: 50%;
  709. overflow: hidden;
  710. img {
  711. width: 100%;
  712. height: 100%;
  713. }
  714. }
  715. .name-list-box {
  716. display: -webkit-box;
  717. -webkit-box-orient: vertical;
  718. overflow: hidden;
  719. text-overflow: ellipsis;
  720. -webkit-line-clamp: 2; /* 限制为2行 */
  721. }
  722. .opt-btn {
  723. margin-left: 40%;
  724. min-width: 140px;
  725. height: 40px;
  726. padding: 5px 10px;
  727. border-radius: 8px;
  728. background-color: var(--primary-color);
  729. color: var(--text-color-inverse);
  730. text-align: center;
  731. &.following {
  732. background-color: var(--bg-disabled-color);
  733. color: var(--text-color-grey);
  734. }
  735. }
  736. }
  737. }
  738. </style>