2025008071805

This commit is contained in:
张潘 2025-08-11 17:18:14 +08:00
parent 74fc92b222
commit 9b23266010
27 changed files with 4213 additions and 326 deletions

View File

@ -1,5 +1,5 @@
{ {
"java.compile.nullAnalysis.mode": "automatic", "java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive", "java.configuration.updateBuildConfiguration": "automatic",
"java.debug.settings.onBuildFailureProceed": true "java.debug.settings.onBuildFailureProceed": true
} }

View File

@ -56,6 +56,23 @@
<version>2.11.0</version> <version>2.11.0</version>
</dependency> </dependency>
<!-- Apache POI - Excel支持 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1453,7 +1453,7 @@ public class AppleOrderController extends BaseController {
orderList.add(orderResult); orderList.add(orderResult);
totalAmount = totalAmount.add(new BigDecimal(orderResult.get("allprice").toString())); totalAmount = totalAmount.add(new BigDecimal(orderResult.get("allprice").toString()));
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) { if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
String payBeforeId = payBeforeUtil.createPayBefore(user, totalAmount, orderid, null, null, 11L, null, null, null, null, null, Long.valueOf(serviceGoods.getType()),null,null); String payBeforeId = payBeforeUtil.createPayBefore(user, totalAmount, maincorid, null, null, 5L, null, null, null, null, null, Long.valueOf(serviceGoods.getType()),null,null);
Map<String, Object> result1 = new HashMap<>(); Map<String, Object> result1 = new HashMap<>();
result1.put("type", "2"); result1.put("type", "2");
result1.put("orderid", payBeforeId); result1.put("orderid", payBeforeId);
@ -1510,6 +1510,9 @@ public class AppleOrderController extends BaseController {
} }
} }
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) { if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
jsonObject.put("name", "订单创建成功");
OrderUtil.addgoodsorderlog(999L,maincorid,"订单生成","1",jsonObject,2L);
String payBeforeId = payBeforeUtil.createPayBefore(user, totalAmount, maincorid, null, null, 5L, null, null, null, null, null,2L,null,null); String payBeforeId = payBeforeUtil.createPayBefore(user, totalAmount, maincorid, null, null, 5L, null, null, null, null, null,2L,null,null);
Map<String, Object> result1 = new HashMap<>(); Map<String, Object> result1 = new HashMap<>();
result1.put("type", "2"); result1.put("type", "2");
@ -4296,7 +4299,7 @@ public class AppleOrderController extends BaseController {
// List<OrderLog> orderLogs = orderLogService.selectOrderLogByOrderId(goodsOrder.getOrderId()); // List<OrderLog> orderLogs = orderLogService.selectOrderLogByOrderId(goodsOrder.getOrderId());
// 6. 查询订单日志 // 6. 查询订单日志
OrderLog logQuery = new OrderLog(); OrderLog logQuery = new OrderLog();
logQuery.setOid(goodsOrder.getId()); logQuery.setOrderId(goodsOrder.getMainOrderId());
logQuery.setOrdertype(2L); logQuery.setOrdertype(2L);
List<OrderLog> logList = orderLogService.selectOrderLogList(logQuery); List<OrderLog> logList = orderLogService.selectOrderLogList(logQuery);
List<Map<String, Object>> logArr = new ArrayList<>(); List<Map<String, Object>> logArr = new ArrayList<>();
@ -4390,9 +4393,26 @@ public class AppleOrderController extends BaseController {
} }
// // 7. 构建订单状态时间线 // // 7. 构建订单状态时间线
// List<Map<String, Object>> timeline = buildOrderTimeline(goodsOrder, orderLogs); // List<Map<String, Object>> timeline = buildOrderTimeline(goodsOrder, orderLogs);
GoodsOrder goodsOrderDATA = new GoodsOrder();
goodsOrderDATA.setMainOrderId(goodsOrder.getMainOrderId());
List<GoodsOrder> goodsOrderList = goodsOrderService.selectGoodsOrderList(goodsOrderDATA);
List<Map<String, Object>> goodsOrderListDATA = new ArrayList<>();
for (GoodsOrder goodsOrderdata : goodsOrderList) {
ServiceGoods serviceGoods1 = serviceGoodsService.selectServiceGoodsById(goodsOrderdata.getProductId());
if (serviceGoods != null) {
Map<String, Object> productInfo = new HashMap<>();
productInfo.put("id", serviceGoods1.getId());
productInfo.put("title", serviceGoods1.getTitle());
productInfo.put("sub_title", serviceGoods1.getSubTitle());
productInfo.put("icon", AppletControllerUtil.buildImageUrl(serviceGoods1.getIcon()));
productInfo.put("price", goodsOrderdata.getTotalPrice() != null ? goodsOrderdata.getTotalPrice().toString() : "0.00");
productInfo.put("sku",AppletControllerUtil.parseSkuStringToObject(goodsOrderdata.getSku()));
productInfo.put("num", goodsOrderdata.getNum());
goodsOrderListDATA.add(productInfo);
}
}
// 8. 构建商品信息 // 8. 构建商品信息
Map<String, Object> productInfo = buildProductInfo(goodsOrder, serviceGoods); // Map<String, Object> productInfo = buildProductInfo(goodsOrder, serviceGoods);
// 9. 构建订单信息 // 9. 构建订单信息
Map<String, Object> orderInfo = buildOrderInfo(goodsOrder); Map<String, Object> orderInfo = buildOrderInfo(goodsOrder);
@ -4402,11 +4422,11 @@ public class AppleOrderController extends BaseController {
// 10. 构建返回结果 // 10. 构建返回结果
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
result.put("orderId", goodsOrder.getOrderId()); result.put("orderId", goodsOrder.getMainOrderId());
result.put("shopAddress", shopAddress); result.put("shopAddress", shopAddress);
result.put("status", goodsOrder.getStatus()); result.put("status", goodsOrder.getStatus());
result.put("timeline", logArr); result.put("timeline", logArr);
result.put("product", productInfo); result.put("product", goodsOrderListDATA);
result.put("orderInfo", orderInfo); result.put("orderInfo", orderInfo);
// 11. 添加退货数据如果有退货信息 // 11. 添加退货数据如果有退货信息
@ -4489,10 +4509,10 @@ public class AppleOrderController extends BaseController {
private Map<String, Object> buildOrderInfo(GoodsOrder goodsOrder) { private Map<String, Object> buildOrderInfo(GoodsOrder goodsOrder) {
Map<String, Object> orderInfo = new HashMap<>(); Map<String, Object> orderInfo = new HashMap<>();
java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
UsersPayBefor usersPayBefor = usersPayBeforService.selectUsersPayBeforByOrderId(goodsOrder.getOrderId()); UsersPayBefor usersPayBefor = usersPayBeforService.selectUsersPayBeforByOrderId(goodsOrder.getMainOrderId());
if (usersPayBefor == null){ // if (usersPayBefor == null){
usersPayBefor = usersPayBeforService.selectUsersPayBeforByOrderId(goodsOrder.getMainOrderId()); // usersPayBefor = usersPayBeforService.selectUsersPayBeforByOrderId(goodsOrder.getMainOrderId());
} // }
if (usersPayBefor != null){ if (usersPayBefor != null){
orderInfo.put("totalPrice", usersPayBefor.getAllmoney()); orderInfo.put("totalPrice", usersPayBefor.getAllmoney());
orderInfo.put("payPrice", usersPayBefor.getAllmoney()); orderInfo.put("payPrice", usersPayBefor.getAllmoney());
@ -4506,7 +4526,7 @@ public class AppleOrderController extends BaseController {
} }
//orderInfo.put("sku", AppletControllerUtil.parseSkuStringToObject(goodsOrder.getSku())); //orderInfo.put("sku", AppletControllerUtil.parseSkuStringToObject(goodsOrder.getSku()));
orderInfo.put("orderId", goodsOrder.getOrderId()); orderInfo.put("orderId", goodsOrder.getMainOrderId());
orderInfo.put("postage", goodsOrder.getPostage() != null ? goodsOrder.getPostage() : BigDecimal.ZERO); orderInfo.put("postage", goodsOrder.getPostage() != null ? goodsOrder.getPostage() : BigDecimal.ZERO);
// logMap.put("created_at", log.getCreatedAt() != null ? dateFormat.format(log.getCreatedAt()) : null); // logMap.put("created_at", log.getCreatedAt() != null ? dateFormat.format(log.getCreatedAt()) : null);
orderInfo.put("createdAt", goodsOrder.getCreatedAt() != null ? dateFormat.format(goodsOrder.getCreatedAt()) : null); orderInfo.put("createdAt", goodsOrder.getCreatedAt() != null ? dateFormat.format(goodsOrder.getCreatedAt()) : null);

View File

@ -671,7 +671,7 @@ public class AppletController extends BaseController {
} }
// 6. 查询商品订单列表 // 6. 查询商品订单列表
List<GoodsOrder> orderList = goodsOrderService.selectGoodsOrderList(queryOrder); List<GoodsOrder> orderList = goodsOrderService.selectGoodsOrdergrouBymAIDList(queryOrder);
// 7. 为每个订单填充商品信息 // 7. 为每个订单填充商品信息
List<Map<String, Object>> resultList = new ArrayList<>(); List<Map<String, Object>> resultList = new ArrayList<>();
@ -680,10 +680,11 @@ public class AppletController extends BaseController {
for (GoodsOrder order : orderList) { for (GoodsOrder order : orderList) {
Map<String, Object> orderData = new HashMap<>(); Map<String, Object> orderData = new HashMap<>();
// 订单基本信息 // 订单基本信息
orderData.put("id", order.getId()); orderData.put("id", order.getId());
orderData.put("order_id", order.getOrderId()); orderData.put("order_id", order.getMainOrderId());
orderData.put("order_no", order.getOrderId()); // 小程序常用字段 orderData.put("order_no", order.getMainOrderId()); // 小程序常用字段
orderData.put("status", order.getStatus()); orderData.put("status", order.getStatus());
orderData.put("status_text", getOrderStatusText(order.getStatus())); // 状态文本 orderData.put("status_text", getOrderStatusText(order.getStatus())); // 状态文本
orderData.put("total_price", order.getTotalPrice() != null ? order.getTotalPrice().toString() : "0.00"); orderData.put("total_price", order.getTotalPrice() != null ? order.getTotalPrice().toString() : "0.00");
@ -707,22 +708,40 @@ public class AppletController extends BaseController {
} else { } else {
orderData.put("created_at", null); orderData.put("created_at", null);
} }
GoodsOrder goodsOrderDATA = new GoodsOrder();
// 查询并添加商品详细信息 goodsOrderDATA.setMainOrderId(order.getMainOrderId());
if (order.getProductId() != null) { List<GoodsOrder> goodsOrderList = goodsOrderService.selectGoodsOrderList(goodsOrderDATA);
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId()); List<Map<String, Object>> goodsOrderListDATA = new ArrayList<>();
if (serviceGoods != null) { for (GoodsOrder goodsOrder : goodsOrderList) {
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(goodsOrder.getProductId());
if (serviceGoods != null) {
Map<String, Object> productInfo = new HashMap<>(); Map<String, Object> productInfo = new HashMap<>();
productInfo.put("id", serviceGoods.getId()); productInfo.put("id", serviceGoods.getId());
productInfo.put("title", serviceGoods.getTitle()); productInfo.put("title", serviceGoods.getTitle());
productInfo.put("sub_title", serviceGoods.getSubTitle()); productInfo.put("sub_title", serviceGoods.getSubTitle());
productInfo.put("icon", AppletControllerUtil.buildImageUrl(serviceGoods.getIcon())); productInfo.put("icon", AppletControllerUtil.buildImageUrl(serviceGoods.getIcon()));
productInfo.put("price", order.getTotalPrice() != null ? order.getTotalPrice().toString() : "0.00"); productInfo.put("price", goodsOrder.getTotalPrice() != null ? goodsOrder.getTotalPrice().toString() : "0.00");
productInfo.put("num", order.getNum()); productInfo.put("sku",AppletControllerUtil.parseSkuStringToObject(goodsOrder.getSku()));
productInfo.put("num", goodsOrder.getNum());
orderData.put("product", productInfo); goodsOrderListDATA.add(productInfo);
} }
} }
orderData.put("product", goodsOrderListDATA);
// // 查询并添加商品详细信息
// if (order.getProductId() != null) {
// ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
// if (serviceGoods != null) {
// Map<String, Object> productInfo = new HashMap<>();
// productInfo.put("id", serviceGoods.getId());
// productInfo.put("title", serviceGoods.getTitle());
// productInfo.put("sub_title", serviceGoods.getSubTitle());
// productInfo.put("icon", AppletControllerUtil.buildImageUrl(serviceGoods.getIcon()));
// productInfo.put("price", order.getTotalPrice() != null ? order.getTotalPrice().toString() : "0.00");
// productInfo.put("num", order.getNum());
//
// orderData.put("product", productInfo);
// }
// }
resultList.add(orderData); resultList.add(orderData);
} }
// 8. 构建分页信息 // 8. 构建分页信息

View File

@ -5,6 +5,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.ruoyi.system.ControllerUtil.ScheduledTaskUtil;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -167,8 +169,8 @@ public class DiyCityController extends BaseController
{ {
try { try {
// 获取定时任务工具类 // 获取定时任务工具类
com.ruoyi.system.controllerUtil.ScheduledTaskUtil scheduledTaskUtil = ScheduledTaskUtil scheduledTaskUtil =
com.ruoyi.common.utils.spring.SpringUtils.getBean(com.ruoyi.system.controllerUtil.ScheduledTaskUtil.class); com.ruoyi.common.utils.spring.SpringUtils.getBean(ScheduledTaskUtil.class);
// 执行手动恢复 // 执行手动恢复
String result = scheduledTaskUtil.manualWorkerStatusResume(); String result = scheduledTaskUtil.manualWorkerStatusResume();

View File

@ -21,12 +21,23 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* 商品订单Controller * 商品订单Controller
@ -38,6 +49,8 @@ import com.ruoyi.common.core.page.TableDataInfo;
@RequestMapping("/system/GoodsOrder") @RequestMapping("/system/GoodsOrder")
public class GoodsOrderController extends BaseController public class GoodsOrderController extends BaseController
{ {
private static final Logger log = LoggerFactory.getLogger(GoodsOrderController.class);
@Autowired @Autowired
private IGoodsOrderService goodsOrderService; private IGoodsOrderService goodsOrderService;
@Autowired @Autowired
@ -58,7 +71,7 @@ public class GoodsOrderController extends BaseController
public TableDataInfo list(GoodsOrder goodsOrder) public TableDataInfo list(GoodsOrder goodsOrder)
{ {
startPage(); startPage();
List<GoodsOrder> list = goodsOrderService.selectGoodsOrderList(goodsOrder); List<GoodsOrder> list = goodsOrderService.selectGoodsOrdergrouBymAIDList(goodsOrder);
for(GoodsOrder goodsOrderdata:list){ for(GoodsOrder goodsOrderdata:list){
ServiceGoods serviceGoods=serviceGoodsService.selectServiceGoodsById(goodsOrderdata.getProductId()); ServiceGoods serviceGoods=serviceGoodsService.selectServiceGoodsById(goodsOrderdata.getProductId());
@ -75,6 +88,90 @@ public class GoodsOrderController extends BaseController
} }
return getDataTable(list); return getDataTable(list);
} }
@GetMapping("/getByMainOrderId/{mainOrderId}")
public AjaxResult getGoodsOrderByMainOrderId(@PathVariable String mainOrderId) {
try {
GoodsOrder goodsOrderdata = new GoodsOrder();
goodsOrderdata.setMainOrderId(mainOrderId);
List<GoodsOrder> orders = goodsOrderService.selectGoodsOrderList(goodsOrderdata);
// 为每个订单补充商品详细信息
for (GoodsOrder order : orders) {
if (order.getProductId() != null) {
try {
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
if (serviceGoods != null) {
// 补充商品详细信息
order.setProductName(serviceGoods.getTitle()); // 商品名称
// 可以添加更多商品信息字段比如
// order.setProductImage(serviceGoods.getImage()); // 商品图片
// order.setProductCategory(serviceGoods.getCategory()); // 商品分类
// order.setProductDescription(serviceGoods.getDescription()); // 商品描述
}
} catch (Exception e) {
// 如果获取商品信息失败记录日志但不影响订单数据
log.warn("获取商品信息失败商品ID: {}, 错误: {}", order.getProductId(), e.getMessage());
}
}
}
return AjaxResult.success(orders);
} catch (Exception e) {
log.error("获取主订单数据失败主订单ID: {}, 错误: {}", mainOrderId, e.getMessage());
return AjaxResult.error("获取主订单数据失败: " + e.getMessage());
}
}
/**
* 根据商品ID获取商品详细信息
*/
@GetMapping("/getProductInfo/{productId}")
public AjaxResult getProductInfo(@PathVariable Long productId) {
try {
if (productId == null) {
return AjaxResult.error("商品ID不能为空");
}
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(productId);
if (serviceGoods == null) {
return AjaxResult.error("未找到商品信息");
}
return AjaxResult.success(serviceGoods);
} catch (Exception e) {
log.error("获取商品信息失败商品ID: {}, 错误: {}", productId, e.getMessage());
return AjaxResult.error("获取商品信息失败: " + e.getMessage());
}
}
/**
* 批量获取商品信息
*/
@PostMapping("/getBatchProductInfo")
public AjaxResult getBatchProductInfo(@RequestBody List<Long> productIds) {
try {
if (productIds == null || productIds.isEmpty()) {
return AjaxResult.error("商品ID列表不能为空");
}
Map<Long, ServiceGoods> productMap = new HashMap<>();
for (Long productId : productIds) {
try {
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(productId);
if (serviceGoods != null) {
productMap.put(productId, serviceGoods);
}
} catch (Exception e) {
log.warn("获取商品信息失败商品ID: {}, 错误: {}", productId, e.getMessage());
}
}
return AjaxResult.success(productMap);
} catch (Exception e) {
log.error("批量获取商品信息失败,错误: {}", e.getMessage());
return AjaxResult.error("批量获取商品信息失败: " + e.getMessage());
}
}
/** /**
* 导出商品订单列表 * 导出商品订单列表
@ -320,7 +417,7 @@ public class GoodsOrderController extends BaseController
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("处理售后申请失败", e); log.error("处理售后申请失败", e);
return error("操作失败:" + e.getMessage()); return error("操作失败:" + e.getMessage());
} }
} }
@ -394,8 +491,393 @@ public class GoodsOrderController extends BaseController
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("订单发货失败", e); log.error("订单发货失败", e);
return error("发货失败:" + e.getMessage()); return error("发货失败:" + e.getMessage());
} }
} }
/**
* Excel导入批量发货
*/
@PreAuthorize("@ss.hasPermi('system:GoodsOrder:edit')")
@Log(title = "Excel导入批量发货", businessType = BusinessType.UPDATE)
@PostMapping("/batchShipByExcel")
public AjaxResult batchShipByExcel(@RequestParam("file") MultipartFile file)
{
try {
if (file.isEmpty()) {
return error("请选择要上传的Excel文件");
}
String fileName = file.getOriginalFilename();
if (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls")) {
return error("请上传Excel格式的文件(.xlsx或.xls)");
}
// 读取Excel文件
List<Map<String, Object>> excelData = readExcelFile(file);
if (excelData == null || excelData.isEmpty()) {
return error("Excel文件内容为空或格式错误");
}
// 验证Excel数据格式
String validationResult = validateExcelData(excelData);
if (!"success".equals(validationResult)) {
return error("Excel数据格式错误" + validationResult);
}
// 执行批量发货
Map<String, Object> result = executeBatchShipping(excelData);
// 返回详细的结果信息
return AjaxResult.success("批量发货完成", result);
} catch (Exception e) {
log.error("Excel导入批量发货失败", e);
return error("批量发货失败:" + e.getMessage());
}
}
/**
* 读取Excel文件内容
*/
private List<Map<String, Object>> readExcelFile(MultipartFile file) throws Exception {
List<Map<String, Object>> dataList = new ArrayList<>();
try (InputStream is = file.getInputStream()) {
Workbook workbook;
if (file.getOriginalFilename().endsWith(".xlsx")) {
workbook = new XSSFWorkbook(is);
} else {
workbook = WorkbookFactory.create(is);
}
Sheet sheet = workbook.getSheetAt(0);
if (sheet == null) {
return dataList;
}
// 跳过标题行从第二行开始读取数据
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
Map<String, Object> rowData = new HashMap<>();
// 读取订单号
Cell orderIdCell = row.getCell(0);
if (orderIdCell != null) {
rowData.put("orderId", getCellValue(orderIdCell));
}
// 读取快递公司
Cell deliveryCompanyCell = row.getCell(1);
if (deliveryCompanyCell != null) {
rowData.put("deliveryCompany", getCellValue(deliveryCompanyCell));
}
// 读取快递单号
Cell deliveryNumCell = row.getCell(2);
if (deliveryNumCell != null) {
rowData.put("deliveryNum", getCellValue(deliveryNumCell));
}
// 读取发货时间
Cell sendTimeCell = row.getCell(3);
if (sendTimeCell != null) {
rowData.put("sendTime", getCellValue(sendTimeCell));
}
// 只添加有订单号的行
if (rowData.get("orderId") != null && !rowData.get("orderId").toString().trim().isEmpty()) {
dataList.add(rowData);
}
}
workbook.close();
}
return dataList;
}
/**
* 获取单元格值
*/
private String getCellValue(Cell cell) {
if (cell == null) {
return "";
}
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(cell.getDateCellValue());
} else {
return String.valueOf((long) cell.getNumericCellValue());
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
default:
return "";
}
}
/**
* 验证Excel数据格式
*/
private String validateExcelData(List<Map<String, Object>> excelData) {
if (excelData == null || excelData.isEmpty()) {
return "Excel数据为空";
}
for (int i = 0; i < excelData.size(); i++) {
Map<String, Object> row = excelData.get(i);
int rowNum = i + 2; // Excel行号从2开始因为第1行是标题
// 验证订单号
Object orderId = row.get("orderId");
if (orderId == null || orderId.toString().trim().isEmpty()) {
return "" + rowNum + "行:订单号不能为空";
}
// 验证快递公司
Object deliveryCompany = row.get("deliveryCompany");
if (deliveryCompany == null || deliveryCompany.toString().trim().isEmpty()) {
return "" + rowNum + "行:快递公司不能为空";
}
// 验证快递单号
Object deliveryNum = row.get("deliveryNum");
if (deliveryNum == null || deliveryNum.toString().trim().isEmpty()) {
return "" + rowNum + "行:快递单号不能为空";
}
// 验证发货时间
Object sendTime = row.get("sendTime");
if (sendTime == null || sendTime.toString().trim().isEmpty()) {
return "" + rowNum + "行:发货时间不能为空";
}
// 验证发货时间格式
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.parse(sendTime.toString());
} catch (Exception e) {
return "" + rowNum + "发货时间格式错误请使用yyyy-MM-dd格式";
}
}
return "success";
}
/**
* 执行批量发货
*/
private Map<String, Object> executeBatchShipping(List<Map<String, Object>> excelData) throws Exception {
Map<String, Object> result = new HashMap<>();
List<String> successList = new ArrayList<>();
List<String> failList = new ArrayList<>();
List<String> skipList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for (Map<String, Object> row : excelData) {
String orderId = row.get("orderId").toString().trim();
String deliveryCompany = row.get("deliveryCompany").toString().trim();
String deliveryNum = row.get("deliveryNum").toString().trim();
String sendTimeStr = row.get("sendTime").toString().trim();
try {
// 根据订单号查询订单
GoodsOrder queryOrder = new GoodsOrder();
queryOrder.setOrderId(orderId);
List<GoodsOrder> orders = goodsOrderService.selectGoodsOrderList(queryOrder);
if (orders == null || orders.isEmpty()) {
failList.add(orderId + ":订单不存在");
continue;
}
GoodsOrder order = orders.get(0);
// 检查订单状态
if (order.getStatus() != 2L) {
skipList.add(orderId + ":订单状态不是待发货状态(当前状态:" + order.getStatus() + "");
continue;
}
// 根据快递公司名称查找快递公司ID
Long deliveryId = findDeliveryIdByName(deliveryCompany);
if (deliveryId == null) {
failList.add(orderId + ":快递公司'" + deliveryCompany + "'不存在");
continue;
}
// 解析发货时间
Date sendTime;
try {
sendTime = sdf.parse(sendTimeStr);
} catch (Exception e) {
failList.add(orderId + ":发货时间格式错误");
continue;
}
// 执行发货
boolean shipResult = shipSingleOrder(order, deliveryId, deliveryNum, sendTime);
if (shipResult) {
successList.add(orderId);
} else {
failList.add(orderId + ":发货失败");
}
} catch (Exception e) {
log.error("处理订单" + orderId + "发货失败", e);
failList.add(orderId + ":处理异常 - " + e.getMessage());
}
}
result.put("total", excelData.size());
result.put("success", successList.size());
result.put("fail", failList.size());
result.put("skip", skipList.size());
result.put("successList", successList);
result.put("failList", failList);
result.put("skipList", skipList);
return result;
}
/**
* 根据快递公司名称查找ID
*/
private Long findDeliveryIdByName(String companyName) {
try {
// 查询所有快递公司
List<SiteDelivery> deliveries = siteDeliveryService.selectSiteDeliveryList(new SiteDelivery());
for (SiteDelivery delivery : deliveries) {
if (companyName.equals(delivery.getTitle()) || companyName.equals(delivery.getCode())) {
return delivery.getId();
}
}
} catch (Exception e) {
log.error("查询快递公司失败", e);
}
return null;
}
/**
* 发货单个订单
*/
private boolean shipSingleOrder(GoodsOrder order, Long deliveryId, String deliveryNum, Date sendTime) {
try {
// 更新订单信息
order.setDeliveryId(deliveryId);
order.setDeliveryNum(deliveryNum);
order.setSendTime(sendTime);
order.setStatus(3L); // 设置为已发货状态
// 更新订单
int result = goodsOrderService.updateGoodsOrder(order);
if (result > 0) {
// 获取快递公司信息
SiteDelivery siteDelivery = siteDeliveryService.selectSiteDeliveryById(deliveryId);
String deliveryTitle = siteDelivery != null ? siteDelivery.getTitle() : "未知快递";
// 添加发货日志
JSONObject logData = new JSONObject();
logData.put("wlgs", deliveryTitle);
logData.put("wldh", deliveryNum);
OrderUtil.addgoodsorderlog(
999L,
order.getMainOrderId(),
"Excel批量导入发货",
"2",
logData,
2L
);
return true;
}
return false;
} catch (Exception e) {
log.error("发货订单" + order.getOrderId() + "失败", e);
return false;
}
}
/**
* 下载批量发货Excel模板
*/
@GetMapping("/downloadTemplate")
public void downloadTemplate(HttpServletResponse response) throws Exception {
try {
// 创建CSV内容
String csvContent = "订单号,快递公司,快递单号,发货时间\n" +
"B00001,顺丰,35434353,2025/8/11\n" +
"B00002,圆通,12345678,2025/8/11";
// 设置响应头
response.setContentType("text/csv;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String fileName = "批量发货模板.csv";
response.setHeader("Content-Disposition", "attachment;filename=" +
java.net.URLEncoder.encode(fileName, "UTF-8"));
// 写入CSV内容
response.getWriter().write(csvContent);
response.getWriter().flush();
} catch (Exception e) {
log.error("下载模板失败", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("下载模板失败:" + e.getMessage());
}
}
/**
* 测试模板文件是否正常
*/
@GetMapping("/testTemplate")
public AjaxResult testTemplate() {
try {
// 获取模板文件的URL
java.net.URL resourceUrl = getClass().getClassLoader().getResource("批量发货模版.xlsx");
if (resourceUrl == null) {
return error("模板文件不存在");
}
// 使用Files.readAllBytes来读取文件内容
java.nio.file.Path filePath = java.nio.file.Paths.get(resourceUrl.toURI());
byte[] fileContent = java.nio.file.Files.readAllBytes(filePath);
if (fileContent.length == 0) {
return error("模板文件为空");
}
// 检查文件头验证是否为有效的XLSX文件
if (fileContent.length < 4) {
return error("模板文件太小,可能已损坏");
}
// XLSX文件应该以PK开头ZIP格式
if (fileContent[0] != 0x50 || fileContent[1] != 0x4B) {
return error("模板文件不是有效的XLSX格式缺少ZIP文件头");
}
return success("模板文件正常,大小:" + fileContent.length + " 字节");
} catch (Exception e) {
log.error("测试模板文件失败", e);
return error("测试模板文件失败:" + e.getMessage());
}
}
} }

View File

@ -7,10 +7,8 @@ import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.system.ControllerUtil.GenerateCustomCode; import com.ruoyi.system.ControllerUtil.GenerateCustomCode;
import com.ruoyi.system.domain.QuoteMaterial; import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.ServiceCate; import com.ruoyi.system.service.*;
import com.ruoyi.system.service.IServiceCateService;
import com.ruoyi.system.service.IServiceGoodsService;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -25,10 +23,9 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.UserSecondaryCard;
import com.ruoyi.system.service.IUserSecondaryCardService;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import java.util.Map;
/** /**
* 次卡管理Controller * 次卡管理Controller
@ -49,6 +46,14 @@ public class UserSecondaryCardController extends BaseController
@Autowired @Autowired
private IServiceCateService serviceCateService; private IServiceCateService serviceCateService;
@Autowired
private IUserUseSecondaryCardService userUseSecondaryCardService;
@Autowired
private IUsersService usersService;
/** /**
* 数字转中文工具方法 * 数字转中文工具方法
*/ */
@ -145,6 +150,22 @@ public class UserSecondaryCardController extends BaseController
@PostMapping @PostMapping
public AjaxResult add(@RequestBody UserSecondaryCard userSecondaryCard) public AjaxResult add(@RequestBody UserSecondaryCard userSecondaryCard)
{ {
// 数据验证
if (userSecondaryCard.getAllnum() == null || userSecondaryCard.getAllnum() <= 0) {
return error("总服务数必须大于0");
}
if (userSecondaryCard.getNum() == null || userSecondaryCard.getNum() <= 0) {
return error("可提供服务数必须大于0");
}
if (userSecondaryCard.getNum() > userSecondaryCard.getAllnum()) {
return error("可提供服务数不能大于总服务数");
}
if (userSecondaryCard.getShowMoney() != null && userSecondaryCard.getRealMoney() != null) {
if (userSecondaryCard.getRealMoney().compareTo(userSecondaryCard.getShowMoney()) > 0) {
return error("实付价格不能大于展示价格");
}
}
userSecondaryCard.setOrderid(GenerateCustomCode.generCreateOrder("CIKA")); userSecondaryCard.setOrderid(GenerateCustomCode.generCreateOrder("CIKA"));
userSecondaryCard.setCreattime(new Date()); userSecondaryCard.setCreattime(new Date());
@ -163,6 +184,24 @@ public class UserSecondaryCardController extends BaseController
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody UserSecondaryCard userSecondaryCard) public AjaxResult edit(@RequestBody UserSecondaryCard userSecondaryCard)
{ {
// 数据验证
if (userSecondaryCard.getAllnum() != null && userSecondaryCard.getAllnum() <= 0) {
return error("总服务数必须大于0");
}
if (userSecondaryCard.getNum() != null && userSecondaryCard.getNum() <= 0) {
return error("可提供服务数必须大于0");
}
if (userSecondaryCard.getNum() != null && userSecondaryCard.getAllnum() != null) {
if (userSecondaryCard.getNum() > userSecondaryCard.getAllnum()) {
return error("可提供服务数不能大于总服务数");
}
}
if (userSecondaryCard.getShowMoney() != null && userSecondaryCard.getRealMoney() != null) {
if (userSecondaryCard.getRealMoney().compareTo(userSecondaryCard.getShowMoney()) > 0) {
return error("实付价格不能大于展示价格");
}
}
// 自动生成introduction字段 // 自动生成introduction字段
String introduction = generateIntroduction(userSecondaryCard.getAllnum(), userSecondaryCard.getNum()); String introduction = generateIntroduction(userSecondaryCard.getAllnum(), userSecondaryCard.getNum());
userSecondaryCard.setIntroduction(introduction); userSecondaryCard.setIntroduction(introduction);
@ -180,4 +219,68 @@ public class UserSecondaryCardController extends BaseController
{ {
return toAjax(userSecondaryCardService.deleteUserSecondaryCardByIds(ids)); return toAjax(userSecondaryCardService.deleteUserSecondaryCardByIds(ids));
} }
/**
* 批量更新次卡状态
*/
@PreAuthorize("@ss.hasPermi('system:UserSecondaryCard:edit')")
@Log(title = "批量更新次卡状态", businessType = BusinessType.UPDATE)
@PutMapping("/batchStatus")
public AjaxResult batchUpdateStatus(@RequestBody Map<String, Object> params)
{
List<Long> ids = (List<Long>) params.get("ids");
Integer status = (Integer) params.get("status");
if (ids == null || ids.isEmpty()) {
return error("请选择要更新的次卡");
}
if (status == null || status < 1 || status > 3) {
return error("状态值无效");
}
int result = 0;
for (Long id : ids) {
UserSecondaryCard card = new UserSecondaryCard();
card.setId(id);
card.setStatus(status.longValue());
result += userSecondaryCardService.updateUserSecondaryCard(card);
}
return toAjax(result);
}
/**
* 批量删除次卡
*/
@PreAuthorize("@ss.hasPermi('system:UserSecondaryCard:remove')")
@Log(title = "批量删除次卡", businessType = BusinessType.DELETE)
@DeleteMapping("/batchDelete")
public AjaxResult batchDelete(@RequestBody List<Long> ids)
{
if (ids == null || ids.isEmpty()) {
return error("请选择要删除的次卡");
}
return toAjax(userSecondaryCardService.deleteUserSecondaryCardByIds(ids.toArray(new Long[0])));
}
/**
* 查询次卡购买详情
*/
@PreAuthorize("@ss.hasPermi('system:UserSecondaryCard:query')")
@GetMapping("/purchaseDetails/{id}")
public AjaxResult getPurchaseDetails(@PathVariable("id") String id)
{
List<UserUseSecondaryCard> list = userUseSecondaryCardService.selectPurchaseDetailsByCardId(id);
for (UserUseSecondaryCard userUseSecondaryCard : list){
Users users = usersService.selectUsersById(userUseSecondaryCard.getUid());
if (users != null) {
userUseSecondaryCard.setRemark(users.getName());
}
}
return success(list);
//return success(userUseSecondaryCardService.selectPurchaseDetailsByCardId(id));
}
} }

View File

@ -10,7 +10,8 @@ import java.util.Map;
import java.math.BigDecimal; import java.math.BigDecimal;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.controllerUtil.ScheduledTaskUtil;
import com.ruoyi.system.ControllerUtil.ScheduledTaskUtil;
import com.ruoyi.system.domain.Users; import com.ruoyi.system.domain.Users;
import com.ruoyi.system.service.IUsersService; import com.ruoyi.system.service.IUsersService;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;

View File

@ -2,7 +2,7 @@ package com.ruoyi.system.ControllerUtil;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.controllerUtil.ScheduledTaskUtil;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Map; import java.util.Map;

View File

@ -1,4 +1,4 @@
package com.ruoyi.system.controllerUtil; package com.ruoyi.system.ControllerUtil;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;

View File

@ -166,6 +166,7 @@ public class GoodsOrder extends BaseEntity
private String returnlogisticscode; private String returnlogisticscode;
private String returnjson; private String returnjson;
private Long returnstatus; private Long returnstatus;
private Long ismany;
private Date returntime; private Date returntime;
private BigDecimal returnmoney; private BigDecimal returnmoney;
@ -668,6 +669,14 @@ public class GoodsOrder extends BaseEntity
this.returnrealmoney = returnrealmoney; this.returnrealmoney = returnrealmoney;
} }
public Long getIsmany() {
return ismany;
}
public void setIsmany(Long ismany) {
this.ismany = ismany;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -46,6 +46,14 @@ public interface GoodsOrderMapper
*/ */
public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder); public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder);
/**
* 查询商品订单列表
*
* @param goodsOrder 商品订单
* @return 商品订单集合
*/
public List<GoodsOrder> selectGoodsOrdergrouBymAIDList(GoodsOrder goodsOrder);
/** /**
* 新增商品订单 * 新增商品订单
* *

View File

@ -63,4 +63,12 @@ public interface UserUseSecondaryCardMapper
* @return 结果 * @return 结果
*/ */
public int deleteUserUseSecondaryCardByIds(Long[] ids); public int deleteUserUseSecondaryCardByIds(Long[] ids);
/**
* 根据次卡ID查询购买详情
*
* @param cardId 次卡ID
* @return 购买详情列表
*/
public List<UserUseSecondaryCard> selectPurchaseDetailsByCardId(String cardId);
} }

View File

@ -27,6 +27,9 @@ public interface IGoodsOrderService
*/ */
public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder); public List<GoodsOrder> selectGoodsOrderList(GoodsOrder goodsOrder);
public List<GoodsOrder> selectGoodsOrdergrouBymAIDList(GoodsOrder goodsOrder);
public GoodsOrder selectGoodsOrderByorderId(String orderId); public GoodsOrder selectGoodsOrderByorderId(String orderId);
public int selectCountGoodsOrderByUid(Long uid,Long status); public int selectCountGoodsOrderByUid(Long uid,Long status);

View File

@ -63,4 +63,12 @@ public interface IUserUseSecondaryCardService
* @return 结果 * @return 结果
*/ */
public int deleteUserUseSecondaryCardById(Long id); public int deleteUserUseSecondaryCardById(Long id);
/**
* 根据次卡ID查询购买详情
*
* @param cardId 次卡ID
* @return 购买详情列表
*/
public List<UserUseSecondaryCard> selectPurchaseDetailsByCardId(String cardId);
} }

