|
|
@@ -3,406 +3,845 @@
|
|
|
<!-- 返回按钮 -->
|
|
|
<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>
|
|
|
+ <span class="ml-2 text-lg font-bold">商品配置</span>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 入池清单信息卡片 -->
|
|
|
- <el-card shadow="hover" class="mb-4">
|
|
|
- <el-descriptions :column="4" border>
|
|
|
- <el-descriptions-item label="订单编号">{{ poolInfo.poolNo }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="产品池名称">{{ poolInfo.name }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="申请时间">{{ poolInfo.createTime }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="审核时间">{{ poolInfo.reviewTime || '-' }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="状态">
|
|
|
- <dict-tag :options="product_review_status" :value="poolInfo.productReviewStatus" />
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="创建人">{{ poolInfo.createBy }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="11" label-class-name="custom-label">11</el-descriptions-item>
|
|
|
- <el-descriptions-item label="审核人">{{ poolInfo.reviewBy || '-' }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="驳回意见" :span="4">
|
|
|
- <span v-if="poolInfo.reviewReason">{{ poolInfo.reviewReason }}</span>
|
|
|
- <span v-else class="text-gray-400">-</span>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
- </el-card>
|
|
|
+ <!-- 搜索区域 -->
|
|
|
+ <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" 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-option label="上架中" value="2" />
|
|
|
+ </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-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </transition>
|
|
|
|
|
|
- <!-- 标签页 -->
|
|
|
<el-card shadow="never">
|
|
|
- <el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
|
|
- <el-tab-pane label="待入池产品" name="pending">
|
|
|
- <!-- 待入池产品按钮 -->
|
|
|
- <div class="mb-4">
|
|
|
- <el-button type="primary" icon="Plus">加入入池清单</el-button>
|
|
|
+ <template #header>
|
|
|
+ <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="warning" plain :disabled="!hasReviewableItems" @click="handleBatchReview">批量审核</el-button>
|
|
|
+ <el-button type="danger" plain :disabled="selectedPoolLinks.length === 0" @click="handleBatchRemove">批量移出</el-button>
|
|
|
+ <el-button type="primary" plain :disabled="!hasSubmittableItems" @click="handleSubmitReview">提交审核</el-button>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
|
|
|
- <!-- 待入池产品表格 -->
|
|
|
- <el-table v-loading="pendingLoading" border :data="pendingProductList">
|
|
|
- <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" 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 class="text-gray-500">库存:{{ scope.row.stock || '-' }}</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="productPrice" width="120">
|
|
|
- <template #default="scope">
|
|
|
- ¥{{ scope.row.productPrice || '0.00' }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="商品状态" align="center" width="100">
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :options="product_review_status" :value="scope.row.productReviewStatus" />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="创建供应商" align="center" prop="supplier" width="120" />
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <pagination v-show="pendingTotal > 0" :total="pendingTotal" v-model:page="pendingQuery.pageNum" v-model:limit="pendingQuery.pageSize" @pagination="getPendingList" />
|
|
|
- </el-tab-pane>
|
|
|
-
|
|
|
- <el-tab-pane label="入池清单" name="approved">
|
|
|
- <!-- 入池清单表格 -->
|
|
|
- <el-table v-loading="approvedLoading" border :data="approvedProductList">
|
|
|
- <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" 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 class="text-gray-500">库存:{{ scope.row.stock || '-' }}</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="productPrice" width="120">
|
|
|
- <template #default="scope">
|
|
|
- ¥{{ scope.row.productPrice || '0.00' }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="商品状态" align="center" width="100">
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :options="product_review_status" :value="scope.row.productReviewStatus" />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="创建供应商" align="center" prop="supplier" width="120" />
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <pagination v-show="approvedTotal > 0" :total="approvedTotal" v-model:page="approvedQuery.pageNum" v-model:limit="approvedQuery.pageSize" @pagination="getApprovedList" />
|
|
|
- </el-tab-pane>
|
|
|
- </el-tabs>
|
|
|
+ <el-table v-loading="loading" border :data="productList" @selection-change="handlePoolLinkSelectionChange">
|
|
|
+ <el-table-column type="selection" width="55" align="center" />
|
|
|
+ <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-tag v-if="scope.row.productStatus === '1'" type="success">已上架</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.productStatus === '0'" type="warning">下架</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.productStatus === '2'" type="info">上架中</el-tag>
|
|
|
+ <el-tag v-else type="info">未知</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="审核状态" align="center" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag v-if="scope.row.productReviewStatus === '0'" type="info">待提交</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.productReviewStatus === '1'" type="warning">待审核</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.productReviewStatus === '2'" type="success">审核通过</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.productReviewStatus === '3'" type="danger">审核驳回</el-tag>
|
|
|
+ <el-tag v-else type="info">未知</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="handleStockMaintain(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>
|
|
|
|
|
|
- <!-- 底部审核按钮 -->
|
|
|
- <div class="fixed bottom-0 left-0 right-0 bg-white border-t p-4 flex justify-center gap-4" style="z-index: 100;">
|
|
|
- <el-button @click="handleReject" size="large">驳回</el-button>
|
|
|
- <el-button type="primary" @click="handleApprove" size="large">通过</el-button>
|
|
|
- </div>
|
|
|
+ <!-- 价格维护对话框 -->
|
|
|
+ <el-dialog title="价格维护" v-model="priceDialog.visible" width="500px" append-to-body>
|
|
|
+ <el-form ref="priceFormRef" :model="priceDialog.form" :rules="priceRules" label-width="100px">
|
|
|
+ <el-form-item label="商品名称">
|
|
|
+ <span>{{ priceDialog.row?.itemName }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="市场价" prop="marketPrice">
|
|
|
+ <el-input-number v-model="priceDialog.form.marketPrice" :precision="2" :min="0" controls-position="right" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="平台售价" prop="platformPrice">
|
|
|
+ <el-input-number v-model="priceDialog.form.platformPrice" :precision="2" :min="0" controls-position="right" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="最低售价" prop="minPrice">
|
|
|
+ <el-input-number v-model="priceDialog.form.minPrice" :precision="2" :min="0" controls-position="right" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="产品价格" prop="productPrice">
|
|
|
+ <el-input-number v-model="priceDialog.form.productPrice" :precision="2" :min="0" controls-position="right" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="priceDialog.visible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitPriceForm">确 定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
|
|
|
- <!-- 驳回对话框 -->
|
|
|
- <el-dialog title="驳回原因" v-model="rejectDialog.visible" width="500px" append-to-body>
|
|
|
- <el-form ref="rejectFormRef" :model="rejectForm" :rules="rejectRules" label-width="100px">
|
|
|
- <el-form-item label="驳回原因:" prop="reviewReason">
|
|
|
- <el-input
|
|
|
- v-model="rejectForm.reviewReason"
|
|
|
- type="textarea"
|
|
|
- placeholder="请输入驳回原因"
|
|
|
- maxlength="200"
|
|
|
- show-word-limit
|
|
|
- :rows="4"
|
|
|
- />
|
|
|
+ <!-- 修改库存对话框 -->
|
|
|
+ <el-dialog title="修改库存" v-model="stockDialog.visible" width="500px" append-to-body>
|
|
|
+ <el-form ref="stockFormRef" :model="stockDialog.form" :rules="stockRules" label-width="100px">
|
|
|
+ <el-form-item label="商品名称">
|
|
|
+ <span>{{ stockDialog.row?.itemName }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="当前库存">
|
|
|
+ <span>{{ stockDialog.row?.stock || 0 }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="库存数量" prop="stock">
|
|
|
+ <el-input-number v-model="stockDialog.form.stock" :min="0" :precision="0" controls-position="right" style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
- <div class="dialog-footer">
|
|
|
- <el-button :loading="buttonLoading" type="primary" @click="submitReject">确 认</el-button>
|
|
|
- <el-button @click="rejectDialog.visible = false">取 消</el-button>
|
|
|
- </div>
|
|
|
+ <el-button @click="stockDialog.visible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitStockForm">确 定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 批量审核对话框 -->
|
|
|
+ <el-dialog title="批量审核" v-model="reviewDialog.visible" width="500px" append-to-body>
|
|
|
+ <el-form ref="reviewFormRef" :model="reviewDialog.form" :rules="reviewRules" label-width="100px">
|
|
|
+ <el-form-item label="审核结果" prop="productReviewStatus">
|
|
|
+ <el-radio-group v-model="reviewDialog.form.productReviewStatus">
|
|
|
+ <el-radio label="2">通过</el-radio>
|
|
|
+ <el-radio label="3">驳回</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="reviewDialog.form.productReviewStatus === '3'" label="驳回原因" prop="reviewReason">
|
|
|
+ <el-input v-model="reviewDialog.form.reviewReason" type="textarea" :rows="3" placeholder="请输入驳回原因" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="reviewDialog.visible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitReviewForm">确 定</el-button>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- 添加商品对话框 -->
|
|
|
+ <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.productList.length > 0"
|
|
|
+ v-model:page="addProductQuery.pageNum"
|
|
|
+ v-model:limit="addProductQuery.pageSize"
|
|
|
+ v-model:way="addProductQuery.way"
|
|
|
+ :cursor-mode="true"
|
|
|
+ :has-more="addProductHasMore"
|
|
|
+ @pagination="getProductList"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
-<script setup name="PoolReviewDetail" lang="ts">
|
|
|
+<script setup name="PoolLink" lang="ts">
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
-import { getPool, updatePool } from '@/api/product/pool';
|
|
|
-import { PoolVO } from '@/api/product/pool/types';
|
|
|
-import { listPoolLink } from '@/api/product/poolLink';
|
|
|
-import { PoolLinkVO, PoolLinkQuery } from '@/api/product/poolLink/types';
|
|
|
+import { categoryTree, listBase } from '@/api/product/base';
|
|
|
+import { BaseVO, BaseQuery } from '@/api/product/base/types';
|
|
|
+import { listPoolLink, batchAddProducts, BatchAddProductData, batchReview, reSubmit, editPrice, editStock, PoolLinkForm } from '@/api/product/poolLink';
|
|
|
+import { PoolLinkQuery, PoolLinkVO } from '@/api/product/poolLink/types';
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
|
|
|
-// 产品池信息
|
|
|
-const poolInfo = ref<PoolVO>({
|
|
|
- id: '',
|
|
|
- poolNo: '',
|
|
|
- name: '',
|
|
|
- isShow: '',
|
|
|
- productReviewStatus: '',
|
|
|
- reviewReason: '',
|
|
|
- remark: '',
|
|
|
- createTime: '',
|
|
|
- createBy: '',
|
|
|
- reviewBy: ''
|
|
|
-});
|
|
|
+const productList = ref<PoolLinkVO[]>([]);
|
|
|
+const selectedPoolLinks = ref<PoolLinkVO[]>([]); // 主列表选中的商品
|
|
|
+const loading = ref(false);
|
|
|
+const showSearch = ref(true);
|
|
|
+const total = ref(0);
|
|
|
|
|
|
-// 当前标签页
|
|
|
-const activeTab = ref('pending');
|
|
|
+// 添加商品弹框游标分页相关
|
|
|
+const addProductHasMore = ref(true); // 是否还有更多数据
|
|
|
+// 页面历史记录,存储每页的第一个id和最后一个id,用于支持双向翻页
|
|
|
+const addProductPageHistory = ref<Array<{ firstId: any; lastId: any }>>([]);
|
|
|
|
|
|
-// 待入池产品列表
|
|
|
-const pendingProductList = ref<PoolLinkVO[]>([]);
|
|
|
-const pendingLoading = ref(false);
|
|
|
-const pendingTotal = ref(0);
|
|
|
-const pendingQuery = ref<PoolLinkQuery>({
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 10,
|
|
|
- poolId: undefined,
|
|
|
- productReviewStatus: '1' // 待审核
|
|
|
-});
|
|
|
+const queryFormRef = ref<ElFormInstance>();
|
|
|
|
|
|
-// 入池清单列表
|
|
|
-const approvedProductList = ref<PoolLinkVO[]>([]);
|
|
|
-const approvedLoading = ref(false);
|
|
|
-const approvedTotal = ref(0);
|
|
|
-const approvedQuery = ref<PoolLinkQuery>({
|
|
|
+const queryParams = ref({
|
|
|
pageNum: 1,
|
|
|
pageSize: 10,
|
|
|
- poolId: undefined,
|
|
|
- productReviewStatus: '2' // 审核通过
|
|
|
+ poolId: (route.params.id || route.query.poolId) as string | number,
|
|
|
+ productReviewStatus: route.query.productReviewStatus as string | undefined,
|
|
|
+ productNo: undefined,
|
|
|
+ itemName: undefined,
|
|
|
+ brandId: undefined,
|
|
|
+ productStatus: undefined,
|
|
|
+ categoryId: undefined,
|
|
|
+ supplier: undefined,
|
|
|
+ dateRange: undefined,
|
|
|
});
|
|
|
|
|
|
-// 驳回对话框
|
|
|
-const rejectDialog = reactive({
|
|
|
- visible: false
|
|
|
+const categoryOptions = ref<any[]>([]);
|
|
|
+const categoryMap = ref<Map<string | number, any>>(new Map());
|
|
|
+
|
|
|
+// 添加商品对话框
|
|
|
+const addProductDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ loading: false,
|
|
|
+ productList: [] as BaseVO[],
|
|
|
+ total: 0,
|
|
|
});
|
|
|
|
|
|
-const rejectFormRef = ref<ElFormInstance>();
|
|
|
-const rejectForm = ref({
|
|
|
- reviewReason: ''
|
|
|
+// 添加商品查询参数
|
|
|
+const addProductQuery = ref({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productNo: undefined as string | undefined,
|
|
|
+ itemName: undefined as string | undefined,
|
|
|
+ lastSeenId: undefined as string | number | undefined, // 游标分页的lastSeenId
|
|
|
+ way: undefined as number | undefined // 翻页方向: 0=上一页, 1=下一页
|
|
|
});
|
|
|
|
|
|
-const rejectRules = {
|
|
|
- reviewReason: [
|
|
|
- { required: true, message: "请输入驳回原因", trigger: "blur" }
|
|
|
- ]
|
|
|
+// 选中的商品
|
|
|
+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 buttonLoading = ref(false);
|
|
|
+/** 构建分类映射 */
|
|
|
+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 { product_review_status } = toRefs<any>(proxy?.$dict.getDict('product_review_status'));
|
|
|
+/** 获取分类完整路径 */
|
|
|
+const getCategoryFullPath = (categoryId: string | number): string => {
|
|
|
+ const category = categoryMap.value.get(categoryId);
|
|
|
+ return category?.fullPath || '';
|
|
|
+};
|
|
|
|
|
|
-/** 获取产品池信息 */
|
|
|
-const getPoolInfo = async () => {
|
|
|
+/** 查询商品列表 */
|
|
|
+const getList = async () => {
|
|
|
+ loading.value = true;
|
|
|
try {
|
|
|
- const poolId = route.params.id || route.query.poolId;
|
|
|
- if (!poolId) {
|
|
|
- proxy?.$modal.msgError('缺少产品池ID');
|
|
|
- goBack();
|
|
|
- return;
|
|
|
+ const query: PoolLinkQuery = {
|
|
|
+ pageNum: queryParams.value.pageNum,
|
|
|
+ pageSize: queryParams.value.pageSize,
|
|
|
+ poolId: queryParams.value.poolId,
|
|
|
+ productReviewStatus: queryParams.value.productReviewStatus,
|
|
|
+ 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 getPool(poolId);
|
|
|
- poolInfo.value = res.data;
|
|
|
-
|
|
|
- // 设置查询参数的poolId
|
|
|
- pendingQuery.value.poolId = poolId;
|
|
|
- approvedQuery.value.poolId = poolId;
|
|
|
+
|
|
|
+ const res = await listPoolLink(query);
|
|
|
+ productList.value = res.rows || [];
|
|
|
+ total.value = res.total || 0;
|
|
|
} catch (error) {
|
|
|
- console.error('获取产品池信息失败:', error);
|
|
|
- proxy?.$modal.msgError('获取产品池信息失败');
|
|
|
+ console.error('获取商品列表失败:', error);
|
|
|
+ productList.value = [];
|
|
|
+ total.value = 0;
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+/** 返回 */
|
|
|
+const goBack = () => {
|
|
|
+ router.back();
|
|
|
+}
|
|
|
+
|
|
|
+/** 搜索 */
|
|
|
+const handleQuery = () => {
|
|
|
+ queryParams.value.pageNum = 1;
|
|
|
+ getList();
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置 */
|
|
|
+const resetQuery = () => {
|
|
|
+ queryFormRef.value?.resetFields();
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+
|
|
|
+/** 添加商品 */
|
|
|
+const handleAddProduct = () => {
|
|
|
+ addProductDialog.visible = true;
|
|
|
+ // 重置查询条件
|
|
|
+ addProductQuery.value = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ productNo: undefined,
|
|
|
+ itemName: undefined,
|
|
|
+ lastSeenId: undefined,
|
|
|
+ way: undefined,
|
|
|
+ };
|
|
|
+ addProductPageHistory.value = []; // 重置页面历史
|
|
|
+ selectedProducts.value = [];
|
|
|
+ getProductList();
|
|
|
};
|
|
|
|
|
|
-/** 获取待入池产品列表 */
|
|
|
-const getPendingList = async () => {
|
|
|
- pendingLoading.value = true;
|
|
|
+/** 获取商品列表(游标分页) */
|
|
|
+const getProductList = async () => {
|
|
|
+ addProductDialog.loading = true;
|
|
|
try {
|
|
|
- const res = await listPoolLink(pendingQuery.value);
|
|
|
- pendingProductList.value = res.rows || [];
|
|
|
- pendingTotal.value = res.total || 0;
|
|
|
+ const currentPageNum = addProductQuery.value.pageNum;
|
|
|
+ const params: any = { ...addProductQuery.value };
|
|
|
+
|
|
|
+ // 第一页不需要游标参数
|
|
|
+ if (currentPageNum === 1) {
|
|
|
+ delete params.lastSeenId;
|
|
|
+ delete params.firstSeenId;
|
|
|
+ delete params.way;
|
|
|
+ } else {
|
|
|
+ // way参数:0=上一页,1=下一页
|
|
|
+ if (addProductQuery.value.way === 0) {
|
|
|
+ // 上一页:使用目标页的firstId
|
|
|
+ const nextPageHistory = addProductPageHistory.value[currentPageNum];
|
|
|
+ if (nextPageHistory) {
|
|
|
+ params.firstSeenId = nextPageHistory.firstId;
|
|
|
+ params.way = 0;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 下一页:使用前一页的lastId作为lastSeenId
|
|
|
+ const prevPageHistory = addProductPageHistory.value[currentPageNum - 1];
|
|
|
+ if (prevPageHistory) {
|
|
|
+ params.lastSeenId = prevPageHistory.lastId;
|
|
|
+ params.way = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await listBase(params);
|
|
|
+ // 兼容两种返回结构
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否还有更多数据
|
|
|
+ addProductHasMore.value = addProductDialog.productList.length === addProductQuery.value.pageSize;
|
|
|
+
|
|
|
+ // 记录当前页的第一个id和最后一个id
|
|
|
+ if (addProductDialog.productList.length > 0) {
|
|
|
+ const firstItem = addProductDialog.productList[0];
|
|
|
+ const lastItem = addProductDialog.productList[addProductDialog.productList.length - 1];
|
|
|
+ // 如果长度小于currentPageNum则创建
|
|
|
+ if (addProductPageHistory.value.length <= currentPageNum) {
|
|
|
+ addProductPageHistory.value[currentPageNum] = {
|
|
|
+ firstId: firstItem.id,
|
|
|
+ lastId: lastItem.id
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
- console.error('获取待入池产品列表失败:', error);
|
|
|
- pendingProductList.value = [];
|
|
|
- pendingTotal.value = 0;
|
|
|
+ console.error('获取商品列表失败:', error);
|
|
|
+ addProductDialog.productList = [];
|
|
|
+ addProductDialog.total = 0;
|
|
|
} finally {
|
|
|
- pendingLoading.value = false;
|
|
|
+ addProductDialog.loading = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-/** 获取入池清单列表 */
|
|
|
-const getApprovedList = async () => {
|
|
|
- approvedLoading.value = true;
|
|
|
+/** 搜索商品 */
|
|
|
+const handleSearchProducts = () => {
|
|
|
+ addProductQuery.value.pageNum = 1;
|
|
|
+ addProductQuery.value.lastSeenId = undefined;
|
|
|
+ addProductQuery.value.way = undefined;
|
|
|
+ addProductPageHistory.value = []; // 重置页面历史
|
|
|
+ getProductList();
|
|
|
+};
|
|
|
+
|
|
|
+/** 选择变化 */
|
|
|
+const handleSelectionChange = (selection: BaseVO[]) => {
|
|
|
+ selectedProducts.value = selection;
|
|
|
+};
|
|
|
+
|
|
|
+/** 批量加入清单 */
|
|
|
+const handleBatchAdd = async () => {
|
|
|
+ if (selectedProducts.value.length === 0) {
|
|
|
+ proxy?.$modal.msgWarning('请先选择要添加的商品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
- const res = await listPoolLink(approvedQuery.value);
|
|
|
- approvedProductList.value = res.rows || [];
|
|
|
- approvedTotal.value = res.total || 0;
|
|
|
+ // 构造批量添加的数据
|
|
|
+ const batchData: BatchAddProductData = {
|
|
|
+ poolId: queryParams.value.poolId ,
|
|
|
+ products: selectedProducts.value.map(product => ({
|
|
|
+ productId: product.id ,
|
|
|
+ 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);
|
|
|
- approvedProductList.value = [];
|
|
|
- approvedTotal.value = 0;
|
|
|
- } finally {
|
|
|
- approvedLoading.value = false;
|
|
|
+ console.error('添加商品失败:', error);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-/** 标签页切换 */
|
|
|
-const handleTabClick = () => {
|
|
|
- if (activeTab.value === 'pending') {
|
|
|
- getPendingList();
|
|
|
- } else {
|
|
|
- getApprovedList();
|
|
|
+/** 添加单个商品 */
|
|
|
+const handleAddSingleProduct = async (row: BaseVO) => {
|
|
|
+ try {
|
|
|
+ // 构造单个商品添加的数据
|
|
|
+ const batchData: BatchAddProductData = {
|
|
|
+ poolId: queryParams.value.poolId ,
|
|
|
+ products: [{
|
|
|
+ productId: row.id ,
|
|
|
+ agreementPrice: row.standardPrice || row.midRangePrice // 使用平台价或市场价作为协议价
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ await batchAddProducts(batchData);
|
|
|
+ proxy?.$modal.msgSuccess('添加成功');
|
|
|
+ // 不关闭对话框,允许继续添加
|
|
|
+ await getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('添加商品失败:', error);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-/** 返回 */
|
|
|
-const goBack = () => {
|
|
|
- router.back();
|
|
|
+/** 获取分类名称 */
|
|
|
+const getCategoryName = (row: BaseVO): string => {
|
|
|
+ // 优先使用完整路径
|
|
|
+ if (row.bottomCategoryId) {
|
|
|
+ return getCategoryFullPath(row.bottomCategoryId);
|
|
|
+ }
|
|
|
+ return '-';
|
|
|
};
|
|
|
|
|
|
-/** 驳回 */
|
|
|
-const handleReject = () => {
|
|
|
- rejectForm.value.reviewReason = '';
|
|
|
- rejectDialog.visible = true;
|
|
|
+/** 主列表选择变化 */
|
|
|
+const handlePoolLinkSelectionChange = (selection: PoolLinkVO[]) => {
|
|
|
+ selectedPoolLinks.value = selection;
|
|
|
};
|
|
|
|
|
|
-/** 提交驳回 */
|
|
|
-const submitReject = () => {
|
|
|
- rejectFormRef.value?.validate(async (valid: boolean) => {
|
|
|
- if (valid) {
|
|
|
- buttonLoading.value = true;
|
|
|
- try {
|
|
|
- await updatePool({
|
|
|
- id: poolInfo.value.id,
|
|
|
- productReviewStatus: '3', // 驳回
|
|
|
- reviewReason: rejectForm.value.reviewReason
|
|
|
- });
|
|
|
- proxy?.$modal.msgSuccess("驳回成功");
|
|
|
- rejectDialog.visible = false;
|
|
|
- goBack();
|
|
|
- } finally {
|
|
|
- buttonLoading.value = false;
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
+/** 是否有可审核的项(待审核状态) */
|
|
|
+const hasReviewableItems = computed(() => {
|
|
|
+ return selectedPoolLinks.value.some(item => item.productReviewStatus === '1');
|
|
|
+});
|
|
|
+
|
|
|
+/** 是否有可提交审核的项(待提交或驳回状态) */
|
|
|
+const hasSubmittableItems = computed(() => {
|
|
|
+ return selectedPoolLinks.value.some(item => item.productReviewStatus === '0' || item.productReviewStatus === '3');
|
|
|
+});
|
|
|
+
|
|
|
+// ========== 批量审核相关 ==========
|
|
|
+const reviewDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ form: {
|
|
|
+ productReviewStatus: '2' as string,
|
|
|
+ reviewReason: '' as string
|
|
|
+ }
|
|
|
+});
|
|
|
+const reviewFormRef = ref<ElFormInstance>();
|
|
|
+const reviewRules = reactive({
|
|
|
+ productReviewStatus: [{ required: true, message: '请选择审核结果', trigger: 'change' }],
|
|
|
+ reviewReason: [{ required: true, message: '请输入驳回原因', trigger: 'blur' }]
|
|
|
+});
|
|
|
+
|
|
|
+/** 批量审核 */
|
|
|
+const handleBatchReview = () => {
|
|
|
+ const reviewableItems = selectedPoolLinks.value.filter(item => item.productReviewStatus === '1');
|
|
|
+ if (reviewableItems.length === 0) {
|
|
|
+ proxy?.$modal.msgWarning('请选择待审核的商品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ reviewDialog.form = { productReviewStatus: '2', reviewReason: '' };
|
|
|
+ reviewDialog.visible = true;
|
|
|
};
|
|
|
|
|
|
-/** 通过 */
|
|
|
-const handleApprove = async () => {
|
|
|
- try {
|
|
|
- await proxy?.$modal.confirm('确认通过该产品池审核吗?');
|
|
|
- buttonLoading.value = true;
|
|
|
- try {
|
|
|
- await updatePool({
|
|
|
- id: poolInfo.value.id,
|
|
|
- productReviewStatus: '2', // 通过
|
|
|
- reviewReason: ''
|
|
|
- });
|
|
|
- proxy?.$modal.msgSuccess("审核通过");
|
|
|
- goBack();
|
|
|
- } finally {
|
|
|
- buttonLoading.value = false;
|
|
|
- }
|
|
|
- } catch {
|
|
|
- // 取消操作
|
|
|
+/** 提交审核表单 */
|
|
|
+const submitReviewForm = async () => {
|
|
|
+ await reviewFormRef.value?.validate();
|
|
|
+ const reviewableItems = selectedPoolLinks.value.filter(item => item.productReviewStatus === '1');
|
|
|
+ const data: PoolLinkForm[] = reviewableItems.map(item => ({
|
|
|
+ id: item.id,
|
|
|
+ productReviewStatus: reviewDialog.form.productReviewStatus,
|
|
|
+ reviewReason: reviewDialog.form.productReviewStatus === '3' ? reviewDialog.form.reviewReason : undefined
|
|
|
+ }));
|
|
|
+ await batchReview(data);
|
|
|
+ proxy?.$modal.msgSuccess('审核成功');
|
|
|
+ reviewDialog.visible = false;
|
|
|
+ await getList();
|
|
|
+};
|
|
|
+
|
|
|
+/** 提交审核(待提交和驳回的商品) */
|
|
|
+const handleSubmitReview = async () => {
|
|
|
+ const submittableItems = selectedPoolLinks.value.filter(item => item.productReviewStatus === '0' || item.productReviewStatus === '3');
|
|
|
+ if (submittableItems.length === 0) {
|
|
|
+ proxy?.$modal.msgWarning('请选择待提交或已驳回的商品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ await proxy?.$modal.confirm(`确认提交 ${submittableItems.length} 个商品进行审核吗?`);
|
|
|
+ const data: PoolLinkForm[] = submittableItems.map(item => ({ id: item.id, productReviewStatus: '1' }));
|
|
|
+ await reSubmit(data);
|
|
|
+ proxy?.$modal.msgSuccess('提交成功');
|
|
|
+ await getList();
|
|
|
+};
|
|
|
+
|
|
|
+/** 批量移出 */
|
|
|
+const handleBatchRemove = async () => {
|
|
|
+ if (selectedPoolLinks.value.length === 0) {
|
|
|
+ proxy?.$modal.msgWarning('请先选择要移出的商品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ await proxy?.$modal.confirm(`确认要移出选中的 ${selectedPoolLinks.value.length} 个商品吗?`);
|
|
|
+ const ids = selectedPoolLinks.value.map(item => item.id);
|
|
|
+ // 调用删除接口
|
|
|
+ const { delPoolLink } = await import('@/api/product/poolLink');
|
|
|
+ await delPoolLink(ids);
|
|
|
+ proxy?.$modal.msgSuccess('移出成功');
|
|
|
+ await getList();
|
|
|
+};
|
|
|
+
|
|
|
+// ========== 价格维护相关 ==========
|
|
|
+const priceDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ row: null as PoolLinkVO | null,
|
|
|
+ form: {
|
|
|
+ marketPrice: 0,
|
|
|
+ platformPrice: 0,
|
|
|
+ minPrice: 0,
|
|
|
+ productPrice: 0
|
|
|
}
|
|
|
+});
|
|
|
+const priceFormRef = ref<ElFormInstance>();
|
|
|
+const priceRules = reactive({
|
|
|
+ productPrice: [{ required: true, message: '请输入产品价格', trigger: 'blur' }]
|
|
|
+});
|
|
|
+
|
|
|
+/** 价格维护 */
|
|
|
+const handlePriceMaintain = (row: PoolLinkVO) => {
|
|
|
+ priceDialog.row = row;
|
|
|
+ priceDialog.form = {
|
|
|
+ marketPrice: row.marketPrice || 0,
|
|
|
+ platformPrice: row.platformPrice || 0,
|
|
|
+ minPrice: row.minPrice || 0,
|
|
|
+ productPrice: row.productPrice || 0
|
|
|
+ };
|
|
|
+ priceDialog.visible = true;
|
|
|
+};
|
|
|
+
|
|
|
+/** 提交价格表单 */
|
|
|
+const submitPriceForm = async () => {
|
|
|
+ await priceFormRef.value?.validate();
|
|
|
+ const data: PoolLinkForm = {
|
|
|
+ id: priceDialog.row?.id,
|
|
|
+ productPrice: priceDialog.form.productPrice
|
|
|
+ };
|
|
|
+ await editPrice(data);
|
|
|
+ proxy?.$modal.msgSuccess('价格修改成功');
|
|
|
+ priceDialog.visible = false;
|
|
|
+ await getList();
|
|
|
+};
|
|
|
+
|
|
|
+// ========== 库存维护相关 ==========
|
|
|
+const stockDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ row: null as PoolLinkVO | null,
|
|
|
+ form: {
|
|
|
+ stock: 0
|
|
|
+ }
|
|
|
+});
|
|
|
+const stockFormRef = ref<ElFormInstance>();
|
|
|
+const stockRules = reactive({
|
|
|
+ stock: [{ required: true, message: '请输入库存数量', trigger: 'blur' }]
|
|
|
+});
|
|
|
+
|
|
|
+/** 修改库存 */
|
|
|
+const handleStockMaintain = (row: PoolLinkVO) => {
|
|
|
+ stockDialog.row = row;
|
|
|
+ stockDialog.form = {
|
|
|
+ stock: row.stock || 0
|
|
|
+ };
|
|
|
+ stockDialog.visible = true;
|
|
|
+};
|
|
|
+
|
|
|
+/** 提交库存表单 */
|
|
|
+const submitStockForm = async () => {
|
|
|
+ await stockFormRef.value?.validate();
|
|
|
+ const data: PoolLinkForm = {
|
|
|
+ id: stockDialog.row?.id,
|
|
|
+ stock: stockDialog.form.stock
|
|
|
+ };
|
|
|
+ await editStock(data);
|
|
|
+ proxy?.$modal.msgSuccess('库存修改成功');
|
|
|
+ stockDialog.visible = false;
|
|
|
+ await getList();
|
|
|
};
|
|
|
|
|
|
-onMounted(async () => {
|
|
|
- await getPoolInfo();
|
|
|
- // 默认加载待入池产品
|
|
|
- await getPendingList();
|
|
|
+onMounted(() => {
|
|
|
+ getCategoryTree();
|
|
|
+ getList();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
-// 为底部固定按钮留出空间
|
|
|
-:deep(.el-card__body) {
|
|
|
- padding-bottom: 80px;
|
|
|
-}
|
|
|
-
|
|
|
-.custom-label {
|
|
|
- font-weight: normal;
|
|
|
+.add-product-dialog {
|
|
|
+ :deep(.el-form--inline .el-form-item) {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|