160 lines
3.8 KiB
Vue
160 lines
3.8 KiB
Vue
<template>
|
|
<view class="page login-page">
|
|
<view class="login-head">
|
|
<text class="page-title">银城员工端</text>
|
|
<text class="page-subtitle">使用手机号登录后,回到当前任务。</text>
|
|
</view>
|
|
|
|
<view class="panel login-card">
|
|
<text class="panel-title">手机号登录</text>
|
|
<input
|
|
v-model="phone"
|
|
class="input"
|
|
type="number"
|
|
maxlength="11"
|
|
placeholder="请输入手机号"
|
|
/>
|
|
<view class="inline-actions">
|
|
<input
|
|
v-model="smsCode"
|
|
class="input code-input"
|
|
type="number"
|
|
maxlength="6"
|
|
placeholder="验证码"
|
|
/>
|
|
<button class="secondary-button code-button" :disabled="sending" @click="sendCode">
|
|
{{ sending ? '发送中' : '发验证码' }}
|
|
</button>
|
|
</view>
|
|
<button class="primary-button" :disabled="loggingIn" @click="login">
|
|
{{ loggingIn ? '登录中' : '登录' }}
|
|
</button>
|
|
<text v-if="message" class="status-message">{{ message }}</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { onShow } from '@dcloudio/uni-app';
|
|
import type { LoginResult } from '@/types/api';
|
|
import { apiRequest } from '@/services/api';
|
|
import { consumeLoginRedirect, getAuth, isLoggedIn, phoneKey, saveAuth, validatePhone } from '@/services/auth';
|
|
|
|
const stored = getAuth();
|
|
const phone = ref(stored.phone || uni.getStorageSync(phoneKey) || '');
|
|
const smsCode = ref('');
|
|
const sending = ref(false);
|
|
const loggingIn = ref(false);
|
|
const message = ref('');
|
|
const tabPages = new Set([
|
|
'/pages/user/today/index',
|
|
'/pages/user/practice/index',
|
|
'/pages/user/sop/index',
|
|
'/pages/user/profile/index'
|
|
]);
|
|
|
|
const goAfterLogin = () => {
|
|
const redirect = consumeLoginRedirect() || '/pages/user/today/index';
|
|
if (tabPages.has(redirect)) {
|
|
uni.switchTab({ url: redirect });
|
|
return;
|
|
}
|
|
uni.redirectTo({ url: redirect });
|
|
};
|
|
|
|
const sendCode = async () => {
|
|
if (sending.value) return;
|
|
const value = phone.value.trim();
|
|
if (!validatePhone(value)) {
|
|
message.value = '请输入正确手机号';
|
|
return;
|
|
}
|
|
sending.value = true;
|
|
message.value = '';
|
|
try {
|
|
await apiRequest<void>({
|
|
url: `/resource/sms/code?phonenumber=${encodeURIComponent(value)}`,
|
|
method: 'GET',
|
|
auth: false
|
|
});
|
|
message.value = '验证码已发送';
|
|
} catch (error) {
|
|
message.value = error instanceof Error ? error.message : '验证码发送失败';
|
|
} finally {
|
|
sending.value = false;
|
|
}
|
|
};
|
|
|
|
const login = async () => {
|
|
if (loggingIn.value) return;
|
|
const value = phone.value.trim();
|
|
if (!validatePhone(value)) {
|
|
message.value = '请输入正确手机号';
|
|
return;
|
|
}
|
|
if (!smsCode.value.trim()) {
|
|
message.value = '请输入短信验证码';
|
|
return;
|
|
}
|
|
loggingIn.value = true;
|
|
message.value = '';
|
|
try {
|
|
const result = await apiRequest<LoginResult>({
|
|
url: '/auth/mobile/sms-login',
|
|
method: 'POST',
|
|
data: {
|
|
phonenumber: value,
|
|
smsCode: smsCode.value.trim(),
|
|
tenantId: '000000'
|
|
},
|
|
auth: false
|
|
});
|
|
if (!result.access_token || !result.client_id) {
|
|
throw new Error('登录响应缺少认证信息');
|
|
}
|
|
saveAuth(result, value);
|
|
goAfterLogin();
|
|
} catch (error) {
|
|
message.value = error instanceof Error ? error.message : '登录失败';
|
|
} finally {
|
|
loggingIn.value = false;
|
|
}
|
|
};
|
|
|
|
onShow(() => {
|
|
if (isLoggedIn()) {
|
|
goAfterLogin();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.login-page {
|
|
display: flex;
|
|
min-height: 100vh;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
.login-head {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.login-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 14px;
|
|
}
|
|
|
|
.code-input {
|
|
flex: 1;
|
|
}
|
|
|
|
.code-button {
|
|
width: 112px;
|
|
flex: none;
|
|
font-size: 14px;
|
|
}
|
|
</style>
|