zhouhui.jiang
Showing 30 changed files with 742 additions and 38 deletions
This diff is collapsed. Click to expand it.
package com.apple.erp.config;
import com.apple.erp.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -34,9 +32,6 @@ import java.util.Arrays;
public class SecurityConfig {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
......@@ -72,6 +67,7 @@ public class SecurityConfig {
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/test/public").permitAll() // 允许测试接口
.antMatchers("/api/dashboard/**").authenticated() // 首页统计需要认证
.antMatchers("/actuator/**").permitAll()
.antMatchers("/druid/**").permitAll()
.antMatchers("/swagger-ui/**").permitAll()
......
......@@ -9,6 +9,7 @@ import com.apple.erp.dto.response.UserInfoRes;
import com.apple.erp.entity.SysUser;
import com.apple.erp.service.SysUserService;
import com.apple.erp.service.SysLogService;
import com.apple.erp.service.SessionService;
import com.apple.erp.utils.JwtUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
......@@ -24,7 +25,9 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 认证控制器
......@@ -52,6 +55,9 @@ public class AuthController {
@Autowired
private SysLogService sysLogService;
@Autowired
private SessionService sessionService;
/**
* 用户登录
*/
......@@ -96,6 +102,21 @@ public class AuthController {
String token = jwtUtils.generateToken(username);
String refreshToken = jwtUtils.generateRefreshToken(username);
// 将用户会话信息存储到Redis
try {
Map<String, Object> sessionData = new HashMap<>();
sessionData.put("username", username);
sessionData.put("loginTime", System.currentTimeMillis());
sessionData.put("clientIp", getClientIp(request));
sessionData.put("token", token);
sessionService.storeUserSession(username, sessionData);
log.info("用户会话已存储: {}", username);
} catch (Exception e) {
log.error("存储用户会话失败", e);
// Redis失败不影响登录流程
}
LoginRes loginResponse = new LoginRes(token, refreshToken, username);
ApiRes<LoginRes> response = ApiRes.success("登录成功", loginResponse);
return ResponseEntity.ok(response);
......@@ -192,6 +213,16 @@ public class AuthController {
}
}
// 清除Redis中的用户会话
if (username != null) {
try {
sessionService.removeUserSession(username);
log.info("用户会话已清除: {}", username);
} catch (Exception e) {
log.error("清除用户会话失败", e);
}
}
// 清除Spring Security上下文
SecurityContextHolder.clearContext();
......
package com.apple.erp.controller;
import com.apple.erp.dto.response.ApiRes;
import com.apple.erp.dto.response.DashboardStatsRes;
import com.apple.erp.service.DashboardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 首页仪表板控制器
* 提供首页统计数据接口
*/
@Slf4j
@RestController
@RequestMapping("/api/dashboard")
public class DashboardController {
@Autowired
private DashboardService dashboardService;
/**
* 获取首页统计数据
* @return 统计数据
*/
@GetMapping("/stats")
public ApiRes<DashboardStatsRes> getDashboardStats() {
log.info("获取首页统计数据请求");
try {
DashboardStatsRes result = dashboardService.getDashboardStats();
log.info("首页统计数据获取成功: {}", result);
return ApiRes.success("获取统计数据成功", result);
} catch (Exception e) {
log.error("获取首页统计数据失败", e);
return ApiRes.error(500, "获取统计数据失败: " + e.getMessage());
}
}
/**
* 测试接口
* @return 测试数据
*/
@GetMapping("/test")
public ApiRes<DashboardStatsRes> getTestStats() {
log.info("测试接口调用");
DashboardStatsRes stats = new DashboardStatsRes();
stats.setTodayOrderCount(10);
stats.setPendingDeliveryCount(5);
stats.setPendingInvoiceCount(3);
stats.setTodaySalesAmount(10000.0);
stats.setOnlineUserCount(100);
stats.setSystemStatus("测试正常");
stats.setSystemVersion("v1.0.0");
return ApiRes.success("测试成功", stats);
}
/**
* 获取最近活动
* @return 最近活动列表
*/
@GetMapping("/activities")
public ApiRes<List<Map<String, Object>>> getRecentActivities() {
log.info("获取最近活动请求");
try {
List<Map<String, Object>> activities = dashboardService.getRecentActivities();
return ApiRes.success("获取最近活动成功", activities);
} catch (Exception e) {
log.error("获取最近活动失败", e);
return ApiRes.error(500, "获取最近活动失败: " + e.getMessage());
}
}
}
......@@ -6,12 +6,14 @@ import com.apple.erp.dto.ExceptionWorkorderRes;
import com.apple.erp.dto.ExceptionWorkorderStatusUpdateReq;
import com.apple.erp.dto.ExceptionWorkorderUpdateReq;
import com.apple.erp.service.ExceptionWorkorderService;
import com.apple.erp.service.ExcelExportService;
import com.apple.erp.dto.response.ApiRes;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
......@@ -34,6 +36,9 @@ public class ExceptionWorkorderController {
@Autowired
private ExceptionWorkorderService exceptionWorkorderService;
@Autowired
private ExcelExportService excelExportService;
@Operation(summary = "分页查询异常工单列表", description = "根据条件分页查询异常工单列表")
@GetMapping("/list")
@PreAuthorize("hasAuthority('exception:workorder:list')")
......@@ -168,4 +173,22 @@ public class ExceptionWorkorderController {
List<ExceptionWorkorderRes> stats = exceptionWorkorderService.getExceptionWorkorderStats();
return ApiRes.success(stats);
}
@Operation(summary = "导出异常工单数据", description = "根据查询条件导出异常工单数据到Excel")
@PostMapping("/export")
@PreAuthorize("hasAuthority('exception:workorder:export')")
public ResponseEntity<byte[]> exportExceptionWorkorders(@RequestBody(required = false) ExceptionWorkorderQueryReq queryReq) {
try {
// 如果请求体为空,创建默认查询条件
if (queryReq == null) {
queryReq = new ExceptionWorkorderQueryReq();
}
// 获取异常工单数据
List<ExceptionWorkorderRes> workorders = exceptionWorkorderService.getExceptionWorkorderListForExport(queryReq);
// 导出Excel
return excelExportService.exportExceptionWorkorders(workorders);
} catch (Exception e) {
throw new RuntimeException("导出异常工单数据失败: " + e.getMessage());
}
}
}
......
package com.apple.erp.dto.response;
import lombok.Data;
/**
* 首页统计数据响应DTO
*/
@Data
public class DashboardStatsRes {
/**
* 今日订单数量
*/
private Integer todayOrderCount;
/**
* 待出库数量
*/
private Integer pendingDeliveryCount;
/**
* 待开票数量
*/
private Integer pendingInvoiceCount;
/**
* 今日销售额
*/
private Double todaySalesAmount;
/**
* 在线用户数
*/
private Integer onlineUserCount;
/**
* 系统状态
*/
private String systemStatus;
/**
* 系统版本
*/
private String systemVersion;
/**
* 今日订单增长率
*/
private String orderGrowthRate;
/**
* 今日销售额增长率
*/
private String salesGrowthRate;
}
......@@ -54,4 +54,12 @@ public interface ExceptionWorkorderMapper extends BaseMapper<ExceptionWorkorder>
int batchUpdateWorkorderStatus(@Param("workorderIds") List<Long> workorderIds,
@Param("workorderStatus") Integer workorderStatus,
@Param("handlerUser") String handlerUser);
/**
* 获取异常工单列表用于导出
*
* @param queryReq 查询条件
* @return 异常工单列表(不分页)
*/
List<ExceptionWorkorderRes> selectExceptionWorkorderListForExport(@Param("query") ExceptionWorkorderQueryReq queryReq);
}
......
package com.apple.erp.service;
import com.apple.erp.dto.response.DashboardStatsRes;
import java.util.List;
import java.util.Map;
/**
* 首页仪表板服务接口
*/
public interface DashboardService {
/**
* 获取首页统计数据
* @return 统计数据
*/
DashboardStatsRes getDashboardStats();
/**
* 获取最近活动
* @return 最近活动列表
*/
List<Map<String, Object>> getRecentActivities();
}
......@@ -67,6 +67,20 @@ public interface DeliveryMainService extends IService<DeliveryMain> {
* @return 是否成功
*/
boolean updateDeliveryStatus(Long deliveryId, Integer deliveryStatus);
/**
* 获取待出库数量
* @return 待出库数量
*/
Integer getPendingDeliveryCount();
/**
* 获取最近的出库记录
*
* @param limit 限制数量
* @return 最近出库列表
*/
List<DeliveryRes> getRecentDeliveries(Integer limit);
}
......
......@@ -91,4 +91,12 @@ public interface ExceptionWorkorderService extends IService<ExceptionWorkorder>
* @return 统计信息
*/
List<ExceptionWorkorderRes> getExceptionWorkorderStats();
/**
* 获取异常工单列表用于导出
*
* @param queryReq 查询条件
* @return 异常工单列表(不分页)
*/
List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq);
}
......
......@@ -67,6 +67,20 @@ public interface InvoiceMainService extends IService<InvoiceMain> {
* @return 是否成功
*/
boolean updateInvoiceStatus(Long invoiceId, Integer invoiceStatus);
/**
* 获取待开票数量
* @return 待开票数量
*/
Integer getPendingInvoiceCount();
/**
* 获取最近的发票记录
*
* @param limit 限制数量
* @return 最近发票列表
*/
List<InvoiceRes> getRecentInvoices(Integer limit);
}
......
......@@ -92,5 +92,29 @@ public interface OrderMainService extends IService<OrderMain> {
* @return 是否成功
*/
boolean updateRebateCalcFlag(Long orderId, Integer rebateCalcFlag);
/**
* 获取今日订单数量
*
* @param date 日期
* @return 订单数量
*/
Integer getTodayOrderCount(String date);
/**
* 获取今日销售额
*
* @param date 日期
* @return 销售额
*/
Double getTodaySalesAmount(String date);
/**
* 获取最近的订单记录
*
* @param limit 限制数量
* @return 最近订单列表
*/
List<OrderRes> getRecentOrders(Integer limit);
}
......
......@@ -139,4 +139,12 @@ public interface RebateService extends IService<Rebate> {
* @return 趋势统计数据
*/
List<Map<String, Object>> getRebateTrendStats(String startDate, String endDate);
/**
* 获取最近的返利记录
*
* @param limit 限制数量
* @return 最近返利列表
*/
List<RebateRes> getRecentRebates(Integer limit);
}
......
package com.apple.erp.service;
import java.util.Map;
/**
* 会话管理服务接口
*
* @author Apple ERP Team
* @version 1.0.0
* @since 2024-01-01
*/
public interface SessionService {
/**
* 存储用户会话信息
* @param username 用户名
* @param sessionData 会话数据
*/
void storeUserSession(String username, Map<String, Object> sessionData);
/**
* 获取用户会话信息
* @param username 用户名
* @return 会话数据
*/
Map<String, Object> getUserSession(String username);
/**
* 删除用户会话
* @param username 用户名
*/
void removeUserSession(String username);
/**
* 获取在线用户数
* @return 在线用户数
*/
Integer getOnlineUserCount();
/**
* 清理过期会话
*/
void cleanupExpiredSessions();
}
......@@ -22,6 +22,7 @@ import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
......@@ -254,6 +255,34 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del
return null;
}
}
@Override
public Integer getPendingDeliveryCount() {
LambdaQueryWrapper<DeliveryMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DeliveryMain::getDelFlag, "0")
.eq(DeliveryMain::getDeliveryStatus, 0); // 0表示待出库
return Math.toIntExact(count(wrapper));
}
@Override
public List<DeliveryRes> getRecentDeliveries(Integer limit) {
try {
LambdaQueryWrapper<DeliveryMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DeliveryMain::getDelFlag, "0")
.orderByDesc(DeliveryMain::getCreateTime)
.last("LIMIT " + (limit != null ? limit : 5));
List<DeliveryMain> deliveries = list(wrapper);
return deliveries.stream().map(delivery -> {
DeliveryRes deliveryRes = new DeliveryRes();
BeanUtils.copyProperties(delivery, deliveryRes);
return deliveryRes;
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("获取最近出库记录失败", e);
return new ArrayList<>();
}
}
}
......
......@@ -18,11 +18,9 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* 异常工单Service实现类
......@@ -200,4 +198,10 @@ public class ExceptionWorkorderServiceImpl extends ServiceImpl<ExceptionWorkorde
public List<ExceptionWorkorderRes> getExceptionWorkorderStats() {
return exceptionWorkorderMapper.selectExceptionWorkorderStats();
}
@Override
public List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq) {
// 不分页查询所有数据用于导出
return exceptionWorkorderMapper.selectExceptionWorkorderListForExport(queryReq);
}
}
......
......@@ -21,6 +21,7 @@ import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
......@@ -229,4 +230,31 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi
}
}
@Override
public Integer getPendingInvoiceCount() {
LambdaQueryWrapper<InvoiceMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(InvoiceMain::getDelFlag, "0")
.eq(InvoiceMain::getInvoiceStatus, 0); // 0表示待开票
return Math.toIntExact(count(wrapper));
}
@Override
public List<InvoiceRes> getRecentInvoices(Integer limit) {
try {
LambdaQueryWrapper<InvoiceMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(InvoiceMain::getDelFlag, "0")
.orderByDesc(InvoiceMain::getCreateTime)
.last("LIMIT " + (limit != null ? limit : 5));
List<InvoiceMain> invoices = list(wrapper);
return invoices.stream().map(invoice -> {
InvoiceRes invoiceRes = new InvoiceRes();
BeanUtils.copyProperties(invoice, invoiceRes);
return invoiceRes;
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("获取最近发票记录失败", e);
return new ArrayList<>();
}
}
}
......
......@@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
......@@ -288,5 +289,59 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
order.setUpdateTime(LocalDateTime.now());
return orderMainMapper.updateById(order) > 0;
}
@Override
public Integer getTodayOrderCount(String date) {
try {
LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OrderMain::getDelFlag, "0")
.like(OrderMain::getCreateTime, date);
long count = count(wrapper);
System.out.println("今日订单数量查询结果: " + count + ", 日期: " + date);
return Math.toIntExact(count);
} catch (Exception e) {
System.err.println("查询今日订单数量失败: " + e.getMessage());
return 0;
}
}
@Override
public Double getTodaySalesAmount(String date) {
try {
LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OrderMain::getDelFlag, "0")
.like(OrderMain::getCreateTime, date);
List<OrderMain> orders = list(wrapper);
double totalAmount = orders.stream()
.mapToDouble(order -> order.getTotalAmount() != null ? order.getTotalAmount().doubleValue() : 0.0)
.sum();
System.out.println("今日销售额查询结果: " + totalAmount + ", 日期: " + date);
return totalAmount;
} catch (Exception e) {
System.err.println("查询今日销售额失败: " + e.getMessage());
return 0.0;
}
}
@Override
public List<OrderRes> getRecentOrders(Integer limit) {
try {
LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OrderMain::getDelFlag, "0")
.orderByDesc(OrderMain::getCreateTime)
.last("LIMIT " + (limit != null ? limit : 5));
List<OrderMain> orders = list(wrapper);
return orders.stream().map(order -> {
OrderRes orderRes = new OrderRes();
BeanUtils.copyProperties(order, orderRes);
return orderRes;
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("获取最近订单失败", e);
return new ArrayList<>();
}
}
}
......
......@@ -275,4 +275,24 @@ public class RebateServiceImpl extends ServiceImpl<RebateMapper, Rebate> impleme
log.info("获取返利趋势统计数据,开始日期:{},结束日期:{}", startDate, endDate);
return rebateMapper.getRebateTrendStats(startDate, endDate);
}
@Override
public List<RebateRes> getRecentRebates(Integer limit) {
try {
LambdaQueryWrapper<Rebate> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Rebate::getDelFlag, "0")
.orderByDesc(Rebate::getCreateTime)
.last("LIMIT " + (limit != null ? limit : 5));
List<Rebate> rebates = list(wrapper);
return rebates.stream().map(rebate -> {
RebateRes rebateRes = new RebateRes();
BeanUtils.copyProperties(rebate, rebateRes);
return rebateRes;
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("获取最近返利记录失败", e);
return new ArrayList<>();
}
}
}
......
package com.apple.erp.service.impl;
import com.apple.erp.service.SessionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 会话管理服务实现
*
* @author Apple ERP Team
* @version 1.0.0
* @since 2024-01-01
*/
@Slf4j
@Service
public class SessionServiceImpl implements SessionService {
private static final String SESSION_KEY_PREFIX = "user:session:";
private static final long SESSION_TIMEOUT = 1800; // 30分钟
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void storeUserSession(String username, Map<String, Object> sessionData) {
try {
String sessionKey = SESSION_KEY_PREFIX + username;
redisTemplate.opsForValue().set(sessionKey, sessionData, SESSION_TIMEOUT);
log.debug("用户会话已存储: {}", username);
} catch (Exception e) {
log.error("存储用户会话失败: {}", username, e);
}
}
@Override
public Map<String, Object> getUserSession(String username) {
try {
String sessionKey = SESSION_KEY_PREFIX + username;
Object sessionData = redisTemplate.opsForValue().get(sessionKey);
if (sessionData instanceof Map) {
return (Map<String, Object>) sessionData;
}
} catch (Exception e) {
log.error("获取用户会话失败: {}", username, e);
}
return new HashMap<>();
}
@Override
public void removeUserSession(String username) {
try {
String sessionKey = SESSION_KEY_PREFIX + username;
redisTemplate.delete(sessionKey);
log.debug("用户会话已删除: {}", username);
} catch (Exception e) {
log.error("删除用户会话失败: {}", username, e);
}
}
@Override
public Integer getOnlineUserCount() {
try {
String pattern = SESSION_KEY_PREFIX + "*";
Set<String> sessionKeys = redisTemplate.keys(pattern);
if (sessionKeys != null) {
int onlineCount = sessionKeys.size();
log.debug("当前在线用户数: {}", onlineCount);
return onlineCount;
} else {
log.warn("Redis中未找到用户会话数据");
return 0;
}
} catch (Exception e) {
log.error("获取在线用户数失败", e);
return 0;
}
}
@Override
@Scheduled(fixedRate = 300000) // 每5分钟执行一次
public void cleanupExpiredSessions() {
try {
String pattern = SESSION_KEY_PREFIX + "*";
Set<String> sessionKeys = redisTemplate.keys(pattern);
if (sessionKeys != null) {
int cleanedCount = 0;
for (String sessionKey : sessionKeys) {
// Redis会自动清理过期的key,这里可以添加额外的清理逻辑
// 比如检查会话的最后活动时间等
cleanedCount++;
}
log.debug("会话清理完成,检查了 {} 个会话", cleanedCount);
}
} catch (Exception e) {
log.error("清理过期会话失败", e);
}
}
}
......@@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 系统菜单Service实现类
......@@ -77,7 +76,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
wrapper.eq(SysMenu::getDelFlag, "0");
// 排序:按父菜单ID和排序号升序
wrapper.orderByAsc(SysMenu::getParentId, SysMenu::getSort);
wrapper.orderByAsc(SysMenu::getParentId).orderByAsc(SysMenu::getSort);
return wrapper;
}
......
......@@ -198,33 +198,6 @@ public class DictValueConverter {
}
}
/**
* 加载指定字典类型到Redis
*/
private static void loadDictToRedis(String dictType) {
if (staticDictItemService == null) {
return;
}
try {
// 根据字典类型获取字典项
List<SysDictItem> dictItems = staticDictItemService.getDictItemsByType(dictType);
Map<String, String> mapping = new HashMap<>();
for (SysDictItem item : dictItems) {
if (item.getDelFlag() == null || "0".equals(item.getDelFlag())) {
mapping.put(item.getDictValue(), item.getDictLabel());
}
}
// 存储到Redis
String cacheKey = DICT_CACHE_PREFIX + dictType;
staticRedisTemplate.opsForValue().set(cacheKey, mapping, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
} catch (Exception e) {
System.err.println("加载字典到Redis失败: " + e.getMessage());
}
}
/**
* 根据字典类型ID获取字典类型编码
......
......@@ -150,4 +150,76 @@
AND del_flag = '0'
</update>
<!-- 获取异常工单列表用于导出 -->
<select id="selectExceptionWorkorderListForExport" resultType="com.apple.erp.dto.ExceptionWorkorderRes">
SELECT
ew.workorder_id,
ew.workorder_no,
ew.order_no,
ew.dealer_code,
ew.dealer_name,
ew.exception_type,
CASE ew.exception_type
WHEN 1 THEN '逻辑验证异常'
WHEN 2 THEN '源头验证异常'
WHEN 3 THEN '交叉验证异常'
ELSE '未知类型'
END AS exception_type_name,
ew.severity_level,
CASE ew.severity_level
WHEN 1 THEN '高'
WHEN 2 THEN '中'
WHEN 3 THEN '低'
ELSE '未知'
END AS severity_level_name,
ew.workorder_status,
CASE ew.workorder_status
WHEN 1 THEN '待处理'
WHEN 2 THEN '处理中'
WHEN 3 THEN '已解决'
WHEN 4 THEN '已关闭'
ELSE '未知状态'
END AS workorder_status_name,
ew.exception_desc,
ew.handler_user,
ew.create_by,
ew.create_time,
ew.update_time
FROM t_exception_workorder ew
<where>
ew.del_flag = '0'
<if test="query.workorderNo != null and query.workorderNo != ''">
AND ew.workorder_no LIKE CONCAT('%', #{query.workorderNo}, '%')
</if>
<if test="query.orderNo != null and query.orderNo != ''">
AND ew.order_no LIKE CONCAT('%', #{query.orderNo}, '%')
</if>
<if test="query.dealerCode != null and query.dealerCode != ''">
AND ew.dealer_code = #{query.dealerCode}
</if>
<if test="query.dealerName != null and query.dealerName != ''">
AND ew.dealer_name LIKE CONCAT('%', #{query.dealerName}, '%')
</if>
<if test="query.workorderStatus != null">
AND ew.workorder_status = #{query.workorderStatus}
</if>
<if test="query.exceptionType != null">
AND ew.exception_type = #{query.exceptionType}
</if>
<if test="query.severityLevel != null">
AND ew.severity_level = #{query.severityLevel}
</if>
<if test="query.handlerUser != null and query.handlerUser != ''">
AND ew.handler_user LIKE CONCAT('%', #{query.handlerUser}, '%')
</if>
<if test="query.startTime != null">
AND ew.create_time >= #{query.startTime}
</if>
<if test="query.endTime != null">
AND ew.create_time &lt;= #{query.endTime}
</if>
</where>
ORDER BY ew.create_time DESC
</select>
</mapper>
......
import { request } from '@/utils/request'
/**
* 首页统计数据响应接口
*/
export interface DashboardStats {
todayOrderCount: number
pendingDeliveryCount: number
pendingInvoiceCount: number
todaySalesAmount: number
onlineUserCount: number
systemStatus: string
systemVersion: string
orderGrowthRate: string
salesGrowthRate: string
}
export interface RecentActivity {
id: number
type: string
title: string
time: string
}
/**
* 首页API
*/
export const dashboardApi = {
/**
* 获取首页统计数据
*/
getDashboardStats: (): Promise<DashboardStats> => {
return request.get('/api/dashboard/stats')
},
/**
* 获取最近活动
*/
getRecentActivities: (): Promise<RecentActivity[]> => {
return request.get('/api/dashboard/activities')
},
/**
* 获取测试数据
*/
getTestStats: (): Promise<DashboardStats> => {
return request.get('/api/dashboard/test')
}
}
export default dashboardApi
......@@ -146,6 +146,13 @@ export const exceptionWorkorderApi = {
// 获取异常工单统计信息
getExceptionWorkorderStats: () => {
return request.get('/api/exception-workorder/stats')
},
// 导出异常工单数据
exportExceptionWorkorders: (params: ExceptionWorkorderQueryReq) => {
return request.post('/api/exception-workorder/export', params, {
responseType: 'blob'
})
}
}
......
......@@ -32,6 +32,8 @@ export interface RebateSearchParams {
productCode?: string
operateType?: number
calcFlag?: number
auditStatus?: number
dataSource?: string
rebateStartDate?: string
rebateEndDate?: string
}
......
This diff is collapsed. Click to expand it.
......@@ -734,8 +734,38 @@ const handleBatchProcess = () => {
}
// 导出
const handleExport = () => {
ElMessage.info('导出功能开发中...')
const handleExport = async () => {
try {
await ElMessageBox.confirm('确定要导出异常工单数据吗?', '确认导出', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
ElMessage.info('正在导出数据,请稍候...')
const response = await exceptionWorkorderApi.exportExceptionWorkorders(searchParams.value)
// 创建下载链接
const blob = new Blob([response as unknown as BlobPart], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `异常工单数据_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.xlsx`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
ElMessage.success('导出成功')
} catch (error: any) {
if (error !== 'cancel') {
console.error('导出失败:', error)
ElMessage.error('导出失败: ' + (error?.message || '未知错误'))
}
}
}
// 提交新增
......
This diff is collapsed. Click to expand it.