fix: 修复赛事规程下载文件无后缀问题
- event-rules页面H5环境使用a标签download属性指定文件名 - 修复api.config.js生产环境API地址配置 - 优化多个页面的附件展示 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,27 @@
|
||||
<template>
|
||||
<view class="event-info-page">
|
||||
<!-- 附件下载区 -->
|
||||
<view class="attachments-section" v-if="attachments.length > 0">
|
||||
<view class="section-title">
|
||||
<text class="title-icon">📎</text>
|
||||
<text class="title-text">相关附件</text>
|
||||
</view>
|
||||
<view class="attachments-list">
|
||||
<view class="attachment-item" v-for="(file, index) in attachments" :key="index" @click="downloadFile(file)">
|
||||
<view class="file-info">
|
||||
<text class="file-icon">{{ getFileIcon(file.fileType) }}</text>
|
||||
<view class="file-details">
|
||||
<text class="file-name">{{ file.fileName }}</text>
|
||||
<text class="file-size">{{ file.fileSize }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="download-btn">
|
||||
<text class="download-icon">⬇</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 信息列表 -->
|
||||
<view class="info-list">
|
||||
<view class="info-item" v-for="(item, index) in infoList" :key="index" @click="handleItemClick(item)">
|
||||
@@ -13,7 +35,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="infoList.length === 0">
|
||||
<view class="empty-state" v-if="infoList.length === 0 && attachments.length === 0">
|
||||
<text class="empty-text">暂无信息发布</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -21,21 +43,57 @@
|
||||
|
||||
<script>
|
||||
import infoAPI from '@/api/info.js'
|
||||
import competitionAPI from '@/api/competition.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
eventId: '',
|
||||
infoList: []
|
||||
infoList: [],
|
||||
attachments: []
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.eventId) {
|
||||
this.eventId = options.eventId
|
||||
this.loadInfoList(options.eventId)
|
||||
this.loadAttachments(options.eventId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 加载附件列表
|
||||
*/
|
||||
async loadAttachments(eventId) {
|
||||
try {
|
||||
const res = await competitionAPI.getAttachments({
|
||||
competitionId: eventId,
|
||||
type: 'info'
|
||||
})
|
||||
|
||||
let list = []
|
||||
if (res && Array.isArray(res)) {
|
||||
list = res
|
||||
} else if (res && res.records) {
|
||||
list = res.records
|
||||
} else if (res && res.data && Array.isArray(res.data)) {
|
||||
list = res.data
|
||||
}
|
||||
|
||||
if (list.length > 0) {
|
||||
this.attachments = list.map(file => ({
|
||||
id: file.id,
|
||||
fileName: file.fileName || file.name,
|
||||
fileUrl: file.fileUrl || file.url,
|
||||
fileSize: this.formatFileSize(file.fileSize || file.size),
|
||||
fileType: file.fileType || this.getFileType(file.fileName || file.name)
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载附件失败:', err)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 加载信息发布列表
|
||||
*/
|
||||
@@ -50,11 +108,6 @@ export default {
|
||||
list = res
|
||||
}
|
||||
|
||||
// 如果后端没有数据,使用模拟数据
|
||||
if (list.length === 0) {
|
||||
list = this.getMockData()
|
||||
}
|
||||
|
||||
// 数据映射
|
||||
this.infoList = list.map(item => ({
|
||||
id: item.id,
|
||||
@@ -66,81 +119,100 @@ export default {
|
||||
}))
|
||||
} catch (err) {
|
||||
console.error('加载信息列表失败:', err)
|
||||
// 加载失败时使用模拟数据
|
||||
const list = this.getMockData()
|
||||
this.infoList = list.map(item => ({
|
||||
id: item.id,
|
||||
type: this.getInfoType(item.info_type || item.type),
|
||||
typeText: this.getInfoTypeText(item.info_type || item.type),
|
||||
title: item.title,
|
||||
desc: item.content,
|
||||
time: this.formatTime(item.publishTime)
|
||||
}))
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取模拟数据
|
||||
* 下载文件
|
||||
*/
|
||||
getMockData() {
|
||||
return [
|
||||
{
|
||||
id: 1,
|
||||
info_type: 3,
|
||||
title: '重要通知:赛事报名截止时间变更',
|
||||
content: '由于场馆调整,本次赛事报名截止时间延长至2025年12月20日,请各位选手抓紧时间报名。如有疑问,请联系赛事组委会。',
|
||||
publishTime: '2025-01-10 09:00:00'
|
||||
downloadFile(file) {
|
||||
const fileExt = file.fileType || this.getFileType(file.fileName) || 'pdf'
|
||||
|
||||
// #ifdef H5
|
||||
const link = document.createElement('a')
|
||||
link.href = file.fileUrl
|
||||
link.download = file.fileName
|
||||
link.target = '_blank'
|
||||
link.style.display = 'none'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
uni.showToast({
|
||||
title: '开始下载',
|
||||
icon: 'success'
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.showLoading({ title: '准备下载' })
|
||||
uni.downloadFile({
|
||||
url: file.fileUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.openDocument({
|
||||
filePath: res.tempFilePath,
|
||||
fileType: fileExt,
|
||||
success: () => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '打开成功', icon: 'success' })
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading()
|
||||
console.error('打开文件失败:', err)
|
||||
uni.showToast({ title: '打开失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
info_type: 1,
|
||||
title: '参赛选手须知',
|
||||
content: '请各位参赛选手提前1小时到达比赛场地进行检录,携带身份证原件及复印件。比赛期间请遵守赛场纪律,服从裁判判决。',
|
||||
publishTime: '2025-01-09 14:30:00'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
info_type: 2,
|
||||
title: '比赛场地及交通指引',
|
||||
content: '本次赛事在市体育中心举行,地址:XX市XX区XX路100号。可乘坐地铁2号线至体育中心站下车,或乘坐公交车88路、99路至体育中心站。场馆提供免费停车位。',
|
||||
publishTime: '2025-01-08 16:00:00'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
info_type: 1,
|
||||
title: '赛前训练安排通知',
|
||||
content: '为方便各位选手熟悉场地,组委会安排在比赛前一天(12月24日)下午14:00-17:00开放场地供选手训练。请需要训练的选手提前联系组委会预约。',
|
||||
publishTime: '2025-01-07 10:20:00'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
info_type: 2,
|
||||
title: '比赛流程及注意事项',
|
||||
content: '比赛采用淘汰赛制,分为预赛、半决赛和决赛三个阶段。每场比赛时长为5分钟,选手需提前做好热身准备。比赛过程中严禁使用违禁器材。',
|
||||
publishTime: '2025-01-06 11:45:00'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
info_type: 1,
|
||||
title: '医疗保障及安全提示',
|
||||
content: '赛事现场配备专业医疗团队和救护车,设有医疗服务点。建议选手自备常用药品,如有特殊疾病请提前告知组委会。比赛前请充分热身,避免受伤。',
|
||||
publishTime: '2025-01-05 15:10:00'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
info_type: 3,
|
||||
title: '关于赛事直播安排的通知',
|
||||
content: '本次赛事将进行全程网络直播,届时可通过官方网站和APP观看。精彩瞬间将在赛后剪辑发布,敬请期待!',
|
||||
publishTime: '2025-01-04 13:00:00'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
info_type: 2,
|
||||
title: '志愿者招募公告',
|
||||
content: '赛事组委会现招募志愿者50名,负责现场引导、秩序维护、后勤保障等工作。有意者请扫描海报二维码报名,报名截止时间为12月15日。',
|
||||
publishTime: '2025-01-03 09:30:00'
|
||||
fail: (err) => {
|
||||
uni.hideLoading()
|
||||
console.error('下载失败:', err)
|
||||
uni.showToast({ title: '下载失败', icon: 'none' })
|
||||
}
|
||||
]
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
*/
|
||||
getFileType(fileName) {
|
||||
if (!fileName) return 'pdf'
|
||||
const ext = fileName.split('.').pop().toLowerCase()
|
||||
return ext
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文件图标
|
||||
*/
|
||||
getFileIcon(fileType) {
|
||||
const iconMap = {
|
||||
'pdf': '📕',
|
||||
'doc': '📘',
|
||||
'docx': '📘',
|
||||
'xls': '📗',
|
||||
'xlsx': '📗',
|
||||
'ppt': '📙',
|
||||
'pptx': '📙',
|
||||
'txt': '📄',
|
||||
'zip': '📦',
|
||||
'rar': '📦'
|
||||
}
|
||||
return iconMap[fileType] || '📄'
|
||||
},
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
*/
|
||||
formatFileSize(bytes) {
|
||||
if (!bytes || bytes === 0) return '0 B'
|
||||
if (typeof bytes === 'string') return bytes
|
||||
|
||||
const k = 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i]
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -190,7 +262,6 @@ export default {
|
||||
},
|
||||
|
||||
handleItemClick(item) {
|
||||
// 跳转到信息详情页
|
||||
uni.navigateTo({
|
||||
url: `/pages/event-info-detail/event-info-detail?id=${item.id}&type=${item.type}&typeText=${encodeURIComponent(item.typeText)}&title=${encodeURIComponent(item.title)}&content=${encodeURIComponent(item.desc)}&time=${encodeURIComponent(item.time)}`
|
||||
})
|
||||
@@ -206,6 +277,103 @@ export default {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
// 区块标题
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.title-icon {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
// 附件下载区
|
||||
.attachments-section {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.attachments-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 25rpx 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s;
|
||||
|
||||
&:active {
|
||||
background-color: #f8f8f8;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
font-size: 48rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.file-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
background-color: #C93639;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.download-icon {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user