合同编辑详情开发
This commit is contained in:
@@ -9,12 +9,14 @@ import com.gear.mes.production.domain.vo.GearProductionTaskListVo;
|
||||
import com.gear.mes.production.domain.vo.GearProductionTaskWithDetailVo;
|
||||
import com.gear.mes.production.service.IGearProductionTaskService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -54,4 +56,58 @@ public class GearProductionTaskController extends BaseController {
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{taskId}/uncomplete")
|
||||
public R<Void> uncomplete(@PathVariable("taskId") Long taskId) {
|
||||
boolean ok = productionTaskService.uncompleteTask(taskId);
|
||||
if (!ok) {
|
||||
return R.fail("撤销完成失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{taskId}/start")
|
||||
public R<Void> start(@PathVariable("taskId") Long taskId) {
|
||||
boolean ok = productionTaskService.startTask(taskId);
|
||||
if (!ok) {
|
||||
return R.fail("开始失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{taskId}/pause")
|
||||
public R<Void> pause(@PathVariable("taskId") Long taskId) {
|
||||
boolean ok = productionTaskService.pauseTask(taskId);
|
||||
if (!ok) {
|
||||
return R.fail("暂停失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{taskId}/resume")
|
||||
public R<Void> resume(@PathVariable("taskId") Long taskId) {
|
||||
boolean ok = productionTaskService.resumeTask(taskId);
|
||||
if (!ok) {
|
||||
return R.fail("继续失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public R<Void> edit(@RequestBody GearProductionTaskWithDetailVo bo) {
|
||||
boolean ok = productionTaskService.updateTaskWithDetail(bo);
|
||||
if (!ok) {
|
||||
return R.fail("修改失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{taskId}")
|
||||
public R<Void> remove(@PathVariable("taskId") Long taskId) {
|
||||
boolean ok = productionTaskService.deleteTask(taskId);
|
||||
if (!ok) {
|
||||
return R.fail("删除失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,9 @@ public interface GearProductionTaskMapper {
|
||||
@Param("status") String status,
|
||||
@Param("updateBy") String updateBy,
|
||||
@Param("updateTime") Date updateTime);
|
||||
|
||||
int updateDelFlag(@Param("taskId") Long taskId,
|
||||
@Param("delFlag") String delFlag,
|
||||
@Param("updateBy") String updateBy,
|
||||
@Param("updateTime") Date updateTime);
|
||||
}
|
||||
|
||||
@@ -14,4 +14,16 @@ public interface IGearProductionTaskService {
|
||||
Long insertTaskWithDetail(GearProductionTaskWithDetailVo bo);
|
||||
|
||||
boolean completeTask(Long taskId);
|
||||
|
||||
boolean uncompleteTask(Long taskId);
|
||||
|
||||
boolean startTask(Long taskId);
|
||||
|
||||
boolean pauseTask(Long taskId);
|
||||
|
||||
boolean resumeTask(Long taskId);
|
||||
|
||||
boolean updateTaskWithDetail(GearProductionTaskWithDetailVo bo);
|
||||
|
||||
boolean deleteTask(Long taskId);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import com.gear.mes.production.domain.GearProductionTaskProduct;
|
||||
import com.gear.mes.production.domain.vo.GearProductionTaskListVo;
|
||||
import com.gear.mes.production.domain.vo.GearProductionTaskMaterialVo;
|
||||
import com.gear.mes.production.domain.vo.GearProductionTaskWithDetailVo;
|
||||
import com.gear.mes.production.domain.vo.GearProductionTaskProductVo;
|
||||
import com.gear.common.utils.DateUtils;
|
||||
import com.gear.common.helper.LoginHelper;
|
||||
import com.gear.mes.production.mapper.GearProductionTaskMapper;
|
||||
import com.gear.mes.production.mapper.GearProductionTaskMaterialMapper;
|
||||
import com.gear.mes.production.mapper.GearProductionTaskProductMapper;
|
||||
@@ -72,8 +74,11 @@ public class GearProductionTaskServiceImpl implements IGearProductionTaskService
|
||||
task.setDelFlag("0");
|
||||
}
|
||||
if (task.getStatus() == null || String.valueOf(task.getStatus()).trim().isEmpty()) {
|
||||
task.setStatus("1");
|
||||
task.setStatus("0");
|
||||
}
|
||||
String username = LoginHelper.getUsername();
|
||||
task.setCreateBy(username);
|
||||
task.setUpdateBy(username);
|
||||
task.setCreateTime(DateUtils.getNowDate());
|
||||
task.setUpdateTime(DateUtils.getNowDate());
|
||||
taskMapper.insertTask(task);
|
||||
@@ -131,7 +136,8 @@ public class GearProductionTaskServiceImpl implements IGearProductionTaskService
|
||||
if ("2".equals(String.valueOf(task.getStatus()))) {
|
||||
return true;
|
||||
}
|
||||
int updated = taskMapper.updateTaskStatus(taskId, "2", task.getUpdateBy(), DateUtils.getNowDate());
|
||||
String username = LoginHelper.getUsername();
|
||||
int updated = taskMapper.updateTaskStatus(taskId, "2", username, DateUtils.getNowDate());
|
||||
if (updated <= 0) {
|
||||
GearProductionTask after = taskMapper.selectTaskById(taskId);
|
||||
return after != null && "2".equals(String.valueOf(after.getStatus()));
|
||||
@@ -140,6 +146,159 @@ public class GearProductionTaskServiceImpl implements IGearProductionTaskService
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean uncompleteTask(Long taskId) {
|
||||
if (taskId == null) {
|
||||
return false;
|
||||
}
|
||||
GearProductionTask task = taskMapper.selectTaskById(taskId);
|
||||
if (task == null) {
|
||||
return false;
|
||||
}
|
||||
if (!"2".equals(String.valueOf(task.getStatus()))) {
|
||||
return true;
|
||||
}
|
||||
String username = LoginHelper.getUsername();
|
||||
int updated = taskMapper.updateTaskStatus(taskId, "1", username, DateUtils.getNowDate());
|
||||
if (updated <= 0) {
|
||||
GearProductionTask after = taskMapper.selectTaskById(taskId);
|
||||
return after != null && !"2".equals(String.valueOf(after.getStatus()));
|
||||
}
|
||||
materialMapper.deleteByTaskId(taskId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean startTask(Long taskId) {
|
||||
return setStatus(taskId, "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean pauseTask(Long taskId) {
|
||||
return setStatus(taskId, "3");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean resumeTask(Long taskId) {
|
||||
return setStatus(taskId, "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateTaskWithDetail(GearProductionTaskWithDetailVo bo) {
|
||||
if (bo == null || bo.getTask() == null || bo.getTask().getTaskId() == null) {
|
||||
return false;
|
||||
}
|
||||
Long taskId = bo.getTask().getTaskId();
|
||||
GearProductionTask existed = taskMapper.selectTaskById(taskId);
|
||||
if (existed == null) {
|
||||
return false;
|
||||
}
|
||||
GearProductionTask task = bo.getTask();
|
||||
task.setStatus(existed.getStatus());
|
||||
task.setDelFlag(existed.getDelFlag());
|
||||
task.setUpdateBy(LoginHelper.getUsername());
|
||||
task.setUpdateTime(DateUtils.getNowDate());
|
||||
taskMapper.updateTask(task);
|
||||
|
||||
Map<Long, GearProductionTaskProductVo> existingProducts = new LinkedHashMap<>();
|
||||
List<GearProductionTaskProductVo> existList = productMapper.selectByTaskId(taskId);
|
||||
if (existList != null) {
|
||||
existList.forEach(p -> {
|
||||
if (p != null && p.getProductId() != null) {
|
||||
existingProducts.put(p.getProductId(), p);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
productMapper.deleteByTaskId(taskId);
|
||||
List<GearProductionTaskProduct> rows = mergeProductsForSave(taskId, bo.getProducts(), existingProducts);
|
||||
if (!rows.isEmpty()) {
|
||||
productMapper.insertBatch(rows);
|
||||
}
|
||||
if ("2".equals(String.valueOf(existed.getStatus()))) {
|
||||
regenerateReceiptMaterials(taskId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteTask(Long taskId) {
|
||||
if (taskId == null) {
|
||||
return false;
|
||||
}
|
||||
String username = LoginHelper.getUsername();
|
||||
int updated = taskMapper.updateDelFlag(taskId, "1", username, DateUtils.getNowDate());
|
||||
if (updated <= 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setStatus(Long taskId, String targetStatus) {
|
||||
if (taskId == null) {
|
||||
return false;
|
||||
}
|
||||
GearProductionTask task = taskMapper.selectTaskById(taskId);
|
||||
if (task == null) {
|
||||
return false;
|
||||
}
|
||||
if (targetStatus.equals(String.valueOf(task.getStatus()))) {
|
||||
return true;
|
||||
}
|
||||
if ("2".equals(String.valueOf(task.getStatus())) && !"2".equals(targetStatus)) {
|
||||
return false;
|
||||
}
|
||||
String username = LoginHelper.getUsername();
|
||||
int updated = taskMapper.updateTaskStatus(taskId, targetStatus, username, DateUtils.getNowDate());
|
||||
if (updated <= 0) {
|
||||
GearProductionTask after = taskMapper.selectTaskById(taskId);
|
||||
return after != null && targetStatus.equals(String.valueOf(after.getStatus()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<GearProductionTaskProduct> mergeProductsForSave(Long taskId,
|
||||
List<GearProductionTaskProductVo> incoming,
|
||||
Map<Long, GearProductionTaskProductVo> existed) {
|
||||
Map<Long, GearProductionTaskProduct> map = new LinkedHashMap<>();
|
||||
if (incoming != null) {
|
||||
incoming.forEach(p -> {
|
||||
if (p == null || p.getProductId() == null) return;
|
||||
GearProductionTaskProduct hit = map.get(p.getProductId());
|
||||
BigDecimal planQty = p.getPlanQty() == null ? BigDecimal.ZERO : p.getPlanQty();
|
||||
if (hit == null) {
|
||||
GearProductionTaskProduct row = new GearProductionTaskProduct();
|
||||
row.setLineId(IdUtil.getSnowflakeNextId());
|
||||
row.setTaskId(taskId);
|
||||
row.setProductId(p.getProductId());
|
||||
row.setPlanQty(planQty);
|
||||
GearProductionTaskProductVo old = existed != null ? existed.get(p.getProductId()) : null;
|
||||
row.setFinishedQty(old != null && old.getFinishedQty() != null ? old.getFinishedQty() : BigDecimal.ZERO);
|
||||
row.setBadQty(old != null && old.getBadQty() != null ? old.getBadQty() : BigDecimal.ZERO);
|
||||
String unit = (p.getUnit() != null && !p.getUnit().trim().isEmpty()) ? p.getUnit() : (old != null ? old.getUnit() : null);
|
||||
row.setUnit(unit);
|
||||
row.setRemark(p.getRemark());
|
||||
map.put(p.getProductId(), row);
|
||||
return;
|
||||
}
|
||||
hit.setPlanQty((hit.getPlanQty() == null ? BigDecimal.ZERO : hit.getPlanQty()).add(planQty));
|
||||
if ((hit.getUnit() == null || hit.getUnit().trim().isEmpty()) && p.getUnit() != null && !p.getUnit().trim().isEmpty()) {
|
||||
hit.setUnit(p.getUnit());
|
||||
}
|
||||
if ((hit.getRemark() == null || hit.getRemark().trim().isEmpty()) && p.getRemark() != null && !p.getRemark().trim().isEmpty()) {
|
||||
hit.setRemark(p.getRemark());
|
||||
}
|
||||
});
|
||||
}
|
||||
return new ArrayList<>(map.values());
|
||||
}
|
||||
|
||||
private void regenerateReceiptMaterials(Long taskId) {
|
||||
materialMapper.deleteByTaskId(taskId);
|
||||
List<GearProductionTaskMaterial> required = materialMapper.selectRequirementByTaskId(taskId);
|
||||
|
||||
@@ -121,4 +121,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND status <![CDATA[<>]]> #{status}
|
||||
</update>
|
||||
|
||||
<update id="updateDelFlag">
|
||||
UPDATE gear_production_task
|
||||
SET
|
||||
del_flag = #{delFlag},
|
||||
update_by = #{updateBy},
|
||||
update_time = #{updateTime}
|
||||
WHERE task_id = #{taskId}
|
||||
AND del_flag = '0'
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.gear.oa.controller;
|
||||
|
||||
import com.gear.common.annotation.Log;
|
||||
import com.gear.common.annotation.RepeatSubmit;
|
||||
import com.gear.common.core.controller.BaseController;
|
||||
import com.gear.common.core.domain.PageQuery;
|
||||
import com.gear.common.core.domain.R;
|
||||
import com.gear.common.core.page.TableDataInfo;
|
||||
import com.gear.common.core.validate.AddGroup;
|
||||
import com.gear.common.core.validate.EditGroup;
|
||||
import com.gear.common.enums.BusinessType;
|
||||
import com.gear.common.utils.poi.ExcelUtil;
|
||||
import com.gear.oa.domain.bo.GearContractBo;
|
||||
import com.gear.oa.domain.vo.GearContractVo;
|
||||
import com.gear.oa.service.IGearContractService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oa/contract")
|
||||
public class GearContractController extends BaseController {
|
||||
|
||||
private final IGearContractService iGearContractService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<GearContractVo> list(GearContractBo bo, PageQuery pageQuery) {
|
||||
return iGearContractService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@Log(title = "合同编辑详情", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(GearContractBo bo, HttpServletResponse response) {
|
||||
List<GearContractVo> list = iGearContractService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "合同编辑详情", GearContractVo.class, response);
|
||||
}
|
||||
|
||||
@GetMapping("/{contractId}")
|
||||
public R<GearContractVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long contractId) {
|
||||
return R.ok(iGearContractService.queryById(contractId));
|
||||
}
|
||||
|
||||
@Log(title = "合同编辑详情", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody GearContractBo bo) {
|
||||
return toAjax(iGearContractService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "合同编辑详情", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody GearContractBo bo) {
|
||||
return toAjax(iGearContractService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "合同编辑详情", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{contractIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] contractIds) {
|
||||
return toAjax(iGearContractService.deleteWithValidByIds(Arrays.asList(contractIds), true));
|
||||
}
|
||||
}
|
||||
|
||||
45
gear-oa/src/main/java/com/gear/oa/domain/GearContract.java
Normal file
45
gear-oa/src/main/java/com/gear/oa/domain/GearContract.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.gear.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.gear.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("gear_contract")
|
||||
public class GearContract extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "contract_id")
|
||||
private Long contractId;
|
||||
|
||||
private String contractNo;
|
||||
|
||||
private String partyA;
|
||||
|
||||
private String partyB;
|
||||
|
||||
private String effectiveFlag;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date signDate;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date deliveryDate;
|
||||
|
||||
private String signPlace;
|
||||
|
||||
private String partyAAddress;
|
||||
|
||||
private String partyBAddress;
|
||||
|
||||
@TableLogic(value = "0", delval = "2")
|
||||
private String delFlag;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.gear.oa.domain.bo;
|
||||
|
||||
import com.gear.common.core.domain.BaseEntity;
|
||||
import com.gear.common.core.validate.AddGroup;
|
||||
import com.gear.common.core.validate.EditGroup;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class GearContractBo extends BaseEntity {
|
||||
|
||||
@NotNull(message = "合同ID不能为空", groups = {EditGroup.class})
|
||||
private Long contractId;
|
||||
|
||||
@NotBlank(message = "合同号不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String contractNo;
|
||||
|
||||
private String partyA;
|
||||
|
||||
private String partyB;
|
||||
|
||||
private String effectiveFlag;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date signDate;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date deliveryDate;
|
||||
|
||||
private String signPlace;
|
||||
|
||||
private String partyAAddress;
|
||||
|
||||
private String partyBAddress;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date signDateStart;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date signDateEnd;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date deliveryDateStart;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date deliveryDateEnd;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.gear.oa.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.gear.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class GearContractVo extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ExcelProperty(value = "合同ID")
|
||||
private Long contractId;
|
||||
|
||||
@ExcelProperty(value = "合同号")
|
||||
private String contractNo;
|
||||
|
||||
@ExcelProperty(value = "甲方/供方")
|
||||
private String partyA;
|
||||
|
||||
@ExcelProperty(value = "乙方/需方")
|
||||
private String partyB;
|
||||
|
||||
@ExcelProperty(value = "是否生效")
|
||||
private String effectiveFlag;
|
||||
|
||||
@ExcelProperty(value = "签订日期")
|
||||
private Date signDate;
|
||||
|
||||
@ExcelProperty(value = "交货日期")
|
||||
private Date deliveryDate;
|
||||
|
||||
@ExcelProperty(value = "签订地点")
|
||||
private String signPlace;
|
||||
|
||||
@ExcelProperty(value = "甲方地址")
|
||||
private String partyAAddress;
|
||||
|
||||
@ExcelProperty(value = "乙方地址")
|
||||
private String partyBAddress;
|
||||
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gear.oa.mapper;
|
||||
|
||||
import com.gear.common.core.mapper.BaseMapperPlus;
|
||||
import com.gear.oa.domain.GearContract;
|
||||
import com.gear.oa.domain.vo.GearContractVo;
|
||||
|
||||
public interface GearContractMapper extends BaseMapperPlus<GearContractMapper, GearContract, GearContractVo> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gear.oa.service;
|
||||
|
||||
import com.gear.common.core.domain.PageQuery;
|
||||
import com.gear.common.core.page.TableDataInfo;
|
||||
import com.gear.oa.domain.bo.GearContractBo;
|
||||
import com.gear.oa.domain.vo.GearContractVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface IGearContractService {
|
||||
|
||||
GearContractVo queryById(Long contractId);
|
||||
|
||||
TableDataInfo<GearContractVo> queryPageList(GearContractBo bo, PageQuery pageQuery);
|
||||
|
||||
List<GearContractVo> queryList(GearContractBo bo);
|
||||
|
||||
Boolean insertByBo(GearContractBo bo);
|
||||
|
||||
Boolean updateByBo(GearContractBo bo);
|
||||
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.gear.oa.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gear.common.core.domain.PageQuery;
|
||||
import com.gear.common.core.page.TableDataInfo;
|
||||
import com.gear.common.utils.StringUtils;
|
||||
import com.gear.oa.domain.GearContract;
|
||||
import com.gear.oa.domain.bo.GearContractBo;
|
||||
import com.gear.oa.domain.vo.GearContractVo;
|
||||
import com.gear.oa.mapper.GearContractMapper;
|
||||
import com.gear.oa.service.IGearContractService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class GearContractServiceImpl implements IGearContractService {
|
||||
|
||||
private final GearContractMapper baseMapper;
|
||||
|
||||
@Override
|
||||
public GearContractVo queryById(Long contractId) {
|
||||
return baseMapper.selectVoById(contractId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<GearContractVo> queryPageList(GearContractBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<GearContract> lqw = buildQueryWrapper(bo);
|
||||
Page<GearContractVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GearContractVo> queryList(GearContractBo bo) {
|
||||
LambdaQueryWrapper<GearContract> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<GearContract> buildQueryWrapper(GearContractBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<GearContract> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(bo.getContractId() != null, GearContract::getContractId, bo.getContractId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getContractNo()), GearContract::getContractNo, bo.getContractNo());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getPartyA()), GearContract::getPartyA, bo.getPartyA());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getPartyB()), GearContract::getPartyB, bo.getPartyB());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getEffectiveFlag()), GearContract::getEffectiveFlag, bo.getEffectiveFlag());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSignPlace()), GearContract::getSignPlace, bo.getSignPlace());
|
||||
lqw.ge(bo.getSignDateStart() != null, GearContract::getSignDate, bo.getSignDateStart());
|
||||
lqw.le(bo.getSignDateEnd() != null, GearContract::getSignDate, bo.getSignDateEnd());
|
||||
lqw.ge(bo.getDeliveryDateStart() != null, GearContract::getDeliveryDate, bo.getDeliveryDateStart());
|
||||
lqw.le(bo.getDeliveryDateEnd() != null, GearContract::getDeliveryDate, bo.getDeliveryDateEnd());
|
||||
lqw.orderByDesc(GearContract::getSignDate);
|
||||
lqw.orderByDesc(GearContract::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean insertByBo(GearContractBo bo) {
|
||||
GearContract add = BeanUtil.toBean(bo, GearContract.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean ok = baseMapper.insert(add) > 0;
|
||||
if (ok) {
|
||||
bo.setContractId(add.getContractId());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateByBo(GearContractBo bo) {
|
||||
GearContract update = BeanUtil.toBean(bo, GearContract.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
private void validEntityBeforeSave(GearContract entity) {
|
||||
boolean isInsert = entity.getContractId() == null;
|
||||
if (entity.getContractId() == null) {
|
||||
entity.setContractId(IdUtil.getSnowflakeNextId());
|
||||
}
|
||||
if (StringUtils.isBlank(entity.getContractNo())) {
|
||||
entity.setContractNo("CON_" + IdUtil.getSnowflakeNextIdStr());
|
||||
}
|
||||
if (StringUtils.isBlank(entity.getEffectiveFlag())) {
|
||||
entity.setEffectiveFlag("0");
|
||||
}
|
||||
if (isInsert) {
|
||||
if (StringUtils.isBlank(entity.getDelFlag())) {
|
||||
entity.setDelFlag("0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,3 +29,46 @@ export function completeProductionTask(taskId) {
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function uncompleteProductionTask(taskId) {
|
||||
return request({
|
||||
url: '/mes/production/task/' + taskId + '/uncomplete',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function startProductionTask(taskId) {
|
||||
return request({
|
||||
url: '/mes/production/task/' + taskId + '/start',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function pauseProductionTask(taskId) {
|
||||
return request({
|
||||
url: '/mes/production/task/' + taskId + '/pause',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function resumeProductionTask(taskId) {
|
||||
return request({
|
||||
url: '/mes/production/task/' + taskId + '/resume',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function updateProductionTask(data) {
|
||||
return request({
|
||||
url: '/mes/production/task',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteProductionTask(taskId) {
|
||||
return request({
|
||||
url: '/mes/production/task/' + taskId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
40
gear-ui3/src/api/oms/contract.js
Normal file
40
gear-ui3/src/api/oms/contract.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listContract(query) {
|
||||
return request({
|
||||
url: '/oa/contract/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getContract(contractId) {
|
||||
return request({
|
||||
url: '/oa/contract/' + contractId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addContract(data) {
|
||||
return request({
|
||||
url: '/oa/contract',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateContract(data) {
|
||||
return request({
|
||||
url: '/oa/contract',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function delContract(contractId) {
|
||||
return request({
|
||||
url: '/oa/contract/' + contractId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<el-form :inline="true" class="filter-form">
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="filters.status" placeholder="全部" clearable style="width: 140px;">
|
||||
<el-option label="未开始" value="0" />
|
||||
<el-option label="进行中" value="1" />
|
||||
<el-option label="已完成" value="2" />
|
||||
<el-option label="已暂停" value="3" />
|
||||
@@ -101,7 +102,7 @@
|
||||
<div class="task-item__meta">
|
||||
<span v-if="t.planStartTime || t.planEndTime">计划 {{ formatTimeRange(t.planStartTime, t.planEndTime) }}</span>
|
||||
<span v-if="t.createBy" style="margin-left: 10px;">创建 {{ t.createBy }}</span>
|
||||
<span v-if="t.updateTime" style="margin-left: 10px;">更新 {{ formatTime(t.updateTime) }}</span>
|
||||
<span v-if="t.updateTime" style="margin-left: 10px;">状态 {{ statusLabel(t.status) }} {{ formatTime(t.updateTime) }}</span>
|
||||
</div>
|
||||
<el-progress :percentage="taskProgressPercent(t)" :stroke-width="8" :show-text="false" />
|
||||
</div>
|
||||
@@ -120,15 +121,15 @@
|
||||
<span class="meta-main">{{ selectedTask.taskName || selectedTask.taskCode || ('任务' + selectedTask.taskId) }}</span>
|
||||
<el-tag size="small" :type="statusTagType(selectedTask.status)" effect="light" style="margin-left: 8px;">{{ statusLabel(selectedTask.status) }}</el-tag>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="String(selectedTask.status) === '1'"
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="completeLoading"
|
||||
@click="completeSelectedTask"
|
||||
>
|
||||
完成任务
|
||||
</el-button>
|
||||
<div class="task-actions">
|
||||
<el-button v-if="String(selectedTask.status) === '0'" size="small" type="success" :loading="statusLoading" @click="startSelectedTask">开始</el-button>
|
||||
<el-button v-if="String(selectedTask.status) === '1'" size="small" type="warning" :loading="statusLoading" @click="pauseSelectedTask">暂停</el-button>
|
||||
<el-button v-if="String(selectedTask.status) === '3'" size="small" type="success" :loading="statusLoading" @click="resumeSelectedTask">继续</el-button>
|
||||
<el-button v-if="String(selectedTask.status) !== '2'" size="small" type="primary" :loading="completeLoading" @click="completeSelectedTask">完成</el-button>
|
||||
<el-button v-if="String(selectedTask.status) === '2'" size="small" type="warning" :loading="statusLoading" @click="uncompleteSelectedTask">撤销完成</el-button>
|
||||
<el-button v-if="String(selectedTask.status) !== '2'" size="small" @click="openEdit">编辑</el-button>
|
||||
<el-button size="small" type="danger" :loading="deleteLoading" @click="deleteSelectedTask">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -225,8 +226,8 @@
|
||||
<el-col :span="8">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="addForm.status" placeholder="请选择">
|
||||
<el-option label="未开始" value="0" />
|
||||
<el-option label="进行中" value="1" />
|
||||
<el-option label="已完成" value="2" />
|
||||
<el-option label="已暂停" value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -288,12 +289,83 @@
|
||||
<el-button type="primary" :loading="addSaving" @click="submitAdd">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="editOpen" title="编辑生产任务" width="1100px" top="5vh" append-to-body>
|
||||
<el-form ref="editFormRef" :model="editForm" :rules="addRules" label-width="100px">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="任务编号" prop="taskCode">
|
||||
<el-input v-model="editForm.taskCode" placeholder="可不填" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="任务名称" prop="taskName">
|
||||
<el-input v-model="editForm.taskName" placeholder="请输入任务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="计划开始" prop="planStartTime">
|
||||
<el-date-picker v-model="editForm.planStartTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="计划结束" prop="planEndTime">
|
||||
<el-date-picker v-model="editForm.planEndTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="editForm.remark" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider content-position="left">生产产品明细</el-divider>
|
||||
<div style="margin-bottom: 8px;">
|
||||
<el-button type="primary" @click="addEditProductLine">新增产品行</el-button>
|
||||
</div>
|
||||
<el-table :data="editProducts" border size="small" :header-cell-style="{ background: '#f5f7fa' }">
|
||||
<el-table-column label="产品" min-width="220">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.productId" filterable clearable placeholder="请选择" style="width: 100%;" @change="onProductPicked(scope.row)">
|
||||
<el-option v-for="p in productOptions" :key="p.productId" :label="p.productName" :value="p.productId" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划数量" width="140" align="right">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.planQty" :min="0" :precision="4" controls-position="right" style="width: 120px;" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" width="140">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.unit" placeholder="单位" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="200">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.remark" placeholder="备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link @click="removeEditProductLine(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="editOpen = false">取消</el-button>
|
||||
<el-button type="primary" :loading="editSaving" @click="submitEdit">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Production">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { addProductionTask, completeProductionTask, getProductionTask, listProductionTask } from '@/api/mes/productionTask'
|
||||
import { addProductionTask, completeProductionTask, deleteProductionTask, getProductionTask, listProductionTask, pauseProductionTask, resumeProductionTask, startProductionTask, uncompleteProductionTask, updateProductionTask } from '@/api/mes/productionTask'
|
||||
import { listProductBase } from '@/api/mat/product'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
@@ -315,11 +387,13 @@ const filters = ref({
|
||||
const addOpen = ref(false)
|
||||
const addSaving = ref(false)
|
||||
const completeLoading = ref(false)
|
||||
const statusLoading = ref(false)
|
||||
const deleteLoading = ref(false)
|
||||
const addFormRef = ref()
|
||||
const addForm = ref({
|
||||
taskCode: '',
|
||||
taskName: '',
|
||||
status: '1',
|
||||
status: '0',
|
||||
planStartTime: '',
|
||||
planEndTime: '',
|
||||
remark: ''
|
||||
@@ -330,6 +404,18 @@ const addRules = {
|
||||
|
||||
const productOptions = ref([])
|
||||
const addProducts = ref([])
|
||||
const editOpen = ref(false)
|
||||
const editSaving = ref(false)
|
||||
const editFormRef = ref()
|
||||
const editForm = ref({
|
||||
taskId: null,
|
||||
taskCode: '',
|
||||
taskName: '',
|
||||
planStartTime: '',
|
||||
planEndTime: '',
|
||||
remark: ''
|
||||
})
|
||||
const editProducts = ref([])
|
||||
|
||||
function toNumber(v) {
|
||||
const n = Number(v)
|
||||
@@ -457,6 +543,7 @@ function onCustomRangePicked(v) {
|
||||
|
||||
function statusLabel(v) {
|
||||
const s = String(v || '')
|
||||
if (s === '0') return '未开始'
|
||||
if (s === '1') return '进行中'
|
||||
if (s === '2') return '已完成'
|
||||
if (s === '3') return '已暂停'
|
||||
@@ -465,6 +552,7 @@ function statusLabel(v) {
|
||||
|
||||
function statusTagType(v) {
|
||||
const s = String(v || '')
|
||||
if (s === '0') return 'info'
|
||||
if (s === '1') return 'success'
|
||||
if (s === '2') return 'danger'
|
||||
if (s === '3') return 'warning'
|
||||
@@ -548,7 +636,7 @@ function openAdd() {
|
||||
addForm.value = {
|
||||
taskCode: '',
|
||||
taskName: '',
|
||||
status: '1',
|
||||
status: '0',
|
||||
planStartTime: '',
|
||||
planEndTime: '',
|
||||
remark: ''
|
||||
@@ -625,6 +713,7 @@ function submitAdd() {
|
||||
const taskId = res && res.data ? res.data : null
|
||||
ElMessage.success('已新增')
|
||||
addOpen.value = false
|
||||
filters.value.status = ''
|
||||
return loadTasks().then(() => {
|
||||
if (taskId != null) {
|
||||
selectedTaskId.value = taskId
|
||||
@@ -638,6 +727,75 @@ function submitAdd() {
|
||||
})
|
||||
}
|
||||
|
||||
function openEdit() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
ensureProductOptions()
|
||||
loading.value = true
|
||||
return getProductionTask(taskId)
|
||||
.then((res) => {
|
||||
const data = res && res.data ? res.data : {}
|
||||
const task = data.task || {}
|
||||
editForm.value = {
|
||||
taskId: task.taskId,
|
||||
taskCode: task.taskCode || '',
|
||||
taskName: task.taskName || '',
|
||||
planStartTime: task.planStartTime || '',
|
||||
planEndTime: task.planEndTime || '',
|
||||
remark: task.remark || ''
|
||||
}
|
||||
const rows = Array.isArray(data.products) ? data.products : []
|
||||
editProducts.value = rows.map((p) => ({
|
||||
productId: p.productId,
|
||||
planQty: p.planQty || 0,
|
||||
unit: p.unit || '',
|
||||
remark: p.remark || ''
|
||||
}))
|
||||
if (!editProducts.value.length) {
|
||||
editProducts.value = [{ productId: null, planQty: 0, unit: '', remark: '' }]
|
||||
}
|
||||
editOpen.value = true
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function addEditProductLine() {
|
||||
editProducts.value.push({ productId: null, planQty: 0, unit: '', remark: '' })
|
||||
}
|
||||
|
||||
function removeEditProductLine(idx) {
|
||||
editProducts.value.splice(idx, 1)
|
||||
}
|
||||
|
||||
function submitEdit() {
|
||||
if (!editFormRef.value) return
|
||||
editFormRef.value.validate((valid) => {
|
||||
if (!valid) return
|
||||
const task = Object.assign({}, editForm.value)
|
||||
const products = mergeProductLines(editProducts.value).map((p) => ({
|
||||
productId: p.productId,
|
||||
planQty: p.planQty || 0,
|
||||
unit: p.unit || '',
|
||||
remark: p.remark || ''
|
||||
}))
|
||||
editSaving.value = true
|
||||
updateProductionTask({ task, products })
|
||||
.then(() => {
|
||||
ElMessage.success('已保存')
|
||||
editOpen.value = false
|
||||
const taskId = selectedTaskId.value
|
||||
return loadTasks().then(() => {
|
||||
if (taskId != null) return selectTask(taskId)
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
editSaving.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function completeSelectedTask() {
|
||||
const task = selectedTask.value
|
||||
const taskId = selectedTaskId.value
|
||||
@@ -664,6 +822,101 @@ function completeSelectedTask() {
|
||||
})
|
||||
}
|
||||
|
||||
function uncompleteSelectedTask() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
statusLoading.value = true
|
||||
return ElMessageBox.confirm('撤销完成后将回到进行中,且回执会清空(再次完成会重新生成),是否继续?', '确认撤销', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => uncompleteProductionTask(taskId))
|
||||
.then(() => {
|
||||
ElMessage.success('已撤销完成')
|
||||
return loadTasks().then(() => selectTask(taskId))
|
||||
})
|
||||
.catch((e) => {
|
||||
const s = String(e || '')
|
||||
if (s && s !== 'cancel' && s !== 'close') {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
statusLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function startSelectedTask() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
statusLoading.value = true
|
||||
return startProductionTask(taskId)
|
||||
.then(() => {
|
||||
ElMessage.success('已开始')
|
||||
return loadTasks().then(() => selectTask(taskId))
|
||||
})
|
||||
.finally(() => {
|
||||
statusLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function pauseSelectedTask() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
statusLoading.value = true
|
||||
return pauseProductionTask(taskId)
|
||||
.then(() => {
|
||||
ElMessage.success('已暂停')
|
||||
return loadTasks().then(() => selectTask(taskId))
|
||||
})
|
||||
.finally(() => {
|
||||
statusLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function resumeSelectedTask() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
statusLoading.value = true
|
||||
return resumeProductionTask(taskId)
|
||||
.then(() => {
|
||||
ElMessage.success('已继续')
|
||||
return loadTasks().then(() => selectTask(taskId))
|
||||
})
|
||||
.finally(() => {
|
||||
statusLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function deleteSelectedTask() {
|
||||
const taskId = selectedTaskId.value
|
||||
if (taskId == null) return
|
||||
deleteLoading.value = true
|
||||
return ElMessageBox.confirm('删除后将不在列表展示,是否继续?', '确认删除', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => deleteProductionTask(taskId))
|
||||
.then(() => {
|
||||
ElMessage.success('已删除')
|
||||
selectedTaskId.value = null
|
||||
productRows.value = []
|
||||
materialRows.value = []
|
||||
return loadTasks()
|
||||
})
|
||||
.catch((e) => {
|
||||
const s = String(e || '')
|
||||
if (s && s !== 'cancel' && s !== 'close') {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
deleteLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
applyDatePreset()
|
||||
})
|
||||
@@ -695,6 +948,12 @@ onMounted(() => {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.task-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.card-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
284
gear-ui3/src/views/oms/contractEdit/index.vue
Normal file
284
gear-ui3/src/views/oms/contractEdit/index.vue
Normal file
@@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form ref="queryRef" :model="queryParams" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="合同号" prop="contractNo">
|
||||
<el-input v-model="queryParams.contractNo" placeholder="请输入合同号" clearable @keyup.enter="handleQuery" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="供方" prop="partyA">
|
||||
<el-input v-model="queryParams.partyA" placeholder="请输入供方" clearable @keyup.enter="handleQuery" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="需方" prop="partyB">
|
||||
<el-input v-model="queryParams.partyB" placeholder="请输入需方" clearable @keyup.enter="handleQuery" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="已生效" prop="effectiveFlag">
|
||||
<el-select v-model="queryParams.effectiveFlag" placeholder="全部" clearable style="width: 140px">
|
||||
<el-option label="否" value="0" />
|
||||
<el-option label="是" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="签订日期">
|
||||
<el-date-picker
|
||||
v-model="queryParams.signDateRange"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 260px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="交货日期">
|
||||
<el-date-picker
|
||||
v-model="queryParams.deliveryDateRange"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 260px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="签订地点" prop="signPlace">
|
||||
<el-input v-model="queryParams.signPlace" placeholder="请输入签订地点" clearable @keyup.enter="handleQuery" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="small" type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button size="small" icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="mb8 toolbar">
|
||||
<el-button size="small" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
|
||||
<div class="toolbar-right">
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="contractList">
|
||||
<el-table-column label="合同号" prop="contractNo" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.contractNo" />
|
||||
<span v-else>{{ row.contractNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供方" prop="partyA" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.partyA" />
|
||||
<span v-else>{{ row.partyA }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="需方" prop="partyB" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.partyB" />
|
||||
<span v-else>{{ row.partyB }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="签订日期" prop="signDate" width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-date-picker
|
||||
v-if="isEditing(row)"
|
||||
v-model="editRow.signDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
style="width: 120px"
|
||||
/>
|
||||
<span v-else>{{ formatDate(row.signDate) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="交货日期" prop="deliveryDate" width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-date-picker
|
||||
v-if="isEditing(row)"
|
||||
v-model="editRow.deliveryDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
style="width: 120px"
|
||||
/>
|
||||
<span v-else>{{ formatDate(row.deliveryDate) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="签订地点" prop="signPlace" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.signPlace" />
|
||||
<span v-else>{{ row.signPlace }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供方地址" prop="partyAAddress" min-width="260" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<el-input v-if="isEditing(row)" v-model="editRow.partyAAddress" />
|
||||
<span v-else>{{ row.partyAAddress }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已生效" prop="effectiveFlag" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-select v-if="isEditing(row)" v-model="editRow.effectiveFlag" style="width: 90px">
|
||||
<el-option label="否" value="0" />
|
||||
<el-option label="是" value="1" />
|
||||
</el-select>
|
||||
<el-tag v-else :type="row.effectiveFlag === '1' ? 'success' : 'info'" effect="light">{{ row.effectiveFlag === '1' ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="{ row }">
|
||||
<template v-if="isEditing(row)">
|
||||
<el-button link type="primary" icon="Check" :loading="saving" @click="saveRow">保存</el-button>
|
||||
<el-button link type="primary" icon="Close" :disabled="saving" @click="cancelEdit">取消</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button link type="primary" icon="Edit" :disabled="editingId !== null" @click="startEdit(row)">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" :disabled="editingId !== null" @click="deleteRow(row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="ContractEdit">
|
||||
import { getCurrentInstance, onMounted, ref } from 'vue'
|
||||
import { delContract, listContract, updateContract } from '@/api/oms/contract'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const showSearch = ref(true)
|
||||
const loading = ref(false)
|
||||
const total = ref(0)
|
||||
const contractList = ref([])
|
||||
const queryRef = ref()
|
||||
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
contractNo: '',
|
||||
partyA: '',
|
||||
partyB: '',
|
||||
effectiveFlag: '',
|
||||
signDateRange: [],
|
||||
deliveryDateRange: [],
|
||||
signPlace: ''
|
||||
})
|
||||
|
||||
const editingId = ref(null)
|
||||
const editRow = ref({})
|
||||
const saving = ref(false)
|
||||
|
||||
function buildQuery() {
|
||||
const q = { ...queryParams.value }
|
||||
const signRange = Array.isArray(q.signDateRange) ? q.signDateRange : []
|
||||
const deliveryRange = Array.isArray(q.deliveryDateRange) ? q.deliveryDateRange : []
|
||||
delete q.signDateRange
|
||||
delete q.deliveryDateRange
|
||||
q.signDateStart = signRange[0] ? `${signRange[0]} 00:00:00` : ''
|
||||
q.signDateEnd = signRange[1] ? `${signRange[1]} 23:59:59` : ''
|
||||
q.deliveryDateStart = deliveryRange[0] ? `${deliveryRange[0]} 00:00:00` : ''
|
||||
q.deliveryDateEnd = deliveryRange[1] ? `${deliveryRange[1]} 23:59:59` : ''
|
||||
return q
|
||||
}
|
||||
|
||||
function getList() {
|
||||
loading.value = true
|
||||
return listContract(buildQuery())
|
||||
.then((res) => {
|
||||
contractList.value = res?.rows || []
|
||||
total.value = res?.total || 0
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
queryRef.value?.resetFields()
|
||||
queryParams.value.signDateRange = []
|
||||
queryParams.value.deliveryDateRange = []
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
function isEditing(row) {
|
||||
return row && editingId.value != null && String(row.contractId) === String(editingId.value)
|
||||
}
|
||||
|
||||
function startEdit(row) {
|
||||
editingId.value = row.contractId
|
||||
editRow.value = {
|
||||
contractId: row.contractId,
|
||||
contractNo: row.contractNo || '',
|
||||
partyA: row.partyA || '',
|
||||
partyB: row.partyB || '',
|
||||
effectiveFlag: row.effectiveFlag != null ? String(row.effectiveFlag) : '0',
|
||||
signDate: row.signDate ? formatDate(row.signDate) : '',
|
||||
deliveryDate: row.deliveryDate ? formatDate(row.deliveryDate) : '',
|
||||
signPlace: row.signPlace || '',
|
||||
partyAAddress: row.partyAAddress || '',
|
||||
partyBAddress: row.partyBAddress || '',
|
||||
remark: row.remark || ''
|
||||
}
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
editingId.value = null
|
||||
editRow.value = {}
|
||||
}
|
||||
|
||||
function saveRow() {
|
||||
if (!editRow.value?.contractId) return
|
||||
saving.value = true
|
||||
return updateContract({ ...editRow.value })
|
||||
.then(() => {
|
||||
proxy.$modal.msgSuccess('保存成功')
|
||||
cancelEdit()
|
||||
return getList()
|
||||
})
|
||||
.finally(() => {
|
||||
saving.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function deleteRow(row) {
|
||||
if (!row?.contractId) return
|
||||
proxy.$modal.confirm('是否确认删除该合同?').then(() => {
|
||||
return delContract(row.contractId)
|
||||
}).then(() => {
|
||||
proxy.$modal.msgSuccess('删除成功')
|
||||
cancelEdit()
|
||||
getList()
|
||||
})
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
proxy.download('oa/contract/export', {
|
||||
...buildQuery()
|
||||
}, `contract_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
function formatDate(v) {
|
||||
if (!v) return ''
|
||||
const d = new Date(v)
|
||||
if (Number.isNaN(d.getTime())) return ''
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -500,21 +500,26 @@ function handleAdd() {
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
const userId = row.userId || ids.value
|
||||
// let userId
|
||||
// if (row && row.userId) {
|
||||
// userId = row.userId
|
||||
// } else if (ids.value && ids.value.length > 0) {
|
||||
// userId = ids.value[0]
|
||||
// } else {
|
||||
// return
|
||||
// }
|
||||
let userId
|
||||
if (row && row.userId) {
|
||||
userId = row.userId
|
||||
} else if (ids.value && ids.value.length > 0) {
|
||||
userId = ids.value[0]
|
||||
} else {
|
||||
return
|
||||
}
|
||||
getUser(userId).then(response => {
|
||||
form.value = response.data
|
||||
postOptions.value = response.data.posts
|
||||
roleOptions.value = response.data.roles
|
||||
form.value.postIds = response.data.postIds
|
||||
form.value.roleIds = response.data.roleIds
|
||||
const data = response && response.data ? response.data : {}
|
||||
const user = data.user ? data.user : {}
|
||||
form.value = {
|
||||
...form.value,
|
||||
...user,
|
||||
deptId: user.deptId != null ? Number(user.deptId) : undefined,
|
||||
postIds: Array.isArray(data.postIds) ? data.postIds.map((v) => Number(v)) : [],
|
||||
roleIds: Array.isArray(data.roleIds) ? data.roleIds.map((v) => Number(v)) : []
|
||||
}
|
||||
postOptions.value = data.posts || []
|
||||
roleOptions.value = data.roles || []
|
||||
open.value = true
|
||||
title.value = "修改用户"
|
||||
form.value.password = ""
|
||||
|
||||
35
script/sql/mysql/item/gear_contract.sql
Normal file
35
script/sql/mysql/item/gear_contract.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
-- ================================
|
||||
-- 合同编辑(用于“销售管理 -> 合同编辑详情”)
|
||||
-- 目标:提供合同基础信息维护与快速编辑能力(列表行内修改/保存)
|
||||
-- 说明:
|
||||
-- 1) 单表存储合同主信息;与订单/客户关系后续可扩展
|
||||
-- 2) 逻辑删除使用 del_flag(0存在 2删除)
|
||||
-- ================================
|
||||
|
||||
DROP TABLE IF EXISTS gear_contract;
|
||||
CREATE TABLE gear_contract (
|
||||
contract_id bigint(20) NOT NULL COMMENT '合同ID',
|
||||
contract_no varchar(64) NOT NULL COMMENT '合同号(唯一)',
|
||||
party_a varchar(255) DEFAULT '' COMMENT '甲方/供方',
|
||||
party_b varchar(255) DEFAULT '' COMMENT '乙方/需方',
|
||||
effective_flag char(1) NOT NULL DEFAULT '0' COMMENT '是否生效(0否 1是)',
|
||||
sign_date date COMMENT '签订日期',
|
||||
delivery_date date COMMENT '交货日期',
|
||||
sign_place varchar(255) DEFAULT '' COMMENT '签订地点',
|
||||
party_a_address varchar(255) DEFAULT '' COMMENT '甲方地址',
|
||||
party_b_address varchar(255) DEFAULT '' COMMENT '乙方地址',
|
||||
remark varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
del_flag char(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0存在 2删除)',
|
||||
create_by varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
create_time datetime COMMENT '创建时间',
|
||||
update_by varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
update_time datetime COMMENT '更新时间',
|
||||
PRIMARY KEY (contract_id),
|
||||
UNIQUE KEY uk_contract_no (contract_no),
|
||||
KEY idx_sign_date (sign_date),
|
||||
KEY idx_delivery_date (delivery_date),
|
||||
KEY idx_effective_flag (effective_flag),
|
||||
KEY idx_party_a (party_a),
|
||||
KEY idx_party_b (party_b)
|
||||
) ENGINE=InnoDB COMMENT='合同表(编辑详情)';
|
||||
|
||||
@@ -204,3 +204,5 @@ INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`
|
||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2041777949048430593, '工人管理', 1952975318515830785, 21, 'worker', 'oms/worker/index', NULL, 1, 0, 'C', '0', '0', NULL, 'user', 'admin', '2026-04-08 15:19:32', 'admin', '2026-04-13 16:32:20', '');
|
||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2041786163248885761, '薪资录入', 1952975318515830785, 97, 'wageEntryDetail', 'oms/wageEntryDetail/index', NULL, 1, 0, 'C', '0', '0', NULL, 'edit', 'admin', '2026-04-08 15:52:11', 'admin', '2026-04-08 15:52:11', '');
|
||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2041816674390265858, '薪资补录', 1952975318515830785, 98, 'wageMakeup', 'oms/wageMakeup/index', NULL, 1, 0, 'C', '0', '0', NULL, 'edit', 'admin', '2026-04-08 17:53:25', 'admin', '2026-04-08 17:53:25', '');
|
||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2060000000000000001, '合同编辑', 1962721165348478977, 8, 'contract', NULL, NULL, 1, 0, 'M', '0', '0', NULL, 'edit', 'admin', '2026-05-28 10:00:00', 'admin', '2026-05-28 10:00:00', '');
|
||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2060000000000000002, '合同编辑详情', 2060000000000000001, 1, 'editDetail', 'oms/contractEdit/index', NULL, 1, 0, 'C', '0', '0', NULL, 'table', 'admin', '2026-05-28 10:00:00', 'admin', '2026-05-28 10:00:00', '');
|
||||
|
||||
Reference in New Issue
Block a user