panhui пре 5 година
родитељ
комит
00beeca1fe
9 измењених фајлова са 1163 додато и 37 уклоњено
  1. 16 15
      .prettierrc.js
  2. 7 0
      project.config.json
  3. 4 11
      src/App.vue
  4. 186 0
      src/components/GoodsSuk.vue
  5. 1 0
      src/main.js
  6. 795 0
      src/pages/shoppingDetail.vue
  7. 131 0
      src/pages/shoppingMall.vue
  8. 14 7
      src/pages/submit.vue
  9. 9 4
      src/pages/tuxiang.vue

+ 16 - 15
.prettierrc.js

@@ -2,19 +2,20 @@ module.exports = {
     printWidth: 120,
     singleQuote: true,
     tabWidth: 4,
-    overrides: [
-        {
-            files: '*.html',
-            options: {
-                parser: 'html'
-            }
-        },
-        {
-            files: '*.vue',
-            options: {
-                parser: 'vue'
-            }
-        }
-    ],
-    endOfLine: 'auto'
+    // overrides: [
+    //     {
+    //         files: '*.html',
+    //         options: {
+    //             parser: 'html'
+    //         }
+    //     },
+    //     {
+    //         files: '*.vue',
+    //         options: {
+    //             parser: 'vue'
+    //         }
+    //     }
+    // ],
+    endOfLine: 'auto',
+    // trailingCommas: 'none',
 };

+ 7 - 0
project.config.json

@@ -79,6 +79,13 @@
                     "pathName": "pages/tuxiang",
                     "scene": null
                 },
