|
|
@@ -1,31 +1,82 @@
|
|
|
<template>
|
|
|
<div class="p-2">
|
|
|
+ <!-- 返回按钮 -->
|
|
|
+ <div class="mb-4 flex items-center">
|
|
|
+ <el-button link icon="ArrowLeft" @click="goBack">返回</el-button>
|
|
|
+ <span class="ml-2 text-lg font-bold">商品配置</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索区域 -->
|
|
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
|
|
<div v-show="showSearch" class="mb-[10px]">
|
|
|
<el-card shadow="hover">
|
|
|
- <el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
|
|
- <el-form-item label="所属池ID" prop="poolId">
|
|
|
- <el-input v-model="queryParams.poolId" placeholder="请输入所属池ID" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="产品id" prop="productId">
|
|
|
- <el-input v-model="queryParams.productId" placeholder="请输入产品id" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="产品价格" prop="productPrice">
|
|
|
- <el-input v-model="queryParams.productPrice" placeholder="请输入产品价格" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="审核原因" prop="reviewReason">
|
|
|
- <el-input v-model="queryParams.reviewReason" placeholder="请输入审核原因" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="是否显示:1=是,0=否" prop="isShow">
|
|
|
- <el-input v-model="queryParams.isShow" placeholder="请输入是否显示:1=是,0=否" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="平台标识" prop="platformCode">
|
|
|
- <el-input v-model="queryParams.platformCode" placeholder="请输入平台标识" clearable @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
|
- </el-form-item>
|
|
|
+ <el-form ref="queryFormRef" :model="queryParams" label-width="90px">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="商品编号" prop="productNo">
|
|
|
+ <el-input v-model="queryParams.productNo" placeholder="请输入商品编号" clearable @keyup.enter="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="商品名称" prop="itemName">
|
|
|
+ <el-input v-model="queryParams.itemName" placeholder="请输入商品名称" clearable @keyup.enter="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="商品品牌" prop="brandId">
|
|
|
+ <el-input v-model="queryParams.brandId" placeholder="请选择" clearable />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="上下架状态" prop="productStatus">
|
|
|
+ <el-select v-model="queryParams.productStatus" placeholder="请选择" clearable>
|
|
|
+ <el-option label="上架" value="1" />
|
|
|
+ <el-option label="下架" value="0" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="商品类别" prop="categoryId">
|
|
|
+ <el-tree-select
|
|
|
+ v-model="queryParams.categoryId"
|
|
|
+ :data="categoryOptions"
|
|
|
+ :props="{ value: 'id', label: 'label', children: 'children' }"
|
|
|
+ check-strictly
|
|
|
+ :render-after-expand="false"
|
|
|
+ clearable
|
|
|
+ placeholder="请选择商品类别"
|
|
|
+ >
|
|
|
+ <template #default="{ data }">
|
|
|
+ <span>{{ getCategoryFullPath(data.id) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-tree-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="创建供应商" prop="supplier">
|
|
|
+ <el-input v-model="queryParams.supplier" placeholder="请选择创建供应商" clearable />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-form-item label="入池时间" prop="dateRange">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="queryParams.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始时间"
|
|
|
+ end-placeholder="结束时间"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6" class="text-left">
|
|
|
+ <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
+ <el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
|
+ <el-button type="danger" plain @click="handleClearPool">清空产品池</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
</el-form>
|
|
|
</el-card>
|
|
|
</div>
|
|
|
@@ -33,242 +84,506 @@
|
|
|
|
|
|
<el-card shadow="never">
|
|
|
<template #header>
|
|
|
- <el-row :gutter="10" class="mb8">
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['product:poolLink:add']">新增</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['product:poolLink:edit']">修改</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['product:poolLink:remove']">删除</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['product:poolLink:export']">导出</el-button>
|
|
|
- </el-col>
|
|
|
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
- </el-row>
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <span class="font-bold">商品列表信息列表</span>
|
|
|
+ <div class="flex gap-2">
|
|
|
+ <el-button type="primary" icon="Plus" @click="handleAddProduct">添加商品</el-button>
|
|
|
+ <el-button type="success" icon="Download" @click="handleExportProduct">导出商品</el-button>
|
|
|
+ <el-button type="warning" icon="Upload" @click="handleImportProduct">导入商品</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
- <el-table v-loading="loading" border :data="poolLinkList" @selection-change="handleSelectionChange">
|
|
|
- <el-table-column type="selection" width="55" align="center" />
|
|
|
- <el-table-column label="主键ID" align="center" prop="id" v-if="true" />
|
|
|
- <el-table-column label="所属池ID" align="center" prop="poolId" />
|
|
|
- <el-table-column label="产品id" align="center" prop="productId" />
|
|
|
- <el-table-column label="产品价格" align="center" prop="productPrice" />
|
|
|
- <el-table-column label="是否在池中:1-是,0-否" align="center" prop="isPoolStatus" />
|
|
|
- <el-table-column label="产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回" align="center" prop="productReviewStatus" />
|
|
|
- <el-table-column label="审核原因" align="center" prop="reviewReason" />
|
|
|
- <el-table-column label="是否显示:1=是,0=否" align="center" prop="isShow" />
|
|
|
- <el-table-column label="备注" align="center" prop="remark" />
|
|
|
- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
|
|
+ <el-table v-loading="loading" border :data="productList">
|
|
|
+ <el-table-column type="index" label="序号" width="60" align="center" />
|
|
|
+ <el-table-column label="商品编号" align="center" prop="productNo" width="120" />
|
|
|
+ <el-table-column label="商品图片" align="center" prop="productImageUrl" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <image-preview :src="scope.row.productImageUrl" :width="60" :height="60"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品信息" align="center" width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>{{ scope.row.itemName }}</div>
|
|
|
+ <div class="text-gray-500">品牌:{{ scope.row.brandName || '-' }}</div>
|
|
|
+ <div class="text-gray-500">库存:{{ scope.row.stock || '999' }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品类别" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>{{ scope.row.categoryName || '办公设备+扫描设备+平板式扫描仪' }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="单位" align="center" prop="unitName" width="80" />
|
|
|
+ <el-table-column label="SKU价格" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">市场价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.marketPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">平台售价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.platformPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">最低售价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.minPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="成本数据" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">采购价:</span>
|
|
|
+ <span>¥{{ scope.row.purchasePrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">暂估毛利率:</span>
|
|
|
+ <span>{{ scope.row.grossMargin || '0.00' }}%</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="项目平台价" align="center" prop="platformPrice" width="100" />
|
|
|
+ <el-table-column label="商品状态" align="center" width="80">
|
|
|
<template #default="scope">
|
|
|
- <el-tooltip content="修改" placement="top">
|
|
|
- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['product:poolLink:edit']"></el-button>
|
|
|
- </el-tooltip>
|
|
|
- <el-tooltip content="删除" placement="top">
|
|
|
- <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['product:poolLink:remove']"></el-button>
|
|
|
- </el-tooltip>
|
|
|
+ <el-tag v-if="scope.row.productStatus === '1'" type="success">上架</el-tag>
|
|
|
+ <el-tag v-else type="warning">下架</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="入池时间" align="center" prop="createTime" width="120" />
|
|
|
+ <el-table-column label="创建供应商" align="center" prop="supplier" width="100" />
|
|
|
+ <el-table-column label="操作" align="center" width="120" fixed="right">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="flex flex-col gap-1">
|
|
|
+ <el-link type="primary" :underline="false" @click="handlePriceMaintain(scope.row)">价格维护</el-link>
|
|
|
+ <el-link type="primary" :underline="false" @click="handleInventoryMaintain(scope.row)">修改库存</el-link>
|
|
|
+ <el-link type="danger" :underline="false" @click="handleRemoveProduct(scope.row)">移除商品池</el-link>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
|
|
</el-card>
|
|
|
- <!-- 添加或修改产品池和产品关联对话框 -->
|
|
|
- <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
|
|
- <el-form ref="poolLinkFormRef" :model="form" :rules="rules" label-width="80px">
|
|
|
- <el-form-item label="所属池ID" prop="poolId">
|
|
|
- <el-input v-model="form.poolId" placeholder="请输入所属池ID" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="产品id" prop="productId">
|
|
|
- <el-input v-model="form.productId" placeholder="请输入产品id" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="产品价格" prop="productPrice">
|
|
|
- <el-input v-model="form.productPrice" placeholder="请输入产品价格" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="审核原因" prop="reviewReason">
|
|
|
- <el-input v-model="form.reviewReason" placeholder="请输入审核原因" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="是否显示:1=是,0=否" prop="isShow">
|
|
|
- <el-input v-model="form.isShow" placeholder="请输入是否显示:1=是,0=否" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="备注" prop="remark">
|
|
|
- <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <template #footer>
|
|
|
- <div class="dialog-footer">
|
|
|
- <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
|
|
- <el-button @click="cancel">取 消</el-button>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
+
|
|
|
+ <!-- 添加商品对话框 -->
|
|
|
+ <el-dialog title="添加商品" v-model="addProductDialog.visible" width="1400px" append-to-body top="5vh">
|
|
|
+ <div class="add-product-dialog">
|
|
|
+ <!-- 搜索区域 -->
|
|
|
+ <el-form :model="addProductQuery" :inline="true" class="mb-4">
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="Plus" @click="handleBatchAdd">加入清单</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="商品名称:">
|
|
|
+ <el-input v-model="addProductQuery.itemName" placeholder="商品名称" clearable style="width: 200px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="商品编号:">
|
|
|
+ <el-input v-model="addProductQuery.productNo" placeholder="商品编号" clearable style="width: 200px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="Search" @click="handleSearchProducts">搜索</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 商品列表 -->
|
|
|
+ <el-table
|
|
|
+ ref="addProductTableRef"
|
|
|
+ v-loading="addProductDialog.loading"
|
|
|
+ :data="addProductDialog.productList"
|
|
|
+ border
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ max-height="500"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55" align="center" />
|
|
|
+ <el-table-column label="商品编号" align="center" prop="productNo" width="120" />
|
|
|
+ <el-table-column label="商品图片" align="center" prop="productImageUrl" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <image-preview :src="scope.row.productImageUrl" :width="60" :height="60"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品信息" align="center" min-width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>{{ scope.row.itemName }}</div>
|
|
|
+ <div class="text-gray-500">品牌:{{ scope.row.brandName || '雅唐' }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品分类" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>{{ getCategoryName(scope.row) }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="单位" align="center" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>单位:{{ scope.row.unitName || '件' }}</div>
|
|
|
+ <div>起订量:{{ scope.row.minOrderQuantity || 1 }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="SKU价格" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">市场价:</span>
|
|
|
+ <span>¥{{ scope.row.midRangePrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">平台价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.standardPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">最低价:</span>
|
|
|
+ <span>¥{{ scope.row.certificatePrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="库存情况" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div class="text-red-500">库存总数:{{ scope.row.stock || 0 }}</div>
|
|
|
+ <div>现有库存:{{ scope.row.availableStock || 0 }}</div>
|
|
|
+ <div>虚拟库存:{{ scope.row.virtualStock || 0 }}</div>
|
|
|
+ <div class="text-orange-500">[现有库存不足时]</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="供应情况" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px;">
|
|
|
+ <div>供应商数量:{{ scope.row.supplierCount || 0 }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="协议价" align="center" prop="agreementPrice" width="100" />
|
|
|
+ <el-table-column label="操作" align="center" width="100" fixed="right">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-link type="primary" :underline="false" @click="handleAddSingleProduct(scope.row)">加入清单</el-link>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination
|
|
|
+ v-show="addProductDialog.total > 0"
|
|
|
+ :total="addProductDialog.total"
|
|
|
+ v-model:page="addProductQuery.pageNum"
|
|
|
+ v-model:limit="addProductQuery.pageSize"
|
|
|
+ @pagination="getProductList"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="PoolLink" lang="ts">
|
|
|
-import { listPoolLink, getPoolLink, delPoolLink, addPoolLink, updatePoolLink } from '@/api/product/poolLink';
|
|
|
-import { PoolLinkVO, PoolLinkQuery, PoolLinkForm } from '@/api/product/poolLink/types';
|
|
|
+import { useRouter, useRoute } from 'vue-router';
|
|
|
+import { categoryTree, listBase } from '@/api/product/base';
|
|
|
+import { BaseVO, BaseQuery } from '@/api/product/base/types';
|
|
|
+import { listPoolLink, batchAddProducts, BatchAddProductData } from '@/api/product/poolLink';
|
|
|
+import { PoolLinkQuery } from '@/api/product/poolLink/types';
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
+const router = useRouter();
|
|
|
+const route = useRoute();
|
|
|
|
|
|
-const poolLinkList = ref<PoolLinkVO[]>([]);
|
|
|
-const buttonLoading = ref(false);
|
|
|
-const loading = ref(true);
|
|
|
+const productList = ref<any[]>([]);
|
|
|
+const loading = ref(false);
|
|
|
const showSearch = ref(true);
|
|
|
-const ids = ref<Array<string | number>>([]);
|
|
|
-const single = ref(true);
|
|
|
-const multiple = ref(true);
|
|
|
const total = ref(0);
|
|
|
|
|
|
const queryFormRef = ref<ElFormInstance>();
|
|
|
-const poolLinkFormRef = ref<ElFormInstance>();
|
|
|
|
|
|
-const dialog = reactive<DialogOption>({
|
|
|
+const queryParams = ref({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ poolId: route.params.id || route.query.poolId,
|
|
|
+ productNo: undefined,
|
|
|
+ itemName: undefined,
|
|
|
+ brandId: undefined,
|
|
|
+ productStatus: undefined,
|
|
|
+ categoryId: undefined,
|
|
|
+ supplier: undefined,
|
|
|
+ dateRange: undefined,
|
|
|
+});
|
|
|
+
|
|
|
+const categoryOptions = ref<any[]>([]);
|
|
|
+const categoryMap = ref<Map<string | number, any>>(new Map());
|
|
|
+
|
|
|
+// 添加商品对话框
|
|
|
+const addProductDialog = reactive({
|
|
|
visible: false,
|
|
|
- title: ''
|
|
|
+ loading: false,
|
|
|
+ productList: [] as BaseVO[],
|
|
|
+ total: 0,
|
|
|
});
|
|
|
|
|
|
-const initFormData: PoolLinkForm = {
|
|
|
- id: undefined,
|
|
|
- poolId: undefined,
|
|
|
- productId: undefined,
|
|
|
- productPrice: undefined,
|
|
|
- isPoolStatus: undefined,
|
|
|
- productReviewStatus: undefined,
|
|
|
- reviewReason: undefined,
|
|
|
- isShow: undefined,
|
|
|
- remark: undefined,
|
|
|
-}
|
|
|
-const data = reactive<PageData<PoolLinkForm, PoolLinkQuery>>({
|
|
|
- form: {...initFormData},
|
|
|
- queryParams: {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 10,
|
|
|
- poolId: undefined,
|
|
|
- productId: undefined,
|
|
|
- productPrice: undefined,
|
|
|
- isPoolStatus: undefined,
|
|
|
- productReviewStatus: undefined,
|
|
|
- reviewReason: undefined,
|
|
|
- isShow: undefined,
|
|
|
- platformCode: undefined,
|
|
|
- params: {
|
|
|
- }
|
|
|
- },
|
|
|
- rules: {
|
|
|
- productPrice: [
|
|
|
- { required: true, message: "产品价格不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
- productReviewStatus: [
|
|
|
- { required: true, message: "产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回不能为空", trigger: "change" }
|
|
|
- ],
|
|
|
- reviewReason: [
|
|
|
- { required: true, message: "审核原因不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
- isShow: [
|
|
|
- { required: true, message: "是否显示:1=是,0=否不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
- remark: [
|
|
|
- { required: true, message: "备注不能为空", trigger: "blur" }
|
|
|
- ],
|
|
|
- }
|
|
|
+// 添加商品查询参数
|
|
|
+const addProductQuery = ref<BaseQuery>({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productNo: undefined,
|
|
|
+ itemName: undefined,
|
|
|
});
|
|
|
|
|
|
-const { queryParams, form, rules } = toRefs(data);
|
|
|
+// 选中的商品
|
|
|
+const selectedProducts = ref<BaseVO[]>([]);
|
|
|
+const addProductTableRef = ref<any>();
|
|
|
|
|
|
-/** 查询产品池和产品关联列表 */
|
|
|
+/** 获取分类树 */
|
|
|
+const getCategoryTree = async () => {
|
|
|
+ try {
|
|
|
+ const res = await categoryTree();
|
|
|
+ categoryOptions.value = res.data || [];
|
|
|
+ // 构建分类映射
|
|
|
+ buildCategoryMap(categoryOptions.value);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取分类树失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 构建分类映射 */
|
|
|
+const buildCategoryMap = (categories: any[], parentPath = '') => {
|
|
|
+ categories.forEach(category => {
|
|
|
+ const fullPath = parentPath ? `${parentPath} > ${category.label}` : category.label;
|
|
|
+ categoryMap.value.set(category.id, { ...category, fullPath });
|
|
|
+ if (category.children && category.children.length > 0) {
|
|
|
+ buildCategoryMap(category.children, fullPath);
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+/** 获取分类完整路径 */
|
|
|
+const getCategoryFullPath = (categoryId: string | number): string => {
|
|
|
+ const category = categoryMap.value.get(categoryId);
|
|
|
+ return category?.fullPath || '';
|
|
|
+};
|
|
|
+
|
|
|
+/** 查询商品列表 */
|
|
|
const getList = async () => {
|
|
|
loading.value = true;
|
|
|
- const res = await listPoolLink(queryParams.value);
|
|
|
- poolLinkList.value = res.rows;
|
|
|
- total.value = res.total;
|
|
|
- loading.value = false;
|
|
|
-}
|
|
|
-
|
|
|
-/** 取消按钮 */
|
|
|
-const cancel = () => {
|
|
|
- reset();
|
|
|
- dialog.visible = false;
|
|
|
+ try {
|
|
|
+ const query: PoolLinkQuery = {
|
|
|
+ pageNum: queryParams.value.pageNum,
|
|
|
+ pageSize: queryParams.value.pageSize,
|
|
|
+ poolId: queryParams.value.poolId,
|
|
|
+ productNo: queryParams.value.productNo,
|
|
|
+ itemName: queryParams.value.itemName,
|
|
|
+ brandId: queryParams.value.brandId,
|
|
|
+ categoryId: queryParams.value.categoryId,
|
|
|
+ productStatus: queryParams.value.productStatus,
|
|
|
+ supplier: queryParams.value.supplier
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理日期范围
|
|
|
+ if (queryParams.value.dateRange && queryParams.value.dateRange.length === 2) {
|
|
|
+ query.params = {
|
|
|
+ beginCreateTime: queryParams.value.dateRange[0],
|
|
|
+ endCreateTime: queryParams.value.dateRange[1]
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await listPoolLink(query);
|
|
|
+ productList.value = res.rows || [];
|
|
|
+ total.value = res.total || 0;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取商品列表失败:', error);
|
|
|
+ productList.value = [];
|
|
|
+ total.value = 0;
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-/** 表单重置 */
|
|
|
-const reset = () => {
|
|
|
- form.value = {...initFormData};
|
|
|
- poolLinkFormRef.value?.resetFields();
|
|
|
+/** 返回 */
|
|
|
+const goBack = () => {
|
|
|
+ router.back();
|
|
|
}
|
|
|
|
|
|
-/** 搜索按钮操作 */
|
|
|
+/** 搜索 */
|
|
|
const handleQuery = () => {
|
|
|
queryParams.value.pageNum = 1;
|
|
|
getList();
|
|
|
}
|
|
|
|
|
|
-/** 重置按钮操作 */
|
|
|
+/** 重置 */
|
|
|
const resetQuery = () => {
|
|
|
queryFormRef.value?.resetFields();
|
|
|
handleQuery();
|
|
|
}
|
|
|
|
|
|
-/** 多选框选中数据 */
|
|
|
-const handleSelectionChange = (selection: PoolLinkVO[]) => {
|
|
|
- ids.value = selection.map(item => item.id);
|
|
|
- single.value = selection.length != 1;
|
|
|
- multiple.value = !selection.length;
|
|
|
+/** 清空产品池 */
|
|
|
+const handleClearPool = async () => {
|
|
|
+ await proxy?.$modal.confirm('确认要清空该产品池的所有商品吗?');
|
|
|
+ // TODO: 调用清空API
|
|
|
+ proxy?.$modal.msgSuccess('清空成功');
|
|
|
+ await getList();
|
|
|
}
|
|
|
|
|
|
-/** 新增按钮操作 */
|
|
|
-const handleAdd = () => {
|
|
|
- reset();
|
|
|
- dialog.visible = true;
|
|
|
- dialog.title = "添加产品池和产品关联";
|
|
|
+/** 添加商品 */
|
|
|
+const handleAddProduct = () => {
|
|
|
+ addProductDialog.visible = true;
|
|
|
+ // 重置查询条件
|
|
|
+ addProductQuery.value = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productNo: undefined,
|
|
|
+ itemName: undefined,
|
|
|
+ };
|
|
|
+ selectedProducts.value = [];
|
|
|
+ getProductList();
|
|
|
+};
|
|
|
+
|
|
|
+/** 获取商品列表 */
|
|
|
+const getProductList = async () => {
|
|
|
+ addProductDialog.loading = true;
|
|
|
+ try {
|
|
|
+ const res = await listBase(addProductQuery.value);
|
|
|
+ // 兼容两种返回结构
|
|
|
+ if (res.rows) {
|
|
|
+ addProductDialog.productList = res.rows;
|
|
|
+ addProductDialog.total = res.total || 0;
|
|
|
+ } else if (res.data) {
|
|
|
+ addProductDialog.productList = Array.isArray(res.data) ? res.data : [];
|
|
|
+ addProductDialog.total = addProductDialog.productList.length;
|
|
|
+ } else {
|
|
|
+ addProductDialog.productList = [];
|
|
|
+ addProductDialog.total = 0;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取商品列表失败:', error);
|
|
|
+ addProductDialog.productList = [];
|
|
|
+ addProductDialog.total = 0;
|
|
|
+ } finally {
|
|
|
+ addProductDialog.loading = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 搜索商品 */
|
|
|
+const handleSearchProducts = () => {
|
|
|
+ addProductQuery.value.pageNum = 1;
|
|
|
+ getProductList();
|
|
|
+};
|
|
|
+
|
|
|
+/** 选择变化 */
|
|
|
+const handleSelectionChange = (selection: BaseVO[]) => {
|
|
|
+ selectedProducts.value = selection;
|
|
|
+};
|
|
|
+
|
|
|
+/** 批量加入清单 */
|
|
|
+const handleBatchAdd = async () => {
|
|
|
+ if (selectedProducts.value.length === 0) {
|
|
|
+ proxy?.$modal.msgWarning('请先选择要添加的商品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 构造批量添加的数据
|
|
|
+ const batchData: BatchAddProductData = {
|
|
|
+ poolId: queryParams.value.poolId as number,
|
|
|
+ products: selectedProducts.value.map(product => ({
|
|
|
+ productId: product.id as number,
|
|
|
+ agreementPrice: product.standardPrice || product.midRangePrice // 使用平台价或市场价作为协议价
|
|
|
+ }))
|
|
|
+ };
|
|
|
+
|
|
|
+ await batchAddProducts(batchData);
|
|
|
+ proxy?.$modal.msgSuccess(`成功添加 ${selectedProducts.value.length} 个商品到商品池`);
|
|
|
+ addProductDialog.visible = false;
|
|
|
+ // 清空选中项
|
|
|
+ selectedProducts.value = [];
|
|
|
+ if (addProductTableRef.value) {
|
|
|
+ addProductTableRef.value.clearSelection();
|
|
|
+ }
|
|
|
+ await getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('添加商品失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 添加单个商品 */
|
|
|
+const handleAddSingleProduct = async (row: BaseVO) => {
|
|
|
+ try {
|
|
|
+ // 构造单个商品添加的数据
|
|
|
+ const batchData: BatchAddProductData = {
|
|
|
+ poolId: queryParams.value.poolId as number,
|
|
|
+ products: [{
|
|
|
+ productId: row.id as number,
|
|
|
+ agreementPrice: row.standardPrice || row.midRangePrice // 使用平台价或市场价作为协议价
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ await batchAddProducts(batchData);
|
|
|
+ proxy?.$modal.msgSuccess('添加成功');
|
|
|
+ // 不关闭对话框,允许继续添加
|
|
|
+ await getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('添加商品失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 获取分类名称 */
|
|
|
+const getCategoryName = (row: BaseVO): string => {
|
|
|
+ // 优先使用完整路径
|
|
|
+ if (row.bottomCategoryId) {
|
|
|
+ return getCategoryFullPath(row.bottomCategoryId);
|
|
|
+ }
|
|
|
+ return '-';
|
|
|
+};
|
|
|
+
|
|
|
+/** 导出商品 */
|
|
|
+const handleExportProduct = () => {
|
|
|
+ // TODO: 导出功能
|
|
|
+ proxy?.$modal.msgInfo('导出商品功能');
|
|
|
}
|
|
|
|
|
|
-/** 修改按钮操作 */
|
|
|
-const handleUpdate = async (row?: PoolLinkVO) => {
|
|
|
- reset();
|
|
|
- const _id = row?.id || ids.value[0]
|
|
|
- const res = await getPoolLink(_id);
|
|
|
- Object.assign(form.value, res.data);
|
|
|
- dialog.visible = true;
|
|
|
- dialog.title = "修改产品池和产品关联";
|
|
|
+/** 导入商品 */
|
|
|
+const handleImportProduct = () => {
|
|
|
+ // TODO: 导入功能
|
|
|
+ proxy?.$modal.msgInfo('导入商品功能');
|
|
|
}
|
|
|
|
|
|
-/** 提交按钮 */
|
|
|
-const submitForm = () => {
|
|
|
- poolLinkFormRef.value?.validate(async (valid: boolean) => {
|
|
|
- if (valid) {
|
|
|
- buttonLoading.value = true;
|
|
|
- if (form.value.id) {
|
|
|
- await updatePoolLink(form.value).finally(() => buttonLoading.value = false);
|
|
|
- } else {
|
|
|
- await addPoolLink(form.value).finally(() => buttonLoading.value = false);
|
|
|
- }
|
|
|
- proxy?.$modal.msgSuccess("操作成功");
|
|
|
- dialog.visible = false;
|
|
|
- await getList();
|
|
|
- }
|
|
|
- });
|
|
|
+/** 价格维护 */
|
|
|
+const handlePriceMaintain = (row: any) => {
|
|
|
+ // TODO: 打开价格维护对话框
|
|
|
+ proxy?.$modal.msgInfo('价格维护功能');
|
|
|
}
|
|
|
|
|
|
-/** 删除按钮操作 */
|
|
|
-const handleDelete = async (row?: PoolLinkVO) => {
|
|
|
- const _ids = row?.id || ids.value;
|
|
|
- await proxy?.$modal.confirm('是否确认删除产品池和产品关联编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
|
|
|
- await delPoolLink(_ids);
|
|
|
- proxy?.$modal.msgSuccess("删除成功");
|
|
|
- await getList();
|
|
|
+/** 修改库存 */
|
|
|
+const handleInventoryMaintain = (row: any) => {
|
|
|
+ // TODO: 打开修改库存对话框
|
|
|
+ proxy?.$modal.msgInfo('修改库存功能');
|
|
|
}
|
|
|
|
|
|
-/** 导出按钮操作 */
|
|
|
-const handleExport = () => {
|
|
|
- proxy?.download('product/poolLink/export', {
|
|
|
- ...queryParams.value
|
|
|
- }, `poolLink_${new Date().getTime()}.xlsx`)
|
|
|
+/** 移除商品池 */
|
|
|
+const handleRemoveProduct = async (row: any) => {
|
|
|
+ await proxy?.$modal.confirm('确认要移除该商品吗?');
|
|
|
+ // TODO: 调用移除API
|
|
|
+ proxy?.$modal.msgSuccess('移除成功');
|
|
|
+ await getList();
|
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
|
+ getCategoryTree();
|
|
|
getList();
|
|
|
});
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.add-product-dialog {
|
|
|
+ :deep(.el-form--inline .el-form-item) {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|