소스 검색

换绑接口的对接

pujiaming 2 년 전
부모
커밋
e008f1c14d

+ 28 - 0
src/api/index.ts

@@ -156,4 +156,32 @@ export const userNcoin = <T>(params:T) => {
         method: 'get',
         params
     })
+}
+export const unbindCaptcha = <T>(params?:T) => {
+    return request({
+        url: '/user/unbind_captcha',
+        method: 'get',
+        params
+    })
+}
+export const clearMobile = <T>(data:T) => {
+    return request({
+        url: '/user/clear_mobile',
+        method: 'post',
+        data
+    })
+}
+export const bindCaptcha = <T>(data:T) => {
+    return request({
+        url: '/user/bind_captcha',
+        method: 'post',
+        data
+    })
+}
+export const bindMobile = <T>(data:T) => {
+    return request({
+        url: '/user/bind_mobile',
+        method: 'post',
+        data
+    })
 }

+ 11 - 3
src/components/MobileCom.vue

@@ -17,9 +17,9 @@
             <!-- <van-icon name="apps-o" size="26" /> -->
             <van-dropdown-menu class="psa" style="left: 30px;">
                 <van-dropdown-item ref="item">
-                    <van-cell class="menu_title" v-for="item in menuPath" :key="item" :title="item.text"
+                    <van-cell class="menu_title" v-for="item in user.menuPath" :key="item" :title="item.text"
                         @click="toPath(item.url)"></van-cell>
-                    <van-cell title="密码设置" @click="setPwd"></van-cell>
+                    <van-cell title="设置" @click="setPwd"></van-cell>
                     <van-cell v-if="hasToken" title="退出登录" @click="logOut"></van-cell>
                 </van-dropdown-item>
             </van-dropdown-menu>
@@ -28,12 +28,14 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue';
+import { ref, onMounted } from 'vue';
 import { useRouter } from 'vue-router';
+import { useStore } from '@/store/index'
 
 const router = useRouter()
 const hasToken = ref(localStorage.getItem('token'))
 const item:any = ref(null)
