uniapp+vue3 接入typescript

2022-07-09  本文已影响0人  东扯葫芦西扯瓜

以下演示的编辑器使用HbuildX

首先安装typescript编译插件。下面演示从HbuildX安装

在HbuildX里面,依次找到 工具 -> 插件安装 -> 安装新插件 -> 前往插件市场安装


image.png

然后输入typescript,搜索,选择 typescript编译

image.png

这是因为typescript编译插件不是HbuildX的核心插件,只能去插件市场。因此,其实也可以直接访问 https://ext.dcloud.net.cn/search?q=typescript&cat1=1&cat2=11
搜索插件然后安装即可。安装好后,在已安装插件处可以看到

image.png

uniapp 对vue3+ts已经做了兼容,安装好插件后,基本就可以用vue3写了。由于uniapp 项目,通常的应用场景里面vue3都可以兼容,因此这里就不讨论vue2的写法,以下就做下vue3的示例
yl-phone-msg-code 插件地址:https://ext.dcloud.net.cn/plugin?id=8544

vue3 setup 组合式api写法,应用生命周期函数onLoad,onShow等和setUp同级

<template>
  <view class="container">
    <view class="app-top-box column-center">
      <view class="kedang-app-img"></view>
      <view class="row-center kedang-text">
        欢迎光临
      </view>
    </view>
    <yl-phone-msg-code
        v-if="loginMethod===0"
        mobile-prepend="+86"
        :req-mobile-code="getCode"
        :mobile-style="customStyle"
        :mobile-prepend-style="customStyle"
        :code-style="customStyle"
        :msg-code-text-config="{getCodeText:'发送验证码'}"
        class="userLogin"
    >
      <template #getCode="{msgCodeText}">
        <view class="getCode">
          <view class="getCodeInner">{{ msgCodeText }}</view>
        </view>
      </template>
    </yl-phone-msg-code>
    <view class="userLogin" v-if="loginMethod===1">
      <view class="inputbox">
        <input type="text" v-model.trim="loginform.username" placeholder-class="input-placeholder" placeholder="请输入用户名" />
        <view class="row-center clearBox">
          <image v-if="loginform.username" src="../../static/login/close.png" class="clear" @tap="loginform.username=''"></image>
        </view>
      </view>
      <view class="inputbox">
        <input type="password" v-model.trim="loginform.password" placeholder-class="input-placeholder" placeholder="请输入密码" />
        <view class="row-center clearBox">
          <image v-if="loginform.password" src="../../static/login/close.png" class="clear" @tap="loginform.password=''"></image>
        </view>
      </view>
    </view>
    <view class="read-"></view>
    <view class="row-center b-btn-box" style="margin-top:40rpx;">
      <button class="u-btn" hover-class="u-hover-btn" @tap="onLogin">登录</button>
    </view>
    <view class="row-center login-switch" @click="loginSwitch">{{ ["账号密码登录","验证码登录"][loginMethod] }}</view>
<!--    <view class="row-end findPassBox">-->
<!--      <navigator class="navigator" url="/pages/findPassword/findPassword" hover-class="navigator-hover">-->
<!--        <text class="findPassText">找回密码</text>-->
<!--      </navigator>-->
<!--    </view>-->

    <view class="wxLoginBox">
      <view class="otherLoginBox row-center">
        <view class="line"></view>
        <view class="text">其他登陆方式</view>
        <view class="line"></view>
      </view>
      <view class="row-center">
        <image class="wxImg" src="../../static/login/wx.png" @tap="wxLogin"></image>
      </view>
    </view>
<!--    <view class="regesterText row-center" @tap="goRegister">注册账号</view>-->
    <view class="regesterText row-center" @tap="goRegister">xxx信息技术有限责任公司</view>
  </view>
</template>

