|
|
@@ -192,11 +192,11 @@
|
|
|
|
|
|
<!-- 分页 -->
|
|
|
<pagination
|
|
|
- v-show="filteredProducts.length > 0"
|
|
|
+ v-show="newProductPagination.total > 0"
|
|
|
v-model:page="newProductPagination.pageNum"
|
|
|
v-model:limit="newProductPagination.pageSize"
|
|
|
- :total="filteredProducts.length"
|
|
|
- @pagination="() => {}"
|
|
|
+ :total="newProductPagination.total"
|
|
|
+ @pagination="loadAvailableProducts"
|
|
|
/>
|
|
|
|
|
|
<template #footer>
|
|
|
@@ -240,7 +240,14 @@
|
|
|
<script setup name="IndustrialBooth" lang="ts">
|
|
|
import { ref, reactive, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
-import { Close, Picture, ArrowLeft, ArrowRight, View, Plus, Upload } from '@element-plus/icons-vue';
|
|
|
+import { Close, Picture, ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
|
|
|
+import { listProduct } from '@/api/product/base';
|
|
|
+import { listRecommend, listRecommendLink, addRecommendLink, delRecommendLink } from '@/api/product/recommend';
|
|
|
+
|
|
|
+// 推荐位编号(工业装修-轮播展位商品)
|
|
|
+const recommendNo = 'industrial_booth';
|
|
|
+const recommendId = ref<number | null>(null);
|
|
|
+const loading = ref(false);
|
|
|
|
|
|
// 对话框
|
|
|
const dialog = reactive({
|
|
|
@@ -263,70 +270,14 @@ const importProductIds = ref('');
|
|
|
// 搜索关键词
|
|
|
const searchKeyword = ref('');
|
|
|
|
|
|
-// 可选商品列表(模拟数据)
|
|
|
-const availableProducts = ref([
|
|
|
- {
|
|
|
- id: '002169823',
|
|
|
- name: '江润双色塑钢培训椅',
|
|
|
- imageUrl: '/img/江润双色塑钢培训椅.png',
|
|
|
- price: '299.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169822',
|
|
|
- name: '江润多媒体讲台',
|
|
|
- imageUrl: '/img/江润多媒体讲台.png',
|
|
|
- price: '799.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169821',
|
|
|
- name: '江润六边形折叠培训桌 800*500*750mm (直径 1.6m)',
|
|
|
- imageUrl: '/img/江润六边形折叠培训桌.png',
|
|
|
- price: '699.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169820',
|
|
|
- name: '梦洁200*230cm锦玉梦韵四件套',
|
|
|
- imageUrl: '/img/梦洁锦玉梦韵四件套.png',
|
|
|
- price: '1299.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169819',
|
|
|
- name: '洁丽雅纯棉四件套2*2.3M',
|
|
|
- imageUrl: '/img/洁丽雅纯棉四件套.png',
|
|
|
- price: '249.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169818',
|
|
|
- name: '江润实验台2000*750*800mm',
|
|
|
- imageUrl: '/img/江润实验台.png',
|
|
|
- price: '3699.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169817',
|
|
|
- name: '江润办公屏风办公桌',
|
|
|
- imageUrl: '/img/江润办公屏风办公桌.png',
|
|
|
- price: '1599.00'
|
|
|
- },
|
|
|
- {
|
|
|
- id: '002169816',
|
|
|
- name: '创维100V5-HG1会议平板触控一体机',
|
|
|
- imageUrl: '/img/创维100V5-HG1会议平板触控一体机.png',
|
|
|
- price: '12999.00'
|
|
|
- }
|
|
|
-]);
|
|
|
+// 可选商品列表(从接口获取)
|
|
|
+const availableProducts = ref<any[]>([]);
|
|
|
|
|
|
// 选中的商品ID列表(用于新增商品标签页)
|
|
|
const selectedProductIds = ref<string[]>([]);
|
|
|
|
|
|
// 新增商品分页
|
|
|
const newProductPagination = reactive({
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 20,
|
|
|
- total: 1895427
|
|
|
-});
|
|
|
-
|
|
|
-// 已选商品分页
|
|
|
-const selectedProductPagination = reactive({
|
|
|
pageNum: 1,
|
|
|
pageSize: 20,
|
|
|
total: 0
|
|
|
@@ -340,58 +291,89 @@ const pageSize = 5; // 每页显示5个商品
|
|
|
let autoPlayTimer: ReturnType<typeof setInterval> | null = null;
|
|
|
const autoPlayInterval = 3000; // 3秒切换一次
|
|
|
|
|
|
-// 模拟数据 - 已选商品列表
|
|
|
-const selectedProducts = ref([
|
|
|
- {
|
|
|
- id: '000294732',
|
|
|
- name: '江润双色塑钢培训椅',
|
|
|
- imageUrl: '/img/江润双色塑钢培训椅.png',
|
|
|
- price: '299.00',
|
|
|
- sort: 9
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000130005',
|
|
|
- name: '江润六边形折叠培训桌 800*500*750mm',
|
|
|
- imageUrl: '/img/江润六边形折叠培训桌.png',
|
|
|
- price: '699.00',
|
|
|
- sort: 8
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000371498',
|
|
|
- name: '梦洁200*230cm锦玉梦韵四件套',
|
|
|
- imageUrl: '/img/梦洁锦玉梦韵四件套.png',
|
|
|
- price: '1299.00',
|
|
|
- sort: 7
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000207453',
|
|
|
- name: '洁丽雅纯棉四件套2*2.3M',
|
|
|
- imageUrl: '/img/洁丽雅纯棉四件套.png',
|
|
|
- price: '249.00',
|
|
|
- sort: 6
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000359317',
|
|
|
- name: '江润实验台2000*750*800mm',
|
|
|
- imageUrl: '/img/江润实验台.png',
|
|
|
- price: '3699.00',
|
|
|
- sort: 5
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000123456',
|
|
|
- name: '江润办公屏风办公桌',
|
|
|
- imageUrl: '/img/江润办公屏风办公桌.png',
|
|
|
- price: '1599.00',
|
|
|
- sort: 4
|
|
|
- },
|
|
|
- {
|
|
|
- id: '000789012',
|
|
|
- name: '创维100V5-HG1会议平板触控一体机',
|
|
|
- imageUrl: '/img/创维100V5-HG1会议平板触控一体机.png',
|
|
|
- price: '12999.00',
|
|
|
- sort: 3
|
|
|
+// 已选商品列表(从接口获取)
|
|
|
+const selectedProducts = ref<any[]>([]);
|
|
|
+
|
|
|
+// 获取可选商品列表
|
|
|
+const loadAvailableProducts = async () => {
|
|
|
+ try {
|
|
|
+ const params: any = {
|
|
|
+ pageNum: newProductPagination.pageNum,
|
|
|
+ pageSize: newProductPagination.pageSize
|
|
|
+ };
|
|
|
+ if (searchKeyword.value) {
|
|
|
+ params.itemName = searchKeyword.value;
|
|
|
+ }
|
|
|
+ const res: any = await listProduct(params);
|
|
|
+ // 字段映射
|
|
|
+ availableProducts.value = (res.rows || []).map((item: any) => ({
|
|
|
+ id: item.id,
|
|
|
+ productNo: item.productNo,
|
|
|
+ name: item.itemName,
|
|
|
+ imageUrl: item.productImageUrl || item.productImage,
|
|
|
+ price: item.minSellingPrice || item.memberPrice || '0.00'
|
|
|
+ }));
|
|
|
+ newProductPagination.total = res.total || 0;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取商品列表失败', error);
|
|
|
+ availableProducts.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取推荐位ID
|
|
|
+const loadRecommendId = async () => {
|
|
|
+ try {
|
|
|
+ const res: any = await listRecommend({ recommendNo, pageSize: 1 });
|
|
|
+ if (res.rows && res.rows.length > 0) {
|
|
|
+ recommendId.value = res.rows[0].id;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取推荐位失败', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取已选商品列表(通过推荐关联)
|
|
|
+const loadSelectedProducts = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ if (!recommendId.value) {
|
|
|
+ await loadRecommendId();
|
|
|
+ }
|
|
|
+ if (!recommendId.value) {
|
|
|
+ selectedProducts.value = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 先获取推荐关联的商品ID列表
|
|
|
+ const linkRes: any = await listRecommendLink({ recommendId: recommendId.value, pageSize: 100 });
|
|
|
+ const links = linkRes.rows || [];
|
|
|
+ if (links.length === 0) {
|
|
|
+ selectedProducts.value = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 获取商品详情
|
|
|
+ const productIds = links.map((link: any) => link.productId);
|
|
|
+ const productRes: any = await listProduct({ ids: productIds.join(','), pageSize: 100 });
|
|
|
+ const productMap = new Map((productRes.rows || []).map((p: any) => [p.id, p]));
|
|
|
+ // 组装数据
|
|
|
+ selectedProducts.value = links.map((link: any, index: number) => {
|
|
|
+ const product: any = productMap.get(link.productId) || {};
|
|
|
+ return {
|
|
|
+ id: product.id || link.productId,
|
|
|
+ linkId: link.id, // 关联ID,用于删除
|
|
|
+ productNo: product.productNo,
|
|
|
+ name: product.itemName || `商品${link.productId}`,
|
|
|
+ imageUrl: product.productImageUrl || product.productImage,
|
|
|
+ price: product.minSellingPrice || product.memberPrice || '0.00',
|
|
|
+ sort: links.length - index // 默认排序
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取已选商品失败', error);
|
|
|
+ selectedProducts.value = [];
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
}
|
|
|
-]);
|
|
|
+};
|
|
|
|
|
|
// 计算当前显示的商品(按排序值降序排列)
|
|
|
const sortedProducts = computed(() => {
|
|
|
@@ -421,8 +403,10 @@ const hasNext = computed(() => {
|
|
|
});
|
|
|
|
|
|
// 查看推荐商品
|
|
|
-const handleViewProducts = () => {
|
|
|
+const handleViewProducts = async () => {
|
|
|
dialog.visible = true;
|
|
|
+ // 每次打开都重新加载数据
|
|
|
+ await loadSelectedProducts();
|
|
|
};
|
|
|
|
|
|
// 对话框关闭
|
|
|
@@ -436,6 +420,8 @@ const handleAddProduct = () => {
|
|
|
selectedProductIds.value = [];
|
|
|
searchKeyword.value = '';
|
|
|
newProductPagination.pageNum = 1;
|
|
|
+ // 加载可选商品列表
|
|
|
+ loadAvailableProducts();
|
|
|
// 等待DOM更新后,清除表格选中状态
|
|
|
nextTick(() => {
|
|
|
if (newProductTableRef.value) {
|
|
|
@@ -458,8 +444,7 @@ const handleSelectDialogClose = () => {
|
|
|
// 搜索商品
|
|
|
const handleSearchProducts = () => {
|
|
|
newProductPagination.pageNum = 1;
|
|
|
- // 这里可以调用搜索接口
|
|
|
- ElMessage.success('搜索功能开发中...');
|
|
|
+ loadAvailableProducts();
|
|
|
};
|
|
|
|
|
|
// 表格选择变化
|
|
|
@@ -470,58 +455,59 @@ const handleSelectionChange = (selection: any[]) => {
|
|
|
|
|
|
|
|
|
// 确认选择商品
|
|
|
-const handleConfirmSelect = () => {
|
|
|
+const handleConfirmSelect = async () => {
|
|
|
if (selectedProductIds.value.length === 0) {
|
|
|
ElMessage.warning('请至少选择一个商品');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 添加选中的商品到已选列表
|
|
|
- selectedProductIds.value.forEach((id) => {
|
|
|
- const product = availableProducts.value.find((p) => p.id === id);
|
|
|
- if (product && !selectedProducts.value.find((p) => p.id === id)) {
|
|
|
- selectedProducts.value.push({
|
|
|
- ...product,
|
|
|
- sort: Math.max(...selectedProducts.value.map((p) => p.sort), 0) + 1
|
|
|
- });
|
|
|
+ try {
|
|
|
+ if (!recommendId.value) {
|
|
|
+ await loadRecommendId();
|
|
|
}
|
|
|
- });
|
|
|
-
|
|
|
- ElMessage.success(`成功添加 ${selectedProductIds.value.length} 个商品`);
|
|
|
- handleSelectDialogClose();
|
|
|
-};
|
|
|
-
|
|
|
-// 过滤后的可选商品列表(不分页,用于搜索)
|
|
|
-const filteredProducts = computed(() => {
|
|
|
- let products = [...availableProducts.value];
|
|
|
-
|
|
|
- // 根据搜索关键词过滤
|
|
|
- if (searchKeyword.value) {
|
|
|
- const keyword = searchKeyword.value.toLowerCase();
|
|
|
- products = products.filter(
|
|
|
- (p) =>
|
|
|
- p.id.toLowerCase().includes(keyword) ||
|
|
|
- p.name.toLowerCase().includes(keyword)
|
|
|
- );
|
|
|
+ if (!recommendId.value) {
|
|
|
+ ElMessage.error('推荐位不存在,请先创建');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 批量添加推荐关联,统计实际添加数量
|
|
|
+ let addedCount = 0;
|
|
|
+ let skippedCount = 0;
|
|
|
+ for (const productId of selectedProductIds.value) {
|
|
|
+ // 检查是否已存在
|
|
|
+ if (selectedProducts.value.find((p) => String(p.id) === String(productId))) {
|
|
|
+ skippedCount++;
|
|
|
+ } else {
|
|
|
+ await addRecommendLink({ recommendId: recommendId.value, productId });
|
|
|
+ addedCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (addedCount > 0) {
|
|
|
+ ElMessage.success(`成功添加 ${addedCount} 个商品${skippedCount > 0 ? `,${skippedCount} 个已存在被跳过` : ''}`);
|
|
|
+ } else {
|
|
|
+ ElMessage.warning('所选商品均已存在');
|
|
|
+ }
|
|
|
+ handleSelectDialogClose();
|
|
|
+ // 刷新已选列表
|
|
|
+ await loadSelectedProducts();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('添加失败');
|
|
|
}
|
|
|
+};
|
|
|
|
|
|
- return products;
|
|
|
-});
|
|
|
-
|
|
|
-// 分页后的可选商品列表
|
|
|
+// 分页后的可选商品列表(过滤掉已选的商品)
|
|
|
const filteredAvailableProducts = computed(() => {
|
|
|
- const start = (newProductPagination.pageNum - 1) * newProductPagination.pageSize;
|
|
|
- const end = start + newProductPagination.pageSize;
|
|
|
- return filteredProducts.value.slice(start, end);
|
|
|
+ const selectedIds = selectedProducts.value.map((p) => String(p.id));
|
|
|
+ return availableProducts.value.filter((item) => !selectedIds.includes(String(item.id)));
|
|
|
});
|
|
|
|
|
|
-// 更新分页总数
|
|
|
+// 分页变化
|
|
|
watch(
|
|
|
- () => filteredProducts.value.length,
|
|
|
- (newTotal) => {
|
|
|
- newProductPagination.total = newTotal;
|
|
|
- },
|
|
|
- { immediate: true }
|
|
|
+ () => [newProductPagination.pageNum, newProductPagination.pageSize],
|
|
|
+ () => {
|
|
|
+ if (selectDialog.visible) {
|
|
|
+ loadAvailableProducts();
|
|
|
+ }
|
|
|
+ }
|
|
|
);
|
|
|
|
|
|
|
|
|
@@ -582,20 +568,28 @@ const handleConfirmImport = () => {
|
|
|
|
|
|
// 删除商品
|
|
|
const handleDeleteProduct = (id: string) => {
|
|
|
+ const product = selectedProducts.value.find((item) => String(item.id) === String(id));
|
|
|
ElMessageBox.confirm('是否确认删除该商品?', '提示', {
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning'
|
|
|
})
|
|
|
- .then(() => {
|
|
|
- const index = selectedProducts.value.findIndex((item) => item.id === id);
|
|
|
- if (index !== -1) {
|
|
|
- selectedProducts.value.splice(index, 1);
|
|
|
+ .then(async () => {
|
|
|
+ try {
|
|
|
+ if (product?.linkId) {
|
|
|
+ await delRecommendLink(product.linkId);
|
|
|
+ }
|
|
|
+ const index = selectedProducts.value.findIndex((item) => String(item.id) === String(id));
|
|
|
+ if (index !== -1) {
|
|
|
+ selectedProducts.value.splice(index, 1);
|
|
|
+ }
|
|
|
ElMessage.success('删除成功');
|
|
|
// 调整页码确保不越界
|
|
|
if (currentPage.value >= totalPages.value && currentPage.value > 0) {
|
|
|
currentPage.value = totalPages.value - 1;
|
|
|
}
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('删除失败');
|
|
|
}
|
|
|
})
|
|
|
.catch(() => {});
|
|
|
@@ -629,20 +623,28 @@ const handleNext = () => {
|
|
|
|
|
|
// 移除商品(从展示区域移除)
|
|
|
const handleRemoveProduct = (id: string) => {
|
|
|
+ const product = selectedProducts.value.find((item) => String(item.id) === String(id));
|
|
|
ElMessageBox.confirm('是否确认从展示区域移除该商品?', '提示', {
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning'
|
|
|
})
|
|
|
- .then(() => {
|
|
|
- const index = selectedProducts.value.findIndex((item) => item.id === id);
|
|
|
- if (index !== -1) {
|
|
|
- selectedProducts.value.splice(index, 1);
|
|
|
+ .then(async () => {
|
|
|
+ try {
|
|
|
+ if (product?.linkId) {
|
|
|
+ await delRecommendLink(product.linkId);
|
|
|
+ }
|
|
|
+ const index = selectedProducts.value.findIndex((item) => String(item.id) === String(id));
|
|
|
+ if (index !== -1) {
|
|
|
+ selectedProducts.value.splice(index, 1);
|
|
|
+ }
|
|
|
ElMessage.success('移除成功');
|
|
|
// 调整页码确保不越界
|
|
|
if (currentPage.value >= totalPages.value && currentPage.value > 0) {
|
|
|
currentPage.value = totalPages.value - 1;
|
|
|
}
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('移除失败');
|
|
|
}
|
|
|
})
|
|
|
.catch(() => {});
|
|
|
@@ -676,6 +678,8 @@ const stopAutoPlay = () => {
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
+ // 加载已选商品
|
|
|
+ loadSelectedProducts();
|
|
|
// 启动自动轮播
|
|
|
startAutoPlay();
|
|
|
});
|