“mitao”
2026-01-14 9e8e7a10958c20b010d439767a4392fd57ff95db
feat(management):专车订单-异常订单申诉
3个文件已修改
204 ■■■■■ 已修改文件
ManagementQYTTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TOrderPrivateCarController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementQYTTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tOrderPrivateCar/tOrderPrivateCar.html 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementQYTTravel/guns-admin/src/main/webapp/static/modular/system/tOrderPrivateCar/tOrderPrivateCar.js 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementQYTTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TOrderPrivateCarController.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.beetl.ShiroExtUtil;
import com.stylefeng.guns.core.common.constant.factory.PageFactory;
import com.stylefeng.guns.core.util.DateUtil;
@@ -564,6 +565,36 @@
    }
    /**
     * 异常订单申诉
     *
     * @param orderId       订单ID
     * @param abnormalIntro 申诉描述
     * @param abnormalImg   申诉图片(多张用逗号分隔)
     * @return
     */
    @RequestMapping(value = "/addAppeal")
    @ResponseBody
    public Object addAppeal(@RequestParam Integer orderId,
                            @RequestParam String abnormalIntro,
                            @RequestParam(required = false) String abnormalImg) {
        TOrderPrivateCar orderPrivateCar = tOrderPrivateCarService.selectById(orderId);
        if (null == orderPrivateCar) {
            return new ErrorTip(500, "订单不存在");
        }
        if (orderPrivateCar.getState() != 7) {
            return new ErrorTip(500, "只有待支付状态的订单才能申诉");
        }
        if (ToolUtil.isNotEmpty(orderPrivateCar.getAbnormalIntro())) {
            return new ErrorTip(500, "该订单已提交过申诉,请勿重复提交");
        }
        orderPrivateCar.setAbnormalIntro(abnormalIntro);
        orderPrivateCar.setAbnormalImg(abnormalImg);
        orderPrivateCar.setAbnormal(2);
        tOrderPrivateCarService.updateById(orderPrivateCar);
        return SUCCESS_TIP;
    }
    @RequestMapping("/add")
    @ResponseBody
    public Object add(TOrderPrivateCar privateCar) {
ManagementQYTTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tOrderPrivateCar/tOrderPrivateCar.html
@@ -127,6 +127,9 @@
                            @if(shiro.hasPermission("/tOrderPrivateCar/addOrder")){
                            <#button name="导出Excel" icon="" clickFun="TOrderPrivateCar.exportExcel()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/tOrderPrivateCar/addAppeal")){
                            <#button name="异常订单申诉" icon="fa-exclamation-circle" clickFun="TOrderPrivateCar.appeal()" space="true"/>
                            @}
                        </div>
                        <#table id="TOrderPrivateCarTable"/>
                    </div>
@@ -142,4 +145,27 @@
        ,range: true
    });
</script>
<!-- 异常订单申诉弹窗模板 -->
<script type="text/html" id="appealFormTpl">
    <div style="padding: 20px;">
        <div class="form-group">
            <label style="display: block; margin-bottom: 8px; font-weight: bold;">申述描述:</label>
            <textarea id="appealIntro" class="form-control" rows="4" placeholder="请输入申诉描述" style="width: 100%; resize: none;"></textarea>
        </div>
        <div class="form-group" style="margin-top: 15px;">
            <label style="display: block; margin-bottom: 8px; font-weight: bold;">凭证上传:</label>
            <div id="appealImgContainer" style="display: flex; flex-wrap: wrap; gap: 10px;">
                <div id="appealImgList" style="display: flex; flex-wrap: wrap; gap: 10px;"></div>
                <div id="appealUploadBtn" style="width: 100px; height: 100px; border: 2px dashed #ccc; display: flex; align-items: center; justify-content: center; cursor: pointer; border-radius: 4px;">
                    <span style="font-size: 30px; color: #ccc;">+</span>
                    <input type="file" id="appealFileInput" accept="image/*" style="display: none;" multiple>
                </div>
            </div>
        </div>
        <div style="text-align: center; margin-top: 25px;">
            <button type="button" class="btn btn-primary" onclick="TOrderPrivateCar.submitAppeal()" style="padding: 8px 50px;">确认提交</button>
        </div>
    </div>
</script>
@}
ManagementQYTTravel/guns-admin/src/main/webapp/static/modular/system/tOrderPrivateCar/tOrderPrivateCar.js
@@ -532,6 +532,153 @@
    TOrderPrivateCar.search();
};
/**
 * 异常订单申诉 - 已上传的图片URL列表
 */
TOrderPrivateCar.appealImgUrls = [];
/**
 * 异常订单申诉
 */
