Files
map-client-vue/web/public/diagnose-storage.html
2025-10-14 21:52:11 +08:00

293 lines
8.5 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LocalStorage 诊断工具</title>
<style>
body {
font-family: 'Monaco', 'Menlo', monospace;
padding: 20px;
background: #1e1e1e;
color: #d4d4d4;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
h1 {
color: #4ec9b0;
border-bottom: 2px solid #4ec9b0;
padding-bottom: 10px;
}
h2 {
color: #dcdcaa;
margin-top: 30px;
}
.section {
background: #252526;
padding: 20px;
border-radius: 8px;
margin: 15px 0;
border: 1px solid #3c3c3c;
}
.key-name {
color: #9cdcfe;
font-weight: bold;
}
.value {
color: #ce9178;
}
pre {
background: #1e1e1e;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
border: 1px solid #3c3c3c;
}
button {
background: #0e639c;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px;
font-size: 14px;
}
button:hover {
background: #1177bb;
}
.success { color: #4ec9b0; }
.error { color: #f48771; }
.warning { color: #dcdcaa; }
.info { color: #9cdcfe; }
table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #3c3c3c;
}
th {
background: #1e1e1e;
color: #4ec9b0;
}
.action-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin: 20px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>🔍 LocalStorage 完整诊断</h1>
<div class="action-buttons">
<button onclick="diagnose()">🔄 重新诊断</button>
<button onclick="fixData()">🔧 修复数据</button>
<button onclick="clearAll()">🗑️ 清空所有</button>
<button onclick="exportData()">💾 导出数据</button>
</div>
<div id="output"></div>
</div>
<script>
function diagnose() {
const output = document.getElementById('output')
let html = ''
// 1. 显示所有 LocalStorage 键
html += '<div class="section">'
html += '<h2>📋 所有 LocalStorage 键值对</h2>'
html += '<table>'
html += '<tr><th>键名</th><th>大小</th><th>数据类型</th><th>操作</th></tr>'
const allKeys = Object.keys(localStorage).sort()
if (allKeys.length === 0) {
html += '<tr><td colspan="4" class="warning">⚠️ LocalStorage 为空</td></tr>'
} else {
allKeys.forEach(key => {
const value = localStorage.getItem(key)
const size = new Blob([value]).size
let type = 'string'
try {
const parsed = JSON.parse(value)
type = Array.isArray(parsed) ? 'array' : typeof parsed
} catch (e) {
type = 'string'
}
html += `<tr>
<td class="key-name">${key}</td>
<td>${(size / 1024).toFixed(2)} KB</td>
<td>${type}</td>
<td><button onclick="viewKey('${key}')">查看</button></td>
</tr>`
})
}
html += '</table></div>'
// 2. 重点检查模型相关的键
html += '<div class="section">'
html += '<h2>🎯 模型服务相关键检查</h2>'
const modelKeys = [
'model-services',
'model-providers',
'model-service-config',
'services',
'providers'
]
modelKeys.forEach(key => {
const value = localStorage.getItem(key)
html += `<h3 class="key-name">${key}:</h3>`
if (!value) {
html += `<p class="error">✗ 不存在</p>`
} else {
try {
const parsed = JSON.parse(value)
if (Array.isArray(parsed)) {
html += `<p class="success">✓ 找到 ${parsed.length} 项</p>`
html += '<pre>' + JSON.stringify(parsed, null, 2) + '</pre>'
} else {
html += '<pre>' + JSON.stringify(parsed, null, 2) + '</pre>'
}
} catch (e) {
html += `<p class="warning">⚠️ 非JSON格式</p>`
html += '<pre>' + value.substring(0, 500) + '...</pre>'
}
}
})
html += '</div>'
// 3. 诊断建议
html += '<div class="section">'
html += '<h2>💡 诊断结果与建议</h2>'
const modelServices = localStorage.getItem('model-services')
const modelProviders = localStorage.getItem('model-providers')
if (!modelServices && !modelProviders) {
html += '<p class="error">❌ 未找到任何模型服务数据</p>'
html += '<p class="info">原因可能:</p>'
html += '<ul>'
html += '<li>数据保存失败(检查浏览器控制台是否有错误)</li>'
html += '<li>使用了不同的存储方式sessionStorage、IndexedDB等</li>'
html += '<li>页面域名不同导致 LocalStorage 隔离</li>'
html += '</ul>'
html += '<p class="warning">🔧 建议:点击"修复数据"按钮创建测试数据</p>'
} else if (modelServices && !modelProviders) {
html += '<p class="warning">⚠️ 找到 model-services 但缺少 model-providers</p>'
html += '<p class="info">需要同步数据到 model-providers</p>'
} else if (!modelServices && modelProviders) {
html += '<p class="success">✓ model-providers 有数据(正确的键)</p>'
html += '<p class="info">可以清理旧的 model-services 键</p>'
} else {
html += '<p class="info"> 两个键都存在,需要判断哪个是最新的</p>'
}
html += '</div>'
output.innerHTML = html
}
function viewKey(key) {
const value = localStorage.getItem(key)
const newWindow = window.open('', '_blank')
newWindow.document.write('<pre>' + JSON.stringify(JSON.parse(value), null, 2) + '</pre>')
}
function fixData() {
// 检查是否有 model-services 数据
const modelServices = localStorage.getItem('model-services')
if (modelServices) {
// 复制到 model-providers
localStorage.setItem('model-providers', modelServices)
alert('✓ 已将 model-services 同步到 model-providers')
} else {
// 创建测试数据
const testData = [
{
id: 'test-dashscope',
name: '阿里大模型',
type: 'dashscope',
url: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
apiKey: 'sk-test',
enabled: true,
connected: true,
status: 'connected',
models: [
{ id: 'qwen-max', name: 'Qwen Max' },
{ id: 'qwen-plus', name: 'Qwen Plus' }
]
},
{
id: 'test-volcengine',
name: '火山大模型',
type: 'volcengine',
url: 'https://ark.cn-beijing.volces.com/api/v3',
apiKey: 'test-key',
enabled: true,
connected: true,
status: 'connected',
models: [
{ id: 'doubao-pro-4k', name: 'Doubao Pro 4K' },
{ id: 'doubao-pro-32k', name: 'Doubao Pro 32K' }
]
}
]
localStorage.setItem('model-providers', JSON.stringify(testData))
localStorage.setItem('model-services', JSON.stringify(testData))
alert('✓ 已创建测试数据')
}
diagnose()
}
function clearAll() {
if (confirm('确定要清空所有 LocalStorage 数据吗?')) {
localStorage.clear()
alert('✓ 已清空')
diagnose()
}
}
function exportData() {
const data = {}
Object.keys(localStorage).forEach(key => {
try {
data[key] = JSON.parse(localStorage.getItem(key))
} catch (e) {
data[key] = localStorage.getItem(key)
}
})
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'localStorage-backup.json'
a.click()
}
// 页面加载时自动诊断
window.onload = diagnose
</script>
</body>
</html>