lizhen_gitee il y a 6 mois
Parent
commit
dad896da05

+ 1 - 0
addons/faredis/.addonrc

@@ -0,0 +1 @@
+{"files":["application\\admin\\controller\\faredis\\Index.php","application\\admin\\view\\faredis\\index\\index.html","public\\assets\\js\\backend\\faredis\\index.js","public\\assets\\addons\\faredis\\img\\db_16.png","public\\assets\\addons\\faredis\\img\\key_16.png","public\\assets\\addons\\faredis\\img\\loading.gif","public\\assets\\addons\\faredis\\img\\redis_16.png"],"license":"regular","licenseto":"19079","licensekey":"VmpugiArk16YHOfb 8miNFrK4NUn9JDaBPFmS7w==","domains":[],"licensecodes":[],"validations":[],"menus":["faredis\/index"]}

+ 61 - 0
addons/faredis/Faredis.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace addons\faredis;
+
+use app\common\library\Menu;
+use think\Addons;
+
+/**
+ * 插件
+ */
+class Faredis extends Addons
+{
+
+    /**
+     * 插件安装方法
+     * @return bool
+     */
+    public function install()
+    {
+        $menu = [
+            [
+                'name'    => 'faredis/index',
+                'title'   => 'Redis数据管理工具',
+                'ismenu'  => 1,
+                'sublist' => []
+            ]
+        ];
+        Menu::create($menu);
+        return true;
+    }
+
+    /**
+     * 插件卸载方法
+     * @return bool
+     */
+    public function uninstall()
+    {
+        Menu::delete("faredis/index");
+        return true;
+    }
+
+    /**
+     * 插件启用方法
+     * @return bool
+     */
+    public function enable()
+    {
+        Menu::enable("faredis/index");
+        return true;
+    }
+
+    /**
+     * 插件禁用方法
+     * @return bool
+     */
+    public function disable()
+    {
+        Menu::disable("faredis/index");
+        return true;
+    }
+}

+ 44 - 0
addons/faredis/config.php

@@ -0,0 +1,44 @@
+<?php
+
+return [
+    [
+        'name'    => 'host',
+        'title'   => '主机',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '127.0.0.1',
+        'rule'    => 'required',
+        'extend'  => '',
+        'tip'     => ''
+    ],
+    [
+        'name'    => 'port',
+        'title'   => '端口',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '6379',
+        'rule'    => 'required',
+        'extend'  => '',
+        'tip'     => ''
+    ],
+    [
+        'name'    => 'password',
+        'title'   => '密码',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '',
+        'rule'    => '',
+        'extend'  => '',
+        'tip'     => ''
+    ],
+    [
+        'name'    => 'dbnums',
+        'title'   => '库数量',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '16',
+        'rule'    => '',
+        'extend'  => '',
+        'tip'     => ''
+    ],
+];

+ 10 - 0
addons/faredis/info.ini

@@ -0,0 +1,10 @@
+name = faredis
+title = Redis数据管理工具
+intro = Redis数据管理工具
+author = xiaoyu5062
+website = https://www.fastadmin.net
+version = 2.0.0
+state = 1
+url = /addons/faredis
+license = regular
+licenseto = 19079

+ 278 - 0
application/admin/controller/faredis/Index.php

