Jelajahi Sumber

12-19-zl-前端

林小张 4 hari lalu
induk
melakukan
ceac37ece0

+ 194 - 16
src/views/platform/decoration/fresh/index.vue

@@ -98,10 +98,12 @@
 </template>
 
 <script setup name="Fresh" lang="ts">
-import { ref, reactive, onMounted } from 'vue';
-import { ElMessage } from 'element-plus';
+import { ref, reactive, computed, onMounted, nextTick } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
 import { Picture, CircleClose } from '@element-plus/icons-vue';
 import { getDecorationSectionByType, addDecorationSection, updateDecorationSection } from '@/api/decoration/section';
+import { listProduct } from '@/api/product/base';
+import { listRecommend, listRecommendLink, addRecommendLink, delRecommendLink } from '@/api/product/recommend';
 
 // 标题配置
 const headerConfig = ref({
@@ -176,24 +178,86 @@ const handleLinkClick = () => {
   }
 };
 
-// 商品列表(模拟数据,等同事接口)- 在这里修改图片路径
-const productList = ref([
-  { id: 1, name: '联想笔记本电脑', description: '高性能商务本', price: '4999.00', imageUrl: '/img/联想.jpg' },
-  { id: 2, name: '惠普打印机', description: '高效办公打印', price: '1299.00', imageUrl: '/img/惠普.jpg' },
-  { id: 3, name: '奔图激光打印机', description: '国产高品质', price: '899.00', imageUrl: '/img/奔图.jpg' },
-  { id: 4, name: 'MAXHUB会议平板', description: '智能会议解决方案', price: '12999.00', imageUrl: '/img/MAXHUB.jpg' },
-  { id: 5, name: '飞利浦显示器', description: '护眼高清屏', price: '1599.00', imageUrl: '/img/PHILIPS.jpg' }
-]);
+// 推荐位编号
+const recommendNo = 'decoration_fresh';
+const recommendId = ref<number | null>(null);
 
-// 商品操作
-const handleRemoveProduct = (id: number) => {
-  const index = productList.value.findIndex(item => item.id === id);
-  if (index > -1) {
-    productList.value.splice(index, 1);
-    ElMessage.success('已移除');
+// 商品列表
+const productList = ref<any[]>([]);
+
+// 获取推荐位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 loadProductList = async () => {
+  try {
+    if (!recommendId.value) {
+      await loadRecommendId();
+    }
+    if (!recommendId.value) {
+      productList.value = [];
+      return;
+    }
+    // 获取推荐关联
+    const linkRes: any = await listRecommendLink({ recommendId: recommendId.value, pageSize: 100 });
+    const links = linkRes.rows || [];
+    if (links.length === 0) {
+      productList.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]));
+    // 组装数据
+    productList.value = links.map((link: any) => {
+      const product: any = productMap.get(link.productId) || {};
+      return {
+        id: product.id || link.productId,
+        linkId: link.id,
+        name: product.itemName || `商品${link.productId}`,
+        description: product.remark || '',
+        price: product.minSellingPrice || product.memberPrice || '0.00',
+        imageUrl: product.productImageUrl || product.productImage
+      };
+    });
+  } catch (error) {
+    console.error('加载商品列表失败', error);
+    productList.value = [];
   }
 };
 
