panhui il y a 5 ans
Parent
commit
9f54496774

+ 4 - 1
megalo.config.js

@@ -36,7 +36,10 @@ module.exports = {
             .use('style-resources-loader')
             .loader('style-resources-loader')
             .options({
-                patterns: [path.resolve(__dirname, './src/styles/common.less')]
+                patterns: [
+                    path.resolve(__dirname, './src/styles/common.less'),
+                    path.resolve(__dirname, './src/styles/fonts.less')
+                ]
             })
             .end();
     },

+ 17 - 4
project.config.json

@@ -112,20 +112,20 @@
                 {
                     "id": -1,
                     "name": "新闻咨询",
-                    "pathName": "pages/news/News",
+                    "pathName": "pagesNews/News",
                     "scene": null
                 },
                 {
                     "id": -1,
                     "name": "新闻咨询详情",
-                    "pathName": "pages/news/Detail",
+                    "pathName": "pagesNews/Detail",
                     "scene": null,
                     "query": "id=104"
                 },
                 {
                     "id": -1,
                     "name": "活动报名",
-                    "pathName": "pages/news/Submit",
+                    "pathName": "pagesNews/Submit",
                     "scene": null,
                     "query": "infoId=104&activityId=6806"
                 },
@@ -154,7 +154,20 @@
                     "pathName": "pages/ProductList",
                     "query": "categoryIds=9",
                     "scene": null
-                }
+                },
+                {
+                    "id": -1,
+                    "name": "商品详情",
+                    "pathName": "pagesProduct/Detail",
+                    "query": "id=4763",
+                    "scene": null
+                },{
+                      "id": -1,
+                      "name": "商品对比",
+                      "pathName": "pagesProduct/Contrast",
+                      "query": "productId=4763",
+                      "scene": null
+                  }
             ]
         }
     }

+ 20 - 7
src/App.vue

@@ -9,7 +9,18 @@ export default {
                 this.$http.post('/auth/maLogin', { code: res.code }).then(res => {
                     this.$http.setToken(res.token);
                     this.$store.commit('setSessionKey', res.sessionKey);
-                    this.$store.dispatch('getUserInfo');
+                    this.$store
+                        .dispatch('getUserInfo')
+                        .then(() => {
+                            this.globalData.initialize = true;
+                            console.log(this.globalData);
+                            if (this.globalData.initializeCallback) {
+                                this.globalData.initializeCallback();
+                            }
+                        })
+                        .catch(() => {
+                            this.globalData.initialize = true;
+                        });
                 });
             },
             fail() {}
@@ -29,7 +40,7 @@ export default {
     },
     globalData() {
         return {
-            a: 'I am global data'
+            initialize: false
         };
     }
 };
@@ -114,11 +125,6 @@ page {
     background-color: #fff;
 }
 
-@font-face {
-    font-family: 'OSP';
-    src: url(http://imt.oss-cn-hangzhou.aliyuncs.com/micro/OSP-DIN.ttf);
-}
-
 .form {
     .van-cell {
         --cell-vertical-padding: 23px;
@@ -135,4 +141,11 @@ page {
         }
     }
 }
+
+.my-icon {
+    &:active {
+        color: @warn!important;
+        background-color: darken(#fff, 5);
+    }
+}
 </style>

+ 8 - 8
src/components/Banner.vue

@@ -11,14 +11,14 @@
                     <van-image :src="item.img" width="100%" height="100%" fit="cover" :radius="radius" />
                 </swiper-item>
             </swiper>
-            <div class="dots" :class="{ isRight: right }" v-if="banners.length > 1">
-                <div
-                    class="dot"
-                    :class="{ active: index === current }"
-                    v-for="(item, index) in banners"
-                    :key="item.id"
-                ></div>
-            </div>
+        </div>
+        <div class="dots" :class="{ isRight: right }" v-if="banners.length > 1">
+            <div
+                class="dot"
+                :class="{ active: index === current }"
+                v-for="(item, index) in banners"
+                :key="item.id"
+            ></div>
         </div>
     </div>
 </template>

+ 1 - 1
src/components/News/Grid.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="news-grid news" @click="navigateTo('/pages/news/Detail?id=' + info.id, false)">
+    <div class="news-grid news" @click="navigateTo('/pagesNews/Detail?id=' + info.id, false)">
         <van-image :src="info.img" fit="cover" :height="180" custom-class="my-img" />
         <div class="text1">{{ info.title }}</div>
         <div class="activity" v-if="isActivity">

+ 1 - 1
src/components/News/Row.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="news" @click="navigateTo('/pages/news/Detail?id=' + info.id, false)">
+    <div class="news" @click="navigateTo('/news/Detail?id=' + info.id, false)">
         <van-image :src="info.img" fit="cover" :width="120" :height="120" custom-class="my-img" />
         <div class="news-info">
             <div class="text1">{{ info.title }}</div>

+ 9 - 1
src/components/bar/CustomBar.vue

@@ -29,6 +29,14 @@ export default {
         title: {
             type: String,
             default: ''
+        },
+        dark: {
+            type: Boolean,
+            default: true
+        },
+        barTop: {
+            type: Number,
+            default: 100
         }
     },
     data() {
@@ -54,7 +62,7 @@ export default {
             return style;
         },
         fontColor() {
-            return this.ratio ? '#000' : '#fff';
+            return this.ratio || !this.dark ? '#000' : '#fff';
         }
     },
     mounted() {

+ 9 - 2
src/components/product/Grid.vue

@@ -1,6 +1,6 @@
 <template>
-    <div class="grid">
-        <van-image class="grid-img" width="100%" :src="getList(info.img)" fit="cover" />
+    <div class="grid" @click="navigateTo(`/pagesProduct/Detail?id=${info.id}`, false)">
+        <van-image class="grid-img" width="100%" :src="img" fit="cover" />
         <div class="content">
             <div class="text">
                 <h4>{{ name }}</h4>
@@ -25,6 +25,13 @@ export default {
     computed: {
         name() {
             return this.getName(this.info);
+        },
+        img() {
+            if (this.getList(this.info.img)) {
+                return this.getList(this.info.img) + '?x-oss-process=image/resize,m_fill,h_200,w_200';
+            } else {
+                return '';
+            }
         }
     }
 };

+ 9 - 2
src/components/product/GridBig.vue

@@ -1,6 +1,6 @@
 <template>
-    <div class="grid">
-        <van-image class="grid-img" width="100%" height="170px" :src="getList(info.img)" fit="cover" />
+    <div class="grid" @click="navigateTo(`/pagesProduct/Detail?id=${info.id}`, false)">
+        <van-image class="grid-img" width="100%" height="170px" :src="img" fit="cover" />
         <div class="content">
             <div class="text">
                 <h3>{{ name }}</h3>
@@ -27,6 +27,13 @@ export default {
     computed: {
         name() {
             return this.getName(this.info);
+        },
+        img() {
+            if (this.getList(this.info.img)) {
+                return this.getList(this.info.img) + '?x-oss-process=image/resize,m_fill,h_750,w_750';
+            } else {
+                return '';
+            }
         }
     }
 };

+ 9 - 2
src/components/product/GridNormal.vue

@@ -1,6 +1,6 @@
 <template>
-    <div class="grid">
-        <van-image class="grid-img" width="100%" height="170px" :src="getList(info.img)" fit="cover" />
+    <div class="grid" @click="navigateTo(`/pagesProduct/Detail?id=${info.id}`, false)">
+        <van-image class="grid-img" width="100%" height="170px" :src="img" fit="cover" />
         <div class="content">
             <van-image class="grid-logo" width="56" height="24" :src="info.logo" fit="cover" />
             <div class="text">
@@ -40,6 +40,13 @@ export default {
                     })
                     .slice(0, 3) || []
             );
+        },
+        img() {
+            if (this.getList(this.info.img)) {
+                return this.getList(this.info.img) + '?x-oss-process=image/resize,m_fill,h_300,w_300';
+            } else {
+                return '';
+            }
         }
     }
 };