+const user = useStore('user')
 
 const menuPath: any = ref([
     { text: '首页', value: 1, url: 'm_index' },
@@ -53,6 +55,12 @@ const logOut = () => {
 const setPwd = () => {
     router.push({ path: 'm_reset' })
 }
+onMounted(() => {
+  let token = localStorage.getItem('token')
+    if(token){
+        user.getUserProfile()
+    }  
+})
 </script>
 
 <style lang="scss" scoped>

+ 24 - 12
src/router/index.ts

@@ -89,37 +89,37 @@ const routes:Array<RouteRecordRaw> = [
     ]
   },
   {
-    path: '/order',
+    path: '/p_order',
     name: 'order',
     component: Layout,
     meta: { type: 'pc', title:'订单' },
     children: [
       {
-        path: '/order',
+        path: '/p_order',
         component: () => import('@/view/p_views/order/index.vue')
       }
     ]
   },
   {
-    path: '/ecoin',
+    path: '/p_ecoin',
     name: 'ecoin',
     component: Layout,
     meta: { type: 'pc', title:'订单' },
     children: [
       {
-        path: '/ecoin',
+        path: '/p_ecoin',
         component: () => import('@/view/p_views/ecoin/index.vue')
       }
     ]
   },
   {
-    path: '/ncoin',
+    path: '/p_ncoin',
     name: 'ncoin',
     component: Layout,
     meta: { type: 'pc', title:'订单' },
     children: [
       {
-        path: '/ncoin',
+        path: '/p_ncoin',
         component: () => import('@/view/p_views/ncoin/index.vue')
       }
     ]
@@ -181,12 +181,24 @@ const routes:Array<RouteRecordRaw> = [
     meta: { type: 'mobile', title:'密码设置' },
     component: () => import('@/view/m_views/resetPwd/resetPwd.vue')
   },
-  // {
-  //   path: '/m_reset',
-  //   name: 'm_reset',
-  //   meta: { type: 'mobile', title:'订单' },
-  //   component: () => import('@/view/m_views/resetPwd/resetPwd.vue')
-  // }
+  {
+    path: '/m_order',
+    name: 'm_order',
+    meta: { type: 'mobile', title:'订单' },
+    component: () => import('@/view/m_views/order/index.vue')
+  },
+  {
+    path: '/m_ecoin',
+    name: 'm_ecoin',
+    meta: { type: 'mobile', title:'青雀币' },
+    component: () => import('@/view/m_views/ecoin/index.vue')
+  },
+  {
+    path: '/m_ncoin',
+    name: 'm_ncoin',
+    meta: { type: 'mobile', title:'新币' },
+    component: () => import('@/view/m_views/ncoin/index.vue')
+  }
 ]
 
 

+ 20 - 5
src/store/user.ts

@@ -13,9 +13,15 @@ const userInfo = defineStore({
             { id: 0, path: '/p_index', title: '首页' },
             // { id: 1, path: '/p_rank', title: '排行' },
             { id: 2, path: '/p_categroy', title: '分类' },
-            { id: 4, path: '/order', title: '订单' },
+            { id: 4, path: '/p_order', title: '订单' },
             { id: 3, path: '/p_mine', title: '我的' }
-        ] as {id:number,path:string,title:string}[]
+        ] as {id:number,path:string,title:string}[],
+        menuPath:[
+            { text: '首页', value: 1, url: 'm_index' },
+            // { text: '排行', value: 2, url: 'm_rank' },
+            { text: '分类', value: 3, url: 'm_categroy' },
+            { text: '我的游戏', value: 4, url: 'm_mine' },
+        ]
     }),
     actions: {
         setUerInfo(data: any) {
@@ -34,11 +40,20 @@ const userInfo = defineStore({
                     { id: 0, path: '/p_index', title: '首页' },
                     // { id: 1, path: '/p_rank', title: '排行' },
                     { id: 2, path: '/p_categroy', title: '分类' },
-                    { id: 4, path: '/order', title: '订单' },
-                    { id: 5, path: '/ecoin', title: this.profile.ecoinName },
-                    { id: 6, path: '/ncoin', title: this.profile.ncoinName },
+                    { id: 4, path: '/p_order', title: '订单' },
+                    { id: 5, path: '/p_ecoin', title: this.profile.ecoinName },
+                    { id: 6, path: '/p_ncoin', title: this.profile.ncoinName },
                     { id: 3, path: '/p_mine', title: '我的' }
                 ]
+                this.menuPath = [
+                    { text: '首页', value: 1, url: 'm_index' },
+                    // { text: '排行', value: 2, url: 'm_rank' },
+                    { text: '分类', value: 3, url: 'm_categroy' },
+                    { text: '订单', value: 5, url: 'm_order' },
+                    { text: this.profile.ecoinName, value: 6, url: 'm_ecoin' },
+                    { text: this.profile.ncoinName, value: 7, url: 'm_ncoin' },
+                    { text: '我的游戏', value: 4, url: 'm_mine' },
+                ]
             }).catch((error) => {
                 console.log(error)
             })

+ 123 - 0
src/view/m_views/ecoin/index.vue

@@ -0,0 +1,123 @@
+<template>
+    <m_header></m_header>
+    <div v-if="token">
+        <div v-if="gameHot.length > 0">
+            <el-table :data="gameHot" style="width: 100%">
+            <el-table-column prop="game_name" label="游戏名称"  />
+           
+            <el-table-column prop="total_ecoin" label="余额" />
+            <el-table-column prop="created_at" label="创建时间" width="180" />
+            <el-table-column prop="modified_at" label="修改时间" width="180" />
+        </el-table>
+            <div class="demo-pagination-block">
+                <el-pagination
+                    v-model:current-page="pageConfig.page"
+                    hide-on-single-page
+                    v-model:page-size="pageConfig.pagesize"
+                    layout="prev, pager, next, jumper,total"
+                    :total="pageConfig.total"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+        </div>
+        <van-empty v-else description="No Data" />
+    </div>
+    <div v-else :style="{ height: viewWidth + 'px' }" class="df fdc aic jcc">
+        <van-empty>
+            <van-button color="#ed8c0f" @click="goLogin">去登录 &gt;&gt;</van-button>
+        </van-empty>
+    </div>
+   
+    <van-back-top style="background-color: #ed8c0f;" />
+    <!-- <m_footer></m_footer> -->
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, reactive } from 'vue'
+import { userEcoin } from '@/api/index'
+import Message from '@/utils/Message'
+import IndexList from '@/components/IndexList.vue'
+import {parseTime } from '@/utils/index'
+
+const gameHot: any = ref([])
+const gameRecommand: any = ref([])
+const prefix = ref<string>('')
+const isLoading = ref<boolean>(true)
+const viewWidth = ref<number>(document.documentElement.clientHeight - 80)
+const token = ref<string | null>(localStorage.getItem('token'))
+
+const pageConfig = reactive({
+    page: 1,
+    pagesize: 10,
+    total: 0
+})
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`)
+  pageConfig.page = val
+}
+const status = ref<any[]>([])
+const getTableData = async() => {
+   const params = {
+    page:pageConfig.page,
+    pagesize: pageConfig.pagesize
+   }
+   await userEcoin(params).then(res => {
+        console.log('热门游戏', res.data);
+        if (res.data.code === 200 && res.data.data) {
+            gameHot.value = res.data.data.lists || []
+            isLoading.value = false
+            pageConfig.total = res.data.data.total.total || 0
+            status.value = res.data.data.status
+        }
+    }).catch(err => {
+        console.log(err);
+        
+        Message.error(err.data.msg)
+    })
+}
+onMounted(async() => {
+    getTableData()
+})
+const goLogin = () => {
+    router.push({ path: 'm_login' })
+}
+
+</script>
+
+<style scoped lang="scss">
+.game_list {
+    box-sizing: border-box;
+    padding: 20px;
+    background-color: #fff;
+    margin: 0 auto 20px;
+
+    h3 {
+        font-size: 22px;
+        font-weight: normal;
+        height: 30px;
+    }
+}
+
+.more {
+    margin: 20px auto 0;
+    height: 60px;
+    background-color: #f7f7f7;
+
+    .el-button {
+        width: 100px;
+        height: 40px;
+        background-color: transparent;
+        color: #323332;
+        border: 1px solid #c7c7c7;
+    }
+}
+.title-length{
+    // flex: ;
+}
+
+</style>
+<style>
+.value-length{
+    flex: 2!important;
+}
+</style>

+ 126 - 0
src/view/m_views/ncoin/index.vue

@@ -0,0 +1,126 @@
+<template>
+    <m_header></m_header>
+    <div v-if="token">
+        <div v-if="gameHot.length > 0">
+            <el-table :data="gameHot" style="width: 100%">
+            <el-table-column prop="game_name" label="游戏名称"  />
+           
+            <el-table-column prop="total_coin" label="余额" />
+            <el-table-column prop="created_at" label="创建时间" width="180" />
+            <el-table-column prop="modified_at" label="修改时间" width="180" />
+        </el-table>
+            <div class="demo-pagination-block">
+                <el-pagination
+                    v-model:current-page="pageConfig.page"
+                    hide-on-single-page
+                    v-model:page-size="pageConfig.pagesize"
+                    layout="prev, pager, next, jumper,total"
+                    :total="pageConfig.total"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+        </div>
+        <van-empty v-else description="No Data" />
+    </div>
+    <div v-else :style="{ height: viewWidth + 'px' }" class="df fdc aic jcc">
+        <van-empty>
+            <van-button color="#ed8c0f" @click="goLogin">去登录 &gt;&gt;</van-button>
+        </van-empty>
+    </div>
+   
+    <van-back-top style="background-color: #ed8c0f;" />
+    <!-- <m_footer></m_footer> -->
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, reactive } from 'vue'
+import { userNcoin } from '@/api/index'
+import Message from '@/utils/Message'
+import {parseTime } from '@/utils/index'
+import { useStore } from '@/store/index'
+import { useRouter } from 'vue-router'
+
+
+const token = ref<string | null>(localStorage.getItem('token'))
+const user = useStore('user')
+const router = useRouter()
+
+const gameHot: any = ref([])
+const gameRecommand: any = ref([])
+const prefix = ref<string>('')
+const isLoading = ref<boolean>(true)
+const viewWidth = ref<number>(document.documentElement.clientHeight - 80)
+const pageConfig = reactive({
+    page: 1,
+    pagesize: 10,
+    total: 0
+})
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`)
+  pageConfig.page = val
+}
+const getTableData = async() => {
+   const params = {
+    page:pageConfig.page,
+    pagesize: pageConfig.pagesize
+   }
+   await userNcoin(params).then(res => {
+        console.log('热门游戏', res.data);
+        if (res.data.code === 200 && res.data.data) {
+            gameHot.value = res.data.data.lists || []
+            isLoading.value = false
+            pageConfig.total = res.data.data.total || 0
+        }
+    }).catch(err => {
+        console.log(err);
+        
+        Message.error(err.data.msg)
+    })
+}
+onMounted(async() => {
+    getTableData()
+})
+const goLogin = () => {
+    router.push({ path: 'm_login' })
+}
+
+
+</script>
+
+<style scoped lang="scss">
+.game_list {
+    box-sizing: border-box;
+    padding: 20px;
+    background-color: #fff;
+    margin: 0 auto 20px;
+
+    h3 {
+        font-size: 22px;
+        font-weight: normal;
+        height: 30px;
+    }
+}
+
+.more {
+    margin: 20px auto 0;
+    height: 60px;
+    background-color: #f7f7f7;
+
+    .el-button {
+        width: 100px;
+        height: 40px;
+        background-color: transparent;
+        color: #323332;
+        border: 1px solid #c7c7c7;
+    }
+}
+.title-length{
+    // flex: ;
+}
+
+</style>
+<style>
+.value-length{
+    flex: 2!important;
+}
+</style>

