bubifengyun 2016-10-29 12:38:02 5957次浏览 3条评论 3 1 0

改版前网址:https://my.oschina.net/bubifengyun/blog/605908

上文四、值得完善之处,发现有改进的可能。后来网站开发需要,有更多的一边是树形结构,一边是表格的形式,用原来的方法,太过粗糙,当然本次改版,也没有逃脱效率低下的困境,唯一的优势是代码量大幅度下降,而且还不惧原来插件的更新。

第十八章 treeview 跟 Gridview 的结合(改版)

参考资料:

一、示例提供的安装教程(前半部分)

如有不明白,可以参照原教程的 1-3 点。

1、安装插件

composer require kartik-v/yii2-tree-manager "@dev"
composer require kartik-v/yii2-grid "@dev"

2、导入数据库

php yii migrate/up --migrationPath=@vendor/kartik-v/yii2-tree-manager/migrations

解释:

  • 我是使用 XAMPP 开发的,使用 phpmyadmin 可以更改这个数据库,建议对这个 Tree 数据表添加你需要的属性。

3、建立模型(model)

我是使用 gii 直接导入的这个模型(model),需要把他的父类修改一下,

namespace common\models;

use Yii;

class Tree extends \kartik\tree\models\Tree
{
/*略*/
}

4、建立模块(module)

'modules' => [
   'treemanager' =>  [
        'class' => '\kartik\tree\Module',
        // other module settings, refer detailed documentation
    ]
]

二、结合 GridView 的部分

使用 TreeView 插件,假设现有一个 Personinfo ,对应有 PersoninfoController 的动作,

    /**
     * Every User take control of Out in special unit.
     * @return mixed
     */
    public function actionOut()
    {
        $see_unit = Yii::$app->user->identity->see_unit;
        $current_unit = Yii::$app->session->get('current_unit', 0);
        if ($current_unit === 0) {
            $current_unit = $see_unit;
        }
        if (Unit::findOne($see_unit) == null) {
            throw new NotFoundHttpException('请检查你可以查看的单位范围');
        }
        // add children and itself.
        $query = Unit::findOne($see_unit)
            ->children()
            ->orWhere(['id' => $see_unit])
            ->addOrderBy('root, lft');

        return $this->render('out', [
            'query' => $query,
            'current_unit' => $current_unit,
        ]);
    }

下面说渲染的页面 ./frontend/views/personinfo/out.php,代码如下:

<?php

use yii\helpers\Html;
use yii\helpers\Url;
use kartik\tree\TreeView;
use kartik\tree\Module;
use common\models\Unit;

/* @var $this yii\web\View */
/* @var $model common\models\Personinfo */

$this->title = '外出管理';
$this->params['breadcrumbs'][] = ['label' => '所有人员', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="personinfo-view">

<?= TreeView::widget([
    'query'             => $query,
    'headingOptions'    => ['label' => '部别'],
    'nodeView'          => '@frontend/views/personinfo/_nodeoutgridview',
    'nodeActions' => [
        Module::NODE_MANAGE => Url::to(['treemanager-router', 'router' => 'out']),
    ],
    'isAdmin'           => false,
    'rootOptions'       => ['label' => '您可以查看的部别'],
    'displayValue'      => $current_unit,
    'toolbar'           => [
        TreeView::BTN_REFRESH => false,
        TreeView::BTN_CREATE => false,
        TreeView::BTN_CREATE_ROOT => false,
        TreeView::BTN_REMOVE => false,
        TreeView::BTN_SEPARATOR => false,
        TreeView::BTN_MOVE_UP => false,
        TreeView::BTN_MOVE_DOWN => false,
        TreeView::BTN_MOVE_LEFT => false,
        TreeView::BTN_MOVE_RIGHT => false,
        TreeView::BTN_SEPARATOR => false,
    ],
]) ?>

</div>

解释:

  • 其他部分的解释见原文
  • 里面有一个特殊的动作,也即 Url::to(['treemanager-router', 'router' => 'out']),下面将会介绍。主要由该函数实现原博客粘贴整个模块要实现的功能。位于 ./frontend/controller/PersoninforController.php
use kartik\tree\TreeView;
use kartik\tree\controllers\NodeController;
//** skip many code.
    public function actionTreemanagerRouter($router)
    {
        extract(static::getPostData());
        if (isset($id) && !empty($id)) {
            Yii::$app->session->set('current_unit', $id);
        }
        return $this->redirect([$router]);
    }

    protected static function getPostData()
    {
        if (empty($_POST)) {
            return [];
        }
        $out = [];
        foreach ($_POST as $key => $value) {
            $out[$key] = in_array($key, NodeController::$boolKeys) ? filter_var($value, FILTER_VALIDATE_BOOLEAN) : $value;
        }
        return $out;
    }
// skip many code

解释:

  • 由于原来插件中 getPostData() 函数是 protected 的,无法直接调用,不得已,复制在此。

文中缺少的部分解释,详见原文,此处不再赘述。

觉得很赞
  • 评论于 2017-03-04 18:12 举报

    楼主你的文章中有一个坑啊,用 gii 生成 model,会自动给每个字段添加验证,而插件作者的原始表 lft/rgt/lvl 三个字段都是 NOT NULL,结果生成了验证 required,从而导致无法添加节点。我搞了半天,调试到里面去,再仔细看原作者的文档,发现他的model是手写的,都没有验证的。所以正确的做法是,手写model,或者gii生成后,把原始表的所有字段的验证全去掉。
    另外,你额外写一遍 getPostData() 函数,而这个函数 其实作者有的,所以,我觉得 应该让自己的controller 从 NodeController派生,从而不需要自己写这个函数,因为这个函数里面本身用了static,也就是延迟绑定的。
    我自己的需求的代码还没搞好,暂时发现这些问题

    2 条回复
    评论于 2017-03-06 18:50 回复

    抱歉,由于是在第一篇博客的基础上修改的,部分代码比较混乱,没有弄清楚。我是使用 gii 生成,但是后面把 rules 的验证规则给修改了。忘记说明,谢谢。

    额外的 getPostData() 函数是已有的,我在文章中说的不够明显,意思却也表明了原文有这个函数。当时没有想到继承这个方法,只是无法调用,如果可以继承,当然很不错的。

    谢谢你的建议。我修改一下博客。

    评论于 2017-03-06 19:05 回复

    我刚刚试了以下 parent::getPostData()函数,由于使用了他们各自的全局变量,还是其他原因,我也没有弄明白,反正页面就不能很好的显示了,建议保留该函数吧。等弄明白了,再来修改你提的这个问题,谢谢。

  • 评论于 2017-03-06 19:11 举报

    抱歉,这个博客有错误,但是我也不知道在哪里修改该博客了。请到这里https://my.oschina.net/bubifengyun/blog/776979 参考修改后的文章。谢谢。如有改动,以开源中国的博客为准,这里我搞不明白怎么修改博客。谢谢。

  • 评论于 2017-10-16 00:02 举报

    如何把VIEW_PART_1的去掉呢。就是它右边的Form表单

    1 条回复
    评论于 2017-10-24 18:47 回复

    不太明白,你可以去查查 树形结构原版说明,http://demos.krajee.com/tree-manager

    我也是很久没有再折腾了,不太清楚怎么弄。

您需要登录后才可以评论。登录 | 立即注册