Files
telegram-management-system/test-export-fix.html
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
Full-stack web application for Telegram management
- Frontend: Vue 3 + Vben Admin
- Backend: NestJS
- Features: User management, group broadcast, statistics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 15:37:50 +08:00

313 lines
12 KiB
HTML
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.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TG账号导出功能修复测试</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.test-section {
margin: 20px 0;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.status {
margin: 10px 0;
padding: 10px;
border-radius: 3px;
}
.success { background-color: #d4edda; color: #155724; }
.error { background-color: #f8d7da; color: #721c24; }
.info { background-color: #d1ecf1; color: #0c5460; }
button {
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border: none;
border-radius: 3px;
background-color: #007bff;
color: white;
}
button:hover { background-color: #0056b3; }
.log {
background-color: #f8f9fa;
padding: 10px;
margin: 10px 0;
border-radius: 3px;
font-family: monospace;
white-space: pre-wrap;
max-height: 300px;
overflow-y: auto;
}
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
z-index: 1000;
}
.modal.show { display: block; }
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 999;
}
.overlay.show { display: block; }
</style>
</head>
<body>
<h1>TG账号导出功能修复测试</h1>
<div id="app">
<div class="test-section">
<h2>1. 环境检查</h2>
<div class="status" :class="envStatus.vue ? 'success' : 'error'">
Vue 3: {{ envStatus.vue ? '✅ 已加载' : '❌ 未加载' }}
</div>
<div class="status" :class="envStatus.xlsx ? 'success' : 'error'">
XLSX: {{ envStatus.xlsx ? '✅ 已加载' : '❌ 未加载' }}
</div>
</div>
<div class="test-section">
<h2>2. 模拟导出功能</h2>
<button @click="showExportModal">导出 (测试按钮点击)</button>
<button @click="testDirectExport">直接导出Excel (测试Excel功能)</button>
<button @click="testCSVExport">导出CSV (备用方案)</button>
<div class="log" v-if="logs.length">
<div v-for="log in logs" :key="log.time">
[{{ formatTime(log.time) }}] {{ log.message }}
</div>
</div>
</div>
<div class="test-section">
<h2>3. API测试</h2>
<button @click="testAPI">测试获取账号数据</button>
<div v-if="apiData.length" class="info">
获取到 {{ apiData.length }} 条账号数据
</div>
</div>
<!-- 模拟导出模态框 -->
<div class="overlay" :class="{ show: exportModalVisible }" @click="exportModalVisible = false"></div>
<div class="modal" :class="{ show: exportModalVisible }">
<h3>导出账号</h3>
<div style="margin: 20px 0;">
<label>
<input type="radio" v-model="exportRange" value="all"> 全部导出
</label>
<label style="margin-left: 20px;">
<input type="radio" v-model="exportRange" value="current"> 当前页
</label>
</div>
<div>
<button @click="confirmExport">确认导出</button>
<button @click="exportModalVisible = false" style="background-color: #6c757d;">取消</button>
</div>
</div>
</div>
<script>
const { createApp, ref, reactive, onMounted } = Vue;
createApp({
setup() {
const envStatus = reactive({
vue: false,
xlsx: false
});
const logs = ref([]);
const apiData = ref([]);
const exportModalVisible = ref(false);
const exportRange = ref('all');
const addLog = (message) => {
logs.value.push({
time: new Date(),
message
});
console.log(`[测试日志] ${message}`);
};
const formatTime = (date) => {
return date.toLocaleTimeString();
};
// 检查环境
onMounted(() => {
envStatus.vue = typeof Vue !== 'undefined';
envStatus.xlsx = typeof XLSX !== 'undefined';
addLog('环境检查完成');
});
// 模拟showExportModal函数
const showExportModal = () => {
addLog('showExportModal被调用');
exportModalVisible.value = true;
addLog('模态框已显示');
};
// 测试API
const testAPI = async () => {
addLog('开始测试API...');
try {
const response = await fetch('http://localhost:3000/tgAccount/test-all', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const data = await response.json();
if (data.success) {
apiData.value = data.data;
addLog(`成功获取 ${data.data.length} 条账号数据`);
} else {
addLog('API返回失败');
}
} catch (error) {
addLog(`API错误: ${error.message}`);
}
};
// 确认导出
const confirmExport = async () => {
addLog(`确认导出,范围: ${exportRange.value}`);
exportModalVisible.value = false;
let dataToExport = [];
if (exportRange.value === 'all' && apiData.value.length === 0) {
await testAPI();
}
dataToExport = apiData.value;
if (dataToExport.length > 0) {
exportFile(dataToExport);
} else {
addLog('没有数据可导出');
}
};
// 导出文件
const exportFile = (list) => {
addLog(`开始导出 ${list.length} 条数据`);
if (!XLSX) {
addLog('XLSX库未加载使用CSV导出');
exportAsCSV(list);
return;
}
try {
const data = list.map(item => ({
'手机号': item.phone || '',
'密码': item.password || '',
'姓': item.firstname || '',
'名': item.lastname || '',
'用途ID': item.usageId || '',
'Session': item.session ? item.session.substring(0, 50) + '...' : ''
}));
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "账号列表");
const date = new Date();
const filename = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}-账号列表.xlsx`;
XLSX.writeFile(wb, filename);
addLog(`✅ Excel文件导出成功: ${filename}`);
} catch (error) {
addLog(`❌ Excel导出失败: ${error.message}`);
exportAsCSV(list);
}
};
// CSV导出
const exportAsCSV = (list) => {
addLog('使用CSV导出作为备用方案');
try {
const headers = ['手机号', '密码', '姓', '名', '用途ID', 'Session'];
const headerKeys = ['phone', 'password', 'firstname', 'lastname', 'usageId', 'session'];
const csvContent = [
headers.join(','),
...list.map(row => headerKeys.map(key => {
const value = row[key] || '';
if (value.toString().includes(',') || value.toString().includes('"')) {
return `"${value.toString().replace(/"/g, '""')}"`;
}
return value;
}).join(','))
].join('\n');
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
const date = new Date();
link.download = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}-账号列表.csv`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
addLog(`✅ CSV文件导出成功`);
} catch (error) {
addLog(`❌ CSV导出失败: ${error.message}`);
}
};
// 直接测试Excel导出
const testDirectExport = () => {
const testData = [
{ phone: '12345678901', password: 'test123', firstname: '张', lastname: '三' },
{ phone: '12345678902', password: 'test456', firstname: '李', lastname: '四' }
];
exportFile(testData);
};
// 测试CSV导出
const testCSVExport = () => {
const testData = [
{ phone: '12345678901', password: 'test123', firstname: '张', lastname: '三' },
{ phone: '12345678902', password: 'test456', firstname: '李', lastname: '四' }
];
exportAsCSV(testData);
};
return {
envStatus,
logs,
apiData,
exportModalVisible,
exportRange,
formatTime,
showExportModal,
testAPI,
confirmExport,
testDirectExport,
testCSVExport
};
}
}).mount('#app');
</script>
</body>
</html>