Переглянути джерело

feat:增加视频教学等页面

徐志豪 5 роки тому
батько
коміт
dbd02289de

+ 3 - 0
pc/src/apis/index.js

@@ -3,5 +3,8 @@ import axios from '@/util/http'
 export default {
   saveAduit (data) {
     return axios.post('agentAduit/save')
+  },
+  getEmailAuthCode (data) {
+    return axios.post('sso/user/getEmailAuthCode', data)
   }
 }

BIN
pc/src/assets/images/online/house/item-2.jpg


BIN
pc/src/assets/images/online/house/item-2.png


BIN
pc/src/assets/images/refactor/appDownload/banner.jpg


+ 17 - 0
pc/src/assets/images/refactor/footer/dy.svg

@@ -0,0 +1,17 @@
+<svg id="WKND-button-standard" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: #ebebeb;
+      }
+
+      .cls-2 {
+        fill: #202020;
+      }
+    </style>
+  </defs>
+  <rect id="background" class="cls-1" width="48" height="48"/>
+  <g id="douyin" transform="translate(14.969 14.22)">
+    <path id="路径_3717" data-name="路径 3717" class="cls-2" d="M892.085,39.21a4.8,4.8,0,0,1-2.179-4H886.47l0,13.767a2.887,2.887,0,1,1-2.884-3,2.766,2.766,0,0,1,.853.136V42.606a6.117,6.117,0,0,0-.853-.061,6.323,6.323,0,1,0,6.323,6.323v-6.98a8.169,8.169,0,0,0,4.778,1.536V39.989a4.767,4.767,0,0,1-2.6-.779Z" transform="translate(-877.259 -35.206)"/>
+  </g>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 20 - 0
pc/src/assets/images/refactor/footer/wb.svg


Різницю між файлами не показано, бо вона завелика
+ 19 - 0
pc/src/assets/images/refactor/footer/wechat.svg


BIN
pc/src/assets/images/refactor/login/forget-img.png


+ 3 - 1
pc/src/components/common/phoneAddressSelect.vue

