Browse Source

[feat]售后管理:

售后单
新增详情功能
dev
liuxiaoxu 5 months ago
parent
commit
819e2425da
  1. 11
      ruoyi-admin/src/main/java/com/ruoyi/aftersales/controller/AftersalesOrderController.java
  2. 7
      ruoyi-admin/src/main/java/com/ruoyi/aftersales/domain/AftersalesOrder.java
  3. 9
      ruoyi-admin/src/main/java/com/ruoyi/aftersales/mapper/AftersalesOrderMapper.java
  4. 9
      ruoyi-admin/src/main/java/com/ruoyi/aftersales/service/IAftersalesOrderService.java
  5. 17
      ruoyi-admin/src/main/java/com/ruoyi/aftersales/service/impl/AftersalesOrderServiceImpl.java
  6. 49
      ruoyi-admin/src/main/resources/mapper/aftersales/AftersalesOrderMapper.xml
  7. 16
      ruoyi-admin/src/main/resources/templates/aftersales/aftersalesOrder/aftersalesOrder.html
  8. 430
      ruoyi-admin/src/main/resources/templates/aftersales/aftersalesOrder/detail.html

11
ruoyi-admin/src/main/java/com/ruoyi/aftersales/controller/AftersalesOrderController.java

@ -126,6 +126,17 @@ public class AftersalesOrderController extends BaseController
return toAjax(aftersalesOrderService.updateAftersalesOrder(aftersalesOrder)); return toAjax(aftersalesOrderService.updateAftersalesOrder(aftersalesOrder));
} }
/**
* 查看销售订单详情
*/
@GetMapping("/detail/{aftersalesOrderId}")
public String detail(@PathVariable("aftersalesOrderId") Long aftersalesOrderId, ModelMap mmap)
{
AftersalesOrder aftersalesOrder = aftersalesOrderService.selectAftersalesOrderWithAttachById(aftersalesOrderId);
mmap.put("detail", aftersalesOrder);
return prefix + "/detail";
}
/** /**
* 派单 * 派单

7
ruoyi-admin/src/main/java/com/ruoyi/aftersales/domain/AftersalesOrder.java

@ -74,7 +74,7 @@ public class AftersalesOrder extends BaseEntity
/** 客户要求出发日期 */ /** 客户要求出发日期 */
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "客户要求出发日期", width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "客户要求出发日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date startDate; private String startDate;
/** 收货联系人 */ /** 收货联系人 */
@Excel(name = "收货联系人") @Excel(name = "收货联系人")
@ -261,12 +261,12 @@ public class AftersalesOrder extends BaseEntity
{ {
return enterpriseSum; return enterpriseSum;
} }
public void setStartDate(Date startDate) public void setStartDate(String startDate)
{ {
this.startDate = startDate; this.startDate = startDate;
} }
public Date getStartDate() public String getStartDate()
{ {
return startDate; return startDate;
} }
@ -449,6 +449,7 @@ public class AftersalesOrder extends BaseEntity
.append("applyUser", getApplyUser()) .append("applyUser", getApplyUser())
.append("cancelInstanceId", getCancelInstanceId()) .append("cancelInstanceId", getCancelInstanceId())
.append("restoreInstanceId", getRestoreInstanceId()) .append("restoreInstanceId", getRestoreInstanceId())
.append("fileIdStr",getFileIdStr())
.toString(); .toString();
} }
} }

9
ruoyi-admin/src/main/java/com/ruoyi/aftersales/mapper/AftersalesOrderMapper.java

