index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. <template>
  2. <!-- 商品属性规格弹窗 -->
  3. <view>
  4. <view class="product-window"
  5. :class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt?'join':'') + ' ' + (iScart?'joinCart':'')">
  6. <view class="textpic acea-row row-between-wrapper">
  7. <view class="pictrue" @click="showImg()">
  8. <image :src="attr.productSelect.image"></image>
  9. <view class="icon acea-row row-center-wrapper" v-if="cusPreviewImg">
  10. <view class="iconfont icon-fangda1"></view>
  11. </view>
  12. </view>
  13. <view class="text">
  14. <view class="line1">
  15. {{ type == 'setMeal'?title : attr.productSelect.store_name }}
  16. </view>
  17. <view class="money font-color">
  18. <view class="acea-row row-middle">
  19. <text v-if="type =='points'">
  20. <text v-if="parseFloat(attr.productSelect.integral)"><text class="num">{{ attr.productSelect.integral }}</text>积分</text>
  21. <text v-if="parseFloat(attr.productSelect.price) && parseFloat(attr.productSelect.integral)">+</text>
  22. <text v-if="parseFloat(attr.productSelect.price)">¥<text class="num">{{ attr.productSelect.price }}</text></text>
  23. </text>
  24. <text v-else>¥<text class="num">{{ attr.productSelect.price }}</text></text>
  25. <text class='vip-money'
  26. v-if="is_vip>0 && attr.productSelect.vip_price && storeInfo && storeInfo.price_type == 'member'">¥{{attr.productSelect.vip_price}}</text>
  27. <view class="vipImg" v-if="is_vip>0 && attr.productSelect.vip_price && storeInfo && storeInfo.price_type == 'member'">
  28. <image src="../../static/images/vip.png"></image>
  29. </view>
  30. <view class="icon" v-if="is_vip>0 && attr.productSelect.vip_price && storeInfo && storeInfo.price_type == 'level'"><text class="iconfont icon-dengjitubiao"></text>{{storeInfo.level_name}}</view>
  31. </view>
  32. <text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
  33. <text class='stock' v-if="limitNum">{{type == 'seckill' ? '限量' : type == 'points'?'剩余':'库存'}}: {{attr.productSelect.quota}}</text>
  34. <slot name="bottom" :attr="attr"></slot>
  35. </view>
  36. </view>
  37. <view class="iconfont icon-guanbi" @click="closeAttr"></view>
  38. </view>
  39. <view class="rollTop">
  40. <view class="productWinList">
  41. <view class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
  42. <view class="title">{{ item.attr_name }}</view>
  43. <view class="listn acea-row row-middle">
  44. <view class="itemn" :class="item.index === itemn.attr ? 'on' : ''"
  45. v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
  46. :key="indexn">
  47. {{ itemn.attr }}
  48. </view>
  49. </view>
  50. </view>
  51. <view class="item" v-if="isDelivery">
  52. <view class="title">配送方式</view>
  53. <view class="listn acea-row row-middle">
  54. <view class="itemn" v-if="attr.deliveryType.includes('1')" @click="getstoreInfo('1')" :class="flag==1?'on':isStoreBuy?'on2':''">商城配送</view>
  55. <view class="itemn" v-if="attr.deliveryType.includes('2') && attr.store_self_mention && selfStoreList.length" @click="getstoreInfo('2')" :class="flag==2?'on':''">门店自提</view>
  56. <view class="itemn" v-if="attr.deliveryType.includes('3') && storeList.length" @click="getstoreInfo('3')" :class="flag==3?'on':''">门店配送</view>
  57. </view>
  58. </view>
  59. <view class="address acea-row row-middle" v-if="flag ==1 && isDelivery" @click="openAddress">
  60. <view class="adsInfo">{{addressInfo}}</view>
  61. <view class="iconfont icon-gengduo3"></view>
  62. </view>
  63. <view class="address acea-row row-middle" v-if="flag ==3 && isDelivery" @click="openStore">
  64. <view class="adsInfo">{{deliveryName}}{{deliveryAddress}}{{distance}}</view>
  65. <view class="iconfont icon-gengduo3" v-if="attr.isType != 1"></view>
  66. </view>
  67. <view class="address" v-if="flag ==2 && isDelivery" @click="openStore">
  68. <view>{{deliveryName}}</view>
  69. <view class="info acea-row row-between-wrapper">
  70. <view class="con">{{deliveryAddress}}</view>
  71. <view>{{distance}}<text class="iconfont icon-gengduo3" v-if="attr.isType != 1"></text></view>
  72. </view>
  73. </view>
  74. </view>
  75. <view class="cart acea-row row-between-wrapper" v-if="type != 'setMeal' && type !='points'">
  76. <view class="title">数量</view>
  77. <view class="carnum acea-row row-left">
  78. <view class="item reduce acea-row row-center-wrapper"
  79. :class="attr.productSelect.cart_num <= 1 ? 'on' : ''" v-if="attr.productSelect.cart_num <= 1">
  80. <text class="iconfont icon-shangpinshuliang-jian"></text>
  81. </view>
  82. <view class="item reduce acea-row row-center-wrapper"
  83. :class="attr.productSelect.cart_num <= 1 ? 'on' : ''" @click="CartNumDes" v-else>
  84. <text class="iconfont icon-shangpinshuliang-jian"></text>
  85. </view>
  86. <view class='item num acea-row row-middle'>
  87. <input type="number" v-model="attr.productSelect.cart_num"
  88. data-name="productSelect.cart_num" :always-embed="true" :adjust-position="true" cursor-spacing="30"
  89. @input="bindCode(attr.productSelect.cart_num)"></input>
  90. </view>
  91. <view v-if="iSplus" class="item plus acea-row row-center-wrapper" :class="
  92. attr.productSelect.cart_num >= attr.productSelect.stock
  93. ? 'on'
  94. : ''
  95. " @click="CartNumAdd">
  96. <text class="iconfont icon-shangpinshuliang-jia"></text>
  97. </view>
  98. <view v-else class='item plus'
  99. :class='(attr.productSelect.cart_num >= attr.productSelect.quota) || (attr.productSelect.cart_num >= attr.productSelect.product_stock) || (attr.productSelect.cart_num >= attr.productSelect.num) || (type=="seckill" && attr.productSelect.cart_num >= attr.productSelect.once_num)? "on":""'
  100. @click='CartNumAdd'>+</view>
  101. </view>
  102. </view>
  103. </view>
  104. <view class="joinBnt bg-color"
  105. v-if="iSbnt && attr.productSelect.product_stock>0 &&attr.productSelect.quota>0" @click="goCat">我要参团
  106. </view>
  107. <view class="joinBnt on"
  108. v-else-if="(iSbnt && attr.productSelect.quota<=0)||(iSbnt &&attr.productSelect.product_stock<=0)">已售罄
  109. </view>
  110. <view class="joinBnt bg-color" v-if="iScart && attr.productSelect.stock" @click="goCat">确定</view>
  111. <view class="joinBnt on" v-else-if="iScart && !attr.productSelect.stock">已售罄</view>
  112. </view>
  113. <!-- 选择门店 -->
  114. <view class="product-window" :class="isStore?'store':''">
  115. <view class="storeTitle">选择门店<text class="iconfont icon-guanbi5" @click="closeStore"></text></view>
  116. <view class="storeList">
  117. <view class="item" :class="active == index?'on':''" v-for="(item,index) in storeList" :key="index" @click="tapStore(index,item)">
  118. <view class="name line1">{{item.name}}</view>
  119. <view class="address acea-row row-between">
  120. <view class="iconfont icon-dingwei2"></view>
  121. <view class="info">{{item.address}}</view>
  122. </view>
  123. <view class="time acea-row row-middle">
  124. <view class="iconfont icon-yingyeshijian2"></view>
  125. <view>营业时间:{{item.day_time}}</view>
  126. </view>
  127. <view class="iconfont icon-xuanzhong6" v-if="active == index"></view>
  128. </view>
  129. </view>
  130. </view>
  131. <addressWindow ref="addressWindow" :isFooter="isFooter" :pagesUrl="pagesUrl" :fromType="1" :address="address" @changeClose="changeClose" @OnChangeAddress="OnChangeAddress">
  132. </addressWindow>
  133. <view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></view>
  134. <view class="mask on" @touchmove.prevent :hidden="isStore === false" @click="closeStore"></view>
  135. </view>
  136. </template>
  137. <script>
  138. import addressWindow from '@/components/addressWindow';
  139. import {getAddressList} from '@/api/user.js'
  140. import {storeListApi} from '@/api/store.js'
  141. import {
  142. mapGetters,
  143. mapState
  144. } from 'vuex';
  145. export default {
  146. computed: {
  147. ...mapState({
  148. nearbyStore: state => state.app.nearbyStore
  149. }),
  150. ...mapGetters(['isLogin'])
  151. },
  152. components:{
  153. addressWindow
  154. },
  155. props: {
  156. isStoreBuy: {
  157. type: Number,
  158. value: 0
  159. },
  160. productId: {
  161. type: Number | String,
  162. value: 0
  163. },
  164. productType: {
  165. type: Number | String,
  166. value: 0
  167. },
  168. cusPreviewImg: {
  169. type: Number,
  170. value: 0
  171. },
  172. title: {
  173. type: String,
  174. default: ''
  175. },
  176. attr: {
  177. type: Object,
  178. default: () => {}
  179. },
  180. storeInfo: {
  181. type: Object,
  182. default: () => {}
  183. },
  184. limitNum: {
  185. type: Number,
  186. value: 0
  187. },
  188. isShow: {
  189. type: Number,
  190. value: 0
  191. },
  192. iSbnt: {
  193. type: Number,
  194. value: 0
  195. },
  196. iSplus: {
  197. type: Number,
  198. value: 0
  199. },
  200. iScart: {
  201. type: Number,
  202. value: 0
  203. },
  204. is_vip: {
  205. type: Number,
  206. value: 0
  207. },
  208. type: {
  209. type: String,
  210. default: ''
  211. },
  212. isFooter: {
  213. type: Boolean,
  214. default: false
  215. }
  216. },
  217. data() {
  218. return {
  219. flag:1,
  220. addressInfo:'', // 商城快递
  221. deliveryName:'', // 门店配送
  222. distance:'',
  223. deliveryAddress:'',
  224. address: {
  225. address: false
  226. },
  227. pagesUrl:'',
  228. user_latitude: 0,
  229. user_longitude: 0,
  230. isDelivery: false,
  231. storeList: [],
  232. deliveryStoreList: [],
  233. selfStoreList: [],
  234. active:0,
  235. isStore: false
  236. }
  237. },
  238. mounted() {
  239. try {
  240. this.user_latitude = uni.getStorageSync('user_latitude');
  241. this.user_longitude = uni.getStorageSync('user_longitude');
  242. } catch (e) {}
  243. },
  244. watch: {
  245. // 'attr.deliveryType': {
  246. // handler(newV) {
  247. // if(newV){
  248. // if(this.active<1){
  249. // if (this.user_latitude && this.user_longitude) {
  250. // this.getList();
  251. // } else {
  252. // this.selfLocation();
  253. // }
  254. // }
  255. // this.flag = newV[0];
  256. // this.$emit('deliveryFun',newV[0]);
  257. // }
  258. // },
  259. // deep: true
  260. // }
  261. 'attr.deliveryType'(newValue, oldValue) {
  262. if (JSON.stringify(newValue) != JSON.stringify(oldValue)) {
  263. if (newValue.length) {
  264. if(this.active<1){
  265. this.getList();
  266. // if (this.user_latitude && this.user_longitude) {
  267. // this.getList();
  268. // } else {
  269. // this.selfLocation();
  270. // }
  271. }
  272. let num = 1;
  273. if(newValue[0] == 1 && this.isStoreBuy){
  274. num = newValue[1];
  275. }else{
  276. num = newValue[0];
  277. }
  278. this.flag = num
  279. this.$emit('deliveryFun',num);
  280. }
  281. }
  282. }
  283. },
  284. methods: {
  285. closeStore(){
  286. this.isStore = false;
  287. },
  288. openStore(){
  289. if(this.attr.isType != 1){
  290. this.isStore = true;
  291. }
  292. },
  293. // 切换门店
  294. tapStore(index,item){
  295. this.active = index;
  296. this.deliveryName = item.name;
  297. this.deliveryAddress = item.detailed_address+'\xa0';
  298. this.distance = '距您'+item.range+'km';
  299. this.isStore = false;
  300. this.$emit('onstoreId',item,this.flag);
  301. },
  302. // 切换地址
  303. OnChangeAddress: function(e,row) {
  304. this.address.address = false;
  305. this.addressInfo = row.province+'省'+'\xa0'+row.city+'\xa0'+row.district+'\xa0'+row.street+'\xa0'+row.detail
  306. this.$emit('onAddressId',row)
  307. },
  308. // 打开弹窗
  309. openAddress(){
  310. this.$refs.addressWindow.getAddressList();
  311. this.address.address = true;
  312. this.pagesUrl = '/pages/users/user_address/index'
  313. },
  314. goCat: function() {
  315. this.$emit('goCat');
  316. },
  317. // 配送地址
  318. getAddressList() {
  319. getAddressList({
  320. page: 1,
  321. limit: 1
  322. }).then(res=>{
  323. let data = res.data[0];
  324. if(res.data.length){
  325. this.addressInfo = data.province+'省'+'\xa0'+data.city+'\xa0'+data.district+'\xa0'+data.street+'\xa0'+data.detail
  326. this.$emit('onAddressId',data)
  327. }else{
  328. this.addressInfo = '点击添加地址'
  329. }
  330. })
  331. },
  332. // 关闭地址弹窗;
  333. changeClose: function() {
  334. this.$set(this.address, 'address', false);
  335. },
  336. selfLocation() {
  337. let self = this
  338. // #ifdef H5
  339. if (self.$wechat.isWeixin()) {
  340. self.$wechat.location().then(res => {
  341. this.user_latitude = res.latitude;
  342. this.user_longitude = res.longitude;
  343. uni.setStorageSync('user_latitude', res.latitude);
  344. uni.setStorageSync('user_longitude', res.longitude);
  345. self.getList();
  346. })
  347. } else {
  348. // #endif
  349. uni.getLocation({
  350. type: 'wgs84',
  351. success: (res) => {
  352. try {
  353. this.user_latitude = res.latitude;
  354. this.user_longitude = res.longitude;
  355. uni.setStorageSync('user_latitude', res.latitude);
  356. uni.setStorageSync('user_longitude', res.longitude);
  357. } catch {}
  358. self.getList();
  359. },
  360. fail:(res)=>{
  361. console.log(res)
  362. // #ifdef MP
  363. uni.getSetting({
  364. success: res=>{
  365. if(typeof(res.authSetting['scope.userLocation']) != 'undefined' && !res.authSetting['scope.userLocation']){
  366. uni.setStorageSync('refuseLocation', true);
  367. }
  368. }
  369. })
  370. // #endif
  371. }
  372. // complete: function() {
  373. // self.getList();
  374. // }
  375. });
  376. // #ifdef H5
  377. }
  378. // #endif
  379. },
  380. getList: function(id) {
  381. let data = {
  382. latitude: this.user_latitude || "", //纬度
  383. longitude: this.user_longitude || "", //经度
  384. page: 1,
  385. limit: 100,
  386. product_id: this.productId,
  387. is_store:'', //查找所有门店列表
  388. type: this.type == 'seckill'?1:0,
  389. store_id: id?id:this.nearbyStore
  390. };
  391. storeListApi(data)
  392. .then(res => {
  393. let list = res.data.list.list;
  394. if(!id && list.length && this.attr && ((this.attr.deliveryType.indexOf('2') != -1 && this.attr.store_self_mention) || this.attr.deliveryType.indexOf('3') != -1)){
  395. this.isDelivery = true;
  396. if(this.$store.getters.isLogin){
  397. this.getAddressList()
  398. }
  399. }
  400. // 拆分自提门店列表和配送门店列表
  401. let selfStoreList = [];
  402. list.forEach(function(item,index){
  403. if(item.is_store === 1) selfStoreList.push(item);
  404. });
  405. this.storeList = this.flag==2?selfStoreList:list;
  406. this.selfStoreList = selfStoreList;//门店自提
  407. this.deliveryStoreList = list;//门店配送
  408. this.active = 0;
  409. this.deliveryName = list[0].name;
  410. this.deliveryAddress = list[0].detailed_address+'\xa0';
  411. this.distance = '距您'+list[0].range+'km';
  412. this.$emit('onstoreId',list[0],this.flag);
  413. })
  414. .catch(err => {
  415. this.$util.Tips({
  416. title: err
  417. })
  418. });
  419. },
  420. /**
  421. * 购物车手动输入数量
  422. *
  423. */
  424. bindCode: function(e) {
  425. this.$emit('iptCartNum', this.attr.productSelect.cart_num);
  426. },
  427. closeAttr: function() {
  428. this.$emit('myevent');
  429. },
  430. CartNumDes: function() {
  431. this.$emit('ChangeCartNum', false);
  432. },
  433. CartNumAdd: function() {
  434. this.$emit('ChangeCartNum', true);
  435. },
  436. tapAttr: function(indexw, indexn) {
  437. let that = this;
  438. that.$emit("attrVal", {
  439. indexw: indexw,
  440. indexn: indexn
  441. });
  442. this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
  443. let value = that
  444. .getCheckedValue()
  445. .join(",");
  446. that.$emit("ChangeAttr", value);
  447. },
  448. //获取被选中属性;
  449. getCheckedValue: function() {
  450. let productAttr = this.attr.productAttr;
  451. let value = [];
  452. for (let i = 0; i < productAttr.length; i++) {
  453. for (let j = 0; j < productAttr[i].attr_values.length; j++) {
  454. if (productAttr[i].index === productAttr[i].attr_values[j]) {
  455. value.push(productAttr[i].attr_values[j]);
  456. }
  457. }
  458. }
  459. return value;
  460. },
  461. // 选择配送方式
  462. getstoreInfo(index) {
  463. if(index == 1 && this.isStoreBuy){
  464. return false
  465. }
  466. if(index === '2' || index === '3'){
  467. if ((!this.user_latitude || !this.user_longitude) && !uni.getStorageSync('refuseLocation')) {
  468. this.selfLocation();
  469. }
  470. }
  471. if(index === '2') this.storeList = this.selfStoreList; //门店自提
  472. if(index === '3') this.storeList = this.deliveryStoreList; //门店配送
  473. this.flag = index;
  474. this.active = 0;
  475. this.deliveryName = this.storeList[0].name;
  476. this.deliveryAddress = this.storeList[0].detailed_address+'\xa0';
  477. this.distance = '距您'+this.storeList[0].range+'km';
  478. this.$emit('deliveryFun',index);
  479. this.$emit('onstoreId',this.storeList[0],index);
  480. },
  481. showLocation(){
  482. if ((!this.user_latitude || !this.user_longitude) && !uni.getStorageSync('refuseLocation')) {
  483. this.selfLocation();
  484. }
  485. },
  486. showImg() {
  487. this.$emit('getImg');
  488. }
  489. }
  490. }
  491. </script>
  492. <style scoped lang="scss">
  493. .mask.on{
  494. z-index: 100 !important;
  495. }
  496. .product-window{
  497. .productWinList{
  498. .address{
  499. width: 690rpx;
  500. background: #F5F5F5;
  501. padding: 30rpx 24rpx;
  502. margin: 0 auto;
  503. margin-top: 20rpx;
  504. font-weight: 400;
  505. color: #333333;
  506. font-size: 26rpx;
  507. border-radius: 10rpx;
  508. .adsInfo{
  509. max-width: 594rpx;
  510. }
  511. .iconfont{
  512. font-size: 18rpx;
  513. margin-left: 12rpx;
  514. }
  515. .info{
  516. font-weight: 400;
  517. color: #999999;
  518. margin-top: 12rpx;
  519. .con{
  520. width: 416rpx;
  521. }
  522. }
  523. }
  524. }
  525. }
  526. .active {
  527. position: relative;
  528. border: 1px solid var(--view-theme);
  529. .icon-xuanzhong6 {
  530. font-size: 46rpx;
  531. position: absolute;
  532. bottom: -4rpx;
  533. right: -6rpx;
  534. color: var(--view-theme);
  535. }
  536. }
  537. .vip-money {
  538. color: #282828;
  539. font-size: 28rpx;
  540. font-weight: 700;
  541. margin-left: 6rpx;
  542. }
  543. .vipImg {
  544. width: 56rpx;
  545. height: 20rpx;
  546. margin-left: 6rpx;
  547. image {
  548. width: 100%;
  549. height: 100%;
  550. display: block;
  551. }
  552. }
  553. .product-window{
  554. &.store{
  555. background-color: #F5F5F5;
  556. border-radius: 20rpx 20rpx 0 0;
  557. transform: translate3d(0, 0, 0);
  558. z-index: 102;
  559. margin: 0;
  560. }
  561. .storeTitle{
  562. text-align: center;
  563. height: 100rpx;
  564. line-height: 100rpx;
  565. font-size: 32rpx;
  566. font-weight: 500;
  567. color: #282828;
  568. position: relative;
  569. .iconfont{
  570. position: absolute;
  571. font-size: 35rpx;
  572. right: 30rpx;
  573. }
  574. }
  575. .storeList{
  576. max-height: 690rpx;
  577. overflow: auto;
  578. .item{
  579. width: 690rpx;
  580. background: #FFFFFF;
  581. border-radius: 12rpx;
  582. margin: 0 auto 20rpx auto;
  583. padding: 28rpx 30rpx;
  584. border: 1px solid #fff;
  585. position: relative;
  586. &.on{
  587. border-color: var(--view-theme);
  588. }
  589. .icon-xuanzhong6{
  590. position: absolute;
  591. right: -6rpx;
  592. bottom: -6rpx;
  593. color: var(--view-theme);
  594. font-size: 54rpx;
  595. }
  596. .name{
  597. font-weight: 500;
  598. color: #333333;
  599. font-size: 28rpx;
  600. }
  601. .time{
  602. font-weight: 400;
  603. color: #888888;
  604. font-size: 22rpx;
  605. margin-top: 15rpx;
  606. .iconfont{
  607. font-size: 20rpx;
  608. margin-right: 8rpx;
  609. }
  610. }
  611. .address{
  612. font-weight: 400;
  613. color: #888888;
  614. font-size: 22rpx;
  615. margin-top: 13rpx;
  616. .iconfont{
  617. font-size: 20rpx;
  618. margin-right: 8rpx;
  619. margin-top: 6rpx;
  620. }
  621. .info{
  622. width: 590rpx;
  623. line-height: 1.5;
  624. }
  625. }
  626. }
  627. }
  628. }
  629. .product-window {
  630. position: fixed;
  631. bottom: 0;
  632. width: 100%;
  633. left: 0;
  634. background-color: #fff;
  635. z-index: 100;
  636. border-radius: 16rpx 16rpx 0 0;
  637. transform: translate3d(0, 100%, 0);
  638. transition: all .3s cubic-bezier(.25, .5, .5, .9);
  639. padding-bottom: 140rpx;
  640. padding-bottom: calc(140rpx+ constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  641. padding-bottom: calc(140rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  642. }
  643. .product-window.on {
  644. transform: translate3d(0, 0, 0);
  645. }
  646. .product-window.join {
  647. padding-bottom: 30rpx;
  648. }
  649. .product-window.joinCart {
  650. padding-bottom: 30rpx;
  651. z-index: 10000;
  652. }
  653. .product-window .textpic {
  654. padding: 0 130rpx 0 30rpx;
  655. margin-top: 29rpx;
  656. position: relative;
  657. }
  658. .product-window .textpic .pictrue {
  659. width: 150rpx;
  660. height: 150rpx;
  661. position: relative;
  662. .icon{
  663. width: 30rpx;
  664. height: 30rpx;
  665. background-color: rgba(0,0,0,0.4);
  666. border-radius: 4rpx;
  667. position: absolute;
  668. bottom: 8rpx;
  669. right: 8rpx;
  670. text-align: center;
  671. line-height: 23rpx;
  672. .iconfont{
  673. color: #fff;
  674. font-size: 20rpx;
  675. }
  676. }
  677. }
  678. .product-window .textpic .pictrue image {
  679. width: 100%;
  680. height: 100%;
  681. border-radius: 10rpx;
  682. }
  683. .product-window .textpic .text {
  684. width: 410rpx;
  685. font-size: 32rpx;
  686. color: #202020;
  687. }
  688. .product-window .textpic .text .money {
  689. font-size: 24rpx;
  690. margin-top: 40rpx;
  691. .icon{
  692. display: inline-block;
  693. font-size: 16rpx;
  694. font-weight: normal;
  695. background: #FF9500;
  696. color: #fff;
  697. border-radius: 18rpx;
  698. padding: 2rpx 6rpx;
  699. margin-left: 10rpx;
  700. .iconfont{
  701. font-size: 16rpx;
  702. margin-right: 4rpx;
  703. color: #fff;
  704. }
  705. }
  706. }
  707. .product-window .textpic .text .money .num {
  708. font-size: 36rpx;
  709. }
  710. .product-window .textpic .text .money .stock {
  711. color: #999;
  712. margin-left: 6rpx;
  713. }
  714. .product-window .textpic .icon-guanbi {
  715. position: absolute;
  716. right: 30rpx;
  717. top: -5rpx;
  718. font-size: 35rpx;
  719. color: #8a8a8a;
  720. }
  721. .product-window .rollTop {
  722. max-height: 535rpx;
  723. overflow: auto;
  724. margin-top: 36rpx;
  725. }
  726. .product-window .productWinList .item~.item {
  727. margin-top: 36rpx;
  728. }
  729. .product-window .productWinList .item .title {
  730. font-size: 30rpx;
  731. color: #999;
  732. padding: 0 30rpx;
  733. }
  734. .product-window .productWinList .item .listn {
  735. padding: 0 30rpx 0 16rpx;
  736. }
  737. .product-window .productWinList .item .listn .itemn {
  738. border: 1px solid #F2F2F2;
  739. font-size: 26rpx;
  740. color: #282828;
  741. padding: 7rpx 33rpx;
  742. border-radius: 25rpx;
  743. margin: 20rpx 0 0 14rpx;
  744. background-color: #F2F2F2;
  745. word-break: break-all;
  746. }
  747. .product-window .productWinList .item .listn .itemn.on {
  748. color: var(--view-theme);
  749. background: var(--view-minorColorT);
  750. border-color: var(--view-theme);
  751. }
  752. .product-window .productWinList .item .listn .itemn.on2{
  753. background: #bbb;
  754. color: #fff;
  755. border-color: #bbb;
  756. }
  757. .product-window .productWinList .item .listn .itemn.limit {
  758. color: #999;
  759. text-decoration: line-through;
  760. }
  761. .product-window .cart {
  762. margin-top: 36rpx;
  763. padding: 0 30rpx;
  764. }
  765. .product-window .cart .title {
  766. font-size: 30rpx;
  767. color: #999;
  768. }
  769. .product-window .cart .carnum {
  770. height: 54rpx;
  771. margin-top: 24rpx;
  772. }
  773. .product-window .cart .carnum .iconfont {
  774. font-size: 25rpx;
  775. }
  776. .product-window .cart .carnum view {
  777. // border: 1px solid #a4a4a4;
  778. width: 84rpx;
  779. text-align: center;
  780. height: 100%;
  781. line-height: 54rpx;
  782. color: #282828;
  783. font-size: 45rpx;
  784. }
  785. .product-window .cart .carnum .reduce {
  786. border-right: 0;
  787. border-radius: 6rpx 0 0 6rpx;
  788. line-height: 48rpx;
  789. font-size: 60rpx;
  790. }
  791. .product-window .cart .carnum .reduce.on {
  792. color: #DEDEDE;
  793. }
  794. .product-window .cart .carnum .plus {
  795. border-left: 0;
  796. border-radius: 0 6rpx 6rpx 0;
  797. line-height: 46rpx;
  798. }
  799. .product-window .cart .carnum .plus.on {
  800. // border-color: #e3e3e3;
  801. color: #dedede;
  802. }
  803. .product-window .cart .carnum .num {
  804. background: rgba(242, 242, 242, 1);
  805. color: #282828;
  806. font-size: 28rpx;
  807. }
  808. .product-window .joinBnt {
  809. font-size: 30rpx;
  810. width: 620rpx;
  811. height: 86rpx;
  812. border-radius: 50rpx;
  813. text-align: center;
  814. line-height: 86rpx;
  815. color: #fff;
  816. margin: 21rpx auto 0 auto;
  817. }
  818. .product-window .joinBnt.on {
  819. background-color: #bbb;
  820. color: #fff;
  821. }
  822. </style>