feat(flowable): 新增审批人配置功能

- 添加审批人配置页面和相关接口
- 实现审批人和审批角色的选择和保存功能
- 优化工作流展示页面,支持显示已配置的审批信息
dev_1.0.0
chenhao 2025-07-31 09:30:32 +08:00
parent a217cd48c6
commit d99bf79480
59 changed files with 2027 additions and 315 deletions

View File

@ -4,8 +4,16 @@ package com.ruoyi.web.controller.flowable;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.dto.ApproveConfigDto;
import com.ruoyi.sip.flowable.domain.BuApproveConfig;
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
@ -20,7 +28,9 @@ import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.image.ProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.system.domain.Process;
@ -30,7 +40,10 @@ import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;
/**
@ -49,11 +62,20 @@ public class FlowController {
@Resource
RepositoryService repositoryService;
@Autowired
private IBuApproveConfigService approveConfigService;
@Autowired
private ISysRoleService roleService;
@Autowired
private ISysUserService userService;
@Resource
ProcessEngineConfiguration configuration;
private String prefix = "flowable/manage";
@Autowired
private SysUserMapper sysUserMapper;
@GetMapping("")
public String processList()
@ -145,14 +167,41 @@ public class FlowController {
ServletOutputStream output = response.getOutputStream();
IOUtils.copy(is, output);
}
@ApiOperation("查看工作流图片")
@ApiOperation("审批人配置")
@RequestMapping(value = "/approveUser", method = RequestMethod.GET)
public String approveUser(@RequestParam("pdid") String pdid,
HttpServletResponse response) throws Exception {
HttpServletResponse response, ModelMap modelMap) throws Exception {
BpmnModel bpmnModel = repositoryService.getBpmnModel(pdid);
List<org.flowable.bpmn.model.Process> processesList = bpmnModel.getProcesses();
List<BuApproveConfig> buApproveConfigs = approveConfigService.listByProcess(processesList.get(0));
modelMap.put("approveConfig",buApproveConfigs);
List<SysRole> sysRoles = roleService.selectRoleAll();
modelMap.put("roles",sysRoles);
// bpmnModel.getProcesses().get(0).findFlowElementsOfType(UserTask.class);
return "flowable/manage/approveUser";
}
@GetMapping(value = "/selectPeople")
public String approveUser(@RequestParam(value = "user",required = false)String chooseUser, ModelMap modelMap) {
List<SysUser> sysUsers = Collections.emptyList();
List<Long> userId = Collections.emptyList();
if (StringUtils.isNotEmpty(chooseUser)) {
SysUser sysUser = new SysUser();
userId = Arrays.stream(chooseUser.split(",")).map(Long::parseLong).collect(Collectors.toList());
sysUser.setUserIdList(userId);
sysUsers = sysUserMapper.selectUserList(sysUser);
}
modelMap.put("chooseUserArr",sysUsers);
modelMap.put("chooseUserId",userId);
return "flowable/manage/selectPeople";
}
@ApiOperation("审批人配置")
@PostMapping(value = "/approveUser")
@ResponseBody
public AjaxResult approveUser(ApproveConfigDto approveConfigDto) {
approveConfigService.saveBatch(approveConfigDto.getApproveConfigList());
return AjaxResult.success();
}
@ApiOperation("查看工作流定义")
@RequestMapping(value = "/showProcessDefinition", method = RequestMethod.GET)

View File

@ -62,4 +62,10 @@ spring:
merge-sql: true
wall:
config:
multi-statement-allow: true
multi-statement-allow: true
unis:
order:
# 执行单截止时间
endHour: 96
mail:
enabled: false

View File

@ -113,7 +113,7 @@ shiro:
cipherKey:
session:
# Session超时时间-1代表永不过期默认30分钟
expireTime: 30
expireTime: 120
# 同步session到数据库的周期默认1分钟
dbSyncPeriod: 1
# 相隔多久检查一次session的有效性默认就是10分钟
@ -154,4 +154,6 @@ process:
unis:
order:
# 执行单截止时间
endHour: 96
endHour: 96
mail:
enabled: true

View File

@ -1,53 +1,99 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增模型')" />
<th:block th:include="include :: header('编辑审批人')" />
<th:block th:include="include :: datetimepicker-css" />
<th:block th:include="include :: select2-css" />
<th:block th:include="include :: bootstrap-select-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="model-add">
<div class="form-group">
<label class="col-sm-3 control-label">模型标识:</label>
<div class="col-sm-8">
<input name="key" class="form-control" type="text" required>
<form class="form-horizontal m" id="model-approve-edit">
<div class="row" th:each="info : ${approveConfig}">
<div class="col-xs-2">
<div class="form-group">
<label class=" control-label">流程节点:[[${info.taskName}]]</label>
<input type="hidden" th:name="${'approveConfigList['+infoStat.index+'].id'}" th:value="${info.id}">
<input type="hidden" th:name="${'approveConfigList['+infoStat.index+'].processKey'}" th:value="${info.processKey}">
<input type="hidden" th:name="${'approveConfigList['+infoStat.index+'].taskName'}" th:value="${info.taskName}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">模型名称:</label>
<div class="col-sm-8">
<input name="name" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">分类:</label>
<div class="col-sm-8">
<input name="category" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">描述:</label>
<div class="col-sm-8">
<textarea type="text" name="description" class="form-control" placeholder="请输入文本"></textarea>
<div class="col-xs-5">
<div class="form-group">
<label class="col-sm-4 control-label">审批人:</label>
<div class="col-sm-8">
<input type="hidden" th:name="${'approveConfigList['+infoStat.index+'].approveUser'}" th:value="${info.approveUser}">
<input type="text" th:onclick="selectPeople([[${infoStat.index}]])" readonly th:name="${'approveConfigList['+infoStat.index+'].approveUserName'}" th:value="${info.approveUserName}">
</div>
</div>
</div>
<div class="col-xs-5">
<div class="form-group">
<label class="col-sm-4 control-label">审批角色:</label>
<div class="col-sm-8">
<select class="form-control noselect2 selectpicker" th:data-selected="${info.approveRole}" th:name="${'approveConfigList['+infoStat.index+'].approveRole'}" data-none-selected-text="请选择审批角色" multiple>
<option th:each="role : ${roles}" th:value="${role.roleId.toString()}"
th:selected="${info.approveRoleList.contains(role.roleId.toString())}">[[${role.roleName}]]</option>
</select>
</div>
</div>
</div>
</div>
</form>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<th:block th:include="include :: select2-js" />
<th:block th:include="include :: bootstrap-select-js" />
<script th:inline="javascript">
var prefix = ctx + "model/manage"
var prefix = ctx + "flow/manage"
$("#form-leaveapply-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#model-add').serialize());
$.operate.save(prefix + "/approveUser", $('#model-approve-edit').serialize());
}
}
function selectPeople(listIndex) {
let approveUser = $(`input[name="approveConfigList[${listIndex}].approveUser"]`).val()
var url = prefix + "/selectPeople?user="+(approveUser?approveUser:"");
top.layer.open($.extend({
id: 'chooseApproveUser', // 唯一id
type: 2,
maxmin: true ,
shade: 0.3,
title: '选择审批人',
fix: false,
area: [ '680px', '680px'],
content: url,
btn: ['确定', '取消'],
shadeClose: true ,
yes: function ( index,layero){
doSubmitPeople(index, layero,listIndex)
},
cancel: function () {
return true;
}
}));
}
function doSubmitPeople(index, layero,listIndex) {
var rows = layero.find("iframe")[0].contentWindow.getSelections();
$.modal.close(index);
let nameDomKey=`input[name="approveConfigList[${listIndex}].approveUserName"]`
$(nameDomKey).val(rows.map(item=>item.userName).join(","))
let idDomKey=`input[name="approveConfigList[${listIndex}].approveUser"]`
$(idDomKey).val(rows.map(item=>item.userId).join(","))
}
$(function(){
})
</script>
</body>

View File

@ -95,7 +95,7 @@
});
}
function approveUser(id){
$.modal.open('上传部署文件', '/flow/manage/approveUser?pdid='+id, '800', '650');
$.modal.open('审批人配置', '/flow/manage/approveUser?pdid='+id, '800', '650');
}
</script>
</body>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('选择代理商')"/>
</head>
<style>
.select-list li {
display: inline-block;
}
.select-list li label {
width: 88px !important;
}
</style>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>用户名称:</label>
<input type="text" name="userName"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i
class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer"/>
<script th:inline="javascript">
var prefix = ctx + "system/user";
let checkIds = [[${chooseUserId}]]
let rowArr=[[${chooseUserArr}]]
$(function () {
var options = {
url: prefix + "/list",
showSearch: true,
showToggle: false,
showPageGo: true,
showRefresh: false,
search: false,
params: {},
columns: [{
checkbox: true,
formatter: function (value, row, index) {
if ($.inArray(row.userId, checkIds) != -1) {
return {
checked: true//设置选中
};
} else {
return {
checked: false//设置不选择
};
}
}
},
{
field: 'userName',
title: '人员名称'
},
{
field: 'phonenumber',
title: '人员电话'
},
{
field: 'dept.deptName',
title: '所属部门'
}
],
onCheck: function (row) {
checkIds.push(row.userId);
rowArr.push({userId:row.userId,userName:row.userName})
},
onUncheck: function (row) {
if ($.inArray(row.userId, checkIds) != -1) {
checkIds.splice($.inArray(row.userId, checkIds), 1);
rowArr=rowArr.filter(item=>item.userId!==row.userId);
}
},
onCheckAll: function (rows) {
for (var i = 0; i < rows.length; i++) {
checkIds.push(rows[i].userId);
rowArr.push({userId:rows[i].userId,userName:rows[i].userName})
}
},
onUncheckAll: function (rows) {
for (var i = 0; i < rows.length; i++) {
checkIds.splice($.inArray(rows[i].userId, checkIds), 1);
rowArr=rowArr.filter(item=>item.userId!==rows[i].userId);
}
}
};
$.table.init(options);
});
function getSelections() {
return rowArr.filter(item=>checkIds.includes(item.userId));
}
</script>
</body>
</html>

View File

@ -105,6 +105,19 @@
<script th:inline="javascript"> /*<![CDATA[*/
const updatePriceProductList=['8813A3YA','8813A3YB','8813A7U4','8813A7U2']
const FOLD_ON_FOLD = 0.988;
const productType=[{
name:'softwareProjectProductInfoList',
type:'1',
title:'软件产品'
},{
name:'hardwareProjectProductInfoList',
type:'2',
title:'终端产品'
},{
name:'maintenanceProjectProductInfoList',
type:'11,22,99',
title:'服务产品'
}]
document.addEventListener("DOMContentLoaded", function () {
// 初始化删除逻辑等
// $('.productTable .delRow').on('click', function () {
@ -167,7 +180,8 @@
$('#displayactualPurchaseAmount').val(formatAmountNumber(allPriceDiscount))
}
}
function setTotalData(show,discountFold){
function setTotalData(show, discountFold, id) {
if (!show){
return
}
@ -179,7 +193,7 @@
$('#productTable tbody').find('tr').find('.allPrice').each(function (index) {
allPrice+=parseFloat($(this).val())
})
let softwarePrice=Number(allPrice).toFixed(2);
let softwarePrice=formatAmountNumber(allPrice);
let softwareHtml=$( `<span class="total-price" style="
font-size: 20px;
font-weight: bold;
@ -193,7 +207,7 @@
allPrice+=parseFloat($(this).val())
hardwarePrice+=parseFloat($(this).val())
})
hardwarePrice=Number(hardwarePrice).toFixed(2);
hardwarePrice=formatAmountNumber(hardwarePrice);
let hardwareHtml=$( `<span class="total-price" style="
font-size: 20px;
font-weight: bold;
@ -208,7 +222,7 @@
allPrice+=parseFloat($(this).val())
maintenancePrice+=parseFloat($(this).val())
})
maintenancePrice=Number(maintenancePrice).toFixed(2);
maintenancePrice=formatAmountNumber(maintenancePrice);
let maintenanceHtml=$( `<span class="total-price" style="
font-size: 20px;
font-weight: bold;
@ -217,7 +231,8 @@
justify-content: flex-end;
"><span style="padding-right: 10px">配置组小计</span> ${maintenancePrice}</span>`)
$('#productTable3').after(maintenanceHtml);
allPrice = Number(allPrice).toFixed(2);
allPrice = formatAmountNumber(allPrice);
allPriceDiscount=formatAmountNumber(allPriceDiscount);
let allPriceHtml=$( `<span class="total-price all-total-price" style="
font-size: 20px;
font-weight: bold;
@ -238,7 +253,7 @@
flex-direction: row;
justify-content: flex-end;
"><div style="width: 65svw;display: flex;justify-content: center;"><span ><span class="discount-text">利润折扣</span>,折扣率<span id="allPriceCountValueSpan"></span>
<select id="allPriceCountValue" onchange="changeAllPriceCount()" >
<select id="allPriceCountValue" onchange="changeAllPriceCount(${id})" >
<option value="1" ${(!discountFold || discountFold===1)?'selected':''} >100%</option>
<option value="0.988" ${discountFold===0.988?'selected':''} >98.8%</option>
<option value="0.985" ${discountFold===0.985?'selected':''} >98.5%</option>
@ -246,155 +261,74 @@
</span> </div> <span style="border-left: 1px solid;padding-left: 100px;">折后总价<span id="allPriceCount" style="padding-left: 10px"> ${allPriceDiscount}</span></span></div>`)
$('.layui-tab').after(allPriceHtml);
}
function changeAllPriceCount(){
let val = $('#allPriceCountValue').val();
let allPriceCount = $('#allPriceTotal').text();
$('#allPriceCount').text((allPriceCount*val).toFixed(2));
function changeAllPriceCount(id) {
let discountFold = $('#allPriceCountValue').val();
let allPriceDiscount=0.00;
$('.price-column').find('.price').each(function (index) {
let price = $(this).val();
let quantity = $(this)?.parent()?.parent()?.find('.quantity')?.val();
let discountPrice = ((price*discountFold).toFixed(2)*quantity).toFixed(2);
$(this)?.parent()?.parent()?.find('.allPrice-discount').val(discountPrice)
$(this)?.parent()?.parent()?.find('.allPrice-discount-format').val(formatAmountNumber(discountPrice))
allPriceDiscount+=parseFloat(discountPrice)
// allPriceDiscount+=parseFloat($(this).val())
})
$('#allPriceCount').text(formatAmountNumber(allPriceDiscount))
}
function addProduct(data) {
let length = $('#productTable tbody').find('tr').length
let flag=true
if (data){
flag =! updatePriceProductList.filter(item=>item===data.productBomCode).length>0;
}
let tr = $(`
<tr>
<td style="text-align: center;" class="indexBox">${length + 1}</td>
<td class="product-bom-code-column"> <input type="hidden" name="softwareProjectProductInfoList[${length}].id" value="${data.id || ''}"><input class="form-control productBomCode" type="text" onclick="selectProduct('1','软件产品',this)" value="${data.productBomCode || ''}" name="softwareProjectProductInfoList[${length}].productBomCode"></td>
<td class="model-column"><input readonly class="form-control model" type="text" onclick="selectProduct('1','软件产品',this)" value="${data.model || ''}" name="softwareProjectProductInfoList[${length}].model"></td>
<td class="product-desc-column"><textarea name="softwareProjectProductInfoList[${length}].productDesc" required class="form-control productDesc" placeholder="自动带入" readonly>${data.productDesc || ''}</textarea></td>
<td class="quantity-column"><input value="${data.quantity || ''}" name="softwareProjectProductInfoList[${length}].quantity" type="number" class="form-control quantity" step="1" required></td>
<td class="catalogue-price-column">
<input value="${data.cataloguePrice || ''}" name="softwareProjectProductInfoList[${length}].cataloguePrice" readonly type="hidden" class="form-control cataloguePrice" required>
<input value="${data.cataloguePriceFormmat || ''}" readonly="${flag}" type="text" class="form-control catalogue-price-format" required>
</td>
<td class="guidance-discount-column">
<input value="${data.guidanceDiscount || ''}" name="softwareProjectProductInfoList[${length}].guidanceDiscount" readonly type="hidden" class="form-control guidanceDiscount" >
<label style="display: flex;align-items: center"><input style="width: calc(100% - 10px);" value="${data.guidanceDiscountFormat || ''}" readonly required type="number" min="0" max="100" step="0.01" class="form-control guidance-discount-format" required>%
</label>
</td>
<td class="discount-column"><input value="${data.discount || ''}" name="softwareProjectProductInfoList[${length}].discount" type="hidden" class="form-control discount" required>
<label style="display: flex;align-items: center"><input style="width: calc(100% - 10px);" value="${data.discountFormat || ''}" type="number" min="0" max="100" step="0.01" class="form-control discount-format" required>%
</label></td>
<td class="price-column">
<input value="${data.price || ''}" name="softwareProjectProductInfoList[${length}].price" type="hidden" class="form-control price" placeholder="自动计算" required readonly>
<input type="text" value="${data.priceFormmat || ''}" class="form-control price-formmat" onfocus="getData(this,'price')" onblur="this.value=formatAmountNumber(this.value)" placeholder="自动计算" required >
</td>
<td class="discount-column-zd hide-column" >
<input type="text" value="${data.zdDiscount || ''}" class="form-control" placeholder="自动计算" required readonly>
</td>
<td class="all-price-column">
<input value="${data.allPrice || ''}" name="softwareProjectProductInfoList[${length}].allPrice" type="hidden" class="form-control allPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.allPriceFormmat || ''}" class="form-control allPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="all-price-discount-column hide-column">
<input type="hidden" value="${data.allPriceDisCount || ''}" class="form-control allPrice-discount" placeholder="自动计算" readonly>
<input type="text" value="${data.allPriceDisCountFormat || ''}" class="form-control allPrice-discount-format" placeholder="自动计算" required readonly>
</td>
<td class="catalogue-all-price-column">
<input value="${data.catalogueAllPrice || ''}" name="softwareProjectProductInfoList[${length}].catalogueAllPrice" type="hidden" class="form-control catalogueAllPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.catalogueAllPriceFormmat || ''}" class="form-control catalogueAllPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="remark-column"><input value="${data.remark || ''}" name="softwareProjectProductInfoList[${length}].remark" type="text" class="form-control remark" ></td>
<td class="del-row-column"><span style="cursor:pointer;color: #ff5722" onclick="delProductRow(this)" class="delRow">删除</span></td>
</tr>`)
$('#productTable tbody').append(tr)
$('#productTable tbody').append(generatedTr(0,data,length))
// initSearchProduct('1')
initPrice()
}
function addProduct2(data) {
let length = $('#productTable2 tbody').find('tr').length
let flag=true
if (data){
flag =! updatePriceProductList.filter(item=>item===data.productBomCode).length>0;
}
let tr = $(`
<tr>
<td style="text-align: center;" class="indexBox">${length + 1}</td>
<td class="product-bom-code-column"> <input type="hidden" name="hardwareProjectProductInfoList[${length}].id" value="${data.id || ''}"><input class="form-control productBomCode" type="text" onclick="selectProduct('2','终端产品',this)" value="${data.productBomCode || ''}" name="hardwareProjectProductInfoList[${length}].productBomCode"></td>
<td class="model-column"><input readonly class="form-control model" type="text" onclick="selectProduct('2','终端产品',this)" value="${data.model || ''}" name="hardwareProjectProductInfoList[${length}].model"></td>
<td class="product-desc-column"><textarea name="hardwareProjectProductInfoList[${length}].productDesc" required class="form-control productDesc" placeholder="自动带入" readonly>${data.productDesc || ''}</textarea></td>
<td class="quantity-column"><input value="${data.quantity || ''}" name="hardwareProjectProductInfoList[${length}].quantity" type="number" class="form-control quantity" step="1" required></td>
<td class="catalogue-price-column">
<input value="${data.cataloguePrice || ''}" name="hardwareProjectProductInfoList[${length}].cataloguePrice" readonly type="hidden" class="form-control cataloguePrice" required>
<input value="${data.cataloguePriceFormmat || ''}" readonly="${flag}" type="text" class="form-control catalogue-price-format" required>
</td>
<td class="guidance-discount-column">
<input value="${data.guidanceDiscount || ''}" name="hardwareProjectProductInfoList[${length}].guidanceDiscount" readonly type="hidden" class="form-control guidanceDiscount" >
<label style="display: flex;align-items: center"><input style="width: calc(100% - 10px);" value="${data.guidanceDiscountFormat || ''}" readonly required type="number" min="0" max="100" step="0.01" class="form-control guidance-discount-format" required>%
</label>
</td>
<td class="discount-column"><input value="${data.discount || ''}" name="hardwareProjectProductInfoList[${length}].discount" type="hidden" class="form-control discount" required>
<label style="display: flex;align-items: center"><input style="width: calc(100% - 10px);" value="${data.discountFormat || ''}" required type="number" min="0" max="100" step="0.01" class="form-control discount-format" >%
</label></td>
<td class="price-column">
<input value="${data.price || ''}" name="hardwareProjectProductInfoList[${length}].price" type="hidden" class="form-control price" placeholder="自动计算" required readonly>
<input type="text" value="${data.priceFormmat || ''}" class="form-control price-formmat" placeholder="自动计算" onfocus="getData(this,'price')" onblur="this.value=formatAmountNumber(this.value)" required >
</td>
<td class="discount-column-zd hide-column" >
<input type="text" value="${data.zdDiscount || ''}" class="form-control" placeholder="自动计算" required readonly>
</td>
<td class="all-price-column">
<input value="${data.allPrice || ''}" name="hardwareProjectProductInfoList[${length}].allPrice" type="hidden" class="form-control allPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.allPriceFormmat || ''}" class="form-control allPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="all-price-discount-column hide-column">
<input type="hidden" value="${data.allPriceDisCount || ''}" class="form-control allPrice-discount" placeholder="自动计算" readonly>
<input type="text" value="${data.allPriceDisCountFormat || ''}" class="form-control allPrice-discount-format" placeholder="自动计算" required readonly></td>
<td class="catalogue-all-price-column">
<input value="${data.catalogueAllPrice || ''}" name="hardwareProjectProductInfoList[${length}].catalogueAllPrice" type="hidden" class="form-control catalogueAllPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.catalogueAllPriceFormmat || ''}" class="form-control catalogueAllPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="remark-column"><input value="${data.remark || ''}" name="hardwareProjectProductInfoList[${length}].remark" type="text" class="form-control" ></td>
<td class="del-row-column"><span style="cursor:pointer;color: #ff5722" onclick="delProductRow(this)" class="delRow">删除</span></td>
</tr>`)
$('#productTable2 tbody').append(tr)
$('#productTable2 tbody').append(generatedTr(1,data,length))
initPrice()
}
function addProduct3(data) {
let length = $('#productTable3 tbody').find('tr').length
function generatedTr(index,data,length){
let flag=true
console.log(data)
if (data){
flag =! updatePriceProductList.filter(item=>item===data.productBomCode).length>0;
}
let productTypeParam=productType[index]
let queryParam=productTypeParam.type
let title=productTypeParam.title
let submitName=productTypeParam.name
let tr = $(`
if (data){
flag =! updatePriceProductList.filter(item=>item===data.productBomCode).length>0;
}
let tr=$(`
<tr>
<td style="text-align: center;" class="indexBox">${length + 1}</td>
<td class="product-bom-code-column"> <input type="hidden" name="maintenanceProjectProductInfoList[${length}].id" value="${data.id || ''}"><input class="form-control productBomCode" type="text" onclick="selectProduct('11,22,99','服务产品',this)" value="${data.productBomCode || ''}" name="maintenanceProjectProductInfoList[${length}].productBomCode"></td>
<td class="model-column"><input readonly class="form-control model" type="text" onclick="selectProduct('11,22,99','服务产品',this)" value="${data.model || ''}" name="maintenanceProjectProductInfoList[${length}].model"></td>
<td class="product-desc-column"><textarea name="maintenanceProjectProductInfoList[${length}].productDesc" required class="form-control productDesc" placeholder="自动带入" readonly>${data.productDesc || ''}</textarea></td>
<td class="quantity-column"><input value="${data.quantity || ''}" name="maintenanceProjectProductInfoList[${length}].quantity" type="number" class="form-control quantity" step="1" required></td>
<td class="catalogue-price-column"><input value="${data.cataloguePrice || ''}" name="maintenanceProjectProductInfoList[${length}].cataloguePrice" readonly type="hidden" class="form-control cataloguePrice" required>
<td class="product-bom-code-column"> <input type="hidden" name="${submitName}[${length}].id" value="${data.id || ''}"><input class="form-control productBomCode" type="text" onclick="selectProduct('${queryParam}','${title}',this)" value="${data.productBomCode || ''}" name="${submitName}[${length}].productBomCode"></td>
<td class="model-column"><input readonly class="form-control model" type="text" onclick="selectProduct('${queryParam}','${title}',this)" value="${data.model || ''}" name="${submitName}[${length}].model"></td>
<td class="product-desc-column"><textarea name="${submitName}[${length}].productDesc" required class="form-control productDesc" placeholder="自动带入" readonly>${data.productDesc || ''}</textarea></td>
<td class="quantity-column"><input value="${data.quantity || ''}" name="${submitName}[${length}].quantity" type="number" class="form-control quantity" step="1" required></td>
<td class="catalogue-price-column"><input value="${data.cataloguePrice || ''}" name="${submitName}[${length}].cataloguePrice" readonly type="hidden" class="form-control cataloguePrice" required>
<input value="${data.cataloguePriceFormmat || ''}" ${flag?"readonly":''} onfocus="getData(this,'cataloguePrice')" onblur="this.value=formatAmountNumber(this.value)" type="text" class="form-control catalogue-price-format" required>
</td>
<td class="guidance-discount-column">
<input value="${data.guidanceDiscount || ''}" name="maintenanceProjectProductInfoList[${length}].guidanceDiscount" readonly type="hidden" class="form-control guidanceDiscount" >
<input value="${data.guidanceDiscount || ''}" name="${submitName}[${length}].guidanceDiscount" readonly type="hidden" class="form-control guidanceDiscount" >
<label style="display: flex;align-items: center">
<input style="width: calc(100% - 10px);" value="${data.guidanceDiscountFormat || ''}" readonly type="number" min="0" max="100" step="0.01" class="form-control guidance-discount-format" required>%
</label>
</td >
<td class="discount-column"><input value="${data.discount || ''}" name="maintenanceProjectProductInfoList[${length}].discount" type="hidden" class="form-control discount" required>
<td class="discount-column"><input value="${data.discount || ''}" name="${submitName}[${length}].discount" type="hidden" class="form-control discount" required>
<label style="display: flex;align-items: center"><input style="width: calc(100% - 10px);" value="${data.discountFormat || ''}" type="number" min="0" max="100" step="0.01" class="form-control discount-format" required>%
</label>
</td>
<td class="price-column">
<input value="${data.price || ''}" name="maintenanceProjectProductInfoList[${length}].price" type="hidden" class="form-control price" placeholder="自动计算" required readonly>
<input value="${data.price || ''}" name="${submitName}[${length}].price" type="hidden" class="form-control price" placeholder="自动计算" required readonly>
<input type="text" value="${data.priceFormmat || ''}" onfocus="getData(this,'price')" onblur="this.value=formatAmountNumber(this.value)" class="form-control price-formmat" placeholder="自动计算" required >
</td>
<td class="discount-column-zd hide-column" >
<input type="text" value="${data.zdDiscount || ''}" class="form-control" placeholder="自动计算" required readonly>
</td>
<td class="all-price-column">
<input value="${data.allPrice || ''}" name="maintenanceProjectProductInfoList[${length}].allPrice" type="hidden" class="form-control allPrice" placeholder="自动计算" required readonly>
<input value="${data.allPrice || ''}" name="${submitName}[${length}].allPrice" type="hidden" class="form-control allPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.allPriceFormmat || ''}" class="form-control allPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="all-price-discount-column hide-column">
@ -402,14 +336,21 @@
<input type="text" value="${data.allPriceDisCountFormat || ''}" class="form-control allPrice-discount-format" placeholder="自动计算" required readonly>
</td>
<td class="catalogue-all-price-column">
<input value="${data.catalogueAllPrice || ''}" name="maintenanceProjectProductInfoList[${length}].catalogueAllPrice" type="hidden" class="form-control catalogueAllPrice" placeholder="自动计算" required readonly>
<input value="${data.catalogueAllPrice || ''}" name="${submitName}[${length}].catalogueAllPrice" type="hidden" class="form-control catalogueAllPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.catalogueAllPriceFormmat || ''}" class="form-control catalogueAllPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="remark-column"><input value="${data.remark || ''}" name="maintenanceProjectProductInfoList[${length}].remark" type="text" class="form-control" ></td>
<td class="remark-column"><input value="${data.remark || ''}" name="${submitName}[${length}].remark" type="text" class="form-control" ></td>
<td class="del-row-column"><span style="cursor:pointer;color: #ff5722" onclick="delProductRow(this)" class="delRow">删除</span></td>
</tr>`)
$('#productTable3 tbody').append(tr)
return tr;
}
function addProduct3(data) {
let length = $('#productTable3 tbody').find('tr').length
$('#productTable3 tbody').append(generatedTr(2,data,length))
initPrice()
}

View File

@ -181,18 +181,18 @@
<td >
<select name="operateInstitution" class="form-control"
th:with="type=${@dict.getType('operate_institution')}"
onchange="changeInstitution()">
onchange="changeInstitution()" required>
<option value="">请选择合作渠道</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
</td>
<td>新华三联系人</td>
<td>新华三联系人<span class="is-required h3c hidden">*</span></td>
<td >
<input name="h3cPerson" class="form-control" type="text"
>
</td>
<td>新华三TEL</td>
<td>新华三TEL<span class="is-required h3c hidden">*</span></td>
<td >
<input name="h3cPhone" class="form-control" type="text"
>
@ -570,6 +570,15 @@
if ($('[name="operateInstitution"]').val() == 'h3c') {
$('[name="partnerName"]').val('新华三')
$('[name="partnerCode"]').val('')
$('.h3c').removeClass("hidden")
$('[name="h3cPerson"]').prop("required",true)
$('[name="h3cPhone"]').prop("required",true)
}else{
$('[name="partnerName"]').val('')
$('[name="partnerCode"]').val('')
$('.h3c').addClass("hidden")
$('[name="h3cPerson"]').prop("required",false)
$('[name="h3cPhone"]').prop("required",false)
}
}

View File

@ -110,8 +110,8 @@
autocomplete="off"
class="form-control" placeholder="yyyy-MM-dd" type="text">
</td>
<td class="shortTd" style=" text-align: right;">实际完成时间<span class="is-required">*</span></td>
<td><input name="projectPocInfo.realFinishTime" required
<td class="shortTd" style=" text-align: right;">实际完成时间</td>
<td><input name="projectPocInfo.realFinishTime"
autocomplete="off"
class="form-control" placeholder="yyyy-MM-dd" type="text">
</td>

View File

@ -193,22 +193,22 @@
</td>
</tr>
<tr>
<td>运作方</td>
<td>运作方<span class="is-required">*</span></td>
<td >
<select name="operateInstitution" class="form-control"
th:with="type=${@dict.getType('operate_institution')}"
th:with="type=${@dict.getType('operate_institution')}" required
onchange="changeInstitution()" th:field="*{operateInstitution}">
<option value="">请选择合作渠道</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
</td>
<td>新华三联系人</td>
<td>新华三联系人<span class="is-required h3c hidden">*</span></td>
<td >
<input name="h3cPerson" class="form-control" type="text" th:field="*{h3cPerson}"
>
</td>
<td>新华三TEL</td>
<td>新华三TEL<span class="is-required h3c hidden">*</span></td>
<td >
<input name="h3cPhone" class="form-control" type="text" th:field="*{h3cPhone}"
>
@ -666,6 +666,15 @@
if ($('[name="operateInstitution"]').val() == 'h3c') {
$('[name="partnerName"]').val('新华三')
$('[name="partnerCode"]').val('')
$('.h3c').removeClass("hidden")
$('[name="h3cPerson"]').prop("required",true)
$('[name="h3cPhone"]').prop("required",true)
}else{
$('[name="partnerName"]').val('')
$('[name="partnerCode"]').val('')
$('.h3c').addClass("hidden")
$('[name="h3cPerson"]').prop("required",false)
$('[name="h3cPhone"]').prop("required",false)
}
}

View File

@ -264,7 +264,7 @@
{
field: 'projectStage',
title: '项目阶段',
width: 100,
width: 160,
formatter: function (value, row, index) {
return $.table.selectDictLabel([[${@dict.getType('project_stage')}]], value);
}

View File

@ -20,20 +20,8 @@
<div class="select-list">
<ul>
<li>
<label>代理商编码:</label>
<input type="text" name="partnerCode"/>
</li>
<li>
<label>代理商名称:</label>
<input type="text" name="partnerName"/>
</li>
<li>
<label>认证级别:</label>
<select name="level" th:with="type=${@dict.getType('identify_level')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
<label>用户名称:</label>
<input type="text" name="userName"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i

View File

@ -360,21 +360,21 @@
}
$.operate.post(ctx + 'system/product/list', {...data, type: '1'}, function (res) {
softwareProjectProductInfoList = res.rows
softwareProjectProductInfoList.unshift({
softwareProjectProductInfoList?.unshift({
model: '',
productCode: ''
})
})
$.operate.post(ctx + 'system/product/list', {...data, type: '2'}, function (res) {
hardwareProjectProductInfoList = res.rows
hardwareProjectProductInfoList.unshift({
hardwareProjectProductInfoList?.unshift({
model: '',
productCode: ''
})
})
$.operate.post(ctx + 'system/product/list', {...data, type: '11,22'}, function (res) {
maintenanceProjectProductInfoList = res.rows
maintenanceProjectProductInfoList.unshift({
maintenanceProjectProductInfoList?.unshift({
model: '',
productCode: ''
})

View File

@ -1181,11 +1181,12 @@ ${
}) : '';
window.localStorage.removeItem('getDetail')
setTotalData(true, [[${projectOrderInfo.discountFold}]])
setTotalData(true, [[${projectOrderInfo.discountFold}]], [[${projectOrderInfo.projectId}]])
if (!$('#shipmentAmount').val()|| !$('#actualPurchaseAmount').val()) {
setOrderPriceData()
}
if ([[${todo.taskName}]] != '商务') {
if (!([[${todo.taskName}]]).startsWith('商务')) {
$('#allPriceCountValue').prop("disabled", true)
}
$('.layui-tab table tbody tr td').find('input,textarea').each(function () {

View File

@ -333,7 +333,22 @@
<td><input name="partnerPhone" class="form-control" type="text" required th:field="*{partnerPhone}">
</td>
</tr>
<tr>
<td>收货地址<span class="is-required">*</span></td>
<td colspan="5">
<input name="notifierAddress" required class="form-control" type="text" th:field="*{notifierAddress}">
</td>
</tr>
<tr>
<td>收货人</td>
<td><input name="notifier" class="form-control" type="text" th:field="*{notifier}"></td>
<td>Email</td>
<td><input type="text" name="notifierEmail" th:field="*{notifierEmail}"
class="form-control"></td>
<td>联系方式<span class="is-required">*</span></td>
<td><input name="notifierPhone" class="form-control" type="text" required th:field="*{notifierPhone}">
</td>
</tr>
<tr>
<td>其他特别说明</td>
<td colspan="5">
@ -355,25 +370,25 @@
</div>
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this" lay-id="11" th:if="${showFileFlag}">合同信息</li>
<li lay-id="22" th:class="${showFileFlag ?'':'layui-this'}">备货信息</li>
<li class="layui-this" lay-id="11" th:if="${showFileFlag || orderBakFile.size()>0}">合同信息</li>
<li lay-id="22" th:class="${(showFileFlag || orderBakFile.size()>0)?'':'layui-this'}">备货信息</li>
<li lay-id="33">物流信息</li>
<li lay-id="44">审批信息</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show" th:if="${showFileFlag}">
<div class="layui-tab-item layui-show" th:if="${showFileFlag || orderBakFile.size()>0}">
<div class="row">
<div class="col-sm-12">
<div class="tabs-container">
<div class="col-xs-12 flex-end">
<div class="col-xs-12 flex-end" th:if="${showFileFlag}">
<button type="button" class="btn btn-white btn-sm" onclick="downloadTem()"><i
class="fa fa-download">
下载模板</i></button>
</div>
<ul class="nav nav-tabs" id="file-version-tab">
<li th:each="entry : ${projectOrderInfo.contractTableData.entrySet()}"
<li th:each="entry : ${showFileFlag ? projectOrderInfo.contractTableData.entrySet():orderBakFile.entrySet() }"
th:class="${entry.key == projectOrderInfo.versionCode ? 'active' : ''}">
<a data-toggle="tab" th:href="'#tab-'+${entry.key}" aria-expanded="true">
版本号Rev.[[${entry.key}]]</a>
@ -381,7 +396,7 @@
</ul>
<div class="tab-content" id="file-version-content">
<input id="deleteFileId" name="deleteFileId" type="hidden"/>
<div th:each="entry : ${projectOrderInfo.contractTableData.entrySet()}"
<div th:each="entry : ${showFileFlag ? projectOrderInfo.contractTableData.entrySet():orderBakFile.entrySet()}"
th:id="'tab-'+${entry.key}"
th:class="'tab-pane '+${entry.key == projectOrderInfo.versionCode ? 'active current-version' : ''}">
@ -395,7 +410,7 @@
</div>
<div class="panel-body">
<div class="panel-body" th:if="${showFileFlag}">
<h3 style="margin-bottom: 5px">附件信息</h3>
<table>
<thead>
@ -465,7 +480,7 @@
<!-- </div>-->
</div>
</div>
<div th:class="${showFileFlag?'layui-tab-item':' layui-tab-item layui-show'}">内容-2</div>
<div th:class="${(showFileFlag || orderBakFile.size()>0)?'layui-tab-item':' layui-tab-item layui-show'}">内容-2</div>
<div class="layui-tab-item">内容-3</div>
<div class="layui-tab-item">
<ul class="nav nav-tabs">
@ -719,13 +734,14 @@
parent.parent.$('.saveDraft').show()
},
end: function (index) {
parent.parent.$('.layui-layer-btn').show()
parent.parent.$('.saveDraft').show()
// parent.parent.$('.layui-layer-btn').show()
// parent.parent.$('.saveDraft').show()
}
};
layer.open(options)
}
function submitHandler(type) {
if (type == 'draft') {
if (!$('[name="projectCode"]').val()) {
@ -876,7 +892,11 @@
return;
}
$('#projectNameBox').text(rows[0].projectName)
//处理客户信息
$('[name="customerName"]').val(rows[0].customerName);
$('[name="notifier"]').val(rows[0].customerUserName);
$('[name="notifierPhone"]').val(rows[0].customerPhone);
$('[name="notifierAddress"]').val(rows[0].customerAddress);
$('[name="projectCode"]').val(rows[0].projectCode);
$('[name="projectId"]').val(rows[0].id);
$('[name="projectName"]').val(rows[0].projectName);
@ -1199,16 +1219,16 @@
return
}
let draft = $(`
<span class="saveDraft" style=" position: absolute;
right: 180px;
bottom: 12px;
<span class="saveDraft" style="
position: relative;
right: 215px;
display: inline-block;
background: #ff5722;
padding: 6px 10px;
border-radius: 5px;
color: #fff;cursor: pointer"> 保存</span>`)
parent.$('.layui-layer-btn0').text('提交审批')
parent.$('.layui-layer-btn').after(draft)
parent.$('.layui-layer-btn1').after(draft)
parent.$('.saveDraft').on('click', function () {
$('[name="orderStatus"]').val(0)
submitHandler('draft')

View File

@ -20,20 +20,8 @@
<div class="select-list">
<ul>
<li>
<label>代理商编码:</label>
<input type="text" name="partnerCode"/>
</li>
<li>
<label>代理商名称:</label>
<input type="text" name="partnerName"/>
</li>
<li>
<label>认证级别:</label>
<select name="level" th:with="type=${@dict.getType('identify_level')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
<label>用户名称:</label>
<input type="text" name="userName"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i

View File

@ -69,6 +69,16 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-3 control-label is-required">制造商:</label>
<div class="col-sm-8">
<select name="vendorCode" class="form-control" required>
<option th:each="vendor : ${vendorList}" th:text="${vendor.vendorName}" th:value="${vendor.vendorCode}"></option>
</select>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-3 control-label">产品描述:</label>

View File

@ -69,6 +69,16 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-3 control-label is-required">制造商:</label>
<div class="col-sm-8">
<select name="vendorCode" class="form-control" th:field="*{vendorCode}" required>
<option th:each="vendor : ${vendorList}" th:text="${vendor.vendorName}" th:value="${vendor.vendorCode}"></option>
</select>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-3 control-label">产品描述:</label>

View File

@ -27,6 +27,10 @@
<label>产品型号:</label>
<input type="text" name="model"/>
</li>
<li>
<label>制造商:</label>
<input type="text" name="vendorName"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
@ -96,6 +100,11 @@
width:100,
field: 'model',
title: '产品型号'
},
{
width:100,
field: 'vendorName',
title: '制造商'
},
{
width:100,

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增制造商信息')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-vendor-add">
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">制造商编码:</label>
<div class="col-sm-8">
<input name="vendorCode" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">制造商名称:</label>
<div class="col-sm-8">
<input name="vendorName" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系人:</label>
<div class="col-sm-8">
<input name="vendorUser" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label">联系邮箱:</label>
<div class="col-sm-8">
<input name="vendorEmail" class="form-control" type="text">
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系电话:</label>
<div class="col-sm-8">
<input name="vendorPhone" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">生产地址:</label>
<div class="col-sm-10">
<textarea rows="3" name="vendorAddress" class="form-control" type="text"></textarea>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/vendor"
$("#form-vendor-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-vendor-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改制造商信息')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-vendor-edit" th:object="${vendorInfo}">
<input name="vendorId" th:field="*{vendorId}" type="hidden">
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">制造商编码:</label>
<div class="col-sm-8">
<input name="vendorCode" th:field="*{vendorCode}" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">制造商名称:</label>
<div class="col-sm-8">
<input name="vendorName" th:field="*{vendorName}" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系人:</label>
<div class="col-sm-8">
<input name="vendorUser" th:field="*{vendorUser}" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label">联系邮箱:</label>
<div class="col-sm-8">
<input name="vendorEmail" th:field="*{vendorEmail}" class="form-control" type="text">
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系电话:</label>
<div class="col-sm-8">
<input name="vendorPhone" th:field="*{vendorPhone}" class="form-control" type="text" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">合作状态:</label>
<div class="col-sm-8">
<select name="vendorStatus" class="form-control" th:with="type=${@dict.getType('vendor_status')}">
<option value="">请选择</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}" th:selected="${vendorInfo.vendorStatus == dict.dictValue}"></option>
</select>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">生产地址:</label>
<div class="col-sm-10">
<textarea rows="3" name="vendorAddress" th:field="*{vendorAddress}" class="form-control" type="text"></textarea>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/vendor";
const updateFlag= [[${update}]];
$("#form-vendor-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-vendor-edit').serialize());
}
}
$(function(){
if (!updateFlag) {
$('#form-vendor-edit').find('input,select,textarea').each(function () {
$(this).prop("disabled", true);
})
}
})
</script>
</body>
</html>

View File

@ -0,0 +1,154 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('制造商信息列表')" />
</head>
<style>
.select-list li p, .select-list li label:not(.radio-box){
width: 80px;
}
</style>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>制造商编码:</label>
<input type="text" name="vendorCode"/>
</li>
<li>
<label>制造商名称:</label>
<input type="text" name="vendorName"/>
</li>
<li>
<label>生产地址:</label>
<input type="text" name="vendorAddress"/>
</li>
<li>
<label>联系人:</label>
<input type="text" name="vendorUser"/>
</li>
<li>
<label>合作状态:</label>
<select name="vendorStatus" class="form-control" th:with="type=${@dict.getType('vendor_status')}">
<option value="">请选择</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:vendor:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:vendor:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:vendor:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:vendor:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:vendor:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:vendor:remove')}]];
var qrCodeFlag = [[${@permission.hasPermi('system:vendor:qrCode')}]];
var vendorStatusDatas = [[${@dict.getType('vendor_status')}]];
var prefix = ctx + "system/vendor";
function generatedQrCode(id){
window.location.href = prefix + `/qr/code?id=` +id;
}
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
detailUrl: prefix + "/view/{id}",
modalName: "制造商信息",
columns: [{
checkbox: true
},
{
field: 'vendorId',
title: '',
visible: false
},
{
width: '100',
field: 'vendorCode',
title: '制造商编码'
},
{
width: '200',
field: 'vendorName',
title: '制造商名称'
},
{
width: '600',
field: 'vendorAddress',
title: '生产地址'
},
{
width: '100',
field: 'vendorUser',
title: '联系人'
},
{
width: '100',
field: 'vendorEmail',
title: '联系邮箱'
},
{
width: '100',
field: 'vendorPhone',
title: '联系电话'
},
{
width: '100',
field: 'vendorStatus',
title: '合作状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(vendorStatusDatas, value);
}
},
{
width: '350',
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.vendorId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-info btn-xs " href="javascript:void(0)" onclick="$.operate.detail(\'' + row.vendorId + '\')"><i class="fa fa-search"></i>查看详情</a>');
actions.push('<a style="margin:0px 5px" class="btn btn-info btn-xs '+qrCodeFlag+' " href="javascript:void(0)" onclick="generatedQrCode(\'' + row.vendorId + '\')"><i class="fa fa-remove"></i>生成二维码</a>');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.vendorId + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -0,0 +1,217 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('制造商查询')" />
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f9f9f9;
}
.container {
/*width: 100%;*/
margin: 0;
padding: 10px 0;
background-color: white;
border-radius: 8px;
display: flex;
flex-direction: row;
gap: 30px;
justify-content: center;
}
h1 {
text-align: center;
color: #e74c3c;
}
.form-group {
margin-bottom: 15px;
display: flex;
flex-direction: row;
align-items: center;
}
.tableBOx{
width:70vw;
}
label {
margin-bottom: 0;
width: 80px;
font-weight: 600;
}
input[type="text"] {
width: 100%;
padding:5px 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
width:100px;
padding:0;
height: 30px;
background-color: #1c84c6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
border-color: #1a7bb9;
}
.topBox{
display: flex;
flex-direction: row;
gap: 20px;
margin: 30px 0 10px;
align-items: center;
}
.topBox .title{
font-size: 24px;
font-weight: 600;
}
.table-striped {
display: flex;justify-content: flex-start;flex-direction: column;align-items: center
}
.table-striped thead{
background: #f5f5f5 !important;
}
.table-striped thead th{
padding: 10px;
}
.table-striped tbody td{
padding: 10px;
}
.tabBtn{
display: inline-block;
padding:8px 10px;
cursor: pointer;
width: 80px;
text-align: center;
}
.form-group label{
width: 100px;
}
@media (max-width: 768px) {
.tableBOx {
width: 100%;
}
.container,.topBox{
display: none;
}
.table-striped thead {
display: none; /* 隐藏表头 */
}
.table-striped tbody tr {
display: flex;
flex-direction: column;
border-bottom: 1px solid #ddd;
margin-bottom: 10px;
}
.table-striped tbody td {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 10px;
border-bottom: 1px solid #eee;
}
/*.table-striped tbody tr td:first-child {*/
/* font-weight: bold;*/
/* min-width: 100px;*/
/* max-width: 120px;*/
/*}*/
/* 新增样式:为每个 td 添加伪元素来显示表头 */
.table-striped tbody tr td::before {
content: attr(data-th); /* 使用 data-th 属性来显示表头 */
font-weight: bold;
display: inline-block;
min-width: 100px;
max-width: 100px;
margin-right: 10px;
}
}
</style>
</head>
<body class="gray-bg">
<div class="col-sm-12 select-table table-striped" >
<div class="topBox">
<div class="title">制造商查询 </div>
<!-- <div style="color: #dd242a">H3C产品保修条款</div>-->
</div>
<div class="container">
<div class="form-group">
<label for="vendorCode">制造商代码</label>
<input type="text" th:value="${code}" id="vendorCode" placeholder="请输入代理商代码">
</div>
<button type="button" onclick="getData()">查询</button>
</div>
<div style="font-size: 20px;text-align: left;width: 70vw;margin: 10px 0">查询结果</div>
<div style="font-size: 16px;text-align: left;width: 70vw;font-weight: 600;"><blockquote style="border-left-color: #1c84c6">制造商信息</blockquote> </div>
<div style="width: 70svw;overflow-x: auto">
<table class="tableBOx" id="tableBOx">
<thead>
<tr>
<th style="min-width: 100px">制造商编码</th>
<th style="min-width: 100px">制造商名称</th>
<th style="min-width: 100px">生产地址</th>
<th style="min-width: 100px">联系人</th>
<th style="min-width: 100px">联系邮箱</th>
<th style="min-width: 100px">联系电话</th>
<th style="min-width: 100px">合作状态</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javaScript">
var prefix = ctx + "system/partner";
$(function() {
getData()
});
function getData() {
let vendorCode = $('#vendorCode').val()
$.operate.get(`/system/vendor/list/query?vendorCode=${vendorCode}`, function (res) {
let str = `<tr><td colspan="8" style="text-align: center">暂无数据</td></tr>`
if (res.data.length) {
str = ``
res.data.forEach((ele) => {
str += `<tr>
<td data-th="制造商编码">${ele.vendorCode}</td>
<td data-th="制造商名称">${ele.vendorName}</td>
<td data-th="生产地址">${ele.vendorAddress}</td>
<td data-th="联系人">${ele.vendorUser}</td>
<td data-th="联系邮箱">${ele.vendorEmail}</td>
<td data-th="联系电话">${ele.vendorPhone}</td>
<td data-th="合作状态">${ele.vendorStatusName}</td>
</tr>`
})
}
$('#tableBOx tbody').html(str)
})
}
</script>
</body>
</html>

View File

@ -7,6 +7,7 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
@ -155,5 +156,13 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
{
return applicationContext.getEnvironment().getRequiredProperty(key);
}
public static String getProperty(String key, String defaultValue)
{
return applicationContext.getEnvironment().getProperty(key,defaultValue);
}
public static Resource getResource(String path)
{
return applicationContext.getResource(path);
}
}

View File

@ -3,6 +3,8 @@ package com.ruoyi.sip.controller;
import java.util.List;
import com.ruoyi.sip.domain.MaintenanceRecordsDto;
import com.ruoyi.sip.domain.VendorInfo;
import com.ruoyi.sip.service.IVendorInfoService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -36,6 +38,8 @@ public class ProductInfoController extends BaseController
@Autowired
private IProductInfoService productInfoService;
@Autowired
private IVendorInfoService vendorInfoService;
@RequiresPermissions("system:product:view")
@GetMapping()
public String product()
@ -75,8 +79,9 @@ public class ProductInfoController extends BaseController
*/
@RequiresPermissions("system:product:add")
@GetMapping("/add")
public String add()
public String add(ModelMap modelMap)
{
modelMap.put("vendorList", vendorInfoService.selectVendorInfoList(new VendorInfo()));
return prefix + "/add";
}
@ -101,6 +106,7 @@ public class ProductInfoController extends BaseController
{
ProductInfo productInfo = productInfoService.selectProductInfoById(id);
mmap.put("productInfo", productInfo);
mmap.put("vendorList", vendorInfoService.selectVendorInfoList(new VendorInfo()));
return prefix + "/edit";
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.controller;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
@ -11,11 +12,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.domain.ProjectInfo;

View File

@ -6,7 +6,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.config.RuoYiConfig;
@ -95,6 +97,20 @@ public class ProjectOrderInfoController extends BaseController
mmap.put("todo", todoService.selectTodo(todo));
return prefix + "/approve";
}
@GetMapping("/h5/approve/{id}")
@ResponseBody
public AjaxResult approve(@PathVariable("id") Long id) {
Map<String,Object> result=new HashMap<>();
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoById(id);
result.put("projectOrderInfo", projectOrderInfo);
result.put("user", ShiroUtils.getSysUser());
Todo todo = new Todo();
todo.setBusinessKey(projectOrderInfo.getOrderCode());
result.put("approveLog", todoService.selectTodoCompletedList(todo));
todo.setApproveUser(ShiroUtils.getUserId().toString());
result.put("todo", todoService.selectTodo(todo));
return AjaxResult.success(result);
}
@PostMapping("/order/approve")
@ResponseBody

View File

@ -0,0 +1,201 @@
package com.ruoyi.sip.controller;
import java.io.File;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.sip.domain.VendorInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.service.IVendorInfoService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Controller
*
* @author ruoyi
* @date 2025-07-23
*/
@Controller
@RequestMapping("/system/vendor")
@Slf4j
public class VendorInfoController extends BaseController
{
private String prefix = "system/vendor";
@Autowired
private IVendorInfoService vendorInfoService;
@RequiresPermissions("system:vendor:view")
@GetMapping()
public String vendor()
{
return prefix + "/vendor";
}
@GetMapping("/query")
@Anonymous
public String partnerQuery(@RequestParam(value = "code",required = false)String code, ModelMap modelMap)
{
modelMap.put("code",code);
return prefix + "/vendorQuery";
}
@GetMapping("/list/query")
@ResponseBody
@Anonymous
public AjaxResult listQuery(VendorInfo vendorInfo)
{
if (StringUtils.isEmpty(vendorInfo.getVendorCode())){
return AjaxResult.success(Collections.emptyList());
}
List<VendorInfo> list = vendorInfoService.selectVendorInfoList(vendorInfo);
for (VendorInfo info : list) {
info.setVendorStatusName(DictUtils.getDictLabel("vendor_status",info.getVendorStatus()));
}
return AjaxResult.success(list);
}
/**
*
*/
@RequiresPermissions("system:vendor:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(VendorInfo vendorInfo)
{
startPage();
List<VendorInfo> list = vendorInfoService.selectVendorInfoList(vendorInfo);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("system:vendor:export")
@Log(title = "制造商信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(VendorInfo vendorInfo)
{
List<VendorInfo> list = vendorInfoService.selectVendorInfoList(vendorInfo);
ExcelUtil<VendorInfo> util = new ExcelUtil<VendorInfo>(VendorInfo.class);
return util.exportExcel(list, "制造商信息数据");
}
/**
*
*/
@RequiresPermissions("system:vendor:add")
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
*
*/
@RequiresPermissions("system:vendor:add")
@Log(title = "制造商信息", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(VendorInfo vendorInfo)
{
return toAjax(vendorInfoService.insertVendorInfo(vendorInfo));
}
/**
*
*/
@RequiresPermissions("system:vendor:edit")
@GetMapping("/edit/{vendorId}")
public String edit(@PathVariable("vendorId") Long vendorId, ModelMap mmap)
{
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorId(vendorId);
mmap.put("vendorInfo", vendorInfo);
mmap.put("update", true);
return prefix + "/edit";
}
/**
*
*/
@GetMapping("/view/{vendorId}")
public String view(@PathVariable("vendorId") Long vendorId, ModelMap mmap)
{
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorId(vendorId);
mmap.put("vendorInfo", vendorInfo);
mmap.put("update", false);
return prefix + "/edit";
}
/**
*
*/
@RequiresPermissions("system:vendor:edit")
@Log(title = "制造商信息", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(VendorInfo vendorInfo)
{
return toAjax(vendorInfoService.updateVendorInfo(vendorInfo));
}
/**
*
*/
@RequiresPermissions("system:vendor:remove")
@Log(title = "制造商信息", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(vendorInfoService.deleteVendorInfoByVendorIds(ids));
}
@GetMapping("/qr/code")
public void download(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response) {
try {
VendorInfo
vendorInfo = vendorInfoService.selectVendorInfoByVendorId(id);
String localPath = RuoYiConfig.getProfile();
String filePath = Paths.get(localPath, "vendor", vendorInfo.getVendorCode() + ".jpg").toString();
log.info("Generating QR code at: {}", filePath);
File file = new File(filePath);
if (!file.getParentFile().exists()) {
// 自动创建目录结构
file.getParentFile().mkdirs();
}
StringBuilder url=new StringBuilder();
url.append("http://oms.unissense.top")
.append("/system/vendor/query?code=")
.append(vendorInfo.getVendorCode());
QrCodeUtil.generate(url.toString(), 300, 300, FileUtil.file(filePath));
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, vendorInfo.getVendorCode()+".jpg");
FileUtils.writeBytes(filePath, response.getOutputStream());
} catch (Exception e) {
log.error("下载文件失败", e);
}
}
}

View File

@ -60,7 +60,8 @@ public class ProductInfo extends BaseEntity
/** 删除时间 */
private Date deletedAt;
private String serialNumber;
private String vendorCode;
private String vendorName;
@Getter
public enum ProductTypeEnum {
/**

View File

@ -64,6 +64,7 @@ public class ProjectInfo extends BaseEntity
/** 客户code */
// @Excel(name = "客户code")
private String customerCode;
private String customerAddress;
/** 客户名称 */
@Excel(name = "最终客户")
private String customerName;

View File

@ -178,6 +178,10 @@ public class ProjectOrderInfo extends BaseEntity {
*/
// @Excel(name = "通知人电话")
private String notifierPhone;
/**
*
*/
private String notifierAddress;

View File

@ -65,6 +65,7 @@ public class ProjectProductInfo extends BaseEntity
/** 总价 */
@Excel(name = "总价")
private BigDecimal allPrice;
private BigDecimal allPriceDisCount;
/** 指导折扣 */
// @Excel(name = "指导折扣")

View File

@ -0,0 +1,64 @@
package com.ruoyi.sip.domain;
import lombok.Data;
import lombok.Getter;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* varchar_info
*
* @author ruoyi
* @date 2025-07-23
*/
@Data
public class VendorInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
private Long vendorId;
/** 制造商编码 */
@Excel(name = "制造商编码")
private String vendorCode;
/** 制造商名称 */
@Excel(name = "制造商名称")
private String vendorName;
/** 生产地址 */
@Excel(name = "生产地址")
private String vendorAddress;
/** 联系人 */
@Excel(name = "联系人")
private String vendorUser;
/** 联系邮箱 */
@Excel(name = "联系邮箱")
private String vendorEmail;
/** 联系电话 */
@Excel(name = "联系电话")
private String vendorPhone;
/** 合作状态 */
@Excel(name = "合作状态")
private String vendorStatus;
private String vendorStatusName;
@Getter
public enum VendorStatusEnum {
NORMAL("0", "正常合作"),
DISABLE("1", "暂停合作"),
;
private final String value;
private final String code;
VendorStatusEnum(String value, String code) {
this.value = value;
this.code = code;
}
}
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.sip.dto;
import com.ruoyi.sip.flowable.domain.BuApproveConfig;
import lombok.Data;
import java.util.List;
/**
* @author : ch
* @version : 1.0
* @ClassName : ApproveConfigDto
* @Description :
* @DATE : Created in 15:23 2025/7/24
* <pre> Copyright: Copyright(c) 2025 </pre>
* <pre> Company : </pre>
* Modification History:
* Date Author Version Discription
* --------------------------------------------------------------------------
* 2025/07/24 ch 1.0 Why & What is modified: <> *
*/
@Data
public class ApproveConfigDto {
private List<BuApproveConfig> approveConfigList;
}

View File

@ -1,9 +1,14 @@
package com.ruoyi.sip.flowable.domain;
import lombok.Data;
import com.ruoyi.common.utils.StringUtils;
import lombok.*;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Getter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* bu_approve_config
@ -28,11 +33,29 @@ public class BuApproveConfig extends BaseEntity
/** 审批人 */
@Excel(name = "审批人")
private String approveUser;
private String approveUserName;
private List<String> approveUserList;
/** 审批角色 */
@Excel(name = "审批角色")
private String approveRole;
private List<String> approveRoleList;
public List<String> getApproveRoleList() {
if (StringUtils.isEmpty(this.approveRole) ){
return Collections.emptyList();
}
return Arrays.stream(this.approveRole.split(",")).collect(Collectors.toList());
}
public List<String> getApproveUserList() {
if (StringUtils.isEmpty(this.approveUser) ){
return Collections.emptyList();
}
return Arrays.stream(this.approveUser.split(",")).collect(Collectors.toList());
}
@Getter
public enum APPROVE_KEY{

View File

@ -1,15 +1,18 @@
package com.ruoyi.sip.flowable.listener;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.config.flow.Instance;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.system.service.ISysUserService;
@ -19,21 +22,21 @@ import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityEvent;
import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
import org.flowable.engine.delegate.event.impl.FlowableEntityWithVariablesEventImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.flowable.variable.api.event.FlowableVariableEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -49,21 +52,40 @@ public class ProcessListener extends AbstractFlowableEngineEventListener {
*/
private static final Logger log = LoggerFactory.getLogger(ProcessListener.class);
private RuntimeService runtimeService;
private TaskService taskService;
private TodoService todoService;
private Snowflake snowflake = new Snowflake(12, 10);
private ISysUserService userService;
private ProcessConfig processConfig;
private final RuntimeService runtimeService;
private final TaskService taskService;
private final TodoService todoService;
private final Snowflake snowflake = new Snowflake(12, 10);
private final ISysUserService userService;
private final ProcessConfig processConfig;
private final IBuApproveConfigService approveConfigService;
public ProcessListener(RuntimeService runtimeService, TodoService todoService, ISysUserService userService, TaskService taskService, ProcessConfig processConfig) {
public ProcessListener(RuntimeService runtimeService, TodoService todoService, ISysUserService userService, TaskService taskService, ProcessConfig processConfig,IBuApproveConfigService approveConfigService) {
this.runtimeService = runtimeService;
this.todoService = todoService;
this.userService = userService;
this.taskService = taskService;
this.processConfig = processConfig;
this.runtimeService.addEventListener(this);
this.approveConfigService=approveConfigService;
}
@Override
protected void multiInstanceActivityStarted(FlowableMultiInstanceActivityEvent event) {
if ("userTask".equals(event.getActivityType())){
//用户任务动态设置审批人
String processInstanceId = event.getProcessInstanceId();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
List<Long> approveUserList = approveConfigService.listByProcessKeyAndTaskName(processInstance.getProcessDefinitionKey(), event.getActivityName());
if (CollUtil.isEmpty(approveUserList)) {
throw new ServiceException("审批人为空,无法提交审核");
}
((ExecutionEntityImpl) processInstance).setVariable("approveUserns",approveUserList);
}
super.multiInstanceActivityStarted(event);
}
@Override
@ -95,25 +117,6 @@ public class ProcessListener extends AbstractFlowableEngineEventListener {
log.info("全局监听WorkFlowListener1-任务创建");
}
@Override
protected void variableCreated(FlowableVariableEvent event) {
log.info("全局监听WorkFlowListener1-创建变量");
}
@Override
protected void processCreated(FlowableEngineEntityEvent event) {
log.info("全局监听WorkFlowListener1-创建流程");
}
@Override
protected void processStarted(FlowableProcessStartedEvent event) {
log.info("全局监听WorkFlowListener1-开始流程");
}
@Override
protected void taskAssigned(FlowableEngineEntityEvent event) {
log.info("全局监听:任务分配");
}
@SneakyThrows
@Override

View File

@ -61,4 +61,6 @@ public interface BuApproveConfigMapper
* @return
*/
public int deleteBuApproveConfigByProcessKeys(String[] processKeys);
void saveBatch(List<BuApproveConfig> approveConfigList);
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.sip.flowable.mapper;
import com.ruoyi.sip.flowable.domain.Todo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -76,5 +77,7 @@ public interface TodoMapper
void deleteTodoByBusinessKey(String businessKey);
Todo selectLastApproveTodo(@Param("businessKey") String businessKey,@Param("taskName") String taskName);
// List<Todo> listApprove(WorkOrderStatisticsRequestDto dto);
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.sip.flowable.service;
import com.ruoyi.sip.flowable.domain.BuApproveConfig;
import org.flowable.bpmn.model.Process;
import java.util.List;
@ -67,4 +68,8 @@ public interface IBuApproveConfigService
* @return
*/
public List<Long> listByProcessKeyAndTaskName(String processKey,String taskName);
List<BuApproveConfig> listByProcess(Process process);
void saveBatch(List<BuApproveConfig> approveConfigList);
}

View File

@ -121,6 +121,8 @@ public interface TodoService
List<Todo> selectTodoListByProcessInstanceId(Todo todo);
ProcessInstance getProcessInstance(String businessKey);
public List<ProcessInstance> listProcessInstance(String businessKey);
void deleteTodoByBusinessKey(String businessKey);
Todo selectLastApproveTodo(String businessKey,String taskName);
}

View File

@ -1,11 +1,10 @@
package com.ruoyi.sip.flowable.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
@ -14,6 +13,8 @@ import com.ruoyi.sip.flowable.mapper.BuApproveConfigMapper;
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
import com.ruoyi.system.mapper.SysUserMapper;
import liquibase.pro.packaged.A;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -33,6 +34,9 @@ public class BuApproveConfigServiceImpl implements IBuApproveConfigService
@Autowired
private SysUserMapper userMapper;
@Autowired
private SysUserMapper sysUserMapper;
/**
*
*
@ -121,4 +125,56 @@ public class BuApproveConfigServiceImpl implements IBuApproveConfigService
}
return result;
}
@Override
public List<BuApproveConfig> listByProcess(Process process) {
BuApproveConfig queryDto = new BuApproveConfig();
queryDto.setProcessKey(process.getId());
List<BuApproveConfig> buApproveConfigs = buApproveConfigMapper.selectBuApproveConfigList(queryDto);
//设置用户名
String userIds = buApproveConfigs.stream().filter(item -> StringUtils.isNotEmpty(item.getApproveUser())).map(BuApproveConfig::getApproveUser).collect(Collectors.joining(","));
SysUser queryUserDto = new SysUser();
queryUserDto.setUserIdList(Arrays.stream(userIds.split(",")).filter(StringUtils::isNotEmpty).map(Long::parseLong).distinct().collect(Collectors.toList()));
List<SysUser> sysUsers = sysUserMapper.selectUserList(queryUserDto);
Map<String, String> userNameMap = sysUsers.stream().collect(Collectors.toMap(item->item.getUserId().toString(), SysUser::getUserName));
for (BuApproveConfig buApproveConfig : buApproveConfigs) {
if (StringUtils.isNotEmpty(buApproveConfig.getApproveUser())){
String[] split = buApproveConfig.getApproveUser().split(",");
StringJoiner stringJoiner=new StringJoiner(",");
for (String s : split) {
stringJoiner.add(userNameMap.get(s));
}
buApproveConfig.setApproveUserName(stringJoiner.toString());
}
}
Map<String, BuApproveConfig> configMap = buApproveConfigs.stream().collect(Collectors.toMap(BuApproveConfig::getTaskName, Function.identity()));
List<UserTask> flowElementsOfType = process.findFlowElementsOfType(UserTask.class);
List<BuApproveConfig> result=new ArrayList<>();
for (UserTask flowElement : flowElementsOfType) {
if (configMap.containsKey(flowElement.getName())){
result.add(configMap.get(flowElement.getName()));
}else{
BuApproveConfig buApproveConfig = new BuApproveConfig();
buApproveConfig.setProcessKey(process.getId());
buApproveConfig.setTaskName(flowElement.getName());
result.add(buApproveConfig);
}
}
return result;
}
@Override
public void saveBatch(List<BuApproveConfig> approveConfigList) {
if (CollUtil.isEmpty(approveConfigList)){
return;
}
buApproveConfigMapper.saveBatch(approveConfigList);
}
}

View File

@ -285,6 +285,11 @@ public class TodoServiceImpl implements TodoService {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
return processInstance;
}
@Override
public List<ProcessInstance> listProcessInstance(String businessKey) {
return runtimeService.createProcessInstanceQuery().processInstanceBusinessKeyLike("%"+businessKey+"%").list();
}
@Override
@ -292,6 +297,11 @@ public class TodoServiceImpl implements TodoService {
todoMapper.deleteTodoByBusinessKey(businessKey);
}
@Override
public Todo selectLastApproveTodo(String businessKey, String taskName) {
return todoMapper.selectLastApproveTodo(businessKey,taskName);
}
/**
*
*/

View File

@ -29,6 +29,7 @@ public interface ProjectOrderInfoMapper
* @return
*/
public List<ProjectOrderInfo> selectProjectOrderInfoList(ProjectOrderInfo projectOrderInfo);
public ProjectOrderInfo selectProjectOrderInfoByCode(String orderCode);
/**
*

View File

@ -0,0 +1,63 @@
package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.VendorInfo;
import java.util.List;
/**
* Mapper
*
* @author ruoyi
* @date 2025-07-23
*/
public interface VendorInfoMapper
{
/**
*
*
* @param vendorId
* @return
*/
public VendorInfo selectVendorInfoByVendorId(Long vendorId);
/**
*
*
* @param vendorInfo
* @return
*/
public List<VendorInfo> selectVendorInfoList(VendorInfo vendorInfo);
/**
*
*
* @param vendorInfo
* @return
*/
public int insertVendorInfo(VendorInfo vendorInfo);
/**
*
*
* @param vendorInfo
* @return
*/
public int updateVendorInfo(VendorInfo vendorInfo);
/**
*
*
* @param vendorId
* @return
*/
public int deleteVendorInfoByVendorId(Long vendorId);
/**
*
*
* @param vendorIds
* @return
*/
public int deleteVendorInfoByVendorIds(String[] vendorIds);
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.service;
import java.math.BigDecimal;
import java.util.List;
import com.ruoyi.sip.domain.ProjectInfo;
import com.ruoyi.sip.dto.HomepageQueryDto;
@ -64,4 +65,6 @@ public interface IProjectInfoService
String exportList(ProjectInfo projectInfo);
StatisticsDto homePageData(HomepageQueryDto dto);
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.service;
import java.math.BigDecimal;
import java.util.List;
import java.util.function.Supplier;
@ -64,4 +65,6 @@ public interface IProjectProductInfoService
List<ProjectProductInfo> selectProjectProductInfoListByProjectId(List<Long> projectId);
void saveBatch(List<ProjectProductInfo> addList);
void calcByDiscountFold(BigDecimal discountFold, Long projectId);
}

View File

@ -0,0 +1,63 @@
package com.ruoyi.sip.service;
import com.ruoyi.sip.domain.VendorInfo;
import java.util.List;
/**
* Service
*
* @author ruoyi
* @date 2025-07-23
*/
public interface IVendorInfoService
{
/**
*
*
* @param vendorId
* @return
*/
public VendorInfo selectVendorInfoByVendorId(Long vendorId);
/**
*
*
* @param vendorInfo
* @return
*/
public List<VendorInfo> selectVendorInfoList(VendorInfo vendorInfo);
/**
*
*
* @param vendorInfo
* @return
*/
public int insertVendorInfo(VendorInfo vendorInfo);
/**
*
*
* @param vendorInfo
* @return
*/
public int updateVendorInfo(VendorInfo vendorInfo);
/**
*
*
* @param vendorIds
* @return
*/
public int deleteVendorInfoByVendorIds(String vendorIds);
/**
*
*
* @param vendorId
* @return
*/
public int deleteVendorInfoByVendorId(Long vendorId);
}

View File

@ -32,6 +32,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
@ -62,6 +63,8 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
private IProjectOperateLogService operateLogService;
@Autowired
private IProjectPocInfoService pocInfoService;
@Autowired
private ICustomerInfoService customerInfoService;
@Autowired
private IProjectOrderInfoService orderInfoService;
@ -128,11 +131,22 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
if (CollUtil.isEmpty(projectInfos)){
return projectInfos;
}
//处理客户信息地址
List<String> customerCodeList = projectInfos.stream().map(ProjectInfo::getCustomerCode).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
CustomerInfo queryCustomerDto = new CustomerInfo();
queryCustomerDto.setCustomerCodeList(customerCodeList);
List<CustomerInfo> customerInfoList = customerInfoService.selectCustomerInfoList(queryCustomerDto);
Map<String, CustomerInfo> customerInfoMap = customerInfoList.stream().collect(Collectors.toMap(CustomerInfo::getCustomerCode, Function.identity(), (v1, v2) -> v1));
List<Long> idList = projectInfos.stream().map(ProjectInfo::getId).collect(Collectors.toList());
List<ProjectOrderInfo> projectOrderInfos = orderInfoService.selectProjectOrderInfoByProjectId(idList);
Map<Long, ProjectOrderInfo> orderInfoMap = projectOrderInfos.stream().collect(Collectors.toMap(ProjectOrderInfo::getProjectId, Function.identity(), (v1, v2) -> v1));
LocalDate now = LocalDate.now();
for (ProjectInfo info : projectInfos) {
CustomerInfo customerInfo = customerInfoMap.get(info.getCustomerCode());
if (customerInfo != null) {
info.setCustomerAddress(customerInfo.getAddress());
}
info.setCanGenerate(orderInfoMap.get(info.getId()) == null);
if (info.getLastWorkUpdateTime() != null) {
LocalDate localDate = info.getLastWorkUpdateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

View File

@ -1,6 +1,9 @@
package com.ruoyi.sip.service.impl;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
@ -9,7 +12,15 @@ import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.mail.Mail;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.extra.template.engine.thymeleaf.ThymeleafEngine;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
@ -25,6 +36,7 @@ import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.flowable.domain.BuApproveConfig;
import com.ruoyi.sip.flowable.domain.Todo;
@ -37,6 +49,7 @@ import com.ruoyi.sip.service.*;
import com.ruoyi.sip.flowable.service.DeleteFlowableProcessInstanceCmd;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.utils.TemplateMailUtil;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
@ -47,6 +60,7 @@ import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.ProjectOrderInfoMapper;
import com.ruoyi.common.core.text.Convert;
@ -330,56 +344,56 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
}
fileLogService.deleteProjectOrderFileLogByIds(deleteFileId);
}
if (StringUtils.isNotEmpty(projectOrderInfo.getProcessType())) {
ProcessInstance processInstance = todoService.getProcessInstance(getFlowBusinessKey(existProjectOrderInfo.getOrderCode(),projectOrderInfo.getProcessTemplate()));
// if (processInstance != null) {
// DeleteFlowableProcessInstanceCmd cmd = new DeleteFlowableProcessInstanceCmd(processInstance.getProcessInstanceId(), "删除流程实例", true);
// managementService.executeCommand(cmd);
// todoService.deleteTodoByBusinessKey();
// }
if (processInstance == null) {
String orderFlowKey= ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(projectOrderInfo.getProcessType())?
orderOnlineFlowKey:orderOfflineFlowKey;
//启动流程
todoService.startProcess(getFlowBusinessKey(existProjectOrderInfo.getOrderCode(),projectOrderInfo.getProcessTemplate()), new HashMap<String, Object>() {{
put("processType", projectOrderInfo.getProcessType());
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
put("extendField1", projectOrderInfo.getVersionCode());
// put("approveUserls", userMapper.selectApproveUserls(order.getDepCoding()));
}}, orderFlowKey);
if (ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode().equals(projectOrderInfo.getOrderStatus())) {
List<ProcessInstance> processInstanceList = todoService.listProcessInstance(existProjectOrderInfo.getOrderCode());
if (CollUtil.isNotEmpty(processInstanceList)) {
for (ProcessInstance processInstance : processInstanceList) {
//删除流程实例 不删流程实例可能导致 售前A提交流程被驳回后 售前B无法提交审核 因为流程驳回是驳回后,流程处理人是售前A
DeleteFlowableProcessInstanceCmd cmd = new DeleteFlowableProcessInstanceCmd(processInstance.getProcessInstanceId(), "删除流程实例", true);
managementService.executeCommand(cmd);
}
todoService.deleteTodoByBusinessKey(existProjectOrderInfo.getOrderCode());
}
// todoService.completed(null, null,orderFlowKey+"#"+projectOrderInfo.getProjectCode());
complete(null, null, getFlowBusinessKey(existProjectOrderInfo.getOrderCode(),projectOrderInfo.getProcessTemplate()));
String orderFlowKey = ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(projectOrderInfo.getProcessType()) ?
orderOnlineFlowKey : orderOfflineFlowKey;
//启动流程
todoService.startProcess(getFlowBusinessKey(existProjectOrderInfo.getOrderCode(), projectOrderInfo.getProcessType()), new HashMap<String, Object>() {{
put("processTemplate", projectOrderInfo.getProcessTemplate());
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
put("extendField1", projectOrderInfo.getVersionCode());
}}, orderFlowKey);
complete(null, null, getFlowBusinessKey(existProjectOrderInfo.getOrderCode(), projectOrderInfo.getProcessType()));
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode());
//根据提交类型判断折上折是 100% 98.8%或者98.5%
if ("0".equals(projectOrderInfo.getProcessTemplate())){
if ("0".equals(projectOrderInfo.getProcessTemplate())) {
//直签 98.8
projectOrderInfo.setDiscountFold(new BigDecimal("0.985"));
}else if("1".equals(projectOrderInfo.getProcessTemplate())){
} else if ("1".equals(projectOrderInfo.getProcessTemplate())) {
//总代 98.5
projectOrderInfo.setDiscountFold(new BigDecimal("0.985"));
}else{
} else {
projectOrderInfo.setDiscountFold(BigDecimal.ONE);
}
}
return projectOrderInfoMapper.updateProjectOrderInfo(projectOrderInfo);
}
private String getFlowBusinessKey(String code,String processTemplate) {
private String getFlowBusinessKey(String code, String processType) {
if (StringUtils.isEmpty(code)) {
throw new ServiceException("流程BusinessKey为空");
}
if (StringUtils.isEmpty(processTemplate)) {
if (StringUtils.isEmpty(processType)) {
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderCode(code);
List<ProjectOrderInfo> projectOrderInfos = projectOrderInfoMapper.selectProjectOrderInfoList(projectOrderInfo);
if (CollUtil.isEmpty(projectOrderInfos)){
throw new ServiceException("流程对应的订单不存在");
}
processTemplate = projectOrderInfos.get(0).getProcessTemplate();
processType = projectOrderInfos.get(0).getProcessType();
}
String orderFlowKey= ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(processTemplate)?
String orderFlowKey = ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(processType) ?
orderOnlineFlowKey:orderOfflineFlowKey;
if (code.startsWith(orderFlowKey + "#")) {
return code;
@ -955,19 +969,11 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
//设置审批人
Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).taskAssignee(String.valueOf(getSysUser().getUserId())).singleResult();
String name = task.getName();
List<Long> approveUserList = approveConfigService.listByProcessKeyAndTaskName(BuApproveConfig.APPROVE_KEY.ORDER_APPROVE.getKey(), name);
if (CollUtil.isEmpty(approveUserList)) {
throw new ServiceException("审批人为空,无法提交审核");
}
// variable.put("approveUsern", approveUserList.get(0));
variable.put("approveUserns", approveUserList);
if (StringUtils.isEmpty(taskId)) {
taskId = task.getId();
}
if (ObjectUtils.isNotEmpty(variable.get("comment"))) {
ProcessInstance processInstance = todoService.getProcessInstance(businessKey);
taskService.addComment(taskId, processInstance.getProcessInstanceId(), String.valueOf(variable.get("comment")));
@ -985,6 +991,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override
public boolean todoApproveCallback(Todo todo) {
if (CollUtil.isNotEmpty(todo.getVariables())) {
Integer approveBtn = (Integer) todo.getVariables().get("approveBtn");
@ -999,19 +1006,28 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
}
if ("公司领导".equals(todo.getTaskName()) && approveBtn.equals(1)) {
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoByCode(todo.getBusinessKey());
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode());
//修改执行单时间 只有直签且有现金折扣的时间才是配置时间 否则默认30天
int addHour = ProjectOrderInfo.ProcessTemplateEnum.DIRECT_SIGNING.getCode().equals(dbProjectOrderInfo.getProcessTemplate())
&& dbProjectOrderInfo.getDiscountFold() != null && dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) < 0 ? endHour : 30;
projectOrderInfo.setOrderEndTime(DateUtils.addHours(DateUtils.getNowDate(), addHour));
projectOrderInfo.setOrderCode(todo.getBusinessKey());
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
projectOrderInfoMapper.bakData(projectOrderInfo);
//修改执行单时间
projectOrderInfo.setOrderEndTime(DateUtils.addHours(DateUtils.getNowDate(),endHour));
//todo 发送邮件
List<ProjectOrderInfo> projectOrderInfos = projectOrderInfoMapper.selectProjectOrderInfoList(projectOrderInfo);
if (CollUtil.isNotEmpty(projectOrderInfos)) {
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfos.get(0);
// MailUtil.send();
//修改产品数据
// projectInfo
if (dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE)!=0){
productInfoService.calcByDiscountFold(dbProjectOrderInfo.getDiscountFold(), projectOrderInfo.getProjectId());
}
//todo 总代 发 代理商 商务 执行单发 商务 制造商
}
}
return TodoCommonTemplate.super.todoApproveCallback(todo);
@ -1027,4 +1043,20 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
return null;
}
private void sendDeliveryMail(List<String> toEmail,ProjectOrderInfo projectOrderInfo){
if (CollUtil.isEmpty(toEmail)){
log.info("发货邮件发送失败,收件人为空");
return;
}
List<ProjectProductInfo> projectProductInfos = productInfoService.selectProjectProductInfoListByProjectId(Collections.singletonList(projectOrderInfo.getProjectId()));
if (CollUtil.isEmpty(projectProductInfos)){
log.info("发货邮件发送失败,产品信息为空");
return;
}
String templateTile="{}-紫光汇智云桌面-{}-供应商通知发货单";
String title = StringUtils.format(templateTile, projectOrderInfo.getOrderCode(), projectOrderInfo.getProjectName());
TemplateMailUtil.sendTemplateMail(toEmail,title,
TemplateMailUtil.MailTemplate.ORDER_DELIVERY,Dict.create().set("productList", projectProductInfos));
}
}

View File

@ -157,4 +157,16 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
}
}
@Override
public void calcByDiscountFold(BigDecimal discountFold, Long projectId) {
List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(projectId));
for (ProjectProductInfo info : projectProductInfos) {
BigDecimal price = info.getPrice().multiply(discountFold).setScale(2,RoundingMode.HALF_UP);
info.setPrice(price);
info.setAllPrice(price.multiply(new BigDecimal(info.getQuantity())).setScale(2,RoundingMode.HALF_UP));
info.setDiscount(price.divide(info.getCataloguePrice(),4,RoundingMode.HALF_UP));
}
projectProductInfoMapper.updateBatch(projectProductInfos);
}
}

View File

@ -0,0 +1,113 @@
package com.ruoyi.sip.service.impl;
import java.util.List;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.VendorInfo;
import com.ruoyi.sip.mapper.VendorInfoMapper;
import com.ruoyi.sip.service.IVendorInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.text.Convert;
/**
* Service
*
* @author ruoyi
* @date 2025-07-23
*/
@Service
public class VendorInfoServiceImpl implements IVendorInfoService {
@Autowired
private VendorInfoMapper vendorInfoMapper;
/**
*
*
* @param vendorId
* @return
*/
@Override
public VendorInfo selectVendorInfoByVendorId(Long vendorId) {
return vendorInfoMapper.selectVendorInfoByVendorId(vendorId);
}
/**
*
*
* @param vendorInfo
* @return
*/
@Override
public List<VendorInfo> selectVendorInfoList(VendorInfo vendorInfo) {
return vendorInfoMapper.selectVendorInfoList(vendorInfo);
}
/**
*
*
* @param vendorInfo
* @return
*/
@Override
public int insertVendorInfo(VendorInfo vendorInfo) {
checkUnqCode(vendorInfo);
vendorInfo.setVendorStatus(VendorInfo.VendorStatusEnum.NORMAL.getCode());
vendorInfo.setCreateTime(DateUtils.getNowDate());
vendorInfo.setCreateBy(ShiroUtils.getUserId().toString());
return vendorInfoMapper.insertVendorInfo(vendorInfo);
}
private void checkUnqCode(VendorInfo vendorInfo) {
VendorInfo queryDto = new VendorInfo();
queryDto.setVendorCode(vendorInfo.getVendorCode());
List<VendorInfo> vendorInfos = vendorInfoMapper.selectVendorInfoList(queryDto);
int count = vendorInfos.size();
if (vendorInfo.getVendorId() != null) {
count = Math.toIntExact(vendorInfos.stream().filter(vendorInfo1 -> !vendorInfo1.getVendorId().equals(vendorInfo.getVendorId())).count());
}
if (count > 0) {
throw new ServiceException("制造商编码重复,保存失败");
}
}
/**
*
*
* @param vendorInfo
* @return
*/
@Override
public int updateVendorInfo(VendorInfo vendorInfo) {
checkUnqCode(vendorInfo);
vendorInfo.setUpdateTime(DateUtils.getNowDate());
vendorInfo.setUpdateBy(ShiroUtils.getUserId().toString());
return vendorInfoMapper.updateVendorInfo(vendorInfo);
}
/**
*
*
* @param vendorIds
* @return
*/
@Override
public int deleteVendorInfoByVendorIds(String vendorIds) {
return vendorInfoMapper.deleteVendorInfoByVendorIds(Convert.toStrArray(vendorIds));
}
/**
*
*
* @param vendorId
* @return
*/
@Override
public int deleteVendorInfoByVendorId(Long vendorId) {
return vendorInfoMapper.deleteVendorInfoByVendorId(vendorId);
}
}

View File

@ -0,0 +1,89 @@
package com.ruoyi.sip.utils;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.mail.Mail;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.extra.template.engine.thymeleaf.ThymeleafEngine;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import java.util.List;
/**
* @author : ch
* @version : 1.0
* @ClassName : TemplateMailUtil
* @Description :
* @DATE : Created in 10:10 2025/7/29
* <pre> Copyright: Copyright(c) 2025 </pre>
* <pre> Company : </pre>
* Modification History:
* Date Author Version Discription
* --------------------------------------------------------------------------
* 2025/07/29 ch 1.0 Why & What is modified: <> *
*/
@Slf4j
public class TemplateMailUtil {
/**
*
* @param toEmail
* @param title
* @param path mailTemplate
* @param dict Dict.create().set("productList", projectProductInfos)
* @author ch
* @Date 2025/07/29 09:55
*/
public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict) {
String enbaled = SpringUtils.getProperty("unis.mail.enabled", "false");
if (Boolean.getBoolean(enbaled)) {
log.warn("邮件发送开关未开启");
return;
}
TemplateConfig config = new TemplateConfig("mailTemplate", TemplateConfig.ResourceMode.CLASSPATH);
config.setCustomEngine(ThymeleafEngine.class);
TemplateEngine engine = TemplateUtil.createEngine(config);
Template template = engine.getTemplate(path.getPath());
String result = template.render(dict);
try{
org.springframework.core.io.Resource resource = SpringUtils.getResource("classpath:static/img/companyLogo.png");
Mail mail = Mail.create()
.setTos(toEmail.toArray(new String[0]))
.setTitle(title)
.setContent(result)
.setHtml(true);
mail.addImage("signature",resource.getFile());
mail.send();
} catch (Exception e) {
log.error("发送邮件失败,错误原因:{},错误详情:{}",e.getMessage(),e.getStackTrace());
}
}
@Getter
public enum MailTemplate {
/**
*
*/
ORDER_DELIVERY("mailOrderDeliveryTemplate.html","发货单"),
;
private final String path;
private final String desc;
MailTemplate(String path,String desc) {
this.path = path;
this.desc = desc;
}
}
}

View File

@ -43,6 +43,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="approveRole != null">#{approveRole},</if>
</trim>
</insert>
<insert id="saveBatch">
insert into bu_approve_config (process_key, task_name, approve_user, approve_role) values
<foreach item="item" collection="list" separator=",">
(#{item.processKey}, #{item.taskName}, #{item.approveUser}, #{item.approveRole})
</foreach>
on duplicate key update
approve_user=values(approve_user),
approve_role=values(approve_role)
</insert>
<update id="updateBuApproveConfig" parameterType="BuApproveConfig">
update bu_approve_config

View File

@ -25,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectTodoCompletedVo">
select todo_id, business_key, process_key, process_name, task_name, approve_user_name,approve_time,approve_opinion,
approve_status,apply_user_name, apply_time, extend_field1, extend_field2,task_id,process_instance_id,form_key from bu_todo_completed
approve_status,apply_user_name, apply_time, extend_field1, extend_field2,task_id,process_instance_id,form_key,approve_user from bu_todo_completed
</sql>
<select id="selectTodoList" parameterType="Todo" resultType="todo">
@ -233,4 +233,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</if>
</select>
<select id="selectLastApproveTodo" resultType="com.ruoyi.sip.flowable.domain.Todo">
<include refid="selectTodoCompletedVo"/>
where business_key = #{businessKey}
<if test="taskName!=null and taskName!=''">
and task_name like concat('%',#{taskName},'%')
</if>
</select>
</mapper>

View File

@ -31,6 +31,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="filePath != null and filePath != ''"> and file_path = #{filePath}</if>
<if test="fileType != null and fileType != ''"> and file_type = #{fileType}</if>
</where>
order by t1.id
</select>
<select id="selectProjectOrderFileLogById" parameterType="Long" resultMap="ProjectOrderFileLogResult">

View File

@ -19,6 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="deliveryTime" column="delivery_time" />
<result property="companyDelivery" column="company_delivery" />
<result property="notifier" column="notifier" />
<result property="notifierAddress" column="notifier_address" />
<result property="notifierEmail" column="notifier_email" />
<result property="notifierPhone" column="notifier_phone" />
<result property="duty" column="duty" />
@ -38,7 +39,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectProjectOrderInfoVo">
select id, project_id,province, city, business_person, business_email, business_phone, order_code, currencyType,
shipment_amount, actual_purchase_amount, order_end_time, delivery_time, company_delivery, notifier,
notifier_email, notifier_phone, duty, duty_email, duty_phone, order_channel, partner_code, supplier,
notifier_email, notifier_phone, duty, duty_email, duty_phone, order_channel, partner_code, supplier,notifier_address,
remark, order_status, create_by, create_time, update_by, update_time,version_code,process_type,process_template,discount_fold from project_order_info t1
</sql>
<sql id="selectProjectOrderInfoRelationVo">
@ -46,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.shipment_amount, t1.actual_purchase_amount, t1.order_end_time, t1.delivery_time, t1.company_delivery, t1.notifier,
t1.notifier_email, t1.notifier_phone, t1.duty, t1.duty_email, t1.duty_phone, t1.order_channel, t1.partner_code, t1.supplier,
t1.remark, t1.order_status, t1.create_by, t1.create_time, t1.update_by, t1.update_time,t1.partner_user_name,t1.partner_email
,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold
,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold,t1.notifier_address
,t2.project_code,t2.project_name,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time
,t2.customer_phone,t2.customer_user_name,t2.agent_code,t2.customer_code
,t3.partner_name,t3.level
@ -83,6 +84,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="notifier != null and notifier != ''"> and t1.notifier = #{notifier}</if>
<if test="notifierEmail != null and notifierEmail != ''"> and t1.notifier_email = #{notifierEmail}</if>
<if test="notifierPhone != null and notifierPhone != ''"> and t1.notifier_phone = #{notifierPhone}</if>
<if test="notifierAddress != null and notifierAddress != ''"> and t1.notifier_address = #{notifierAddress}</if>
<if test="duty != null and duty != ''"> and t1.duty = #{duty}</if>
<if test="dutyName != null and dutyName != ''"> and t5.user_name like concat('%', #{dutyName}, '%')</if>
<if test="dutyEmail != null and dutyEmail != ''"> and t1.duty_email = #{dutyEmail}</if>
@ -169,6 +171,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where create_time >=DATE_SUB(CURDATE(), INTERVAL ${day} DAY)
group by date_format(create_time,'%Y-%m-%d')
</select>
<select id="selectProjectOrderInfoByCode" resultType="com.ruoyi.sip.domain.ProjectOrderInfo">
<include refid="selectProjectOrderInfoRelationVo"/>
where t1.order_code = #{orderCode}
</select>
<insert id="insertProjectOrderInfo" parameterType="ProjectOrderInfo" useGeneratedKeys="true" keyProperty="id">
insert into project_order_info
@ -190,6 +196,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="notifier != null">notifier,</if>
<if test="notifierEmail != null">notifier_email,</if>
<if test="notifierPhone != null">notifier_phone,</if>
<if test="notifierAddress != null">notifier_address,</if>
<if test="duty != null">duty,</if>
<if test="dutyEmail != null">duty_email,</if>
<if test="dutyPhone != null">duty_phone,</if>
@ -227,6 +234,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="notifier != null">#{notifier},</if>
<if test="notifierEmail != null">#{notifierEmail},</if>
<if test="notifierPhone != null">#{notifierPhone},</if>
<if test="notifierAddress != null">#{notifierAddress},</if>
<if test="duty != null">#{duty},</if>
<if test="dutyEmail != null">#{dutyEmail},</if>
<if test="dutyPhone != null">#{dutyPhone},</if>
@ -271,6 +279,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="notifier != null">notifier = #{notifier},</if>
<if test="notifierEmail != null">notifier_email = #{notifierEmail},</if>
<if test="notifierPhone != null">notifier_phone = #{notifierPhone},</if>
<if test="notifierAddress != null">notifier_address = #{notifierAddress},</if>
<if test="duty != null">duty = #{duty},</if>
<if test="dutyEmail != null">duty_email = #{dutyEmail},</if>
<if test="dutyPhone != null">duty_phone = #{dutyPhone},</if>
@ -320,6 +329,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="notifier != null">notifier = #{notifier},</if>
<if test="notifierEmail != null">notifier_email = #{notifierEmail},</if>
<if test="notifierPhone != null">notifier_phone = #{notifierPhone},</if>
<if test="notifierAddress != null">notifier_address = #{notifierAddress},</if>
<if test="duty != null">duty = #{duty},</if>
<if test="dutyEmail != null">duty_email = #{dutyEmail},</if>
<if test="dutyPhone != null">duty_phone = #{dutyPhone},</if>

View File

@ -1,9 +1,9 @@
<?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">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sip.mapper.ProductInfoMapper">
<resultMap type="ProductInfo" id="ProductInfoResult">
<result property="id" column="id" />
<result property="productCode" column="product_code" />
@ -20,27 +20,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectProductInfoVo">
select id, product_code, product_name, model, description, remark, created_at, updated_at, deleted_at,value,type,hz_code,catalogue_price,guidance_discount from product_info
select t1.id, t1.product_code, t1.product_name, t1.model, t1.description, t1.remark, t1.created_at, t1.updated_at,
t1.deleted_at,t1.value,t1.type,t1.hz_code,t1.catalogue_price,t1.guidance_discount,t1.vendor_code
,t2.vendor_name
from product_info t1 left join vendor_info t2 on t1.vendor_code = t2.vendor_code
</sql>
<select id="selectProductInfoList" parameterType="ProductInfo" resultMap="ProductInfoResult">
<include refid="selectProductInfoVo"/>
<where>
and status = 0
<if test="productCode != null and productCode != ''"> and product_code like concat('%', #{productCode}, '%')</if>
<if test="productName != null and productName != ''"> and product_name like concat('%', #{productName}, '%')</if>
<if test="model != null and model != ''"> and model like concat('%', #{model}, '%')</if>
<if test="type != null and type != ''"> and find_in_set(type , #{type})</if>
and t1.status = 0
<if test="productCode != null and productCode != ''"> and t1.product_code like concat('%', #{productCode}, '%')</if>
<if test="productName != null and productName != ''"> and t1.product_name like concat('%', #{productName}, '%')</if>
<if test="model != null and model != ''"> and t1.model like concat('%', #{model}, '%')</if>
<if test="type != null and type != ''"> and find_in_set(t1.type , #{type})</if>
<if test="vendorName != null and vendorName != ''"> and t2.vendor_name like concat('%', #{vendorName}, '%')</if>
</where>
</select>
<select id="selectProductInfoById" parameterType="Long" resultMap="ProductInfoResult">
<include refid="selectProductInfoVo"/>
where id = #{id}
where t1.id = #{id}
</select>
<select id="selectProductInfoByCodeList" resultMap="ProductInfoResult">
<include refid="selectProductInfoVo"/>
where product_code in
where t1.product_code in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
@ -48,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="listByProductCodeList" resultMap="ProductInfoResult">
<include refid="selectProductInfoVo"/>
where product_code in
where t1.product_code in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
@ -70,6 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.deleted_at ,
t1.catalogue_price,
t1.guidance_discount,
t1.vendor_code
t2.serial_number
FROM
product_info t1 left join delivery_list t2 on t1.product_code=t2.product_code
@ -98,26 +103,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cataloguePrice != null">catalogue_price,</if>
<if test="guidanceDiscount != null ">guidance_discount,</if>
<if test="model != null and model != ''">model,</if>
<if test="vendorCode != null and vendorCode != ''">vendor_code,</if>
<if test="description != null">description,</if>
<if test="remark != null">remark,</if>
<if test="type != null">type,</if>
<if test="value != null">value,</if>
<if test="hzCode != null">hz_code,</if>
created_at,status,create_by
</trim>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="productCode != null and productCode != ''">#{productCode},</if>
<if test="productName != null and productName != ''">#{productName},</if>
<if test="cataloguePrice != null">#{cataloguePrice},</if>
<if test="guidanceDiscount != null ">#{guidanceDiscount},</if>
<if test="model != null and model != ''">#{model},</if>
<if test="vendorCode != null and vendorCode != ''">#{vendorCode},</if>
<if test="description != null">#{description},</if>
<if test="remark != null">#{remark},</if>
<if test="type != null">#{type},</if>
<if test="value != null">#{value},</if>
<if test="hzCode != null">#{hzCode},</if>
NOW(),0,#{createBy}
</trim>
</trim>
</insert>
<update id="updateProductInfo" parameterType="ProductInfo">
@ -129,6 +136,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="guidanceDiscount != null ">guidance_discount=#{guidanceDiscount},</if>
<if test="model != null and model != ''">model = #{model},</if>
<if test="description != null">description = #{description},</if>
<if test="vendorCode != null and vendorCode != ''">vendor_code=#{vendorCode},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="type != null">type = #{type},</if>
<if test="value != null">value = #{value},</if>

View File

@ -0,0 +1,103 @@
<?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.sip.mapper.VendorInfoMapper">
<resultMap type="VendorInfo" id="VendorInfoResult">
<result property="vendorId" column="vendor_id" />
<result property="vendorCode" column="vendor_code" />
<result property="vendorName" column="vendor_name" />
<result property="vendorAddress" column="vendor_address" />
<result property="vendorUser" column="vendor_user" />
<result property="vendorEmail" column="vendor_email" />
<result property="vendorPhone" column="vendor_phone" />
<result property="vendorStatus" column="vendor_status" />
<result property="createBy" column="create_by" />
<result property="updateBy" column="update_by" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectVendorInfoVo">
select vendor_id, vendor_code, vendor_name, vendor_address, vendor_user, vendor_email, vendor_phone, vendor_status, create_by, update_by, create_time, update_time from vendor_info
</sql>
<select id="selectVendorInfoList" parameterType="VendorInfo" resultMap="VendorInfoResult">
<include refid="selectVendorInfoVo"/>
<where>
<if test="vendorCode != null and vendorCode != ''"> and vendor_code like concat('%', #{vendorCode}, '%')</if>
<if test="vendorName != null and vendorName != ''"> and vendor_name like concat('%', #{vendorName}, '%')</if>
<if test="vendorAddress != null and vendorAddress != ''"> and vendor_address like concat('%', #{vendorAddress}, '%')</if>
<if test="vendorUser != null and vendorUser != ''"> and vendor_user = #{vendorUser}</if>
<if test="vendorStatus != null and vendorStatus != ''"> and vendor_status = #{vendorStatus}</if>
</where>
</select>
<select id="selectVendorInfoByVendorId" parameterType="Long" resultMap="VendorInfoResult">
<include refid="selectVendorInfoVo"/>
where vendor_id = #{vendorId}
</select>
<insert id="insertVendorInfo" parameterType="VendorInfo">
insert into vendor_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="vendorId != null">vendor_id,</if>
<if test="vendorCode != null and vendorCode != ''">vendor_code,</if>
<if test="vendorName != null and vendorName != ''">vendor_name,</if>
<if test="vendorAddress != null">vendor_address,</if>
<if test="vendorUser != null and vendorUser != ''">vendor_user,</if>
<if test="vendorEmail != null">vendor_email,</if>
<if test="vendorPhone != null and vendorPhone != ''">vendor_phone,</if>
<if test="vendorStatus != null">vendor_status,</if>
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="vendorId != null">#{vendorId},</if>
<if test="vendorCode != null and vendorCode != ''">#{vendorCode},</if>
<if test="vendorName != null and vendorName != ''">#{vendorName},</if>
<if test="vendorAddress != null">#{vendorAddress},</if>
<if test="vendorUser != null and vendorUser != ''">#{vendorUser},</if>
<if test="vendorEmail != null">#{vendorEmail},</if>
<if test="vendorPhone != null and vendorPhone != ''">#{vendorPhone},</if>
<if test="vendorStatus != null">#{vendorStatus},</if>
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateVendorInfo" parameterType="VendorInfo">
update vendor_info
<trim prefix="SET" suffixOverrides=",">
<if test="vendorCode != null and vendorCode != ''">vendor_code = #{vendorCode},</if>
<if test="vendorName != null and vendorName != ''">vendor_name = #{vendorName},</if>
<if test="vendorAddress != null">vendor_address = #{vendorAddress},</if>
<if test="vendorUser != null and vendorUser != ''">vendor_user = #{vendorUser},</if>
<if test="vendorEmail != null">vendor_email = #{vendorEmail},</if>
<if test="vendorPhone != null and vendorPhone != ''">vendor_phone = #{vendorPhone},</if>
<if test="vendorStatus != null">vendor_status = #{vendorStatus},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where vendor_id = #{vendorId}
</update>
<delete id="deleteVendorInfoByVendorId" parameterType="Long">
delete from vendor_info where vendor_id = #{vendorId}
</delete>
<delete id="deleteVendorInfoByVendorIds" parameterType="String">
delete from vendor_info where vendor_id in
<foreach item="vendorId" collection="array" open="(" separator="," close=")">
#{vendorId}
</foreach>
</delete>
</mapper>

View File

@ -63,9 +63,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select u.user_id, u.dept_id, u.login_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.salt, 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="userIdList!=null and userIdList.size>0">
and u.user_id in
<foreach collection="userIdList" item="userId" separator="," open=" (" close=")">
#{userId}
</foreach>
</if>
<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="loginName != null and loginName != ''">
AND u.login_name like concat('%', #{loginName}, '%')
</if>