panhui 3 éve
szülő
commit
b55317f620

+ 1 - 1
.env.app_test

@@ -1,4 +1,4 @@
-VUE_APP_BASE_URL=https://test.raex.vip
+VUE_APP_BASE_URL=https://www.raex.vip
 NODE_ENV=production
 VUE_APP_PUBLIC_PATH=./
 ASSETS_PATH=raex

BIN
src/assets/beijing-icon.png


BIN
src/assets/dianliang-icon.png


BIN
src/assets/laxin-icon.png


BIN
src/assets/weidianliang-icon.png


+ 139 - 0
src/components/Level.vue

@@ -0,0 +1,139 @@
+<template>
+    <van-overlay :show="show" @click="show = false" z-index="99">
+        <div class="box">
+            <van-image width="260" height="220" :src="levelInfo.bg" fit="contain" />
+            <div class="box-top">
+                <div class="box-title" :style="{ color: levelInfo.color, borderColor: levelInfo.color }">
+                    恭喜您 获得新勋章
+                </div>
+
+                <div class="icon">
+                    <van-image :src="levelInfo.icon" width="114" height="114" />
+                    <span class="text2" :style="{ color: levelInfo.color }">{{ levelInfo.level }}</span>
+                </div>
+                <div class="text3" :style="{ color: levelInfo.color, backgroundColor: levelInfo.color + '23' }">
+                    {{ levelInfo.realm }}
+                </div>
+                <div class="text1" :style="{ color: levelInfo.color }">{{ levelInfo.title }}</div>
+            </div>
+            <div class="box-content">
+                <div class="text1">
+                    您已升级至<span :style="{ color: levelInfo.color }">V{{ levelInfo.level }}</span
+                    >,感谢您对绿洲的信任。愿绿洲的荣光普照河山!!
+                </div>
+                <div class="btn">
+                    <van-button :color="levelInfo.color" block round>领取</van-button>
+                </div>
+            </div>
+        </div>
+    </van-overlay>
+</template>
+
+<script>
+import level from '../mixins/level';
+export default {
+    data() {
+        return {
+            show: false
+        };
+    },
+    mixins: [level],
+    methods: {
+        changeLevel(level) {
+            if (level >= 10) {
+                this.show = true;
+            }
+            this.$http.post(
+                '/user/save',
+                {
+                    level: level,
+                    id: this.$store.state.userInfo.id
+                },
+                { body: 'json' }
+            );
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.box {
+    background-color: @bg;
+    border-radius: 16px;
+    overflow: hidden;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    position: absolute;
+
+    .box-content {
+        padding: 16px 23px 20px;
+        .text1 {
+            font-size: 12px;
+            line-height: 17px;
+            text-align: center;
+            span {
+                font-weight: bold;
+            }
+        }
+    }
+
+    .btn {
+        padding: 16px 40px 0;
+    }
+}
+
+.box-top {
+    position: absolute;
+    width: 260px;
+    height: 220px;
+    top: 0;
+    left: 0;
+    .flex-col();
+    align-items: center;
+    justify-content: center;
+
+    .text3 {
+        border-radius: 2px;
+        padding: 0 9px;
+        margin-top: 6px;
+        font-size: 12px;
+        line-height: 20px;
+    }
+    .text1 {
+        font-size: 12px;
+        line-height: 17px;
+        margin-top: 2px;
+    }
+}
+
+.box-title {
+    font-size: 14px;
+    font-weight: bold;
+    line-height: 24px;
+    vertical-align: middle;
+    &::after,
+    &::before {
+        display: inline-block;
+        width: 30px;
+        content: '';
+        border-top: 1px solid;
+        vertical-align: middle;
+        margin: 10px;
+    }
+}
+
+.icon {
+    position: relative;
+    margin-top: 9px;
+    .text2 {
+        font-size: 34px;
+        font-weight: bold;
+        font-family: AlibabaPuHuiTi-Bold, AlibabaPuHuiTi;
+        line-height: 34px;
+        position: absolute;
+        left: 52px;
+        top: 38px;
+    }
+}
+</style>

+ 94 - 56
src/components/Post.vue

@@ -5,59 +5,67 @@
                 <div class="img" ref="wrap" v-if="img" @click.stop="preview(0, [img])">
                     <img :src="img" />
                 </div>
-                <div class="content" v-if="!img" ref="post">
-                    <!-- @load="loadImg" -->
-                    <!-- <img crossOrigin="anonymous" :src="banners" class="detailImg" /> -->
-                    <van-image :src="detailImg" class="detailImg" fit="cover" />
-                    <div class="info">
-                        <div class="name van-multi-ellipsis--l2">
-                            {{ info.name }}
+                <template v-if="!img">
+                    <div class="assignmentPost" v-if="assignment && pageUrl === 'productDetail'" ref="post">
+                        <van-image class="assignmentPostBg" width="300" height="500" :src="shareBg" fit="cover" />
+                        <div class="qrcode">
+                            <vue-qrcode :value="url" :options="{ width: 82, margin: 0 }"></vue-qrcode>
                         </div>
-                        <div class="tabs">
-                            <span v-if="info.category">{{ info.category }}</span>
-                            <span v-if="info.number">编号{{ info.number }}</span>
-                        </div>
-                        <template v-if="pageUrl !== 'assetDetail'">
-                            <div class="text" v-if="isBuy">
-                                <div class="price">
-                                    <img src="@assets/jiage_huang.png" alt="" />
-                                    <span>{{ info.price }}</span>
+                    </div>
+                    <div class="content" v-else ref="post">
+                        <!-- @load="loadImg" -->
+                        <!-- <img crossOrigin="anonymous" :src="banners" class="detailImg" /> -->
+                        <van-image :src="detailImg" class="detailImg" fit="cover" />
+                        <div class="info">
+                            <div class="name van-multi-ellipsis--l2">
+                                {{ info.name }}
+                            </div>
+                            <div class="tabs">
+                                <span v-if="info.category">{{ info.category }}</span>
+                                <span v-if="info.number">编号{{ info.number }}</span>
+                            </div>
+                            <template v-if="pageUrl !== 'assetDetail'">
+                                <div class="text" v-if="isBuy">
+                                    <div class="price">
+                                        <img src="@assets/jiage_huang.png" alt="" />
+                                        <span>{{ info.price }}</span>
+                                    </div>
+                                    <div class="text1" v-if="info.stock && !time">
+                                        <span>已售 {{ Math.max(Math.min(info.sale, info.total), 0) }}</span>
+                                        <span>剩余 {{ Math.min(Math.max(info.stock, 0), info.total) }}</span>
+                                    </div>
                                 </div>
-                                <div class="text1" v-if="info.stock && !time">
-                                    <span>已售 {{ Math.max(Math.min(info.sale, info.total), 0) }}</span>
-                                    <span>剩余 {{ Math.min(Math.max(info.stock, 0), info.total) }}</span>
+
+                                <div class="status" v-if="!info.salable">仅展示</div>
+                            </template>
+                            <template v-else>
+                                <div class="text" v-if="info.consignment">
+                                    <div class="price">
+                                        <img src="@assets/jiage_huang.png" alt="" />
+                                        <span>{{ info.sellPrice || 0 }}</span>
+                                    </div>
                                 </div>
-                            </div>
 
-                            <div class="status" v-if="!info.salable">仅展示</div>
-                        </template>
-                        <template v-else>
-                            <div class="text" v-if="info.consignment">
-                                <div class="price">
-                                    <img src="@assets/jiage_huang.png" alt="" />
-                                    <span>{{ info.sellPrice || 0 }}</span>
+                                <div class="status" v-else-if="info.status == 'NORMAL'">
+                                    {{ info.publicShow ? '仅展示' : '未展示' }}
                                 </div>
+                            </template>
+                        </div>
+                        <div class="minter">
+                            <div class="minter-content">
+                                <van-image width="26" height="26" round :src="userImg" fit="cover" />
+                                <div class="text1">{{ info.minter }}</div>
+                                <div class="text2">铸造者</div>
                             </div>
 
-                            <div class="status" v-else-if="info.status == 'NORMAL'">
-                                {{ info.publicShow ? '仅展示' : '未展示' }}
-                            </div>
-                        </template>
-                    </div>
-                    <div class="minter">
-                        <div class="minter-content">
-                            <van-image width="26" height="26" round :src="userImg" fit="cover" />
-                            <div class="text1">{{ info.minter }}</div>
-                            <div class="text2">铸造者</div>
+                            <vue-qrcode :value="url" :options="{ width: 70, margin: 3 }" class="code"></vue-qrcode>
+                        </div>
+                        <div class="sold xianliang" v-if="time">
+                            <img src="@assets/shizhong.png" alt="" />
+                            <span>即将开售:{{ time }}</span>
                         </div>
-
-                        <vue-qrcode :value="url" :options="{ width: 70, margin: 3 }" class="code"></vue-qrcode>
-                    </div>
-                    <div class="sold xianliang" v-if="time">
-                        <img src="@assets/shizhong.png" alt="" />
-                        <span>即将开售:{{ time }}</span>
                     </div>
-                </div>
+                </template>
 
                 <div class="btn" @click.stop="" v-if="cordova">
                     <van-button type="primary" round @click="save">点击保存到本地</van-button>
@@ -107,7 +115,8 @@ export default {
             img: '',
             detailImg: '',
             userImg: '',
-            cordova: window.cordova
+            cordova: window.cordova,
+            shareBg: ''
         };
     },
     computed: {
@@ -118,7 +127,12 @@ export default {
                 pageUrl = 'productDetail';
                 id = this.info.publicCollectionId;
             }
-            if (this.isLogin) {
+            if (this.isLogin && this.assignment && pageUrl === 'productDetail') {
+                return resolveUrl(
+                    this.$baseUrl,
+                    '9th/productTasks?id=' + id + '&invitor=' + this.$store.state.userInfo.id
+                );
+            } else if (this.isLogin) {
                 return resolveUrl(
                     this.$baseUrl,
                     '9th/' + pageUrl + '?id=' + id + '&invitor=' + this.$store.state.userInfo.id
@@ -155,8 +169,12 @@ export default {
                     forbidClick: true
                 });
                 this.$nextTick(() => {
-                    this.getImgBase64(this.banners, 'detailImg');
-                    this.getImgBase64(this.info.minterAvatar, 'userImg');
+                    if (this.assignment && this.pageUrl === 'productDetail') {
+                        this.getImgBase64(this.info.shareBg, 'shareBg');
+                    } else {
+                        this.getImgBase64(this.banners, 'detailImg');
+                        this.getImgBase64(this.info.minterAvatar, 'userImg');
+                    }
                     setTimeout(() => {
                         this.loadImg();
                     }, 1000);
@@ -211,14 +229,13 @@ export default {
                         console.log('File saved on ' + filePath);
                     },
                     function (msg) {
-                        _this.$dialog
-                            .alert({
-                                title: '提示',
-                                message: msg
-                            })
-                            .then(() => {
-                                _this.preview(0, [_this.img]);
-                            });
+                        _this.$dialog.alert({
+                            title: '提示',
+                            message: msg
+                        });
+                        (1).then(() => {
+                            _this.preview(0, [_this.img]);
+                        });
                     }
                 );
             }
@@ -409,4 +426,25 @@ export default {
 .btn {
     padding: 30px;
 }
+
+.assignmentPost {
+    width: 300px;
+    height: 500px;
+    background: #ffffff;
+    border-radius: 30px;
+    position: relative;
+    .qrcode {
+        background-color: @bg3;
+        padding: 6px;
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        bottom: 94px;
+        border-radius: 6px;
+        z-index: 20;
+        /deep/canvas {
+            display: block;
+        }
+    }
+}
 </style>

+ 187 - 0
src/components/product/Tasks.vue

@@ -0,0 +1,187 @@
+<template>
+    <div class="tasks">
+        <div class="top">
+            <img class="bg" src="../../assets/beijing-icon.png" alt="" />
+            <img class="top-icon" src="../../assets/laxin-icon.png" alt="" />
+            <span>白名单任务</span>
+        </div>
+        <div class="content">
+            <div class="title">
+                每邀请<span>一位新用户注册</span>成功可点亮一枚勋章,当5枚“创世勋章”<span>全部点亮</span>时获得购买资格!
+            </div>
+
+            <div class="persons">
+                <div class="person" v-for="i in assignment" :key="i">
+                    <van-image
+                        width="42"
+                        height="42"
+                        radius="42"
+                        :src="
+                            i <= assignments.length
+                                ? require('../../assets/dianliang-icon.png')
+                                : require('../../assets/weidianliang-icon.png')
+                        "
+                        fit="contain"
+                    />
+                    <template v-if="i <= assignments.length">
+                        <div class="text2">已点亮</div>
+                        <div class="text3">{{ assignments[i - 1].nickname }}</div>
+                    </template>
+                    <template v-else>
+                        <div class="text1">待点亮</div>
+                        <div class="text3">...</div>
+                    </template>
+                </div>
+            </div>
+
+            <div class="tips">点击右下角按钮邀请吧~</div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props: {
+        info: {
+            type: Object,
+            default: () => {
+                return {};
+            }
+        },
+        assignments: {
+            type: Array,
+            default: () => {
+                return [];
+            }
+        }
+    },
+    computed: {
+        assignment() {
+            return this.info.assignment || 0;
+        }
+    },
+    mounted() {
+        this.getAssignment();
+    },
+    methods: {
+        getAssignment() {
+            if (this.isLogin) {
+                this.$http
+                    .get('/user/collectionInvite', {
+                        collectionId: Number(this.info.id)
+                    })
+                    .then(res => {
+                        this.$emit('update:assignments', res);
+                    });
+            }
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.tasks {
+    border-radius: 12px;
+    overflow: hidden;
+    margin-top: 20px;
+}
+.top {
+    .flex();
+    position: relative;
+    height: 42px;
+    justify-content: center;
+    background: linear-gradient(313deg, #ffe7cf 0%, #fccd8d 100%);
+    .bg {
+        width: 94px;
+        height: 42px;
+        position: absolute;
+        left: 0;
+        top: 0;
+    }
+
+    .top-icon {
+        width: 18px;
+        height: 18px;
+    }
+    span {
+        font-size: 16px;
+        font-weight: bold;
+        color: #fd3737;
+        line-height: 24px;
+        background: linear-gradient(121deg, #fc3837 0%, #ff7832 100%, #ffa06c 100%);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+    }
+}
+
+.content {
+    background-color: #1c1c1c;
+}
+
+.title {
+    font-size: 12px;
+    color: #939599;
+    line-height: 17px;
+    padding: 10px 6px;
+    text-align: center;
+    span {
+        color: #ffda9f;
+    }
+}
+
+.persons {
+    .flex();
+    justify-content: center;
+    padding-top: 3px;
+
+    .person {
+        .flex-col();
+        align-items: center;
+        height: 74px;
+        width: 60px;
+        overflow: hidden;
+        .van-image {
+            flex-shrink: 0;
+        }
+        .text1 {
+            margin-top: 6px;
+            font-size: 10px;
+            color: #939599;
+            line-height: 10px;
+        }
+
+        .text2 {
+            font-size: 12px;
+            color: #ffda9f;
+            margin-top: 7px;
+            line-height: 10px;
+            transform: scale(0.8);
+        }
+
+        .text3 {
+            font-size: 12px;
+            color: #ffffff;
+            line-height: 10px;
+            margin-top: 4px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            width: 100%;
+            text-align: center;
+            transform: scale(0.8);
+        }
+    }
+
+    .person + .person {
+        margin-left: 10px;
+    }
+}
+
+.tips {
+    font-size: 12px;
+    color: #939599;
+    line-height: 17px;
+    text-align: center;
+    padding: 16px;
+}
+</style>

+ 116 - 0
src/mixins/level.js

@@ -0,0 +1,116 @@
+export default {
+    data() {
+        return {
+            medals: [
+                {
+                    start: 10,
+                    end: 19,
+                    color: '#557595',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV10-19-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V10-19.png'
+                },
+                {
+                    start: 20,
+                    end: 29,
+                    color: '#A65F3B',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV20-29-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V20-29.png'
+                },
+                {
+                    start: 30,
+                    end: 39,
+                    color: '#3C62FF',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV30-39-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V30-39.png'
+                },
+                {
+                    start: 40,
+                    end: 49,
+                    color: '#663FA7',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV40-49-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V40-49.png'
+                },
+                {
+                    start: 50,
+                    end: 59,
+                    color: '#1076E1',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV50-59-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V50-59.png'
+                },
+                {
+                    start: 60,
+                    end: 69,
+                    color: '#DB31CA',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV60-69-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V60-69.png'
+                },
+                {
+                    start: 70,
+                    end: 79,
+                    color: '#3D26D2',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV70-79-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V70-79.png'
+                },
+                {
+                    start: 80,
+                    end: 89,
+                    color: '#DF1637',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV80-89-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V80-89.png'
+                },
+                {
+                    start: 90,
+                    end: 99,
+                    color: '#FA6802',
+                    icon: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/LV90-99-icon.png',
+                    bg: 'https://raex-meta.oss-cn-shenzhen.aliyuncs.com/medals/V90-99.png'
+                }
+            ],
+            levels: [],
+            money: 0
+        };
+    },
+    computed: {
+        levelInfo() {
+            if (this.isLogin) {
+                let level = Math.floor(this.money / 10);
+                console.log(level);
+                let info = {};
+                [...this.medals].forEach(item => {
+                    if (level > item.start) {
+                        info = { ...item };
+                    }
+                });
+                let _info =
+                    [...this.levels].find(item => {
+                        return level >= item.startLevel;
+                    }) || {};
+                return { level, ...info, ..._info };
+            } else {
+                return {};
+            }
+        }
+    },
+    mounted() {
+        this.$http.post('/purchaseLevel/all', {}, { body: 'json' }).then(res => {
+            this.levels = res.content.map((item, index) => {
+                let start = index - 1 >= 0 ? res.content[index - 1].endLevel : 0;
+                return {
+                    ...item,
+                    startLevel: item.startLevel || ''
+                };
+            });
+
+            if (this.isLogin) {
+                this.$http.get('/asset/breakdown').then(res => {
+                    this.money = res.buy;
+                    this.$nextTick(() => {
+                        if (this.$store.state.userInfo.level !== this.levelInfo.level) {
+                            this.changeLevel(this.levelInfo.level);
+                        }
+                    });
+                });
+            }
+        });
+    }
+};

+ 1 - 1
src/mixins/product.js

@@ -61,7 +61,7 @@ export default {
             return this.info && !this.info.noSoldOut && this.info.salable;
         },
         assignment() {
-            return 0;
+            return this.info.assignment || 0;
         }
     },
     methods: {

+ 19 - 0
src/router/index.js

@@ -248,6 +248,17 @@ const routes = [
             tabColor: '#181818'
         }
     },
+    {
+        path: '/productTasks',
+        name: 'productTasks',
+        component: () => import('../views/product/Tasks.vue'),
+        meta: {
+            pageType: Page.Every,
+            menuPage: true,
+            title: '第九空间',
+            tabColor: '#181818'
+        }
+    },
     {
         path: '/productDetail2',
         name: 'productDetail2',
@@ -518,6 +529,14 @@ const routes = [
         meta: {
             title: '第九空间'
         }
+    },
+    {
+        path: '/mineLevel',
+        name: 'mineLevel',
+        component: () => import('../views/user/Level.vue'),
+        meta: {
+            title: '第九空间'
+        }
     }
 ];
 

+ 6 - 1
src/views/Mine.vue

@@ -158,11 +158,14 @@
         </van-grid>
 
         <div class="tabbar-placeholder"></div>
+
+        <level></level>
     </div>
 </template>
 
 <script>
 import { mapState } from 'vuex';
+import Level from '../components/Level';
 export default {
     data() {
         return {
@@ -170,6 +173,7 @@ export default {
             showMore: false
         };
     },
+    components: { Level },
     computed: {
         ...mapState(['userInfo'])
     },
@@ -190,9 +194,10 @@ export default {
                     if (!res.empty) {
                         this.form = res.content[0];
                         this.org = this.form.org;
-                        console.log(this.org);
                     }
                 });
+
+         
         }
     },
     methods: {

+ 10 - 1
src/views/account/Register.vue

@@ -84,6 +84,7 @@
                 </template>
             </van-field>
             <van-field
+                v-if="showInvite"
                 type="text"
                 name="邀请码"
                 placeholder="请输入邀请码"
@@ -137,7 +138,8 @@ export default {
                 code: '',
                 inviteCode: this.$store.state.inviteCode || ''
             },
-            checked: false
+            checked: false,
+            showInvite: true
         };
     },
     beforeRouteEnter(to, from) {
@@ -181,6 +183,13 @@ export default {
                     }
                 });
         }
+    },
+    mounted() {
+        if (this.$store.state.invitor && this.$store.state.productId) {
+            this.showInvite = false;
+        } else {
+            this.showInvite = true;
+        }
     }
 };
 </script>

+ 1 - 1
src/views/activity/ChooseProduct.vue

@@ -119,7 +119,7 @@ export default {
                     '/asset/all',
                     {
                         page: 0,
-                        size: 99,
+                        size: 999,
                         query: { status: 'NORMAL,TRADING,GIFTING', userId: this.$store.state.userInfo.id },
                         search: this.search
                     },

+ 18 - 30
src/views/product/Detail.vue

@@ -23,6 +23,8 @@
                 </div>
                 <div class="text" v-if="info.couponPayment">优惠券藏品</div>
             </div>
+
+            <tasks v-if="assignment" :info="info" v-model:assignments="assignments"></tasks>
             <!-- <div class="title">{{ info.name }}</div> -->
             <div class="info-bottom">
                 <!-- <span class="text1" v-if="info.number"> 编号 {{ info.number }} </span> -->
@@ -252,15 +254,16 @@
                     <!-- <van-button class="no-btn" v-else-if="isSold" block round>已售罄</van-button> -->
                     <van-button class="no-btn" v-else-if="isSold" block round>已售罄</van-button>
                     <!-- <van-button class="no-btn" v-else-if="isSold" block round>即将售罄</van-button> -->
+                    <van-button class="no-btn" v-else-if="limit.limit > 0 && limit.count >= limit.limit" block round>
+                        限购{{ limit.limit }}件
+                    </van-button>
                     <van-button
-                        class="no-btn"
-                        v-else-if="limit.limit && limit.limit > 0 && limit.count >= limit.limit"
+                        @click="share"
+                        type="primary"
+                        v-else-if="assignment && assignments.length < assignment"
                         block
                         round
                     >
-                        限购{{ limit.limit }}件
-                    </van-button>
-                    <van-button type="primary" v-else-if="assignment && assignments.length < assignment" block round>
                         邀请获取白名单
                     </van-button>
                     <van-button v-else type="primary" block round @click="buy">
@@ -296,6 +299,7 @@ import 'swiper/swiper-bundle.min.css';
 
 import SwiperCore, { Pagination } from 'swiper';
 import Post from '../../components/Post.vue';
+import Tasks from '../../components/product/Tasks.vue';
 
 SwiperCore.use([Pagination]);
 
@@ -308,7 +312,8 @@ export default {
         ProductBanner,
         Swiper,
         SwiperSlide,
-        Post
+        Post,
+        Tasks
     },
     mixins: [product, coupon],
     name: 'productDetail',
@@ -325,8 +330,8 @@ export default {
             activeNames: ['1', '2', '3', '4', '5', '6', 'hashCode', '8'],
             inWeixin,
             limit: {},
-            assignments: [],
-            couponList: []
+            couponList: [],
+            assignments: []
         };
     },
     computed: {
@@ -444,12 +449,6 @@ export default {
                         }
                     });
                     this.$toast.clear();
-                    //白名单
-                    this.$nextTick(() => {
-                        if (this.assignment) {
-                            this.getAssignment();
-                        }
-                    });
 
                     if (res.type === 'BLIND_BOX') {
                         return this.$http.post(
@@ -509,22 +508,11 @@ export default {
                 }
             });
         },
-        getAssignment() {
-            if (this.isLogin) {
-                this.$http
-                    .post(
-                        '/user/all',
-                        {
-                            query: {
-                                collectionInvitor: this.$store.state.userInfo.id,
-                                collectionId: this.info.id
-                            }
-                        },
-                        { body: 'json' }
-                    )
-                    .then(res => {
-                        this.assignments = res.content;
-                    });
+        share() {
+            if (this.assignment && !this.isLogin) {
+                this.checkLogin();
+            } else {
+                this.$refs.post.init();
             }
         }
     }

+ 173 - 0
src/views/product/Tasks.vue

@@ -0,0 +1,173 @@
+<template>
+    <div class="tasks">
+        <van-image class="bg" width="100%" :src="registerBg" fit="scale-down" />
+        <div class="box">
+            <div class="title">帮好友助力获得白名单权限</div>
+            <van-form @submit="submit" ref="form">
+                <van-field
+                    type="tel"
+                    name="手机号码"
+                    placeholder="请输入手机号码"
+                    v-model="form.phone"
+                    :maxlength="11"
+                    :rules="[
+                        { required: true, message: '请输入手机号码' },
+                        {
+                            pattern: phonePattern,
+                            message: '手机号码格式错误'
+                        }
+                    ]"
+                >
+                </van-field>
+
+                <van-field
+                    type="digit"
+                    name="验证码"
+                    placeholder="请输入验证码"
+                    v-model="form.code"
+                    :maxlength="4"
+                    :rules="[{ required: true, message: '请输入验证码' }]"
+                >
+                    <template #button>
+                        <van-button
+                            round
+                            @click="sendPhone"
+                            class="sub-code"
+                            size="small"
+                            color="#0F0F0F"
+                            :disabled="isSend"
+                        >
+                            {{ isSend ? `已发送(${sendNum})S` : '发送验证码' }}
+                        </van-button>
+                    </template>
+                </van-field>
+                <div class="button">
+                    <van-button round block native-type="submit" color="#0F0F0F" class="sure"> 立即助力 </van-button>
+                </div>
+            </van-form>
+        </div>
+    </div>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+import phone from '../../mixins/phone';
+export default {
+    mixins: [phone],
+    data() {
+        return {
+            form: {
+                phone: '',
+                code: '',
+                invitor: '',
+                collectionId: ''
+            },
+            checked: false,
+            registerBg: ''
+        };
+    },
+    computed: {
+        ...mapState(['productId', 'invitor'])
+    },
+    mounted() {
+        if (this.productId) {
+            this.form.collectionId = this.productId;
+            this.$http.get('/collection/get/' + this.productId).then(res => {
+                this.registerBg = res.registerBg;
+            });
+        }
+        if (this.invitor) {
+            this.form.invitor = this.invitor;
+        }
+    },
+    methods: {
+        sendPhone() {
+            this.$refs.form.validate('手机号码').then(() => {
+                this.sendMsg(this.form.phone);
+            });
+        },
+        submit() {
+            this.$toast.loading({
+                message: '加载中...',
+                forbidClick: true
+            });
+            this.$http
+                .post('/auth/phoneRegister', this.form)
+                .then(res => {
+                    localStorage.setItem('nineToken', res);
+                    return this.$store.dispatch('getUserInfo');
+                })
+                .then(() => {
+                    this.$dialog
+                        .alert({
+                            title: '助力成功'
+                        })
+                        .then(() => {
+                            this.$router.replace('/home');
+                        });
+                })
+                .catch(e => {
+                    if (e) {
+                        this.$toast(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.tasks {
+    background-color: #181818;
+    position: relative;
+}
+.bg {
+    display: block;
+}
+.box {
+    width: calc(100vw - 40px);
+    background: #ffffff;
+    border-radius: 30px;
+    position: absolute;
+    top: 268px;
+    left: 20px;
+    padding-bottom: 14px;
+}
+
+.title {
+    font-size: 16px;
+    font-weight: bold;
+    color: #000000;
+    line-height: 22px;
+    text-align: center;
+    padding: 16px 0 12px;
+}
+
+/deep/.van-form {
+    padding: 0 20px;
+
+    .van-field__control {
+        background: #f5f7fa;
+        border-radius: 22px;
+        height: 38px;
+        padding: 0 10px 0 20px;
+    }
+    .van-cell {
+        padding: 0;
+        &::after {
+            content: none;
+        }
+    }
+    .van-cell + .van-cell {
+        margin-top: 10px;
+    }
+
+    .button {
+        margin-top: 16px;
+    }
+
+    .sub-code {
+        min-width: 98px;
+    }
+}
+</style>

+ 140 - 0
src/views/user/Level.vue

@@ -0,0 +1,140 @@
+<template>
+    <div class="level">
+        <div class="level-title">
+            <div class="text1">绿洲宇宙元力等级系统</div>
+            <div class="text2">
+                在绿洲宇宙中使用绿洲石,绿洲石将会产生原力,原力是绿洲藏家晋升之路的基础。原力越高,境界与头衔越高。
+            </div>
+        </div>
+        <div class="level-title">
+            <div class="text1">勋章展示</div>
+            <div class="text2">10级以上(包含10级)将会获得勋章奖励,最高等级Lv99</div>
+        </div>
+
+        <swiper slidesPerView="auto" :spaceBetween="16" class="box-swiper">
+            <swiper-slide class="box" v-for="(item, index) in medals" :key="index">
+                <van-image class="box-bg" :src="item.bg" width="88" height="100" />
+                <div class="box-content">
+                    <van-image width="35" height="35" :src="item.icon" />
+                    <div class="box-text">Lv{{ item.start }}-{{ item.end }}</div>
+                </div>
+            </swiper-slide>
+        </swiper>
+
+        <div class="table">
+            <div class="tr">
+                <div class="th">原力级别</div>
+                <div class="th">境界</div>
+                <div class="th">头衔</div>
+            </div>
+
+            <div class="tr" v-for="(item, index) in levels" :key="index">
+                <div class="td">
+                    Lv{{ item.startLevel || item.startLevel === 0 ? item.startLevel + '~' : '' }} {{ item.endLevel }}级
+                </div>
+                <div class="td">{{ item.realm }}</div>
+                <div class="td">{{ item.title }}</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { Swiper, SwiperSlide } from 'swiper/vue';
+import 'swiper/swiper.min.css';
+import 'swiper/swiper-bundle.min.css';
+import level from '../../mixins/level';
+export default {
+    data() {
+        return {};
+    },
+    mixins: [level],
+    components: {
+        Swiper,
+        SwiperSlide
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.level-title {
+    padding: 10px 16px;
+    .text1 {
+        font-size: 14px;
+        font-weight: bold;
+        color: #000000;
+        line-height: 24px;
+    }
+
+    .text2 {
+        font-size: 12px;
+        color: #939599;
+        line-height: 17px;
+    }
+}
+/deep/.box-swiper {
+    padding: 6px 0 30px 16px;
+    .swiper-slide {
+        background-color: @bg3;
+        height: 100px;
+        width: 88px;
+    }
+}
+
+.table {
+    margin: 16px;
+    border-radius: 12px;
+    overflow: hidden;
+    .tr {
+        height: 32px;
+        .flex();
+
+        & > div {
+            width: 33%;
+            padding: 0 24px;
+
+            &.th {
+                font-size: 12px;
+                color: #000000;
+                line-height: 17px;
+            }
+
+            &.td {
+                font-size: 12px;
+                color: #939599;
+                line-height: 17px;
+                &:first-child {
+                    color: #000000;
+                }
+            }
+        }
+
+        &:nth-child(2n + 1) {
+            background: #f5f7fa;
+        }
+    }
+}
+
+.box {
+    position: relative;
+
+    .box-content {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        .flex-col();
+        align-items: center;
+
+        .box-text {
+            white-space: nowrap;
+            font-size: 12px;
+            line-height: 20px;
+            padding: 0 5px;
+            background-color: rgba(255, 255, 255, 0.3);
+            margin-top: 10px;
+            border-radius: 12px;
+        }
+    }
+}
+</style>