Sfoglia il codice sorgente

feat(product): 添加产品属性和品牌管理功能

- 新增产品属性编辑页面,支持品牌名称、首字母、分类选择等字段
- 实现产品品牌编辑页面,包含品牌基本信息、LOGO上传、品牌故事等功能
- 添加物流公司管理API接口,支持增删改查和状态变更
- 集成第三方对接项目管理相关API,包括商品、品牌、分类等模块
- 实现产品基础信息管理API,支持分类树、品牌列表、属性查询等功能
- 新增产品属性定义API,用于动态属性配置管理
- 完善产品分类管理功能,支持层级分类和完整路径显示
肖路 2 mesi fa
parent
commit
d58858d519
1 ha cambiato i file con 392 aggiunte e 0 eliminazioni
  1. 392 0
      src/views/product/base/detail.vue

+ 392 - 0
src/views/product/base/detail.vue

@@ -0,0 +1,392 @@
+<template>
+  <div class="app-container">
+    <el-card shadow="never" class="mb-4">
+      <template #header>
+        <div class="flex justify-between items-center">
+          <span class="text-lg font-bold">基础信息</span>
+          <el-button type="warning" @click="handleBack">返回</el-button>
+        </div>
+      </template>
+
+      <el-form :model="form" label-width="140px" class="detail-form">
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="商品编号" required>
+              <el-input v-model="form.productNo" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="商品名称" required>
+              <el-input v-model="form.itemName" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="我方平台分类" required>
+              <el-input v-model="form.categoryName" disabled placeholder="请选择" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="商品品牌" required>
+              <el-input v-model="form.brandName" disabled placeholder="请力" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="单位" required>
+              <el-input v-model="form.unitName" disabled placeholder="包" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="可售状态" required>
+              <el-switch 
+                v-model="form.canSale" 
+                active-text="是" 
+                inactive-text="否"
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="起订量" required>
+              <el-input-number v-model="form.minOrderQuantity" :min="1" disabled style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="市场价" required>
+              <el-input-number v-model="form.marketPrice" :precision="2" :min="0" disabled style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="平台价格" required>
+              <el-input-number v-model="form.memberPrice" :precision="2" :min="0" disabled style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="最低单价">
+              <el-input-number v-model="form.minSellingPrice" :precision="2" :min="0" disabled style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="副标题">
+              <el-input v-model="form.subtitle" placeholder="请输入副标题" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="UPC条码(69码)">
+              <el-input v-model="form.upcBarcode" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="规格/型号">
+              <el-input v-model="form.specification" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="16">
+            <el-form-item label="第三方电商链接">
+              <el-input v-model="form.referenceLink" placeholder="请输入第三方电商链接" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="商品卖点">
+              <el-input 
+                v-model="form.mainLibraryIntro" 
+                type="textarea" 
+                :rows="3"
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 图片管理 -->
+    <el-card shadow="never" class="mb-4">
+      <template #header>
+        <span class="text-lg font-bold">图片管理</span>
+      </template>
+
+      <div class="image-gallery">
+        <div class="image-item main-image">
+          <el-image 
+            :src="form.productImage" 
+            fit="cover"
+            :preview-src-list="[form.productImage]"
+          >
+            <template #error>
+              <div class="image-slot">
+                <el-icon><Picture /></el-icon>
+              </div>
+            </template>
+          </el-image>
+          <div class="image-label">+ 主图</div>
+        </div>
+
+        <div 
+          v-for="(image, index) in additionalImages" 
+          :key="index"
+          class="image-item"
+        >
+          <el-image 
+            :src="image" 
+            fit="cover"
+            :preview-src-list="allImages"
+            :initial-index="index + 1"
+          >
+            <template #error>
+              <div class="image-slot">
+                <el-icon><Picture /></el-icon>
+              </div>
+            </template>
+          </el-image>
+        </div>
+
+        <div class="image-item add-image">
+          <div class="image-placeholder">
+            <el-icon><Plus /></el-icon>
+            <span>+ 附图</span>
+          </div>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 产品详情 -->
+    <el-card shadow="never">
+      <template #header>
+        <span class="text-lg font-bold">产品详情</span>
+      </template>
+
+      <div class="editor-container">
+        <Editor v-model="form.pcDetail" :read-only="true" />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts" name="ProductBaseDetail">
+import { getBase } from '@/api/product/base';
+import { BaseVO, BaseForm } from '@/api/product/base/types';
+import { useRoute, useRouter } from 'vue-router';
+import Editor from '@/components/Editor/index.vue';
+import { Picture, Plus } from '@element-plus/icons-vue';
+
+const route = useRoute();
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const loading = ref(false);
+const form = ref<any>({
+  id: undefined,
+  productNo: '',
+  itemName: '',
+  brandId: undefined,
+  topCategoryId: undefined,
+  mediumCategoryId: undefined,
+  bottomCategoryId: undefined,
+  unitId: undefined,
+  productImage: '',
+  productImageUrl: '',
+  isSelf: '',
+  productReviewStatus: '',
+  homeRecommended: '',
+  categoryRecommendation: '',
+  cartRecommendation: '',
+  recommendedProductOrder: 0,
+  isPopular: '',
+  isNew: '',
+  productStatus: '',
+  dataSource: '',
+  marketPrice: 0,
+  memberPrice: 0,
+  minSellingPrice: 0,
+  purchasingPrice: 0,
+  tempGrossMargin: 0,
+  remark: '',
+  mainLibraryIntro: '',
+  upcBarcode: '',
+  specification: '',
+  referenceLink: '',
+  minOrderQuantity: 1,
+  brandName: '',
+  categoryName: '',
+  unitName: '',
+  pcDetail: '',
+  subtitle: '',
+  canSale: true
+});
+
+// 可售状态
+const canSale = computed({
+  get: () => form.value.productStatus === '1',
+  set: (val: boolean) => {
+    form.value.productStatus = val ? '1' : '0';
+  }
+});
+
+// 附加图片列表
+const additionalImages = ref<string[]>([]);
+
+// 所有图片列表(用于预览)
+const allImages = computed(() => {
+  return [form.value.productImage, ...additionalImages.value].filter(img => img);
+});
+
+/** 获取产品详情 */
+const getDetail = async () => {
+  loading.value = true;
+  try {
+    const id = route.params.id as string;
+    const res = await getBase(id);
+    form.value = res.data;
+    
+    // 解析附加图片(如果有的话,根据实际数据结构调整)
+    if (form.value.mainImage) {
+      const images = form.value.mainImage.split(',');
+      additionalImages.value = images.slice(1); // 第一张是主图,其余是附图
+    }
+  } catch (error) {
+    console.error('获取详情失败:', error);
+    proxy?.$modal.msgError('获取详情失败');
+  } finally {
+    loading.value = false;
+  }
+};
+
+/** 返回 */
+const handleBack = () => {
+  router.back();
+};
+
+onMounted(() => {
+  getDetail();
+});
+</script>
+
+<style scoped lang="scss">
+.app-container {
+  padding: 20px;
+}
+
+.detail-form {
+  :deep(.el-form-item__label) {
+    color: #606266;
+    font-weight: 500;
+  }
+
+  :deep(.el-input.is-disabled .el-input__inner),
+  :deep(.el-textarea.is-disabled .el-textarea__inner),
+  :deep(.el-input-number.is-disabled .el-input__inner) {
+    color: #606266;
+    background-color: #f5f7fa;
+  }
+}
+
+.image-gallery {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+  gap: 16px;
+  padding: 10px 0;
+
+  .image-item {
+    position: relative;
+    width: 150px;
+    height: 150px;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    overflow: hidden;
+    cursor: pointer;
+    transition: all 0.3s;
+
+    &:hover {
+      border-color: #409eff;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+    }
+
+    &.main-image {
+      border-color: #67c23a;
+      border-width: 2px;
+    }
+
+    .el-image {
+      width: 100%;
+      height: 100%;
+    }
+
+    .image-label {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      background: rgba(0, 0, 0, 0.6);
+      color: #fff;
+      text-align: center;
+      padding: 4px;
+      font-size: 12px;
+    }
+
+    .image-slot {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      height: 100%;
+      background: #f5f7fa;
+      color: #909399;
+
+      .el-icon {
+        font-size: 30px;
+      }
+    }
+  }
+
+  .add-image {
+    border-style: dashed;
+    background: #fafafa;
+
+    &:hover {
+      background: #f5f7fa;
+    }
+
+    .image-placeholder {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      width: 100%;
+      height: 100%;
+      color: #909399;
+
+      .el-icon {
+        font-size: 30px;
+        margin-bottom: 8px;
+      }
+
+      span {
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.editor-container {
+  min-height: 400px;
+
+  :deep(.w-e-text-container) {
+    background-color: #f5f7fa !important;
+  }
+}
+</style>