gaoluyang
2 天以前 0e053f43fe591be3e0e92e3cfb4ad90d660b0546
中兴实强app
1.白屏问题解决
已添加1个文件
已修改5个文件
130 ■■■■ 文件已修改
debug-uniapp-white-screen.md 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/oa/ReimburseManage/reimburse-form/useFinReimburseForm.js 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/versionUpgrade.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
debug-uniapp-white-screen.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
# Debug Session: uniapp-white-screen
**Status:** [OPEN]
**Created:** 2026-05-28
## Problem Description
UniApp çœŸæœºè¿è¡ŒæŠ¥é”™ç™½å±ï¼š
```
reportJSException >>>> exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->
  at s (app-service.js:15:401)
  at  (app-service.js:942:153013)
  at  (app-service.js:1041:51133)
```
## Environment
- Platform: UniApp
- Target: Android/iOS App
- Build Tool: Vite
## Hypotheses
1. **H1: SCSS/预处理器配置问题** - `modern-compiler` API ä¸å…¼å®¹çœŸæœºçŽ¯å¢ƒ
   - Status: Tested, changed to `legacy`, issue persists
2. **H2: JavaScript è¯­æ³•兼容性问题** - ä½¿ç”¨äº†çœŸæœº JavaScriptCore ä¸æ”¯æŒçš„ ES6+ è¯­æ³•
   - Observation Points: æ£€æŸ¥å¯é€‰é“¾æ“ä½œç¬¦ `?.`、空值合并 `??`、BigInt ç­‰
3. **H3: æŸä¸ªé¡µé¢æˆ–组件存在语法错误** - ç‰¹å®šæ–‡ä»¶çš„语法错误导致整个应用无法启动
   - Observation Points: æ£€æŸ¥æœ€è¿‘修改的文件,特别是 works.vue
4. **H4: ä¾èµ–包版本不兼容** - æŸäº› npm åŒ…使用了不兼容真机的语法
   - Observation Points: æ£€æŸ¥ package.json ä¸­çš„依赖版本
5. **H5: æž„建产物损坏或缓存问题** - éœ€è¦æ¸…除缓存重新构建
   - Observation Points: æ£€æŸ¥ dist ç›®å½•和构建日志
## Evidence Log
### Step 1: Initial Analysis
- File works.vue structure appears valid
- Template tags properly closed
- SCSS configuration changed from `modern-compiler` to `legacy`
### Step 2: ES6+ Syntax Check
**FOUND ISSUE**: Project uses extensive ES2020 syntax that is not supported in older JavaScriptCore:
- Optional chaining (`?.`) - found 100+ occurrences
- Nullish coalescing (`??`) - found 50+ occurrences
**Files with problematic syntax:**
- `src/store/modules/user.ts`
- `src/utils/versionUpgrade.js`
- `src/pages/sales/salesQuotation/*.vue`
- `src/pages/productionManagement/**/*.vue`
- `src/pages/oa/_utils/*.js`
- Many more...
### Step 3: Fix Applied
Updated `vite.config.js` to set build target to ES2015 to ensure proper transpilation of ES2020 syntax.
### Step 4: Root Cause Found - Store Initialization Issue
**CRITICAL ISSUE**: In `useFinReimburseForm.js`, `useUserStore()` was called at module level (line 37), which causes Pinia store initialization before Vue app context is ready.
**This is the main cause of `createInstanceContext failed` error!**
### Step 5: Fix Applied
- Modified `useFinReimburseForm.js` to use lazy initialization pattern
- Store is now created only when `getUserStore()` is called within function scope
## Summary of All Fixes
1. âœ… vite.config.js - SCSS api changed to `legacy`
2. âœ… vite.config.js - Build target set to `es2015`
3. âœ… App.vue - Changed `<div>` to `<view>`
4. âœ… user.ts - Fixed optional chaining syntax
5. âœ… versionUpgrade.js - Fixed optional chaining and nullish coalescing syntax
6. âœ… useFinReimburseForm.js - Fixed store initialization timing
## Next Steps
1. Clear build cache: `rd /s /q dist`
2. Rebuild and test on real device
3. If still failing, check for other module-level store calls
src/App.vue
@@ -1,8 +1,8 @@
<template>
  <Splash v-if="showSplash" />
  <div v-else>
  <view v-else>
    <router-view />
  </div>
  </view>
</template>
<script setup>
  import { ref, onMounted } from "vue";
