erp-frontend/public/diagnose-vue.html
2026-04-01 17:07:17 +08:00

314 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue应用诊断</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
.test { margin: 20px 0; padding: 15px; border: 1px solid #ccc; }
button { padding: 10px 15px; margin: 5px; }
pre { background: #f5f5f5; padding: 10px; overflow: auto; }
.success { color: green; }
.error { color: red; }
</style>
</head>
<body>
<h1>Vue应用诊断</h1>
<div class="test">
<h3>1. 检查Vue应用加载</h3>
<button onclick="checkVueApp()">检查Vue应用</button>
<div id="vueResult"></div>
</div>
<div class="test">
<h3>2. 检查环境变量</h3>
<button onclick="checkEnvVars()">检查环境变量</button>
<div id="envResult"></div>
</div>
<div class="test">
<h3>3. 测试前端axios实例</h3>
<button onclick="testFrontendAxios()">测试前端axios</button>
<div id="axiosResult"></div>
</div>
<div class="test">
<h3>4. 模拟Vue登录页面请求</h3>
<button onclick="simulateVueLogin()">模拟Vue登录</button>
<div id="vueLoginResult"></div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/axios-mock-adapter/dist/axios-mock-adapter.min.js"></script>
<script>
// 模拟前端的axios配置
const frontendAxios = axios.create({
baseURL: '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
});
// 模拟前端的请求拦截器
frontendAxios.interceptors.request.use(
config => {
const token = localStorage.getItem('erp_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
// 模拟前端的响应拦截器
frontendAxios.interceptors.response.use(
response => {
if (response.status === 204) {
return { code: 200, message: 'success' };
}
if (response.data !== undefined && response.data !== null) {
return response.data;
}
if (response.status === 200) {
return { code: 200, message: 'success' };
}
return response;
},
error => {
console.error('请求错误:', error);
if (error.response?.status === 401) {
localStorage.removeItem('erp_token');
localStorage.removeItem('current_user');
}
return Promise.reject(error);
}
);
function showResult(elementId, message, isError = false) {
const element = document.getElementById(elementId);
element.innerHTML = `<pre class="${isError ? 'error' : 'success'}">${message}</pre>`;
}
async function checkVueApp() {
showResult('vueResult', '检查中...');
try {
// 检查Vue是否加载
const vueLoaded = typeof Vue !== 'undefined';
// 检查是否有Vue应用挂载
const appElement = document.getElementById('app');
let result = 'Vue应用检查:\n\n';
result += `Vue已加载: ${vueLoaded ? '✅ 是' : '❌ 否'}\n`;
result += `Vue版本: ${vueLoaded ? Vue.version : '未找到'}\n`;
result += `#app元素: ${appElement ? '✅ 找到' : '❌ 未找到'}\n`;
if (appElement) {
result += `#app内容: ${appElement.innerHTML.substring(0, 200)}...\n`;
}
// 检查路由
const currentPath = window.location.pathname;
result += `\n当前路径: ${currentPath}\n`;
showResult('vueResult', result);
} catch (error) {
showResult('vueResult', `检查失败: ${error.message}`, true);
}
}
async function checkEnvVars() {
showResult('envResult', '检查中...');
try {
// 尝试获取Vite环境变量
const response = await fetch('/@vite/env');
let result = '环境变量检查:\n\n';
if (response.ok) {
try {
const env = await response.json();
result += '✅ Vite环境变量可访问\n';
result += `VITE_USE_MOCK: ${env.VITE_USE_MOCK || '未找到'}\n`;
result += `VITE_API_BASE_URL: ${env.VITE_API_BASE_URL || '未找到'}\n`;
result += `MODE: ${env.MODE || '未找到'}\n`;
result += `DEV: ${env.DEV || '未找到'}\n`;
result += `\n完整环境变量:\n${JSON.stringify(env, null, 2)}`;
} catch (e) {
result += `❌ 解析环境变量失败: ${e.message}\n`;
const text = await response.text();
result += `响应文本: ${text.substring(0, 200)}...`;
}
} else {
result += '❌ 无法访问Vite环境变量\n';
result += `状态码: ${response.status}\n`;
// 尝试从全局变量获取
if (window.__VITE_ENV__) {
result += `\n从全局变量找到环境变量:\n`;
result += JSON.stringify(window.__VITE_ENV__, null, 2);
} else {
result += '\n全局变量中未找到环境变量';
}
}
showResult('envResult', result);
} catch (error) {
showResult('envResult', `检查失败: ${error.message}`, true);
}
}
async function testFrontendAxios() {
showResult('axiosResult', '测试中...');
try {
// 先清除可能的Mock
const mock = new AxiosMockAdapter(frontendAxios, { delayResponse: 300 });
// 设置Mock
mock.onPost('/auth/login').reply((config) => {
console.log('前端Mock被调用:', config.data);
const data = JSON.parse(config.data);
const { email, password } = data;
if (email === 'admin@erp.com' && password === 'password123') {
return [200, {
code: 200,
message: '登录成功',
data: {
token: 'frontend-mock-token-' + Date.now(),
user: {
id: 'user-001',
email: 'admin@erp.com',
name: '管理员',
role: 'admin'
}
}
}];
} else {
return [401, {
code: 401,
message: '邮箱或密码错误'
}];
}
});
let result = '前端axios测试:\n\n';
// 测试登录
result += '1. 测试登录:\n';
try {
const loginRes = await frontendAxios.post('/auth/login', {
email: 'admin@erp.com',
password: 'password123'
});
result += ` 状态码: 200 (通过拦截器转换)\n`;
result += ` 响应code: ${loginRes.code}\n`;
result += ` 消息: ${loginRes.message}\n`;
result += ` Token: ${loginRes.data?.token?.substring(0, 30)}...\n`;
result += ` 用户: ${loginRes.data?.user?.name}\n`;
// 保存token测试拦截器
if (loginRes.data?.token) {
localStorage.setItem('erp_token', loginRes.data.token);
result += `\n✅ Token已保存到localStorage\n`;
}
} catch (error) {
result += ` ❌ 登录失败: ${error.message}\n`;
if (error.response) {
result += ` 实际状态码: ${error.response.status}\n`;
result += ` 响应数据: ${JSON.stringify(error.response.data, null, 2)}\n`;
}
}
// 测试401处理
result += '\n2. 测试错误登录(401):\n';
try {
const errorRes = await frontendAxios.post('/auth/login', {
email: 'wrong@email.com',
password: 'wrongpassword'
});
result += ` ❌ 预期失败但成功了: ${JSON.stringify(errorRes, null, 2)}\n`;
} catch (error) {
if (error.response?.status === 401) {
result += ` ✅ 正确返回401\n`;
result += ` 错误信息: ${error.response.data?.message}\n`;
} else {
result += ` ❌ 其他错误: ${error.message}\n`;
}
}
// 恢复Mock
mock.restore();
showResult('axiosResult', result);
} catch (error) {
showResult('axiosResult', `测试失败: ${error.message}`, true);
}
}
async function simulateVueLogin() {
showResult('vueLoginResult', '模拟中...');
try {
// 模拟Vue登录页面的请求
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'admin@erp.com',
password: 'password123'
})
});
let result = '模拟Vue登录请求:\n\n';
result += `URL: ${response.url}\n`;
result += `状态码: ${response.status}\n`;
result += `状态文本: ${response.statusText}\n`;
try {
const text = await response.text();
result += `\n响应文本: ${text}\n`;
if (text) {
try {
const data = JSON.parse(text);
result += `\n解析后的JSON:\n${JSON.stringify(data, null, 2)}`;
} catch (e) {
result += `\nJSON解析失败: ${e.message}`;
}
} else {
result += '\n响应为空';
}
} catch (e) {
result += `\n读取响应失败: ${e.message}`;
}
showResult('vueLoginResult', result, !response.ok);
} catch (error) {
showResult('vueLoginResult', `模拟失败: ${error.message}`, true);
}
}
// 页面加载时自动检查
window.addEventListener('load', () => {
console.log('Vue诊断页面已加载');
checkVueApp();
checkEnvVars();
});
</script>
</body>
</html>