策略模块

今天遇到一个很好的大哥哥,必须表扬一下嘿嘿
在这里插入图片描述
不厌其烦的给我指点,哇塞,太棒啦
言归正传,首先我们得先去导入基础代码,不讲了,然后是对于页面的基础布局,
在这里插入图片描述
然后我们先来修改新增对话框,
在这里插入图片描述

需要改动的就是将策略方案设置成数字框,接下来就是查看详细
在这里插入图片描述
这里我们首先先增加一个按钮去绑定事件,然后去查找,创建一个集合去接受数据,在这里插入图片描述
这里因为我们需要查找的是关于策略相同的地区的,所以我们应该在需要传递的参数里面加上关于id的值,这里大家要是用的是row.id的话有时候可能不对,这时候我我们可以去输出打印出来row的值,然后看看哪个是我们需要的字段的值,这里需要注意的是关于策略的名称的展示,视频里面可以进行展示,但是我这里没法展示,所以我又去调了一下api去返回表单的值。
接下里讲一下关于策略分配的改造,
在这里插入图片描述
首先就是需要创建一个对话框,然后这里面需要注意的值我们在进行表单的校验的时候必须使用machineRef不然在下面公用提交表单的时候没法通过校验,然后就是向后端去发送请求
在这里插入图片描述
这里面使用的是前端进行相应的值,就是拿到那一行的对象,然后直接进行返回就行。

商品管理

这里我们还是先需要根据页面原型来生成前端的基础代码,这里就不进行详细进行讲解,我们直接来讲解业务。
在这里插入图片描述
关于前端的基础界面也不讲了,课程听到这里前面进行展示的效果大家应该都已经把业务跑熟练了,这里粗略讲解一下,就是向后端发送请求,然后使用循环来进行遍历,这里主包当时遇到一个很好玩的事情,当时主包在进行回显查询的时候
在这里插入图片描述
在这里插入图片描述
当时不是封装给表单嘛,但是主包当时纯了,直接变成循环了,所以展示的就是一个没有数据回显的下拉列表。
在这里插入图片描述
这里是直接拷贝的,需要注意的是代理后面那一块,必须和表单上面的响应式数据一直,不然会报错。
关于商品的删除,我们在这里面没有使用数据库的外键,是让我们后端来进行使用逻辑外键来约束,
在这里插入图片描述
商品的批量导入: 对于这个我们来细细探讨,先来讲前端,首先我们需要先新增一个按钮,里面来设置函数,去打开上传文件的对话框,
在这里插入图片描述
这里面去定义一个响应式的空对象uploadRef用来获取我们进行提交的文件,这里我们直接去饿了么官网去看,然后就是关于前端的检验了,因为我们在上传的时候需要提交,所以我们首先先在提交按钮里面去通过响应式数据里面的submit进行提交,这里面因为在官网里面是使用的是ts,所以我们加个if判断就行,然后就是上传,这里面的action就是需要上传的路径,由于我们在开发环境里面,所以我们需要使用代理来进行转发请求,还要在发送的请求里面进行加上header
在这里插入图片描述

这里是直接copy若依框架里面的图片上传的代码,到这里,一个文件的上传就基本搞定了,但是因为我们需要上传的是一个excel文件,所以我们在这里需要进行判断是不是我们所需要的文件,所以我们就需要在上传前加上判断,要不是的话就直接显示文件格式错误,也不进行上传

/** excel上传 */
const uploadRef=ref({});
function submitUpload() { 
   if (uploadRef.value!== null) { 
    uploadRef.value.submit();
   }
}

const props = defineProps({
  modelValue: [String, Object, Array],
  // 文件数量限制
  limit: {
    type: Number,
    default: 1,
  },
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default:1,
  },
  // 文件类型, 例如[xls,xlsx]
  fileType: {
    type: Array,
    default: () => ["xls", "xlsx"],
  }
});
// 上传成功回调
function handleUploadSuccess(res, file) {
  if (res.code === 200) {
    proxy.$modal.msgSuccess("上传成功");
    importOpen.value = false;
    getList();
  } else {
     proxy.$modal.msgError("上传文件失败");
  }
  uploadRef.value.clearFiles();
  proxy.$modal.closeLoading();

}
// 上传失败
function handleUploadError() {
  proxy.$modal.msgError("上传文件失败");
 
  uploadRef.value.clearFiles();
  proxy.$modal.closeLoading();
}