View File

@ -63,6 +63,18 @@ public class GoodsOrderServiceImpl implements IGoodsOrderService
return goodsOrderMapper.selectGoodsOrderList(goodsOrder); return goodsOrderMapper.selectGoodsOrderList(goodsOrder);
} }
/**
* 查询商品订单列表
*
* @param goodsOrder 商品订单
* @return 商品订单
*/
@Override
public List<GoodsOrder> selectGoodsOrdergrouBymAIDList(GoodsOrder goodsOrder)
{
return goodsOrderMapper.selectGoodsOrdergrouBymAIDList(goodsOrder);
}
/** /**
* 新增商品订单 * 新增商品订单
* *

View File

@ -97,4 +97,16 @@ public class UserUseSecondaryCardServiceImpl implements IUserUseSecondaryCardSer
{ {
return userUseSecondaryCardMapper.deleteUserUseSecondaryCardById(id); return userUseSecondaryCardMapper.deleteUserUseSecondaryCardById(id);
} }
/**
* 根据次卡ID查询购买详情
*
* @param cardId 次卡ID
* @return 购买详情列表
*/
@Override
public List<UserUseSecondaryCard> selectPurchaseDetailsByCardId(String cardId)
{
return userUseSecondaryCardMapper.selectPurchaseDetailsByCardId(cardId);
}
} }

