Parcourir la source

调整蚁群APP接入页面

yangguanjin il y a 2 semaines
Parent
commit
bc80d684ad
5 fichiers modifiés avec 300 ajouts et 113 suppressions
  1. 0 113
      index.html
  2. 5 0
      src/api/login.ts
  3. 9 0
      src/pages.json
  4. 285 0
      src/pages/loading/index.vue
  5. 1 0
      src/types/uni-pages.d.ts

+ 0 - 113
index.html

@@ -22,118 +22,5 @@
   <body>
     <div id="app"><!--app-html--></div>
     <script type="module" src="/src/main.ts"></script>
-    <script>
-      var API_BASE = 'http://192.168.0.118:9000/appapi'
-
-      // 通用请求方法(带token)
-      function apiGet(path, params) {
-        var url = API_BASE + path
-        if (params) {
-          var qs = Object.keys(params).map(function(k) { return k + '=' + encodeURIComponent(params[k]) }).join('&')
-          url += '?' + qs
-        }
-        var token = window.localStorage.getItem('APP_ACCESS_TOKEN') || ''
-        return fetch(url, {
-          method: 'GET',
-          headers: {
-            'Content-Type': 'application/json',
-            'Authorization': 'Bearer ' + token,
-            'X-Tenant-Id': '1'
-          }
-        }).then(function(res) { return res.json() })
-      }
-
-      // 获取用户信息(参照login.vue fetchUserInfo)
-      function fetchUserInfo(userId) {
-        return apiGet('/system/auth/userinfo', { id: userId })
-          .then(function(res) {
-            console.log('[fetchUserInfo] Response:', JSON.stringify(res))
-            if (res.code === 0 && res.data) {
-              window.localStorage.setItem('APP_USER_INFO', JSON.stringify(res.data))
-              console.log('[fetchUserInfo] APP_USER_INFO saved')
-              // 获取部门成员列表
-              if (res.data.deptId) {
-                return fetchDeptMembers(res.data.deptId)
-              }
-            }
-          })
-          .catch(function(e) {
-            console.error('[fetchUserInfo] Failed:', e)
-          })
-      }
-
-      // 获取部门成员列表(参照login.vue fetchGetMemberByDeptApi)
-      function fetchDeptMembers(deptId) {
-        return apiGet('/bpm/user-group/user-list', { deptIds: deptId })
-          .then(function(res) {
-            console.log('[fetchDeptMembers] Response: ok')
-            if (res.code === 0 && res.data && res.data.length) {
-              window.localStorage.setItem('USER_LIST', JSON.stringify(res.data))
-            }
-          })
-          .catch(function(e) {
-            console.error('[fetchDeptMembers] Failed:', e)
-          })
-      }
-
-      // 通知Vue应用刷新store
-      function notifyAppRefresh(loginData) {
-        window.dispatchEvent(new CustomEvent('app-token-login', { detail: loginData }))
-      }
-
-      window.loginByAppToken = function (token) {
-        fetch(API_BASE + '/system/auth/loginByAppToken', {
-          method: 'POST',
-          headers: { 'Content-Type': 'application/json' },
-          body: JSON.stringify({ appToken: token })
-        })
-        .then(function (res) { return res.json() })
-        .then(function (res) {
-          console.log('[loginByAppToken] Response:', JSON.stringify(res))
-          if (res.code === 0 && res.data) {
-            // 存储 accessToken
-            window.localStorage.setItem('APP_ACCESS_TOKEN', res.data.accessToken)
-            console.log('[loginByAppToken] APP_ACCESS_TOKEN saved')
-            // 获取用户信息
-            if (res.data.userId) {
-              fetchUserInfo(res.data.userId).then(function() {
-                // 通知Vue应用刷新store
-                notifyAppRefresh({ accessToken: res.data.accessToken, userId: res.data.userId })
-              })
-            } else {
-              console.warn('[loginByAppToken] No userId in response')
-              notifyAppRefresh({ accessToken: res.data.accessToken })
-            }
-          } else {
-            console.error('[loginByAppToken] Login failed:', res.msg)
-          }
-        })
-        .catch(function (e) {
-          console.error('[loginByAppToken] Failed:', e)
-        })
-      }
-
-      window.saveToLocalStorage = function (jsonStr) {
-        try {
-          var data = JSON.parse(jsonStr)
-          if (data && typeof data === 'object') {
-            Object.keys(data).forEach(function (key) {
-              window.localStorage.setItem(key, typeof data[key] === 'object' ? JSON.stringify(data[key]) : String(data[key]))
-            })
-          }
-          console.log('[saveToLocalStorage] Success:', data)
-          // 写入成功后,取出token调用登录接口
-          var token = window.localStorage.getItem('token')
-          if (token) {
-            console.log('[saveToLocalStorage] Got token, calling loginByAppToken...')
-            window.loginByAppToken(token)
-          } else {
-            console.warn('[saveToLocalStorage] No token found in data')
-          }
-        } catch (e) {
-          console.error('[saveToLocalStorage] Failed:', e)
-        }
-      }
-    </script>
   </body>
 </html>

+ 5 - 0
src/api/login.ts

@@ -6,6 +6,11 @@ export const handleLogin = (data: { username: string; password: string }) => {
   return httpPost('/system/auth/login', data)
 }
 
+// 通过AppToken登录
+export const loginByAppToken = (data: { appToken: string }) => {
+  return httpPost('/system/auth/loginByAppToken', data)
+}
+
 // 获取用户权限信息
 export const handleGetUserInfo = () => {
   return httpGet('/system/auth/get-permission-info')

+ 9 - 0
src/pages.json

@@ -101,6 +101,15 @@
         "disableScroll": true
       }
     },
+    {
+      "path": "pages/loading/index",
+      "type": "page",
+      "layout": "default",
+      "style": {
+        "navigationBarTitleText": "加载中",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/login/login",
       "type": "page",

+ 285 - 0
src/pages/loading/index.vue

@@ -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>

+ 1 - 0
src/types/uni-pages.d.ts

@@ -10,6 +10,7 @@ interface NavigateToOptions {
        "/pages/deviceExam/deviceExamDetail" |
        "/pages/importanceEditor/importanceEditor" |
        "/pages/inspectionPlanAudit/inspectionPlanEditor" |
+       "/pages/loading/index" |
        "/pages/login/login" |
        "/pages/securityCheck/securityCheckEditor" |
        "/pages/securityCheck/securityCheckList" |