+// 移除商品
+const handleRemoveProduct = (id: number) => {
+  const product = productList.value.find((item) => item.id === id);
+  ElMessageBox.confirm('是否确认移除该商品?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(async () => {
+      try {
+        if (product?.linkId) {
+          await delRecommendLink(product.linkId);
+        }
+        await loadProductList();
+        ElMessage.success('已移除');
+      } catch (error) {
+        ElMessage.error('移除失败');
+      }
+    })
+    .catch(() => {});
+};
+
 // 排序对话框
 const sortDialog = reactive({ visible: false, productId: 0, sortValue: 0 });
 const handleSort = (id: number) => {
@@ -206,8 +270,94 @@ const saveSortConfig = () => {
   ElMessage.success('排序已保存');
 };
 
+// 选择商品对话框
+const selectDialog = reactive({
+  visible: false,
+  keyword: '',
+  pageNum: 1,
+  pageSize: 10,
+  total: 0
+});
+const availableProducts = ref<any[]>([]);
+const selectedProductIds = ref<number[]>([]);
+const productTableRef = ref();
+
+// 加载可选商品
+const loadAvailableProducts = async () => {
+  try {
+    const params: any = { pageNum: selectDialog.pageNum, pageSize: selectDialog.pageSize };
+    if (selectDialog.keyword) params.itemName = selectDialog.keyword;
+    const res: any = await listProduct(params);
+    availableProducts.value = (res.rows || []).map((item: any) => ({
+      id: item.id,
+      name: item.itemName,
+      imageUrl: item.productImageUrl || item.productImage,
+      price: item.minSellingPrice || item.memberPrice || '0.00'
+    }));
+    selectDialog.total = res.total || 0;
+  } catch (error) {
+    console.error('加载商品失败', error);
+    availableProducts.value = [];
+  }
+};
+
+// 过滤已选商品
+const filteredAvailableProducts = computed(() => {
+  const selectedIds = productList.value.map((p) => String(p.id));
+  return availableProducts.value.filter((item) => !selectedIds.includes(String(item.id)));
+});
+
+// 新增商品
+const handleAddProduct = () => {
+  selectDialog.keyword = '';
+  selectDialog.pageNum = 1;
+  selectDialog.visible = true;
+  selectedProductIds.value = [];
+  loadAvailableProducts();
+  nextTick(() => { productTableRef.value?.clearSelection(); });
+};
+
+// 选择变化
+const handleSelectionChange = (selection: any[]) => {
+  selectedProductIds.value = selection.map((item) => item.id);
+};
+
+// 确认选择
+const handleConfirmSelect = async () => {
+  if (selectedProductIds.value.length === 0) {
+    ElMessage.warning('请至少选择一个商品');
+    return;
+  }
+  try {
+    if (!recommendId.value) {
+      await loadRecommendId();
+    }
+    if (!recommendId.value) {
+      ElMessage.error('推荐位不存在,请先创建');
+      return;
+    }
+    let addedCount = 0;
+    for (const productId of selectedProductIds.value) {
+      if (!productList.value.find((p) => String(p.id) === String(productId))) {
+        await addRecommendLink({ recommendId: recommendId.value, productId });
+        addedCount++;
+      }
+    }
+    if (addedCount > 0) {
+      ElMessage.success(`成功添加 ${addedCount} 个商品`);
+    } else {
+      ElMessage.warning('所选商品均已存在');
+    }
+    selectDialog.visible = false;
+    await loadProductList();
+  } catch (error) {
+    ElMessage.error('添加失败');
+  }
+};
+
 onMounted(() => {
   loadHeaderConfig();
+  loadProductList();
 });
 </script>
 
@@ -223,6 +373,13 @@ onMounted(() => {
   margin: 0 auto;
 }
 
+.action-card {
+  background: #fff;
+  border-radius: 4px;
+  padding: 15px 20px;
+  margin-bottom: 12px;
+}
+
 .section-header-card {
   display: flex;
   justify-content: space-between;
@@ -341,4 +498,25 @@ onMounted(() => {
     }
   }
 }
+
+.search-bar {
+  display: flex;
+  gap: 10px;
+}
+
+.image-placeholder-small {
+  width: 60px;
+  height: 60px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #f5f5f5;
+  color: #ccc;
+  font-size: 20px;
+}
+
+.price-text {
+  color: #f56c6c;
+  font-weight: 600;
+}
 </style>

+ 47 - 5
src/views/platform/gift/title/index.vue

@@ -15,7 +15,11 @@
         <!-- 表格 -->
         <el-table v-loading="loading" :data="titleList" border>
         <el-table-column label="标题名称" align="center" prop="title" min-width="140" />
-        <el-table-column label="导航类型" align="center" prop="remark" min-width="120" />
+        <el-table-column label="导航类型" align="center" prop="remark" min-width="120">
+          <template #default="scope">
+            {{ navTypeMap[scope.row.remark] || scope.row.remark }}
+          </template>
+        </el-table-column>
         <el-table-column label="链接地址" align="center" prop="link" :show-overflow-tooltip="true" min-width="240" />
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
@@ -106,16 +110,53 @@ import type { ComponentInternalInstance } from 'vue';
 import type { ElFormInstance } from 'element-plus';
 import dayjs from 'dayjs';
 import { listAdContent, addAdContent, updateAdContent, delAdContent } from '@/api/ad/content';
+import { listNavigation } from '@/api/system/navigation';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 const loading = ref(false);
 const total = ref(0);
 const titleList = ref<any[]>([]);
-const navTypeOptions = [
-  { label: '首页导航', value: '首页导航' },
-  { label: '其他导航', value: '其他导航' }
-];
+const navTypeOptions = ref<{ label: string; value: string }[]>([]);
+
+// 导航类型映射
+const navTypeMap: Record<string, string> = {
+  home: '首页导航',
+  inner: '内页导航',
+  search: '搜索导航',
+  footer: '底部导航',
+  float: '浮动导航'
+};
+
+// 加载导航类型选项
+const loadNavTypeOptions = async () => {
+  try {
+    const res = await listNavigation({ pageNum: 1, pageSize: 100 });
+    const list = res.rows || res.data || [];
+    // 提取navType并去重
+    const typeSet = new Set<string>();
+    list.forEach((item: any) => {
+      if (item.navType) {
+        typeSet.add(item.navType);
+      }
+    });
+    // 转换为下拉选项
+    navTypeOptions.value = Array.from(typeSet).map((type) => ({
+      label: navTypeMap[type] || type,
+      value: type
+    }));
+  } catch (error) {
+    console.error('获取导航类型失败', error);
+    // 接口失败时使用默认选项
+    navTypeOptions.value = [
+      { label: '首页导航', value: 'home' },
+      { label: '内页导航', value: 'inner' },
+      { label: '搜索导航', value: 'search' },
+      { label: '底部导航', value: 'footer' },
+      { label: '浮动导航', value: 'float' }
+    ];
+  }
+};
 
 const queryParams = ref({
   pageNum: 1,
@@ -227,6 +268,7 @@ const cancel = () => {
 };
 
 onMounted(() => {
+  loadNavTypeOptions();
   getList();
 });
 </script>