深入分析discuz的管理后台技术

本文深入解析了Discuz!论坛系统的后台管理实现方式,介绍了其独特的无HTML文件结构,通过几个核心函数完成了复杂的后台管理功能。文章还详细说明了如何新增一个管理页面,包括修改菜单配置文件、语言文件等步骤。

discuz的后台拥有着非常变态的实现过程, 即没有html文件, 全部的实现都靠几个函数来完成,当然这种结构下就促使了它的后台单一化,及极其难修改. 整体来说过程是非常清晰的, 仅仅用了几个通用函数就解决了这一页页的后台管理.

   现在我们开始分析.

  admincp.php文件:

<?php

/*
        [Discuz!] (C)2001-2009 Comsenz Inc.
        This is NOT a freeware, use is subject to license terms

        $Id: admincp.php 16688 2008-11-14 06:41:07Z cnteacher $
*/

define('IN_ADMINCP', TRUE);
define('NOROBOT', TRUE);
require_once './include/common.inc.php';
//加载后台函数
require_once DISCUZ_ROOT.'./admin/global.func.php';
//加载管理员类库
require_once DISCUZ_ROOT.'./admin/cpanel.share.php';
//加载缓存系统.
require_once DISCUZ_ROOT.'./include/cache.func.php';
//加载语言模块
include language('admincp');

//设置当前动作
$discuz_action = 211;
//取得当前IP
$admincp['checkip'] && $onlineip = empty($_SERVER['REMOTE_ADDR']) ? getenv('REMOTE_ADDR') : $_SERVER['REMOTE_ADDR'];
//开始更新管理员记录
$adminsession = new AdminSession($discuz_uid, $groupid, $adminid, $onlineip);
//取得管理员记录.
$dactionarray = $adminsession->get('dactionarray');
//判断.
if($dactionarray ===  null) {
        $dactionarray = array();
        if($radminid != $groupid) {
                $tmp = unserialize($db->result_first("SELECT disabledactions FROM {$tablepre}adminactions WHERE admingid='$groupid'"));
                $dactionarray = $tmp ? $tmp : array();
        }
        $adminsession->set('dactionarray', $dactionarray, true);
}
//如果会员ID不是管理员,就为0, 如果是管理员, 就为1, 如果已经登录,就为2
$cpaccess = $adminsession->cpaccess;
//如果标识为0 即前台会员未登录,或者管理员ID不正确, 就进入登录页.
if($cpaccess == 0 || (!$discuz_secques && $admincp['forcesecques'])) {
        require_once DISCUZ_ROOT.'./admin/login.inc.php';
} elseif($cpaccess == 1) {
        //当$admin_password不为空, 就登录.
        if($admin_password != '') {
                require_once DISCUZ_ROOT.'./uc_client/client.php';
                $ucresult = uc_user_login($discuz_uid, $admin_password, 1, 1, $admin_questionid, $admin_answer);  //uc的接口.
                if($ucresult[0] > 0) {
                        $adminsession->errorcount = -1;
                        $adminsession->update();
                        dheader('Location: '.$BASESCRIPT.'?'.cpurl('url', array('sid')));  //直接用跳转.
                } else {
                        $adminsession->errorcount ++;
                        $adminsession->update();
                        writelog('cplog', dhtmlspecialchars("$timestamp/t$discuz_userss/t$adminid/t$onlineip/t$action/tAUTHENTIFICATION(PASSWORD)"));
                }
        }
        //如果上而代码没有跳转, 那又回到登录页.
        require_once DISCUZ_ROOT.'./admin/login.inc.php';
} else {
        //$cpaccess为2了.
        //处理管理员用户名
        $username = !empty($username) ? dhtmlspecialchars($username) : '';
        //处理GET
        $action = !empty($action) && is_string($action) ? trim($action) : '';
        $operation = !empty($operation) && is_string($operation) ? trim($operation) : '';
        $page = isset($page) ? intval((max(1, $page))) : 0;
        //处理两个动作.
        if(!empty($action) && !in_array($action, array('main', 'logs'))) {
                switch($cpaccess) {
                        case 1:
                                $extralog = 'AUTHENTIFICATION(ERROR #'.intval($adminsession['errorcount']).')';
                                break;
                        case 3:
                                $extralog = implodearray(array('GET' => $_GET, 'POST' => $_POST), array('formhash', 'submit', 'addsubmit', 'admin_password', 'sid', 'action'));
                                break;
                        default:
                                $extralog = '';
                }
                $extralog = trim(str_replace(array('GET={};', 'POST={};'), '', $extralog));
                $extralog = (($action == 'home' && isset($securyservice)) || ($action == 'insenz' && in_array($operation, array('register', 'binding')))) ? '' : $extralog;
                writelog('cplog', implode("/t", clearlogstring(array($timestamp,$discuz_userss,$adminid,$onlineip,$action,$extralog))));
                unset($extralog);
        }

        $isfounder = $adminsession->isfounder = isfounder();
        if(empty($action) || isset($frames)) {
                //管理页的首页.
                $extra = cpurl('url');
                $extra = $extra && $action ? $extra : (!empty($runwizard) ? 'action=runwizard' : 'action=home');
                require_once DISCUZ_ROOT.'./admin/main.inc.php';
        } elseif($action == 'logout') {
                //退出动作.
                $adminsession ->destroy();
                dheader("Location: $indexname");
        } else {
                //更新当前动作.
                checkacpaction($action, $operation);
                //这句有意思了, action来引入某个执行文件. 关键点.
                if(in_array($action, array('home', 'settings', 'members', 'profilefields', 'admingroups', 'usergroups', 'ranks', 'forums', 'threadtypes', 'threads', 'moderate', 'attach', 'smilies', 'recyclebin', 'prune', 'styles', 'plugins', 'tasks', 'magics', 'medals', 'google', 'qihoo', 'video', 'announce', 'faq', 'ec', 'tradelog', 'creditwizard', 'jswizard', 'project', 'counter', 'misc', 'adv', 'insenz', 'logs', 'tools', 'checktools', 'search', 'upgrade')) || ($isfounder && in_array($action, array('runwizard', 'templates', 'db')))) {
                        require_once DISCUZ_ROOT.'./admin/'.$action.'.inc.php';  // 引入.
                        $title = 'cplog_'.$action.($operation ? '_'.$operation : '');
                        if(!in_array($action, array('home', 'custommenu')) && lang($title, false)) {
                                (strtolower($_SERVER['REQUEST_METHOD']) == 'get') && admincustom($title, cpurl('url'));
                        }
                } else {
                        cpheader();
                        cpmsg('noaccess');
                }
                //结束函数.
                cpfooter();
        }
}