View File

@ -17,6 +17,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="forserviceid" column="forserviceid" /> <result property="forserviceid" column="forserviceid" />
<result property="name" column="name" /> <result property="name" column="name" />
<result property="returnrealmoney" column="returnrealmoney" /> <result property="returnrealmoney" column="returnrealmoney" />
<result property="ismany" column="ismany" />
<result property="phone" column="phone" /> <result property="phone" column="phone" />
<result property="address" column="address" /> <result property="address" column="address" />
@ -59,7 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectGoodsOrderVo"> <sql id="selectGoodsOrderVo">
select id, type, main_order_id,returnshow,returnrealmoney, returnstatus,order_id,returntime,returnmoney,returnfinshtime,returntype,returnreason,returnfiledata,returnlogistics,returnlogisticscode,returnjson, transaction_id,forserviceid,isforservice,isself,coupon_id,shopadresssid, uid, product_id, name, phone, address, num, total_price, good_price, service_price, pay_price, deduction, postage, pay_time, status, delivery_id, delivery_num, send_time, mark, address_id, sku, created_at, updated_at, deleted_at from goods_order select id, type, main_order_id,returnshow,ismany,returnrealmoney, returnstatus,order_id,returntime,returnmoney,returnfinshtime,returntype,returnreason,returnfiledata,returnlogistics,returnlogisticscode,returnjson, transaction_id,forserviceid,isforservice,isself,coupon_id,shopadresssid, uid, product_id, name, phone, address, num, total_price, good_price, service_price, pay_price, deduction, postage, pay_time, status, delivery_id, delivery_num, send_time, mark, address_id, sku, created_at, updated_at, deleted_at from goods_order
</sql> </sql>
<select id="selectGoodsOrderList" parameterType="GoodsOrder" resultMap="GoodsOrderResult"> <select id="selectGoodsOrderList" parameterType="GoodsOrder" resultMap="GoodsOrderResult">
@ -78,8 +79,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and status in(20,21,22) and status in(20,21,22)
</if> </if>
<if test="uid != null "> and uid = #{uid}</if> <if test="uid != null "> and uid = #{uid}</if>
<if test="status != null "> and status = #{status}</if> <if test="status != null "> and status = #{status}</if>
<if test="productId != null "> and product_id = #{productId}</if> <if test="productId != null "> and product_id = #{productId}</if>
@ -94,6 +93,41 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
END ASC, END ASC,
updated_at DESC updated_at DESC
</select> </select>
<select id="selectGoodsOrdergrouBymAIDList" parameterType="GoodsOrder" resultMap="GoodsOrderResult">
<include refid="selectGoodsOrderVo"/>
<where>
<if test="payPriceMin != null and payPriceMax != null">
and pay_price BETWEEN #{payPriceMin} AND #{payPriceMax}
</if>
<if test="startdate != null and enddate != null">
and created_at BETWEEN #{startdate} AND #{enddate}
</if>
<if test="paystartdate != null and payenddate != null">
and pay_time BETWEEN #{paystartdate} AND #{payenddate}
</if>
<if test="returnstatus != null and returnstatus != null">
and status in(20,21,22)
</if>
<if test="uid != null "> and uid = #{uid}</if>
<if test="status != null "> and status = #{status}</if>
<if test="productId != null "> and product_id = #{productId}</if>
<if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if>
<if test="transactionId != null and transactionId != ''"> and transaction_id = #{transactionId}</if>
<if test="mainOrderId != null and mainOrderId != ''"> and main_order_id = #{mainOrderId}</if>
</where>
GROUP BY
main_order_id
ORDER BY
CASE
WHEN (status = 2 OR returnstatus IN (1,4)) THEN 0
ELSE 1
END ASC,
updated_at DESC
</select>
<select id="selectGoodsOrderByorderId" parameterType="String" resultMap="GoodsOrderResult"> <select id="selectGoodsOrderByorderId" parameterType="String" resultMap="GoodsOrderResult">
<include refid="selectGoodsOrderVo"/> <include refid="selectGoodsOrderVo"/>
@ -163,6 +197,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="returnstatus != null">returnstatus,</if> <if test="returnstatus != null">returnstatus,</if>
<if test="returnshow != null">returnshow,</if> <if test="returnshow != null">returnshow,</if>
<if test="returnrealmoney != null">returnrealmoney,</if> <if test="returnrealmoney != null">returnrealmoney,</if>
<if test="ismany != null">ismany,</if>
created_at, created_at,
updated_at updated_at
@ -210,6 +245,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="returnstatus != null">#{returnstatus},</if> <if test="returnstatus != null">#{returnstatus},</if>
<if test="returnshow != null">#{returnshow},</if> <if test="returnshow != null">#{returnshow},</if>
<if test="returnrealmoney != null">#{returnrealmoney},</if> <if test="returnrealmoney != null">#{returnrealmoney},</if>
<if test="ismany != null">#{ismany},</if>
NOW(), NOW(),
NOW() NOW()
@ -263,6 +299,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="returnstatus != null">returnstatus = #{returnstatus},</if> <if test="returnstatus != null">returnstatus = #{returnstatus},</if>
<if test="returnshow != null">returnshow = #{returnshow},</if> <if test="returnshow != null">returnshow = #{returnshow},</if>
<if test="returnrealmoney != null">returnrealmoney = #{returnrealmoney},</if> <if test="returnrealmoney != null">returnrealmoney = #{returnrealmoney},</if>
<if test="ismany != null">ismany = #{ismany},</if>
updated_at=NOW() updated_at=NOW()

