瀏覽代碼

初步完成APP的webview集成适配

yangguanjin 1 周之前
父節點
當前提交
68af4cd2cd

+ 7 - 3
index.html

@@ -24,8 +24,9 @@
     <script>
       window.loadingLogin = function (params) {
          if(!window.loginAppToken){
-           if (!window._loadingLoginTimer) {
-             window._loadingLoginTimer = setTimeout(() => {
+            if (!window._loadingLoginTimer) {
+              window._loadingLoginTimer = setTimeout(() => {
+              //  console.log('loadingLogin not found loginAppToken')
                window._loadingLoginTimer = null;
                window.loadingLogin(params);
              }, 500);
@@ -35,7 +36,10 @@
              clearTimeout(window._loadingLoginTimer);
              window._loadingLoginTimer = null;
            }
-           window.loginAppToken(params);
+          //  console.log('applogin route....', window.location.pathname)
+           if (window.location.pathname === '/app-h5/pages/loading/index') {
+             window.loginAppToken(params);
+           }
          }
       }
     </script>

+ 7 - 7
pages.config.ts

@@ -17,9 +17,9 @@ export default defineUniPages({
     },
   },
   tabBar: {
-    color: '#aaa',
-    selectedColor: '#39b54a',
-    backgroundColor: '#F8F8F8',
+    color: '#333333',
+    selectedColor: '#071F50',
+    backgroundColor: '#fff',
     borderStyle: 'black',
     height: '50px',
     fontSize: '11px',
@@ -27,14 +27,14 @@ export default defineUniPages({
     spacing: '3px',
     list: [
       {
-        iconPath: '/static/tabbar/tabbar-home-2.png',
-        selectedIconPath: '/static/tabbar/tabbar-home.png',
+        iconPath: '/static/tabbar/home.png',
+        selectedIconPath: '/static/tabbar/home_selected.png',
         pagePath: 'pages/home/index',
         text: '首页',
       },
       {
-        iconPath: '/static/tabbar/tabbar-user-2.png',
-        selectedIconPath: '/static/tabbar/tabbar-user.png',
+        iconPath: '/static/tabbar/user.png',
+        selectedIconPath: '/static/tabbar/user_selected.png',
         pagePath: 'pages/user/index',
         text: '我的',
       },

+ 5 - 0
src/api/boiler/boilerTaskOrder.ts

@@ -35,6 +35,11 @@ export const confirmBoilerEquipmentClaim = (data: { id: string }) => {
   return httpPost('/pressure2/boiler-task-order/order-item/claim', data)
 }
 
+export const confirmBoilerEquipmentBatchClaim = (data: { orderItemIdList: string[] }) => {
+  return httpPost('/pressure2/boiler-task-order/order-item/batchClaim', data)
+}
+
+
 // 取消设备认领
 export const cancelBoilerEquipmentClaim = (data: { id: string }) => {
   return httpPost('/pressure2/boiler-task-order/order-item/cancelClaim', data)

+ 7 - 7
src/pages.json

@@ -14,9 +14,9 @@
     }
   },
   "tabBar": {
-    "color": "#aaa",
-    "selectedColor": "#39b54a",
-    "backgroundColor": "#F8F8F8",
+    "color": "#333333",
+    "selectedColor": "#071F50",
+    "backgroundColor": "#fff",
     "borderStyle": "black",
     "height": "50px",
     "fontSize": "11px",
@@ -24,14 +24,14 @@
     "spacing": "3px",
     "list": [
       {
-        "iconPath": "/static/tabbar/tabbar-home-2.png",
-        "selectedIconPath": "/static/tabbar/tabbar-home.png",
+        "iconPath": "/static/tabbar/home.png",
+        "selectedIconPath": "/static/tabbar/home_selected.png",
         "pagePath": "pages/home/index",
         "text": "首页"
       },
       {
-        "iconPath": "/static/tabbar/tabbar-user-2.png",
-        "selectedIconPath": "/static/tabbar/tabbar-user.png",
+        "iconPath": "/static/tabbar/user.png",
+        "selectedIconPath": "/static/tabbar/user_selected.png",
         "pagePath": "pages/user/index",
         "text": "我的"
       }

+ 160 - 19
src/pages/home/index.vue

@@ -34,16 +34,10 @@
       <!-- 待办事项标题 -->
       <view class="todo-title-box">
         <text class="todo-title">我的待办事项</text>
-        <wd-picker
-          style="z-index: 999;"
-          class="equip-picker"
-          :model-value="equipType"
-          :columns="equipmentOptions"
-          label-key="label"
-          value-key="value"
-          placeholder="请选择"
-          @confirm="onEquipTypeChange"
-        />
+        <view class="equip-picker" @click="showEquipPopup = true">
+          <text class="equip-picker-text">{{ equipTypeLabel }}</text>
+          <text class="equip-picker-arrow">›</text>
+        </view>
       </view>
 
       <!-- 待办卡片列表 -->
@@ -86,6 +80,30 @@
     <view v-if="!networkStatus" class="network-toast">
       <text class="network-toast-text">当前网络不可用</text>
     </view>
+
+    <!-- 设备类型选择弹窗 -->
+    <view v-if="showEquipPopup" class="popup-mask" @click="showEquipPopup = false">
+      <view class="popup-content" @click.stop>
+        <view class="popup-header">
+          <text class="popup-title">选择设备类型</text>
+          <view class="popup-close" @click="showEquipPopup = false">
+            <text class="popup-close-icon">✕</text>
+          </view>
+        </view>
+        <view
+          v-for="item in equipOptions"
+          :key="item.value"
+          class="popup-option"
+          :class="{ 'popup-option-active': item.value === equipType }"
+          @click="onEquipSelect(item.value)"
+        >
+          <text class="popup-option-label">{{ item.label }}</text>
+          <view v-if="item.value === equipType" class="popup-option-check">
+            <text class="popup-check-icon">✓</text>
+          </view>
+        </view>
+      </view>
+    </view>
   </view>
 </template>
 
@@ -122,24 +140,51 @@ const userInfo = computed(() => userStore.userInfo)
 
 const configStore = useConfigStore()
 const equipType = computed(() => configStore.getEquipType())
+const showEquipPopup = ref(false)
+
+const equipTypeLabel = computed(() => {
+  const map: Record<string, string> = {
+    [EquipmentType.CONTAINER]: '压力容器',
+    [EquipmentType.BOILER]: '锅炉',
+    [EquipmentType.PIPE]: '管道',
+  }
+  return map[equipType.value] || '请选择'
+})
 
-const equipmentOptions = [
+const equipOptions = [
+  { label: '压力容器', value: EquipmentType.CONTAINER },
   { label: '锅炉', value: EquipmentType.BOILER },
   { label: '管道', value: EquipmentType.PIPE },
-  // { label: '压力容器', value: EquipmentType.CONTAINER },
 ]
 
-onShow(() => {
-  refreshAllCards()
-})
+const onEquipSelect = (value: EquipmentType) => {
+  if (value === EquipmentType.CONTAINER) {
+    // 容器:通知 RN 端跳转首页
+    if (window.ReactNativeWebView) {
+      window.ReactNativeWebView.postMessage(
+        JSON.stringify({ type: 'switchEquipType', equipType: EquipmentType.CONTAINER })
+      )
+    }
+    return
+  }
 
-const onEquipTypeChange = ({ value }: { value: string }) => {
-  if (value && value !== equipType.value) {
-    configStore.switchEquipType(value as any)
-    uni.reLaunch({ url: '/pages/home/index' })
+  // 锅炉、管道:切换设备类型
+  if (value !== equipType.value) {
+    configStore.switchEquipType(value)
+    refreshAllCards()
   }
+  showEquipPopup.value = false
 }
 
+onShow(() => {
+  // 登录后首次进入且未选择过设备类型,自动弹出选择弹窗
+  const hasChosenEquipType = equipType.value !== null
+  if (!hasChosenEquipType) {
+    showEquipPopup.value = true
+  }
+  refreshAllCards()
+})
+
 // 获取屏幕宽度
 const getWindowWidth = () => {
   const systemInfo = uni.getSystemInfoSync()
@@ -553,9 +598,23 @@ const onRefresh = () => {
 }
 
 .equip-picker {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
   flex-shrink: 0;
 }
 
+.equip-picker-text {
+  font-size: 14px;
+  color: #666;
+}
+
+.equip-picker-arrow {
+  margin-left: 4px;
+  font-size: 16px;
+  color: #999;
+}
+
 .todo-title {
   font-size: 18px;
   color: rgb(51, 51, 51);
@@ -638,4 +697,86 @@ const onRefresh = () => {
   font-size: 14px;
   color: #fff;
 }
+
+.popup-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 9999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.5);
+}
+
+.popup-content {
+  width: 80%;
+  max-width: 360px;
+  padding: 0 20px 20px;
+  background-color: #fff;
+  border-radius: 12px;
+}
+
+.popup-header {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  padding: 20px 0 16px;
+  border-bottom: 1px solid #eee;
+}
+
+.popup-title {
+  font-size: 18px;
+  font-weight: bold;
+  color: #333;
+}
+
+.popup-close {
+  padding: 4px;
+}
+
+.popup-close-icon {
+  font-size: 18px;
+  color: #999;
+}
+
+.popup-option {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  padding: 16px 12px;
+  margin-top: 8px;
+  background-color: #f9f9f9;
+  border-radius: 8px;
+  border-left: 4px solid transparent;
+}
+
+.popup-option-active {
+  border-left-color: #071f50;
+  background-color: #f0f4fa;
+}
+
+.popup-option-label {
+  font-size: 16px;
+  color: #333;
+}
+
+.popup-option-check {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 22px;
+  height: 22px;
+  background-color: #071f50;
+  border-radius: 11px;
+}
+
+.popup-check-icon {
+  font-size: 12px;
+  color: #fff;
+}
 </style>

+ 13 - 2
src/pages/loading/index.vue

@@ -53,6 +53,8 @@ import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
 import { useUserStore } from '@/store/user'
 import { loginByAppToken, getUserInfo, getMemberByDeptApi } from '@/api/login'
+import { EquipmentType } from '@/utils/dictMap'
+import { useConfigStore } from '@/store/config'
 
 defineOptions({
   name: 'loading',
@@ -65,6 +67,13 @@ interface PayloadData {
   [key: string]: any
 }
 
+interface LoginAppTokenParams {
+  token: string
+  userId: string
+  username: string
+  equipType?: EquipmentType
+}
+
 const statusText = ref('正在加载...')
 const fromType = ref('APP')
 
@@ -74,9 +83,11 @@ const payload = ref<PayloadData>({})
 // WEB模式表单
 const inputUserInfo = ref('')
 const inputPassword = ref('')
+const configStore = useConfigStore()
 
-const loginAppToken = (params: { token: string; userId: string; username: string }) => {
+const loginAppToken = (params: LoginAppTokenParams) => {
   doLogin(params.token, params.userId, params.username, '', 'APP')
+  configStore.switchEquipType(params.equipType)
 }
 window.loginAppToken = loginAppToken
 
@@ -172,7 +183,7 @@ const doLogin = async (
       userStore.setUserInfo({ ...info, token: loginData.accessToken })
     }
 
-    uni.switchTab({ url: '/pages/home/index' })
+    uni.reLaunch({ url: '/pages/home/index' })
   } catch (error) {
     console.error('[LoadingPage] 加载失败:', error)
     statusText.value = '加载失败,请重试'

+ 4 - 7
src/pages/taskOnline/TaskOnlineEquipmentList.vue

@@ -281,7 +281,7 @@ import {
 import dayjs from 'dayjs'
 import UpdateSafetyManagerPopup from '@/pages/unClaim/components/UpdateSafetyManagerPopup.vue'
 import { TaskOrderFuncName, requestFunc } from '@/api/ApiRouter/taskOrder'
-import { getBoilerTaskItemListByOrderId, addInspectProject } from '@/api/boiler/boilerTaskOrder'
+import { getBoilerTaskItemListByOrderId, addInspectProject, confirmBoilerEquipmentBatchClaim } from '@/api/boiler/boilerTaskOrder'
 import { updateEquipBoilerSecurityManager } from '@/api/boiler/boilerEquip'
 import NavBar from '@/components/NavBar/NavBar.vue'
 import BoilerCheckProject from '@/pages/taskOnline/components/BoilerCheckProject.vue'
@@ -445,13 +445,10 @@ const closeTipsPopup = () => {
 
 const handleBatchClaim = async () => {
   closeTipsPopup()
-  const ids = selectedEquipments.value.map((item: any) => item.id)
-  const params: { ids: string[]; isCancel?: true } = { ids }
-  if (tipsPopupData.value.isClaim) {
-    params.isCancel = true
-  }
+  const ids = selectedEquipments.value.map((item: any) => item.mainID)
+  const params: { orderItemIdList: string[] } = { orderItemIdList: ids }
   try {
-    const result = await batchClaim(params)
+    const result = await confirmBoilerEquipmentBatchClaim(params)
     updateClaim(result, ids, !tipsPopupData.value.isClaim)
   } catch (error) {
     uni.showToast({ title: '操作失败', icon: 'error' })

二進制
src/static/tabbar/home.png


二進制
src/static/tabbar/home_selected.png


二進制
src/static/tabbar/user.png


二進制
src/static/tabbar/user_selected.png