TOrderPrivateCar.appeal = function () {
    if (this.check()) {
        var orderNum = TOrderPrivateCar.seItem.orderNum;
        if (TOrderPrivateCar.seItem.state != 7) {
            swal("操作失败", "只有【待支付】状态的订单才能进行申诉", "warning");
            return;
        }
        if (TOrderPrivateCar.seItem.abnormal == 2) {
            swal("操作失败", "该订单已提交过申诉,请勿重复提交", "warning");
            return;
        }
        // 重置图片列表
        TOrderPrivateCar.appealImgUrls = [];
        var index = layer.open({
            type: 1,
            title: '订单异常申述',
            area: ['550px', '450px'],
            content: $('#appealFormTpl').html(),
            success: function(layero, index) {
                // 绑定上传按钮点击事件
                $(layero).find('#appealUploadBtn').on('click', function(e) {
                    // 如果点击的是input本身,不再触发
                    if (e.target.tagName === 'INPUT') {
                        return;
                    }
                    $(layero).find('#appealFileInput')[0].click();
                });
                // 绑定文件选择事件
                $(layero).find('#appealFileInput').on('change', function(e) {
                    var files = e.target.files;
                    for (var i = 0; i < files.length; i++) {
                        TOrderPrivateCar.uploadAppealImg(files[i], layero);
                    }
                    // 清空input,允许重复选择同一文件
                    $(this).val('');
                });
            }
        });
        TOrderPrivateCar.appealLayerIndex = index;
    }
};
/**
 * 上传申诉图片
 */
TOrderPrivateCar.uploadAppealImg = function(file, layero) {
    var formData = new FormData();
    formData.append('file', file);
    // 显示上传中提示
    var loadIndex = layer.load(1, {shade: [0.3, '#000']});
    $.ajax({
        url: Feng.ctxPath + '/upload/image',
        type: 'POST',
        data: formData,
        processData: false,
        contentType: false,
        success: function(res) {
            layer.close(loadIndex);
            if (res.code == 200 && res.data) {
                var imgUrl = res.data;
                TOrderPrivateCar.appealImgUrls.push(imgUrl);
                // 添加图片预览
                var imgHtml = '<div class="appeal-img-item" style="position: relative; width: 100px; height: 100px;">' +
                    '<img src="' + imgUrl + '" style="width: 100%; height: 100%; object-fit: cover; border-radius: 4px;">' +
                    '<div class="appeal-img-actions" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s; border-radius: 4px;">' +
                    '<span class="appeal-img-preview" style="color: #fff; cursor: pointer; margin-right: 10px; font-size: 18px;" data-url="' + imgUrl + '"><i class="fa fa-search-plus"></i></span>' +
                    '<span class="appeal-img-delete" style="color: #fff; cursor: pointer; font-size: 18px;" data-url="' + imgUrl + '"><i class="fa fa-trash"></i></span>' +
                    '</div>' +
                    '</div>';
                $(layero).find('#appealImgList').append(imgHtml);
                // 绑定hover效果
                $(layero).find('.appeal-img-item').last().hover(
                    function() { $(this).find('.appeal-img-actions').css('opacity', '1'); },
                    function() { $(this).find('.appeal-img-actions').css('opacity', '0'); }
                );
                // 绑定预览事件
                $(layero).find('.appeal-img-preview').last().on('click', function() {
                    var url = $(this).data('url');
                    layer.open({
                        type: 1,
                        title: false,
                        closeBtn: 1,
                        area: ['auto', 'auto'],
                        maxWidth: 800,
                        maxHeight: 600,
                        content: '<img src="' + url + '" style="max-width: 100%; max-height: 80vh;">'
                    });
                });
                // 绑定删除事件
                $(layero).find('.appeal-img-delete').last().on('click', function() {
                    var url = $(this).data('url');
                    var index = TOrderPrivateCar.appealImgUrls.indexOf(url);
                    if (index > -1) {
                        TOrderPrivateCar.appealImgUrls.splice(index, 1);
                    }
                    $(this).closest('.appeal-img-item').remove();
                });
            } else {
                Feng.error("图片上传失败");
            }
        },
        error: function() {
            layer.close(loadIndex);
            Feng.error("图片上传失败,请重试");
        }
    });
};
/**
 * 提交申诉
 */
TOrderPrivateCar.submitAppeal = function() {
    var abnormalIntro = $('#appealIntro').val();
    if (!abnormalIntro || abnormalIntro.trim() == '') {
        Feng.info("请输入申诉描述");
        return;
    }
    var abnormalImg = TOrderPrivateCar.appealImgUrls.join(',');
    var ajax = new $ax(Feng.ctxPath + "/tOrderPrivateCar/addAppeal", function (data) {
        layer.close(TOrderPrivateCar.appealLayerIndex);
        swal("提交成功", "异常订单申诉已提交", "success");
        TOrderPrivateCar.table.refresh();
    }, function (data) {
        swal("提交失败", data.responseJSON.message + "!", "warning");
    });
    ajax.set("orderId", TOrderPrivateCar.seItem.id);
    ajax.set("abnormalIntro", abnormalIntro);
    ajax.set("abnormalImg", abnormalImg);
    ajax.start();
};
$(function () {
    var defaultColunms = TOrderPrivateCar.initColumn();
    var table = new BSTable(TOrderPrivateCar.id, "/tOrderPrivateCar/list", defaultColunms);