src/pages/oa/ReimburseManage/reimburse-form/useFinReimburseForm.js
@@ -34,7 +34,14 @@
  getTravelStandardByTier,
} from "../_utils/travelReimburseUtils.js";
const userStore = useUserStore();
// å»¶è¿Ÿåˆå§‹åŒ– userStore,避免在模块加载时调用
let userStore = null;
function getUserStore() {
  if (!userStore) {
    userStore = useUserStore();
  }
  return userStore;
}
function buildOverBudgetWarnings(f, detailTotal, hotelLimit, transportLimit, mealLimit) {
  const warnings = [];
@@ -198,14 +205,15 @@
  /** æ–°å¢žæ—¶é»˜è®¤å¸¦å‡ºå½“前登录人,减少选人步骤 */
  function tryApplyCurrentUser() {
    if (modeRef.value === "edit" || form.applicantId) return;
    const id = userStore.id;
    const store = getUserStore();
    const id = store.id;
    if (!id) return;
    let u = userById(id);
    if (!u) {
      u = {
        userId: id,
        nickName: userStore.nickName,
        userName: userStore.name,
        nickName: store.nickName,
        userName: store.name,
      };
    }
    fillApplicantFromUser(u);
src/store/modules/user.ts
@@ -33,7 +33,7 @@
      return new Promise((resolve, reject) => {
        loginCheckFactory(userName, password, factoryId)
          .then((res: any) => {
            const token = res.token || res.data?.token;
            const token = res.token || (res.data && res.data.token);
            if (token) {
              setToken(token);
              this.token = token;
src/utils/versionUpgrade.js
@@ -26,12 +26,12 @@
}
async function getCurrentVersion(logPrefix) {
  let currentVersion = config?.appInfo?.version || "1.0.0";
  let currentVersion = (config && config.appInfo && config.appInfo.version) || "1.0.0";
  console.log(`${logPrefix} å¼€å§‹èŽ·å–å½“å‰ç‰ˆæœ¬ï¼Œé»˜è®¤å€¼:`, currentVersion);
  // #ifdef MP-WEIXIN
  try {
    const accountInfo = uni.getAccountInfoSync();
    if (accountInfo?.miniProgram?.version) {
    if (accountInfo && accountInfo.miniProgram && accountInfo.miniProgram.version) {
      currentVersion = accountInfo.miniProgram.version;
      console.log(`${logPrefix} å½“前环境=MP-WEIXIN,版本=`, currentVersion);
      return currentVersion;
@@ -45,14 +45,14 @@
    // APP-PLUS ä¸‹ï¼Œplus.runtime.version ä¸æ˜¯ä¸šåŠ¡ç‰ˆæœ¬å·ï¼ˆç»å¸¸æ˜¯è¿è¡Œæ—¶/SDK版本),
    // è¿™é‡Œæ”¹ç”¨ getProperty å–系统层面的 app version。
    // @ts-ignore
    if (plus?.runtime?.getProperty) {
    if (plus && plus.runtime && plus.runtime.getProperty) {
      // @ts-ignore
      const appid = plus.runtime.appid;
      const appInfo = await new Promise((resolve) => {
        // @ts-ignore
        plus.runtime.getProperty(appid, (info) => resolve(info || {}));
      });
      const v = appInfo?.version || appInfo?.versionName || appInfo?.appVersion || "";
      const v = (appInfo && appInfo.version) || (appInfo && appInfo.versionName) || (appInfo && appInfo.appVersion) || "";
      if (v) {
        currentVersion = String(v);
        console.log(`${logPrefix} å½“前环境=APP-PLUS,版本=`, currentVersion);
@@ -90,7 +90,7 @@
    },
    (err) => {
      console.log(`${logPrefix} å®‰è£…失败:`, err);
      uni.showToast({ title: err?.message || "安装更新包失败", icon: "none" });
      uni.showToast({ title: (err && err.message) || "安装更新包失败", icon: "none" });
    }
  );
  // #endif
@@ -101,7 +101,7 @@
  if (!u) return "";
  // å·²ç»æ˜¯ç»å¯¹åœ°å€ï¼Œç›´æŽ¥è¿”回
  if (/^https?:\/\//i.test(u)) return u;
  const base = String(config?.fileUrl || config?.baseUrl || "").replace(/\/+$/, "");
  const base = String((config && config.fileUrl) || (config && config.baseUrl) || "").replace(/\/+$/, "");
  const path = u.startsWith("/") ? u : `/${u}`;
  return `${base}${path}`;
}
vite.config.js
@@ -7,6 +7,10 @@
        build: {
            minify: true,
            outDir: 'dist',
            target: 'es2015',
        },
        esbuild: {
            target: 'es2015',
        },
        server: {
            port: '80'
@@ -20,9 +24,14 @@
        css: {
            preprocessorOptions: {
                scss: {
                    api: 'modern-compiler'
                    api: 'legacy'
                }
            }
        }
        },
        optimizeDeps: {
            esbuildOptions: {
                target: 'es2015',
            },
        },
    }
})
})