Browse Source

增加手机号登录和验证码获取资料

Limengbo 5 years ago
parent
commit
30cff6a50f
12 changed files with 319 additions and 218 deletions
  1. 0 21
      LICENSE
  2. 0 96
      README-zh.md
  3. 0 15
      README.md
  4. 1 1
      config/dev.env.js
  5. 19 0
      src/api/login.js
  6. 10 0
      src/api/table.js
  7. 3 0
      src/store/getters.js
  8. 17 1
      src/store/modules/list.js
  9. 26 1
      src/store/modules/user.js
  10. 2 2
      src/utils/validate.js
  11. 104 31
      src/views/allFile/index.vue
  12. 137 50
      src/views/login/index.vue

+ 0 - 21
LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017-present PanJiaChen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

File diff suppressed because it is too large
+ 0 - 96
README-zh.md


+ 0 - 15
README.md

@@ -1,17 +1,5 @@
-# vue-admin-template
-
-> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
-
-**Live demo:** http://panjiachen.github.io/vue-admin-template
-
-[中文文档](https://github.com/PanJiaChen/vue-admin-template/blob/master/README-zh.md)
-
-## Build Setup
 
 ```bash
-# Clone project
-git clone https://github.com/PanJiaChen/vue-admin-template.git
-
 # Install dependencies
 npm install
 
@@ -20,7 +8,4 @@ npm run dev
 
 # Build for production with minification
 npm run build
-
-# Build for production and view the bundle analyzer report
-npm run build --report
 ```

+ 1 - 1
config/dev.env.js

@@ -4,6 +4,6 @@ const prodEnv = require('./prod.env')
 
 module.exports = merge(prodEnv, {
   NODE_ENV: '"development"',
-  BASE_API: '"https://whiteboardtest.ai160.com"',
+  BASE_API: '"https://whiteboardtest.ai160.com/sharedWhiteBoard"',
   // BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
 })

+ 19 - 0
src/api/login.js

@@ -29,3 +29,22 @@ export function loginSuccess(code) {
     params: { code }
   })
 }
+// 获取登录验证码
+export function sendMag(phoneNum) {
+  return request({
+    url: `/wx/user/sendMag`,
+    method: 'get',
+    params: { phoneNum }
+  })
+}
+// 验证码登录
+export function loginByPhone(form) {
+  return request({
+    url: `/wx/user/loginByPhone`,
+    method: 'post',
+    data: {
+      'mobile': form.username,
+      'sign': form.code
+    }
+  })
+}

+ 10 - 0
src/api/table.js

@@ -61,3 +61,13 @@ export function deleteList(joinUser) {
     data: joinUser
   })
 }
+// 输入授权码获取会议资料
+export function codeFile(code) {
+  return request({
+    url: `wx/task/findByCode`,
+    method: 'get',
+    params: {
+      code
+    }
+  })
+}

+ 3 - 0
src/store/getters.js

@@ -25,6 +25,9 @@ const getters = {
       logList: state.list.logList,
       logSize: state.list.logSize
     }
+  },
+  codeList: state => {
+    return state.list.codeList
   }
 }
 export default getters

+ 17 - 1
src/store/modules/list.js

@@ -1,4 +1,4 @@
-import { joinUser, taskFile, getViewLogList } from '@/api/table'
+import { joinUser, taskFile, getViewLogList, codeFile } from '@/api/table'
 import { getToken } from '@/utils/auth'
 
 const user = {
@@ -7,6 +7,7 @@ const user = {
     joinUserList: [],
     fileList: [],
     logList: [],
+    codeList: [],
     totalSize: 0,
     logSize: 0
   },
@@ -24,6 +25,9 @@ const user = {
     },
     SET_TOTALSIZE: (state, size) => {
       state.totalSize = size
+    },
+    SET_CODELIST: (state, data) => {
+      state.codeList = [...data.localFile, ...data.screenshot]
     }
   },
 
@@ -65,6 +69,18 @@ const user = {
           reject(error)
         })
       })
+    },
+    // 输入授权码获取会议资料
+    CodeFile({ commit, state }, code) {
+      return new Promise((resolve, reject) => {
+        codeFile(code).then(response => {
+          const data = response.data.data
+          commit('SET_CODELIST', data)
+          resolve(data)
+        }).catch(error => {
+          reject(error)
+        })
+      })
     }
   }
 }

+ 26 - 1
src/store/modules/user.js

