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 && 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'])): ?>
1): ?>
1): ?> 上一页 上一页
1) { echo '1'; if ($start > 2) { echo '...'; } } // 显示页码 for ($i = $start; $i <= $end; $i++) { if ($i == $currentPage) { echo '' . $i . ''; } else { echo '' . $i . ''; } } // 显示最后页和省略号 if ($end < $totalPages) { if ($end < $totalPages - 1) { echo '...'; } echo '' . $totalPages . ''; } ?>
下一页 下一页