Jelajahi Sumber

图片组件更换

Memory_LG 1 Minggu lalu
induk
melakukan
cd66d2c518

+ 45 - 41
qmjszx-admin/src/main/resources/templates/carousel/add.html

@@ -2,7 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org">
 <head>
     <th:block th:include="include :: header('新增轮播')"/>
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
 </head>
 <body class="white-bg">
 <div class="wrapper wrapper-content animated fadeInRight ibox-content">
@@ -19,10 +19,8 @@
             <div class="form-group">
                 <label class="col-sm-3 control-label">图片:</label>
                 <div class="col-sm-8">
-                    <input type="hidden" name="carouselImg">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="carouselImg" name="file" type="file" multiple>
-                    </div>
+<!--                    <input type="hidden" name="carouselImg">-->
+                    <div id="image-upload-container"></div>
                 </div>
             </div>
         </div>
@@ -37,7 +35,7 @@
     </form>
 </div>
 <th:block th:include="include :: footer"/>
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "carousel"
     $("#form-carousel-add").validate({
@@ -46,46 +44,52 @@
 
     function submitHandler() {
         if ($.validate.form()) {
-            $.operate.save(prefix + "/add", $('#form-carousel-add').serialize());
-        }
-    }
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
 
-    $(".file-upload").fileinput({
-        uploadUrl: ctx + 'common/upload',
-        maxFileCount: 5,
-        allowedFileExtensions: ['jpg', 'png'],
-        maxFileSize: 10240,
-        multiple: true,
-    }).on('fileuploaded', function (event, data, previewId, index) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fullUrl = data.response.url; // 获取完整的URL
-        /*var urlObject = new URL(fullUrl);
-        var relativePath = urlObject.pathname; // 获取路径部分
-        // var newBaseUrl = "http://192.168.4.27"; // 新的基URL
-        var newBaseUrl = "http://localhost"; // 新的基URL
-        var absoluteUrl = newBaseUrl + relativePath; // 拼接完整的URL*/
+            // 检查是否有上传组件实例
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
 
-        // 如果已经存在值,则在后面加上逗号分隔的新值
-        if (existingValue) {
-            $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
-        } else {
-            $("input[name='" + inputName + "']").val(fullUrl);
-        }
-    }).on('fileremoved', function (event, key, jqXHR, pd) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fileUrls = existingValue.split(',');
+                // 如果需要封面必填
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
 
-        // 假设key是文件的key或者index,需要找到对应的URL并移除
-        // 这里假设key是文件的index
-        var index = key;
-        if (fileUrls[index]) {
-            fileUrls.splice(index, 1);
+                // 将图片URL数组转换为逗号分隔的字符串
+                var imageUrls = uploadedFiles.join(',');
+                console.log('图片URL字符串:', imageUrls);
+
+                // 注意:图片上传组件已经通过 addHiddenField 方法添加了隐藏字段
+                // 我们不需要再次添加,只需要确保所有图片都已被收集
+                // 组件会自动处理隐藏字段
+            } else {
+                // 如果没有上传组件实例,直接检查是否有隐藏字段
+                var existingImages = $('#form-competition-add input[name="competitionImg"]').map(function() {
+                    return $(this).val();
+                }).get().filter(function(val) {
+                    return val && val.trim() !== '';
+                });
+
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+            }
+            $.operate.save(prefix + "/add", $('#form-carousel-add').serialize());
         }
+    }
 
-        // 重新拼接文件路径
-        $("input[name='" + inputName + "']").val(fileUrls.join(','));
+    // 初始化图片上传组件
+    $('#image-upload-container').imageUpload({
+        uploadUrl: ctx + "common/upload",
+        maxFiles: 1,
+        maxSize: 5 * 1024 * 1024,
+        allowedTypes: ['image/jpeg', 'image/png'],
+        previewWidth: 200,
+        previewHeight: 150,
+        inputName: 'carouselImg'
     });
 </script>
 </body>

+ 78 - 44
qmjszx-admin/src/main/resources/templates/carousel/edit.html

@@ -2,7 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org">
 <head>
     <th:block th:include="include :: header('修改轮播')"/>
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
 </head>
 <body class="white-bg">
 <div class="wrapper wrapper-content animated fadeInRight ibox-content">
@@ -20,10 +20,7 @@
             <div class="form-group">
                 <label class="col-sm-3 control-label">图片:</label>
                 <div class="col-sm-8">
-                    <input type="hidden" name="carouselImg" th:field="*{carouselImg}">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="carouselImg" name="file" type="file" multiple>
-                    </div>
+                    <div id="image-upload-container"></div>
                 </div>
             </div>
         </div>