View File

@ -51,6 +51,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where orderid = #{orderid} where orderid = #{orderid}
</select> </select>
<select id="selectPurchaseDetailsByCardId" parameterType="String" resultMap="UserUseSecondaryCardResult">
<include refid="selectUserUseSecondaryCardVo"/>
where carid = #{cardId}
order by created_at desc
</select>
<insert id="insertUserUseSecondaryCard" parameterType="UserUseSecondaryCard" useGeneratedKeys="true" keyProperty="id"> <insert id="insertUserUseSecondaryCard" parameterType="UserUseSecondaryCard" useGeneratedKeys="true" keyProperty="id">

View File

@ -108,3 +108,42 @@ export function getPrePaymentByOrderId(orderId) {
method: 'get' method: 'get'
}) })
} }
// 根据主订单ID查询所有子订单
export function getGoodsOrderByMainOrderId(mainOrderId) {
return request({
url: '/system/GoodsOrder/getByMainOrderId/' + mainOrderId,
method: 'get'
})
}
// 根据商品ID获取商品详细信息
export function getProductInfo(productId) {
return request({
url: '/system/GoodsOrder/getProductInfo/' + productId,
method: 'get'
})
}
// 批量获取商品信息
export function getBatchProductInfo(productIds) {
return request({
url: '/system/GoodsOrder/getBatchProductInfo',
method: 'post',
data: productIds
})
}
// Excel导入批量发货
export function batchShipByExcel(file) {
const formData = new FormData()
formData.append('file', file)
return request({
url: '/system/GoodsOrder/batchShipByExcel',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}

View File

@ -68,3 +68,11 @@ export function delUserSecondaryCard(id) {
method: 'delete' method: 'delete'
}) })
} }
// 查询次卡购买详情
export function getPurchaseDetails(cardId) {
return request({
url: '/system/UserSecondaryCard/purchaseDetails/' + cardId,
method: 'get'
})
}