@@ -1,4 +1,4 @@
-import { logout, getInfo, loginCode, loginSuccess } from '@/api/login'
+import { logout, getInfo, loginCode, loginSuccess, sendMag, loginByPhone } from '@/api/login'
 import { getToken, removeToken } from '@/utils/auth'
 
 const user = {
@@ -99,6 +99,31 @@ const user = {
           }
         })
       })
+    },
+    // 发送手机验证码
+    sendMag({ commit }, form) {
+      return new Promise((resolve, reject) => {
+        sendMag(form.username).then(response => {
+          if (response) {
+            resolve(response)
+          } else {
+            reject('错误')
+          }
+        })
+      })
+    },
+    // 验证码登录
+    loginByPhone({ commit }, form) {
+      return new Promise((resolve, reject) => {
+        loginByPhone(form).then(response => {
+          if (response) {
+            commit('SET_LOGIN', response)
+            resolve(response)
+          } else {
+            reject('错误')
+          }
+        })
+      })
     }
   }
 }

+ 2 - 2
src/utils/validate.js

@@ -3,8 +3,8 @@
  */
 
 export function isvalidUsername(str) {
-  const valid_map = ['admin', 'editor']
-  return valid_map.indexOf(str.trim()) >= 0
+  const telStr = /^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][1,8,9]))[0-9]{8}$/
+  return telStr.test(str)
 }
 
 /* 合法uri*/

+ 104 - 31
src/views/allFile/index.vue

@@ -1,32 +1,37 @@
 <template>
   <div class="app-container">