<script lang="ts">
import { defineComponent,ref } from 'vue'
import {useStore} from "vuex";
import {reqMobileCode} from "../../api/common"
import {preventContinuePoint,showAlert,backToFrom,jsonToqs} from "../../utils/util"
import { apiBaseUrl } from '../../utils/config.js'

export default defineComponent({
  onLoad({fromPath,isTab,options}):void{
    this.autocommplete()
    this.fromRouteInfo={fromPath,isTab,options}
  },
  onShow():void{
    this.autocommplete()
  },
  setup(props,context) {
    let store=useStore();
    let loginform= ref({
      username: '', //正式时清除
      password: '', //正式时清除
    })
    let isLogin= ref(false)
    let loginMethod=ref(0)//登录方式 0 验证码 1 账号
    let hasGetCode=ref(false)//是否获取验证码
    let fromRouteInfo=ref({})//来源路由信息
    let customStyle=ref({
      color:"#ffffff"
    })// 自定义样式
    /**
     * 获取验证码
     * @param mobile
     * @param code
     * @returns {Promise<void>}
     */
    const getCode = async (mobile:string,code:string):Promise<any> => {
      let result = await reqMobileCode(mobile)
      console.log(result)
      loginform.value= {mobile,code}
      hasGetCode.value=true
    }
    /**
     * 登录
     * @returns {Promise<void>}
     */
    const onLogin = async ():Promise<any>  => { //status == 426 用户不存在
      await preventContinuePoint(this)
      let {username,password,code,mobile} = loginform.value
      if(loginMethod.value===1){
        if (!username) {
          showAlert('请输入正确的用户名')
          return
        }
        if (!password) {
          showAlert('请输入正确的密码')
          return
        }
      }else if(loginMethod===0){
        if (!mobile) {
          showAlert('请输入手机号')
          return
        }
        if (!code) {
          showAlert('请输入短信验证码')
          return
        }
      }

      if(isLogin.value){
        uni.showToast({
          title:'正在登录,请稍后操作',
          icon:'none'
        })
        return
      }
      isLogin.value = true
      uni.showLoading({
        title: '登录中...'
      })
      console.log(apiBaseUrl)
      uni.request({
        url: apiBaseUrl + ['auth/login_by_code','auth/login',][loginMethod],
        method:'POST',
        data:loginform.value,
        timeout: 1000 * 5,
        success:res=> {
          uni.hideLoading()
          console.log(res);
          //登录成功
          uni.setStorageSync('loginUser', {
            username,
            password,
            checked: true
          })
          setLoginInfo(res)
        },
        fail:err=> {
          uni.hideLoading()
          console.log(err);
          let msg=err.msg
          isLogin.value = false
          showAlert(msg || '网络错误!请稍后重试')
        },
        complete:()=> {
          // uni.hideLoading()
          isLogin.value=false
        }
      })

    }
    /**
     * 设置登录信息
     */
    const setLoginInfo = (res:any,isWx?:boolean):any => {
      let {errmsg,errno,data}=res.data
      console.log(errno)
      if(errno!==0){
        uni.showToast({
          title:errmsg,
          icon:'error'
        })
        return
      }
      //设置登录信息
      uni.setStorage({
        key: 'hasLogin',
        data: 1,
      })
      let {token,userInfo}=res.data.data
      uni.setStorage({
        key: 'token',
        data: token,
      })
      userInfo.originUserType=userInfo.userType
      store.dispatch('setLoginInfo', userInfo)
      uni.setStorage({
        key:'userInfo',
        data:userInfo
      })
      let queryString=jsonToqs(fromRouteInfo.value)
      queryString=decodeURIComponent(queryString)
      if(isWx && !userInfo.mobile){
        //没有手机号时去绑定
        uni.redirectTo({
          url:`/pages/bindPhone/bindPhone?${queryString}`
        })
      }else{
        backToFrom(fromRouteInfo.value)
      }
    }
    /**
     * 自动获取密码登陆
     * @returns {Promise<void>}
     */
    const autocommplete = async ():Promise<any> => {
      let loginUser = await uni.getStorageSync('loginUser')
      if (loginUser.username) {
        loginform.value.username = loginUser.username
        loginform.value.password = loginUser.password
      }
    }
    /**
     * 跳转注册
     */
    const goRegister = ():void => {
      uni.redirectTo({
        url:'../register/register'
      })
    }
    /**
     * 使用微信登录
     */
    const wxLogin = ():void => {
      uni.showLoading({title:'加载中'})
      // 获取用户信息
      uni.getUserProfile({
        desc:'用于完善会员资料,提升用户体验',
        success: infoRes=> {
          console.log(infoRes)
          uni.login({
            provider: 'weixin',
            onlyAuthorize:true,
            success: async (loginRes:any):Promise<any> => {
              console.log(loginRes.code)
              console.log(loginRes)
              uni.request({
                url:apiBaseUrl +'auth/login_by_weixin',
                data:{
                  code: loginRes.code,
                  userInfo: infoRes.userInfo
                },
                method:'POST',
                success:(res:any)=>{
                  console.log('调用微信登录成功')
                  console.log(res)
                  uni.hideLoading()
                  this.setLoginInfo(res,true)
                },
                fail:(err:any):void=>{
                  uni.hideLoading()
                  uni.showToast({
                    title:err.errMsg || '网络错误',
                    icon:'error'
                  })
                },
              })
            },
            fail:function (err:any):void{
              uni.showToast({
                title:'微信登录出错',
                icon:'error'
              })
            }
          })
        },
        fail():void{
          uni.hideLoading()
        }
      })
    }
    /**
     * 登录切换
     */
    const loginSwitch = ():void => {
      loginMethod.value = 1 - loginMethod.value
    }
    return {
      loginform,
      isLogin,
      loginMethod,//登录方式 0 验证码 1 账号
      hasGetCode,//是否获取验证码
      fromRouteInfo,//来源路由信息
      customStyle,// 自定义样式
      getCode,
      onLogin,
      setLoginInfo,
      autocommplete,
      goRegister,
      wxLogin,
      loginSwitch
    }
  },
})
</script>