@@ -0,0 +1,278 @@
+<?php
+
+namespace app\admin\controller\faredis;
+
+use app\common\controller\Backend;
+
+class Index extends Backend
+{
+
+    protected $handler = null;
+
+    public function _initialize($options = [])
+    {
+        parent::_initialize();
+
+        if (!extension_loaded('redis')) {
+            throw new \BadFunctionCallException('未安装redis扩展');
+        }
+        $options = get_addon_config('faredis');
+        $this->handler = new \Redis;
+        try {
+            $this->handler->connect($options['host'], $options['port'], 0);
+            if ('' != $options['password']) {
+                $this->handler->auth($options['password']);
+            }
+        } catch (\RedisException $e) {
+            $this->error('连接失败,请检查配置文件或Redis服务是否开启', url('faredis/index'), null, 3);
+        }
+    }
+
+
+    public function index()
+    {
+        if ($this->request->isAjax()) {
+            $root = array('text' => 'Redis', 'id' => -1, 'type' => 'root', 'state' => array('opened' => true));
+            $nums = get_addon_config('faredis')['dbnums'];
+            for ($i = 1; $i <= $nums; $i++) {
+                $this->handler->select($i - 1);
+                $count = $this->handler->dbSize();
+                $root['children'][] = array('text' => 'DB' . ($i - 1) . '(' . $count . ')', 'id' => $i, 'type' => 'db');
+            }
+            return json($root);
+        }
+        // add test data
+        // for ($i = 1; $i < 20; $i++) {
+        //     $this->handler->select(0);
+        //     $this->handler->set('k' . $i, $i);
+        // }
+        return $this->view->fetch();
+    }
+
+    public function reloadDb($db)
+    {
+        $this->handler->select($db - 1);
+        $node = array('text' => 'DB' . ($db - 1) . '(' . $this->handler->dbSize() . ')', 'id' => $db, 'type' => 'db', 'parent' => -1);
+        return json($node);
+    }
+
+    public function flushDb($db)
+    {
+        $this->handler->select($db - 1);
+        $this->handler->flushDb();
+        $this->success();
+    }
+
+    public function keys($db)
+    {
+        $this->handler->select($db);
+        $keys = $this->handler->keys('*');
+        $data = [];
+        foreach ($keys as $k => $v) {
+            $data[] = array('text' => $v, 'id' => $db . '_' . $v, 'type' => 'key');
+        }
+        return json($data);
+    }
+
+    public function getValue($db, $key)
+    {
+        $this->handler->select($db);
+        $type = $this->handler->type($key);
+        $ttl = $this->handler->ttl($key);
+        $value = null;
+        // 1 string 2 set   3 list 4 zset  5 hash
+        switch ($type) {
+            case 1:
+                $value = $this->handler->get($key);
+                break;
+            case 2:
+                $value = $this->handler->SMEMBERS($key);
+                break;
+            case 3:
+                $value = $this->handler->lrange($key, 0, -1);
+                break;
+            case 4:
+                $value = $this->handler->zrange($key, 0, -1, true);
+                break;
+            case 5:
+                $value = $this->handler->hGetAll($key);
+                break;
+            default:
+                # code...
+                break;
+        }
+        return json(array('db' => $db, 'key' => $key, 'type' => $type, 'value' => $value, 'ttl' => $ttl));
+    }
+
+    public function delKey($db, $key)
+    {
+        $this->handler->select($db);
+        $r = $this->handler->del($key);
+        $r == 1 ? $this->success() : $this->error();
+    }
+
+    public function rename($db, $key)
+    {
+        $this->handler->select($db);
+        $newkey = input('newkey', $key);
+        $r = $this->handler->rename($key, $newkey);
+        $r == 1 ? $this->success() : $this->error();
+    }
+
+    public function ttl($db, $key)
+    {
+        $this->handler->select($db);
+        $newttl = input('ttl');
+        if ($newttl == -1)
+            $this->handler->persist($key);
+        else
+            $this->handler->expire($key, $newttl);
+        $this->success();
+    }
+
+    public function updateValue()
+    {
+        $db = input('db');
+        $key = input('key');
+        $value = input('value');
+        $json = json_decode($value);
+        if (!is_null($json)) {
+            $value = json_encode($json);
+        }
+        $this->handler->select($db);
+        $type = $this->handler->type($key);
+        // 1 string 2 set   3 list 4 zset  5 hash
+        switch ($type) {
+            case 1:
+                $this->handler->set($key, $value);
+                break;
+            case 2:
+                $old = input('oldvalue');
+                $this->handler->sRem($key, $old);
+                $this->handler->sadd($key, $value);
+                break;
+            case 3:
+                $list_idx = input('oldvalue');
+                $this->handler->lSet($key, $list_idx, $value);
+                break;
+            case 4:
+                $zset_key = input('zset-key'); //rem
+                $zset_score = input('zset-score'); //add + value
+                $this->handler->zrem($key, $zset_key);
+                $this->handler->zadd($key, $zset_score, $value);
+                break;
+            case 5:
+                $hash_key = input('hash-key');
+                $this->handler->hSet($key, $hash_key, $value);
+                break;
+            default:
+                # code...
+                break;
+        }
+        $this->success('操作成功');
+    }
+
+    public function addValue()
+    {
+        $db = input('db');
+        $key = input('key');
+        $value = input('value');
+        $json = json_decode($value);
+        if (!is_null($json)) {
+            $value = json_encode($json);
+        }
+        $this->handler->select($db);
+        $type = $this->handler->type($key);
+        // 1 string 2 set   3 list 4 zset  5 hash
+        switch ($type) {
+            case 2:
+                $this->handler->sadd($key, $value);
+                break;
+            case 3:
+                $this->handler->rpush($key, $value);
+                break;
+            case 4:
+                $zset_score = input('zset_score', 0);
+                $this->handler->zadd($key, $zset_score, $value);
+                break;
+            case 5:
+                $hash_key = input('hash_key');
+                $this->handler->hset($key, $hash_key, $value);
+                break;
+            default:
+                # code...
+                break;
+        }
+        $this->success('操作成功');
+    }
+
+    public function delValue()
+    {
+        $db = input('db');
+        $key = input('key');
+        $value = input('value');
+        $json = json_decode($value);
+        if (!is_null($json)) {
+            $value = json_encode($json);
+        }
+        $this->handler->select($db);
+        $type = $this->handler->type($key);
+        // 1 string 2 set   3 list 4 zset  5 hash
+        switch ($type) {
+            case 2:
+                $this->handler->srem($key, $value);
+                break;
+            case 3:
+                $this->handler->lrem($key, $value);
+                break;
+            case 4:
+                $this->handler->zrem($key, $value);
+                break;
+            case 5:
+                $this->handler->hdel($key, $value);
+                break;
+            default:
+                # code...
+                break;
+        }
+        $this->success('操作成功');
+    }
+
+    public function newKey()
+    {
+        $db = input('newdb', 1);
+        --$db;
+        $key = input('newkey');
+        $value = input('newvalue');
+        $json = json_decode($value);
+        if (!is_null($json)) {
+            $value = json_encode($json);
+        }
+        $this->handler->select($db);
+        $type = input('newType', 'string');
+        // 1 string 2 set   3 list 4 zset  5 hash
+        switch ($type) {
+            case 'string':
+                $this->handler->set($key, $value);
+                break;
+            case 'set':
+                $this->handler->sadd($key, $value);
+                break;
+            case 'list':
+                $this->handler->rpush($key, $value);
+                break;
+            case 'zset':
+                $zset_score = input('newscore', 0);
+                $this->handler->zadd($key, $zset_score, $value);
+                break;
+            case 'hash':
+                $hash_key = input('newfield');
+                $this->handler->hset($key, $hash_key, $value);
+                break;
+            default:
+                # code...
+                break;
+        }
+        $this->success('操作成功');
+    }
+}

