springboot2.* 普通utils类调用service接口/mapper接口,解决方案

本文介绍了一种在SpringBoot项目中解决普通工具类无法自动注入的问题的方法。通过创建一个实现了ApplicationContextAware接口的BeanContext类来获取Spring容器中的Bean实例,进而实现在多线程或定时任务中调用Service层接口更新数据库的功能。

问题描述:

在springboot 开发中,需要在utils和多线程中使用mapper/Service接口,将数据写入mysql数据库。 普通工具类中自动注入失败。

网上给的方案使用@Component注解,多次尝试后失败,于是使用了别的方案。 详情下方两段代码

 

解决方案: 新建BeanContext 类实现springframework的ApplicationContextAware类

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @Author: louis
 * @Date: 2019/4/17 下午1:51
 */

@Component
public class BeanContext implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanContext.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T)applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clz) throws BeansException {
        return (T)applicationContext.getBean(clz);
    }
}

在普通类中使用方法:

/**
 * @Author: louis
 * @Date: 2019/6/24 下午7:12
 *代码段取自一个调度job 使用spring cron调度es统计数据写入mysql
  *调用mapper接口  注入
*private CoreService coreService;
*this.coreService=BeanContext.getApplicationContext().getBean(CoreService.class);
 */
public class EsFlowCountByIpJob {

    //第一步:注入CoreService接口
    private CoreService coreService;

    //第二步:在方法中getBean