+ 95 - 0
src/components/product/Parameter.vue

@@ -0,0 +1,95 @@
+<template>
+    <div class="Parameter">
+        <div class="parameter-item" v-for="item in list" :key="item.id">
+            <div class="parameter-first">{{ getName(item) }}</div>
+            <div class="parameter-info" v-if="item.value || item.children.length === 0">
+                <div class="parameter-value">
+                    {{ item.value || '-' }}
+                </div>
+            </div>
+            <div class="parameter-info" v-else>
+                <div class="parameter-pa" v-for="child in item.children" :key="child.id">
+                    <div class="parameter-pa1">{{ getName(child) }}</div>
+                    <div class="parameter-pa1">{{ item.value || '-' }}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    props: {
+        productId: {
+            type: [Number, String],
+            default: ''
+        }
+    },
+    data() {
+        return {
+            list: []
+        };
+    },
+    mounted() {
+        this.$http.post('/productParameter/getProductParameter?productId=' + this.productId).then(res => {
+            this.list = res;
+        });
+    }
+};
+</script>
+<style lang="less" scoped>
+.Parameter {
+    border: 1px solid #f2f3f5;
+}
+.parameter-item {
+    display: flex;
+    &:not(:last-child) {
+        border-bottom: 1px solid #f2f3f5;
+    }
+    .parameter-first {
+        padding: 12px;
+        font-size: 12px;
+        font-weight: bold;
+        color: #292c33;
+        line-height: 22px;
+        display: flex;
+        align-items: center;
+        width: 83px;
+        flex-shrink: 0;
+        box-sizing: border-box;
+    }
+
+    .parameter-info {
+        flex-grow: 1;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        border-left: 1px solid #f2f3f5;
+
+        .parameter-value {
+            padding: 12px;
+            box-sizing: border-box;
+            font-size: 12px;
+            color: #292c33;
+            line-height: 22px;
+        }
+
+        .parameter-pa {
+            display: flex;
+            &:not(:last-child) {
+                border-bottom: 1px solid #f2f3f5;
+            }
+            .parameter-pa1 {
+                width: 50%;
+                padding: 12px;
+                box-sizing: border-box;
+                font-size: 12px;
+                color: #292c33;
+                line-height: 22px;
+                &:not(:last-child) {
+                    border-right: 1px solid #f2f3f5;
+                }
+            }
+        }
+    }
+}
+</style>

+ 45 - 0
src/components/product/RowMini copy.vue

@@ -0,0 +1,45 @@
+<template>
+    <div class="product">
+        <van-image :src="img" :width="62" :height="62" fit="cover" />
+        <div class="info">
+            <h3>{{ getName(info) }}</h3>
+            <div class="sub">
+                <van-image :src="info.logo" v-if="info.logo" :width="39" :height="17" fit="contain" />
+                <p>{{ info.model }}</p>
+            </div>
+        </div>
+        <van-icon :size="20" color="#BCC1CC" name="delete" />
+    </div>
+</template>
+<script>
+export default {
+    props: {
+        info: {
+            type: Object,
+            default: () => {
+                return {};
+            }
+        }
+    },
+    computed: {
+        img() {
+            if (this.getList(this.info.img)) {
+                return this.getList(this.info.img) + '?x-oss-process=image/resize,m_fill,h_200,w_200';
+            } else {
+                return '';
+            }
+        }
+    },
+    data() {
+        return {};
+    }
+};
+</script>
+<style lang="less" scoped>
+.product {
+    display: flex;
+    .info {
+        flex-grow: 1;
+    }
+}
+</style>

+ 64 - 0
src/components/product/RowMini.vue