@@ -38,7 +35,7 @@
     </form>
 </div>
 <th:block th:include="include :: footer"/>
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "carousel";
     $("#form-carousel-edit").validate({
@@ -47,55 +44,92 @@
 
     function submitHandler() {
         if ($.validate.form()) {
+            // 获取上传组件实例
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
+
+            // 检查是否有上传的图片
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
+
+                // 检查封面图片是否上传
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+                // 组件会自动更新隐藏字段,我们不需要额外处理
+            } else {
+                // 如果没有上传组件实例,检查是否有隐藏字段
+                var existingImages = $('#form-competition-edit input[name="carouselImg"]').map(function() {
+                    return $(this).val();
+                }).get().filter(function(val) {
+                    return val && val.trim() !== '';
+                });
+
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+            }
             $.operate.save(prefix + "/edit", $('#form-carousel-edit').serialize());
         }
     }
 
-    $(".file-upload").each(function (i) {
-        var inputName = this.id;
-        var val = $("input[name='" + inputName + "']").val();
+    $(function (){
+        // ============ 修复:初始化图片上传组件并回显已有图片 ============
+        // 获取已有的封面图片数据(逗号分隔的字符串)
+        var imgStr = [[${beilvCarousel.carouselImg}]];
+        var existingImages = [];
 
-        // 将已上传的图片路径分割成数组
-        var initialPreview = val ? val.split(',') : [];
+        console.log('原始图片字符串:', imgStr);
 
-        $(this).fileinput({
-            uploadUrl: ctx + 'common/upload',
-            initialPreviewAsData: true,
-            initialPreview: initialPreview,
-            maxFileCount: 5,
-            allowedFileExtensions: ['jpg', 'png'],
-            maxFileSize: 10240,
-            multiple: true,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fullUrl = data.response.url; // 获取完整的URL
-            /*var urlObject = new URL(fullUrl);
-            var relativePath = urlObject.pathname; // 获取路径部分
-            // var newBaseUrl = "http://192.168.4.27"; // 新的基URL
-            var newBaseUrl = "http://localhost"; // 新的基URL
-            var absoluteUrl = newBaseUrl + relativePath; // 拼接完整的URL*/
+        if (imgStr && imgStr.trim() !== '') {
+            // 分割逗号分隔的图片字符串
+            existingImages = imgStr.split(',').map(function(img) {
+                return img.trim();
+            }).filter(function(img) {
+                // 过滤掉空字符串和无效的URL
+                return img !== '' && img !== null && img !== undefined;
+            });
 
-            // 如果已经存在值,则在后面加上逗号分隔的新值
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
-            } else {
-                $("input[name='" + inputName + "']").val(fullUrl);
-            }
-        }).on('fileremoved', function (event, id, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fileUrls = existingValue.split(',');
+            console.log('解析后的图片数组:', existingImages);
+            console.log('图片数量:', existingImages.length);
+        }
 
-            // 移除对应的文件路径
-            fileUrls.splice(index, 1);
+        // 初始化图片上传组件
+        var imageUploadConfig = {
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'carouselImg'
+        };
 
-            // 重新拼接文件路径
-            $("input[name='" + inputName + "']").val(fileUrls.join(','));
+        // 只有在有图片时才传递 initialFiles
+        if (existingImages.length > 0) {
+            imageUploadConfig.initialFiles = existingImages;
+        }
+
+        console.log('图片上传配置:', imageUploadConfig);
+
+        $('#image-upload-container').imageUpload(imageUploadConfig);
+
+        // 监听事件(可选)
+        $('#image-upload-container').on('upload.success', function(e, data) {
+            console.log('上传成功:', data.url);
         });
 
-        $(this).fileinput('_initFileActions');
-    });
+        $('#image-upload-container').on('upload.error', function(e, data) {
+            console.error('上传失败:', data.error);
+        });
+
+        $('#image-upload-container').on('files.set', function(e, data) {
+            console.log('图片已设置:', data.urls);
+        });
+        // ============ 修复结束 ============
+    })
 </script>
 </body>
 </html>

+ 172 - 157
qmjszx-admin/src/main/resources/templates/information/add.html

@@ -1,9 +1,9 @@
 <!DOCTYPE html>
-<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<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 :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: header('新增卡种信息')"/>
+    <th:block th:include="include :: datetimepicker-css"/>
+    <th:block th:include="include :: image-upload-css"/>
     <!-- 自定义 CSS -->
     <style>
         /* 修改文本域的背景颜色和文字颜色 */
@@ -14,182 +14,197 @@
     </style>
 </head>
 <body class="white-bg">
-    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
-        <form class="form-horizontal m" id="form-information-add">
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label is-required">名称:</label>
-                    <div class="col-sm-4">
-                        <input name="name" class="form-control" type="text" maxlength="20" required>
-                    </div>
-                    <label class="col-sm-2 control-label is-required">类型:</label>
-                    <div class="col-sm-4">
-                        <select name="type" class="form-control" th:with="type=${@dict.getType('site_type')}" required>
-                            <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
-                        </select>
-                    </div>
+<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+    <form class="form-horizontal m" id="form-information-add">
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label is-required">名称:</label>
+                <div class="col-sm-4">
+                    <input name="name" class="form-control" type="text" maxlength="20" required>
+                </div>
+                <label class="col-sm-2 control-label is-required">类型:</label>
+                <div class="col-sm-4">
+                    <select name="type" class="form-control" th:with="type=${@dict.getType('site_type')}" required>
+                        <option th:each="dict : ${type}" th:text="${dict.dictLabel}"
+                                th:value="${dict.dictValue}"></option>
+                    </select>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label is-required">可用次数:</label>
-                    <div class="col-sm-4">
-                        <input name="totalNumber" class="form-control" type="number" min="0" step="1" maxlength="8" required>
-                    </div>
-                    <label class="col-sm-2 control-label is-required">原价格:</label>
-                    <div class="col-sm-4">
-                        <input name="originalPrice" class="form-control" type="number" min="0" step="0.01" maxlength="8" required>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label is-required">可用次数:</label>
+                <div class="col-sm-4">
+                    <input name="totalNumber" class="form-control" type="number" min="0" step="1" maxlength="8"
+                           required>
+                </div>
+                <label class="col-sm-2 control-label is-required">原价格:</label>
+                <div class="col-sm-4">
+                    <input name="originalPrice" class="form-control" type="number" min="0" step="0.01" maxlength="8"
+                           required>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <!--<label class="col-sm-2 control-label is-required">会员价格:</label>
-                    <div class="col-sm-4">
-                        <input name="memberPrice" class="form-control" type="number" min="0" step="0.01" maxlength="8" required>
-                    </div>-->
-                    <label class="col-sm-2 control-label is-required">单次积分:</label>
-                    <div class="col-sm-4">
-                        <input name="point" class="form-control" type="number" min="0" step="1" maxlength="8" required>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <!--<label class="col-sm-2 control-label is-required">会员价格:</label>
+                <div class="col-sm-4">
+                    <input name="memberPrice" class="form-control" type="number" min="0" step="0.01" maxlength="8" required>
+                </div>-->
+                <label class="col-sm-2 control-label is-required">单次积分:</label>
+                <div class="col-sm-4">
+                    <input name="point" class="form-control" type="number" min="0" step="1" maxlength="8" required>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label">使用规则:</label>
-                    <div class="col-sm-8">
-                        <input name="notes" class="form-control" type="hidden" maxlength="255">
-                        <div class="summernote" id = "notes"></div>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label">使用规则:</label>
+                <div class="col-sm-8">
+                    <input name="notes" class="form-control" type="hidden" maxlength="255">
+                    <div class="summernote" id="notes"></div>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label is-required">图片:</label>
-                    <div class="col-sm-8">
-                        <input type="hidden" name="file">
-                        <div class="file-loading">
-                            <input class="form-control file-upload" id="file" name="file" type="file">
-                        </div>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label is-required">图片:</label>
+                <div class="col-sm-8">
+                    <div id="image-upload-container"></div>
                 </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 :: bootstrap-fileinput-js"/>
-    <th:block th:include="include :: summernote-css"/>
-    <script th:inline="javascript">
-        var prefix = ctx + "information"
-        $("#form-information-add").validate({
-            focusCleanup: true,
-            rules: {
-                originalPrice:{
-                    required: true, // 必填
-                    digits: true, // 必须为整数
-                    min: 1 // 最小值为1,确保为正整数
-                },
-                file:{
-                    required: true, // 必填
-                }
+        </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 :: image-upload-js"/>
+<th:block th:include="include :: summernote-css"/>
+<script th:inline="javascript">
+    var prefix = ctx + "information"
+    $("#form-information-add").validate({
+        focusCleanup: true,
+        rules: {
+            originalPrice: {
+                required: true, // 必填
+                digits: true, // 必须为整数
+                min: 1 // 最小值为1,确保为正整数
             },
-            messages: {
-                originalPrice: {
-                    required: "原价格不能为空",
-                    digits: "原价格必须为整数",
-                    min: "原价格必须大于0"
-                },
-                file: {
-                    required: "图片不能为空",
-                }
+            file: {
+                required: true, // 必填
             }
-        });
-
-        function submitHandler() {
-            if ($.validate.form()) {
-                const originalPrice = parseInt(document.getElementsByName("originalPrice")[0].value);
-                // const memberPrice = parseInt(document.getElementsByName("memberPrice")[0].value);
-                // if (memberPrice>originalPrice){
-                //     alert("会员价格不能大于原价格")
-                // }else {
-                    $.operate.save(prefix + "/add", $('#form-information-add').serialize());
-                // }
+        },
+        messages: {
+            originalPrice: {
+                required: "原价格不能为空",
+                digits: "原价格必须为整数",
+                min: "原价格必须大于0"
+            },
+            file: {
+                required: "图片不能为空",
             }
         }
+    });
 
-        $("input[name='expirationDate']").datetimepicker({
-            format: "yyyy-mm-dd",
-            minView: "month",
-            autoclose: true
-        });
+    function submitHandler() {
+        var uploadInstance = $('#image-upload-container').data('imageUpload');
 
-        $(".file-upload").fileinput({
-            uploadUrl: ctx + 'common/upload',
-            maxFileCount: 1,
-            allowedFileExtensions:['jpg','png'],
-            maxFileSize: 10240,
-            multiple: true,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var newValue = data.response.url;
+        // 检查是否有上传组件实例
+        if (uploadInstance) {
+            var uploadedFiles = uploadInstance.getFiles();
+            console.log('已上传的图片:', uploadedFiles);
 
-            // 如果已经存在值,则在后面加上逗号分隔的新值
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + newValue);
-            } else {
-                $("input[name='" + inputName + "']").val(newValue);
+            // 如果需要封面必填
+            if (uploadedFiles.length === 0) {
+                $.modal.alertWarning("请上传封面图片");
+                return false;
             }
-        }).on('fileremoved', function (event, id, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fileUrls = existingValue.split(',');
 
-            // 移除对应的文件路径
-            fileUrls.splice(index, 1);
+            // 将图片URL数组转换为逗号分隔的字符串
+            var imageUrls = uploadedFiles.join(',');
+            console.log('图片URL字符串:', imageUrls);
 
-            // 重新拼接文件路径
-            $("input[name='" + inputName + "']").val(fileUrls.join(','));
-        });
+            // 注意:图片上传组件已经通过 addHiddenField 方法添加了隐藏字段
+            // 我们不需要再次添加,只需要确保所有图片都已被收集
+            // 组件会自动处理隐藏字段
+        } else {
+            // 如果没有上传组件实例,直接检查是否有隐藏字段
+            var existingImages = $('#form-competition-add input[name="competitionImg"]').map(function() {
+                return $(this).val();
+            }).get().filter(function(val) {
+                return val && val.trim() !== '';
+            });
+
+            if (existingImages.length === 0) {
+                $.modal.alertWarning("请上传封面图片");
+                return false;
+            }
+        }
+        if ($.validate.form()) {
+            const originalPrice = parseInt(document.getElementsByName("originalPrice")[0].value);
+            // const memberPrice = parseInt(document.getElementsByName("memberPrice")[0].value);
+            // if (memberPrice>originalPrice){
+            //     alert("会员价格不能大于原价格")
+            // }else {
+            $.operate.save(prefix + "/add", $('#form-information-add').serialize());
+            // }
+        }
+    }
+
+    $("input[name='expirationDate']").datetimepicker({
+        format: "yyyy-mm-dd",
+        minView: "month",
+        autoclose: true
+    });
 
-        $(function () {
-            $('.summernote').summernote({
-                lang: 'zh-CN',
-                dialogsInBody: true,
-                height: 150,
-                callbacks: {
-                    onChange: function (contents, $edittable) {
-                        $("input[name='" + this.id + "']").val(contents);
-                    },
-                    onImageUpload: function (files) {
-                        var obj = this;
-                        var data = new FormData();
-                        data.append("file", files[0]);
-                        $.ajax({
-                            type: "post",
-                            url: ctx + "common/upload",
-                            data: data,
-                            cache: false,
-                            contentType: false,
-                            processData: false,
-                            dataType: 'json',
-                            success: function (result) {
-                                if (result.code == web_status.SUCCESS) {
-                                    $('#' + obj.id).summernote('insertImage', result.url);
-                                } else {
-                                    $.modal.alertError(result.msg);
-                                }
-                            },
-                            error: function (error) {
-                                $.modal.alertWarning("图片上传失败。");
+
+    $(function () {
+        $('.summernote').summernote({
+            lang: 'zh-CN',
+            dialogsInBody: true,
+            height: 150,
+            callbacks: {
+                onChange: function (contents, $edittable) {
+                    $("input[name='" + this.id + "']").val(contents);
+                },
+                onImageUpload: function (files) {
+                    var obj = this;
+                    var data = new FormData();
+                    data.append("file", files[0]);
+                    $.ajax({
+                        type: "post",
+                        url: ctx + "common/upload",
+                        data: data,
+                        cache: false,
+                        contentType: false,
+                        processData: false,
+                        dataType: 'json',
+                        success: function (result) {
+                            if (result.code == web_status.SUCCESS) {
+                                $('#' + obj.id).summernote('insertImage', result.url);
+                            } else {
+                                $.modal.alertError(result.msg);
                             }
-                        });
-                    }
+                        },
+                        error: function (error) {
+                            $.modal.alertWarning("图片上传失败。");
+                        }
+                    });
                 }
-            });
+            }
+        });
+        // 初始化图片上传组件
+        $('#image-upload-container').imageUpload({
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'file'
         });
-    </script>
+    });
+</script>
 </body>
 </html>

+ 84 - 46
qmjszx-admin/src/main/resources/templates/information/edit.html

@@ -3,7 +3,7 @@
 <head>
     <th:block th:include="include :: header('修改卡种信息')" />
     <th:block th:include="include :: datetimepicker-css" />
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
     <!-- 自定义 CSS -->
     <style>
         /* 修改文本域的背景颜色和文字颜色 */
@@ -68,10 +68,7 @@
                 <div class="form-group">
                     <label class="col-sm-2 control-label is-required">图片:</label>
                     <div class="col-sm-8">
-                        <input type="hidden" name="file" th:field="*{file}">
-                        <div class="file-loading">
-                            <input class="form-control file-upload" id="file" name="file" type="file">
-                        </div>
+                        <div id="image-upload-container"></div>
                     </div>
                 </div>
             </div>
@@ -81,7 +78,7 @@
     <th:block th:include="include :: datetimepicker-js" />
     <th:block th:include="include :: summernote-js"/>
     <th:block th:include="include :: summernote-css"/>
-    <th:block th:include="include :: bootstrap-fileinput-js"/>
+    <th:block th:include="include :: image-upload-js"/>
     <script th:inline="javascript">
         var prefix = ctx + "information";
         $("#form-information-edit").validate({
@@ -110,6 +107,33 @@
 
         function submitHandler() {
             if ($.validate.form()) {
+                // 获取上传组件实例
+                var uploadInstance = $('#image-upload-container').data('imageUpload');
+
+                // 检查是否有上传的图片
+                if (uploadInstance) {
+                    var uploadedFiles = uploadInstance.getFiles();
+                    console.log('已上传的图片:', uploadedFiles);
+
+                    // 检查封面图片是否上传
+                    if (uploadedFiles.length === 0) {
+                        $.modal.alertWarning("请上传封面图片");
+                        return false;
+                    }
+                    // 组件会自动更新隐藏字段,我们不需要额外处理
+                } else {
+                    // 如果没有上传组件实例,检查是否有隐藏字段
+                    var existingImages = $('#form-competition-edit input[name="file"]').map(function() {
+                        return $(this).val();
+                    }).get().filter(function(val) {
+                        return val && val.trim() !== '';
+                    });
+
+                    if (existingImages.length === 0) {
+                        $.modal.alertWarning("请上传封面图片");
+                        return false;
+                    }
+                }
                 const originalPrice = parseInt(document.getElementsByName("originalPrice")[0].value);
                 // const memberPrice = parseInt(document.getElementsByName("memberPrice")[0].value);
                 // if (memberPrice>originalPrice){
@@ -126,46 +150,6 @@
             autoclose: true
         });
 
-        $(".file-upload").each(function (i) {
-            var inputName = this.id;
-            var val = $("input[name='" + inputName + "']").val();
-
-            // 将已上传的图片路径分割成数组
-            var initialPreview = val ? val.split(',') : [];
-
-            $(this).fileinput({
-                'uploadUrl': ctx + 'common/upload',
-                initialPreviewAsData: true,
-                initialPreview: initialPreview,
-                maxFileCount: 1,
-                allowedFileExtensions: ['jpg', 'png'],
-                maxFileSize: 10240,
-                multiple: true,
-            }).on('fileuploaded', function (event, data, previewId, index) {
-                var inputName = event.currentTarget.id;
-                var existingValue = $("input[name='" + inputName + "']").val();
-                var newValue = data.response.url;
-
-                // 如果已经存在值,则在后面加上逗号分隔的新值
-                if (existingValue) {
-                    $("input[name='" + inputName + "']").val(existingValue + ',' + newValue);
-                } else {
-                    $("input[name='" + inputName + "']").val(newValue);
-                }
-            }).on('fileremoved', function (event, id, index) {
-                var inputName = event.currentTarget.id;
-                var existingValue = $("input[name='" + inputName + "']").val();
-                var fileUrls = existingValue.split(',');
-
-                // 移除对应的文件路径
-                fileUrls.splice(index, 1);
-
-                // 重新拼接文件路径
-                $("input[name='" + inputName + "']").val(fileUrls.join(','));
-            });
-
-            $(this).fileinput('_initFileActions');
-        });
 
         $(function() {
             $('.summernote').each(function(i) {
@@ -207,6 +191,60 @@
                 var content = $("input[name='" + this.id + "']").val();
                 $('#' + this.id).summernote('code', content);
             })
+
+            // ============ 修复:初始化图片上传组件并回显已有图片 ============
+            // 获取已有的封面图片数据(逗号分隔的字符串)
+            var imgStr = [[${carInformation.file}]];
+            var existingImages = [];
+
+            console.log('原始图片字符串:', imgStr);
+
+            if (imgStr && imgStr.trim() !== '') {
+                // 分割逗号分隔的图片字符串
+                existingImages = imgStr.split(',').map(function(img) {
+                    return img.trim();
+                }).filter(function(img) {
+                    // 过滤掉空字符串和无效的URL
+                    return img !== '' && img !== null && img !== undefined;
+                });
+
+                console.log('解析后的图片数组:', existingImages);
+                console.log('图片数量:', existingImages.length);
+            }
+
+            // 初始化图片上传组件
+            var imageUploadConfig = {
+                uploadUrl: ctx + "common/upload",
+                maxFiles: 1,
+                maxSize: 5 * 1024 * 1024,
+                allowedTypes: ['image/jpeg', 'image/png'],
+                previewWidth: 200,
+                previewHeight: 150,
+                inputName: 'file'
+            };
+
+            // 只有在有图片时才传递 initialFiles
+            if (existingImages.length > 0) {
+                imageUploadConfig.initialFiles = existingImages;
+            }
+
+            console.log('图片上传配置:', imageUploadConfig);
+
+            $('#image-upload-container').imageUpload(imageUploadConfig);
+
+            // 监听事件(可选)
+            $('#image-upload-container').on('upload.success', function(e, data) {
+                console.log('上传成功:', data.url);
+            });
+
+            $('#image-upload-container').on('upload.error', function(e, data) {
+                console.error('上传失败:', data.error);
+            });
+
+            $('#image-upload-container').on('files.set', function(e, data) {
+                console.log('图片已设置:', data.urls);
+            });
+            // ============ 修复结束 ============
         });
     </script>
 </body>

+ 48 - 43
qmjszx-admin/src/main/resources/templates/system/mall/add.html

@@ -2,7 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <head>
     <th:block th:include="include :: header('新增商城')" />
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
 </head>
 <body class="white-bg">
 <div class="wrapper wrapper-content animated fadeInRight ibox-content">
@@ -89,11 +89,8 @@
             <div class="form-group">
                 <label class="col-sm-3 control-label">商品图片:</label>
                 <div class="col-sm-8">
-                    <input type="hidden" name="goodsImg">
-                    <div class="file-loading">
-<!--                        <input class="form-control file-upload" id="goodsImg" name="file" type="file" multiple accept=".png, .jpg" onchange="validateFiles(this)">-->
-                        <input class="form-control file-upload" id="goodsImg" name="file" type="file" multiple >
-                    </div>
+<!--                    <input type="hidden" name="goodsImg">-->
+                    <div id="image-upload-container"></div>
                 </div>
             </div>
         </div>
@@ -108,7 +105,7 @@
     </form>
 </div>
 <th:block th:include="include :: footer" />
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "system/mall"
     $("#form-mall-add").validate({
@@ -123,49 +120,57 @@
         },
     });
 
+    // 初始化图片上传组件
+    $('#image-upload-container').imageUpload({
+        uploadUrl: ctx + "common/upload",
+        maxFiles: 1,
+        maxSize: 5 * 1024 * 1024,
+        allowedTypes: ['image/jpeg', 'image/png'],
+        previewWidth: 200,
+        previewHeight: 150,
+        inputName: 'goodsImg'
+    });
+
     function submitHandler() {
         if ($.validate.form()) {
-            $.operate.save(prefix + "/add", $('#form-mall-add').serialize());
-        }
-    }
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
 
-    $(".file-upload").fileinput({
-        uploadUrl: ctx + 'common/upload',
-        maxFileCount: 5,
-        allowedFileExtensions: ['jpg', 'png'],
-        maxFileSize: 10240,
-        multiple: true,
-    }).on('fileuploaded', function (event, data, previewId, index) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fullUrl = data.response.url; // 获取完整的URL
-        /*var urlObject = new URL(fullUrl);
-        var relativePath = urlObject.pathname; // 获取路径部分
-        // var newBaseUrl = "http://192.168.4.27"; // 新的基URL
-        var newBaseUrl = "http://localhost"; // 新的基URL
-        var absoluteUrl = newBaseUrl + relativePath; // 拼接完整的URL*/
+            // 检查是否有上传组件实例
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
 
-        // 如果已经存在值,则在后面加上逗号分隔的新值
-        if (existingValue) {
-            $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
-        } else {
-            $("input[name='" + inputName + "']").val(fullUrl);
-        }
-    }).on('fileremoved', function (event, key, jqXHR, pd) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fileUrls = existingValue.split(',');
+                // 如果需要封面必填
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传封面图片");
+                    return false;
+                }
 
-        // 假设key是文件的key或者index,需要找到对应的URL并移除
-        // 这里假设key是文件的index
-        var index = key;
-        if (fileUrls[index]) {
-            fileUrls.splice(index, 1);
+                // 将图片URL数组转换为逗号分隔的字符串
+                var imageUrls = uploadedFiles.join(',');
+                console.log('图片URL字符串:', imageUrls);
+
+                // 注意:图片上传组件已经通过 addHiddenField 方法添加了隐藏字段
+                // 我们不需要再次添加,只需要确保所有图片都已被收集
+                // 组件会自动处理隐藏字段
+            } else {
+                // 如果没有上传组件实例,直接检查是否有隐藏字段
+                var existingImages = $('#form-competition-add input[name="competitionImg"]').map(function() {
+                    return $(this).val();
+                }).get().filter(function(val) {
+                    return val && val.trim() !== '';
+                });
+
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传封面图片");
+                    return false;
+                }
+            }
+            $.operate.save(prefix + "/add", $('#form-mall-add').serialize());
         }
+    }
+
 
-        // 重新拼接文件路径
-        $("input[name='" + inputName + "']").val(fileUrls.join(','));
-    });
 </script>
 </body>
 </html>

+ 84 - 48
qmjszx-admin/src/main/resources/templates/system/mall/edit.html

@@ -2,7 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <head>
     <th:block th:include="include :: header('修改商城')" />
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
 </head>
 <body class="white-bg">
 <div class="wrapper wrapper-content animated fadeInRight ibox-content">
@@ -106,10 +106,7 @@
             <div class="form-group">
                 <label class="col-sm-3 control-label">商品图片:</label>
                 <div class="col-sm-8">
-                    <input type="hidden" name="goodsImg" th:field="*{goodsImg}">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="goodsImg" name="file" type="file" multiple>
-                    </div>
+                    <div id="image-upload-container"></div>
                 </div>
             </div>
         </div>
@@ -124,7 +121,7 @@
     </form>
 </div>
 <th:block th:include="include :: footer" />
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "system/mall";
     $("#form-mall-edit").validate({
@@ -141,55 +138,94 @@
 
     function submitHandler() {
         if ($.validate.form()) {
+            // 获取上传组件实例
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
+
+            // 检查是否有上传的图片
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
+
+                // 检查封面图片是否上传
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传封面图片");
+                    return false;
+                }
+                // 组件会自动更新隐藏字段,我们不需要额外处理
+            } else {
+                // 如果没有上传组件实例,检查是否有隐藏字段
+                var existingImages = $('#form-competition-edit input[name="goodsImg"]').map(function() {
+                    return $(this).val();
+                }).get().filter(function(val) {
+                    return val && val.trim() !== '';
+                });
+
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传封面图片");
+                    return false;
+                }
+            }
+
+
             $.operate.save(prefix + "/edit", $('#form-mall-edit').serialize());
         }
     }
 
-    $(".file-upload").each(function (i) {
-        var inputName = this.id;
-        var val = $("input[name='" + inputName + "']").val();
-
-        // 将已上传的图片路径分割成数组
-        var initialPreview = val ? val.split(',') : [];
-
-        $(this).fileinput({
-            uploadUrl: ctx + 'common/upload',
-            initialPreviewAsData: true,
-            initialPreview: initialPreview,
-            maxFileCount: 5,
-            allowedFileExtensions: ['jpg', 'png'],
-            maxFileSize: 10240,
-            multiple: true,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fullUrl = data.response.url; // 获取完整的URL
-            /*var urlObject = new URL(fullUrl);
-            var relativePath = urlObject.pathname; // 获取路径部分
-            // var newBaseUrl = "http://192.168.4.27"; // 新的基URL
-            var newBaseUrl = "http://localhost"; // 新的基URL
-            var absoluteUrl = newBaseUrl + relativePath; // 拼接完整的URL*/
-
-            // 如果已经存在值,则在后面加上逗号分隔的新值
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
-            } else {
-                $("input[name='" + inputName + "']").val(fullUrl);
-            }
-        }).on('fileremoved', function (event, id, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fileUrls = existingValue.split(',');
+   $(function(){
+       // ============ 修复:初始化图片上传组件并回显已有图片 ============
+       // 获取已有的封面图片数据(逗号分隔的字符串)
+       var imgStr = [[${qmjsShoppingMall.goodsImg}]];
+       var existingImages = [];
 
-            // 移除对应的文件路径
-            fileUrls.splice(index, 1);
+       console.log('原始图片字符串:', imgStr);
 
-            // 重新拼接文件路径
-            $("input[name='" + inputName + "']").val(fileUrls.join(','));
-        });
+       if (imgStr && imgStr.trim() !== '') {
+           // 分割逗号分隔的图片字符串
+           existingImages = imgStr.split(',').map(function(img) {
+               return img.trim();
+           }).filter(function(img) {
+               // 过滤掉空字符串和无效的URL
+               return img !== '' && img !== null && img !== undefined;
+           });
 
-        $(this).fileinput('_initFileActions');
-    });
+           console.log('解析后的图片数组:', existingImages);
+           console.log('图片数量:', existingImages.length);
+       }
+
+       // 初始化图片上传组件
+       var imageUploadConfig = {
+           uploadUrl: ctx + "common/upload",
+           maxFiles: 1,
+           maxSize: 5 * 1024 * 1024,
+           allowedTypes: ['image/jpeg', 'image/png'],
+           previewWidth: 200,
+           previewHeight: 150,
+           inputName: 'goodsImg'
+       };
+
+       // 只有在有图片时才传递 initialFiles
+       if (existingImages.length > 0) {
+           imageUploadConfig.initialFiles = existingImages;
+       }
+
+       console.log('图片上传配置:', imageUploadConfig);
+
+       $('#image-upload-container').imageUpload(imageUploadConfig);
+
+       // 监听事件(可选)
+       $('#image-upload-container').on('upload.success', function(e, data) {
+           console.log('上传成功:', data.url);
+       });
+
+       $('#image-upload-container').on('upload.error', function(e, data) {
+           console.error('上传失败:', data.error);
+       });
+
+       $('#image-upload-container').on('files.set', function(e, data) {
+           console.log('图片已设置:', data.urls);
+       });
+       // ============ 修复结束 ============
+   })
 </script>
 </body>
 </html>

+ 2 - 2
qmjszx-admin/src/main/resources/templates/system/notice/add.html

@@ -92,7 +92,7 @@
     // 初始化图片上传组件
     $('#image-upload-container').imageUpload({
         uploadUrl: ctx + "common/upload",
-        maxFiles: 2,
+        maxFiles: 1,
         maxSize: 5 * 1024 * 1024,
         allowedTypes: ['image/jpeg', 'image/png'],
         previewWidth: 200,
@@ -158,7 +158,7 @@
             // 组件会自动处理隐藏字段
         } else {
             // 如果没有上传组件实例,直接检查是否有隐藏字段
-            var existingImages = $('#form-competition-add input[name="competitionImg"]').map(function() {
+            var existingImages = $('#form-competition-add input[name="noticeImg"]').map(function() {
                 return $(this).val();
             }).get().filter(function(val) {
                 return val && val.trim() !== '';

+ 2 - 62
qmjszx-admin/src/main/resources/templates/system/notice/edit.html

@@ -120,7 +120,6 @@
         $('#editor').summernote('code', content);
 
         // ============ 修复:初始化图片上传组件并回显已有图片 ============
-        console.log(typeof '${notice.noticeImg}')
         // 获取已有的封面图片数据(逗号分隔的字符串)
         var imgStr = [[${notice.noticeImg}]];
         var existingImages = [];
@@ -175,65 +174,6 @@
         // ============ 修复结束 ============
     });
 
-
-    $(".file-upload").each(function (i) {
-        var inputName = this.id;
-        var val = $("input[name='" + inputName + "']").val();
-        // 将已上传的图片路径分割成数组
-        var initialPreview = val ? val.split(',') : [];
-        $(this).fileinput({
-            uploadUrl: ctx + 'common/upload',
-            initialPreviewAsData: true,
-            initialPreview: initialPreview,
-            maxFileCount: 1,
-            allowedFileExtensions: ['jpg', 'png'],
-            maxFileSize: 10240,
-            overwriteInitial: true,
-            multiple: false,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var newValue = data.response.url;
-
-            // 如果已经存在值,则在后面加上逗号分隔的新值
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + newValue);
-            } else {
-                $("input[name='" + inputName + "']").val(newValue);
-            }
-        }).on('fileremoved', function (event, id, index) {
-            var inputName = event.currentTarget.id;
-            $("input[name='" + inputName + "']").val(''); // 移除后清空输入框
-        });
-
-        $(this).fileinput('_initFileActions');
-    });
-
-    // 上传文件
-    function sendFile(file, obj) {
-        var data = new FormData();
-        data.append("file", file);
-        $.ajax({
-            type: "POST",
-            url: ctx + "common/upload",
-            data: data,
-            cache: false,
-            contentType: false,
-            processData: false,
-            dataType: 'json',
-            success: function (result) {
-                if (result.code == web_status.SUCCESS) {
-                    $(obj).summernote('editor.insertImage', result.url, result.fileName);
-                } else {
-                    $.modal.alertError(result.msg);
-                }
-            },
-            error: function (error) {
-                $.modal.alertWarning("图片上传失败。");
-            }
-        });
-    }
-
     $("#form-notice-edit").validate({
         focusCleanup: true,
         rules: {
@@ -255,7 +195,7 @@
 
                 // 检查封面图片是否上传
                 if (uploadedFiles.length === 0) {
-                    $.modal.alertWarning("请上传封面图片");
+                    $.modal.alertWarning("请上传图片");
                     return false;
                 }
                 // 组件会自动更新隐藏字段,我们不需要额外处理
@@ -268,7 +208,7 @@
                 });
 
                 if (existingImages.length === 0) {
-                    $.modal.alertWarning("请上传封面图片");
+                    $.modal.alertWarning("请上传图片");
                     return false;
                 }
             }

+ 46 - 36
qmjszx-admin/src/main/resources/templates/system/site/add.html

@@ -3,7 +3,7 @@
 <head>
     <th:block th:include="include :: header('新增球场管理')"/>
     <th:block th:include="include :: summernote-css"/>
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
     <!-- 自定义 CSS -->
     <style>
         /* 修改文本域的背景颜色和文字颜色 */
@@ -63,10 +63,7 @@
             <div class="form-group">
                 <label class="col-sm-2 control-label">封面:</label>
                 <div class="col-sm-4">
-                    <input type="hidden" name="cover">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="cover" name="file" type="file" >
-                    </div>
+                    <div id="image-upload-container"></div>
                 </div>
 
                 <label class="col-sm-2 control-label">简介:</label>
@@ -80,7 +77,7 @@
 </div>
 <th:block th:include="include :: footer"/>
 <th:block th:include="include :: summernote-js"/>
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "system/site"
     $("#form-site-add").validate({
@@ -102,42 +99,45 @@
     });
 
     function submitHandler() {
-        if ($.validate.form()) {
-            $.operate.save(prefix + "/add", $('#form-site-add').serialize());
-        }
-    }
+        var uploadInstance = $('#image-upload-container').data('imageUpload');
 
+        // 检查是否有上传组件实例
+        if (uploadInstance) {
+            var uploadedFiles = uploadInstance.getFiles();
+            console.log('已上传的图片:', uploadedFiles);
 
-    $(".file-upload").fileinput({
-        uploadUrl: ctx + 'common/upload',
-        maxFileCount: 1,
-        allowedFileExtensions: ['jpg', 'png'],
-        maxFileSize: 10240,
-        multiple: true,
-    }).on('fileuploaded', function (event, data, previewId, index) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fullUrl = data.response.url; // 获取完整的URL
-        if (existingValue) {
-            $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
+            // 如果需要封面必填
+            if (uploadedFiles.length === 0) {
+                $.modal.alertWarning("请上传图片");
+                return false;
+            }
+
+            // 将图片URL数组转换为逗号分隔的字符串
+            var imageUrls = uploadedFiles.join(',');
+            console.log('图片URL字符串:', imageUrls);
+
+            // 注意:图片上传组件已经通过 addHiddenField 方法添加了隐藏字段
+            // 我们不需要再次添加,只需要确保所有图片都已被收集
+            // 组件会自动处理隐藏字段
         } else {
-            $("input[name='" + inputName + "']").val(fullUrl);
-        }
-    }).on('fileremoved', function (event, key, jqXHR, pd) {
-        var inputName = event.currentTarget.id;
-        var existingValue = $("input[name='" + inputName + "']").val();
-        var fileUrls = existingValue.split(',');
+            // 如果没有上传组件实例,直接检查是否有隐藏字段
+            var existingImages = $('#form-competition-add input[name="cover"]').map(function() {
+                return $(this).val();
+            }).get().filter(function(val) {
+                return val && val.trim() !== '';
+            });
 
-        // 假设key是文件的key或者index,需要找到对应的URL并移除
-        // 这里假设key是文件的index
-        var index = key;
-        if (fileUrls[index]) {
-            fileUrls.splice(index, 1);
+            if (existingImages.length === 0) {
+                $.modal.alertWarning("请上传图片");
+                return false;
+            }
+        }
+        if ($.validate.form()) {
+            $.operate.save(prefix + "/add", $('#form-site-add').serialize());
         }
+    }
+
 
-        // 重新拼接文件路径
-        $("input[name='" + inputName + "']").val(fileUrls.join(','));
-    });
 
     $(function () {
         $('.summernote').summernote({
@@ -174,6 +174,16 @@
                 }
             }
         });
+        // 初始化图片上传组件
+        $('#image-upload-container').imageUpload({
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'cover'
+        });
     });
 </script>
 </body>

+ 83 - 44
qmjszx-admin/src/main/resources/templates/system/site/edit.html

@@ -3,7 +3,7 @@
 <head>
     <th:block th:include="include :: header('修改球场管理')"/>
     <th:block th:include="include :: datetimepicker-css"/>
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
     <th:block th:include="include :: summernote-css"/>
     <!-- 自定义 CSS -->
     <style>
@@ -68,10 +68,7 @@
             <div class="form-group">
                 <label class="col-sm-2 control-label">封面:</label>
                 <div class="col-sm-4">
-                    <input type="hidden" name="cover" th:field="*{cover}">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="cover" name="file" type="file">
-                    </div>
+                    <div id="image-upload-container"></div>
                 </div>
                 <label class="col-sm-2 control-label">简介:</label>
                 <div class="col-sm-4">
@@ -84,8 +81,8 @@
 </div>
 <th:block th:include="include :: footer"/>
 <th:block th:include="include :: datetimepicker-js"/>
-<th:block th:include="include :: bootstrap-fileinput-js"/>
 <th:block th:include="include :: summernote-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "system/site";
     $("#form-site-edit").validate({
@@ -108,49 +105,37 @@
 
     function submitHandler() {
         if ($.validate.form()) {
-            $.operate.save(prefix + "/edit", $('#form-site-edit').serialize());
-        }
-    }
+            // 获取上传组件实例
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
 
+            // 检查是否有上传的图片
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
 
-    $(".file-upload").each(function (i) {
-        var inputName = this.id;
-        var val = $("input[name='" + inputName + "']").val();
-
-        // 将已上传的图片路径分割成数组
-        var initialPreview = val ? val.split(',') : [];
-
-        $(this).fileinput({
-            uploadUrl: ctx + 'common/upload',
-            initialPreviewAsData: true,
-            initialPreview: initialPreview,
-            maxFileCount: 1,
-            allowedFileExtensions: ['jpg', 'png'],
-            maxFileSize: 10240,
-            multiple: true,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fullUrl = data.response.url; // 获取完整的URL
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
+                // 检查封面图片是否上传
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+                // 组件会自动更新隐藏字段,我们不需要额外处理
             } else {
-                $("input[name='" + inputName + "']").val(fullUrl);
-            }
-        }).on('fileremoved', function (event, id, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fileUrls = existingValue.split(',');
-
-            // 移除对应的文件路径
-            fileUrls.splice(index, 1);
+                // 如果没有上传组件实例,检查是否有隐藏字段
+                var existingImages = $('#form-competition-edit input[name="cover"]').map(function() {
+                    return $(this).val();
+                }).get().filter(function(val) {
+                    return val && val.trim() !== '';
+                });
 
-            // 重新拼接文件路径
-            $("input[name='" + inputName + "']").val(fileUrls.join(','));
-        });
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+            }
+            $.operate.save(prefix + "/edit", $('#form-site-edit').serialize());
+        }
+    }
 
-        $(this).fileinput('_initFileActions');
-    });
 
 
     $(function () {
@@ -192,6 +177,60 @@
             var content = $("input[name='" + this.id + "']").val();
             $('#' + this.id).summernote('code', content);
         })
