|
|
@@ -0,0 +1,285 @@
|
|
|
+<route lang="json5" type="page">
|
|
|
+{
|
|
|
+ layout: 'default',
|
|
|
+ style: {
|
|
|
+ navigationBarTitleText: '加载中',
|
|
|
+ navigationStyle: 'custom',
|
|
|
+ },
|
|
|
+}
|
|
|
+</route>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <!-- APP模式:loading界面 -->
|
|
|
+ <view v-if="fromType === 'APP'" class="loading-container">
|
|
|
+ <view class="loading-content">
|
|
|
+ <view class="spinner" />
|
|
|
+ <text class="loading-text">{{ statusText }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- WEB模式:输入框界面 -->
|
|
|
+ <view v-else class="form-container">
|
|
|
+ <view class="status-bar-placeholder" :style="{ height: statusBarHeight + 'px' }" />
|
|
|
+ <view class="form-content">
|
|
|
+ <text class="form-title">请输入登录信息</text>
|
|
|
+ <view class="input-group">
|
|
|
+ <text class="input-label">用户ID</text>
|
|
|
+ <input
|
|
|
+ class="form-input"
|
|
|
+ v-model="inputUserId"
|
|
|
+ placeholder="请输入用户ID"
|
|
|
+ placeholder-style="color: #bbb"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ <view class="input-group">
|
|
|
+ <text class="input-label">用户名</text>
|
|
|
+ <input
|
|
|
+ class="form-input"
|
|
|
+ v-model="inputUsername"
|
|
|
+ placeholder="请输入用户名"
|
|
|
+ placeholder-style="color: #bbb"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ <button class="submit-btn" @click="handleWebSubmit">
|
|
|
+ <text class="submit-btn-text">继续</text>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref } from 'vue'
|
|
|
+import { onLoad } from '@dcloudio/uni-app'
|
|
|
+import { useUserStore } from '@/store/user'
|
|
|
+import { loginByAppToken, getUserInfo, getMemberByDeptApi } from '@/api/login'
|
|
|
+
|
|
|
+defineOptions({
|
|
|
+ name: 'loading',
|
|
|
+})
|
|
|
+
|
|
|
+const statusText = ref('正在加载...')
|
|
|
+const fromType = ref('APP')
|
|
|
+
|
|
|
+// WEB模式表单
|
|
|
+const inputUserId = ref('')
|
|
|
+const inputUsername = ref('')
|
|
|
+
|
|
|
+// URL参数(APP模式用)
|
|
|
+const urlToken = ref('')
|
|
|
+const urlUserId = ref('')
|
|
|
+const urlUsername = ref('')
|
|
|
+
|
|
|
+// 状态栏高度
|
|
|
+const statusBarHeight = ref(20)
|
|
|
+const systemInfo = uni.getSystemInfoSync()
|
|
|
+statusBarHeight.value = systemInfo.statusBarHeight || 20
|
|
|
+
|
|
|
+const userStore = useUserStore()
|
|
|
+
|
|
|
+onLoad((options) => {
|
|
|
+ fromType.value = options?.from || 'WEB'
|
|
|
+ urlToken.value = options?.token || ''
|
|
|
+ urlUserId.value = options?.userId || ''
|
|
|
+ urlUsername.value = options?.username || ''
|
|
|
+
|
|
|
+ // WEB模式:预填URL参数到表单
|
|
|
+ if (fromType.value !== 'APP') {
|
|
|
+ inputUserId.value = urlUserId.value
|
|
|
+ inputUsername.value = urlUsername.value
|
|
|
+ }
|
|
|
+
|
|
|
+ // APP模式:直接登录
|
|
|
+ if (fromType.value === 'APP') {
|
|
|
+ if (!urlToken.value) {
|
|
|
+ statusText.value = '缺少token参数'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ doLogin(urlToken.value)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// WEB模式:点击继续
|
|
|
+const handleWebSubmit = () => {
|
|
|
+ if (!inputUserId.value.trim()) {
|
|
|
+ statusText.value = '请输入用户ID'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!inputUsername.value.trim()) {
|
|
|
+ statusText.value = '请输入用户名'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ statusText.value = ''
|
|
|
+ doLogin(urlToken.value, inputUserId.value.trim(), inputUsername.value.trim())
|
|
|
+}
|
|
|
+
|
|
|
+// appToken登录
|
|
|
+const doLogin = async (appToken: string, extraUserId?: string, extraUsername?: string) => {
|
|
|
+ try {
|
|
|
+ statusText.value = '正在加载...'
|
|
|
+ const loginRes: any = await loginByAppToken({ appToken })
|
|
|
+ const loginData = loginRes?.data
|
|
|
+
|
|
|
+ if (!loginRes || loginRes.code !== 0 || !loginData) {
|
|
|
+ statusText.value = '加载失败: ' + (loginRes?.msg || '未知错误')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 存储accessToken
|
|
|
+ uni.setStorageSync('APP_ACCESS_TOKEN', loginData.accessToken)
|
|
|
+
|
|
|
+ // 获取用户信息
|
|
|
+ const userId = extraUserId || loginData.userId
|
|
|
+ if (userId) {
|
|
|
+ await fetchUserInfo(userId, extraUsername)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通知store刷新
|
|
|
+ const userInfoStr = uni.getStorageSync('APP_USER_INFO')
|
|
|
+ if (userInfoStr) {
|
|
|
+ const info = typeof userInfoStr === 'string' ? JSON.parse(userInfoStr) : userInfoStr
|
|
|
+ userStore.setUserInfo({ ...info, token: loginData.accessToken })
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.switchTab({ url: '/pages/home/index' })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[LoadingPage] 加载失败:', error)
|
|
|
+ statusText.value = '加载失败,请重试'
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 获取用户信息
|
|
|
+const fetchUserInfo = async (userId: string, overrideUsername?: string) => {
|
|
|
+ try {
|
|
|
+ const res: any = await getUserInfo({ id: userId })
|
|
|
+ const user = res?.data
|
|
|
+
|
|
|
+ if (user) {
|
|
|
+ // WEB模式下用输入的username覆盖
|
|
|
+ if (overrideUsername) {
|
|
|
+ user.nickname = overrideUsername
|
|
|
+ user.username = overrideUsername
|
|
|
+ }
|
|
|
+ uni.setStorageSync('APP_USER_INFO', user)
|
|
|
+ userStore.setUserInfo(user)
|
|
|
+
|
|
|
+ if (user.deptId) {
|
|
|
+ await fetchDeptMembers(user.deptId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[LoadingPage] 加载页面失败:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 获取部门成员列表
|
|
|
+const fetchDeptMembers = async (deptId: string) => {
|
|
|
+ try {
|
|
|
+ const result: any = await getMemberByDeptApi({ deptIds: deptId })
|
|
|
+ if (result.code === 0 && result?.data?.length) {
|
|
|
+ uni.setStorageSync('USER_LIST', result.data)
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[LoadingPage] 加载页面失败:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.loading-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 100vh;
|
|
|
+ background-color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.loading-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.spinner {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ border: 3px solid #e0e0e0;
|
|
|
+ border-top-color: #071f50;
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: spin 0.8s linear infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes spin {
|
|
|
+ to {
|
|
|
+ transform: rotate(360deg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.loading-text {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+// WEB模式表单样式
|
|
|
+.form-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background-color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.status-bar-placeholder {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.form-content {
|
|
|
+ padding: 60px 30px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.form-title {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.input-group {
|
|
|
+ margin-bottom: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.input-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.form-input {
|
|
|
+ height: 44px;
|
|
|
+ padding: 0 12px;
|
|
|
+ font-size: 16px;
|
|
|
+ border-width: 1px;
|
|
|
+ border-style: solid;
|
|
|
+ border-color: #ddd;
|
|
|
+ border-radius: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn {
|
|
|
+ margin-top: 40px;
|
|
|
+ height: 47px;
|
|
|
+ background-color: #071f50;
|
|
|
+ border-radius: 6px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn-text {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.error-text {
|
|
|
+ margin-top: 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #ff4d4f;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+</style>
|