以下是开发Discuz自动提取标签插件的详细步骤指南,包含完整的后台管理功能:
1.创建插件目录结构
在/source/plugin/下新建目录auto_tag
,结构如下:
auto_tag/
├─ plugin.xml // 插件配置文件
├─ plugin_auto_tag.class.php // 主程序
├─ admin.php // 后台管理
├─ install.php // 安装脚本
├─ uninstall.php // 卸载脚本
├─ lang/
│ ├─ lang_script.php // 脚本语言包
│ └─ lang_template.php// 模板语言包
└─ template/
└─ admin_menu.htm // 后台模板
2.插件配置文件 (plugin.xml)
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="name"><![CDATA[自动标签生成]]></item>
<item id="version">1.0.0</item>
<item id="description"><![CDATA[自动从帖子内容提取关键词生成标签]]></item>
<item id="vars">
<item id="source">
<title><![CDATA[标签来源]]></title>
<type>radio</type>
<value>1</value>
<choices>
<choice value="0">仅标题</choice>
<choice value="1">标题+内容</choice>
</choices>
</item>
<item id="max_tags">
<title><![CDATA[最大标签数量]]></title>
<type>text</type>
<value>5</value>
</item>
</item>
<item id="adminmenus">
<item id="setting">
<name>基本设置</name>
<url>plugins&operation=config&identifier=auto_tag</url>
</item>
<item id="stopwords">
<name>过滤词管理</name>
<url>admin.php?action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords</url>
</item>
</item>
</root>
3.主程序文件 (plugin_auto_tag.class.php)
<?php
if(!defined('IN_DISCUZ')) exit('Access Denied');
class plugin_auto_tag {
// 挂载帖子保存后的钩子
public function forum_post_after($param) {
global $_G;
$tid = $param['tid'];
$post = $param['post'];
// 获取插件配置
$config = $_G['cache']['plugin']['auto_tag'];
$maxTags = intval($config['max_tags']) ?: 5;
// 提取文本内容
$content = $post['subject'];
if($config['source'] == 1) {
$content .= ' '.$post['message'];
}
// 调用标签生成逻辑
$tags = $this->generate_tags($content, $maxTags);
// 保存标签到数据库
if(!empty($tags)) {
C::t('forum_thread')->update($tid, array('tag' => implode(',', $tags)));
}
}
// 核心标签生成算法
private function generate_tags($text, $maxTags) {
// 1. 过滤HTML标签
$text = strip_tags($text);
// 2. 加载过滤词
$stopwords = C::t('#auto_tag#plugin_stopwords')->fetch_all();
$stopwords = array_column($stopwords, 'word');
// 3. 中文分词(需安装中文分词扩展)
$words = $this->segment_text($text);
// 4. 统计词频并过滤
$wordCount = array_count_values($words);
arsort($wordCount);
// 5. 生成最终标签
$tags = array();
foreach($wordCount as $word => $count) {
if(count($tags) >= $maxTags) break;
if(!in_array($word, $stopwords) && strlen($word) > 2) {
$tags[] = $word;
}
}
return $tags;
}
// 简单分词示例(实际应使用分词组件)
private function segment_text($text) {
// 这里可以替换为结巴分词等实现
preg_match_all('/[\x{4e00}-\x{9fa5}]{2,}/u', $text, $matches);
return $matches[0];
}
}
class plugin_auto_tag_forum extends plugin_auto_tag {}
4.后台管理文件 (admin.php)
<?php
if(!defined('IN_DISCUZ') || !defined('ADMINISTRATOR')) exit('Access Denied');
$pmod = $_GET['pmod'] ?: 'setting';
if($pmod == 'stopwords') {
// 过滤词管理逻辑
if(submitcheck('submit')) {
$newword = trim(dhtmlspecialchars($_POST['newword']));
if(!empty($newword)) {
C::t('#auto_tag#plugin_stopwords')->insert(array(
'word' => $newword,
'dateline' => TIMESTAMP
));
cpmsg('操作成功', 'action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords', 'succeed');
}
} elseif($_GET['delete']) {
C::t('#auto_tag#plugin_stopwords')->delete(intval($_GET['delete']));
cpmsg('删除成功', 'action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords', 'succeed');
}
// 显示现有过滤词
$words = C::t('#auto_tag#plugin_stopwords')->fetch_all();
include template('auto_tag:admin_stopwords');
} else {
// 默认显示设置页面
include template('auto_tag:admin_setting');
}
5.数据库表操作(install.php)
<?php
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS `pre_plugin_stopwords` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`word` varchar(50) NOT NULL DEFAULT '',
`dateline` int(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `word` (`word`)
) ENGINE=MyISAM;
SQL;
runquery($sql);
$finish = TRUE;
6.后台模板文件 (template/admin_stopwords.htm)
<!--{template common/header}-->
<form method="post" action="admin.php?action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords">
<table class="tb tb2 ">
<tr><th colspan="2">添加过滤词</th></tr>
<tr class="noborder">
<td class="vtop rowform"><input type="text" name="newword" style="width:300px;"></td>
<td class="vtop tips2">多个词请用逗号分隔</td>
</tr>
</table>
<div class="fixsel">
<input type="submit" class="btn" name="submit" value="提交">
</div>
</form>
<table class="tb tb2 ">
<tr><th>ID</th><th>过滤词</th><th>添加时间</th><th>操作</th></tr>
<!--{loop $words $word}-->
<tr>
<td>{$word[id]}</td>
<td>{$word[word]}</td>
<td>{echo date('Y-m-d H:i', $word[dateline])}</td>
<td><a href="admin.php?action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords&delete={$word[id]}">删除</a></td>
</tr>
<!--{/loop}-->
</table>
<!--{template common/footer}-->
开发注意事项:
-
实际生产环境需要:
- 使用更精确的分词组件(如结巴分词)
- 增加标签黑名单过滤功能
- 添加标签长度限制
- 实现标签合并去重
-
性能优化建议:
- 使用缓存机制存储高频词
- 添加后台批量处理功能
- 限制处理频率(防止高并发压力)
-
扩展功能建议:
- 添加标签云展示功能
- 支持自定义词性过滤
- 添加操作日志功能
- 支持正则表达式过滤规则
安装步骤:
- 将插件文件夹上传到/source/plugin/
- 进入Discuz后台 → 应用 → 安装新插件
- 找到"自动标签生成"插件并安装
- 配置插件参数并管理过滤词
该插件实现了一个完整的标签自动化处理流程,包含后台配置、词库管理、核心处理算法等模块,能够有效提升论坛的内容组织效率。
以下是您需要的完整文件代码实现:
1.卸载脚本 (uninstall.php)
<?php
if(!defined('IN_DISCUZ')) exit('Access Denied');
$sql = <<<SQL
DROP TABLE IF EXISTS pre_plugin_stopwords;
SQL;
runquery($sql);
// 清除插件缓存
loadcache('plugin');
unset($_G['cache']['plugin']['auto_tag']);
updatecache('plugin');
$finish = TRUE;
2.脚本语言包 (lang/lang_script.php)
<?php
if(!defined('IN_DISCUZ')) exit('Access Denied');
$_lang = array(
'auto_tag_admin' => '自动标签管理',
'auto_tag_setting' => '基本设置',
'auto_tag_stopwords' => '过滤词库',
'auto_tag_max_tags_tips' => '建议设置3-10个,过多可能影响性能',
'auto_tag_source_tips' => '选择标签生成的内容来源',
);
3.模板语言包 (lang/lang_template.php)
<?php
if(!defined('IN_DISCUZ')) exit('Access Denied');
$_lang = array(
'auto_tag_admin_menu' => '自动标签设置',
'auto_tag_add_stopword' => '添加过滤词',
'auto_tag_stopword_list' => '现有过滤词列表',
'auto_tag_delete_confirm' => '确定要删除该过滤词吗?',
'auto_tag_input_placeholder' => '输入要过滤的关键词',
);
4.后台菜单模板 (template/admin_menu.htm)
<!--{template common/header}-->
<div class="mbm cl">
<h2 class="mbn">{$_lang['auto_tag_admin_menu']} v1.0</h2>
<div class="mbn url">
<a href="admin.php?action=plugins&operation=config&identifier=auto_tag" class="xi2"{if $pmod == 'setting'} style="color:#F60;font-weight:bold"{/if}>$_lang[auto_tag_setting]</a>
|
<a href="admin.php?action=plugins&operation=admin&identifier=auto_tag&pmod=stopwords" class="xi2"{if $pmod == 'stopwords'} style="color:#F60;font-weight:bold"{/if}>$_lang[auto_tag_stopwords]</a>
</div>
</div>
<!--{if $pmod == 'setting'}-->
<form action="admin.php?action=plugins&operation=config&identifier=auto_tag" method="post">
<table class="tb tb2">
<tr><th colspan="2">$_lang[auto_tag_setting]</th></tr>
<tr>
<td class="td27">$_lang[auto_tag_source]</td>
<td>
<label><input type="radio" name="source" value="0" {if $_G['setting']['source'] == 0}checked{/if}> $_lang[auto_tag_title_only]</label>
<label><input type="radio" name="source" value="1" {if $_G['setting']['source'] == 1}checked{/if}> $_lang[auto_tag_title_content]</label>
</td>
</tr>
<tr>
<td class="td27">$_lang[auto_tag_max_tags]</td>
<td>
<input type="text" name="max_tags" value="{$_G['setting']['max_tags']}" size="5">
<span class="xg1">$_lang[auto_tag_max_tags_tips]</span>
</td>
</tr>
</table>
<div class="fixsel">
<input type="submit" class="btn" value="$_lang[submit]">
</div>
</form>
<!--{/if}-->
<!--{template common/footer}-->
代码说明及注意事项:
1.卸载脚本:
- 使用
DROP TABLE IF EXISTS
确保安全删除数据表
- 清除插件缓存保持系统清洁
- 兼容Discuz的安装/卸载机制
2.语言包设计:
- 脚本语言包用于PHP程序中的文本
- 模板语言包用于HTML模板中的文本
- 使用统一的"autotag"前缀避免命名冲突
- 支持多语言扩展能力
3.后台菜单模板:
- 使用Discuz标准模板语法
- 高亮当前选中菜单项
- 包含配置表单的基础结构
- 与语言包紧密集成实现多语言支持
4.安全增强建议:
// 在uninstall.php增加表存在性检查
if(DB::result_first("SHOW TABLES LIKE 'pre_plugin_stopwords'")) {
runquery("DROP TABLE pre_plugin_stopwords");
}
// 在语言文件增加防御代码
defined('IN_DISCUZ') || exit('Access Denied');
使用这些文件时需要注意:
- 文件编码必须使用UTF-8 without BOM
- 模板文件中的HTML注释需要保留Discuz的特殊标记
- 语言包键名需要与模板中的引用完全一致
- 卸载操作会永久删除过滤词数据表
- 后台菜单URL需要与plugin.xml配置保持一致
建议在实际使用前进行以下测试:
- 完整安装/卸载流程测试
- 多语言切换测试
- 表单提交安全测试(XSS防护)
- 数据库表操作回滚测试
- 高并发情况下的标签生成压力测试
如果需要增加更多功能,可以在这些文件基础上扩展:
- 在卸载脚本中添加配置备份功能
- 为语言包增加更多操作提示
- 在菜单模板中添加统计信息展示
- 增加操作日志记录功能