+
+        // ============ 修复:初始化图片上传组件并回显已有图片 ============
+        // 获取已有的封面图片数据(逗号分隔的字符串)
+        var imgStr = [[${beilvSite.cover}]];
+        var existingImages = [];
+
+        console.log('原始图片字符串:', imgStr);
+
+        if (imgStr && imgStr.trim() !== '') {
+            // 分割逗号分隔的图片字符串
+            existingImages = imgStr.split(',').map(function(img) {
+                return img.trim();
+            }).filter(function(img) {
+                // 过滤掉空字符串和无效的URL
+                return img !== '' && img !== null && img !== undefined;
+            });
+
+            console.log('解析后的图片数组:', existingImages);
+            console.log('图片数量:', existingImages.length);
+        }
+
+        // 初始化图片上传组件
+        var imageUploadConfig = {
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'cover'
+        };
+
+        // 只有在有图片时才传递 initialFiles
+        if (existingImages.length > 0) {
+            imageUploadConfig.initialFiles = existingImages;
+        }
+
+        console.log('图片上传配置:', imageUploadConfig);
+
+        $('#image-upload-container').imageUpload(imageUploadConfig);
+
+        // 监听事件(可选)
+        $('#image-upload-container').on('upload.success', function(e, data) {
+            console.log('上传成功:', data.url);
+        });
+
+        $('#image-upload-container').on('upload.error', function(e, data) {
+            console.error('上传失败:', data.error);
+        });
+
+        $('#image-upload-container').on('files.set', function(e, data) {
+            console.log('图片已设置:', data.urls);
+        });
+        // ============ 修复结束 ============
     });
 </script>
 </body>