+ 268 - 0
application/admin/view/faredis/index/index.html

@@ -0,0 +1,268 @@
+<style>
+    .tree{
+        max-height:calc(90vh);
+        overflow: auto;
+        overflow-x: hidden;
+    }
+</style>
+
+<div class="panel panel-default col-xs-4 col-sm-4">
+    <div class="panel-body">
+        <input type="text" id="search_input" placeholder="在展开节点中搜索.." /><br/>
+        <div id="tree" class="tree"></div>
+    </div>
+</div>
+<!--add key panel-->
+<div class="panel panel-default col-xs-8 col-sm-8 addkey" hidden style="padding:0%">
+    <div class="panel-heading">
+        <h3 class="panel-title">新增键值</h3>
+    </div>
+    <div class="panel-body">
+        <form id="add-form" class="form-horizontal" role="form-add" data-toggle="validator"
+            method="POST" action="faredis/index/newkey">
+            <input id="c-newdb" class="form-control c-newdb" style="display: none;" name="newdb" type="text">
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Key:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <input id="c-newkey" class="form-control" name="newkey" type="text">
+                </div>                
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">类型:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <select id="c-newtype" class="form-control selectpicker" name="newType">                        
+                        <option value="string">string</option>
+                        <option value="list">list</option>
+                        <option value="set">set</option>
+                        <option value="zset">zset</option>
+                        <option value="hash">hash</option>
+                    </select>
+                </div>                
+            </div>
+            <div class="form-group hash-filed">
+                <label class="control-label col-xs-2 col-sm-2">Field:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <textarea id="c-newfiled" name="newfield" style="width: 100%;" rows="10"></textarea>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Value:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <textarea id="c-newvalue" name="newvalue" style="width: 100%;" rows="10"></textarea>
+                </div>
+            </div>
+            <div class="form-group newsource">
+                <label class="control-label col-xs-2 col-sm-2">Score:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <input id="c-newscore" class="form-control" name="newscore" type="number" min="0" step="1">
+                </div>                
+            </div>
+            <div class="form-group layer-footer">
+                <label class="control-label col-xs-12 col-sm-2"></label>
+                <div class="col-xs-12 col-sm-8"> 
+                    <button id="add-reset" type="reset" class="btn btn-default">重置</button>
+                    <button type="submit" class="btn btn-success btn-embossed">新增</button></button>
+                   
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+<!--string-->
+<div class="panel panel-default col-xs-8 col-sm-8 string" hidden style="padding:0%">
+    <div class="panel-heading">
+        <h3 class="panel-title p-title">key</h3>
+    </div>
+    <div class="panel-body">
+        <form id="add-form" class="form-horizontal" role="form" data-toggle="validator"
+            method="POST" action="faredis/index/updateValue">
+            <input id="c-db" class="form-control c-db" style="display: none;" name="db" type="text">
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">STRING:</label>
+                <div class="col-xs-2 col-sm-2">
+                    <input id="c-key" class="form-control c-key" readonly name="key" type="text">
+                </div>
+                <div class="col-xs-8 col-sm-8">
+                    TTL:<label id="ttl" class="ttl"> </label>
+                    <button type="button" class="btn btn-default btn-embossed rds_rename">重命名</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_del">删除</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_ttl">设置TTL</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Value:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <textarea id="c-value" name="value" style="width: 100%;" rows="10"></textarea>
+                </div>
+            </div>
+            <div class="form-group layer-footer">
+                <label class="control-label col-xs-12 col-sm-2"></label>
+                <div class="col-xs-12 col-sm-8">
+                    <button type="submit" class="btn btn-success btn-embossed">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+<!--Set list-->
+<div class="panel panel-default col-xs-8 col-sm-8 set" hidden style="padding:0%">
+    <div class="panel-heading">
+        <h3 class="panel-title p-title">key</h3>
+    </div>
+    <div class="panel-body">
+        <form id="add-form" class="form-horizontal" role="form" data-toggle="validator"
+            method="POST" action="faredis/index/updateValue">
+            <input id="c-db" class="form-control c-db" style="display: none;" name="db" type="text">
+
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2 type-lb">SET:</label>
+                <div class="col-xs-2 col-sm-2">
+                    <input id="c-key" class="form-control c-key" readonly name="key" type="text">
+                </div>
+                <div class="col-xs-8 col-sm-8">
+                    元素个数:<label id="size"  class="size"> </label>
+                    &nbsp;&nbsp;TTL:<label id="ttl"  class="ttl"> </label>
+                    <button type="button" class="btn btn-default btn-embossed rds_rename">重命名</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_del">删除</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_ttl">设置TTL</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2"></label>
+                <div class="col-xs-10 col-sm-10" style="display: flex;flex-direction:row;">
+                    <select  multiple="true" style="width: 80%;height: 200px;" id='set-list' name="oldvalue">
+                    </select>
+
+                    <div style="display: flex; flex-direction: column;margin-left: 10px;">
+                        <button type="button" class="btn btn-default btn-embossed rds_add_row">增加项</button>
+                        <button type="button" style="margin-top: 10px;" data-type="set-list" class="btn btn-default btn-embossed rds_delete_row">删除项</button>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Value:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <textarea id="c-value" class="set-value" name="value" style="width: 100%;" rows="10"></textarea>
+                </div>
+            </div>
+            <div class="form-group layer-footer">
+                <label class="control-label col-xs-12 col-sm-2"></label>
+                <div class="col-xs-12 col-sm-8">
+                    <button type="submit" class="btn btn-success btn-embossed">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+
+<!--hash-->
+<div class="panel panel-default col-xs-8 col-sm-8 hash" hidden style="padding:0%">
+    <div class="panel-heading">
+        <h3 class="panel-title p-title">key</h3>
+    </div>
+    <div class="panel-body">
+        <form id="add-form" class="form-horizontal" role="form" data-toggle="validator"
+            method="POST" action="faredis/index/updateValue">
+            <input id="c-db" class="form-control c-db" style="display: none;" name="db" type="text">
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2 type-lb">HASH:</label>
+                <div class="col-xs-2 col-sm-2">
+                    <input id="c-key" class="form-control c-key" readonly name="key" type="text">
+                </div>
+                <div class="col-xs-8 col-sm-8">
+                    元素个数:<label id="size"  class="size"> </label>
+                    &nbsp;&nbsp;TTL:<label id="ttl"  class="ttl"> </label>
+                    <button type="button" class="btn btn-default btn-embossed rds_rename">重命名</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_del">删除</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_ttl">设置TTL</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2"></label>
+                <div class="col-xs-10 col-sm-10"  style="display: flex;flex-direction:row;">
+                    <select  multiple="true" style="width: 80%;height: 200px;" id='hash-list'>
+                    </select>
+                    <div style="display: flex; flex-direction: column;margin-left: 10px;">
+                        <button type="button" class="btn btn-default btn-embossed rds_add_row_hash">增加项</button>
+                        <button type="button" style="margin-top: 10px;" data-type="hash-list" class="btn btn-default btn-embossed rds_delete_row">删除项</button>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Key:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <input id="c-hash-key" class="form-control hash-key" readonly name="hash-key" style="width: 100%;" >
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Value:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <textarea id="c-hash-value" class="hash-value" name="value" style="width: 100%;" rows="10"></textarea>
+                </div>
+            </div>
+            <div class="form-group layer-footer">
+                <label class="control-label col-xs-12 col-sm-2"></label>
+                <div class="col-xs-12 col-sm-8">
+                    <button type="submit" class="btn btn-success btn-embossed">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+
+<!--zset-->
+<div class="panel panel-default col-xs-8 col-sm-8 zset" hidden style="padding:0%">
+    <div class="panel-heading">
+        <h3 class="panel-title p-title">key</h3>
+    </div>
+    <div class="panel-body">
+        <form id="add-form" class="form-horizontal" role="form" data-toggle="validator"
+            method="POST" action="faredis/index/updateValue">
+            <input id="c-db" class="form-control c-db" style="display: none;" name="db" type="text">
+
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2 type-lb">ZSET:</label>
+                <div class="col-xs-2 col-sm-2">
+                    <input id="c-key" class="form-control c-key" readonly name="key" type="text">
+                </div>
+                <div class="col-xs-8 col-sm-8">
+                    元素个数:<label id="size"  class="size"> </label>
+                    &nbsp;&nbsp;TTL:<label id="ttl"  class="ttl"> </label>
+                    <button type="button" class="btn btn-default btn-embossed rds_rename">重命名</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_del">删除</button>
+                    <button type="button" class="btn btn-default btn-embossed rds_ttl">设置TTL</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2"></label>
+                <div class="col-xs-10 col-sm-10"  style="display: flex;flex-direction:row;">
+                    <select  multiple="true" style="width: 80%;height: 200px;" name="zset-key" id='zset-list'>
+                    </select>
+                    <div style="display: flex; flex-direction: column;margin-left: 10px;">
+                        <button type="button" class="btn btn-default btn-embossed rds_add_row_zset">增加项</button>
+                        <button type="button" style="margin-top: 10px;"  data-type="zset-list" class="btn btn-default btn-embossed rds_delete_row">删除项</button>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Value:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <input id="c-zset-value" class="form-control zset-value" readonly name="value" style="width: 100%;">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label col-xs-2 col-sm-2">Score:</label>
+                <div class="col-xs-10 col-sm-10">
+                    <input id="c-zset-score" class="form-control zset-score" name="zset-score" type="number" step="1">
+                    </div>
+            </div>
+           
+            <div class="form-group layer-footer">
+                <label class="control-label col-xs-12 col-sm-2"></label>
+                <div class="col-xs-12 col-sm-8">
+                    <button type="submit" class="btn btn-success btn-embossed">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

