Detail.vue 22 KB

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