@@ -0,0 +1,64 @@
+<template>
+    <div class="product" @click="choose">
+        <van-icon :name="checked ? 'checked' : 'circle'" :color="checked ? $colors.warn : '#BCC1CC'" :size="16" />
+        <van-image :src="img" :width="62" :height="62" fit="cover" />
+        <div class="info">
+            <h3>{{ getName(info) }}</h3>
+            <div class="sub">
+                <van-image :src="info.logo" v-if="info.logo" :width="39" :height="17" fit="contain" />
+                <p>{{ info.model }}</p>
+            </div>
+        </div>
+        <van-icon @click.stop="del" :size="20" color="#BCC1CC" name="delete" />
+    </div>
+</template>
+<script>
+export default {
+    props: {
+        info: {
+            type: Object,
+            default: () => {
+                return {};
+            }
+        },
+        checked: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        img() {
+            if (this.getList(this.info.img)) {
+                return this.getList(this.info.img) + '?x-oss-process=image/resize,m_fill,h_300,w_300';
+            } else {
+                return '';
+            }
+        }
+    },
+    methods: {
+        choose() {
+            this.$emit('choose', this.info.id);
+        },
+        del() {
+            this.$emit('del', this.info.id);
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.product {
+    display: flex;
+    .info {
+        flex-grow: 1;
+        margin-left: 8px;
+    }
+
+    ._van-icon {
+        align-self: center;
+    }
+
+    ._van-image {
+        margin-left: 12px;
+    }
+}
+</style>

+ 13 - 5
src/main.js

@@ -69,10 +69,17 @@ export default {
             'pages/ProductList',
             'pages/FilterPage',
             'pages/imt/Index',
-            'pages/imt/ServiceDetail',
-            'pages/news/News',
-            'pages/news/Detail',
-            'pages/news/Submit'
+            'pages/imt/ServiceDetail'
+        ],
+        subPackages: [
+            {
+                root: 'pagesProduct',
+                pages: ['Detail', 'Contrast']
+            },
+            {
+                root: 'pagesNews',
+                pages: ['Detail', 'News', 'Submit']
+            }
         ],
         tabBar: {
             color: '#878D99',
@@ -143,7 +150,8 @@ export default {
             'van-dropdown-menu': '/native/vant/dropdown-menu/index',
             'van-dropdown-item': '/native/vant/dropdown-item/index',
             'van-nav-bar': '/native/vant/nav-bar/index',
-            'van-tag': '/native/vant/tag/index'
+            'van-tag': '/native/vant/tag/index',
+            'van-divider': '/native/vant/divider/index'
         }
     }
 };

+ 33 - 15
src/mixins/commont.js

@@ -1,4 +1,17 @@
+import Dialog from '../native/vant/dialog/dialog';
 export default {
+    onLoad() {
+        const app = getApp();
+        if (this.loginMethods) {
+            if (app.globalData.initialize) {
+                this.loginMethods();
+            } else {
+                app.globalData.initializeCallback = () => {
+                    this.loginMethods();
+                };
+            }
+        }
+    },
     methods: {
         getImport(name) {
             if (this.search) {
@@ -25,12 +38,14 @@ export default {
                 console.log('已登录');
                 return Promise.resolve(this.$store.state.userInfo);
             } else {
+                wx.navigateTo({
+                    url: '/pages/Authorized'
+                });
                 return Promise.reject('未登录');
             }
         },
         getList(info, index = 0) {
             let img = '';
-            console.log(info);
             if (info instanceof Array && info.length > index) {
                 img = [...info][index];
             } else if (typeof info === 'string' && info) {
@@ -39,7 +54,6 @@ export default {
             return img;
         },
         navigateTo(e, checkLogin = true) {
-            console.log(e);
             if (checkLogin) {
                 this.checkLogin()
                     .then(() => {
@@ -48,9 +62,7 @@ export default {
                         });
                     })
                     .catch(e => {
-                        wx.navigateTo({
-                            url: '/pages/Authorized'
-                        });
+                        console.log(e);
                     });
             } else {
                 wx.navigateTo({
@@ -61,16 +73,22 @@ export default {
         navigateBack() {
             wx.navigateBack();
         },
-        toast(message, type = 'text') {
-            if (type === 'text') {
-                this.$toast(message);
-            } else if (type === 'success') {
-                this.$toast.success(message);
-            } else if (type === 'fail') {
-                this.$toast.fail(message);
-            } else if (type !== 'loading') {
-                this.$toast({ message: message, type: type });
-            }
+        toast(title, icon = 'none', duration = 1500) {
+            wx.showToast({
+                icon: icon,
+                title: title,
+                mask: true,
+                duration: duration
+            });
+        },
+        dialog(message, showCancelButton = false, useSlot = false, confirmButtonText = '确认') {
+            return Dialog.confirm({
+                message: message,
+                useSlot: useSlot,
+                confirmButtonColor: this.$colors.warn,
+                showCancelButton: showCancelButton,
+                confirmButtonText: confirmButtonText
+            });
         }
     }
 };

+ 37 - 17
src/pages/Home.vue

@@ -70,7 +70,7 @@
                     content-class="menu-info"
                     icon="http://imt.oss-cn-hangzhou.aliyuncs.com/micro/home_icon_xinwen.png"
                     :text="$t('xin-wen-zi-xun')"
-                    @click="navigateTo('/pages/news/News', false)"
+                    @click="navigateTo('/pagesNews/News', false)"
                 />
             </van-grid>
 
@@ -84,31 +84,29 @@
         <div class="hot" v-if="hotProductsList.length > 0">
             <div class="title">
                 <h1>{{ $t('re-men-chan-pin') }}</h1>
-                <van-button size="small" :color="$colors.info" plain>
+                <!-- <van-button size="small" :color="$colors.info" plain>
                     查看更多
                     <van-icon name="arrow" :color="$colors.info" />
-                </van-button>
+                </van-button> -->
             </div>
             <van-tabs :active="hotActive" @change="hotActive = $event.detail.index" :ellipsis="false">
                 <van-tab :title="item.name" v-for="item in hotProductsList" :key="item.id"></van-tab>
             </van-tabs>
-            <div class="van-content">
+            <div class="van-content" v-if="nowProductsList.length > 0">
                 <product-grid-big :info="mainProductInfo"></product-grid-big>
-
+                <grid-big></grid-big>
                 <swiper
-                    :style="{ height: (swiperProduct[0].length / 3) * 360 + 25 + 'rpx' }"
+                    :style="{ height: swiperHeight + 'rpx' }"
                     :current="hotSwiperIndex"
                     @change="hotSwiperIndex = $event.detail.current"
                 >
-                    <block v-for="(list, index) in swiperProduct" :key="index">
-                        <swiper-item>
-                            <div class="product-list">
-                                <div class="col-3" v-for="item in list" :key="item.id">
-                                    <product-grid :info="item" :clo="3" :padding="3"></product-grid>
-                                </div>
+                    <swiper-item v-for="(list, index) in swiperProduct" :key="index">
+                        <div class="product-list">
+                            <div class="col-3" v-for="item in list" :key="item.id">
+                                <product-grid :info="item" :clo="3" :padding="3"></product-grid>
                             </div>
-                        </swiper-item>
-                    </block>
+                        </div>
+                    </swiper-item>
                 </swiper>
 
                 <div class="dots">
@@ -120,6 +118,8 @@
                     ></div>
                 </div>
             </div>
+
+            <van-empty description="暂未设置该类型热门商品" v-else />
         </div>
         <div class="datas">
             <van-image
@@ -153,7 +153,7 @@
                 </van-button>
             </div>
             <swiper
-                :style="{ height: (vendorInfos[0].length / 3) * 238 + 25 + 'rpx' }"
+                :style="{ height: vendorInfosHeight + 'rpx' }"
                 :current="vendorSwiper"
                 @change="vendorSwiper = $event.detail.current"
             >
@@ -183,8 +183,8 @@
 import SearchBar from '../components/bar/SearchBar';
 import { getBanner } from '../utils/commont';
 import { mapState } from 'vuex';
-import ProductGridBig from '../components/product/GridBig';
-import ProductGrid from '../components/product/Grid';
+import ProductGridBig from '../components/product/GridBig.vue';
+import ProductGrid from '../components/product/Grid.vue';
 import VendorGrid from '../components/vendor/Grid';
 export default {
     data() {
@@ -249,6 +249,22 @@ export default {
                 }
             });
             return [..._list.values()];
+        },
+        swiperHeight() {
+            const list = [...this.swiperProduct];
+            if (list.length > 0) {
+                return Math.ceil(list[0].length / 3) * 360 + 25;
+            } else {
+                return 0;
+            }
+        },
+        vendorInfosHeight() {
+            const vendorInfos = [...this.vendorInfos];
+            if (vendorInfos.length > 0) {
+                return Math.ceil(vendorInfos[0].length / 3) * 238 + 25;
+            } else {
+                return 0;
+            }
         }
     },
     onLoad() {
@@ -472,4 +488,8 @@ export default {
         }
     }
 }
+
+.van-empty {
+    background-color: #f5f7fa;
+}
 </style>

+ 1 - 1
src/pages/News.vue

@@ -10,7 +10,7 @@
 </config>
 <template>
     <div>
-        <custom-bar :ratio="ratio" :pre="0" :title="title"></custom-bar>
+        <custom-bar :ratio="ratio" :pre="0" :title="title" :barTop="140"></custom-bar>
         <banner :banners="banners" fixed :height="140" :radius="0" :scrollTop="scrollTop"></banner>
         <div class="main" id="main">
             <van-sticky :offset-top="71" :z-index="100" :container="main">

+ 1 - 1
src/pages/imt/Index.vue

@@ -8,7 +8,7 @@
 </config>
 <template>
     <div class="imt">
-        <custom-bar title="IMT平台" :pre="0" :fixed="false"></custom-bar>
+        <custom-bar title="IMT平台" :pre="0" :fixed="false" :barTop="300"></custom-bar>
 
         <template v-if="active === 0">
             <div class="banner">

+ 5 - 5
src/pages/news/Detail.vue → src/pagesNews/Detail.vue

@@ -10,7 +10,7 @@
 </config>
 <template>
     <div>
-        <custom-bar :pre="0" :title="isActivity ? '活动详情' : '新闻详情'"></custom-bar>
+        <custom-bar :pre="0" :title="isActivity ? '活动详情' : '新闻详情'" :barTop="260"></custom-bar>
         <banner :banners="banners" fixed :height="260" :radius="0"></banner>
 
         <div class="main" id="main">
@@ -50,16 +50,16 @@
                 block
                 :color="$colors.warn"
                 :radius="4"
-                @click="navigateTo('/pages/news/Submit?infoId=' + info.id + '&activityId=' + activityId)"
+                @click="navigateTo('/pagesNews/Submit?infoId=' + info.id + '&activityId=' + activityId)"
                 >{{ isEnd ? '报名结束' : activityId ? '查看报名信息' : '立即报名' }}</van-button
             >
         </fixed-button>
     </div>
 </template>
 <script>
-import Banner from '../../components/Banner.vue';
-import CustomBar from '../../components/bar/CustomBar.vue';
-import FixedButton from '../../components/FixedButton';
+import Banner from '../components/Banner.vue';
+import CustomBar from '../components/bar/CustomBar.vue';
+import FixedButton from '../components/FixedButton';
 export default {
     data() {
         return {

+ 9 - 9
src/pages/news/News.vue → src/pagesNews/News.vue

@@ -10,7 +10,7 @@
 </config>
 <template>
     <div>
-        <custom-bar :pre="0" :title="title"></custom-bar>
+        <custom-bar :pre="0" :title="title" :barTop="140"></custom-bar>
         <banner :banners="banners" fixed :height="140" :radius="0"></banner>
         <div class="main" id="main">
             <van-sticky :offset-top="71" :z-index="100" :container="main">
@@ -45,14 +45,14 @@
     </div>
 </template>
 <script>
-import Banner from '../../components/Banner.vue';
-import CustomBar from '../../components/bar/CustomBar.vue';
-import { getBanner } from '../../utils/commont';
-import { InformationType } from '../../utils/appState';
-import searchList from '../../mixins/searchList';
-import SortList from '../../components/SortList.vue';
-import NewsGrid from '../../components/News/Grid.vue';
-import NewsRow from '../../components/News/Row.vue';
+import Banner from '../components/Banner.vue';
+import CustomBar from '../components/bar/CustomBar.vue';
+import { getBanner } from '../utils/commont';
+import { InformationType } from '../utils/appState';
+import searchList from '../mixins/searchList';
+import SortList from '../components/SortList.vue';
+import NewsGrid from '../components/News/Grid.vue';
+import NewsRow from '../components/News/Row.vue';
 export default {
     components: { Banner, CustomBar, SortList, NewsGrid, NewsRow },
     data() {

+ 3 - 3
src/pages/news/Submit.vue → src/pagesNews/Submit.vue

@@ -33,7 +33,7 @@
                     >
                         <span> {{ item }}</span>
 
-                        <img src="../../static/imgs/icon_list_xuanzhong.png" alt="" />
+                        <img src="../static/imgs/icon_list_xuanzhong.png" alt="" />
                     </div>
                 </div>
             </div>
@@ -87,8 +87,8 @@
 </template>
 <script>
 import { mapState } from 'vuex';
-import FixedButton from '../../components/FixedButton';
-import { sexModels } from '../../utils/appState';
+import FixedButton from '../components/FixedButton';
+import { sexModels } from '../utils/appState';
 export default {
     data() {
         return {

+ 265 - 0
src/pagesProduct/Contrast.vue

@@ -0,0 +1,265 @@
+<config>
+{
+'navigationBarTitleText': '产品对比',
+}
+</config>
+<template>
+    <div class="contrast">
+        <div class="notice">
+            <van-notice-bar
+                left-icon="volume-o"
+                wrapable
+                color="#565B66"
+                background="#F5F7FA"
+                :scrollable="false"
+                custom-class="my-notice"
+                text="产品对比仅限同类别产品进行对比,若要更换类别,请先将列表中的产品删除,再次添加产品则会变为新产品的类别"
+            />
+            <van-button :color="$colors.warn" plain>我知道了</van-button>
+        </div>
+
+        <div class="contrast-top" v-if="category.id">
+            <div class="category-btn">
+                <van-button :color="$colors.warn" plain block>当前类别&nbsp;&nbsp;{{ getName(category) }}</van-button>
+            </div>
+
+            <div class="product-list">
+                <product-row
+                    :checked="[...chooseIds].includes(item.id)"
+                    v-for="item in contrastList"
+                    :key="item.id"
+                    :info="item"
+                    @choose="choose"
+                    @del="delContrast"
+                ></product-row>
+            </div>
+        </div>
+
+        <van-empty description="暂无对比商品" v-else />
+
+        <div class="contrast-content" v-if="list.length > 0">
+            <div class="title">同类别推荐</div>
+            <div class="product-list">
+                <product-row
+                    :checked="[...addList].includes(item.id)"
+                    v-for="item in list"
+                    :key="item.id"
+                    :info="item"
+                    @choose="choose"
+                ></product-row>
+            </div>
+        </div>
+
+        <van-dialog id="van-dialog">
+            <div class="dialog-center">
+                <van-icon name="info" :size="55" :color="$colors.warn" />
+                <div class="dialog-title">
+                    产品对比仅限同类别产品进行对比<br />是否立即清空当前对比列表<br />添加当前商品对比
+                </div>
+            </div>
+        </van-dialog>
+    </div>
+</template>
+<script>
+import ProductRow from '../components/product/RowMini.vue';
+export default {
+    data() {
+        return {
+            productId: '',
+            contrastInfo: {},
+            chooseIds: [],
+            list: [],
+            addList: []
+        };
+    },
+    onLoad(options) {
+        console.log(options);
+        if (options.productId) {
+            this.productId = Number(options.productId);
+        }
+    },
+    computed: {
+        contrastList() {
+            return this.contrastInfo.product || [];
+        },
+        category() {
+            return this.contrastInfo.category || {};
+        }
+    },
+    watch: {
+        contrastList() {
+            if (this.contrastList.length > 0) {
+                this.getRelated([...this.contrastList][0].id);
+            } else {
+                this.list = [];
+            }
+        }
+    },
+    methods: {
+        loginMethods() {
+            this.chooseIds = [this.productId];
+            this.getContrastInfo()
+                .then(() => {
+                    return this.$http.post('/intentionList/add', {
+                        productId: this.productId,
+                        type: 'PRODUCT_COMPARISON'
+                    });
+                })
+                .then(() => {
+                    this.getContrastInfo();
+                })
+                .catch(res => {
+                    if (res.error === '已添加') {
+                        console.log('已经添加');
+                    } else if (res.error === '类别不同') {
+                        this.dialog('', true, true, '立即添加')
+                            .then(() => {
+                                return this.clearAllContrast();
+                            })
+                            .then(() => {
+                                return this.$http.post('/intentionList/add', {
+                                    productId: this.productId,
+                                    type: 'PRODUCT_COMPARISON'
+                                });
+                            })
+                            .then(() => {
+                                this.getContrastInfo();
+                            })
+                            .catch(e => {
+                                console.log('取消');
+                                this.chooseIds = [];
+                            });
+                    }
+                });
+        },
+        clearAllContrast() {
+            return this.$http.post('/intentionList/delAll', {
+                type: 'PRODUCT_COMPARISON'
+            });
+        },
+        delContrast(id) {
+            this.dialog('确认要删除该商品吗?', true, false, '立即删除')
+                .then(() => {
+                    return this.$http.post('/intentionList/delOne', {
+                        type: 'PRODUCT_COMPARISON',
+                        productId: id
+                    });
+                })
+                .then(() => {
+                    this.toast('删除成功!', 'success');
+                    this.getContrastInfo();
+                });
+        },
+        getContrastInfo() {
+            return this.$http.get('/intentionList/myCompared').then(res => {
+                this.contrastInfo = res || {};
+            });
+        },
+        choose(id) {
+            console.log(id);
+            const chooseIds = [...this.chooseIds];
+            if (chooseIds.includes(id)) {
+                chooseIds.splice(chooseIds.indexOf(id), 1);
+            } else {
+                chooseIds.push(id);
+            }
+            this.chooseIds = [...chooseIds];
+        },
+        getRelated(id) {
+            this.$http
+                .get('/product/related', {
+                    id: id
+                })
+                .then(res => {
+                    this.list = res;
+                });
+        }
+    },
+    components: {
+        ProductRow
+    }
+};
+</script>
+
+<style lang="less">
+.my-notice {
+    &.van-notice-bar {
+        align-items: flex-start;
+        --notice-bar-line-height: 20px;
+        --notice-bar-icon-size: 20px;
+        .van-notice-bar__left-icon {
+            margin-top: 3px;
+        }
+    }
+}
+
+.notice {
+    padding: 16px 0 6px;
+    background: #f5f7fa;
+    --notice-bar-wrapable-padding: 0 16px;
+    --button-border-width: 0px;
+    .van-button {
+        padding: 0 16px;
+    }
+    display: flex;
+    flex-direction: column;
+    ._van-button {
+        align-self: flex-end;
+    }
+}
+
+.dialog-center {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 36px 30px 20px;
+
+    .dialog-title {
+        font-size: 14px;
+        font-weight: bold;
+        color: #353535;
+        line-height: 23px;
+        text-align: center;
+        margin-top: 25px;
+    }
+}
+
+.contrast-top {
+    padding: 16px;
+    --button-plain-background-color: #ffa52612;
+    --button-border-width: 0px;
+}
+
+.product-list {
+    // padding: 16px 0;
+    .product {
+        padding: 16px 0;
+        position: relative;
+    }
+
+    .product + .product {
+        &::after {
+            content: '';
+            position: absolute;
+            bottom: 0;
+            left: 28px;
+            right: 0px;
+            height: 1px;
+            background: #f5f7fa;
+        }
+    }
+}
+.contrast-content {
+    .title {
+        background: #f2f3f5;
+        padding: 7px 16px;
+        font-size: 12px;
+        color: #878d99;
+        line-height: 17px;
+    }
+
+    .product-list {
+        padding: 0 16px;
+    }
+}
+</style>

+ 445 - 0
src/pagesProduct/Detail.vue

@@ -0,0 +1,445 @@
+<config>
+{
+'navigationBarTitleText': '',
+'navigationBarTextStyle':'black',
+'backgroundColorBottom': '#fff',
+'navigationStyle':'custom',
+}
+</config>
+<template>
+    <div>
+        <custom-bar title="产品详情" :pre="0" :dark="false" :barTop="375"></custom-bar>
+        <banner :banners="banners" :height="375" :radius="0"></banner>
+        <div class="main" id="main">
+            <div class="info">
+                <div class="ad">
+                    <span>可在MT展厅线下体验,点击查看地址</span>
+                    <img src="../static/imgs/iocn_dingwei.png" alt="" />
+                </div>
+
+                <div class="info-top">
+                    <div class="title">
+                        {{ getName(productInfo) }}
+                    </div>
+                    <div class="sub">{{ productInfo.model }}</div>
+
+                    <div class="btn">
+                        <van-icon
+                            custom-class="my-icon"
+                            name="icon-icon_collect"
+                            :size="32"
+                            color="#BCC1CC"
+                            class-prefix="iconfont"
+                        />
+                        <van-icon
+                            custom-class="my-icon"
+                            name="icon-icon_share"
+                            :size="32"
+                            color="#BCC1CC"
+                            class-prefix="iconfont"
+                        />
+                    </div>
+                </div>
+                <van-divider />
+
+                <van-cell-group :border="false">
+                    <van-cell :title="$t('chan-pin-pin-pai')" :border="false" :value="productInfo.brand" />
+                    <van-cell :title="$t('ying-wen-pin-ming')" :border="false" :value="productInfo.enName" />
+                    <van-cell :title="$t('chan-pin-lei-bie')" :border="false" :value="productCategoryName" />
+                    <van-cell title="平均交货周期" :border="false" :value="productInfo.averageLeadTime" />
+                    <van-cell title="产地" :border="false" :value="productInfo.origin" />
+                    <van-cell title="应用领域" :border="false" :value="applicationField" />
+                    <van-cell title="产品标签" :border="false">
+                        <div>
+                            <van-tag plain v-for="(item, index) in tags" :key="index">{{ item }}</van-tag>
+                        </div>
+                    </van-cell>
+                </van-cell-group>
+            </div>
+
+            <div class="vendor">
+                <van-icon :name="vendorInfo.logo" :size="60" />
+                <div class="vendor-info">
+                    <h3>{{ getName(vendorInfo, ['chCompanyName', 'enCompanyName']) }}</h3>
+
+                    <div class="vendor-btn">
+                        <van-button :color="$colors.warn" size="small">进入展商</van-button>
+                    </div>
+                </div>
+            </div>
+
+            <div class="detail" v-if="productInfo.id" id="detail">
+                <van-tabs
+                    :active="hotActive"
+                    @change="tabClick"
+                    :line-width="22"
+                    :line-height="3"
+                    sticky
+                    :offset-top="71"
+                >
+                    <van-tab title="图文详情">
+                        <div class="detail-content">
+                            <rich-text v-if="detailImg" :nodes="detailImg"></rich-text>
+                            <van-empty v-else description="暂无详情" />
+                        </div>
+                    </van-tab>
+                    <van-tab title="详细参数">
+                        <div class="detail-content">
+                            <parameter :productId="productId"></parameter>
+                        </div>
+                    </van-tab>
+                    <van-tab title="PDF资料">PDF资料</van-tab>
+                </van-tabs>
+            </div>
+
+            <div class="fixed-bottom">
+                <div class="fixed-bottom-content">
+                    <div class="btn-icon" @click="navigateTo('/pagesProduct/Contrast?productId=' + productId)">
+                        <van-icon name="icon-xiangqingye_iocn_vs" :size="24" class-prefix="iconfont" />
+                        <div class="text">对比</div>
+                    </div>
+                    <div class="btn-icon">
+                        <van-icon
+                            name="icon-xiangqingye_iocn_yixiangdan"
+                            :info="intentionList.length > 0 ? intentionList.length : ''"
+                            :size="24"
+                            class-prefix="iconfont"
+                        />
+                        <div class="text">意向单</div>
+                    </div>
+
+                    <div class="btn-list">
+                        <van-button
+                            :color="$colors.prim"
+                            :radius="0"
+                            :disabled="isIntented"
+                            @click="addIntentionList"
+                            >{{ isIntented ? '已添加' : '添加意向单' }}</van-button
+                        >
+                        <van-button :color="$colors.warn" type="primary" :radius="0">询价</van-button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import Banner from '../components/Banner.vue';
+import CustomBar from '../components/bar/CustomBar.vue';
+import Parameter from '../components/product/Parameter.vue';
+import { mapState } from 'vuex';
+export default {
+    components: { CustomBar, Banner, Parameter },
+    data() {
+        return {
+            productId: 0,
+            productInfo: {},
+            vendorInfo: {},
+            hotActive: 0,
+            detailTop: 0
+        };
+    },
+    computed: {
+        ...mapState(['intentionList']),
+        banners() {
+            if (this.productInfo.img) {
+                return this.productInfo.img.split(',').map(item => {
+                    return {
+                        img: item + '?x-oss-process=image/resize,m_fill,h_750,w_750'
+                    };
+                });
+            }
+            return [];
+        },
+        applicationField() {
+            let list = this.productInfo.applicationField ? [...this.productInfo.applicationField] : [];
+            list = list.map(item => {
+                return this.getName(item);
+            });
+            if (this.productInfo.customApplicationField) {
+                const _list = this.productInfo.customApplicationField.split(',');
+
+                list = [...list, ..._list];
+            }
+            return list.join('、');
+        },
+        tags() {
+            return this.productInfo.tag || [];
+        },
+        productCategoryName() {
+            if (this.productInfo.productCategory) {
+                return this.getName(this.productInfo.productCategory);
+            } else {
+                return '';
+            }
+        },
+        detailImg() {
+            let detail = this.productInfo.detailImg || '';
+            if (detail) {
+                detail = detail.replace(/<img/g, `<img class='detaiImg' `);
+            }
+            return detail;
+        },
+        isIntented() {
+            const list = [...this.intentionList];
+            return list
+                .map(item => {
+                    return Number(item.id);
+                })
+                .includes(Number(this.productId));
+        }
+    },
+    onLoad(options) {
+        if (options.id) {
+            this.productId = options.id;
+            this.$http
+                .get(`/product/getDto/${options.id}`)
+                .then(res => {
+                    this.productInfo = res;
+                    return this.$http.get('/vendorInfo/getHome/' + res.vendorInfoId);
+                })
+                .then(res => {
+                    this.vendorInfo = res;
+                });
+        }
+    },
+    onPageScroll() {},
+    methods: {
+        tabClick(e) {
+            console.log(e);
+            if (!this.detailTop) {
+                wx.createSelectorQuery()
+                    .select('#main')
+                    .boundingClientRect(rect => {
+                        const mainHeight = rect.height;
+                        wx.createSelectorQuery()
+                            .select('#detail')
+                            .boundingClientRect(rect => {
+                                this.detailTop = mainHeight - rect.height + 375 - 51;
+                                wx.pageScrollTo({
+                                    scrollTop: this.detailTop,
+                                    duration: 300
+                                });
+                            })
+                            .exec();
+                    })
+                    .exec();
+            } else {
+                wx.pageScrollTo({
+                    scrollTop: this.detailTop,
+                    duration: 300
+                });
+            }
+            this.hotActive = e.detail.index;
+            if (e.detail.index === 2) {
+                wx.downloadFile({
+                    // 示例 url,并非真实存在
+                    url: 'https://imt.oss-cn-hangzhou.aliyuncs.com/application/2020-11-13-16-57-03rREcAPTN.pdf',
+                    success: res => {
+                        const filePath = res.tempFilePath;
+                        this.hotActive = 0;
+                        wx.openDocument({
+                            filePath: filePath,
+                            success: res => {}
+                        });
+                    }
+                });
+            }
+        },
+        loginMethods() {
+            this.$store.dispatch('getIntentionList');
+        },
+        addIntentionList() {
+            if (this.isIntented) {
+                return;
+            }
+            this.checkLogin()
+                .then(() => {
+                    return this.$http.post('/intentionList/add', {
+                        productId: this.productId,
+                        type: 'BATCH_INQUIRY'
+                    });
+                })
+                .then(() => {
+                    console.log('aaaa');
+                    this.toast('添加成功!', 'success');
+                    this.$store.dispatch('getIntentionList');
+                })
+                .catch(e => {
+                    if (e.error) {
+                        this.toast(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less">
+.main {
+    background-color: #fff;
+}
+.info {
+    padding: 12px 16px 30px;
+
+    .info-top {
+        padding: 12px 0;
+        position: relative;
+
+        .title {
+            font-size: 18px;
+            font-weight: bold;
+            color: #292c33;
+            line-height: 25px;
+        }
+
+        .sub {
+            font-size: 16px;
+            color: #878d99;
+            line-height: 22px;
+            margin-top: 8px;
+        }
+    }
+
+    .btn {
+        position: absolute;
+        right: 0;
+        bottom: 12px;
+
+        ._van-icon {
+            margin-left: 5px;
+        }
+    }
+
+    --divider-text-color: #f2f4f5;
+    --divider-margin: 10px 0px;
+    --cell-vertical-padding: 8px;
+    --cell-horizontal-padding: 0px;
+    --cell-text-color: #292c33;
+    --cell-font-size: 13px;
+    --cell-value-color: #444444;
+    .van-cell__title {
+        font-weight: bold;
+    }
+
+    .van-cell__value {
+        flex-grow: 2;
+    }
+}
+.ad {
+    background: rgba(255, 165, 38, 0.06);
+    border-radius: 4px;
+    display: flex;
+    align-items: center;
+    padding: 0 10px;
+    justify-content: space-between;
+    span {
+        font-size: 12px;
+        color: @warn;
+        line-height: 22px;
+    }
+
+    img {
+        width: 16px;
+        height: 16px;
+    }
+}
+
+.van-tag {
+    margin-left: 5px;
+}
+
+.vendor {
+    display: flex;
+    padding: 13px 16px;
+    border-top: 5px solid #f2f3f5;
+    border-bottom: 5px solid #f2f3f5;
+    .vendor-info {
+        flex-grow: 1;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        margin-left: 8px;
+
+        .vendor-btn {
+            --button-small-height: 26px;
+            --button-small-min-width: 70px;
+        }
+    }
+}
+
+.van-tabs {
+    .van-tabs__line {
+        bottom: 5px;
+    }
+}
+
+.detail {
+    padding: 20px 0;
+    --tab-text-color: #878d99;
+
+    .van-tabs__nav {
+        margin: 0 16px;
+    }
+}
+
+.detail-content {
+    min-height: calc(100vh - 105px - 80rpx);
+    padding: 20px 16px;
+    box-sizing: border-box;
+}
+
+.detaiImg {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 0 0px;
+}
+
+.fixed-bottom {
+    height: 60px;
+    .fixed-bottom-content {
+        background-color: #fff;
+        padding: 8px 16px;
+        position: fixed;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        height: 60px;
+        display: flex;
+        z-index: 200;
+        box-sizing: border-box;
+        box-shadow: 0px -1px 2px 0px rgba(0, 0, 0, 0.04);
+        align-items: center;
+        .btn-icon {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 0 10px;
+            .text {
+                font-size: 11px;
+                color: #565b66;
+                line-height: 16px;
+                white-space: nowrap;
+            }
+
+            &:active {
+                background-color: darken(#fff, 5);
+            }
+        }
+
+        .btn-list {
+            flex-grow: 1;
+            margin-left: 10px;
+            border-radius: 4px;
+            overflow: hidden;
+            display: flex;
+            justify-content: flex-end;
+            .van-button {
+                width: 120px;
+
+                --button-border-radius: 0px;
+            }
+        }
+    }
+}
+</style>

BIN
src/static/imgs/iocn_dingwei.png


BIN
src/static/imgs/xiangqingye_iocn_vs.png


BIN
src/static/imgs/xiangqingye_iocn_yixiangdan.png


+ 16 - 2
src/store/index.js

@@ -9,7 +9,8 @@ export default new Vuex.Store({
         loginInfo: null,
         userIcon: '',
         filterInfo: {},
-        productCategories: []
+        productCategories: [],
+        intentionList: []
     },
     mutations: {
         setSafeAreaTop(state, val) {
@@ -33,6 +34,9 @@ export default new Vuex.Store({
         setFilterInfo(state, filterInfo) {
             state.filterInfo = filterInfo;
         },
+        updateIntentionList(state, intentionList) {
+            state.intentionList = intentionList;
+        },
         setProductCategories(state, productCategories) {
             state.productCategories = productCategories;
         }
@@ -40,7 +44,7 @@ export default new Vuex.Store({
     actions: {
         getUserInfo(context) {
             let userInfo = {};
-            http.http
+            return http.http
                 .get('/user/my')
                 .then(res => {
                     if (res.phone) {
@@ -57,6 +61,7 @@ export default new Vuex.Store({
                         userInfo.avatar = res.logo;
                     }
                     context.commit('setUserInfo', userInfo);
+                    return Promise.resolve();
                 });
         },
         getProductCategories(context) {
@@ -75,6 +80,15 @@ export default new Vuex.Store({
 
                 return Promise.resolve(list);
             });
+        },
+        getIntentionList(context) {
+            if (!context.state.userInfo) {
+                context.commit('updateIntentionList', []);
+            } else {
+                http.http.get('/intentionList/myIntention').then(res => {
+                    context.commit('updateIntentionList', res || []);
+                });
+            }
         }
     }
 });

+ 2 - 0
src/styles/common.less

@@ -52,3 +52,5 @@ image {
     height: 100%;
     display: block;
 }
+
+

+ 37 - 0
src/styles/fonts.less

@@ -0,0 +1,37 @@
+@font-face {
+    font-family: 'OSP';
+    src: url(http://imt.oss-cn-hangzhou.aliyuncs.com/micro/OSP-DIN.ttf);
+}
+
+@font-face {
+    font-family: 'iconfont'; /* project id 2026145 */
+    src: url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.eot');
+    src: url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.eot?#iefix') format('embedded-opentype'),
+        url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.woff2') format('woff2'),
+        url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.woff') format('woff'),
+        url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.ttf') format('truetype'),
+        url('//at.alicdn.com/t/font_2026145_vpadufm8f6i.svg#iconfont') format('svg');
+}
+.iconfont {
+    font-family: 'iconfont' !important;
+    font-size: 16px;
+    font-style: normal;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    position: relative;
+}
+
+.iconfont-icon-icon_collect:before {
+    content: '\e616';
+}
+
+.iconfont-icon-icon_share:before {
+    content: '\e617';
+}
+
+.iconfont-icon-xiangqingye_iocn_yixiangdan:before {
+    content: '\e61a';
+}
+.iconfont-icon-xiangqingye_iocn_vs:before {
+    content: '\e61b';
+}