serviceDetail.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <view style="height: 100%; background: #F8F9FA;">
  3. <u-swiper :list="courseInfo.slider||[]" keyName="url"
  4. :indicatorStyle="{right: '20rpx', bottom: '20rpx', width: '100px',marginLeft: 'auto'}" indicator
  5. indicatorMode="number" :height="'360rpx'" imgMode="scaleToFill">
  6. </u-swiper>
  7. <view class="huodong-ccontent" >
  8. <view class="course-content">
  9. <view class="course-title fw700 fs18">{{ courseInfo.goods_name }}</view>
  10. <view class="course-price" style="position: relative;">
  11. <span style="font-size: 24rpx; color: #C29556;">¥&nbsp;</span><span class="fw700" style="font-size: 36rpx;color: #C29556;">{{courseInfo.price_selling}}</span>
  12. <view style="position: absolute;right:0rpx;font-size: 22rpx;color:#888888; display: flex;">
  13. <view style="padding-top: 7rpx;width:28rpx;height: 28rpx ">
  14. <van-image
  15. class="huodongText2-img"
  16. height="28rpx"
  17. src="/static/bottom-menu-cert.png"
  18. width="28rpx"
  19. style="display: flex;"
  20. />
  21. </view>
  22. <span style="padding-left: 20rpx;padding-right: 5rpx">&nbsp;已售:&nbsp;{{courseInfo.stock_sales}}</span>
  23. </view>
  24. </view>
  25. <u-divider line-color="#E8E8E8"></u-divider>
  26. <view class="course-title fw600">
  27. 门店信息
  28. </view>
  29. <view class="course-store display-flex-between">
  30. <view class="course-store-left">
  31. <view class="display-flex ">
  32. <view class="course-store-left-img mr10">
  33. <van-image
  34. class="huodongText2-img"
  35. height="28rpx"
  36. src="/static/hd-if-b.png"
  37. width="28rpx"
  38. style="display: flex; align-items: center;justify-content: center;"
  39. />
  40. </view>
  41. <view class="course-store-left-text">
  42. {{store_position}}
  43. </view>
  44. </view>
  45. <view class="display-flex-between ">
  46. <view class="display-flex ">
  47. <view class="course-store-left-img mr10">
  48. <van-image
  49. class="huodongText2-img"
  50. height="24rpx"
  51. src="/static/huodong-a.png"
  52. width="24rpx"
  53. style="display: flex; align-items: center;justify-content: center;"
  54. />
  55. </view>
  56. <view class="course-store-left-text">
  57. {{business_hours}}
  58. </view>
  59. </view>
  60. <view class="course-store-left-right">
  61. <view class="course-store-left-right-img " @click="openLocation">
  62. <van-image
  63. class="huodongText2-img"
  64. height="56rpx"
  65. src="/static/daohang.png"
  66. width="56rpx"
  67. style="display: flex;align-items: center; justify-content: center;"
  68. />
  69. </view>
  70. <view class="course-store-left-right-img ml10" @click="makePhoneCall">
  71. <van-image
  72. class="huodongText2-img"
  73. height="56rpx"
  74. src="/static/dianhua.png"
  75. width="56rpx"
  76. style="display: flex;align-items: center; justify-content: center;"
  77. />
  78. </view>
  79. </view>
  80. </view>
  81. </view>
  82. </view>
  83. </view>
  84. </view>
  85. <view class="course-content-title">
  86. 课程介绍
  87. </view>
  88. <view id="course-content" ref="courseContent" style="width: 95%;margin: 0 auto;" v-html="courseInfo.content">
  89. </view>
  90. <view style="width: 100%;height: 165rpx" > </view>
  91. <van-toast id="van-toast"/>
  92. <view class="bottom-navigation">
  93. <view class="bottom-navigation-div">
  94. <view style="width: 40rpx;margin-right: 30rpx" @click="toJump( 1)" >
  95. <van-image
  96. height="36rpx"
  97. src="/static/hd-icon-a.png"
  98. width="36rpx"
  99. style="display: flex;align-items: center; justify-content: center;"
  100. />
  101. <span>
  102. 首页
  103. </span>
  104. </view>
  105. <view style="width: 40rpx;position:relative" open-type="contact">
  106. <van-image
  107. height="36rpx"
  108. src="/static/hd-icon-c.png"
  109. width="36rpx"
  110. style="display: flex;align-items: center; justify-content: center;"
  111. />
  112. <span>
  113. 咨询
  114. </span>
  115. <button style="position: absolute;width: 100%;height: 100%;z-index: 999;opacity: 0;top:0;"
  116. open-type="contact" ></button>
  117. </view>
  118. </view>
  119. <button class="course-button" @click="handleRegister">立刻预约</button>
  120. </view>
  121. </view>
  122. </template>
  123. <script>
  124. import {getConfigData} from '@/common/api/common.js';
  125. import Toast from "../../wxcomponents/vant/dist/toast/toast";
  126. import {getGoodsDetail} from "../../common/api";
  127. export default {
  128. components: {},
  129. data() {
  130. return {
  131. page: 1,
  132. pageSize: 10,
  133. courseTypeList: [],
  134. goods_code: 0,
  135. courseInfo: {},
  136. entry_end: 0,
  137. remainingImages: [],
  138. entry_num:0,
  139. entry_max:0,
  140. entry_balance:0,
  141. is_entry:false,
  142. suitNum:1,
  143. phoneNumber: '',
  144. store_name: '',
  145. store_position: '',
  146. business_hours: '',
  147. latlng: '',
  148. };
  149. },
  150. onLoad: function (option) {
  151. this.goods_code = option.code
  152. },
  153. onShow() {
  154. this.$nextTick(() => {
  155. this.getCourseDetail()
  156. this.setImgWidth()
  157. });
  158. },
  159. created() {
  160. const configs = uni.getStorageSync("configs");
  161. if (configs) {
  162. this.store_name = configs.store_name
  163. this.phoneNumber = configs.store_phone
  164. this.store_position = configs.store_position
  165. this.business_hours = configs.business_hours
  166. this.latlng = configs.latlng
  167. }
  168. },
  169. computed: {},
  170. watch: {},
  171. methods: {
  172. getConfigDatalist() {
  173. getConfigData({dict_id: 36}).then(({data}) => {
  174. this.courseTypeList = data.reverse();
  175. });
  176. },
  177. makePhoneCall() {
  178. uni.makePhoneCall({
  179. phoneNumber: this.phoneNumber, // 需要拨打的电话号码
  180. success() {
  181. console.log('拨打成功');
  182. },
  183. fail(err) {
  184. console.error('拨打失败', err);
  185. uni.showToast({
  186. title: '拨打失败,请检查号码!',
  187. icon: 'none'
  188. });
  189. }
  190. });
  191. },
  192. openLocation() {
  193. let [Lat, Lng] = ["36.02","117.93"]
  194. if (this.latlng){
  195. [Lat, Lng] = this.latlng.split(',')
  196. }
  197. uni.openLocation({
  198. latitude: Number.parseFloat(Lat), // 实际的纬度,这里使用的是示例值
  199. longitude: Number.parseFloat(Lng), // 实际的经度,这里使用的是示例值
  200. scale: 18, // 地图缩放级别,范围通常是5~18,18是最详细的级别
  201. name: this.store_name, // 可选,位置名称,会在地图的某些视图上显示
  202. address: this.store_position // 可选,详细地址,同样会在地图的某些视图上显示
  203. });
  204. },
  205. handleRegister() {
  206. uni.navigateTo({
  207. url: `/subPages/service/serviceSave?code=${this.goods_code}&id=${this.courseInfo.id}`
  208. })
  209. },
  210. getCourseDetail() {
  211. getGoodsDetail({goods_code: this.goods_code}).then(({data}) => {
  212. console.log(data)
  213. this.courseInfo = data.goods
  214. // 修正 courseInfo.content 中的 src 属性值
  215. if (this.courseInfo.content) {
  216. this.courseInfo.content = this.courseInfo.content.replace(/\/apihttps:/g, 'https:');
  217. // 使用正则表达式匹配和修改 img 标签的 style 属性
  218. this.courseInfo.content = this.courseInfo.content.replace(/<img([^>]*)>/gi, (match, attributes) => {
  219. // 检查是否已经存在 style 属性
  220. if (attributes.includes('style')) {
  221. // 如果存在 style 属性,添加 width: 100%;
  222. return match.replace(/style="([^"]*)"/i, (styleMatch, styleContent) => {
  223. if (!styleContent.includes('width: 100%')) {
  224. return `style="${styleContent}; width: 100%;"`;
  225. }
  226. return styleMatch;
  227. });
  228. } else {
  229. // 如果不存在 style 属性,添加 style="width: 100%;"
  230. return match.replace(/<img/i, '<img style="width: 100%;"');
  231. }
  232. });
  233. // 使用正则表达式匹配和修改 p 标签的 style 属性
  234. this.courseInfo.content = this.courseInfo.content.replace(/<p([^>]*)>/gi, (match, attributes) => {
  235. // 检查是否已经存在 style 属性
  236. if (attributes.includes('style')) {
  237. // 如果存在 style 属性,添加新的样式
  238. return match.replace(/style="([^"]*)"/i, (styleMatch, styleContent) => {
  239. const newStyles = 'font-weight: 400; font-size: 24rpx; color: #666666; line-height: 36rpx;';
  240. if (!styleContent.includes(newStyles)) {
  241. return `style="${styleContent}; ${newStyles}"`;
  242. }
  243. return styleMatch;
  244. });
  245. } else {
  246. // 如果不存在 style 属性,添加 style 属性
  247. const newStyles = 'font-weight: 400; font-size: 24rpx; color: #666666; line-height: 36rpx;';
  248. return match.replace(/<p/i, `<p style="${newStyles}"`);
  249. }
  250. });
  251. }
  252. // 确保在数据更新后调用 setImgWidth
  253. this.$nextTick(() => {
  254. this.setImgWidth();
  255. });
  256. });
  257. },
  258. setImgWidth() {
  259. this.$nextTick(() => {
  260. if (this.$refs.courseContent) {
  261. const imgElements = this.$refs.courseContent.querySelectorAll('img');
  262. imgElements.forEach(img => {
  263. img.style.width = '100%';
  264. });
  265. } else {
  266. console.log(this.$refs)
  267. }
  268. });
  269. },
  270. getStyles(index=0) {
  271. let le =28
  272. let py=30
  273. if (this.entry_num%2==1){
  274. py+= 224/2-(84/2)-(le*Math.floor(this.entry_num / 2 ))-le/2
  275. }else{
  276. py+=224/2-(84/2)-(le*this.entry_num/2)
  277. }
  278. let right= index*le+py
  279. var newVar = {
  280. position: 'absolute',
  281. width: '84rpx',
  282. height: '84rpx',
  283. borderRadius: '84rpx',
  284. top: '30rpx',
  285. right: right+'rpx',
  286. };
  287. return newVar
  288. },
  289. toJump( index) {
  290. if(index==1){
  291. uni.switchTab({
  292. url:'/pages/home/index'
  293. });
  294. }else if(index==2){
  295. }
  296. },
  297. },
  298. };
  299. </script>
  300. <style lang="scss" scoped>
  301. .common-page {
  302. height: 100%;
  303. padding: 30rpx;
  304. }
  305. .huodong-ccontent {
  306. position: relative; /* 相对定位 */
  307. width: 650rpx;
  308. padding: 0rpx;
  309. margin: 30rpx auto;
  310. margin-bottom: 0;
  311. padding: 30rpx;
  312. background: #FFFFFF;
  313. border-radius: 16rpx 16rpx 16rpx 16rpx;
  314. }
  315. .course-content {
  316. margin-top: 30 rp;
  317. .course-title {
  318. font-family: PingFang SC-粗体;
  319. font-weight: normal;
  320. color: #333333;
  321. line-height: 40rpx;
  322. text-align: left;
  323. font-style: normal;
  324. text-transform: none;
  325. margin-bottom: 16rpx;
  326. }
  327. .course-price {
  328. font-family: 苹方, 苹方;
  329. font-weight: 400;
  330. font-size: 24rpx;
  331. color: #666666;
  332. line-height: 40rpx;
  333. text-align: justify;
  334. font-style: normal;
  335. text-transform: none;
  336. display: flex;
  337. }
  338. .course-store {
  339. &-left{
  340. width: 100%;
  341. &-img{
  342. display: flex;
  343. align-items: center;
  344. justify-content: center;
  345. width: 28rpx;
  346. height: 28rpx;
  347. }
  348. &-text{
  349. font-family: PingFang SC, PingFang SC;
  350. font-weight: 500;
  351. font-size: 24rpx;
  352. color: #666666;
  353. line-height: 36rpx;
  354. text-align: left;
  355. font-style: normal;
  356. text-transform: none;
  357. }
  358. &-right{
  359. display: flex;
  360. align-items: center;
  361. justify-content: center;
  362. &-img{
  363. }
  364. }
  365. }
  366. }
  367. }
  368. .bottom-navigation{
  369. position: fixed;
  370. // 文字垂直居中
  371. display: flex;
  372. align-items: center;
  373. justify-content: center;
  374. bottom: 0;
  375. height: 100rpx;
  376. width: calc(100% - 40rpx);
  377. background: #FFFFFF;
  378. box-shadow: 0rpx -2rpx 0rpx 0rpx #F1F3F6;
  379. border-radius: 24rpx 24rpx 0rpx 0rpx;
  380. border: 0rpx solid #979797;
  381. padding: 20rpx 20rpx 68rpx 20rpx ;
  382. &-div{
  383. height: 76rpx;
  384. width: 404rpx;
  385. padding-top: 10rpx;
  386. // 文字垂直居中
  387. display: flex;
  388. align-items: center;
  389. padding-left: 30rpx;
  390. span{
  391. font-family: PingFang SC, PingFang SC;
  392. font-weight: 400;
  393. font-size: 20rpx;
  394. color: #333333;
  395. line-height: 32rpx;
  396. text-align: left;
  397. font-style: normal;
  398. text-transform: none;
  399. }
  400. }
  401. .course-button {
  402. width: 264rpx;
  403. height: 80rpx;
  404. background: linear-gradient(315deg, #CA9359 0%, #E2B98E 100%);
  405. border-radius: 292rpx 292rpx 292rpx 292rpx;
  406. font-family: PingFang SC, PingFang SC;
  407. font-weight: 400;
  408. font-size: 28rpx;
  409. color: #FFFFFF;
  410. line-height: 36rpx;
  411. text-align: center;
  412. font-style: normal;
  413. text-transform: none;
  414. // 文字垂直居中
  415. display: flex;
  416. align-items: center;
  417. justify-content: center;
  418. }
  419. }
  420. /* 设置 v-html 渲染的内容中的 img 标签宽度为 100% */
  421. [v-html] img {
  422. width: 100%!important;
  423. }
  424. /* 定义 CSS 变量 */
  425. :root {
  426. --nav-bar-icon-color: black;
  427. --nav-bar-arrow-size: 16px;
  428. --tab-font-size: 28rpx;
  429. }
  430. .course-content-title {
  431. margin: 30rpx auto;
  432. width: 680rpx;
  433. // 垂直居中
  434. font-family: PingFang SC, PingFang SC;
  435. font-weight: 400;
  436. font-size: 28rpx;
  437. color: #333333;
  438. line-height: 40rpx;
  439. font-style: normal;
  440. text-transform: none;
  441. margin-bottom: 20rpx;
  442. // 加粗
  443. font-weight: bold;
  444. }
  445. /* 确保 van-nav-bar 内部的内容能够正确适应新的高度 */
  446. /deep/ .van-nav-bar__title {
  447. font-family: PingFang SC, PingFang SC !important;
  448. font-weight: 400 !important;
  449. font-size: 36rpx !important;
  450. color: #333333 !important;
  451. text-align: center;
  452. // 加粗
  453. // font-weight: bold;
  454. }
  455. /deep/ .van-nav-bar__content {
  456. text-align: center;
  457. }
  458. #course-content img{
  459. width: 100%!important;
  460. }
  461. /* 添加 van-tab 标题的字体大小样式 */
  462. /deep/ .van-tab__text {
  463. font-family: PingFang SC, PingFang SC;
  464. font-weight: 400;
  465. font-size: 28rpx;
  466. }
  467. </style>