+ 155 - 0
src/view/m_views/order/index.vue

@@ -0,0 +1,155 @@
+<template>
+    <m_header></m_header>
+    <div v-if="token">
+        <div v-if="gameHot.length > 0">
+            <el-table :data="gameHot" style="width: 100%">
+                <el-table-column prop="order_number" label="订单号" width="180"/>
+                <el-table-column prop="appname" label="游戏名称"  />
+                <el-table-column prop="game_product_name" label="道具名称"  />
+                <el-table-column prop="order_amount" label="道具数量" />
+                <el-table-column prop="order_submit_time" label="创建时间" width="180">
+                    <template #default="scope">
+                        <div>
+                            {{ parseTime(scope.row.order_submit_time) }}
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="order_asynch_time" label="付款时间" width="180">
+                    <template #default="scope">
+                        <div>
+                            {{ scope.row.order_asynch_time? parseTime(scope.row.order_asynch_time):'-' }}
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="channel_name" label="支付方式" />
+                <el-table-column prop="order_submit_time" label="订单状态" >
+                    <template #default="scope">
+                        <div>
+                            {{ status[scope.row.order_status] }}
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="target_role_id" label="游戏订单号" width="180"/>
+                <el-table-column prop="out_trade_no" label="支付平台订单号" width="180" />
+            </el-table>
+            <div class="demo-pagination-block">
+                <el-pagination
+                    v-model:current-page="pageConfig.page"
+                    hide-on-single-page
+                    v-model:page-size="pageConfig.pagesize"
+                    layout="prev, pager, next, jumper,total"
+                    :total="pageConfig.total"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+        </div>
+        <van-empty v-else description="No Data" />
+    </div>
+    <div v-else :style="{ height: viewWidth + 'px' }" class="df fdc aic jcc">
+        <van-empty>
+            <van-button color="#ed8c0f" @click="goLogin">去登录 &gt;&gt;</van-button>
+        </van-empty>
+    </div>
+   
+    <van-back-top style="background-color: #ed8c0f;" />
+    <!-- <m_footer></m_footer> -->
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, reactive } from 'vue'
+import { useRouter, useRoute } from 'vue-router'
+import Message from '@/utils/Message'
+import { useStore } from '@/store/index'
+import { showSuccessToast, showFailToast } from 'vant';
+import { userOrder } from '@/api/index'
+import {parseTime } from '@/utils/index'
+
+const router = useRouter()
+const route = useRoute()
+
+const mineGame: any = ref([])
+const total = ref<number>(0)
+const userAccount = ref<string | null>(localStorage.getItem('account'))
+const token = ref<string | null>(localStorage.getItem('token'))
+const user = useStore('user')
+
+const gameHot: any = ref([])
+const gameRecommand: any = ref([])
+const prefix = ref<string>('')
+const isLoading = ref<boolean>(true)
+const viewWidth = ref<number>(document.documentElement.clientHeight - 80)
+const pageConfig = reactive({
+    page: 1,
+    pagesize: 10,
+    total: 0
+})
+const handleCurrentChange = (val: number) => {
+  console.log(`current page: ${val}`)
+  pageConfig.page = val
+}
+const status = ref<any[]>([])
+const getTableData = async() => {
+   const params = {
+    page:pageConfig.page,
+    pagesize: pageConfig.pagesize
+   }
+   await userOrder(params).then(res => {
+        console.log('热门游戏', res.data);
+        if (res.data.code === 200 && res.data.data) {
+            gameHot.value = res.data.data.lists || []
+            isLoading.value = false
+            pageConfig.total = res.data.data.total.total || 0
+            status.value = res.data.data.status
+        }
+    }).catch(err => {
+        console.log(err);
+        
+        Message.error(err.data.msg)
+    })
+}
+const goLogin = () => {
+    router.push({ path: 'm_login' })
+}
+onMounted(async() => {
+    getTableData()
+})
+
+</script>
+
+<style scoped lang="scss">
+.game_list {
+    box-sizing: border-box;
+    padding: 20px;
+    background-color: #fff;
+    margin: 0 auto 20px;
+
+    h3 {
+        font-size: 22px;
+        font-weight: normal;
+        height: 30px;
+    }
+}
+
+.more {
+    margin: 20px auto 0;
+    height: 60px;
+    background-color: #f7f7f7;
+
+    .el-button {
+        width: 100px;
+        height: 40px;
+        background-color: transparent;
+        color: #323332;
+        border: 1px solid #c7c7c7;
+    }
+}
+.title-length{
+    // flex: ;
+}
+
+</style>
+<style>
+.value-length{
+    flex: 2!important;
+}
+</style>

