Files
smartDriveEEUniApp/pages/ai_analysis/ai_analysis.vue
zhonghua.li 303315e840 1
2026-04-20 20:54:20 +08:00

312 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- #ifdef APP -->
<statusBar></statusBar>
<!-- #endif -->
<!-- 导航栏 -->
<uni-nav-bar
:fixed="true"
:statusBar="true"
title="AI销冠系统"
leftIcon="left"
@clickLeft="goBack"
color="#333"
backgroundColor="#FFFFFF">
</uni-nav-bar>
<view class="content">
<soft-sales-scenario
:content-top="computedContentTop || contentTop"
:content-bottom="contentBottom"
/>
</view>
</view>
</template>
<script>
// #ifdef APP
import statusBar from "@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar";
// #endif
import SoftSalesScenario from '@/components/soft_sales_scenario.vue';
// 注意:子包组件不使用 import 导入,而是通过 componentPlaceholder 配置
// 这样可以确保子包异步加载时组件能正确找到
// CustomerCountPopup, QualityCoveragePopup 通过 componentPlaceholder 自动注册
// 获取系统信息的辅助函数,优先使用新 API
function getSystemInfo() {
// #ifdef MP-WEIXIN
// 微信小程序:优先使用新的 API
if (typeof wx !== 'undefined' && wx.getWindowInfo) {
try {
const windowInfo = wx.getWindowInfo();
return {
statusBarHeight: windowInfo.statusBarHeight || 20,
windowWidth: windowInfo.windowWidth,
windowHeight: windowInfo.windowHeight
};
} catch (e) {
console.warn('[AIAnalysis] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:', e);
}
}
// #endif
// 回退到旧的 API 或使用 uni-app 的 API
try {
const systemInfo = uni.getSystemInfoSync();
return {
statusBarHeight: systemInfo.statusBarHeight || 20,
windowWidth: systemInfo.windowWidth,
windowHeight: systemInfo.windowHeight
};
} catch (e) {
console.error('[AIAnalysis] Failed to get system info:', e);
return {
statusBarHeight: 20,
windowWidth: 375,
windowHeight: 667
};
}
}
export default {
// #ifdef APP
components: {
statusBar,
SoftSalesScenario,
},
// #endif
// #ifndef APP
components: {
SoftSalesScenario,
},
// #endif
data() {
// 动态计算导航栏高度
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight; // 默认20px
const navbarHeight = 44; // navbar高度44px
// 转换为rpx1px = 2rpx在375px设计稿下
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
return {
contentTop: totalNavbarHeight + 'rpx', // 内容区域距离顶部的距离
contentBottom: '96rpx', // 内容区域距离底部的距离(默认值,会在 onReady 中更新)
subpackageLoaded: false, // 子包是否已加载
}
},
computed: {
// 计算内容区域的位置(使用计算属性确保响应式)
computedContentTop() {
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
const navbarHeight = 44;
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
return totalNavbarHeight + 'rpx';
}
},
onLoad() {
// 更新导航栏位置
this.updateNavbarPosition();
// 在微信小程序中,子包会在组件使用时自动加载
// 但我们可以尝试预加载以提高响应速度
// #ifdef MP-WEIXIN
// 延迟预加载,避免阻塞页面初始化
setTimeout(() => {
this.preloadSubpackage();
}, 100);
// #endif
},
onShow() {
// 每次页面显示时都重新计算导航栏位置
this.$nextTick(() => {
this.updateNavbarPosition();
setTimeout(() => {
this.updateNavbarPosition();
}, 50);
});
},
onReady() {
// 页面渲染完成后,查询实际导航栏高度并更新位置
this.$nextTick(() => {
// 查询导航栏实际高度
const query = uni.createSelectorQuery().in(this);
query.select('.uni-navbar__content').boundingClientRect((data) => {
if (data && data.height) {
// 使用实际高度(已经是包含状态栏的总高度)
const actualHeight = data.height; // 实际导航栏高度px
// 转换为rpx1px = 2rpx在375px设计稿下
const actualHeightRpx = actualHeight * 2;
// 稍微减小一点,确保紧贴
const adjustedHeight = Math.max(actualHeightRpx - 4, 0);
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
console.log('[AIAnalysis] 使用实际导航栏高度:', actualHeight, 'px =', actualHeightRpx, 'rpx, 调整后:', adjustedHeight, 'rpx');
} else {
// 如果查询失败,使用默认计算并减小一点
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
const navbarHeight = 44;
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
const adjustedHeight = Math.max(totalNavbarHeight - 4, 0);
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
}
}).exec();
// 查询底部 tabbar 实际高度
const queryTabbar = uni.createSelectorQuery().in(this);
queryTabbar.select('.tabbar').boundingClientRect((tabbarData) => {
if (tabbarData && tabbarData.height) {
// 使用实际高度
const tabbarHeight = tabbarData.height; // tabbar 实际高度px
const tabbarHeightRpx = tabbarHeight * 2;
// 稍微减小一点,确保紧贴
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
this.$set(this, 'contentBottom', adjustedBottom + 'rpx');
console.log('[AIAnalysis] 使用实际tabbar高度:', tabbarHeight, 'px =', tabbarHeightRpx, 'rpx, 调整后:', adjustedBottom, 'rpx');
} else {
// 如果查询失败,使用默认值
this.$set(this, 'contentBottom', '96rpx');
}
}).exec();
// 延迟再次更新确保DOM已渲染
setTimeout(() => {
// 再次查询并更新导航栏
const query2 = uni.createSelectorQuery().in(this);
query2.select('.uni-navbar__content').boundingClientRect((data) => {
if (data && data.height) {
const actualHeight = data.height;
const actualHeightRpx = actualHeight * 2;
// 稍微减小一点,确保紧贴
const adjustedHeight = Math.max(actualHeightRpx - 4, 0);
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
console.log('[AIAnalysis] 延迟更新导航栏高度:', actualHeight, 'px =', actualHeightRpx, 'rpx, 调整后:', adjustedHeight, 'rpx');
}
}).exec();
// 再次查询 tabbar 高度
const queryTabbar2 = uni.createSelectorQuery().in(this);
queryTabbar2.select('.tabbar').boundingClientRect((tabbarData) => {
if (tabbarData && tabbarData.height) {
const tabbarHeight = tabbarData.height;
const tabbarHeightRpx = tabbarHeight * 2;
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
this.$set(this, 'contentBottom', adjustedBottom + 'rpx');
console.log('[AIAnalysis] 延迟更新tabbar高度:', tabbarHeight, 'px =', tabbarHeightRpx, 'rpx, 调整后:', adjustedBottom, 'rpx');
}
}).exec();
}, 200);
});
},
methods: {
// 预加载子包
// #ifdef MP-WEIXIN
preloadSubpackage() {
// 使用微信原生 API 预加载子包
if (typeof wx !== 'undefined' && wx.loadSubpackage) {
wx.loadSubpackage({
name: 'pages-subpackage',
success: () => {
console.log('[AIAnalysis] Subpackage loaded successfully');
this.subpackageLoaded = true;
},
fail: (err) => {
console.error('[AIAnalysis] Failed to load subpackage:', err);
// 即使加载失败,也尝试继续(可能已经加载过了)
this.subpackageLoaded = true;
}
});
} else {
// 如果 API 不可用,标记为已加载(可能已经自动加载)
console.log('[AIAnalysis] loadSubpackage API not available, assuming subpackage will load automatically');
this.subpackageLoaded = true;
}
},
// #endif
// 计算并更新导航栏和内容区域的位置
updateNavbarPosition() {
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
const navbarHeight = 44;
// 转换为rpx1px = 2rpx在375px设计稿下
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
const contentTop = totalNavbarHeight + 'rpx';
this.$set(this, 'contentTop', contentTop);
// #ifdef MP-WEIXIN
this.$forceUpdate();
// #endif
},
goBack() {
// 检查页面栈,如果当前是第一个页面,则不能返回
const pages = getCurrentPages();
if (pages.length <= 1) {
console.log('[AIAnalysis][goBack] 当前是第一个页面,无法返回');
return;
}
uni.navigateBack({
fail: (err) => {
console.error('[AIAnalysis][goBack] 返回失败:', err);
}
});
}
}
}
</script>
<style scoped>
page {
background-color: #F5F5F5;
}
.page {
min-height: 100vh;
background-color: #f5f5f5;
}
.content {
padding-top: 0 !important;
margin-top: 0 !important;
position: relative;
width: 100%;
min-height: calc(100vh - 200rpx);
top: 0;
}
/* 隐藏导航栏占位区域,避免产生空白 */
::v-deep .uni-navbar__placeholder {
display: none !important;
height: 0 !important;
}
::v-deep .uni-navbar__placeholder-view {
display: none !important;
height: 0 !important;
}
/* 隐藏底部 tabBar 占位区域,避免产生空白(类似顶部导航栏的处理方式) */
/* 注意:只隐藏占位符,不隐藏实际的 tabbar */
::v-deep [class*="tabbar"][class*="placeholder"] {
display: none !important;
height: 0 !important;
}
/* 隐藏可能的页面底部安全区域占位符 */
::v-deep [class*="safe-area"][class*="bottom"],
::v-deep [class*="bottom"][class*="safe"] {
display: none !important;
height: 0 !important;
}
</style>