+ 145 - 136
qmjszx-admin/src/main/resources/templates/system/venue/add.html

@@ -1,9 +1,9 @@
 <!DOCTYPE html>
-<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
 <head>
-    <th:block th:include="include :: header('新增场馆信息')" />
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
-    <th:block th:include="include :: summernote-css" />
+    <th:block th:include="include :: header('新增场馆信息')"/>
+    <th:block th:include="include :: image-upload-css"/>
+    <th:block th:include="include :: summernote-css"/>
     <!-- 自定义 CSS -->
     <style>
         /* 修改文本域的背景颜色和文字颜色 */
@@ -14,158 +14,167 @@
     </style>
 </head>
 <body class="white-bg">
-    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
-        <form class="form-horizontal m" id="form-venue-add">
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label is-required">名称:</label>
-                    <div class="col-sm-4">
-                        <input name="venueName" class="form-control" type="text" required>
-                    </div>
-                    <label class="col-sm-2 control-label is-required">地址:</label>
-                    <div class="col-sm-4">
-                        <input name="address" class="form-control" type="text" required>
-                    </div>
+<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+    <form class="form-horizontal m" id="form-venue-add">
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label is-required">名称:</label>
+                <div class="col-sm-4">
+                    <input name="venueName" class="form-control" type="text" required>
+                </div>
+                <label class="col-sm-2 control-label is-required">地址:</label>
+                <div class="col-sm-4">
+                    <input name="address" class="form-control" type="text" required>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label is-required">电话:</label>
-                    <div class="col-sm-4">
-                        <input id="phoneNumber" name="phoneNumber" placeholder="请输入电话" class="form-control" type="text" maxlength="11" required>
-                    </div>
-                    <label class="col-sm-2 control-label is-required">营业时间:</label>
-                    <div class="col-sm-4">
-                        <input name="businessHours" class="form-control" type="text" required>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label is-required">电话:</label>
+                <div class="col-sm-4">
+                    <input id="phoneNumber" name="phoneNumber" placeholder="请输入电话" class="form-control" type="text"
+                           maxlength="11" required>
+                </div>
+                <label class="col-sm-2 control-label is-required">营业时间:</label>
+                <div class="col-sm-4">
+                    <input name="businessHours" class="form-control" type="text" required>
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label">场地服务:</label>
-                    <div class="col-sm-4">
-                        <input name="venueService" class="form-control" type="text" >
-                    </div>
-                    <label class="col-sm-2 control-label">开始前几分钟不可预定:</label>
-                    <div class="col-sm-4">
-                        <input name="thresholdValue" class="form-control" type="text">
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label">场地服务:</label>
+                <div class="col-sm-4">
+                    <input name="venueService" class="form-control" type="text">
+                </div>
+                <label class="col-sm-2 control-label">开始前几分钟不可预定:</label>
+                <div class="col-sm-4">
+                    <input name="thresholdValue" class="form-control" type="text">
                 </div>
             </div>
