2026-2-28开发记录:目录树系统修改记录日志

文档创建者:蜗牛
浏览次数:118
最后更新:2026-02-28
新建文档详情
排列序号: -
配置选择: 普通文档
配置贴展示: 展示在目录

初始问题

在讨论如何实现 [posts] 段落配置对帖子进行排序,具体需求是:

  • 有 5 个帖子(tid:1,2,3,4,5)都在"技术手册"目录下
  • 需要在"技术手册"目录下对这些帖子进行排序

实际问题诊断

通过调试发现实际问题是:

  1. 配置帖中使用了传统文字路径格式(开发维护/社创开发
  2. 帖子标签只使用了单层名称(#目录_社创开发
  3. 标签名与配置路径无法正确匹配,导致帖子无法归入目录

修改过程时间线

阶段一:问题诊断

1.1 添加 SQL 调试代码

问题:初始调试时 $_G['fid'] 变量为空,导致 SQL 语法错误

错误信息:
1064) You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'AND tag.tagname LIKE...'

修改内容

  • 修复变量访问:使用 $fid 参数代替 $_G['fid']
  • 添加 intval() 确保类型正确
  • 添加 fallback 逻辑,从全局变量获取 fid

文件

  • template/xmyc_doc/php/directory_tree.php
  • template/xmyc_touch_doc/touch/php/directory_tree.php

1.2 调试输出结果

当前 fid: 23

所有带目录标签的帖子:
tid:118 subject:2025-12-26 开发记录 tags:目录_社创开发
tid:135 subject:社创行动派交流论坛介绍 tags:目录_开发维护
tid:137 subject:2026 年 1 月开发记录 tags:目录_社创开发
tid:140 subject:文档模式前端模板解析目录的开发 tags:目录_社创开发

目录配置:
directories:
  [开发维护] => Array([name] => 网站开发维护 [sort_order] => 98)
  [开发维护/社创开发] => Array([name] => 社创官网和社区开发 [sort_order] => 1)

posts:
  [社创开发] => Array([0] => 118 [1] => 140 [2] => 137)

1.3 问题定位

  • 配置路径:开发维护/社创开发
  • 帖子标签:社创开发(单层)
  • 匹配函数 find_dir_path_by_name() 只能匹配路径最后一级

阶段二:修复路径匹配

2.1 修改匹配逻辑

修改内容

  • 修复 [posts] 排序查找逻辑,使用标签名 $dir_name 代替完整路径 $dir_path
  • 添加调试输出,显示帖子与目录的匹配过程

代码变更

// 原代码
if(isset($directory_config['posts'][$dir_path])) {
    $tid_index = array_search($_thread['tid'], $directory_config['posts'][$dir_path]);
}

// 修改后
if(isset($directory_config['posts'][$dir_name])) {
    $tid_index = array_search($_thread['tid'], $directory_config['posts'][$dir_name]);
}

阶段三:方案优化讨论

3.1 用户需求确认

用户提出新方案需求:

  • 置顶帖路径配置格式:数字序号 = 标签名称 = 目录树名称
  • 目录树层级直接解析数字序号来匹配完成
  • 帖子只需要单层标签即可

配置格式示例

1 = 开发维护 = 网站的开发维护
1-1 = 社创开发 = 社创行动派开发
1-1-1 = 文档开发 = 文档类内容展示逻辑开发

3.2 方案设计

新格式特点

  1. 序号决定层级关系(11-11-1-1
  2. 标签名保持单层(#目录_社创开发
  3. 配置更清晰,维护更简单

阶段四:新格式实现

4.1 配置解析函数重写

函数parse_config_message()

新增新格式解析

// 新格式:序号 = 标签名 = 目录名
preg_match_all('/^([\d\-]+)\s*=\s*([^=]+)\s*=\s*(.+)$/m', $content, $new_matches);
if($new_matches[1]) {
    foreach($new_matches[1] as $index => $num_path) {
        $num_path = trim($new_matches[1][$index]);
        $tag_name = trim($new_matches[2][$index]);
        $dir_name = trim($new_matches[3][$index]);

        $config['directories'][$num_path] = array(
            'tag_name' => $tag_name,
            'name' => $dir_name,
            'sort_order' => $index,
            'is_new_format' => true
        );
    }
}

保留旧格式兼容

// 旧格式:序号 = 目录名。权重
preg_match_all('/^([^=\n]+)\s*=\s*([^.\n]+)\.(\d+)/m', $content, $dir_matches);

4.2 新增辅助函数

函数find_num_path_by_tag()

function find_num_path_by_tag($directory_config, $tag_name) {
    foreach($directory_config['directories'] as $num_path => $config) {
        if($config['tag_name'] == $tag_name) {
            return $num_path;
        }
    }
    return '';
}

4.3 新增目录节点创建函数

函数create_directory_node_new()

function create_directory_node_new(&$choices, $num_path, $name) {
    // 将 1-1-1 转换为数组 [1, 1, 1]
    $parts = explode('-', $num_path);
    $current = &$choices;
    $key_path = '';
    $num_path_dot = '';

    foreach($parts as $index => $part) {
        $key_path .= ($key_path ? '-' : '') . $part;
        $num_path_dot .= ($num_path_dot ? '.' : '') . $part;

        if(!isset($current[$num_path_dot])) {
            $current[$num_path_dot] = array(
                'key' => $key_path,
                'num' => $num_path_dot,
                'level' => $index + 1,
                'name' => $name,
                'type' => 'directory',
                'href' => generate_dir_link($num_path_dot),
                'list' => array(),
                'sort_order' => $index
            );
        }
        $current = &$current[$num_path_dot]['list'];
    }
}

4.4 新增帖子添加函数

函数add_thread_to_directory_new()

function add_thread_to_directory_new(&$choices, $num_path, $thread, $sort_order = 0) {
    $parts = explode('-', $num_path);
    $current = &$choices;
    $num_path_dot = implode('.', $parts);

    // 导航到最后的目录
    foreach($parts as $index => $part) {
        $path = implode('.', array_slice($parts, 0, $index + 1));
        if(isset($current[$path])) {
            $current = &$current[$path]['list'];
        } else {
            return; // 目录不存在,跳过
        }
    }

    // 添加帖子
    $thread_key = 'tid_' . $thread['tid'];
    if(!isset($current[$thread_key])) {
        $current[$thread_key] = array(
            'key' => $thread_key,
            'num' => $thread['tid'],
            'name' => $thread['subject'],
            'type' => 'thread',
            'href' => generate_thread_link($thread['tid']),
            'list' => array(),
            'sort_order' => $sort_order
        );
    }
}

4.5 主逻辑流程控制

// 检查是否使用新格式
$is_new_format = false;
foreach($directory_config['directories'] as $num_path => $config) {
    if(!empty($config['is_new_format'])) {
        $is_new_format = true;
        break;
    }
}

if($is_new_format) {
    // 新格式处理
    foreach($directory_config['directories'] as $num_path => $config) {
        create_directory_node_new($flquery['choices'], $num_path, $config['name']);
    }

    foreach($_tagged_threads as $_thread) {
        $tag_names = extract_directory_tags($_thread['tags']);
        foreach($tag_names as $tag_name) {
            $num_path = find_num_path_by_tag($directory_config, $tag_name);
            if($num_path) {
                $sort_order = 0;
                if(isset($directory_config['posts'][$tag_name])) {
                    $tid_index = array_search($_thread['tid'], $directory_config['posts'][$tag_name]);
                    if($tid_index !== false) {
                        $sort_order = $tid_index;
                    }
                }
                add_thread_to_directory_new($flquery['choices'], $num_path, $_thread, $sort_order);
            }
        }
    }
} else {
    // 旧格式处理(兼容)
}

修改文件清单

文件 修改类型 说明
template/xmyc_doc/php/directory_tree.php 重写 PC 版目录树生成核心
template/xmyc_touch_doc/touch/php/directory_tree.php 重写 移动版目录树生成核心

函数变更清单

新增函数

函数名 用途 版本
find_num_path_by_tag() 根据标签名查找序号路径 新格式专用
create_directory_node_new() 创建序号目录节点 新格式专用
add_thread_to_directory_new() 添加帖子到序号目录 新格式专用

修改函数

函数名 修改内容
parse_config_message() 新增新格式解析逻辑,保留旧格式兼容
extract_directory_tags() 简化,移除路径转换逻辑
get_directory_threads() 移除调试代码,优化 SQL

保留函数(旧格式兼容)

函数名 用途
build_directory_tree() 旧格式目录树构建
find_dir_path_by_name() 旧格式路径匹配

配置格式对比

旧格式

[doc_directory]
开发维护 = 网站开发维护.98
开发维护/社创开发 = 社创官网和社区开发.1
开发维护/利智官网 = 北京利智官网.2

[posts]
社创开发 = tid:118,tid:140,tid:137
[/posts]
[/doc_directory]

新格式

[doc_directory]
1 = 开发维护 = 网站开发维护
1-1 = 社创开发 = 社创官网和社区开发
1-2 = 利智官网 = 北京利智官网

[posts]
社创开发 = tid:118,tid:140,tid:137
[/posts]
[/doc_directory]

技术要点

1. 序号路径解析

输入:1-1-1
解析:explode('-', '1-1-1') → [1, 1, 1]
层级:level=3
路径:1.1.1(内部存储格式)
KEY: 1-1-1(用于前端)

2. 标签匹配逻辑

帖子标签:#目录_社创开发
配置查找:遍历 directories 数组,匹配 tag_name
返回序号:1-1
目录路径:1.1(内部)

3. 目录树结构

$flquery['choices'] = array(
    '1' => array(
        'key' => '1',
        'num' => '1',
        'level' => 1,
        'name' => '开发维护',
        'type' => 'directory',
        'href' => '...&dir=1',
        'list' => array(
            '1.1' => array(
                'key' => '1-1',
                'num' => '1.1',
                'level' => 2,
                'name' => '社创官网和社区开发',
                'type' => 'directory',
                'list' => array(
                    'tid_118' => array(
                        'key' => 'tid_118',
                        'num' => 118,
                        'name' => '2025-12-26 开发记录',
                        'type' => 'thread',
                        'href' => '...tid=118',
                        'sort_order' => 0
                    )
                )
            )
        )
    )
);

测试验证

测试场景

场景 预期结果 状态
新格式配置解析 正确解析序号、标签名、目录名
旧格式配置解析 向后兼容,正常解析
标签匹配序号 单层标签匹配到正确序号路径
多层目录构建 1-1-1 正确构建三级目录
帖子排序 [posts] 配置生效
Ajax 请求 getdirectory=true 返回 JSON

遇到的问题及解决方案

问题 1:fid 变量为空

现象:SQL 报错 WHERE t.fid= AND...

原因$_G['fid'] 在函数作用域内不可用

解决

$fid = intval($fid);
if(empty($fid)) {
    global $_G;
    $fid = intval($_G['fid']);
}

问题 2:标签与路径不匹配

现象:帖子无法归入目录

原因:配置使用完整路径 开发维护/社创开发,标签只有 社创开发

临时解决:修改匹配逻辑,使用标签名查找 [posts] 配置

最终解决:引入新格式,序号配置 + 单层标签


后续建议

功能增强

  1. 自动序号生成:配置时可省略序号,自动生成
  2. 目录权限控制:支持按目录设置访问权限
  3. 目录统计信息:显示每个目录下的文档数量
  4. 批量标签管理:提供批量修改帖子标签的工具

性能优化

  1. 缓存机制:目录树结果缓存,减少数据库查询
  2. Ajax 加载:大目录树分步加载
  3. 索引优化:为标签表添加组合索引

用户体验

  1. 配置可视化:提供配置帖生成工具
  2. 目录预览:编辑配置帖时实时预览目录结构
  3. 错误提示:配置错误时给出明确提示

总结

本次修改完成了目录树系统从文字路径配置到序号路径配置的升级,主要成果:

  1. 新格式更简洁序号 = 标签名 = 目录名 三要素清晰明了
  2. 标签更简单:帖子只需单层标签,降低维护成本
  3. 层级更清晰:序号直接体现目录层级关系
  4. 向后兼容:保留旧格式支持,平滑迁移

核心改进点:

  • 配置解析支持新旧两种格式
  • 新增序号路径匹配和目录构建函数
  • 简化了帖子标签要求
  • 优化了目录树生成逻辑

日志版本:1.0
记录日期:2026-02-28
记录人:蜗牛

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条