<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>积分商城网厅常见问题分类配置</title>
<script src="../js/jquery-1.min.js"></script>
<script src="../js/bootstrap.min.js"></script>
<link href="../css/bootstrap.min.css" rel="stylesheet">
<script src="../js/lay.js"></script>
<!-- 添加 TinyMCE 引用 -->
<script src="../js/tinymce/tinymce.min.js"></script>
<style>
/* 添加编辑器样式调整 */
.tox-tinymce {
border-radius: 4px !important;
border: 1px solid #dcdfe6 !important;
}
/* 隐藏原始文本区域 */
#content {
display: none;
}
</style>
</head>
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
max-width: 1400px;
margin: 30px auto;
padding: 20px;
background-color: #f8f9fa;
}
.hidden-id {
display: none;
}
.form-container {
background-color: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
}
.form-section {
border: 1px solid #ebeef5;
padding: 20px;
margin-bottom: 25px;
border-radius: 8px;
background: #fafafa;
}
.form-section h3 {
color: #409eff;
margin: 0 0 20px 0;
padding-bottom: 10px;
border-bottom: 1px solid #ebeef5;
font-size: 16px;
}
.table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.table th, .table td {
padding: 12px 15px;
border: 1px solid #ddd;
text-align: left;
}
.table th {
background-color: #f5f5f5;
font-weight: 600;
}
.table tr:nth-child(even) {
background-color: #f9f9f9;
}
.table tr:hover {
background-color: #f1f1f1;
}
.btn {
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
border: none;
transition: all 0.3s;
display: inline-flex;
align-items: center;
justify-content: center;
}
.btn-primary {
background-color: #409eff;
color: white;
}
.btn-primary:hover {
background-color: #66b1ff;
}
.btn-success {
background-color: #67c23a;
color: white;
}
.btn-success:hover {
background-color: #85ce61;
}
.btn-danger {
background-color: #f56c6c;
color: white;
}
.btn-danger:hover {
background-color: #f78989;
}
.btn-sm {
padding: 4px 8px;
font-size: 12px;
}
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
}
.modal-content {
background-color: #fefefe;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
border-radius: 8px;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover {
color: black;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #606266;
}
.form-control {
width: 100%;
padding: 8px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
box-sizing: border-box;
}
textarea.form-control {
height: auto;
min-height: 100px;
}
.required label::before {
content: "*";
color: #f56c6c;
margin-right: 4px;
}
.child-node {
padding-left: 30px;
background-color: #f9f9f9;
vertical-align: middle;
}
.submit-btn {
display: block;
width: 200px;
margin: 20px auto 0;
padding: 10px;
background: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.submit-btn:hover {
background: #66b1ff;
}
.action-buttons {
text-align: left; /* 内容左对齐 */
}
.action-buttons button {
display: inline-block;
margin-right: 5px; /* 按钮之间的间距 */
vertical-align: middle; /* 垂直居中 */
}
.table th:nth-child(4), .table td:nth-child(4) {
width: 15%; /* 与表头设置一致 */
min-width: 180px; /* 设置最小宽度防止内容挤压 */
white-space: nowrap; /* 防止内容换行 */
}
</style>
<body>
<div class="form-container">
<div class="form-section">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h3 style="margin: 0 auto;">常见问题分类配置</h3>
<button id="addTopCategory" class="btn btn-primary">添加一级分类</button>
</div>
<table class="table" id="categoryTable">
<thead>
<tr>
<th width="15%">分类名称</th>
<th width="50%">分类内容</th>
<th width="5%">排序</th>
<th width="30%">操作</th>
</tr>
</thead>
<tbody id="categoryList">
<!-- 动态加载数据 -->
</tbody>
</table>
</div>
</div>
<!-- 添加/编辑分类的模态框 -->
<div id="categoryModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<h3 id="modalTitle">添加分类</h3>
<form id="categoryForm" novalidate>
<input type="hidden" id="id" name="id">
<input type="hidden" id="pid" name="pid" value="0">
<div class="form-group required">
<label for="name">分类名称:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入分类名称,同级别不允许重复" required>
</div>
<div class="form-group required" id="contentGroup">
<label for="content">分类内容:</label>
<textarea class="form-control" id="content" name="content" placeholder="请输入分类描述" required></textarea>
</div>
<div class="form-group required">
<label for="orderNum">排序顺序:
<span style="color: #888; font-size: 12px; margin-left: 5px;">值越小越靠前,请输入正整数</span>
</label>
<input type="number" class="form-control" id="orderNum" name="orderNum" placeholder="请输入分类排序,同级别不允许重复" required min="1" step="1">
</div>
<button type="submit" class="submit-btn">保存</button>
</form>
</div>
</div>
<script>
// 动态设置 required 的函数
function setContentRequired(required) {
if (required) {
$('#content').attr('required', 'required');
$("#contentGroup").removeClass("hidden");
tinymce.get('content').show();
$('#content').css({visibility: 'visible', position: 'static'}); // 移除隐藏样式
} else {
$('#content').removeAttr('required');
$("#contentGroup").addClass("hidden");
tinymce.get('content').hide();
$('#content').css({visibility: 'hidden', position: 'absolute', left: '-9999px'}); // 恢复隐藏样式
}
}
$(document).ready(function() {
// 初始化 TinyMCE
tinymce.init({
license_key: 'gpl', // 对于GPL许可证
selector: '#content',
language: 'zh_CN',
language_url: '../js/tinymce/langs/zh_CN.js',
height: 300,
plugins: 'link lists image table code help wordcount',
toolbar: 'undo redo | formatselect | image | bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link image | code help',
images_upload_url: '../point/uploadFileNew?limit=010',
images_upload_handler: function (blobInfo, progress) {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
// 显示上传进度
progress(0);
$.ajax({
url: tinymce.activeEditor.settings.images_upload_url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: function() {
const xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
progress((e.loaded / e.total) * 100);
}
});
}
return xhr;
},
success: function(response) {
if (response.state === '200') {
resolve(response.filePath); // 传递图片 URL 给编辑器
} else {
$.MsgBox.Alert("上传失败", response.msg || "未知错误");
reject(response.msg);
}
},
error: function(xhr) {
$.MsgBox.Alert("上传失败", "网络错误:" + xhr.statusText);
reject("网络错误:" + xhr.statusText);
}
});
});
},
skin: 'oxide',
content_css: 'default',
menubar: false,
branding: false,
relative_urls: false,
remove_script_host: false,
setup: function(editor) {
editor.on('init', function() {
console.log('TinyMCE 初始化成功');
});
editor.on('error', function(e) {
console.error('TinyMCE 错误:', e);
});
editor.on('change', function() {
// 内容变化时的逻辑(如实时保存)
});
},
valid_elements: 'p,br,strong/b,em/i,u,ol,ul,li,h1,h2,h3,h4,a[href|target=_blank],img[src|alt|title|width|height|class]',
valid_children: '-p[strong/b|em/i|u|a|img],-li[p|ol|ul]',
extended_valid_elements: '',
invalid_elements: 'script,iframe,object,embed,form,input,textarea,button,select,option,style',
content_security_policy: "default-src 'self'; img-src 'self' data:; media-src 'none'; script-src 'none';",
forced_root_block: 'p',
force_br_newlines: false,
convert_newlines_to_brs: false,
remove_linebreaks: false,
// 允许的CSS类
valid_classes: {
'*': 'text-left,text-center,text-right,text-justify'
},
// 粘贴过滤设置
paste_as_text: false,
paste_postprocess: function(editor, node) {
// 额外的粘贴后处理
},
init_instance_callback: function(editor) {
console.log('Editor完全初始化完成:', editor.id);
}
});
// 加载分类数据
loadCategoryData();
// 打开添加一级分类模态框
$("#addTopCategory").click(function() {
$("#modalTitle").text("添加一级分类");
$("#categoryForm")[0].reset();
$("#id").val("");
$("#pid").val("0");
$("#content").removeAttr("required");
$("#contentGroup").addClass("hidden");
tinymce.get('content').hide();
$("#categoryModal").show();
setContentRequired(false);
});
// 添加 orderNum 输入限制
$("#orderNum").on('input', function() {
let value = parseInt($(this).val()) || 0;
if (value < 1) {
$(this).val(1);
}
});
// 关闭模态框
$(".close").click(function() {
$("#categoryModal").hide();
tinymce.get('content').setContent('');
});
// 点击模态框外部关闭
$(window).click(function(event) {
if (event.target == $("#categoryModal")[0]) {
$("#categoryModal").hide();
tinymce.get('content').setContent('');
}
});
// 提交表单
$("#categoryForm").submit(function(e) {
e.preventDefault();
// 验证分类名称不能为空
var name = $("#name").val().trim();
if (name === '') {
$.MsgBox.Alert("提示", "分类名称不能为空");
$("#name").focus(); // 聚焦到输入框
return;
}
// 验证分类内容(如果是必填的)
if ($("#content").is(':required') && tinymce.get('content').getContent().trim() === '') {
$.MsgBox.Alert("提示", "分类内容不能为空");
tinymce.get('content').focus(); // 聚焦到编辑器
return;
}
// 同步编辑器内容到 textarea
var content = tinymce.get('content').getContent();
$('#content').val(content);
saveCategory();
});
});
// 加载分类数据
function loadCategoryData() {
$.ajax({
url: "../problemClassification/list",
type: "GET",
dataType: "json",
success: function(data) {
renderCategoryTable(data);
},
error: function() {
$.MsgBox.Alert("提示", "加载分类数据失败");
}
});
}
// 渲染分类表格
function renderCategoryTable(data) {
var html = "";
$.each(data, function(index, item) {
html += '<tr data-id="' + item.id + '">';
html += ' <td class="hidden-id">' + item.id + '</td>'; // 隐藏的ID列
html += ' <td>' + item.name + '</td>';
html += ' <td>' + (item.content || '') + '</td>'; // 新增内容列
html += ' <td>' + (item.orderNum || 0) + '</td>';
html += ' <td class="action-buttons">';
html += ' <button class="btn btn-primary btn-sm edit-btn" data-id="' + item.id + '">编辑</button>';
html += ' <button class="btn btn-success btn-sm add-child-btn" data-id="' + item.id + '">添加子类</button>';
html += ' <button class="btn btn-danger btn-sm delete-btn" data-id="' + item.id + '">删除</button>';
html += ' </td>';
html += '</tr>';
// 添加子分类
if (item.chilsNode && item.chilsNode.length > 0) {
$.each(item.chilsNode, function(i, child) {
html += '<tr class="child-node" data-id="' + child.id + '">';
html += ' <td class="hidden-id">' + child.id + '</td>'; // 隐藏的ID列
html += ' <td>└ ' + child.name + '</td>';
html += ' <td>' + (child.content || '') + '</td>'; // 新增内容列
html += ' <td>' + (child.orderNum || 0) + '</td>';
html += ' <td class="action-buttons">';
html += ' <button class="btn btn-primary btn-sm edit-btn" data-id="' + child.id + '">编辑</button>';
html += ' <button class="btn btn-danger btn-sm delete-btn" data-id="' + child.id + '">删除</button>';
html += ' </td>';
html += '</tr>';
});
}
});
$("#categoryList").html(html);
// 绑定按钮事件
$(".edit-btn").click(function() {
var id = $(this).data("id");
editCategory(id);
});
// 添加子分类按钮点击事件
$(".add-child-btn").click(function() {
var pid = $(this).data("id");
$("#modalTitle").text("添加子分类");
$("#categoryForm")[0].reset();
$("#id").val("");
$("#pid").val(pid);
$("#content").attr("required", true);
$("#contentGroup").removeClass("hidden");
tinymce.get('content').show(); // 显示编辑器
$("#categoryModal").show();
setContentRequired(true);
});
$(".delete-btn").click(function() {
var id = $(this).data("id");
$.MsgBox.Confirm("提示", "确定要删除这个分类吗?", function() {
deleteCategory(id);
});
});
}
// 编辑分类
function editCategory(id) {
$("#modalTitle").html("编辑分类 <small>(加载中...)</small>");
// 先确保编辑器实例存在
if (!tinymce.get('content')) {
console.error('TinyMCE 编辑器未初始化');
$.MsgBox.Alert("温馨提示", "编辑器初始化失败,请刷新页面重试");
return;
}
$.ajax({
url: "../problemClassification/get/" + id,
type: "GET",
dataType: "json",
success: function(data) {
$("#modalTitle").text("编辑分类");
$("#id").val(data.id);
$("#name").val(data.name);
$("#orderNum").val(data.orderNum);
$("#pid").val(data.pid);
// 确保编辑器可见性正确
if(data.pid == 0) {
setContentRequired(false);
} else {
setContentRequired(true);
}
// 延迟设置内容以确保编辑器就绪
setTimeout(function() {
try {
tinymce.get('content').setContent(data.content || '');
$("#categoryModal").show();
} catch(e) {
console.error('设置编辑器内容失败:', e);
$.MsgBox.Alert("温馨提示", "编辑器内容设置失败,请重试");
}
}, 100);
},
error: function() {
$.MsgBox.Alert("温馨提示", "获取分类信息失败");
}
});
}
// 保存分类
function saveCategory() {
// 获取提交按钮,并禁用 + 修改文字
var $submitBtn = $("#categoryForm").find("button[type='submit']");
$submitBtn.prop("disabled", true).text("保存中...");
// 强制同步 TinyMCE 内容到 textarea
tinymce.get('content').save();
// 自定义验证
if ($("#content").is(':required') && tinymce.get('content').getContent().trim() === '') {
$.MsgBox.Alert("温馨提示", '分类内容不能为空');
$submitBtn.prop("disabled", false).text("保存"); // 恢复按钮状态
return false;
}
// 新增 orderNum 校验
const orderNum = parseInt($("#orderNum").val());
if (isNaN(orderNum) || orderNum < 1) {
$.MsgBox.Alert("温馨提示", "排序顺序必须为正整数");
$submitBtn.prop("disabled", false).text("保存"); // 恢复按钮状态
return false;
}
var formData = $("#categoryForm").serialize();
var url = $("#id").val() ? "../problemClassification/update" : "../problemClassification/add";
$.ajax({
url: url,
type: "POST",
data: formData,
success: function(response) {
if (response === "添加成功" || response === "更新成功") {
$("#categoryModal").hide();
loadCategoryData();
} else {
$.MsgBox.Alert("温馨提示", response);
}
},
error: function() {
$.MsgBox.Alert("温馨提示", "操作失败");
},
complete: function() {
// 无论成功或失败,最终恢复按钮状态
$submitBtn.prop("disabled", false).text("保存");
}
});
}
// 删除分类
function deleteCategory(id) {
$.ajax({
url: "../problemClassification/delete/" + id,
type: "POST",
success: function(response) {
if(response === "删除成功") {
loadCategoryData();
} else {
$.MsgBox.Alert("温馨提示", response);
}
},
error: function() {
$.MsgBox.Alert("温馨提示", "删除失败");
}
});
}
</script>
</body>
</html>
分下一下,上传图片报错:Cannot read properties of undefined(reading 'images_upload_url')