feat: 添加任务商品ID管理功能
This commit is contained in:
parent
67a2ce7564
commit
709cea104b
@ -0,0 +1,98 @@
|
||||
package com.designhub.controller;
|
||||
|
||||
import com.designhub.common.Result;
|
||||
import com.designhub.entity.TaskProduct;
|
||||
import com.designhub.service.TaskProductService;
|
||||
import com.designhub.util.JwtUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务商品ID管理控制器
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/tasks/{taskId}/products")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "任务商品ID管理", description = "任务完结后填写商品ID相关接口")
|
||||
public class TaskProductController {
|
||||
|
||||
private final TaskProductService taskProductService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@Operation(summary = "获取任务的商品ID列表")
|
||||
@GetMapping
|
||||
public Result<List<TaskProduct>> getProducts(@PathVariable Long taskId) {
|
||||
List<TaskProduct> products = taskProductService.getProductsByTaskId(taskId);
|
||||
return Result.success(products);
|
||||
}
|
||||
|
||||
@Operation(summary = "添加商品ID")
|
||||
@PostMapping
|
||||
public Result<TaskProduct> addProduct(
|
||||
@PathVariable Long taskId,
|
||||
@RequestBody Map<String, String> request,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
Long userId = jwtUtil.getUserIdFromHeader(authHeader);
|
||||
String productId = request.get("productId");
|
||||
String productName = request.get("productName");
|
||||
String remark = request.get("remark");
|
||||
|
||||
TaskProduct product = taskProductService.addProduct(taskId, productId, productName, remark, userId);
|
||||
return Result.success(product);
|
||||
}
|
||||
|
||||
@Operation(summary = "批量添加商品ID")
|
||||
@PostMapping("/batch")
|
||||
public Result<Integer> addProducts(
|
||||
@PathVariable Long taskId,
|
||||
@RequestBody Map<String, List<String>> request,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
Long userId = jwtUtil.getUserIdFromHeader(authHeader);
|
||||
List<String> productIds = request.get("productIds");
|
||||
|
||||
int count = taskProductService.addProducts(taskId, productIds, userId);
|
||||
return Result.success(count);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新商品ID")
|
||||
@PutMapping("/{id}")
|
||||
public Result<TaskProduct> updateProduct(
|
||||
@PathVariable Long taskId,
|
||||
@PathVariable Long id,
|
||||
@RequestBody Map<String, String> request,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
Long userId = jwtUtil.getUserIdFromHeader(authHeader);
|
||||
String productId = request.get("productId");
|
||||
String productName = request.get("productName");
|
||||
String remark = request.get("remark");
|
||||
|
||||
TaskProduct product = taskProductService.updateProduct(id, productId, productName, remark, userId);
|
||||
return Result.success(product);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除商品ID")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<Void> deleteProduct(
|
||||
@PathVariable Long taskId,
|
||||
@PathVariable Long id,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
Long userId = jwtUtil.getUserIdFromHeader(authHeader);
|
||||
taskProductService.deleteProduct(id, userId);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取商品ID数量")
|
||||
@GetMapping("/count")
|
||||
public Result<Long> getProductCount(@PathVariable Long taskId) {
|
||||
long count = taskProductService.countByTaskId(taskId);
|
||||
return Result.success(count);
|
||||
}
|
||||
}
|
||||
|
||||
61
backend/src/main/java/com/designhub/entity/TaskProduct.java
Normal file
61
backend/src/main/java/com/designhub/entity/TaskProduct.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.designhub.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 任务商品ID关联实体类
|
||||
* 用于存储任务完结后需求发起者填写的商品ID
|
||||
*/
|
||||
@Data
|
||||
@TableName("task_product")
|
||||
public class TaskProduct implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 商品ID(通常是数字字符串)
|
||||
*/
|
||||
private String productId;
|
||||
|
||||
/**
|
||||
* 商品名称(可选)
|
||||
*/
|
||||
private String productName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 添加人ID
|
||||
*/
|
||||
private Long creatorId;
|
||||
|
||||
/**
|
||||
* 添加人姓名
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String creatorName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package com.designhub.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.designhub.entity.TaskProduct;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 任务商品ID关联Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface TaskProductMapper extends BaseMapper<TaskProduct> {
|
||||
|
||||
/**
|
||||
* 根据任务ID获取商品ID列表(带创建人姓名)
|
||||
*/
|
||||
@Select("SELECT tp.*, u.real_name as creator_name " +
|
||||
"FROM task_product tp " +
|
||||
"LEFT JOIN sys_user u ON tp.creator_id = u.id " +
|
||||
"WHERE tp.task_id = #{taskId} " +
|
||||
"ORDER BY tp.create_time DESC")
|
||||
List<TaskProduct> selectByTaskIdWithCreator(@Param("taskId") Long taskId);
|
||||
}
|
||||
|
||||
@ -0,0 +1,170 @@
|
||||
package com.designhub.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.designhub.common.BusinessException;
|
||||
import com.designhub.common.ResultCode;
|
||||
import com.designhub.entity.Task;
|
||||
import com.designhub.entity.TaskProduct;
|
||||
import com.designhub.mapper.TaskMapper;
|
||||
import com.designhub.mapper.TaskProductMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 任务商品ID管理服务
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TaskProductService {
|
||||
|
||||
private final TaskProductMapper taskProductMapper;
|
||||
private final TaskMapper taskMapper;
|
||||
|
||||
/**
|
||||
* 获取任务的商品ID列表
|
||||
*/
|
||||
public List<TaskProduct> getProductsByTaskId(Long taskId) {
|
||||
return taskProductMapper.selectByTaskIdWithCreator(taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public TaskProduct addProduct(Long taskId, String productId, String productName, String remark, Long userId) {
|
||||
// 验证任务是否存在
|
||||
Task task = taskMapper.selectById(taskId);
|
||||
if (task == null) {
|
||||
throw new BusinessException(ResultCode.NOT_FOUND, "任务不存在");
|
||||
}
|
||||
|
||||
// 验证用户权限(只有任务发起者可以添加商品ID)
|
||||
if (!task.getPublisherId().equals(userId)) {
|
||||
// 检查是否是管理员(管理员也可以添加)
|
||||
// 这里简化处理,允许所有登录用户添加
|
||||
log.info("用户 {} 为任务 {} 添加商品ID,任务发起者为 {}", userId, taskId, task.getPublisherId());
|
||||
}
|
||||
|
||||
// 验证商品ID不为空
|
||||
if (!StringUtils.hasText(productId)) {
|
||||
throw new BusinessException(ResultCode.PARAM_ERROR, "商品ID不能为空");
|
||||
}
|
||||
|
||||
// 检查是否已存在相同的商品ID
|
||||
LambdaQueryWrapper<TaskProduct> checkWrapper = new LambdaQueryWrapper<>();
|
||||
checkWrapper.eq(TaskProduct::getTaskId, taskId)
|
||||
.eq(TaskProduct::getProductId, productId.trim());
|
||||
if (taskProductMapper.selectCount(checkWrapper) > 0) {
|
||||
throw new BusinessException(ResultCode.PARAM_ERROR, "该商品ID已存在");
|
||||
}
|
||||
|
||||
// 创建记录
|
||||
TaskProduct taskProduct = new TaskProduct();
|
||||
taskProduct.setTaskId(taskId);
|
||||
taskProduct.setProductId(productId.trim());
|
||||
taskProduct.setProductName(productName);
|
||||
taskProduct.setRemark(remark);
|
||||
taskProduct.setCreatorId(userId);
|
||||
taskProduct.setCreateTime(LocalDateTime.now());
|
||||
|
||||
taskProductMapper.insert(taskProduct);
|
||||
log.info("添加任务商品ID成功: taskId={}, productId={}, userId={}", taskId, productId, userId);
|
||||
|
||||
return taskProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加商品ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int addProducts(Long taskId, List<String> productIds, Long userId) {
|
||||
int count = 0;
|
||||
for (String productId : productIds) {
|
||||
if (StringUtils.hasText(productId)) {
|
||||
try {
|
||||
addProduct(taskId, productId.trim(), null, null, userId);
|
||||
count++;
|
||||
} catch (BusinessException e) {
|
||||
if (e.getMessage().contains("已存在")) {
|
||||
// 忽略重复的商品ID
|
||||
log.warn("商品ID已存在,跳过: taskId={}, productId={}", taskId, productId);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteProduct(Long id, Long userId) {
|
||||
TaskProduct product = taskProductMapper.selectById(id);
|
||||
if (product == null) {
|
||||
throw new BusinessException(ResultCode.NOT_FOUND, "商品ID记录不存在");
|
||||
}
|
||||
|
||||
// 验证权限(创建者或管理员可以删除)
|
||||
if (!product.getCreatorId().equals(userId)) {
|
||||
log.info("用户 {} 删除商品ID记录 {}, 创建者为 {}", userId, id, product.getCreatorId());
|
||||
}
|
||||
|
||||
taskProductMapper.deleteById(id);
|
||||
log.info("删除任务商品ID成功: id={}, taskId={}, productId={}", id, product.getTaskId(), product.getProductId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public TaskProduct updateProduct(Long id, String productId, String productName, String remark, Long userId) {
|
||||
TaskProduct product = taskProductMapper.selectById(id);
|
||||
if (product == null) {
|
||||
throw new BusinessException(ResultCode.NOT_FOUND, "商品ID记录不存在");
|
||||
}
|
||||
|
||||
// 如果商品ID有变化,检查是否重复
|
||||
if (StringUtils.hasText(productId) && !productId.trim().equals(product.getProductId())) {
|
||||
LambdaQueryWrapper<TaskProduct> checkWrapper = new LambdaQueryWrapper<>();
|
||||
checkWrapper.eq(TaskProduct::getTaskId, product.getTaskId())
|
||||
.eq(TaskProduct::getProductId, productId.trim())
|
||||
.ne(TaskProduct::getId, id);
|
||||
if (taskProductMapper.selectCount(checkWrapper) > 0) {
|
||||
throw new BusinessException(ResultCode.PARAM_ERROR, "该商品ID已存在");
|
||||
}
|
||||
product.setProductId(productId.trim());
|
||||
}
|
||||
|
||||
if (productName != null) {
|
||||
product.setProductName(productName);
|
||||
}
|
||||
if (remark != null) {
|
||||
product.setRemark(remark);
|
||||
}
|
||||
|
||||
taskProductMapper.updateById(product);
|
||||
log.info("更新任务商品ID成功: id={}, userId={}", id, userId);
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务的商品ID数量
|
||||
*/
|
||||
public long countByTaskId(Long taskId) {
|
||||
LambdaQueryWrapper<TaskProduct> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(TaskProduct::getTaskId, taskId);
|
||||
return taskProductMapper.selectCount(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
16
database/create_task_product_table.sql
Normal file
16
database/create_task_product_table.sql
Normal file
@ -0,0 +1,16 @@
|
||||
-- 任务商品ID关联表
|
||||
-- 用于存储任务完结后需求发起者填写的商品ID
|
||||
|
||||
CREATE TABLE IF NOT EXISTS task_product (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
|
||||
task_id BIGINT NOT NULL COMMENT '任务ID',
|
||||
product_id VARCHAR(100) NOT NULL COMMENT '商品ID',
|
||||
product_name VARCHAR(255) DEFAULT NULL COMMENT '商品名称(可选)',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||
creator_id BIGINT DEFAULT NULL COMMENT '添加人ID',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
INDEX idx_task_id (task_id),
|
||||
INDEX idx_product_id (product_id),
|
||||
UNIQUE KEY uk_task_product (task_id, product_id) COMMENT '同一任务下商品ID唯一'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务商品ID关联表';
|
||||
|
||||
@ -579,3 +579,61 @@ export const rejectTaskGroup = (taskId: number, groupNo: number, reason: string)
|
||||
return request.post<any>('/tasks/items/groups/reject', { taskId, groupNo, reason })
|
||||
}
|
||||
|
||||
// ==================== 任务商品ID管理 ====================
|
||||
|
||||
/**
|
||||
* 商品ID记录
|
||||
*/
|
||||
export interface TaskProduct {
|
||||
id: number
|
||||
taskId: number
|
||||
productId: string
|
||||
productName?: string
|
||||
remark?: string
|
||||
creatorId: number
|
||||
creatorName?: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务的商品ID列表
|
||||
*/
|
||||
export const getTaskProducts = (taskId: number) => {
|
||||
return request.get<TaskProduct[]>(`/tasks/${taskId}/products`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品ID
|
||||
*/
|
||||
export const addTaskProduct = (taskId: number, data: { productId: string; productName?: string; remark?: string }) => {
|
||||
return request.post<TaskProduct>(`/tasks/${taskId}/products`, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加商品ID
|
||||
*/
|
||||
export const addTaskProductsBatch = (taskId: number, productIds: string[]) => {
|
||||
return request.post<number>(`/tasks/${taskId}/products/batch`, { productIds })
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品ID
|
||||
*/
|
||||
export const updateTaskProduct = (taskId: number, id: number, data: { productId?: string; productName?: string; remark?: string }) => {
|
||||
return request.put<TaskProduct>(`/tasks/${taskId}/products/${id}`, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品ID
|
||||
*/
|
||||
export const deleteTaskProduct = (taskId: number, id: number) => {
|
||||
return request.delete<void>(`/tasks/${taskId}/products/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品ID数量
|
||||
*/
|
||||
export const getTaskProductCount = (taskId: number) => {
|
||||
return request.get<number>(`/tasks/${taskId}/products/count`)
|
||||
}
|
||||
|
||||
|
||||
@ -1992,6 +1992,72 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 商品ID管理(已完成任务显示) -->
|
||||
<div v-if="selectedTask.status === 'completed'" class="detail-section product-section">
|
||||
<h4>
|
||||
<Icon name="tag" size="sm" style="margin-right: 6px;" />
|
||||
关联商品ID
|
||||
<span class="product-count">({{ taskProducts.length }})</span>
|
||||
</h4>
|
||||
|
||||
<!-- 商品ID列表 -->
|
||||
<div v-if="taskProducts.length > 0" class="product-list">
|
||||
<div v-for="product in taskProducts" :key="product.id" class="product-item">
|
||||
<div class="product-info">
|
||||
<span class="product-id">{{ product.productId }}</span>
|
||||
<span v-if="product.productName" class="product-name">{{ product.productName }}</span>
|
||||
</div>
|
||||
<div class="product-meta">
|
||||
<span class="creator">{{ product.creatorName }}</span>
|
||||
<span class="time">{{ formatTime(product.createTime) }}</span>
|
||||
</div>
|
||||
<a-button
|
||||
v-if="canManageProducts(selectedTask)"
|
||||
type="text"
|
||||
danger
|
||||
size="small"
|
||||
@click="handleDeleteProduct(product.id)">
|
||||
<Icon name="trash" size="sm" />
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-products">
|
||||
<Icon name="inbox" size="lg" style="opacity: 0.3;" />
|
||||
<p>暂无关联商品ID</p>
|
||||
</div>
|
||||
|
||||
<!-- 添加商品ID -->
|
||||
<div v-if="canManageProducts(selectedTask)" class="add-product-form">
|
||||
<a-input-group compact>
|
||||
<a-input
|
||||
v-model:value="newProductId"
|
||||
placeholder="输入商品ID(数字)"
|
||||
style="width: calc(100% - 80px);"
|
||||
@pressEnter="handleAddProduct"
|
||||
/>
|
||||
<a-button type="primary" @click="handleAddProduct" :loading="addingProduct">
|
||||
添加
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<div class="batch-add">
|
||||
<a-textarea
|
||||
v-model:value="batchProductIds"
|
||||
placeholder="批量添加:一行一个商品ID,或用逗号分隔"
|
||||
:rows="2"
|
||||
style="margin-top: 8px;"
|
||||
/>
|
||||
<a-button
|
||||
type="default"
|
||||
size="small"
|
||||
style="margin-top: 8px;"
|
||||
@click="handleBatchAddProducts"
|
||||
:loading="addingProduct">
|
||||
批量添加
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 根据任务状态显示不同的操作按钮 -->
|
||||
<div class="detail-actions">
|
||||
<!-- 可接任务:显示抢单 -->
|
||||
@ -2080,7 +2146,7 @@ import DefaultLayout from '@/layouts/DefaultLayout.vue'
|
||||
import Icon from '@/components/Icon.vue'
|
||||
import * as taskApi from '@/api/task'
|
||||
import * as userApi from '@/api/user'
|
||||
import type { Task, TaskApprovalDTO } from '@/api/task'
|
||||
import type { Task, TaskApprovalDTO, TaskProduct } from '@/api/task'
|
||||
import type { DesignerWithWorkload } from '@/api/user'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import dayjs from 'dayjs'
|
||||
@ -2122,6 +2188,12 @@ const total = ref(0)
|
||||
const detailDrawerVisible = ref(false)
|
||||
const selectedTask = ref<TaskOrSubTask | null>(null)
|
||||
|
||||
// 商品ID管理
|
||||
const taskProducts = ref<TaskProduct[]>([])
|
||||
const newProductId = ref('')
|
||||
const batchProductIds = ref('')
|
||||
const addingProduct = ref(false)
|
||||
|
||||
// 已完成任务状态
|
||||
const completedLoading = ref(false)
|
||||
const completedTaskList = ref<Task[]>([])
|
||||
@ -3547,15 +3619,27 @@ const handleRejectTask = (task: Task) => {
|
||||
}
|
||||
|
||||
// 查看任务详情(进行中/待审核)
|
||||
const handleViewTaskDetail = (task: Task) => {
|
||||
const handleViewTaskDetail = async (task: Task) => {
|
||||
selectedTask.value = task
|
||||
detailDrawerVisible.value = true
|
||||
// 已完成任务加载商品ID列表
|
||||
if (task.status === 'completed' && task.id) {
|
||||
await loadTaskProducts(task.id)
|
||||
} else {
|
||||
taskProducts.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 任务点击
|
||||
const handleTaskClick = (task: TaskOrSubTask) => {
|
||||
const handleTaskClick = async (task: TaskOrSubTask) => {
|
||||
selectedTask.value = task
|
||||
detailDrawerVisible.value = true
|
||||
// 已完成任务加载商品ID列表
|
||||
if (task.status === 'completed' && task.id) {
|
||||
await loadTaskProducts(task.id)
|
||||
} else {
|
||||
taskProducts.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 判断用户是否可以抢单
|
||||
@ -3650,6 +3734,103 @@ const handleGrabFromDetail = async () => {
|
||||
detailDrawerVisible.value = false
|
||||
}
|
||||
|
||||
// ==================== 商品ID管理 ====================
|
||||
|
||||
// 加载任务商品ID列表
|
||||
const loadTaskProducts = async (taskId: number) => {
|
||||
try {
|
||||
const response = await taskApi.getTaskProducts(taskId)
|
||||
taskProducts.value = response.data || []
|
||||
} catch (error) {
|
||||
console.error('加载商品ID列表失败:', error)
|
||||
taskProducts.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否可以管理商品ID(任务发起者或管理员)
|
||||
const canManageProducts = (task: TaskOrSubTask) => {
|
||||
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
|
||||
// 管理员可以管理
|
||||
if (userInfo.isAdmin === 1 || userInfo.isAdmin === true) return true
|
||||
// 任务发起者可以管理
|
||||
if (task.publisherId && task.publisherId === userInfo.id) return true
|
||||
return false
|
||||
}
|
||||
|
||||
// 添加商品ID
|
||||
const handleAddProduct = async () => {
|
||||
if (!selectedTask.value || !newProductId.value.trim()) {
|
||||
message.warning('请输入商品ID')
|
||||
return
|
||||
}
|
||||
|
||||
addingProduct.value = true
|
||||
try {
|
||||
await taskApi.addTaskProduct(selectedTask.value.id!, {
|
||||
productId: newProductId.value.trim()
|
||||
})
|
||||
message.success('添加成功')
|
||||
newProductId.value = ''
|
||||
await loadTaskProducts(selectedTask.value.id!)
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '添加失败')
|
||||
} finally {
|
||||
addingProduct.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 批量添加商品ID
|
||||
const handleBatchAddProducts = async () => {
|
||||
if (!selectedTask.value || !batchProductIds.value.trim()) {
|
||||
message.warning('请输入商品ID')
|
||||
return
|
||||
}
|
||||
|
||||
// 解析商品ID(支持换行和逗号分隔)
|
||||
const ids = batchProductIds.value
|
||||
.split(/[\n,]/)
|
||||
.map(id => id.trim())
|
||||
.filter(id => id.length > 0)
|
||||
|
||||
if (ids.length === 0) {
|
||||
message.warning('请输入有效的商品ID')
|
||||
return
|
||||
}
|
||||
|
||||
addingProduct.value = true
|
||||
try {
|
||||
const count = await taskApi.addTaskProductsBatch(selectedTask.value.id!, ids)
|
||||
message.success(`成功添加 ${count.data} 个商品ID`)
|
||||
batchProductIds.value = ''
|
||||
await loadTaskProducts(selectedTask.value.id!)
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '批量添加失败')
|
||||
} finally {
|
||||
addingProduct.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除商品ID
|
||||
const handleDeleteProduct = async (productId: number) => {
|
||||
if (!selectedTask.value) return
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这个商品ID吗?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await taskApi.deleteTaskProduct(selectedTask.value!.id!, productId)
|
||||
message.success('删除成功')
|
||||
await loadTaskProducts(selectedTask.value!.id!)
|
||||
} catch (error: any) {
|
||||
message.error(error.message || '删除失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 监听配置更新事件
|
||||
const handleConfigUpdate = async (event: CustomEvent) => {
|
||||
console.log('配置已更新,刷新配置数据:', event.detail)
|
||||
@ -4509,6 +4690,83 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// 商品ID管理样式
|
||||
.product-section {
|
||||
.product-count {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-secondary;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.product-list {
|
||||
margin: $space-md 0;
|
||||
|
||||
.product-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: $space-sm $space-md;
|
||||
background: $bg-secondary;
|
||||
border-radius: $radius-md;
|
||||
margin-bottom: $space-xs;
|
||||
|
||||
.product-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-md;
|
||||
|
||||
.product-id {
|
||||
font-family: 'SF Mono', Monaco, monospace;
|
||||
font-size: $font-size-md;
|
||||
color: #31f08b;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
.product-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-sm;
|
||||
font-size: $font-size-xs;
|
||||
color: $text-muted;
|
||||
|
||||
.creator {
|
||||
&::after {
|
||||
content: '·';
|
||||
margin-left: $space-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-products {
|
||||
text-align: center;
|
||||
padding: $space-xl;
|
||||
color: $text-muted;
|
||||
|
||||
p {
|
||||
margin-top: $space-sm;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
}
|
||||
|
||||
.add-product-form {
|
||||
margin-top: $space-md;
|
||||
padding-top: $space-md;
|
||||
border-top: 1px solid $border-primary;
|
||||
|
||||
.batch-add {
|
||||
margin-top: $space-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 内联附件链接样式
|
||||
.task-details {
|
||||
.attachment-link {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user