    public void esFlowCount(){
    
   this.coreService=BeanContext.getApplicationContext().getBean(CoreService.class);

    //第三步:实现业务逻辑,这里我调用了coreService的updateFlowCount方法,更新数据库数据
   coreService.updateFlowCount(to_client,to_server,update_time);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试可以正常调用,解决问题。

import com.ruoyi.merchant.RuoYiMerchantApplication; import com.ruoyi.merchant.service.RegisterService; import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.system.api.SysDeptRemoteService; import com.ruoyi.system.api.domain.SysUser; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; @SpringBootTest(classes = RuoYiMerchantApplication.class) public class LzbTest { @Resource private RegisterService registerService; @Resource private SysDeptRemoteService sysDeptRemoteService; @Resource private RemoteUserService remoteUserService; @Test public void selectBy(){ SysUser byUser = sysDeptRemoteService.findByUser("ry", "inner"); System.out.println(byUser); } } package com.ruoyi.system.api; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysUser; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; @FeignClient("ruoyi-system") public interface SysDeptRemoteService { @GetMapping("/dept/select") SysDept selectByName(@RequestParam("deptName") String deptName); @GetMapping("/user/findByUserName") SysUser findByUser(@RequestParam("userName") String userName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); } package com.ruoyi.system.controller; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import com.ruoyi.common.core.constant.SecurityConstants; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.InnerAuth; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysPermissionService; import com.ruoyi.system.service.ISysPostService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; /** * 用户信息 * * @author ruoyi */ @RestController @RequestMapping("/user") public class SysUserController extends BaseController { @Autowired private ISysUserService userService; @Autowired private ISysRoleService roleService; @Autowired private ISysDeptService deptService; @Autowired private ISysPostService postService; @Autowired private ISysPermissionService permissionService; @Autowired private ISysConfigService configService; @Autowired private TokenService tokenService; /** * 获取用户列表 */ @RequiresPermissions("system:user:list") @GetMapping("/list") public TableDataInfo list(SysUser user) { startPage(); List<SysUser> list = userService.selectUserList(user); return getDataTable(list); } @Log(title = "用户管理", businessType = BusinessType.EXPORT) @RequiresPermissions("system:user:export") @PostMapping("/export") public void export(HttpServletResponse response, SysUser user) { List<SysUser> list = userService.selectUserList(user); ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); util.exportExcel(response, list, "用户数据"); } @Log(title = "用户管理", businessType = BusinessType.IMPORT) @RequiresPermissions("system:user:import") @PostMapping("/importData") public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); List<SysUser> userList = util.importExcel(file.getInputStream()); String operName = SecurityUtils.getUsername(); String message = userService.importUser(userList, updateSupport, operName); return success(message); } @PostMapping("/importTemplate") public void importTemplate(HttpServletResponse response) throws IOException { ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); util.importTemplateExcel(response, "用户数据"); } /** * 获取当前用户信息 */ @InnerAuth @GetMapping("/info/{username}") public R<LoginUser> info(@PathVariable("username") String username) { SysUser sysUser = userService.selectUserByUserName(username); if (StringUtils.isNull(sysUser)) { return R.fail("用户名或密码错误"); } // 角色集合 Set<String> roles = permissionService.getRolePermission(sysUser); // 权限集合 Set<String> permissions = permissionService.getMenuPermission(sysUser); LoginUser sysUserVo = new LoginUser(); sysUserVo.setSysUser(sysUser); sysUserVo.setRoles(roles); sysUserVo.setPermissions(permissions); return R.ok(sysUserVo); } @InnerAuth @GetMapping("/select/{username}") public SysUser selectUser(@PathVariable("username") String username) { return userService.selectUserByUserName(username); } /** * 注册用户信息 */ @InnerAuth @PostMapping("/register") public R<Boolean> register(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source, @RequestHeader(value = "clientType", required = false) String clientType) { sysUser.setClientType(clientType); // 记录端型 // 区分端型,处理角色和审核 if (SecurityConstants.CLIENT_TYPE_MERCHANT.equals(clientType)) { sysUser.setAuditStatus("0"); // 商家端:待审核 sysUser.setStatus("1"); // 禁用(审核通过前不可登录) } else if (SecurityConstants.CLIENT_TYPE_USER.equals(clientType)) { sysUser.setAuditStatus("1"); // 用户端:直接通过 sysUser.setStatus("0"); // 启用 } // 按端型分配角色 assignRoleByClientType(sysUser); // 原有注册逻辑 return R.ok(userService.registerUser(sysUser)); } /** * 按端型分配角色 */ private void assignRoleByClientType(SysUser user) { if (SecurityConstants.CLIENT_TYPE_USER.equals(user.getClientType())) { user.setRoleIds(new Long[]{2L}); } else if (SecurityConstants.CLIENT_TYPE_MERCHANT.equals(user.getClientType())) { user.setRoleIds(new Long[]{4L}); } } /** *记录用户登录IP地址和登录时间 */ @InnerAuth @PutMapping("/recordlogin") public R<Boolean> recordlogin(@RequestBody SysUser sysUser) { return R.ok(userService.updateLoginInfo(sysUser)); } /** * 获取用户信息 * * @return 用户信息 */ @GetMapping("getInfo") public AjaxResult getInfo() { LoginUser loginUser = SecurityUtils.getLoginUser(); SysUser user = loginUser.getSysUser(); // 角色集合 Set<String> roles = permissionService.getRolePermission(user); // 权限集合 Set<String> permissions = permissionService.getMenuPermission(user); if (!loginUser.getPermissions().equals(permissions)) { loginUser.setPermissions(permissions); tokenService.refreshToken(loginUser); } AjaxResult ajax = AjaxResult.success(); ajax.put("user", user); ajax.put("roles", roles); ajax.put("permissions", permissions); ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate())); ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate())); return ajax; } // 检查初始密码是否提醒修改 public boolean initPasswordIsModify(Date pwdUpdateDate) { Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify")); return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null; } // 检查密码是否过期 public boolean passwordIsExpiration(Date pwdUpdateDate) { Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays")); if (passwordValidateDays != null && passwordValidateDays > 0) { if (StringUtils.isNull(pwdUpdateDate)) { // 如果从未修改过初始密码,直接提醒过期 return true; } Date nowDate = DateUtils.getNowDate(); return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays; } return false; } /** * 根据用户编号获取详细信息 */ @RequiresPermissions("system:user:query") @GetMapping(value = { "/", "/{userId}" }) public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { AjaxResult ajax = AjaxResult.success(); if (StringUtils.isNotNull(userId)) { userService.checkUserDataScope(userId); SysUser sysUser = userService.selectUserById(userId); ajax.put(AjaxResult.DATA_TAG, sysUser); ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); } List<SysRole> roles = roleService.selectRoleAll(); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll()); return ajax; } /** * 新增用户 */ @RequiresPermissions("system:user:add") @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@Validated @RequestBody SysUser user) { deptService.checkDeptDataScope(user.getDeptId()); roleService.checkRoleDataScope(user.getRoleIds()); if (!userService.checkUserNameUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setCreateBy(SecurityUtils.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); return toAjax(userService.insertUser(user)); } /** * 修改用户 */ @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@Validated @RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); deptService.checkDeptDataScope(user.getDeptId()); roleService.checkRoleDataScope(user.getRoleIds()); if (!userService.checkUserNameUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUser(user)); } /** * 删除用户 */ @RequiresPermissions("system:user:remove") @Log(title = "用户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{userIds}") public AjaxResult remove(@PathVariable Long[] userIds) { if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { return error("当前用户不能删除"); } return toAjax(userService.deleteUserByIds(userIds)); } /** * 重置密码 */ @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/resetPwd") public AjaxResult resetPwd(@RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.resetPwd(user)); } /** * 状态修改 */ @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public AjaxResult changeStatus(@RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUserStatus(user)); } /** * 根据用户编号获取授权角色 */ @RequiresPermissions("system:user:query") @GetMapping("/authRole/{userId}") public AjaxResult authRole(@PathVariable("userId") Long userId) { AjaxResult ajax = AjaxResult.success(); SysUser user = userService.selectUserById(userId); List<SysRole> roles = roleService.selectRolesByUserId(userId); ajax.put("user", user); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); return ajax; } /** * 用户授权角色 */ @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.GRANT) @PutMapping("/authRole") public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { userService.checkUserDataScope(userId); roleService.checkRoleDataScope(roleIds); userService.insertUserAuth(userId, roleIds); return success(); } /** * 获取部门树列表 */ @RequiresPermissions("system:user:list") @GetMapping("/deptTree") public AjaxResult deptTree(SysDept dept) { return success(deptService.selectDeptTreeList(dept)); } @GetMapping("/queryByPhone") public R<LoginUser> getUserInfoByPhone(@RequestParam("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) { // 1. 校验手机号格式 if (!StringUtils.isMobile(phone)) { return R.fail("手机号格式错误"); } // 2. 调用 Service 层查询用户 SysUser sysUser = userService.findUserByPhonenumber(phone); if (sysUser == null) { return R.fail("用户不存在"); } LoginUser loginUser = new LoginUser(); loginUser.setSysUser(sysUser); System.out.println(sysUser); return R.ok(loginUser); } @InnerAuth @GetMapping("/findByUserName") public SysUser findByUser(@RequestParam("userName") String userName){ return userService.findUserByUserName(userName); } } package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import javax.annotation.Resource; import javax.validation.Validator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.bean.BeanValidators; import com.ruoyi.common.datascope.annotation.DataScope; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.domain.SysPost; import com.ruoyi.system.domain.SysUserPost; import com.ruoyi.system.domain.SysUserRole; import com.ruoyi.system.mapper.SysPostMapper; import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.mapper.SysUserPostMapper; import com.ruoyi.system.mapper.SysUserRoleMapper; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysUserService; /** * 用户 业务层处理 * * @author ruoyi */ @Service public class SysUserServiceImpl implements ISysUserService { private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); @Resource private SysUserMapper userMapper; @Resource private SysRoleMapper roleMapper; @Resource private SysPostMapper postMapper; @Resource private SysUserRoleMapper userRoleMapper; @Resource private SysUserPostMapper userPostMapper; @Resource private ISysConfigService configService; @Resource private ISysDeptService deptService; @Resource protected Validator validator; /** * 根据条件分页查询用户列表 * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") public List<SysUser> selectUserList(SysUser user) { return userMapper.selectUserList(user); } /** * 根据条件分页查询已分配用户角色列表 * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") public List<SysUser> selectAllocatedList(SysUser user) { return userMapper.selectAllocatedList(user); } /** * 根据条件分页查询未分配用户角色列表 * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") public List<SysUser> selectUnallocatedList(SysUser user) { return userMapper.selectUnallocatedList(user); } /** * 通过用户名查询用户 * * @param userName 用户名 * @return 用户对象信息 */ @Override public SysUser selectUserByUserName(String userName) { return userMapper.selectUserByUserName(userName); } /** * 通过用户ID查询用户 * * @param userId 用户ID * @return 用户对象信息 */ @Override public SysUser selectUserById(Long userId) { return userMapper.selectUserById(userId); } /** * 查询用户所属角色组 * * @param userName 用户名 * @return 结果 */ @Override public String selectUserRoleGroup(String userName) { List<SysRole> list = roleMapper.selectRolesByUserName(userName); if (CollectionUtils.isEmpty(list)) { return StringUtils.EMPTY; } return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); } /** * 查询用户所属岗位组 * * @param userName 用户名 * @return 结果 */ @Override public String selectUserPostGroup(String userName) { List<SysPost> list = postMapper.selectPostsByUserName(userName); if (CollectionUtils.isEmpty(list)) { return StringUtils.EMPTY; } return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); } /** * 校验用户名称是否唯一 * * @param user 用户信息 * @return 结果 */ @Override public boolean checkUserNameUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); SysUser info = userMapper.checkUserNameUnique(user.getUserName()); if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; } /** * 校验手机号码是否唯一 * * @param user 用户信息 * @return */ @Override public boolean checkPhoneUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; } /** * 校验email是否唯一 * * @param user 用户信息 * @return */ @Override public boolean checkEmailUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); SysUser info = userMapper.checkEmailUnique(user.getEmail()); if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; } /** * 校验用户是否允许操作 * * @param user 用户信息 */ @Override public void checkUserAllowed(SysUser user) { if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) { throw new ServiceException("不允许操作超级管理员用户"); } } /** * 校验用户是否有数据权限 * * @param userId 用户id */ @Override public void checkUserDataScope(Long userId) { if (!SysUser.isAdmin(SecurityUtils.getUserId())) { SysUser user = new SysUser(); user.setUserId(userId); List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user); if (StringUtils.isEmpty(users)) { throw new ServiceException("没有权限访问用户数据!"); } } } /** * 新增保存用户信息 * * @param user 用户信息 * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int insertUser(SysUser user) { // 新增用户信息 int rows = userMapper.insertUser(user); // 新增用户岗位关联 insertUserPost(user); // 新增用户与角色管理 insertUserRoleByUser(user); return rows; } /** * 注册用户信息 * * @param user 用户信息 * @return 结果 */ @Override public boolean registerUser(SysUser user) { userMapper.insertUser(user); Long userId = user.getUserId(); Long roleId = user.getRoleId(); SysUserRole sysUserRole = new SysUserRole(); sysUserRole.setUserId(userId); sysUserRole.setRoleId(roleId); List<SysUserRole> userRoleList = new ArrayList<>(); userRoleList.add(sysUserRole); int i = userRoleMapper.batchUserRole(userRoleList); return i >= 1; } /** * 修改保存用户信息 * * @param user 用户信息 * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int updateUser(SysUser user) { Long userId = user.getUserId(); // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); // 新增用户与角色管理 insertUserRole(userId, user.getRoleIds()); // 删除用户与岗位关联 userPostMapper.deleteUserPostByUserId(userId); // 新增用户与岗位管理 insertUserPost(user); return userMapper.updateUser(user); } /** * 用户授权角色 * * @param userId 用户ID * @param roleIds 角色组 */ @Override @Transactional(rollbackFor = Exception.class) public void insertUserAuth(Long userId, Long[] roleIds) { userRoleMapper.deleteUserRoleByUserId(userId); insertUserRole(userId, roleIds); } /** * 修改用户状态 * * @param user 用户信息 * @return 结果 */ @Override public int updateUserStatus(SysUser user) { return userMapper.updateUserStatus(user.getUserId(), user.getStatus()); } /** * 修改用户基本信息 * * @param user 用户信息 * @return 结果 */ @Override public boolean updateUserProfile(SysUser user) { return userMapper.updateUser(user) > 0; } /** * 修改用户头像 * * @param userId 用户ID * @param avatar 头像地址 * @return 结果 */ @Override public boolean updateUserAvatar(Long userId, String avatar) { return userMapper.updateUserAvatar(userId, avatar) > 0; } /** * 更新用户登录信息(IP和登录时间) * * @param user 用户信息 * @return 结果 */ public boolean updateLoginInfo(SysUser user) { return userMapper.updateLoginInfo(user) > 0; } /** * 重置用户密码 * * @param user 用户信息 * @return 结果 */ @Override public int resetPwd(SysUser user) { return userMapper.resetUserPwd(user.getUserId(), user.getPassword()); } /** * 重置用户密码 * * @param userId 用户ID * @param password 密码 * @return 结果 */ @Override public int resetUserPwd(Long userId, String password) { return userMapper.resetUserPwd(userId, password); } /** * 新增用户角色信息(通过SysUser对象) */ public void insertUserRoleByUser(SysUser user) { this.insertUserRole(user.getUserId(), user.getRoleIds()); } /** * 新增用户岗位信息 * * @param user 用户对象 */ public void insertUserPost(SysUser user) { Long[] posts = user.getPostIds(); if (StringUtils.isNotEmpty(posts)) { // 新增用户与岗位管理 List<SysUserPost> list = new ArrayList<SysUserPost>(); for (Long postId : posts) { SysUserPost up = new SysUserPost(); up.setUserId(user.getUserId()); up.setPostId(postId); list.add(up); } userPostMapper.batchUserPost(list); } } /** * 新增用户角色信息(接收用户ID和角色ID数组) */ public void insertUserRole(Long userId, Long[] roleIds) { if (StringUtils.isNotEmpty(roleIds)) { // 新增用户与角色管理 List<SysUserRole> list = new ArrayList<SysUserRole>(); for (Long roleId : roleIds) { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); list.add(ur); } userRoleMapper.batchUserRole(list); } } /** * 通过用户ID删除用户 * * @param userId 用户ID * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int deleteUserById(Long userId) { // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); // 删除用户与岗位表 userPostMapper.deleteUserPostByUserId(userId); return userMapper.deleteUserById(userId); } /** * 批量删除用户信息 * * @param userIds 需要删除的用户ID * @return 结果 */ @Override @Transactional(rollbackFor = Exception.class) public int deleteUserByIds(Long[] userIds) { for (Long userId : userIds) { checkUserAllowed(new SysUser(userId)); checkUserDataScope(userId); } // 删除用户与角色关联 userRoleMapper.deleteUserRole(userIds); // 删除用户与岗位关联 userPostMapper.deleteUserPost(userIds); return userMapper.deleteUserByIds(userIds); } /** * 导入用户数据 * * @param userList 用户数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 * @param operName 操作用户 * @return 结果 */ @Override public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) { if (StringUtils.isNull(userList) || userList.size() == 0) { throw new ServiceException("导入用户数据不能为空!"); } int successNum = 0; int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); for (SysUser user : userList) { try { // 验证是否存在这个用户 SysUser u = userMapper.selectUserByUserName(user.getUserName()); if (StringUtils.isNull(u)) { BeanValidators.validateWithException(validator, user); deptService.checkDeptDataScope(user.getDeptId()); String password = configService.selectConfigByKey("sys.user.initPassword"); user.setPassword(SecurityUtils.encryptPassword(password)); user.setCreateBy(operName); userMapper.insertUser(user); successNum++; successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功"); } else if (isUpdateSupport) { BeanValidators.validateWithException(validator, user); checkUserAllowed(u); checkUserDataScope(u.getUserId()); deptService.checkDeptDataScope(user.getDeptId()); user.setUserId(u.getUserId()); user.setDeptId(u.getDeptId()); user.setUpdateBy(operName); userMapper.updateUser(user); successNum++; successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功"); } else { failureNum++; failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在"); } } catch (Exception e) { failureNum++; String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); log.error(msg, e); } } if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); } else { successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); } return successMsg.toString(); } @Override public SysUser findUserByPhonenumber(String phonenumber) { return userMapper.selectUserByPhonenumber(phonenumber); } @Override public SysUser findUserByUserName(String userName) { return userMapper.selectUserByUserName(userName); } } package com.ruoyi.system.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; import com.ruoyi.system.api.domain.SysUser; /** * 用户表 数据层 * * @author ruoyi */ public interface SysUserMapper { /** * 根据条件分页查询用户列表 * * @param sysUser 用户信息 * @return 用户信息集合信息 */ public List<SysUser> selectUserList(SysUser sysUser); /** * 根据条件分页查询已配用户角色列表 * * @param user 用户信息 * @return 用户信息集合信息 */ public List<SysUser> selectAllocatedList(SysUser user); /** * 根据条件分页查询未分配用户角色列表 * * @param user 用户信息 * @return 用户信息集合信息 */ public List<SysUser> selectUnallocatedList(SysUser user); /** * 通过用户名查询用户 * * @param userName 用户名 * @return 用户对象信息 */ public SysUser selectUserByUserName(String userName); /** * 通过用户ID查询用户 * * @param userId 用户ID * @return 用户对象信息 */ public SysUser selectUserById(Long userId); /** * 新增用户信息 * * @param user 用户信息 * @return 结果 */ public int insertUser(SysUser user); /** * 修改用户信息 * * @param user 用户信息 * @return 结果 */ public int updateUser(SysUser user); /** * 修改用户头像 * * @param userId 用户ID * @param avatar 头像地址 * @return 结果 */ public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar); /** * 修改用户状态 * * @param userId 用户ID * @param status 状态 * @return 结果 */ public int updateUserStatus(@Param("userId") Long userId, @Param("status") String status); /** * 更新用户登录信息(IP和登录时间) * * @param user 用户信息 * @return 结果 */ public int updateLoginInfo(SysUser user); /** * 重置用户密码 * * @param userId 用户ID * @param password 密码 * @return 结果 */ public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password); /** * 通过用户ID删除用户 * * @param userId 用户ID * @return 结果 */ public int deleteUserById(Long userId); /** * 批量删除用户信息 * * @param userIds 需要删除的用户ID * @return 结果 */ public int deleteUserByIds(Long[] userIds); /** * 校验用户名称是否唯一 * * @param userName 用户名称 * @return 结果 */ public SysUser checkUserNameUnique(String userName); /** * 校验手机号码是否唯一 * * @param phonenumber 手机号码 * @return 结果 */ public SysUser checkPhoneUnique(String phonenumber); /** * 校验email是否唯一 * * @param email 用户邮箱 * @return 结果 */ public SysUser checkEmailUnique(String email); SysUser selectUserByPhonenumber(String phonenumber); } <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.system.mapper.SysUserMapper"> <resultMap type="SysUser" id="SysUserResult"> <id property="userId" column="user_id" /> <result property="deptId" column="dept_id" /> <result property="userName" column="user_name" /> <result property="nickName" column="nick_name" /> <result property="email" column="email" /> <result property="phonenumber" column="phonenumber" /> <result property="sex" column="sex" /> <result property="avatar" column="avatar" /> <result property="password" column="password" /> <result property="status" column="status" /> <result property="delFlag" column="del_flag" /> <result property="loginIp" column="login_ip" /> <result property="loginDate" column="login_date" /> <result property="pwdUpdateDate" column="pwd_update_date" /> <result property="createBy" column="create_by" /> <result property="createTime" column="create_time" /> <result property="updateBy" column="update_by" /> <result property="updateTime" column="update_time" /> <result property="remark" column="remark" /> <association property="dept" javaType="SysDept" resultMap="deptResult" /> <collection property="roles" javaType="java.util.List" resultMap="RoleResult" /> </resultMap> <resultMap id="deptResult" type="SysDept"> <id property="deptId" column="dept_id" /> <result property="parentId" column="parent_id" /> <result property="deptName" column="dept_name" /> <result property="ancestors" column="ancestors" /> <result property="orderNum" column="order_num" /> <result property="leader" column="leader" /> <result property="status" column="dept_status" /> </resultMap> <resultMap id="RoleResult" type="SysRole"> <id property="roleId" column="role_id" /> <result property="roleName" column="role_name" /> <result property="roleKey" column="role_key" /> <result property="roleSort" column="role_sort" /> <result property="dataScope" column="data_scope" /> <result property="status" column="role_status" /> </resultMap> <sql id="selectUserVo"> select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.remark, d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status from sys_user u left join sys_dept d on u.dept_id = d.dept_id left join sys_user_role ur on u.user_id = ur.user_id left join sys_role r on r.role_id = ur.role_id </sql> <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u left join sys_dept d on u.dept_id = d.dept_id where u.del_flag = '0' <if test="userId != null and userId != 0"> AND u.user_id = #{userId} </if> <if test="userName != null and userName != ''"> AND u.user_name like concat('%', #{userName}, '%') </if> <if test="status != null and status != ''"> AND u.status = #{status} </if> <if test="phonenumber != null and phonenumber != ''"> AND u.phonenumber like concat('%', #{phonenumber}, '%') </if> <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 --> AND date_format(u.create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d') </if> <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> AND date_format(u.create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d') </if> <if test="deptId != null and deptId != 0"> AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) )) </if> <!-- 数据范围过滤 --> ${params.dataScope} </select> <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time from sys_user u left join sys_dept d on u.dept_id = d.dept_id left join sys_user_role ur on u.user_id = ur.user_id left join sys_role r on r.role_id = ur.role_id where u.del_flag = '0' and r.role_id = #{roleId} <if test="userName != null and userName != ''"> AND u.user_name like concat('%', #{userName}, '%') </if> <if test="phonenumber != null and phonenumber != ''"> AND u.phonenumber like concat('%', #{phonenumber}, '%') </if> <!-- 数据范围过滤 --> ${params.dataScope} </select> <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult"> select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time from sys_user u left join sys_dept d on u.dept_id = d.dept_id left join sys_user_role ur on u.user_id = ur.user_id left join sys_role r on r.role_id = ur.role_id where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL) and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId}) <if test="userName != null and userName != ''"> AND u.user_name like concat('%', #{userName}, '%') </if> <if test="phonenumber != null and phonenumber != ''"> AND u.phonenumber like concat('%', #{phonenumber}, '%') </if> <!-- 数据范围过滤 --> ${params.dataScope} </select> <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult"> <include refid="selectUserVo"/> where u.user_name = #{userName} and u.del_flag = '0' </select> <select id="selectUserById" parameterType="Long" resultMap="SysUserResult"> <include refid="selectUserVo"/> where u.user_id = #{userId} </select> <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult"> select user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0' limit 1 </select> <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult"> select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} and del_flag = '0' limit 1 </select> <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1 </select> <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId"> insert into sys_user( <if test="userId != null and userId != 0">user_id,</if> <if test="deptId != null and deptId != 0">dept_id,</if> <if test="userName != null and userName != ''">user_name,</if> <if test="nickName != null and nickName != ''">nick_name,</if> <if test="email != null and email != ''">email,</if> <if test="avatar != null and avatar != ''">avatar,</if> <if test="phonenumber != null and phonenumber != ''">phonenumber,</if> <if test="sex != null and sex != ''">sex,</if> <if test="password != null and password != ''">password,</if> <if test="status != null and status != ''">status,</if> <if test="pwdUpdateDate != null">pwd_update_date,</if> <if test="createBy != null and createBy != ''">create_by,</if> <if test="remark != null and remark != ''">remark,</if> create_time )values( <if test="userId != null and userId != ''">#{userId},</if> <if test="deptId != null and deptId != ''">#{deptId},</if> <if test="userName != null and userName != ''">#{userName},</if> <if test="nickName != null and nickName != ''">#{nickName},</if> <if test="email != null and email != ''">#{email},</if> <if test="avatar != null and avatar != ''">#{avatar},</if> <if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if> <if test="sex != null and sex != ''">#{sex},</if> <if test="password != null and password != ''">#{password},</if> <if test="status != null and status != ''">#{status},</if> <if test="pwdUpdateDate != null">#{pwdUpdateDate},</if> <if test="createBy != null and createBy != ''">#{createBy},</if> <if test="remark != null and remark != ''">#{remark},</if> sysdate() ) </insert> <update id="updateUser" parameterType="SysUser"> update sys_user <set> <if test="deptId != 0">dept_id = #{deptId},</if> <if test="nickName != null and nickName != ''">nick_name = #{nickName},</if> <if test="email != null ">email = #{email},</if> <if test="phonenumber != null ">phonenumber = #{phonenumber},</if> <if test="sex != null and sex != ''">sex = #{sex},</if> <if test="avatar != null and avatar != ''">avatar = #{avatar},</if> <if test="password != null and password != ''">password = #{password},</if> <if test="status != null and status != ''">status = #{status},</if> <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if> <if test="loginDate != null">login_date = #{loginDate},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="remark != null">remark = #{remark},</if> update_time = sysdate() </set> where user_id = #{userId} </update> <update id="updateUserStatus" parameterType="SysUser"> update sys_user set status = #{status}, update_time = sysdate() where user_id = #{userId} </update> <update id="updateUserAvatar" parameterType="SysUser"> update sys_user set avatar = #{avatar}, update_time = sysdate() where user_id = #{userId} </update> <update id="updateLoginInfo" parameterType="SysUser"> update sys_user set login_ip = #{loginIp}, login_date = #{loginDate} where user_id = #{userId} </update> <update id="resetUserPwd" parameterType="SysUser"> update sys_user set pwd_update_date = sysdate(), password = #{password}, update_time = sysdate() where user_id = #{userId} </update> <delete id="deleteUserById" parameterType="Long"> update sys_user set del_flag = '2' where user_id = #{userId} </delete> <delete id="deleteUserByIds" parameterType="Long"> update sys_user set del_flag = '2' where user_id in <foreach collection="array" item="userId" open="(" separator="," close=")"> #{userId} </foreach> </delete> <select id="selectUserByPhonenumber" parameterType="java.lang.String" resultType="SysUser"> SELECT * FROM sys_user WHERE phonenumber = #{phonenumber} </select> </mapper> 这个远程调用的测试,为什么返回的全是null
09-19
server: port: 9090 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false&serverTimezone=GMT%2b8 username: root password: root servlet: multipart: enabled: true max-file-size: 10MB max-request-size: 10MB location: ${java.io.tmpdir} # 临时目录 # 日期格式化 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 # Swagger配置 swagger: enabled: true # http://localhost:9090/swagger-ui.html jwt: secretKey: "jieyou" python: path: python # 或 python(Windows 上可能是 py 或 python.exe) app: script: path: src/main/resources/scripts/crawler.py package com.shop.jieyou.controller; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.shop.jieyou.common.Result; import com.shop.jieyou.entity.UserItem; import com.shop.jieyou.service.ItemService; import com.shop.jieyou.service.PythonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 花卉相关接口控制器 * 提供三大功能: * 1. 获取中国十大名花数据(来自爬虫或缓存) * 2. 手动刷新花卉数据(强制重新爬取) * 3. 基于用户行为的花卉推荐(调用Python协同过滤脚本) */ @RestController @CrossOrigin(origins = "*") // 允许所有域访问,用于前端开发试(生产环境建议限制域名) @RequestMapping("/api") public class FlowerController { @Autowired private PythonService pythonService; // 注入业务服务层,处理数据获取与推荐逻辑 @Autowired private ItemService itemService; /** * 接口:GET /api/flowers * 功能:获取“中国十大名花”数据列表 * 数据来源:可能来自数据库、Redis 缓存 或 调用 Python 爬虫脚本 * * @return Result<List<Map<String, Object>>> 返回包含花卉信息的成功响应 */ @GetMapping("/flowers") public Result<List<Map<String, Object>>> getTopTenFlowers() { try { // 调用服务层获取花卉数据(内部可能带缓存机制) List<Map<String, Object>> flowers = pythonService.getFlowers(); return Result.success(flowers); // 成功返回数据 } catch (Exception e) { // 捕获异常并统一返回错误码和消息,避免暴露堆栈给前端 return Result.error("500", "获取花卉数据失败:" + e.getMessage()); } } /** * 接口:POST /api/flowers/refresh * 功能:强制刷新花卉数据缓存,触发重新爬取 * 使用场景:管理员手动更新数据时调用 * * @return Result<Map<String, Object>> 返回刷新结果信息 */ @PostMapping("/flowers/refresh") public Result<Map<String, Object>> refreshData() { try { // TODO: 如果实现了 clearCache 方法,请取消注释并调用 // pythonService.clearCache(); // 清除旧缓存,下次 getFlowers 将重新爬取 // 重新获取最新数据(假设此时会触发爬虫) List<Map<String, Object>> flowers = pythonService.getFlowers(); // 构造返回信息 Map<String, Object> data = new HashMap<>(); data.put("message", "数据已刷新"); data.put("count", flowers.size()); return Result.success(data); } catch (Exception e) { return Result.error("500", "刷新失败:" + e.getMessage()); } } // ========== 推荐系统相关常量定义 ========== /** * 输入文件路径:Java 将用户-商品行为数据写入此 JSON 文件供 Python 脚本读取 * 注意:src/main/resources 是编译后打包进 jar 的资源目录,不适合运行时写入! * 建议改为外部路径如 "./data/input.json" */ private static final String INPUT_PATH = "src/main/resources/scripts/input.json"; /** * 输出文件路径:Python 脚本将推荐结果写入此文件,Java 再读取返回给前端 */ private static final String OUTPUT_PATH = "src/main/resources/scripts/output.json"; /** * Python 协同过滤脚本路径 * 注意:resources 目录下的 .py 文件在打包后无法直接作为可执行脚本运行 * 更佳做法是将脚本放在项目外部或使用 ProcessBuilder 启动独立服务 */ private static final String PYTHON_SCRIPT = "src/main/resources/scripts/collaborative.py"; /** * 接口:GET /api/recommend?userId=123 * 功能:为指定用户生成个性化花卉推荐列表 * 实现方式:Java 查询数据库 → 写入 JSON 文件 → 调用 Python 脚本计算 → 读取结果返回 * * @param userId 用户ID,必填参数 * @return Result<JsonNode> 推荐的商品ID数组(如 [101, 105, 108]) */ @GetMapping("/recommend") public Result recommendFlowers(@RequestParam("userId") Long userId) { try { // 1. 获取用户行为数据 List<UserItem> matrix = pythonService.getUserItemMatrix(); // 2. 调用 Python 脚本(通过 stdin/stdout 通信) ProcessBuilder pb = new ProcessBuilder("python", PYTHON_SCRIPT, String.valueOf(userId)); pb.redirectErrorStream(true); // 合并错误流 Process process = pb.start(); // 3. 将数据写入脚本的标准输入 ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(process.getOutputStream(), matrix); process.getOutputStream().close(); // 关闭输入,通知Python结束读取 // 4. 读取Python脚本的输出(推荐结果) JsonNode result = mapper.readTree(process.getInputStream()); // 5. 等待脚本执行完毕 int exitCode = process.waitFor(); if (exitCode != 0) { return Result.error("500", "Python script failed with exit code: " + exitCode); } System.out.println(result); return Result.success(result); } catch (Exception e) { e.printStackTrace(); return Result.error("500", "推荐生成失败:" + e.getMessage()); } } @PostMapping("/predict") public ResponseEntity<String> predict(@RequestParam("file") MultipartFile file) { try { // 保存上传的文件到临时路径 String tempDir = System.getProperty("java.io.tmpdir"); File tempFile = new File(tempDir, file.getOriginalFilename()); file.transferTo(tempFile); // 调用 Python 脚本执行预测 ProcessBuilder pb = new ProcessBuilder( "D:\\Python\\python.exe", "D:/DevCode/商城/Shop-master/shop-springboot/src/main/resources/scripts/image_classifier.py", "predict", tempFile.getAbsolutePath() ); pb.redirectErrorStream(true); // 合并 stdout 和 stderr Process process = pb.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder output = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { output.append(line); } int exitCode = process.waitFor(); if (exitCode == 0) { return ResponseEntity.ok(output.toString().trim()); } else { return ResponseEntity.status(500).body("{\"error\": \"Prediction failed\"}"); } } catch (Exception e) { return ResponseEntity.status(500).body("{\"error\": \"" + e.getMessage() + "\"}"); } } private static final String PYTHON_EXECUTABLE = "D:\\Python\\python.exe"; // 或 "python3" private static final String INFER_SCRIPT_PATH = "D:/DevCode/商城/Shop-master/shop-springboot/src/main/resources/scripts/python-model/infer.py"; @PostMapping("/uploadPython") public Result<Map<String, Object>> classifyImage(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return Result.error("400", "文件为空"); } try { // 只做参数传递,逻辑交给 Service Map<String, Object> result = pythonService.classify(file); return Result.success(result); } catch (IOException e) { return Result.error("500", "文件处理失败:" + e.getMessage()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return Result.error("500", "处理被中断"); } catch (Exception e) { return Result.error("500", "识别出错:" + e.getMessage()); } } }<template> <div class="animal-classifier"> <el-upload :show-file-list="false" :before-upload="handleFileUpload" :http-request="dummyRequest" accept="image/jpeg,image/png" > <el-button size="large" type="primary">选择图片</el-button> </el-upload> <div v-if="previewImage" class="preview"> <img :src="previewImage" alt="预览图" /> </div> <el-progress v-if="loading" :percentage="progress" status="success" /> <div v-if="result" class="result"> <h3>识别结果:{{ result.predicted_class }}</h3> <p>置信度:{{ result.confidence }}</p> </div> </div> </template> <script> import request from "@/utils/request"; // 确保路径正确,指向你封装的 axios 实例 import { Message } from "element-ui"; export default { data() { return { previewImage: null, loading: false, progress: 0, result: null, }; }, methods: { // 阻止 el-upload 默认上传行为 dummyRequest() { // 不做任何事,由 handleFileUpload 控制上传逻辑 }, async handleFileUpload(file) { const allowedTypes = ["image/jpeg", "image/jpg", "image/png"]; const maxSize = 5 * 1024 * 1024; // 5MB // 校验文件型 if (!allowedTypes.includes(file.type)) { Message.error("仅支持 JPG/PNG 格式!"); return false; } // 校验文件大小 if (file.size > maxSize) { Message.error("图片不能超过 5MB!"); return false; } // 图片预览 const reader = new FileReader(); reader.onload = (e) => { this.previewImage = e.target.result; }; reader.readAsDataURL(file); // 开始上传状态 this.loading = true; this.progress = 0; this.result = null; // 模拟上传进度(真实进度需后端配合 WebSocket 或 Axios onUploadProgress) const interval = setInterval(() => { if (this.progress >= 90) clearInterval(interval); else this.progress += 5; }, 200); // 构造 FormData const formData = new FormData(); formData.append("file", file); // 必须与后端 @RequestParam("file") 名称一致 try { // ✅ 正确方式:不要设置 Content-Type,让浏览器自动添加 boundary const res = await request.post("/api/uploadPython", formData); // 清除模拟进度 clearInterval(interval); this.progress = 100; this.loading = false; // 假设后端返回格式为 { success: true, data: { predicted_class: "...", confidence: "..." } } this.result = res.data; Message.success(`识别完成:${this.result.predicted_class}`); } catch (err) { clearInterval(interval); this.progress = 100; this.loading = false; console.error("上传失败:", err); // 错误已被 request 拦截器处理,也可在此补充提示 Message.error( err.response?.data?.message || "上传失败,请检查服务是否正常" ); } return false; // 阻止 el-upload 再次尝试上传 }, }, }; </script> <style scoped> .animal-classifier { padding: 20px; text-align: center; } .preview img { max-width: 300px; border-radius: 8px; margin-top: 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .result { margin-top: 20px; font-size: 16px; color: #333; } .result h3 { color: #1890ff; } </style> org.springframework.web.multipart.MultipartException: Current request is not a multipart request at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValueInternal(RequestParamMethodArgumentResolver.java:210) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:114) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.24.jar:5.3.24]
最新发布
10-22
package cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApiImpl; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.marketing.controller.admin.aftersalesmanagement.vo.AftersalesManagementSaveReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainPageReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainRespVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainSaveReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainStartFlowReqVO; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.iomanagementmain.IoManagementMainDO; import cn.iocoder.yudao.module.yavwarehouse.service.iomanagementdetail.IoManagementDetailService; import cn.iocoder.yudao.module.yavwarehouse.service.iomanagementmain.IoManagementMainService; 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.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 出入库管理") @RestController @RequestMapping("/yavwarehouse/io-management-main") @Validated public class IoManagementMainController { @Resource private IoManagementMainService ioManagementMainService; @Resource private IoManagementDetailService ioManagementDetailService; @Resource private BpmProcessInstanceApiImpl bpmProcessInstanceApi; // 变更说明: // 1) 参数校验、鉴权保持不变;业务逻辑仍在 Service 层,控制器保持薄。 @PostMapping("/create") @Operation(summary = "创建出入库主") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:create')") public CommonResult<Long> createIoManagementMain(@Valid @RequestBody IoManagementMainSaveReqVO createReqVO) { return success(ioManagementMainService.createIoManagementMain(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新出入库主") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:update')") public CommonResult<Boolean> updateIoManagementMain(@Valid @RequestBody IoManagementMainSaveReqVO updateReqVO) { ioManagementMainService.updateIoManagementMain(updateReqVO); return success(true); } @PostMapping("/approval") @Operation(summary = "审批出入库主") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:approval')") public CommonResult<Boolean> approvalIoManagementMain(@Valid @RequestBody IoManagementMainSaveReqVO updateReqVO) { ioManagementMainService.approvalIoManagementMain(updateReqVO); return success(true); } @DeleteMapping("/delete") @Operation(summary = "删除出入库主") @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:delete')") public CommonResult<Boolean> deleteIoManagementMain(@RequestParam("id") Long id) { ioManagementMainService.deleteIoManagementMain(id); return success(true); } @DeleteMapping("/delete-list") @Parameter(name = "ids", description = "编号", required = true) @Operation(summary = "批量删除出入库主") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:delete')") public CommonResult<Boolean> deleteIoManagementMainList(@RequestParam("ids") List<Long> ids) { ioManagementMainService.deleteIoManagementMainListByIds(ids); return success(true); } @GetMapping("/get") @Operation(summary = "获得出入库主") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:query')") public CommonResult<IoManagementMainRespVO> getIoManagementMain(@RequestParam("id") Long id, @RequestParam(value = "withItems", required = false, defaultValue = "false") boolean withItems) { // 变更:将“查明细与组装”下沉到 Service;Controller 只透传参数 return success(ioManagementMainService.getIoManagementMainWithItems(id, withItems)); } @GetMapping("/page") @Operation(summary = "获得出入库主分页") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:query')") public CommonResult<PageResult<IoManagementMainRespVO>> getIoManagementMainPage(@Valid IoManagementMainPageReqVO pageReqVO) { return success(ioManagementMainService.getIoManagementMainPages(pageReqVO)); } @GetMapping("/export-excel") @Operation(summary = "导出出入库主 Excel") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:export')") @ApiAccessLog(operateType = EXPORT) public void exportIoManagementMainExcel(@Valid IoManagementMainPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); List<IoManagementMainDO> list = ioManagementMainService.getIoManagementMainPage(pageReqVO).getList(); // 导出 Excel ExcelUtils.write(response, "出入库主.xls", "数据", IoManagementMainRespVO.class, BeanUtils.toBean(list, IoManagementMainRespVO.class)); } @GetMapping("/getOrderPage") @Operation(summary = "根据业务型查询单据") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:query')") public CommonResult getOrderPage(@RequestParam String businessType, @RequestParam String businessTypeValue, @RequestParam String applyType, PageParam pageParam) { return success(ioManagementMainService.getOrderPage(businessType, businessTypeValue, applyType, pageParam)); } @PutMapping("/startFlow") @Operation(summary = "发起出入库流程") @PreAuthorize("@ss.hasPermission('yavwarehouse:io-management-main:update')") public CommonResult<Boolean> startFlow(@Valid @RequestBody IoManagementMainStartFlowReqVO reqVO) { Map<String, Object> variables = new HashMap<>(); variables.put("ioId", reqVO.getId()); String processInstanceId = bpmProcessInstanceApi.createProcessInstance(getLoginUserId(), new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey("inbound") .setVariables(variables) .setBusinessKey(String.valueOf(reqVO.getId())) .setStartUserSelectAssignees(reqVO.getNextAssignees())); ioManagementMainService.updateProcessInfo(reqVO.getId(), processInstanceId, "RUNNING"); return success(true); } } package cn.iocoder.yudao.module.yavwarehouse.service.iomanagementmain; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.AuditStateEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.marketing.controller.admin.profilesalesorder.vo.ProfileSalesOrderPageReqVO; import cn.iocoder.yudao.module.marketing.controller.admin.projectsalesorder.vo.ProjectSalesOrderPageReqVO; import cn.iocoder.yudao.module.marketing.controller.admin.salesorder.vo.KreSalesOrderPageReqVO; import cn.iocoder.yudao.module.marketing.dal.dataobject.profilesalesorder.ProfileSalesOrderDO; import cn.iocoder.yudao.module.marketing.dal.dataobject.projectsalesorder.ProjectSalesOrderDO; import cn.iocoder.yudao.module.marketing.dal.dataobject.salesorder.KreSalesOrderDO; import cn.iocoder.yudao.module.marketing.dal.mysql.profilesalesorder.ProfileSalesOrderMapper; import cn.iocoder.yudao.module.marketing.dal.mysql.projectsalesorder.ProjectSalesOrderMapper; import cn.iocoder.yudao.module.marketing.dal.mysql.salesorder.KreSalesOrderMapper; import cn.iocoder.yudao.module.plan.controller.admin.factorymaterials.vo.FactoryMaterialsPageReqVO; import cn.iocoder.yudao.module.plan.controller.admin.fenestrationmanagement.vo.FenestrationManagementPageReqVO; import cn.iocoder.yudao.module.plan.controller.admin.profilecheck.vo.ProfileCheckPageReqVO; import cn.iocoder.yudao.module.plan.dal.dataobject.factorymaterials.FactoryMaterialsDO; import cn.iocoder.yudao.module.plan.dal.dataobject.fenestrationmanagement.FenestrationManagementDO; import cn.iocoder.yudao.module.plan.dal.dataobject.profilecheck.ProfileCheckDO; import cn.iocoder.yudao.module.plan.dal.mysql.factorymaterials.FactoryMaterialsMapper; import cn.iocoder.yudao.module.plan.dal.mysql.fenestrationmanagement.FenestrationManagementMapper; import cn.iocoder.yudao.module.plan.dal.mysql.profilecheck.ProfileCheckMapper; import cn.iocoder.yudao.module.purchase.controller.admin.receipt.vo.ReceiptPageReqVO; import cn.iocoder.yudao.module.purchase.dal.dataobject.material.MaterialDO; import cn.iocoder.yudao.module.purchase.dal.dataobject.materialinventory.MaterialInventoryDO; import cn.iocoder.yudao.module.purchase.dal.dataobject.receipt.ReceiptDO; import cn.iocoder.yudao.module.purchase.dal.mysql.material.MaterialMapper; import cn.iocoder.yudao.module.purchase.dal.mysql.materialinventory.MaterialInventoryMapper; import cn.iocoder.yudao.module.purchase.dal.mysql.receipt.ReceiptMapper; import cn.iocoder.yudao.module.purchase.utils.OrderNoGeneratorUtil; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.inventorydetails.vo.InventoryDetailsSaveReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementdetail.vo.IoManagementDetailRespVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementdetail.vo.IoManagementDetailSaveReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainPageReqVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainRespVO; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.IoManagementMainSaveReqVO; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.inventorydetails.InventoryDetailsDO; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.iomanagementdetail.IoManagementDetailDO; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.iomanagementmain.IoManagementMainDO; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.yavwarehouse.YavWarehouseDO; import cn.iocoder.yudao.module.yavwarehouse.dal.mysql.iomanagementdetail.IoManagementDetailMapper; import cn.iocoder.yudao.module.yavwarehouse.dal.mysql.iomanagementmain.IoManagementMainMapper; import cn.iocoder.yudao.module.yavwarehouse.dal.mysql.yavwarehouse.YavWarehouseMapper; import cn.iocoder.yudao.module.yavwarehouse.enums.BILL_TYPE; import cn.iocoder.yudao.module.yavwarehouse.enums.CostStrategyType; import cn.iocoder.yudao.module.yavwarehouse.enums.YavConstants; import cn.iocoder.yudao.module.yavwarehouse.service.inventorydetails.InventoryDetailsService; import cn.iocoder.yudao.module.yavwarehouse.service.iomanagementdetail.IoManagementDetailService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.datical.liquibase.ext.checks.config.IFileAccessor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.yavwarehouse.enums.ErrorCodeConstants.*; /** * 出入库主 Service 实现 */ @Service @Validated @Slf4j public class IoManagementMainServiceImpl implements IoManagementMainService { @Resource private IoManagementMainMapper ioManagementMainMapper; @Resource private IoManagementDetailService ioManagementDetailService; @Resource private InventoryDetailsService inventoryDetailsService; @Resource private IoManagementDetailMapper ioManagementDetailMapper; @Resource private ProfileCheckMapper profileCheckMapper; @Resource private FenestrationManagementMapper fenestrationManagementMapper; @Resource private FactoryMaterialsMapper factoryMaterialsMapper; @Resource private ReceiptMapper receiptMapper; @Resource private KreSalesOrderMapper kreSalesOrderMapper; @Resource private ProjectSalesOrderMapper projectSalesOrderMapper; @Resource private ProfileSalesOrderMapper profileSalesOrderMapper; @Resource private MaterialInventoryMapper materialInventoryMapper; @Resource private MaterialMapper materialMapper; @Resource private YavWarehouseMapper warehouseMapper; @Override @Transactional(rollbackFor = Exception.class) public Long createIoManagementMain(IoManagementMainSaveReqVO createReqVO) { // 插入主表记录 if (StringUtils.isBlank(createReqVO.getIoBillNo())) { String next = OrderNoGeneratorUtil.next(); if (createReqVO.getIoBillType().equals(BILL_TYPE.OUTBOUND)) { createReqVO.setIoBillNo(BILL_TYPE.CK + "_" + next); } else { createReqVO.setIoBillNo(BILL_TYPE.RK + "_" + next); } } IoManagementMainDO ioManagementMain = BeanUtils.toBean(createReqVO, IoManagementMainDO.class); if (ObjectUtil.equals(createReqVO.getAuditState(), AuditStateEnum.NO.getStatus())) { checkSave(createReqVO); ioManagementMain.setAuditState(AuditStateEnum.NO.getStatus()); } if (ObjectUtil.equals(createReqVO.getAuditState(), AuditStateEnum.NOT_PASS.getStatus())) { checkAuditState(createReqVO); ioManagementMain.setAuditState(AuditStateEnum.NOT_PASS.getStatus()); } ioManagementMainMapper.insert(ioManagementMain); // 根据 ioBillType 判断入库/出库,影响库存增减方向与校验 boolean isInbound = BILL_TYPE.INBOUND.equals(createReqVO.getIoBillType()); // 默认策略:FIFO(保持现有行为不变)。如需切换策略,仅需改此处。 final CostStrategyType costStrategy = CostStrategyType.FIFO; // 明细持久化:先统一补主表关联字段,再调用明细创建(可后续优化为批量) List<IoManagementDetailDO> ioManagementDetailDOS = BeanUtils.toBean(createReqVO.getItems(), IoManagementDetailDO.class); ioManagementDetailDOS.forEach(item -> { item.setMainId(ioManagementMain.getId()); item.setIoBillNo(ioManagementMain.getIoBillNo()); if (!isInbound) item.setIoMainUnitQty(item.getIoMainUnitQty().negate()); Long detailId = ioManagementDetailService.createIoManagementDetail(item); Long warehouseId = item.getIoWarehouseId(); if (!isInbound) { if (costStrategy == CostStrategyType.FIFO) { // FIFO:按入库明细顺序分摊并写回成本 updateInboundDetail(warehouseId, item.getIoMaterialId(), detailId, item.getIoMainUnitQty().negate()); } else { // 其他策略:计算并写回成本(不改变入库明细的已出库数量) computeAndWriteOutboundCostByStrategy(warehouseId, item.getIoMaterialId(), detailId, item.getIoMainUnitQty().negate(), costStrategy); } } }); if (CollectionUtils.isNotEmpty(ioManagementDetailDOS)) { ioManagementDetailDOS.stream().map(p -> p.getIoWarehouseId()).distinct().forEach(warehouseId -> { // 合并明细:按物料ID汇总数量;使用已带方向(出库为负、入库为正)的明细集合 Map<Long, BigDecimal> materialIdToDelta = ioManagementDetailDOS.stream() .filter(p -> Objects.equals(p.getIoWarehouseId(), warehouseId)) .collect(Collectors.toMap( IoManagementDetailDO::getIoMaterialId, IoManagementDetailDO::getIoMainUnitQty, BigDecimal::add)); // 一次性查询所有涉及物料的现存库存,返回以 materialId 为 key 的 Map Map<Long, InventoryDetailsDO> materialIdToInv = inventoryDetailsService .listByWarehouseIdAndMaterialIds(warehouseId, materialIdToDelta.keySet()); // 分流创建/更新:出库校验库存存在与不为负 for (Map.Entry<Long, BigDecimal> entry : materialIdToDelta.entrySet()) { Long materialId = entry.getKey(); BigDecimal delta = entry.getValue(); // 已包含方向(入库+,出库-) InventoryDetailsDO inv = materialIdToInv.get(materialId); if (inv == null) { if (!isInbound) { // 出库:库存不存在,直接拒绝 throw exception(INVENTORY_REFUSE_OUTBOUND); } // 入库:不存在则创建 YavWarehouseDO warehouseDO = warehouseMapper.selectById(warehouseId); List<MaterialInventoryDO> materialInventoryDOS = materialInventoryMapper.selectList(new LambdaQueryWrapper<MaterialInventoryDO>().eq(Objects.nonNull(warehouseDO) && StringUtils.isNotBlank(warehouseDO.getWhName()), MaterialInventoryDO::getMWarehouse, warehouseDO.getWhName())); String position = ""; String unit = ""; String ioCustomOrder = ""; if (CollectionUtils.isNotEmpty(materialInventoryDOS)) { MaterialInventoryDO materialInventoryDO = materialInventoryDOS.get(0); position = materialInventoryDO.getMWarehouseShelf() + "-" + materialInventoryDO.getMWarehouseColumn() + "-" + materialInventoryDO.getMWarehouseNum(); } MaterialDO materialDO = materialMapper.selectById(materialId); List<IoManagementDetailDO> detailDOS = ioManagementDetailDOS.stream() .filter(p -> Objects.equals(p.getIoWarehouseId(), warehouseId) && Objects.equals(p.getIoMaterialCode(), Objects.nonNull(materialDO) ? materialDO.getMCode() : null)) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(detailDOS)) { position = detailDOS.get(0).getIoWarehouseLocation(); unit = detailDOS.get(0).getIoMainUnit(); ioCustomOrder = detailDOS.get(0).getIoCustomOrder(); } inventoryDetailsService.createInventoryDetails(InventoryDetailsSaveReqVO.builder() .idWhId(warehouseId) .idMaterialId(materialId) .idMaterialName(materialDO.getMName()) .idMaterialCode(materialDO.getMCode()) .idAvailableQuantity(delta) .idStockQuantity(delta) .idInventoryUnit(unit) .idCustomOrder(StringUtils.isNotBlank(ioCustomOrder) ? Integer.valueOf(ioCustomOrder) : null) .idMaterialPosition(position) .idWhName(Objects.nonNull(warehouseDO) ? warehouseDO.getWhName() : "") .idWhCode(Objects.nonNull(warehouseDO) ? warehouseDO.getWhNumber() : "") .build()); } else { BigDecimal newAvailable = inv.getIdAvailableQuantity().add(delta); BigDecimal newStock = inv.getIdStockQuantity().add(delta); if (!isInbound && newStock.compareTo(BigDecimal.ZERO) < 0) { // 出库:扣减后为负,拒绝 throw exception(BOUND_RUN_OUT); } YavWarehouseDO warehouseDO = warehouseMapper.selectById(warehouseId); List<MaterialInventoryDO> materialInventoryDOS = materialInventoryMapper.selectList(new LambdaQueryWrapper<MaterialInventoryDO>().eq(Objects.nonNull(warehouseDO) && StringUtils.isNotBlank(warehouseDO.getWhName()), MaterialInventoryDO::getMWarehouse, warehouseDO.getWhName())); String position = ""; String unit = ""; String ioCustomOrder = ""; if (CollectionUtils.isNotEmpty(materialInventoryDOS)) { MaterialInventoryDO materialInventoryDO = materialInventoryDOS.get(0); position = materialInventoryDO.getMWarehouseShelf() + "-" + materialInventoryDO.getMWarehouseColumn() + "-" + materialInventoryDO.getMWarehouseNum(); } MaterialDO materialDO = materialMapper.selectById(materialId); List<IoManagementDetailDO> detailDOS = ioManagementDetailDOS.stream() .filter(p -> Objects.equals(p.getIoWarehouseId(), warehouseId) && Objects.equals(p.getIoMaterialCode(), Objects.nonNull(materialDO) ? materialDO.getMCode() : null)) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(detailDOS)) { position = detailDOS.get(0).getIoWarehouseLocation(); unit = detailDOS.get(0).getIoMainUnit(); ioCustomOrder = detailDOS.get(0).getIoCustomOrder(); } inventoryDetailsService.updateInventoryDetails(InventoryDetailsSaveReqVO.builder() .id(inv.getId()) .idWhId(warehouseId) .idMaterialId(materialId) .idMaterialName(Objects.nonNull(materialDO) ? materialDO.getMName() : "") .idMaterialCode(Objects.nonNull(materialDO) ? materialDO.getMCode() : "") .idAvailableQuantity(newAvailable) .idStockQuantity(newStock) .idInventoryUnit(unit) .idCustomOrder(StringUtils.isNotBlank(ioCustomOrder) ? Integer.valueOf(ioCustomOrder) : null) .idMaterialPosition(position) .idMaterialPosition(position) .idWhName(Objects.nonNull(warehouseDO) ? warehouseDO.getWhName() : "") .idWhCode(Objects.nonNull(warehouseDO) ? warehouseDO.getWhNumber() : "") .build()); } } }); } //更改对应单据来源表出入库状态 if (Objects.nonNull(createReqVO.getIoRelateNum())) { updateSourceBillStatus(createReqVO, createReqVO.getIoBillType()); } return ioManagementMain.getId(); } private void checkSave(IoManagementMainSaveReqVO createReqVO) { } private void checkAuditState(IoManagementMainSaveReqVO createReqVO) { //入库型、入库时间、应用型、入库总成本、关联单号、入库用途、选择物料、仓库、仓库型、入库数量、单位 if (StringUtils.isBlank(createReqVO.getIoBillType())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "入库/出库型不能为空"); } String name = createReqVO.getIoBillType().equals(BILL_TYPE.INBOUND) ? "入库" : "出库"; if (ObjectUtil.isEmpty(createReqVO.getIoBillDate())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), name + "时间不能为空"); } if (StringUtils.isBlank(createReqVO.getIoApplyType())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "应用型不能为空"); } if (ObjectUtil.isEmpty(createReqVO.getIoTotalCost())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), name + "总成本不能为空"); } if (ObjectUtil.isEmpty(createReqVO.getIoRelateNum())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "关联单号不能为空"); } if (StringUtils.isBlank(createReqVO.getIoPurpose())) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), name + "用途不能为空"); } List<IoManagementDetailSaveReqVO> items = createReqVO.getItems(); if (CollectionUtils.isEmpty(items)) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "选择物料不能为空"); } if (items.stream().anyMatch(item -> StringUtils.isBlank(item.getIoWarehouse()))) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "仓库名字不能为空"); } if (items.stream().anyMatch(item -> StringUtils.isBlank(item.getIoWarehouseType()))) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "仓库型不能为空"); } if (items.stream().anyMatch(item -> ObjectUtil.isEmpty(item.getIoMainUnitQty()))) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), name + "数量不能为空"); } if (items.stream().anyMatch(item -> ObjectUtil.isEmpty(item.getIoMainUnit()))) { throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST_PARAM.getCode(), "主单位不能为空"); } } /** * 更新源单据状态 */ private void updateSourceBillStatus(IoManagementMainSaveReqVO createReqVO, String ioBillType) { Long ioRelateNum = createReqVO.getIoRelateNum(); if (ioRelateNum == null) { log.warn("关联单据ID为空,无法更新源单据状态"); return; } String ioApplyType = createReqVO.getIoApplyType(); String ioBusinessType = createReqVO.getIoBusinessType(); try { if (BILL_TYPE.INBOUND.equals(ioBillType)) { updateInboundSourceStatus(ioBusinessType, ioRelateNum); } else { updateOutboundSourceStatus(ioBusinessType, ioApplyType, ioRelateNum); } } catch (Exception e) { log.error("更新源单据状态失败: billType={}, businessType={}, applyType={}, relateNum={}", ioBillType, ioBusinessType, ioApplyType, ioRelateNum, e); } } /** * 更新入库源单据状态 */ private void updateInboundSourceStatus(String ioBusinessType, Long ioRelateNum) { if (YavConstants.ONE_STR.equals(ioBusinessType)) { // 采购入库(收料通知单表) receiptMapper.update(new LambdaUpdateWrapper<ReceiptDO>() .eq(ReceiptDO::getId, ioRelateNum) .set(ReceiptDO::getRWareStatus, YavConstants.ONE_STR)); } // 可以在这里添加其他入库型的处理 } /** * 更新出库源单据状态 */ private void updateOutboundSourceStatus(String ioBusinessType, String ioApplyType, Long ioRelateNum) { if (YavConstants.ONE_STR.equals(ioBusinessType)) { switch (ioApplyType) { case YavConstants.ONE_STR: // 型材配置 profileCheckMapper.update(new LambdaUpdateWrapper<ProfileCheckDO>() .eq(ProfileCheckDO::getId, ioRelateNum) .set(ProfileCheckDO::getRWareStatus, YavConstants.ONE_STR)); break; case YavConstants.TWO_STR: // 门窗原料 fenestrationManagementMapper.update(new LambdaUpdateWrapper<FenestrationManagementDO>() .eq(FenestrationManagementDO::getId, ioRelateNum) .set(FenestrationManagementDO::getRWareStatus, YavConstants.ONE_STR)); break; case YavConstants.THREE_STR: // 门窗工厂 factoryMaterialsMapper.update(new LambdaUpdateWrapper<FactoryMaterialsDO>() .eq(FactoryMaterialsDO::getId, ioRelateNum) .set(FactoryMaterialsDO::getRWareStatus, YavConstants.ONE_STR)); break; default: log.warn("未知的出库应用型: {}", ioApplyType); } } else { //出库-销售订单 switch (ioApplyType) { case YavConstants.ONE_STR: // 型材配置 profileSalesOrderMapper.update(new LambdaUpdateWrapper<ProfileSalesOrderDO>() .eq(ProfileSalesOrderDO::getId, ioRelateNum) .set(ProfileSalesOrderDO::getPsShipper, YavConstants.ONE)); break; case YavConstants.TWO_STR: // 家装销售订单 kreSalesOrderMapper.update(new LambdaUpdateWrapper<KreSalesOrderDO>() .eq(KreSalesOrderDO::getId, ioRelateNum) .set(KreSalesOrderDO::getSoShipper, YavConstants.ONE)); break; case YavConstants.THREE_STR: // 工程销售订单 projectSalesOrderMapper.update(new LambdaUpdateWrapper<ProjectSalesOrderDO>() .eq(ProjectSalesOrderDO::getId, ioRelateNum) .set(ProjectSalesOrderDO::getEsShipper, YavConstants.ONE)); break; default: log.warn("未知的出库应用型: {}", ioApplyType); } return; } } // 计算除 FIFO 以外策略下的出库成本并写回当前出库明细(不改变入库明细) private void computeAndWriteOutboundCostByStrategy(Long warehouseId, Long ioMaterialId, Long outboundDetailId, BigDecimal outboundQty, CostStrategyType strategy) { if (outboundQty == null || outboundQty.compareTo(BigDecimal.ZERO) <= 0) { return; } BigDecimal unitCost; switch (strategy) { case AVERAGE: unitCost = computeAverageUnitCost(warehouseId, ioMaterialId); break; case WEIGHTED: unitCost = computeWeightedUnitCost(warehouseId, ioMaterialId); break; case MOVING_AVERAGE: unitCost = computeMovingAverageUnitCost(warehouseId, ioMaterialId); break; default: unitCost = BigDecimal.ZERO; } writeOutboundCost(outboundDetailId, unitCost, outboundQty); } // 简单平均:历史“可消耗入库明细”的单价算术平均(不考虑数量) private BigDecimal computeAverageUnitCost(Long warehouseId, Long materialId) { List<IoManagementDetailDO> inboundList = ioManagementDetailMapper.selectConsumableInbound(warehouseId, materialId); if (inboundList == null || inboundList.isEmpty()) return BigDecimal.ZERO; BigDecimal sum = BigDecimal.ZERO; int count = 0; for (IoManagementDetailDO d : inboundList) { if (d.getIoCostPrice() != null) { sum = sum.add(d.getIoCostPrice()); count++; } } if (count == 0) return BigDecimal.ZERO; return sum.divide(new BigDecimal(count), 6, RoundingMode.HALF_UP); } // 加权平均:按“剩余可用数量”加权 private BigDecimal computeWeightedUnitCost(Long warehouseId, Long materialId) { List<IoManagementDetailDO> inboundList = ioManagementDetailMapper.selectConsumableInbound(warehouseId, materialId); if (inboundList == null || inboundList.isEmpty()) return BigDecimal.ZERO; BigDecimal weightedSum = BigDecimal.ZERO; BigDecimal totalQty = BigDecimal.ZERO; for (IoManagementDetailDO d : inboundList) { BigDecimal inQty = d.getIoMainUnitQty(); BigDecimal used = d.getIoOutboundQuantity() == null ? BigDecimal.ZERO : d.getIoOutboundQuantity(); BigDecimal remain = inQty.subtract(used); if (remain.compareTo(BigDecimal.ZERO) <= 0) continue; BigDecimal unit = d.getIoCostPrice() == null ? BigDecimal.ZERO : d.getIoCostPrice(); weightedSum = weightedSum.add(unit.multiply(remain)); totalQty = totalQty.add(remain); } if (totalQty.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO; return weightedSum.divide(totalQty, 6, RoundingMode.HALF_UP); } // 移动加权平均:优先使用主表平均成本;没有则回退为当前加权平均 private BigDecimal computeMovingAverageUnitCost(Long warehouseId, Long materialId) { // 主表暂未保存 avgCost 字段,先回退到加权平均 return computeWeightedUnitCost(warehouseId, materialId); } private void writeOutboundCost(Long outboundDetailId, BigDecimal unitCost, BigDecimal qty) { if (outboundDetailId == null || unitCost == null || qty == null) return; BigDecimal line = unitCost.multiply(qty); IoManagementDetailDO update = new IoManagementDetailDO(); update.setId(outboundDetailId); update.setIoCostPrice(unitCost); update.setIoLineCost(line); ioManagementDetailMapper.updateById(update); } // FIFO:按时间顺序(先进先出)累计入库明细的已出库数量,并计算本次出库成本 private void updateInboundDetail(Long warehouseId, Long ioMaterialId, Long outboundDetailId, BigDecimal outboundQty) { if (outboundQty == null || outboundQty.compareTo(BigDecimal.ZERO) <= 0) { return; } BigDecimal need = outboundQty; BigDecimal costSum = BigDecimal.ZERO; List<IoManagementDetailDO> inboundList = ioManagementDetailMapper.selectConsumableInbound(warehouseId, ioMaterialId); for (IoManagementDetailDO inbound : inboundList) { if (need.compareTo(BigDecimal.ZERO) <= 0) { break; } BigDecimal inQty = inbound.getIoMainUnitQty(); BigDecimal used = inbound.getIoOutboundQuantity() == null ? BigDecimal.ZERO : inbound.getIoOutboundQuantity(); BigDecimal remain = inQty.subtract(used); if (remain.compareTo(BigDecimal.ZERO) <= 0) { continue; } BigDecimal alloc = need.min(remain); int affected = ioManagementDetailMapper.increaseOutboundQuantity(inbound.getId(), alloc); if (affected != 1) { inboundList = ioManagementDetailMapper.selectConsumableInbound(warehouseId, ioMaterialId); continue; } BigDecimal unitCost = inbound.getIoCostPrice() == null ? BigDecimal.ZERO : inbound.getIoCostPrice(); costSum = costSum.add(unitCost.multiply(alloc)); need = need.subtract(alloc); if (need.compareTo(BigDecimal.ZERO) > 0) { throw exception(BOUND_RUN_OUT); } } if (outboundDetailId != null) { IoManagementDetailDO update = new IoManagementDetailDO(); update.setId(outboundDetailId); update.setIoLineCost(costSum); BigDecimal unit = costSum.divide(outboundQty, 6, RoundingMode.HALF_UP); update.setIoCostPrice(unit); ioManagementDetailMapper.updateById(update); } } @Override @Transactional(readOnly = true) public IoManagementMainRespVO getIoManagementMainWithItems(Long id, boolean withItems) { IoManagementMainDO main = ioManagementMainMapper.selectById(id); if (main == null) { throw exception(IO_MANAGEMENT_MAIN_NOT_EXISTS); } IoManagementMainRespVO vo = BeanUtils.toBean(main, IoManagementMainRespVO.class); List<IoManagementDetailDO> details = ioManagementDetailService.listByMainId(id); vo.setItems(BeanUtils.toBean(details, IoManagementDetailRespVO.class)); vo.setIoApplyType(CollectionUtils.isNotEmpty(details) ? details.get(0).getIoApplyType() : ""); return vo; } @Transactional(rollbackFor = Exception.class) @Override public void updateIoManagementMain(IoManagementMainSaveReqVO updateReqVO) { // 校验存在 validateIoManagementMainExists(updateReqVO.getId()); // 更新 IoManagementMainDO updateObj = BeanUtils.toBean(updateReqVO, IoManagementMainDO.class); if (ObjectUtil.equals(updateReqVO.getAuditState(), AuditStateEnum.NO.getStatus())) { checkSave(updateReqVO); updateObj.setAuditState(AuditStateEnum.NO.getStatus()); } if (ObjectUtil.equals(updateReqVO.getAuditState(), AuditStateEnum.NOT_PASS.getStatus())) { checkAuditState(updateReqVO); updateObj.setAuditState(AuditStateEnum.NOT_PASS.getStatus()); //更新明细 if (CollectionUtils.isNotEmpty(updateReqVO.getItems())) { updateReqVO.getItems().forEach(updateItem -> { IoManagementDetailDO newUpdateItem = BeanUtils.toBean(updateItem, IoManagementDetailDO.class); ioManagementDetailMapper.insertOrUpdate(newUpdateItem); }); } } ioManagementMainMapper.updateById(updateObj); } @Override public void approvalIoManagementMain(IoManagementMainSaveReqVO updateReqVO) { Long id = updateReqVO.getId(); IoManagementMainDO ioManagementMainDO = ioManagementMainMapper.selectById(id); // 状态校验 审批不通过,数据状态变为保存 if (ObjectUtil.equals(updateReqVO.getAuditState(), AuditStateEnum.NO.getStatus())) { ioManagementMainDO.setAuditState(AuditStateEnum.NO.getStatus()); } ioManagementMainDO.setAuditState(updateReqVO.getAuditState()); ioManagementMainMapper.updateById(ioManagementMainDO); } @Override public void deleteIoManagementMain(Long id) { // 校验存在 validateIoManagementMainExists(id); // 删除 ioManagementMainMapper.deleteById(id); } @Transactional(rollbackFor = Exception.class) @Override public void deleteIoManagementMainListByIds(List<Long> ids) { // 删除 ioManagementMainMapper.deleteByIds(ids); //删除出入库明细 ioManagementDetailMapper.delete(new LambdaUpdateWrapper<IoManagementDetailDO>().in(CollectionUtils.isNotEmpty(ids), IoManagementDetailDO::getMainId, ids)); } private void validateIoManagementMainExists(Long id) { if (ioManagementMainMapper.selectById(id) == null) { throw exception(IO_MANAGEMENT_MAIN_NOT_EXISTS); } } @Override public IoManagementMainDO getIoManagementMain(Long id) { return ioManagementMainMapper.selectById(id); } @Override public PageResult<IoManagementMainDO> getIoManagementMainPage(IoManagementMainPageReqVO pageReqVO) { return ioManagementMainMapper.selectPage(pageReqVO); } //@Override //public PageResult<IoManagementMainRespVO> getIoManagementMainPages(IoManagementMainPageReqVO pageReqVO) { // PageResult<IoManagementMainDO> pageResult = ioManagementMainMapper.selectPage(pageReqVO); // PageResult<IoManagementMainRespVO> result = BeanUtils.toBean(pageResult, IoManagementMainRespVO.class); // if (CollectionUtils.isEmpty(result.getList())) { // return result; // } // List<Long> ids = result.getList().stream().map(p -> p.getId()).collect(Collectors.toList()); // List<IoManagementDetailDO> detailDOS = ioManagementDetailMapper.selectList(new LambdaQueryWrapper<IoManagementDetailDO>().in(IoManagementDetailDO::getMainId, ids)); // // 5. 将明细数据按mainId分组 // Map<Long, List<IoManagementDetailDO>> detailMap = detailDOS.stream() // .collect(Collectors.groupingBy(IoManagementDetailDO::getMainId)); // result.getList().forEach(p -> { // List<IoManagementDetailDO> details = detailMap.get(p.getId()); // p.setIoApplyType(details.get(0).getIoApplyType()); // }); // return result; //} @Override public PageResult<IoManagementMainRespVO> getIoManagementMainPages(IoManagementMainPageReqVO pageReqVO) { PageResult<IoManagementMainDO> pageResult = ioManagementMainMapper.selectPage(pageReqVO); PageResult<IoManagementMainRespVO> result = BeanUtils.toBean(pageResult, IoManagementMainRespVO.class); if (CollectionUtils.isEmpty(result.getList())) { return result; } List<Long> ids = result.getList().stream().map(p -> p.getId()).collect(Collectors.toList()); List<IoManagementDetailDO> detailDOS = ioManagementDetailMapper.selectList( new LambdaQueryWrapper<IoManagementDetailDO>().in(IoManagementDetailDO::getMainId, ids) ); Map<Long, List<IoManagementDetailDO>> detailMap = detailDOS.stream() .collect(Collectors.groupingBy(IoManagementDetailDO::getMainId)); // 修复:增加非空判断,避免空指针 result.getList().forEach(p -> { List<IoManagementDetailDO> details = detailMap.get(p.getId()); if (CollectionUtils.isNotEmpty(details)) { // 只有明细数据存在时才赋值 p.setIoApplyType(details.get(0).getIoApplyType()); } else { p.setIoApplyType(null); // 无明细时设为null或默认值 } }); return result; } /** * @Description:根据业务型查询单据列表 * @Author: hjs * @Date 2025/9/3 **/ @Override public PageResult<?> getOrderPage(String businessType, String businessTypeValue, String applyType, PageParam pageParam) { log.info("根据业务型查询单据列表入参,businessType={},businessTypeValue={},applyType={}", businessType, businessTypeValue, applyType); if (BILL_TYPE.CK_BUSINESS_TYPE.equals(businessType)) { if (businessTypeValue.equals(YavConstants.ONE_STR)) { //出库-生产领料(字典出库明细应用型 ck_apply_type) if (applyType.equals(YavConstants.ONE_STR)) { //型材配置 ProfileCheckPageReqVO pageReqVO = new ProfileCheckPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setRWareStatus(YavConstants.TWO_STR); return profileCheckMapper.selectPage(pageReqVO); } else if (applyType.equals(YavConstants.TWO_STR)) { //门窗原料-家装 FenestrationManagementPageReqVO pageReqVO = new FenestrationManagementPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setRWareStatus(YavConstants.TWO_STR); return fenestrationManagementMapper.selectPage(pageReqVO); } else if (applyType.equals(YavConstants.THREE_STR)) { //门窗工厂 FactoryMaterialsPageReqVO pageReqVO = new FactoryMaterialsPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setRWareStatus(YavConstants.TWO_STR); return factoryMaterialsMapper.selectPage(pageReqVO); } } else if (businessTypeValue.equals(YavConstants.TWO_STR)) { //出库-销售出库(字典出库明细应用型 xs_ck_apply_type) if (applyType.equals(YavConstants.ONE_STR)) { //型材销售订单 ProfileSalesOrderPageReqVO pageReqVO = new ProfileSalesOrderPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setPsShipper(YavConstants.ZERO); return profileSalesOrderMapper.selectPage(pageReqVO); } else if (applyType.equals(YavConstants.TWO_STR)) { //家装销售订单 KreSalesOrderPageReqVO pageReqVO = new KreSalesOrderPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setSoShipper(YavConstants.ZERO); return kreSalesOrderMapper.selectPage(pageReqVO); } else if (applyType.equals(YavConstants.THREE_STR)) { //工程销售订单 ProjectSalesOrderPageReqVO pageReqVO = new ProjectSalesOrderPageReqVO(); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setEsShipper(YavConstants.ZERO); return projectSalesOrderMapper.selectPage(pageReqVO); } } } else { if (businessTypeValue.equals(YavConstants.ONE_STR)) { //入库-采购入库(收料通知单表) ReceiptPageReqVO pageReqVO = new ReceiptPageReqVO(); pageReqVO.setPageNo(pageParam.getPageNo()); pageReqVO.setPageSize(pageParam.getPageSize()); pageReqVO.setRWareStatus(YavConstants.TWO_STR); return receiptMapper.selectPage(pageReqVO); } else if (businessTypeValue.equals(YavConstants.TWO_STR)) { //入库-生产入库(来源生产订单,目前还没有) return null; } } return null; } @Override public void updateProcessInfo(Long id, String processInstanceId, String status) { validateIoManagementMainExists(id); IoManagementMainDO updateObj = new IoManagementMainDO(); updateObj.setId(id); updateObj.setProcessInstanceId(processInstanceId); updateObj.setStatus(status); ioManagementMainMapper.updateById(updateObj); } @Override public void updateProcessStatus(Long id, String status) { validateIoManagementMainExists(id); IoManagementMainDO updateObj = new IoManagementMainDO(); updateObj.setId(id); updateObj.setStatus(status); ioManagementMainMapper.updateById(updateObj); } } package cn.iocoder.yudao.module.yavwarehouse.dal.mysql.iomanagementmain; import java.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.yavwarehouse.dal.dataobject.iomanagementmain.IoManagementMainDO; import org.apache.ibatis.annotations.Mapper; import cn.iocoder.yudao.module.yavwarehouse.controller.admin.iomanagementmain.vo.*; /** * 出入库主 Mapper * * @author YAVII */ @Mapper public interface IoManagementMainMapper extends BaseMapperX<IoManagementMainDO> { default PageResult<IoManagementMainDO> selectPage(IoManagementMainPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX<IoManagementMainDO>() .eqIfPresent(IoManagementMainDO::getIoBillNo, reqVO.getIoBillNo()) .eqIfPresent(IoManagementMainDO::getIoBillType, reqVO.getIoBillType()) .eqIfPresent(IoManagementMainDO::getIoBusinessType, reqVO.getIoBusinessType()) .betweenIfPresent(IoManagementMainDO::getIoBillDate, reqVO.getIoBillDate()) .eqIfPresent(IoManagementMainDO::getIoWarehouseId, reqVO.getIoWarehouseId()) .eqIfPresent(IoManagementMainDO::getIoWarehouse, reqVO.getIoWarehouse()) .eqIfPresent(IoManagementMainDO::getIoWarehouseCode, reqVO.getIoWarehouseCode()) .eqIfPresent(IoManagementMainDO::getIoTotalCost, reqVO.getIoTotalCost()) .eqIfPresent(IoManagementMainDO::getIoReferenceTotalCost, reqVO.getIoReferenceTotalCost()) .eqIfPresent(IoManagementMainDO::getIoRemark, reqVO.getIoRemark()) .eqIfPresent(IoManagementMainDO::getReserve1, reqVO.getReserve1()) .eqIfPresent(IoManagementMainDO::getReserve2, reqVO.getReserve2()) .eqIfPresent(IoManagementMainDO::getReserve3, reqVO.getReserve3()) .eqIfPresent(IoManagementMainDO::getReserve4, reqVO.getReserve4()) .eqIfPresent(IoManagementMainDO::getReserve5, reqVO.getReserve5()) .eqIfPresent(IoManagementMainDO::getState, reqVO.getState()) .eqIfPresent(IoManagementMainDO::getIoRelateNum, reqVO.getIoRelateNum()) .eqIfPresent(IoManagementMainDO::getIoOwnership, reqVO.getIoOwnership()) .eqIfPresent(IoManagementMainDO::getIoPurpose, reqVO.getIoPurpose()) .eqIfPresent(IoManagementMainDO::getStatus, reqVO.getStatus()) .eqIfPresent(IoManagementMainDO::getAuditState, reqVO.getAuditState()) .betweenIfPresent(IoManagementMainDO::getCreateTime, reqVO.getCreateTime()) .orderByDesc(IoManagementMainDO::getId)); } }分页查询不显示
10-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值