Commit d719f549 by pangchong

feat: 登录完成

parent bc35c6f9
......@@ -8,17 +8,19 @@ export const getGifCaptchaApi = (data, config) => {
config
})
}
export const getUserCallStateApi = (data) => {
export const getUserCallStateApi = (data, config) => {
return http({
method: 'POST',
url: '/call/getUserCallState',
data,
config
})
}
export const loginApi = (data) => {
export const loginApi = (data, config) => {
return http({
method: 'POST',
url: '/user/login',
data,
config
})
}
import { createSSRApp } from 'vue'
import App from './App.vue'
import pinia from './store'
export function createApp() {
const app = createSSRApp(App)
app.use(pinia)
......
......@@ -50,7 +50,7 @@
"tabBar": {
"color": "#1D2129",
"selectedColor": "#0E42D2",
"borderStyle": "#E7E7E7",
"borderStyle": "black",
"iconWidth": "24px",
"backgroundColor": "#fff",
"list": [
......
......@@ -10,7 +10,7 @@
</uni-forms-item>
<uni-forms-item label="验证码" name="verifyCode">
<view class="verify-code">
<uni-easyinput type="text" v-model="loginForm.password" placeholder="请输入验证码" />
<uni-easyinput type="text" v-model="loginForm.verifyCode" placeholder="请输入验证码" />
<image :src="loginCode" mode="scaleToFill" v-if="loginCode" />
</view>
</uni-forms-item>
......@@ -20,9 +20,10 @@
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import { getGifCaptchaApi } from '@/api/user'
import { reactive, ref, toRaw, watch } from 'vue'
import { getGifCaptchaApi, loginApi } from '@/api/user'
import { debounce } from 'lodash'
import message from '@/utils/message'
//表单数据
const loginForm = reactive({
......@@ -47,6 +48,14 @@ const rules = reactive({
errorMessage: '请输入密码'
}
]
},
verifyCode: {
rules: [
{
required: true,
errorMessage: '请输入验证码'
}
]
}
})
//获取验证码
......@@ -55,9 +64,9 @@ const getGifCaptcha = async () => {
const params = {
username: loginForm.username
}
const blob = await getGifCaptchaApi(params, { blob: true })
if (blob) {
loginCode.value = URL.createObjectURL(blob)
const res = await getGifCaptchaApi(params, { arraybuffer: true })
if (res) {
loginCode.value = 'data:image/png;base64,' + uni.arrayBufferToBase64(res)
}
}
watch(
......@@ -72,6 +81,15 @@ watch(
const loginFormRef = ref()
const handleLogin = async () => {
await loginFormRef.value?.validate()
const res = await loginApi(toRaw(loginForm), { loading: '登陆中...' })
if (res.code == 200) {
//跳转工作台
uni.switchTab({
url: '/pages/panel/index'
})
} else {
message.error(res.message)
}
}
</script>
......@@ -87,6 +105,11 @@ const handleLogin = async () => {
display: flex;
justify-content: space-between;
align-items: center;
image {
margin-left: 10rpx;
width: 200rpx;
height: 70rpx;
}
}
.login-btn {
margin-top: 50rpx;
......
......@@ -14,10 +14,46 @@ import useUserStore from '@/store/modules/user'
const baseURL = 'https://hna-platform.anyremote.cn'
class ServiceLoading {
constructor() {
this.count = 0
}
open(loading) {
if (this.count < 0) {
this.count = 0
}
if (loading || loading === '') {
let loadingText = '加载中'
if (typeof loading === 'string' && loading !== '') {
loadingText = loading
}
this.count++
uni.showLoading({
title: loadingText
});
}
}
close() {
this.count--
if (this.count <= 0) {
uni.hideLoading();
}
}
}
const serviceLoading = new ServiceLoading()
// 添加拦截器
const httpInterceptor = {
// 拦截前触发
invoke(options) {
//responseType
if (options.config?.arraybuffer) {
options.responseType = 'arraybuffer'
}
//loading
const loading = options.config?.loading
serviceLoading.open(loading)
//重组提交数据
if (options.data) {
options.data = {
...options.data,
......@@ -26,18 +62,18 @@ const httpInterceptor = {
realUserId: '21'
}
}
// 1. 非 http 开头需拼接地址
// 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时, 默认 60s
// 请求超时, 默认 60s
options.timeout = 10000
// 3. 添加小程序端请求头标识
// 添加小程序端请求头标识
options.header = {
'Content-Type': 'application/x-www-form-urlencoded',
...options.header,
}
// 4. 添加 token 请求头标识
// 添加 token 请求头标识
const userStore = useUserStore()
if (userStore.token) {
options.header.Authorization = `Bearer ${userStore.token}`
......@@ -67,14 +103,11 @@ export const http = (options) => {
...options,
// 响应成功
success(res) {
serviceLoading.close()
// 状态码 2xx, axios 就是这样设计的
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
if (options.config?.blob) {
resolve(res.data?.blob())
} else {
resolve(res.data)
}
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
const userStore = useUserStore()
......@@ -85,6 +118,7 @@ export const http = (options) => {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
mask: true,
title: res.data.msg || '请求错误',
})
reject(res)
......@@ -92,6 +126,7 @@ export const http = (options) => {
},
// 响应失败
fail(err) {
serviceLoading.close()
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
......
// utils/message.js
export default {
// 成功提示
success(options) {
uni.showToast({
title: options.title || '操作成功',
icon: 'success',
duration: 2000,
...options
});
},
// 错误提示
error(options) {
uni.showToast({
title: options.title || '操作失败',
icon: 'none',
duration: 2000,
...options
});
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment