Detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <script setup>
  2. import apiReport from '@/api/modules/report'
  3. import { useRoute } from 'vue-router'
  4. import { Message } from 'tdesign-mobile-vue';
  5. import apiCommon from '@/api/modules/common'
  6. import apiUser from '@/api/modules/user'
  7. import { useThrottleFn } from '@vueuse/core'
  8. const route = useRoute()
  9. // 获取系统配置
  10. let systemConfig = null
  11. function getSystemConfig() {
  12. apiCommon.systemConfig().then(res => {
  13. if (res.Ret === 200) {
  14. systemConfig = res.Data
  15. console.log(res.Data);
  16. }
  17. })
  18. }
  19. getSystemConfig()
  20. // 获取用户信息
  21. let userInfo = null
  22. async function getUserInfo() {
  23. const res = await apiUser.userInfo()
  24. if (res.Ret === 200) {
  25. userInfo = res.Data
  26. }
  27. }
  28. const reportId = route.query.reportid
  29. const reportInfo = ref(null)
  30. const reportContent = ref('')
  31. const reportStatus = ref(0)//1已过期,2没有该品种权限,3没有权限,4有权限,5未绑定
  32. const reportCollected = ref(false)//报告是否收藏
  33. const isBind=ref(false)
  34. async function getReportInfo() {
  35. if (!reportId) return
  36. const res = await apiReport.getReportDetail({
  37. ReportId: Number(reportId)
  38. })
  39. if (res.Ret === 200) {
  40. reportInfo.value = res.Data.Report
  41. reportStatus.value = res.Data.Status
  42. reportCollected.value = res.Data.IsCollect || false
  43. isBind.value=res.Data.IsSignIn
  44. nextTick(() => {
  45. handlePreviewImgs()
  46. })
  47. // 设置分享文案
  48. wx.miniProgram.postMessage({
  49. data: {
  50. title: res.Data.Report.Title
  51. }
  52. });
  53. await getUserInfo()
  54. if (res.Data.Status === 4) {
  55. if (userInfo.Status === 2 && userInfo.HasPermission === '私有权限') {
  56. reportInfo.value.Content=modifyReportContentIframeData(reportInfo.value.Content)
  57. formatIframeData()
  58. }else{
  59. reportContent.value = modifyReportContentIframeData(reportInfo.value.Content)
  60. splitReportContent(reportContent.value)
  61. }
  62. } else {//无权限
  63. reportContent.value = modifyReportContentIframeData(reportInfo.value.ContentSub)
  64. }
  65. }
  66. }
  67. getReportInfo()
  68. // 修改报告中嵌入的图表地址
  69. function modifyReportContentIframeData(str){
  70. let temStr=str.replace(/http:\/\/eta.dwfutures.com:8001/g,'https://dwresearch.dwfutures.com')
  71. return temStr.replace(/http:\/\/58.210.74.21:9100\/etastatic/g,'https://dwresearch.dwfutures.com/etastatic')
  72. }
  73. // 给报告详情中图表加参数
  74. function formatIframeData() {
  75. reportContent.value = reportInfo.value.Content.replace(/\/chartshow\?code=/g, `/chartshow?source=etamini&token=${localStorage.getItem('token')}&reportId=${reportId}&code=`)
  76. splitReportContent(reportContent.value)
  77. }
  78. // 报告内容分页
  79. const pageSize=20
  80. let page=0
  81. let endPageNum=0
  82. let contentTotals=[]
  83. const renderContentList=ref([])
  84. function splitReportContent(data){
  85. const arr=data.split('</p>');
  86. contentTotals=arr.map(_ => _+'</p>')
  87. renderContentList.value=contentTotals.slice(0,pageSize)
  88. endPageNum=parseInt(contentTotals.length / pageSize) + 1;
  89. }
  90. function handleLoadContent(){
  91. renderContentList.value=renderContentList.value.concat(contentTotals.slice(page*pageSize,(page+1)*pageSize))
  92. }
  93. // 拨打电话
  94. function handleCallPhone() {
  95. let tel = userInfo.SellerPhone
  96. if (!tel) {
  97. systemConfig.forEach(item => {
  98. if (item.ConfKey === 'ServicePhone') {
  99. tel = item.ConfVal
  100. }
  101. });
  102. }
  103. var phoneLink = 'tel:' + tel;
  104. var link = document.createElement('a');
  105. link.setAttribute('href', phoneLink);
  106. link.onclick = function () {
  107. return true;
  108. };
  109. link.click();
  110. }
  111. // 点击收藏
  112. async function handleCollect() {
  113. const res = reportCollected.value ? await apiReport.reportCollectCancel({ ReportId: Number(reportId) }) : await apiReport.reportCollect({ ReportId: Number(reportId) })
  114. if (res.Ret === 200) {
  115. Message.success(reportCollected.value ? '取消收藏成功' : '收藏成功')
  116. reportCollected.value = !reportCollected.value
  117. // 通知更新收藏列表
  118. wx.miniProgram.postMessage({
  119. data: 'refreshCollectList'
  120. });
  121. }
  122. }
  123. // 显示免责声明
  124. const isShowMZSM = ref(false)
  125. // 显示返回顶部
  126. const showToTop = ref(false)
  127. const handlePageScroll=useThrottleFn(()=>{
  128. const top = document.documentElement.scrollTop || document.body.scrollTop
  129. if (top > window.outerHeight) {
  130. showToTop.value = true
  131. } else {
  132. showToTop.value = false
  133. }
  134. if(page >= endPageNum) return
  135. const clientHeight = document.documentElement.clientHeight || document.body.clientHeight; // 可视高度
  136. const scrollHeight = document.body.scrollHeight; // 总高度
  137. const bufferHeight = 400;
  138. if((scrollHeight - top - clientHeight) < bufferHeight+100) {
  139. console.log('触底')
  140. page++
  141. handleLoadContent();
  142. }
  143. },300)
  144. function handleBackTop() {
  145. document.body.scrollTop = document.documentElement.scrollTop = 0
  146. }
  147. // 点击报告内容中的图片
  148. function handlePreviewImgs() {
  149. document.getElementById('rich-content').addEventListener('click', function (event) {
  150. let imgArray = [];
  151. let curImageSrc = event.target.src;
  152. let oParent = event.target.parentNode;
  153. if (curImageSrc && !oParent.hasAttribute('href')) {
  154. let imgs = document.querySelectorAll('.rich-content img');
  155. for (let i = 0; i < imgs.length; i++) {
  156. let itemSrc = imgs[i].src;
  157. imgArray.push(itemSrc);
  158. }
  159. wx.previewImage({ current: curImageSrc, urls: imgArray });
  160. }
  161. });
  162. }
  163. onMounted(() => {
  164. window.addEventListener('scroll', handlePageScroll)
  165. })
  166. onUnmounted(() => {
  167. window.removeEventListener('scroll', handlePageScroll)
  168. })
  169. function handleGoLogin(){
  170. const redirectUrl=encodeURIComponent(`/pages-report/reportDetail/index?id=${route.query.reportid}`)
  171. wx.miniProgram.reLaunch({
  172. url:`/pages/login/index?redirectUrl=${redirectUrl}`
  173. })
  174. }
  175. </script>
  176. <template>
  177. <div class="report-detail-page" v-if="reportInfo">
  178. <div class="title-box">{{ reportInfo.Title }}</div>
  179. <div class="author-box">{{ reportInfo.Author }}</div>
  180. <div class="time-box">
  181. <span>{{ reportInfo.PublishTime }}</span>
  182. <span class="btn" @click="isShowMZSM = true">免责声明</span>
  183. </div>
  184. <div class="des-box" v-if="reportInfo.Abstract">
  185. <svg-icon name="icon01"></svg-icon>
  186. <div>{{ reportInfo.Abstract }}</div>
  187. </div>
  188. <div
  189. id="rich-content"
  190. class="report-content-box rich-content"
  191. >
  192. <div v-for="item in renderContentList" :key="item" v-html="item"></div>
  193. </div>
  194. <!-- 右侧悬浮操作栏 -->
  195. <div class="right-fix-box">
  196. <!-- 收藏 -->
  197. <svg-icon
  198. @click="handleCollect"
  199. class="item collect-icon"
  200. :name="reportCollected ? 'collected' : 'collect'"
  201. v-if="reportStatus === 4"
  202. />
  203. <!-- 返回顶部 -->
  204. <div class="item back-top-img">
  205. <svg-icon
  206. name="backtop"
  207. v-show="showToTop"
  208. @click="handleBackTop"
  209. class="back-top-img"
  210. />
  211. </div>
  212. </div>
  213. </div>
  214. <!-- 无权限 -->
  215. <div class="no-auth-wrap" v-if="reportStatus !== 4">
  216. <div class="opcity-box"></div>
  217. <div class="content-box">
  218. <img class="icon" src="@/assets/imgs/lock-img.png" alt="" />
  219. <div class="text" v-if="reportStatus === 3">
  220. 您暂无权限查看,<br />请联系客服人员开通!
  221. </div>
  222. <div class="text" v-if="reportStatus === 2">
  223. 您暂无该品种权限,<br />请联系销售人员开通!
  224. </div>
  225. <div class="text" v-if="reportStatus === 1">
  226. 您的权限已过期,<br />请联系销售人员开通!
  227. </div>
  228. <t-button
  229. theme="primary"
  230. block
  231. style="width: 300px; margin: 30px auto"
  232. @click="handleCallPhone"
  233. >立即联系</t-button
  234. >
  235. </div>
  236. </div>
  237. <!-- 未绑定 -->
  238. <div class="no-auth-wrap" v-if="reportStatus === 5&&!isBind">
  239. <div class="opcity-box"></div>
  240. <div class="content-box">
  241. <img class="icon" src="@/assets/imgs/lock-img.png" alt="" />
  242. <div class="text">
  243. 为了优化您的用户体验<br />请登录后查看更多信息!
  244. </div>
  245. <t-button
  246. theme="primary"
  247. block
  248. style="width: 300px; margin: 30px auto"
  249. @click="handleGoLogin"
  250. >去登陆</t-button
  251. >
  252. </div>
  253. </div>
  254. <!-- 免责声明 -->
  255. <disclaimers-wrap v-model:show="isShowMZSM" />
  256. </template>
  257. <style lang="scss" scoped>
  258. .report-detail-page {
  259. background-color: #fff;
  260. padding: var(--page-padding);
  261. .title-box {
  262. font-size: 36px;
  263. line-height: 44px;
  264. margin-bottom: 20px;
  265. }
  266. .time-box {
  267. margin-top: 10px;
  268. font-size: var(--font-size-small);
  269. color: var(--text-color-grey);
  270. .btn {
  271. float: right;
  272. color: var(--primary-color);
  273. }
  274. }
  275. .des-box {
  276. background-color: #f8f8f8;
  277. padding: 20px;
  278. margin: 20px 0;
  279. display: flex;
  280. gap: 0 10px;
  281. color: var(--text-color-sub);
  282. font-size: var(--font-size-small);
  283. line-height: 36px;
  284. }
  285. .report-content-box {
  286. margin-top: 20px;
  287. line-height: 1.8;
  288. font-size: 36px;
  289. :deep(img) {
  290. width: 100% !important;
  291. }
  292. :deep(span) {
  293. font-size: 36px !important;
  294. line-height: 1.8 !important;
  295. background-color: rgba(255, 255, 255, 0) !important;
  296. }
  297. :deep(p) {
  298. font-size: 36px !important;
  299. line-height: 1.8 !important;
  300. background-color: rgba(255, 255, 255, 0) !important;
  301. }
  302. :deep(ul) {
  303. font-size: 36px !important;
  304. line-height: 1.8 !important;
  305. background-color: rgba(255, 255, 255, 0) !important;
  306. }
  307. :deep(ol) {
  308. font-size: 36px !important;
  309. line-height: 1.8 !important;
  310. background-color: rgba(255, 255, 255, 0) !important;
  311. }
  312. :deep(iframe) {
  313. width: 100% !important;
  314. }
  315. :deep(li) {
  316. font-size: 36px !important;
  317. line-height: 1.8 !important;
  318. background-color: rgba(255, 255, 255, 0) !important;
  319. list-style: inherit !important;
  320. list-style-position: inside !important;
  321. }
  322. :deep(span.fr-emoticon) {
  323. width: 36px !important;
  324. height: 36px !important;
  325. background-repeat: no-repeat !important;
  326. background-size: cover !important;
  327. display: inline-block !important;
  328. vertical-align: middle !important;
  329. }
  330. }
  331. .right-fix-box {
  332. position: fixed;
  333. z-index: 99;
  334. right: 34px;
  335. bottom: 130px;
  336. .item {
  337. margin-top: 10px;
  338. }
  339. .back-top-img {
  340. width: 100px;
  341. height: 100px;
  342. display: block;
  343. }
  344. .collect-icon {
  345. width: 100px;
  346. height: 100px;
  347. display: block;
  348. }
  349. }
  350. }
  351. .no-auth-wrap {
  352. position: fixed;
  353. left: 0;
  354. right: 0;
  355. bottom: 0;
  356. z-index: 99;
  357. .opcity-box {
  358. height: 129px;
  359. background: linear-gradient(
  360. 360deg,
  361. #ffffff 0%,
  362. rgba(255, 255, 255, 0) 100%
  363. );
  364. }
  365. .content-box {
  366. background-color: #fff;
  367. padding-bottom: 200px;
  368. text-align: center;
  369. color: var(--primary-color);
  370. }
  371. .icon {
  372. display: block;
  373. margin: 0 auto;
  374. width: 200px;
  375. height: 200px;
  376. }
  377. }
  378. @media (min-width: 600px) {
  379. .report-detail-page {
  380. .title-box {
  381. font-size: 18px;
  382. line-height: 22px;
  383. margin-bottom: 10px;
  384. }
  385. .time-box {
  386. margin-top: 5px;
  387. }
  388. .des-box {
  389. padding: 10px;
  390. margin: 10px 0;
  391. gap: 0 5px;
  392. line-height: 18px;
  393. }
  394. .report-content-box {
  395. margin-top: 10px;
  396. font-size: 18px;
  397. :deep(span) {
  398. font-size: 18px !important;
  399. }
  400. :deep(p) {
  401. font-size: 18px !important;
  402. }
  403. :deep(ul) {
  404. font-size: 18px !important;
  405. }
  406. :deep(ol) {
  407. font-size: 18px !important;
  408. }
  409. :deep(li) {
  410. font-size: 18px !important;
  411. }
  412. :deep(span.fr-emoticon) {
  413. width: 18px !important;
  414. height: 18px !important;
  415. }
  416. }
  417. .right-fix-box {
  418. right: 17px;
  419. bottom: 65px;
  420. .item {
  421. margin-top: 5px;
  422. }
  423. .back-top-img {
  424. width: 50px;
  425. height: 50px;
  426. }
  427. .collect-icon {
  428. width: 50px;
  429. height: 50px;
  430. }
  431. }
  432. }
  433. .no-auth-wrap {
  434. .opcity-box {
  435. height: 65px;
  436. }
  437. .content-box {
  438. padding-bottom: 100px;
  439. }
  440. .icon {
  441. width: 100px;
  442. height: 100px;
  443. }
  444. }
  445. }
  446. </style>