-    <el-button :disabled="delect" class="btn" type="primary" @click="deleteList">删除</el-button>
-    <el-table
-      ref="multipleTable"
-      :data="joinUserList"
-      :row-class-name="tableRowClassName"
-      tooltip-effect="dark"
-      style="width: 100%"
-      @selection-change="handleSelectionChange"
-      @row-click="detail">
-      <el-table-column
-        :selectable="select"
-        type="selection"
-        width="55"/>
-      <el-table-column
-        :label=" '选中' +multipleSelection.length.toString() + '文件/文件夹'">
-        <template slot-scope="scope">
-          <img src="@/icons/image/file_icon.png" alt="file_icon" style="vertical-align: middle; margin-right: 10px">
-          <span>{{ scope.row.task.title }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="日期"
-        width="160"
-        show-overflow-tooltip>
-        <template slot-scope="scope">{{ scope.row.task.gmtCreated }}</template>
-      </el-table-column>
-    </el-table>
+    <div class="empower">
+      <el-input v-model="input" placeholder="输入授权码获取最新会议资料" @keyup.enter.native="findByCode" />
+      <el-button v-if="joinUserList.length !== 0" :disabled="delect" class="btn" type="primary" @click="deleteList">删除</el-button>
+    </div>
+    <div v-if="joinUserList.length !== 0">
+      <el-table
+        ref="multipleTable"
+        :data="joinUserList"
+        :row-class-name="tableRowClassName"
+        tooltip-effect="dark"
+        style="width: 100%"
+        @selection-change="handleSelectionChange"
+        @row-click="detail">
+        <el-table-column
+          :selectable="select"
+          type="selection"
+          width="55"/>
+        <el-table-column
+          :label=" '选中' +multipleSelection.length.toString() + '文件/文件夹'">
+          <template slot-scope="scope">
+            <img src="@/icons/image/file_icon.png" alt="file_icon" style="vertical-align: middle; margin-right: 10px">
+            <span>{{ scope.row.task.title }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="日期"
+          width="160"
+          show-overflow-tooltip>
+          <template slot-scope="scope">{{ scope.row.task.gmtCreated }}</template>
+        </el-table-column>
+      </el-table>
+    </div>
     <div v-if="joinUserList.length !== 0" class="page">
       <el-pagination
         :total="totalSize"
@@ -35,7 +40,36 @@
         @size-change="handleSizeChange"
         @current-change="handleCurrentChange"/>
     </div>
-
+    <div v-if="codeList.length !== 0">
+      <el-table
+        ref="multipleTable"
+        :data="codeList"
+        tooltip-effect="dark"
+        style="width: 100%"
+        @selection-change="handleSelectionChange">
+        <el-table-column
+          type="selection"
+          width="55"/>
+        <el-table-column
+          label="资料">
+          <template slot-scope="scope">
+            <img :src="(scope.row.fileType == 'png' || scope.row.fileType == 'jpg') ? scope.row.path : imgUrl(scope.row)" alt="file_icon" style="vertical-align: middle; margin-right: 10px">
+            <span>{{ scope.row.fileName }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="日期"
+          width="160"
+          show-overflow-tooltip>
+          <template slot-scope="scope">{{ scope.row.gmtCreated }}</template>
+        </el-table-column>
+        <el-table-column
+          label="操作"
+          width="80">
+          <template slot-scope="scope"><i class="el-icon-download" @click="detailUpload(scope.row)"/></template>
+        </el-table-column>
+      </el-table>
+    </div>
   </div>
 </template>
 
@@ -43,18 +77,21 @@
 import { mapGetters } from 'vuex'
 import { parseTime } from '@/utils/index'
 import { deleteList } from '@/api/table'
+import { addViewLog } from '@/api/table'
 
 export default {
   data() {
     return {
       multipleSelection: [],
-      delect: true
+      delect: true,
+      input: ''
     }
   },
   computed: {
     ...mapGetters([
       'joinUserList',
-      'totalSize'
+      'totalSize',
+      'codeList'
     ])
   },
   created() {
@@ -130,12 +167,48 @@ export default {
         return false
       }
       return true
+    },
+    findByCode() {
+      if (!this.input) {
+        alert('请输入授权码')
+        return false
+      }
+      this.$store.dispatch('CodeFile', this.input).then((res) => {
+        // 格式化时间和文件格式
+        this.codeList.forEach((item, index) => {
+          this.codeList[index].gmtCreated = parseTime(item.gmtCreated)
+          this.codeList[index].fileType = item.path.slice(item.path.lastIndexOf('.') + 1)
+        })
+      })
+    },
+    detailUpload(row) {
+      const link = document.createElement('a')
+      link.style.display = 'none'
+      link.href = `https://whiteboardtest.ai160.com/download?path=${row.path}&fileName=${row.fileName}`
+      link.setAttribute('download', 'excel.xlsx')
+      document.body.appendChild(link)
+      link.click()
+      addViewLog(row.id, row.taskId)
+    },
+    imgUrl(url) {
+      if (url.fileType) {
+        return require(`@/assets/fileimg/${url.fileType}.png`)
+      }
     }
   }
 }
 </script>
 
-<style>
+<style rel="stylesheet/scss" lang="scss" scoped>
+.empower {
+  display: flex;
+  justify-content: space-between;
+  .el-input {
+    height: 47px;
+    width: 400px;
+  }
+}
+
 .line{
   text-align: center;
 }

+ 137 - 50
src/views/login/index.vue

@@ -1,33 +1,72 @@
 <template>
   <div :style="bg" class="login-container">
-    <div class="code">
+    <!-- <div class="code">
       <span>微信扫一扫登录</span>
       <img :src="code" class="code-img">
-    </div>
+    </div> -->
+    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" label-position="left">
+      <h3 class="title">手机号码登录</h3>
+      <p class="tips">手机号码登录,未注册将自动创建智能白板账号</p>
+      <el-form-item prop="username">
+        <el-input v-model="loginForm.username" name="username" type="text" placeholder="手机号" />
+      </el-form-item>
+      <el-form-item prop="code">
+        <el-input
+          v-model="loginForm.code"
+          name="code"
+          type="text"
+          placeholder="验证码"
+          @keyup.enter.native="handleLogin" />
+        <el-button :disabled="flag" type="primary" @click.native.prevent="handleCode">{{ msg }}</el-button>
+      </el-form-item>
+      <el-form-item>
+        <el-button :loading="loading" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
+          登录
+        </el-button>
+      </el-form-item>
+    </el-form>
   </div>
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+// import { mapGetters } from 'vuex'
 import { setToken } from '@/utils/auth'
+import { isvalidUsername } from '@/utils/validate'
 
 export default {
   name: 'Login',
   data() {
+    const validateUsername = (rule, value, callback) => {
+      if (!isvalidUsername(value)) {
+        callback(new Error('请输入正确的手机号'))
+      } else {
+        callback()
+      }
+    }
     return {
+      loginForm: {
+        username: '',
+        code: ''
+      },
+      loginRules: {
+        username: [{ required: true, trigger: 'blur', validator: validateUsername }]
+      },
       loading: false,
-      pwdType: 'password',
       redirect: undefined,
+      flag: false,
+      time: 10,
+      msg: '获取验证码',
       bg: {
         backgroundImage: 'url(' + require('@/assets/bg.jpg') + ')'
       }
     }
   },
-  computed: {
-    ...mapGetters([
-      'code'
-    ])
-  },
+  // 获取二维码暂时注释改为手机号登录 需要的话可以打开
+  // computed: {
+  //   ...mapGetters([
+  //     'code'
+  //   ])
+  // },
   watch: {
     $route: {
       handler: function(route) {
@@ -36,24 +75,78 @@ export default {
       immediate: true
     }
   },
-  created() {
-    this.getLogincode()
-  },
   methods: {
-    getLogincode() {
-      this.$store.dispatch('LoginCode').then(() => {
-        this.queryLogin()
+    // 获取二维码暂时注释改为手机号登录 需要的话可以打开
+    // getLogincode() {
+    //   this.$store.dispatch('LoginCode').then(() => {
+    //     this.queryLogin()
+    //   })
+    // },
+    // queryLogin() {
+    //   setTimeout(() => {
+    //     this.$store.dispatch('loginSuccess').then(res => { // 拉取用户信息
+    //       setToken(res.data.id)
+    //       this.$router.push({ path: this.redirect || '/' })
+    //     }).catch(() => {
+    //       this.queryLogin()
+    //     })
+    //   }, 5000)
+    // },
+    // showPwd() {
+    //   if (this.pwdType === 'password') {
+    //     this.pwdType = ''
+    //   } else {
+    //     this.pwdType = 'password'
+    //   }
+    // },
+    handleCode() {
+      this.$refs.loginForm.validate(valid => {
+        if (valid && (!this.flag)) {
+          this.$store.dispatch('sendMag', this.loginForm).then(() => {
+            this.countDown()
+          }).catch(() => {
+
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
       })
     },
-    queryLogin() {
+    handleLogin() {
+      if (!this.loginForm.code) {
+        alert('输入验证码')
+        return false
+      }
+      this.$refs.loginForm.validate(valid => {
+        if (valid) {
+          this.loading = true
+          this.$store.dispatch('loginByPhone', this.loginForm).then((res) => {
+            this.loading = false
+            setToken(res.data.id)
+            this.$router.push({ path: this.redirect || '/' })
+          }).catch(() => {
+            this.loading = false
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    countDown() {
       setTimeout(() => {
-        this.$store.dispatch('loginSuccess').then(res => { // 拉取用户信息
-          setToken(res.data.id)
-          this.$router.push({ path: this.redirect || '/' })
-        }).catch(() => {
-          this.queryLogin()
-        })
-      }, 5000)
+        this.time--
+        if (this.time > 0) {
+          this.flag = true
+          this.msg = `${this.time}秒后重新发送`
+          this.countDown()
+        } else {
+          this.flag = false
+          this.msg = `获取验证码`
+          this.time = 10
+        }
+      }, 1000)
     }
   }
 }
@@ -78,7 +171,6 @@ $light_gray:#eee;
       color: $light_gray;
       height: 47px;
       &:-webkit-autofill {
-        -webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
         -webkit-text-fill-color: #fff !important;
       }
     }
@@ -88,6 +180,9 @@ $light_gray:#eee;
     background: rgba(0, 0, 0, 0.1);
     border-radius: 5px;
     color: #454545;
+    .el-form-item__content {
+      display: flex;
+    }
   }
 }
 
@@ -114,12 +209,6 @@ $light_gray:#eee;
   .tips {
     font-size: 14px;
     color: #fff;
-    margin-bottom: 10px;
-    span {
-      &:first-of-type {
-        margin-right: 16px;
-      }
-    }
   }
   .svg-container {
     padding: 6px 5px 6px 15px;
@@ -132,8 +221,6 @@ $light_gray:#eee;
     font-size: 26px;
     font-weight: 400;
     color: $light_gray;
-    margin: 0px auto 40px auto;
-    text-align: center;
     font-weight: bold;
   }
   .show-pwd {
@@ -145,23 +232,23 @@ $light_gray:#eee;
     cursor: pointer;
     user-select: none;
   }
-  .code {
-    position: absolute;
-    right: 222px;
-    top: 50%;
-    margin-top: -171px;
-    width: 320px;
-    height: 342px;
-    background: rgba(255,255,255,1);
-    border-radius: 5px;
-    text-align: center;
-    padding-top: 20px;
-    box-sizing: border-box;
-    .code-img {
-      width:218px;
-      height: 218px;
-      margin: 20px 0;
-    }
-  }
+  // .code {
+  //   position: absolute;
+  //   right: 222px;
+  //   top: 50%;
+  //   margin-top: -171px;
+  //   width: 320px;
+  //   height: 342px;
+  //   background: rgba(255,255,255,1);
+  //   border-radius: 5px;
+  //   text-align: center;
+  //   padding-top: 20px;
+  //   box-sizing: border-box;
+  //   .code-img {
+  //     width:218px;
+  //     height: 218px;
+  //     margin: 20px 0;
+  //   }
+  // }
 }
 </style>