courseDetail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <template>
  2. <view style="height: 100%; background: #F8F9FA;">
  3. <!-- <van-image-->
  4. <!-- class="huodongText2-img"-->
  5. <!-- height="360rpx"-->
  6. <!-- :src="courseInfo.cover"-->
  7. <!-- width="100%"-->
  8. <!-- style="display: flex;align-items: center;"-->
  9. <!-- />-->
  10. <u-swiper :list="bannerList||[]" keyName="url"
  11. :indicatorStyle="{right: '20rpx', bottom: '20rpx', width: '100px',marginLeft: 'auto'}" indicator
  12. indicatorMode="number" :height="'360rpx'" imgMode="scaleToFill">
  13. </u-swiper>
  14. <view class="huodong-ccontent" >
  15. <view class="course-content">
  16. <view class="course-title">{{ courseInfo.goods_name }}</view>
  17. <view class="course-date">
  18. <view style="padding-top: 7rpx;width:28rpx;height: 28rpx ">
  19. <van-image
  20. class="huodongText2-img"
  21. height="28rpx"
  22. src="/static/miaoshu.png"
  23. width="28rpx"
  24. style="display: flex;"
  25. />
  26. </view>
  27. <span style="padding: 0 16rpx">{{courseInfo.remark}}</span>
  28. </view>
  29. <view class="course-price" style="position: relative;">
  30. <span style="font-size: 24rpx; color: #C29556;">¥&nbsp;</span><span style="font-size: 36rpx;color: #C29556;">{{courseInfo.price_selling}}</span>
  31. <view style="position: absolute;right:0rpx;font-size: 22rpx;color:#888888; display: flex;">
  32. <view style="padding-top: 7rpx;width:28rpx;height: 28rpx ">
  33. <van-image
  34. class="huodongText2-img"
  35. height="28rpx"
  36. src="/static/baoming.png"
  37. width="28rpx"
  38. style="display: flex;"
  39. />
  40. </view>
  41. <span style="padding-left: 20rpx;"> &nbsp;{{courseInfo.stock_sales}}&nbsp;人已学习</span>
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. <view class="course-content-title">
  47. 课程介绍
  48. </view>
  49. <view id="course-content" ref="courseContent" style="width: 95%;margin: 0 auto;" v-html="courseInfo.content">
  50. </view>
  51. <view style="width: 100%;height: 165rpx" > </view>
  52. <van-toast id="van-toast"/>
  53. <view class="bottom-navigation">
  54. <view class="bottom-navigation-div">
  55. <view style="width: 40rpx;margin-right: 30rpx" @click="toJump( 1)" >
  56. <van-image
  57. height="36rpx"
  58. src="/static/hd-icon-a.png"
  59. width="36rpx"
  60. style="display: flex;align-items: center; justify-content: center;"
  61. />
  62. <span>
  63. 首页
  64. </span>
  65. </view>
  66. <view style="width: 40rpx;position:relative" open-type="contact">
  67. <van-image
  68. height="36rpx"
  69. src="/static/hd-icon-c.png"
  70. width="36rpx"
  71. style="display: flex;align-items: center; justify-content: center;"
  72. />
  73. <span>
  74. 咨询
  75. </span>
  76. <button style="position: absolute;width: 100%;height: 100%;z-index: 999;opacity: 0;top:0;"
  77. open-type="contact" ></button>
  78. </view>
  79. </view>
  80. <button class="course-button" @click="handleRegister">报名学习</button>
  81. </view>
  82. </view>
  83. </template>
  84. <script>
  85. import {getConfigData} from '@/common/api/common.js';
  86. import Toast from "../../wxcomponents/vant/dist/toast/toast";
  87. import {getGoodsDetail} from "../../common/api";
  88. export default {
  89. components: {},
  90. data() {
  91. return {
  92. bannerList: [],
  93. page: 1,
  94. pageSize: 10,
  95. courseTypeList: [],
  96. goods_code: 0,
  97. courseInfo: {},
  98. entry_end: 0,
  99. remainingImages: [],
  100. entry_num:0,
  101. entry_max:0,
  102. entry_balance:0,
  103. is_entry:false,
  104. suitNum:1,
  105. };
  106. },
  107. onLoad: function (option) {
  108. this.goods_code = option.goods_code
  109. this.getCourseDetail()
  110. this.setImgWidth()
  111. },
  112. onShow() {
  113. this.$nextTick(() => {
  114. });
  115. },
  116. onReachBottom() {
  117. },
  118. onShareAppMessage(res) {
  119. let params = {};
  120. params = {
  121. goods_code: this.goods_code
  122. };
  123. let configs = uni.getStorageSync('configs') || {};
  124. return {
  125. title: configs.shop_share_title,
  126. imageUrl: configs.shop_share_img,
  127. path: `/subPages/courseDetail/courseDetail${this.$stringPageOptions(params)}`
  128. };
  129. },
  130. onShareTimeline(res) {
  131. let params = {};
  132. params = {
  133. goods_code: this.goods_code
  134. };
  135. let configs = uni.getStorageSync('configs') || {};
  136. return {
  137. title: configs.shop_share_title,
  138. imageUrl: configs.shop_share_img,
  139. path: `/subPages/courseDetail/courseDetail${this.$stringPageOptions(params)}`
  140. };
  141. },
  142. computed: {},
  143. watch: {},
  144. methods: {
  145. getConfigDatalist() {
  146. getConfigData({dict_id: 36}).then(({data}) => {
  147. this.courseTypeList = data.reverse();
  148. });
  149. },
  150. handleRegister() {
  151. // Toast('敬请期待');
  152. let tempList = this.courseInfo.data_specs[0].list
  153. tempList = tempList.map(item => {
  154. return {
  155. group_name: item.group,
  156. spec_name: item.name
  157. }
  158. })
  159. let specText = tempList.map(item => {
  160. return `${item.group_name}::${item.spec_name}`
  161. })
  162. // 准备发送的数据结构,包含商品代码、套件数量和规格文本
  163. const sendData = {
  164. items: [{
  165. code: this.courseInfo.code, // 商品代码
  166. count: this.suitNum, // 套件数量
  167. // 将规格文本数组用“;;”连接成单个字符串
  168. spec: specText.join(';;')
  169. }]
  170. }
  171. // 调用API创建订单
  172. this.$api.createOrder(sendData).then(res => {
  173. // 成功创建订单后,显示成功提示
  174. uni.showToast({
  175. title: '订单创建成功'
  176. })
  177. // 导航到结算中心页面,并传递订单号作为查询参数
  178. uni.navigateTo({
  179. url: `/subPages/settleCenter/courseSettleCenter?orderNo=${res.data.order_no}`
  180. })
  181. })
  182. },
  183. getCourseDetail() {
  184. getGoodsDetail({goods_code: this.goods_code}).then(({data}) => {
  185. console.log(data)
  186. this.courseInfo = data.goods
  187. this.bannerList=this.courseInfo.slider||[]
  188. console.log('this.courseInfo.content', this.bannerList)
  189. // 修正 courseInfo.content 中的 src 属性值
  190. if (this.courseInfo.content) {
  191. this.courseInfo.content = this.courseInfo.content.replace(/\/apihttps:/g, 'https:');
  192. // 使用正则表达式匹配和修改 img 标签的 style 属性
  193. this.courseInfo.content = this.courseInfo.content.replace(/<img([^>]*)>/gi, (match, attributes) => {
  194. // 检查是否已经存在 style 属性
  195. if (attributes.includes('style')) {
  196. // 如果存在 style 属性,添加 width: 100%;
  197. return match.replace(/style="([^"]*)"/i, (styleMatch, styleContent) => {
  198. if (!styleContent.includes('width: 100%')) {
  199. return `style="${styleContent}; width: 100%;"`;
  200. }
  201. return styleMatch;
  202. });
  203. } else {
  204. // 如果不存在 style 属性,添加 style="width: 100%;"
  205. return match.replace(/<img/i, '<img style="width: 100%;"');
  206. }
  207. });
  208. // 使用正则表达式匹配和修改 p 标签的 style 属性
  209. this.courseInfo.content = this.courseInfo.content.replace(/<p([^>]*)>/gi, (match, attributes) => {
  210. // 检查是否已经存在 style 属性
  211. if (attributes.includes('style')) {
  212. // 如果存在 style 属性,添加新的样式
  213. return match.replace(/style="([^"]*)"/i, (styleMatch, styleContent) => {
  214. const newStyles = 'font-weight: 400; font-size: 24rpx; color: #666666; line-height: 36rpx;';
  215. if (!styleContent.includes(newStyles)) {
  216. return `style="${styleContent}; ${newStyles}"`;
  217. }
  218. return styleMatch;
  219. });
  220. } else {
  221. // 如果不存在 style 属性,添加 style 属性
  222. const newStyles = 'font-weight: 400; font-size: 24rpx; color: #666666; line-height: 36rpx;';
  223. return match.replace(/<p/i, `<p style="${newStyles}"`);
  224. }
  225. });
  226. }
  227. // 确保在数据更新后调用 setImgWidth
  228. this.$nextTick(() => {
  229. this.setImgWidth();
  230. });
  231. });
  232. },
  233. setImgWidth() {
  234. this.$nextTick(() => {
  235. if (this.$refs.courseContent) {
  236. const imgElements = this.$refs.courseContent.querySelectorAll('img');
  237. imgElements.forEach(img => {
  238. img.style.width = '100%';
  239. });
  240. } else {
  241. console.log(this.$refs)
  242. }
  243. });
  244. },
  245. getStyles(index=0) {
  246. let le =28
  247. let py=30
  248. if (this.entry_num%2==1){
  249. py+= 224/2-(84/2)-(le*Math.floor(this.entry_num / 2 ))-le/2
  250. }else{
  251. py+=224/2-(84/2)-(le*this.entry_num/2)
  252. }
  253. let right= index*le+py
  254. var newVar = {
  255. position: 'absolute',
  256. width: '84rpx',
  257. height: '84rpx',
  258. borderRadius: '84rpx',
  259. top: '30rpx',
  260. right: right+'rpx',
  261. };
  262. return newVar
  263. },
  264. toJump( index) {
  265. if(index==1){
  266. uni.switchTab({
  267. url:'/pages/home/index'
  268. });
  269. }else if(index==2){
  270. }
  271. },
  272. },
  273. };
  274. </script>
  275. <style lang="scss" scoped>
  276. .common-page {
  277. height: 100%;
  278. padding: 30rpx;
  279. }
  280. .huodong-ccontent {
  281. position: relative; /* 相对定位 */
  282. width: 650rpx;
  283. padding: 0rpx;
  284. margin: 30rpx auto;
  285. margin-bottom: 0;
  286. padding: 30rpx;
  287. background: #FFFFFF;
  288. border-radius: 16rpx 16rpx 16rpx 16rpx;
  289. }
  290. .course-content {
  291. margin-top: 30 rp;
  292. .course-title {
  293. font-family: PingFang SC, PingFang SC;
  294. font-weight: 400;
  295. font-size: 32rpx;
  296. color: #333333;
  297. line-height: 40rpx;
  298. text-align: left;
  299. font-style: normal;
  300. text-transform: none;
  301. font-weight: bold;
  302. margin-bottom: 16rpx;
  303. }
  304. .course-date {
  305. font-family: 苹方, 苹方;
  306. font-size: 26rpx;
  307. color: #666666;
  308. line-height: 40rpx;
  309. text-align: left;
  310. font-style: normal;
  311. text-transform: none;
  312. font-weight: 400;
  313. margin-bottom: 10rpx;
  314. display: flex;
  315. }
  316. .course-price {
  317. font-family: 苹方, 苹方;
  318. font-weight: 400;
  319. font-size: 24rpx;
  320. color: #666666;
  321. line-height: 40rpx;
  322. text-align: justify;
  323. font-style: normal;
  324. text-transform: none;
  325. display: flex;
  326. }
  327. }
  328. .bottom-navigation{
  329. position: fixed;
  330. // 文字垂直居中
  331. display: flex;
  332. align-items: center;
  333. justify-content: center;
  334. bottom: 0;
  335. height: 100rpx;
  336. width: calc(100% - 40rpx);
  337. background: #FFFFFF;
  338. box-shadow: 0rpx -2rpx 0rpx 0rpx #F1F3F6;
  339. border-radius: 24rpx 24rpx 0rpx 0rpx;
  340. border: 0rpx solid #979797;
  341. padding: 20rpx 20rpx 68rpx 20rpx ;
  342. &-div{
  343. height: 76rpx;
  344. width: 404rpx;
  345. padding-top: 10rpx;
  346. // 文字垂直居中
  347. display: flex;
  348. align-items: center;
  349. padding-left: 30rpx;
  350. span{
  351. font-family: PingFang SC, PingFang SC;
  352. font-weight: 400;
  353. font-size: 20rpx;
  354. color: #333333;
  355. line-height: 32rpx;
  356. text-align: left;
  357. font-style: normal;
  358. text-transform: none;
  359. }
  360. }
  361. .course-button {
  362. width: 264rpx;
  363. height: 80rpx;
  364. background: linear-gradient(315deg, #CA9359 0%, #E2B98E 100%);
  365. border-radius: 292rpx 292rpx 292rpx 292rpx;
  366. font-family: PingFang SC, PingFang SC;
  367. font-weight: 400;
  368. font-size: 28rpx;
  369. color: #FFFFFF;
  370. line-height: 36rpx;
  371. text-align: center;
  372. font-style: normal;
  373. text-transform: none;
  374. // 文字垂直居中
  375. display: flex;
  376. align-items: center;
  377. justify-content: center;
  378. }
  379. }
  380. /* 设置 v-html 渲染的内容中的 img 标签宽度为 100% */
  381. [v-html] img {
  382. width: 100%!important;
  383. }
  384. /* 定义 CSS 变量 */
  385. :root {
  386. --nav-bar-icon-color: black;
  387. --nav-bar-arrow-size: 16px;
  388. --tab-font-size: 28rpx;
  389. }
  390. .course-content-title {
  391. margin: 30rpx auto;
  392. width: 680rpx;
  393. // 垂直居中
  394. font-family: PingFang SC, PingFang SC;
  395. font-weight: 400;
  396. font-size: 28rpx;
  397. color: #333333;
  398. line-height: 40rpx;
  399. font-style: normal;
  400. text-transform: none;
  401. margin-bottom: 20rpx;
  402. // 加粗
  403. font-weight: bold;
  404. }
  405. /* 确保 van-nav-bar 内部的内容能够正确适应新的高度 */
  406. /deep/ .van-nav-bar__title {
  407. font-family: PingFang SC, PingFang SC !important;
  408. font-weight: 400 !important;
  409. font-size: 36rpx !important;
  410. color: #333333 !important;
  411. text-align: center;
  412. // 加粗
  413. // font-weight: bold;
  414. }
  415. /deep/ .van-nav-bar__content {
  416. text-align: center;
  417. }
  418. #course-content img{
  419. width: 100%!important;
  420. }
  421. /* 添加 van-tab 标题的字体大小样式 */
  422. /deep/ .van-tab__text {
  423. font-family: PingFang SC, PingFang SC;
  424. font-weight: 400;
  425. font-size: 28rpx;
  426. }
  427. </style>