View File

@ -49,6 +49,24 @@ export function delWorkerApply(id) {
}) })
} }
// 审核师傅申请记录
export function auditWorkerApply(data) {
return request({
url: '/system/WorkerApply/audit',
method: 'post',
data: data
})
}
// 批量审核师傅申请记录
export function batchAuditWorkerApply(data) {
return request({
url: '/system/WorkerApply/batchAudit',
method: 'post',
data: data
})
}
// 获取地区列表 // 获取地区列表
export function selectAreaList(pid) { export function selectAreaList(pid) {
return request({ return request({

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,11 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="分类" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择分类" clearable>
<el-option v-for="cate in serviceCateList" :key="cate.id" :label="cate.title" :value="cate.id" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable> <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
@ -24,6 +28,36 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="价格范围" prop="priceRange">
<el-input-number
v-model="queryParams.minPrice"
placeholder="最低价"
:min="0"
:precision="2"
style="width: 120px"
/>
<span style="margin: 0 8px">-</span>
<el-input-number
v-model="queryParams.maxPrice"
placeholder="最高价"
:min="0"
:precision="2"
style="width: 120px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="dateRange">
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 240px"
/>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -74,6 +108,17 @@
v-hasPermi="['system:UserSecondaryCard:export']" v-hasPermi="['system:UserSecondaryCard:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-refresh"
size="mini"
:disabled="multiple"
@click="handleBatchStatusUpdate"
v-hasPermi="['system:UserSecondaryCard:edit']"
>批量状态更新</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
@ -156,8 +201,23 @@
</el-table-column> </el-table-column>
<el-table-column label="状态" align="center" prop="status" width="100"> <el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag v-if="scope.row.status !== undefined && scope.row.status !== null" :options="dict.type.cika" :value="scope.row.status" class="status-tag"/> <el-dropdown @command="handleStatusChange" trigger="click">
<span v-else>-</span> <span class="el-dropdown-link">
<dict-tag v-if="scope.row.status !== undefined && scope.row.status !== null" :options="dict.type.cika" :value="scope.row.status" class="status-tag"/>
<span v-else>-</span>
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="dict in dict.type.cika"
:key="dict.value"
:command="{id: scope.row.id, status: dict.value, label: dict.label}"
:disabled="scope.row.status == dict.value"
>
{{ dict.label }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="creattime" width="180"> <el-table-column label="创建时间" align="center" prop="creattime" width="180">
@ -184,6 +244,13 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleViewPurchaseDetails(scope.row)"
v-hasPermi="['system:UserSecondaryCard:query']"
>购买明细查看</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -308,11 +375,71 @@
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 购买明细查看对话框 -->
<el-dialog
title="购买明细查看"
:visible.sync="purchaseDetailsOpen"
width="80%"
append-to-body
:close-on-click-modal="false"
>
<div class="purchase-details-header">
<el-descriptions :column="3" border>
<el-descriptions-item label="次卡标题">{{ purchaseDetailsData.title }}</el-descriptions-item>
<el-descriptions-item label="次卡ID">{{ purchaseDetailsData.id }}</el-descriptions-item>
<el-descriptions-item label="订单ID">{{ purchaseDetailsData.orderid }}</el-descriptions-item>
<el-descriptions-item label="展示价格">¥{{ purchaseDetailsData.showMoney }}</el-descriptions-item>
<el-descriptions-item label="实付价格">¥{{ purchaseDetailsData.realMoney }}</el-descriptions-item>
<el-descriptions-item label="状态">
<dict-tag :options="dict.type.cika" :value="purchaseDetailsData.status" />
</el-descriptions-item>
</el-descriptions>
</div>
<el-table
v-loading="purchaseDetailsLoading"
:data="purchaseDetailsList"
style="margin-top: 20px;"
>
<el-table-column label="ID" align="center" prop="id" width="80" />
<el-table-column label="用户" align="center" prop="remark" width="100" />
<!-- <el-table-column label="次卡ID" align="center" prop="carid" width="100" />-->
<!-- <el-table-column label="服务项目" align="center" prop="goodsids" min-width="150" />-->
<el-table-column label="可用数量" align="center" prop="num" width="100" />
<el-table-column label="已用数量" align="center" prop="usenum" width="100" />
<el-table-column label="订单ID" align="center" prop="orderid" width="150" />
<el-table-column label="支付ID" align="center" prop="transactionId" width="150" />
<el-table-column label="支付金额" align="center" prop="paymoney" width="120">
<template slot-scope="scope">
<span class="price-text">¥{{ scope.row.paymoney || '0.00' }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope">
<el-tag
:type="scope.row.status === 1 ? 'success' : scope.row.status === 2 ? 'danger' : 'info'"
>
{{ scope.row.status === 1 ? '可用' : scope.row.status === 2 ? '已用完' : '已退款' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
<template slot-scope="scope">
<span>{{ scope.row.createdAt ? parseTime(scope.row.createdAt, '{y}-{m}-{d} {h}:{i}:{s}') : '-' }}</span>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="purchaseDetailsOpen = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listUserSecondaryCard, getUserSecondaryCard, delUserSecondaryCard, addUserSecondaryCard, updateUserSecondaryCard ,selectList,selectServiceCateList} from "@/api/system/UserSecondaryCard" import { listUserSecondaryCard, getUserSecondaryCard, delUserSecondaryCard, addUserSecondaryCard, updateUserSecondaryCard ,selectList,selectServiceCateList, getPurchaseDetails} from "@/api/system/UserSecondaryCard"
import { getGoodsDataList } from "@/api/system/GoodsOrder" import { getGoodsDataList } from "@/api/system/GoodsOrder"
export default { export default {
name: "UserSecondaryCard", name: "UserSecondaryCard",
@ -358,7 +485,10 @@ export default {
updatedAt: null, updatedAt: null,
type: null, type: null,
num: null, num: null,
allnum: null allnum: null,
minPrice: null,
maxPrice: null,
dateRange: null
}, },
// //
form: {}, form: {},
@ -392,13 +522,23 @@ export default {
], ],
num: [ num: [
{ required: true, message: '请输入可提供服务数', trigger: 'blur' }, { required: true, message: '请输入可提供服务数', trigger: 'blur' },
{ pattern: /^[1-9]\d*$/, message: '请输入正整数', trigger: 'blur' } { pattern: /^[1-9]\d*$/, message: '请输入正整数', trigger: 'blur' },
{ validator: this.validateNum, trigger: 'blur' }
], ],
allnum: [ allnum: [
{ required: true, message: '请输入总服务数', trigger: 'blur' }, { required: true, message: '请输入总服务数', trigger: 'blur' },
{ pattern: /^[1-9]\d*$/, message: '请输入正整数', trigger: 'blur' } { pattern: /^[1-9]\d*$/, message: '请输入正整数', trigger: 'blur' },
{ validator: this.validateAllnum, trigger: 'blur' }
] ]
} },
//
purchaseDetailsOpen: false,
purchaseDetailsData: {},
purchaseDetailsList: [],
purchaseDetailsLoading: false,
//
batchUpdateStatus: null
} }
}, },
created() { created() {
@ -603,6 +743,16 @@ export default {
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
//
if (this.form.num > this.form.allnum) {
this.$message.error('可提供服务数不能大于总服务数');
return;
}
if (this.form.realMoney > this.form.showMoney) {
this.$message.warning('实付价格大于展示价格,请确认是否合理');
}
// showimage // showimage
let showimageVal = ''; let showimageVal = '';
if (Array.isArray(this.form.showimage)) { if (Array.isArray(this.form.showimage)) {
@ -628,19 +778,29 @@ export default {
carouselImage: JSON.stringify(carouselArr), carouselImage: JSON.stringify(carouselArr),
goodsids: Array.isArray(this.form.goodsids) ? JSON.stringify(this.form.goodsids.map(String)) : this.form.goodsids goodsids: Array.isArray(this.form.goodsids) ? JSON.stringify(this.form.goodsids.map(String)) : this.form.goodsids
} }
if (this.form.id != null) {
updateUserSecondaryCard(submitForm).then(response => { //
this.$modal.msgSuccess("修改成功") this.$confirm('确认提交次卡信息?', '提示', {
this.open = false confirmButtonText: '确定',
this.getList() cancelButtonText: '取消',
}) type: 'warning'
} else { }).then(() => {
addUserSecondaryCard(submitForm).then(response => { if (this.form.id != null) {
this.$modal.msgSuccess("新增成功") updateUserSecondaryCard(submitForm).then(response => {
this.open = false this.$modal.msgSuccess("修改成功")
this.getList() this.open = false
}) this.getList()
} })
} else {
addUserSecondaryCard(submitForm).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}).catch(() => {
//
})
} }
}) })
}, },
@ -662,7 +822,110 @@ export default {
}, },
// //
onGoodsidsChange(val) { onGoodsidsChange(val) {
this.form.allnum = Array.isArray(val) ? val.length : 0 if (Array.isArray(val) && val.length > 0) {
this.form.allnum = val.length;
//
if (this.form.num && this.form.num > val.length) {
this.form.num = val.length;
}
} else {
this.form.allnum = 0;
this.form.num = 0;
}
},
//
handleViewPurchaseDetails(row) {
this.purchaseDetailsData = row;
this.purchaseDetailsOpen = true;
this.loadPurchaseDetails(row.id);
},
//
loadPurchaseDetails(cardId) {
this.purchaseDetailsLoading = true;
getPurchaseDetails(cardId).then(response => {
this.purchaseDetailsList = response.data || [];
this.purchaseDetailsLoading = false;
}).catch(() => {
this.purchaseDetailsLoading = false;
});
},
//
validateNum(rule, value, callback) {
if (value > this.form.allnum) {
callback(new Error('可提供服务数不能大于总服务数'));
} else {
callback();
}
},
//
validateAllnum(rule, value, callback) {
if (value < this.form.num) {
callback(new Error('总服务数不能小于可提供服务数'));
} else {
callback();
}
},
//
handleBatchStatusUpdate() {
if (!this.ids.length) {
this.$message.warning('请选择要更新的次卡');
return;
}
//
this.$prompt('请输入要更新的状态值1-启用2-禁用3-下架)', '批量状态更新', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[1-3]$/,
inputErrorMessage: '状态值只能是1、2或3'
}).then(({ value }) => {
const status = parseInt(value);
const statusText = this.dict.type.cika.find(item => item.value == status)?.label || `状态${status}`;
this.$confirm(`确定要批量更新选中的 ${this.ids.length} 个次卡状态为"${statusText}"吗?`, '确认操作', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
this.$http.put('/system/UserSecondaryCard/batchStatus', {
ids: this.ids,
status: status
}).then(response => {
if (response.code === 200) {
this.$modal.msgSuccess('批量状态更新成功');
this.getList();
} else {
this.$modal.msgError('批量状态更新失败: ' + response.msg);
}
}).catch(() => {
this.$modal.msgError('批量状态更新失败');
});
}).catch(() => {});
}).catch(() => {});
},
//
handleStatusChange(command) {
const { id, status, label } = command;
const statusText = this.dict.type.cika.find(item => item.value == status)?.label || `状态${status}`;
this.$confirm(`确定要将次卡状态更改为"${statusText}"吗?`, '确认操作', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
updateUserSecondaryCard({ id, status }).then(response => {
this.$modal.msgSuccess(`次卡状态更新成功,当前状态为:${statusText}`);
this.getList();
}).catch(error => {
this.$modal.msgError(`次卡状态更新失败: ${error.msg}`);
});
}).catch(() => {});
} }
} }
} }
@ -695,6 +958,26 @@ export default {
.status-tag { .status-tag {
font-weight: bold; font-weight: bold;
} }
.el-dropdown-link {
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
}
.el-dropdown-link:hover {
opacity: 0.8;
}
.el-dropdown-menu .el-dropdown-item {
padding: 8px 16px;
}
.el-dropdown-menu .el-dropdown-item.is-disabled {
color: #c0c4cc;
cursor: not-allowed;
}
.image-container { .image-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -758,4 +1041,12 @@ export default {
color: #909399; color: #909399;
text-align: center; text-align: center;
} }
.purchase-details-header {
margin-bottom: 20px;
}
.purchase-details-header .el-descriptions {
margin-bottom: 0;
}
</style> </style>

View File

@ -21,8 +21,22 @@
<el-form-item label="身份证号码" prop="cardNo"> <el-form-item label="身份证号码" prop="cardNo">
<el-input v-model="form.cardNo" placeholder="请输入身份证号码" /> <el-input v-model="form.cardNo" placeholder="请输入身份证号码" />
</el-form-item> </el-form-item>
<el-form-item label="技能ID" prop="skillId"> <el-form-item label="技能" prop="skillId">
<el-input v-model="form.skillId" type="textarea" placeholder="请输入内容" /> <el-select
v-model="selectedSkills"
multiple
filterable
placeholder="请选择技能"
style="width: 100%"
@change="handleSkillChange"
>
<el-option
v-for="item in skillList"
:key="item.id"
:label="item.title"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="电子照片" prop="image"> <el-form-item label="电子照片" prop="image">
<image-upload v-model="form.image" :limit="1"/> <image-upload v-model="form.image" :limit="1"/>
@ -80,7 +94,7 @@
</template> </template>
<script> <script>
import { getSiteSkillList } from "@/api/system/SiteSkill"
export default { export default {
name: "WorkerApplyEdit", name: "WorkerApplyEdit",
@ -141,6 +155,9 @@ export default {
], ],
cityIds: [ cityIds: [
{ required: true, message: "接单地区不能为空", trigger: "change" } { required: true, message: "接单地区不能为空", trigger: "change" }
],
skillId: [
{ required: true, message: "技能不能为空", trigger: "change" }
] ]
}, },
@ -156,7 +173,11 @@ export default {
{ id: 9, name: '临潼区' }, { id: 9, name: '临潼区' },
{ id: 10, name: '阎良区' } { id: 10, name: '阎良区' }
], // ], //
selectedAreas: [] // selectedAreas: [], //
//
skillList: [],
selectedSkills: []
} }
}, },
watch: { watch: {
@ -168,12 +189,53 @@ export default {
if (this.form.cityIds) { if (this.form.cityIds) {
this.selectedAreas = this.form.cityIds.split(',').map(Number) this.selectedAreas = this.form.cityIds.split(',').map(Number)
} }
// ,
if (this.form.skillId) {
this.selectedSkills = this.parseSkillIds(this.form.skillId).map(Number)
}
} }
}, },
immediate: true immediate: true
},
visible(val) {
if (val) {
//
this.loadSkillList();
}
} }
}, },
methods: { methods: {
// ID
parseSkillIds(skillIdData) {
if (!skillIdData) return [];
try {
// JSON
if (typeof skillIdData === 'string') {
// JSON
if (skillIdData.startsWith('[') && skillIdData.endsWith(']')) {
const parsed = JSON.parse(skillIdData);
return Array.isArray(parsed) ? parsed : [];
}
//
return skillIdData.split(',').filter(id => id.trim());
}
//
if (Array.isArray(skillIdData)) {
return skillIdData;
}
return [];
} catch (error) {
console.error('解析技能ID失败:', error, '原始数据:', skillIdData);
// JSON
if (typeof skillIdData === 'string') {
return skillIdData.split(',').filter(id => id.trim());
}
return [];
}
},
// //
handleAreaChange(value) { handleAreaChange(value) {
@ -185,6 +247,40 @@ export default {
this.form.cityPid = undefined this.form.cityPid = undefined
} }
}, },
//
handleSkillChange(value) {
if (value && value.length > 0) {
// JSON
this.form.skillId = JSON.stringify(value)
} else {
this.form.skillId = undefined
}
},
//
loadSkillList() {
getSiteSkillList().then(response => {
if (response.code === 200) {
this.skillList = response.data || [];
} else {
// 使
this.skillList = [
{ id: 1, title: '水电工' },
{ id: 2, title: '油工师傅' },
{ id: 3, title: '改造维修' },
{ id: 4, title: '工程施工' }
];
}
}).catch((error) => {
console.error('获取技能列表异常:', error);
// 使
this.skillList = [
{ id: 1, title: '水电工' },
{ id: 2, title: '油工师傅' },
{ id: 3, title: '改造维修' },
{ id: 4, title: '工程施工' }
];
});
},
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
@ -217,6 +313,7 @@ export default {
cityIds: undefined cityIds: undefined
} }
this.selectedAreas = [] this.selectedAreas = []
this.selectedSkills = []
this.resetForm("form") this.resetForm("form")
} }
} }