+                {
+                    "id": -1,
+                    "name": "商城详情",
+                    "pathName": "pages/shoppingDetail",
+                    "query": "id=1565980527708240",
+                    "scene": null
+                },
                 {
                     "id": -1,
                     "name": "新闻详情&活动详情",

+ 4 - 11
src/App.vue

@@ -3,9 +3,6 @@ export default {
     onLaunch(options) {
         wx.login({
             success: res => {
-                // console.log(res.code);
-                // return;
-                // eslint-disable-next-line no-unreachable
                 new Promise((resolve, reject) => {
                     wx.request({
                         method: 'get',
@@ -63,14 +60,6 @@ export default {
                             url: '/pages/home'
                         });
                     });
-
-                // this.$http.post('/auth/maLogin', { code: res.code }).then(res => {
-                //     this.$http.setToken(res.token);
-                //     this.$store.commit('setSessionKey', res.sessionKey);
-                //     this.$http.get('/user/my').then(res => {
-                //         this.$store.commit('setUserInfo', res);
-                //     });
-                // });
             },
             fail() {}
         });
@@ -168,4 +157,8 @@ export default {
         color: @prim !important;
     }
 }
+
+.van-popup {
+    overflow: visible;
+}
 </style>

+ 186 - 0
src/components/GoodsSuk.vue

@@ -0,0 +1,186 @@
+<template>
+    <div class="suk">
+        <div class="top">
+            <van-image :src="mainImg" fit="cover" class="icon" width="100" height="100" />
+            <div class="info">
+                <div class="name">{{ info.name }}</div>
+                <div class="price">¥{{ info.price }}</div>
+                <div class="sub">商品编码:{{ info.id }}</div>
+            </div>
+        </div>
+
+        <div class="skuSpec">
+            <div class="spec" v-for="(item, index) in allSkuSpecValues" :key="item.id">
+                <div class="text1">{{ item.name }}</div>
+                <div class="btns">
+                    <van-button
+                        :color="skuSpecValues.includes(spec.id) ? $colors.prim : ''"
+                        size="small"
+                        v-for="spec in item.specValues"
+                        :key="spec.id"
+                        @click="changeSuk(spec.id, index)"
+                    >
+                        {{ spec.name }}
+                    </van-button>
+                </div>
+            </div>
+        </div>
+
+        <div class="num">
+            <div class="text1">购买数量</div>
+            <van-stepper :value="num" @change="changeNum" />
+        </div>
+
+        <div style="flex-grow:1;min-height:10px"></div>
+        <van-button :color="$colors.prim" block @click="submit">立即购买</van-button>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+export default {
+    name: 'goodsSuk',
+    props: {
+        info: {
+            type: Object,
+            default: () => {
+                return {};
+            }
+        },
+        num: {
+            type: Number,
+            default: 0
+        }
+    },
+    data() {
+        return {
+            allSkuSpecValues: [],
+            allSuks: []
+        };
+    },
+    computed: {
+        ...mapState(['userInfo']),
+        skuSpecValues() {
+            return (
+                [...this.info.skuSpecValues].map(item => {
+                    return item.specValueId;
+                }) || []
+            );
+        },
+        sku() {
+            return this.info.sku || {};
+        },
+        mainImg() {
+            return this.info.images ? [...this.info.images].shift() : '';
+        }
+    },
+    watch: {
+        info() {
+            if (this.info.id) {
+                this.getSpecs();
+            }
+        }
+    },
+    methods: {
+        getSpecs() {
+            this.$http.post('/applets/queryspuspecs?spuId=' + this.info.spuId).then(res => {
+                console.log(res);
+                this.allSkuSpecValues = res;
+                this.$http.post('/applets/queryskuspecs?spuId=' + this.info.spuId).then(res => {
+                    this.allSuks = res.map(item => {
+                        return {
+                            key: item.id,
+                            values: item.skuSpecValues.map(child => {
+                                return child.specValueId;
+                            })
+                        };
+                    });
+                });
+            });
+        },
+        changeNum(e) {
+            // console.log(e);
+            this.$emit('update:num', e.detail);
+        },
+        changeSuk(id, index) {
+            console.log(id);
+            console.log(index);
+            const newSkuSpecValues = [...this.skuSpecValues];
+            newSkuSpecValues[index] = id;
+            console.log(newSkuSpecValues);
+            console.log(this.allSuks);
+            const sukInfo = [...this.allSuks].find(item => {
+                return item.values.join(',') === newSkuSpecValues.join(',');
+            });
+            this.$emit('changeSuk', sukInfo.key);
+        },
+        submit() {
+            this.$emit('submit');
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.suk {
+    min-height: 70vh;
+    display: flex;
+    flex-direction: column;
+}
+.top {
+    display: flex;
+    align-items: center;
+    transform: translateY(-10px);
+    padding: 0 15px;
+    .info {
+        padding: 10px;
+        .name {
+            font-size: 14px;
+            line-height: 16px;
+        }
+        .price {
+            font-size: 15px;
+            line-height: 15px;
+            color: #f23030;
+            padding-top: 5px;
+            font-weight: 700;
+        }
+        .sub {
+            font-size: 13px;
+            line-height: 13px;
+            color: #999;
+            margin-top: 5px;
+        }
+    }
+}
+
+.skuSpec {
+    padding: 15px;
+    .text1 {
+        font-size: 13px;
+        color: #81838e;
+    }
+
+    .btns {
+        display: flex;
+        align-items: center;
+        flex-wrap: wrap;
+        ._van-button {
+            margin-top: 5px;
+            margin-right: 5px;
+        }
+    }
+    .spec + .spec {
+        margin-top: 10px;
+    }
+}
+
+.num {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 15px;
+    .text1 {
+        font-size: 14px;
+    }
+    border-top: 1px solid #eee;
+}
+</style>

+ 1 - 0
src/main.js

@@ -73,6 +73,7 @@ export default {
             'pages/cityChoose',
             'pages/dealer',
             'pages/detail',
+            'pages/shoppingDetail',
             'pages/calculator',
             'pages/submit',
             'pages/addressEdit',

+ 795 - 0
src/pages/shoppingDetail.vue

@@ -0,0 +1,795 @@
+<config>
+{
+    "backgroundColor": "#ffffff",
+    "navigationBarTitleText": "商品详情"
+}
+</config>
+<template>
+    <div>
+        <van-empty description="找不到该商品信息" v-if="empty">
+            <div style="width: 100px;">
+                <van-button round block size="small" @click="back">
+                    返回
+                </van-button>
+            </div>
+        </van-empty>
+        <div v-else-if="loading" class="loading">
+            <van-loading size="24px" color="#1989fa">加载中...</van-loading>
+        </div>
+        <div v-else>
+            <swiper
+                class="product-swiper"
+                :indicator-dots="true"
+                indicator-color="rgba(0,0,0,0.1)"
+                indicator-active-color="rgba(0,0,0,0.3)"
+            >
+                <swiper-item v-for="(item, i) in info.images || []" :key="item" class="item" @click="preview(i)">
+                    <img :src="item" mode="aspectFill" />
+                </swiper-item>
+            </swiper>
+            <div class="title-block">
+                <div class="title">{{ info.name }}</div>
+                <div class="sub-title">{{ info.subTitle }}</div>
+                <div class="price-wrapper">
+                    <!-- <div>定金:</div> -->
+                    <div class="price">¥{{ info.price }}</div>
+                </div>
+            </div>
+            <div class="desc-block">
+                <div v-for="(item, index) in (info.sku || {}).descInformationList || []" :key="item.name">
+                    <div class="title">
+                        <div class="content">{{ item.name }}:</div>
+                        <img src="../static/imgs/icon_into.png" class="into" />
+                    </div>
+                    <div class="desc-item" v-for="(detailItem, i) in item.descDetailList" :key="i">
+                        <div class="tag" v-if="detailItem.tip">
+                            {{ detailItem.tip }}
+                        </div>
+                        <div class="content">{{ detailItem.content }}</div>
+                    </div>
+                    <div class="divider" v-if="index < ((info.sku || {}).descInformationList || []).length - 1"></div>
+                </div>
+            </div>
+            <div class="form-block">
+                <div class="info-item" v-if="skuSpecValues" @click="showSuk = true">{{ skuSpecValues }}</div>
+            </div>
+            <div class="form-block">
+                <div class="info-item">库存: {{ info.stock || 0 }}件</div>
+            </div>
+            <div class="form-block">
+                <div class="info-item" @click="showCityPicker = true">
+                    送至 <van-icon name="location" color="#ee0a24" />{{ provinceName }} {{ cityName }} {{ distName }}
+                </div>
+                <div class="info-item">运费: {{ freight.toFixed(2) }}元</div>
+            </div>
+            <!-- <div class="form-block">
+                <div class="item">
+                    <div class="label">适用车型:</div>
+                    <div class="value">全部车型</div>
+                    <img src="../static/imgs/icon_into.png" class="into" />
+                </div>
+                <div class="item">
+                    <div class="label">选择颜色:</div>
+                    <div class="value">到店为准</div>
+                    <img src="../static/imgs/icon_into.png" class="into" />
+                </div>
+                <div class="item" @click="showCityPicker = true">
+                    <div class="label">选择城市:</div>
+                    <div class="value" v-if="cityId">{{ cityName }}</div>
+                    <div class="value placeholder" v-else>请选择</div>
+                    <img src="../static/imgs/icon_into.png" class="into" />
+                </div>
+                <div class="item noborder" @click="chooseDealer">
+                    <div class="label">线下提车:</div>
+                    <div class="value" v-if="dealerId">{{ dealerName }}</div>
+                    <div class="value placeholder" v-else>请选择</div>
+                    <img src="../static/imgs/icon_into.png" class="into" />
+                </div>
+            </div> -->
+            <div class="tabs flex">
+                <div class="tab f15 text2 flex center" :class="{ active: tab === 0 }" @click="tab = 0">
+                    商品详情
+                </div>
+                <div class="tab f15 text2 flex center" :class="{ active: tab === 1 }" @click="(tab = 1), scroll()">
+                    参数配置
+                </div>
+            </div>
+            <div class="detail-wrapper" style="font-size: 0; padding-bottom: calc(env(safe-area-inset-bottom) + 44px);">
+                <rich-text :nodes="info.mobileDesc || ''" v-if="tab === 0"></rich-text>
+                <div v-if="tab === 1" class="specs-container">
+                    <div class="speces-info">
+                        <div class="speces-item" v-for="item in spuAttributeValues" :key="item.id">
+                            <div class="text1">
+                                {{ item.attributeName }}
+                            </div>
+                            <div class="text2">{{ item.attributeValue }}</div>
+                        </div>
+                    </div>
+
+                    <div class="f11 text1" style="margin: 15px 0 0 35px;">
+                        备注:详情可咨询当地经销商
+                    </div>
+                </div>
+            </div>
+            <van-button :color="$colors.prim" block class="btn-order" @click="submit">立即购买</van-button>
+        </div>
+
+        <van-action-sheet :show="showCityPicker">
+            <!-- eslint-disable -->
+            <van-picker
+                :columns="pickerColumns"
+                value-key="name"
+                show-toolbar
+                title="选择城市"
+                @cancel="showCityPicker = false"
+                @confirm="confirmCity"
+                @change="pickerChange"
+                id="cityPicker"
+            />
+            <!-- eslint-enable -->
+        </van-action-sheet>
+        <van-popup
+            :show="showSuk"
+            position="bottom"
+            closeable
+            custom-style="overflow: visible;"
+            @close="showSuk = false"
+        >
+            <goods-suk :info="info" :num.sync="num" @changeSuk="getInfo" @submit="submit"></goods-suk>
+        </van-popup>
+
+        <van-dialog id="van-dialog" />
+    </div>
+</template>
+<script>
+import qs from 'qs';
+import Dialog from '../vant/dialog/dialog';
+import GoodsSuk from '../components/GoodsSuk';
+var QQMapWX = require('../qqmap-wx-jssdk.js');
+let qqmapsdk;
+export default {
+    data() {
+        return {
+            info: {},
+            tab: 0,
+            showModelPicker: false,
+            models: [],
+            config: null,
+            specs: [],
+            provinceName: null,
+            provinceId: null,
+            cityName: null,
+            cityId: null,
+            distName: null,
+            distId: null,
+            showCityPicker: null,
+            picker: null,
+            dealerName: '',
+            dealerId: null,
+            dealerList: [],
+            showDealerPicker: false,
+            loading: false,
+            empty: false,
+            showSuk: false,
+            num: 1,
+            freight: 0,
+            areas: [],
+            pickerColumns: [],
+            sukId: 0
+        };
+    },
+    computed: {
+        mainImg() {
+            return this.info.images && this.info.images.length > 0 ? this.info.images[0] : '';
+        },
+        skuSpecValues() {
+            console.log(this.info.skuSpecValues);
+            if (this.info.skuSpecValues) {
+                return (
+                    [...this.info.skuSpecValues]
+                        .map(item => {
+                            return item.spec.name + ' ' + item.valueRemark;
+                        })
+                        .join(' , ') +
+                    ' ' +
+                    this.num +
+                    '个'
+                );
+            } else {
+                return '';
+            }
+        },
+        spuAttributeValues() {
+            return this.info.spuAttributeValues || [];
+        }
+    },
+    created() {
+        qqmapsdk = new QQMapWX({
+            key: 'MC4BZ-4QDWP-B5ZDD-VS3HX-NHBAO-CRBOQ'
+        });
+        this.locate();
+    },
+    onShow() {
+        if (this.info && this.info.id) {
+            return;
+        }
+
+        this.getInfo(this.$mp.query.id);
+    },
+    watch: {
+        skuSpecValues() {
+            this.getFreight();
+        },
+        cityId() {
+            this.getFreight();
+        }
+    },
+    methods: {
+        getInfo(sukId) {
+            this.loading = true;
+            this.sukId = sukId;
+            this.$http
+                .get('/applets/queryspudetail', {
+                    skuId: sukId
+                })
+                .then(res => {
+                    this.loading = false;
+                    if (!res.data) {
+                        this.empty = true;
+                        return;
+                    }
+                    if (res.data.mobileDesc) {
+                        res.data.mobileDesc = res.data.mobileDesc.replace(/<img/g, '<img class="rich-text-img"');
+                    }
+                    if (res.data.mobileConfig) {
+                        res.data.mobileConfig = res.data.mobileConfig.replace(/<img/g, '<img class="rich-text-img"');
+                    }
+                    this.info = res.data;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.loading = false;
+                    this.empty = true;
+                });
+        },
+        back() {
+            wx.navigateBack();
+        },
+        locate() {
+            let province, city, provinceId, cityId, dist;
+            this.$http
+                .get('https://apis.map.qq.com/ws/location/v1/ip', {
+                    key: 'MC4BZ-4QDWP-B5ZDD-VS3HX-NHBAO-CRBOQ'
+                })
+                .then(res => {
+                    console.log(res);
+                    this.location = res.result.location;
+                    province = res.result.ad_info.province.replace(/省/, '');
+                    city = res.result.ad_info.city;
+                    dist = res.result.ad_info.district;
+                    return this.$http.post('/applets/queryallprovinces');
+                })
+                .then(res => {
+                    console.log(province);
+                    console.log(res);
+                    let provinceInfo = res.data.find(i => i.name === province) || {};
+                    this.provinceName = provinceInfo.name;
+                    this.provinceId = provinceInfo.id;
+                    let cityInfo = (provinceInfo.child || []).find(i => i.name === city) || {};
+                    this.cityName = cityInfo.name;
+                    this.cityId = cityInfo.id;
+                    let distInfo = (cityInfo.child || []).find(i => i.name === dist) || {};
+                    this.distName = distInfo.name;
+                    this.distId = distInfo.id;
+                    this.areas = res.data.sort((a, b) => {
+                        return a.id - b.id;
+                    });
+                    this.getPickerColum(this.provinceId, this.cityId);
+                })
+                .catch(e => {
+                    console.log(e);
+                });
+        },
+        getPickerColum(provinceId, cityId) {
+            const provinceInfo = [...this.areas].find(item => {
+                return provinceId === item.id;
+            }) || { child: [] };
+            if (!cityId) {
+                cityId = provinceInfo.child[0].id;
+            }
+            const cityInfo = [...provinceInfo.child].find(item => {
+                return cityId === item.id;
+            }) || { child: [] };
+
+            if (cityInfo.child.length > 0) {
+                this.pickerColumns = [
+                    {
+                        values: [...this.areas],
+                        className: 'column1',
+                        defaultIndex:
+                            [...this.areas].findIndex(item => {
+                                return provinceId === item.id;
+                            }) || 0
+                    },
+                    {
+                        values: provinceInfo.child,
+                        className: 'column2'
+                    },
+                    {
+                        values: cityInfo.child,
+                        className: 'column3'
+                    }
+                ];
+            } else {
+                this.pickerColumns = [
+                    {
+                        values: [...this.areas],
+                        className: 'column1'
+                    },
+                    {
+                        values: provinceInfo.child,
+                        className: 'column2'
+                    }
+                ];
+            }
+        },
+        calculator() {
+            wx.navigateTo({
+                url: '/pages/calculator'
+            });
+        },
+        submit() {
+            if (!this.$store.state.loginInfo.link) {
+                Dialog.alert({
+                    title: '提示',
+                    message: '你还没有登录,是否立即登录',
+                    className: 'custom-class-name',
+                    showCancelButton: true
+                }).then(() => {
+                    wx.navigateTo({
+                        url: '/pages/login'
+                    });
+                });
+                return;
+            }
+            // if (!this.cityId) {
+            //     wx.showToast({
+            //         icon: 'none',
+            //         title: '请选择城市'
+            //     });
+            //     return;
+            // }
+
+            wx.navigateTo({
+                url:
+                    '/pages/submit?' +
+                    qs.stringify({
+                        skuId: this.info.id,
+                        num: this.num
+                    })
+            });
+        },
+        scroll() {
+            const query = wx.createSelectorQuery();
+            query.select('.tabs').boundingClientRect();
+            query.selectViewport().scrollOffset();
+            query.exec(function(res) {
+                console.log(res);
+                wx.pageScrollTo({
+                    scrollTop: res[0].top + res[1].scrollTop,
+                    duration: 250
+                });
+            });
+        },
+        confirmModel(e) {
+            let value = this.$mp.page.selectComponent('#modelPicker').getColumnValue(0);
+            this.getConfig(value.id);
+            this.showModelPicker = false;
+        },
+        getConfig(id) {
+            this.$http
+                .get(
+                    `https://dealer.jetour.com.cn/api-basic/api/carmodel/front/${id}`,
+                    {},
+                    { header: { Authorization: '' } }
+                )
+                .then(res => {
+                    this.specs = JSON.parse(res.config).map((i, index) => {
+                        i.name = i.name.replace('■', '');
+                        i.show = index === 0;
+                        return i;
+                    });
+                    console.log('config::', this.specs);
+                    this.config = res;
+                });
+        },
+        numberWithCommas(x) {
+            return x.toLocaleString('en');
+        },
+        confirmCity(e) {
+            console.log(e);
+            this.provinceId = e.detail.value[0].id;
+            this.provinceName = e.detail.value[0].name;
+            this.cityId = e.detail.value[1].id;
+            this.cityName = e.detail.value[1].name;
+            this.distId = e.detail.value[2].id;
+            this.distName = e.detail.value[2].name;
+            this.showCityPicker = false;
+            this.dealerName = '';
+            this.dealerId = null;
+            this.getDealer();
+        },
+        pickerChange(e) {
+            console.log(e);
+            if (e.detail.index === 0) {
+                this.getPickerColum(e.detail.value[0].id);
+            } else if (e.detail.index === 1) {
+                this.getPickerColum(e.detail.value[0].id, e.detail.value[1].id);
+            }
+
+            // if (e.detail.index === 0) {
+            //     this.$http
+            //         .get(
+            //             // eslint-disable-next-line prettier/prettier
+            //             `https://dealer.jetour.com.cn/api-dealer/dealer-info/getCityBySeriesIdAndProvinceId/0cbe50af-c29a-4eb0-91cc-4a05c5f05c57/${this.info.categories[0].carSystem}/${e.detail.value[0].id}`
+            //         )
+            //         .then(res => {
+            //             // eslint-disable-next-line prettier/prettier
+            //             this.picker.setColumnValues(
+            //                 1, //
+            //                 res.data.sort((a, b) => a.id - b.id)
+            //             );
+            //         });
+            // }
+        },
+        getDealer() {
+            // this.$http
+            //     .post(
+            //         'https://dealer.jetour.com.cn/api-dealer/dealer-info/searchDealerListByCondition',
+            //         {
+            //             brandId: '0cbe50af-c29a-4eb0-91cc-4a05c5f05c57',
+            //             provinceId: this.provinceId,
+            //             cityId: this.cityId,
+            //             enabledFlag: 1,
+            //             type: 1
+            //         },
+            //         {
+            //             header: {
+            //                 Authorization: '',
+            //                 'Content-Type': 'application/json'
+            //             }
+            //         }
+            //     )
+            //     .then(res => {
+            //         res.data = res.data.filter(
+            //             i => i.showWebsiteFlag == 1 && !(typeof i.code === 'string' && i.code.startsWith('99999'))
+            //         );
+            //         this.dealerList = res.data;
+            //     });
+        },
+        chooseDealer() {
+            if (!this.cityId) {
+                wx.showToast({
+                    icon: 'none',
+                    title: '请先选择城市'
+                });
+                return;
+            }
+            this.showDealerPicker = true;
+        },
+        confirmDealer() {
+            let value = this.$mp.page.selectComponent('#dealerPicker').getColumnValue(0);
+            this.dealerName = value.name;
+            this.dealerId = value.id;
+            this.showDealerPicker = false;
+        },
+        preview(i) {
+            wx.previewImage({
+                current: this.info.images[i],
+                urls: this.info.images
+            });
+        },
+        getFreight() {
+            console.log('获取运费');
+            if (this.info.id) {
+                this.$http
+                    .post('/applets/calculatefreight', {
+                        skuId: this.info.skuNo,
+                        cityId: this.cityId,
+                        storeId: this.info.storeId,
+                        num: this.num
+                    })
+                    .then(res => {
+                        this.freight = res.data;
+                    });
+            }
+        }
+    },
+    components: {
+        GoodsSuk
+    }
+};
+</script>
+<style lang="less">
+page {
+    background: @bg;
+}
+.product-swiper {
+    width: 100%;
+    height: 100vw;
+    background: white;
+    .item {
+        width: 100%;
+        height: 100%;
+        img {
+            width: 100%;
+            height: 100%;
+        }
+    }
+}
+.title-block {
+    padding: 15px 25px;
+    background: white;
+    line-height: 1;
+    margin-top: 10px;
+    .title {
+        font-size: 15px;
+        color: @text1;
+    }
+    .sub-title {
+        font-size: 12px;
+        color: @prim;
+        margin-top: 14px;
+    }
+    .price-wrapper {
+        .flex();
+        font-size: 10px;
+        color: @text2;
+        margin-top: 17px;
+        align-items: baseline;
+        .price {
+            margin-left: 12px;
+            font-size: 16px;
+            color: #ff0101;
+        }
+    }
+}
+.desc-block {
+    margin-top: 10px;
+    background: white;
+    padding: 0 25px;
+    .title {
+        .flex();
+        height: 35px;
+        .content {
+            flex-grow: 1;
+            font-size: 15px;
+            color: @text3;
+        }
+        .into {
+            width: 24px;
+            height: 24px;
+        }
+    }
+    .desc-item {
+        .flex();
+        padding: 10px 0;
+        align-items: flex-start;
+        .tag {
+            width: 65px;
+            min-width: 65px;
+            height: 20px;
+            box-sizing: border-box;
+            border: 1px solid @prim;
+            .flex();
+            justify-content: center;
+            margin-right: 10px;
+            font-size: 12px;
+            color: @prim;
+        }
+        .content {
+            flex-basis: 0;
+            flex-grow: 1;
+            font-size: 13px;
+            color: @text1;
+            // .ellipsis();
+            line-height: 20px;
+        }
+    }
+    .divider {
+        background: #dedede;
+        height: 1px;
+        min-height: 1px;
+        width: 100%;
+        margin-top: 6px;
+        margin-bottom: 6px;
+    }
+}
+.form-block {
+    background: white;
+    padding: 0 25px;
+    margin-top: 10px;
+    .item {
+        .flex();
+        font-size: 15px;
+        border-bottom: 1px solid #dedede;
+        height: 45px;
+        .label {
+            width: 80px;
+            color: @text3;
+        }
+        .value {
+            flex-grow: 1;
+            color: @text1;
+            .ellipsis();
+        }
+        .placeholder {
+            color: @text3;
+        }
+        .into {
+            width: 24px;
+            height: 24px;
+        }
+        &.noborder {
+            border: none;
+        }
+    }
+}
+.tabs {
+    align-items: flex-start;
+    background: white;
+    margin-top: 10px;
+    .tab {
+        flex-basis: 0;
+        flex-grow: 1;
+        border-bottom: 1px solid #dedede;
+        height: 48px;
+        &.active {
+            color: @prim;
+            border-bottom: 2px solid @prim;
+        }
+    }
+}
+rich-text {
+    width: 100%;
+    background: white;
+}
+.rich-text-img {
+    width: 100% !important;
+    height: auto;
+}
+.detail-wrapper {
+    background: white;
+    padding-bottom: 0;
+}
+.btn-order {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    .van-button {
+        border-radius: 0;
+        padding-bottom: calc(env(safe-area-inset-bottom) / 2) !important;
+        height: calc(52px + env(safe-area-inset-bottom) / 2) !important;
+        font-size: 15px;
+    }
+}
+.specs-container {
+    padding: 16px;
+    background: #fff;
+    .specs-card {
+        background: #ffffff;
+        border: 1px solid #ececec;
+        box-shadow: 0px 1px 6px 0 rgba(0, 0, 0, 0.08);
+        border-radius: 6px;
+        .title {
+            padding: 34px 0 30px 0;
+            text-align: center;
+            border-bottom: 1px solid @border5;
+            font-size: 21px;
+            color: @text1;
+        }
+        .dropdown {
+            .flex();
+            height: 34px;
+            border-bottom: 1px solid @border5;
+            padding: 0 11px 0 22px;
+            font-weight: bold;
+            img {
+                width: 15px;
+                height: 15px;
+            }
+        }
+        .tip {
+            .flex();
+            height: 34px;
+            border-bottom: 1px solid @border5;
+            padding: 0 11px 0 22px;
+            font-weight: bold;
+            color: @text2;
+            .item {
+                margin-right: 20px;
+                .sym {
+                    margin-right: 5px;
+                }
+            }
+        }
+        .row {
+            .flex();
+            font-size: 11px;
+            border-bottom: 1px solid @border5;
+            align-items: stretch;
+            .col1,
+            .col2 {
+                flex-basis: 0;
+                flex-grow: 1;
+                .flex();
+                padding: 11px 10px;
+            }
+            .col1 {
+                justify-content: start;
+                padding-left: 22px;
+                border-right: 1px solid @border5;
+                color: @text1;
+            }
+            .col2 {
+                justify-content: center;
+                color: @text1;
+                padding: 11px 10px;
+            }
+            .prim {
+                color: @prim;
+            }
+            &.noborder {
+                border: none;
+            }
+        }
+        .head {
+            height: 34px;
+            .flex();
+            font-size: 11px;
+            border-bottom: 1px solid @border5;
+            padding-left: 23px;
+            font-size: 15px;
+            color: @text1;
+            background: #ececec;
+            .icon {
+                width: 15px;
+                height: 15px;
+                margin-right: 11px;
+            }
+        }
+    }
+}
+.loading {
+    .flex();
+    height: 80vh;
+    justify-content: center;
+}
+.info-item {
+    font-size: 14px;
+    padding: 10px 0;
+}
+
+.speces-info {
+    font-size: 12px;
+    color: #848689;
+    border: 1px solid #eee;
+}
+.speces-item {
+    display: flex;
+    border-bottom: 1px solid #eee;
+    div {
+        padding: 10px;
+
+        &.text2 {
+            flex-grow: 1;
+        }
+
+        &.text1 {
+            min-width: 110px;
+            border-right: 1px solid #eee;
+        }
+    }
+}
+</style>

+ 131 - 0
src/pages/shoppingMall.vue

@@ -0,0 +1,131 @@
+<template>
+    <div class="shooping-list">
+        <div class="shooping-item" v-for="item in list" :key="item.id" @click="detail(item)">
+            <img class="cover" mode="aspectFill" :src="item.columnValue.appImgurl" />
+            <div class="content">
+                <div class="title">{{ item.columnValue.name }}</div>
+                <div class="btn">
+                    <div class="price">{{ item.columnValue.price }}</div>
+                    <van-button size="small" round :color="$colors.prim">立即抢购</van-button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import format from 'date-fns/format';
+import parse from 'date-fns/parse';
+export default {
+    data() {
+        return {
+            page: 1,
+            size: 20,
+            last: false,
+            list: [],
+            loading: false
+        };
+    },
+    created() {
+        this.getData();
+    },
+    methods: {
+        fmt(time) {
+            return format(parse(time, 'yyyy-MM-dd HH:mm:ss', new Date()), 'yyyy/MM/dd');
+        },
+        getData() {
+            if (this.loading) return;
+            this.loading = true;
+            this.$http
+                .get('/applets/carPopup/6')
+                .then(res => {
+                    this.loading = false;
+                    this.list = res.data.map(item => {
+                        return {
+                            ...item,
+                            columnValue: JSON.parse(item.columnValue)
+                        };
+                    });
+                    // if (res.success) {
+                    //     if (res.data.page.currentPage === 1) {
+                    //         this.list = [];
+                    //     }
+                    //     this.list = this.list.concat(res.data.pp);
+                    //     this.last = res.data.page.currentPage === res.data.page.totalPage;
+                    // }
+                })
+                .catch(e => {
+                    this.loading = false;
+                });
+        },
+        loadmore() {
+            if (!this.loading && !this.last) {
+                // this.page++;
+                // this.getData();
+            }
+        },
+        detail(item) {
+            // wx.request({
+            //     method: 'PUT',
+            //     url: 'https://www.jetour.com.cn/cmsapi/business/Carousel/videoadd?id=' + item.id,
+            //     dataType: 'json',
+            //     success(res) {},
+            //     fail(err) {}
+            // }); url: '/pages/detail?id=' + item.skuId
+            wx.navigateTo({
+                url: `/pages/shoppingDetail?id=${item.columnValue.skuId}`
+            });
+        }
+    }
+};
+</script>
+<style lang="less">
+.shooping-list {
+    background: #ffffff;
+}
+.shooping-item {
+    padding: 20px 15px;
+    display: flex;
+
+    .cover {
+        width: 118px;
+        height: 118px;
+    }
+    .content {
+        flex-grow: 1;
+        padding: 20px 0 20px 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+
+        .title {
+            font-size: 21px;
+            color: #333333;
+            line-height: 24px;
+        }
+
+        .btn {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .price {
+                font-size: 15px;
+                font-weight: bold;
+                color: #838383;
+            }
+        }
+    }
+}
+
+.shooping-item + .shooping-item {
+    position: relative;
+    &::before {
+        content: '';
+        position: absolute;
+        top: 0px;
+        right: 15px;
+        left: 15px;
+        height: 1px;
+        background-color: #ebebeb;
+    }
+}
+</style>

+ 14 - 7
src/pages/submit.vue

@@ -34,7 +34,7 @@
                 <div class="name">
                     {{ normalSku.name }}
                 </div>
-                <div class="amount">×1</div>
+                <div class="amount">×{{ num }}</div>
             </div>
             <div class="extra">
                 <div class="row" style="margin-top: 8px;">
@@ -47,15 +47,15 @@
                 </div>
             </div>
             <div class="sum f12 text3">
-                共件&nbsp;<span class="f14 text1">
-                    小计:<span class="price">¥{{ settlementInfo.orderTotalPrice }}</span>
+                共{{ num }}件&nbsp;<span class="f14 text1">
+                    小计:<span class="price">¥{{ totalPrice }}</span>
                 </span>
             </div>
         </div>
         <div class="bottom">
             <div class="sum f12 text3">
-                共件&nbsp;<span class="f14 text1"
-                    >小计:<span class="price">¥{{ settlementInfo.orderTotalPrice }}</span></span
+                共{{ num }}件&nbsp;<span class="f14 text1"
+                    >小计:<span class="price">¥{{ totalPrice }}</span></span
                 >
             </div>
             <div class="btn" @click="submit">提交订单</div>
@@ -72,7 +72,8 @@ export default {
             skuInfo: {},
             settlementInfo: {},
             addressId: null,
-            remark: ''
+            remark: '',
+            num: 1
         };
     },
     created() {
@@ -82,6 +83,9 @@ export default {
         this.skuInfo = skuInfo;
         console.log(skuInfo);
         this.settlement();
+        if (skuInfo.num) {
+            this.num = skuInfo.num;
+        }
     },
     computed: {
         storeName() {
@@ -92,6 +96,9 @@ export default {
                 ((((this.settlementInfo.storeSettlements || [])[0] || {}).shoppingCartResponse || {}).normalSkus ||
                     [])[0] || {}
             );
+        },
+        totalPrice() {
+            return Number(this.settlementInfo.orderTotalPrice) * this.num;
         }
     },
     methods: {
@@ -155,7 +162,7 @@ export default {
                                 }
                             ],
                             ids: [],
-                            skuInfo: this.skuInfo.skuId + ',1',
+                            skuInfo: this.skuInfo.skuId + ',' + this.num,
                             redEnvelopeCode: null,
                             isGroup: 0,
                             groupId: null,

+ 9 - 4
src/pages/tuxiang.vue

@@ -5,26 +5,28 @@
                 <van-tab title="活动" name="1"></van-tab>
                 <van-tab title="精彩视频" name="2"></van-tab>
                 <van-tab title="新闻" name="3"></van-tab>
-                <van-tab title="旅行+" name="4"></van-tab>
+                <van-tab title="旅行商城" name="4"></van-tab>
             </van-tabs>
         </van-sticky>
         <event-list v-if="tab === '1'" ref="eventList"></event-list>
         <video-list v-if="tab === '2'" ref="videoList"></video-list>
         <news-list v-if="tab === '3'" ref="newsList"></news-list>
-        <tour v-if="tab === '4'"></tour>
+        <!-- <tour v-if="tab === '4'"></tour> -->
+        <shopping-mall v-if="tab === '4'" ref="shoopingMall"></shopping-mall>
     </div>
 </template>
 <script>
 import eventList from './eventList';
 import newsList from './newsList';
 import tour from './tour';
+import shoppingMall from './shoppingMall';
 import videoList from './videoList';
 export default {
     components: {
         eventList,
-        tour,
         newsList,
-        videoList
+        videoList,
+        shoppingMall
     },
     data() {
         return {
@@ -47,6 +49,9 @@ export default {
             case '3':
                 this.$refs.newsList.loadmore();
                 break;
+            case '4':
+                this.$refs.shoopingMall.loadmore();
+                break;
         }
     },
     methods: {