From 4740c7123680053df6b6fc667ccd8ebc21cbb8ec Mon Sep 17 00:00:00 2001
From: XIGE <710062962@qq.com>
Date: Mon, 23 Feb 2026 17:23:48 +0800
Subject: [PATCH] 1.0
---
Action.php | 386 +++++++++++++
Plugin.php | 1371 ++++++++++++++++++++++++++++++++++++++++++++
assets/style.css | 109 ++++
manage-panel.php | 1426 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 3292 insertions(+)
create mode 100644 Action.php
create mode 100644 Plugin.php
create mode 100644 assets/style.css
create mode 100644 manage-panel.php
diff --git a/Action.php b/Action.php
new file mode 100644
index 0000000..8614f38
--- /dev/null
+++ b/Action.php
@@ -0,0 +1,386 @@
+db = Typecho_Db::get();
+ $this->prefix = $this->db->getPrefix();
+ $this->request = $request ?: Typecho_Request::getInstance();
+ $this->response = $response ?: Typecho_Response::getInstance();
+ }
+
+ /**
+ * 添加历史记录 - 修复:使用Typecho正确的SQL构建方法
+ */
+ public function addHistory($data)
+ {
+ try {
+ $now = new Typecho_Date(Typecho_Date::gmtTime());
+
+ $insert = array(
+ 'content' => $data['content'],
+ 'event_date' => $data['event_date'],
+ 'post_cids' => isset($data['post_cids']) ? $this->cleanCids($data['post_cids']) : '',
+ 'created' => $now->format('Y-m-d H:i:s'),
+ 'modified' => $now->format('Y-m-d H:i:s'),
+ 'status' => 1
+ );
+
+ // 使用Typecho的查询构建器,但先验证数据
+ $this->validateInsertData($insert);
+
+ // 修复:正确构建并执行插入查询
+ // 在Typecho中,insert()->rows()需要调用query()方法来执行
+ $query = $this->db->insert($this->prefix . 'development_history')->rows($insert);
+
+ // 执行查询
+ $this->db->query($query);
+
+ // 获取最后插入的ID - Typecho的方式
+ $row = $this->db->fetchRow($this->db->select('LAST_INSERT_ID() as id'));
+ return $row ? $row['id'] : 0;
+
+ } catch (Exception $e) {
+ error_log("addHistory Error: " . $e->getMessage());
+ error_log("Data: " . print_r($data, true));
+ throw new Exception("发布失败: " . $e->getMessage());
+ }
+ }
+
+ /**
+ * 验证插入数据
+ */
+ private function validateInsertData(&$data)
+ {
+ // 确保所有必需字段都有值
+ if (empty($data['content'])) {
+ throw new Exception("内容不能为空");
+ }
+
+ if (empty($data['event_date'])) {
+ throw new Exception("日期不能为空");
+ }
+
+ // 验证日期格式
+ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $data['event_date'])) {
+ throw new Exception("日期格式错误,应为YYYY-MM-DD");
+ }
+
+ // 清理和转义内容
+ $data['content'] = trim($data['content']);
+ if (empty($data['content'])) {
+ throw new Exception("内容不能为空");
+ }
+
+ // 确保所有字段都是字符串
+ foreach ($data as $key => $value) {
+ if (!is_string($value) && !is_numeric($value)) {
+ $data[$key] = (string)$value;
+ }
+ }
+ }
+
+ /**
+ * 批量添加历史记录(按事件时间排序插入,越近的ID越大)
+ */
+ public function batchAddHistories($histories)
+ {
+ // 按事件时间排序,越近的时间越晚插入,这样ID越大
+ usort($histories, function($a, $b) {
+ return strtotime($a['event_date']) - strtotime($b['event_date']);
+ });
+
+ $now = new Typecho_Date(Typecho_Date::gmtTime());
+ $nowStr = $now->format('Y-m-d H:i:s');
+
+ foreach ($histories as $history) {
+ $insert = array(
+ 'content' => $history['content'],
+ 'event_date' => $history['event_date'],
+ 'post_cids' => '',
+ 'created' => $nowStr,
+ 'modified' => $nowStr,
+ 'status' => 1
+ );
+
+ $query = $this->db->insert($this->prefix . 'development_history')->rows($insert);
+ $this->db->query($query);
+ }
+ }
+
+ /**
+ * 更新历史记录
+ */
+ public function updateHistory($data)
+ {
+ try {
+ $now = new Typecho_Date(Typecho_Date::gmtTime());
+
+ $update = array(
+ 'content' => $data['edit_content'],
+ 'event_date' => $data['edit_event_date'],
+ 'post_cids' => isset($data['edit_post_cids']) ? $this->cleanCids($data['edit_post_cids']) : '',
+ 'modified' => $now->format('Y-m-d H:i:s')
+ );
+
+ $query = $this->db->update($this->prefix . 'development_history')
+ ->rows($update)
+ ->where('id = ?', intval($data['edit_id']));
+
+ $this->db->query($query);
+
+ } catch (Exception $e) {
+ error_log("updateHistory Error: " . $e->getMessage());
+ throw new Exception("更新失败: " . $e->getMessage());
+ }
+ }
+
+ /**
+ * 删除历史记录
+ */
+ public function deleteHistory($id)
+ {
+ $query = $this->db->delete($this->prefix . 'development_history')->where('id = ?', intval($id));
+ $this->db->query($query);
+ }
+
+ /**
+ * 批量删除
+ */
+ public function deleteHistories($ids)
+ {
+ foreach ($ids as $id) {
+ $this->deleteHistory(intval($id));
+ }
+ }
+
+ /**
+ * 获取历史记录
+ */
+ public function getHistories($page = 1, $perPage = 10)
+ {
+ $offset = ($page - 1) * $perPage;
+
+ $query = $this->db->select()
+ ->from($this->prefix . 'development_history')
+ ->where('status = ?', 1)
+ ->order('id', Typecho_Db::SORT_DESC)
+ ->limit($perPage)
+ ->offset($offset);
+
+ return $this->db->fetchAll($query);
+ }
+
+ /**
+ * 获取所有历史记录(用于导出)
+ */
+ public function getAllHistories()
+ {
+ $query = $this->db->select()
+ ->from($this->prefix . 'development_history')
+ ->where('status = ?', 1)
+ ->order('id', Typecho_Db::SORT_DESC);
+
+ return $this->db->fetchAll($query);
+ }
+
+ /**
+ * 获取总记录数
+ */
+ public function getTotalCount()
+ {
+ $query = $this->db->select('COUNT(*) as count')
+ ->from($this->prefix . 'development_history')
+ ->where('status = ?', 1);
+
+ $result = $this->db->fetchRow($query);
+ return $result['count'];
+ }
+
+ /**
+ * 获取单条记录
+ */
+ public function getHistory($id)
+ {
+ $query = $this->db->select()
+ ->from($this->prefix . 'development_history')
+ ->where('id = ?', $id)
+ ->limit(1);
+
+ return $this->db->fetchRow($query);
+ }
+
+ /**
+ * 根据文章CID获取文章信息
+ */
+ public function getPostByCid($cid)
+ {
+ try {
+ $query = $this->db->select('cid, title, slug, created')
+ ->from($this->prefix . 'contents')
+ ->where('cid = ?', intval($cid))
+ ->where('type = ?', 'post')
+ ->where('status = ?', 'publish')
+ ->limit(1);
+
+ $post = $this->db->fetchRow($query);
+
+ if ($post) {
+ $options = Typecho_Widget::widget('Widget_Options');
+ if (!empty($post['slug'])) {
+ $post['url'] = Typecho_Common::url($post['slug'] . '.html', $options->index);
+ } else {
+ $post['url'] = Typecho_Common::url('archives/' . $post['cid'], $options->index);
+ }
+ }
+
+ return $post;
+ } catch (Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * 清理CID字符串
+ */
+ private function cleanCids($cids)
+ {
+ if (empty($cids)) {
+ return '';
+ }
+
+ $cidsArray = array_filter(array_map('trim', explode(',', $cids)));
+ $validCids = array();
+
+ foreach ($cidsArray as $cid) {
+ if (is_numeric($cid) && $cid > 0) {
+ $validCids[] = intval($cid);
+ }
+ }
+
+ // 去重并返回逗号分隔的字符串
+ return implode(',', array_unique($validCids));
+ }
+
+ /**
+ * 导出数据为文本格式
+ */
+ public function exportData()
+ {
+ $histories = $this->getAllHistories();
+ $content = '';
+
+ foreach ($histories as $history) {
+ // 使用 Y.m.d 格式导出
+ $date = date('Y.m.d', strtotime($history['event_date']));
+ $text = str_replace(array("\r\n", "\r", "\n"), " ", $history['content']);
+ $content .= $date . ' ' . $text . "\n";
+ }
+
+ return $content;
+ }
+
+ /**
+ * 导入数据(增强版,支持调试)
+ */
+ public function importData($text)
+ {
+ // 标准化换行符
+ $text = str_replace("\r\n", "\n", $text);
+ $text = str_replace("\r", "\n", $text);
+
+ $lines = explode("\n", $text);
+ $imported = 0;
+ $failed = 0;
+ $failReasons = array(); // 记录失败原因
+ $histories = array();
+
+ foreach ($lines as $lineNum => $line) {
+ $line = trim($line);
+ if (empty($line)) continue;
+
+ // 移除行尾的分号(如果有)
+ if (substr($line, -1) === ';') {
+ $line = substr($line, 0, -1);
+ $line = trim($line);
+ }
+
+ // 找到第一个空格的位置来分割日期和内容
+ $firstSpacePos = strpos($line, ' ');
+ if ($firstSpacePos === false) {
+ $failed++;
+ $failReasons[] = "第 " . ($lineNum + 1) . " 行:找不到空格分隔日期和内容 - '{$line}'";
+ continue;
+ }
+
+ $date = trim(substr($line, 0, $firstSpacePos));
+ $content = trim(substr($line, $firstSpacePos + 1));
+
+ // 验证日期格式 - 支持单个数字的月份和日期
+ // 允许的格式:YYYY.M.D, YYYY.MM.D, YYYY.M.DD, YYYY.MM.DD
+ $datePattern = '/^(\d{4})\.(\d{1,2})\.(\d{1,2})$/';
+ if (!preg_match($datePattern, $date, $matches)) {
+ $failed++;
+ $failReasons[] = "第 " . ($lineNum + 1) . " 行:日期格式错误,应为 YYYY.M[M].D[D] - '{$date}'";
+ continue;
+ }
+
+ // 检查日期是否有效
+ $year = intval($matches[1]);
+ $month = intval($matches[2]);
+ $day = intval($matches[3]);
+
+ if (!checkdate($month, $day, $year)) {
+ $failed++;
+ $failReasons[] = "第 " . ($lineNum + 1) . " 行:无效的日期 - {$date}";
+ continue;
+ }
+
+ // 转换日期格式为 Y-m-d 以便数据库存储,补零成两位数字
+ $dbDate = sprintf('%04d-%02d-%02d', $year, $month, $day);
+
+ // 验证内容
+ if (empty($content)) {
+ $failed++;
+ $failReasons[] = "第 " . ($lineNum + 1) . " 行:内容为空";
+ continue;
+ }
+
+ $histories[] = array(
+ 'event_date' => $dbDate,
+ 'content' => $content
+ );
+ $imported++;
+ }
+
+ if (!empty($histories)) {
+ $this->batchAddHistories($histories);
+ }
+
+ // 返回包含失败原因的结果
+ return array(
+ 'imported' => $imported,
+ 'failed' => $failed,
+ 'fail_reasons' => $failReasons
+ );
+ }
+}
\ No newline at end of file
diff --git a/Plugin.php b/Plugin.php
new file mode 100644
index 0000000..a51da9c
--- /dev/null
+++ b/Plugin.php
@@ -0,0 +1,1371 @@
+getPrefix();
+ $tableName = $prefix . 'development_history';
+
+ // 检查主表是否存在
+ $tables = $db->fetchAll($db->query("SHOW TABLES LIKE '{$tableName}'"));
+
+ if (empty($tables)) {
+ // 表不存在,创建新表(不带title字段)
+ $sql = "CREATE TABLE `{$tableName}` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ `content` TEXT NOT NULL COMMENT '内容',
+ `event_date` DATE NOT NULL COMMENT '事件日期',
+ `post_cids` VARCHAR(255) DEFAULT '' COMMENT '关联文章CID,多个用逗号分隔',
+ `created` DATETIME NOT NULL COMMENT '创建时间',
+ `modified` DATETIME NOT NULL COMMENT '修改时间',
+ `status` TINYINT(1) DEFAULT 1 COMMENT '状态:1正常'
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发展历史记录表';";
+
+ try {
+ $db->query($sql);
+ } catch (Typecho_Db_Exception $e) {
+ throw new Typecho_Plugin_Exception('创建数据表失败: ' . $e->getMessage());
+ }
+ } else {
+ // 表已存在,检查是否有title字段,如果有则删除
+ $columns = $db->fetchAll($db->query("SHOW COLUMNS FROM `{$tableName}`"));
+ $hasTitle = false;
+
+ foreach ($columns as $column) {
+ if ($column['Field'] == 'title') {
+ $hasTitle = true;
+ break;
+ }
+ }
+
+ if ($hasTitle) {
+ // 删除title字段
+ try {
+ $db->query("ALTER TABLE `{$tableName}` DROP COLUMN `title`");
+ } catch (Typecho_Db_Exception $e) {
+ // 如果删除字段失败,可能是表结构问题,继续执行
+ }
+ }
+
+ // 检查是否有post_cids字段,如果没有则添加
+ $hasPostCids = false;
+ foreach ($columns as $column) {
+ if ($column['Field'] == 'post_cids') {
+ $hasPostCids = true;
+ break;
+ }
+ }
+
+ if (!$hasPostCids) {
+ try {
+ $db->query("ALTER TABLE `{$tableName}` ADD `post_cids` VARCHAR(255) DEFAULT '' COMMENT '关联文章CID,多个用逗号分隔' AFTER `event_date`");
+ } catch (Typecho_Db_Exception $e) {
+ // 如果添加字段失败,继续执行
+ }
+ }
+ }
+
+ // 添加管理菜单
+ Helper::addPanel(3, 'DevelopmentHistory/manage-panel.php', '发展历史', '发展历史管理', 'administrator');
+
+ return _t('发展历史插件已激活,请到插件设置中进行配置');
+ }
+
+ /**
+ * 禁用插件
+ *
+ * @return string
+ */
+ public static function deactivate()
+ {
+ Helper::removePanel(3, 'DevelopmentHistory/manage-panel.php');
+ return _t('发展历史插件已禁用');
+ }
+
+ /**
+ * 插件配置面板
+ *
+ * @param Typecho_Widget_Helper_Form $form
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ echo '
发展历史插件配置
';
+ echo '版本:1.1.0 | 作者:您的名字 | 访问官网
';
+ echo '
';
+
+ // 每页显示数量
+ $perPage = new Typecho_Widget_Helper_Form_Element_Text(
+ 'perPage',
+ NULL,
+ '10',
+ _t('后台每页显示数量'),
+ _t('后台管理页面每页显示的历史记录数量,默认:10')
+ );
+ $perPage->input->setAttribute('class', 'mini');
+ $form->addInput($perPage->addRule('isInteger', _t('请输入整数')));
+
+ // 前端每页显示数量
+ $frontPerPage = new Typecho_Widget_Helper_Form_Element_Text(
+ 'frontPerPage',
+ NULL,
+ '20',
+ _t('主题调用每页显示数量'),
+ _t('在主题中调用时每页显示的历史记录数量,默认:20')
+ );
+ $frontPerPage->input->setAttribute('class', 'mini');
+ $form->addInput($frontPerPage->addRule('isInteger', _t('请输入整数')));
+
+ // 时间格式
+ $dateFormat = new Typecho_Widget_Helper_Form_Element_Text(
+ 'dateFormat',
+ NULL,
+ 'Y.m.d',
+ _t('日期显示格式'),
+ _t('PHP日期格式,如:Y.m.d、Y-m-d、Y年m月d日等')
+ );
+ $form->addInput($dateFormat);
+
+ // 是否显示关联文章
+ $showRelatedPosts = new Typecho_Widget_Helper_Form_Element_Radio(
+ 'showRelatedPosts',
+ array(
+ '1' => _t('显示'),
+ '0' => _t('不显示')
+ ),
+ '1',
+ _t('显示关联文章'),
+ _t('是否在历史记录下方显示关联的文章链接')
+ );
+ $form->addInput($showRelatedPosts);
+
+ // 关联文章标题
+ $relatedPostsTitle = new Typecho_Widget_Helper_Form_Element_Text(
+ 'relatedPostsTitle',
+ NULL,
+ '相关文章',
+ _t('关联文章标题'),
+ _t('关联文章部分的标题文本')
+ );
+ $form->addInput($relatedPostsTitle);
+ }
+
+ /**
+ * 个人用户配置
+ *
+ * @param Typecho_Widget_Helper_Form $form
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form)
+ {
+ // 个人配置(如果需要)
+ }
+
+ /**
+ * 插件配置面板
+ *
+ * @param string $panel
+ */
+ public static function configPanel($panel)
+ {
+ // 配置面板
+ }
+
+ /**
+ * 渲染方法(用于在主题模板中调用)
+ */
+ public static function render()
+ {
+ // 获取配置
+ $options = Typecho_Widget::widget('Widget_Options');
+ $config = $options->plugin('DevelopmentHistory');
+
+ // 数据库操作
+ $db = Typecho_Db::get();
+ $prefix = $db->getPrefix();
+
+ // 获取当前页面文件名
+ $currentFile = basename($_SERVER['PHP_SELF']);
+
+ // 统一使用 'y' 参数
+ $selectedYear = 0;
+ $currentPage = 1;
+ $searchKeyword = '';
+
+ // 读取 'y' 参数
+ if (isset($_GET['y']) && is_numeric($_GET['y'])) {
+ $selectedYear = intval($_GET['y']);
+ }
+
+ // 保持向后兼容:如果旧链接使用了 'year' 参数,也支持
+ if ($selectedYear == 0 && isset($_GET['year']) && is_numeric($_GET['year'])) {
+ $selectedYear = intval($_GET['year']);
+ }
+
+ if (isset($_GET['page']) && is_numeric($_GET['page']) && $_GET['page'] > 0) {
+ $currentPage = intval($_GET['page']);
+ }
+
+ // 读取搜索关键词参数 - 正确处理URL编码
+ if (isset($_GET['search']) && !empty($_GET['search'])) {
+ $searchKeyword = trim($_GET['search']);
+ // 解码URL编码的参数
+ $searchKeyword = urldecode($searchKeyword);
+ }
+
+ // URL构建函数 - 正确处理编码
+ function buildUrl($year = 0, $page = 1, $search = '') {
+ $currentFile = basename($_SERVER['PHP_SELF']);
+ $params = array();
+
+ if ($page > 1) {
+ $params['page'] = $page;
+ }
+
+ if ($year > 0) {
+ $params['y'] = $year;
+ }
+
+ if (!empty($search)) {
+ // 这里使用原始搜索词,http_build_query会自动编码
+ $params['search'] = $search;
+ }
+
+ if (empty($params)) {
+ return $currentFile;
+ }
+
+ return $currentFile . '?' . http_build_query($params);
+ }
+
+ // 年份筛选URL
+ function buildYearUrl($year, $search = '') {
+ return buildUrl($year, 1, $search);
+ }
+
+ $perPage = isset($config->frontPerPage) ? intval($config->frontPerPage) : 20;
+ $offset = ($currentPage - 1) * $perPage;
+
+ // 构建查询条件
+ $where = 'status = ?';
+ $whereParams = array(1);
+
+ if ($selectedYear > 0) {
+ $where .= ' AND YEAR(event_date) = ?';
+ $whereParams[] = $selectedYear;
+ }
+
+ if (!empty($searchKeyword)) {
+ $where .= ' AND content LIKE ?';
+ $whereParams[] = '%' . $searchKeyword . '%';
+ }
+
+ // 查询数据
+ $query = $db->select()
+ ->from($prefix . 'development_history')
+ ->where($where, ...$whereParams)
+ ->order('id', Typecho_Db::SORT_DESC)
+ ->limit($perPage)
+ ->offset($offset);
+
+ $histories = $db->fetchAll($query);
+
+ // 为每条记录获取关联的文章信息 - 修复URL生成
+ foreach ($histories as &$history) {
+ if (!empty($history['post_cids'])) {
+ $cids = array_filter(array_map('trim', explode(',', $history['post_cids'])));
+ $posts = array();
+ foreach ($cids as $cid) {
+ if (is_numeric($cid)) {
+ $postQuery = $db->select('cid, title, slug, created')
+ ->from($prefix . 'contents')
+ ->where('cid = ?', intval($cid))
+ ->where('type = ?', 'post')
+ ->where('status = ?', 'publish')
+ ->limit(1);
+ $post = $db->fetchRow($postQuery);
+ if ($post) {
+ // 修复:直接使用slug变量值
+ if (!empty($post['slug'])) {
+ $post['url'] = Typecho_Common::url($post['slug'] . '.html', $options->index);
+ } else {
+ $post['url'] = Typecho_Common::url('archives/' . $post['cid'], $options->index);
+ }
+ $posts[] = $post;
+ }
+ }
+ }
+ $history['posts'] = $posts;
+ } else {
+ $history['posts'] = array();
+ }
+ }
+
+ // 获取总数
+ $countQuery = $db->select('COUNT(*) as count')
+ ->from($prefix . 'development_history')
+ ->where($where, ...$whereParams);
+ $totalResult = $db->fetchRow($countQuery);
+ $total = $totalResult['count'];
+ $totalPages = ceil($total / $perPage);
+
+ // 获取所有年份及记录数(考虑搜索条件)
+ $yearsWhere = 'status = ?';
+ $yearsParams = array(1);
+
+ if (!empty($searchKeyword)) {
+ $yearsWhere .= ' AND content LIKE ?';
+ $yearsParams[] = '%' . $searchKeyword . '%';
+ }
+
+ $yearsQuery = $db->select('YEAR(event_date) as year, COUNT(*) as count')
+ ->from($prefix . 'development_history')
+ ->where($yearsWhere, ...$yearsParams)
+ ->group('YEAR(event_date)')
+ ->order('year', Typecho_Db::SORT_DESC);
+ $yearsData = $db->fetchAll($yearsQuery);
+
+ // 获取全部记录数(考虑搜索条件)
+ $totalAllWhere = 'status = ?';
+ $totalAllParams = array(1);
+
+ if (!empty($searchKeyword)) {
+ $totalAllWhere .= ' AND content LIKE ?';
+ $totalAllParams[] = '%' . $searchKeyword . '%';
+ }
+
+ $totalAllQuery = $db->select('COUNT(*) as count')
+ ->from($prefix . 'development_history')
+ ->where($totalAllWhere, ...$totalAllParams);
+ $totalAllResult = $db->fetchRow($totalAllQuery);
+ $totalAll = $totalAllResult['count'];
+
+ // 输出内容
+ if (empty($histories) && empty($searchKeyword) && $selectedYear == 0) {
+ echo '暂无发展历史记录
';
+ return;
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索 "" 找到 条记录
+ 0): ?>
+ (在 年中)
+
+
+
+
+
+
+
+
+
+
+
+ 0 && empty($searchKeyword)): ?>
+
+
+
+
+ 0)): ?>
+
+ 0): ?>
+ 未找到包含 "
" 的 年历史记录
+
+ 未找到包含 "
" 的历史记录
+ 0): ?>
+ 年暂无历史记录
+
+
+
+
+
+
+
+
+
+
+
+ dateFormat) ? $config->dateFormat : 'Y.m.d', strtotime($history['event_date'])); ?>
+
+
+
+ $1',
+ $content
+ );
+ }
+ echo nl2br($content);
+ ?>
+
+
+ showRelatedPosts) && $config->showRelatedPosts == 1 && !empty($history['posts'])):
+ ?>
+
+
+ relatedPostsTitle) ? $config->relatedPostsTitle : '相关文章'; ?>
+
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
+
+ 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 = '失败原因:
';
+ $displayCount = min(10, count($result['fail_reasons']));
+ for ($i = 0; $i < $displayCount; $i++) {
+ $errorDetails .= htmlspecialchars($result['fail_reasons'][$i]) . '
';
+ }
+ if (count($result['fail_reasons']) > 10) {
+ $errorDetails .= '...还有 ' . (count($result['fail_reasons']) - 10) . ' 条失败记录';
+ }
+ $errorMsg = $errorDetails;
+ }
+ }
+ } else {
+ $errorMsg = '导入失败!未找到可导入的记录或格式不正确';
+ if (!empty($result['fail_reasons'])) {
+ $errorMsg .= '
失败原因:
';
+ $displayCount = min(10, count($result['fail_reasons']));
+ for ($i = 0; $i < $displayCount; $i++) {
+ $errorMsg .= htmlspecialchars($result['fail_reasons'][$i]) . '
';
+ }
+ }
+ }
+ }
+}
+
+// 获取记录
+$histories = $action->getHistories($page, $perPage);
+$total = $action->getTotalCount();
+$totalPages = ceil($total / $perPage);
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
导出数据
+
导出所有历史记录为文本文件格式
+
+
+
+
+
+
+
导入数据
+
从文本文件导入历史记录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
历史记录列表
+
+
+
+ 暂无历史记录,请先添加记录
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file