<style lang="scss" scoped>
.container {
  background: #13141a;
  height: 100vh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  position: relative;
  padding-top:170rpx;
}
.app-top-box{
  margin-bottom: 100rpx;
  border:solid 1px blue;
  .kedang-app-img{
    width: 160rpx;
    height: 160rpx;
    border:solid 1px red;
    margin-bottom: 20rpx;
  }
  .kedang-text{
    color:#ffffff;
  }
}
.userLogin{
  height:200rpx;
}
.wxLoginBox{
  //margin-top:124rpx;
  //margin-bottom: 88rpx;
  .otherLoginBox{
    margin-bottom: 40rpx;
    .line{
      width: 144rpx;
      height: 1rpx;
      background: #EEEEEE;
    }
    .text{
      font-size: 24rpx;
      color:#aaaaaa;
      margin:0 10rpx;
    }
  }
  .wxImg{
    width:96rpx;
    height:96rpx;
  }
}
.login-switch{
  margin-top:40rpx;
  color:#999999;
  margin-bottom: 100rpx;
}
.regesterText{
  font-size: 24rpx;
  color:#666666;
}
.findPassBox{
  padding:20rpx 30rpx;
}
.findPassText{
  color:#3F99FF;
}
.getCode{
  background: linear-gradient(90deg,#f6b847, #f1950e);
  padding:2rpx;
  border-radius: 30rpx;
  overflow: hidden;
  .getCodeInner{
    width: 160rpx;
    font-size: 20rpx;
    text-align: center;
    color: #faad14;
    background: #13141a;
    padding:10rpx 20rpx;
    border-radius: 30rpx;
    overflow: hidden;
  }
}
</style>

上一篇下一篇

猜你喜欢

热点阅读