| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285 |
- <!--
- Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
- https://www.mall4j.com/
- 未经允许,不可做商业用途!
- 版权所有,侵权必究!
- -->
- <template>
- <div
- class="Mall4j page-detail"
- @click="onClosePop"
- >
- <!-- 面包屑导航 -->
- <div
- v-if="!scoreFee"
- class="crumbs-shop"
- >
- <div class="content">
- <div class="crumbs" />
- <div class="shop-box">
- <router-link
- v-if="prodInfo.shopId"
- :to="{
- path: '/shop-index',
- query: {
- sid: prodInfo.shopId
- }
- }"
- class="shop"
- >
- <i
- v-if="shopInfo && shopInfo.shopId === 1"
- class="self"
- >{{
- $t('prodDetail.selfEmployed')
- }}</i>
- <i
- v-if="shopInfo && shopInfo.shopId !== 1"
- class="shop-icon"
- />
- {{ shopInfo ? shopInfo.shopName : '' }}
- </router-link>
- <a
- href="javascript:void(0)"
- class="im-chat"
- @click="toChatIm(prodInfo)"
- ><span class="btn-im" />{{ $t('prodDetail.contactCustomerService') }}</a>
- <span
- v-if="!isShopCollection"
- class="favourite"
- @click="toggleShopCollect"
- >
- <i class="favourite-icon" />{{ $t('prodDetail.collectionStores') }}
- </span>
- <span
- v-else
- class="favourite active"
- @click="toggleShopCollect"
- >
- <i class="favourite-icon" />{{ $t('prodDetail.collectedStores') }}
- </span>
- <a
- href="javascript:void(0)"
- class="im-chat"
- @click="onToQualifications(prodInfo)"
- >
- <img
- src="@/assets/images/qualifications.png"
- style="width: 16px;height: 16px;margin-right: 5px;float: left"
- >
- {{ $t('shopInfo.qualifications') }}
- </a>
- </div>
- </div>
- </div>
- <!-- /面包屑导航 -->
- <!-- 积分面包屑导航 -->
- <div
- v-if="scoreFee"
- class="crumbs-shop"
- >
- <div class="content">
- <div class="crumbs" />
- </div>
- </div>
- <!-- /积分面包屑导航 -->
- <div class="content">
- <div class="detail-up">
- <!-- 商品图片 -->
- <div class="img">
- <div class="big-img">
- <ImgShow
- v-if="(!prodInfo.video || !showVideo) && prodInfo.pic"
- :src="prodInfo.pic"
- @error="changePicUrl"
- />
- <img
- v-if="(!prodInfo.video || !showVideo) && !prodInfo.pic"
- src="@/assets/img/def.png"
- alt
- >
- <!-- 商品视频 -->
- <video
- v-show="showVideo"
- id="prodVideo"
- class="big-img prod-video"
- :src="checkFileUrl(prodInfo.video)"
- controls
- @error="prodInfo.video=''"
- />
- <!-- 商品视频end -->
- <div
- v-if="showPlayBtn && prodInfo.video"
- class="oper-btn"
- >
- <img
- src="@/assets/images/play.png"
- :alt="$t('prodDetail.play')"
- @click="playVideo"
- >
- </div>
- <div
- v-if="!showPlayBtn && showVideo"
- class="close-btn"
- >
- <img
- src="@/assets/images/close.png"
- :alt="$t('userCenter.close')"
- @click="stopVideo"
- >
- </div>
- </div>
- <div class="small-img">
- <i
- class="left-arrow"
- :class="{
- limit: prodImgs.length - 5 <= 0 || offsetCount < 1
- }"
- @click="prevImg"
- ><</i>
- <i
- class="right-arrow"
- :class="{
- limit:
- prodImgs.length - 5 <= 0 ||
- offsetCount >= prodImgs.length - 5
- }"
- @click="nextImg"
- >></i>
- <div class="img-box">
- <div
- ref="carouserRef"
- class="offset-box"
- >
- <div
- v-for="(item, index) in prodImgs"
- :key="index"
- class="item"
- :class="{ active: item.isActive }"
- @mouseover="changeProdImg(index)"
- >
- <ImgShow :src="item.img" />
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- /商品图片 -->
- <!-- 商品详情 -->
- <div
- v-if="!scoreFee"
- class="info"
- >
- <div class="name-box">
- <div class="name">
- {{ prodInfo.prodName }}
- </div>
- <div class="des">
- <div
- :title="prodInfo.brief"
- class="brief"
- >
- {{ prodInfo.brief }}
- </div>
- <span
- v-if="discountDet.length && prodInfo.prodType !== 5 && (!productActivity.seckill || productActivity.seckill && countdown.obj.signs===0)"
- class="discount-info"
- >
- <a
- href="javascript:void(0)"
- class="go-discount"
- @click="toDiscountDetail(discountDet[0].discountId)"
- >
- {{ discountDet[0].discountName
- }}{{ $t('prodDetail.specialZone') }},{{
- discountDet[0].endTime.substring(0, 10)
- }}{{ $t('prodDetail.deadline') }},{{
- $t('prodDetail.grabYourCopyNow')
- }}
- <span class="arr">>></span>
- </a>
- </span>
- </div>
- </div>
- <!-- 预售商品 -->
- <div
- v-if="prodInfo.preSellStatus === 1 && prodInfo.prodType !== 1 && prodInfo.prodType !== 2"
- class="activity"
- >
- <div class="name flash-sale">
- {{ $t('prodDetail.preSale') }}
- </div>
- <div class="limit">
- {{ $t('prodDetail.expected') }} {{
- prodInfo.preSellTime
- }} {{ $t('prodDetail.startShipping') }}
- </div>
- </div>
- <!-- /预售商品 -->
- <!-- 拼团商品 -->
- <div
- v-if="(prodInfo.prodType === 1 && productActivity.groupActivity) || (prodInfo.prodType === 2 && productActivity.seckill)"
- class="activity"
- >
- <div :class="['name', prodInfo.prodType === 2 ? 'flash-sale' : 'group-buy']">
- <span v-if="prodInfo.prodType === 1">{{ $t('prodDetail.groupingTogetherForMoreBenefits') }}</span>
- <span v-else> {{ productActivity.seckill.prodName ? productActivity.seckill.prodName : $t('spike.secondsOfActivity') }} </span>
- </div>
- <div class="limit">
- {{ $t('prodDetail.distanceActivity') }}
- {{ countdown.obj.signs ? $t('end') : $t('start') }}
- {{ $t('onlyLeft') }}:
- <span
- v-if="countdown.obj.day"
- class="time"
- >{{ countdown.obj.day }}{{ $t('day')
- }}{{ countdown.obj.hou }}:{{ countdown.obj.min }}:{{
- countdown.obj.sec
- }}</span>
- <span
- v-else
- class="time"
- >{{ countdown.obj.hou }}:{{ countdown.obj.min }}:{{
- countdown.obj.sec
- }}</span>
- </div>
- </div>
- <!-- /拼团商品 -->
- <div class="price-box">
- <div class="item goods-price">
- <span class="tit">{{ $t('price') }}</span>
- <div class="con">
- <div
- v-if="prodInfo.prodType === 2 && (countdownFlag || seckillDefSku)"
- class="price"
- >
- ¥
- <span class="big">{{ parsePrice(defaultSku.seckillPrice || seckillDefSku?.seckillPrice)[0] }}</span>
- .{{ parsePrice(defaultSku.seckillPrice || seckillDefSku?.seckillPrice)[1] }}
- </div>
- <div
- v-else
- class="price"
- >
- ¥
- <span class="big">{{ parsePrice(productActivity.groupActivity ? defaultSku.actPrice : defaultSku.price)[0] }}</span>
- .{{ parsePrice(productActivity.groupActivity ? defaultSku.actPrice : defaultSku.price)[1] }}
- </div>
- <!-- 商品销售价大于市场价时 不展示市场价 -->
- <div
- v-if="
- ((productActivity.groupActivity ? defaultSku.price : defaultSku.oriPrice) &&
- (productActivity.groupActivity ? defaultSku.price : defaultSku.oriPrice) > (productActivity.groupActivity ? defaultSku.actPrice : defaultSku.price))
- || (prodInfo.prodType === 2 && (defaultSku.priceFee || defaultSku.price) > (defaultSku.seckillPrice || seckillDefSku?.seckillPrice))
- "
- class="old-price"
- >
- ¥{{ productActivity.groupActivity ? defaultSku.price : (defaultSku.oriPrice || defaultSku.price || defaultSku.priceFee || seckillDefSku?.priceFee) }}
- </div>
- </div>
- <template v-if="findSku && prodInfo.deliveryModeVO?.hasShopDelivery">
- <span class="tit">{{
- $t('prodDetail.remainingInventory')
- }}</span>
- <div class="con">
- {{ prodInfo.prodType === 2 && countdownFlag ? defaultSku.seckillStocks : defaultSku.stocks }}
- </div>
- </template>
- </div>
- <!-- 预售 -->
- <div
- v-if="!(prodInfo.prodType !== 2 && prodInfo.prodType !== 1) && prodInfo.preSellStatus === 1"
- class="item coupons"
- >
- <span class="tit">{{ $t('prodDetail.preSale') }}</span>
- <div class="con pre-sale-red">
- {{ $t('prodDetail.thisItemIsAPreSaleItem') }},{{
- $t('prodDetail.expected')
- }} {{ cutDate(prodInfo.preSellTime) }} {{
- $t('prodDetail.startShipping')
- }}
- </div>
- </div>
- <!-- /预售 -->
- <!-- 领券 -->
- <div
- v-if="couponList.length > 0 && prodInfo.prodType !== 5"
- class="item coupons"
- >
- <span class="tit">{{ $t('vouchers') }}</span>
- <div class="con">
- <div
- v-for="coupon in couponList"
- :key="coupon.couponId"
- class="coupon-block"
- @click="receiveCoupon(coupon)"
- >
- <span
- v-if="coupon.couponType === 1 && $t('full') === '满'"
- class="conpon"
- >{{ $t('full') }}{{ $t('yuan') + coupon.cashCondition }}{{ $t('less')
- }}{{ $t('yuan') }}{{ coupon.reduceAmount }}</span>
- <span
- v-if="coupon.couponType === 2 && $t('full') === '满'"
- class="conpon"
- >{{ $t('full') }}{{ $t('yuan') + coupon.cashCondition }}{{ $t('enjoy')
- }}{{ coupon.couponDiscount }}{{ $t('fold') }}</span>
- <!-- 英文版优惠卷样式 -->
- <span
- v-if="coupon.couponType === 1 && $t('full') !== '满'"
- class="conpon"
- >{{ $t('yuan') + coupon.reduceAmount + ' off over '
- }}{{ $t('yuan') + coupon.cashCondition }}</span>
- <span
- v-if="coupon.couponType === 2 && $t('full') !== '满'"
- class="conpon"
- >{{ coupon.couponDiscount + '%' + ' off over' }}
- {{ $t('yuan') + coupon.cashCondition }}</span>
- </div>
- <router-link
- to="/coupons"
- class="more"
- >
- {{ $t('more') }}
- <i class="arrow">>></i>
- </router-link>
- </div>
- </div>
- <!-- /领券 -->
- <!-- 限时特惠 -->
- <div
- v-if="(discountDet.length && !productActivity.groupActivity && (!productActivity.seckill || productActivity.seckill && countdown.obj.signs===0)) || productActivity.giveaway && productActivity.giveaway.giveawayProds.length"
- class="item discount"
- >
- <span class="tit">{{ $t('promotion') }}</span>
- <div class="con">
- <div class="discount-con">
- <div
- v-if="productActivity.giveaway && productActivity.giveaway.giveawayProds.length"
- class="discount-item"
- >
- <div class="type">
- {{ $t('prodDetail.gift') }}
- </div>
- <router-link
- v-for="(item, giveawayProdsIndex) in productActivity.giveaway.giveawayProds"
- :key="giveawayProdsIndex"
- :to="{
- path:'/detail',
- query:{
- prodId:item.prodId
- }
- }"
- target="_blank"
- class="packge-item"
- >
- <ImgShow
- :src="item.pic"
- :class-list="['img']"
- />
- <div class="count">
- ×{{ item.giveawayNum }}
- </div>
- </router-link>
- </div>
- <div
- v-for="(item, index) in discountDet"
- :key="item.discountId"
- class="discount-item"
- :class="index > 0 ? 'item-box' : ''"
- >
- <div class="type">
- {{
- [
- $t('prodDetail.fullAmountReduction'),
- $t('prodDetail.fullPieceDiscount'),
- $t('prodDetail.fullDiscount'),
- $t('prodDetail.discountOnFullItems')
- ][item.discountRule]
- }}
- </div>
- <div class="text">
- {{ item.discountName }}
- </div>
- <a
- href="javascript:void(0)"
- class="det"
- @click="toDiscountDetail(item.discountId)"
- >
- {{ $t('more') }}
- <span class="arr">>></span>
- </a>
- </div>
- </div>
- </div>
- </div>
- <!-- /限时特惠 -->
- <!-- 虚拟商品-说明 -->
- <div
- v-if="
- prodInfo.mold === 1 &&
- (prodInfo.writeOffNum !== 0 ||
- (prodInfo.writeOffNum === 0 && prodInfo.isRefund === 0))
- "
- class="item"
- >
- <span class="tit">{{ $t('prodDetail.instructions') }}</span>
- <!-- writeOffNum 0无需核销 1单次核销 -1多次核销 -->
- <span v-if="prodInfo.writeOffNum !== 0">
- <!-- writeOffTime核销有效期 -1.长期有效 0.自定义 1.当天24点前 x.x天内有效 -->
- <span v-if="prodInfo.writeOffTime === -1">{{
- $t('prodDetail.longTermValidity')
- }}</span>
- <span v-else-if="prodInfo.writeOffTime === 0">{{ $t('prodDetail.afterPurchase') }}
- {{ prodInfo.writeOffStart }} {{ $t('prodDetail.to') }}
- {{ prodInfo.writeOffEnd }}
- <i v-if="$t('language') === 'zh_CN'">{{
- $t('prodDetail.effective')
- }}</i></span>
- <span v-else-if="prodInfo.writeOffTime === 1">{{
- $t('prodDetail.validOnTheSameDay')
- }}</span>
- <span v-else>{{ $t('prodDetail.purchase') }}{{ prodInfo.writeOffTime
- }}{{ $t('prodDetail.validDay') }}</span>
- </span>
- <span v-if="prodInfo.isRefund === 0"><span v-if="prodInfo.writeOffNum !== 0">,</span>{{ $t('prodDetail.refundsAreNotAllowed') }}</span>
- </div>
- </div>
- <div
- v-if="prodInfo.skuList && prodInfo.skuList.length"
- class="sku-box"
- >
- <div
- v-for="(skuLine, key) in skuGroup"
- :key="key"
- class="items sku-text"
- >
- <span class="tit">{{ key.replace(';', '') }}</span>
- <div class="con">
- <span
- v-for="(skuLineItem, index) in skuLine"
- :key="index"
- class="item"
- :class="[
- selectedProp.find(
- el => el.key === key.replace(';', '') && el.value === skuLineItem
- )
- ? 'active'
- : '',
- isSkuLineItemNotOptional(
- allProperties,
- selectedPropObj,
- key,
- skuLineItem,
- propKeys
- )
- ? 'not-optional'
- : ''
- ]"
- @click="toChooseItem(skuLineItem, key, $event)"
- >{{ skuLineItem }}</span>
- </div>
- </div>
- <div
- v-if="prodInfo.mold === 2 && combineList?.length > 0"
- class="items"
- >
- <span class="tit">{{ $t('prodDetail.comboDetail') }}</span>
- <div class="con">
- <combine-detail
- :combine="combineList"
- />
- </div>
- </div>
- </div>
- <!-- 计数器 -->
- <div
- v-if="prodInfo.deliveryModeVO?.hasShopDelivery"
- class="sku-box"
- >
- <div class="items">
- <span class="tit">{{ $t('quantity') }}</span>
- <div class="con">
- <div class="goods-number">
- <span
- :class="['reduce', prohibit1 ? 'limit' : '']"
- @click="reduce"
- >-</span>
- <input
- v-model="prodNum"
- type="number"
- class="number"
- oninput="value=value.replace(/[^\d]/g,'')"
- @blur="judgeInput"
- >
- <span
- :class="['increase', prohibit2 ? 'limit' : '']"
- @click="increase"
- >+</span>
- </div>
- <!-- 秒杀/拼团限购提示 -->
- <div
- v-if="countdown.obj.signs && ((prodInfo.prodType === 1 && productActivity.groupActivity?.maxNum > 0) || (prodInfo.prodType === 2 && productActivity.seckill?.maxNum > 0))"
- class="purchase-limit"
- >
- {{ $t('prodDetail.eventLimit') }}
- <span class="font-red"> {{ prodInfo.prodType === 1 ? productActivity.groupActivity?.maxNum : productActivity.seckill?.maxNum }} </span>
- {{ $t('prodDetail.piece') }}
- </div>
- </div>
- </div>
- </div>
- <!-- 配送 -->
- <!-- 虚拟商品和组合选品不显示 -->
- <div
- v-if="addrInfo && prodInfo.mold !== 1 && prodInfo.mold !== 3 && prodInfo.prodType !== 5"
- class="sku-box"
- >
- <div
- v-if="prodInfo.deliveryModeVO?.hasShopDelivery"
- class="items"
- >
- <span class="tit">{{ $t('prodDetail.delivery') }}</span>
- <div class="delivery-con">
- <div
- class="delivery-info"
- @click.stop="onOpenDeliveryPop()"
- >
- {{ addrInfo.province }} {{ addrInfo.city }} {{ addrInfo.area }}
- <el-icon>
- <ArrowDownBold />
- </el-icon>
- </div>
- <div
- v-if="isShowDeliveryPop"
- class="delivery-pop"
- >
- <div
- v-for="item in deliveryList"
- :key="item.addrId"
- class="delivery-item"
- :class="{active: item.addrId === addrInfo.addrId}"
- @click.stop="onSelectDelivery(item.addrId)"
- >
- {{ item.receiver }}、{{ item.mobile }}、{{ item.province }}{{ item.city }}{{ item.area }}{{ item.addr }}
- </div>
- </div>
- <div class="delivery-free">
- <span v-if="([0, 1, 2].includes(prodInfo.prodType) && (!findSku || !defaultSku.warehouseStock))">
- {{ $t('prodDetail.noStockTips') }}
- </span>
- <span v-else-if="!isDelivery">{{ $t('prodDetail.notDeliveryTips') }}</span>
- <span v-else-if="!defaultSku.isHasStock">{{ $t('prodDetail.noStockRegionTips') }}</span>
- <span v-else>{{ totalTransFee===0 ? $t('prodDetail.freeShipping') :`${$t('prodDetail.shippingFee')} ¥ ${totalTransFee.toFixed(2)}` }}</span>
- </div>
- </div>
- </div>
- </div>
- <!-- 商品按钮 -->
- <div
- class="btns"
- :class="prodInfo.prodType === 1?'group-btn':''"
- >
- <!-- 普通商品按钮 -->
- <template v-if="prodInfo.prodType === 0 || (prodInfo.prodType === 1 && !productActivity.groupActivity || prodInfo.prodType === 2 && !productActivity.seckill)">
- <!-- 立即购买 -->
- <a
- v-if="!prodInfo.deliveryModeVO?.hasShopDelivery || (findSku && defaultSku.stocks)"
- href="javascript:void(0)"
- :class="['buy-now', isGrayBtn ? 'shortage' : '' ]"
- @click="buyNow"
- >{{ $t('buyNow') }}
- <span
- v-if="!prodInfo.deliveryModeVO?.hasShopDelivery"
- class="qr-code"
- >
- <span class="text"> {{ $t('prodDetail.scanCode') }}</span>
- <div :class="['code-img', !prodInfo.deliveryModeVO?.hasShopDelivery ? getQrcode('getQrCode') : 'display-none']">
- <canvas id="getQrCode" />
- </div>
- </span>
- </a>
- <!-- 无货: 禁用sku; 缺货: 库存为0 -->
- <a
- v-if="prodInfo.deliveryModeVO.hasShopDelivery && (!findSku || !defaultSku.stocks)"
- href="javascript:void(0)"
- class="shortage"
- >{{ !findSku ? $t('prodDetail.productOutOfStock') : $t('prodDetail.productNotInStock') }}</a>
- <!-- 加入购物车 -->
- <a
- v-if="prodInfo.preSellStatus !== 1 && findSku && defaultSku.stocks&& prodInfo.deliveryModeVO.hasShopDelivery"
- href="javascript:void(0)"
- :class="['add-cart', !defaultSku.isHasStock || !isDelivery ? 'shortage' : '']"
- @click="addToCart"
- >{{ $t('prodDetail.addToCart') }}</a>
- </template>
- <!-- 普通商品按钮 end -->
- <!-- 团购商品按钮 -->
- <template v-if="prodInfo.prodType === 1 && productActivity.groupActivity">
- <a
- v-if="findSku"
- href="javascript:void(0)"
- :class="[
- 'build-group',
- countdown.obj.signs ? '' : 'disabled-gray',
- store.locale === 'en' ? 'en' : ''
- ]"
- >
- <span class="group-price">
- ¥{{ defaultSku.actPrice ? defaultSku.actPrice.toFixed(2) : '' }}
- </span>
- <span class="group-text">
- {{ $t('prodDetail.iWantToOpenAGroup') }}
- </span>
- <div class="group-code">
- <span class="text">
- {{ countdown.obj.signs ? $t('prodDetail.cellPhoneScanCodeOpenGroup') : $t('prodDetail.groupingActivitiesHaveNotStarted') }}
- </span>
- <div :class="['code-img', countdown.obj.signs ? '' : 'display-none']">
- <canvas id="groupQrcode" />
- </div>
- </div>
- </a>
- <a
- href="javascript:void(0)"
- :class="[
- 'alone-group',
- !findSku || !defaultSku.isHasStock || !isDelivery ? 'cannotbuy' : '',
- store.locale === 'en' ? 'en' : ''
- ]"
- @click="buyNow"
- >
- <span class="group-price">¥{{ Number(defaultSku.price).toFixed(2) }}</span>
- <span class="group-text">{{ $t(`prodDetail.${prodInfo.prodType === 1 ? 'separatePurchase' : 'grabYourCopyNow'}`) }}</span>
- <span
- v-if="!prodInfo.deliveryModeVO?.hasShopDelivery"
- class="qr-code"
- >
- <span class="text">{{ $t('prodDetail.scanCode') }}</span>
- <div :class="['code-img', !prodInfo.deliveryModeVO?.hasShopDelivery ? getQrcode('groupQrcodeTwo') : 'display-none']">
- <canvas id="groupQrcodeTwo" />
- </div>
- </span>
- </a>
- <a
- v-if="findSku && defaultSku.stocks&&prodInfo.deliveryModeVO?.hasShopDelivery"
- href="javascript:void(0)"
- class="add-cart add-cart-group"
- :class="['add-cart add-cart-group', defaultSku.isHasStock && isDelivery ? '' : 'disabled-gray']"
- @click="addToCart"
- >
- <span>{{ $t('prodDetail.addToCart') }}</span>
- </a>
- </template>
- <!-- 团购商品按钮 end -->
- <!-- 秒杀商品按钮 -->
- <template v-if="prodInfo.prodType === 2 && productActivity.seckill">
- <!-- 无货: 禁用sku; 缺货: 库存为0 -->
- <a
- v-if="!defaultSku.stationStock && !defaultSku.warehouseStock && (countdown.obj.signs === 1 && (!findSku || !defaultSku.seckillStocks)) || (!countdown.obj.signs && (!findSku || !defaultSku.stocks))"
- href="javascript:void(0)"
- class="shortage"
- >{{ !findSku ? $t('prodDetail.productOutOfStock') : $t('prodDetail.productNotInStock') }}</a>
- <a
- v-if="(defaultSku.seckillStocks || defaultSku.stationStock || defaultSku.warehouseStock) && countdown.obj.signs === 1"
- href="javascript:void(0)"
- class="buy-now"
- :class="[countdown.obj.signs && !isGrayBtn ? '' : 'disabled-gray']"
- @click="buyNow"
- >{{ $t('prodDetail.grabYourCopyNow') }}
- <span
- v-if="!prodInfo.deliveryModeVO?.hasShopDelivery"
- class="qr-code"
- >
- <span class="text">{{ $t('prodDetail.scanCode') }}</span>
- <div :class="['code-img', !prodInfo.deliveryModeVO?.hasShopDelivery ? getQrcode('groupQrcodeTwo') : 'display-none']">
- <canvas id="groupQrcodeTwo" />
- </div>
- </span>
- </a>
- <a
- v-if="defaultSku.stocks && countdown.obj.signs !== 1 "
- href="javascript:void(0)"
- :class="['buy-now', isGrayBtn ? 'shortage' : '']"
- @click="buyNow"
- >{{ $t('prodDetail.retailPricePurchase') }}
- <span
- v-if="!prodInfo.deliveryModeVO?.hasShopDelivery"
- class="qr-code"
- >
- <span class="text">{{ $t('prodDetail.scanCode') }}</span>
- <div :class="['code-img', !prodInfo.deliveryModeVO?.hasShopDelivery ? getQrcode('groupQrcodeTwo') : 'display-none']">
- <canvas id="groupQrcodeTwo" />
- </div>
- </span></a>
- </template>
- <!-- 秒杀商品按钮 end -->
- <!-- 公共按钮 -->
- <!-- 活动商品按钮 -->
- <a
- v-if="prodInfo.prodType === 5"
- href="javascript:void(0)"
- class="shortage"
- >{{ $t('prodDetail.notAvailableForPurchase') }}</a>
- <!-- 收藏/取选收藏 -->
- <a
- href="javascript:void(0)"
- :class="!isCollection ? 'collect': 'collected'"
- @click="toggleCollect()"
- >
- <i class="icon" />{{ !isCollection ? $t('prodDetail.collectionOfProducts') : $t('prodDetail.bookmarked') }}
- </a>
- </div>
- </div>
- <!-- 商品详情 -->
- <!-- 积分商品详情 -->
- <div
- v-else
- class="info"
- >
- <div class="name-box">
- <div class="name">
- {{ prodInfo.prodName }}
- </div>
- <div class="des">
- {{ prodInfo.brief }}
- </div>
- </div>
- <div class="price-box">
- <div class="item goods-price">
- <span class="tit">{{ $t('price') }}</span>
- <div class="con">
- <div class="price">
- <span class="big">{{ defaultSku.skuScore }}</span>
- <span class="text">{{ $t('prodDetail.points') }}</span>
- </div>
- <div
- v-if="defaultSku.price"
- class="add-symbol"
- >
- +
- </div>
- <div
- v-if="defaultSku.price"
- class="price"
- >
- ¥
- <span class="big">{{ parsePrice(defaultSku.price)[0] }}</span>
- .{{ parsePrice(defaultSku.price)[1] }}
- </div>
- </div>
- <template v-if="findSku && prodInfo.deliveryModeVO?.hasShopDelivery">
- <span class="tit">{{ $t('prodDetail.remainingInventory') }}</span>
- <div class="con">
- {{ defaultSku.stocks }}
- </div>
- </template>
- </div>
- <!-- 销售价大于等于市场价 市场价不展示 -->
- <div
- v-if="defaultSku.oriPrice > defaultSku.price"
- class="item goods-price"
- >
- <span class="tit">{{ $t('prodDetail.originalPrice') }}</span>
- <div class="con">
- <div class="old-price">
- ¥{{ defaultSku.oriPrice.toFixed(2) }}
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="prodInfo.skuList && prodInfo.skuList.length"
- class="sku-box"
- >
- <div
- v-for="(skuLine, key) in skuGroup"
- :key="key"
- class="items sku-text"
- >
- <span class="tit">{{ key.replace(';', '') }}</span>
- <div class="con">
- <span
- v-for="skuLineItem in skuLine"
- :key="skuLineItem"
- class="item"
- :class="[
- selectedProp.find(
- el => el.key === key.replace(';', '') && el.value === skuLineItem
- )
- ? 'active'
- : '',
- isSkuLineItemNotOptional(
- allProperties,
- selectedPropObj,
- key,
- skuLineItem,
- propKeys
- )
- ? 'not-optional'
- : ''
- ]"
- @click="toChooseItem(skuLineItem, key, $event)"
- >{{ skuLineItem }}</span>
- </div>
- </div>
- </div>
- <!-- 计数器 -->
- <div
- v-if="prodInfo.deliveryModeVO?.hasShopDelivery"
- class="sku-box"
- >
- <div class="items">
- <span class="tit">{{ $t('quantity') }}</span>
- <div class="con">
- <div class="goods-number">
- <span
- :class="['reduce', prohibit1 ? 'limit' : '']"
- @click="reduce"
- >-</span>
- <input
- v-model="prodNum"
- type="number"
- class="number"
- oninput="value=value.replace(/[^\d]/g,'')"
- @blur="judgeInput"
- >
- <span
- :class="['increase', prohibit2 ? 'limit' : '']"
- @click="increase"
- >+</span>
- </div>
- </div>
- </div>
- <div
- v-if="addrInfo && prodInfo.deliveryModeVO?.hasShopDelivery"
- class="items"
- >
- <span class="tit">{{ $t('prodDetail.delivery') }}</span>
- <div class="delivery-con">
- <div
- class="delivery-info"
- @click.stop="onOpenDeliveryPop()"
- >
- {{ addrInfo.province }} {{ addrInfo.city }} {{ addrInfo.area }}
- <el-icon>
- <ArrowDownBold />
- </el-icon>
- </div>
- <div
- v-if="isShowDeliveryPop"
- class="delivery-pop"
- >
- <div
- v-for="item in deliveryList"
- :key="item.addrId"
- class="delivery-item"
- :class="{active: item.addrId === addrInfo.addrId}"
- @click.stop="onSelectDelivery(item.addrId)"
- >
- {{ item.receiver }}、{{ item.mobile }}、{{ item.province }}{{ item.city }}{{ item.area }}{{ item.addr }}
- </div>
- </div>
- <div class="delivery-free">
- <span v-if="(prodInfo.prodType === 3 && (!findSku || !defaultSku.warehouseStock))">
- {{ $t('prodDetail.noStockTips') }}
- </span>
- <span v-else-if="!isDelivery">{{ $t('prodDetail.notDeliveryTips') }}</span>
- <span v-else-if="!defaultSku.isHasStock">{{ $t('prodDetail.noStockRegionTips') }}</span>
- <span v-else>{{ totalTransFee===0 ? $t('prodDetail.freeShipping') :`${$t('prodDetail.shippingFee')} ¥ ${totalTransFee.toFixed(2)}` }}</span>
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="prodInfo.prodType !== 1"
- class="btns"
- >
- <a
- v-if="findSku && defaultSku.stocks"
- href="javascript:void(0)"
- :class="['buy-now', !isDelivery ? 'shortage' : '' ]"
- @click="buyNow"
- >{{ $t('buyNow') }}</a>
- <a
- v-else-if="!findSku"
- href="javascript:void(0)"
- class="shortage"
- >{{ $t('prodDetail.productNotInStock') }}</a>
- <a
- v-else-if="!defaultSku.stocks"
- href="javascript:void(0)"
- class="shortage"
- >{{ $t('prodDetail.productOutOfStock') }}</a>
- </div>
- </div>
- <!-- /积分商品详情 -->
- </div>
- <div
- v-if="comboList && comboList.length"
- class="detail-down"
- >
- <div class="introduce-box packages">
- <div class="tab">
- <div
- v-for="(combo,index) in comboList"
- :key="index"
- class="item"
- :class="{active: selectComboId === combo.comboId }"
- @click="selectCombo(combo.comboId)"
- >
- {{ combo.name }}
- </div>
- </div>
- <!-- defaultCombo -->
- <div
- v-if="defaultCombo"
- class="packages-content"
- >
- <div class="left">
- <div class="prod-box">
- <ImgShow
- :src="defaultCombo.mainProd.pic"
- :class-list="['img']"
- />
- <div class="prod-name">
- {{ defaultCombo.mainProd.prodName }}
- </div>
- <div class="price">
- ¥{{ price(defaultCombo.mainProd.comboPrice) }}
- <span class="combo-count">x {{ defaultCombo.mainProd.leastNum }}</span>
- </div>
- </div>
- <div
- v-if="defaultCombo.matchingProds.length"
- class="add-icon"
- />
- <div
- v-for="(item, index) in defaultCombo.matchingProds"
- :key="index"
- class="prod-box necessary"
- >
- <ImgShow
- :src="item.pic"
- :class-list="['img']"
- />
- <div class="prod-name">
- {{ item.prodName }}
- </div>
- <div class="price">
- <div class="price-count-con">
- <input
- type="checkbox"
- :style="{cursor: item.required ? 'not-allowed' : 'pointer'}"
- class="checkbox default"
- :class="{ checked: isChecked(item), default: 1 }"
- @click="selectComboItem(item)"
- >
- <span>¥{{ price(item.comboPrice) }}</span>
- </div>
- <span class="combo-count">x {{ item.leastNum }}</span>
- </div>
- </div>
- </div>
- <div class="right">
- <div class="mean-icon" />
- <div class="settlement-box">
- <div class="text">
- {{ $t("package.selected") }}{{ choiceCombNum }}{{ $t("package.packageItem") }}
- </div>
- <div class="text item">
- {{ $t("package.packagePrice") }}
- <span class="price-text item">¥{{ comboAmount }}</span>
- </div>
- <div
- class="btn item"
- @click="handleSelectPackage"
- >
- {{ $t("buyNow") }}
- </div>
- <div
- class="btn-add-cart item"
- @click="handleSelectPackage"
- >
- {{ $t("prodDetail.addToCart") }}
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="!scoreFee"
- class="detail-down detail-comment"
- >
- <div class="introduce-box">
- <div class="tab">
- <div
- :class="['item', introduceOrCommentInt ? 'active' : '']"
- @click="toggleIntroduceInt"
- >
- {{ $t('prodDetail.productIntroduction') }}
- </div>
- <div
- :class="['item', introduceOrCommentCom ? 'active' : '']"
- @click="toggleIntroduceCom"
- >
- {{ $t('prodDetail.productReviews') }}
- <i class="number">({{ prodCommData.number }})</i>
- </div>
- </div>
- <!-- <transition name="fade"> -->
- <!-- 商品介绍 -->
- <div
- v-show="introduceOrCommentInt"
- class="introduce"
- >
- <div>
- <div
- v-for="(params, index) in prodParameterList"
- :key="index"
- class="params"
- >
- <div
- v-for="item in params"
- :key="item.prodParameterId"
- class="params-box"
- >
- <div class="key">
- {{ item.parameterKey }}
- </div>
- <div
- :title="item.parameterValue"
- class="value"
- >
- {{ item.parameterValue }}
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="prodInfo.content"
- v-rich="prodInfo.content"
- />
- </div>
- <div
- v-if="introduceOrCommentCom"
- class="comment"
- >
- <!-- 好评率 -->
- <div class="good-rates">
- <div class="score">
- <div class="tit">
- {{ $t('prodDetail.favorableRatingRate') }}:
- </div>
- <div class="con">
- {{ prodCommData.positiveRating }}%
- </div>
- </div>
- <div class="average">
- <div class="item">
- <div class="text">
- 5.0
- </div>
- <div class="stars">
- <i class="star" />
- <i class="star" />
- <i class="star" />
- <i class="star" />
- <i class="star" />
- </div>
- <div class="number">
- ({{ prodCommData.scoreNumber5 }})
- </div>
- </div>
- <div class="item">
- <div class="text">
- 4.0
- </div>
- <div class="stars">
- <i class="star" />
- <i class="star" />
- <i class="star" />
- <i class="star" />
- <i class="star-gray" />
- </div>
- <div class="number">
- ({{ prodCommData.scoreNumber4 }})
- </div>
- </div>
- <div class="item">
- <div class="text">
- 3.0
- </div>
- <div class="stars">
- <i class="star" />
- <i class="star" />
- <i class="star" />
- <i class="star-gray" />
- <i class="star-gray" />
- </div>
- <div class="number">
- ({{ prodCommData.scoreNumber3 }})
- </div>
- </div>
- <div class="item">
- <div class="text">
- 2.0
- </div>
- <div class="stars">
- <i class="star" />
- <i class="star" />
- <i class="star-gray" />
- <i class="star-gray" />
- <i class="star-gray" />
- </div>
- <div class="number">
- ({{ prodCommData.scoreNumber2 }})
- </div>
- </div>
- <div class="item">
- <div class="text">
- 1.0
- </div>
- <div class="stars">
- <i class="star" />
- <i class="star-gray" />
- <i class="star-gray" />
- <i class="star-gray" />
- <i class="star-gray" />
- </div>
- <div class="number">
- ({{ prodCommData.scoreNumber1 }})
- </div>
- </div>
- </div>
- </div>
- <!-- /好评率 -->
- <!-- 评论列表 -->
- <div class="comment-tab">
- <div
- class="item"
- :class="evaluate === -1 ? 'active' : ''"
- @click="getProdCommPageByProd(-1)"
- >
- {{ $t('all') }}
- <span class="number">({{ prodCommData.number }})</span>
- </div>
- <div
- class="item"
- :class="evaluate === 0 ? 'active' : ''"
- @click="getProdCommPageByProd(0)"
- >
- {{ $t('prodDetail.goodReview') }}
- <span class="number">({{ prodCommData.praiseNumber }})</span>
- </div>
- <div
- class="item"
- :class="evaluate === 1 ? 'active' : ''"
- @click="getProdCommPageByProd(1)"
- >
- {{ $t('prodDetail.mediumRating') }}
- <span class="number">({{ prodCommData.secondaryNumber }})</span>
- </div>
- <div
- class="item"
- :class="evaluate === 2 ? 'active' : ''"
- @click="getProdCommPageByProd(2)"
- >
- {{ $t('prodDetail.poorReviews') }}
- <span class="number">({{ prodCommData.negativeNumber }})</span>
- </div>
- <div
- class="item"
- :class="evaluate === 3 ? 'active' : ''"
- @click="getProdCommPageByProd(3)"
- >
- {{ $t('prodDetail.withPictures') }}
- <span class="number">({{ prodCommData.picNumber }})</span>
- </div>
- </div>
- <div
- v-if="prodCommList.length"
- class="comment-con"
- >
- <div
- v-for="(item, comIndex) in prodCommList"
- :key="item.prodCommId"
- class="item"
- >
- <div class="buyer-msg">
- <div class="img">
- <img
- v-if="item.pic"
- :src="checkFileUrl(item.pic)"
- alt
- @error="item.pic=''"
- >
- <img
- v-else
- src="@/assets/images/buyer-img.png"
- alt
- >
- </div>
- <div class="name">
- {{
- item.isWriteOff ?
- $t('prodDetail.userOff') :
- (item.nickName
- ? item.nickName
- : $t('prodDetail.anonymousUser'))
- }}
- </div>
- </div>
- <div class="buyer-comment">
- <div style="display: flex">
- <div
- class="stars"
- style="width:95px"
- >
- <i
- v-for="index in item.score"
- :key="index"
- class="star"
- />
- </div>
- <div style="color: #999">
- {{ item.skuName || '' }}
- </div>
- </div>
- <div class="text">
- <span style="white-space:pre-wrap;">{{
- item.content
- }}</span>
- </div>
- <div
- v-if="item.pics"
- class="img-box"
- >
- <div
- v-for="(img, imgIndex1) in item.prodImgs"
- :key="imgIndex1"
- class="img"
- >
- <ImgShow
- :src="img"
- @handle-click="()=>imgShow(comIndex, imgIndex1)"
- />
- <div
- v-if="showBigImg"
- class="big-img-show"
- >
- <i
- class="left-arrow"
- @click="prevImgCom()"
- ><</i>
- <i
- class="right-arrow"
- @click="nextImgCom()"
- >></i>
- <div
- class="mask"
- @click="closeShowBigImg()"
- />
- <ImgShow :src="imgPath" />
- </div>
- </div>
- </div>
- <div class="time-sku">
- <span class="time">{{ item.recTime }}</span>
- </div>
- <div
- v-if="item.replyContent"
- class="seller-reply"
- >
- <div class="tit">
- {{ $t('prodDetail.merchantResponse') }}:
- </div>
- <div class="con">
- {{ item.replyContent }}
- </div>
- <div class="time">
- {{ item.replyTime }}
- </div>
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="!prodCommList.length"
- class="comment-con"
- >
- <div class="comment-empty">
- {{ $t('prodDetail.noComments') }}
- </div>
- </div>
- <!-- /评论列表 -->
- <!-- 页码 -->
- <div class="pagination">
- <div
- v-if="page.pages >= 1"
- class="pages"
- >
- <a
- href="javascript:void(0);"
- class="item prev"
- :class="{ default: page.current <= 1 }"
- @click="getSearchProdPage(page.current - 1)"
- >{{ $t('pagination.previousPage') }}</a>
- <div
- v-for="item in page.rainbow"
- :key="item.prodId"
- >
- <a
- v-if="item !== '...'"
- href="javascript:void(0);"
- class="item"
- :class="{ cur: page.current === item }"
- @click="getSearchProdPage(item)"
- >{{ item }}</a>
- <span
- v-else
- class="ellipsis"
- >...</span>
- </div>
- <a
- href="javascript:void(0);"
- class="item next"
- :class="{ default: page.current > page.pages - 1 }"
- @click="getSearchProdPage(page.current + 1)"
- >{{ $t('pagination.nextPage') }}</a>
- <div class="total-num">
- {{ $t('pagination.total') }}
- <span class="num">{{ page.pages }}</span>{{ $t('pagination.page') }}
- </div>
- </div>
- <!-- /页码 -->
- </div>
- </div>
- <!-- /商品评论 -->
- <!-- </transition> -->
- </div>
- <div
- v-if="!scoreFee"
- class="side"
- >
- <!-- 店内搜索 -->
- <div class="shop-search">
- <div class="tit">
- {{ $t('prodDetail.inStoreSearch') }}
- </div>
- <div class="con">
- <input
- v-model="prodName"
- type="text"
- class="text"
- >
- <a
- href="javascript:void(0)"
- class="btn"
- @click="toShopIndex"
- />
- </div>
- </div>
- <!-- /店内搜索 -->
- <!-- 店内分类 -->
- <div class="shop-category">
- <div class="tit">
- {{ $t('prodDetail.inStoreCategories') }}
- </div>
- <div class="con">
- <div
- v-for="(item, index) in shopCategorys"
- :key="index"
- class="items active"
- >
- <router-link
- :to="{
- path:'/shop-prod-list',
- query:{
- sid:prodInfo.shopId,
- cid:item.categoryId
- }
- }
- "
- >
- <div class="item-main">
- {{ item.categoryName }}
- </div>
- </router-link>
- </div>
- </div>
- </div>
- <!-- 店内分类 -->
- <!-- 热销产品 -->
- <div class="sale-well">
- <div class="tit">
- {{ $t('prodDetail.hotProducts') }}
- </div>
- <div class="con">
- <div
- v-for="item in hotSales"
- :key="item.prodId"
- class="item"
- >
- <router-link
- :to="{
- path:'/detail',
- query:{
- prodId:item.prodId
- }
- }"
- target="_blank"
- >
- <div class="goods-img">
- <ImgShow :src="item.pic" />
- </div>
- <div class="goods-msg">
- <div class="goods-name">
- {{ item.prodName }}
- </div>
- <div class="goods-price">
- <div class="price">
- ¥
- <span class="big">{{ parsePrice(item.price)[0] }}</span>
- .{{ parsePrice(item.price)[1] }}
- </div>
- </div>
- </div>
- </router-link>
- </div>
- </div>
- </div>
- <!-- 热销产品 -->
- </div>
- </div>
- <div
- v-if="scoreFee"
- class="detail-down"
- >
- <div class="introduce-box">
- <div class="tab">
- <div class="item active">
- {{ $t('prodDetail.productIntroduction') }}
- </div>
- </div>
- <!-- 商品介绍 -->
- <div class="introduce">
- <div
- v-if="prodInfo.content"
- v-rich="prodInfo.content"
- />
- </div>
- <!-- /商品介绍 -->
- </div>
- <div class="side">
- <!-- 热销产品 -->
- <div
- class="sale-well"
- style="margin:0"
- >
- <div class="tit">
- {{ $t('prodDetail.recommendGoodies') }}
- </div>
- <div class="con">
- <div
- v-for="item in scoreList"
- :key="item.prodId"
- class="item"
- @click="toScoreProdDet(item.prodId,item.scorePrice)"
- >
- <div class="goods-img">
- <ImgShow :src="item.pic" />
- </div>
- <div class="goods-msg">
- <div class="goods-name">
- {{ item.prodName }}
- </div>
- <div class="goods-price">
- <div class="icon">
- <img
- src="@/assets/images/member-pic/integral-icon.png"
- alt
- >
- </div>
- <div class="integral-price">
- {{ item.scorePrice }} {{ $t('prodDetail.points') }}
- </div>
- <div
- v-if="item.price > 0"
- class="add"
- >
- +
- </div>
- <div
- v-if="item.price > 0"
- class="price"
- >
- ¥{{ item.price }}
- </div>
- </div>
- <div class="old-price">
- {{ $t('prodDetail.marketPrice') }}¥{{ item.oriPrice }}
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 热销产品 -->
- </div>
- </div>
- </div>
- <!-- 滑动导航 -->
- <transition name="fade">
- <div
- v-if="showScrollTab"
- class="scroll-tab"
- >
- <div class="content">
- <div class="shop-search">
- <input
- v-model="prodName"
- type="text"
- class="text"
- :placeholder="$t('prodDetail.inStoreSearch')"
- >
- <a
- href="javascript:void(0)"
- class="btn"
- @click="toShopIndex"
- />
- </div>
- <div class="tab">
- <div
- :class="['item', introduceOrCommentInt ? 'active' : '']"
- @click="toggleIntroduceInt"
- >
- {{ $t('prodDetail.productIntroduction') }}
- </div>
- <div
- :class="['item', introduceOrCommentCom ? 'active' : '']"
- @click="toggleIntroduceCom"
- >
- {{ $t('prodDetail.productReviews') }}
- <i class="number">({{ prodCommData.number }})</i>
- </div>
- </div>
- <div
- class="add-cart-btn"
- @click="addToCart"
- >
- {{ $t('prodDetail.addToCart') }}
- </div>
- </div>
- </div>
- </transition>
- <!-- /滑动导航 -->
- <!-- 弹窗 -->
- <div
- v-if="false"
- class="popup-mask"
- />
- <div
- v-if="false"
- class="popup-box"
- >
- <div class="tit">
- <div class="text">
- {{ $t('tips') }}
- </div>
- <div class="close" />
- </div>
- <div class="con">
- <div class="tip">
- <div
- class="tip-
- success"
- />
- <div class="tip-info">
- <div class="result">
- {{ $t('prodDetail.congratulationsYouHaveSuccessfullyReceived') }}
- <span class="number"> <i class="small">¥</i>500 </span>{{ $t('discountCoupon') }}!
- </div>
- <div class="date">
- {{ $t('prodDetail.timeOfUse') }}:2019.12.12-2019.12.12
- </div>
- <div class="btns">
- <a
- href="javascript:void(0)"
- class="btn"
- >
- {{ $t('prodDetail.viewCouponsCollected') }}
- <span class="arrow">>></span>
- </a>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- /弹窗 -->
- <!-- 登录弹窗组件 -->
- <LoginPopup
- v-if="showLogin"
- @hide-login-pop="hideLoginPop"
- />
- <!-- /登录弹窗组件 -->
- <!-- 选择套餐 -->
- <SelectPackage
- v-if="showSelectPackage"
- ref="selectPackageRef"
- :shop-info="shopInfo"
- :combo-id="selectComboId"
- :select-match-ids="selectMatchIds"
- @hide-select-package="hideSelectPackage"
- />
- </div>
- </template>
- <script setup>
- import QRCode from 'qrcode'
- import Cookie from 'vue-cookies'
- import { bus } from '@/utils/bus.js'
- import Big from 'big.js'
- import * as pageUtil from '@/utils/pageUtil'
- import DOMPurify from 'dompurify'
- import * as util from '@/utils'
- import { tapLog } from '@/utils/flow'
- import LoginPopup from '@/components/login-popup/index.vue'
- import SelectPackage from '@/components/select-package/index.vue'
- import { checkFileUrl } from '@/utils/index.js'
- import { ElMessage, ElMessageBox } from 'element-plus'
- import defaultUrl from '@/assets/img/def.png'
- import CombineDetail from './components/combine-detail/index.vue'
- // 截取日期: 2020-11-25 00:00:00 -> 2020-11-25
- const cutDate = (dateStr) => {
- if (!dateStr) return ''
- return dateStr.split(' ')[0]
- }
- const price = (value) => {
- if (value) {
- return value.toFixed(2)
- }
- return 0.00
- }
- const store = useLanguageStore()
- const h5Path = import.meta.env.VITE_APP_H5_DOMAIN
- const router = useRouter()
- const route = useRoute()
- const scoreFee = route.query.scoreFee
- const prodId = ref(route.query.prodId)
- const defaultCombo = ref(null)
- const selectMatchIds = ref([])
- const comboAmount = computed(() => {
- if (!defaultCombo.value) {
- return 0
- }
- let price = new Big(defaultCombo.value.mainProd.comboPrice).times(defaultCombo.value.mainProd.leastNum)
- defaultCombo.value.matchingProds.forEach(item => {
- if (selectMatchIds.value.findIndex(id => id === item.prodId) >= 0) {
- price = price.plus(new Big(item.comboPrice).times(item.leastNum))
- }
- })
- price = price.toFixed(2)
- return price
- })
- // 按钮置灰
- const isGrayBtn = computed(() => {
- return prodInfo.value?.deliveryModeVO?.hasShopDelivery && (!defaultSku.value?.isHasStock || !isDelivery.value)
- })
- const defaultSku = ref({}) // 选中的sku
- const prodNum = ref(1) // 计数器数量
- const prohibit1 = ref(true) // 计数器-是否禁用
- const prohibit2 = ref(false) // 计数器+是否禁用
- watch(prodNum, (nv) => {
- if (nv <= 1) {
- prohibit1.value = true
- if (defaultSku.value.stocks === 0 || nv === defaultSku.value.stocks) {
- prohibit2.value = true
- }
- } else if (nv === defaultSku.value.stocks) {
- prohibit1.value = false
- prohibit2.value = true
- } else {
- prohibit1.value = false
- prohibit2.value = false
- }
- })
- watch(() => defaultSku.value, () => {
- const key = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (!defaultSku.value[key]) {
- prodNum.value = 0
- prohibit1.value = true
- prohibit2.value = true
- }
- })
- let prodVideo = ''
- const scoreList = ref({})
- const prodInfo = ref({})
- const prodCommData = ref({})
- const discountDet = ref([]) // 限时特惠专区详情
- const prodParameterList = ref([])
- const showPlayBtn = ref(true) // 视频播放按钮
- const comboList = ref([])
- onMounted(async () => {
- if (Cookie.get('bbcToken')) await onOpenDeliveryPop(false)
- await getProdInfo()
- if (!scoreFee) {
- getShopHead(prodInfo.value.shopId)
- watchPreSellTime()
- // 监听预售时间
- prodInfo.value.content = prodInfo.value.content ? DOMPurify.sanitize(util.formatHtml(prodInfo.value.content), { ADD_ATTR: ['target'] }) : ''
- let flag = 0
- prodParameterList.value[flag] = []
- const isProdParameterList = prodInfo.value.prodParameterList || []
- for (let i = 0; i < isProdParameterList.length; i++) {
- const params = isProdParameterList[i]
- if (i % 3 === 0 && i !== 0) {
- flag++
- prodParameterList.value[flag] = []
- }
- prodParameterList.value[flag].push(params)
- }
- // 查询商品是否已经收藏
- isProdCollected()
- isShopCollected()
- // 获取店铺分类
- getShopCategory()
- // 获取热销商品
- getHotSales()
- // 获取商品评论数
- http.get('/prod/prodCommData', {
- params: {
- prodId: route.query.prodId
- }
- }).then(({ data }) => {
- handleProdComm(data.prodCommDtoPage)
- prodCommData.value = data
- })
- // 优惠券
- getCouponList()
- // 通过商品id获取商品所有促销活动
- http.get('/marking/discount/getDiscountByProdId', {
- params: {
- prodId: route.query.prodId
- }
- }).then(({ data }) => {
- discountDet.value = data
- })
- // 监听页面滚动
- window.addEventListener('scroll', scrollToTop)
- }
- if (comboList.value && comboList.value.length > 0) {
- selectCombo(comboList.value[0].comboId)
- }
- if (prodInfo.value.video) {
- // 获取商品视频
- prodVideo = document.getElementById('prodVideo')
- showPlayBtn.value = true
- }
- // 组装sku
- if (prodInfo.value.prodType === 0 || prodInfo.value.prodType === 3) {
- groupSkuProp(prodInfo.value.skuList, prodInfo.value.price)
- } else {
- // 秒杀/团购 商品
- groupBuyInfo()
- }
- // 保存足迹 (积分商品不保留足迹)
- if (Cookie.get('bbcToken')) {
- http.post('/p/prodBrowseLog', {
- prodId: route.query.prodId
- })
- }
- // 积分推荐商品列表
- recommendGoods()
- })
- const recommendGoods = () => {
- http.get('/search/page', {
- params: {
- current: 1,
- size: 20,
- prodType: 3,
- sort: 2,
- stationId: 0 // 过滤掉门店发布的商品
- }
- }).then(({ data }) => {
- scoreList.value = data.records[0].products
- })
- }
- let timer = null// 倒计时定时器
- let preSellTimer = null// 倒计时定时器
- onUnmounted(() => {
- // 页面销毁时移除监听
- !scoreFee && window.removeEventListener('scroll', scrollToTop)
- clearTimeout(timer)
- clearTimeout(preSellTimer)
- })
- // 秒杀默认sku
- const seckillDefSku = computed(() => {
- const { seckillSkuList, activityStatus } = seckillActInfo.value
- if (activityStatus === 1) {
- return seckillSkuList.find(f => f.skuId === defaultSku.value.skuId) || null
- }
- return null
- })
- const seckillActInfo = ref({})
- const getSeckillInfo = async (addrId) => {
- let userId = null
- if (Cookie.get('bbcToken')) {
- userId = userStore.userId
- }
- const commonAddrItem = deliveryList.value.find(item => item.commonAddr === 1)
- await http.get('/seckill/prod', {
- params: {
- seckillId: prodInfo.value.activityId,
- addrId: addrId || (commonAddrItem ? commonAddrItem.addrId : 0),
- userId: userId || '',
- needPointStock: false
- }
- }).then(({ data }) => {
- if (data.activityStatus === 1) {
- seckillActInfo.value = data
- const { seckillSkuList } = seckillActInfo.value
- let minProdPriceInfo = {
- price: Number.MAX_VALUE
- }
- seckillSkuList.forEach(item => {
- if (minProdPriceInfo.price > item.seckillPrice) {
- minProdPriceInfo = item
- }
- })
- groupSkuProp(prodInfo.value.skuList, minProdPriceInfo.priceFee)
- return
- }
- data.seckillSkuList.forEach(item => {
- item.seckillStocks = item.stock
- item.isHasStock = item.hasStock
- })
- prodInfo.value.productActivity.seckill.seckillSkuList = data.seckillSkuList
- groupSkuProp(data.seckillSkuList, data.seckillPrice)
- })
- .catch(() => {
- groupSkuProp(prodInfo.value.skuList, prodInfo.value.priceFee)
- })
- }
- const formatDate = (val) => {
- if (val) {
- return util.tsToDate(val.replace(/-/g, '/'), 'Y-M-D')
- }
- }
- const updateMetaTags = (prodInfo) => {
- const prodName = prodInfo?.prodName
- const keyWords = prodInfo?.keyWords
- const brief = prodInfo?.brief
- // 设置页面标题
- if (prodName) {
- document.title = prodName
- } else {
- document.title = $t('product.productDetails')
- }
- // 更新 keywords meta 标签
- if (keyWords) {
- let metaKeywords = document.querySelector("meta[name='keywords']")
- if (!metaKeywords) {
- metaKeywords = document.createElement('meta')
- metaKeywords.setAttribute('name', 'keywords')
- document.head.appendChild(metaKeywords)
- }
- metaKeywords.setAttribute('content', keyWords)
- }
- // 更新 description meta 标签
- if (brief) {
- let metaDescription = document.querySelector("meta[name='description']")
- if (!metaDescription) {
- metaDescription = document.createElement('meta')
- metaDescription.setAttribute('name', 'description')
- document.head.appendChild(metaDescription)
- }
- metaDescription.setAttribute('content', brief)
- }
- }
- const productActivity = computed(() => {
- return prodInfo.value.productActivity || {}
- })
- const totalStocks = ref(0)
- const shopId = ref('')
- const addrInfo = ref(null) // 用户地址
- const totalTransFee = ref(0) // 运费
- let addrId = 0 // 用户选择的地址id
- const isDelivery = ref(true) // 是否支持配送
- const prodImgs = ref([])
- const userStore = useUserStore()
- const getProdInfo = (addrId) => {
- let userId = null
- if (Cookie.get('bbcToken')) {
- userId = userStore.userId
- }
- const commonAddrItem = deliveryList.value.find(item => item.commonAddr === 1)
- return new Promise((resolve, reject) => {
- http.get('/prod/prodInfo', {
- params: {
- prodId: route.query.prodId,
- userId,
- needPointStock: false,
- addrId: addrId || (commonAddrItem ? commonAddrItem.addrId : 0),
- dvyType: 1
- }
- })
- .then(({ data }) => {
- const isProdImgs = []
- if (data.imgs) {
- if (data.imgs[0]) {
- data.imgs.split(',').forEach(imgStr => {
- isProdImgs.push({
- img: imgStr,
- isActive: false
- })
- })
- isProdImgs[0].isActive = true
- }
- }
- data.deliveryModeVO = data.deliveryModeVO || JSON.parse(data.deliveryMode)
- prodInfo.value = data
- updateMetaTags(data)
- totalStocks.value = data.totalStocks
- isDelivery.value = data.isDelivery
- prodInfo.value.preSellTime = formatDate(prodInfo.value.preSellTime)
- // 将组合关联商品拷贝一份至团购规格下
- if (data.productActivity.groupActivity) {
- if (data.productActivity.groupActivity.groupSkuList) {
- data.productActivity.groupActivity.groupSkuList = data.productActivity.groupActivity.groupSkuList.map(item => {
- const skuInfo = data.skuList.find(i => i.skuId === item.skuId)
- item.warehouseStock = skuInfo?.warehouseStock || item.stocks
- data.mold && (item.skuComboList = skuInfo.skuComboList)
- return item
- })
- }
- }
- prodImgs.value = isProdImgs
- shopId.value = data.shopId
- // 处理套餐 (主商品不支持快递不显示该套餐,非必选的搭配商品不支持快递不显示该商品,必选的搭配商品不支持快递不显示该套餐
- if (data.productActivity.comboList && data.productActivity.comboList.length) {
- const conboListLen = data.productActivity.comboList.length
- for (let conboIndex = conboListLen - 1; conboIndex >= 0; conboIndex--) {
- const conboItem = data.productActivity.comboList[conboIndex]
- conboItem.mainProd.deliveryMode = conboItem.mainProd.deliveryMode ? JSON.parse(conboItem.mainProd.deliveryMode) : {}
- if (!conboItem.mainProd.deliveryMode.hasShopDelivery) {
- // 主商品不支持快递配送,则移除该套餐
- data.productActivity.comboList.splice(conboIndex, 1)
- continue
- }
- let flag = false // 判断搭配商品是否存在必选但是不支持快递配送的
- const matchingProdsLen = conboItem.matchingProds?.length || 0 // 搭配商品数组长度
- for (let matchingSpuIndex = matchingProdsLen - 1; matchingSpuIndex >= 0; matchingSpuIndex--) {
- // 搭配商品item
- const matchingProdItem = conboItem.matchingProds[matchingSpuIndex]
- // 配送方式
- matchingProdItem.deliveryMode = matchingProdItem.deliveryMode ? JSON.parse(matchingProdItem.deliveryMode) : {}
- if (matchingProdItem.deliveryMode.hasShopDelivery) {
- continue
- } else if (matchingProdItem.required) {
- // 不支持快递配送,且为必选的搭配商品,则将该套餐移除
- flag = true
- break
- } else {
- // 不支持快递配送,但是非必选,则将该商品移除
- conboItem.matchingProds.splice(matchingSpuIndex, 1)
- }
- }
- if (flag) {
- data.productActivity.comboList.splice(conboIndex, 1)
- continue
- }
- }
- }
- comboList.value = data.productActivity.comboList || []
- totalTransFee.value = data.userDeliveryInfo && data.userDeliveryInfo.totalTransFee
- addrInfo.value = data.userDeliveryInfo && data.userDeliveryInfo.userAddr
- resolve(true)
- })
- .catch(err => {
- reject(err)
- if (err.data.code === 'A00001') {
- setTimeout(() => {
- router.push({ path: '/' })
- }, 1500)
- }
- })
- })
- }
- /**
- * 监听预售时间
- */
- const watchPreSellTime = () => {
- preSellTimer = setInterval(() => {
- const preSellTimeStamp = Date.parse(prodInfo.value.preSellTime)
- const nowTimeStamp = Date.now()
- if (preSellTimeStamp - nowTimeStamp <= 0) {
- clearTimeout(preSellTimer)
- // 开始售卖,重新获取商品信息
- http.get('/prod/prodInfo', {
- params: {
- prodId: route.query.prodId,
- dvyType: 1
- }
- }).then(({ data }) => {
- prodInfo.value = data
- })
- }
- }, 1000)
- }
- /**
- * 页面滚动事件
- */
- const introduceOrCommentInt = ref(true) // true商品介绍 false商品评论
- const showScrollTab = ref(false)
- const scrollToTop = util._throttle(() => {
- showScrollTab.value = getRectTop() <= 0
- }, 100)
- const getRectTop = () => {
- const element = document.querySelector('.detail-comment')
- const rect = element.getBoundingClientRect()
- return rect.top
- }
- /**
- * 评论点击图片显示大图
- */
- const imgPath = ref('') // 当前点击的评论图片
- const prodCommList = ref([])
- const showBigImg = ref(false) // 评论大图显隐
- let bigComIndex = -1 // 评论大图切换
- let bigImgIndex = -1 // 评论大图切换
- const imgShow = (comIndex, imgIndex) => {
- bigComIndex = comIndex
- document.documentElement.style.overflowY = 'hidden'
- const bigProdImgs = prodCommList.value[comIndex].prodImgs.length
- if (imgIndex === -1) {
- closeShowBigImg()
- bigImgIndex = -1
- bigComIndex = -1
- return
- }
- if (imgIndex === bigProdImgs) {
- closeShowBigImg()
- bigImgIndex = -1
- bigComIndex = -1
- return
- }
- imgPath.value = prodCommList.value[comIndex].prodImgs[imgIndex]
- if (imgPath.value) {
- showBigImg.value = true
- }
- bigImgIndex = imgIndex
- }
- const prevImgCom = () => {
- const comIndex = bigComIndex
- const imgIndex = bigImgIndex - 1
- imgShow(comIndex, imgIndex)
- }
- const nextImgCom = () => {
- const comIndex = bigComIndex
- const imgIndex = bigImgIndex + 1
- imgShow(comIndex, imgIndex)
- }
- // 获取选中套餐数量
- const selectMatchNum = () => {
- if (defaultCombo.value.mainProd) {
- let mainProdNum = defaultCombo.value.mainProd.leastNum
- if (defaultCombo.value.matchingProds.length) {
- defaultCombo.value.matchingProds.forEach(item => {
- if (item.isChecked) {
- mainProdNum += item.leastNum
- }
- })
- }
- return mainProdNum
- }
- }
- /**
- * 关闭评论大图显隐
- */
- const closeShowBigImg = () => {
- showBigImg.value = false
- document.documentElement.style.overflowY = ''
- }
- /**
- * 关闭视频
- */
- const showVideo = ref(false) // 是否展示视频
- const stopVideo = () => {
- showVideo.value = false
- if (prodVideo) {
- prodVideo.pause()
- }
- showPlayBtn.value = true
- }
- /**
- * 播放视频
- */
- const playVideo = () => {
- showVideo.value = true
- prodVideo.play(0)
- showPlayBtn.value = false
- }
- // 切换图片
- const carouserRef = ref(null)
- const offsetCount = ref(0) // 图片偏移数
- const prevImg = () => {
- if (prodImgs.value.length - 5 > 0) {
- if (offsetCount.value > 0) {
- offsetCount.value--
- carouserRef.value.style.left = '-' + 78 * offsetCount.value + 'px'
- } else {
- return false
- }
- } else if (prodImgs.value.length - 5 <= 0) {
- return false
- } else {
- return false
- }
- }
- const nextImg = () => {
- if (prodImgs.value.length - 5 > 0) {
- if (offsetCount.value < prodImgs.value.length - 5) {
- offsetCount.value++
- carouserRef.value.style.left = '-' + 78 * offsetCount.value + 'px'
- } else if (prodImgs.value.length - 5 <= 0) {
- return false
- } else {
- return false
- }
- } else {
- return false
- }
- }
- /**
- * 团购信息
- */
- const countdown = ref({ obj: { day: '', hou: '', min: '', sec: '', signs: '' } }) // 倒计时
- const countdownFlag = ref(null) // 判断团购活动开始结束
- const groupBuyInfo = (addrId) => {
- if ((prodInfo.value.prodType !== 1 || !prodInfo.value.productActivity.groupActivity) && (prodInfo.value.prodType !== 2 || !prodInfo.value.productActivity.seckill)) {
- groupSkuProp(prodInfo.value.skuList, prodInfo.value.price)
- return
- }
- let key = 'groupActivity'
- if (prodInfo.value.prodType !== 1) {
- key = 'seckill'
- }
- const betweenTimestamp = util.betweenTimestamp(
- util.dateToTimestamp(prodInfo.value.productActivity[key].startTime),
- util.dateToTimestamp(prodInfo.value.productActivity[key].endTime)
- )
- countdown.value = {
- obj: util.betweenTime(betweenTimestamp),
- stamp: betweenTimestamp
- }
- countdownFlag.value = countdown.value.obj.signs
- startCountdown() // 请求倒计时
- if (key === 'seckill') {
- getSeckillInfo(addrId)
- if (!countdown.value.obj.signs) {
- groupSkuProp(prodInfo.value.skuList, prodInfo.value.price)
- }
- } else {
- groupSkuProp(prodInfo.value.productActivity.groupActivity.groupSkuList, prodInfo.value.productActivity.groupActivity.actPrice)
- getQrcode()
- }
- }
- /**
- * 倒计时
- */
- const startCountdown = () => {
- countdown.value = {
- stamp:
- countdown.value.stamp < 0 ? countdown.value.stamp + 1000 : countdown.value.stamp - 1000,
- obj: util.betweenTime(countdown.value.stamp)
- }
- if (countdown.value.obj.signs !== countdownFlag.value) {
- clearTimeout(timer)
- location.reload()
- return
- }
- timer = setTimeout(() => {
- startCountdown()
- }, 1000)
- }
- const getQrcode = (id = 'groupQrcode') => {
- nextTick(() => {
- QRCode.toCanvas(document.getElementById(id), h5Path + `/package-prod/pages/prod/prod?prodId=${prodId.value}`,
- { version: 6, errorCorrectionLevel: 'L', width: '110', height: '110' })
- })
- }
- /**
- * 小图点击事件
- */
- const changeProdImg = (index) => {
- if (prodImgs.value[index].isActive === true) {
- return
- }
- prodImgs.value.forEach(prodImg => {
- prodImg.isActive = false
- })
- prodImgs.value[index].isActive = true
- prodInfo.value.pic = prodImgs.value[index].img
- stopVideo()
- }
- /**
- * 大图加载失败时往下一张图加载
- */
- const changePicUrl = () => {
- const currentIndex = prodImgs.value.findIndex(prodImg => {
- return prodImg.isActive === true
- }
- )
- if (currentIndex === -1) {
- prodInfo.value.pic = defaultUrl
- return
- }
- prodImgs.value[currentIndex].img = defaultUrl
- const nextIndex = currentIndex + 1
- if (nextIndex >= prodImgs.value.length) {
- prodInfo.value.pic = prodImgs.value[0].img
- return
- }
- changeProdImg(nextIndex)
- }
- /**
- * 获取店铺信息
- */
- const shopInfo = ref({})
- const getShopHead = (shopId) => {
- http.get('/shop/headInfo', {
- params: {
- shopId
- }
- }).then(({ data }) => {
- shopInfo.value = data
- })
- }
- /**
- * 获取店铺分类
- */
- const shopCategorys = ref([])
- const getShopCategory = () => {
- http.get('/category/categoryInfo', {
- params: {
- shopId: shopId.value
- }
- }).then(({ data }) => {
- shopCategorys.value = data.categoryInfo
- })
- }
- /**
- * 价格过滤
- */
- const parsePrice = (value) => {
- let val = Number(value)
- if (!val) {
- val = 0
- }
- // 截取小数点后两位,并以小数点为切割点将val转化为数组
- return val.toFixed(2).split('.')
- }
- /**
- * 切换商品介绍/商品评论
- */
- const introduceOrCommentCom = ref(false)
- const toggleIntroduceInt = () => {
- introduceOrCommentInt.value = true
- introduceOrCommentCom.value = false
- }
- const toggleIntroduceCom = () => {
- introduceOrCommentInt.value = false
- introduceOrCommentCom.value = true
- }
- /**
- * 获取评论分页数据
- */
- const page = ref({
- pages: 0, // 总页数
- rainbow: [], // 分页条
- current: 1
- })
- const evaluate = ref(-1)
- const getSearchProdPage = (current) => {
- if (
- current !== 0 &&
- current !== page.value.current &&
- current <= page.value.pages
- ) {
- getProdCommPageByProd(evaluate.value, current)
- }
- }
- /**
- * 获取商品评论列表
- */
- const getProdCommPageByProd = (evaluateTemp, curPage) => {
- evaluate.value = evaluateTemp
- http.get('/prod/prodCommPageByProd', {
- params: {
- prodId: route.query.prodId,
- current: curPage || 1,
- size: 10,
- evaluate: evaluate.value
- }
- }).then(({ data }) => {
- handleProdComm(data)
- })
- }
- const handleProdComm = (data) => {
- const records = data.records
- prodCommList.value = records.map(prodComm => {
- prodComm.prodImgs = prodComm.pics?.split(',') || []
- return prodComm
- })
- data.rainbow = pageUtil.rainbowWithDot(data.current, data.pages, 5)
- page.value = data
- }
- /**
- * 获取热销商品
- */
- const hotSales = ref([])
- const getHotSales = () => {
- http.get('/search/page', {
- params: {
- shopId: prodInfo.value.shopId,
- size: 5,
- sort: 1,
- orderBy: 1,
- isAllProdType: true,
- current: 1,
- isActive: 1, // 过滤掉活动商品
- stationId: 0 // 过滤掉门店发布的商品
- }
- }).then(({ data }) => {
- hotSales.value = data.records[0].products
- })
- }
- /**
- * 收藏商品
- */
- const isCollection = ref(false) // 商品是否已收藏
- const toggleCollect = () => {
- const prodId = prodInfo.value.prodId
- if (!prodId) {
- return
- }
- http.post('/p/user/collection/addOrCancel', prodId).then(() => {
- isCollection.value = !isCollection.value
- if (isCollection.value) {
- ElMessage({
- message: $t('prodDetail.collectionSuccess'),
- type: 'success',
- duration: 1000
- })
- } else {
- ElMessage({
- message: $t('prodDetail.uncollected'),
- type: 'warning',
- duration: 1000
- })
- }
- })
- }
- /**
- * 查询商品是否已收藏
- */
- const isProdCollected = () => {
- if (!Cookie.get('bbcToken')) {
- return
- }
- http.get('/p/user/collection/isCollection', {
- params: {
- prodId: prodInfo.value.prodId
- }
- }).then(({ data }) => {
- isCollection.value = data
- })
- }
- /**
- * 收藏店铺
- */
- const isShopCollection = ref(false) // 店铺是否已收藏
- const toggleShopCollect = () => {
- const shopId = prodInfo.value.shopId
- if (!shopId) return
- http.post('/p/shop/collection/addOrCancel', shopId).then(() => {
- isShopCollection.value = !isShopCollection.value
- if (isShopCollection.value) {
- ElMessage({
- message: $t('prodDetail.collectionSuccess'),
- type: 'success',
- duration: 1000
- })
- } else {
- ElMessage({
- message: $t('prodDetail.uncollected'),
- type: 'warning',
- duration: 1000
- })
- }
- })
- }
- /**
- * 查询店铺是否已收藏
- */
- const isShopCollected = () => {
- if (!Cookie.get('bbcToken')) {
- return
- }
- http.get('/p/shop/collection/isCollection', {
- params: {
- shopId: prodInfo.value.shopId
- }
- }).then(({ data }) => {
- isShopCollection.value = data
- })
- }
- /**
- * 减少商品数量
- */
- const reduce = () => {
- const newProdNum = parseInt(prodNum.value)
- const key = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (defaultSku.value[key]) {
- if (!newProdNum || newProdNum <= 1) {
- prodNum.value = newProdNum
- prohibit1.value = true // 禁用
- prohibit2.value = false
- } else {
- prodNum.value = newProdNum - 1
- prohibit1.value = false
- prohibit2.value = false
- }
- } else {
- prodNum.value = 0
- prohibit1.value = true
- prohibit2.value = true
- }
- }
- /*
- * 失去焦点时对输入框的判断
- */
- const judgeInput = () => {
- const newProdNum = parseInt(prodNum.value)
- const key = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (defaultSku.value[key]) {
- if (!newProdNum || newProdNum <= 0) {
- prohibit1.value = true
- prohibit2.value = false
- } else {
- prohibit1.value = false
- prohibit2.value = false
- }
- if (prodInfo.value.productActivity.seckill && countdown.value.obj.signs) {
- if (prodInfo.value.productActivity.seckill.maxNum > 0 && newProdNum > prodInfo.value.productActivity.seckill.maxNum) {
- ElMessage({
- message: $t('purchaseRestrictions') + prodInfo.value.productActivity.seckill.maxNum + $t('items'),
- type: 'warning',
- duration: 1000
- })
- prodNum.value = 1
- prohibit1.value = false // -是否禁用
- prohibit2.value = true // +是否禁用
- return
- }
- }
- if (newProdNum > defaultSku.value[key]) {
- ElMessage({
- message: $t('prodDetail.insufficientInventory'),
- type: 'warning',
- duration: 1000
- })
- prohibit1.value = false
- prohibit2.value = true
- prodNum.value = 1
- }
- } else {
- prodNum.value = 0
- prohibit1.value = true
- prohibit2.value = true
- }
- }
- /**
- * 增加商品数量
- */
- const increase = () => {
- const newProdNum = parseInt(prodNum.value)
- const key = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (defaultSku.value[key]) {
- if (!newProdNum) {
- prodNum.value = 1
- return
- }
- if (prodInfo.value.productActivity.seckill && countdown.value.obj.signs) {
- if (prodInfo.value.productActivity.seckill.maxNum > 0 && newProdNum >= prodInfo.value.productActivity.seckill.maxNum) {
- ElMessage({
- message: $t('purchaseRestrictions') + prodInfo.value.productActivity.seckill.maxNum + $t('items'),
- type: 'warning',
- duration: 1000
- })
- prohibit2.value = true // +是否禁用
- return
- }
- }
- if (newProdNum < defaultSku.value[key]) {
- prodNum.value = newProdNum + 1
- } else {
- ElMessage({
- message: $t('prodDetail.insufficientInventory'),
- type: 'warning',
- duration: 1000
- })
- prohibit1.value = false // -是否禁用
- prohibit2.value = true // +是否禁用
- }
- } else {
- prodNum.value = 0
- prohibit1.value = true // -是否禁用
- prohibit2.value = true // +是否禁用
- }
- }
- /**
- * 请求优惠券列表
- */
- const couponList = ref([]) // 优惠券
- const getCouponList = () => {
- http.get('/coupon/listByProdId', {
- params: {
- prodId: route.query.prodId,
- shopId: prodInfo.value.shopId
- }
- }).then(({ data }) => {
- couponList.value = data ? data.slice(0, Math.min(8, data.length)) : []
- })
- }
- /**
- * 组装SKU
- */
- let selectedPropObj = {}
- const allProperties = ref('')
- const propKeys = ref('')
- let imgCounts = 0 // 缩略图数量
- const skuGroup = ref([])
- const combineList = ref([])
- const groupSkuProp = (skuList, defaultPrice, isChangeAddrRefreshSku = false) => {
- if (skuList.length === 1 && !skuList[0].properties) {
- defaultSku.value = skuList[0]
- imgCounts = !scoreFee && prodImgs.value.length
- carouserRef.value.style.width = !scoreFee && imgCounts * 78 + 'px' // 设置图片盒子的初始宽度
- combineList.value = skuList[0].skuComboList || []
- return
- }
- const isSkuGroup = {}
- const isAllProperties = []
- const isPropKeys = []
- const isSelectedPropObj = {}
- let isDefaultSku = null
- const key = prodInfo.value.productActivity.groupActivity ? 'actPrice' : prodInfo.value.productActivity.seckill && countdownFlag.value ? 'seckillPrice' : 'price'
- for (let i = 0; i < skuList.length; i++) {
- let isDefault = false
- if (!isDefaultSku && skuList[i][key] === defaultPrice && (!isChangeAddrRefreshSku || (isChangeAddrRefreshSku && skuList[i].skuId === defaultSku.value?.skuId))) {
- // 找到和商品价格一样的那个SKU,作为默认选中的SKU
- isDefaultSku = skuList[i]
- isDefault = true
- }
- const properties = skuList[i].properties // 版本:公开版;颜色:金色;内存:64GB
- isAllProperties.push(properties)
- const propList = properties.split(';') // ["版本:公开版","颜色:金色","内存:64GB"]
- for (let j = 0; j < propList.length; j++) {
- const index = propList[j].indexOf(':')
- const propval = [propList[j].slice(0, index), propList[j].substring(index + 1)] // ["版本","公开版"]
- let props = isSkuGroup[propval[0] + ';'] // 先取出 版本对应的值数组
- // 如果当前是默认选中的sku,把对应的属性值 组装到selectedProp
- if (isDefault) {
- isPropKeys.push(propval[0])
- isSelectedPropObj[propval[0]] = propval[1]
- }
- if (props === undefined) {
- props = [] // 假设还没有版本,新建个新的空数组
- props.push(propval[1]) // 把 "公开版" 放进空数组
- } else {
- if (props.indexOf(propval[1]) === -1) {
- // 如果数组里面没有"公开版"
- props.push(propval[1]) // 把 "公开版" 放进数组
- }
- }
- isSkuGroup[propval[0] + ';'] = props // 最后把数据 放回版本对应的值
- }
- }
- if (!isDefaultSku) {
- const priceList = skuList.map(x => x[key])
- isDefaultSku = skuList[priceList.indexOf(Math.min(...priceList))]
- }
- if (isDefaultSku) {
- imgCounts = isDefaultSku.pic ? prodImgs.value.length + 1 : prodImgs.value.length
- }
- carouserRef.value.style.width = imgCounts * 78 + 'px' // 设置图片盒子的初始宽度
- defaultSku.value = isDefaultSku
- combineList.value = isDefaultSku.skuComboList || []
- propKeys.value = isPropKeys
- selectedPropObj = isSelectedPropObj
- // 商品图片多出来
- parseSelectedObjToVals(skuList)
- skuGroup.value = isSkuGroup
- allProperties.value = isAllProperties
- }
- /**
- * 将已选的 {key:val,key2:val2}转换成 [val,val2]
- */
- let selectedProperties = ''
- const selectedProp = ref([])
- const findSku = ref(true) // 能不能找得到sku
- const parseSelectedObjToVals = (skuList) => {
- const isSelectedPropObj = selectedPropObj
- let isSelectedProperties = ''
- const isSelectedProp = []
- for (const key in isSelectedPropObj) {
- isSelectedProp.push({ key, value: isSelectedPropObj[key] })
- isSelectedProperties += key + ':' + isSelectedPropObj[key] + ';'
- }
- isSelectedProperties = isSelectedProperties.substring(
- 0,
- isSelectedProperties.length - 1
- )
- selectedProp.value = isSelectedProp
- selectedProperties = isSelectedProperties
- selectedPropObj = isSelectedPropObj
- let isDefaultSku = null
- let isFindSku = false
- for (let i = 0; i < skuList.length; i++) {
- // 解决排序问题导致无法匹配
- if (
- compareArray(
- isSelectedProperties.split(';').sort(),
- skuList[i].properties.split(';').sort()
- )
- ) {
- isFindSku = true
- isDefaultSku = skuList[i]
- changeSkuImg(isDefaultSku.pic || isDefaultSku.imgUrl)
- break
- }
- }
- if (!isDefaultSku) {
- isDefaultSku = {
- pic: setSkuImg(skuList, selectedPropObj) || '',
- price: 0,
- properties: '',
- seckillPrice: 0,
- seckillSkuId: '',
- seckillStocks: 0,
- skuId: null
- }
- changeSkuImg(isDefaultSku.pic || isDefaultSku.imgUrl)
- }
- defaultSku.value = isDefaultSku
- combineList.value = isDefaultSku.skuComboList || []
- findSku.value = isFindSku
- // 组装团购sku
- setDefaultGroupSku()
- }
- const setSkuImg = (skuList, selObj) => {
- for (let i = 0; i < allProperties.value.length; i++) {
- const firstSku = allProperties.value[i].split(';')[0]
- const index = firstSku.indexOf(':')
- if (selObj[firstSku.slice(0, index)] === firstSku.substring(index + 1)) {
- return skuList[i].pic
- }
- }
- }
- /**
- * 比较两个数组中的元素是否相等
- * @param a1 第一个数组
- * @param a2 第二个数组
- * @return boolean 两个数组中的元素都相等则返回 true,反之返回 false
- */
- const compareArray = (a1, a2) => {
- if (!a1 || !a2) {
- return false
- }
- if (a1.length !== a2.length) {
- return false
- }
- for (let i = 0, n = a1.length; i < n; i++) {
- if (a1[i] !== a2[i]) {
- return false
- }
- }
- return true
- }
- /**
- * 切换SKU图片
- */
- const changeSkuImg = (skuPic) => {
- if (!scoreFee) {
- const selectedImg = skuPic || (prodImgs.value.length > 0 && prodImgs.value[0].img)
- prodImgs.value.forEach(prodImg => {
- prodImg.isActive = false
- })
- prodInfo.value.pic = checkFileUrl(selectedImg)
- } else {
- const selectedImg = skuPic || (prodInfo.value.imgs.split(',')[0])
- if (prodImgs.value[0].sku) {
- prodImgs.value.shift()
- }
- if (skuPic) {
- prodImgs.value.forEach(prodImg => {
- prodImg.isActive = false
- })
- prodImgs.value.unshift({
- img: selectedImg,
- isActive: true,
- sku: true
- })
- }
- prodInfo.value.pic = selectedImg
- }
- }
- /**
- * 判断当前的规格值 是否可以选
- */
- const isSkuLineItemNotOptional = (allProperties, selectedPropObj, key, item, propKeys) => {
- const selectedPropObjTemp = Object.assign({}, selectedPropObj)
- let properties = ''
- selectedPropObjTemp[key] = item
- for (let j = 0; j < propKeys.length; j++) {
- if (propKeys[j] === key.substring(0, key.length - 1)) {
- properties += propKeys[j] + ':' + item + ';'
- } else {
- properties += propKeys[j] + ':' + selectedPropObjTemp[propKeys[j]] + ';'
- }
- }
- properties = properties.substring(0, properties.length - 1)
- for (let i = 0; i < allProperties.length; i++) {
- if (properties === allProperties[i]) {
- return false
- }
- }
- for (let i = 0; i < allProperties.length; i++) {
- if (allProperties[i].indexOf(item) >= 0) {
- return true
- }
- }
- return false
- }
- /**
- * 规格点击事件
- */
- let skuList = []
- const toChooseItem = (skuLineItem, key) => {
- selectedPropObj[key.replace(';', '')] = skuLineItem
- if (prodInfo.value.productActivity.groupActivity) {
- skuList = prodInfo.value.productActivity.groupActivity.groupSkuList
- } else {
- skuList = countdownFlag.value && prodInfo.value.productActivity.seckill ? prodInfo.value.productActivity.seckill.seckillSkuList : prodInfo.value.skuList
- }
- parseSelectedObjToVals(skuList)
- resetProdNum()
- }
- // 重置商品数量
- const resetProdNum = () => {
- const objKey = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (defaultSku.value[objKey]) {
- // 有库存
- prodNum.value = 1
- prohibit1.value = true
- prohibit2.value = false
- } else {
- prodNum.value = 0
- prohibit1.value = true // 禁用
- prohibit2.value = true // 禁用
- }
- }
- /**
- * 组装团购sku
- */
- const groupSkuList1 = [] // 团购sku列表
- const setDefaultGroupSku = () => {
- const groupSkuList = JSON.parse(JSON.stringify(groupSkuList1))
- const selectedP = selectedProperties.split(';')
- if (groupSkuList.length) {
- for (let i = 0; i < groupSkuList.length; i++) {
- // 进行规格名称对应判断
- const skuNames = groupSkuList[i].properties.split(';')
- const haveSku = selectedP.every(item => {
- return skuNames.some(itemC => {
- return item === itemC
- })
- })
- // 规格名一一对应则进行赋值
- if (haveSku) {
- break
- }
- }
- }
- }
- // 预售/组合选品/秒杀商品/非快递配送商品不能加入购物车
- const verifyAddCart = () => {
- const { prodType, preSellStatus, productActivity } = prodInfo.value
- const preSellFlag = prodType === 0 && preSellStatus === 1 // 预售
- const seckillFlag = prodType === 2 && productActivity.seckill && countdown.value.obj.signs === 1 // 已开始的秒杀
- const actFlag = prodType === 5 // 组合选品
- if (preSellFlag || seckillFlag || actFlag) {
- ElMessage({
- message: $t('prodDetail.addCartTips'),
- type: 'error',
- duration: 1500
- })
- return false
- }
- if (!prodInfo.value.deliveryModeVO?.hasShopDelivery) {
- ElMessage({
- message: $t('prodDetail.addCartTips2'),
- type: 'error',
- duration: 1500
- })
- return false
- }
- return true
- }
- /**
- * 加入购物车
- */
- const addToCart = () => {
- if (!defaultSku.value.isHasStock || !isDelivery.value) {
- return
- }
- if (!verifyAddCart()) return
- if (!findSku.value) {
- return
- }
- if (!prodNum.value || prodNum.value <= 0) {
- ElMessage({
- message: $t('prodDetail.pleaseEnterTheCorrectNumberOfItems'),
- type: 'warning',
- duration: 1000
- })
- return
- }
- http.post('/p/shopCart/changeItem', {
- basketId: 0,
- count: prodNum.value,
- prodId: route.query.prodId,
- shopId: prodInfo.value.shopId,
- shopName: shopInfo.value.shopName,
- skuId: defaultSku.value.skuId,
- stationId: 0,
- type: 1
- }).then(() => {
- tapLog(4, prodNum.value)
- getCartCount()
- ElMessage.success($t('prodDetail.successfullyAddedCart'))
- })
- }
- /**
- * 获取购物车商品总数
- */
- const cartNumberStore = useCartNumberStore()
- const getCartCount = () => {
- http.get('/p/shopCart/prodCount', { params: { type: 1 } }).then(({ data }) => {
- cartNumberStore.changeCartNumber(data)
- })
- }
- /**
- * 立即购买
- */
- const buyNow = () => {
- if (!defaultSku.value.isHasStock || !isDelivery.value) {
- return
- }
- if (!prodInfo.value.deliveryModeVO?.hasShopDelivery) {
- return
- }
- if (!findSku.value) {
- ElMessage.error($t('prodDetail.productNotInStock') + '~')
- return
- }
- const key = countdownFlag.value && prodInfo.value.productActivity.seckill ? 'seckillStocks' : 'stocks'
- if (!defaultSku.value[key] || prodNum.value > defaultSku.value[key]) {
- ElMessage({
- message: $t('prodDetail.insufficientInventory'),
- type: 'warning',
- duration: 1000
- })
- return
- }
- if (!prodNum.value || prodNum.value <= 0) {
- ElMessage({
- message: $t('prodDetail.pleaseEnterTheCorrectNumberOfItems'),
- type: 'warning',
- duration: 1000
- })
- return
- }
- if (!Cookie.get('bbcToken')) {
- bus.emit('showLogin', true)
- } else {
- if (prodInfo.value.prodType === 0 || prodInfo.value.prodType === 1 || (prodInfo.value.prodType === 2 && !prodInfo.value.productActivity.seckill)) {
- toSubmitOrder()
- return
- }
- if (scoreFee) {
- sessionStorage.setItem('bbcOrderItem', JSON.stringify({
- prodId: prodInfo.value.prodId,
- skuId: defaultSku.value.skuId,
- prodCount: prodNum.value,
- shopId: prodInfo.value.shopId
- }))
- router.push({
- path: '/submit-integral-order',
- query: {
- orderEntry: 1,
- addrId: addrId || null
- }
- })
- return
- }
- if (countdownFlag.value && prodInfo.value.productActivity.seckill) {
- const secKillObj = {
- prodCount: prodNum.value,
- seckillSkuId: defaultSku.value.seckillSkuId,
- skuId: defaultSku.value.skuId,
- prodId: prodInfo.value.prodId,
- shopId: prodInfo.value.shopId
- }
- sessionStorage.setItem('bbcSecKillObj', JSON.stringify(secKillObj))
- router.push({
- path: '/secdetail',
- query: {
- seckillI: prodInfo.value.productActivity.seckill.seckillId,
- addrId
- }
- })
- } else {
- // 原价购买弹窗确认
- ElMessageBox.confirm($t('prodDetail.retailPriceTips'), $t('tips'), {
- distinguishCancelAndClose: true,
- confirmButtonText: $t('determine'),
- cancelButtonText: $t('cancel')
- }).then(() => {
- toSubmitOrder()
- })
- }
- }
- }
- /**
- * 立即购买: 购买普通商品 / 原价购买秒杀商品
- */
- const toSubmitOrder = () => {
- sessionStorage.setItem(
- 'bbcOrderItem',
- JSON.stringify({
- prodId: prodInfo.value.prodId,
- skuId: defaultSku.value.skuId,
- prodCount: prodNum.value,
- shopId: prodInfo.value.shopId
- })
- )
- router.push({
- path: '/submit-order',
- query: {
- orderEntry: 1,
- addrId: addrId || null
- }
- })
- }
- /**
- * 领取优惠券
- */
- const receiveCoupon = (coupon) => {
- http.post('/p/myCoupon/receive', coupon.couponId).then(({ data }) => {
- if (data) {
- ElMessage({
- message: data,
- type: 'success',
- duration: 1000
- })
- }
- })
- }
- const prodName = ref('')
- const toShopIndex = () => {
- if (!shopId.value) return
- const searchTerms = prodName.value.trim() // 去除字符串的头尾空格
- if (!searchTerms) {
- ElMessage({
- message: $t('prodDetail.searchContentCannotBeEmpty'),
- type: 'error',
- duration: 1000
- })
- return
- }
- // 跳转到商品列表页
- router.push({
- path: '/shop-prod-list',
- query: {
- sid: shopId.value,
- pn: searchTerms
- }
- })
- }
- // 跳转活动详情
- const toDiscountDetail = (discountId) => {
- router.push({
- path: '/discount-detail',
- query: {
- discountId
- }
- })
- }
- // 跳转商家客服
- const showLogin = ref(false)
- const toChatIm = (prodInfo) => {
- if (!prodInfo.shopId) return
- if (Cookie.get('bbcToken')) {
- const routeUrl = router.resolve({
- path: '/chat',
- query: {
- shopId: prodInfo.shopId,
- prodId: prodInfo.prodId
- }
- })
- window.open(routeUrl.href, 'view_window')
- } else {
- showLogin.value = true
- }
- }
- /**
- * 隐藏登录弹窗
- */
- const hideLoginPop = () => {
- showLogin.value = false
- }
- const selectComboId = ref(0)
- const selectPackageRef = ref(null)
- const showSelectPackage = ref(false)
- const handleSelectPackage = () => {
- if (!Cookie.get('bbcToken')) {
- bus.emit('showLogin', true)
- return
- }
- http.post('/combo/getCombo', {
- comboId: selectComboId.value,
- matchingProdIds: selectMatchIds.value
- }).then(({ data }) => {
- showSelectPackage.value = true
- nextTick(() => {
- selectPackageRef.value?.getComboData(data)
- })
- })
- }
- const hideSelectPackage = () => {
- showSelectPackage.value = false
- }
- const isChecked = (combo) => {
- return combo.required || combo.isChecked || false
- }
- const choiceCombNum = ref(0) // 选中的套餐商品数量
- const selectComboItem = (comboItem) => {
- if (comboItem.required) {
- return
- }
- if (isChecked(comboItem)) {
- comboItem.isChecked = false
- const index = findProdIndex(comboItem.prodId)
- if (index >= 0) {
- selectMatchIds.value.splice(index, 1)
- }
- } else {
- comboItem.isChecked = true
- if (findProdIndex(comboItem.prodId) < 0) {
- selectMatchIds.value.push(comboItem.prodId)
- }
- }
- choiceCombNum.value = selectMatchNum()
- }
- const findProdIndex = (prodId) => {
- return selectMatchIds.value.findIndex(item => item === prodId)
- }
- // 选择套餐
- const selectCombo = (comboId) => {
- selectComboId.value = comboId
- selectMatchIds.value = []
- // defaultCombo
- for (let i = 0; i < comboList.value.length; i++) {
- if (comboList.value[i].comboId === comboId) {
- defaultCombo.value = comboList.value[i]
- break
- }
- }
- defaultCombo.value.matchingProds.forEach(item => {
- if (item.required) {
- item.isChecked = true
- selectMatchIds.value.push(item.prodId)
- } else {
- item.isChecked = false
- }
- })
- choiceCombNum.value = selectMatchNum()
- }
- // 跳转到积分商品详情
- const toScoreProdDet = (prodId, scoreFee) => {
- http.get('/search/page', {
- params: {
- current: 1,
- size: 20,
- prodType: 3,
- sort: 2,
- stationId: 0 // 过滤掉门店发布的商品
- }
- }).then(() => {
- const newPage = router.resolve({
- path: '/detail',
- query: {
- prodId,
- scoreFee
- }
- })
- window.open(newPage.href, '_blank', 'noopener,noreferrer')
- })
- }
- /**
- * 去往 资质证照 页面
- */
- const onToQualifications = (prodInfo) => {
- if (!prodInfo.shopId) return
- router.push({
- path: '/shop-qualifications',
- query: {
- sid: prodInfo.shopId
- }
- })
- }
- const isShowDeliveryPop = ref(false) // 选择地址弹窗显示
- const deliveryList = ref([])
- const onOpenDeliveryPop = (falg = true) => {
- http.get('/p/address/list', {
- params: {
- isDefaultFirst: false
- }
- }).then(({ data }) => {
- data.sort((a, b) => {
- return b.commonAddr - a.commonAddr
- })
- deliveryList.value = data
- if (falg) isShowDeliveryPop.value = true
- })
- }
- // 切换地址
- const onSelectDelivery = async (id) => {
- addrId = id
- await getProdInfo(addrId)
- if (prodInfo.value.prodType === 0 || prodInfo.value.prodType === 3) {
- groupSkuProp(prodInfo.value.skuList, defaultSku.value.price, true)
- } else {
- // 秒杀/团购 商品
- if (timer) clearTimeout(timer)
- groupBuyInfo(addrId)
- }
- isShowDeliveryPop.value = false
- resetProdNum()
- }
- const onClosePop = () => {
- if (isShowDeliveryPop.value) isShowDeliveryPop.value = false
- }
- </script>
- <style lang="scss" scoped>
- @use './index.scss';
- </style>
|