Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
performance-score
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tools
performance-score
Commits
7a5f3bf6
Commit
7a5f3bf6
authored
Aug 12, 2025
by
Performance System
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
28357a9b
Pipeline
#3160
passed with stage
in 28 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
436 additions
and
20 deletions
+436
-20
debug-image-url.html
+276
-0
src/views/admin/AdminPanel.vue
+160
-20
No files found.
debug-image-url.html
0 → 100644
View file @
7a5f3bf6
<!DOCTYPE html>
<html
lang=
"zh-CN"
>
<head>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
图片URL调试工具
</title>
<style>
body
{
font-family
:
Arial
,
sans-serif
;
max-width
:
1200px
;
margin
:
0
auto
;
padding
:
20px
;
line-height
:
1.6
;
}
.header
{
background
:
#E6A23C
;
color
:
white
;
padding
:
20px
;
border-radius
:
8px
;
margin-bottom
:
20px
;
text-align
:
center
;
}
.section
{
background
:
#f5f5f5
;
padding
:
20px
;
margin
:
15px
0
;
border-radius
:
8px
;
border-left
:
4px
solid
#E6A23C
;
}
.debug-steps
{
border-left-color
:
#409EFF
;
background
:
#f0f9ff
;
}
.warning
{
border-left-color
:
#F56C6C
;
background
:
#fef0f0
;
}
.code
{
background
:
#f4f4f4
;
padding
:
15px
;
border-radius
:
4px
;
font-family
:
monospace
;
margin
:
10px
0
;
overflow-x
:
auto
;
white-space
:
pre-wrap
;
}
.checklist
{
list-style
:
none
;
padding
:
0
;
}
.checklist
li
{
padding
:
8px
0
;
position
:
relative
;
padding-left
:
30px
;
}
.checklist
li
:before
{
content
:
"🔍"
;
position
:
absolute
;
left
:
0
;
font-size
:
16px
;
}
.highlight
{
background
:
#fff3cd
;
padding
:
2px
6px
;
border-radius
:
3px
;
font-weight
:
bold
;
}
.grid
{
display
:
grid
;
grid-template-columns
:
1
fr
1
fr
;
gap
:
20px
;
margin
:
20px
0
;
}
</style>
</head>
<body>
<div
class=
"header"
>
<h1>
🔍 图片URL缺失问题调试指南
</h1>
<p>
排查用户视图导出中 image.url 为空的原因
</p>
</div>
<div
class=
"section warning"
>
<h2>
⚠️ 问题现象
</h2>
<p>
在用户视图导出ZIP功能中,
<span
class=
"highlight"
>
image.url
</span>
字段可能为空,导致无法生成图片文件。
</p>
<h3>
🎯 可能的原因
</h3>
<ul>
<li><strong>
数据存储问题
</strong>
:图片保存时url字段丢失
</li>
<li><strong>
数据过滤问题
</strong>
:加载时被过滤掉了无效图片
</li>
<li><strong>
权限问题
</strong>
:获取的机构数据不完整
</li>
<li><strong>
数据映射问题
</strong>
:导出时数据转换错误
</li>
</ul>
</div>
<div
class=
"section debug-steps"
>
<h2>
🔍 调试步骤
</h2>
<h3>
第一步:检查控制台日志
</h3>
<ol
class=
"checklist"
>
<li>
打开浏览器开发者工具 (F12)
</li>
<li>
切换到 Console 标签页
</li>
<li>
清空控制台日志
</li>
<li>
进入管理员页面 → 用户视图
</li>
<li>
选择一个用户,观察日志输出
</li>
</ol>
<h3>
第二步:查看用户机构数据
</h3>
<p>
在控制台中查找以下日志:
</p>
<div
class=
"code"
>
=== 用户机构数据调试 ===
用户ID: [用户ID]
用户名: [用户名]
获取到的机构数量: [数量]
机构 1: {
id: "inst_xxx",
institutionId: "001",
name: "机构名称",
ownerId: "user_xxx",
hasImages: true/false,
imageCount: [数量],
images: [...]
}
</div>
<h3>
第三步:检查图片数据结构
</h3>
<p>
重点关注每个图片对象的结构:
</p>
<div
class=
"code"
>
图片 1 原始数据: {
id: "img_xxx",
name: "图片名称.jpg",
hasUrl: true/false, ← 关键检查点
urlType: "string",
urlLength: [长度],
size: [文件大小],
uploadTime: "2024-xx-xx"
}
</div>
<h3>
第四步:尝试导出并观察详细日志
</h3>
<p>
点击"导出用户数据 → ZIP图片包",观察详细处理日志:
</p>
<div
class=
"code"
>
=== 开始处理机构和图片数据 ===
导出数据结构: {...}
--- 处理机构: [机构名] ---
机构详细信息: {...}
处理图片 1/[总数]: [图片名]
✅ 已添加图片: [路径] 或 ❌ 图片缺少URL数据
</div>
</div>
<div
class=
"section"
>
<h2>
🔧 常见问题和解决方案
</h2>
<div
class=
"grid"
>
<div>
<h3>
❌ 问题1:hasUrl: false
</h3>
<p><strong>
现象:
</strong>
图片对象存在但url字段为空
</p>
<p><strong>
原因:
</strong>
图片保存时出现问题
</p>
<p><strong>
解决:
</strong>
检查图片上传逻辑
</p>
</div>
<div>
<h3>
❌ 问题2:imageCount: 0
</h3>
<p><strong>
现象:
</strong>
机构没有图片数据
</p>
<p><strong>
原因:
</strong>
用户确实没有上传图片
</p>
<p><strong>
解决:
</strong>
选择有图片的用户测试
</p>
</div>
</div>
<div
class=
"grid"
>
<div>
<h3>
❌ 问题3:权限错误
</h3>
<p><strong>
现象:
</strong>
获取到的机构数量为0
</p>
<p><strong>
原因:
</strong>
用户-机构关联错误
</p>
<p><strong>
解决:
</strong>
检查ownerId字段
</p>
</div>
<div>
<h3>
❌ 问题4:数据过滤
</h3>
<p><strong>
现象:
</strong>
原有图片被过滤掉
</p>
<p><strong>
原因:
</strong>
数据验证过于严格
</p>
<p><strong>
解决:
</strong>
检查过滤条件
</p>
</div>
</div>
</div>
<div
class=
"section"
>
<h2>
🛠️ 手动检查方法
</h2>
<h3>
方法1:直接检查localStorage
</h3>
<p>
在浏览器控制台中执行:
</p>
<div
class=
"code"
>
// 检查存储的机构数据
const institutions = JSON.parse(localStorage.getItem('score_system_institutions') || '[]')
console.log('所有机构:', institutions)
// 检查特定用户的机构
const userId = 'your_user_id' // 替换为实际用户ID
const userInstitutions = institutions.filter(inst => inst.ownerId === userId)
console.log('用户机构:', userInstitutions)
// 检查图片数据
userInstitutions.forEach(inst => {
console.log(`机构 ${inst.name}:`)
if (inst.images) {
inst.images.forEach((img, index) => {
console.log(` 图片 ${index + 1}:`, {
name: img.name,
hasUrl: !!img.url,
urlLength: img.url ? img.url.length : 0
})
})
}
})
</div>
<h3>
方法2:检查数据存储函数
</h3>
<p>
在控制台中测试数据存储:
</p>
<div
class=
"code"
>
// 获取数据存储实例
const dataStore = window.dataStore || app.config.globalProperties.$dataStore
// 检查用户机构
const userId = 'your_user_id'
const institutions = dataStore.getInstitutionsByUserId(userId)
console.log('通过dataStore获取的机构:', institutions)
// 检查每个机构的图片
institutions.forEach(inst => {
console.log(`机构 ${inst.name} 的图片:`, inst.images)
})
</div>
</div>
<div
class=
"section"
>
<h2>
📋 调试检查清单
</h2>
<ol
class=
"checklist"
>
<li>
确认选择的用户确实有图片数据
</li>
<li>
检查localStorage中的原始数据
</li>
<li>
验证getInstitutionsByUserId返回的数据
</li>
<li>
确认图片对象包含url字段
</li>
<li>
检查url字段是否为有效的Base64格式
</li>
<li>
验证数据映射过程中url字段是否丢失
</li>
<li>
确认ZIP生成过程中的错误处理
</li>
</ol>
</div>
<div
class=
"section warning"
>
<h2>
🚨 如果发现问题
</h2>
<h3>
情况1:url字段确实为空
</h3>
<ul>
<li>
检查图片上传功能是否正常保存url
</li>
<li>
查看addImageToInstitution函数的实现
</li>
<li>
确认imageData参数包含url字段
</li>
</ul>
<h3>
情况2:数据被错误过滤
</h3>
<ul>
<li>
检查loadFromStorage中的过滤逻辑
</li>
<li>
确认过滤条件:img
&&
img.id
&&
img.url
</li>
<li>
可能需要放宽过滤条件
</li>
</ul>
<h3>
情况3:权限或关联问题
</h3>
<ul>
<li>
检查机构的ownerId是否正确
</li>
<li>
确认用户-机构关联关系
</li>
<li>
验证getInstitutionsByUserId的逻辑
</li>
</ul>
</div>
<div
class=
"section debug-steps"
>
<h2>
✅ 下一步行动
</h2>
<p>
现在请按照以上步骤进行调试:
</p>
<ol>
<li><strong>
打开控制台
</strong>
,清空日志
</li>
<li><strong>
进入用户视图
</strong>
,选择用户
</li>
<li><strong>
观察详细日志
</strong>
,找出问题点
</li>
<li><strong>
尝试导出
</strong>
,查看错误信息
</li>
<li><strong>
根据日志结果
</strong>
,确定具体问题
</li>
</ol>
<p>
请将控制台中的关键日志信息反馈给我,我会根据具体情况提供针对性的修复方案!
</p>
</div>
</body>
</html>
src/views/admin/AdminPanel.vue
View file @
7a5f3bf6
...
...
@@ -1979,6 +1979,28 @@ const loadSelectedUserData = () => {
performanceScore
:
userScore
?.
performanceScore
||
0
}
selectedUserInstitutions
.
value
=
dataStore
.
getInstitutionsByUserId
(
user
.
id
)
// 调试:检查获取到的机构数据
console
.
log
(
'=== 用户机构数据调试 ==='
)
console
.
log
(
'用户ID:'
,
user
.
id
)
console
.
log
(
'用户名:'
,
user
.
name
)
console
.
log
(
'获取到的机构数量:'
,
selectedUserInstitutions
.
value
.
length
)
selectedUserInstitutions
.
value
.
forEach
((
inst
,
index
)
=>
{
console
.
log
(
`机构
${
index
+
1
}
:`
,
{
id
:
inst
.
id
,
institutionId
:
inst
.
institutionId
,
name
:
inst
.
name
,
ownerId
:
inst
.
ownerId
,
hasImages
:
!!
inst
.
images
,
imageCount
:
inst
.
images
?
inst
.
images
.
length
:
0
,
images
:
inst
.
images
?
inst
.
images
.
map
(
img
=>
({
id
:
img
.
id
,
name
:
img
.
name
,
hasUrl
:
!!
img
.
url
,
urlLength
:
img
.
url
?
img
.
url
.
length
:
0
}))
:
[]
})
})
}
}
...
...
@@ -2035,19 +2057,63 @@ const exportUserData = async (format = 'json') => {
interactionScore
:
dataStore
.
calculateInteractionScore
(
selectedViewUser
.
value
.
id
),
performanceScore
:
dataStore
.
calculatePerformanceScore
(
selectedViewUser
.
value
.
id
)
},
institutions
:
selectedUserInstitutions
.
value
.
map
(
inst
=>
({
id
:
inst
.
id
,
institutionId
:
inst
.
institutionId
,
name
:
inst
.
name
,
imageCount
:
inst
.
images
?
inst
.
images
.
length
:
0
,
images
:
inst
.
images
?
inst
.
images
.
map
(
img
=>
({
id
:
img
.
id
,
name
:
img
.
name
,
uploadTime
:
img
.
uploadTime
,
size
:
img
.
size
,
url
:
img
.
url
// 添加图片的Base64数据,ZIP导出需要此字段
}))
:
[]
}))
institutions
:
selectedUserInstitutions
.
value
.
map
(
inst
=>
{
console
.
log
(
`\n=== 准备导出数据 - 机构:
${
inst
.
name
}
===`
)
console
.
log
(
'原始机构数据:'
,
{
id
:
inst
.
id
,
institutionId
:
inst
.
institutionId
,
name
:
inst
.
name
,
ownerId
:
inst
.
ownerId
,
hasImages
:
!!
inst
.
images
,
imageCount
:
inst
.
images
?
inst
.
images
.
length
:
0
})
const
mappedImages
=
inst
.
images
?
inst
.
images
.
map
((
img
,
imgIndex
)
=>
{
console
.
log
(
` 图片
${
imgIndex
+
1
}
原始数据:`
,
{
id
:
img
.
id
,
name
:
img
.
name
,
hasUrl
:
!!
img
.
url
,
urlType
:
typeof
img
.
url
,
urlLength
:
img
.
url
?
img
.
url
.
length
:
0
,
size
:
img
.
size
,
uploadTime
:
img
.
uploadTime
})
const
mappedImg
=
{
id
:
img
.
id
,
name
:
img
.
name
,
uploadTime
:
img
.
uploadTime
,
size
:
img
.
size
,
url
:
img
.
url
// 添加图片的Base64数据,ZIP导出需要此字段
}
console
.
log
(
` 图片
${
imgIndex
+
1
}
映射后:`
,
{
id
:
mappedImg
.
id
,
name
:
mappedImg
.
name
,
hasUrl
:
!!
mappedImg
.
url
,
urlPreserved
:
img
.
url
===
mappedImg
.
url
})
return
mappedImg
})
:
[]
const
result
=
{
id
:
inst
.
id
,
institutionId
:
inst
.
institutionId
,
name
:
inst
.
name
,
imageCount
:
inst
.
images
?
inst
.
images
.
length
:
0
,
images
:
mappedImages
}
console
.
log
(
'机构导出数据准备完成:'
,
{
name
:
result
.
name
,
imageCount
:
result
.
imageCount
,
actualImagesLength
:
result
.
images
.
length
,
imagesWithUrl
:
result
.
images
.
filter
(
img
=>
!!
img
.
url
).
length
})
return
result
})
}
// 根据格式导出
...
...
@@ -2157,18 +2223,78 @@ const exportUserDataAsZIP = async (exportData, userName, currentMonth) => {
zip
.
file
(
`
${
userName
}
_数据摘要.json`
,
JSON
.
stringify
(
summaryData
,
null
,
2
))
// 按机构创建文件夹并添加图片
console
.
log
(
'=== 开始处理机构和图片数据 ==='
)
console
.
log
(
'导出数据结构:'
,
{
institutionsCount
:
exportData
.
institutions
.
length
,
institutions
:
exportData
.
institutions
.
map
(
inst
=>
({
name
:
inst
.
name
,
id
:
inst
.
id
,
institutionId
:
inst
.
institutionId
,
imageCount
:
inst
.
images
?
inst
.
images
.
length
:
0
,
hasImages
:
!!
(
inst
.
images
&&
inst
.
images
.
length
>
0
)
}))
})
for
(
const
institution
of
exportData
.
institutions
)
{
console
.
log
(
`处理机构:
${
institution
.
name
}
, 图片数量:
${
institution
.
images
?
institution
.
images
.
length
:
0
}
`
)
console
.
log
(
`\n--- 处理机构:
${
institution
.
name
}
---`
)
console
.
log
(
'机构详细信息:'
,
{
id
:
institution
.
id
,
institutionId
:
institution
.
institutionId
,
name
:
institution
.
name
,
imageCount
:
institution
.
imageCount
,
imagesArrayLength
:
institution
.
images
?
institution
.
images
.
length
:
0
,
imagesExists
:
!!
institution
.
images
})
if
(
institution
.
images
&&
institution
.
images
.
length
>
0
)
{
const
folderName
=
`
${
institution
.
name
}
_
${
institution
.
institutionId
}
`
totalImages
+=
institution
.
images
.
length
for
(
const
image
of
institution
.
images
)
{
console
.
log
(
`机构
${
institution
.
name
}
的图片列表:`
)
institution
.
images
.
forEach
((
img
,
index
)
=>
{
console
.
log
(
` 图片
${
index
+
1
}
:`
,
{
id
:
img
.
id
,
name
:
img
.
name
,
hasUrl
:
!!
img
.
url
,
urlType
:
img
.
url
?
typeof
img
.
url
:
'undefined'
,
urlLength
:
img
.
url
?
img
.
url
.
length
:
0
,
urlPrefix
:
img
.
url
?
img
.
url
.
substring
(
0
,
50
)
+
'...'
:
'N/A'
,
size
:
img
.
size
,
uploadTime
:
img
.
uploadTime
})
})
for
(
const
[
index
,
image
]
of
institution
.
images
.
entries
())
{
try
{
// 检查图片URL是否存在
console
.
log
(
`\n处理图片
${
index
+
1
}
/
${
institution
.
images
.
length
}
:
${
image
.
name
}
`
)
// 详细检查图片URL
if
(
!
image
.
url
)
{
console
.
warn
(
`图片缺少URL数据:
${
image
.
name
}
`
)
console
.
error
(
`❌ 图片缺少URL数据:`
,
{
imageName
:
image
.
name
,
imageId
:
image
.
id
,
imageObject
:
image
,
institutionName
:
institution
.
name
})
continue
}
// 检查URL格式
if
(
typeof
image
.
url
!==
'string'
)
{
console
.
error
(
`❌ 图片URL不是字符串:`
,
{
imageName
:
image
.
name
,
urlType
:
typeof
image
.
url
,
url
:
image
.
url
})
continue
}
// 检查是否是Base64格式
if
(
!
image
.
url
.
startsWith
(
'data:'
))
{
console
.
error
(
`❌ 图片URL不是Base64格式:`
,
{
imageName
:
image
.
name
,
urlPrefix
:
image
.
url
.
substring
(
0
,
100
)
})
continue
}
...
...
@@ -2182,14 +2308,28 @@ const exportUserDataAsZIP = async (exportData, userName, currentMonth) => {
zip
.
file
(
`
${
folderName
}
/
${
fileName
}
`
,
base64Data
,
{
base64
:
true
})
addedImages
++
console
.
log
(
`已添加图片:
${
folderName
}
/
${
fileName
}
`
)
console
.
log
(
`✅ 已添加图片:
${
folderName
}
/
${
fileName
}
`
,
{
mimeType
,
extension
,
base64Length
:
base64Data
.
length
})
}
else
{
console
.
warn
(
`图片Base64数据无效:
${
image
.
name
}
`
)
console
.
error
(
`❌ 图片Base64数据无效:`
,
{
imageName
:
image
.
name
,
url
:
image
.
url
,
splitResult
:
image
.
url
.
split
(
','
)
})
}
}
catch
(
error
)
{
console
.
warn
(
`处理图片失败:
${
image
.
name
}
`
,
error
)
console
.
error
(
`❌ 处理图片失败:
${
image
.
name
}
`
,
{
error
:
error
.
message
,
stack
:
error
.
stack
,
imageData
:
image
})
}
}
}
else
{
console
.
log
(
`机构
${
institution
.
name
}
没有图片数据`
)
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment