feat: 商品条码支持添加多个,验证库存后才能添加到列表

This commit is contained in:
Your Name 2026-01-06 18:16:06 +08:00
parent 66135374e9
commit 93887a21ec
4 changed files with 118 additions and 32 deletions

View File

@ -44,6 +44,7 @@ public class PipelineTaskDTO {
private LocalDateTime deadline; // 截止时间
private String releaseType; // 发布类型:default/recruitment/assigned
private Long receiverId; // 指定接收人ID(assigned模式使用)
private List<String> productBarcodes; // 商品条码列表(已验证库存)
/**
* 子任务项DTO

View File

@ -236,6 +236,12 @@ public class Task implements Serializable {
*/
private Integer productIdFilled;
/**
* 商品条码列表(逗号分隔,已验证库存)
*/
@TableField("product_barcodes")
private String productBarcodes;
/**
* 是否紧急:0-否 1-是
*/

View File

@ -296,6 +296,11 @@ public class TaskService {
task.setRemark(dto.getRemark());
task.setPriority(dto.getPriority() != null ? dto.getPriority() : 1); // 默认优先级:1-普通
// 设置商品条码列表(如果有)
if (dto.getProductBarcodes() != null && !dto.getProductBarcodes().isEmpty()) {
task.setProductBarcodes(String.join(",", dto.getProductBarcodes()));
}
// 设置时间字段
task.setCreateTime(LocalDateTime.now());
// 如果前端没有传递截止时间,默认为创建时间+7天

View File

@ -226,45 +226,61 @@
<a-form-item
v-if="selectedSubTypeNeedsInventoryCheck"
label="商品条码"
name="productBarcode"
required
>
<a-input-group compact>
<!-- 已添加的条码列表 -->
<div v-if="formData.productBarcodes && formData.productBarcodes.length > 0" class="barcode-list">
<div class="barcode-list-title">
<span>已添加条码 ({{ formData.productBarcodes.length }}个)</span>
</div>
<div class="barcode-tags">
<a-tag
v-for="(barcode, index) in formData.productBarcodes"
:key="index"
color="green"
closable
@close="removeBarcode(index)"
>
{{ barcode }}
</a-tag>
</div>
</div>
<!-- 添加新条码 -->
<a-input-group compact style="margin-top: 8px;">
<a-input
v-model:value="formData.productBarcode"
placeholder="请输入商品条码用于库存检查"
v-model:value="newBarcodeInput"
placeholder="请输入商品条码,验证库存后添加"
size="large"
style="width: calc(100% - 100px)"
@pressEnter="handleCheckInventory"
style="width: calc(100% - 120px)"
@pressEnter="handleAddBarcode"
/>
<a-button
type="primary"
size="large"
@click="handleCheckInventory"
@click="handleAddBarcode"
:loading="checkingInventory"
>
检查库存
验证并添加
</a-button>
</a-input-group>
<!-- 库存检查结果 -->
<!-- 库存检查结果(临时显示) -->
<div v-if="inventoryCheckResult" class="inventory-result" :class="{ 'success': inventoryCheckResult.canPublish, 'error': !inventoryCheckResult.canPublish }">
<a-alert
:type="inventoryCheckResult.canPublish ? 'success' : 'error'"
:message="inventoryCheckResult.canPublish ? '库存充足' : '库存不足'"
:message="inventoryCheckResult.canPublish ? '库存充足,已添加' : '库存不足'"
:description="inventoryCheckResult.message"
show-icon
/>
<div v-if="inventoryCheckResult.found" class="inventory-details">
<div v-if="inventoryCheckResult.found && !inventoryCheckResult.canPublish" class="inventory-details">
<div class="detail-item">
<span class="label">商品名称:</span>
<span class="value">{{ inventoryCheckResult.name || '-' }}</span>
</div>
<div class="detail-item">
<span class="label">可用库存:</span>
<span class="value" :class="{ 'low-stock': inventoryCheckResult.availableQty <= 1 }">
{{ inventoryCheckResult.availableQty }}
</span>
<span class="value low-stock">{{ inventoryCheckResult.availableQty }}</span>
</div>
</div>
</div>
@ -602,11 +618,14 @@ const formData = reactive({
previewImage: '', // 预览图URL
remark: '', // 备注信息
releaseType: 'default',
productBarcode: '', // 商品条码(库存检查用)
productBarcodes: [] as string[], // 商品条码列表(已验证库存)
// receiverId: undefined, // 已移除,改用子任务指定
isUrgent: false
})
// 新条码输入框
const newBarcodeInput = ref('')
// 库存检查相关
const checkingInventory = ref(false)
const inventoryCheckResult = ref<InventoryResult | null>(null)
@ -618,24 +637,39 @@ const selectedSubTypeNeedsInventoryCheck = computed(() => {
return selectedSubType?.checkInventory === 1
})
// 检查库存
const handleCheckInventory = async () => {
if (!formData.productBarcode) {
// 验证并添加条码
const handleAddBarcode = async () => {
const barcode = newBarcodeInput.value.trim()
if (!barcode) {
message.warning('请输入商品条码')
return
}
// 检查是否已添加
if (formData.productBarcodes.includes(barcode)) {
message.warning('该条码已添加')
return
}
checkingInventory.value = true
inventoryCheckResult.value = null
try {
const response = await checkInventoryForTask(formData.productBarcode)
const response = await checkInventoryForTask(barcode)
inventoryCheckResult.value = response.data
if (response.data.canPublish) {
message.success('库存检查通过,可以发布任务')
// 库存充足,添加到列表
formData.productBarcodes.push(barcode)
newBarcodeInput.value = '' // 清空输入框
message.success(`条码 ${barcode} 库存充足,已添加`)
// 2秒后清除结果提示
setTimeout(() => {
inventoryCheckResult.value = null
}, 2000)
} else {
message.error(response.data.message || '库存不足,请先申请样品')
message.error(response.data.message || '库存不足,无法添加该条码')
}
} catch (error: any) {
console.error('检查库存失败:', error)
@ -645,6 +679,14 @@ const handleCheckInventory = async () => {
}
}
// 移除条码
const removeBarcode = (index: number) => {
formData.productBarcodes.splice(index, 1)
}
// 兼容旧函数名
const handleCheckInventory = handleAddBarcode
// 表单验证规则
const formRules = {
title: [
@ -1110,16 +1152,8 @@ const handleSubmit = async () => {
// 检查库存(如果需要)
if (selectedSubTypeNeedsInventoryCheck.value) {
if (!formData.productBarcode) {
message.error('请输入商品条码')
return
}
if (!inventoryCheckResult.value) {
message.error('请先检查库存')
return
}
if (!inventoryCheckResult.value.canPublish) {
message.error('库存不足,请先申请样品后再发布任务')
if (!formData.productBarcodes || formData.productBarcodes.length === 0) {
message.error('请至少添加一个已验证库存的商品条码')
return
}
}
@ -1207,7 +1241,8 @@ const handleSubmit = async () => {
remark: formData.remark || '',
priority: formData.isUrgent ? 3 : 1, // 0-低 1-普通 2-高 3-紧急
releaseType: formData.releaseType, // 发布类型
receiverId: undefined // 主任务不设接收人,由子任务指定
receiverId: undefined, // 主任务不设接收人,由子任务指定
productBarcodes: formData.productBarcodes // 商品条码列表
}
let response: any
@ -2285,6 +2320,45 @@ onUnmounted(() => {
}
}
// 条码列表样式
.barcode-list {
padding: 12px;
background: rgba(49, 240, 139, 0.05);
border: 1px solid rgba(49, 240, 139, 0.2);
border-radius: 8px;
margin-bottom: 8px;
.barcode-list-title {
font-size: 12px;
color: $text-tertiary;
margin-bottom: 8px;
}
.barcode-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
:deep(.ant-tag) {
margin: 0;
padding: 4px 10px;
font-size: 13px;
border-radius: 4px;
background: rgba(49, 240, 139, 0.15);
border-color: rgba(49, 240, 139, 0.3);
color: #31f08b;
.anticon-close {
color: rgba(255, 255, 255, 0.6);
&:hover {
color: #ff4d4f;
}
}
}
}
}
// 库存检查结果样式
.inventory-result {
margin-top: 12px;