2 Commits
Author SHA1 Message Date
c-zhangr1 360ce71f0b 移动端品牌活动图片预览整改 2026-11-06 11:08:55 +08:00
c-zhangr1 0a431bf86e 移动端品牌活动活动介绍预览整改 2026-11-05 10:31:15 +08:00
3 changed files with 122 additions and 32 deletions
@@ -347,6 +347,19 @@ module.exports = {
// 预览图片
handlePreview(file) {
if (this.upload_mode === "image") {
// 回显记录的名称可能是无扩展名的下载地址;图片模式直接预览缩略图地址。
const url = file.url || (this.upload_result_type === "url" && file.response?.data)
if (!url) {
this.$message.warning("暂无可预览的图片")
return
}
const image = new Image()
image.src = url
const viewer = new Viewer(image, {zIndex: 99999, title: false, hidden: () => viewer.destroy()})
viewer.show()
return
}
const suffix = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase()
const fileId = file.response.data.substring(file.response.data.lastIndexOf("=") + 1)
const buildFile = {
@@ -10,13 +10,48 @@ layout("/layouts/platform_h5.html"){
box-shadow: 0 8px 12px #ebedf0;
text-align: center !important;
}
.info-container {
margin-bottom: 60px;
.activity-info-sheet {
height: 90vh;
height: 90dvh;
max-height: 90vh;
max-height: 90dvh;
}
.button {
position: fixed;
bottom: 0;
.activity-info-sheet .van-action-sheet__content {
display: flex;
min-height: 0;
overflow: hidden;
}
.activity-info-sheet .info-container {
display: flex;
flex: 1;
min-width: 0;
min-height: 0;
flex-direction: column;
}
.activity-info-sheet .info-body {
flex: 1;
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* PDF内部使用百分比高度,必须提供明确的预览高度;外层正文仍可滚动查看封面和全文。 */
.activity-info-sheet .info-preview {
height: 60vh;
height: 60dvh;
min-height: 260px;
}
.activity-info-sheet .info-preview > div {
height: 100%;
}
.activity-info-sheet .info-preview .content img {
max-width: 100%;
height: auto;
}
.activity-info-sheet .button {
flex-shrink: 0;
width: 100%;
padding-bottom: env(safe-area-inset-bottom);
background: #fff;
}
.info-img {
display: block;
@@ -27,7 +62,7 @@ layout("/layouts/platform_h5.html"){
</style>
<div id="app">
<van-nav-bar title="品牌活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-nav-bar title="品牌活动" left-text="返回" left-arrow @click-left="onNavBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
@@ -67,13 +102,14 @@ layout("/layouts/platform_h5.html"){
</template>
</table-list>
<van-action-sheet :close-on-click-overlay="false" title="详细信息" v-model="infoVisible">
<van-action-sheet class="activity-info-sheet" :close-on-click-overlay="false" title="详细信息"
:value="infoVisible" @input="visible => { if (!visible) closeInfo() }">
<div class="info-container">
<div>
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
<div class="info-body">
<van-image class="info-img" height="124" width="100%" :src="infoRow.cover"></van-image>
<div class="info-title">{{infoRow.activityName}}</div>
<pdf-preview :content="infoRow.introduce"></pdf-preview>
<div class="info-preview"><pdf-preview :content="infoRow.introduce"></pdf-preview></div>
</div>
<div class="button">
<van-button @click="onApply(infoRow)" type="primary" block>
@@ -82,7 +118,7 @@ layout("/layouts/platform_h5.html"){
</span>
<template v-else>
距离开始
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒" @finish="time = 0"></van-count-down>
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒" @finish="this.$set(this, 'time', 0)"></van-count-down>
</template>
</van-button>
</div>
@@ -100,6 +136,9 @@ layout("/layouts/platform_h5.html"){
},
data() {
return {
popupOwnerId: 'train-activity-info-' + Date.now(),
infoClosing: false,
pageDisposed: false,
time: 0,
pageForm: {
pageNumber: 1,
@@ -116,35 +155,45 @@ layout("/layouts/platform_h5.html"){
],
infoVisible: false,
infoRow: {},
id: GetQueryString('id')
}
},
methods: {
onView(row) {
this.infoRow = row
this.time = this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds')
this.infoVisible = true
if (this.pageDisposed || this.infoClosing) return
// 详情只由列表中的“查看介绍”点击打开,不根据链接参数或报名操作自动打开。
this.$set(this, 'infoRow', row)
this.$set(this, 'time', this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds'))
this.$set(this, 'infoVisible', true)
// 重复查看仅更新内容,不重复压入历史;关闭和系统返回统一交给全局栈。
window.mobilePopupHistory.open(this.popupOwnerId, 'info')
},
closeInfo() {
if (!this.infoVisible || this.infoClosing) return
// 回退为异步操作:立即隐藏并锁定本次关闭,防止连点产生多次历史回退。
this.$set(this, 'infoClosing', true)
this.$set(this, 'infoVisible', false)
window.mobilePopupHistory.close(this.popupOwnerId, 'info')
},
onInfoHistoryClose() {
// 系统返回和关闭按钮共用回调,关闭后允许用户再次主动查看。
this.$set(this, 'infoVisible', false)
this.$set(this, 'infoClosing', false)
},
onNavBack() {
if (window.mobilePopupHistory.hasOpen(this.popupOwnerId)) this.closeInfo()
else historyBack()
},
onApply(row) {
if(this.$moment().isBefore(this.$moment(row.activitySignUpStartTime))) {
this.onView(row)
this.$toast('报名尚未开始')
return
}
window.mobilePopupHistory.clear(this.popupOwnerId)
this.$pjaxReplace('/platform/trainSignUp/apply/list/h5?id=' + row.id)
},
fetchOne() {
this.$axios.post('/platform/trainSignUp/manage/findOne', {id: this.id}).then((res) => {
if(res.code === 0) {
this.onView(res.data)
}
})
},
onReady() {
// 首次进入和组件重新就绪都只加载列表,不触发详情弹窗。
this.doSearch()
if(this.id) {
this.fetchOne()
}
},
doSearch() {
this.$nextTick(() => {
@@ -154,8 +203,12 @@ layout("/layouts/platform_h5.html"){
})
}
},
mounted() {
created() {
window.mobilePopupHistory.register(this.popupOwnerId, () => this.onInfoHistoryClose())
},
beforeDestroy() {
this.$set(this, 'pageDisposed', true)
window.mobilePopupHistory.unregister(this.popupOwnerId)
}
})
</script>
@@ -707,9 +707,8 @@ layout("/layouts/platform_h5.html"){
:key="option.id"
class="welfare-option"
:class="{ selected: projectInfo.isCheckBox === 'radio' ? selectedRadioId === option.id : option.selectNum > 0 }"
@click="projectInfo.isCheckBox === 'radio' && !isDeadlinePassed ? selectRadioOption(option.id) : null"
>
<div class="welfare-option-image">
<div class="welfare-option-image" @click.stop="previewOptionImage(option.imgUrl)">
<van-image :src="option.imgUrl" fit="cover" width="100%" height="100%" radius="4px"></van-image>
<div class="welfare-tag"
v-if="projectInfo.isCheckBox === 'radio' ? selectedRadioId === option.id : option.selectNum > 0">
@@ -717,7 +716,8 @@ layout("/layouts/platform_h5.html"){
</div>
</div>
<div class="welfare-option-content">
<div class="welfare-option-content"
@click="projectInfo.isCheckBox === 'radio' && !isDeadlinePassed ? selectRadioOption(option.id) : null">
<div class="welfare-option-title">{{ option.optionName }}</div>
<!-- 查看详情按钮 -->
@@ -846,6 +846,10 @@ layout("/layouts/platform_h5.html"){
</div>
</van-action-sheet>
<van-image-preview :value="showOptionImagePreview" :images="optionPreviewImages"
closeable :show-index="false" :close-on-popstate="false"
@input="visible => { if (!visible) closeOptionImagePreview() }"></van-image-preview>
<!-- 选项详情弹窗 -->
<van-popup v-model="showOptionDetailDialog" round closeable close-icon="close" position="bottom"
:close-on-click-overlay="false"
@@ -932,6 +936,8 @@ layout("/layouts/platform_h5.html"){
isSubmitting: false,
hasSubmittedBefore: false, // 是否之前提交过
showOptionDetailDialog: false, // 选项详情弹窗
showOptionImagePreview: false,
optionPreviewImages: [],
selectedOption: null, // 当前选中的选项
popupHistoryOwner: "welfare-select-" + Date.now(),
detailScale: 1,
@@ -1347,6 +1353,21 @@ layout("/layouts/platform_h5.html"){
},
// 显示选项详情
previewOptionImage(url) {
if (!url || this.showOptionImagePreview) return
// 图片预览不修改选项状态,返回键只关闭当前预览层。
this.$set(this, "optionPreviewImages", [url])
this.$set(this, "showOptionImagePreview", true)
window.mobilePopupHistory.open(this.popupHistoryOwner, "optionImage")
},
closeOptionImagePreview() {
if (!this.showOptionImagePreview) return
// 先隐藏,防止关闭动画期间的重复点击触发多次历史回退。
this.$set(this, "showOptionImagePreview", false)
window.mobilePopupHistory.close(this.popupHistoryOwner, "optionImage")
},
showOptionDetail(option) {
this.selectedOption = option
this.showOptionDetailDialog = true
@@ -1370,6 +1391,9 @@ layout("/layouts/platform_h5.html"){
},
closePopupFromHistory(popupId) {
if (popupId === "optionImage") {
this.$set(this, "showOptionImagePreview", false)
}
if (popupId === "optionDetail") {
this.showOptionDetailDialog = false
}