以下演示的編輯器使用HbuildX
首先安裝typescript編譯插件改基。下面演示從HbuildX安裝
在HbuildX里面盼砍,依次找到 工具 -> 插件安裝 -> 安裝新插件 -> 前往插件市場(chǎng)安裝
image.png
然后輸入typescript,搜索,選擇 typescript編譯
image.png
這是因?yàn)閠ypescript編譯插件不是HbuildX的核心插件瓦糕,只能去插件市場(chǎng)空另。因此狸臣,其實(shí)也可以直接訪問 https://ext.dcloud.net.cn/search?q=typescript&cat1=1&cat2=11,
搜索插件然后安裝即可粉寞。安裝好后尼荆,在已安裝插件處可以看到
image.png
uniapp 對(duì)vue3+ts已經(jīng)做了兼容,安裝好插件后唧垦,基本就可以用vue3寫了捅儒。由于uniapp 項(xiàng)目,通常的應(yīng)用場(chǎng)景里面vue3都可以兼容振亮,因此這里就不討論vue2的寫法巧还,以下就做下vue3的示例
yl-phone-msg-code 插件地址:https://ext.dcloud.net.cn/plugin?id=8544
vue3 setup 組合式api寫法,應(yīng)用生命周期函數(shù)onLoad,onShow等和setUp同級(jí)
<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:'發(fā)送驗(yàn)證碼'}"
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="請(qǐng)輸入用戶名" />
<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="請(qǐng)輸入密碼" />
<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">{{ ["賬號(hào)密碼登錄","驗(yàn)證碼登錄"][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">注冊(cè)賬號(hào)</view>-->
<view class="regesterText row-center" @tap="goRegister">xxx信息技術(shù)有限責(zé)任公司</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: '', //正式時(shí)清除
password: '', //正式時(shí)清除
})
let isLogin= ref(false)
let loginMethod=ref(0)//登錄方式 0 驗(yàn)證碼 1 賬號(hào)
let hasGetCode=ref(false)//是否獲取驗(yàn)證碼
let fromRouteInfo=ref({})//來源路由信息
let customStyle=ref({
color:"#ffffff"
})// 自定義樣式
/**
* 獲取驗(yàn)證碼
* @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('請(qǐng)輸入正確的用戶名')
return
}
if (!password) {
showAlert('請(qǐng)輸入正確的密碼')
return
}
}else if(loginMethod===0){
if (!mobile) {
showAlert('請(qǐng)輸入手機(jī)號(hào)')
return
}
if (!code) {
showAlert('請(qǐng)輸入短信驗(yàn)證碼')
return
}
}
if(isLogin.value){
uni.showToast({
title:'正在登錄坊秸,請(qǐng)稍后操作',
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 || '網(wǎng)絡(luò)錯(cuò)誤麸祷!請(qǐng)稍后重試')
},
complete:()=> {
// uni.hideLoading()
isLogin.value=false
}
})
}
/**
* 設(shè)置登錄信息
*/
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
}
//設(shè)置登錄信息
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){
//沒有手機(jī)號(hào)時(shí)去綁定
uni.redirectTo({
url:`/pages/bindPhone/bindPhone?${queryString}`
})
}else{
backToFrom(fromRouteInfo.value)
}
}
/**
* 自動(dòng)獲取密碼登陸
* @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
}
}
/**
* 跳轉(zhuǎn)注冊(cè)
*/
const goRegister = ():void => {
uni.redirectTo({
url:'../register/register'
})
}
/**
* 使用微信登錄
*/
const wxLogin = ():void => {
uni.showLoading({title:'加載中'})
// 獲取用戶信息
uni.getUserProfile({
desc:'用于完善會(huì)員資料,提升用戶體驗(yàn)',
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('調(diào)用微信登錄成功')
console.log(res)
uni.hideLoading()
this.setLoginInfo(res,true)
},
fail:(err:any):void=>{
uni.hideLoading()
uni.showToast({
title:err.errMsg || '網(wǎng)絡(luò)錯(cuò)誤',
icon:'error'
})
},
})
},
fail:function (err:any):void{
uni.showToast({
title:'微信登錄出錯(cuò)',
icon:'error'
})
}
})
},
fail():void{
uni.hideLoading()
}
})
}
/**
* 登錄切換
*/
const loginSwitch = ():void => {
loginMethod.value = 1 - loginMethod.value
}
return {
loginform,
isLogin,
loginMethod,//登錄方式 0 驗(yàn)證碼 1 賬號(hào)
hasGetCode,//是否獲取驗(yàn)證碼
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>