BIN
public/assets/addons/faredis/img/db_16.png


BIN
public/assets/addons/faredis/img/key_16.png


BIN
public/assets/addons/faredis/img/loading.gif


BIN
public/assets/addons/faredis/img/redis_16.png


+ 419 - 0
public/assets/js/backend/faredis/index.js

@@ -0,0 +1,419 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'jstree'],
+    function ($, undefined, Backend, Table, Form, Template, jstree) {
+        var SELECTED_NODE = null;
+        var KEYDATA = null;
+        var Controller = {
+            jstreeoptions: function () {
+                var options = {
+                    "types": {
+                        "root": {
+                            "icon": "/assets/addons/faredis/img/redis_16.png"
+                        },
+                        "db": {
+                            "icon": "/assets/addons/faredis/img/db_16.png"
+                        },
+                        "loading": {
+                            "icon": "/assets/addons/faredis/img/loading.gif"
+                        },
+                        "key": {
+                            "icon": "/assets/addons/faredis/img/key_16.png"
+                        }
+                    },
+                    "plugins": ["types", "wholerow", "contextmenu", "search"],
+                    "contextmenu": {
+                        "items": Controller.menu
+                    },
+                    "state": {
+                        'opened': true
+                    },
+                    'core': {
+                        "data": {
+                            "url": "faredis/index",
+                        },
+                        "check_callback": true,
+                    }
+                };
+                return options;
+            },
+            jstreeevent: function () {
+                $('#tree').bind("select_node.jstree", function (event, data) {
+                    var inst = data.instance;
+                    var selectedNode = inst.get_node(data.selected);
+                    SELECTED_NODE = selectedNode;
+                    var level = $("[id^='" + selectedNode.id + "']").attr('aria-level');
+                    if (!level || typeof (level) == "undefined") {
+                        level = $("[id^='" + selectedNode.id + "'] a").attr('aria-level');
+                    }
+                    $('.addkey').hide();
+                    $('.string').hide();
+                    $('.set').hide();
+                    $('.hash').hide();
+                    $('.zset').hide();
+                    if (level == 2) {
+                        $('#c-newdb').val(selectedNode.id);
+                        $('.addkey').show();
+                        if (selectedNode.children.length > 0) {
+                            return;
+                        }
+                        inst.set_type(selectedNode, 'loading');
+                        Controller.loadChild(inst, selectedNode);
+                    } else if (level == 3) {
+                        var tmp = selectedNode.id.split('_');
+                        var db = tmp[0];
+                        var key = selectedNode.text;
+                        Controller.loadValue(db, key);
+                    }
+                });
+            },
+            isJSON: function (str) {
+                if (typeof str == 'string') {
+                    try {
+                        var obj = JSON.parse(str);
+                        if (typeof obj == 'object' && obj) {
+                            return true;
+                        } else return false;
+                    } catch (e) {
+                        return false;
+                    }
+                }
+            },
+            jsonFormat: function (el) {
+                if (Controller.isJSON($(el).val())) {
+                    $(el).val(JSON.stringify(eval('(' + $(el).val() + ')'), null, 4));
+                }
+            },
+            loadChild: function (inst, selectedNode) {
+                $.post("faredis/index/keys", {
+                    db: selectedNode.id - 1
+                }, function (res) {
+                    selectedNode.children = [];
+                    $.each(res, function (i, item) {
+                        inst.create_node(selectedNode, item, 'last');
+                    });
+                    inst.open_node(selectedNode);
+                    inst.set_type(selectedNode, 'db');
+                });
+            },
+            loadValue: function (db, key) {
+                $.post('faredis/index/getValue', {
+                    db: db,
+                    key: key
+                }, function (res) {
+                    //reset
+                    $('#c-value').val('');
+                    $('.size').text('');
+                    $('.set-value').val('');
+                    $('.hash-key').val('');
+                    $('.hash-value').val('');
+                    $('.zset-value').val('');
+                    $('.zset-score').val('');
+                    KEYDATA = res;
+                    $('.p-title').text("db" + db + "::" + key);
+                    $('.c-key').val(key);
+                    $('.c-db').val(db);
+                    $(".ttl").text(res.ttl);
+                    switch (res.type) {
+                        case 1: //string
+                            $('.string').show();
+                            $('.set').hide();
+                            $('.hash').hide();
+                            $('.zset').hide();
+                            $('#c-value').val(res.value);
+                            Controller.jsonFormat($('#c-value'));
+                            break;
+                        case 2: //set
+                        case 3: //list
+                            $('.type-lb').text(res.type == 2 ? "SET:" : "LIST:");
+                            $('.set').show();
+                            $('.string').hide();
+                            $('.hash').hide();
+                            $('.zset').hide();
+                            // $('#set-value').val(res.value);
+                            var html = '';
+                            if (res.type == 2) {
+                                res.value.forEach(v => {
+                                    html += "<option value='" + v + "'>" + v + "</option>"
+                                });
+                            } else {
+                                var lidx = 0;
+                                res.value.forEach(v => {
+                                    html += "<option value='" + lidx++ + "'>" + v + "</option>"
+                                });
+                            }
+                            $('#set-list').html(html);
+                            $('.size').text(res.value.length);
+                            break;
+                        case 4:
+                            $('.type-lb').text("ZSET:");
+                            $('.hash').hide();
+                            $('.string').hide();
+                            $('.set').hide();
+                            $('.zset').show();
+                            let count4 = 0;
+                            Object.keys(res.value).forEach(v => {
+                                html += "<option value='" + v + "'>" + v + "</option>"
+                                count4++;
+                            });
+                            $('#zset-list').html(html);
+                            $('.size').text(count4);
+                            break;
+                        case 5: //hash
+                            $('.type-lb').text("HASH:");
+                            $('.hash').show();
+                            $('.string').hide();
+                            $('.set').hide();
+                            $('.zset').hide();
+                            var html = '';
+                            let count = 0;
+                            Object.keys(res.value).forEach(v => {
+                                html += "<option value='" + v + "'>" + v + "</option>"
+                                count++;
+                            });
+                            $('#hash-list').html(html);
+                            $('.size').text(count);
+                            break;
+                        default:
+                            $('.string').hide();
+                            $('.set').hide();
+                            break;
+                    }
+                });
+            },
+            menu: function (node) {
+                var items = {
+                    "reload": {
+                        "label": "重载",
+                        "icon": "fa fa-refresh",
+                        "action": function (data) {
+                            console.log('reload');
+                            var inst = $.jstree.reference(data.reference);
+                            obj = inst.get_node(data.reference);
+                            $.post('faredis/index/reloadDb?db=' + obj.id, null, function (res) {
+                                console.log(res);
+                                $("#tree").jstree('set_text', obj, res.text);
+                                Controller.loadChild(inst, obj);
+                            })
+                        }
+                    },
+                    "flush": {
+                        "label": "清空",
+                        "icon": "fa fa-trash",
+                        "action": function (data) {
+                            console.log('flush');
+                            var inst = $.jstree.reference(data.reference);
+                            obj = inst.get_node(data.reference);
+                            console.log(obj);
+                            Layer.confirm("确认清空吗?", function () {
+                                $.post("faredis/index/flushDb", {
+                                    db: obj.id
+                                }, function (res) {
+                                    Layer.closeAll('dialog');
+                                    $("#tree").jstree('set_text', SELECTED_NODE, "DB" + (obj.id - 1) + "(0)");
+                                    var childNodes = inst.get_children_dom(obj);
+                                    $.each(childNodes, function (index, item) {
+                                        inst.delete_node(item);
+                                    })
+                                });
+                            });
+                        }
+                    },
+
+                };
+                if (node.type == 'db') {
+                    return items;
+                }
+            },
+            index: function () {
+                $('#tree').jstree(Controller.jstreeoptions());
+                Controller.jstreeevent();
+                $('.rds_del').on('click', function () {
+                    Layer.confirm("确认删除?", function () {
+                        $.post("faredis/index/delKey", {
+                            db: KEYDATA.db,
+                            key: KEYDATA.key
+                        }, function (res) {
+                            Layer.closeAll('dialog');
+                            $("#tree").jstree('set_text', SELECTED_NODE, KEYDATA.key + "(Removed)");
+                        });
+                    });
+
+                });
+                $('.rds_ttl').on('click', function () {
+                    Layer.prompt({
+                            title: "修改TTL",
+                            value: KEYDATA.ttl
+                        },
+                        function (value, index, ele) {
+                            $.get("faredis/index/ttl", {
+                                db: KEYDATA.db,
+                                key: KEYDATA.key,
+                                ttl: value
+                            }, function (res) {
+                                Layer.close(index);
+                                $(".ttl").text(value);
+                            });
+                        }
+                    )
+                });
+                $('.rds_rename').on('click', function () {
+                    Layer.prompt({
+                            title: "重命名",
+                            value: KEYDATA.key
+                        },
+                        function (value, index, ele) {
+                            $.get("faredis/index/rename", {
+                                db: KEYDATA.db,
+                                key: KEYDATA.key,
+                                newkey: value
+                            }, function (res) {
+                                Layer.close(index);
+                                $("#tree").jstree('set_text', SELECTED_NODE, value);
+                            });
+                        }
+                    )
+                });
+                //set list 
+                $('#set-list').on('click', function () {
+                    if ($('.type-lb').first().text() == 'LIST:') {
+                        $('.set-value').val($(this).find("option:selected").text());
+                    } else
+                        $('.set-value').val($(this).val());
+                    Controller.jsonFormat($('.set-value'));
+                });
+
+                $('.rds_add_row').on('click', function () {
+                    console.log('add row')
+                    Layer.prompt({
+                            title: "增加新项",
+                            placeholder: '请输入新项的值'
+                        },
+                        function (value, index, ele) {
+                            $.get("faredis/index/addValue", {
+                                db: KEYDATA.db,
+                                key: KEYDATA.key,
+                                value: value
+                            }, function (res) {
+                                Layer.close(index);
+                                var treeNode = $('#tree').jstree(true).get_selected(true)[0];
+                                $("#tree").jstree("deselect_all", true);
+                                $('#tree').jstree('select_node', treeNode.id);
+                            });
+                        }
+                    )
+                });
+
+                $('.rds_add_row_hash').on('click', function () {
+                    Layer.prompt({
+                            title: "增加新项(key/value)",
+                            placeholder: '请输入新项的Key'
+                        },
+                        function (value, index, ele) {
+                            $.get("faredis/index/addValue", {
+                                db: KEYDATA.db,
+                                key: KEYDATA.key,
+                                hash_key: value,
+                                value: $('#hash_value').val()
+                            }, function (res) {
+                                Layer.close(index);
+                                var treeNode = $('#tree').jstree(true).get_selected(true)[0];
+                                $("#tree").jstree("deselect_all", true);
+                                $('#tree').jstree('select_node', treeNode.id);
+                            });
+                        });
+                    $('.layui-layer-content').append('<br/><input type="text" id="hash_value" class="layui-layer-input" placeholder="请输入value值" />')
+                });
+
+                $('.rds_add_row_zset').on('click', function () {
+                    Layer.prompt({
+                            title: "增加新项",
+                            placeholder: '请输入新项的Key'
+                        },
+                        function (value, index, ele) {
+                            $.get("faredis/index/addValue", {
+                                db: KEYDATA.db,
+                                key: KEYDATA.key,
+                                value: value,
+                                zset_score: $('#add_row_zset_score').val()
+                            }, function (res) {
+                                Layer.close(index);
+                                var treeNode = $('#tree').jstree(true).get_selected(true)[0];
+                                $("#tree").jstree("deselect_all", true);
+                                $('#tree').jstree('select_node', treeNode.id);
+                            });
+                        });
+                    $('.layui-layer-content').append('<br/><input type="text" id="add_row_zset_score" class="layui-layer-input" placeholder="请设置value的score" />')
+                });
+
+                $('.rds_delete_row').on('click', function () {
+                    var type = $(this).data('type');
+                    console.log("rds_delete_row", $('#' + type).find("option:selected").text());
+                    $.get("faredis/index/delValue", {
+                        db: KEYDATA.db,
+                        key: KEYDATA.key,
+                        value: $('#' + type).find("option:selected").text(),
+                    }, function (res) {
+                        if (res.code == 1) {
+                            var treeNode = $('#tree').jstree(true).get_selected(true)[0];
+                            $("#tree").jstree("deselect_all", true);
+                            $('#tree').jstree('select_node', treeNode.id);
+                        } else {
+                            Layer.alert("操作失败");
+                        }
+
+                    });
+                });
+                //hash
+                $('#hash-list').on('click', function () {
+                    let key = $(this).val();
+                    $('.hash-key').val(key);
+                    $('.hash-value').val(KEYDATA.value[key]);
+                    Controller.jsonFormat($('.hash-value'));
+                });
+                //zset
+                $('#zset-list').on('click', function () {
+                    let key = $(this).val();
+                    $('.zset-value').val(key);
+                    $('.zset-score').val(KEYDATA.value[key]);
+                });
+
+
+                $('#search_input').keyup(function () {
+                    $("#tree").jstree(true).search($('#search_input').val());
+                });
+
+                $('.newsource').hide();
+                $('.hash-filed').hide();
+                $('#c-newtype').on('changed.bs.select', function (e) {
+                    if (e.target.value == 'zset') {
+                        $('.newsource').show();
+                    } else {
+                        $('.newsource').hide();
+                    }
+                    if (e.target.value == 'hash') {
+                        $('.hash-filed').show();
+                    } else {
+                        $('.hash-filed').hide();
+                    }
+                });
+
+                Form.api.bindevent($("form[role=form]"), function (data, ret) {
+                    var treeNode = $('#tree').jstree(true).get_selected(true)[0];
+                    $("#tree").jstree("deselect_all", true);
+                    $('#tree').jstree('select_node', treeNode.id);
+                });
+                Form.api.bindevent($("form[role=form-add]"), function (data, ret) {
+                    Layer.confirm('新增成功,是否重新加载该库下所有keys?', function () {
+                        Layer.closeAll();
+                        $.post('faredis/index/reloadDb?db=' + SELECTED_NODE.id, null, function (res) {
+                            var inst = $.jstree.reference(SELECTED_NODE);
+                            $("#tree").jstree('set_text', SELECTED_NODE, res.text);
+                            Controller.loadChild(inst, SELECTED_NODE);
+                        })
+                    })
+                    $('#add-reset').trigger('click');
+                });
+            }
+
+        };
+        return Controller;
+    });