diff --git a/mobile/src/pages/xg/xsjcxx/xsjcxx/index.vue b/mobile/src/pages/xg/xsjcxx/xsjcxx/index.vue index a646bd0b..49b1e42a 100644 --- a/mobile/src/pages/xg/xsjcxx/xsjcxx/index.vue +++ b/mobile/src/pages/xg/xsjcxx/xsjcxx/index.vue @@ -10,6 +10,12 @@ + + + + 部分辅助数据正在后台加载中... + + @@ -95,7 +101,7 @@ 籍贯 - {{ getRegionFullPath(form.nativePlace) || '-' }} + {{ nativePlaceDisplayName || '-' }} 政治面貌 @@ -172,7 +178,7 @@ 生源地区 - {{ getRegionFullPath(form.sourceRegion) || '-' }} + {{ sourceRegionDisplayName || '-' }} @@ -782,38 +788,32 @@ export default { // 显示名称(异步加载) roomDisplayName: '', bedDisplayName: '', + nativePlaceDisplayName: '', // 籍贯显示名称 + sourceRegionDisplayName: '', // 生源地区显示名称 + + // 加载状态 + regionLoadingPromise: null, + backgroundDataLoaded: false, // 后台数据是否加载完成 }; }, async created() { console.log('=== 学生信息页面初始化开始 ==='); - try { - await this.loadDictData(); - console.log('✓ 字典数据加载完成'); - } catch (error) { - console.error('字典数据加载出错(不影响后续流程):', error); - } - - try { - await this.loadRegionAndDormData(); - console.log('✓ 区域和宿舍数据加载完成'); - } catch (error) { - console.error('区域和宿舍数据加载出错:', error); - } - - try { - await this.loadDormRoomAndBedData(); - console.log('✓ 房间和床位数据加载完成'); - } catch (error) { - console.error('房间和床位数据加载出错:', error); - } + // 第一阶段:立即加载核心个人信息,让页面内容快速显示 try { + this.loading = true; await this.getPersonalInfoData(); - console.log('✓ 个人信息加载完成'); + console.log('✓ 核心个人信息加载完成,页面可以显示'); } catch (error) { - console.error('个人信息加载出错:', error); + console.error('个人信息加载失败:', error); + // 即使个人信息加载失败,也要设置loading为false,避免页面一直loading + this.loading = false; } + + // 第二阶段:并行加载辅助数据(不阻塞页面显示) + this.loadSupportingDataInBackground(); + console.log('=== 学生信息页面初始化完成 ==='); }, @@ -1054,6 +1054,256 @@ export default { return getDictTagType(this.studentStatusOptions, this.form.studentStatus, fallbackMap); }, + // 后台并行加载辅助数据 + async loadSupportingDataInBackground() { + console.log('开始后台加载辅助数据...'); + + // 第一阶段:并行加载所有非核心数据,互不阻塞 + const loadPromises = [ + this.loadDictDataSafely(), + this.loadDormDataSafely(), + this.loadDormRoomAndBedDataSafely(), + ]; + + // 使用Promise.allSettled确保即使某些请求失败也不影响其他 + const results = await Promise.allSettled(loadPromises); + + results.forEach((result, index) => { + const taskNames = ['字典数据', '宿舍数据', '房间床位数据']; + if (result.status === 'fulfilled') { + console.log(`✓ ${taskNames[index]}后台加载完成`); + } else { + console.warn(`✗ ${taskNames[index]}后台加载失败:`, result.reason); + } + }); + + // 第二阶段:更新宿舍相关显示名称(不依赖区域数据) + try { + await this.updateDisplayNamesAfterBackgroundLoad(); + console.log('✓ 后台数据加载后显示名称更新完成'); + } catch (error) { + console.warn('后台数据加载后显示名称更新失败:', error); + } + + // 第三阶段:尝试加载区域数据并更新区域显示名称(可选,不阻塞整体完成) + this.loadRegionDataAndUpdateDisplay(); + + console.log('=== 后台辅助数据加载完成 ==='); + this.backgroundDataLoaded = true; + }, + + // 安全加载字典数据(出错不影响页面) + async loadDictDataSafely() { + try { + await this.loadDictData(); + } catch (error) { + console.warn('字典数据加载失败,使用默认值:', error); + // 确保字典数组不为undefined + this.ensureDictArraysExist(); + } + }, + + // 安全加载宿舍数据(出错不影响页面) + async loadDormDataSafely() { + try { + await this.loadDormBuildingData(); + } catch (error) { + console.warn('宿舍数据加载失败,使用默认值:', error); + this.dormBuildingOptions = []; + } + }, + + // 安全加载房间床位数据(出错不影响页面) + async loadDormRoomAndBedDataSafely() { + try { + await this.loadDormRoomAndBedData(); + } catch (error) { + console.warn('房间床位数据加载失败,使用默认值:', error); + this.dormRoomOptions = []; + this.dormBedOptions = []; + } + }, + + // 设置临时显示名称,避免页面空白 + setTemporaryDisplayNames() { + // 设置临时的区域显示名称 + if (this.form.nativePlace) { + this.nativePlaceDisplayName = `区域${this.form.nativePlace}`; + } + if (this.form.sourceRegion) { + this.sourceRegionDisplayName = `区域${this.form.sourceRegion}`; + } + + // 房间和床位显示名称暂时留空,将在后台数据加载完成后更新 + console.log('临时显示名称已设置'); + }, + + // 异步加载区域数据并更新显示名称(不阻塞主流程) + async loadRegionDataAndUpdateDisplay() { + try { + console.log('开始异步加载区域数据...'); + await this.loadRegionDataLazily(); + + // 区域数据加载完成后,更新区域显示名称 + if (this.form.nativePlace) { + const nativePlaceName = this.buildRegionPath(this.form.nativePlace); + if (nativePlaceName !== `区域${this.form.nativePlace}`) { + this.nativePlaceDisplayName = nativePlaceName; + console.log('✓ 异步更新籍贯名称:', nativePlaceName); + } + } + + if (this.form.sourceRegion) { + const sourceRegionName = this.buildRegionPath(this.form.sourceRegion); + if (sourceRegionName !== `区域${this.form.sourceRegion}`) { + this.sourceRegionDisplayName = sourceRegionName; + console.log('✓ 异步更新生源地区名称:', sourceRegionName); + } + } + + console.log('✓ 区域数据加载和显示名称更新完成'); + } catch (error) { + console.warn('区域数据加载失败,保持临时显示名称:', error); + } + }, + + // 后台数据加载完成后更新显示名称(仅处理宿舍相关) + async updateDisplayNamesAfterBackgroundLoad() { + const updatePromises = []; + + // 更新房间和床位名称(需要宿舍数据) + if (this.form.dormitoryRoom) { + updatePromises.push( + this.getRoomName(this.form.dormitoryRoom) + .then((name) => { + this.roomDisplayName = name; + console.log('✓ 后台更新房间名称:', name); + }) + .catch((error) => { + console.warn('后台更新房间名称失败:', error); + }), + ); + } + + if (this.form.extField1) { + updatePromises.push( + this.getBedName(this.form.extField1) + .then((name) => { + this.bedDisplayName = name; + console.log('✓ 后台更新床位名称:', name); + }) + .catch((error) => { + console.warn('后台更新床位名称失败:', error); + }), + ); + } + + // 等待所有宿舍相关更新完成 + await Promise.allSettled(updatePromises); + console.log('宿舍相关显示名称更新完成'); + }, + + // 确保字典数组存在,避免页面报错 + ensureDictArraysExist() { + const dictArrays = [ + 'genderOptions', + 'nationalityOptions', + 'politicalStatusOptions', + 'educationLevelOptions', + 'householdRegisterTypeOptions', + 'maritalStatusOptions', + 'yesNoOptions', + 'familyEconomicOptions', + 'bloodTypeOptions', + 'disabilityTypeOptions', + 'academicLevelOptions', + 'trainingModeOptions', + 'admissionCategoryOptions', + 'studentStatusOptions', + ]; + + dictArrays.forEach((arrayName) => { + if (!this[arrayName] || !Array.isArray(this[arrayName])) { + this[arrayName] = []; + } + }); + }, + + // 单独加载宿舍楼栋数据 + async loadDormBuildingData() { + console.log('开始加载宿舍楼栋数据...'); + try { + const dormRes = await request({ + url: '/xgss/dormBuildingTree/listAll', + method: 'GET', + }); + + if (dormRes && dormRes.data) { + this.dormBuildingOptions = this.processDormTreeData(dormRes.data); + console.log('宿舍楼栋数据处理完成,条目数:', this.dormBuildingOptions.length); + } else { + console.warn('宿舍楼栋数据加载失败或为空'); + this.dormBuildingOptions = []; + } + } catch (error) { + console.error('加载宿舍楼栋数据失败:', error); + this.dormBuildingOptions = []; + throw error; + } + }, + + // 懒加载行政区划数据(仅在需要时加载) + async loadRegionDataLazily() { + // 如果已经加载过,直接返回 + if (this.regionOptions && this.regionOptions.length > 0) { + return this.regionOptions; + } + + // 如果正在加载中,等待加载完成 + if (this.regionLoadingPromise) { + return await this.regionLoadingPromise; + } + + // 开始加载 + this.regionLoadingPromise = this.doLoadRegionData(); + + try { + await this.regionLoadingPromise; + return this.regionOptions; + } finally { + this.regionLoadingPromise = null; + } + }, + + // 实际执行行政区划数据加载 + async doLoadRegionData() { + console.log('懒加载行政区划数据...'); + try { + const regionRes = await request({ + url: '/system/SysRegion/tree', + method: 'GET', + }); + + if (regionRes && regionRes.data) { + this.regionOptions = regionRes.data; + console.log('行政区划数据懒加载完成,条目数:', regionRes.data.length); + } else { + console.warn('行政区划数据懒加载失败或为空'); + this.regionOptions = []; + } + } catch (error) { + console.error('懒加载行政区划数据失败:', error); + this.regionOptions = []; + // 显示用户友好的错误提示 + uni.showToast({ + title: '区域数据加载失败', + icon: 'none', + duration: 2000, + }); + throw error; + } + }, + // 加载字典数据 async loadDictData() { console.log('开始加载字典数据...'); @@ -1163,105 +1413,6 @@ export default { } }, - // 加载行政区划和宿舍楼栋数据 - async loadRegionAndDormData() { - console.log('开始加载区域和宿舍数据...'); - try { - console.log('发起并行请求: 行政区划 & 宿舍楼栋'); - const [regionRes, dormRes] = await Promise.all([ - request({ - url: '/system/SysRegion/tree', - method: 'GET', - }) - .then((res) => { - console.log('✓ 行政区划请求完成'); - return res; - }) - .catch((err) => { - console.error('✗ 行政区划请求失败:', err); - throw err; - }), - request({ - url: '/xgss/dormBuildingTree/listAll', - method: 'GET', - }) - .then((res) => { - console.log('✓ 宿舍楼栋请求完成'); - return res; - }) - .catch((err) => { - console.error('✗ 宿舍楼栋请求失败:', err); - throw err; - }), - ]); - - // 处理行政区划数据 - if (regionRes && regionRes.data) { - this.regionOptions = regionRes.data; - console.log('行政区划数据处理完成,条目数:', regionRes.data.length); - } else { - console.warn('行政区划数据加载失败或为空'); - } - - // 处理宿舍楼栋数据,添加性别标识 - if (dormRes && dormRes.data) { - console.log('dormRes', dormRes); - this.dormBuildingOptions = this.processDormTreeData(dormRes.data); - console.log('宿舍楼栋数据处理完成,条目数:', this.dormBuildingOptions.length); - } else { - console.warn('宿舍楼栋数据加载失败或为空'); - this.dormBuildingOptions = []; - } - } catch (error) { - console.error('加载区域和宿舍数据失败:', error); - uni.showToast({ - title: '加载基础数据失败,部分功能可能受影响', - icon: 'none', - duration: 3000, - }); - } - }, - - // 处理宿舍楼栋树形数据,为楼栋添加性别标识 - processDormTreeData(nodes) { - console.log('processDormTreeData - nodes', nodes); - if (!nodes || !Array.isArray(nodes)) { - console.warn('宿舍楼栋数据格式不正确'); - return []; - } - - return nodes.map((node) => { - const processedNode = { ...node }; - - // 如果是楼栋类型,添加性别标识 - if (node.type === 'building' && node.buildingType) { - console.log('node.buildingType', node.buildingType); - const genderSuffix = - node.buildingType === '1' - ? '(男)' - : node.buildingType === '2' - ? '(女)' - : ''; - - // 确保 label 和 name 存在后再添加后缀 - if (node.label) { - processedNode.label = node.label + genderSuffix; - } - if (node.name) { - processedNode.name = node.name + genderSuffix; - } - } - - // 递归处理子节点 - if (node.children && node.children.length > 0) { - processedNode.children = this.processDormTreeData(node.children); - } - console.log('processedNode', processedNode); - - return processedNode; - }); - }, - // 加载房间和床位数据(改为按需加载) async loadDormRoomAndBedData() { console.log('房间和床位数据改为按需加载模式,不再预加载所有数据'); @@ -1270,29 +1421,70 @@ export default { this.dormBedOptions = []; }, - // 异步加载房间和床位显示名称 - async loadRoomAndBedDisplayNames() { + // 异步加载各种显示名称(房间、床位、区域) + async loadDisplayNames() { try { - // 加载房间名称 + // 并行加载房间和床位名称 + const loadPromises = []; + if (this.form.dormitoryRoom) { - this.roomDisplayName = await this.getRoomName(this.form.dormitoryRoom); - console.log('房间名称加载完成:', this.roomDisplayName); + loadPromises.push( + this.getRoomName(this.form.dormitoryRoom).then((name) => { + this.roomDisplayName = name; + console.log('房间名称加载完成:', name); + }), + ); } - // 加载床位名称 if (this.form.extField1) { - this.bedDisplayName = await this.getBedName(this.form.extField1); - console.log('床位名称加载完成:', this.bedDisplayName); + loadPromises.push( + this.getBedName(this.form.extField1).then((name) => { + this.bedDisplayName = name; + console.log('床位名称加载完成:', name); + }), + ); } + + // 并行加载区域显示名称(不阻塞房间床位显示) + if (this.form.nativePlace) { + loadPromises.push( + this.getRegionFullPathAsync(this.form.nativePlace) + .then((name) => { + this.nativePlaceDisplayName = name; + console.log('籍贯显示名称加载完成:', name); + }) + .catch((error) => { + console.warn('籍贯显示名称加载失败:', error); + this.nativePlaceDisplayName = `区域${this.form.nativePlace}`; + }), + ); + } + + if (this.form.sourceRegion) { + loadPromises.push( + this.getRegionFullPathAsync(this.form.sourceRegion) + .then((name) => { + this.sourceRegionDisplayName = name; + console.log('生源地区显示名称加载完成:', name); + }) + .catch((error) => { + console.warn('生源地区显示名称加载失败:', error); + this.sourceRegionDisplayName = `区域${this.form.sourceRegion}`; + }), + ); + } + + // 等待所有显示名称加载完成(使用 allSettled 确保部分失败不影响其他) + await Promise.allSettled(loadPromises); + console.log('所有显示名称加载完成'); } catch (error) { - console.error('加载房间和床位显示名称失败:', error); + console.error('加载显示名称失败:', error); } }, // 获取学生个人信息 async getPersonalInfoData() { try { - this.loading = true; const response = await request({ url: '/studentMsg/studentMsg/personalInfo', method: 'GET', @@ -1331,8 +1523,10 @@ export default { extField1Type: typeof this.form.extField1, }); - // 异步加载房间和床位信息 - await this.loadRoomAndBedDisplayNames(); + // 立即设置临时显示名称,避免空白 + this.setTemporaryDisplayNames(); + + console.log('✓ 个人信息加载完成,页面可以显示'); } else { uni.showToast({ title: response.msg || '获取个人信息失败', @@ -1437,9 +1631,63 @@ export default { } }, - // 根据行政区划代码获取完整路径(省/市/区) - getRegionFullPath(code) { - if (!code || !this.regionOptions) return ''; + // 处理宿舍楼栋树形数据,为楼栋添加性别标识 + processDormTreeData(nodes) { + console.log('processDormTreeData - nodes', nodes); + if (!nodes || !Array.isArray(nodes)) { + console.warn('宿舍楼栋数据格式不正确'); + return []; + } + + return nodes.map((node) => { + const processedNode = { ...node }; + + // 如果是楼栋类型,添加性别标识 + if (node.type === 'building' && node.buildingType) { + console.log('node.buildingType', node.buildingType); + const genderSuffix = + node.buildingType === '1' + ? '(男)' + : node.buildingType === '2' + ? '(女)' + : ''; + + // 确保 label 和 name 存在后再添加后缀 + if (node.label) { + processedNode.label = node.label + genderSuffix; + } + if (node.name) { + processedNode.name = node.name + genderSuffix; + } + } + + // 递归处理子节点 + if (node.children && node.children.length > 0) { + processedNode.children = this.processDormTreeData(node.children); + } + console.log('processedNode', processedNode); + + return processedNode; + }); + }, + + // 异步获取区域完整路径(用于后台加载) + async getRegionFullPathAsync(code) { + if (!code) return ''; + + // 懒加载区域数据 + await this.loadRegionDataLazily(); + + // 获取完整路径 + return this.buildRegionPath(code); + }, + + // 构建区域路径(纯计算,不触发加载) + buildRegionPath(code) { + if (!code || !this.regionOptions || this.regionOptions.length === 0) { + return `区域${code}`; + } + const path = []; const findPath = (nodes, targetCode) => { for (const node of nodes) { @@ -1456,8 +1704,58 @@ export default { } return false; }; - findPath(this.regionOptions, code); - return path.join(' / '); + + if (findPath(this.regionOptions, code)) { + return path.join(' / '); + } + + return `区域${code}`; + }, + + // 根据行政区划代码获取完整路径(省/市/区)- 同步版本,用于模板(已弃用) + getRegionFullPath(code) { + if (!code) return ''; + + // 如果行政区划数据未加载,触发懒加载并返回临时显示 + if (!this.regionOptions || this.regionOptions.length === 0) { + // 异步加载区域数据,不阻塞当前显示 + this.loadRegionDataLazily() + .then(() => { + // 加载完成后触发页面更新 + this.$forceUpdate(); + }) + .catch(() => { + // 加载失败时显示代码 + console.warn('行政区划数据懒加载失败,显示原始代码'); + }); + + // 返回代码作为临时显示 + return `区域${code}`; + } + + const path = []; + const findPath = (nodes, targetCode) => { + for (const node of nodes) { + path.push(node.name); + if (node.code === targetCode) { + return true; + } + if (node.children && node.children.length > 0) { + if (findPath(node.children, targetCode)) { + return true; + } + } + path.pop(); + } + return false; + }; + + if (findPath(this.regionOptions, code)) { + return path.join(' / '); + } + + // 如果找不到,返回代码 + return `区域${code}`; }, // 根据楼栋ID获取楼栋名称(含性别标识) @@ -1726,6 +2024,21 @@ export default { min-height: 100vh; } +.background-loading-tip { + display: flex; + align-items: center; + justify-content: center; + padding: 16rpx 30rpx; + background-color: #f0f9ff; + border-bottom: 1px solid #e1ecf4; + gap: 8rpx; +} + +.tip-text { + font-size: 24rpx; + color: #606266; +} + .content-wrapper { padding: 20rpx; padding-bottom: 40rpx;