View File

@ -50,9 +50,46 @@
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="info" icon="el-icon-view" size="mini" @click="handleViewPending">查看待审核</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- &lt;!&ndash; 审核统计信息 &ndash;&gt;-->
<!-- <el-row :gutter="20" class="mb8">-->
<!-- <el-col :span="6">-->
<!-- <el-card shadow="hover" class="stat-card" @click.native="handleViewAll">-->
<!-- <div class="stat-content">-->
<!-- <div class="stat-number">{{ statistics.total }}</div>-->
<!-- <div class="stat-label">总申请数</div>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :span="6">-->
<!-- <el-card shadow="hover" class="stat-card" @click.native="handleViewPending">-->
<!-- <div class="stat-content">-->
<!-- <div class="stat-number pending">{{ statistics.pending }}</div>-->
<!-- <div class="stat-label">待审核</div>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :span="6">-->
<!-- <el-card shadow="hover" class="stat-card" @click.native="handleViewApproved">-->
<!-- <div class="stat-content">-->
<!-- <div class="stat-number approved">{{ statistics.approved }}</div>-->
<!-- <div class="stat-label">已通过</div>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :span="6">-->
<!-- <el-card shadow="hover" class="stat-card" @click.native="handleViewRejected">-->
<!-- <div class="stat-content">-->
<!-- <div class="stat-number rejected">{{ statistics.rejected }}</div>-->
<!-- <div class="stat-label">已拒绝</div>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- <el-row :gutter="10" class="mb8"> <!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
@ -99,6 +136,21 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> --> </el-row> -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-check"
size="mini"
:disabled="multiple"
@click="handleBatchAudit"
v-hasPermi="['system:WorkerApply:audit']"
>批量审核</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="WorkerApplyList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="WorkerApplyList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="ID" align="center" width="55" prop="id" /> <el-table-column label="ID" align="center" width="55" prop="id" />
@ -107,9 +159,32 @@
<el-table-column label="电话" align="center" prop="phone" /> <el-table-column label="电话" align="center" prop="phone" />
<el-table-column label="地区" align="center" prop="address" /> <el-table-column label="地区" align="center" prop="address" />
<el-table-column label="状态" align="center" prop="status"> <el-table-column label="技能" align="center" prop="skillId" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.worker_apply_status" :value="scope.row.status"/> <div v-if="scope.row.skillId && scope.row.skillId !== '' && isSkillListReady">
<el-tag
v-for="(skillId, index) in parseSkillIds(scope.row.skillId)"
:key="`skill-${scope.row.id}-${index}`"
size="mini"
type="success"
style="margin: 2px;"
>
{{ getSkillName(skillId) }}
</el-tag>
</div>
<span v-else-if="!isSkillListReady">加载中...</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="120">
<template slot-scope="scope">
<el-tag
:type="getStatusTagType(scope.row.status)"
size="medium"
>
<dict-tag :options="dict.type.worker_apply_status" :value="scope.row.status"/>
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
@ -119,8 +194,30 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button
v-if="scope.row.status === 0"
size="mini"
type="primary"
icon="el-icon-check"
@click="handleAudit(scope.row)"
v-hasPermi="['system:WorkerApply:audit']"
>审核</el-button>
<!-- <el-button-->
<!-- v-if="scope.row.status === 0"-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-view"-->
<!-- @click="handleViewDetail(scope.row)"-->
<!-- >查看</el-button>-->
<!-- <el-button-->
<!-- v-if="scope.row.status !== 1"-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-view"-->
<!-- @click="handleViewDetail(scope.row)"-->
<!-- >查看</el-button>-->
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -154,17 +251,37 @@
:data="form" :data="form"
@confirm="handleEditConfirm" @confirm="handleEditConfirm"
/> />
<!-- 审核对话框组件 -->
<worker-apply-audit
:visible.sync="auditOpen"
:title="auditTitle"
:data="auditForm"
:readonly="auditTitle.includes('查看')"
@confirm="handleAuditConfirm"
/>
<!-- 批量审核对话框组件 -->
<worker-apply-batch-audit
:visible.sync="batchAuditOpen"
:record-ids="ids"
@confirm="handleBatchAuditConfirm"
/>
</div> </div>
</template> </template>
<script> <script>
import { listWorkerApply, getWorkerApply, delWorkerApply, addWorkerApply, updateWorkerApply } from "@/api/system/WorkerApply" import { listWorkerApply, getWorkerApply, delWorkerApply, addWorkerApply, updateWorkerApply, getUserDataList, auditWorkerApply, batchAuditWorkerApply } from "@/api/system/WorkerApply"
import { getSiteSkillList } from "@/api/system/SiteSkill"
import WorkerApplyEdit from './WorkerApplyEdit.vue' import WorkerApplyEdit from './WorkerApplyEdit.vue'
import WorkerApplyAudit from './WorkerApplyAudit.vue'
import WorkerApplyBatchAudit from './WorkerApplyBatchAudit.vue'
import { resetForm } from "@/utils/ruoyi"
export default { export default {
name: "WorkerApply", name: "WorkerApply",
dicts: ['worker_apply_status'], dicts: ['worker_apply_status'],
components: { WorkerApplyEdit }, components: { WorkerApplyEdit, WorkerApplyAudit, WorkerApplyBatchAudit },
data() { data() {
return { return {
// //
@ -199,12 +316,38 @@ export default {
cityIds: null, cityIds: null,
}, },
// //
form: {} form: {},
//
skillList: [],
skillNameCache: {},
//
userDataList: [],
//
auditOpen: false,
auditTitle: '',
auditForm: {},
//
batchAuditOpen: false,
//
statistics: {
total: 0,
pending: 0,
approved: 0,
rejected: 0
}
}
},
computed: {
//
isSkillListReady() {
return this.skillList.length > 0;
} }
}, },
created() { created() {
this.getList() this.getUserDataList()
this.getuserDataList() this.loadSkillList().then(() => {
this.getList()
})
}, },
methods: { methods: {
/** 查询师傅申请记录列表 */ /** 查询师傅申请记录列表 */
@ -214,6 +357,24 @@ export default {
this.WorkerApplyList = response.rows this.WorkerApplyList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
//
this.updateStatistics();
//
console.log('师傅申请记录列表:', this.WorkerApplyList);
this.WorkerApplyList.forEach((item, index) => {
console.log(`记录 ${index}: ID=${item.id}, 技能ID=${item.skillId}, 类型=${typeof item.skillId}`);
if (item.skillId) {
const parsedSkills = this.parseSkillIds(item.skillId);
console.log(`记录 ${index}: 解析后的技能ID数组:`, parsedSkills);
}
});
//
this.$nextTick(() => {
this.forceRefreshSkills();
});
}) })
}, },
// //
@ -232,7 +393,7 @@ export default {
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.resetForm("queryForm") resetForm.call(this, "queryForm")
this.handleQuery() this.handleQuery()
}, },
// //
@ -242,11 +403,113 @@ export default {
this.multiple = !selection.length this.multiple = !selection.length
}, },
getuserDataList(){ getUserDataList(){
getUserDataList("1").then(response => { getUserDataList("1").then(response => {
this.userDataList = response.data this.userDataList = response.data
}) })
}, },
//
loadSkillList() {
console.log('开始加载技能列表...');
return new Promise((resolve) => {
getSiteSkillList().then(response => {
console.log('技能列表API响应:', response);
if (response.code === 200) {
this.skillList = response.data || [];
console.log('技能列表数据:', this.skillList);
this.updateSkillNameCache();
} else {
console.warn('技能列表API返回非200状态:', response.code);
this.useDefaultSkillList();
}
resolve();
}).catch((error) => {
console.error('获取技能列表异常:', error);
this.useDefaultSkillList();
resolve();
});
});
},
// 使
useDefaultSkillList() {
this.skillList = [
{ id: 1, title: '水电工' },
{ id: 2, title: '油工师傅' },
{ id: 3, title: '改造维修' },
{ id: 4, title: '工程施工' }
];
console.log('使用默认技能列表:', this.skillList);
this.updateSkillNameCache();
},
//
updateSkillNameCache() {
this.skillNameCache = {};
this.skillList.forEach(skill => {
this.skillNameCache[skill.id] = skill.title;
});
console.log('技能名称缓存已更新:', this.skillNameCache);
},
// ID
parseSkillIds(skillIdData) {
if (!skillIdData) return [];
try {
// JSON
if (typeof skillIdData === 'string') {
// JSON
if (skillIdData.startsWith('[') && skillIdData.endsWith(']')) {
const parsed = JSON.parse(skillIdData);
return Array.isArray(parsed) ? parsed : [];
}
//
return skillIdData.split(',').filter(id => id.trim());
}
//
if (Array.isArray(skillIdData)) {
return skillIdData;
}
return [];
} catch (error) {
console.error('解析技能ID失败:', error, '原始数据:', skillIdData);
// JSON
if (typeof skillIdData === 'string') {
return skillIdData.split(',').filter(id => id.trim());
}
return [];
}
},
//
getSkillName(skillId) {
if (!skillId) return '-';
// skillId
const id = String(skillId).trim();
if (!id) return '-';
//
let skillName = this.skillNameCache[id];
//
if (!skillName && this.skillList.length > 0) {
const skill = this.skillList.find(s => String(s.id) === id);
if (skill) {
//
this.skillNameCache[id] = skill.title;
skillName = skill.title;
}
}
//
if (!skillName) {
console.log(`未找到技能名称: ID=${id}, 缓存=${JSON.stringify(this.skillNameCache)}`);
return `未知技能(${id})`;
}
return skillName;
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
@ -279,6 +542,11 @@ export default {
}) })
} }
}, },
//
forceRefreshSkills() {
this.$forceUpdate();
},
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids const ids = row.id || this.ids
@ -294,7 +562,158 @@ export default {
this.download('system/WorkerApply/export', { this.download('system/WorkerApply/export', {
...this.queryParams ...this.queryParams
}, `WorkerApply_${new Date().getTime()}.xlsx`) }, `WorkerApply_${new Date().getTime()}.xlsx`)
},
/** 查看详情 */
handleViewDetail(row) {
this.auditForm = row;
this.auditTitle = "查看师傅申请详情";
this.auditOpen = true;
},
/** 审核按钮操作 */
handleAudit(row) {
this.$modal.confirm(`是否确认审核师傅申请记录"${row.name}"`).then(() => {
this.auditForm = row;
this.auditTitle = "审核师傅申请记录";
this.auditOpen = true;
}).catch(() => {});
},
/** 审核确认 */
handleAuditConfirm(formData) {
auditWorkerApply(formData).then(response => {
this.$modal.msgSuccess("审核成功");
this.auditOpen = false;
this.getList();
}).catch(error => {
this.$modal.msgError("审核失败");
});
},
/** 批量审核 */
handleBatchAudit() {
const ids = this.ids;
if (ids.length === 0) {
this.$modal.msgError("请选择要审核的师傅申请记录");
return;
}
this.$modal.confirm(`是否确认批量审核选中的 ${ids.length} 条师傅申请记录?`).then(() => {
this.batchAuditOpen = true;
}).catch(() => {});
},
/** 批量审核确认 */
handleBatchAuditConfirm(auditData) {
batchAuditWorkerApply(auditData).then(response => {
this.$modal.msgSuccess("批量审核成功");
this.batchAuditOpen = false;
this.getList();
}).catch(error => {
this.$modal.msgError("批量审核失败");
});
},
/** 查看待审核 */
handleViewPending() {
this.queryParams.status = 1; //
this.queryParams.pageNum = 1;
this.getList();
},
/** 查看所有 */
handleViewAll() {
this.queryParams.status = null; //
this.queryParams.pageNum = 1;
this.getList();
},
/** 查看已通过 */
handleViewApproved() {
this.queryParams.status = 2; //
this.queryParams.pageNum = 1;
this.getList();
},
/** 查看已拒绝 */
handleViewRejected() {
this.queryParams.status = 3; //
this.queryParams.pageNum = 1;
this.getList();
},
//
getStatusTagType(status) {
switch (status) {
case 1: //
return 'info';
case 2: //
return 'success';
case 3: //
return 'danger';
default:
return 'info';
}
},
//
updateStatistics() {
this.statistics.total = this.WorkerApplyList.length;
this.statistics.pending = this.WorkerApplyList.filter(item => item.status === 1).length;
this.statistics.approved = this.WorkerApplyList.filter(item => item.status === 2).length;
this.statistics.rejected = this.WorkerApplyList.filter(item => item.status === 3).length;
} }
} }
} }
</script> </script>
<style scoped>
.stat-card {
text-align: center;
cursor: pointer;
transition: all 0.3s;
position: relative;
overflow: hidden;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.stat-card:hover::after {
content: '点击查看';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
opacity: 0.9;
}
.stat-content {
padding: 10px;
position: relative;
z-index: 1;
}
.stat-number {
font-size: 28px;
font-weight: bold;
margin-bottom: 8px;
}
.stat-number.pending {
color: #409EFF;
}
.stat-number.approved {
color: #67C23A;
}
.stat-number.rejected {
color: #F56C6C;
}
.stat-label {
font-size: 14px;
color: #606266;
}
.mb8 {
margin-bottom: 20px;
}
</style>