fix: 完善活动公告,修复图片生成参考图无法放大问题。

This commit is contained in:
Gsh
2026-01-19 22:58:20 +08:00
parent 4ce77ececc
commit ace5a9a1ec
2 changed files with 174 additions and 38 deletions

View File

@@ -11,6 +11,21 @@ const isLoadingData = ref(false);
const activeTab = ref('activity');
// 图片预览相关状态
const isImageViewerVisible = ref(false);
const currentPreviewUrl = ref('');
// 打开图片预览
function openImagePreview(url: string) {
currentPreviewUrl.value = url;
isImageViewerVisible.value = true;
}
// 关闭图片预览
function closeImagePreview() {
isImageViewerVisible.value = false;
}
// 窗口宽度响应式状态
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1920);
@@ -123,9 +138,18 @@ watch(isDialogVisible, async (newValue) => {
:key="index"
class="activity-item"
>
<!-- 活动图片 -->
<div v-if="activity.imageUrl" class="activity-image-wrapper">
<!-- 活动图片 - 浮动在右上方 -->
<div v-if="activity.imageUrl" class="activity-image-wrapper" @click="openImagePreview(activity.imageUrl)">
<img :src="activity.imageUrl" :alt="activity.title" class="activity-image">
<!-- 放大图标提示 -->
<div class="zoom-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
<line x1="11" y1="8" x2="11" y2="14"></line>
<line x1="8" y1="11" x2="14" y2="11"></line>
</svg>
</div>
<!-- 图片上的状态标签 -->
<div class="activity-status-badge">
<el-tag
@@ -233,6 +257,16 @@ watch(isDialogVisible, async (newValue) => {
</el-button>
</div>
</template>
<!-- 图片预览组件 -->
<teleport to="body">
<el-image-viewer
v-if="isImageViewerVisible"
:url-list="[currentPreviewUrl]"
:initial-index="0"
@close="closeImagePreview"
/>
</teleport>
</el-dialog>
</template>
@@ -489,15 +523,22 @@ watch(isDialogVisible, async (newValue) => {
.activity-item {
position: relative;
padding: 0;
padding: 16px;
background: #fff;
border-radius: 16px;
overflow: hidden;
overflow: visible;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
border: 2px solid transparent;
background-clip: padding-box;
// 清除浮动,确保父容器高度正确
&::after {
content: '';
display: table;
clear: both;
}
&::before {
content: '';
position: absolute;
@@ -525,9 +566,8 @@ watch(isDialogVisible, async (newValue) => {
opacity: 1;
}
.activity-image {
transform: scale(1.1);
filter: brightness(1.05);
.activity-image-wrapper {
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.2);
}
.detail-link {
@@ -545,10 +585,31 @@ watch(isDialogVisible, async (newValue) => {
.activity-image-wrapper {
position: relative;
width: 100%;
height: 220px;
float: right;
width: 160px;
height: 160px;
margin-left: 16px;
margin-bottom: 8px;
border-radius: 12px;
overflow: hidden;
background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
shape-outside: inset(0);
transition: box-shadow 0.3s;
cursor: pointer;
z-index: 1; // 确保在内容之上
&:hover {
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
}
&:hover .activity-image {
transform: scale(1.1);
}
&:hover .zoom-icon {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
&::before {
content: '';
@@ -560,6 +621,7 @@ watch(isDialogVisible, async (newValue) => {
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
z-index: 1;
animation: shine 3s infinite;
pointer-events: none; // 确保不拦截鼠标事件
}
&::after {
@@ -587,22 +649,22 @@ watch(isDialogVisible, async (newValue) => {
.activity-image {
width: 100%;
height: 100%;
object-fit: cover;
object-fit: contain; // 等比例缩放,完整显示图片,不裁剪
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.activity-status-badge {
position: absolute;
top: 16px;
right: 16px;
top: 12px;
right: 12px;
z-index: 2;
animation: fadeInScale 0.5s ease-out 0.3s both;
:deep(.el-tag) {
border-radius: 20px;
padding: 7px 18px;
border-radius: 16px;
padding: 5px 14px;
font-weight: 700;
font-size: 13px;
font-size: 11px;
border: none;
backdrop-filter: blur(12px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
@@ -648,24 +710,52 @@ watch(isDialogVisible, async (newValue) => {
}
}
.zoom-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.8);
width: 48px;
height: 48px;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(8px);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none; // 不拦截鼠标事件让父容器接收hover
z-index: 10; // 提高层级,确保在状态标签之上
svg {
width: 24px;
height: 24px;
color: #fff;
stroke-width: 2;
}
}
.activity-body {
padding: 20px;
// 内容会自动环绕浮动的图片
position: relative;
z-index: 0; // 确保在浮动图片之下
}
.activity-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
margin-bottom: 8px;
}
.activity-title {
margin: 0;
font-size: 18px;
font-size: 16px;
font-weight: 700;
color: #1a1a1a;
flex: 1;
line-height: 1.4;
line-height: 1.3;
background: linear-gradient(135deg, #1a1a1a 0%, #4a5568 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
@@ -679,23 +769,23 @@ watch(isDialogVisible, async (newValue) => {
.activity-content-list {
padding: 0;
margin: 0 0 16px 0;
margin: 0 0 12px 0;
color: #4a5568;
font-size: 14px;
line-height: 1.8;
font-size: 13px;
line-height: 1.6;
.content-line {
margin: 8px 0;
padding-left: 18px;
margin: 6px 0;
padding-left: 16px;
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 11px;
width: 6px;
height: 6px;
top: 9px;
width: 5px;
height: 5px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
}
@@ -715,8 +805,9 @@ watch(isDialogVisible, async (newValue) => {
justify-content: space-between;
align-items: center;
gap: 16px;
padding-top: 16px;
padding-top: 12px;
border-top: 1px dashed #e8e9eb;
clear: both; // 清除浮动始终在新行显示占满100%宽度
}
.activity-time-range {
@@ -727,7 +818,7 @@ watch(isDialogVisible, async (newValue) => {
}
.activity-time {
font-size: 13px;
font-size: 12px;
color: #718096;
display: flex;
align-items: center;
@@ -735,19 +826,19 @@ watch(isDialogVisible, async (newValue) => {
&:first-child::before {
content: '🕐';
font-size: 14px;
font-size: 13px;
}
}
.detail-link {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 18px;
gap: 6px;
padding: 8px 16px;
background: linear-gradient(135deg, #f0f1f3 0%, #e8eaed 100%);
color: #667eea;
border-radius: 24px;
font-size: 13px;
border-radius: 20px;
font-size: 12px;
font-weight: 700;
text-decoration: none;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
@@ -1095,16 +1186,27 @@ watch(isDialogVisible, async (newValue) => {
.activity-item {
border-radius: 10px;
}
.activity-image-wrapper {
height: 180px;
padding: 0;
}
.activity-body {
padding: 16px;
}
.activity-image-wrapper {
float: none;
width: 100%;
height: 180px;
min-height: 180px;
margin: 0 0 16px 0;
border-radius: 10px 10px 0 0;
}
.activity-status-badge {
top: 12px;
right: 12px;
}
.activity-header {
margin-bottom: 10px;
}
@@ -1183,7 +1285,18 @@ watch(isDialogVisible, async (newValue) => {
.activity-content {
.activity-image-wrapper {
float: none;
width: 100%;
height: 200px;
margin: 0 0 16px 0;
}
.activity-item {
padding: 0;
}
.activity-body {
padding: 18px;
}
}

View File

@@ -46,6 +46,8 @@ const generating = ref(false);
const currentTaskId = ref('');
const currentTask = ref<TaskStatusResponse | null>(null);
const showViewer = ref(false);
const referenceImageViewerVisible = ref(false);
const referenceImagePreviewUrl = ref('');
let pollTimer: any = null;
let debounceTimer: any = null;
@@ -130,6 +132,17 @@ function handleRemove(file: UploadFile) {
fileList.value.splice(index, 1);
}
function handlePreview(file: UploadFile) {
if (file.url) {
referenceImagePreviewUrl.value = file.url;
referenceImageViewerVisible.value = true;
}
}
function closeReferenceImageViewer() {
referenceImageViewerVisible.value = false;
}
// Handle paste event for reference images
function handlePaste(event: ClipboardEvent) {
const items = event.clipboardData?.items;
@@ -510,6 +523,7 @@ onUnmounted(() => {
:limit="2"
:on-change="handleFileChange"
:on-remove="handleRemove"
:on-preview="handlePreview"
accept=".jpg,.jpeg,.png,.bmp,.webp"
:class="{ 'hide-upload-btn': fileList.length >= 2 }"
>
@@ -644,6 +658,15 @@ onUnmounted(() => {
</div>
</div>
</div>
<!-- 参考图预览组件 -->
<teleport to="body">
<el-image-viewer
v-if="referenceImageViewerVisible && referenceImagePreviewUrl"
:url-list="[referenceImagePreviewUrl]"
@close="closeReferenceImageViewer"
/>
</teleport>
</template>
<style scoped>