Files
DevelopmentHistory/manage-panel.php

1426 lines
44 KiB
PHP
Raw Normal View History

2026-02-23 17:23:48 +08:00
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* 发展历史插件后台管理面板
*/
// 获取配置
$options = Typecho_Widget::widget('Widget_Options');
$config = $options->plugin('DevelopmentHistory');
// 引入Action类
require_once __DIR__ . '/Action.php';
$action = new DevelopmentHistory_Action();
// 获取当前页码
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$perPage = isset($config->perPage) ? intval($config->perPage) : 10;
// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 处理新增 - 关键:处理完后不重定向,刷新当前页面
// 在manage-panel.php中修改发布处理部分第29-38行
// 处理新增
if (!empty($_POST['content'])) {
try {
$action->addHistory(array(
'content' => $_POST['content'],
'event_date' => $_POST['event_date'],
'post_cids' => isset($_POST['post_cids']) ? $_POST['post_cids'] : ''
));
$successMsg = '记录添加成功!';
// 添加滚动到列表的锚点
header('Location: ' . $_SERVER['PHP_SELF'] . '?panel=DevelopmentHistory/manage-panel.php&page=' . $page . '#history-list-anchor');
exit;
} catch (Exception $e) {
// 如果数据已保存但出现错误,只显示警告
$successMsg = '记录已添加,但出现警告:' . htmlspecialchars($e->getMessage());
}
}
// 处理批量删除
if (!empty($_POST['delete_ids']) && is_array($_POST['delete_ids'])) {
$action->deleteHistories($_POST['delete_ids']);
$successMsg = '删除成功!';
// 添加滚动到列表的锚点
header('Location: ' . $_SERVER['PHP_SELF'] . '?panel=DevelopmentHistory/manage-panel.php&page=' . $page . '#history-list-anchor');
exit;
}
// 处理编辑
if (!empty($_POST['edit_id'])) {
$action->updateHistory(array(
'edit_id' => $_POST['edit_id'],
'edit_content' => $_POST['edit_content'],
'edit_event_date' => $_POST['edit_event_date'],
'edit_post_cids' => isset($_POST['edit_post_cids']) ? $_POST['edit_post_cids'] : ''
));
$successMsg = '记录更新成功!';
// 添加滚动到列表的锚点
header('Location: ' . $_SERVER['PHP_SELF'] . '?panel=DevelopmentHistory/manage-panel.php&page=' . $page . '#history-list-anchor');
exit;
}
// 处理导出
if (isset($_POST['export'])) {
$exportContent = $action->exportData();
$filename = 'development_history_' . date('Ymd_His') . '.txt';
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . strlen($exportContent));
echo $exportContent;
exit;
}
// 处理导入
if (isset($_POST['import']) && !empty($_FILES['import_file']['tmp_name'])) {
$fileContent = file_get_contents($_FILES['import_file']['tmp_name']);
$result = $action->importData($fileContent);
if ($result['imported'] > 0) {
$successMsg = '导入成功!成功导入 ' . $result['imported'] . ' 条记录';
if ($result['failed'] > 0) {
$successMsg .= ',失败 ' . $result['failed'] . ' 条记录';
// 显示失败原因限制显示前10条
if (!empty($result['fail_reasons'])) {
$errorDetails = '<strong>失败原因:</strong><br>';
$displayCount = min(10, count($result['fail_reasons']));
for ($i = 0; $i < $displayCount; $i++) {
$errorDetails .= htmlspecialchars($result['fail_reasons'][$i]) . '<br>';
}
if (count($result['fail_reasons']) > 10) {
$errorDetails .= '...还有 ' . (count($result['fail_reasons']) - 10) . ' 条失败记录';
}
$errorMsg = $errorDetails;
}
}
} else {
$errorMsg = '导入失败!未找到可导入的记录或格式不正确';
if (!empty($result['fail_reasons'])) {
$errorMsg .= '<br><strong>失败原因:</strong><br>';
$displayCount = min(10, count($result['fail_reasons']));
for ($i = 0; $i < $displayCount; $i++) {
$errorMsg .= htmlspecialchars($result['fail_reasons'][$i]) . '<br>';
}
}
}
}
}
// 获取记录
$histories = $action->getHistories($page, $perPage);
$total = $action->getTotalCount();
$totalPages = ceil($total / $perPage);
?>
<?php include 'header.php'; ?>
<?php include 'menu.php'; ?>
<style>
/* 基础重置 */
* {
box-sizing: border-box;
}
/* 浮动消息提示 */
.floating-message {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
max-width: 350px;
opacity: 0;
transform: translateY(-20px);
transition: opacity 0.3s, transform 0.3s;
padding: 14px 20px;
border-radius: 6px;
border: 1px solid transparent;
font-size: 14px;
}
.floating-message.show {
opacity: 1;
transform: translateY(0);
}
.floating-message.success {
color: #0f5132;
background-color: #d1e7dd;
border-color: #badbcc;
}
.floating-message.error {
color: #842029;
background-color: #f8d7da;
border-color: #f5c2c7;
}
/* 表格样式 */
.data-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
margin: 0px 0;
font-size: 14px;
background-color: #fff;
border-radius: 6px;
overflow: hidden;
table-layout: fixed;
}
.data-table th,
.data-table td {
padding: 14px 12px;
border-bottom: 1px solid #f0f0f0;
text-align: left;
vertical-align: middle;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.data-table th {
background-color: #fafbfc;
font-weight: 600;
color: #333;
border-bottom: 2px solid #e0e0e0;
font-size: 14px;
}
.data-table tbody tr:hover {
background-color: #f8f9fa;
}
.data-table tbody tr:last-child td {
border-bottom: none;
}
/* 复选框列 */
.data-table th:first-child,
.data-table td:first-child {
text-align: center;
width: 50px;
min-width: 50px;
max-width: 50px;
padding: 14px 8px;
}
.data-table th:first-child input[type="checkbox"],
.data-table td:first-child input[type="checkbox"] {
margin: 0;
vertical-align: middle;
width: 16px;
height: 16px;
cursor: pointer;
}
/* ID列样式 - 固定宽度 */
.data-table th:nth-child(2),
.data-table td:nth-child(2) {
text-align: center;
width: 70px;
min-width: 70px;
max-width: 70px;
font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
font-size: 13px;
color: #666;
white-space: nowrap;
}
/* 内容列 - 最大宽度,不换行 */
.data-table th:nth-child(3),
.data-table td:nth-child(3) {
width: auto;
min-width: 250px;
max-width: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 事件时间列 - 固定宽度,不换行 */
.data-table th:nth-child(4),
.data-table td:nth-child(4) {
text-align: center;
width: 110px;
min-width: 110px;
max-width: 110px;
font-size: 13px;
white-space: nowrap;
}
/* 发布时间列 - 固定宽度,不换行 - 修复:改为黑色 */
.data-table th:nth-child(5),
.data-table td:nth-child(5) {
text-align: center;
width: 110px;
min-width: 110px;
max-width: 110px;
font-size: 13px;
white-space: nowrap;
color: #000; /* 改为黑色 */
}
/* 文章关联列 - 固定宽度 */
.data-table th:nth-child(6),
.data-table td:nth-child(6) {
text-align: left; /* 改为左对齐以便显示多个CID */
width: 180px; /* 增加宽度以便显示多个CID */
min-width: 180px;
max-width: 180px;
font-size: 13px;
white-space: normal; /* 允许多行显示 */
overflow: visible; /* 允许内容溢出 */
}
/* 操作列样式 */
.data-table th:last-child,
.data-table td:last-child {
text-align: center;
width: 80px;
min-width: 80px;
max-width: 80px;
padding: 14px 8px;
white-space: nowrap;
}
/* 日期样式 */
.date-badge {
display: inline-block;
background-color: #f0f7ff;
color: #0066cc;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
}
/* 发布时间样式 - 修复:改为普通黑色文字 */
.publish-time {
color: #000;
font-size: 13px;
}
/* CID徽章样式 */
.cid-badge {
display: inline-block;
background-color: #e8f5e8;
color: #2e7d32;
padding: 3px 8px;
margin: 2px;
border-radius: 3px;
font-size: 11px;
font-weight: 500;
font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
white-space: nowrap;
border: 1px solid #c8e6c9;
line-height: 1;
}
.cid-container {
display: flex;
flex-wrap: wrap; /* 允许多行显示 */
gap: 3px;
max-height: 60px;
overflow-y: auto;
}
.no-cid {
color: #999;
font-size: 12px;
font-style: italic;
}
/* 批量操作区域 */
.bulk-actions-header, .bulk-actions-footer {
padding: 15px;
background-color: #f8f9fa;
border: 1px solid #e0e0e0;
display: flex;
justify-content: space-between;
align-items: center;
}
.bulk-actions-footer {
border-top: none;
border-bottom: 2px solid #e0e0e0;
}
/* 模态框样式 */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-content {
background-color: #fff;
margin: 8% auto;
padding: 0;
border-radius: 8px;
width: 85%;
max-width: 500px;
box-shadow: 0 5px 25px rgba(0,0,0,0.15);
position: relative;
}
.close {
position: absolute;
right: 20px;
top: 18px;
font-size: 22px;
cursor: pointer;
color: #999;
background: none;
border: none;
padding: 0;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
.close:hover {
color: #333;
background-color: #f5f5f5;
}
.modal-header {
margin: 0;
padding: 20px 25px;
border-bottom: 1px solid #e0e0e0;
background-color: #fafbfc;
border-radius: 8px 8px 0 0;
}
.modal-header h3 {
margin: 0;
color: #333;
font-size: 16px;
font-weight: 600;
}
.modal-content form {
padding: 25px;
}
/* 分页样式 */
.pagination {
margin-top: 25px;
margin-bottom:25px;
text-align: center;
}
.pagination ul {
list-style: none;
padding: 0;
margin: 0;
display: inline-flex;
gap: 4px;
}
.pagination li {
display: inline;
}
.pagination a, .pagination span {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 12px;
background-color: #fff;
color: #495057;
text-decoration: none;
border-radius: 4px;
border: 1px solid #dee2e6;
min-width: 36px;
height: 36px;
font-size: 13px;
}
.pagination a:hover {
background-color: #f8f9fa;
border-color: #dee2e6;
}
.pagination .active a, .pagination .active span {
background-color: #007bff;
color: white;
border-color: #007bff;
}
/* 消息提示 */
.message {
padding: 14px 20px;
margin: 18px 0;
border-radius: 6px;
border: 1px solid transparent;
font-size: 14px;
}
.message.success {
color: #0f5132;
background-color: #d1e7dd;
border-color: #badbcc;
}
.message.error {
color: #842029;
background-color: #f8d7da;
border-color: #f5c2c7;
}
/* 表单样式 */
.form-section {
background: #fff;
padding: 25px;
margin-bottom: 22px;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
.form-section h2 {
margin-top: 0;
margin-bottom: 22px;
padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
color: #333;
font-size: 18px;
font-weight: 600;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #555;
font-size: 14px;
}
.form-control {
width: 100%;
padding: 10px 14px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
color: #333;
background-color: #fff;
}
.form-control:focus {
outline: none;
border-color: #80bdff;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.15);
}
textarea.form-control {
resize: vertical;
min-height: 100px;
}
.description {
font-size: 12px;
color: #6c757d;
margin-top: 6px;
}
/* 文章关联输入框样式 */
.post-cids-input-wrapper {
position: relative;
}
.post-cids-input {
width: 100%;
padding: 10px 12px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
color: #333;
background-color: #fff;
}
.post-cids-input:focus {
outline: none;
border-color: #80bdff;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.15);
}
.post-cids-display {
margin-top: 8px;
font-size: 12px;
color: #6c757d;
}
/* 按钮样式 */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 18px;
font-size: 14px;
font-weight: 500;
text-align: center;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
height: 40px;
min-width: 80px;
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0069d9;
border-color: #0062cc;
}
.btn-secondary {
color: #fff;
background-color: #6c757d;
border-color: #6c757d;
}
.btn-secondary:hover {
background-color: #5a6268;
border-color: #545b62;
}
.btn-danger {
color: #fff;
background-color: #dc3545;
border-color: #dc3545;
}
.btn-danger:hover {
background-color: #c82333;
border-color: #bd2130;
}
.btn-success {
color: #fff;
background-color: #28a745;
border-color: #28a745;
}
.btn-success:hover {
background-color: #218838;
border-color: #1e7e34;
}
.btn-info {
color: #fff;
background-color: #17a2b8;
border-color: #17a2b8;
}
.btn-info:hover {
background-color: #138496;
border-color: #117a8b;
}
.btn-sm {
padding: 6px 12px;
font-size: 12px;
height: 32px;
min-width: 60px;
}
.btn-group {
display: flex;
gap: 10px;
}
/* 主容器样式 */
.main {
padding: 25px 0;
min-height: calc(100vh - 60px);
}
.body.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.typecho-page-title {
margin-bottom: 25px;
padding-bottom: 18px;
border-bottom: 1px solid #e0e0e0;
}
.typecho-page-title h1 {
margin: 0;
color: #333;
font-size: 24px;
font-weight: 600;
}
/* 全宽布局 */
.typecho-page-main {
display: block;
width: 100%;
}
.table-section {
background: #fff;
padding: 0;
border-radius: 8px;
border: 1px solid #e0e0e0;
margin-bottom: 22px;
overflow: hidden;
}
.table-section h2 {
margin: 0;
padding: 20px 25px;
border-bottom: 1px solid #f0f0f0;
color: #333;
font-size: 18px;
font-weight: 600;
}
/* 统计信息盒子 */
.stats-box {
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
padding: 22px;
border-radius: 8px;
margin-bottom: 22px;
border: 1px solid #dee2e6;
}
.stats-box h3 {
margin-top: 0;
margin-bottom: 18px;
color: #495057;
font-size: 16px;
font-weight: 600;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.stat-item {
background: white;
padding: 18px;
border-radius: 6px;
border-left: 4px solid #007bff;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.stat-item .label {
font-size: 12px;
color: #6c757d;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 500;
}
.stat-item .value {
font-size: 20px;
font-weight: 600;
color: #343a40;
}
/* 导入导出样式 */
.import-export-section {
margin-bottom: 22px;
border-radius: 8px;
}
.import-export-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
margin-bottom: 22px;
}
.import-box, .export-box {
background: #f8f9fa;
padding: 22px;
border-radius: 6px;
border: 1px solid #dee2e6;
}
.import-box h4, .export-box h4 {
margin-top: 0;
margin-bottom: 16px;
color: #495057;
font-size: 15px;
font-weight: 600;
}
.format-example {
background: #fff;
padding: 16px;
border-radius: 6px;
border-left: 3px solid #007bff;
margin-top: 18px;
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
font-size: 13px;
}
.format-example pre {
margin: 0;
white-space: pre-wrap;
font-size: 12px;
}
.format-example code {
color: #e83e8c;
font-family: inherit;
font-size: 12px;
}
.format-example strong {
color: #333;
font-weight: 600;
margin-bottom: 8px;
display: block;
}
/* 锚点定位样式 */
.anchor-target {
scroll-margin-top: 20px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.body.container {
padding: 0 15px;
}
.import-export-grid {
grid-template-columns: 1fr;
}
.bulk-actions-header, .bulk-actions-footer {
flex-direction: column;
gap: 10px;
}
.floating-message {
left: 20px;
right: 20px;
max-width: none;
}
/* 响应式调整关联文章列 */
.data-table th:nth-child(6),
.data-table td:nth-child(6) {
width: 140px;
min-width: 140px;
max-width: 140px;
}
}
</style>
<div class="main">
<div class="body container">
<!-- 浮动消息提示 -->
<?php if (isset($successMsg)): ?>
<div id="floatingMessage" class="floating-message success show">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div style="flex-grow: 1;">
<strong> 成功</strong>
<div style="margin-top: 5px;"><?php echo $successMsg; ?></div>
</div>
<button type="button" onclick="hideMessage()" style="background: none; border: none; color: inherit; font-size: 18px; cursor: pointer; margin-left: 10px; padding: 0 5px;">&times;</button>
</div>
</div>
<?php endif; ?>
<?php if (isset($errorMsg)): ?>
<div id="floatingMessage" class="floating-message error show">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div style="flex-grow: 1;">
<strong> 错误</strong>
<div style="margin-top: 5px;"><?php echo $errorMsg; ?></div>
</div>
<button type="button" onclick="hideMessage()" style="background: none; border: none; color: inherit; font-size: 18px; cursor: pointer; margin-left: 10px; padding: 0 5px;">&times;</button>
</div>
</div>
<?php endif; ?>
<div class="typecho-page-main" role="main">
<!-- 统计信息 -->
<div class="stats-box">
<div class="stats-grid">
<div class="stat-item">
<div class="label">总记录数</div>
<div class="value"><?php echo $total; ?> 条</div>
</div>
<div class="stat-item">
<div class="label">当前页数</div>
<div class="value"><?php echo $page; ?> / <?php echo $totalPages; ?></div>
</div>
<div class="stat-item">
<div class="label">每页显示</div>
<div class="value"><?php echo $perPage; ?> 条</div>
</div>
</div>
</div>
<!-- 导入导出功能 -->
<div class="import-export-section">
<div class="import-export-grid">
<!-- 导出功能 -->
<div class="export-box">
<h4>导出数据</h4>
<p style="margin-bottom: 15px;color:#000;">导出所有历史记录为文本文件格式</p>
<form method="post" action="">
<input type="hidden" name="action" value="development-history">
<button type="submit" name="export" class="btn btn-success">
导出为 TXT 文件
</button>
</form>
<div class="format-example">
<strong>导出格式示例:</strong>
<pre>2025.12.21 网站正式上线
2025.12.25 新增用户注册功能
2025.12.28 优化了网站性能</pre>
</div>
</div>
<!-- 导入功能 -->
<div class="import-box">
<h4>导入数据</h4>
<p style="margin-bottom: 15px;color:#000;">从文本文件导入历史记录</p>
<form method="post" action="" enctype="multipart/form-data">
<input type="hidden" name="action" value="development-history">
<div class="form-group" style="margin-bottom: 15px;">
<label for="import_file">选择文件</label>
<input type="file" id="import_file" name="import_file" class="form-control" required accept=".txt,.text">
<p class="description">支持 .txt 文本文件格式</p>
</div>
<button type="submit" name="import" class="btn btn-info">
导入 TXT 文件
</button>
</form>
<div class="format-example">
<strong>导入格式要求:</strong>
<pre>每行一条记录,格式为:<code>日期 内容</code>
日期格式YYYY.M[M].D[D](支持单数字月份和日期)
例如:<code>2023.12.9 网站更新</code>
例如:<code>2023.8.8 新功能上线</code></pre>
<p style="margin-top: 10px; font-size: 12px; color: #666;">
提示:请确保文件编码为 UTF-8,每行一条记录
</p>
</div>
</div>
</div>
</div>
<!-- 发布表单 -->
<div class="form-section">
<h2>发布新历史</h2>
<!-- 修复表单action设为空字符串提交到当前页面 -->
<form method="post" action="" id="publishForm">
<div class="form-group">
<label for="content">内容 *</label>
<textarea id="content" name="content" class="form-control" rows="4" required
placeholder="请输入详细网站发展历史内容"></textarea>
</div>
<div class="form-group">
<label for="event_date">日期 *</label>
<div class="btn-group">
<input type="date" id="event_date" name="event_date" class="form-control"
value="<?php echo date('Y-m-d'); ?>" required>
<button type="button" class="btn btn-secondary" onclick="document.getElementById('event_date').value = '<?php echo date('Y-m-d'); ?>'">
今天
</button>
</div>
</div>
<div class="form-group">
<label for="post_cids">关联文章CID可选</label>
<div class="post-cids-input-wrapper">
<input type="text" id="post_cids" name="post_cids" class="form-control post-cids-input"
placeholder="输入文章CID多个用逗号分隔123,456">
</div>
<p class="description post-cids-display">
可关联多个文章输入文章CID用逗号分隔
</p>
</div>
<div style="text-align: center;">
<button type="reset" class="btn btn-secondary" style="margin-right: 10px;">重置</button>
<button type="submit" class="btn btn-primary" id="publishBtn">发布</button>
</div>
</form>
</div>
<!-- 锚点目标,用于滚动定位 -->
<div id="history-list-anchor" class="anchor-target"></div>
<!-- 历史记录列表 -->
<div class="table-section">
<h2>历史记录列表</h2>
<?php if (empty($histories)): ?>
<div class="message info" style="text-align: center; padding: 30px;">
暂无历史记录,请先添加记录
</div>
<?php else: ?>
<form method="post" action="" id="mainForm">
<!-- 表头多选操作栏 -->
<div class="bulk-actions-header">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; align-items: center;">
<input type="checkbox" id="header-select-all" style="margin: 0; width: 16px; height: 16px;">
<label for="header-select-all" style="color:#000;margin-left: 8px; font-weight: 500; font-size: 14px;">
全选本页
</label>
</div>
<div class="selected-info">
<span class="description">
已选择 <strong id="selected-count-text">0</strong> 条记录
</span>
</div>
</div>
<div>
<button type="button" id="header-delete-btn" class="btn btn-danger btn-sm">
删除选中
</button>
</div>
</div>
<table class="data-table">
<thead>
<tr>
<th>
<input type="checkbox" id="thead-select-all" title="全选/全不选">
</th>
<th>ID</th>
<th>内容</th>
<th>历史时间</th>
<th>发布时间</th>
<th>文章关联</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($histories as $history):
$cids = !empty($history['post_cids']) ? explode(',', $history['post_cids']) : array();
?>
<tr>
<td>
<input type="checkbox" name="delete_ids[]" value="<?php echo $history['id']; ?>" class="row-checkbox">
</td>
<td>
<span class="history-id">#<?php echo $history['id']; ?></span>
</td>
<td title="<?php echo htmlspecialchars($history['content']); ?>">
<div style="font-size: 13px; color: #333; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<?php echo htmlspecialchars($history['content']); ?>
</div>
</td>
<td>
<span class="date-badge">
<?php echo date('Y-m-d', strtotime($history['event_date'])); ?>
</span>
</td>
<td>
<!-- 修复:发布时间改为黑色普通文字 -->
<span class="publish-time">
<?php echo date('Y-m-d', strtotime($history['created'])); ?>
</span>
</td>
<td>
<?php if (!empty($cids)): ?>
<div class="cid-container">
<?php foreach ($cids as $cid):
$cid = trim($cid);
if (!empty($cid)): ?>
<span class="cid-badge" title="文章CID: <?php echo $cid; ?>">
<?php echo $cid; ?>
</span>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php else: ?>
<span class="no-cid">-</span>
<?php endif; ?>
</td>
<td>
<button type="button" class="btn btn-sm btn-primary edit-btn"
data-history='<?php echo htmlspecialchars(json_encode($history), ENT_QUOTES, 'UTF-8'); ?>'
style="padding: 4px 10px; font-size: 12px;">
编辑
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- 表尾多选操作栏 -->
<div class="bulk-actions-footer">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="display: flex; align-items: center;">
<input type="checkbox" id="footer-select-all" style="margin: 0; width: 16px; height: 16px;">
<label for="footer-select-all" style="color:#000;margin-left: 8px; font-weight: 500; font-size: 14px;">
全选本页
</label>
</div>
<div class="selected-info">
<span class="description">
已选择 <strong id="footer-selected-count">0</strong> 条记录
</span>
</div>
</div>
<div>
<button type="button" id="footer-delete-btn" class="btn btn-danger btn-sm">
删除选中
</button>
</div>
</div>
<!-- 隐藏的提交按钮 -->
<input type="submit" id="hidden-submit" style="display: none;">
</form>
<!-- 分页 -->
<?php if ($totalPages > 1): ?>
<div class="pagination">
<ul>
<?php if ($page > 1): ?>
<li><a href="?panel=DevelopmentHistory/manage-panel.php&page=<?php echo $page-1; ?>#history-list-anchor">&laquo; 上一页</a></li>
<?php endif; ?>
<?php
$start = max(1, $page - 2);
$end = min($totalPages, $page + 2);
if ($start > 1) {
echo '<li><a href="?panel=DevelopmentHistory/manage-panel.php&page=1#history-list-anchor">1</a></li>';
if ($start > 2) echo '<li><span>...</span></li>';
}
for ($i = $start; $i <= $end; $i++): ?>
<li <?php if ($i == $page) echo 'class="active"'; ?>>
<a href="?panel=DevelopmentHistory/manage-panel.php&page=<?php echo $i; ?>#history-list-anchor"><?php echo $i; ?></a>
</li>
<?php endfor; ?>
<?php if ($end < $totalPages): ?>
<?php if ($end < $totalPages - 1): ?>
<li><span>...</span></li>
<?php endif; ?>
<li><a href="?panel=DevelopmentHistory/manage-panel.php&page=<?php echo $totalPages; ?>#history-list-anchor"><?php echo $totalPages; ?></a></li>
<?php endif; ?>
<?php if ($page < $totalPages): ?>
<li><a href="?panel=DevelopmentHistory/manage-panel.php&page=<?php echo $page+1; ?>#history-list-anchor">下一页 &raquo;</a></li>
<?php endif; ?>
</ul>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
<!-- 编辑模态框 -->
<div id="editModal" class="modal" style="display:none;">
<div class="modal-content">
<button type="button" class="close" onclick="closeModal()">&times;</button>
<div class="modal-header">
<h3>编辑历史记录</h3>
</div>
<form id="editForm" method="post" action="">
<div class="form-group">
<label for="edit_content">内容 *</label>
<textarea id="edit_content" name="edit_content" class="form-control" rows="5" required></textarea>
</div>
<div class="form-group">
<label for="edit_event_date">日期 *</label>
<input type="date" id="edit_event_date" name="edit_event_date" class="form-control" required>
</div>
<div class="form-group">
<label for="edit_post_cids">关联文章CID可选</label>
<div class="post-cids-input-wrapper">
<input type="text" id="edit_post_cids" name="edit_post_cids" class="form-control post-cids-input"
placeholder="输入文章CID多个用逗号分隔123,456">
</div>
<p class="description post-cids-display">
可关联多个文章输入文章CID用逗号分隔
</p>
</div>
<input type="hidden" name="edit_id" id="edit_id">
<div style="text-align:right;margin-top:20px; padding-top: 15px; border-top: 1px solid #eee;">
<button type="button" class="btn btn-secondary" onclick="closeModal()" style="margin-right:10px;">
取消
</button>
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</form>
</div>
</div>
<script>
// 页面加载后自动滚动到锚点
document.addEventListener('DOMContentLoaded', function() {
if (window.location.hash === '#history-list-anchor') {
setTimeout(function() {
var anchor = document.getElementById('history-list-anchor');
if (anchor) {
anchor.scrollIntoView({ behavior: 'smooth' });
}
}, 100);
}
// 自动隐藏浮动消息
var floatingMessage = document.getElementById('floatingMessage');
if (floatingMessage) {
setTimeout(function() {
hideMessage();
}, 5000);
}
});
// 隐藏浮动消息
function hideMessage() {
var message = document.getElementById('floatingMessage');
if (message) {
message.classList.remove('show');
setTimeout(function() {
if (message.parentNode) {
message.parentNode.removeChild(message);
}
}, 300);
}
}
// 更新选中数量函数
function updateSelectedCount() {
var checkboxes = document.querySelectorAll('.row-checkbox:checked');
var count = checkboxes.length;
document.getElementById('selected-count-text').textContent = count;
document.getElementById('footer-selected-count').textContent = count;
var headerBtn = document.getElementById('header-delete-btn');
var footerBtn = document.getElementById('footer-delete-btn');
if (count > 0) {
headerBtn.textContent = '删除选中(' + count + ')';
footerBtn.textContent = '删除选中(' + count + ')';
} else {
headerBtn.textContent = '删除选中';
footerBtn.textContent = '删除选中';
}
var allCheckboxes = document.querySelectorAll('.row-checkbox');
var headerCheckboxes = document.querySelectorAll('#header-select-all, #thead-select-all, #footer-select-all');
if (allCheckboxes.length > 0) {
var allChecked = count === allCheckboxes.length;
var someChecked = count > 0 && count < allCheckboxes.length;
headerCheckboxes.forEach(function(checkbox) {
checkbox.checked = allChecked;
checkbox.indeterminate = someChecked;
});
}
return count;
}
// 全选/全不选功能
function setupSelectAll(selector, targetSelector) {
var selectAll = document.querySelector(selector);
if (selectAll) {
selectAll.addEventListener('change', function(e) {
var checkboxes = document.querySelectorAll(targetSelector);
checkboxes.forEach(function(checkbox) {
checkbox.checked = e.target.checked;
});
updateSelectedCount();
});
}
}
// 为行复选框添加事件监听
function setupRowCheckboxes() {
var checkboxes = document.querySelectorAll('.row-checkbox');
checkboxes.forEach(function(checkbox) {
checkbox.addEventListener('change', updateSelectedCount);
});
}
// 统一的删除确认函数
function confirmDelete() {
var checkboxes = document.querySelectorAll('.row-checkbox:checked');
var count = checkboxes.length;
if (count === 0) {
alert('请先选择要删除的记录!');
return false;
}
var confirmMsg = '确定要删除选中的 ' + count + ' 条记录吗?此操作不可恢复!';
if (!confirm(confirmMsg)) {
return false;
}
document.getElementById('hidden-submit').click();
return true;
}
// 初始化选择功能
document.addEventListener('DOMContentLoaded', function() {
setupSelectAll('#header-select-all', '.row-checkbox');
setupSelectAll('#thead-select-all', '.row-checkbox');
setupSelectAll('#footer-select-all', '.row-checkbox');
setupRowCheckboxes();
var headerDeleteBtn = document.getElementById('header-delete-btn');
var footerDeleteBtn = document.getElementById('footer-delete-btn');
if (headerDeleteBtn) {
headerDeleteBtn.addEventListener('click', function(e) {
e.preventDefault();
confirmDelete();
});
}
if (footerDeleteBtn) {
footerDeleteBtn.addEventListener('click', function(e) {
e.preventDefault();
confirmDelete();
});
}
updateSelectedCount();
});
// 编辑历史记录
document.addEventListener('DOMContentLoaded', function() {
var editButtons = document.querySelectorAll('.edit-btn');
editButtons.forEach(function(button) {
button.addEventListener('click', function() {
try {
var historyData = JSON.parse(this.getAttribute('data-history'));
editHistory(historyData);
} catch (e) {
console.error('解析历史记录数据失败:', e);
alert('编辑失败:数据格式错误');
}
});
});
});
function editHistory(history) {
document.getElementById('edit_id').value = history.id;
document.getElementById('edit_content').value = history.content;
var eventDate = new Date(history.event_date);
var year = eventDate.getFullYear();
var month = (eventDate.getMonth() + 1).toString().padStart(2, '0');
var day = eventDate.getDate().toString().padStart(2, '0');
document.getElementById('edit_event_date').value = year + '-' + month + '-' + day;
document.getElementById('edit_post_cids').value = history.post_cids || '';
document.getElementById('editModal').style.display = 'block';
}
// 关闭模态框
function closeModal() {
document.getElementById('editModal').style.display = 'none';
}
// 点击模态框外部关闭
window.onclick = function(event) {
var modal = document.getElementById('editModal');
if (event.target == modal) {
closeModal();
}
}
// 表单验证
document.querySelectorAll('form').forEach(function(form) {
if (form.querySelector('button[name="export"]')) return;
form.addEventListener('submit', function(e) {
var requiredFields = form.querySelectorAll('[required]');
var valid = true;
requiredFields.forEach(function(field) {
if (!field.value.trim()) {
valid = false;
field.style.borderColor = '#dc3545';
field.style.boxShadow = '0 0 0 0.2rem rgba(220,53,69,.25)';
} else {
field.style.borderColor = '#ced4da';
field.style.boxShadow = 'none';
}
});
if (!valid) {
e.preventDefault();
alert('请填写所有必填字段!');
}
});
});
// 导入文件验证
var importForm = document.querySelector('form[enctype="multipart/form-data"]');
if (importForm) {
importForm.addEventListener('submit', function(e) {
var fileInput = document.getElementById('import_file');
if (fileInput.files.length === 0) {
e.preventDefault();
alert('请选择要导入的文件!');
return;
}
var file = fileInput.files[0];
if (file.size > 5 * 1024 * 1024) {
e.preventDefault();
alert('文件大小不能超过5MB');
return;
}
if (!file.name.toLowerCase().endsWith('.txt')) {
if (!confirm('文件不是.txt格式确定要导入吗')) {
e.preventDefault();
}
}
});
}
</script>
<?php include 'footer.php'; ?>