// 上传前loading加载
function handleBeforeUpload(file) {
  let isExcel = false;
  if (props.fileType.length) {
    let fileExtension = "";
    if (file.name.lastIndexOf(".") > -1) {
      fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
    }
    isExcel = props.fileType.some(type => {
      if (file.type.indexOf(type) > -1) return true;
      if (fileExtension && fileExtension.indexOf(type) > -1) return true;
      return false;
    });
  } 
  if (!isExcel) {
    proxy.$modal.msgError(
      `文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`
    );
    return false;
  }
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy.$modal.msgError(`上传excel大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  proxy.$modal.loading("正在上传excel,请稍候...");
}

那你肯定是需要定义一个检验的规则,这里就是在加载之前了

// 上传前loading加载
function handleBeforeUpload(file) {
  let isExcel = false;
  if (props.fileType.length) {
    let fileExtension = "";
    if (file.name.lastIndexOf(".") > -1) {
      fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
    }
    isExcel = props.fileType.some(type => {
      if (file.type.indexOf(type) > -1) return true;
      if (fileExtension && fileExtension.indexOf(type) > -1) return true;
      return false;
    });
  } 
  if (!isExcel) {
    proxy.$modal.msgError(
      `文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`
    );
    return false;
  }
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy.$modal.msgError(`上传excel大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  proxy.$modal.loading("正在上传excel,请稍候...");
}

const props = defineProps({
  modelValue: [String, Object, Array],
  // 文件数量限制
  limit: {
    type: Number,
    default: 1,
  },
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default:1,
  },
  // 文件类型, 例如[xls,xlsx]
  fileType: {
    type: Array,
    default: () => ["xls", "xlsx"],
  }
});

这里面进行判断,需要改动的基本没有。然后我们在上传成功的时候,下次上传还是存在上次上传的文件,那么我是不是应该去改动,对了,这就到了

// 上传成功回调
function handleUploadSuccess(res, file) {
  if (res.code === 200) {
    proxy.$modal.msgSuccess("上传成功");
    importOpen.value = false;
    getList();
  } else {
     proxy.$modal.msgError("上传文件失败");
  }
  uploadRef.value.clearFiles();
  proxy.$modal.closeLoading();

}
// 上传失败
function handleUploadError() {
  proxy.$modal.msgError("上传文件失败");
 
  uploadRef.value.clearFiles();
  proxy.$modal.closeLoading();
}

关于成功回调函数,就是去将响应式对象里面的文件进行清理,然后将加载的形式去除,再次查询。
后端:
关于后端就是

/**
 * 导入商品管理列表
 */
