chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
<div class="layui-card">
<div class="layui-card-header">添加版块</div>
<div class="layui-card-body">
<form class="layui-form" id="form">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-block"><input name="name" class="layui-input" lay-verify="required"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">标识</label>
<div class="layui-input-block"><input name="slug" class="layui-input" lay-verify="required"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标</label>
<div class="layui-input-block"><input name="icon" class="layui-input"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">简介</label>
<div class="layui-input-block"><input name="description" class="layui-input"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">排序</label>
<div class="layui-input-block"><input name="sort" value="0" class="layui-input"></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">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</form>
</div>
</div>
<script>
layui.use(['form','jquery'], function(){
var form = layui.form, $ = layui.jquery;
form.on('submit(save)', function(data){
$.post('/forum/backend/board/save', data.field, function(res){
if (res.code === 0) { location.href = '/forum/backend/board'; }
else { layer.msg(res.message); }
}, 'json');
return false;
});
});
</script>
+50
View File
@@ -0,0 +1,50 @@
<div class="layui-card">
<div class="layui-card-header">编辑版块</div>
<div class="layui-card-body">
<form class="layui-form" id="form">
<input type="hidden" name="id" value="{$row.id}">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-block"><input name="name" value="{$row.name}" class="layui-input" lay-verify="required"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">标识</label>
<div class="layui-input-block"><input name="slug" value="{$row.slug}" class="layui-input" lay-verify="required"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标</label>
<div class="layui-input-block"><input name="icon" value="{$row.icon}" class="layui-input"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">简介</label>
<div class="layui-input-block"><input name="description" value="{$row.description}" class="layui-input"></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">排序</label>
<div class="layui-input-block"><input name="sort" value="{$row.sort}" class="layui-input"></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="启用" {if $row.status==1}checked{/if}>
<input type="radio" name="status" value="0" title="禁用" {if $row.status==0}checked{/if}>
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</form>
</div>
</div>
<script>
layui.use(['form','jquery'], function(){
var form = layui.form, $ = layui.jquery;
form.on('submit(save)', function(data){
$.post('/forum/backend/board/update/{$row.id}', data.field, function(res){
if (res.code === 0) { location.href = '/forum/backend/board'; }
else { layer.msg(res.message); }
}, 'json');
return false;
});
});
</script>
+42
View File
@@ -0,0 +1,42 @@
<div class="layui-card">
<div class="layui-card-header">
版块管理
<a href="/forum/backend/board/add" class="layui-btn layui-btn-sm layui-btn-normal" style="float:right;">添加版块</a>
</div>
<div class="layui-card-body">
<table class="layui-table">
<thead>
<tr><th>ID</th><th>名称</th><th>标识</th><th>帖子数</th><th>排序</th><th>状态</th><th>操作</th></tr>
</thead>
<tbody>
{volist name="list" id="b"}
<tr>
<td>{$b.id}</td>
<td>{$b.name}</td>
<td>{$b.slug}</td>
<td>{$b.topic_count}</td>
<td>{$b.sort}</td>
<td>{if $b.status==1}启用{else}禁用{/if}</td>
<td>
<a href="/forum/backend/board/edit/{$b.id}" class="layui-btn layui-btn-xs">编辑</a>
<button class="layui-btn layui-btn-xs layui-btn-danger" data-del="{$b.id}">删除</button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
</div>
<script>
layui.use(['jquery'], function(){
var $ = layui.jquery;
$('[data-del]').on('click', function(){
var id = $(this).data('del');
layer.confirm('确认删除?', function(){
$.post('/forum/backend/board/delete/'+id, {}, function(res){
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
});
});
</script>
+102
View File
@@ -0,0 +1,102 @@
<div class="layui-card">
<div class="layui-card-header">编辑器配置(UEditor</div>
<div class="layui-card-body">
<form class="layui-form" lay-filter="editorForm">
<div class="layui-form-item">
<label class="layui-form-label">上传目录</label>
<div class="layui-input-inline" style="width:360px;">
<input type="text" name="editor_upload_dir" value="{$cfg.editor_upload_dir}" class="layui-input" placeholder="相对 public/ 的目录">
</div>
<div class="layui-form-mid layui-word-aux">图片/附件/视频均存放于此目录下(按类型分子目录)</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图片类型</label>
<div class="layui-input-inline" style="width:360px;">
<input type="text" name="editor_image_ext" value="{$cfg.editor_image_ext}" class="layui-input" placeholder="逗号分隔,不含点">
</div>
<div class="layui-form-mid layui-word-aux">允许上传的图片扩展名</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图片大小(MB)</label>
<div class="layui-input-inline" style="width:160px;">
<input type="number" name="editor_image_size" value="{$cfg.editor_image_size}" class="layui-input" min="1" step="1">
</div>
<div class="layui-form-mid layui-word-aux">单张图片最大体积</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">附件类型</label>
<div class="layui-input-inline" style="width:360px;">
<input type="text" name="editor_file_ext" value="{$cfg.editor_file_ext}" class="layui-input" placeholder="逗号分隔,不含点">
</div>
<div class="layui-form-mid layui-word-aux">允许上传的附件扩展名</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">附件大小(MB)</label>
<div class="layui-input-inline" style="width:160px;">
<input type="number" name="editor_file_size" value="{$cfg.editor_file_size}" class="layui-input" min="1" step="1">
</div>
<div class="layui-form-mid layui-word-aux">单个附件最大体积</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">视频类型</label>
<div class="layui-input-inline" style="width:360px;">
<input type="text" name="editor_video_ext" value="{$cfg.editor_video_ext}" class="layui-input" placeholder="逗号分隔,不含点">
</div>
<div class="layui-form-mid layui-word-aux">允许上传的视频扩展名</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">视频大小(MB)</label>
<div class="layui-input-inline" style="width:160px;">
<input type="number" name="editor_video_size" value="{$cfg.editor_video_size}" class="layui-input" min="1" step="1">
</div>
<div class="layui-form-mid layui-word-aux">单个视频最大体积</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">远程图片抓取</label>
<div class="layui-input-inline">
<input type="checkbox" name="editor_catch_image" value="1" {if $cfg.editor_catch_image == 1}checked{/if} lay-skin="switch" lay-text="开启|关闭">
</div>
<div class="layui-form-mid layui-word-aux">粘贴 Word / 网页时是否把外链图落地到本地</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">初始高度(px)</label>
<div class="layui-input-inline" style="width:160px;">
<input type="number" name="editor_height" value="{$cfg.editor_height}" class="layui-input" min="100" step="20">
</div>
<div class="layui-form-mid layui-word-aux">发帖页编辑器默认高度</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="saveEditor">保存配置</button>
</div>
</div>
</form>
</div>
</div>
<script>
layui.use(['form', 'jquery', 'layer'], function(){
var form = layui.form, $ = layui.jquery, layer = layui.layer;
form.on('submit(saveEditor)', function(data){
// 开关未勾选时浏览器不提交该字段,这里补齐
if (!data.field.editor_catch_image) { data.field.editor_catch_image = 0; }
$.post('/forum/backend/editor/save', data.field, function(res){
if (res.code === 0) {
layer.msg('保存成功', {icon:1});
setTimeout(function(){ location.reload(); }, 800);
} else {
layer.msg(res.message || '保存失败');
}
}, 'json');
return false;
});
});
</script>
+85
View File
@@ -0,0 +1,85 @@
<!--
* @Author: YwxApp <ywx@ywxapp.cn>
* @Date: 2026-08-02 01:10:36
* @LastEditors: YwxApp <ywx@ywxapp.cn>
* @LastEditTime: 2026-08-03 23:40:59
* @Description:
* @FilePath: \ywxapp_dev\addon\forum\view\backend\reply\index.html
* @CustomString: Copyright (c) 2026 YwxApp
-->
<div class="layui-card">
<div class="layui-card-header">回复管理</div>
<div class="layui-card-body">
<form class="layui-form" lay-filter="searchForm">
<div class="layui-form-item">
<div class="layui-inline">
<input type="text" name="keyword" placeholder="回复内容关键词" autocomplete="off" class="layui-input">
</div>
<div class="layui-inline">
<button class="layui-btn" lay-submit lay-filter="searchBtn">搜索</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
</div>
</div>
<script type="text/html" id="dataBar">
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">删除</a>
</script>
<script>
layui.use(['table', 'jquery', 'layer', 'form'], function () {
var table = layui.table, $ = layui.jquery, layer = layui.layer, form = layui.form;
var dataTable = table.render({
elem: '#dataTable',
url: 'index',
page: true,
limit: 20,
cols: [[
{ field: 'id', title: 'ID', width: 80, sort: true, fixed: 'left' },
{ field: 'topic_id', title: '帖子', width: 90, templet: function (d) {
return '<a href="/forum/topic/' + d.topic_id + '" target="_blank">#' + d.topic_id + '</a>';
} },
{ field: 'user_name', title: '用户', width: 120, templet: function (d) {
return d.user_name || ('UID:' + d.user_id);
} },
{ field: 'floor', title: '楼层', width: 80 },
{ field: 'content_preview', title: '内容', minWidth: 200 },
{ field: 'create_at', title: '时间', width: 170, templet: function (d) {
return d.create_at ? layui.util.toDateString(d.create_at * 1000, 'yyyy-MM-dd HH:mm') : '';
} },
{ title: '操作', width: 80, align: 'center', toolbar: '#dataBar', fixed: 'right' }
]]
});
// 搜索
form.on('submit(searchBtn)', function (data) {
dataTable.reload({
where: data.field,
page: { curr: 1 }
});
return false;
});
// 工具条事件
table.on('tool(dataTable)', function (obj) {
var data = obj.data;
if (obj.event === 'delete') {
layer.confirm('确认删除?', function (index) {
layer.close(index);
$.post('delete', { id: data.id }, function (res) {
if (res.code === 0) {
layer.msg('删除成功', { icon: 1 });
dataTable.reload();
} else {
layer.msg(res.message || '删除失败');
}
}, 'json');
});
}
});
});
</script>
+41
View File
@@ -0,0 +1,41 @@
<div class="layui-card">
<div class="layui-card-header">
标签管理
<button class="layui-btn layui-btn-sm layui-btn-normal" id="addTag" style="float:right;">添加标签</button>
</div>
<div class="layui-card-body">
<table class="layui-table">
<thead><tr><th>ID</th><th>名称</th><th>使用数</th><th>操作</th></tr></thead>
<tbody>
{volist name="list" id="t"}
<tr>
<td>{$t.id}</td>
<td>{$t.name}</td>
<td>{$t.topic_count}</td>
<td><button class="layui-btn layui-btn-xs layui-btn-danger" data-del="{$t.id}">删除</button></td>
</tr>
{/volist}
</tbody>
</table>
</div>
</div>
<script>
layui.use(['jquery','layer'], function(){
var $ = layui.jquery, layer = layui.layer;
$('#addTag').on('click', function(){
layer.prompt({title:'输入标签名称'}, function(val, index){
$.post('/forum/backend/tag/save', {name:val}, function(res){
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
});
$('[data-del]').on('click', function(){
var id = $(this).data('del');
layer.confirm('确认删除?', function(){
$.post('/forum/backend/tag/delete/'+id, {}, function(res){
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
});
});
</script>
+72
View File
@@ -0,0 +1,72 @@
<div class="layui-card">
<div class="layui-card-header">编辑帖子</div>
<div class="layui-card-body">
<form class="layui-form" id="form">
<input type="hidden" name="id" value="{$row.id}">
<div class="layui-form-item">
<label class="layui-form-label">版块</label>
<div class="layui-input-block">
<select name="board_id">
{volist name="boards" id="b"}
<option value="{$b.id}" {if $row.board_id==$b.id}selected{/if}>{$b.name}</option>
{/volist}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">类型</label>
<div class="layui-input-block">
<select name="type">
{foreach $typeMap as $k=>$v}
<option value="{$k}" {if $row.type==$k}selected{/if}>{$v}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block"><input name="title" value="{$row.title}" class="layui-input" lay-verify="required"></div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">内容</label>
<div class="layui-input-block"><textarea name="content" class="layui-textarea" style="min-height:200px;">{$row.content}</textarea></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">置顶</label>
<div class="layui-input-block">
<input type="radio" name="is_top" value="1" title="是" {if $row.is_top==1}checked{/if}>
<input type="radio" name="is_top" value="0" title="否" {if $row.is_top==0}checked{/if}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">加精</label>
<div class="layui-input-block">
<input type="radio" name="is_essence" value="1" title="是" {if $row.is_essence==1}checked{/if}>
<input type="radio" name="is_essence" value="0" title="否" {if $row.is_essence==0}checked{/if}>
</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="正常" {if $row.status==1}checked{/if}>
<input type="radio" name="status" value="0" title="待审" {if $row.status==0}checked{/if}>
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</form>
</div>
</div>
<script>
layui.use(['form','jquery'], function(){
var form = layui.form, $ = layui.jquery;
form.on('submit(save)', function(data){
$.post('/forum/backend/topic/update/{$row.id}', data.field, function(res){
if (res.code === 0) { location.href = '/forum/backend/topic'; }
else { layer.msg(res.message); }
}, 'json');
return false;
});
});
</script>
+69
View File
@@ -0,0 +1,69 @@
<div class="layui-card">
<div class="layui-card-header">帖子管理(共 {$list.total} 条)</div>
<div class="layui-card-body">
<table class="layui-table">
<thead>
<tr><th>ID</th><th>标题</th><th>版块</th><th>类型</th><th>作者</th><th>回复</th><th>状态</th><th>操作</th></tr>
</thead>
<tbody>
{volist name="list.list" id="t"}
<tr>
<td>{$t.id}</td>
<td><a href="/forum/topic/{$t.id}" target="_blank">{$t.title}</a></td>
<td>{$t.board.name|default='-'}</td>
<td>{$typeMap[$t.type]|default='-'}</td>
<td>{$t.user_id}</td>
<td>{$t.reply_count}</td>
<td>
{if $t.is_top==1}<span class="layui-badge"></span>{/if}
{if $t.is_essence==1}<span class="layui-badge layui-bg-green"></span>{/if}
{if $t.status==1}正常{elseif $t.status==0}待审{else}已删{/if}
</td>
<td>
<a href="/forum/backend/topic/edit/{$t.id}" class="layui-btn layui-btn-xs">编辑</a>
{if $t.status==0}
<button class="layui-btn layui-btn-xs layui-btn-normal" data-audit="{$t.id}">通过</button>
<button class="layui-btn layui-btn-xs layui-btn-warm" data-reject="{$t.id}">驳回</button>
{/if}
<button class="layui-btn layui-btn-xs layui-btn-danger" data-del="{$t.id}">删除</button>
</td>
</tr>
{/volist}
</tbody>
</table>
<div id="pager"></div>
</div>
</div>
<script>
layui.use(['jquery','laypage'], function(){
var $ = layui.jquery, laypage = layui.laypage;
laypage.render({ elem:'pager', count:{$list.total}, limit:20,
curr:{$list.currentPage}, jump:function(obj,first){
if(!first){ location.href='?page='+obj.curr; }
}});
$('[data-del]').on('click', function(){
var id = $(this).data('del');
layer.confirm('确认删除?', function(){
$.post('/forum/backend/topic/audit/'+id+'?act=del', {}, function(res){}, 'json');
$.post('/forum/backend/topic/delete/'+id, {}, function(res){
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
});
$('[data-audit]').on('click', function(){
var id = $(this).data('audit');
$.post('/forum/backend/topic/audit/'+id, {}, function(res){
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
$('[data-reject]').on('click', function(){
var id = $(this).data('reject');
layer.prompt({title:'驳回理由', formType:2}, function(val, index){
$.post('/forum/backend/topic/reject/'+id, {reason:val}, function(res){
layer.close(index);
if (res.code === 0) { location.reload(); } else { layer.msg(res.message); }
}, 'json');
});
});
});
</script>