REFactor => 移除安全区域相关功能和测试页面,简化导航组件,优化主入口文件结构。

This commit is contained in:
超级老白兔
2025-07-31 16:38:35 +08:00
parent 599d67141f
commit c5d4e80e7c
5 changed files with 2 additions and 610 deletions

View File

@@ -1,8 +1,7 @@
import React, { useState, useEffect } from "react";
import React from "react";
import { NavBar } from "antd-mobile";
import { ArrowLeftOutlined } from "@ant-design/icons";
import { useNavigate } from "react-router-dom";
import { getTopSafeAreaHeight, initSafeArea } from "@/utils/safeArea";
interface NavCommonProps {
title: string;
@@ -18,49 +17,8 @@ const NavCommon: React.FC<NavCommonProps> = ({
left,
}) => {
const navigate = useNavigate();
const [topBarHeight, setTopBarHeight] = useState<number>(0);
useEffect(() => {
// 初始化安全区域
initSafeArea();
// 计算顶部安全区域高度
const calculateTopBarHeight = () => {
const height = getTopSafeAreaHeight();
setTopBarHeight(height);
};
// 立即计算一次
calculateTopBarHeight();
// 监听屏幕方向变化
const handleOrientationChange = () => {
setTimeout(calculateTopBarHeight, 100);
};
// 监听窗口大小变化
const handleResize = () => {
calculateTopBarHeight();
};
window.addEventListener("orientationchange", handleOrientationChange);
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("orientationchange", handleOrientationChange);
window.removeEventListener("resize", handleResize);
};
}, []);
return (
<>
<div
className="mobile-top-bar"
style={{
height: `${topBarHeight}px`,
backgroundColor: "#fff",
}}
></div>
<NavBar
back={null}
style={{ background: "#fff" }}

View File

@@ -2,10 +2,6 @@ import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./styles/global.scss";
import { initSafeArea } from "./utils/safeArea";
// 初始化安全区域
initSafeArea();
// import VConsole from "vconsole";
// new VConsole();

View File

@@ -1,373 +0,0 @@
# 测试页面使用说明
## 概述
这些测试页面只在开发环境中显示用于开发和调试各种功能。所有测试页面都使用了统一的Layout布局组件。
## 访问方式
1. **开发环境**: 访问 `/test``/test/postMessage`
2. **生产环境**: 这些页面不会显示,路由也不会注册
## 测试页面列表
### 1. 测试页面入口 (`/test`)
- 使用Layout布局
- 提供测试页面的导航入口
- 显示开发环境标识
### 2. UniApp桥接测试 (`/test/postMessage`)
测试UniApp WebView桥接功能包括
- ✅ 获取用户信息
- ✅ 获取设备信息
- ✅ 显示Toast提示
- ✅ 显示Alert对话框
- ✅ 显示Confirm确认框
- ✅ 分享内容
- ✅ 支付功能
- ✅ 页面导航
- ✅ 自定义消息发送
- ✅ 桥接状态检查
- ✅ 通信调试工具
**布局特性:**
- 使用Layout布局组件
- 响应式设计(移动端适配)
- 实时状态显示
- 操作日志记录
### 3. 安全区域测试 (`/test/safeArea`)
测试安全区域高度计算功能:
- ✅ 设备类型检测iOS/Android
- ✅ 刘海屏设备检测
- ✅ 安全区域高度计算
- ✅ 屏幕方向变化监听
- ✅ CSS变量动态设置
- ✅ 实时信息更新
**布局特性:**
- 使用Layout布局组件
- 实时显示设备信息
- 动态更新安全区域数据
- 支持屏幕方向变化
### 4. 选择组件测试 (`/test/select`)
测试各种选择组件:
- 设备选择
- 好友选择
- 群组选择
- 内容库选择
- 账号选择
**布局特性:**
- 使用Layout布局组件
- Tab标签页切换
- 实时选择状态显示
## 通信流程
### UniApp ↔ React 通信流程
```
1. UniApp注入桥接代码
2. React检测桥接就绪
3. React发送请求消息
4. UniApp接收并处理
5. UniApp发送响应消息
6. React接收并处理响应
```
### 消息类型映射
| React发送 | UniApp接收 | UniApp响应 | React接收 |
| --------------- | --------------- | --------------- | --------------- |
| `getUserInfo` | `getUserInfo` | `userInfo` | `userInfo` |
| `getDeviceInfo` | `getDeviceInfo` | `deviceInfo` | `deviceInfo` |
| `toast` | `toast` | - | - |
| `alert` | `alert` | - | - |
| `confirm` | `confirm` | `confirmResult` | `confirmResult` |
| `share` | `share` | `shareResult` | `shareResult` |
| `payment` | `payment` | `paymentResult` | `paymentResult` |
### 调试工具
#### 1. 桥接状态检查
- 检查桥接是否就绪
- 检查桥接是否存在
- 显示消息队列状态
- 显示监听器数量
#### 2. 直接消息测试
- 绕过桥接工具直接发送消息
- 测试桥接注入是否成功
- 验证消息传递机制
#### 3. 监听器状态检查
- 检查事件监听器注册状态
- 验证消息处理流程
- 排查通信问题
## 布局组件
所有测试页面都使用了以下布局组件:
### Layout组件
- 提供统一的页面布局结构
- 包含头部导航和内容区域
- 支持移动端适配
### NavCommon组件
- 统一的导航头部
- 支持返回按钮
- 显示页面标题
## 环境配置
### 开发环境特性开关
`src/utils/env.ts` 中配置:
```typescript
export const DEV_FEATURES = {
SHOW_TEST_PAGES: true, // 显示测试页面
ENABLE_DEBUG_LOGS: true, // 启用调试日志
SHOW_DEV_TOOLS: true, // 显示开发工具
ENABLE_MOCK_DATA: true, // 启用Mock数据
};
```
### 环境变量 (Vite)
在Vite项目中使用 `import.meta.env` 访问环境变量:
```typescript
// 环境检测
export const isDevelopment = import.meta.env.DEV;
export const isProduction = import.meta.env.PROD;
// 环境变量
const apiUrl = import.meta.env.VITE_API_BASE_URL;
const appTitle = import.meta.env.VITE_APP_TITLE;
```
### 环境变量列表
- `import.meta.env.MODE`: 环境模式 (development/production)
- `import.meta.env.DEV`: 是否为开发环境 (boolean)
- `import.meta.env.PROD`: 是否为生产环境 (boolean)
- `VITE_APP_TITLE`: 应用标题
- `VITE_API_BASE_URL`: API基础URL
- `VITE_APP_VERSION`: 应用版本
### 环境变量配置
在项目根目录创建 `.env` 文件:
```env
# 开发环境
VITE_APP_TITLE=存客宝
VITE_API_BASE_URL=http://localhost:3000/api
VITE_APP_VERSION=1.0.0
```
## 通信问题排查
### 常见问题及解决方案
#### 1. 桥接初始化超时
**症状**: 页面显示"桥接初始化中..."
**原因**: UniApp端桥接代码注入失败或延迟
**解决**:
- 检查网络连接
- 查看控制台错误信息
- 使用"检查桥接状态"工具
- 使用"强制重新初始化"按钮
#### 2. 消息发送失败
**症状**: 点击按钮无响应或显示错误
**原因**: 桥接未就绪或消息类型不匹配
**解决**:
- 确认桥接已就绪
- 检查消息类型是否正确
- 使用"测试直接发送消息"工具
#### 3. 响应消息未收到
**症状**: 发送请求后未收到响应
**原因**: 监听器未正确注册或消息传递失败
**解决**:
- 检查监听器注册状态
- 查看UniApp端处理逻辑
- 使用"检查监听器状态"工具
#### 4. 桥接注入失败
**症状**: window.uniAppBridge 不存在
**原因**: UniApp端JavaScript注入失败
**解决**:
- 检查UniApp端控制台日志
- 确认web-view组件正常工作
- 检查网络连接和URL配置
#### 5. webview或evalJS方法不存在
**症状**: "UniApp: webview或evalJS方法不存在"
**原因**:
- 不在App环境下运行
- web-view组件未正确初始化
- 平台不支持evalJS方法
**解决**:
- 确认在App环境下运行
- 检查web-view组件配置
- 使用备用注入方案
- 查看平台检测信息
### 调试步骤
1. **环境检测**
- 点击"环境检测"按钮
- 确认运行环境和平台信息
- 检查是否在UniApp WebView中
2. **检查桥接状态**
- 点击"检查桥接状态"按钮
- 确认 `bridgeExists: true``isReady: true`
3. **测试直接通信**
- 点击"测试直接发送消息"按钮
- 查看控制台输出
4. **检查监听器**
- 点击"检查监听器状态"按钮
- 确认监听器数量正确
5. **强制重新初始化**
- 点击"强制重新初始化"按钮
- 观察重新初始化过程
6. **查看详细日志**
- 打开浏览器开发者工具
- 查看Console标签页
- 搜索相关日志信息
7. **检查UniApp端日志**
- 在UniApp开发工具中查看控制台
- 确认桥接代码注入成功
- 检查消息处理逻辑
### 环境检查清单
#### React端检查
- [ ] 页面在UniApp WebView中运行
- [ ] 控制台无JavaScript错误
- [ ] 桥接状态检查通过
- [ ] 监听器正确注册
#### UniApp端检查
- [ ] web-view组件正常加载
- [ ] 桥接代码注入成功
- [ ] 消息处理逻辑正确
- [ ] 响应消息正确发送
#### 网络检查
- [ ] URL配置正确
- [ ] 网络连接正常
- [ ] 无跨域问题
- [ ] 防火墙未阻止
#### 平台检查
- [ ] 确认在App环境下运行
- [ ] web-view组件支持evalJS
- [ ] 平台支持postMessage通信
- [ ] 无平台限制问题
### 常见错误及解决方案
#### 错误1: "window.uniAppBridge 不存在"
**解决方案**:
1. 检查UniApp端桥接注入是否成功
2. 确认web-view组件正常工作
3. 查看UniApp端控制台日志
#### 错误2: "桥接初始化超时"
**解决方案**:
1. 增加超时时间
2. 检查网络连接
3. 使用强制重新初始化
#### 错误3: "消息发送失败"
**解决方案**:
1. 确认桥接已就绪
2. 检查消息类型匹配
3. 验证postMessage方法存在
#### 错误4: "响应消息未收到"
**解决方案**:
1. 检查监听器注册
2. 确认UniApp端响应逻辑
3. 验证消息传递机制
#### 错误5: "webview或evalJS方法不存在"
**解决方案**:
1. 确认在App环境下运行
2. 检查web-view组件配置
3. 使用备用注入方案
4. 查看平台检测信息
## 使用建议
1. **开发阶段**: 充分利用测试页面进行功能验证
2. **调试桥接**: 使用UniApp桥接测试页面验证通信功能
3. **组件测试**: 使用选择组件测试页面验证UI组件
4. **生产部署**: 确保测试页面不会出现在生产环境中
## 注意事项
- 测试页面只在开发环境显示
- 生产环境会自动隐藏所有测试相关功能
- 调试日志只在开发环境输出
- 确保在生产构建前移除所有测试代码
- 所有测试页面都使用统一的Layout布局保持UI一致性
- 使用 `import.meta.env` 而不是 `process.env` 访问环境变量
- 通信问题优先使用内置调试工具排查

View File

@@ -1,10 +1,6 @@
import React from "react";
import { Card, Button, Space, Typography, Tag } from "antd";
import {
MessageOutlined,
SelectOutlined,
SafetyOutlined,
} from "@ant-design/icons";
import { MessageOutlined, SelectOutlined } from "@ant-design/icons";
import { useNavigate } from "react-router-dom";
import { isDevelopment } from "@/utils/env";
import Layout from "@/components/Layout/Layout";
@@ -48,15 +44,6 @@ const TestIndex: React.FC = () => {
>
</Button>
<Button
icon={<SafetyOutlined />}
size="large"
block
onClick={() => navigate("/test/safeArea")}
>
</Button>
</Space>
</Card>

View File

@@ -1,176 +0,0 @@
// 安全区域高度计算工具
/**
* 获取设备的安全区域信息
*/
export interface SafeAreaInfo {
top: number;
bottom: number;
left: number;
right: number;
statusBarHeight: number;
navBarHeight: number;
}
/**
* 计算安全区域高度
*/
export function getSafeAreaHeight(): SafeAreaInfo {
// 获取CSS环境变量
const getCSSValue = (property: string): number => {
const value = getComputedStyle(document.documentElement).getPropertyValue(
property,
);
return parseInt(value) || 0;
};
// 获取状态栏高度
const statusBarHeight =
getCSSValue("--status-bar-height") ||
getCSSValue("--sat") ||
getCSSValue("--safe-area-inset-top") ||
0;
// 获取底部安全区域高度
const bottomSafeArea = getCSSValue("--safe-area-inset-bottom") || 0;
// 获取左右安全区域
const leftSafeArea = getCSSValue("--safe-area-inset-left") || 0;
const rightSafeArea = getCSSValue("--safe-area-inset-right") || 0;
// 导航栏高度通常是44px但可能因设备而异
const navBarHeight = 44;
return {
top: statusBarHeight,
bottom: bottomSafeArea,
left: leftSafeArea,
right: rightSafeArea,
statusBarHeight,
navBarHeight,
};
}
/**
* 获取顶部安全区域高度用于mobile-top-bar
*/
export function getTopSafeAreaHeight(): number {
const safeArea = getSafeAreaHeight();
// 如果状态栏高度为0尝试其他方法
if (safeArea.statusBarHeight === 0) {
// 尝试从CSS变量获取
const statusBar = getComputedStyle(
document.documentElement,
).getPropertyValue("--status-bar-height");
if (statusBar) {
return parseInt(statusBar) || 0;
}
// 尝试从CSS变量获取安全区域
const safeAreaTop = getComputedStyle(
document.documentElement,
).getPropertyValue("--safe-area-inset-top");
if (safeAreaTop) {
return parseInt(safeAreaTop) || 0;
}
// 默认值iPhone X及以后的设备通常为44px
return 44;
}
return safeArea.statusBarHeight;
}
/**
* 动态设置CSS变量
*/
export function setSafeAreaCSSVariables(): void {
const safeArea = getSafeAreaHeight();
// 设置CSS变量
document.documentElement.style.setProperty(
"--safe-area-top",
`${safeArea.top}px`,
);
document.documentElement.style.setProperty(
"--safe-area-bottom",
`${safeArea.bottom}px`,
);
document.documentElement.style.setProperty(
"--safe-area-left",
`${safeArea.left}px`,
);
document.documentElement.style.setProperty(
"--safe-area-right",
`${safeArea.right}px`,
);
document.documentElement.style.setProperty(
"--status-bar-height",
`${safeArea.statusBarHeight}px`,
);
document.documentElement.style.setProperty(
"--nav-bar-height",
`${safeArea.navBarHeight}px`,
);
}
/**
* 检测设备类型
*/
export function getDeviceType(): "ios" | "android" | "unknown" {
const userAgent = navigator.userAgent.toLowerCase();
if (/iphone|ipad|ipod/.test(userAgent)) {
return "ios";
} else if (/android/.test(userAgent)) {
return "android";
}
return "unknown";
}
/**
* 检测是否为刘海屏设备
*/
export function isNotchDevice(): boolean {
const deviceType = getDeviceType();
if (deviceType === "ios") {
// iOS设备检测
const screenHeight = window.screen.height;
const screenWidth = window.screen.width;
// iPhone X及以后的设备
return screenHeight >= 812 || screenWidth >= 812;
} else if (deviceType === "android") {
// Android设备检测
const screenHeight = window.screen.height;
const screenWidth = window.screen.width;
// 高分辨率设备可能是刘海屏
return screenHeight >= 800 || screenWidth >= 800;
}
return false;
}
/**
* 初始化安全区域
*/
export function initSafeArea(): void {
// 设置CSS变量
setSafeAreaCSSVariables();
// 监听屏幕方向变化
window.addEventListener("orientationchange", () => {
setTimeout(() => {
setSafeAreaCSSVariables();
}, 100);
});
// 监听窗口大小变化
window.addEventListener("resize", () => {
setSafeAreaCSSVariables();
});
}