product.vue 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661
  1. <template>
  2. <view
  3. class="product "
  4. :style="{
  5. paddingBottom: userIdentity == 1 && userIdentity == 3 ? '0rpx' : '188rpx',
  6. paddingTop: CustomBar + 'px'
  7. }"
  8. >
  9. <custom-p
  10. v-if="isHeaderPoduct"
  11. :systeminfo="systeminfo"
  12. :navbar-data="nvabarData"
  13. :headerBtnPosi="headerBtnPosi"
  14. :headerColor="headerColor"
  15. :type="isShareType"
  16. :page="backPage"
  17. >
  18. </custom-p>
  19. <view
  20. class="product-topnav"
  21. id="topBar"
  22. v-show="isNavbarFiexd"
  23. :class="navbarFiexd"
  24. :style="{ top: CustomBar + 'px' }"
  25. >
  26. <view class="search-input">
  27. <view class="gosearch-btn" :class="navbarFiexd" @click="this.$api.navigateTo(clickPath)">
  28. <view class="search-icon"> <text class="iconfont icon-iconfonticonfontsousuo1"></text> </view>
  29. <view class="search-text">搜索商品/项目仪器</view>
  30. </view>
  31. </view>
  32. <view class="navbar">
  33. <view
  34. class="nav-item tui-skeleton-fillet"
  35. :class="{ current: tabCurrentIndex === 0 }"
  36. @click="tabClick(0)"
  37. >
  38. <text>详情</text> <text class="line"></text>
  39. </view>
  40. <view
  41. class="nav-item tui-skeleton-fillet"
  42. :class="{ current: tabCurrentIndex === 1 }"
  43. @click="tabClick(1)"
  44. >
  45. <text>服务项目</text> <text class="line"></text>
  46. </view>
  47. <view
  48. class="nav-item tui-skeleton-fillet"
  49. :class="{ current: tabCurrentIndex === 2 }"
  50. @click="tabClick(2)"
  51. >
  52. <text>推荐</text> <text class="line"></text>
  53. </view>
  54. <view
  55. class="nav-item tui-skeleton-fillet"
  56. :class="{ current: tabCurrentIndex === 3 }"
  57. @click="tabClick(3)"
  58. v-if="product.archiveId !== 0"
  59. >
  60. <text>相关资料</text> <text class="line"></text>
  61. </view>
  62. </view>
  63. </view>
  64. <tui-skeleton
  65. v-if="skeletonShow"
  66. backgroundColor="#fafafa"
  67. borderRadius="10rpx"
  68. :isLoading="true"
  69. :loadingType="5"
  70. ></tui-skeleton>
  71. <template v-else>
  72. <view class="cart-content empty" v-if="isInvalid">
  73. <view class="empty-container">
  74. <image class="empty-container-image" :src="productNoneImage" mode="aspectFit"></image>
  75. <text class="error-text">商品已失效,去商城逛逛别的吧~</text>
  76. <view class="login-btn" @click="goIndex">去商城</view>
  77. </view>
  78. </view>
  79. <view class="container-product tui-skeleton" v-else>
  80. <view class="container-product-main">
  81. <view class="product-top">
  82. <view class="banner-section">
  83. <uni-swiper-dot :info="productImage" :current="current" field="content" :mode="mode">
  84. <swiper
  85. class="banner tui-banner tui-skeleton-rect"
  86. @change="swiperChange"
  87. :duration="800"
  88. :autoplay="false"
  89. :circular="true"
  90. >
  91. <swiper-item v-for="(item, index) in productImage" :key="index" class="banner-item">
  92. <image :src="item" @click="previewImg(index)" class="product-img" />
  93. <view class="cm-product-cover" v-if="product.appletsActType === 1"
  94. >云上美博会</view
  95. >
  96. </swiper-item>
  97. </swiper>
  98. <view class="swiper__dots-box">
  99. <tui-tag
  100. padding="12rpx 24rpx"
  101. type="translucent"
  102. shape="circleLeft"
  103. size="32rpx"
  104. :scaleMultiple="0.82"
  105. originRight
  106. >
  107. {{ current + 1 }}/{{ productImage.length }}
  108. </tui-tag>
  109. </view>
  110. </uni-swiper-dot>
  111. </view>
  112. <view class="product-wrap clearfix">
  113. <view class="wrap-top" :class="goodsData.isNoneDisabled ? 'none' : ''">
  114. <view class="wrap-top-price">
  115. <cm-price
  116. v-if="isRequest"
  117. :product="product"
  118. :userIdentity="userIdentity"
  119. :shopID="shopID"
  120. :promotions="product.promotions"
  121. :ladderPriceList="ladderPriceList"
  122. />
  123. </view>
  124. <view class="p-title tui-skeleton-fillet">
  125. <view class="mclap-tag" v-if="product.beautyActFlag == '1'">美博会</view>
  126. <view class="p-title-name" :class="product.beautyActFlag == '1' ? 'indent' : ''">
  127. {{ product.name == undefined ? '' : product.name }}
  128. </view>
  129. <button open-type="share" class="p-title-share tui-share-position" @tap="onShare">
  130. <view class=""><text class="iconfont icon-fenxiang1"></text></view>
  131. <view class="">分享</view>
  132. </button>
  133. </view>
  134. <view class="wrap-label" v-if="product.tagsList.length > 0">
  135. <view
  136. class="label-a tui-skeleton-fillet"
  137. v-for="(label, index) in product.tagsList"
  138. :key="index"
  139. >{{ label }}</view
  140. >
  141. </view>
  142. <view class="product-seve" v-if="hasLogin">
  143. <text class="label">采美承诺:</text>
  144. <text class="iconfont icon-dui tui-skeleton-rect"
  145. ><text class="text">无忧退货</text></text
  146. >
  147. <text class="iconfont icon-dui tui-skeleton-rect"
  148. ><text class="text">快速退款</text></text
  149. >
  150. <text class="iconfont icon-dui tui-skeleton-rect"
  151. ><text class="text">正品保证</text></text
  152. >
  153. </view>
  154. <view
  155. class="productRemarks"
  156. v-if="product.productRemarks != '' && product.productRemarks != null"
  157. >
  158. 备注:{{ product.productRemarks }}
  159. </view>
  160. </view>
  161. </view>
  162. </view>
  163. <view class="product-item-none" v-if="goodsData.isNoneDisabled">
  164. <image class="none-image" :src="productNoneImage" mode=""></image>
  165. <view class="none-text">此商品已{{ goodsData.disabledText }},请浏览以下推荐商品~</view>
  166. </view>
  167. <!-- 参数 -->
  168. <view class="product-parameter" @click="showPopup(0)" v-if="!goodsData.isNoneDisabled">
  169. <text class="title">参数:</text> <text class="name">品牌 起订量 分类...</text>
  170. <text class="iconfont icon-xiayibu"></text>
  171. </view>
  172. <!-- 优惠券 -->
  173. <view
  174. class="product-parameter coupon"
  175. v-if="isShowButton && productCoupon.length > 0"
  176. @click="showPopup(2)"
  177. >
  178. <text class="title">优惠券:</text>
  179. <view class="coupon">
  180. <text class="tags" v-for="(coupon, index) in productCoupon.slice(0, 3)" :key="index">
  181. 满{{ coupon.touchPrice }}减{{ coupon.couponAmount }}
  182. </text>
  183. </view>
  184. <text class="iconfont icon-xiayibu"></text>
  185. </view>
  186. <!-- 仪器培训方案 -->
  187. <view
  188. class="product-parameter"
  189. @click="showPopup(1)"
  190. v-if="product.commodityType == 2 && product.trainingMethod"
  191. >
  192. <text class="title">培训方案:</text>
  193. <text class="name">{{ product.trainingMethod == 1 ? '线上培训' : '线下培训' }}</text>
  194. <text class="iconfont icon-xiayibu"></text>
  195. </view>
  196. <!-- 供应商 -->
  197. <view class="product-supplier" v-if="isNoneSupplier" @click="goSupplier">
  198. <view class="logo">
  199. <img
  200. :src="
  201. shop.logo
  202. ? shop.logo
  203. : 'https://static.caimei365.com/app/img/icon/icon-shoplogo.png'
  204. "
  205. alt=""
  206. /></view>
  207. <view class="main">
  208. <view class="name">{{ shop.name }}</view>
  209. <view class="massgs">
  210. <view class="label">满意度:</view>
  211. <view class="p-stars">
  212. <uni-stars
  213. :stars="6"
  214. :iconClass="iconClass"
  215. :iconColor="iconColor"
  216. :fontSize="36"
  217. :widthInfo="176"
  218. ></uni-stars>
  219. </view>
  220. <view class="acount">
  221. <text>{{ shop.normalNum }}</text
  222. >件商品
  223. </view>
  224. </view>
  225. </view>
  226. <view class="right"><text class="iconfont icon-xiayibu"></text></view>
  227. </view>
  228. </view>
  229. <!-- 商品详情 -->
  230. <view v-show="tabCurrentIndex !== 3">
  231. <view class="product-details product-details0">
  232. <view class="title"> <view class="title-tab">商品详情</view> </view>
  233. <view class="content tui-banner product-rich-text tui-skeleton-rect">
  234. <parser
  235. :html="html"
  236. :img-mode="widthFix"
  237. v-if="!goodsData.isNoneDisabled && product.productDetail.detailInfo"
  238. ></parser>
  239. <view class="product-rich-text-none" v-else>暂无商品信息</view>
  240. </view>
  241. </view>
  242. <!-- 服务项目 -->
  243. <view class="product-details service product-details1">
  244. <view class="title"> <view class="title-tab">服务项目</view> </view>
  245. <view
  246. class="content service"
  247. v-if="product.productDetail.orderInfo || product.productDetail.serviceInfo"
  248. >
  249. <cm-service :product="product.productDetail" v-if="isRequest"></cm-service>
  250. </view>
  251. <view class="content-none" v-else> <text>暂无服务项目</text> </view>
  252. </view>
  253. <!-- 相关推荐 -->
  254. <view class="product-details recommend product-details2">
  255. <view class="title"> <view class="title-tab">相关推荐</view> </view>
  256. <view class="content hot">
  257. <recommend
  258. :query-productid="product.productId"
  259. :query-type="product.recommendType"
  260. v-if="isRequest"
  261. ></recommend>
  262. </view>
  263. </view>
  264. </view>
  265. <!-- 相关资料 -->
  266. <view class="product-details recommend product-details3" v-show="tabCurrentIndex === 3">
  267. <cm-product-doc
  268. @previewImage="changePreViewImageStatus"
  269. :archiveId="product.archiveId"
  270. :userId="userId"
  271. ></cm-product-doc>
  272. </view>
  273. <!-- 商品参数 -->
  274. <tui-bottom-popup :radius="true" :show="popupShow0" @close="hidePopup(0)">
  275. <view class="tui-popup-box clearfix">
  276. <view class="title">商品参数</view>
  277. <div class="tui-popup-main">
  278. <scroll-view class="tui-popup-scroll" scroll-y="true">
  279. <view class="content-tr">
  280. <view class="content-td">起订量</view>
  281. <view class="content-th">{{ product.minBuyNumber }}</view>
  282. </view>
  283. <view class="content-tr">
  284. <view class="content-td">品牌</view>
  285. <view class="content-th">{{
  286. product.brandName == null ? '其他' : product.brandName
  287. }}</view>
  288. </view>
  289. <view class="content-tr">
  290. <view class="content-td">分类</view>
  291. <view class="content-th">{{
  292. product.typeName == null ? '暂无' : product.typeName
  293. }}</view>
  294. </view>
  295. <view class="content-tr">
  296. <view class="content-td">包装规格</view>
  297. <view class="content-th">{{ product.unit }}</view>
  298. </view>
  299. <view class="content-tr">
  300. <view class="content-td">商品编码</view>
  301. <view class="content-th">{{ product.productCode }}</view>
  302. </view>
  303. <view class="content-tr">
  304. <view class="content-td">库存</view>
  305. <view class="content-th">{{ product.stock }}</view>
  306. </view>
  307. <view
  308. class="content-tr"
  309. v-if="product.parametersList.length > 0"
  310. v-for="(item, index) in product.parametersList"
  311. :key="index"
  312. >
  313. <view class="content-td">{{ item.paramsName }}</view>
  314. <view class="content-th">{{ item.paramsContent }}</view>
  315. </view>
  316. </scroll-view>
  317. </div>
  318. <view
  319. class="tui-right-flex tui-popup-btn"
  320. :style="{ paddingBottom: isIphoneX ? '68rpx' : '0rpx' }"
  321. >
  322. <view class="tui-flex-1"> <view class="tui-button" @click="hidePopup(0)">收起</view> </view>
  323. </view>
  324. </view>
  325. </tui-bottom-popup>
  326. <!-- 优惠券 -->
  327. <tui-bottom-popup :radius="true" :show="popupShow2" @close="hidePopup(2)">
  328. <view class="tui-popup-box clearfix">
  329. <view class="title">优惠券</view>
  330. <view class="tui-popup-close" @click="hidePopup(2)">
  331. <text class="iconfont icon-iconfontguanbi"></text>
  332. </view>
  333. <view class="tui-popup-tabs">
  334. <coupon-tabs
  335. :tabs="navbar"
  336. :currentTab="currentTab > 2 ? 0 : currentTab"
  337. @change="couponChange"
  338. :itemWidth="100 / navbar.length + '%'"
  339. selectedColor="#e15616"
  340. sliderBgColor="#e15616"
  341. >
  342. </coupon-tabs>
  343. </view>
  344. <div class="tui-popup-main coupon">
  345. <scroll-view class="tui-popup-scroll" scroll-y="true">
  346. <view class="coupon-empty" v-if="isCouponEmpty">
  347. <image
  348. class="empty-container-image"
  349. :src="StaticUrl + '/icon/icon-coupon-empty@2x.png'"
  350. ></image>
  351. <text class="error-text">暂无可领的优惠券~</text>
  352. </view>
  353. <template v-else>
  354. <view
  355. v-for="(coupon, index) in productCouponList"
  356. :key="index"
  357. :id="coupon.couponId"
  358. class="coupon-list"
  359. >
  360. <view class="list-cell-le">
  361. <view class="coupon-maxMoney"
  362. ><text class="small">¥</text>{{ coupon.couponAmount }}</view
  363. >
  364. <view class="coupon-minMoney">满{{ coupon.touchPrice }}可用</view>
  365. </view>
  366. <view class="list-cell-ri">
  367. <view class="list-cell-top">
  368. <view class="list-cell-type">
  369. <view class="list-cell-tags">
  370. <text class="tags">{{ coupon.couponType | TypeFormat }}</text>
  371. </view>
  372. <view class="list-cell-texts">
  373. <text v-if="coupon.couponType == 0">
  374. {{
  375. coupon.productType && coupon.productType == 1
  376. ? '全商城商品通用'
  377. : '仅可购买指定商品'
  378. }}
  379. </text>
  380. <text v-if="coupon.couponType == 1">
  381. {{
  382. coupon.categoryType == 1
  383. ? '仅限购买产品类商品'
  384. : '仅限购买仪器类商品'
  385. }}
  386. </text>
  387. <text v-if="coupon.couponType == 3"
  388. >仅限购买店铺【{{ coupon.shopName }}】的商品</text
  389. >
  390. <text v-if="coupon.couponType == 4 || coupon.couponType == 2"
  391. >全商城商品通用</text
  392. >
  393. </view>
  394. </view>
  395. <view class="list-cell-btn">
  396. <view class="icon-used">
  397. <view
  398. class="icon-used-btn receive"
  399. v-if="currentTab == 0"
  400. @click="receiveCoupon(coupon)"
  401. >领取</view
  402. >
  403. <view class="icon-used-btn make" v-if="currentTab == 1"
  404. >已领取</view
  405. >
  406. </view>
  407. </view>
  408. </view>
  409. <view class="list-cell-time"
  410. >{{ coupon.startDate }} - {{ coupon.endDate }}</view
  411. >
  412. </view>
  413. </view>
  414. </template>
  415. </scroll-view>
  416. </div>
  417. </view>
  418. </tui-bottom-popup>
  419. <!-- 培训方案 -->
  420. <tui-bottom-popup :radius="true" :show="popupShow1" @close="hidePopup(1)">
  421. <view class="tui-popup-box clearfix">
  422. <view class="title">培训方案</view>
  423. <div class="tui-popup-main">
  424. <scroll-view class="tui-popup-scroll train" scroll-y="true">
  425. <view class="content-tr">
  426. <view class="content-td">培训方式:</view>
  427. <view class="content-th">{{
  428. product.trainingMethod == 1 ? '线上培训' : '线下培训'
  429. }}</view>
  430. </view>
  431. <view class="content-tr">
  432. <view class="content-td">培训费用:</view>
  433. <view class="content-th">{{
  434. product.trainingType == 1 ? '¥' + product.trainingFee : '售价已包含'
  435. }}</view>
  436. </view>
  437. </scroll-view>
  438. </div>
  439. <view
  440. class="tui-right-flex tui-popup-btn"
  441. :style="{ paddingBottom: isIphoneX ? '68rpx' : '0rpx' }"
  442. >
  443. <view class="tui-flex-1"> <view class="tui-button" @click="hidePopup(1)">收起</view> </view>
  444. </view>
  445. </view>
  446. </tui-bottom-popup>
  447. <!-- 底部按钮 -->
  448. <view class="menu" v-if="isShowButton">
  449. <view class="bottom-btn" :style="{ paddingBottom: isIphoneX ? '68rpx' : '0rpx' }">
  450. <view class="bottom-le">
  451. <view class="item-bt" @click="this.$api.switchTabTo('/pages/tabBar/home/index')">
  452. <image src="../../static/icon-home-active@3x.png"></image> <text>首页</text>
  453. </view>
  454. <view class="item-bt" @click="handleCollection">
  455. <image
  456. :src="
  457. collectionType
  458. ? StaticUrl + 'icon/icon-collection@2x.png'
  459. : StaticUrl + 'icon/icon-collection-none@2x.png'
  460. "
  461. ></image>
  462. <text>{{ collectionType ? '已收藏' : '收藏' }}</text>
  463. </view>
  464. <view class="item-bt" @click="buyProductCart()">
  465. <image src="https://static.caimei365.com/app/img/icon/icon-cart-active@3x.png"></image>
  466. <text>购物车</text>
  467. <text
  468. v-if="hasLogin && bottomCartNumber > 0"
  469. class="uni-badge uni-badge-error uni-small uni-badge--small icon-num"
  470. :class="[bottomCartNumber < 10 ? 'goleft' : '']"
  471. >
  472. {{ bottomCartNumber >= 100 ? '99+' : bottomCartNumber }}
  473. </text>
  474. <view class="animation-num" :class="isAnimation ? 'animation' : 'restion'">+1</view>
  475. </view>
  476. </view>
  477. <view class="bottom-ri">
  478. <button
  479. :disabled="goodsData.disabled"
  480. class="btn btn-cart"
  481. :class="[goodsData.disabled ? 'disabled' : '']"
  482. @tap.stop="btnGetConfirm('add')"
  483. >
  484. 加入购物车
  485. </button>
  486. <button
  487. :disabled="goodsData.disabled"
  488. class="btn btn-bay"
  489. :class="[goodsData.disabled ? 'disabled' : '']"
  490. @tap.stop="btnGetConfirm('buy')"
  491. >
  492. 立即购买
  493. </button>
  494. </view>
  495. </view>
  496. </view>
  497. <!--底部选择模态层弹窗组件 -->
  498. <view class="popup spec" :class="specClass" @touchmove.stop.prevent="discard" @tap="hideSpec">
  499. <!-- 遮罩层 -->
  500. <view class="mask"></view>
  501. <view
  502. class="layer"
  503. @tap.stop="discard"
  504. :style="{
  505. paddingBottom: isIphoneX ? '68rpx' : '36rpx',
  506. bottom: isIphoneX ? '-352rpx' : '-296rpx'
  507. }"
  508. >
  509. <view class="content">
  510. <view class="layer-smimg"> <image :src="product.mainImage" mode=""></image> </view>
  511. <view class="layer-nunbox">
  512. <view class="layer-nunbox-t" v-if="product.step === 2">
  513. <view class="text">*该商品只能以起订量的整数倍购买</view>
  514. </view>
  515. <view class="layer-nunbox-t">
  516. <view class="layer-nunbox-text">数量:</view>
  517. <view class="number-box">
  518. <view
  519. class="iconfont icon-jianhao"
  520. :class="[isQuantity == true ? 'disabled' : '']"
  521. @click="changeCountSub()"
  522. ></view>
  523. <input
  524. class="btn-input"
  525. type="number"
  526. v-model="number"
  527. maxlength="4"
  528. @blur="changeNumber($event)"
  529. />
  530. <view
  531. class="iconfont icon-jiahao"
  532. :class="[isStock == true ? 'disabled' : '']"
  533. @click="changeCountAdd()"
  534. ></view>
  535. </view>
  536. </view>
  537. <view class="layer-nunbox-b">
  538. <view class="text"
  539. >单价: <text class="p sm">¥</text>
  540. <text class="p bg">{{ buyRetailPrice.toFixed(2) }}</text>
  541. </view>
  542. </view>
  543. </view>
  544. </view>
  545. <view class="btn"><view class="button" @click.stop="btnConfirm">确定</view></view>
  546. </view>
  547. </view>
  548. <!-- 侧边 -->
  549. <scroll-top :isScrollTop="isScrollTop" :bottom="200" v-show="tabCurrentIndex !== 3"></scroll-top>
  550. </view>
  551. </template>
  552. </view>
  553. </template>
  554. <script>
  555. import { mapState, mapMutations } from 'vuex'
  556. import customP from '@/components/cm-module/headerNavbar/header-poduct' //自定义导航
  557. import cmPrice from '@/components/cm-module/productDetails/cm-price.vue' //价格显示
  558. import cmAttributes from '@/components/cm-module/productDetails/cm-attributes.vue' //规格信息
  559. import parser from '@/components/jyf-Parser/index' //富文本处理
  560. import tuiSkeleton from '@/components/tui-skeleton/tui-skeleton'
  561. import recommend from '@/components/cm-module/productDetails/recommend' //相关推荐
  562. import cmParameter from '@/components/cm-module/productDetails/cm-parameter' //相关参数
  563. import cmService from '@/components/cm-module/productDetails/cm-service' //服务项目
  564. import cmProductDoc from '@/components/cm-module/productDetails/cm-product-doc.vue'
  565. import couponTabs from '@/components/cm-module/coupon/tui-tabs.vue'
  566. import authorize from '@/common/config/authorize.js'
  567. import wxLogin from '@/common/config/wxLogin.js'
  568. import { debounce } from '@/common/config/common.js'
  569. var isPreviewImg
  570. export default {
  571. components: {
  572. customP,
  573. parser,
  574. tuiSkeleton,
  575. recommend,
  576. cmPrice,
  577. cmAttributes,
  578. cmParameter,
  579. cmService,
  580. couponTabs,
  581. cmProductDoc
  582. },
  583. data() {
  584. return {
  585. StaticUrl: this.$Static, //静态图片路径
  586. clickPath: '/pages/search/search',
  587. html: '<div style="text-align: center;color:#333333;">暂无内容</div>',
  588. productNoneImage: 'https://static.caimei365.com/app/img/icon/icon-pnone.png',
  589. mode: 'round',
  590. iconClass: 'icon-aixin',
  591. iconColor: '#ff9100',
  592. specClass: '', // 规格弹窗css类,控制开关动画
  593. isBtnType: '',
  594. isRequest: false,
  595. isScrollTop: false,
  596. current: 0,
  597. shopId: 0,
  598. isShareType: '',
  599. isHeaderPoduct: false,
  600. isNavbarFiexd: false,
  601. navbarFiexd: 'none',
  602. ladderPriceFlag: '',
  603. ladderPriceList: '',
  604. isInvalid: false,
  605. isEvaluate: false,
  606. isAnimation: false,
  607. skeletonShow: true,
  608. isQuantity: false,
  609. isStock: false,
  610. disabled: false,
  611. isNoneDisabled: false,
  612. tabCurrentIndex: 0,
  613. userId: '',
  614. shopID: '',
  615. productId: 0,
  616. userIdentity: 0, // 用户类型
  617. goodsData: {}, // 自定义数据
  618. shop: {}, //供应商信息
  619. product: {}, //采美
  620. productImage: [],
  621. retailPrice: 0,
  622. buyRetailPrice: 0,
  623. buyRetailPriceStep: 1,
  624. stock: 0,
  625. number: 0,
  626. minBuyNumber: 0,
  627. productsList: [],
  628. goodListData: [],
  629. productCoupon: [], // 优惠券
  630. productCouponList: [], // 优惠券弹窗列表
  631. headerBtnPosi: this.setHeaderBtnPosi(), // 获取设备顶部胶囊高度
  632. systeminfo: this.setSysteminfo(), // 获取设备信息
  633. windowHeight: '',
  634. headerColor: false,
  635. backPage: 1,
  636. nvabarData: {
  637. // 顶部自定义导航
  638. showCapsule: 1, // 是否显示左上角图标 1表示显示 0表示不显示
  639. title: '' // 导航栏 中间的标题
  640. },
  641. linkPath: '',
  642. CustomBar: this.CustomBar, // 顶部导航栏高度
  643. popupShow0: false, // 参数弹窗
  644. popupShow1: false, // 培训方案
  645. popupShow2: false, // 优惠券
  646. tabSelectFlag: false,
  647. sectionPropsArr: [],
  648. scrollTopArray: [],
  649. winHeight: '',
  650. isShowButton: true,
  651. isNoneSupplier: false,
  652. isCouponEmpty: false,
  653. currentTab: 0,
  654. couponParam: {
  655. // 获取弹窗优惠券领取参数
  656. userId: 0,
  657. productId: 0,
  658. status: 1,
  659. source: 2
  660. },
  661. bottomCartNumber: 0,
  662. navbar: [{ name: '未领取', num: 0 }, { name: '已领取', num: 0 }],
  663. isPreviewImage: false,
  664. opentype: '',
  665. collectionType: false
  666. }
  667. },
  668. computed: {
  669. ...mapState(['hasLogin', 'isWxAuthorize', 'identity', 'isIphoneX'])
  670. },
  671. filters: {
  672. TypeFormat(value) {
  673. switch (value) {
  674. case 0:
  675. return '活动券'
  676. break
  677. case 1:
  678. return '品类券'
  679. break
  680. case 2:
  681. return '用户专享券'
  682. break
  683. case 3:
  684. return '店铺券'
  685. break
  686. case 4:
  687. return '新用户券'
  688. break
  689. }
  690. }
  691. },
  692. watch: {
  693. isNavbarFiexd(val) {
  694. if (!this.isRequest || !val) return
  695. let timer = null
  696. clearTimeout(timer)
  697. timer = setTimeout(() => {
  698. if (this.sectionPropsArr.length > 0) return
  699. this.getSectionProps()
  700. }, 200)
  701. }
  702. },
  703. onLoad(option) {
  704. this.productId = this.couponParam.productId = option.id //获取商品ID
  705. this.opentype = option.open
  706. this.isShareType = option.type
  707. this.linkPath = option.path
  708. this.isHeaderPoduct = true
  709. if (option.page == 2) {
  710. this.backPage = option.page
  711. }
  712. if (this.isShareType == 'share') {
  713. wxLogin.wxLoginAuthorize()
  714. }
  715. this.getWinHeight()
  716. },
  717. onReady() {
  718. if (this.opentype == 'caimei') {
  719. // 跳转到资料详情
  720. uni.showLoading({
  721. title: '加载中'
  722. })
  723. setTimeout(() => {
  724. this.isNavbarFiexd = true
  725. this.tabClick(3)
  726. uni.hideLoading()
  727. }, 2000)
  728. }
  729. console.log('是iPhoneX', this.isIphoneX)
  730. },
  731. methods: {
  732. initData() {
  733. // 初始化商品详情查询
  734. this.ProductService.QueryProductDetils({
  735. userId: this.userId,
  736. productId: this.productId,
  737. identity: this.identity
  738. })
  739. .then(response => {
  740. this.skeletonShow = false
  741. this.productImage = []
  742. this.shop = response.data.shop
  743. this.shopId = response.data.shopID
  744. this.product = response.data
  745. if (this.product.userLike && this.product.userLike == 1) {
  746. this.collectionType = true
  747. } else {
  748. this.collectionType = false
  749. }
  750. //已删除/已冻结
  751. if (this.product.validFlag === 0 || this.product.validFlag == 10) {
  752. this.isInvalid = true
  753. } else if (this.product.validFlag === 9) {
  754. if (this.userIdentity == 1) {
  755. this.isInvalid = false
  756. } else {
  757. this.isInvalid = true
  758. }
  759. }
  760. this.ladderPriceFlag = this.product.ladderPriceFlag
  761. this.html =
  762. this.product.productDetail == null
  763. ? this.html
  764. : this.$api.adaptRichTextImg(this.product.productDetail.detailInfo)
  765. this.stock = this.product.stock
  766. this.buyRetailPriceStep = this.product.step
  767. this.number = this.product.minBuyNumber
  768. this.minBuyNumber = this.product.minBuyNumber
  769. //处理商品图片列表
  770. this.product.imageList.forEach(item => {
  771. this.productImage.push(item.image)
  772. })
  773. //处理阶梯价格
  774. if (this.product.ladderPriceList != null) {
  775. this.ladderPriceList = this.product.ladderPriceList
  776. }
  777. //拆分金额并转千分位格式显示
  778. if (this.product.price != null) {
  779. this.retailPrice = this.product.price.toFixed(2)
  780. this.buyRetailPrice = this.product.price
  781. }
  782. //处理下架商品和售罄商品
  783. if (this.product.validFlag == 3 || this.stock == 0) {
  784. this.isNoneDisabled = true
  785. this.disabled = true
  786. } else {
  787. this.disabled = false
  788. this.isNoneDisabled = false
  789. this.goodsData.disabledText = ''
  790. }
  791. if (this.product.priceFlag == 1) {
  792. this.disabled = true
  793. } else if (this.product.priceFlag == 2) {
  794. if (this.userIdentity == 4) {
  795. this.disabled = true
  796. } else {
  797. this.disabled = false
  798. }
  799. } else {
  800. this.disabled = false
  801. }
  802. this.goodsData.disabled = this.disabled
  803. this.goodsData.isNoneDisabled = this.isNoneDisabled
  804. if (this.product.validFlag == 3) {
  805. this.goodsData.disabledText = '下架'
  806. }
  807. if (this.product.validFlag == 10) {
  808. this.goodsData.disabledText = '停售'
  809. }
  810. if (this.stock == 0) {
  811. this.goodsData.disabledText = '售罄'
  812. }
  813. console.log(this.disabled)
  814. // setTimeout(() => {
  815. // this.getSectionProps()
  816. // }, 2000)
  817. this.shoppingHeaderCartNumber()
  818. this.queryProductDetilsCoupons()
  819. this.isRequest = true
  820. })
  821. .catch(error => {
  822. this.$util.msg(error.msg, 2000)
  823. })
  824. },
  825. queryProductDetilsCoupons() {
  826. // 初始化商品详情优惠券信息
  827. this.ProductService.QueryProductDetilsCoupons(this.couponParam)
  828. .then(response => {
  829. this.productCoupon = response.data.list
  830. })
  831. .catch(error => {
  832. console.log('获取优惠券列表失败')
  833. })
  834. },
  835. queryPopupCoupons() {
  836. // 获取弹窗优惠券列表
  837. this.ProductService.QueryProductDetilsCoupons(this.couponParam)
  838. .then(response => {
  839. let data = response.data
  840. this.navbar[0].num = data.notCouponNum
  841. this.navbar[1].num = data.couponNum
  842. if (data.couponList && data.couponList.length > 0) {
  843. this.productCouponList = data.couponList
  844. this.isCouponEmpty = false
  845. } else {
  846. this.isCouponEmpty = true
  847. }
  848. })
  849. .catch(error => {
  850. console.log('获取优惠券列表失败')
  851. })
  852. },
  853. shoppingHeaderCartNumber() {
  854. // 获取用户购物车储量
  855. this.ProductService.shoppingHeaderCartNumber({ userId: this.userId })
  856. .then(response => {
  857. this.bottomCartNumber = response.data.length
  858. })
  859. .catch(error => {
  860. console.log('获取购物车数量失败')
  861. })
  862. },
  863. receiveCoupon(coupon) {
  864. // 点击优惠券领取按钮
  865. this.ProductService.ReceiveCoupon({
  866. userId: this.couponParam.userId,
  867. couponId: coupon.couponId,
  868. source: 2
  869. })
  870. .then(response => {
  871. this.$util.msg('领取成功', 1500, true, 'success')
  872. setTimeout(() => {
  873. this.currentTab = 1
  874. this.couponParam.status = 2
  875. this.queryPopupCoupons()
  876. }, 1500)
  877. })
  878. .catch(error => {
  879. this.$util.msg(error.msg, 2000)
  880. })
  881. },
  882. swiperChange(e) {
  883. //顶部商品图片切换
  884. const index = e.detail.current
  885. this.current = index
  886. },
  887. previewImg(index) {
  888. //顶部商品图片预览
  889. isPreviewImg = true
  890. let previewUrls = this.productImage
  891. uni.previewImage({
  892. current: index, //图片索引
  893. urls: previewUrls, //必须是http图片,本地图片无效
  894. longPressActions: ''
  895. })
  896. },
  897. //商品详情&&供应商信息tab切换
  898. tabClick(index) {
  899. // 重新标记
  900. this.getSectionProps()
  901. this.tabCurrentIndex = index
  902. this.tabSelectFlag = true
  903. let timer = null
  904. clearTimeout(timer)
  905. // 点击tab 300ms才执行跳转,避免出错(来回跳动)
  906. timer = setTimeout(() => {
  907. this.tabClickAction(index)
  908. }, 300)
  909. },
  910. // 跳转执行
  911. tabClickAction(index) {
  912. const that = this
  913. if (index === 3) {
  914. return uni.pageScrollTo({
  915. duration: 300, //过渡时间必须为0,uniapp bug,否则运行到手机会报错
  916. scrollTop: this.sectionPropsArr[0].scrollTop
  917. })
  918. }
  919. uni.pageScrollTo({
  920. duration: 300, //过渡时间必须为0,uniapp bug,否则运行到手机会报错
  921. scrollTop: this.sectionPropsArr[index].scrollTop,
  922. success() {
  923. setTimeout(() => {
  924. that.tabSelectFlag = false
  925. }, 300)
  926. }
  927. })
  928. },
  929. handleContact(e) {
  930. //跳转小程序客服
  931. console.log(e.detail.path)
  932. console.log(e.detail.query)
  933. },
  934. buyProductCart() {
  935. //底部购物车按钮点击
  936. if (this.hasLogin) {
  937. // 友盟埋点商品详情购物车入口点击事件
  938. if (process.env.NODE_ENV != 'development') {
  939. this.$uma.trackEvent('Um_Event_ProductShoppingCart', {
  940. Um_Key_PageName: '去购物车',
  941. Um_Key_SourcePage: '商品详情购物车入口'
  942. })
  943. }
  944. // this.$api.navigateTo('/pages/goods/cart')
  945. this.$api.navigateTo('/pages/goods/cart-index')
  946. } else {
  947. this.$api.navigateTo('/pages/login/login?type=1')
  948. }
  949. },
  950. btnGetConfirm(type) {
  951. //加入购物车&&立即购买点击
  952. if (this.hasLogin) {
  953. switch (type) {
  954. case 'add':
  955. // 友盟埋点商品详情加入购物车点击事件
  956. if (process.env.NODE_ENV != 'development') {
  957. this.$uma.trackEvent('Um_Event_ProductAddCart', {
  958. Um_Key_PageName: '加入购物车',
  959. Um_Key_SourcePage: '商品详情',
  960. Um_Key_ProductID: `${this.product.productId}`
  961. })
  962. }
  963. break
  964. case 'buy':
  965. // 友盟埋点商品详情立即购买点击事件
  966. if (process.env.NODE_ENV != 'development') {
  967. this.$uma.trackEvent('Um_Event_ProductBuyConfirm', {
  968. Um_Key_PageName: '立即购买',
  969. Um_Key_SourcePage: '商品详情',
  970. Um_Key_ProductID: `${this.product.productId}`
  971. })
  972. }
  973. break
  974. }
  975. this.showSpec(type)
  976. } else {
  977. this.$api.navigateTo('/pages/login/login?type=1')
  978. }
  979. },
  980. //popup弹窗数量增加按钮
  981. changeCountAdd() {
  982. if (this.buyRetailPriceStep == 2) {
  983. this.number += this.minBuyNumber
  984. } else {
  985. this.number++
  986. }
  987. this.processActivityPrice()
  988. },
  989. //popup弹窗数量减按钮
  990. changeCountSub() {
  991. if (this.number <= this.minBuyNumber) {
  992. this.number = this.minBuyNumber
  993. this.isQuantity = true
  994. this.$util.msg(`该商品最小起订量为${this.minBuyNumber}`, 2000)
  995. return
  996. } else {
  997. if (this.buyRetailPriceStep == 2) {
  998. this.number -= this.minBuyNumber
  999. } else {
  1000. this.number--
  1001. }
  1002. this.processActivityPrice()
  1003. this.isQuantity = false
  1004. }
  1005. },
  1006. changeNumber(e) {
  1007. let _value = e.detail.value
  1008. if (!this.$api.isNumber(_value)) {
  1009. this.number = this.minBuyNumber
  1010. } else if (_value < this.minBuyNumber) {
  1011. this.$util.msg(`该商品最小起订量为${this.minBuyNumber}`, 2000)
  1012. this.number = this.minBuyNumber
  1013. } else if (_value % this.minBuyNumber != 0) {
  1014. this.$util.msg('购买量必须为起订量的整数倍', 2000)
  1015. this.number = this.minBuyNumber
  1016. } else {
  1017. this.number = e.detail.value
  1018. }
  1019. this.processActivityPrice()
  1020. },
  1021. processActivityPrice() {
  1022. //单独处理活动价格和阶梯价格
  1023. if ((this.ladderPriceFlag == '0' && this.product.actStatus == 0) || this.product.actStatus == 1) {
  1024. this.buyRetailPrice = this.product.price
  1025. } else {
  1026. this.ladderPriceList.forEach((item, index) => {
  1027. if (this.number >= item.buyNum) {
  1028. this.buyRetailPrice = item.buyPrice
  1029. }
  1030. })
  1031. }
  1032. },
  1033. showSpec(type) {
  1034. //显示选择数量确认弹窗
  1035. this.isBtnType = type
  1036. this.specClass = 'show'
  1037. if (this.ladderPriceFlag) {
  1038. this.processActivityPrice()
  1039. }
  1040. },
  1041. hideSpec() {
  1042. //关闭选择数量确认弹窗
  1043. this.specClass = 'hide'
  1044. setTimeout(() => {
  1045. this.specClass = 'none'
  1046. }, 200)
  1047. },
  1048. btnConfirm() {
  1049. //加入购物车&&立即购买跳转订单页并关闭弹窗
  1050. // 友盟埋点商品详情确认购买商品点击事件
  1051. if (process.env.NODE_ENV != 'development') {
  1052. this.$uma.trackEvent('Um_Event_ProductShoppingConfirm', {
  1053. Um_Key_PageName: '商品购买确认',
  1054. Um_Key_SourcePage: '商品详情',
  1055. Um_Key_ProductID: `${this.product.productId}`
  1056. })
  1057. }
  1058. if (this.isBtnType == 'add') {
  1059. this.getAddProductCart()
  1060. } else {
  1061. this.toConfirmation()
  1062. }
  1063. },
  1064. toConfirmation() {
  1065. //跳转确认订单页面
  1066. this.specClass = 'hide'
  1067. let productStp = {
  1068. allPrice: this.number * this.buyRetailPrice,
  1069. allCount: this.number,
  1070. productID: this.product.productId,
  1071. productCount: this.number
  1072. }
  1073. this.$api.navigateTo(
  1074. `/pages/user/order/create-order?type=prodcut&data=${JSON.stringify({ data: productStp })}`
  1075. )
  1076. setTimeout(() => {
  1077. this.specClass = 'none'
  1078. }, 200)
  1079. },
  1080. getAddProductCart() {
  1081. //增加购物车成功和toast弹窗提示成功
  1082. this.ProductService.shoppingAddCart({
  1083. productID: this.productId,
  1084. userID: this.userId,
  1085. productCount: this.number
  1086. })
  1087. .then(response => {
  1088. this.specClass = 'hide'
  1089. this.$util.msg('加入购物车成功', 1500, true, 'success')
  1090. this.isAnimation = true
  1091. setTimeout(() => {
  1092. this.specClass = 'none'
  1093. }, 200)
  1094. setTimeout(() => {
  1095. this.isAnimation = false
  1096. }, 2000)
  1097. this.bottomCartNumber = response.data
  1098. })
  1099. .catch(error => {
  1100. this.$util.msg(error.msg, 2000)
  1101. })
  1102. },
  1103. setHeaderBtnPosi() {
  1104. // 获得胶囊按钮位置信息
  1105. let headerBtnPosi = uni.getMenuButtonBoundingClientRect()
  1106. return headerBtnPosi
  1107. },
  1108. setSysteminfo() {
  1109. let systeminfo
  1110. uni.getSystemInfo({
  1111. // 获取设备信息
  1112. success: res => {
  1113. systeminfo = res
  1114. }
  1115. })
  1116. return systeminfo
  1117. },
  1118. goIndex() {
  1119. //商城首页
  1120. uni.switchTab({
  1121. url: '/pages/tabBar/home/index'
  1122. })
  1123. },
  1124. goSupplier() {
  1125. //跳供应商资料页
  1126. this.$api.navigateTo('/pages/supplier/user/my-shop?shopId=' + this.shopId)
  1127. },
  1128. discard() {
  1129. //丢弃
  1130. },
  1131. onShare(res) {
  1132. //分享转发
  1133. if (res.from === 'button') {
  1134. // 来自页面内转发按钮
  1135. }
  1136. return {
  1137. title: `${this.product.name}`,
  1138. path: `pages/goods/product?type=share&id=${this.productId}`,
  1139. imageUrl: `${this.productImage[0]}`
  1140. }
  1141. },
  1142. handleCollection() {
  1143. // 收藏
  1144. if (this.hasLogin) {
  1145. this.ProductService.getProductUserLike({
  1146. userId: this.userId,
  1147. productId: this.product.productId
  1148. })
  1149. .then(response => {
  1150. this.collectionType = !this.collectionType
  1151. this.$util.msg(response.data, 1500, true, 'success')
  1152. })
  1153. .catch(error => {
  1154. this.$util.msg(error.msg, 2000)
  1155. })
  1156. } else {
  1157. this.$api.navigateTo('/pages/login/login')
  1158. }
  1159. },
  1160. showPopup(index) {
  1161. switch (index) {
  1162. case 0:
  1163. this.popupShow0 = true
  1164. break
  1165. case 1:
  1166. this.popupShow1 = true
  1167. break
  1168. case 2:
  1169. if (this.hasLogin) {
  1170. this.queryPopupCoupons()
  1171. this.popupShow2 = true
  1172. } else {
  1173. this.$api.navigateTo('/pages/login/login')
  1174. }
  1175. break
  1176. }
  1177. },
  1178. hidePopup(index) {
  1179. switch (index) {
  1180. case 0:
  1181. this.popupShow0 = false
  1182. break
  1183. case 1:
  1184. this.popupShow1 = false
  1185. break
  1186. case 2:
  1187. this.popupShow2 = false
  1188. break
  1189. }
  1190. },
  1191. couponChange(e) {
  1192. this.currentTab = e.index
  1193. switch (this.currentTab) {
  1194. case 0:
  1195. this.couponParam.status = 1
  1196. this.queryPopupCoupons()
  1197. break
  1198. case 1:
  1199. this.couponParam.status = 2
  1200. this.queryPopupCoupons()
  1201. break
  1202. }
  1203. },
  1204. // 获取每个tab对应区域的区间
  1205. async getSectionProps() {
  1206. const sectionPropsArr = [],
  1207. scrollTopArray = [],
  1208. className = 'product-details'
  1209. // 获取相关节点元素信息
  1210. const productMain = await this.$util.boundingClientRect(this, '.container-product-main', false)
  1211. const productDetail = await this.$util.boundingClientRect(this, '.product-details', true)
  1212. const topBar = await this.$util.boundingClientRect(this, '#topBar', false)
  1213. /*
  1214. 说明:采用累加方式来计算每一个 prdocut-details 的 scrollTop 定位
  1215. scrollTop = 上一个的scrollTop + 上一个的高度
  1216. */
  1217. productDetail.forEach((item, index) => {
  1218. // 上一个 prdocut-details 的 scrollTop 值
  1219. const prev = sectionPropsArr[index - 1]
  1220. const prevScrollTop = prev ? prev.scrollTop : productMain.height
  1221. // 上一个 prdocut-details 的高度
  1222. const add = productDetail[index - 1]
  1223. // 第一个需要减去tabs的高度
  1224. const addHeight = index === 0 ? (add ? add.height : 0) - topBar.height : add ? add.height : 0
  1225. sectionPropsArr.push({
  1226. className: `${className}-${index}`,
  1227. scrollTop: prevScrollTop + addHeight
  1228. })
  1229. // - topBar.height
  1230. })
  1231. this.sectionPropsArr = sectionPropsArr
  1232. console.log('更新tab影响区域')
  1233. },
  1234. //当滑动时也能同步激活tab
  1235. activeTab: debounce(
  1236. (top, _this) => {
  1237. const { sectionPropsArr } = _this
  1238. if (sectionPropsArr.length > 0) {
  1239. sectionPropsArr.forEach((item, index) => {
  1240. // 当前位置为开始位置, 下个起始位置为结束位置
  1241. const openInterval = (index === 0 ? 0 : item.scrollTop) - 20 // 自定义偏移
  1242. const next = sectionPropsArr[index + 1]
  1243. const closedInterval = (next ? next.scrollTop : 10000000) - 20 // 自定义偏移
  1244. if (top >= openInterval && top < closedInterval) {
  1245. _this.tabCurrentIndex = index
  1246. }
  1247. })
  1248. }
  1249. },
  1250. 100,
  1251. true
  1252. ),
  1253. getWinHeight() {
  1254. this.winHeight = wx.getSystemInfoSync().windowHeight
  1255. },
  1256. changePreViewImageStatus(falg) {
  1257. this.isPreviewImage = falg
  1258. }
  1259. },
  1260. onPageScroll(e) {
  1261. //实时获取到滚动的值
  1262. const { scrollTop } = e
  1263. if (!this.tabSelectFlag) {
  1264. this.activeTab(scrollTop, this)
  1265. }
  1266. if (e.scrollTop > 60) {
  1267. this.headerColor = true
  1268. this.navbarFiexd = 'fixed'
  1269. this.isNavbarFiexd = true
  1270. this.nvabarData = {
  1271. showCapsule: 1,
  1272. title: '商品详情'
  1273. }
  1274. } else {
  1275. this.headerColor = false
  1276. this.isNavbarFiexd = false
  1277. this.navbarFiexd = 'none'
  1278. this.nvabarData = {
  1279. showCapsule: 1,
  1280. title: ''
  1281. }
  1282. }
  1283. if (e.scrollTop > 700) {
  1284. this.isScrollTop = true
  1285. } else {
  1286. this.isScrollTop = false
  1287. }
  1288. },
  1289. onShareAppMessage(res) {
  1290. //分享转发
  1291. if (res.from === 'button') {
  1292. // 来自页面内转发按钮
  1293. }
  1294. return {
  1295. title: `${this.product.name}`,
  1296. path: `pages/goods/product?type=share&id=${this.productId}`,
  1297. imageUrl: `${this.productImage[0]}`
  1298. }
  1299. },
  1300. onShow() {
  1301. // 是否开启图片预览 true 不刷新调用接口 false刷新调用接口
  1302. if (!this.isPreviewImage) {
  1303. this.$api
  1304. .getStorage()
  1305. .then(resolve => {
  1306. this.userId = this.couponParam.userId = resolve.userId ? resolve.userId : ''
  1307. this.userIdentity = resolve.userIdentity ? resolve.userIdentity : 0
  1308. this.shopID = resolve.shopId ? resolve.shopId : ''
  1309. if (this.userIdentity == 0 || this.userIdentity == 2 || this.userIdentity == 4) {
  1310. this.isShowButton = true
  1311. } else {
  1312. this.isShowButton = false
  1313. }
  1314. if (isPreviewImg) {
  1315. isPreviewImg = false
  1316. return
  1317. } else {
  1318. this.initData()
  1319. }
  1320. })
  1321. .catch(error => {
  1322. this.initData()
  1323. })
  1324. }
  1325. this.isPreviewImage = false
  1326. },
  1327. created() {}
  1328. }
  1329. </script>
  1330. <style lang="scss">
  1331. page {
  1332. background-color: #ffffff;
  1333. }
  1334. .banner-section {
  1335. width: 100%;
  1336. height: 750rpx;
  1337. position: relative;
  1338. }
  1339. .banner {
  1340. width: 100%;
  1341. height: 750rpx;
  1342. .product-img {
  1343. width: 750rpx;
  1344. }
  1345. image {
  1346. width: 100%;
  1347. height: 100%;
  1348. }
  1349. .banner-item {
  1350. position: relative;
  1351. .cm-product-cover {
  1352. position: absolute;
  1353. right: 30rpx;
  1354. top: 30rpx;
  1355. width: 147rpx;
  1356. height: 57rpx;
  1357. line-height: 57rpx;
  1358. font-size: 24rpx;
  1359. color: #fff;
  1360. text-align: center;
  1361. background: url(https://static.caimei365.com/app/img/icon2/cm_cover_bg_app.png) no-repeat center;
  1362. background-size: 147rpx;
  1363. }
  1364. }
  1365. }
  1366. .swiper__dots-box {
  1367. position: absolute;
  1368. color: #fff;
  1369. bottom: 30rpx;
  1370. right: 0;
  1371. }
  1372. .product-wrap {
  1373. width: 100%;
  1374. height: auto;
  1375. padding: 24rpx 0 0 0;
  1376. background-color: #ffffff;
  1377. border-bottom: 20rpx solid #f7f7f7;
  1378. .productRemarks {
  1379. height: 48rpx;
  1380. width: 100%;
  1381. float: left;
  1382. line-height: 48rpx;
  1383. font-size: 24rpx;
  1384. color: #999999;
  1385. text-align: left;
  1386. }
  1387. .wrap-top {
  1388. width: 702rpx;
  1389. padding: 0 24rpx;
  1390. height: auto;
  1391. float: left;
  1392. padding-bottom: 20rpx;
  1393. border-bottom: 1px solid #f8f8f8;
  1394. &.none {
  1395. .p-title {
  1396. color: #999999;
  1397. }
  1398. }
  1399. .p-title {
  1400. width: 100%;
  1401. height: auto;
  1402. float: left;
  1403. position: relative;
  1404. .p-title-name {
  1405. width: 602rpx;
  1406. height: auto;
  1407. float: left;
  1408. line-height: 48rpx;
  1409. font-size: $font-size-28;
  1410. color: $text-color;
  1411. -o-text-overflow: ellipsis;
  1412. text-overflow: ellipsis;
  1413. display: -webkit-box;
  1414. word-break: break-all;
  1415. -webkit-box-orient: vertical;
  1416. -webkit-line-clamp: 2;
  1417. overflow: hidden;
  1418. &.indent {
  1419. text-indent: 95rpx;
  1420. }
  1421. }
  1422. .mclap-tag {
  1423. display: block;
  1424. width: 84rpx;
  1425. height: 32rpx;
  1426. background-image: linear-gradient(270deg, #f9c023 0%, #f83600 100%);
  1427. border-radius: 4rpx 48rpx 4px 4px;
  1428. line-height: 32rpx;
  1429. font-size: $font-size-22;
  1430. color: #ffffff;
  1431. text-align: center;
  1432. position: absolute;
  1433. left: 0;
  1434. top: 6rpx;
  1435. }
  1436. .p-title-share {
  1437. width: 96rpx;
  1438. height: 96rpx;
  1439. position: absolute;
  1440. right: 0;
  1441. text-align: center;
  1442. color: #999999;
  1443. font-size: $font-size-24;
  1444. box-sizing: border-box;
  1445. display: block;
  1446. background: transparent;
  1447. border-radius: 0;
  1448. border: 0;
  1449. margin: 0;
  1450. padding: 8rpx 0;
  1451. z-index: 980;
  1452. .icon-fenxiang1 {
  1453. font-size: $font-size-34;
  1454. }
  1455. }
  1456. .tui-share-btn::after {
  1457. border: 0;
  1458. }
  1459. }
  1460. .wrap-main-text {
  1461. line-height: 56rpx;
  1462. color: #ff2a2a;
  1463. font-size: $font-size-26;
  1464. display: block;
  1465. float: left;
  1466. font-weight: normal;
  1467. }
  1468. .wrap-main-none {
  1469. display: block;
  1470. width: 256rpx;
  1471. height: 44rpx;
  1472. padding-left: 20rpx;
  1473. border-radius: 11rpx;
  1474. background: $btn-confirm;
  1475. float: right;
  1476. line-height: 44rpx;
  1477. color: #ffffff;
  1478. text-align: center;
  1479. font-size: $font-size-24;
  1480. }
  1481. .p-price-none {
  1482. height: 44rpx;
  1483. line-height: 44rpx;
  1484. float: left;
  1485. font-size: $font-size-24;
  1486. color: #666;
  1487. text-decoration: line-through;
  1488. margin-left: 8rpx;
  1489. }
  1490. .p-minBuy {
  1491. height: 44rpx;
  1492. line-height: 44rpx;
  1493. float: right;
  1494. padding: 0 18rpx;
  1495. border-radius: 22rpx;
  1496. background-color: #f7f7f7;
  1497. color: #7f7f7f;
  1498. font-size: 24rpx;
  1499. text-align: center;
  1500. .min-text {
  1501. margin: 0 6rpx;
  1502. }
  1503. }
  1504. .p-login {
  1505. height: 56rpx;
  1506. line-height: 56rpx;
  1507. color: $color-system;
  1508. font-size: $font-size-24;
  1509. &.grade {
  1510. .price-left {
  1511. float: left;
  1512. .none {
  1513. display: block;
  1514. font-size: $font-size-20;
  1515. line-height: 48rpx;
  1516. color: #4a4b54;
  1517. float: left;
  1518. font-weight: bold;
  1519. margin-left: 5rpx;
  1520. text {
  1521. letter-spacing: 4rpx;
  1522. font-size: $font-size-32;
  1523. }
  1524. }
  1525. }
  1526. }
  1527. .p-no {
  1528. float: left;
  1529. margin-right: 5rpx;
  1530. font-size: $font-size-28;
  1531. color: $text-color;
  1532. }
  1533. .p-login-btn {
  1534. display: block;
  1535. height: 44rpx;
  1536. padding: 0 10rpx 0 20rpx;
  1537. border-radius: 11rpx;
  1538. background: $btn-confirm;
  1539. float: right;
  1540. line-height: 44rpx;
  1541. color: #ffffff;
  1542. text-align: center;
  1543. font-size: $font-size-24;
  1544. }
  1545. }
  1546. }
  1547. .wrap-label {
  1548. float: left;
  1549. width: 100%;
  1550. box-sizing: border-box;
  1551. .label-a {
  1552. padding: 0 18rpx;
  1553. line-height: 32rpx;
  1554. font-size: $font-size-20;
  1555. color: $color-system;
  1556. text-align: center;
  1557. border-radius: 6rpx;
  1558. background: #ffe6dc;
  1559. margin: 0 20rpx 15rpx 0;
  1560. display: inline-block;
  1561. }
  1562. }
  1563. .wrap-top-price {
  1564. float: left;
  1565. width: 100%;
  1566. box-sizing: border-box;
  1567. .wrap-main-item {
  1568. width: 100%;
  1569. height: 56rpx;
  1570. .p-price {
  1571. height: 56rpx;
  1572. line-height: 56rpx;
  1573. float: left;
  1574. color: #ff2a2a;
  1575. font-weight: bold;
  1576. &.none {
  1577. text-decoration: line-through;
  1578. color: #999999;
  1579. font-weight: normal;
  1580. }
  1581. .txt {
  1582. margin: 0 2rpx;
  1583. }
  1584. .txt.sm {
  1585. font-size: $font-size-26;
  1586. }
  1587. .txt.big {
  1588. font-size: $font-size-34;
  1589. }
  1590. }
  1591. }
  1592. .floor-item-act {
  1593. height: 56rpx;
  1594. text-align: center;
  1595. box-sizing: border-box;
  1596. float: left;
  1597. padding: 10rpx 0;
  1598. margin-left: 10rpx;
  1599. .floor-tags {
  1600. float: right;
  1601. height: 28rpx;
  1602. border-radius: 6rpx;
  1603. background-color: #ffffff;
  1604. line-height: 28rpx;
  1605. color: $color-system;
  1606. text-align: center;
  1607. display: inline-block;
  1608. padding: 0 16rpx;
  1609. font-size: $font-size-20;
  1610. margin-left: 15rpx;
  1611. border: 1px solid #e15616;
  1612. }
  1613. }
  1614. .floor-item-btn {
  1615. float: left;
  1616. height: 40rpx;
  1617. margin-top: 8rpx;
  1618. margin-left: 10rpx;
  1619. .btn {
  1620. line-height: 40rpx;
  1621. padding: 0 20rpx;
  1622. height: 40rpx;
  1623. background: $btn-confirm;
  1624. color: #ffffff;
  1625. font-size: $font-size-20;
  1626. border-radius: 4rpx;
  1627. }
  1628. }
  1629. }
  1630. .wrap-info {
  1631. float: left;
  1632. width: 702rpx;
  1633. padding: 24rpx 24rpx 0 24rpx;
  1634. border-bottom: 1px solid #f8f8f8;
  1635. .info-viewT {
  1636. width: 100%;
  1637. min-height: 40rpx;
  1638. font-size: $font-size-28;
  1639. color: $text-color;
  1640. line-height: 40rpx;
  1641. text-align: left;
  1642. &.none {
  1643. color: #999999;
  1644. }
  1645. .info-viewL {
  1646. min-width: 350rpx;
  1647. float: left;
  1648. margin-bottom: 24rpx;
  1649. }
  1650. .info-viewR {
  1651. min-width: 352rpx;
  1652. float: left;
  1653. margin-bottom: 24rpx;
  1654. }
  1655. }
  1656. .info-viewB {
  1657. width: 100%;
  1658. height: auto;
  1659. }
  1660. .info-f {
  1661. width: 50%;
  1662. float: left;
  1663. font-size: $font-size-28;
  1664. color: $text-color;
  1665. line-height: 40rpx;
  1666. margin-bottom: 24rpx;
  1667. text-align: left;
  1668. }
  1669. }
  1670. }
  1671. .product-seve {
  1672. width: 100%;
  1673. height: 60rpx;
  1674. background-color: #ffffff;
  1675. position: relative;
  1676. display: flex;
  1677. line-height: 60rpx;
  1678. .label {
  1679. font-size: $font-size-28;
  1680. color: #333333;
  1681. }
  1682. .iconfont {
  1683. color: #fea785;
  1684. margin-right: 20rpx;
  1685. font-size: $font-size-22;
  1686. }
  1687. .text {
  1688. font-size: $font-size-22;
  1689. color: #fea785;
  1690. margin-left: 10rpx;
  1691. }
  1692. }
  1693. .product-item-none {
  1694. min-height: 348rpx;
  1695. display: flex;
  1696. flex-direction: column;
  1697. align-items: center;
  1698. border-bottom: 20rpx solid #f7f7f7;
  1699. box-sizing: border-box;
  1700. padding: 40rpx 0;
  1701. .none-image {
  1702. width: 284rpx;
  1703. height: 225rpx;
  1704. }
  1705. .none-text {
  1706. text-align: center;
  1707. font-size: $font-size-28;
  1708. color: #fea785;
  1709. line-height: 40rpx;
  1710. }
  1711. }
  1712. .product-parameter {
  1713. width: 702rpx;
  1714. height: 90rpx;
  1715. padding: 0 24rpx;
  1716. background-color: #ffffff;
  1717. position: relative;
  1718. border-bottom: 20rpx solid #f7f7f7;
  1719. &.coupon {
  1720. .title {
  1721. color: #f94b4b;
  1722. }
  1723. .icon-xiayibu {
  1724. color: #f94b4b;
  1725. }
  1726. .coupon {
  1727. float: right;
  1728. box-sizing: border-box;
  1729. padding: 29rpx 0;
  1730. padding-right: 35rpx;
  1731. .tags {
  1732. height: 32rpx;
  1733. box-sizing: border-box;
  1734. border-radius: 8rpx;
  1735. background-color: #fff1eb;
  1736. line-height: 28rpx;
  1737. color: #f94b4b;
  1738. text-align: center;
  1739. display: inline-block;
  1740. padding: 0 10rpx;
  1741. font-size: $font-size-20;
  1742. border: 1px solid #f94b4b;
  1743. float: right;
  1744. margin: 0 6rpx;
  1745. }
  1746. }
  1747. }
  1748. .title {
  1749. line-height: 90rpx;
  1750. display: inline-block;
  1751. float: left;
  1752. font-size: $font-size-28;
  1753. color: #666666;
  1754. }
  1755. .name {
  1756. line-height: 90rpx;
  1757. display: inline-block;
  1758. float: left;
  1759. font-size: $font-size-28;
  1760. color: $text-color;
  1761. padding-right: 48rpx;
  1762. overflow: hidden;
  1763. text-overflow: ellipsis;
  1764. white-space: nowrap;
  1765. text-align: right;
  1766. }
  1767. .icon-xiayibu {
  1768. line-height: 90rpx;
  1769. display: inline-block;
  1770. position: absolute;
  1771. width: 48rpx;
  1772. top: 0;
  1773. right: 0;
  1774. color: #b2b2b2;
  1775. }
  1776. }
  1777. .product-supplier {
  1778. width: 100%;
  1779. height: 174rpx;
  1780. padding: 30rpx 24rpx;
  1781. box-sizing: border-box;
  1782. background-color: #ffffff;
  1783. position: relative;
  1784. box-sizing: border-box;
  1785. border-bottom: 20rpx solid #f7f7f7;
  1786. .logo {
  1787. width: 128rpx;
  1788. height: 92rpx;
  1789. float: left;
  1790. border: 1px solid #efefef;
  1791. border-radius: 6rpx;
  1792. image {
  1793. width: 100%;
  1794. height: 100%;
  1795. display: block;
  1796. border-radius: 6rpx;
  1797. }
  1798. }
  1799. .main {
  1800. width: 470rpx;
  1801. height: 92rpx;
  1802. float: left;
  1803. margin-left: 20rpx;
  1804. .name {
  1805. width: 100%;
  1806. line-height: 46rpx;
  1807. float: left;
  1808. font-size: $font-size-28;
  1809. color: $text-color;
  1810. float: right;
  1811. overflow: hidden;
  1812. text-overflow: ellipsis;
  1813. white-space: nowrap;
  1814. text-align: left;
  1815. }
  1816. .massgs {
  1817. width: 100%;
  1818. line-height: 46rpx;
  1819. float: left;
  1820. font-size: $font-size-24;
  1821. color: #999999;
  1822. .label {
  1823. float: left;
  1824. }
  1825. .p-stars {
  1826. float: left;
  1827. margin-left: 20rpx;
  1828. }
  1829. .acount {
  1830. float: right;
  1831. text {
  1832. color: $color-system;
  1833. }
  1834. }
  1835. }
  1836. }
  1837. .icon-xiayibu {
  1838. line-height: 154rpx;
  1839. display: inline-block;
  1840. position: absolute;
  1841. width: 48rpx;
  1842. top: 0;
  1843. right: 0;
  1844. color: #b2b2b2;
  1845. }
  1846. }
  1847. .product-details {
  1848. width: 100%;
  1849. background: #ffffff;
  1850. border-bottom: 20rpx solid #f7f7f7;
  1851. &.service {
  1852. border-bottom: none;
  1853. }
  1854. &.recommend {
  1855. background-color: #f7f7f7;
  1856. border-bottom: none;
  1857. .title {
  1858. .title-tab {
  1859. background-color: #f7f7f7;
  1860. color: $text-color;
  1861. }
  1862. }
  1863. }
  1864. .product-rich-text-none {
  1865. box-sizing: border-box;
  1866. padding: 0 24rpx;
  1867. text-align: left;
  1868. font-size: 24rpx;
  1869. color: #999999;
  1870. line-height: 60rpx;
  1871. }
  1872. .content-none {
  1873. width: 100%;
  1874. height: 80rpx;
  1875. line-height: 80rpx;
  1876. text-align: left;
  1877. font-size: $font-size-26;
  1878. color: #999999;
  1879. box-sizing: border-box;
  1880. padding: 0 24rpx;
  1881. }
  1882. .title {
  1883. width: 100%;
  1884. box-sizing: border-box;
  1885. padding: 0 24rpx;
  1886. .title-tab {
  1887. width: 100%;
  1888. height: 100rpx;
  1889. background: #fff;
  1890. z-index: 10;
  1891. font-size: $font-size-30;
  1892. text-align: left;
  1893. color: $text-color;
  1894. line-height: 100rpx;
  1895. font-weight: 600;
  1896. }
  1897. .title-msg {
  1898. width: 100%;
  1899. height: 236rpx;
  1900. padding: 18rpx;
  1901. background-color: rgba(225, 86, 22, 0.1);
  1902. color: $color-system;
  1903. box-sizing: border-box;
  1904. margin-bottom: 30rpx;
  1905. .tit {
  1906. line-height: 46rpx;
  1907. font-size: $font-size-24;
  1908. text-align: left;
  1909. }
  1910. .txt {
  1911. line-height: 38rpx;
  1912. font-size: $font-size-20;
  1913. text-align: justify;
  1914. }
  1915. }
  1916. }
  1917. .content {
  1918. width: 100%;
  1919. background-color: #ffffff;
  1920. }
  1921. }
  1922. .isLower {
  1923. width: 100%;
  1924. height: 116rpx;
  1925. line-height: 116rpx;
  1926. text-align: center;
  1927. color: #000000;
  1928. font-size: $font-size-32;
  1929. font-weight: bold;
  1930. }
  1931. .bottom-btn {
  1932. width: 100%;
  1933. height: 100rpx;
  1934. position: fixed;
  1935. bottom: 0;
  1936. left: 0;
  1937. background: #ffffff;
  1938. z-index: 99;
  1939. .bottom-le {
  1940. width: 300rpx;
  1941. height: 100rpx;
  1942. padding: 10rpx 20rpx 10rpx 0;
  1943. float: left;
  1944. box-sizing: border-box;
  1945. .item-bt {
  1946. width: 80rpx;
  1947. height: 100%;
  1948. margin-right: 15rpx;
  1949. display: flex;
  1950. float: left;
  1951. flex-direction: column;
  1952. align-items: center;
  1953. justify-content: center;
  1954. font-size: $font-size-22;
  1955. color: $text-color;
  1956. line-height: 34rpx;
  1957. position: relative;
  1958. .animation-num {
  1959. font-size: $font-size-32;
  1960. color: #ff2a2a;
  1961. position: absolute;
  1962. top: -12rpx;
  1963. right: 4rpx;
  1964. font-weight: bold;
  1965. }
  1966. .animation {
  1967. animation: showAmnation 2.2s ease-in-out both;
  1968. }
  1969. .restion {
  1970. animation: hideAmnation 1s ease-in-out both;
  1971. }
  1972. .icon-num {
  1973. position: absolute;
  1974. right: -12rpx;
  1975. top: -5rpx;
  1976. }
  1977. .icon-num.goleft {
  1978. right: 2rpx;
  1979. }
  1980. &:last-child {
  1981. margin-right: 0;
  1982. }
  1983. image {
  1984. width: 44rpx;
  1985. height: 44rpx;
  1986. }
  1987. button.contact-btn {
  1988. width: 100%;
  1989. height: 100%;
  1990. margin: 0;
  1991. padding: 0;
  1992. display: flex;
  1993. flex-direction: column;
  1994. align-items: center;
  1995. justify-content: center;
  1996. box-sizing: border-box;
  1997. font-size: $font-size-24;
  1998. text-align: center;
  1999. text-decoration: none;
  2000. line-height: 34rpx;
  2001. border-radius: 0;
  2002. -webkit-tap-highlight-color: transparent;
  2003. overflow: hidden;
  2004. color: $text-color;
  2005. background-color: #ffffff;
  2006. }
  2007. }
  2008. }
  2009. .bottom-ri {
  2010. width: 450rpx;
  2011. height: 100%;
  2012. float: right;
  2013. display: flex;
  2014. box-sizing: border-box;
  2015. padding: 13rpx 20rpx 13rpx 0;
  2016. .btn {
  2017. flex: 1;
  2018. width: 200rpx;
  2019. line-height: 80rpx;
  2020. text-align: center;
  2021. font-size: $font-size-24;
  2022. color: #ffffff;
  2023. }
  2024. .btn-cart {
  2025. background-color: #ffe6dc;
  2026. color: $color-system;
  2027. border-radius: 42rpx 0 0 42rpx;
  2028. }
  2029. .btn-cart.disabled {
  2030. background-color: #e1e1e1;
  2031. color: #ffffff;
  2032. }
  2033. .btn-bay {
  2034. background: linear-gradient(to right, #f28f31 0%, #e15616 100%);
  2035. border-radius: 0 42rpx 42rpx 0;
  2036. }
  2037. .btn-bay.disabled {
  2038. background: linear-gradient(135deg, rgba(242, 143, 49, 0.5) 0%, rgba(225, 86, 22, 0.5) 100%);
  2039. }
  2040. }
  2041. }
  2042. .uni-badge--small {
  2043. -webkit-transform: scale(0.8);
  2044. -ms-transform: scale(0.8);
  2045. transform: scale(0.8);
  2046. -webkit-transform-origin: center center;
  2047. -ms-transform-origin: center center;
  2048. transform-origin: center center;
  2049. }
  2050. .uni-badge {
  2051. font-family: 'Helvetica Neue', Helvetica, sans-serif;
  2052. -webkit-box-sizing: border-box;
  2053. box-sizing: border-box;
  2054. font-size: 12px;
  2055. line-height: 1;
  2056. display: inline-block;
  2057. padding: 3px 6px;
  2058. color: #333;
  2059. border-radius: 100px;
  2060. background-color: #f1f1f1;
  2061. }
  2062. .uni-badge-error {
  2063. color: #fff;
  2064. background-color: #dd524d;
  2065. }
  2066. .product-topnav {
  2067. width: 100%;
  2068. height: 174rpx;
  2069. box-sizing: border-box;
  2070. background: #ffffff;
  2071. z-index: 990;
  2072. position: fixed;
  2073. opacity: 1;
  2074. left: 0;
  2075. &.fixed {
  2076. animation: showFixedColor 0.1s ease-in-out both;
  2077. }
  2078. &.none {
  2079. animation: hideFixedColor 0.1s ease-in-out both;
  2080. }
  2081. .navbar {
  2082. width: 100%;
  2083. height: 60rpx;
  2084. box-sizing: border-box;
  2085. padding: 0 24rpx;
  2086. display: flex;
  2087. .nav-item {
  2088. display: flex;
  2089. flex: 1;
  2090. justify-content: center;
  2091. align-items: center;
  2092. height: 60rpx;
  2093. font-size: $font-size-28;
  2094. color: $text-color;
  2095. position: relative;
  2096. float: left;
  2097. position: relative;
  2098. .line {
  2099. width: 60rpx;
  2100. height: 2px;
  2101. border-radius: 1px;
  2102. background: #ffffff;
  2103. position: absolute;
  2104. bottom: 0;
  2105. left: 50%;
  2106. margin-left: -30rpx;
  2107. }
  2108. &.current {
  2109. color: $color-system;
  2110. .line {
  2111. background: $color-system;
  2112. }
  2113. }
  2114. }
  2115. }
  2116. .search-input {
  2117. width: 100%;
  2118. height: 114rpx;
  2119. padding: 24rpx;
  2120. box-sizing: border-box;
  2121. .gosearch-btn {
  2122. width: 100%;
  2123. height: 100%;
  2124. border-radius: 40rpx;
  2125. margin: 0 auto;
  2126. font-size: 26rpx;
  2127. line-height: 66rpx;
  2128. color: #b2b2b2;
  2129. position: relative;
  2130. box-sizing: border-box;
  2131. padding-left: 66rpx;
  2132. &.fixed {
  2133. background: rgba(70, 70, 70, 0.1);
  2134. }
  2135. &.none {
  2136. background: rgba(70, 70, 70, 0.1);
  2137. }
  2138. .search-icon {
  2139. width: 66rpx;
  2140. height: 66rpx;
  2141. position: absolute;
  2142. left: 0;
  2143. top: 2rpx;
  2144. text-align: center;
  2145. line-height: 66rpx;
  2146. .icon-iconfonticonfontsousuo1 {
  2147. margin: 0 6rpx;
  2148. font-size: $font-size-34;
  2149. color: #b2b2b2;
  2150. z-index: 10;
  2151. }
  2152. }
  2153. .search-text {
  2154. font-size: $font-size-24;
  2155. line-height: 66rpx;
  2156. color: #b2b2b2;
  2157. }
  2158. }
  2159. }
  2160. }
  2161. @keyframes showFixedColor {
  2162. 0% {
  2163. background: rgba(255, 255, 255, 0);
  2164. }
  2165. 50% {
  2166. background: rgba(255, 255, 255, 0.5);
  2167. }
  2168. 100% {
  2169. background: rgba(255, 255, 255, 1);
  2170. }
  2171. }
  2172. @keyframes hideFixedColor {
  2173. 0% {
  2174. background: rgba(255, 255, 255, 1);
  2175. }
  2176. 50% {
  2177. background: rgba(255, 255, 255, 0.5);
  2178. }
  2179. 100% {
  2180. background: rgba(255, 255, 255, 0);
  2181. }
  2182. }
  2183. /* 加入购物模态层*/
  2184. @keyframes showPopup {
  2185. 0% {
  2186. opacity: 0;
  2187. }
  2188. 100% {
  2189. opacity: 1;
  2190. }
  2191. }
  2192. @keyframes hidePopup {
  2193. 0% {
  2194. opacity: 1;
  2195. }
  2196. 100% {
  2197. opacity: 0;
  2198. }
  2199. }
  2200. @keyframes showLayer {
  2201. 0% {
  2202. transform: translateY(0);
  2203. }
  2204. 100% {
  2205. transform: translateY(-100%);
  2206. }
  2207. }
  2208. @keyframes hideLayer {
  2209. 0% {
  2210. transform: translateY(-100%);
  2211. }
  2212. 100% {
  2213. transform: translateY(0);
  2214. }
  2215. }
  2216. @keyframes showAmnation {
  2217. 0% {
  2218. top: -12rpx;
  2219. opacity: 0;
  2220. }
  2221. 50% {
  2222. top: -60rpx;
  2223. opacity: 1;
  2224. }
  2225. 100% {
  2226. top: -100rpx;
  2227. opacity: 0;
  2228. }
  2229. }
  2230. @keyframes hideAmnation {
  2231. 0% {
  2232. top: -100rpx;
  2233. opacity: 0;
  2234. }
  2235. 100% {
  2236. top: -12rpx;
  2237. opacity: 0;
  2238. }
  2239. }
  2240. .popup {
  2241. position: fixed;
  2242. top: 0;
  2243. width: 100%;
  2244. height: 100%;
  2245. z-index: 999;
  2246. display: none;
  2247. .mask {
  2248. position: fixed;
  2249. top: 0;
  2250. width: 100%;
  2251. height: 100%;
  2252. z-index: 21;
  2253. background-color: rgba(0, 0, 0, 0.6);
  2254. }
  2255. .layer {
  2256. position: fixed;
  2257. z-index: 22;
  2258. bottom: -294rpx;
  2259. width: 702rpx;
  2260. padding: 24rpx 24rpx 36rpx 24rpx;
  2261. height: 260rpx;
  2262. border-radius: 20rpx 20rpx 0 0;
  2263. background-color: #fff;
  2264. display: flex;
  2265. flex-wrap: wrap;
  2266. align-content: space-between;
  2267. .content {
  2268. width: 100%;
  2269. }
  2270. .btn {
  2271. width: 100%;
  2272. height: 88rpx;
  2273. margin-top: 20rpx;
  2274. .button {
  2275. width: 100%;
  2276. height: 88rpx;
  2277. color: #fff;
  2278. display: flex;
  2279. align-items: center;
  2280. justify-content: center;
  2281. background: $btn-confirm;
  2282. font-size: $font-size-28;
  2283. border-radius: 44rpx;
  2284. }
  2285. }
  2286. }
  2287. &.show {
  2288. display: block;
  2289. .mask {
  2290. animation: showPopup 0.2s linear both;
  2291. }
  2292. .layer {
  2293. animation: showLayer 0.2s linear both;
  2294. }
  2295. }
  2296. &.hide {
  2297. display: block;
  2298. .mask {
  2299. animation: hidePopup 0.2s linear both;
  2300. }
  2301. .layer {
  2302. animation: hideLayer 0.2s linear both;
  2303. }
  2304. }
  2305. &.none {
  2306. display: none;
  2307. }
  2308. &.service {
  2309. .row {
  2310. margin: 30upx 0;
  2311. .title {
  2312. font-size: 30upx;
  2313. margin: 10upx 0;
  2314. }
  2315. .description {
  2316. font-size: 28upx;
  2317. color: #999;
  2318. }
  2319. }
  2320. }
  2321. .layer-smimg {
  2322. width: 114rpx;
  2323. height: 114rpx;
  2324. float: left;
  2325. border-radius: 10rpx;
  2326. margin-right: 24rpx;
  2327. image {
  2328. width: 114rpx;
  2329. height: 114rpx;
  2330. border-radius: 10rpx;
  2331. }
  2332. }
  2333. .layer-nunbox {
  2334. justify-content: space-between;
  2335. align-items: center;
  2336. width: 536rpx;
  2337. height: auto;
  2338. float: left;
  2339. .layer-nunbox-t {
  2340. width: 100%;
  2341. height: 44rpx;
  2342. position: relative;
  2343. display: flex;
  2344. margin-bottom: 10rpx;
  2345. .text {
  2346. font-size: $font-size-24;
  2347. line-height: 48rpx;
  2348. color: #999999;
  2349. }
  2350. .layer-nunbox-text {
  2351. line-height: 44rpx;
  2352. font-size: $font-size-28;
  2353. }
  2354. .number-box {
  2355. display: flex;
  2356. justify-content: center;
  2357. align-items: center;
  2358. border: 2rpx solid #ffe6dc;
  2359. border-radius: 30rpx;
  2360. height: 48rpx;
  2361. margin-left: 20rpx;
  2362. .iconfont {
  2363. font-size: $font-size-24;
  2364. padding: 0 18rpx;
  2365. color: #999999;
  2366. text-align: center;
  2367. line-height: 48rpx;
  2368. font-weight: bold;
  2369. background: #fef6f3;
  2370. &.icon-jianhao {
  2371. border-radius: 30rpx 0 0 30rpx;
  2372. }
  2373. &.icon-jiahao {
  2374. border-radius: 0 30rpx 30rpx 0;
  2375. }
  2376. }
  2377. .btn-input {
  2378. width: 62rpx;
  2379. height: 48rpx;
  2380. line-height: 48rpx;
  2381. background: #ffffff;
  2382. border-radius: 4rpx;
  2383. text-align: center;
  2384. font-size: $font-size-28;
  2385. }
  2386. }
  2387. .product-step {
  2388. position: absolute;
  2389. left: 45rpx;
  2390. bottom: 0;
  2391. height: 44rpx;
  2392. background: #ffffff;
  2393. }
  2394. }
  2395. .layer-nunbox-b {
  2396. width: 100%;
  2397. height: 44rpx;
  2398. margin-top: 13rpx;
  2399. }
  2400. .text {
  2401. line-height: 44rpx;
  2402. font-size: $font-size-28;
  2403. .p {
  2404. color: #ff2a2a;
  2405. }
  2406. .p:first-child {
  2407. margin-left: 30rpx;
  2408. }
  2409. .p.sm {
  2410. font-size: $font-size-24;
  2411. }
  2412. }
  2413. }
  2414. }
  2415. .tui-popup-box {
  2416. position: relative;
  2417. box-sizing: border-box;
  2418. min-height: 220rpx;
  2419. padding: 24rpx 24rpx 0 24rpx;
  2420. .tui-popup-close {
  2421. width: 90rpx;
  2422. height: 90rpx;
  2423. position: absolute;
  2424. right: 0;
  2425. top: 24rpx;
  2426. line-height: 90rpx;
  2427. text-align: center;
  2428. color: #b2b2b2;
  2429. .icon-iconfontguanbi {
  2430. font-size: $font-size-40;
  2431. }
  2432. }
  2433. .title {
  2434. font-size: $font-size-34;
  2435. color: $text-color;
  2436. line-height: 88rpx;
  2437. text-align: center;
  2438. float: left;
  2439. width: 100%;
  2440. height: 88rpx;
  2441. font-weight: bold;
  2442. }
  2443. .tui-popup-main {
  2444. width: 100%;
  2445. float: left;
  2446. &.coupon {
  2447. padding-bottom: 40rpx;
  2448. .coupon-empty {
  2449. width: 100%;
  2450. height: 600rpx;
  2451. display: flex;
  2452. align-items: center;
  2453. justify-content: center;
  2454. flex-direction: column;
  2455. position: fixed;
  2456. background: $bg-color;
  2457. .empty-container-image {
  2458. width: 150rpx;
  2459. height: 150rpx;
  2460. margin-bottom: 0;
  2461. margin-top: 0;
  2462. }
  2463. .error-text {
  2464. font-size: $font-size-28;
  2465. color: #999999;
  2466. line-height: 88rpx;
  2467. }
  2468. }
  2469. }
  2470. .tui-popup-scroll {
  2471. width: 100%;
  2472. height: 600rpx;
  2473. .coupon-list {
  2474. width: 100%;
  2475. height: 200rpx;
  2476. margin-top: 24rpx;
  2477. box-sizing: border-box;
  2478. background: url(https://static.caimei365.com/app/img/icon/icon-coupon-uesb@2x.png);
  2479. background-size: cover;
  2480. &:last-child {
  2481. margin-bottom: 24rpx;
  2482. }
  2483. .list-cell-le {
  2484. width: 224rpx;
  2485. height: 100%;
  2486. box-sizing: border-box;
  2487. padding: 37rpx 0;
  2488. float: left;
  2489. .coupon-maxMoney {
  2490. width: 100%;
  2491. height: 78rpx;
  2492. line-height: 78rpx;
  2493. font-size: 56rpx;
  2494. color: #ffffff;
  2495. text-align: center;
  2496. .small {
  2497. font-size: $font-size-24;
  2498. }
  2499. }
  2500. .coupon-minMoney {
  2501. width: 100%;
  2502. height: 33rpx;
  2503. line-height: 33rpx;
  2504. font-size: $font-size-24;
  2505. color: #ffffff;
  2506. text-align: center;
  2507. }
  2508. }
  2509. .list-cell-ri {
  2510. width: 478rpx;
  2511. height: 100%;
  2512. box-sizing: border-box;
  2513. padding: 20rpx 24rpx 0 24rpx;
  2514. float: right;
  2515. .list-cell-top {
  2516. width: 100%;
  2517. height: 121rpx;
  2518. float: left;
  2519. border-bottom: 1px solid #e1e1e1;
  2520. .list-cell-type {
  2521. width: 286rpx;
  2522. height: 100%;
  2523. float: left;
  2524. .list-cell-tags {
  2525. width: 100%;
  2526. height: 32rpx;
  2527. margin-bottom: 7rpx;
  2528. .tags {
  2529. display: inline-block;
  2530. padding: 0 10rpx;
  2531. height: 32rpx;
  2532. line-height: 32rpx;
  2533. background-color: #ffdcce;
  2534. color: #f94b4b;
  2535. font-size: $font-size-20;
  2536. border-radius: 8rpx;
  2537. text-align: center;
  2538. float: left;
  2539. }
  2540. }
  2541. .list-cell-texts {
  2542. width: 100%;
  2543. height: auto;
  2544. line-height: 35rpx;
  2545. text-overflow: ellipsis;
  2546. display: -webkit-box;
  2547. word-break: break-all;
  2548. -webkit-box-orient: vertical;
  2549. -webkit-line-clamp: 2;
  2550. overflow: hidden;
  2551. font-size: 26rpx;
  2552. color: #333333;
  2553. }
  2554. }
  2555. .list-cell-btn {
  2556. width: 128rpx;
  2557. height: 100%;
  2558. float: right;
  2559. .icon-used {
  2560. width: 100%;
  2561. height: 100%;
  2562. box-sizing: border-box;
  2563. padding-top: 57rpx;
  2564. .icon-used-btn {
  2565. width: 128rpx;
  2566. height: 48rpx;
  2567. border-radius: 28rpx;
  2568. line-height: 48rpx;
  2569. font-size: $font-size-26;
  2570. text-align: center;
  2571. &.receive {
  2572. background-image: linear-gradient(270deg, #f94b4b 0%, #feb673 100%);
  2573. color: #ffffff;
  2574. }
  2575. &.make {
  2576. border: solid 1px #f94b4b;
  2577. color: #f94b4b;
  2578. }
  2579. }
  2580. }
  2581. }
  2582. }
  2583. .list-cell-time {
  2584. width: 100%;
  2585. height: 58rpx;
  2586. line-height: 58rpx;
  2587. text-align: left;
  2588. font-size: $font-size-20;
  2589. color: #999999;
  2590. }
  2591. }
  2592. }
  2593. &.train {
  2594. height: 240rpx;
  2595. }
  2596. .content-tr {
  2597. width: 100%;
  2598. min-height: 58rpx;
  2599. line-height: 58rpx;
  2600. display: flex;
  2601. .content-td {
  2602. display: flex;
  2603. flex: 3;
  2604. font-size: $font-size-26;
  2605. color: #999999;
  2606. line-height: 58rpx;
  2607. text-align: left;
  2608. }
  2609. .content-th {
  2610. display: flex;
  2611. flex: 7;
  2612. font-size: $font-size-26;
  2613. color: #333333;
  2614. line-height: 58rpx;
  2615. text-align: left;
  2616. padding-left: 10rpx;
  2617. }
  2618. }
  2619. }
  2620. }
  2621. }
  2622. .tui-popup-btn {
  2623. width: 100%;
  2624. height: auto;
  2625. float: left;
  2626. margin-top: 24rpx;
  2627. .tui-button {
  2628. width: 100%;
  2629. height: 88rpx;
  2630. background: $btn-confirm;
  2631. line-height: 88rpx;
  2632. text-align: center;
  2633. color: #ffffff;
  2634. font-size: $font-size-28;
  2635. border-radius: 44rpx;
  2636. }
  2637. }
  2638. /*富文本样式*/
  2639. rich-text.p {
  2640. width: 702rpx !important;
  2641. padding: 0 24rpx;
  2642. text-align: justify;
  2643. }
  2644. rich-text.img {
  2645. width: 100%;
  2646. height: auto;
  2647. }
  2648. </style>