@@ -43,6 +43,7 @@ export default {
   overflow: auto;
   position: absolute;
   background: #fff;
+  left: 0;
   .search-w {
     position: relative;
   }
@@ -61,7 +62,7 @@ export default {
   .sousuo-icon {
     position: absolute;
     right: 8px;
-    // top: 8px;
+    top: 8px;
     line-height: 26px;
     color: #909090;
     display: inline;
@@ -70,6 +71,7 @@ export default {
     cursor: pointer;
     border-bottom: 0.25px solid #707070;
     padding: 6px 0;
+    line-height: 18px;
     color: #909090;
     &:hover {
       color: #202020;

+ 3 - 1
pc/src/components/lselect/index.vue

@@ -77,7 +77,7 @@ export default {
     cursor: pointer;
 
     &.active {
-      background-color: #1fe4dc;
+      background-color: #202020;
       color: #fff;
       position: relative;
 
@@ -86,6 +86,8 @@ export default {
         position: absolute;
         top: 0;
         right: $rwidth;
+        font-size: 20px;
+        font-weight: normal;
       }
     }
   }

+ 6 - 6
pc/src/page/conduct/conductHouse/index.vue

@@ -35,7 +35,7 @@ export default {
         },
         {
           name: '房源资讯全方位展示,提高租售决策效率',
-          img: require('@/assets/images/online/house/item-2.jpg'),
+          img: require('@/assets/images/online/house/item-2.png'),
           runAnimation: true
         },
         {
@@ -51,11 +51,11 @@ export default {
           img: require('@/assets/images/online/house/item-3.jpg'),
           runAnimation: true
         },
-        {
-          name: '开放解决方案API,赋能行业应用',
-          img: require('@/assets/images/online/house/item-5.jpg'),
-          runAnimation: true
-        }
+        // {
+        //   name: '开放解决方案API,赋能行业应用',
+        //   img: require('@/assets/images/online/house/item-5.jpg'),
+        //   runAnimation: true
+        // }
       ],
     }
   },

+ 3 - 3
pc/src/page/home2/index.vue

@@ -12,7 +12,7 @@
             <span class="watch-btn action-link">观看视频</span>
           </div>
           <div class="distributor">
-            <router-link to="/" class="">成为经销商</router-link>
+            <router-link to="/distributor" class="">成为经销商</router-link>
           </div>
         </div>
       </div>
@@ -138,9 +138,9 @@ export default {
       {
         title: '安防勘查',
         title_sub: '安防勘查',
-        desc: '海量复刻真房源',
+        desc: '高效复刻灾害现场,记录全面三维档案',
         img: require('@/assets/images/home/solutions-house.png'),
-        list: ['AI自动建模,高效复刻真实房源', '云带看/云讲房,全方位介绍房源信息', '易上手操作,人人都能掌握拍摄流程', '专业地产营销系统,高效管理租售信息']
+        list: ['高效复刻灾害现场,记录全面三维档案', '支持预先采集存档,减少理赔纠纷']
       }],
       space: [
         {

+ 9 - 9
pc/src/page/layout/footer.vue

@@ -23,18 +23,18 @@
             </div>
             <ul class="contacts-w">
               <popup
-                :icon="`${$cdn}images/05dy.png`"
-                :hovericon="`${$cdn}images/05dy_h.png`"
-                :code="`${$cdn}images/code_dy.jpg`"
+                :icon="require('@/assets/images/refactor/footer/wechat.svg')"
+                :hovericon="require('@/assets/images/refactor/footer/wechat.svg')"
+                :code="`${$cdn}images/code_wx.jpg`"
               />
               <popup
-                :icon="`${$cdn}images/05dy.png`"
-                :hovericon="`${$cdn}images/05dy_h.png`"
-                :code="`${$cdn}images/code_dy.jpg`"
+                :icon="require('@/assets/images/refactor/footer/wb.svg')"
+                :hovericon="require('@/assets/images/refactor/footer/wb.svg')"
+                :code="`${$cdn}images/code_wb.jpg`"
               />
               <popup
-                :icon="`${$cdn}images/05dy.png`"
-                :hovericon="`${$cdn}images/05dy_h.png`"
+                :icon="require('@/assets/images/refactor/footer/dy.svg')"
+                :hovericon="require('@/assets/images/refactor/footer/dy.svg')"
                 :code="`${$cdn}images/code_dy.jpg`"
               />
             </ul>
@@ -232,7 +232,7 @@ export default {
   padding-top: 94px;
   color: #202020;
   position: relative;
-  z-index: 11111;
+  z-index: 100;
   p {
     font-size: 40px;
     margin-bottom: 27px;

+ 1 - 1
pc/src/page/layout/header/index.vue

@@ -119,7 +119,7 @@ export default {
           },
           {
             text: '视频教程',
-            link: '/video-course'
+            link: '/service/mVideo/all'
           }
         ]},
         {text: '关于我们',  items: [

+ 4 - 0
pc/src/page/login/components/cameraLogin.vue

@@ -57,6 +57,10 @@ export default {
         }
       }, 3000)
     }
+  },
+  beforeDestroy () {
+    clearInterval(this.t1)
+    this.t1 = null
   }
 }
 </script>

+ 2 - 3
pc/src/page/login/components/codeLogin.vue

@@ -46,7 +46,6 @@ export default {
     },
     async sendCode () {
       if (this.sendCodeExTime) return;
-      console.log(this.loginForm.phone)
       let res = await this.$store.dispatch('getAuthCode', {
         phone: this.loginForm.phone,
         code: Number(this.selectArea[1].substr(1))
@@ -96,7 +95,7 @@ export default {
       this.$router.push('/')
     }
   },
-  destroyed () {
+  beforeDestroy () {
     clearInterval(timer)
     timer = null
   }
@@ -155,7 +154,7 @@ export default {
   margin-top: 30px;
   .input {
     padding-right: 50%;
-    margin: 0;
+    margin: 0 0 13px;
   }
   .code-btn {
     padding: 0 10px;

+ 244 - 0
pc/src/page/login/components/forget/emailForm.vue

@@ -0,0 +1,244 @@
+<template>
+  <div class="email-form">
+    <div class="border-box" v-if="type === 'phone'">
+      <div class="phone-area" @click="showPhoneArea = !showPhoneArea">
+        {{selectArea[1]}}({{selectArea[0]}})<span class="sanjiao"></span>
+        <phoneAddressSelect  v-show="showPhoneArea" @select="changeArea" />
+      </div>
+      <input type="text" placeholder="请输入手机号码" v-model="form.phone">
+    </div>
+    <input class="border-box"  v-model="form.phone" placeholder="邮箱地址" type="text" v-else>
+    <div class="send-code-w border-box">
+      <input type="text" placeholder="验证码"  v-model="form.authCode">
+      <div class="send-btn" @click="sendCode">获取验证码</div>
+    </div>
+    <input class="border-box" placeholder="设置密码" type="text"  v-model="form.password">
+    <input class="border-box" placeholder="重复密码" type="text"  v-model="form.confirmPass">
+    <p class="login-entry">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
+    <div class="submit-btn">提交</div>
+  </div>
+</template>
+
+<script>
+import phoneAddressSelect from '@/components/common/phoneAddressSelect'
+import { mapState } from 'vuex'
+import { encodeStr } from '@/util'
+import { Base64 } from 'js-base64'
+
+export default {
+  props: {
+    type: {
+      type: String,
+      default: 'email'
+    }
+  },
+  data () {
+    return {
+      form: {},
+      interEmailTime: 0,
+      interTime: 0,
+      showPhoneArea: false,
+      selectArea: ['中国', '+86']
+    }
+  },
+  computed: {
+    ...mapState({
+      langToast: state => state.language.home.toast
+    })
+  },
+  components: {
+    phoneAddressSelect
+  },
+  methods: {
+    sendCode () {
+      this.type === 'phone' ? this.getAuthCode() : this.getEmailAuthCode()
+    },
+    changeArea (item) {
+      this.selectArea = item
+    },
+    async getAuthCode () {
+      if (this.interl) {
+        return
+      }
+      let res = await this.$store.dispatch('getAuthCode', {
+        phone: this.form.phone,
+        code: Number(this.selectArea[0].substr(1)),
+        type: 'resigter',
+      })
+      if (res) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interTime = 60
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
+    },
+    async getEmailAuthCode () {
+      if (this.emailInterl) {
+        return
+      }
+      let res = await this.$store.dispatch('getAuthCode', {
+        type: 'resigter',
+        email: this.form.phone,
+        qudao: 'email'
+      })
+      if (res) {
+        this.emailInterl && clearInterval(this.emailInterl)
+        this.emailInterl = null
+        this.interEmailTime = 60
+        this.emailInterl = setInterval(() => {
+          this.interEmailTime--
+          if (this.interEmailTime <= 0) {
+            clearInterval(this.emailInterl)
+            this.emailInterl = null
+          }
+        }, 1000)
+      }
+    },
+    async submit () {
+      let check = value => {
+        for (let i = 0, len = value.length; i < len; i++) {
+          if (!value[i].val) {
+            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+          }
+        }
+        return true
+      }
+      let checkStr = [
+        {
+          name: '手机',
+          En: 'Phone number',
+          val: this.phone
+        },
+        {
+          name: '验证码',
+          En: 'Verification code',
+          val: this.authCode
+        },
+        {
+          name: '密码',
+          En: 'Password',
+          val: this.password
+        },
+        {
+          name: '确认密码',
+          En: 'Password',
+          val: this.confirmpass
+        }
+      ]
+      if (!check(checkStr)) {
+        return
+      }
+      if (this.password.length < 8 || this.confirmpass.length < 8) {
+        return this.$toast.show('warn', this.langToast['31'])
+      }
+
+      let temp = encodeStr(Base64.encode(this.password), Base64.encode(this.confirmpass))
+      let params = {
+        password: temp[0],
+        phoneNum: this.phone,
+        confirmPwd: temp[1],
+        msgAuthCode: this.authCode
+      }
+      let res = await this.$http({
+        method: 'post',
+        headers: {
+          token: this.token
+        },
+        data: params,
+        url: 'sso/user/changePassword'
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', this.langToast[response.code])
+      }
+      this.$toast.show('warn', this.langToast['32'], () => {
+        this.$bus.$emit('currentActive', 'ilogin')
+      })
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.email-form  {
+  padding-top: 35px;
+  font-size: 16px;
+  .border-box {
+    border: 1px solid #909090;
+    border-radius: 3px;
+    height: 42px;
+    line-height: 40px;
+    width: 100%;
+    margin-bottom: 20px;
+    display: flex;
+  }
+  input {
+    border: none;
+    padding-left: 10px;
+    flex: 1;
+  }
+  .send-btn {
+    padding: 0 10px;
+    cursor: pointer;
+  }
+  .login-entry {
+    margin: 80px 0 30px 0;
+    text-align: center;
+    font-size: 14px;
+    span {
+      font-weight: bold;
+      display: inline-block;
+      position: relative;
+      cursor: pointer;
+      &::after {
+        content: '';
+        display: block;
+        height: 2px;
+        width: 100%;
+        background: #1FE4DC;
+      }
+    }
+  }
+  .submit-btn {
+    line-height: 60px;
+    text-align: center;
+    font-size: 20px;
+    font-weight: bold;
+    background: #1FE4DC;
+    border-radius: 3px;
+    cursor: pointer;
+  }
+  .phone-area {
+      padding: 0 16px 0 10px;
+      position: relative;
+      cursor: pointer;
+      width: 120px;
+      &::after {
+        content: '';
+        display: block;
+        height: 28px;
+        width: 1px;
+        background: #707070;
+        position: absolute;
+        right: 0;
+        top: 6px
+      }
+    }
+    .sanjiao {
+      display: inline-block;
+      border: 7px solid #909090;
+      border-bottom: none;
+      border-left-color: transparent;
+      border-right-color: transparent;
+      margin-left: 10px;
+    }
+}
+</style>

+ 49 - 0
pc/src/page/login/components/forget/index.vue

@@ -0,0 +1,49 @@
+<template>
+  <div class="forget">
+    <div class="forget-header">{{ title }}</div>
+    <selectType @change="changePage" v-if="page === 'select'" />
+    <emailForm v-else :type="page" />
+  </div>
+</template>
+
+<script>
+import selectType from './selectType'
+import emailForm from './emailForm'
+export default {
+  data () {
+    return {
+      page: 'select'
+    }
+  },
+  components: {
+    selectType,
+    emailForm
+  },
+  computed: {
+    title () {
+      return '找回密码'
+    }
+  },
+  methods: {
+    changePage (type) {
+      this.page = type
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.forget {
+  width: 400px;
+  padding: 40px;
+  .forget-header {
+    padding: 0 0 10px 0;
+    border-bottom: 1px solid #707070;
+    text-align: center;
+    font-size: 20px;
+    color: #202020;
+    font-weight: bold;
+  }
+  
+}
+</style>

+ 40 - 0
pc/src/page/login/components/forget/selectType.vue

@@ -0,0 +1,40 @@
+<template>
+  <div class="select-type">
+    <img src="@/assets/images/refactor/login/forget-img.png" alt="">
+    <p class="tips">为确认您是本人操作,<br/>请选择验证方式完成密码重置</p>
+    <div class="type-btn" @click="selectType('phone')">使用手机短信验证码</div>
+    <div class="type-btn" @click="selectType('email')">使用E-mail验证码</div>
+  </div>
+</template>
+
+<script>
+export default {
+  methods: {
+    selectType (type) {
+      this.$emit('change', type)
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.select-type {
+  padding-top: 35px;
+  text-align: center;
+  color: #202020;
+}
+.tips {
+  font-size: 12px;
+  color: #909090;
+  margin-top: 10px;
+  line-height: 15px;
+}
+.type-btn {
+  height: 60px;
+  cursor: pointer;
+  background: #EBEBEB;
+  border-radius:3px;
+  line-height: 60px;
+  margin-top: 30px;
+}
+</style>

+ 61 - 7
pc/src/page/login/components/login.vue

@@ -4,16 +4,16 @@
       <div class="login-tab" :class="{'is-active': !type || type === 'codeLogin'}" @click="toOtherLogin('')">用户登录</div><div class="login-tab" :class="{'is-active': type==='camera'}" @click="toOtherLogin('camera')">相机登录</div>
     </div>
     <div class="account-login" v-if="!type">
-      <input type="text" class="input" placeholder="请输入手机号码/邮箱">
-      <input type="password" class="input password" placeholder="请输入密码">
+      <input type="text" class="input" placeholder="请输入手机号码/邮箱" v-model="form.phone">
+      <input type="password" class="input password" placeholder="请输入密码" v-model="form.password">
       <div class="toCodeLogin tips-tap" >
         <a @click="$router.push({name: 'login', query: {type: 'codeLogin'}})">验证码登录</a>
       </div>
-      <p class="checkbox" :class="{checked: isRemember}" @click="isRemember = !isRemember">记住密码</p>
-      <div class="login-btn">登录</div>
+      <p class="checkbox" :class="{checked: rememberMe}" @click="rememberMe = !rememberMe">记住密码</p>
+      <div class="login-btn" @click="login">登录</div>
       <div class="others">
-        <a class="other-actions" @click="toOtherLogin('camera')">忘记密码</a>
-        <a class="other-actions" href="">账号注册</a>
+        <a class="other-actions" @click="$router.push('/login/forget')">忘记密码</a>
+        <a class="other-actions" @click="$router.push('/login/register')">账号注册</a>
       </div>
     </div>
     <cameraLogin v-if="type === 'camera'" />
@@ -24,10 +24,17 @@
 <script>
 import cameraLogin from './cameraLogin'
 import codeLogin from './codeLogin'
+import { encodeStr } from '@/util'
+import { Base64 } from 'js-base64'
+
 export default {
   data () {
     return {
-      isRemember: false
+      rememberMe: false,
+      form: {
+        phone: '',
+        password: ''
+      }
     }
   },
   computed: {
@@ -47,6 +54,53 @@ export default {
           type: type
         }
       })
+    },
+    async login () {
+      let check = value => {
+          for (let i = 0, len = value.length; i < len; i++) {
+            if (!value[i].val) {
+              return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            }
+          }
+          return true
+        }
+        let checkStr = [
+          {
+            name: '手机',
+            En: 'Phone number',
+            val: this.form.phone
+          },
+          {
+            name: '密码',
+            En: 'Password',
+            val: this.form.password
+          }
+        ]
+        if (!check(checkStr)) {
+          return
+        }
+        localStorage.setItem('remember', this.rememberMe)
+        if (this.rememberMe) {
+          localStorage.setItem('username', this.form.phone)
+          localStorage.setItem('password', this.form.password)
+        } else {
+          localStorage.setItem('username', '')
+          localStorage.setItem('password', '')
+        }
+
+        let params = {
+          phoneNum: this.form.phone,
+          password: encodeStr(Base64.encode(this.form.password)),
+          randomcode: '1234',
+          rememberMe: Boolean(this.rememberMe)
+        }
+        await this.$store.dispatch('login', params)
+        const frm = this.$route.query.frm
+        if (frm) {
+          window.location = frm
+        } else {
+          this.$router.push('/')
+        }
     }
   }  
 }

pc/src/page/login/components/forget.vue → pc/src/page/login/components/register/email.vue


+ 335 - 6
pc/src/page/login/components/register/index.vue

@@ -1,15 +1,243 @@
 <template>
   <div class="register">
     <h3>四维账号注册</h3>
-    <p class="tologin">已有账号,<span>直接登录</span></p>
-    <input  type="text">
-    <input  type="text">
-    <input  type="text">
-    <input  type="text">
-    <input  type="text">
+    <p class="tologin">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
+    <!-- 手机注册 -->
+    <div class="phone-register" v-if="type === 'phone'">
+      <input placeholder="请输入昵称" type="text" v-model="form.nickname">
+      <div class="phone-w">
+        <div class="phone-area" @click.stop="showPhoneArea=!showPhoneArea">{{ `${selectArea[1]}(${selectArea[0]})` }}<span class="sanjiao"></span>
+          <phoneAddressSelect  v-show="showPhoneArea" @select="changeArea" />
+        </div>
+        <input placeholder="请输入手机号码" class="phone" type="text" v-model="form.phone">
+      </div>
+      <div class="code-w">
+        <input placeholder="短信验证码" class="phone" type="text" v-model="form.authCode">
+        <div class="send-code-btn" :class="{'is-disabled': interTime}" @click="getAuthCode">{{ interTime ? `${interTime}s后重试` : '获取验证码'}}</div>
+      </div>
+      <input placeholder="设置密码" autocomplete="new-password" v-model="form.password" type="password">
+      <input placeholder="重复密码" autocomplete="new-password" v-model="form.confirmPass" type="password">
+      <div class="right-tips"><span @click="type = 'email'">邮箱注册</span></div>
+    </div>
+    <!-- 邮箱注册 -->
+    <div class="email-register" v-if="type === 'email'">
+      <input placeholder="请输入昵称" type="text" v-model="emailForm.nickname">
+      <div class="code-w">
+        <input placeholder="邮箱地址" class="phone" type="text" v-model="emailForm.phone">
+        <div class="send-code-btn" :class="{'is-disabled': interEmailTime}" @click="getEmailAuthCode">{{ interEmailTime ? `${interEmailTime}s后重试` : '获取验证码'}}</div>
+      </div>
+      <input placeholder="验证码(6位数)"  type="text" v-model="emailForm.authCode">
+      <input placeholder="设置密码" autocomplete="new-password" v-model="emailForm.password" type="password">
+      <input placeholder="重复密码" autocomplete="new-password" v-model="emailForm.confirmPass" type="password">
+      <div class="right-tips"><span @click="type = 'phone'">手机号码注册</span></div>
+    </div>
+    <div class="xieyi-w">
+      <input type="checkbox" v-model="showCluse">
+      <span>我已阅读并同意四维看看用户协议</span>
+    </div>
+    <div class="register-btn" @click="submit">注册</div>
   </div>
 </template>
 
+<script>
+import phoneAddressSelect from '@/components/common/phoneAddressSelect'
+import { mapState } from 'vuex'
+import { encodeStr } from '@/util'
+import { Base64 } from 'js-base64'
+
+export default {
+  data () {
+    return {
+      type: 'phone',
+      showPhoneArea: false,
+      selectArea: ['+86', '中国'],
+      interTime: 0,
+      interEmailTime: 0,
+      showCluse: false,
+      form: {
+        phone: '',
+        authCode: '',
+        nickname: '',
+        password: '',
+        confirmPass: '',
+      },
+      emailForm: {
+        phone: '',
+        password: '',
+        confirmPass: '',
+        msgAuthCode: ''
+      }
+    }
+  },
+  computed : {
+    ...mapState({
+      langToast: state => state.language.home.toast
+    })
+  },
+  watch: {
+    type () {
+      this.form = {
+        phone: '',
+        authCode: '',
+        nickname: '',
+        password: '',
+        confirmPass: '',
+      }
+      this.emailForm = {
+        phone: '',
+        password: '',
+        confirmPass: '',
+        msgAuthCode: ''
+      }
+    }
+  },
+  components: {
+    phoneAddressSelect
+  },
+  methods: {
+    changeArea (item) {
+      this.selectArea = item
+    },
+    async getAuthCode () {
+      if (this.interl) {
+        return
+      }
+      let res = await this.$store.dispatch('getAuthCode', {
+        phone: this.form.phone,
+        code: Number(this.selectArea[0].substr(1)),
+        type: 'resigter',
+      })
+      if (res) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interTime = 60
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
+    },
+    async getEmailAuthCode () {
+      if (this.emailInterl) {
+        return
+      }
+      let res = await this.$store.dispatch('getAuthCode', {
+        type: 'resigter',
+        email: this.emailForm.phone,
+        qudao: 'email'
+      })
+      if (res) {
+        this.emailInterl && clearInterval(this.emailInterl)
+        this.emailInterl = null
+        this.interEmailTime = 60
+        this.emailInterl = setInterval(() => {
+          this.interEmailTime--
+          if (this.interEmailTime <= 0) {
+            clearInterval(this.emailInterl)
+            this.emailInterl = null
+          }
+        }, 1000)
+      }
+    },
+    async submit () {
+      if (!this.showCluse) {
+        return
+      }
+      let check = value => {
+        for (let i = 0, len = value.length; i < len; i++) {
+          if (!value[i].val && value[i].required) {
+            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+          }
+        }
+        return true
+      }
+      let form = this.type === 'email' ? this.emailForm : this.form
+      let checkStr = [
+        {
+          name: '昵称',
+          En: 'User name',
+          val: form.nickname,
+          required: this.type === 'email' ? false : true
+        },
+        {
+          name: '手机',
+          En: 'Phone number',
+          val: form.phone,
+          required: true
+        },
+        {
+          name: '验证码',
+          En: 'Verification code',
+          val: form.authCode,
+          required: true
+        },
+        {
+          name: '密码',
+          En: 'Password',
+          val: form.password,
+          required: true
+        },
+        {
+          name: '确认密码',
+          En: 'Password',
+          val: form.confirmPass,
+          required: true
+        }
+      ]
+      if (!check(checkStr)) {
+        return
+      }
+
+      if (form.password.length < 8 || form.confirmPass.length < 8) {
+        return this.$toast.show('warn', this.langToast['31'])
+      }
+
+      let country = Number(this.selectArea[0].substr(1))
+      let temp = encodeStr(Base64.encode(form.password), Base64.encode(form.confirmPass))
+
+      let params = {
+        password: temp[0],
+        phoneNum: form.phone,
+        msgAuthCode: form.authCode,
+        nickName: form.nickname,
+        country,
+        confirmPwd: temp[1],
+      }
+      let res = await this.$http({
+        method: 'post',
+        data: params,
+        url: '/sso/user/register'
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', this.langToast[response.code])
+      }
+      this.$toast.showConfirm('success', this.langToast['23'], async () => {
+        let params1 = {
+          phoneNum: form.phone,
+          password: encodeStr(Base64.encode(this.password)),
+          randomcode: '1234',
+          rememberMe: false
+        }
+        await this.$store.dispatch('login', params1)
+        if (this.token) {
+          this.$bus.$emit('hasLogin')
+          this.$router.push({name: 'information'})
+          this.$bus.$emit('hideAside')
+        }
+      }, async () => {
+        this.$bus.$emit('currentActive', 'ilogin')
+        this.$bus.$emit('hideAside')
+      })
+    }
+  }
+}
+</script>
 <style lang="scss" scoped>
 .register {
   width: 398px;
@@ -19,10 +247,111 @@
     font-size: 20px;
     letter-spacing:2px;
   }
+  .tologin {
+    text-align: right;
+    margin: 20px 0 10px;
+    font-size: 14px;
+    span {
+      font-weight: bold;
+      display: inline-block;
+      position: relative;
+      cursor: pointer;
+      &::after {
+        content: '';
+        display: block;
+        height: 2px;
+        width: 100%;
+        background: #1FE4DC;
+      }
+    }
+  }
   input {
     line-height: 42px;
     margin-bottom: 20px;
     width: 100%;
+    margin-bottom: 20px;
+    padding-left: 10px;
+    font-size: 16px;
+    border: 1px solid #909090;
+    border-radius: 3px;
+  }
+  .phone-w, .code-w {
+    display: flex;
+    border: 1px solid #909090;
+    border-radius: 3px;
+    margin-bottom: 20px;
+    line-height: 40px;
+    .phone-area {
+      padding: 0 16px 0 10px;
+      position: relative;
+      cursor: pointer;
+      width: 120px;
+      &::after {
+        content: '';
+        display: block;
+        height: 28px;
+        width: 1px;
+        background: #707070;
+        position: absolute;
+        right: 0;
+        top: 6px
+      }
+    }
+    .sanjiao {
+      display: inline-block;
+      border: 7px solid #909090;
+      border-bottom: none;
+      border-left-color: transparent;
+      border-right-color: transparent;
+      margin-left: 10px;
+    }
+    input {
+      flex: 1;
+      border: none;
+      margin-bottom: 0;
+    }
+    .send-code-btn {
+      padding: 0 10px;
+      cursor: pointer;
+      &.is-disabled {
+        color: #909090;
+        cursor: default;
+      }
+    }
+  }
+  .right-tips {
+    text-align: right;
+    font-size: 14px;
+    color: #909090;
+    margin-top: -12px;
+    margin-bottom: 20px;
+    span {
+      cursor: pointer;
+    }
+  }
+  .xieyi-w {
+    font-size: 14px;
+    margin-bottom: 15px;
+    input {
+      width: initial;
+      vertical-align: middle;
+      display: inline-block;
+      margin-bottom: 0;
+    }
+    span {
+      display: inline-block;
+      vertical-align: middle;
+    }
+  }
+  .register-btn {
+    line-height: 60px;
+    text-align: center;
+    background: #1FE4DC;
+    width: 100%;
+    font-size: 20px;
+    font-weight: bold;
+    cursor: pointer;
+    border-radius: 3px;
   }
 }
 </style>

+ 7 - 3
pc/src/page/login/index.vue

@@ -2,7 +2,8 @@
   <div class="login-page">
     <div class="login-container">
       <LoginBox v-if="page==='login'" />
-      <registerBox v-if="page === 'register'" />
+      <registerBox v-else-if="page === 'register'" />
+      <forgetBox v-else-if="page === 'forget'" />
     </div>
   </div>
 </template>
@@ -10,6 +11,7 @@
 <script>
 import LoginBox from './components/login'
 import registerBox from './components/register'
+import forgetBox from './components/forget'
 export default {
   computed: {
     page () {
@@ -18,7 +20,8 @@ export default {
   },
   components: {
     LoginBox,
-    registerBox
+    registerBox,
+    forgetBox
   }
 }
 </script>
@@ -32,7 +35,8 @@ export default {
     position: absolute;
     left: 50%;
     top: 50%;
-    transform: translate(-50%,-50%);
+    transform: translate(-50%, -50%);
+    transform: translate(-50%, calc(-50% + 40px));
     box-shadow:0px 2px 6px rgba(0,0,0,0.4);
     background-color: #fff;
   }

+ 32 - 27
pc/src/page/service/temp/app.vue

@@ -1,28 +1,32 @@
 <template>
-  <div class="app-layout">
-    <div class="logo">
-      <img :src="`${$cdn}images/app-logo.png`"  alt srcset>
-    </div>
-    <div class="info">
-      <img :src=" language==='en'?`${$cdn}images/pro-logo-en.png`:`${$cdn}images/download-pro.png`" alt srcset>
-      <h2></h2>
-      <p>{{langDownload.sub}}</p>
-
-      <div>
-        <p>
-          <a class="button">
-            <img :src="`${$cdn}images/service_icon_ios@2x.png`" >
-            <span>IOS</span>
-          </a>
-          <img class="qrcode" :src="`${$cdn}images/iosqrcode.png`" >
-        </p>
-        <p>
-          <a class="button">
-            <img :src="`${$cdn}images/service_icon_android@2x.png`">
-            <span>Android</span>
-          </a>
-          <img class="qrcode" :src="`${$cdn}images/anzhuoqrcode.png`">
-        </p>
+  <div class="app-download">
+    
+    <div class="container">
+      <div class="common-title">下载软件</div>
+      <div class="logo">
+        <img :src="`${$cdn}images/app-logo.png`"  alt srcset>
+      </div>
+      <div class="info">
+        <img :src=" language==='en'?`${$cdn}images/pro-logo-en.png`:`${$cdn}images/download-pro.png`" alt srcset>
+        <h2></h2>
+        <p>{{langDownload.sub}}</p>
+
+        <div>
+          <p>
+            <a class="button">
+              <img :src="`${$cdn}images/service_icon_ios@2x.png`" >
+              <span>App Store</span>
+            </a>
+            <img class="qrcode" :src="`${$cdn}images/iosqrcode.png`" >
+          </p>
+          <p>
+            <a class="button">
+              <img :src="`${$cdn}images/service_icon_android@2x.png`">
+              <span>Android</span>
+            </a>
+            <img class="qrcode" :src="`${$cdn}images/anzhuoqrcode.png`">
+          </p>
+        </div>
       </div>
     </div>
   </div>
@@ -43,10 +47,11 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-.app-layout {
-  max-width: 1170px;
-  margin: 52px auto 78px;
 
+.container {
+  .common-title {
+    margin: 80px 0 65px;
+  }
   .logo {
     float: left;
   }

+ 11 - 7
pc/src/page/service/temp/clause.vue

@@ -1,5 +1,7 @@
 <template>
-  <div class="use-layout" :class="language">
+  <div class="container">
+    <div class="common-title">保修条款</div>
+    <div class="use-layout" :class="language">
     <lselect :options="navs" :selected="navActive" class="select" :class="{oy: navs.length > 15}" @change="handleChange" />
 
     <template v-if="isFireFox" >
@@ -16,6 +18,7 @@
       </div>
     </template>
   </div>
+  </div>
 </template>
 
 <script>
@@ -107,18 +110,19 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-$lw: 220px;
-$cw: 430px;
+$lw: 304px;
+$cw: 480px;
 $encw: 430px;
-
+.common-title {
+  margin: 85px 0 65px;
+}
 .use-layout {
   position: relative;
-  max-width: 800px;
-  margin: 50px auto 72px;
   overflow: hidden;
   padding-left: $lw + 10px;
   padding-right: 10px;
   box-sizing: border-box;
+  padding-bottom: 120px;
   .select {
     width: $lw;
     position: absolute;
@@ -134,7 +138,7 @@ $encw: 430px;
   }
   .use-con{
     max-height: 100%;
-    height: calc(100vh - 380px);
+    height: 593px;
     width: $cw;
     overflow-y: auto;
     text-align: center;

+ 74 - 36
pc/src/page/service/temp/index.vue

@@ -1,5 +1,13 @@
 <template>
   <div class="temp-layout">
+    <div class="banner">
+      <div class="container">
+        <h1>服务支持</h1>
+        <ul>
+          <li :class="{'is-active': $route.path === item.path}" v-for="item in listItem" :key="item.name" @click="$router.push(item.path)">{{ item.name }}</li>
+        </ul>
+      </div>
+    </div>
     <div class="oper-btn" v-if="$route.params.id === 'use'">
       <a :href="`${$cdn}pdf/${language==='en'?'4DKanKan Pro Product Manual':'四维看看说明书_1.0'}.pdf`" target="_blank">
         <img :src="`${$cdn}images/use-download.png`" alt="">
@@ -19,6 +27,7 @@ import iqa from './qa'
 import iclause from './clause'
 import iproduct from './product'
 import data from './config'
+import mVideo from '../video'
 
 export default {
   computed: {
@@ -28,30 +37,29 @@ export default {
     })
   },
   data () {
-    return {active: ''}
+    return {
+      active: '',
+      listItem: [
+        {
+          name: '视频教程',
+          path: '/service/mVideo/all'
+        },
+        {
+          name: '使用教程',
+          path: '/service/use/pro'
+        },
+        {
+          name: '软件下载',
+          path: '/service/app/pro'
+        },
+        {
+          name: '保修条款',
+          path: '/service/clause/pro'
+        },
+      ]
+    }
   },
   methods: {
-    // getSplit () {
-    //   let ret = ''
-    //   switch (this.active.cp) {
-    //     case 'iapp':
-    //       ret = 145
-    //       break
-    //     case 'iclause':
-    //       ret = this.language === 'en' ? 219 : 219
-    //       break
-    //     case 'iuse':
-    //       ret = this.language === 'en' ? 359 : 219
-    //       break
-    //     case 'iqa':
-    //       ret = this.language === 'en' ? 268 : 219
-    //       break
-    //     default:
-    //       break
-    //   }
-
-    //   return this.split - ret + 'px'
-    // }
   },
   watch: {
     '$route.params': {
@@ -60,31 +68,61 @@ export default {
         if (newVal.active && newVal.active !== 'all') {
           this.active = data[newVal.id][newVal.active]
         } else {
-          this.active = data[newVal.id]
+          this.active = {
+            cp: newVal.id
+          }
         }
       }
     }
   },
-  components: {lselect, ibefore, iuse, iapp, iproduct, iclause, iqa},
+  components: {lselect, ibefore, iuse, iapp, iproduct, iclause, iqa, mVideo},
   mounted () {
   }
 }
 </script>
 
 <style lang="scss" scoped>
-  .temp-layout{
-    overflow: hidden;
-    position: relative;
-    .oper-btn{
-      position: absolute;
-      right: 50px;
-      top: 50px;
-    }
+.temp-layout{
+  overflow: hidden;
+  position: relative;
+  .oper-btn{
+    position: absolute;
+    right: 50px;
+    top: 50px;
+  }
+}
+.banner {
+  width: 100%;
+  height: 290px;
+  background: url(~@/assets/images/refactor/appDownload/banner.jpg) no-repeat center center;
+  h1 {
+    font-size: 40px;
+    font-weight: normal;
+    padding-top: 107px;
+    line-height: 50px;
+    margin-bottom: 30px;
+  }
+  ul {
+    display: flex;
   }
-   @media screen and (max-width: 1600px) {
-    .fix-layout{
-      margin-right: auto!important;
-      max-width: 900px!important;
+  li {
+    padding: 0 30px;
+    font-size: 16px;
+    color: #909090;
+    cursor: pointer;
+    font-weight: bold;
+    &:first-child {
+      padding-left: 0;
+    }
+    &.is-active, &:hover {
+      color: #202020;
     }
   }
+}
+  @media screen and (max-width: 1600px) {
+  // .fix-layout{
+  //   margin-right: auto!important;
+  //   max-width: 900px!important;
+  // }
+}
 </style>

+ 17 - 7
pc/src/page/service/temp/use.vue

@@ -1,5 +1,10 @@
 <template>
-  <div class="use-layout" :class="language">
+  <div class="container">
+    <div class="common-title">
+      使用教程
+    </div>
+  <div class="use-layout " :class="language">
+    
     <template v-if="isFireFox" >
       <div class="ls-outer">
         <lselect :options="navs" :selected="navActive" class="select firefox-select" :class="{oy: navs.length > 15}" @change="handleChange" />
@@ -23,6 +28,7 @@
     </template>
 
   </div>
+  </div>
 </template>
 
 <script>
@@ -119,9 +125,12 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-  $lw: 220px;
-  $cw: 430px;
+  $lw: 304px;
+  $cw: 480px;
   $encw: 430px;
+  .common-title {
+    margin: 85px 0 65px;
+  }
   .ls-outer{
       min-width: 220px;
       position: absolute;
@@ -152,20 +161,21 @@ export default {
 
 .use-layout {
   position: relative;
-  max-width: 800px;
-  margin: 50px auto 72px;
+  // max-width: 800px;
+  // margin: 50px auto 72px;
   overflow: hidden;
   padding-left: $lw + 10px;
   padding-right: 10px;
   box-sizing: border-box;
+  padding-bottom: 120px;
   .select {
     min-width: $lw;
     position: absolute;
     top: 0;
     left: 0;
-    max-height: 100%;
+    max-height: 590px;
     overflow-y: auto;
-    height: 100%;
+    height: 590px;
   }
 
   .firefox-select{

+ 11 - 3
pc/src/store/user.js

@@ -5,6 +5,7 @@ import Toast from '@/components/toast/toast'
 import Cookies from 'js-cookie'
 import toastZH from '@/store/language/cn/toast'
 import toastEN from '@/store/language/en/toast'
+import Api from '@/apis'
 
 Vue.use(Toast)
 
@@ -419,12 +420,12 @@ export default {
     async getAuthCode (context, item) {
       let toastCode = localStorage.getItem('language') === 'en' ? toastEN : toastZH
 
-      let {phone, code, type = ''} = item
+      let {phone, code, type = '', qudao, email} = item
       let areaNum = Number(code) || 86
 
-      if (phone) {
+      if (phone || email) {
         let resp = await http
-          .post('/sso/user/checkUser', {phoneNum: phone})
+          .post('/sso/user/checkUser', {phoneNum: phone, email})
 
         switch (type) {
           case 'resigter':
@@ -443,6 +444,13 @@ export default {
           phoneNum: Number(phone),
           areaNum
         }
+        if (qudao === 'email') {
+          params = {
+            email
+          }
+          Api.getEmailAuthCode(params)
+          return true
+        }
         http({
           method: 'post',
           data: params,