+ 113 - 5
src/view/m_views/resetPwd/resetPwd.vue

@@ -33,7 +33,7 @@
             />
           </van-cell-group>
           <div style="margin: 16px;display: flex;flex-direction: row-reverse;">
-            <van-button round block type="primary" color="#ed8c0f" native-type="submit">
+            <van-button style="width: 100%;padding: 10px;" round block type="primary" color="#ed8c0f" native-type="submit">
               提交
             </van-button>
           </div>
@@ -51,26 +51,54 @@
             :rules="[{ required: true, message: '请填写用户名',trigger: 'onBlur' },{ pattern: pattern, message: '请输入以字母为开头,长度为6-20位的用户名'}]"
           />
           <div v-if="!user.profile.user_name" style="margin: 16px;display: flex;flex-direction: row-reverse;">
-            <van-button round block type="primary" color="#ed8c0f" native-type="submit">
+            <van-button round block style="width: 100%;padding: 10px;" type="primary" color="#ed8c0f" native-type="submit">
               提交
             </van-button>
           </div>
         </van-form>
       </van-tab>
+      <van-tab title="手机号绑定">
+        <van-form>
+          <van-field
+            v-model="ruleForm3.mobile"
+            type="text"
+            name="手机号"
+            :readonly="!!user.profile.mobile"
+            label="手机号"
+            placeholder="请填写手机号"
+            :rules="[{ required: true, message: '请填写手机号',trigger: 'onBlur' },{ pattern: pattern2, message: '请输入正确手机号'}]"
+          />
+          <van-field  v-model="ruleForm3.captcha" type="number" name="验证码"
+                    label="验证码" placeholder="请输入验证码" :rules="[{ required: true, message: '请填写验证码' }]">
+              <template #button>
+                  <van-button v-if="!!user.profile.mobile" color="#ed8c0f" size="small" type="primary" style="width: 20vw;" :disabled="!can_send" @click="getCaptcha">{{ smsMessage }}</van-button>
+                  <van-button v-else size="small" color="#ed8c0f" type="primary" style="width: 20vw;" :disabled="!can_send" @click="getCaptcha2">{{ smsMessage }}</van-button>
+              </template>
+          </van-field>
+          <div style="margin: 16px;">
+            <van-button v-if="!!user.profile.mobile" style="width: 100%;padding: 10px;" round block type="primary" color="#ed8c0f" @click="onSubmit3">
+              解绑
+            </van-button>
+            <van-button v-else round block type="primary" style="width: 100%;padding: 10px;" color="#ed8c0f" @click="onSubmit4">
+              绑定
+            </van-button>
+          </div>
+        </van-form>
+      </van-tab>
     </van-tabs>
     
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed, inject } from 'vue'
+import { ref, reactive, onMounted, computed, onBeforeUnmount } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 import { showSuccessToast, showFailToast } from 'vant';
 import type { FormInstance, FormRules } from 'element-plus'
