|
@@ -14,14 +14,17 @@
|
|
|
|
|
|
|
|
<!-- 品牌展示区域 -->
|
|
<!-- 品牌展示区域 -->
|
|
|
<div class="brand-showcase">
|
|
<div class="brand-showcase">
|
|
|
- <!-- 左侧大图 -->
|
|
|
|
|
|
|
+ <!-- 左侧大图(可点击编辑) -->
|
|
|
<div class="showcase-left">
|
|
<div class="showcase-left">
|
|
|
- <el-image :src="featuredImage" fit="cover" class="featured-image">
|
|
|
|
|
|
|
+ <el-image :src="bannerConfig.imageUrl || 'https://via.placeholder.com/300x400/1a1a2e/FFFFFF?text=Featured'" fit="cover" class="featured-image">
|
|
|
<template #error>
|
|
<template #error>
|
|
|
<div class="image-slot"><el-icon><Picture /></el-icon></div>
|
|
<div class="image-slot"><el-icon><Picture /></el-icon></div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-image>
|
|
</el-image>
|
|
|
- <el-button type="warning" class="view-all-btn" @click="handleViewAll">查看全部></el-button>
|
|
|
|
|
|
|
+ <div class="edit-overlay" @click="handleEditBanner">
|
|
|
|
|
+ <span>点击编辑</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-button type="warning" class="view-all-btn" @click.stop="handleViewAll">查看全部></el-button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 右侧品牌网格 -->
|
|
<!-- 右侧品牌网格 -->
|
|
@@ -76,7 +79,7 @@
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="链接">
|
|
<el-form-item label="链接">
|
|
|
- <el-input v-model="headerForm.link" placeholder="请输入链接地址" />
|
|
|
|
|
|
|
+ <el-input v-model="headerForm.linkUrl" placeholder="请输入链接地址" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
@@ -98,48 +101,173 @@
|
|
|
<el-button @click="headerDialog.visible = false">取 消</el-button>
|
|
<el-button @click="headerDialog.visible = false">取 消</el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 编辑左侧大图对话框 -->
|
|
|
|
|
+ <el-dialog v-model="bannerDialog.visible" title="编辑品牌广告" width="500px" append-to-body>
|
|
|
|
|
+ <el-form :model="bannerForm" label-width="80px">
|
|
|
|
|
+ <el-form-item label="链接">
|
|
|
|
|
+ <el-input v-model="bannerForm.link" placeholder="请输入跳转链接" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="图片">
|
|
|
|
|
+ <image-upload v-model="bannerForm.imageUrl" :limit="1" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <el-button type="primary" @click="saveBannerConfig">确 认</el-button>
|
|
|
|
|
+ <el-button @click="bannerDialog.visible = false">取 消</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup name="FlashSale" lang="ts">
|
|
<script setup name="FlashSale" lang="ts">
|
|
|
-import { ref, reactive } from 'vue';
|
|
|
|
|
|
|
+import { ref, reactive, onMounted } from 'vue';
|
|
|
import { ElMessage } from 'element-plus';
|
|
import { ElMessage } from 'element-plus';
|
|
|
import { Picture, Close } from '@element-plus/icons-vue';
|
|
import { Picture, Close } from '@element-plus/icons-vue';
|
|
|
|
|
+import { getDecorationSectionByType, addDecorationSection, updateDecorationSection } from '@/api/decoration/section';
|
|
|
|
|
+import { listAdContent, addAdContent, updateAdContent } from '@/api/ad/content';
|
|
|
|
|
+import { listByIds } from '@/api/system/oss';
|
|
|
|
|
|
|
|
const searchKeyword = ref('');
|
|
const searchKeyword = ref('');
|
|
|
-const featuredImage = ref('https://via.placeholder.com/300x400/1a1a2e/FFFFFF?text=Featured');
|
|
|
|
|
|
|
+
|
|
|
|
|
+// 左侧大图配置
|
|
|
|
|
+const bannerConfig = ref({
|
|
|
|
|
+ id: null as number | null,
|
|
|
|
|
+ imageUrl: '',
|
|
|
|
|
+ link: ''
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const bannerDialog = reactive({ visible: false });
|
|
|
|
|
+const bannerForm = reactive({
|
|
|
|
|
+ id: null as number | null,
|
|
|
|
|
+ title: '品牌闪购大图',
|
|
|
|
|
+ imageUrl: '',
|
|
|
|
|
+ link: '',
|
|
|
|
|
+ adType: 'flash_sale_banner',
|
|
|
|
|
+ status: 1
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 加载左侧大图
|
|
|
|
|
+const loadBannerConfig = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await listAdContent({ adType: 'flash_sale_banner', pageNum: 1, pageSize: 1 });
|
|
|
|
|
+ if (res.rows && res.rows.length > 0) {
|
|
|
|
|
+ const data = res.rows[0];
|
|
|
|
|
+ let imageUrl = data.imageUrl || '';
|
|
|
|
|
+ // 把 ossId 转换成真正的图片 URL
|
|
|
|
|
+ if (imageUrl && /^\d+$/.test(imageUrl)) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const ossRes = await listByIds(imageUrl);
|
|
|
|
|
+ if (ossRes.data && ossRes.data.length > 0) {
|
|
|
|
|
+ imageUrl = ossRes.data[0].url;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('获取图片URL失败', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ bannerConfig.value = {
|
|
|
|
|
+ id: data.id,
|
|
|
|
|
+ imageUrl: imageUrl,
|
|
|
|
|
+ link: data.link || ''
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('加载大图配置失败', error);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const handleEditBanner = () => {
|
|
|
|
|
+ Object.assign(bannerForm, bannerConfig.value, { adType: 'flash_sale_banner', status: 1 });
|
|
|
|
|
+ bannerDialog.visible = true;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const saveBannerConfig = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (bannerForm.id) {
|
|
|
|
|
+ await updateAdContent(bannerForm);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await addAdContent(bannerForm);
|
|
|
|
|
+ }
|
|
|
|
|
+ await loadBannerConfig();
|
|
|
|
|
+ bannerDialog.visible = false;
|
|
|
|
|
+ ElMessage.success('大图配置已保存');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error('保存失败');
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
// 标题配置
|
|
// 标题配置
|
|
|
const headerConfig = ref({
|
|
const headerConfig = ref({
|
|
|
|
|
+ id: null as number | null,
|
|
|
title: '大牌推荐',
|
|
title: '大牌推荐',
|
|
|
subtitle: '甄选大牌,优质好品',
|
|
subtitle: '甄选大牌,优质好品',
|
|
|
linkText: '查看更多品牌信息',
|
|
linkText: '查看更多品牌信息',
|
|
|
- link: 'https://www.yoe365.com/brand',
|
|
|
|
|
|
|
+ linkUrl: 'https://www.yoe365.com/brand',
|
|
|
bgColor: '#ffffff',
|
|
bgColor: '#ffffff',
|
|
|
textColor: '#303133'
|
|
textColor: '#303133'
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const headerDialog = reactive({ visible: false });
|
|
const headerDialog = reactive({ visible: false });
|
|
|
const headerForm = reactive({
|
|
const headerForm = reactive({
|
|
|
|
|
+ id: null as number | null,
|
|
|
title: '',
|
|
title: '',
|
|
|
subtitle: '',
|
|
subtitle: '',
|
|
|
linkText: '',
|
|
linkText: '',
|
|
|
- link: '',
|
|
|
|
|
|
|
+ linkUrl: '',
|
|
|
bgColor: '#ffffff',
|
|
bgColor: '#ffffff',
|
|
|
textColor: '#303133'
|
|
textColor: '#303133'
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+// 加载标题配置
|
|
|
|
|
+const loadHeaderConfig = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getDecorationSectionByType('flash_sale');
|
|
|
|
|
+ if (res.rows && res.rows.length > 0) {
|
|
|
|
|
+ const data = res.rows[0];
|
|
|
|
|
+ headerConfig.value = {
|
|
|
|
|
+ id: data.id,
|
|
|
|
|
+ title: data.title || '大牌推荐',
|
|
|
|
|
+ subtitle: data.subtitle || '甄选大牌,优质好品',
|
|
|
|
|
+ linkText: data.linkText || '查看更多品牌信息',
|
|
|
|
|
+ linkUrl: data.linkUrl || 'https://www.yoe365.com/brand',
|
|
|
|
|
+ bgColor: data.bgColor || '#ffffff',
|
|
|
|
|
+ textColor: data.textColor || '#303133'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('加载标题配置失败', error);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const handleEditHeader = () => {
|
|
const handleEditHeader = () => {
|
|
|
Object.assign(headerForm, headerConfig.value);
|
|
Object.assign(headerForm, headerConfig.value);
|
|
|
headerDialog.visible = true;
|
|
headerDialog.visible = true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const saveHeaderConfig = () => {
|
|
|
|
|
- Object.assign(headerConfig.value, headerForm);
|
|
|
|
|
- headerDialog.visible = false;
|
|
|
|
|
- ElMessage.success('标题配置已保存');
|
|
|
|
|
|
|
+const saveHeaderConfig = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ ...headerForm,
|
|
|
|
|
+ sectionType: 'flash_sale'
|
|
|
|
|
+ };
|
|
|
|
|
+ if (headerForm.id) {
|
|
|
|
|
+ await updateDecorationSection(data);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await addDecorationSection(data);
|
|
|
|
|
+ }
|
|
|
|
|
+ await loadHeaderConfig();
|
|
|
|
|
+ headerDialog.visible = false;
|
|
|
|
|
+ ElMessage.success('标题配置已保存');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ ElMessage.error('保存失败');
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ loadHeaderConfig();
|
|
|
|
|
+ loadBannerConfig();
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
const brandList = ref([
|
|
const brandList = ref([
|
|
|
{ id: 1, title: '联想', description: '联想', logoUrl: 'https://via.placeholder.com/120x60/FFFFFF/333333?text=Lenovo' },
|
|
{ id: 1, title: '联想', description: '联想', logoUrl: 'https://via.placeholder.com/120x60/FFFFFF/333333?text=Lenovo' },
|
|
|
{ id: 2, title: '惠普', description: '惠普', logoUrl: 'https://via.placeholder.com/120x60/FFFFFF/333333?text=HP' },
|
|
{ id: 2, title: '惠普', description: '惠普', logoUrl: 'https://via.placeholder.com/120x60/FFFFFF/333333?text=HP' },
|
|
@@ -152,7 +280,11 @@ const brandList = ref([
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
const handleViewAll = () => {
|
|
const handleViewAll = () => {
|
|
|
- ElMessage.info('查看全部功能开发中...');
|
|
|
|
|
|
|
+ if (bannerConfig.value.link) {
|
|
|
|
|
+ window.open(bannerConfig.value.link, '_blank');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.info('暂未配置跳转链接');
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleRemove = (item: any) => {
|
|
const handleRemove = (item: any) => {
|
|
@@ -164,8 +296,8 @@ const handleSearch = () => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleLinkClick = () => {
|
|
const handleLinkClick = () => {
|
|
|
- if (headerConfig.value.link) {
|
|
|
|
|
- window.open(headerConfig.value.link, '_blank');
|
|
|
|
|
|
|
+ if (headerConfig.value.linkUrl) {
|
|
|
|
|
+ window.open(headerConfig.value.linkUrl, '_blank');
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
</script>
|
|
</script>
|
|
@@ -228,6 +360,28 @@ const handleLinkClick = () => {
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ .edit-overlay {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 60px;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.3);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ border-radius: 8px 8px 0 0;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transition: opacity 0.3s;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &:hover .edit-overlay {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
.view-all-btn {
|
|
.view-all-btn {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
bottom: 20px;
|
|
bottom: 20px;
|