@ -19,6 +19,15 @@ public interface AftersalesOrderMapper
*/ */
public AftersalesOrder selectAftersalesOrderById(Long aftersalesOrderId); public AftersalesOrder selectAftersalesOrderById(Long aftersalesOrderId);
/**
* 查询售后单关联附件表
*
* @param aftersalesOrderId 售后单ID
* @return 售后单
*/
public AftersalesOrder selectAftersalesOrderWithAttachById(Long aftersalesOrderId);
/** /**
* 查询售后单列表 * 查询售后单列表
* *

9
ruoyi-admin/src/main/java/com/ruoyi/aftersales/service/IAftersalesOrderService.java

@ -19,6 +19,15 @@ public interface IAftersalesOrderService
*/ */
public AftersalesOrder selectAftersalesOrderById(Long aftersalesOrderId); public AftersalesOrder selectAftersalesOrderById(Long aftersalesOrderId);
/**
* 查询售后单关联附件表
*
* @param aftersalesOrderId 售后单ID
* @return 售后单
*/
public AftersalesOrder selectAftersalesOrderWithAttachById(Long aftersalesOrderId);
/** /**
* 查询售后单列表 * 查询售后单列表
* *

17
ruoyi-admin/src/main/java/com/ruoyi/aftersales/service/impl/AftersalesOrderServiceImpl.java

@ -1,5 +1,6 @@
package com.ruoyi.aftersales.service.impl; package com.ruoyi.aftersales.service.impl;
import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -46,6 +47,22 @@ public class AftersalesOrderServiceImpl implements IAftersalesOrderService
return aftersalesOrderMapper.selectAftersalesOrderById(aftersalesOrderId); return aftersalesOrderMapper.selectAftersalesOrderById(aftersalesOrderId);
} }
/**
* 查询售后单关联附件表
*
* @param aftersalesOrderId 售后单ID
* @return 售后单
*/
@Override
public AftersalesOrder selectAftersalesOrderWithAttachById(Long aftersalesOrderId)
{
AftersalesOrder aftersalesOrder = aftersalesOrderMapper.selectAftersalesOrderWithAttachById(aftersalesOrderId);
String startDate = aftersalesOrder.getStartDate();
aftersalesOrder.setStartDate(startDate);
return aftersalesOrder;
}
/** /**
* 查询售后单列表 * 查询售后单列表
* *

49
ruoyi-admin/src/main/resources/mapper/aftersales/AftersalesOrderMapper.xml

@ -39,6 +39,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="applyUser" column="apply_user" /> <result property="applyUser" column="apply_user" />
<result property="cancelInstanceId" column="cancel_instance_id" /> <result property="cancelInstanceId" column="cancel_instance_id" />
<result property="restoreInstanceId" column="restore_instance_id" /> <result property="restoreInstanceId" column="restore_instance_id" />
<result property="photoAttachId" column="photo_attach_id" />
</resultMap> </resultMap>
<sql id="selectAftersalesOrderVo"> <sql id="selectAftersalesOrderVo">
@ -61,7 +62,53 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectAftersalesOrderVo"/> <include refid="selectAftersalesOrderVo"/>
where aftersales_order_id = #{aftersalesOrderId} where aftersales_order_id = #{aftersalesOrderId}
</select> </select>
<!-- 关联附件表-->
<select id="selectAftersalesOrderWithAttachById" parameterType="Long" resultMap="AftersalesOrderResult">
select so.aftersales_order_id,
so.aftersales_order_code,
so.sales_order_code,
so.make_no,
so.user_id,
so.audit_status,
so.aftersales_status,
so.business_name,
so.aftersales_name,
so.customer_id,
so.customer_name,
so.material_no,
so.material_name,
so.material_sum,
so.enterprise_sum,
so.start_date,
so.delivery_name,
so.delivery_number,
so.company_address,
so.create_by,
so.create_time,
so.update_by,
so.update_time,
so.remark,
so.service_content,
so.user_comment_attachment,
so.instance_id,
so.instance_type,
so.submit_instance_id,
so.apply_title,
so.apply_time,
so.apply_user,
so.cancel_instance_id,
so.restore_instance_id,
att.id as photo_attach_id
from aftersales_order as so
left join sys_attach as att
on so.aftersales_order_id = att.rel_id and att.source_type = 'aftersalesOrder' and
att.source_sub_type = 'photo'
where so.aftersales_order_id = #{aftersalesOrderId}
</select>
<insert id="insertAftersalesOrder" parameterType="AftersalesOrder" useGeneratedKeys="true" keyProperty="aftersalesOrderId"> <insert id="insertAftersalesOrder" parameterType="AftersalesOrder" useGeneratedKeys="true" keyProperty="aftersalesOrderId">
insert into aftersales_order insert into aftersales_order
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">

16
ruoyi-admin/src/main/resources/templates/aftersales/aftersalesOrder/aftersalesOrder.html

@ -75,7 +75,7 @@
var restoreFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:restore')}]]; var restoreFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:restore')}]];
var sendOrdersFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:sendOrders')}]]; var sendOrdersFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:sendOrders')}]];
var uploadReportFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:uploadReport')}]]; var uploadReportFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:uploadReport')}]];
var detailFlag = [[${@permission.hasPermi('aftersales:aftersalesOrder:detail')}]];
var aftersalesStatusDatas = [[${@dict.getType('sales_aftersales_status')}]]; var aftersalesStatusDatas = [[${@dict.getType('sales_aftersales_status')}]];
var prefix = ctx + "aftersales/aftersalesOrder"; var prefix = ctx + "aftersales/aftersalesOrder";
@ -90,6 +90,8 @@
exportUrl: prefix + "/export", exportUrl: prefix + "/export",
sendOrdersUrl: prefix + "/sendOrders/{id}", sendOrdersUrl: prefix + "/sendOrders/{id}",
uploadReportUrl: prefix + "/uploadReport/{id}", uploadReportUrl: prefix + "/uploadReport/{id}",
detailUrl: prefix + "/uploadReport/{id}",
modalName: "售后单", modalName: "售后单",
columns: [{ columns: [{
checkbox: true checkbox: true
@ -172,9 +174,9 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-success btn-xs ' + sendOrdersFlag + '" href="javascript:void(0)" onclick="sendOrders(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>派单</a> '); actions.push('<a class="btn btn-success btn-xs ' + sendOrdersFlag + '" href="javascript:void(0)" onclick="sendOrders(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>派单</a> ');
actions.push('<a class="btn btn-success btn-xs ' + uploadReportFlag + '" href="javascript:void(0)" onclick="uploadReport(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>上传报告</a> '); actions.push('<a class="btn btn-success btn-xs ' + uploadReportFlag + '" href="javascript:void(0)" onclick="uploadReport(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>上传报告</a> ');
actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="detail(\'' + row.aftersalesOrderId + '\')"><i class="fa fa-edit"></i>详情</a> ');
return actions.join(''); return actions.join('');
} }
}] }]
@ -182,6 +184,16 @@
$.table.init(options); $.table.init(options);
}); });
/*详情*/
function detail(aftersalesOrderId) {
// 在这里编写派单操作的逻辑,使用传入的aftersalesOrderId参数
// 示例逻辑:
var url = ctx + 'aftersales/aftersalesOrder/detail/'+aftersalesOrderId;
console.log(url);
$.modal.open("上传报告",url);
}
/*派单*/ /*派单*/
function sendOrders(aftersalesOrderId) { function sendOrders(aftersalesOrderId) {
// 在这里编写派单操作的逻辑,使用传入的aftersalesOrderId参数 // 在这里编写派单操作的逻辑,使用传入的aftersalesOrderId参数

430
ruoyi-admin/src/main/resources/templates/aftersales/aftersalesOrder/detail.html

@ -0,0 +1,430 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('上传报告')" />
<th:block th:include="include :: datetimepicker-css" />
<th:block th:include="include :: summernote-css" />
<th:block th:include="include :: select2-css" />
<link th:href="@{/ajax/libs/element-ui/element-ui.css}" rel="stylesheet"/>
</head>
<body class="white-bg">
<div id="app" class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-aftersalesOrder-edit" th:object="${detail}">
<input name="aftersalesOrderId" th:field="*{aftersalesOrderId}" type="hidden">
<div class="form-group">
<label class="col-sm-4 control-label">销售单号:</label>
<div class="col-sm-8">
<input name="salesOrderCode" th:field="*{salesOrderCode}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">生产单号:</label>
<div class="col-sm-8">
<input name="makeNo" th:field="*{makeNo}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">客户ID:</label>
<div class="col-sm-8">
<input name="customerId" th:field="*{customerId}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">客户名称:</label>
<div class="col-sm-8">
<input name="customerName" th:field="*{customerName}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">公司地址:</label>
<div class="col-sm-8">
<input name="companyAddress" th:field="*{companyAddress}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">收货联系人:</label>
<div class="col-sm-8">
<input name="deliveryName" th:field="*{deliveryName}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">收货电话:</label>
<div class="col-sm-8">
<input name="deliveryNumber" th:field="*{deliveryNumber}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">客户要求出发日期:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="startDate" class="form-control" th:value="*{startDate}" placeholder="yyyy-mm-dd" type="text" readonly>
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">备注:</label>
<div class="col-sm-8">
<input name="remark" th:field="*{remark}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-row">
<div class="col-sm-12 select-table table-striped">
<h3 class="mb-4">选择设备</h3>
<table id="bootstrap-table"></table>
</div>
</div>
<div class="form-group">
<h3 class="mb-4">派单</h3>
<label class="col-sm-3 control-label">售后员:</label>
<div class="col-sm-9">
<input name="aftersalesName" th:field="*{aftersalesName}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
</div>
<div class="form-group">
<h3 class="mb-4">售后报告</h3>
<!-- 服务内容 -->
<div class="form-row mb-4">
<label class="col-sm-3 control-label">服务内容:</label>
<div class="col-sm-8">
<textarea name="serviceContent" class="form-control" readonly>[[*{serviceContent}]]</textarea>
</div>
</div>
<!-- 用户评价 -->
<div class="form-row">
<label class="col-sm-4 control-label">用户评价:</label>
<div class="col-sm-8">
<el-upload
:action="fileUploadUrl"
:on-success="uploadSuccess"
:file-list="fileList"
:limit="5"
list-type="picture"
accept=".jpg,.png"
multiple
:before-remove="preventDeletion">
</el-upload>
</div>
<input id="photoAttachId" name = "photoAttachId" hidden th:field="*{photoAttachId}">
<input id="fileIdStr" type="text" name="fileIdStr" th:field="*{fileIdStr}" hidden>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<th:block th:include="include :: summernote-js" />
<th:block th:include="include :: select2-js" />
<script th:src="@{/ajax/libs/vue/vue.js}"></script>
<script th:src="@{/ajax/libs/element-ui/element-ui.js}"></script>
<script th:inline="javascript">
var prefix = ctx + "aftersales/aftersalesOrder";
var detail = [[${detail}]];
$("#form-aftersalesOrder-edit").validate({
focusCleanup: true
});
new Vue({
el: '#app',
data: function() {
return {
fileList: [],
fileUploadUrl: ctx + "common/uploadSingleFile",
fileDeleteUrl: ctx + "common/deleteFile",
getListByAttachIdUrl: ctx + "system/attach/file/getListByAttachId",
fileIdList:[],
removeFileIdList:[],
}
},
mounted() {
// 控制下拉框选中
// var materialType = $("#materialType").val();
// $("#selectMaterialType").val(materialType).trigger("change");
var that = this;
// 页面渲染完成,可以执行需要的操作
console.log('页面已渲染完成');
console.log($("#id").val());
console.log($("#photoAttachId").val());
var attachId = $("#photoAttachId").val();
if(attachId){
$.ajax({
type: "get",
url: that.getListByAttachIdUrl,
data: {attachId:attachId},
cache: false,
async: false, // 设置成同步
dataType: 'json',
success: function(result) {
if (result.code == web_status.SUCCESS) {
result.data.forEach((item) => {
that.fileIdList.push(item.id);
that.fileList.push({name: item.name, url: item.url, attachFileId: item.id,isBind:true});
});
} else {
$.modal.msgError(result.msg);
}
},
error: function(error) {
$.modal.msgError("获取附件失败。");
}
});
}
},
methods: {
uploadSuccess(response, file, fileList) {
console.log(response);
if(response.code == web_status.SUCCESS){
var attachFileId = response.data.id;
file.attachFileId = attachFileId;
file.isBind = false;
this.fileIdList.push(attachFileId);
$("#fileIdStr").val(this.fileIdList.join(";"));
$.modal.msgSuccess("上传成功");
}else{
$.modal.alertError(response.msg);
}
},
uploadRemove(file, fileList) {
console.log(file, fileList);
var attachFileId = file.attachFileId;
var isBind = file.isBind;
if(isBind==false){
$.ajax({
type: "get",
url: this.fileDeleteUrl,
data: {id:attachFileId},
cache: false,
async: false, // 设置成同步
dataType: 'json',
success: function(result) {
if (result.code == web_status.SUCCESS) {
var index = this.fileIdList.indexOf(attachFileId);
if(index!=-1){
this.fileIdList.splice(index,1);
$("#fileIdStr").val(this.fileIdList.join(";"));
}
$.modal.msgSuccess("删除附件成功。");
} else {
$.modal.alertError(result.msg);
}
},
error: function(error) {
$.modal.alertError("删除附件失败。");
}
});
}else{
var index = this.fileIdList.indexOf(attachFileId);
if(index!=-1){
this.fileIdList.splice(index,1);
$("#fileIdStr").val(this.fileIdList.join(";"));
// 保存的时候才删除
this.removeFileIdList.push(attachFileId);
$("#removeFileIdStr").val(this.removeFileIdList.join(";"));
}
}
},
// 控制上传的图片不能删除
preventDeletion(file, fileList) {
return false; // 禁止删除图片
}
}
})
$(function() {
var options = {
url: prefix + "/optionDevices",
modalName: "出货设备",
showColumns: false,
pagination: false,
showToggle: false,
showRefresh:false,
showSearch:false,
queryParams:queryParams,
columns: [{
checkbox: true
},
{
title: '出货设备编号',
field: 'shippingDeviceCode',
visible: false
},
{
title: '料号',
field: 'materialNo',
},
{
title: '图片',
field: 'materialPhotourl',
},
{
title: '物料名称',
field: 'materialName',
},
{
title: '物料类型',
field: 'materialType',
},
{
title: '单位',
field: 'materialUnit',
},
{
title: '品牌',
field: 'materialBrand',
},
{
title: '描述',
field: 'materialDescribe',
},
{
title: '流水号',
field: 'deviceRunningNumber',
},
{
title: '生产图片',
field: 'makePhotourl',
},
{
title: 'SN号',
field: 'snCode',
},
{
title: '售后图片',
field: 'aftersalesPhotourl',
},
]
};
$.table.init(options);
})
function queryParams(params) {
var curParams = {
// 传递参数查询参数
makeNo: detail.makeNo
};
return curParams;
}
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-aftersalesOrder-edit').serialize());
}
}
// $("input[name='startDate']").datetimepicker({
// format: "yyyy-mm-dd",
// minView: "month",
// autoclose: true
// });
$(function() {
var options = {
url: prefix + "/optionDevices",
modalName: "出货设备",
showColumns: false,
pagination: false,
showToggle: false,
showRefresh:false,
showSearch:false,
queryParams:queryParams,
columns: [{
checkbox: true
},
{
title: '出货设备编号',
field: 'shippingDeviceCode',
visible: false
},
{
title: '料号',
field: 'materialNo',
},
{
title: '图片',
field: 'materialPhotourl',
},
{
title: '物料名称',
field: 'materialName',
},
{
title: '物料类型',
field: 'materialType',
},
{
title: '单位',
field: 'materialUnit',
},
{
title: '品牌',
field: 'materialBrand',
},
{
title: '描述',
field: 'materialDescribe',
},
{
title: '流水号',
field: 'deviceRunningNumber',
},
{
title: '生产图片',
field: 'makePhotourl',
},
{
title: 'SN号',
field: 'snCode',
},
{
title: '售后图片',
field: 'aftersalesPhotourl',
},
]
};
$.table.init(options);
})
function queryParams(params) {
var curParams = {
// 传递参数查询参数
makeNo: detail.makeNo
};
return curParams;
}
$(function () {
$.ajax({
url: ctx + 'aftersales/aftersalesOrder/getAftersalesStaffList',
type: 'post',
data: { roleKey: 'shgcsRole' },
success: function (res) {
if (res.data.length > 0) {
var userData = res.data;
for (let i in userData) {
$("#userId_add").append(
"<option value='" + userData[i].userName + "'>" + userData[i].userName + "</option>" // 使用 userName 作为 option 的 value
);
}
// 初始化时触发 change 事件,以确保首次加载时也能正确赋值
$("#userId_add").trigger("change");
} else {
$.modal.msgError(res.msg);
}
}
});
})
</script>
</body>
</html>
Loading…
Cancel
Save