-import {resetPassword,setPassword, userAccount } from '@/api/index'
+import {resetPassword,setPassword, userAccount, unbindCaptcha, clearMobile, bindCaptcha, bindMobile } from '@/api/index'
 import Message from '@/utils/Message'
 import { useStore } from '@/store/index'
-
+import { ElMessage, ElMessageBox } from 'element-plus'
 const user = useStore('user')
 
 const router = useRouter()
@@ -131,14 +159,94 @@ const onSubmit2 = async() => {
   })
 }
 const pattern = ref<RegExp>(/^[a-zA-Z][a-zA-Z0-9]{5,19}$/)
+const pattern2 = ref<RegExp>(/^(?:(?:\+|00)86)?1[3-9]\d{9}$/)
 const from = ref<1 | 2>(1)
 const account = ref<string>('')
+
+const ruleForm3 = reactive({
+  mobile: '',
+  captcha: '',
+})
+const can_send = ref<boolean>(true)
+const smsMessage = ref<'获取验证码' | number>('获取验证码')
+const VALID = 60
+let interval
+const settimes = () => {
+    const setTimeFn = () => {
+        (smsMessage.value as number)--
+        if (smsMessage.value as number < 0 || can_send.value === true) {
+            clearInterval(interval)
+            can_send.value = true
+            smsMessage.value = '获取验证码'
+        }
+    }
+    interval = setInterval(function() {
+        setTimeFn()
+    }, 1000)
+}
+const getCaptcha = async() => {
+  await unbindCaptcha().then((res) => {
+      console.log(res)
+      can_send.value = false
+      smsMessage.value = VALID
+      settimes()
+      showSuccessToast('验证码已发送,请注意查收')
+  }).catch((error) => {
+      console.log(error)
+      showFailToast(error.data.msg)
+
+  })
+}
+const getCaptcha2 = async() => {
+  await bindCaptcha({mobile:ruleForm3.mobile}).then((res) => {
+      console.log(res)
+      can_send.value = false
+      smsMessage.value = VALID
+      settimes()
+      showSuccessToast('验证码已发送,请注意查收')
+  }).catch((error) => {
+      console.log(error)
+      showFailToast(error.data.msg)
+  })
+}
+const onSubmit3 = async() => {
+  await clearMobile({captcha: ruleForm3.captcha}).then(async(res) => {
+    console.log(res)
+    showSuccessToast(res.data.msg)
+    await user.getUserProfile()
+    ruleForm3.mobile = user.profile.mobile
+    ruleForm3.captcha = ''
+    clearInterval(interval)
+    smsMessage.value = '获取验证码'
+    can_send.value = true
+  }).catch((error) => {
+    console.log(error)
+    showFailToast(error.data.msg)
+  })
+}
+const onSubmit4 = async() => {
+  await bindMobile({mobile:ruleForm3.mobile, captcha: ruleForm3.captcha}).then(async(res) => {
+    console.log(res)
+    showSuccessToast(res.data.msg)
+    await user.getUserProfile()
+    ruleForm3.mobile = user.profile.mobile
+    ruleForm3.captcha = ''
+    clearInterval(interval)
+    smsMessage.value = '获取验证码'
+    can_send.value = true
+  }).catch((error) => {
+    console.log(error)
+    showFailToast(error.data.msg)
+  })
+}
 onMounted(async()=>{
   from.value = parseInt(localStorage.getItem('from') as string)as 1 | 2
   await user.getUserProfile()
   account.value = user.profile?.user_name
+  ruleForm3.mobile = user.profile.mobile
 })
 