@PreAuthorize("@ss.hasPermi('manage:sku:add')")
@Log(title = "商品管理", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public AjaxResult excelImport(MultipartFile file) throws Exception {
    ExcelUtil<Sku> util = new ExcelUtil<Sku>(Sku.class);
    List<Sku> skuList = util.importExcel(file.getInputStream());
    return toAjax(skuService.insertSkus(skuList));
}

就是调用若依封装好的导入类进行装配就行,这里主包实在不行了,使用easyexcel实在是一直报错,我实在是不行了,老是报错

货道关联商品

首先就是将资料中的代码导进去,但是主包的命名和里面的不一致,大家可以看看主包的修改的内容来进行修改
在这里插入图片描述
首先就是在货道里面的js代码给后端发送请求的路径不一致,
在这里插入图片描述
在这里面进行引入的组件也是需要更换成设备js
在这里插入图片描述
接下里就是关于商品图片名称之前的自己定义的data,这个可以打印出来看看
后端代码:
在这里插入图片描述
首先我们需要先创建一个controller来进行接受请求,
在这里插入图片描述
然后去imp里面去实现
在这里插入图片描述
这里面是手动去封装一个map,如果在运行的过程中报MyBatis在执行查询时无法找到 com.dkd.manage.mapper.TbSkuMapper.selectTbSkuBySkuId 这个映射语句。这个错误发生在 TbChannelMapper.selectTbChannelByInnerCode 查询的结果处理阶段,大家可以先清理一下项目,然后试试,不行的话把idea关了之后重启,主包在重启之后就是能够正常识别了;
最后就是货道关联商品的改造,这里我们需要先创建一个对象去接受前端传递过来的实体类,然后进行遍历
在这里插入图片描述
这里用到了函数式编程里面的map,就是需要一个参数,然后返回一个结果,参数和返回的结果可以不一致,因为是function的函数式接口,这里不懂得可去看一下主包之前写过的关于函数式编程相关的内容,这里主包当时用ai写的,就是不行,后来才发现是因为在设置商品的id的时候是直接设置的id,没有设置skuid,导致前端一直出现错误。

工单管理

主包最近几天休息了,现在更新,嘿嘿
首先就是需要先创建基础代码,这里主包就不讲了,主要是来讲讲需要进行修改的地方
在这里插入图片描述

在这里插入图片描述
这两个地方需要进行修正,将desc加上反引号进行查询
接下来是查询工单列表,这里需要返回给前端一个taskvo的对象,需要将工单的类型返回给前端,这里就是需要自己在查询的最后进行拼接一个查询语句进行返回
在这里插入图片描述
接下里就是获取运营人员列表,这里需要根据前端传递过来的innercode进行查询,因为公用的是一个公共的接口,所以在前端传递的是三个参数,
在这里插入图片描述
需要根据前端传递过来的最后一个if进行判断来进行向后端传递数据,运维人员也是一样
接下来是新增工单,这里面我们需要进行判断是不是这个设备是不是存在,不存在直接报错,要是存在的话,是不是存在同类型的工单
在这里插入图片描述
还需要校验是不是存在这个员工,以及这个员工是不是负责这个区域,都校验完毕之后就是需要检验是不是补货工单,在补货工单里面需要进行校验是不是补货的列表的信息是null,最后进行补全代码

package com.dkd.manage.service.impl;

import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.dkd.common.constant.DkdContants;
import com.dkd.common.utils.DateUtils;
import com.dkd.common.utils.SecurityUtils;
import com.dkd.manage.domain.DTO.TaskDetailsDto;
import com.dkd.manage.domain.DTO.TaskDto;
import com.dkd.manage.domain.TaskDetails;
import com.dkd.manage.domain.TbEmp;
import com.dkd.manage.domain.TbVendingMachine;
import com.dkd.manage.domain.VO.TaskVo;
import com.dkd.manage.mapper.TaskDetailsMapper;
import com.dkd.manage.mapper.TbEmpMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.dkd.manage.mapper.TaskMapper;
import com.dkd.manage.domain.Task;
import com.dkd.manage.service.ITaskService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 工单Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-11-02
 */
@Service
public class TaskServiceImpl implements ITaskService 
{
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private TbEmpMapper tbEmpMapper;
    @Autowired
    private TaskDetailsMapper taskDetailsMapper;
    /**
     * 查询工单
     * 
     * @param taskId 工单主键
     * @return 工单
     */
    @Override
    public Task selectTaskByTaskId(Long taskId)
    {
        return taskMapper.selectTaskByTaskId(taskId);
    }

    /**
     * 查询工单列表
     * 
     * @param task 工单
     * @return 工单
     */
    @Override
    public List<Task> selectTaskList(Task task)
    {
        return taskMapper.selectTaskList(task);
    }

    /**
     * 新增工单
     * 
     * @param task 工单
     * @return 结果
     */
    @Override
    public int insertTask(Task task)
    {
        task.setCreateTime(DateUtils.getNowDate());
        return taskMapper.insertTask(task);
    }

    /**
     * 修改工单
     * 
     * @param task 工单
     * @return 结果
     */
    @Override
    public int updateTask(Task task)
    {
        task.setUpdateTime(DateUtils.getNowDate());
        return taskMapper.updateTask(task);
    }

    /**
     * 批量删除工单
     * 
     * @param taskIds 需要删除的工单主键
     * @return 结果
     */
    @Override
    public int deleteTaskByTaskIds(Long[] taskIds)
    {
        return taskMapper.deleteTaskByTaskIds(taskIds);
    }

    /**
     * 删除工单信息
     * 
     * @param taskId 工单主键
     * @return 结果
     */
    @Override
    public int deleteTaskByTaskId(Long taskId)
    {
        return taskMapper.deleteTaskByTaskId(taskId);
    }

    /**
     * 返回给前端的工单列表进行不同的人员查询
     * @param task
     * @return
     */
    @Override
    public List<TaskVo> selectTaskVoList(Task task) {
        return taskMapper.selectTaskVoList(task);
    }

    /**
     * 实现关于前端传递过来的新增用户的请求
     * @param taskDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBatchTask(TaskDto taskDto) {
        System.out.println(taskDto);
        Task task = new Task();
        BeanUtils.copyProperties(taskDto,task);
        //1.查询设备是不是存在
        TbVendingMachine tbVendingMachine = tbEmpMapper.selectByInnerCode(task.getInnerCode());
        if (tbVendingMachine == null) {
            throw new RuntimeException("设备不存在");
        }
//        2.校验同类型工单
        //投放工单,如果设备在运行中,那么抛出异常
        extracted( tbVendingMachine.getVmStatus(),task.getProductTypeId() );
        //3.校验是不是存在这个员工
        extracted(task);
        //4.判断是不是负责这个区域
        TbEmp tbEmp = tbEmpMapper.selectTbEmpById(task.getUserId());
        if (tbEmp.getRegionId().equals(task.getRegionId())   ){
            throw new RuntimeException("设备不属于这个区域");
        }

        task.setTaskStatus(DkdContants.TASK_STATUS_CREATE);// 创建工单
        task.setUserName( tbEmpMapper.selectTbEmpById(task.getUserId()).getUserName());// 执行人名称
        task.setRegionId( tbVendingMachine.getRegionId() );// 所属区域id
        task.setAddr(  tbVendingMachine.getAddr());// 地址
        task.setCreateTime(DateUtils.getNowDate());// 创建时间
        task.setTaskCode( getTaskCode());// 工单编号
        int taskResult = taskMapper.insertTask(task);
        //5.判断是否补货
        if (  task.getProductTypeId()== DkdContants.TASK_TYPE_SUPPLY ) {
            List<TaskDetailsDto> taskDetailsDtos = taskDto.getDetails();
            if (CollUtil.isEmpty(taskDetailsDtos)){
                throw new RuntimeException("补货工单详情不能为空");
            }
            List<TaskDetails> collect = taskDetailsDtos.stream().map(taskDetailsDto -> {
                TaskDetails taskDetails = new TaskDetails();
                BeanUtils.copyProperties(taskDetailsDto, taskDetails);
                taskDetails.setTaskId(task.getTaskId());
                return taskDetails;
            }).collect(Collectors.toList());

            taskDetailsMapper.insertBatchTaskDetails(collect);
        }



        return taskResult ;
    }

    /**
     * 取消工单
     * @param task
     * @return
     */
    @Override
    public int updateCancelTask(Task task) {
        //判断工单的状态,要是已经完成或者已经取消的,那么就返回给前端错误
        Long taskId = task.getTaskId();
        Task task1 = taskMapper.selectTaskByTaskId(taskId);
        if (task1.getTaskStatus().equals(DkdContants.TASK_STATUS_FINISH) || task1.getTaskStatus().equals(DkdContants.TASK_STATUS_CANCEL)) {
            throw new RuntimeException("工单已经完成或者已经取消");
        }
        task.setUpdateTime(DateUtils.getNowDate());
        task.setTaskStatus(DkdContants.TASK_STATUS_CANCEL);
        task.setUpdateBy(SecurityUtils.getUsername());
        task.setDesc(task.getDesc());



        return taskMapper.updateTask(task);
    }

    @Autowired
    private RedisTemplate redisTemplate;
    private String getTaskCode() {
       // 生成工单编号
        // 获取当前日期并格式化为"yyyyMMdd"
        String dateStr = DateUtils.getDate().replaceAll("-", "");
        // 根据日期生成redis的键
        String key = "dkd.task.code." + dateStr;
        // 判断key是否存在
        if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
            // 如果key不存在,设置初始值为1,并指定过期时间为1天
            redisTemplate.opsForValue().set(key, 1, Duration.ofDays(1));
            // 返回工单编号(日期+0001)
            return dateStr + "0001";
        }
        // 如果key存在,计数器+1(0002),确保字符串长度为4位
        return dateStr+ StrUtil.padPre(redisTemplate.opsForValue().increment(key).toString(),4,'0');


    }



    private void extracted(Task task) {
        if (tbEmpMapper.selectTbEmpById(task.getUserId())==null) {
            throw new RuntimeException("员工不存在");
        }
    }

    private static void extracted(Long vmStatus,Long  productTypeId) {
        if (vmStatus== DkdContants.VM_STATUS_RUNNING&& productTypeId== DkdContants.TASK_TYPE_DEPLOY) {
            throw new RuntimeException("设备正在运行中,无法进行投放");
        }
        if (vmStatus== DkdContants.VM_STATUS_RUNNING&& productTypeId== DkdContants.TASK_TYPE_REPAIR) {
            throw new RuntimeException("设备正在运行中,无法进行维修");
        }
        if (vmStatus!= DkdContants.VM_STATUS_RUNNING&& productTypeId== DkdContants.TASK_TYPE_REVOKE) {
            throw new RuntimeException("设备不是正在运行中,无法进行撤机");
        }
        if (vmStatus!= DkdContants.VM_STATUS_RUNNING&& productTypeId== DkdContants.TASK_TYPE_SUPPLY) {
            throw new RuntimeException("设备不是正在运行中,无法进行补货");
        }

    }


}


取消工单和查询补货信息很简单不讲了,就是调用mapper更新数据,但是需要校验如果是已经完成的或者是已经取消的那么也是需要进行报错的。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