491 lines
17 KiB
PHP
491 lines
17 KiB
PHP
{include file="public/header" /}
|
||
<div class="config-container">
|
||
<!-- 页面头部 -->
|
||
<div class="page-header">
|
||
<div class="header-title">
|
||
<i class="layui-icon layui-icon-app"></i>
|
||
<span>文章分类管理</span>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" onclick="add()">
|
||
<i class="layui-icon layui-icon-add-1"></i>新增分类
|
||
</button>
|
||
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm" onclick="refresh()">
|
||
<i class="layui-icon layui-icon-refresh"></i>刷新
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主要内容区 -->
|
||
<div class="main-content">
|
||
<div class="layui-row layui-col-space20">
|
||
<!-- 左侧分类列表 -->
|
||
<div class="layui-col-md7">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<span>分类列表</span>
|
||
<small class="text-muted">支持两级分类结构</small>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div id="categoryList" class="category-tree"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧分类信息 -->
|
||
<div class="layui-col-md5">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<span>分类信息</span>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<!-- 默认提示 -->
|
||
<div id="defaultTip" class="empty-tip">
|
||
<i class="layui-icon layui-icon-face-surprised"></i>
|
||
<p>请选择左侧分类或点击新增按钮</p>
|
||
</div>
|
||
|
||
<!-- 分类表单 -->
|
||
<form class="layui-form category-form" lay-filter="categoryForm" style="display: none;">
|
||
<input type="hidden" name="id" id="categoryId">
|
||
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">分类名称</label>
|
||
<div class="layui-input-block">
|
||
<input type="text" name="name" required lay-verify="required" placeholder="请输入分类名称"
|
||
autocomplete="off" class="layui-input">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">父级分类</label>
|
||
<div class="layui-input-block">
|
||
<select name="cid" lay-verify="required">
|
||
<option value="0">顶级分类</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">封面图片</label>
|
||
<div class="layui-input-block">
|
||
<div class="layui-upload-drag" id="uploadImage">
|
||
<i class="layui-icon layui-icon-upload"></i>
|
||
<p>点击上传或拖拽图片至此处</p>
|
||
<div class="layui-hide" id="uploadPreview">
|
||
<hr>
|
||
<img src="" alt="封面图片" style="max-width: 100%">
|
||
</div>
|
||
</div>
|
||
<input type="hidden" name="image" id="imageInput">
|
||
<div class="layui-form-mid layui-word-aux">建议尺寸:250px * 140px</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">排序</label>
|
||
<div class="layui-input-block">
|
||
<input type="number" name="sort" value="0" class="layui-input"
|
||
placeholder="数字越大越靠前">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label">状态</label>
|
||
<div class="layui-input-block">
|
||
<input type="radio" name="status" value="1" title="正常" checked>
|
||
<input type="radio" name="status" value="0" title="禁用">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-form-item form-actions">
|
||
<div class="layui-input-block">
|
||
<button class="layui-btn" lay-submit lay-filter="saveCategory">保存</button>
|
||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||
<button type="button" class="layui-btn layui-btn-danger" id="deleteBtn"
|
||
style="display: none;">删除</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
/* 页面整体样式 */
|
||
.config-container {
|
||
padding: 15px;
|
||
background: #f2f2f2;
|
||
}
|
||
|
||
/* 页面头部样式 */
|
||
.page-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
padding: 10px 15px;
|
||
background: #fff;
|
||
border-radius: 2px;
|
||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.header-title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.header-title .layui-icon {
|
||
margin-right: 8px;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.header-actions .layui-btn {
|
||
margin-left: 8px;
|
||
}
|
||
|
||
/* 主要内容区样式 */
|
||
.main-content {
|
||
min-height: calc(100vh - 170px);
|
||
}
|
||
|
||
.layui-card {
|
||
margin-bottom: 0;
|
||
border-radius: 2px;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.layui-card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
height: auto;
|
||
padding: 12px 15px;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.text-muted {
|
||
margin-left: 10px;
|
||
font-size: 12px;
|
||
font-weight: normal;
|
||
color: #999;
|
||
}
|
||
|
||
/* 分类树样式 */
|
||
.category-tree {
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.category-item {
|
||
margin: 5px 0;
|
||
}
|
||
|
||
.category-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 10px 15px;
|
||
background-color: #f8f8f8;
|
||
border-radius: 2px;
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.category-header:hover {
|
||
background-color: #f2f2f2;
|
||
}
|
||
|
||
.category-header.active {
|
||
background-color: #e6f7ff;
|
||
border-right: 3px solid #1890ff;
|
||
}
|
||
|
||
.category-name {
|
||
flex: 1;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.category-actions {
|
||
/* opacity: 0; */
|
||
transition: opacity 0.3s;
|
||
}
|
||
|
||
.category-header:hover .category-actions {
|
||
opacity: 1;
|
||
}
|
||
|
||
.category-children {
|
||
margin-left: 20px;
|
||
padding-left: 15px;
|
||
border-left: 1px dashed #e6e6e6;
|
||
}
|
||
|
||
.add-child {
|
||
padding: 3px 8px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.add-child .layui-icon {
|
||
font-size: 12px;
|
||
margin-right: 3px;
|
||
}
|
||
|
||
/* 空状态提示 */
|
||
.empty-tip {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 40px 0;
|
||
color: #999;
|
||
}
|
||
|
||
.empty-tip .layui-icon {
|
||
font-size: 32px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
/* 表单样式优化 */
|
||
.category-form {
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.layui-form-label {
|
||
width: 100px;
|
||
}
|
||
|
||
.layui-input-block {
|
||
margin-left: 130px;
|
||
}
|
||
|
||
.form-actions {
|
||
margin-top: 30px;
|
||
}
|
||
|
||
.layui-upload-drag {
|
||
padding: 20px;
|
||
border: 1px dashed #e2e2e2;
|
||
background-color: #fff;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.layui-upload-drag:hover {
|
||
border-color: #009688;
|
||
}
|
||
|
||
.layui-upload-drag img {
|
||
max-width: 100%;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.layui-btn-xs {
|
||
height: 30px;
|
||
line-height: 25px;
|
||
font-size: 12px;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
// 定义全局变量和函数
|
||
var categoryManager = {
|
||
init: function () {
|
||
this.initLayui();
|
||
},
|
||
|
||
initLayui: function () {
|
||
var that = this;
|
||
layui.use(['layer', 'form', 'upload'], function () {
|
||
var layer = layui.layer;
|
||
var form = layui.form;
|
||
var upload = layui.upload;
|
||
var $ = layui.jquery;
|
||
|
||
// 初始化分类列表
|
||
that.initCategoryList = function () {
|
||
$.ajax({
|
||
url: '/admin/article/articlecate',
|
||
type: 'POST',
|
||
success: function (res) {
|
||
if (res.code === 0) {
|
||
var html = '';
|
||
res.data.forEach(function (item) {
|
||
html += that.renderCategory(item);
|
||
});
|
||
$('#categoryList').html(html);
|
||
that.bindEvents();
|
||
} else {
|
||
layer.msg('获取分类数据失败', { icon: 2 });
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
// 渲染分类项
|
||
that.renderCategory = function (category, level = 0) {
|
||
var html = '<div class="category-item" data-id="' + category.id + '">';
|
||
html += '<div class="category-header">';
|
||
html += '<div class="category-name">' + category.title + '</div>';
|
||
if (level === 0) {
|
||
html += '<div class="category-actions">';
|
||
html += '<button type="button" class="layui-btn layui-btn-primary layui-btn-xs add-child">';
|
||
html += '<i class="layui-icon layui-icon-add-1"></i>添加子分类</button>';
|
||
html += '</div>';
|
||
}
|
||
html += '</div>';
|
||
|
||
if (category.children && category.children.length > 0) {
|
||
html += '<div class="category-children">';
|
||
category.children.forEach(function (child) {
|
||
html += that.renderCategory(child, level + 1);
|
||
});
|
||
html += '</div>';
|
||
}
|
||
html += '</div>';
|
||
return html;
|
||
};
|
||
|
||
// 绑定事件
|
||
that.bindEvents = function () {
|
||
// 点击分类项加载编辑信息
|
||
$('.category-header').off('click').on('click', function (e) {
|
||
if (!$(e.target).closest('.add-child').length) {
|
||
var id = $(this).closest('.category-item').data('id');
|
||
that.loadCategoryInfo(id);
|
||
|
||
// 添加选中效果
|
||
$('.category-header').removeClass('active');
|
||
$(this).addClass('active');
|
||
}
|
||
});
|
||
|
||
// 添加子分类
|
||
$('.add-child').off('click').on('click', function (e) {
|
||
e.stopPropagation();
|
||
var parentId = $(this).closest('.category-item').data('id');
|
||
that.showCategoryForm(parentId);
|
||
});
|
||
};
|
||
|
||
// 加载分类信息
|
||
that.loadCategoryInfo = function (id) {
|
||
$.get('/admin/article/cateedit?id=' + id, function (res) {
|
||
if (res.code === 0) {
|
||
that.showCategoryForm(0, res.data);
|
||
}
|
||
});
|
||
};
|
||
|
||
// 显示分类表单
|
||
that.showCategoryForm = function (parentId = 0, data = null) {
|
||
$('#defaultTip').hide();
|
||
$('.category-form').show();
|
||
|
||
// 重置表单
|
||
form.val('categoryForm', {
|
||
id: data ? data.info.id : '',
|
||
name: data ? data.info.name : '',
|
||
cid: data ? data.info.cid : parentId,
|
||
sort: data ? data.info.sort : 0,
|
||
status: data ? data.info.status : 1
|
||
});
|
||
|
||
// 更新父级分类选项
|
||
var $select = $('select[name="cid"]');
|
||
$select.empty().append('<option value="0">顶级分类</option>');
|
||
if (data && data.parentOptions) {
|
||
data.parentOptions.forEach(function (item) {
|
||
$select.append('<option value="' + item.id + '">' + item.name + '</option>');
|
||
});
|
||
}
|
||
|
||
// 更新图片预览
|
||
if (data && data.info.image) {
|
||
$('#uploadPreview').removeClass('layui-hide').find('img').attr('src', data.info.image);
|
||
$('#imageInput').val(data.info.image);
|
||
} else {
|
||
$('#uploadPreview').addClass('layui-hide').find('img').attr('src', '');
|
||
$('#imageInput').val('');
|
||
}
|
||
|
||
// 显示/隐藏删除按钮
|
||
$('#deleteBtn')[data ? 'show' : 'hide']();
|
||
|
||
form.render();
|
||
};
|
||
|
||
// 初始化上传组件
|
||
upload.render({
|
||
elem: '#uploadImage',
|
||
url: '/admin/upload/image',
|
||
accept: 'images',
|
||
acceptMime: 'image/*',
|
||
done: function (res) {
|
||
if (res.code === 0) {
|
||
$('#uploadPreview').removeClass('layui-hide').find('img').attr('src', res.data.url);
|
||
$('#imageInput').val(res.data.url);
|
||
layer.msg('上传成功');
|
||
} else {
|
||
layer.msg('上传失败');
|
||
}
|
||
}
|
||
});
|
||
|
||
// 监听表单提交
|
||
form.on('submit(saveCategory)', function (data) {
|
||
var url = data.field.id ? '/admin/article/cateedit' : '/admin/article/cateadd';
|
||
$.post(url, data.field, function (res) {
|
||
if (res.code === 0) {
|
||
layer.msg(res.msg, { icon: 1 });
|
||
that.initCategoryList();
|
||
} else {
|
||
layer.msg(res.msg, { icon: 2 });
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
|
||
// 监听删除按钮
|
||
$('#deleteBtn').on('click', function () {
|
||
var id = $('#categoryId').val();
|
||
if (!id) return;
|
||
|
||
layer.confirm('确定要删除该分类吗?', function (index) {
|
||
$.post('/admin/article/catedel', { id: id }, function (res) {
|
||
if (res.code === 0) {
|
||
layer.msg(res.msg, { icon: 1 });
|
||
that.initCategoryList();
|
||
$('#defaultTip').show();
|
||
$('.category-form').hide();
|
||
} else {
|
||
layer.msg(res.msg, { icon: 2 });
|
||
}
|
||
});
|
||
layer.close(index);
|
||
});
|
||
});
|
||
|
||
// 初始化页面
|
||
that.initCategoryList();
|
||
});
|
||
}
|
||
};
|
||
|
||
// 初始化
|
||
categoryManager.init();
|
||
|
||
// 新增分类
|
||
function add() {
|
||
categoryManager.showCategoryForm();
|
||
}
|
||
|
||
// 刷新列表
|
||
function refresh() {
|
||
categoryManager.initCategoryList();
|
||
}
|
||
</script> |