+
 </script>
 
 

+ 15 - 7
src/view/p_views/login/index.vue

@@ -13,7 +13,7 @@
             </el-tabs>
             <template v-if="login_typ === 'pwd'">
                 <el-form-item label="用户名" prop="account">
-                <el-input v-model="loginForm.account" type="text" placeholder="请输入账号" clearable :prefix-icon="User" />
+                    <el-input v-model="loginForm.account" type="text" placeholder="请输入账号" clearable :prefix-icon="User" />
                 </el-form-item>
                 <el-form-item label="密&emsp;码" prop="password">
                     <el-input v-model="loginForm.password" type="password" show-password placeholder="请输入密码"
@@ -163,12 +163,20 @@ const resetForm = (formEl: FormInstance | undefined) => {
     if (!formEl) return
     formEl.resetFields()
 }
-const getCaptcha = () => {
-   can_send.value = false
-   smsMessage.value = VALID
-   settimes()
-   sessionStorage.setItem('LOGIN_CAPTCHA', Math.round(new Date().getTime() / 1000).toString())
-   Message.success('验证码已发送,请注意查收')
+
+const getCaptcha = async() => {
+    await getCaptchaHttp({mobile: loginForm.account}).then((res) => {
+        console.log(res)
+        can_send.value = false
+        smsMessage.value = VALID
+        settimes()
+        sessionStorage.setItem('LOGIN_CAPTCHA', Math.round(new Date().getTime() / 1000).toString())
+        Message.success('验证码已发送,请注意查收')
+    }).catch((error) => {
+        console.log(error)
+        Message.error(error.data.msg)
+
+    })
 }
 const settimes = () => {
     var interval

+ 141 - 2
src/view/p_views/resetPwd/resetPwd.vue

@@ -50,6 +50,38 @@
                 </el-form>
               </div>
             </el-tab-pane>
+            <el-tab-pane label="手机号绑定">
+              <div class="form-wrapper">
+                <el-form
+                  ref="ruleFormRef3"
+                  :model="ruleForm3"
+                  :rules="rules3"
+                  label-width="140px"
+                  class="demo-ruleForm"
+                  status-icon
+                >
+                  <el-form-item label="手机号:" prop="mobile">
+                    <el-input type="text" :disabled="!!user.profile.mobile" v-model="ruleForm3.mobile" placeholder="请输入手机号" />
+                  </el-form-item>
+                  <el-form-item label="验证码:" prop="captcha">
+                    <el-input type="text" :disabled="ruleForm3.mobile.length !== 11" v-model="ruleForm3.captcha" placeholder="请输入验证码" >
+                      <template #append>
+                          <el-button v-if="!!user.profile.mobile" @click="getCaptcha" style="width: 100px;" :disabled ="!can_send">{{smsMessage}}</el-button>
+                          <el-button v-else @click="getCaptcha2" style="width: 100px;" :disabled ="!can_send">{{smsMessage}}</el-button>
+                      </template>
+                    </el-input>
+                  </el-form-item>
+                  <el-form-item >
+                    <el-button v-if="!!user.profile.mobile" type="primary" color="#ed8c0f" style="color: #fff;" size="large" @click="submitForm3(ruleFormRef3)">
+                      解绑
+                    </el-button>
+                    <el-button v-else type="primary" color="#ed8c0f" style="color: #fff;" size="large" @click="submitForm4(ruleFormRef3)">
+                      绑定
+                    </el-button>
+                  </el-form-item>
+                </el-form>
+              </div>
+            </el-tab-pane>
         </el-tabs>
         
       </div>
@@ -57,13 +89,15 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed, inject } from 'vue'
+import { ref, reactive, onMounted, computed, inject , onBeforeUnmount} from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 import { showSuccessToast, showFailToast } from 'vant';
 import type { FormInstance, FormRules } from 'element-plus'
-import {resetPassword,setPassword, userAccount } from '@/api/index'
+import {resetPassword,setPassword, userAccount, unbindCaptcha, clearMobile, bindCaptcha, bindMobile } from '@/api/index'
 import Message from '@/utils/Message'
 import { useStore } from '@/store/index'
+import checkRestTime from '@/utils/captcha'
+import { ElMessage, ElMessageBox } from 'element-plus'
 const user = useStore('user')
 
 const router = useRouter()
@@ -72,6 +106,7 @@ const route = useRoute()
 // showFailToast('失败文案')
 const ruleFormRef = ref<FormInstance>()
 const ruleFormRef2 = ref<FormInstance>()
+const ruleFormRef3 = ref<FormInstance>()
 interface RuleForm {
   old_password: string
   new_password: string
@@ -86,6 +121,10 @@ const ruleForm = reactive<RuleForm>({
 const ruleForm2 = reactive({
   account: ''
 })
+const ruleForm3 = reactive({
+  mobile: '',
+  captcha: '',
+})
 const blurValidate = (formEl: FormInstance | undefined) => {
   if (!formEl) return
   if(!ruleForm.new_password || !ruleForm.new_password2) return
@@ -111,6 +150,15 @@ const rules2 = reactive<FormRules>({
     {pattern:'^[a-zA-Z][a-zA-Z0-9]{5,19}$', message: '请输入以字母为开头,长度为6-20位的用户名', trigger: 'blur'}
   ]
 })
+const rules3 = reactive<FormRules>({
+  mobile:[
+    {required: true, message: '请输入手机号', trigger: 'blur'},
+    {pattern:/^(?:(?:\+|00)86)?1[3-9]\d{9}$/, message: '请输入正确手机号', trigger: 'blur'}
+  ],
+  captcha:[
+    {required: true, message: '请输入验证码', trigger: 'blur'},
+  ]
+})
 const rules = reactive<FormRules>({
   old_password: [
     { required: true, message: '请输入旧密码', trigger: 'blur' },
@@ -174,11 +222,102 @@ const submitForm2 = async (formEl: FormInstance | undefined) => {
     }
   })
 }
+const submitForm3 = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  await formEl.validate(async(valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+      await clearMobile({captcha: ruleForm3.captcha}).then(async(res) => {
+        console.log(res)
+        Message.success(res.data.msg)
+        await user.getUserProfile()
+        ruleForm3.mobile = user.profile.mobile
+        ruleForm3.captcha = ''
+        clearInterval(interval)
+        smsMessage.value = '获取验证码'
+        can_send.value = true
+      }).catch((error) => {
+        console.log(error)
+        Message.error(error.data.msg)
+      })
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+const submitForm4 = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  await formEl.validate(async(valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+      await bindMobile({mobile:ruleForm3.mobile, captcha: ruleForm3.captcha}).then(async(res) => {
+        console.log(res)
+        Message.success(res.data.msg)
+        await user.getUserProfile()
+        ruleForm3.mobile = user.profile.mobile
+        ruleForm3.captcha = ''
+        clearInterval(interval)
+        smsMessage.value = '获取验证码'
+        can_send.value = true
+      }).catch((error) => {
+        console.log(error)
+        Message.error(error.data.msg)
+      })
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+const can_send = ref<boolean>(true)
+const smsMessage = ref<'获取验证码' | number>('获取验证码')
+const VALID = 60
+
 const from = ref<1 | 2>(1)
+const getCaptcha = async() => {
+  await unbindCaptcha().then((res) => {
+      console.log(res)
+      can_send.value = false
+      smsMessage.value = VALID
+      settimes()
+      Message.success('验证码已发送,请注意查收')
+  }).catch((error) => {
+      console.log(error)
+      Message.error(error.data.msg)
+
+  })
+}
+const getCaptcha2 = async() => {
+  await bindCaptcha({mobile:ruleForm3.mobile}).then((res) => {
+      console.log(res)
+      can_send.value = false
+      smsMessage.value = VALID
+      settimes()
+      Message.success('验证码已发送,请注意查收')
+  }).catch((error) => {
+      console.log(error)
+      Message.error(error.data.msg)
+
+  })
+}
+let interval
+const settimes = () => {
+    const setTimeFn = () => {
+        (smsMessage.value as number)--
+        if (smsMessage.value as number < 0 || can_send.value === true) {
+            clearInterval(interval)
+            can_send.value = true
+            smsMessage.value = '获取验证码'
+        }
+    }
+    interval = setInterval(function() {
+        setTimeFn()
+    }, 1000)
+}
 onMounted(async()=>{
   from.value = parseInt(localStorage.getItem('from') as string)as 1 | 2
   await user.getUserProfile()
   ruleForm2.account = user.profile?.user_name
+  ruleForm3.mobile = user.profile?.mobile
 })
 
 </script>