?>

 

 

我们依后台管理的全局为例子, 来新建立一个管理页面..

 

 

if(in_array($action, array('home', 'settings', 'members', 'profilefields', 'admingroups', 'usergroups', 'ranks', 'forums', 'threadtypes', 'threads', 'moderate', 'attach', 'smilies', 'recyclebin', 'prune', 'styles', 'plugins', 'tasks', 'magics', 'medals', 'google', 'qihoo', 'video', 'announce', 'faq', 'ec', 'tradelog', 'creditwizard', 'jswizard', 'project', 'counter', 'misc', 'adv', 'insenz', 'logs', 'tools', 'checktools', 'search', 'upgrade')) || ($isfounder && in_array($action, array('runwizard', 'templates', 'db')))) {
                        require_once DISCUZ_ROOT.'./admin/'.$action.'.inc.php';  // 引入.
//全局的标识是: settings 所以我们会引入settings.inc.php文件. 此文件在admin目录中.

 

标识在哪里修改呢??  在admin目录中menu.inc.php文件中.
似乎里面写的全是代码,没有中文, 能够问这个问题, 你可以先看看templates/default/admincp.lang.php语言文件.

 

首先我们打开:menu.inc.php文件
查找:

 

showmenu('global', array(

 

在它的下一行增加:

 

        array('menu_settings_function, 'settings&operation=function'),

 

接着,我们需要修改一下语言文件admincp.menu.lang.php让它显示出我们想要的管理页名称.
查找:

'menu_settings_basic' => '站点信息',

 

在它的上一行增加:

'menu_settings_function' => '分享工作室',

现在刷新一下, 左边是不是显示了一个新的页链接? 分享工作室?

接着, 我们需要定义一下链接显示页的标题:打开admincp.lang.php文件
查找:

'settings_basic' => '站点信息',

 

在它的上一行增加:

 

'settings_function'=>'新增加管理页',

 

似乎现在可以点击,但内容显示为未定义操作。, 那么我们要怎么让程序来运行新的动作呢? 接着我们打开 settings.inc.php,查找:

 

cpmsg('undefined_action');

 

这个函数位于动作判断的最后一个默认输出, 即前面没有符全项目, 就进入这个函数输出.为此,我们增加一个条件判断:写在else前面..

 

elseif ($operation === 'function'){
                echo '我是新符合条件的管理页';
}

 

再点击一下链接,完美了, 结果就是这样:

内容概要:本文围绕EKF SLAM(扩展卡尔曼滤波同步定位与地图构建)的性能展开多项对比实验研究,重点分析在稀疏与稠密landmark环境下、预测与更新步骤同时进行与非同时进行的情况下的系统性能差异,并进一步探讨EKF SLAM在有色噪声干扰下的鲁棒性表现。实验考虑了不确定性因素的影响,旨在评估不同条件下算法的定位精度与地图构建质量,为实际应用中EKF SLAM的优化提供依据。文档还提及多智能体系统在遭受DoS攻击下的弹性控制研究,但核心内容聚焦于SLAM算法的性能测试与分析。; 适合人群:具备一定机器人学、状态估计或自动驾驶基础知识的科研人员及工程技术人员,尤其是从事SLAM算法研究或应用开发的硕士、博士研究生和相关领域研发人员。; 使用场景及目标:①用于比较EKF SLAM在不同landmark密度下的性能表现;②分析预测与更新机制同步与否对滤波器稳定性与精度的影响;③评估系统在有色噪声等非理想观测条件下的适应能力,提升实际部署中的可靠性。; 阅读建议:建议结合MATLAB仿真代码进行实验复现,重点关注状态协方差传播、观测更新频率与噪声模型设置等关键环节,深入理解EKF SLAM在复杂环境下的行为特性。稀疏 landmark 与稠密 landmark 下 EKF SLAM 性能对比实验,预测更新同时进行与非同时进行对比 EKF SLAM 性能对比实验,EKF SLAM 在有色噪声下性能实验
内容概要:本文围绕“基于主从博弈的售电商多元零售套餐设计与多级市场购电策略”展开,结合Matlab代码实现,提出了一种适用于电力市场化环境下的售电商优化决策模型。该模型采用主从博弈(Stackelberg Game)理论构建售电商与用户之间的互动关系,售电商作为领导者制定电价套餐策略,用户作为跟随者响应电价并调整用电行为。同时,模型综合考虑售电商在多级电力市场(如日前市场、实时市场)中的【顶级EI复现】基于主从博弈的售电商多元零售套餐设计与多级市场购电策略(Matlab代码实现)购电组合优化,兼顾成本最小化与收益最大化,并引入不确定性因素(如负荷波动、可再生能源出力变化)进行鲁棒或随机优化处理。文中提供了完整的Matlab仿真代码,涵盖博弈建模、优化求解(可能结合YALMIP+CPLEX/Gurobi等工具)、结果可视化等环节,具有较强的可复现性和工程应用价值。; 适合人群:具备一定电力系统基础知识、博弈论初步认知和Matlab编程能力的研究生、科研人员及电力市场从业人员,尤其适合从事电力市场运营、需求响应、售电策略研究的相关人员。; 使用场景及目标:① 掌握主从博弈在电力市场中的建模方法;② 学习售电商如何设计差异化零售套餐以引导用户用电行为;③ 实现多级市场购电成本与风险的协同优化;④ 借助Matlab代码快速复现顶级EI期刊论文成果,支撑科研项目或实际系统开发。; 阅读建议:建议读者结合提供的网盘资源下载完整代码与案例数据,按照文档目录顺序逐步学习,重点关注博弈模型的数学表达与Matlab实现逻辑,同时尝试对目标函数或约束条件进行扩展改进,以深化理解并提升科研创新能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值