-            <div class="col-xs-12">
-                <div class="form-group">
-                    <label class="col-sm-2 control-label">图片:</label>
-                    <div class="col-sm-4">
-                        <input type="hidden" name="cover">
-                        <div class="file-loading">
-                            <input class="form-control file-upload" id="cover" name="file" type="file" multiple>
-                        </div>
-                    </div>
-                    <label class="col-sm-2 control-label">场馆介绍:</label>
-                    <div class="col-sm-4">
-                        <input type="hidden" class="form-control" name="venueIntroduction">
-                        <div class="summernote" id="venueIntroduction"></div>
-                    </div>
+        </div>
+        <div class="col-xs-12">
+            <div class="form-group">
+                <label class="col-sm-2 control-label">图片:</label>
+                <div class="col-sm-4">
+                    <div id="image-upload-container"></div>
+                </div>
+                <label class="col-sm-2 control-label">场馆介绍:</label>
+                <div class="col-sm-4">
+                    <input type="hidden" class="form-control" name="venueIntroduction">
+                    <div class="summernote" id="venueIntroduction"></div>
                 </div>
             </div>
-        </form>
-    </div>
-    <th:block th:include="include :: footer" />
-    <th:block th:include="include :: bootstrap-fileinput-js"/>
-    <th:block th:include="include :: summernote-js" />
-    <script th:inline="javascript">
-        var prefix = ctx + "system/venue"
-        $("#form-venue-add").validate({
-            focusCleanup: true,
-            rules:{
-                phoneNumber:{
-                    isPhone:true,
-                },
-                thresholdValue:{
-                    digits: true
-                },
-                businessHours:{
-                    isTimeRange: true
-                }
+        </div>
+    </form>
+</div>
+<th:block th:include="include :: footer"/>
+<th:block th:include="include :: image-upload-js"/>
+<th:block th:include="include :: summernote-js"/>
+<script th:inline="javascript">
+    var prefix = ctx + "system/venue"
+    $("#form-venue-add").validate({
+        focusCleanup: true,
+        rules: {
+            phoneNumber: {
+                isPhone: true,
+            },
+            thresholdValue: {
+                digits: true
+            },
+            businessHours: {
+                isTimeRange: true
             }
+        }
 
-        });
+    });
+
+    function submitHandler() {
+        var uploadInstance = $('#image-upload-container').data('imageUpload');
 
-        function submitHandler() {
-            if ($.validate.form()) {
-                $.operate.save(prefix + "/add", $('#form-venue-add').serialize());
+        // 检查是否有上传组件实例
+        if (uploadInstance) {
+            var uploadedFiles = uploadInstance.getFiles();
+            console.log('已上传的图片:', uploadedFiles);
+
+            // 如果需要封面必填
+            if (uploadedFiles.length === 0) {
+                $.modal.alertWarning("请上传图片");
+                return false;
             }
-        }
 
+            // 将图片URL数组转换为逗号分隔的字符串
+            var imageUrls = uploadedFiles.join(',');
+            console.log('图片URL字符串:', imageUrls);
 
-        $(".file-upload").fileinput({
-            uploadUrl: ctx + 'common/upload',
-            maxFileCount: 3,
-            allowedFileExtensions: ['jpg', 'png'],
-            maxFileSize: 10240,
-            multiple: true,
-        }).on('fileuploaded', function (event, data, previewId, index) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fullUrl = data.response.url; // 获取完整的URL
+            // 注意:图片上传组件已经通过 addHiddenField 方法添加了隐藏字段
+            // 我们不需要再次添加,只需要确保所有图片都已被收集
+            // 组件会自动处理隐藏字段
+        } else {
+            // 如果没有上传组件实例,直接检查是否有隐藏字段
+            var existingImages = $('#form-competition-add input[name="competitionImg"]').map(function () {
+                return $(this).val();
+            }).get().filter(function (val) {
+                return val && val.trim() !== '';
+            });
 
-            if (existingValue) {
-                $("input[name='" + inputName + "']").val(existingValue + ',' + fullUrl);
-            } else {
-                $("input[name='" + inputName + "']").val(fullUrl);
+            if (existingImages.length === 0) {
+                $.modal.alertWarning("请上传图片");
+                return false;
             }
-        }).on('fileremoved', function (event, key, jqXHR, pd) {
-            var inputName = event.currentTarget.id;
-            var existingValue = $("input[name='" + inputName + "']").val();
-            var fileUrls = existingValue.split(',');
+        }
+        if ($.validate.form()) {
+            $.operate.save(prefix + "/add", $('#form-venue-add').serialize());
+        }
+    }
 
-            // 假设key是文件的key或者index,需要找到对应的URL并移除
-            // 这里假设key是文件的index
-            var index = key;
-            if (fileUrls[index]) {
-                fileUrls.splice(index, 1);
+    $(function () {
+        $('.summernote').summernote({
+            lang: 'zh-CN',
+            dialogsInBody: true,
+            height: 245,
+            callbacks: {
+                onChange: function (contents, $edittable) {
+                    $("input[name='" + this.id + "']").val(contents);
+                },
+                onImageUpload: function (files) {
+                    var obj = this;
+                    var data = new FormData();
+                    data.append("file", files[0]);
+                    $.ajax({
+                        type: "post",
+                        url: ctx + "common/upload",
+                        data: data,
+                        cache: false,
+                        contentType: false,
+                        processData: false,
+                        dataType: 'json',
+                        success: function (result) {
+                            if (result.code == web_status.SUCCESS) {
+                                $('#' + obj.id).summernote('insertImage', result.url);
+                            } else {
+                                $.modal.alertError(result.msg);
+                            }
+                        },
+                        error: function (error) {
+                            $.modal.alertWarning("图片上传失败。");
+                        }
+                    });
+                }
             }
-
-            // 重新拼接文件路径
-            $("input[name='" + inputName + "']").val(fileUrls.join(','));
         });
 
-        $(function() {
-            $('.summernote').summernote({
-                lang: 'zh-CN',
-                dialogsInBody: true,
-                height: 245,
-                callbacks: {
-                    onChange: function(contents, $edittable) {
-                        $("input[name='" + this.id + "']").val(contents);
-                    },
-                    onImageUpload: function(files) {
-                        var obj = this;
-                    	var data = new FormData();
-                    	data.append("file", files[0]);
-                    	$.ajax({
-                            type: "post",
-                            url: ctx + "common/upload",
-                    		data: data,
-                    		cache: false,
-                    		contentType: false,
-                    		processData: false,
-                    		dataType: 'json',
-                    		success: function(result) {
-                    		    if (result.code == web_status.SUCCESS) {
-                    		        $('#' + obj.id).summernote('insertImage', result.url);
-                    		    } else {
-                    		        $.modal.alertError(result.msg);
-                    		    }
-                    		},
-                    		error: function(error) {
-                    		    $.modal.alertWarning("图片上传失败。");
-                    		}
-                    	});
-                    }
-                }
-            });
+        // 初始化图片上传组件
+        $('#image-upload-container').imageUpload({
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'cover'
         });
-    </script>
+    });
+</script>
 </body>
 </html>

+ 93 - 14
qmjszx-admin/src/main/resources/templates/system/venue/edit.html

@@ -2,7 +2,7 @@
 <html lang="zh" xmlns:th="http://www.thymeleaf.org">
 <head>
     <th:block th:include="include :: header('修改场馆信息')"/>
-    <th:block th:include="include :: bootstrap-fileinput-css"/>
+    <th:block th:include="include :: image-upload-css"/>
     <th:block th:include="include :: summernote-css"/>
     <!-- 自定义 CSS -->
     <style>
@@ -29,7 +29,7 @@
                 </div>
             </div>
         </div>
-        
+
         <div class="col-xs-12">
             <div class="form-group">
                 <label class="col-sm-2 control-label is-required">电话:</label>
@@ -42,7 +42,7 @@
                 </div>
             </div>
         </div>
-        
+
         <div class="col-xs-12">
             <div class="form-group">
                 <label class="col-sm-2 control-label">场地服务:</label>
@@ -59,10 +59,7 @@
             <div class="form-group">
                 <label class="col-sm-2 control-label">图片:</label>
                 <div class="col-sm-4">
-                    <input type="hidden" name="cover" th:field="*{cover}">
-                    <div class="file-loading">
-                        <input class="form-control file-upload" id="cover" name="file" type="file">
-                    </div>
+                    <div id="image-upload-container"></div>
                 </div>
                 <label class="col-sm-2 control-label">场馆介绍:</label>
                 <div class="col-sm-4">
@@ -74,20 +71,20 @@
     </form>
 </div>
 <th:block th:include="include :: footer"/>
-<th:block th:include="include :: bootstrap-fileinput-js"/>
+<th:block th:include="include :: image-upload-js"/>
 <th:block th:include="include :: summernote-js"/>
 <script th:inline="javascript">
     var prefix = ctx + "system/venue";
     $("#form-venue-edit").validate({
         focusCleanup: true,
-        rules:{
-            phoneNumber:{
-                isPhone:true,
+        rules: {
+            phoneNumber: {
+                isPhone: true,
             },
-            thresholdValue:{
+            thresholdValue: {
                 digits: true
             },
-            businessHours:{
+            businessHours: {
                 isTimeRange: true
             }
         }
@@ -95,6 +92,34 @@
 
     function submitHandler() {
         if ($.validate.form()) {
+            // 获取上传组件实例
+            var uploadInstance = $('#image-upload-container').data('imageUpload');
+
+            // 检查是否有上传的图片
+            if (uploadInstance) {
+                var uploadedFiles = uploadInstance.getFiles();
+                console.log('已上传的图片:', uploadedFiles);
+
+                // 检查封面图片是否上传
+                if (uploadedFiles.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+                // 组件会自动更新隐藏字段,我们不需要额外处理
+            } else {
+                // 如果没有上传组件实例,检查是否有隐藏字段
+                var existingImages = $('#form-competition-edit input[name="cover"]').map(function () {
+                    return $(this).val();
+                }).get().filter(function (val) {
+                    return val && val.trim() !== '';
+                });
+
+                if (existingImages.length === 0) {
+                    $.modal.alertWarning("请上传图片");
+                    return false;
+                }
+            }
+
             $.operate.save(prefix + "/edit", $('#form-venue-edit').serialize());
         }
     }
@@ -144,7 +169,7 @@
             $('#' + this.id).summernote({
                 lang: 'zh-CN',
                 dialogsInBody: true,
-                height:245,
+                height: 245,
                 callbacks: {
                     onChange: function (contents, $edittable) {
                         $("input[name='" + this.id + "']").val(contents);
@@ -178,6 +203,60 @@
             var content = $("input[name='" + this.id + "']").val();
             $('#' + this.id).summernote('code', content);
         })
+
+        // ============ 修复:初始化图片上传组件并回显已有图片 ============
+        // 获取已有的封面图片数据(逗号分隔的字符串)
+        var imgStr = [[${beilvVenue.cover}]];
+        var existingImages = [];
+
+        console.log('原始图片字符串:', imgStr);
+
+        if (imgStr && imgStr.trim() !== '') {
+            // 分割逗号分隔的图片字符串
+            existingImages = imgStr.split(',').map(function (img) {
+                return img.trim();
+            }).filter(function (img) {
+                // 过滤掉空字符串和无效的URL
+                return img !== '' && img !== null && img !== undefined;
+            });
+
+            console.log('解析后的图片数组:', existingImages);
+            console.log('图片数量:', existingImages.length);
+        }
+
+        // 初始化图片上传组件
+        var imageUploadConfig = {
+            uploadUrl: ctx + "common/upload",
+            maxFiles: 1,
+            maxSize: 5 * 1024 * 1024,
+            allowedTypes: ['image/jpeg', 'image/png'],
+            previewWidth: 200,
+            previewHeight: 150,
+            inputName: 'cover'
+        };
+
+        // 只有在有图片时才传递 initialFiles
+        if (existingImages.length > 0) {
+            imageUploadConfig.initialFiles = existingImages;
+        }
+
+        console.log('图片上传配置:', imageUploadConfig);
+
+        $('#image-upload-container').imageUpload(imageUploadConfig);
+
+        // 监听事件(可选)
+        $('#image-upload-container').on('upload.success', function (e, data) {
+            console.log('上传成功:', data.url);
+        });
+
+        $('#image-upload-container').on('upload.error', function (e, data) {
+            console.error('上传失败:', data.error);
+        });
+
+        $('#image-upload-container').on('files.set', function (e, data) {
+            console.log('图片已设置:', data.urls);
+        });
+        // ============ 修复结束 ============
     });
 </script>
 </body>