index.vue 23 KB

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